Skip to content

Commit

Permalink
Merge pull request #188 from Pasalc/viewport-clamp
Browse files Browse the repository at this point in the history
Fixed texture clamping caused by texture coordinates being outside of (0,1) interval
  • Loading branch information
Almamu authored Dec 12, 2023
2 parents 827912e + 13ba153 commit 51db296
Show file tree
Hide file tree
Showing 15 changed files with 388 additions and 88 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ add_executable(

src/WallpaperEngine/Render/CWallpaper.h
src/WallpaperEngine/Render/CWallpaper.cpp
src/WallpaperEngine/Render/CWallpaperState.h
src/WallpaperEngine/Render/CWallpaperState.cpp
src/WallpaperEngine/Render/CScene.h
src/WallpaperEngine/Render/CScene.cpp
src/WallpaperEngine/Render/CVideo.h
Expand Down
67 changes: 65 additions & 2 deletions src/WallpaperEngine/Application/CApplicationContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,29 @@ struct option long_options[] = {
{ "noautomute", no_argument, nullptr, 'm' },
{ "no-fullscreen-pause", no_argument, nullptr, 'n' },
{ "disable-mouse", no_argument, nullptr, 'e' },
{ "scaling", required_argument, nullptr, 't' },
{ "clamping", required_argument, nullptr, 't' },
{ nullptr, 0, nullptr, 0 }
};

/* std::hash::operator() isn't constexpr, so it can't be used to get hash values as compile-time constants
* So here is customHash. It skips all spaces, so hashes for " find " and "fi nd" are the same
* Basicly got it from here: https://stackoverflow.com/questions/8317508/hash-function-for-a-string
*/
constexpr size_t customHash(const char* str) {
constexpr size_t A = 54059; /* a prime */
constexpr size_t B = 76963; /* another prime */
constexpr size_t C = 86969; /* yet another prime */
constexpr size_t FIRSTH = 37; /* also prime */
size_t hash = FIRSTH;
while (*str) {
if(*str != ' ') // Skip spaces
hash = (hash * A) ^ (*str * B);
++str;
}
return hash % C;
}

std::string stringPathFixes (const std::string& s)
{
if (s.empty ())
Expand Down Expand Up @@ -66,7 +86,8 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
.mode = NORMAL_WINDOW,
.maximumFPS = 30,
.pauseOnFullscreen = true,
.window = { .geometry = {}},
.window = { .geometry = {}, .clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs,
.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs, },
},
.audio =
{
Expand All @@ -90,7 +111,7 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])

std::string lastScreen;

while ((c = getopt_long (argc, argv, "b:r:p:d:shf:a:w:mn", long_options, nullptr)) != -1)
while ((c = getopt_long (argc, argv, "b:r:p:d:shf:a:w:mnt:", long_options, nullptr)) != -1)
{
switch (c)
{
Expand All @@ -105,6 +126,7 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
// no need to check for previous screen being in the list, as it's the only way for this variable
// to have any value
this->settings.general.screenBackgrounds[lastScreen] = translateBackground (optarg);
this->settings.general.screenScalings[lastScreen] = this->settings.render.window.scalingMode;
break;

case 'o':
Expand Down Expand Up @@ -133,6 +155,7 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
this->settings.render.mode = DESKTOP_BACKGROUND;
lastScreen = optarg;
this->settings.general.screenBackgrounds[lastScreen] = "";
this->settings.general.screenScalings[lastScreen] = this->settings.render.window.scalingMode;
break;

case 'w':
Expand Down Expand Up @@ -196,6 +219,42 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
this->settings.mouse.enabled = false;
break;

case 't':
{
size_t hash = customHash(optarg);
// Use a switch statement with the hash
switch (hash) {
// --scale options
case customHash("stretch"):
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::StretchUVs;
break;
case customHash("fit"):
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFitUVs;
break;
case customHash("fill"):
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFillUVs;
break;
case customHash("default"):
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs;
break;
// --clamp options
case customHash("clamp"):
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs;
break;
case customHash("border"):
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVsBorder;
break;
case customHash("repeat"):
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::NoFlags;
break;
default:
sLog.error("Wrong argument:");
sLog.error(optarg);
sLog.exception("Wrong argument provided for --scale or --clamp option.");
break;
}
}
break;
default:
sLog.out ("Default on path parsing: ", optarg);
break;
Expand Down Expand Up @@ -293,4 +352,8 @@ void CApplicationContext::printHelp (const char* route)
sLog.out ("\t--set-property <name=value>\tOverrides the default value of the given property");
sLog.out ("\t--no-fullscreen-pause\tPrevents the background pausing when an app is fullscreen");
sLog.out ("\t--disable-mouse\tDisables mouse interactions");
sLog.out ("\t--scaling <mode>\t Scaling mode for wallpaper. Can be stretch, fit, fill, default. Must be used before wallpaper provided.\n\
\t\t For default wallpaper last specified value will be used.\n\
\t\t Example: ./wallengine --scaling stretch --screen-root eDP-1 --bg 2667198601 --scaling fill --screen-root eDP-2 2667198602");
sLog.out ("\t--clamping <mode>\t Clamping mode for all wallpapers. Can be clamp, border, repeat. Enables GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_REPEAT accordingly. Default is clamp.");
}
7 changes: 7 additions & 0 deletions src/WallpaperEngine/Application/CApplicationContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

#include "CApplicationState.h"

#include "WallpaperEngine/Assets/ITexture.h"
#include "WallpaperEngine/Render/CWallpaperState.h"

namespace WallpaperEngine::Application
{
/**
Expand Down Expand Up @@ -50,6 +53,8 @@ namespace WallpaperEngine::Application
std::map <std::string, std::filesystem::path> screenBackgrounds;
/** Properties to change values for */
std::map <std::string, std::string> properties;
/** The scaling mode for different screens */
std::map <std::string, WallpaperEngine::Render::CWallpaperState::TextureUVsScaling> screenScalings;
} general;

/**
Expand All @@ -68,6 +73,8 @@ namespace WallpaperEngine::Application
{
/** The window size used in explicit window */
glm::ivec4 geometry;
WallpaperEngine::Assets::ITexture::TextureFlags clamp;
WallpaperEngine::Render::CWallpaperState::TextureUVsScaling scalingMode;
} window;
} render;

