renderer: various fixes to transformations and backgrounds

fixes #111
This commit is contained in:
Vaxry 2024-03-03 02:19:25 +00:00
parent 97548ec0ad
commit ada7ce8e56
11 changed files with 103 additions and 61 deletions

View file

@ -15,8 +15,7 @@ static void handleMode(void* data, wl_output* output, uint32_t flags, int32_t wi
const auto POUTPUT = (COutput*)data; const auto POUTPUT = (COutput*)data;
// handle portrait mode and flipped cases // 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 || if (POUTPUT->transform % 2 == 1)
POUTPUT->transform == WL_OUTPUT_TRANSFORM_FLIPPED_90)
POUTPUT->size = {height, width}; POUTPUT->size = {height, width};
else else
POUTPUT->size = {width, height}; POUTPUT->size = {width, height};

View file

@ -310,6 +310,25 @@ void CHyprlock::run() {
g_pRenderer = std::make_unique<CRenderer>(); g_pRenderer = std::make_unique<CRenderer>();
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(); lockSession();
signal(SIGUSR1, handleUnlockSignal); signal(SIGUSR1, handleUnlockSignal);
@ -388,7 +407,7 @@ void CHyprlock::run() {
m_sLoopState.event = false; m_sLoopState.event = false;
if (pollfds[0].revents & POLLIN /* dbus */) { if (pollfds[0].revents & POLLIN /* wl */) {
Debug::log(TRACE, "got wl event"); Debug::log(TRACE, "got wl event");
wl_display_flush(m_sWaylandState.display); wl_display_flush(m_sWaylandState.display);
if (wl_display_prepare_read(m_sWaylandState.display) == 0) { if (wl_display_prepare_read(m_sWaylandState.display) == 0) {

View file

@ -2,7 +2,7 @@
#include "config/ConfigManager.hpp" #include "config/ConfigManager.hpp"
#include "core/hyprlock.hpp" #include "core/hyprlock.hpp"
void help(){ void help() {
std::cout << "Usage: hyprlock [options]\n\n" std::cout << "Usage: hyprlock [options]\n\n"
"Options:\n" "Options:\n"
" -v, --verbose - Enable verbose logging\n" " -v, --verbose - Enable verbose logging\n"
@ -25,8 +25,7 @@ int main(int argc, char** argv, char** envp) {
else if (arg == "--display" && i + 1 < argc) { else if (arg == "--display" && i + 1 < argc) {
wlDisplay = argv[i + 1]; wlDisplay = argv[i + 1];
i++; i++;
} } else if (arg == "--help" || arg == "-h") {
else if (arg == "--help" || arg == "-h") {
help(); help();
return 0; return 0;
} }

View file

@ -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; ready = true;
} }

View file

@ -14,6 +14,7 @@
static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = nullptr; static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = nullptr;
static PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = 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; const auto PDATA = (SScreencopyData*)data;
@ -85,7 +86,7 @@ static const zwlr_screencopy_frame_v1_listener wlrFrameListener = {
.buffer_done = wlrOnBufferDone, .buffer_done = wlrOnBufferDone,
}; };
CDMAFrame::CDMAFrame(COutput* output) { CDMAFrame::CDMAFrame(COutput* output_) : output(output_) {
if (!glEGLImageTargetTexture2DOES) { if (!glEGLImageTargetTexture2DOES) {
glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
@ -208,10 +209,12 @@ bool CDMAFrame::onBufferReady() {
static const int entries_per_attrib = 2; static const int entries_per_attrib = 2;
EGLAttrib attribs[(general_attribs + plane_attribs * 4) * entries_per_attrib + 1]; EGLAttrib attribs[(general_attribs + plane_attribs * 4) * entries_per_attrib + 1];
int attr = 0; int attr = 0;
Vector2D size{scdata.w, scdata.h};
attribs[attr++] = EGL_WIDTH; attribs[attr++] = EGL_WIDTH;
attribs[attr++] = scdata.w; attribs[attr++] = size.x;
attribs[attr++] = EGL_HEIGHT; attribs[attr++] = EGL_HEIGHT;
attribs[attr++] = scdata.h; attribs[attr++] = size.y;
attribs[attr++] = EGL_LINUX_DRM_FOURCC_EXT; attribs[attr++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[attr++] = scdata.fmt; attribs[attr++] = scdata.fmt;
attribs[attr++] = EGL_DMA_BUF_PLANE0_FD_EXT; attribs[attr++] = EGL_DMA_BUF_PLANE0_FD_EXT;
@ -230,7 +233,7 @@ bool CDMAFrame::onBufferReady() {
} }
asset.texture.allocate(); asset.texture.allocate();
asset.texture.m_vSize = {scdata.w, scdata.h}; asset.texture.m_vSize = size;
glBindTexture(GL_TEXTURE_2D, asset.texture.m_iTexID); 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_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
Debug::log(LOG, "Got dma frame with size {}", size);
asset.ready = true; asset.ready = true;
return true; return true;

View file

@ -42,5 +42,7 @@ class CDMAFrame {
zwlr_screencopy_frame_v1* frameCb = nullptr; zwlr_screencopy_frame_v1* frameCb = nullptr;
SScreencopyData scdata; SScreencopyData scdata;
COutput* output = nullptr;
EGLImage image = nullptr; EGLImage image = nullptr;
}; };

View file

@ -242,9 +242,9 @@ void CRenderer::renderRect(const CBox& box, const CColor& col, int rounding) {
glDisableVertexAttribArray(rectShader.posAttrib); 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<wl_output_transform> tr) {
float matrix[9]; 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 projMatrix.data()); // TODO: write own, don't use WLR here
float glMatrix[9]; float glMatrix[9];
@ -305,7 +305,7 @@ std::vector<std::unique_ptr<IWidget>>* CRenderer::getOrCreateWidgetsFor(const CS
else if (!PATH.empty()) else if (!PATH.empty())
resourceID = "background:" + PATH; resourceID = "background:" + PATH;
widgets[surf].emplace_back(std::make_unique<CBackground>(surf->size, resourceID, c.values)); widgets[surf].emplace_back(std::make_unique<CBackground>(surf->size, surf->output, resourceID, c.values, PATH == "screenshot"));
} else if (c.type == "input-field") { } else if (c.type == "input-field") {
widgets[surf].emplace_back(std::make_unique<CPasswordInputField>(surf->size, c.values)); widgets[surf].emplace_back(std::make_unique<CPasswordInputField>(surf->size, c.values));
} else if (c.type == "label") { } else if (c.type == "label") {
@ -464,7 +464,7 @@ void CRenderer::blurFB(const CFramebuffer& outfb, SBlurParams params) {
// finish // finish
outfb.bind(); 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); glEnable(GL_BLEND);
} }

View file

@ -29,7 +29,7 @@ class CRenderer {
SRenderFeedback renderLock(const CSessionLockSurface& surface); SRenderFeedback renderLock(const CSessionLockSurface& surface);
void renderRect(const CBox& box, const CColor& col, int rounding = 0); 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<wl_output_transform> tr = {});
void blurFB(const CFramebuffer& outfb, SBlurParams params); void blurFB(const CFramebuffer& outfb, SBlurParams params);
std::unique_ptr<CAsyncResourceGatherer> asyncResourceGatherer; std::unique_ptr<CAsyncResourceGatherer> asyncResourceGatherer;

View file

@ -4,21 +4,21 @@
#include <wayland-client.h> #include <wayland-client.h>
#include "../helpers/Box.hpp" #include "../helpers/Box.hpp"
enum wl_output_transform wlr_output_transform_invert(enum wl_output_transform tr) { 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)) { if ((tr & WL_OUTPUT_TRANSFORM_90) && !(tr & WL_OUTPUT_TRANSFORM_FLIPPED)) {
// tr ^= WL_OUTPUT_TRANSFORM_180; tr = (wl_output_transform)((int)tr ^ (int)WL_OUTPUT_TRANSFORM_180);
// } }
return tr; return tr;
} }
void wlr_matrix_identity(float mat[9]) { static void wlr_matrix_identity(float mat[9]) {
const float identity[9] = { const float identity[9] = {
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
}; };
memcpy(mat, identity, sizeof(identity)); 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]; float product[9];
product[0] = a[0] * b[0] + a[1] * b[3] + a[2] * b[6]; 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)); 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] = { float transposition[9] = {
a[0], a[3], a[6], a[1], a[4], a[7], a[2], a[5], a[8], a[0], a[3], a[6], a[1], a[4], a[7], a[2], a[5], a[8],
}; };
memcpy(mat, transposition, sizeof(transposition)); 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] = { float translate[9] = {
1.0f, 0.0f, x, 0.0f, 1.0f, y, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, x, 0.0f, 1.0f, y, 0.0f, 0.0f, 1.0f,
}; };
wlr_matrix_multiply(mat, mat, translate); 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] = { float scale[9] = {
x, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 0.0f, 1.0f, x, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 0.0f, 1.0f,
}; };
wlr_matrix_multiply(mat, mat, scale); 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] = { float rotate[9] = {
cos(rad), -sin(rad), 0.0f, sin(rad), cos(rad), 0.0f, 0.0f, 0.0f, 1.0f, cos(rad), -sin(rad), 0.0f, sin(rad), cos(rad), 0.0f, 0.0f, 0.0f, 1.0f,
}; };
wlr_matrix_multiply(mat, mat, rotate); wlr_matrix_multiply(mat, mat, rotate);
} }
const float transforms[][9] = { static const float transforms[][9] = {
[WL_OUTPUT_TRANSFORM_NORMAL] = [WL_OUTPUT_TRANSFORM_NORMAL] =
{ {
1.0f, 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]); 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); std::memset(mat, 0, sizeof(*mat) * 9);
const float* t = transforms[transform]; 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; 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 x = box->x;
int y = box->y; int y = box->y;
int width = box->width; 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); 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); memset(mat, 0, sizeof(*mat) * 9);
const float* t = transforms[tr]; const float* t = transforms[tr];

