From 3dee616cf6192f73780b40d7ea11b7838b22eb4c Mon Sep 17 00:00:00 2001 From: Pasalc Date: Tue, 17 Oct 2023 23:44:16 +0300 Subject: [PATCH 1/4] Fixed not full texture rendering on viewport resulting in clamping --- src/WallpaperEngine/Render/CWallpaper.cpp | 59 ++--------------------- 1 file changed, 5 insertions(+), 54 deletions(-) diff --git a/src/WallpaperEngine/Render/CWallpaper.cpp b/src/WallpaperEngine/Render/CWallpaper.cpp index f925020..9471928 100644 --- a/src/WallpaperEngine/Render/CWallpaper.cpp +++ b/src/WallpaperEngine/Render/CWallpaper.cpp @@ -219,64 +219,15 @@ void CWallpaper::render (glm::ivec4 viewport, bool vflip) uint32_t projectionHeight = this->getHeight (); float ustart = 0.0f; - float uend = 0.0f; - float vstart = 0.0f; + float uend = 1.0f; + float vstart = 1.0f; float vend = 0.0f; - if ( - (viewport.w > viewport.z && projectionWidth >= projectionHeight) || - (viewport.z > viewport.w && projectionHeight > projectionWidth) - ) + if (vflip) { - 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; + vstart = 0.0f; + vend = 1.0f; } - - 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; - } - } - GLfloat texCoords [] = { ustart, vstart, uend, vstart, From f6bff679ca86107300ad378299742aa09e5fc967 Mon Sep 17 00:00:00 2001 From: Pasalc Date: Mon, 6 Nov 2023 17:30:48 +0300 Subject: [PATCH 2/4] Added --clamp-strategy option --- .../Application/CApplicationContext.cpp | 29 ++++++- .../Application/CApplicationContext.h | 4 + src/WallpaperEngine/Assets/ITexture.h | 1 + src/WallpaperEngine/Render/CFBO.cpp | 5 ++ src/WallpaperEngine/Render/CRenderContext.cpp | 4 +- src/WallpaperEngine/Render/CWallpaper.cpp | 80 +++++++++++++++---- src/WallpaperEngine/Render/CWallpaper.h | 7 +- .../Drivers/Output/CGLFWWindowOutput.cpp | 1 + 8 files changed, 110 insertions(+), 21 deletions(-) diff --git a/src/WallpaperEngine/Application/CApplicationContext.cpp b/src/WallpaperEngine/Application/CApplicationContext.cpp index a4665c0..23bf78b 100644 --- a/src/WallpaperEngine/Application/CApplicationContext.cpp +++ b/src/WallpaperEngine/Application/CApplicationContext.cpp @@ -28,6 +28,7 @@ struct option long_options[] = { { "noautomute", no_argument, nullptr, 'm' }, { "no-fullscreen-pause", no_argument, nullptr, 'n' }, { "disable-mouse", no_argument, nullptr, 'e' }, + { "clamp-strategy", required_argument, nullptr, 't' }, { nullptr, 0, nullptr, 0 } }; @@ -65,7 +66,7 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) .mode = NORMAL_WINDOW, .maximumFPS = 30, .pauseOnFullscreen = true, - .window = { .geometry = {}}, + .window = { .geometry = {}, .clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs, .scaleToFit=false }, }, .audio = { @@ -89,7 +90,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) { @@ -194,6 +195,29 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) this->settings.mouse.enabled = false; break; + case 't': + { + char opt = optarg[0]; + switch (opt) + { + case 's':/* stretch*/ + this->settings.render.window.scaleToFit=true; + break; + case 'b':/* clamp border (crop black)*/ + this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVsBorder;//clampStrategy(optarg); + break; + case 'c':/* clamp*/ + this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs; + break; + case 'r': + this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::NoFlags; + break; + default: + sLog.error("Wrong argument provided for clamp-strategy"); + break; + } + } + break; default: sLog.out ("Default on path parsing: ", optarg); break; @@ -290,4 +314,5 @@ void CApplicationContext::printHelp (const char* route) sLog.out ("\t--set-property \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--clamp-strategy \t Clamp strategy if wallpaper doesn't fit screen. Can be stretch, border, repeat, clamp. Can be shortend to s, b, r, c. Default is clamp"); } \ No newline at end of file diff --git a/src/WallpaperEngine/Application/CApplicationContext.h b/src/WallpaperEngine/Application/CApplicationContext.h index 92d7750..ed0c284 100644 --- a/src/WallpaperEngine/Application/CApplicationContext.h +++ b/src/WallpaperEngine/Application/CApplicationContext.h @@ -11,6 +11,8 @@ #include "CApplicationState.h" +#include "WallpaperEngine/Assets/ITexture.h" + namespace WallpaperEngine::Application { /** @@ -68,6 +70,8 @@ namespace WallpaperEngine::Application { /** The window size used in explicit window */ glm::ivec4 geometry; + WallpaperEngine::Assets::ITexture::TextureFlags clamp; + bool scaleToFit; } window; } render; diff --git a/src/WallpaperEngine/Assets/ITexture.h b/src/WallpaperEngine/Assets/ITexture.h index 338a592..42037a9 100644 --- a/src/WallpaperEngine/Assets/ITexture.h +++ b/src/WallpaperEngine/Assets/ITexture.h @@ -69,6 +69,7 @@ namespace WallpaperEngine::Assets NoInterpolation = 1, ClampUVs = 2, IsGif = 4, + ClampUVsBorder = 8, }; /** diff --git a/src/WallpaperEngine/Render/CFBO.cpp b/src/WallpaperEngine/Render/CFBO.cpp index 11fa2c6..ab79621 100644 --- a/src/WallpaperEngine/Render/CFBO.cpp +++ b/src/WallpaperEngine/Render/CFBO.cpp @@ -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); diff --git a/src/WallpaperEngine/Render/CRenderContext.cpp b/src/WallpaperEngine/Render/CRenderContext.cpp index 08ad438..6f2ed95 100644 --- a/src/WallpaperEngine/Render/CRenderContext.cpp +++ b/src/WallpaperEngine/Render/CRenderContext.cpp @@ -36,9 +36,9 @@ namespace WallpaperEngine::Render // render the background if (ref != this->m_wallpapers.end ()) - ref->second->render (viewport->viewport, this->getOutput ().renderVFlip ()); + ref->second->render (viewport->viewport, this->getOutput ().renderVFlip (), this->getApp().getContext().settings.render.window.scaleToFit); else - this->m_defaultWallpaper->render (viewport->viewport, this->getOutput ().renderVFlip ()); + this->m_defaultWallpaper->render (viewport->viewport, this->getOutput ().renderVFlip (), this->getApp().getContext().settings.render.window.scaleToFit); #if !NDEBUG glPopDebugGroup (); diff --git a/src/WallpaperEngine/Render/CWallpaper.cpp b/src/WallpaperEngine/Render/CWallpaper.cpp index 9471928..38badd4 100644 --- a/src/WallpaperEngine/Render/CWallpaper.cpp +++ b/src/WallpaperEngine/Render/CWallpaper.cpp @@ -211,23 +211,70 @@ void CWallpaper::setDestinationFramebuffer (GLuint framebuffer) this->m_destFramebuffer = framebuffer; } -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 = 1.0f; - float vstart = 1.0f; - float vend = 0.0f; - - if (vflip) - { +void CWallpaper::setTextureUVs(const glm::ivec4& viewport, const bool vflip, const bool scale, + float& ustart, float& uend, float& vstart, float& vend){ + + ustart = 0.0f; + uend = 1.0f; + vstart = 1.0f; + vend = 0.0f; + if (vflip){ vstart = 0.0f; vend = 1.0f; } + if(!scale){ + uint32_t projectionWidth = this->getWidth (); + uint32_t projectionHeight = this->getHeight (); + + if ( + (viewport.w > viewport.z && projectionWidth >= projectionHeight) || + (viewport.z > viewport.w && projectionHeight > projectionWidth) + ) + { + 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) + ) + { + 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; + } + } + } +} + +void CWallpaper::render (glm::ivec4 viewport, bool vflip, bool scale) +{ + this->renderFrame (viewport); + + float ustart,uend,vstart,vend; + setTextureUVs(viewport, vflip, scale, ustart, uend, vstart, vend); + GLfloat texCoords [] = { ustart, vstart, uend, vstart, @@ -270,12 +317,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 diff --git a/src/WallpaperEngine/Render/CWallpaper.h b/src/WallpaperEngine/Render/CWallpaper.h index ed71611..c55f5b6 100644 --- a/src/WallpaperEngine/Render/CWallpaper.h +++ b/src/WallpaperEngine/Render/CWallpaper.h @@ -34,10 +34,15 @@ namespace WallpaperEngine::Render ~CWallpaper (); + /** + * Get texture UV coordinates for render + */ + void setTextureUVs(const glm::ivec4& viewport, const bool vflip, const bool scale, + float& ustart, float& uend, float& vstart, float& vend); /** * Performs a render pass of the wallpaper */ - void render (glm::ivec4 viewport, bool vflip); + void render (glm::ivec4 viewport, bool vflip, bool scale); /** * @return The container to resolve files for this wallpaper diff --git a/src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.cpp b/src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.cpp index 7994f4f..d96f397 100644 --- a/src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.cpp +++ b/src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.cpp @@ -1,3 +1,4 @@ +#include #include #include "CGLFWWindowOutput.h" #include "WallpaperEngine/Logging/CLog.h" From 42120953352a3ae50b47374f06849317dd16b5e2 Mon Sep 17 00:00:00 2001 From: Pasalc Date: Wed, 8 Nov 2023 20:14:22 +0300 Subject: [PATCH 3/4] Added zoom fill --- src/WallpaperEngine/Render/CWallpaper.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/WallpaperEngine/Render/CWallpaper.cpp b/src/WallpaperEngine/Render/CWallpaper.cpp index 38badd4..51b49f6 100644 --- a/src/WallpaperEngine/Render/CWallpaper.cpp +++ b/src/WallpaperEngine/Render/CWallpaper.cpp @@ -225,11 +225,12 @@ void CWallpaper::setTextureUVs(const glm::ivec4& viewport, const bool vflip, con if(!scale){ uint32_t projectionWidth = this->getWidth (); uint32_t projectionHeight = this->getHeight (); - - if ( - (viewport.w > viewport.z && projectionWidth >= projectionHeight) || - (viewport.z > viewport.w && projectionHeight > projectionWidth) - ) + const float m1 = float(viewport.z) / projectionWidth; + const float m2 = float(viewport.w) / projectionHeight; + const float m = std::max(m1,m2); + projectionWidth*=m; + projectionHeight*=m; + if (projectionWidth!=viewport.z) { int newWidth = viewport.w / (float) projectionHeight * projectionWidth; float newCenter = newWidth / 2.0f; @@ -242,10 +243,7 @@ void CWallpaper::setTextureUVs(const glm::ivec4& viewport, const bool vflip, con uend = right / newWidth; } - if ( - (viewport.z > viewport.w && projectionWidth >= projectionHeight) || - (viewport.w > viewport.z && projectionHeight > projectionWidth) - ) + if (projectionHeight!=viewport.w) { int newHeight = viewport.z / (float) projectionWidth * projectionHeight; float newCenter = newHeight / 2.0f; From 11666abf32b446e6ca7deced1f664a9722fc0ddd Mon Sep 17 00:00:00 2001 From: Pasalc Date: Mon, 13 Nov 2023 19:25:17 +0300 Subject: [PATCH 4/4] Added scaling and clamp support --- CMakeLists.txt | 2 + .../Application/CApplicationContext.cpp | 82 ++++++--- .../Application/CApplicationContext.h | 5 +- .../Application/CWallpaperApplication.cpp | 4 +- src/WallpaperEngine/Render/CRenderContext.cpp | 4 +- src/WallpaperEngine/Render/CScene.cpp | 6 +- src/WallpaperEngine/Render/CScene.h | 2 +- src/WallpaperEngine/Render/CVideo.cpp | 4 +- src/WallpaperEngine/Render/CVideo.h | 2 +- src/WallpaperEngine/Render/CWallpaper.cpp | 81 ++------- src/WallpaperEngine/Render/CWallpaper.h | 19 +- .../Render/CWallpaperState.cpp | 170 ++++++++++++++++++ src/WallpaperEngine/Render/CWallpaperState.h | 99 ++++++++++ 13 files changed, 371 insertions(+), 109 deletions(-) create mode 100644 src/WallpaperEngine/Render/CWallpaperState.cpp create mode 100644 src/WallpaperEngine/Render/CWallpaperState.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f457d26..d3f90b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/src/WallpaperEngine/Application/CApplicationContext.cpp b/src/WallpaperEngine/Application/CApplicationContext.cpp index 23bf78b..e7840cb 100644 --- a/src/WallpaperEngine/Application/CApplicationContext.cpp +++ b/src/WallpaperEngine/Application/CApplicationContext.cpp @@ -28,10 +28,29 @@ struct option long_options[] = { { "noautomute", no_argument, nullptr, 'm' }, { "no-fullscreen-pause", no_argument, nullptr, 'n' }, { "disable-mouse", no_argument, nullptr, 'e' }, - { "clamp-strategy", required_argument, nullptr, 't' }, + { "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 ()) @@ -66,7 +85,8 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) .mode = NORMAL_WINDOW, .maximumFPS = 30, .pauseOnFullscreen = true, - .window = { .geometry = {}, .clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs, .scaleToFit=false }, + .window = { .geometry = {}, .clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs, + .scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs, }, }, .audio = { @@ -105,6 +125,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': @@ -133,6 +154,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': @@ -196,25 +218,38 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) break; case 't': - { - char opt = optarg[0]; - switch (opt) - { - case 's':/* stretch*/ - this->settings.render.window.scaleToFit=true; - break; - case 'b':/* clamp border (crop black)*/ - this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVsBorder;//clampStrategy(optarg); - break; - case 'c':/* clamp*/ - this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs; - break; - case 'r': - this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::NoFlags; - break; - default: - sLog.error("Wrong argument provided for clamp-strategy"); - break; + { + 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; @@ -314,5 +349,8 @@ void CApplicationContext::printHelp (const char* route) sLog.out ("\t--set-property \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--clamp-strategy \t Clamp strategy if wallpaper doesn't fit screen. Can be stretch, border, repeat, clamp. Can be shortend to s, b, r, c. Default is clamp"); + sLog.out ("\t--scaling \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 \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."); } \ No newline at end of file diff --git a/src/WallpaperEngine/Application/CApplicationContext.h b/src/WallpaperEngine/Application/CApplicationContext.h index ed0c284..864b19f 100644 --- a/src/WallpaperEngine/Application/CApplicationContext.h +++ b/src/WallpaperEngine/Application/CApplicationContext.h @@ -12,6 +12,7 @@ #include "CApplicationState.h" #include "WallpaperEngine/Assets/ITexture.h" +#include "WallpaperEngine/Render/CWallpaperState.h" namespace WallpaperEngine::Application { @@ -52,6 +53,8 @@ namespace WallpaperEngine::Application std::map screenBackgrounds; /** Properties to change values for */ std::map properties; + /** The scaling mode for different screens */ + std::map screenScalings; } general; /** @@ -71,7 +74,7 @@ namespace WallpaperEngine::Application /** The window size used in explicit window */ glm::ivec4 geometry; WallpaperEngine::Assets::ITexture::TextureFlags clamp; - bool scaleToFit; + WallpaperEngine::Render::CWallpaperState::TextureUVsScaling scalingMode; } window; } render; diff --git a/src/WallpaperEngine/Application/CWallpaperApplication.cpp b/src/WallpaperEngine/Application/CWallpaperApplication.cpp index 2096677..113a488 100644 --- a/src/WallpaperEngine/Application/CWallpaperApplication.cpp +++ b/src/WallpaperEngine/Application/CWallpaperApplication.cpp @@ -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; diff --git a/src/WallpaperEngine/Render/CRenderContext.cpp b/src/WallpaperEngine/Render/CRenderContext.cpp index 6f2ed95..08ad438 100644 --- a/src/WallpaperEngine/Render/CRenderContext.cpp +++ b/src/WallpaperEngine/Render/CRenderContext.cpp @@ -36,9 +36,9 @@ namespace WallpaperEngine::Render // render the background if (ref != this->m_wallpapers.end ()) - ref->second->render (viewport->viewport, this->getOutput ().renderVFlip (), this->getApp().getContext().settings.render.window.scaleToFit); + ref->second->render (viewport->viewport, this->getOutput ().renderVFlip ()); else - this->m_defaultWallpaper->render (viewport->viewport, this->getOutput ().renderVFlip (), this->getApp().getContext().settings.render.window.scaleToFit); + this->m_defaultWallpaper->render (viewport->viewport, this->getOutput ().renderVFlip ()); #if !NDEBUG glPopDebugGroup (); diff --git a/src/WallpaperEngine/Render/CScene.cpp b/src/WallpaperEngine/Render/CScene.cpp index 3f8f80c..f635e62 100644 --- a/src/WallpaperEngine/Render/CScene.cpp +++ b/src/WallpaperEngine/Render/CScene.cpp @@ -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; @@ -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 () diff --git a/src/WallpaperEngine/Render/CScene.h b/src/WallpaperEngine/Render/CScene.h index 4c2f4f1..80b7186 100644 --- a/src/WallpaperEngine/Render/CScene.h +++ b/src/WallpaperEngine/Render/CScene.h @@ -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; diff --git a/src/WallpaperEngine/Render/CVideo.cpp b/src/WallpaperEngine/Render/CVideo.cpp index 8606e19..6b18f0b 100644 --- a/src/WallpaperEngine/Render/CVideo.cpp +++ b/src/WallpaperEngine/Render/CVideo.cpp @@ -11,8 +11,8 @@ void* get_proc_address (void* ctx, const char* name) return static_cast (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) diff --git a/src/WallpaperEngine/Render/CVideo.h b/src/WallpaperEngine/Render/CVideo.h index eb90a30..d1ef5b6 100644 --- a/src/WallpaperEngine/Render/CVideo.h +++ b/src/WallpaperEngine/Render/CVideo.h @@ -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 (); diff --git a/src/WallpaperEngine/Render/CWallpaper.cpp b/src/WallpaperEngine/Render/CWallpaper.cpp index 51b49f6..dbb1be5 100644 --- a/src/WallpaperEngine/Render/CWallpaper.cpp +++ b/src/WallpaperEngine/Render/CWallpaper.cpp @@ -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)), @@ -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); @@ -201,78 +202,26 @@ 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::setTextureUVs(const glm::ivec4& viewport, const bool vflip, const bool scale, - float& ustart, float& uend, float& vstart, float& vend){ - - ustart = 0.0f; - uend = 1.0f; - vstart = 1.0f; - vend = 0.0f; - if (vflip){ - vstart = 0.0f; - vend = 1.0f; - } - if(!scale){ - uint32_t projectionWidth = this->getWidth (); - uint32_t projectionHeight = this->getHeight (); - const float m1 = float(viewport.z) / projectionWidth; - const float m2 = float(viewport.w) / projectionHeight; - const float m = std::max(m1,m2); - projectionWidth*=m; - projectionHeight*=m; - if (projectionWidth!=viewport.z) - { - 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 (projectionHeight!=viewport.w) - { - 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; - } - } +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, bool scale) +void CWallpaper::render (glm::ivec4 viewport, bool vflip) { this->renderFrame (viewport); + //Update UVs coordinates according to scaling mode of this wallpaper + updateUVs(viewport,vflip); + auto [ ustart, uend, vstart, vend ] = this->m_state.getTextureUVs(); - float ustart,uend,vstart,vend; - setTextureUVs(viewport, vflip, scale, ustart, uend, vstart, vend); - GLfloat texCoords [] = { ustart, vstart, uend, vstart, @@ -363,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 ()) - return new WallpaperEngine::Render::CScene (wallpaper->as (), context, audioContext); + return new WallpaperEngine::Render::CScene (wallpaper->as (), context, audioContext, scalingMode); else if (wallpaper->is ()) - return new WallpaperEngine::Render::CVideo (wallpaper->as (), context, audioContext); + return new WallpaperEngine::Render::CVideo (wallpaper->as (), context, audioContext, scalingMode); else sLog.exception ("Unsupported wallpaper type"); } \ No newline at end of file diff --git a/src/WallpaperEngine/Render/CWallpaper.h b/src/WallpaperEngine/Render/CWallpaper.h index c55f5b6..1da4eb9 100644 --- a/src/WallpaperEngine/Render/CWallpaper.h +++ b/src/WallpaperEngine/Render/CWallpaper.h @@ -14,6 +14,8 @@ #include "WallpaperEngine/Render/CFBO.h" #include "WallpaperEngine/Render/Helpers/CContextAware.h" +#include "CWallpaperState.h" + using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Audio; @@ -34,15 +36,10 @@ namespace WallpaperEngine::Render ~CWallpaper (); - /** - * Get texture UV coordinates for render - */ - void setTextureUVs(const glm::ivec4& viewport, const bool vflip, const bool scale, - float& ustart, float& uend, float& vstart, float& vend); /** * Performs a render pass of the wallpaper */ - void render (glm::ivec4 viewport, bool vflip, bool scale); + void render (glm::ivec4 viewport, bool vflip); /** * @return The container to resolve files for this wallpaper @@ -88,9 +85,9 @@ namespace WallpaperEngine::Render [[nodiscard]] CFBO* getFBO () const; /** - * Updates the texcoord used for drawing to the used framebuffer + * Updates the UVs coordinates if window/screen/vflip/projection has changed */ - void updateTexCoord (GLfloat* texCoords, GLsizeiptr size) const; + void updateUVs (const glm::ivec4& viewport, const bool vflip); /** * Updates the destination framebuffer for this wallpaper @@ -116,10 +113,10 @@ namespace WallpaperEngine::Render * * @return */ - static CWallpaper* fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext); + static CWallpaper* fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode); protected: - CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext); + CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode); /** * Renders a frame of the wallpaper @@ -158,5 +155,7 @@ namespace WallpaperEngine::Render std::map m_fbos; /** Audio context that is using this wallpaper */ CAudioContext& m_audioContext; + /** Current Wallpaper state */ + CWallpaperState m_state; }; } diff --git a/src/WallpaperEngine/Render/CWallpaperState.cpp b/src/WallpaperEngine/Render/CWallpaperState.cpp new file mode 100644 index 0000000..f971fe8 --- /dev/null +++ b/src/WallpaperEngine/Render/CWallpaperState.cpp @@ -0,0 +1,170 @@ +#include "CWallpaperState.h" +#include +#include "WallpaperEngine/Logging/CLog.h" + +using namespace WallpaperEngine::Render; + +// Reset UVs to 0/1 values +void CWallpaperState::resetUVs(){ + this->UVs.ustart=0; + this->UVs.uend=1; + if (vflip){ + this->UVs.vstart = 0.0f; + this->UVs.vend = 1.0f; + } + else{ + this->UVs.vstart=1.0f; + this->UVs.vend=0.0f; + } +} + +// Update Us coordinates for current viewport and projection +void CWallpaperState::updateUs(const int& projectionWidth, const int& projectionHeight){ + const float viewportWidth = this->getViewportWidth(); + const float viewportHeight = this->getViewportHeight(); + int newWidth = viewportHeight / projectionHeight * projectionWidth; + float newCenter = newWidth / 2.0f; + float viewportCenter = viewportWidth / 2.0; + + float left = newCenter - viewportCenter; + float right = newCenter + viewportCenter; + + this->UVs.ustart = left / newWidth; + this->UVs.uend = right / newWidth; +} + +// Update Vs coordinates for current viewport and projection +void CWallpaperState::updateVs(const int& projectionWidth, const int& projectionHeight){ + const float viewportWidth = this->getViewportWidth(); + const float viewportHeight = this->getViewportHeight(); + int newHeight = viewportWidth / projectionWidth * projectionHeight; + float newCenter = newHeight / 2.0f; + float viewportCenter = viewportHeight / 2.0; + + float down = newCenter - viewportCenter; + float up = newCenter + viewportCenter; + + if (vflip) + { + this->UVs.vstart = down / newHeight; + this->UVs.vend = up / newHeight; + } + else + { + this->UVs.vstart = up / newHeight; + this->UVs.vend = down / newHeight; + } +} + + +template<> void CWallpaperState::updateTextureUVs(){ + this->resetUVs(); +} + +template<> void CWallpaperState::updateTextureUVs(){ + this->resetUVs(); + + const int viewportWidth = this->getViewportWidth(); + const int viewportHeight = this->getViewportHeight(); + uint32_t projectionWidth = this->getProjectionWidth(); + uint32_t projectionHeight = this->getProjectionHeight(); + + const float m1 = static_cast(viewportWidth) / projectionWidth; + const float m2 = static_cast(viewportHeight) / projectionHeight; + const float m = std::max(m1,m2); + projectionWidth*=m; + projectionHeight*=m; + + if (projectionWidth!=viewportWidth) + { + this->updateUs(projectionWidth,projectionHeight); + } + else if (projectionHeight!=viewportHeight) + { + this->updateVs(projectionWidth,projectionHeight); + } +} + +template<> void CWallpaperState::updateTextureUVs(){ + this->resetUVs(); + + const int viewportWidth = this->getViewportWidth(); + const int viewportHeight = this->getViewportHeight(); + uint32_t projectionWidth = this->getProjectionWidth(); + uint32_t projectionHeight = this->getProjectionHeight(); + + const float m1 = static_cast(viewportWidth) / projectionWidth; + const float m2 = static_cast(viewportHeight) / projectionHeight; + const float m = std::min(m1,m2); + projectionWidth*=m; + projectionHeight*=m; + + if (projectionWidth!=viewportWidth) + { + this->updateUs(projectionWidth,projectionHeight); + } + else if (projectionHeight!=viewportHeight) + { + this->updateVs(projectionWidth,projectionHeight); + } +} + +template<> void CWallpaperState::updateTextureUVs(){ + this->resetUVs(); + + const int viewportWidth = this->getViewportWidth(); + const int viewportHeight = this->getViewportHeight(); + uint32_t projectionWidth = this->getProjectionWidth(); + uint32_t projectionHeight = this->getProjectionHeight(); + + if ( + (viewportHeight > viewportWidth && projectionWidth >= projectionHeight) || + (viewportWidth > viewportHeight && projectionHeight > projectionWidth) + ) + { + updateUs(projectionWidth,projectionHeight); + } + + if ( + (viewportWidth > viewportHeight && projectionWidth >= projectionHeight) || + (viewportHeight > viewportWidth && projectionHeight > projectionWidth) + ) + { + updateVs(projectionWidth,projectionHeight); + } +} + +template void CWallpaperState::updateTextureUVs(){ + sLog.exception("Using generic template for scaling is not allowed. Write specialization template for your scaling mode.\ + This message is for developers, if you are just user it's a bug."); +} + + +void CWallpaperState::updateState(const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth, const int& projectionHeight){ + this->viewport.width = viewport.z; + this->viewport.height = viewport.w; + this->vflip = vflip; + this->projection.width = projectionWidth; + this->projection.height = projectionHeight; + + //Set texture UVs according to choosen scaling mode for this wallpaper + switch (this->getTextureUVsScaling()) + { + case CWallpaperState::TextureUVsScaling::StretchUVs : + this->updateTextureUVs(); + break; + case CWallpaperState::TextureUVsScaling::ZoomFillUVs : + this->updateTextureUVs(); + break; + case CWallpaperState::TextureUVsScaling::ZoomFitUVs : + this->updateTextureUVs(); + break; + case CWallpaperState::TextureUVsScaling::DefaultUVs : + this->updateTextureUVs(); + break; + default: + sLog.exception("Switch case for specified scaling mode doesn't exist. Add your realisation in switch statement.\ + This message is for developers, if you are just user it's a bug."); + break; + } +} \ No newline at end of file diff --git a/src/WallpaperEngine/Render/CWallpaperState.h b/src/WallpaperEngine/Render/CWallpaperState.h new file mode 100644 index 0000000..6c9103f --- /dev/null +++ b/src/WallpaperEngine/Render/CWallpaperState.h @@ -0,0 +1,99 @@ +#pragma once + +#include +#include +#include + +namespace WallpaperEngine::Render +{ + /** + * Represents current wallpaper state + */ + class CWallpaperState + { + public: + // Scaling modes. Defines how UVs coordinates are calculated. + enum class TextureUVsScaling : uint8_t + { + DefaultUVs, + ZoomFitUVs, + ZoomFillUVs, + StretchUVs, + }; + + CWallpaperState(const TextureUVsScaling& textureUVsMode) : m_textureUVsMode(textureUVsMode) + {}; + + // Compares saved state values with passed arguments + bool hasChanged(const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth, const int& projectionHeight) const{ + return this->viewport.width != viewport.z || this->viewport.height != viewport.w || + this->projection.width != projectionWidth || this->projection.height != projectionHeight || this->vflip != vflip; + } + + // Reset UVs to 0/1 values + void resetUVs(); + + // Update Us coordinates for current viewport and projection + void updateUs(const int& projectionWidth, const int& projectionHeight); + + // Update Vs coordinates for current viewport and projection + void updateVs(const int& projectionWidth, const int& projectionHeight); + + // Get texture UV coordinates + auto getTextureUVs() const {return UVs;}; + + // Set texture UV coordinates according to texture scaling mode + template void updateTextureUVs(); + + // Updates state with provided values + void updateState(const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth, const int& projectionHeight); + + // @return The texture scaling mode + TextureUVsScaling getTextureUVsScaling () const { return m_textureUVsMode; }; + + // Set texture scaling mode + void setTextureUVsStrategy(const TextureUVsScaling strategy) { m_textureUVsMode=strategy; } ; + + // @return The width of viewport + int getViewportWidth () const { return viewport.width;}; + + // @return The height of viewport + int getViewportHeight () const { return viewport.height;}; + + // @return The width of viewport + uint32_t getProjectionWidth () const { return projection.width;}; + + // @return The height of viewport + uint32_t getProjectionHeight () const { return projection.height;}; + + private: + // Cached UVs value for texture coordinates. No need to recalculate if viewport and projection haven't changed. + struct + { + float ustart; + float uend; + float vstart; + float vend; + } UVs; + + // Viewport for which UVs were calculated + struct + { + int width; + int height; + } viewport{}; + + // Wallpaper dimensions + struct + { + uint32_t width; + uint32_t height; + } projection{}; + + // Are Vs coordinates fliped + bool vflip = false; + + // Texture scaling mode + TextureUVsScaling m_textureUVsMode = TextureUVsScaling::DefaultUVs; + }; +} \ No newline at end of file