Expand Down
4 changes: 2 additions & 2 deletions src/WallpaperEngine/Application/CWallpaperApplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,13 +322,13 @@ namespace WallpaperEngine::Application
for (const auto& it : this->m_backgrounds)
context->setWallpaper (
it.first,
WallpaperEngine::Render::CWallpaper::fromWallpaper (it.second->getWallpaper (), *context, *audioContext)
WallpaperEngine::Render::CWallpaper::fromWallpaper (it.second->getWallpaper (), *context, *audioContext, this->m_context.settings.general.screenScalings[it.first])
);

// set the default rendering wallpaper if available
if (this->m_defaultBackground != nullptr)
context->setDefaultWallpaper (WallpaperEngine::Render::CWallpaper::fromWallpaper (
this->m_defaultBackground->getWallpaper (), *context, *audioContext
this->m_defaultBackground->getWallpaper (), *context, *audioContext, this->m_context.settings.render.window.scalingMode
));

static time_t seconds;
Expand Down
1 change: 1 addition & 0 deletions src/WallpaperEngine/Assets/ITexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ namespace WallpaperEngine::Assets
NoInterpolation = 1,
ClampUVs = 2,
IsGif = 4,
ClampUVsBorder = 8,
};

/**
Expand Down
5 changes: 5 additions & 0 deletions src/WallpaperEngine/Render/CFBO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ CFBO::CFBO (
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
else if (flags & TextureFlags::ClampUVsBorder)
{
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
}
else
{
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
Expand Down
6 changes: 4 additions & 2 deletions src/WallpaperEngine/Render/CScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "WallpaperEngine/Render/Objects/CImage.h"
#include "WallpaperEngine/Render/Objects/CSound.h"

#include "WallpaperEngine/Render/CWallpaperState.h"

#include "CScene.h"

extern float g_Time;
Expand All @@ -14,8 +16,8 @@ extern float g_TimeLast;
using namespace WallpaperEngine;
using namespace WallpaperEngine::Render;

CScene::CScene (Core::CScene* scene, CRenderContext& context, CAudioContext& audioContext) :
CWallpaper (scene, Type, context, audioContext),
CScene::CScene (Core::CScene* scene, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode) :
CWallpaper (scene, Type, context, audioContext, scalingMode),
m_mousePosition (),
m_mousePositionLast (),
m_parallaxDisplacement ()
Expand Down
2 changes: 1 addition & 1 deletion src/WallpaperEngine/Render/CScene.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace WallpaperEngine::Render
class CScene : public CWallpaper
{
public:
CScene (Core::CScene* scene, CRenderContext& context, CAudioContext& audioContext);
CScene (Core::CScene* scene, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode);

CCamera* getCamera () const;

Expand Down
4 changes: 2 additions & 2 deletions src/WallpaperEngine/Render/CVideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ void* get_proc_address (void* ctx, const char* name)
return static_cast<CVideo*> (ctx)->getContext ().getDriver ().getProcAddress (name);
}

CVideo::CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext) :
CWallpaper (video, Type, context, audioContext),
CVideo::CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode) :
CWallpaper (video, Type, context, audioContext, scalingMode),
m_width (16),
m_height (16),
m_mpvGl (nullptr)
Expand Down
2 changes: 1 addition & 1 deletion src/WallpaperEngine/Render/CVideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace WallpaperEngine::Render
class CVideo : public CWallpaper
{
public:
CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext);
CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode);

Core::CVideo* getVideo ();

Expand Down
94 changes: 20 additions & 74 deletions src/WallpaperEngine/Render/CWallpaper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

using namespace WallpaperEngine::Render;

CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext) :
CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode) :
CContextAware (context),
m_wallpaperData (wallpaperData),
m_type (std::move(type)),
Expand All @@ -22,7 +22,8 @@ CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRend
a_Position (GL_NONE),
a_TexCoord (GL_NONE),
m_vaoBuffer (GL_NONE),
m_audioContext (audioContext)
m_audioContext (audioContext),
m_state(scalingMode)
{
// generate the VAO to stop opengl from complaining
glGenVertexArrays (1, &this->m_vaoBuffer);
Expand Down Expand Up @@ -201,81 +202,25 @@ void CWallpaper::setupShaders ()
this->a_TexCoord = glGetAttribLocation (this->m_shader, "a_TexCoord");
}

void CWallpaper::updateTexCoord (GLfloat* texCoords, GLsizeiptr size) const
{
glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
glBufferData (GL_ARRAY_BUFFER, size, texCoords, GL_STATIC_DRAW);
}
void CWallpaper::setDestinationFramebuffer (GLuint framebuffer)
{
this->m_destFramebuffer = framebuffer;
}

void CWallpaper::updateUVs(const glm::ivec4& viewport, const bool vflip){
//update UVs if something has changed, otherwise use old values
if(this->m_state.hasChanged(viewport, vflip, this->getWidth(), this->getHeight())){
// Update wallpaper state
this->m_state.updateState(viewport, vflip, this->getWidth(), this->getHeight());
}
}

void CWallpaper::render (glm::ivec4 viewport, bool vflip)
{
this->renderFrame (viewport);

uint32_t projectionWidth = this->getWidth ();
uint32_t projectionHeight = this->getHeight ();

float ustart = 0.0f;
float uend = 0.0f;
float vstart = 0.0f;
float vend = 0.0f;

if (
(viewport.w > viewport.z && projectionWidth >= projectionHeight) ||
(viewport.z > viewport.w && projectionHeight > projectionWidth)
)
{
if (vflip)
{
vstart = 0.0f;
vend = 1.0f;
}
else
{
vstart = 1.0f;
vend = 0.0f;
}

int newWidth = viewport.w / (float) projectionHeight * projectionWidth;
float newCenter = newWidth / 2.0f;
float viewportCenter = viewport.z / 2.0;

float left = newCenter - viewportCenter;
float right = newCenter + viewportCenter;

ustart = left / newWidth;
uend = right / newWidth;
}

if (
(viewport.z > viewport.w && projectionWidth >= projectionHeight) ||
(viewport.w > viewport.z && projectionHeight > projectionWidth)
)
{
ustart = 0.0f;
uend = 1.0f;

int newHeight = viewport.z / (float) projectionWidth * projectionHeight;
float newCenter = newHeight / 2.0f;
float viewportCenter = viewport.w / 2.0;

float down = newCenter - viewportCenter;
float up = newCenter + viewportCenter;

if (vflip)
{
vstart = down / newHeight;
vend = up / newHeight;
}
else
{
vstart = up / newHeight;
vend = down / newHeight;
}
}
//Update UVs coordinates according to scaling mode of this wallpaper
updateUVs(viewport,vflip);
auto [ ustart, uend, vstart, vend ] = this->m_state.getTextureUVs();

GLfloat texCoords [] = {
ustart, vstart,
Expand Down Expand Up @@ -319,12 +264,13 @@ void CWallpaper::setupFramebuffers ()
{
uint32_t width = this->getWidth ();
uint32_t height = this->getHeight ();

ITexture::TextureFlags clamp = this->getContext().getApp().getContext().settings.render.window.clamp;

// create framebuffer for the scene
this->m_sceneFBO = this->createFBO (
"_rt_FullFrameBuffer",
ITexture::TextureFormat::ARGB8888,
ITexture::TextureFlags::ClampUVs,
clamp,
1.0,
width, height,
width, height
Expand Down Expand Up @@ -366,12 +312,12 @@ CFBO* CWallpaper::getFBO () const
return this->m_sceneFBO;
}

CWallpaper* CWallpaper::fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext)
CWallpaper* CWallpaper::fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode)
{
if (wallpaper->is <Core::CScene> ())
return new WallpaperEngine::Render::CScene (wallpaper->as <Core::CScene> (), context, audioContext);
return new WallpaperEngine::Render::CScene (wallpaper->as <Core::CScene> (), context, audioContext, scalingMode);
else if (wallpaper->is <Core::CVideo> ())
return new WallpaperEngine::Render::CVideo (wallpaper->as <Core::CVideo> (), context, audioContext);
return new WallpaperEngine::Render::CVideo (wallpaper->as <Core::CVideo> (), context, audioContext, scalingMode);
else
sLog.exception ("Unsupported wallpaper type");
}
Loading

0 comments on commit 51db296

Please sign in to comment.