From ada7ce8e56e34b2c1474877787658b26f0aadc2c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 3 Mar 2024 02:19:25 +0000 Subject: [PATCH] renderer: various fixes to transformations and backgrounds fixes #111 --- src/core/Output.cpp | 3 +-- src/core/hyprlock.cpp | 21 ++++++++++++++- src/main.cpp | 17 ++++++------ src/renderer/AsyncResourceGatherer.cpp | 4 +++ src/renderer/DMAFrame.cpp | 37 +++++++++++++++----------- src/renderer/DMAFrame.hpp | 2 ++ src/renderer/Renderer.cpp | 8 +++--- src/renderer/Renderer.hpp | 2 +- src/renderer/mtx.hpp | 32 +++++++++++----------- src/renderer/widgets/Background.cpp | 31 ++++++++++++++------- src/renderer/widgets/Background.hpp | 7 +++-- 11 files changed, 103 insertions(+), 61 deletions(-) diff --git a/src/core/Output.cpp b/src/core/Output.cpp index 0369baf..fe9a998 100644 --- a/src/core/Output.cpp +++ b/src/core/Output.cpp @@ -15,8 +15,7 @@ static void handleMode(void* data, wl_output* output, uint32_t flags, int32_t wi const auto POUTPUT = (COutput*)data; // handle portrait mode and flipped cases - if (POUTPUT->transform == WL_OUTPUT_TRANSFORM_270 || POUTPUT->transform == WL_OUTPUT_TRANSFORM_90 || POUTPUT->transform == WL_OUTPUT_TRANSFORM_FLIPPED_270 || - POUTPUT->transform == WL_OUTPUT_TRANSFORM_FLIPPED_90) + if (POUTPUT->transform % 2 == 1) POUTPUT->size = {height, width}; else POUTPUT->size = {width, height}; diff --git a/src/core/hyprlock.cpp b/src/core/hyprlock.cpp index d0cf39c..42a3277 100644 --- a/src/core/hyprlock.cpp +++ b/src/core/hyprlock.cpp @@ -310,6 +310,25 @@ void CHyprlock::run() { g_pRenderer = std::make_unique(); + const auto CURRENTDESKTOP = getenv("XDG_CURRENT_DESKTOP"); + const auto SZCURRENTD = std::string{CURRENTDESKTOP ? CURRENTDESKTOP : ""}; + + Debug::log(LOG, "Running on {}", SZCURRENTD); + + // Hyprland violates the protocol a bit to allow for this. + if (SZCURRENTD != "Hyprland") { + while (!g_pRenderer->asyncResourceGatherer->ready) { + wl_display_flush(m_sWaylandState.display); + if (wl_display_prepare_read(m_sWaylandState.display) == 0) { + wl_display_read_events(m_sWaylandState.display); + wl_display_dispatch_pending(m_sWaylandState.display); + } else { + wl_display_dispatch(m_sWaylandState.display); + } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + } + lockSession(); signal(SIGUSR1, handleUnlockSignal); @@ -388,7 +407,7 @@ void CHyprlock::run() { m_sLoopState.event = false; - if (pollfds[0].revents & POLLIN /* dbus */) { + if (pollfds[0].revents & POLLIN /* wl */) { Debug::log(TRACE, "got wl event"); wl_display_flush(m_sWaylandState.display); if (wl_display_prepare_read(m_sWaylandState.display) == 0) { diff --git a/src/main.cpp b/src/main.cpp index 2a5c01e..6fb97e1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,13 +2,13 @@ #include "config/ConfigManager.hpp" #include "core/hyprlock.hpp" -void help(){ - std::cout << "Usage: hyprlock [options]\n\n" - "Options:\n" - " -v, --verbose - Enable verbose logging\n" - " -q, --quiet - Disable logging\n" - " --display (display) - Specify the Wayland display to connect to\n" - " -h, --help - Show this help message\n"; +void help() { + std::cout << "Usage: hyprlock [options]\n\n" + "Options:\n" + " -v, --verbose - Enable verbose logging\n" + " -q, --quiet - Disable logging\n" + " --display (display) - Specify the Wayland display to connect to\n" + " -h, --help - Show this help message\n"; } int main(int argc, char** argv, char** envp) { std::string wlDisplay; @@ -25,8 +25,7 @@ int main(int argc, char** argv, char** envp) { else if (arg == "--display" && i + 1 < argc) { wlDisplay = argv[i + 1]; i++; - } - else if (arg == "--help" || arg == "-h") { + } else if (arg == "--help" || arg == "-h") { help(); return 0; } diff --git a/src/renderer/AsyncResourceGatherer.cpp b/src/renderer/AsyncResourceGatherer.cpp index d2d5b88..7118fa6 100644 --- a/src/renderer/AsyncResourceGatherer.cpp +++ b/src/renderer/AsyncResourceGatherer.cpp @@ -151,6 +151,10 @@ void CAsyncResourceGatherer::gather() { } } + while (std::any_of(dmas.begin(), dmas.end(), [](const auto& d) { return !d->asset.ready; })) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + ready = true; } diff --git a/src/renderer/DMAFrame.cpp b/src/renderer/DMAFrame.cpp index 9969870..08d9ff9 100644 --- a/src/renderer/DMAFrame.cpp +++ b/src/renderer/DMAFrame.cpp @@ -14,7 +14,8 @@ static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = nullptr; static PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullptr; -static void wlrOnBuffer(void* data, zwlr_screencopy_frame_v1* frame, uint32_t format, uint32_t width, uint32_t height, uint32_t stride) { +// +static void wlrOnBuffer(void* data, zwlr_screencopy_frame_v1* frame, uint32_t format, uint32_t width, uint32_t height, uint32_t stride) { const auto PDATA = (SScreencopyData*)data; Debug::log(TRACE, "[sc] wlrOnBuffer for {}", (void*)PDATA); @@ -85,7 +86,7 @@ static const zwlr_screencopy_frame_v1_listener wlrFrameListener = { .buffer_done = wlrOnBufferDone, }; -CDMAFrame::CDMAFrame(COutput* output) { +CDMAFrame::CDMAFrame(COutput* output_) : output(output_) { if (!glEGLImageTargetTexture2DOES) { glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); @@ -208,19 +209,21 @@ bool CDMAFrame::onBufferReady() { static const int entries_per_attrib = 2; EGLAttrib attribs[(general_attribs + plane_attribs * 4) * entries_per_attrib + 1]; int attr = 0; - attribs[attr++] = EGL_WIDTH; - attribs[attr++] = scdata.w; - attribs[attr++] = EGL_HEIGHT; - attribs[attr++] = scdata.h; - attribs[attr++] = EGL_LINUX_DRM_FOURCC_EXT; - attribs[attr++] = scdata.fmt; - attribs[attr++] = EGL_DMA_BUF_PLANE0_FD_EXT; - attribs[attr++] = fd[0]; - attribs[attr++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; - attribs[attr++] = offset[0]; - attribs[attr++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; - attribs[attr++] = stride[0]; - attribs[attr] = EGL_NONE; + Vector2D size{scdata.w, scdata.h}; + + attribs[attr++] = EGL_WIDTH; + attribs[attr++] = size.x; + attribs[attr++] = EGL_HEIGHT; + attribs[attr++] = size.y; + attribs[attr++] = EGL_LINUX_DRM_FOURCC_EXT; + attribs[attr++] = scdata.fmt; + attribs[attr++] = EGL_DMA_BUF_PLANE0_FD_EXT; + attribs[attr++] = fd[0]; + attribs[attr++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; + attribs[attr++] = offset[0]; + attribs[attr++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; + attribs[attr++] = stride[0]; + attribs[attr] = EGL_NONE; image = eglCreateImage(g_pEGL->eglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attribs); @@ -230,7 +233,7 @@ bool CDMAFrame::onBufferReady() { } asset.texture.allocate(); - asset.texture.m_vSize = {scdata.w, scdata.h}; + asset.texture.m_vSize = size; glBindTexture(GL_TEXTURE_2D, asset.texture.m_iTexID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -239,6 +242,8 @@ bool CDMAFrame::onBufferReady() { glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); glBindTexture(GL_TEXTURE_2D, 0); + Debug::log(LOG, "Got dma frame with size {}", size); + asset.ready = true; return true; diff --git a/src/renderer/DMAFrame.hpp b/src/renderer/DMAFrame.hpp index 9763fbd..cb13d24 100644 --- a/src/renderer/DMAFrame.hpp +++ b/src/renderer/DMAFrame.hpp @@ -42,5 +42,7 @@ class CDMAFrame { zwlr_screencopy_frame_v1* frameCb = nullptr; SScreencopyData scdata; + COutput* output = nullptr; + EGLImage image = nullptr; }; \ No newline at end of file diff --git a/src/renderer/Renderer.cpp b/src/renderer/Renderer.cpp index e9ebc43..56765c4 100644 --- a/src/renderer/Renderer.cpp +++ b/src/renderer/Renderer.cpp @@ -242,9 +242,9 @@ void CRenderer::renderRect(const CBox& box, const CColor& col, int rounding) { glDisableVertexAttribArray(rectShader.posAttrib); } -void CRenderer::renderTexture(const CBox& box, const CTexture& tex, float a, int rounding, bool noTransform) { +void CRenderer::renderTexture(const CBox& box, const CTexture& tex, float a, int rounding, std::optional tr) { float matrix[9]; - wlr_matrix_project_box(matrix, &box, noTransform ? WL_OUTPUT_TRANSFORM_NORMAL : WL_OUTPUT_TRANSFORM_FLIPPED_180 /* ugh coordinate spaces */, 0, + wlr_matrix_project_box(matrix, &box, tr.value_or(WL_OUTPUT_TRANSFORM_FLIPPED_180) /* ugh coordinate spaces */, 0, projMatrix.data()); // TODO: write own, don't use WLR here float glMatrix[9]; @@ -305,7 +305,7 @@ std::vector>* CRenderer::getOrCreateWidgetsFor(const CS else if (!PATH.empty()) resourceID = "background:" + PATH; - widgets[surf].emplace_back(std::make_unique(surf->size, resourceID, c.values)); + widgets[surf].emplace_back(std::make_unique(surf->size, surf->output, resourceID, c.values, PATH == "screenshot")); } else if (c.type == "input-field") { widgets[surf].emplace_back(std::make_unique(surf->size, c.values)); } else if (c.type == "label") { @@ -464,7 +464,7 @@ void CRenderer::blurFB(const CFramebuffer& outfb, SBlurParams params) { // finish outfb.bind(); - renderTexture(box, currentRenderToFB->m_cTex, 1.0, 0, true); + renderTexture(box, currentRenderToFB->m_cTex, 1.0, 0, WL_OUTPUT_TRANSFORM_NORMAL); glEnable(GL_BLEND); } \ No newline at end of file diff --git a/src/renderer/Renderer.hpp b/src/renderer/Renderer.hpp index ff1ee25..30fb931 100644 --- a/src/renderer/Renderer.hpp +++ b/src/renderer/Renderer.hpp @@ -29,7 +29,7 @@ class CRenderer { SRenderFeedback renderLock(const CSessionLockSurface& surface); void renderRect(const CBox& box, const CColor& col, int rounding = 0); - void renderTexture(const CBox& box, const CTexture& tex, float a = 1.0, int rounding = 0, bool noTransform = false); + void renderTexture(const CBox& box, const CTexture& tex, float a = 1.0, int rounding = 0, std::optional tr = {}); void blurFB(const CFramebuffer& outfb, SBlurParams params); std::unique_ptr asyncResourceGatherer; diff --git a/src/renderer/mtx.hpp b/src/renderer/mtx.hpp index 372d6bc..7f64991 100644 --- a/src/renderer/mtx.hpp +++ b/src/renderer/mtx.hpp @@ -4,21 +4,21 @@ #include #include "../helpers/Box.hpp" -enum wl_output_transform wlr_output_transform_invert(enum wl_output_transform tr) { - // if ((tr & WL_OUTPUT_TRANSFORM_90) && !(tr & WL_OUTPUT_TRANSFORM_FLIPPED)) { - // tr ^= WL_OUTPUT_TRANSFORM_180; - // } +static enum wl_output_transform wlr_output_transform_invert(enum wl_output_transform tr) { + if ((tr & WL_OUTPUT_TRANSFORM_90) && !(tr & WL_OUTPUT_TRANSFORM_FLIPPED)) { + tr = (wl_output_transform)((int)tr ^ (int)WL_OUTPUT_TRANSFORM_180); + } return tr; } -void wlr_matrix_identity(float mat[9]) { +static void wlr_matrix_identity(float mat[9]) { const float identity[9] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; memcpy(mat, identity, sizeof(identity)); } -void wlr_matrix_multiply(float mat[9], const float a[9], const float b[9]) { +static void wlr_matrix_multiply(float mat[9], const float a[9], const float b[9]) { float product[9]; product[0] = a[0] * b[0] + a[1] * b[3] + a[2] * b[6]; @@ -36,35 +36,35 @@ void wlr_matrix_multiply(float mat[9], const float a[9], const float b[9]) { memcpy(mat, product, sizeof(product)); } -void wlr_matrix_transpose(float mat[9], const float a[9]) { +static void wlr_matrix_transpose(float mat[9], const float a[9]) { float transposition[9] = { a[0], a[3], a[6], a[1], a[4], a[7], a[2], a[5], a[8], }; memcpy(mat, transposition, sizeof(transposition)); } -void wlr_matrix_translate(float mat[9], float x, float y) { +static void wlr_matrix_translate(float mat[9], float x, float y) { float translate[9] = { 1.0f, 0.0f, x, 0.0f, 1.0f, y, 0.0f, 0.0f, 1.0f, }; wlr_matrix_multiply(mat, mat, translate); } -void wlr_matrix_scale(float mat[9], float x, float y) { +static void wlr_matrix_scale(float mat[9], float x, float y) { float scale[9] = { x, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 0.0f, 1.0f, }; wlr_matrix_multiply(mat, mat, scale); } -void wlr_matrix_rotate(float mat[9], float rad) { +static void wlr_matrix_rotate(float mat[9], float rad) { float rotate[9] = { cos(rad), -sin(rad), 0.0f, sin(rad), cos(rad), 0.0f, 0.0f, 0.0f, 1.0f, }; wlr_matrix_multiply(mat, mat, rotate); } -const float transforms[][9] = { +static const float transforms[][9] = { [WL_OUTPUT_TRANSFORM_NORMAL] = { 1.0f, @@ -163,11 +163,11 @@ const float transforms[][9] = { }, }; -void wlr_matrix_transform(float mat[9], enum wl_output_transform transform) { +static void wlr_matrix_transform(float mat[9], enum wl_output_transform transform) { wlr_matrix_multiply(mat, mat, transforms[transform]); } -void matrix_projection(float mat[9], int width, int height, enum wl_output_transform transform) { +static void matrix_projection(float mat[9], int width, int height, enum wl_output_transform transform) { std::memset(mat, 0, sizeof(*mat) * 9); const float* t = transforms[transform]; @@ -188,7 +188,7 @@ void matrix_projection(float mat[9], int width, int height, enum wl_output_trans mat[8] = 1.0f; } -void wlr_matrix_project_box(float mat[9], const CBox* box, enum wl_output_transform transform, float rotation, const float projection[9]) { +static void wlr_matrix_project_box(float mat[9], const CBox* box, enum wl_output_transform transform, float rotation, const float projection[9]) { int x = box->x; int y = box->y; int width = box->width; @@ -214,7 +214,7 @@ void wlr_matrix_project_box(float mat[9], const CBox* box, enum wl_output_transf wlr_matrix_multiply(mat, projection, mat); } -void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) { +static void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) { memset(mat, 0, sizeof(*mat) * 9); const float* t = transforms[tr]; @@ -233,4 +233,4 @@ void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) { // Identity mat[8] = 1.0f; -} \ No newline at end of file +} diff --git a/src/renderer/widgets/Background.cpp b/src/renderer/widgets/Background.cpp index 5a11acc..ed78b27 100644 --- a/src/renderer/widgets/Background.cpp +++ b/src/renderer/widgets/Background.cpp @@ -1,8 +1,9 @@ #include "Background.hpp" #include "../Renderer.hpp" +#include "../mtx.hpp" -CBackground::CBackground(const Vector2D& viewport_, const std::string& resourceID_, const std::unordered_map& props) : - viewport(viewport_), resourceID(resourceID_) { +CBackground::CBackground(const Vector2D& viewport_, COutput* output_, const std::string& resourceID_, const std::unordered_map& props, bool ss) : + viewport(viewport_), resourceID(resourceID_), output(output_), isScreenshot(ss) { color = std::any_cast(props.at("color")); blurPasses = std::any_cast(props.at("blur_passes")); @@ -30,13 +31,19 @@ bool CBackground::draw(const SRenderData& data) { if (!asset) return false; - if (blurPasses > 0 && !blurredFB.isAllocated()) { + if ((blurPasses > 0 || isScreenshot) && !blurredFB.isAllocated()) { // make it brah - CBox texbox = {{}, asset->texture.m_vSize}; + Vector2D size = asset->texture.m_vSize; - Vector2D size = asset->texture.m_vSize; - float scaleX = viewport.x / asset->texture.m_vSize.x; - float scaleY = viewport.y / asset->texture.m_vSize.y; + if (output->transform % 2 == 1 && isScreenshot) { + size.x = asset->texture.m_vSize.y; + size.y = asset->texture.m_vSize.x; + } + + CBox texbox = {{}, size}; + + float scaleX = viewport.x / size.x; + float scaleY = viewport.y / size.y; texbox.w *= std::max(scaleX, scaleY); texbox.h *= std::max(scaleX, scaleY); @@ -48,9 +55,13 @@ bool CBackground::draw(const SRenderData& data) { texbox.round(); blurredFB.alloc(viewport.x, viewport.y); // TODO 10 bit blurredFB.bind(); + g_pRenderer->renderTexture(texbox, asset->texture, 1.0, 0, - true); // this could be omitted but whatever it's only once and makes code cleaner plus less blurring on large texs - g_pRenderer->blurFB(blurredFB, CRenderer::SBlurParams{blurSize, blurPasses, noise, contrast, brightness, vibrancy, vibrancy_darkness}); + isScreenshot ? + wlr_output_transform_invert(output->transform) : + WL_OUTPUT_TRANSFORM_NORMAL); // this could be omitted but whatever it's only once and makes code cleaner plus less blurring on large texs + if (blurPasses > 0) + g_pRenderer->blurFB(blurredFB, CRenderer::SBlurParams{blurSize, blurPasses, noise, contrast, brightness, vibrancy, vibrancy_darkness}); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } @@ -70,7 +81,7 @@ bool CBackground::draw(const SRenderData& data) { else texbox.x = -(texbox.w - viewport.x) / 2.f; texbox.round(); - g_pRenderer->renderTexture(texbox, *tex, data.opacity); + g_pRenderer->renderTexture(texbox, *tex, data.opacity, 0, WL_OUTPUT_TRANSFORM_FLIPPED_180); return data.opacity < 1.0; } \ No newline at end of file diff --git a/src/renderer/widgets/Background.hpp b/src/renderer/widgets/Background.hpp index 6f83a5f..33fd838 100644 --- a/src/renderer/widgets/Background.hpp +++ b/src/renderer/widgets/Background.hpp @@ -9,10 +9,11 @@ #include struct SPreloadedAsset; +class COutput; class CBackground : public IWidget { public: - CBackground(const Vector2D& viewport, const std::string& resourceID, const std::unordered_map& props); + CBackground(const Vector2D& viewport, COutput* output_, const std::string& resourceID, const std::unordered_map& props, bool ss_); virtual bool draw(const SRenderData& data); @@ -30,5 +31,7 @@ class CBackground : public IWidget { Vector2D viewport; std::string resourceID; CColor color; - SPreloadedAsset* asset = nullptr; + SPreloadedAsset* asset = nullptr; + COutput* output = nullptr; + bool isScreenshot = false; }; \ No newline at end of file