From 89b87158dbf100e4177f4a010190ba5f80252eb2 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Wed, 19 Jul 2023 20:09:49 +0200 Subject: [PATCH] internal: Wrap regions (#2750) --- src/defines.hpp | 7 - src/helpers/Monitor.cpp | 6 +- src/helpers/Monitor.hpp | 4 +- src/helpers/Region.cpp | 93 +++++++++++++ src/helpers/Region.hpp | 53 ++++++++ src/helpers/WLClasses.hpp | 3 +- src/managers/AnimationManager.cpp | 15 +- src/managers/input/InputManager.cpp | 4 +- src/protocols/Screencopy.cpp | 10 +- src/protocols/ToplevelExport.cpp | 9 +- src/render/OpenGL.cpp | 204 ++++++++++------------------ src/render/OpenGL.hpp | 20 +-- src/render/Renderer.cpp | 112 ++++++--------- src/render/Renderer.hpp | 7 +- 14 files changed, 297 insertions(+), 250 deletions(-) create mode 100644 src/helpers/Region.cpp create mode 100644 src/helpers/Region.hpp diff --git a/src/defines.hpp b/src/defines.hpp index 3ab76ffb..ca91fa55 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -27,13 +27,6 @@ #define DELTALESSTHAN(a, b, delta) (abs((a) - (b)) < (delta)) -#define PIXMAN_DAMAGE_FOREACH(region) \ - int rectsNum = 0; \ - const auto RECTSARR = pixman_region32_rectangles(region, &rectsNum); \ - for (int i = 0; i < rectsNum; ++i) - -#define PIXMAN_REGION_FOREACH(region) PIXMAN_DAMAGE_FOREACH(region) - #define interface class #define STICKS(a, b) abs((a) - (b)) < 2 diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 390bd3c4..a860585d 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -10,12 +10,10 @@ int ratHandler(void* data) { CMonitor::CMonitor() { wlr_damage_ring_init(&damage); - pixman_region32_init(&lastFrameDamage); } CMonitor::~CMonitor() { wlr_damage_ring_finish(&damage); - pixman_region32_fini(&lastFrameDamage); hyprListener_monitorDestroy.removeCallback(); hyprListener_monitorFrame.removeCallback(); @@ -331,6 +329,10 @@ void CMonitor::addDamage(const pixman_region32_t* rg) { g_pCompositor->scheduleFrameForMonitor(this); } +void CMonitor::addDamage(const CRegion* rg) { + addDamage(const_cast(rg)->pixman()); +} + void CMonitor::addDamage(const wlr_box* box) { static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue; if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 08fe5f2b..b453bc8c 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -8,6 +8,7 @@ #include #include #include "Timer.hpp" +#include "Region.hpp" struct SMonitorRule; @@ -61,7 +62,7 @@ class CMonitor { CMonitor* pMirrorOf = nullptr; std::vector mirrors; - pixman_region32_t lastFrameDamage; // stores last frame damage + CRegion lastFrameDamage; // stores last frame damage // for the special workspace. 0 means not open. int specialWorkspaceID = 0; @@ -84,6 +85,7 @@ class CMonitor { void onConnect(bool noRule); void onDisconnect(); void addDamage(const pixman_region32_t* rg); + void addDamage(const CRegion* rg); void addDamage(const wlr_box* box); void setMirror(const std::string&); bool isMirror(); diff --git a/src/helpers/Region.cpp b/src/helpers/Region.cpp new file mode 100644 index 00000000..3a210d06 --- /dev/null +++ b/src/helpers/Region.cpp @@ -0,0 +1,93 @@ +#include "Region.hpp" +#include + +CRegion::CRegion() { + pixman_region32_init(&m_rRegion); +} + +CRegion::CRegion(pixman_region32_t* ref) { + pixman_region32_init(&m_rRegion); + pixman_region32_copy(&m_rRegion, ref); +} + +CRegion::CRegion(double x, double y, double w, double h) { + pixman_region32_init_rect(&m_rRegion, x, y, w, h); +} + +CRegion::CRegion(wlr_box* box) { + pixman_region32_init_rect(&m_rRegion, box->x, box->y, box->width, box->height); +} + +CRegion::CRegion(const CRegion& other) { + pixman_region32_init(&m_rRegion); + pixman_region32_copy(&m_rRegion, const_cast(&other)->pixman()); +} + +CRegion::CRegion(CRegion&& other) { + pixman_region32_init(&m_rRegion); + pixman_region32_copy(&m_rRegion, other.pixman()); +} + +CRegion::~CRegion() { + pixman_region32_fini(&m_rRegion); +} + +CRegion& CRegion::clear() { + pixman_region32_clear(&m_rRegion); + return *this; +} + +CRegion& CRegion::set(const CRegion& other) { + pixman_region32_copy(&m_rRegion, const_cast(&other)->pixman()); + return *this; +} + +CRegion& CRegion::add(const CRegion& other) { + pixman_region32_union(&m_rRegion, &m_rRegion, const_cast(&other)->pixman()); + return *this; +} + +CRegion& CRegion::add(double x, double y, double w, double h) { + pixman_region32_union_rect(&m_rRegion, &m_rRegion, x, y, w, h); + return *this; +} + +CRegion& CRegion::subtract(const CRegion& other) { + pixman_region32_subtract(&m_rRegion, &m_rRegion, const_cast(&other)->pixman()); + return *this; +} + +CRegion& CRegion::intersect(const CRegion& other) { + pixman_region32_intersect(&m_rRegion, &m_rRegion, const_cast(&other)->pixman()); + return *this; +} + +CRegion& CRegion::intersect(double x, double y, double w, double h) { + pixman_region32_intersect_rect(&m_rRegion, &m_rRegion, x, y, w, h); + return *this; +} + +CRegion& CRegion::invert(pixman_box32_t* box) { + pixman_region32_inverse(&m_rRegion, &m_rRegion, box); + return *this; +} + +CRegion& CRegion::translate(const Vector2D& vec) { + pixman_region32_translate(&m_rRegion, vec.x, vec.y); + return *this; +} + +std::vector CRegion::getRects() const { + std::vector result; + + int rectsNum = 0; + const auto RECTSARR = pixman_region32_rectangles(&m_rRegion, &rectsNum); + + result.assign(RECTSARR, RECTSARR + rectsNum); + + return result; +} + +bool CRegion::empty() { + return !pixman_region32_not_empty(&m_rRegion); +} diff --git a/src/helpers/Region.hpp b/src/helpers/Region.hpp new file mode 100644 index 00000000..5c700fa5 --- /dev/null +++ b/src/helpers/Region.hpp @@ -0,0 +1,53 @@ +#pragma once +#include +#include +#include "Vector2D.hpp" + +struct wlr_box; + +class CRegion { + public: + /* Create an empty region */ + CRegion(); + /* Create from a reference. Copies, does not own. */ + CRegion(pixman_region32_t* ref); + /* Create from a box */ + CRegion(double x, double y, double w, double h); + /* Create from a wlr_box */ + CRegion(wlr_box* box); + + CRegion(const CRegion&); + CRegion(CRegion&&); + + ~CRegion(); + + CRegion& operator=(CRegion&& other) { + pixman_region32_copy(&m_rRegion, other.pixman()); + return *this; + } + + CRegion& operator=(CRegion& other) { + pixman_region32_copy(&m_rRegion, other.pixman()); + return *this; + } + + CRegion& clear(); + CRegion& set(const CRegion& other); + CRegion& add(const CRegion& other); + CRegion& add(double x, double y, double w, double h); + CRegion& subtract(const CRegion& other); + CRegion& intersect(const CRegion& other); + CRegion& intersect(double x, double y, double w, double h); + CRegion& translate(const Vector2D& vec); + CRegion& invert(pixman_box32_t* box); + bool empty(); + + std::vector getRects() const; + + pixman_region32_t* pixman() { + return &m_rRegion; + } + + private: + pixman_region32_t m_rRegion; +}; \ No newline at end of file diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index b7cd6e34..18e223b6 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -7,6 +7,7 @@ #include "SubsurfaceTree.hpp" #include "AnimatedVariable.hpp" #include "WLSurface.hpp" +#include "Region.hpp" struct SLayerRule { std::string targetNamespace = ""; @@ -144,7 +145,7 @@ struct SMouse { wlr_pointer_constraint_v1* currentConstraint = nullptr; bool constraintActive = false; - pixman_region32_t confinedTo; + CRegion confinedTo; std::string name = ""; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 2ed985c8..fa1e2941 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -255,15 +255,12 @@ void CAnimationManager::tick() { // easy, damage the entire box g_pHyprRenderer->damageBox(&dmg); } else { - pixman_region32_t rg; - pixman_region32_init_rect(&rg, dmg.x, dmg.y, dmg.width, dmg.height); - pixman_region32_t wb; - pixman_region32_init_rect(&wb, PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, - PWINDOW->m_vRealSize.vec().y); - pixman_region32_subtract(&rg, &rg, &wb); - g_pHyprRenderer->damageRegion(&rg); - pixman_region32_fini(&rg); - pixman_region32_fini(&wb); + CRegion rg{dmg.x, dmg.y, dmg.width, dmg.height}; + CRegion wb{PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y}; + + rg.subtract(wb); + + g_pHyprRenderer->damageRegion(rg); } } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 8cb7f330..734df863 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1151,9 +1151,9 @@ void CInputManager::recheckConstraint(SMouse* pMouse) { const auto PREGION = &pMouse->currentConstraint->region; if (pMouse->currentConstraint->type == WLR_POINTER_CONSTRAINT_V1_CONFINED) { - pixman_region32_copy(&pMouse->confinedTo, PREGION); + pMouse->confinedTo.set(PREGION); } else { - pixman_region32_clear(&pMouse->confinedTo); + pMouse->confinedTo.clear(); } } diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 801b4615..c93bd5f7 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -403,17 +403,15 @@ void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) { if (!frame->withDamage) return; - PIXMAN_DAMAGE_FOREACH(&frame->pMonitor->lastFrameDamage) { - const auto RECT = &RECTSARR[i]; + for (auto& RECT : frame->pMonitor->lastFrameDamage.getRects()) { - if (frame->buffer->width < 1 || frame->buffer->height < 1 || frame->buffer->width - RECT->x1 < 1 || frame->buffer->height - RECT->y1 < 1) { + if (frame->buffer->width < 1 || frame->buffer->height < 1 || frame->buffer->width - RECT.x1 < 1 || frame->buffer->height - RECT.y1 < 1) { Debug::log(ERR, "[sc] Failed to send damage"); break; } - zwlr_screencopy_frame_v1_send_damage(frame->resource, std::clamp(RECT->x1, 0, frame->buffer->width), std::clamp(RECT->y1, 0, frame->buffer->height), - std::clamp(RECT->x2 - RECT->x1, 0, frame->buffer->width - RECT->x1), - std::clamp(RECT->y2 - RECT->y1, 0, frame->buffer->height - RECT->y1)); + zwlr_screencopy_frame_v1_send_damage(frame->resource, std::clamp(RECT.x1, 0, frame->buffer->width), std::clamp(RECT.y1, 0, frame->buffer->height), + std::clamp(RECT.x2 - RECT.x1, 0, frame->buffer->width - RECT.x1), std::clamp(RECT.y2 - RECT.y1, 0, frame->buffer->height - RECT.y1)); } } diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 180b1489..eeeaa81f 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -347,16 +347,14 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times return false; // render the client - const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID); - pixman_region32_t fakeDamage; - pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x * 10, PMONITOR->vecPixelSize.y * 10); + const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID); + CRegion fakeDamage{0, 0, PMONITOR->vecPixelSize.x * 10, PMONITOR->vecPixelSize.y * 10}; if (frame->overlayCursor) wlr_output_lock_software_cursors(PMONITOR->output, true); if (!wlr_output_attach_render(PMONITOR->output, nullptr)) { Debug::log(ERR, "[toplevel_export] Couldn't attach render"); - pixman_region32_fini(&fakeDamage); wlr_buffer_end_data_ptr_access(frame->buffer); if (frame->overlayCursor) wlr_output_lock_software_cursors(PMONITOR->output, false); @@ -398,7 +396,6 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times if (!PFORMAT) { Debug::log(ERR, "[toplevel_export] Cannot read pixels, unsupported format %lx", PFORMAT); g_pHyprOpenGL->end(); - pixman_region32_fini(&fakeDamage); wlr_buffer_end_data_ptr_access(frame->buffer); if (frame->overlayCursor) wlr_output_lock_software_cursors(PMONITOR->output, false); @@ -415,8 +412,6 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times wlr_output_rollback(PMONITOR->output); - pixman_region32_fini(&fakeDamage); - wlr_buffer_end_data_ptr_access(frame->buffer); if (frame->overlayCursor) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index b3688a17..00204cdd 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -93,7 +93,7 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool return shader; } -void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool fake) { +void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { m_RenderData.pMonitor = pMonitor; if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) { @@ -133,7 +133,7 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool // bind the primary Hypr Framebuffer m_RenderData.pCurrentMonData->primaryFB.bind(); - m_RenderData.pDamage = pDamage; + m_RenderData.damage.set(*pDamage); m_bFakeFrame = fake; @@ -148,7 +148,7 @@ void CHyprOpenGLImpl::end() { // end the render, copy the data to the WLR framebuffer if (!m_bFakeFrame) { - pixman_region32_copy(m_RenderData.pDamage, &m_RenderData.pMonitor->lastFrameDamage); + m_RenderData.damage = m_RenderData.pMonitor->lastFrameDamage; if (!m_RenderData.pMonitor->mirrors.empty()) g_pHyprOpenGL->saveBufferForMirror(); // save with original damage region @@ -373,11 +373,9 @@ void CHyprOpenGLImpl::clear(const CColor& color) { glClearColor(color.r, color.g, color.b, color.a); - if (pixman_region32_not_empty(m_RenderData.pDamage)) { - PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) { - const auto RECT = RECTSARR[i]; + if (!m_RenderData.damage.empty()) { + for (auto& RECT : m_RenderData.damage.getRects()) { scissor(&RECT); - glClear(GL_COLOR_BUFFER_BIT); } } @@ -426,11 +424,11 @@ void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h } void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) { - if (pixman_region32_not_empty(m_RenderData.pDamage)) - renderRectWithDamage(box, col, m_RenderData.pDamage, round); + if (!m_RenderData.damage.empty()) + renderRectWithDamage(box, col, &m_RenderData.damage, round); } -void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixman_region32_t* damage, int round) { +void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, CRegion* damage, int round) { RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); @@ -481,22 +479,17 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib); if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) { - pixman_region32_t damageClip; - pixman_region32_init(&damageClip); - pixman_region32_intersect_rect(&damageClip, damage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height); + CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height}; + damageClip.intersect(*damage); - if (pixman_region32_not_empty(&damageClip)) { - PIXMAN_DAMAGE_FOREACH(&damageClip) { - const auto RECT = RECTSARR[i]; + if (!damageClip.empty()) { + for (auto& RECT : damageClip.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } } - - pixman_region32_fini(&damageClip); } else { - PIXMAN_DAMAGE_FOREACH(damage) { - const auto RECT = RECTSARR[i]; + for (auto& RECT : damage->getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -516,19 +509,19 @@ void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); - renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardActive, false, allowCustomUV, true); + renderTextureInternalWithDamage(tex, pBox, alpha, &m_RenderData.damage, round, discardActive, false, allowCustomUV, true); scissor((wlr_box*)nullptr); } -void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardActive, bool noAA, +void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV, bool allowDim) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!"); alpha = std::clamp(alpha, 0.f, 1.f); - if (!pixman_region32_not_empty(m_RenderData.pDamage)) + if (m_RenderData.damage.empty()) return; wlr_box newBox = *pBox; @@ -670,22 +663,17 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b glEnableVertexAttribArray(shader->texAttrib); if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) { - pixman_region32_t damageClip; - pixman_region32_init(&damageClip); - pixman_region32_intersect_rect(&damageClip, damage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height); + CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height}; + damageClip.intersect(*damage); - if (pixman_region32_not_empty(&damageClip)) { - PIXMAN_DAMAGE_FOREACH(&damageClip) { - const auto RECT = RECTSARR[i]; + if (!damageClip.empty()) { + for (auto& RECT : damageClip.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } } - - pixman_region32_fini(&damageClip); } else { - PIXMAN_DAMAGE_FOREACH(damage) { - const auto RECT = RECTSARR[i]; + for (auto& RECT : damage->getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -701,7 +689,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b // but it works... well, I guess? // // Dual (or more) kawase blur -CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* originalDamage) { +CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* pBox, CRegion* originalDamage) { glDisable(GL_BLEND); glDisable(GL_STENCIL_TEST); @@ -720,12 +708,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue; // prep damage - pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_copy(&damage, originalDamage); - wlr_region_transform(&damage, &damage, wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, + CRegion damage{*originalDamage}; + wlr_region_transform(damage.pixman(), damage.pixman(), wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); - wlr_region_expand(&damage, &damage, *PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES)); + wlr_region_expand(damage.pixman(), damage.pixman(), *PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES)); // helper const auto PMIRRORFB = &m_RenderData.pCurrentMonData->mirrorFB; @@ -734,7 +720,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p CFramebuffer* currentRenderToFB = &m_RenderData.pCurrentMonData->primaryFB; // declare the draw func - auto drawPass = [&](CShader* pShader, pixman_region32_t* pDamage) { + auto drawPass = [&](CShader* pShader, CRegion* pDamage) { if (currentRenderToFB == PMIRRORFB) PMIRRORSWAPFB->bind(); else @@ -770,11 +756,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p glEnableVertexAttribArray(pShader->posAttrib); glEnableVertexAttribArray(pShader->texAttrib); - if (pixman_region32_not_empty(pDamage)) { - PIXMAN_DAMAGE_FOREACH(pDamage) { - const auto RECT = RECTSARR[i]; + if (!pDamage->empty()) { + for (auto& RECT : pDamage->getRects()) { scissor(&RECT, false /* this region is already transformed */); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } } @@ -794,27 +778,23 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p glBindTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTarget, m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTexID); // damage region will be scaled, make a temp - pixman_region32_t tempDamage; - pixman_region32_init(&tempDamage); - wlr_region_scale(&tempDamage, &damage, 1.f / 2.f); // when DOWNscaling, we make the region twice as small because it's the TARGET + CRegion tempDamage{damage}; + wlr_region_scale(tempDamage.pixman(), damage.pixman(), 1.f / 2.f); // when DOWNscaling, we make the region twice as small because it's the TARGET drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage); // and draw for (int i = 1; i < *PBLURPASSES; ++i) { - wlr_region_scale(&tempDamage, &damage, 1.f / (1 << (i + 1))); + wlr_region_scale(tempDamage.pixman(), damage.pixman(), 1.f / (1 << (i + 1))); drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage); // down } for (int i = *PBLURPASSES - 1; i >= 0; --i) { - wlr_region_scale(&tempDamage, &damage, 1.f / (1 << i)); // when upsampling we make the region twice as big - drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up + wlr_region_scale(tempDamage.pixman(), damage.pixman(), 1.f / (1 << i)); // when upsampling we make the region twice as big + drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up } // finish - pixman_region32_fini(&tempDamage); - pixman_region32_fini(&damage); - glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); @@ -862,20 +842,14 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { if (PSURFACE->opaque) return false; - pixman_region32_t inverseOpaque; - pixman_region32_init(&inverseOpaque); + CRegion inverseOpaque; pixman_box32_t surfbox = {0, 0, PSURFACE->current.width, PSURFACE->current.height}; - pixman_region32_copy(&inverseOpaque, &PSURFACE->current.opaque); - pixman_region32_inverse(&inverseOpaque, &inverseOpaque, &surfbox); - pixman_region32_intersect_rect(&inverseOpaque, &inverseOpaque, 0, 0, PSURFACE->current.width, PSURFACE->current.height); + CRegion opaqueRegion{&PSURFACE->current.opaque}; + inverseOpaque.set(opaqueRegion).invert(&surfbox).intersect(0, 0, PSURFACE->current.width, PSURFACE->current.height); - if (!pixman_region32_not_empty(&inverseOpaque)) { - pixman_region32_fini(&inverseOpaque); + if (inverseOpaque.empty()) return false; - } - - pixman_region32_fini(&inverseOpaque); } return true; @@ -907,8 +881,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { m_RenderData.renderModif = {}; // fix shit // make the fake dmg - pixman_region32_t fakeDamage; - pixman_region32_init_rect(&fakeDamage, 0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); + CRegion fakeDamage{0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; wlr_box wholeMonitor = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; const auto POUTFB = blurMainFramebufferWithDamage(1, &wholeMonitor, &fakeDamage); @@ -922,8 +895,6 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { renderTextureInternalWithDamage(POUTFB->m_cTex, &wholeMonitor, 1, &fakeDamage, 0, false, true, false); m_bEndFrame = false; - pixman_region32_fini(&fakeDamage); - m_RenderData.pCurrentMonData->primaryFB.bind(); m_RenderData.pCurrentMonData->blurFBDirty = false; @@ -951,11 +922,10 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, static auto* const PBLURXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur_xray")->intValue; // make a damage region for this window - pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_intersect_rect(&damage, m_RenderData.pDamage, pBox->x, pBox->y, pBox->width, pBox->height); // clip it to the box + CRegion texDamage{m_RenderData.damage}; + texDamage.intersect(pBox->x, pBox->y, pBox->width, pBox->height); - if (!pixman_region32_not_empty(&damage)) + if (texDamage.empty()) return; if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || @@ -965,24 +935,21 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, } // amazing hack: the surface has an opaque region! - pixman_region32_t inverseOpaque; - pixman_region32_init(&inverseOpaque); + CRegion inverseOpaque; if (a >= 1.f) { pixman_box32_t surfbox = {0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale}; - pixman_region32_copy(&inverseOpaque, &pSurface->current.opaque); - pixman_region32_inverse(&inverseOpaque, &inverseOpaque, &surfbox); - pixman_region32_intersect_rect(&inverseOpaque, &inverseOpaque, 0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale); + inverseOpaque = &pSurface->current.opaque; + inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale); - if (!pixman_region32_not_empty(&inverseOpaque)) { - pixman_region32_fini(&inverseOpaque); + if (inverseOpaque.empty()) { renderTexture(tex, pBox, a, round, false, true); return; } } else { - pixman_region32_init_rect(&inverseOpaque, 0, 0, pBox->width, pBox->height); + inverseOpaque = {0, 0, pBox->width, pBox->height}; } - wlr_region_scale(&inverseOpaque, &inverseOpaque, m_RenderData.pMonitor->scale); + wlr_region_scale(inverseOpaque.pixman(), inverseOpaque.pixman(), m_RenderData.pMonitor->scale); // vvv TODO: layered blur fbs? const bool USENEWOPTIMIZE = (*PBLURNEWOPTIMIZE && !blockBlurOptimization && @@ -991,17 +958,13 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, CFramebuffer* POUTFB = nullptr; if (!USENEWOPTIMIZE) { - pixman_region32_translate(&inverseOpaque, pBox->x, pBox->y); - - pixman_region32_intersect(&inverseOpaque, &inverseOpaque, &damage); + inverseOpaque.translate({pBox->x, pBox->y}).intersect(texDamage); POUTFB = blurMainFramebufferWithDamage(a, pBox, &inverseOpaque); } else { POUTFB = &m_RenderData.pCurrentMonData->blurFB; } - pixman_region32_fini(&inverseOpaque); - // bind primary m_RenderData.pCurrentMonData->primaryFB.bind(); @@ -1032,7 +995,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, m_bEndFrame = true; // fix transformed const auto SAVEDRENDERMODIF = m_RenderData.renderModif; m_RenderData.renderModif = {}; // fix shit - renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 1.f : a, &damage, 0, false, false, false); + renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 1.f : a, &texDamage, 0, false, false, false); m_bEndFrame = false; m_RenderData.renderModif = SAVEDRENDERMODIF; @@ -1042,11 +1005,10 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, // draw window glDisable(GL_STENCIL_TEST); - renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true, true); + renderTextureInternalWithDamage(tex, pBox, a, &texDamage, round, false, false, true, true); glStencilMask(-1); glStencilFunc(GL_ALWAYS, 1, 0xFF); - pixman_region32_fini(&damage); scissor((wlr_box*)nullptr); } @@ -1061,7 +1023,7 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); - if (!pixman_region32_not_empty(m_RenderData.pDamage) || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBorder)) + if (m_RenderData.damage.empty() || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBorder)) return; static auto* const PMULTISAMPLE = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue; @@ -1133,22 +1095,17 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib); if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) { - pixman_region32_t damageClip; - pixman_region32_init(&damageClip); - pixman_region32_intersect_rect(&damageClip, m_RenderData.pDamage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height); + CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height}; + damageClip.intersect(m_RenderData.damage); - if (pixman_region32_not_empty(&damageClip)) { - PIXMAN_DAMAGE_FOREACH(&damageClip) { - const auto RECT = RECTSARR[i]; + if (!damageClip.empty()) { + for (auto& RECT : damageClip.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } } - - pixman_region32_fini(&damageClip); } else { - PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) { - const auto RECT = RECTSARR[i]; + for (auto& RECT : m_RenderData.damage.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -1172,9 +1129,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra // we need to "damage" the entire monitor // so that we render the entire window // this is temporary, doesnt mess with the actual wlr damage - pixman_region32_t fakeDamage; - pixman_region32_init(&fakeDamage); - pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y); + CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; begin(PMONITOR, &fakeDamage, true); @@ -1214,8 +1169,6 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra #endif end(); - pixman_region32_fini(&fakeDamage); - wlr_output_rollback(PMONITOR->output); } @@ -1231,9 +1184,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) { // we need to "damage" the entire monitor // so that we render the entire window // this is temporary, doesnt mess with the actual wlr damage - pixman_region32_t fakeDamage; - pixman_region32_init(&fakeDamage); - pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y); + CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; begin(PMONITOR, &fakeDamage, true); @@ -1276,8 +1227,6 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) { #endif end(); - pixman_region32_fini(&fakeDamage); - g_pHyprRenderer->m_bRenderingSnapshot = false; wlr_output_rollback(PMONITOR->output); @@ -1295,9 +1244,7 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) { // we need to "damage" the entire monitor // so that we render the entire window // this is temporary, doesnt mess with the actual wlr damage - pixman_region32_t fakeDamage; - pixman_region32_init(&fakeDamage); - pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y); + CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; begin(PMONITOR, &fakeDamage, true); @@ -1337,8 +1284,6 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) { g_pHyprRenderer->m_bRenderingSnapshot = false; - pixman_region32_fini(&fakeDamage); - wlr_output_rollback(PMONITOR->output); } @@ -1371,8 +1316,7 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) { windowBox.x = ((PWINDOW->m_vRealPosition.vec().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.x * PMONITOR->scale) * scaleXY.x); windowBox.y = ((PWINDOW->m_vRealPosition.vec().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.y * PMONITOR->scale) * scaleXY.y); - pixman_region32_t fakeDamage; - pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y); + CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; if (*PDIMAROUND && (*pWindow)->m_sAdditionalConfigData.dimAround) { wlr_box monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y}; @@ -1385,8 +1329,6 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) { renderTextureInternalWithDamage(it->second.m_cTex, &windowBox, PWINDOW->m_fAlpha.fl(), &fakeDamage, 0); m_bEndFrame = false; - - pixman_region32_fini(&fakeDamage); } void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) { @@ -1403,20 +1345,17 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) { if (it == m_mLayerFramebuffers.end() || !it->second.m_cTex.m_iTexID) return; - const auto PMONITOR = g_pCompositor->getMonitorFromID(PLAYER->monitorID); + const auto PMONITOR = g_pCompositor->getMonitorFromID(PLAYER->monitorID); - wlr_box monbox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; + wlr_box monbox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; - pixman_region32_t fakeDamage; - pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y); + CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; m_bEndFrame = true; renderTextureInternalWithDamage(it->second.m_cTex, &monbox, PLAYER->alpha.fl(), &fakeDamage, 0); m_bEndFrame = false; - - pixman_region32_fini(&fakeDamage); } void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, float a) { @@ -1424,7 +1363,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!"); RASSERT(m_pCurrentWindow, "Tried to render shadow without a window!"); - if (!pixman_region32_not_empty(m_RenderData.pDamage)) + if (m_RenderData.damage.empty()) return; wlr_box newBox = *box; @@ -1479,22 +1418,17 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib); if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) { - pixman_region32_t damageClip; - pixman_region32_init(&damageClip); - pixman_region32_intersect_rect(&damageClip, m_RenderData.pDamage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height); + CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height}; + damageClip.intersect(m_RenderData.damage); - if (pixman_region32_not_empty(&damageClip)) { - PIXMAN_DAMAGE_FOREACH(&damageClip) { - const auto RECT = RECTSARR[i]; + if (!damageClip.empty()) { + for (auto& RECT : damageClip.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } } - - pixman_region32_fini(&damageClip); } else { - PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) { - const auto RECT = RECTSARR[i]; + for (auto& RECT : m_RenderData.damage.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index b696c8cb..fc72782f 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -4,6 +4,7 @@ #include "../helpers/Monitor.hpp" #include "../helpers/Color.hpp" #include "../helpers/Timer.hpp" +#include "../helpers/Region.hpp" #include #include @@ -23,7 +24,8 @@ inline const float fullVerts[] = { }; inline const float fanVertsFull[] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f}; -enum eDiscardMode { +enum eDiscardMode +{ DISCARD_OPAQUE = 1, DISCARD_ALPHA = 1 << 1 }; @@ -35,8 +37,8 @@ struct SRenderModifData { struct SMonitorRenderData { CFramebuffer primaryFB; - CFramebuffer mirrorFB; // these are used for some effects, - CFramebuffer mirrorSwapFB; // etc + CFramebuffer mirrorFB; // these are used for some effects, + CFramebuffer mirrorSwapFB; // etc CFramebuffer monitorMirrorFB; // used for mirroring outputs @@ -71,7 +73,7 @@ struct SCurrentRenderData { SMonitorRenderData* pCurrentMonData = nullptr; - pixman_region32_t* pDamage = nullptr; + CRegion damage; SRenderModifData renderModif; float mouseZoomFactor = 1.f; @@ -93,11 +95,11 @@ class CHyprOpenGLImpl { public: CHyprOpenGLImpl(); - void begin(CMonitor*, pixman_region32_t*, bool fake = false); + void begin(CMonitor*, CRegion*, bool fake = false); void end(); void renderRect(wlr_box*, const CColor&, int round = 0); - void renderRectWithDamage(wlr_box*, const CColor&, pixman_region32_t* damage, int round = 0); + void renderRectWithDamage(wlr_box*, const CColor&, CRegion* damage, int round = 0); void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0, bool allowCustomUV = false); void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false); @@ -139,7 +141,7 @@ class CHyprOpenGLImpl { bool m_bReloadScreenShader = true; // at launch it can be set - CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window + CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window std::unordered_map m_mWindowFramebuffers; std::unordered_map m_mLayerFramebuffers; @@ -166,9 +168,9 @@ class CHyprOpenGLImpl { void initShaders(); // returns the out FB, can be either Mirror or MirrorSwap - CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage); + CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, CRegion* damage); - void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, + void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowCustomUV = false, bool allowDim = false); void renderSplash(cairo_t* const, cairo_surface_t* const, double); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 4388a54f..370e7cfe 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1,6 +1,7 @@ #include "Renderer.hpp" #include "../Compositor.hpp" #include "linux-dmabuf-unstable-v1-protocol.h" +#include "../helpers/Region.hpp" void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { const auto TEXTURE = wlr_surface_get_texture(surface); @@ -455,8 +456,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* g_pHyprOpenGL->m_RenderData.renderModif = RENDERMODIFDATA; // for storing damage when we optimize for occlusion - pixman_region32_t backupDamage; - pixman_region32_init(&backupDamage); + CRegion preOccludedDamage{g_pHyprOpenGL->m_RenderData.damage}; // Render layer surfaces below windows for monitor // if we have a fullscreen, opaque window that convers the screen, we can skip this. @@ -465,8 +465,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* if (!pWorkspace->m_bHasFullscreenWindow || pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL || !PFULLWINDOW || PFULLWINDOW->m_vRealSize.isBeingAnimated() || !PFULLWINDOW->opaque() || pWorkspace->m_vRenderOffset.vec() != Vector2D{}) { - pixman_region32_copy(&backupDamage, g_pHyprOpenGL->m_RenderData.pDamage); - setOccludedForBackLayers(g_pHyprOpenGL->m_RenderData.pDamage, pWorkspace); + setOccludedForBackLayers(g_pHyprOpenGL->m_RenderData.damage, pWorkspace); for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { renderLayer(ls.get(), pMonitor, time); @@ -475,11 +474,9 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* renderLayer(ls.get(), pMonitor, time); } - pixman_region32_copy(g_pHyprOpenGL->m_RenderData.pDamage, &backupDamage); + g_pHyprOpenGL->m_RenderData.damage = preOccludedDamage; } - pixman_region32_fini(&backupDamage); - // pre window pass g_pHyprOpenGL->preWindowPass(); @@ -906,9 +903,9 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { clock_gettime(CLOCK_MONOTONIC, &now); // check the damage - pixman_region32_t damage; - bool hasChanged = pMonitor->output->needs_frame || pixman_region32_not_empty(&pMonitor->damage.current); - int bufferAge; + CRegion damage; + bool hasChanged = pMonitor->output->needs_frame || pixman_region32_not_empty(&pMonitor->damage.current); + int bufferAge; if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0) return; @@ -933,8 +930,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { return; } - pixman_region32_init(&damage); - wlr_damage_ring_get_buffer_damage(&pMonitor->damage, bufferAge, &damage); + wlr_damage_ring_get_buffer_damage(&pMonitor->damage, bufferAge, damage.pixman()); pMonitor->renderingActive = true; @@ -944,9 +940,9 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { // if we have no tracking or full tracking, invalidate the entire monitor if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || pMonitor->forceFullFrames > 0 || damageBlinkCleanup > 0 || pMonitor->isMirror() /* why??? */) { - pixman_region32_union_rect(&damage, &damage, 0, 0, (int)pMonitor->vecTransformedSize.x * 10, (int)pMonitor->vecTransformedSize.y * 10); // wot? - pixman_region32_copy(&pMonitor->lastFrameDamage, &damage); + damage = {0, 0, (int)pMonitor->vecTransformedSize.x * 10, (int)pMonitor->vecTransformedSize.y * 10}; + pMonitor->lastFrameDamage = damage; } else { static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue; @@ -958,14 +954,16 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { const auto BLURRADIUS = *PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think. + auto extents = pixman_region32_extents(damage.pixman()); + // now, prep the damage, get the extended damage region - wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring + wlr_region_expand(damage.pixman(), damage.pixman(), BLURRADIUS); // expand for proper blurring - pixman_region32_copy(&pMonitor->lastFrameDamage, &damage); + pMonitor->lastFrameDamage = damage; - wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring 2 + wlr_region_expand(damage.pixman(), damage.pixman(), BLURRADIUS); // expand for proper blurring 2 } else { - pixman_region32_copy(&pMonitor->lastFrameDamage, &damage); + pMonitor->lastFrameDamage = damage; } } @@ -1043,41 +1041,34 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { g_pHyprOpenGL->end(); // calc frame damage - pixman_region32_t frameDamage; - pixman_region32_init(&frameDamage); + CRegion frameDamage{}; const auto TRANSFORM = wlr_output_transform_invert(pMonitor->output->transform); - wlr_region_transform(&frameDamage, &pMonitor->lastFrameDamage, TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y); + wlr_region_transform(frameDamage.pixman(), pMonitor->lastFrameDamage.pixman(), TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y); if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR) - pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y); + frameDamage.add(0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y); if (*PDAMAGEBLINK) - pixman_region32_union(&frameDamage, &frameDamage, &damage); + frameDamage.add(damage); - wlr_output_set_damage(pMonitor->output, &frameDamage); + //wlr_output_set_damage(pMonitor->output, frameDamage.pixman()); if (!pMonitor->mirrors.empty()) - g_pHyprRenderer->damageMirrorsWith(pMonitor, &frameDamage); - - pixman_region32_fini(&frameDamage); + g_pHyprRenderer->damageMirrorsWith(pMonitor, frameDamage); pMonitor->renderingActive = false; EMIT_HOOK_EVENT("render", RENDER_POST); - wlr_damage_ring_rotate(&pMonitor->damage); - if (!wlr_output_commit(pMonitor->output)) { - pixman_region32_fini(&damage); - if (UNLOCK_SC) wlr_output_lock_software_cursors(pMonitor->output, false); return; } - pixman_region32_fini(&damage); + wlr_damage_ring_rotate(&pMonitor->damage); if (UNLOCK_SC) wlr_output_lock_software_cursors(pMonitor->output, false); @@ -1391,24 +1382,20 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, dou if (g_pCompositor->m_bUnsafeState) return; - pixman_region32_t damageBox; - pixman_region32_init(&damageBox); - wlr_surface_get_effective_damage(pSurface, &damageBox); + CRegion damageBox; + wlr_surface_get_effective_damage(pSurface, damageBox.pixman()); if (scale != 1.0) - wlr_region_scale(&damageBox, &damageBox, scale); + wlr_region_scale(damageBox.pixman(), damageBox.pixman(), scale); // schedule frame events if (!wl_list_empty(&pSurface->current.frame_callback_list)) { g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y))); } - if (!pixman_region32_not_empty(&damageBox)) { - pixman_region32_fini(&damageBox); + if (damageBox.empty()) return; - } - pixman_region32_t damageBoxForEach; - pixman_region32_init(&damageBoxForEach); + CRegion damageBoxForEach; for (auto& m : g_pCompositor->m_vMonitors) { if (!m->output) @@ -1417,23 +1404,19 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, dou double lx = 0, ly = 0; wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, m->output, &lx, &ly); - pixman_region32_copy(&damageBoxForEach, &damageBox); - pixman_region32_translate(&damageBoxForEach, x - m->vecPosition.x, y - m->vecPosition.y); - wlr_region_scale(&damageBoxForEach, &damageBoxForEach, m->scale); - pixman_region32_translate(&damageBoxForEach, lx + m->vecPosition.x, ly + m->vecPosition.y); + damageBoxForEach = damageBox; + damageBoxForEach.translate({x - m->vecPosition.x, y - m->vecPosition.y}); + wlr_region_scale(damageBoxForEach.pixman(), damageBoxForEach.pixman(), m->scale); + damageBoxForEach.translate({lx + m->vecPosition.x, ly + m->vecPosition.y}); m->addDamage(&damageBoxForEach); } - pixman_region32_fini(&damageBoxForEach); - static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue; if (*PLOGDAMAGE) - Debug::log(LOG, "Damage: Surface (extents): xy: %d, %d wh: %d, %d", damageBox.extents.x1, damageBox.extents.y1, damageBox.extents.x2 - damageBox.extents.x1, - damageBox.extents.y2 - damageBox.extents.y1); - - pixman_region32_fini(&damageBox); + Debug::log(LOG, "Damage: Surface (extents): xy: %d, %d wh: %d, %d", damageBox.pixman()->extents.x1, damageBox.pixman()->extents.y1, + damageBox.pixman()->extents.x2 - damageBox.pixman()->extents.x1, damageBox.pixman()->extents.y2 - damageBox.pixman()->extents.y1); } void CHyprRenderer::damageWindow(CWindow* pWindow) { @@ -1493,23 +1476,19 @@ void CHyprRenderer::damageBox(const int& x, const int& y, const int& w, const in damageBox(&box); } -void CHyprRenderer::damageRegion(pixman_region32_t* rg) { - PIXMAN_DAMAGE_FOREACH(rg) { - const auto RECT = RECTSARR[i]; +void CHyprRenderer::damageRegion(const CRegion& rg) { + for (auto& RECT : rg.getRects()) { damageBox(RECT.x1, RECT.y1, RECT.x2 - RECT.x1, RECT.y2 - RECT.y1); } } -void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, pixman_region32_t* pRegion) { +void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, const CRegion& pRegion) { for (auto& mirror : pMonitor->mirrors) { - Vector2D scale = {mirror->vecSize.x / pMonitor->vecSize.x, mirror->vecSize.y / pMonitor->vecSize.y}; + Vector2D scale = {mirror->vecSize.x / pMonitor->vecSize.x, mirror->vecSize.y / pMonitor->vecSize.y}; - pixman_region32_t rg; - pixman_region32_init(&rg); - pixman_region32_copy(&rg, pRegion); - wlr_region_scale_xy(&rg, &rg, scale.x, scale.y); + CRegion rg{pRegion}; + wlr_region_scale_xy(rg.pixman(), rg.pixman(), scale.x, scale.y); pMonitor->addDamage(&rg); - pixman_region32_fini(&rg); g_pCompositor->scheduleFrameForMonitor(mirror); } @@ -1986,9 +1965,8 @@ void CHyprRenderer::initiateManualCrash() { g_pConfigManager->setInt("debug:damage_tracking", 0); } -void CHyprRenderer::setOccludedForBackLayers(pixman_region32_t* region, CWorkspace* pWorkspace) { - pixman_region32_t rg; - pixman_region32_init(&rg); +void CHyprRenderer::setOccludedForBackLayers(CRegion& region, CWorkspace* pWorkspace) { + CRegion rg; const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); @@ -2003,10 +1981,8 @@ void CHyprRenderer::setOccludedForBackLayers(pixman_region32_t* region, CWorkspa const Vector2D POS = w->m_vRealPosition.vec() + Vector2D{ROUNDING, ROUNDING}; const Vector2D SIZE = w->m_vRealSize.vec() - Vector2D{ROUNDING * 2, ROUNDING * 2}; - pixman_region32_union_rect(&rg, &rg, POS.x, POS.y, SIZE.x, SIZE.y); + rg.add(POS.x, POS.y, SIZE.x, SIZE.y); } - pixman_region32_subtract(region, region, &rg); - - pixman_region32_fini(&rg); + region.subtract(rg); } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 11b009a3..77f063e7 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -7,6 +7,7 @@ #include "../Window.hpp" #include "OpenGL.hpp" #include "../helpers/Timer.hpp" +#include "../helpers/Region.hpp" struct SMonitorRule; @@ -39,9 +40,9 @@ class CHyprRenderer { void damageWindow(CWindow*); void damageBox(wlr_box*); void damageBox(const int& x, const int& y, const int& w, const int& h); - void damageRegion(pixman_region32_t*); + void damageRegion(const CRegion&); void damageMonitor(CMonitor*); - void damageMirrorsWith(CMonitor*, pixman_region32_t*); + void damageMirrorsWith(CMonitor*, const CRegion&); bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false); bool shouldRenderWindow(CWindow*, CMonitor*, CWorkspace*); bool shouldRenderWindow(CWindow*); @@ -50,7 +51,7 @@ class CHyprRenderer { void calculateUVForSurface(CWindow*, wlr_surface*, bool main = false); std::tuple getRenderTimes(CMonitor* pMonitor); // avg max min void renderLockscreen(CMonitor* pMonitor, timespec* now); - void setOccludedForBackLayers(pixman_region32_t* region, CWorkspace* pWorkspace); + void setOccludedForBackLayers(CRegion& region, CWorkspace* pWorkspace); bool m_bWindowRequestedCursorHide = false; bool m_bBlockSurfaceFeedback = false;