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 26b3070..7798add 100644 --- a/src/WallpaperEngine/Application/CApplicationContext.cpp +++ b/src/WallpaperEngine/Application/CApplicationContext.cpp @@ -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 ()) @@ -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 = { @@ -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) { @@ -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': @@ -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': @@ -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; @@ -293,4 +352,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--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."); } diff --git a/src/WallpaperEngine/Application/CApplicationContext.h b/src/WallpaperEngine/Application/CApplicationContext.h index 92d7750..864b19f 100644 --- a/src/WallpaperEngine/Application/CApplicationContext.h +++ b/src/WallpaperEngine/Application/CApplicationContext.h @@ -11,6 +11,9 @@ #include "CApplicationState.h" +#include "WallpaperEngine/Assets/ITexture.h" +#include "WallpaperEngine/Render/CWallpaperState.h" + namespace WallpaperEngine::Application { /** @@ -50,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; /** @@ -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; 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/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/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 f925020..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,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, @@ -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 @@ -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 ()) - 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 ed71611..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; @@ -83,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 @@ -111,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 @@ -153,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 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"