View file

@ -1,8 +1,9 @@
#include "Background.hpp" #include "Background.hpp"
#include "../Renderer.hpp" #include "../Renderer.hpp"
#include "../mtx.hpp"
CBackground::CBackground(const Vector2D& viewport_, const std::string& resourceID_, const std::unordered_map<std::string, std::any>& props) : CBackground::CBackground(const Vector2D& viewport_, COutput* output_, const std::string& resourceID_, const std::unordered_map<std::string, std::any>& props, bool ss) :
viewport(viewport_), resourceID(resourceID_) { viewport(viewport_), resourceID(resourceID_), output(output_), isScreenshot(ss) {
color = std::any_cast<Hyprlang::INT>(props.at("color")); color = std::any_cast<Hyprlang::INT>(props.at("color"));
blurPasses = std::any_cast<Hyprlang::INT>(props.at("blur_passes")); blurPasses = std::any_cast<Hyprlang::INT>(props.at("blur_passes"));
@ -30,13 +31,19 @@ bool CBackground::draw(const SRenderData& data) {
if (!asset) if (!asset)
return false; return false;
if (blurPasses > 0 && !blurredFB.isAllocated()) { if ((blurPasses > 0 || isScreenshot) && !blurredFB.isAllocated()) {
// make it brah // 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.w *= std::max(scaleX, scaleY);
texbox.h *= std::max(scaleX, scaleY); texbox.h *= std::max(scaleX, scaleY);
@ -48,8 +55,12 @@ bool CBackground::draw(const SRenderData& data) {
texbox.round(); texbox.round();
blurredFB.alloc(viewport.x, viewport.y); // TODO 10 bit blurredFB.alloc(viewport.x, viewport.y); // TODO 10 bit
blurredFB.bind(); blurredFB.bind();
g_pRenderer->renderTexture(texbox, asset->texture, 1.0, 0, 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 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}); g_pRenderer->blurFB(blurredFB, CRenderer::SBlurParams{blurSize, blurPasses, noise, contrast, brightness, vibrancy, vibrancy_darkness});
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
} }
@ -70,7 +81,7 @@ bool CBackground::draw(const SRenderData& data) {
else else
texbox.x = -(texbox.w - viewport.x) / 2.f; texbox.x = -(texbox.w - viewport.x) / 2.f;
texbox.round(); 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; return data.opacity < 1.0;
} }

View file

@ -9,10 +9,11 @@
#include <any> #include <any>
struct SPreloadedAsset; struct SPreloadedAsset;
class COutput;
class CBackground : public IWidget { class CBackground : public IWidget {
public: public:
CBackground(const Vector2D& viewport, const std::string& resourceID, const std::unordered_map<std::string, std::any>& props); CBackground(const Vector2D& viewport, COutput* output_, const std::string& resourceID, const std::unordered_map<std::string, std::any>& props, bool ss_);
virtual bool draw(const SRenderData& data); virtual bool draw(const SRenderData& data);
@ -31,4 +32,6 @@ class CBackground : public IWidget {
std::string resourceID; std::string resourceID;
CColor color; CColor color;
SPreloadedAsset* asset = nullptr; SPreloadedAsset* asset = nullptr;
COutput* output = nullptr;
bool isScreenshot = false;
}; };