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;
// 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};

View File

@ -310,6 +310,25 @@ void CHyprlock::run() {
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();
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) {

View File

@ -2,7 +2,7 @@
#include "config/ConfigManager.hpp"
#include "core/hyprlock.hpp"
void help(){
void help() {
std::cout << "Usage: hyprlock [options]\n\n"
"Options:\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) {
wlDisplay = argv[i + 1];
i++;
}
else if (arg == "--help" || arg == "-h") {
} else if (arg == "--help" || arg == "-h") {
help();
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;
}

View File

@ -14,6 +14,7 @@
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) {
const auto PDATA = (SScreencopyData*)data;
@ -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,10 +209,12 @@ bool CDMAFrame::onBufferReady() {
static const int entries_per_attrib = 2;
EGLAttrib attribs[(general_attribs + plane_attribs * 4) * entries_per_attrib + 1];
int attr = 0;
Vector2D size{scdata.w, scdata.h};
attribs[attr++] = EGL_WIDTH;
attribs[attr++] = scdata.w;
attribs[attr++] = size.x;
attribs[attr++] = EGL_HEIGHT;
attribs[attr++] = scdata.h;
attribs[attr++] = size.y;
attribs[attr++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[attr++] = scdata.fmt;
attribs[attr++] = EGL_DMA_BUF_PLANE0_FD_EXT;
@ -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;

View File

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

View File

@ -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<wl_output_transform> 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<std::unique_ptr<IWidget>>* CRenderer::getOrCreateWidgetsFor(const CS
else if (!PATH.empty())
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") {
widgets[surf].emplace_back(std::make_unique<CPasswordInputField>(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);
}

View File

@ -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<wl_output_transform> tr = {});
void blurFB(const CFramebuffer& outfb, SBlurParams params);
std::unique_ptr<CAsyncResourceGatherer> asyncResourceGatherer;

View File

@ -4,21 +4,21 @@
#include <wayland-client.h>
#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];

View File

@ -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<std::string, std::any>& props) :
viewport(viewport_), resourceID(resourceID_) {
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_), output(output_), isScreenshot(ss) {
color = std::any_cast<Hyprlang::INT>(props.at("color"));
blurPasses = std::any_cast<Hyprlang::INT>(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;
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,8 +55,12 @@ 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
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;
}

View File

@ -9,10 +9,11 @@
#include <any>
struct SPreloadedAsset;
class COutput;
class CBackground : public IWidget {
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);
@ -31,4 +32,6 @@ class CBackground : public IWidget {
std::string resourceID;
CColor color;
SPreloadedAsset* asset = nullptr;
COutput* output = nullptr;
bool isScreenshot = false;
};