summaryrefslogtreecommitdiff
path: root/src/render
diff options
context:
space:
mode:
authorxDarksome <dev@darkso.me>2022-07-02 19:43:52 +0300
committerGitHub <noreply@github.com>2022-07-02 19:43:52 +0300
commit185c4d6ea13ad5f4483aa2e389e43bd09106002f (patch)
treea7bc4a9510c39e367317b5ce64d2ee0e0a72d4f0 /src/render
parentfc4b10d13c14c4eb08febb0637f27177cb6a1940 (diff)
parentb7b3344188e3ebd2baed14bc288ee42a1ae8d6f2 (diff)
Merge branch 'hyprwm:main' into main
Diffstat (limited to 'src/render')
-rw-r--r--src/render/OpenGL.cpp239
-rw-r--r--src/render/OpenGL.hpp29
-rw-r--r--src/render/Renderer.cpp204
-rw-r--r--src/render/Renderer.hpp2
-rw-r--r--src/render/Shader.cpp13
-rw-r--r--src/render/Shader.hpp15
-rw-r--r--src/render/Shaders.hpp3
-rw-r--r--src/render/decorations/CHyprDropShadowDecoration.cpp71
-rw-r--r--src/render/decorations/CHyprGroupBarDecoration.cpp8
-rw-r--r--src/render/decorations/IHyprWindowDecoration.hpp2
-rw-r--r--src/render/shaders/Border.hpp91
-rw-r--r--src/render/shaders/Shadow.hpp3
12 files changed, 425 insertions, 255 deletions
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index e44e108b..793901aa 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -81,6 +81,12 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos");
m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord");
+ prog = createProgram(QUADVERTSRC, FRAGBORDER1);
+ m_shBORDER1.program = prog;
+ m_shBORDER1.proj = glGetUniformLocation(prog, "proj");
+ m_shBORDER1.posAttrib = glGetAttribLocation(prog, "pos");
+ m_shBORDER1.texAttrib = glGetAttribLocation(prog, "texcoord");
+
Debug::log(LOG, "Shaders initialized successfully.");
// End shaders
@@ -138,7 +144,9 @@ void CHyprOpenGLImpl::begin(SMonitor* pMonitor, pixman_region32_t* pDamage, bool
glViewport(0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
- wlr_matrix_projection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL); // TODO: this is deprecated
+ matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL);
+
+ m_RenderData.pCurrentMonData = &m_mMonitorRenderResources[pMonitor];
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
@@ -146,22 +154,22 @@ void CHyprOpenGLImpl::begin(SMonitor* pMonitor, pixman_region32_t* pDamage, bool
m_iWLROutputFb = m_iCurrentOutputFb;
// ensure a framebuffer for the monitor exists
- if (m_mMonitorRenderResources.find(pMonitor) == m_mMonitorRenderResources.end() || m_mMonitorRenderResources[pMonitor].primaryFB.m_Size != pMonitor->vecPixelSize) {
- m_mMonitorRenderResources[pMonitor].stencilTex.allocate();
+ if (m_mMonitorRenderResources.find(pMonitor) == m_mMonitorRenderResources.end() || m_RenderData.pCurrentMonData->primaryFB.m_Size != pMonitor->vecPixelSize) {
+ m_RenderData.pCurrentMonData->stencilTex.allocate();
- m_mMonitorRenderResources[pMonitor].primaryFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
- m_mMonitorRenderResources[pMonitor].mirrorFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
- m_mMonitorRenderResources[pMonitor].mirrorSwapFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
+ m_RenderData.pCurrentMonData->primaryFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
+ m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
+ m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
- m_mMonitorRenderResources[pMonitor].primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
- m_mMonitorRenderResources[pMonitor].mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
- m_mMonitorRenderResources[pMonitor].mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
+ m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
+ m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
+ m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
createBGTextureForMonitor(pMonitor);
}
// bind the primary Hypr Framebuffer
- m_mMonitorRenderResources[pMonitor].primaryFB.bind();
+ m_RenderData.pCurrentMonData->primaryFB.bind();
m_RenderData.pDamage = pDamage;
@@ -180,7 +188,7 @@ void CHyprOpenGLImpl::end() {
m_bEndFrame = true;
- renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &monbox, 255.f, 0);
+ renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 255.f, 0);
m_bEndFrame = false;
}
@@ -277,11 +285,11 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
// Rounded corners
- glUniform2f(glGetUniformLocation(m_shQUAD.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
- glUniform2f(glGetUniformLocation(m_shQUAD.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
- glUniform2f(glGetUniformLocation(m_shQUAD.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
- glUniform1f(glGetUniformLocation(m_shQUAD.program, "radius"), round);
- glUniform1i(glGetUniformLocation(m_shQUAD.program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
+ glUniform2f(m_shQUAD.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
+ glUniform2f(m_shQUAD.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
+ glUniform2f(m_shQUAD.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
+ glUniform1f(m_shQUAD.getUniformLocation("radius"), round);
+ glUniform1i(m_shQUAD.getUniformLocation("primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -309,15 +317,15 @@ void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha
renderTexture(CTexture(tex), pBox, alpha, round);
}
-void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool border, bool allowPrimary) {
+void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool allowPrimary) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
- renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, border, false, allowPrimary);
+ renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, false, allowPrimary);
scissor((wlr_box*)nullptr);
}
-void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool border, bool noAA, bool allowPrimary) {
+void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool noAA, bool allowPrimary) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
@@ -351,23 +359,6 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
RASSERT(false, "tex.m_iTarget unsupported!");
}
- // stencil for when we want a border
- if (border) {
- glClearStencil(0);
- glClear(GL_STENCIL_BUFFER_BIT);
-
- glEnable(GL_STENCIL_TEST);
-
- glStencilFunc(GL_ALWAYS, 1, -1);
- glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
-
- // hacky fix to fix broken borders.
- // TODO: this is kinda slow... question mark?
- renderRect(pBox, CColor(0, 0, 0, 0), round);
-
- glDisable(GL_STENCIL_TEST);
- }
-
glActiveTexture(GL_TEXTURE0);
glBindTexture(tex.m_iTarget, tex.m_iTexID);
@@ -389,11 +380,11 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
// Rounded corners
- glUniform2f(glGetUniformLocation(shader->program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
- glUniform2f(glGetUniformLocation(shader->program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
- glUniform2f(glGetUniformLocation(shader->program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
- glUniform1f(glGetUniformLocation(shader->program, "radius"), round);
- glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !border && !noAA));
+ glUniform2f(shader->getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
+ glUniform2f(shader->getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
+ glUniform2f(shader->getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
+ glUniform1f(shader->getUniformLocation("radius"), round);
+ glUniform1i(shader->getUniformLocation("primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA));
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -421,30 +412,10 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
}
}
- if (border) {
- glEnable(GL_STENCIL_TEST);
-
- glStencilFunc(GL_EQUAL, 1, -1);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
- }
-
glDisableVertexAttribArray(shader->posAttrib);
glDisableVertexAttribArray(shader->texAttrib);
glBindTexture(tex.m_iTarget, 0);
-
- // if border draw
- // we dont disable stencil here if we havent touched it.
- // some other func might be using it.
- if (border) {
- auto BORDERCOL = m_pCurrentWindow->m_cRealBorderColor.col();
- static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
- BORDERCOL.a *= alpha / 255.f;
- renderBorder(pBox, BORDERCOL, *PBORDERSIZE, round);
- glStencilMask(-1);
- glStencilFunc(GL_ALWAYS, 1, 0xFF);
- glDisable(GL_STENCIL_TEST);
- }
}
// This probably isn't the fastest
@@ -478,10 +449,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
wlr_region_expand(&damage, &damage, pow(2, *PBLURPASSES) * *PBLURSIZE);
// helper
- const auto PMIRRORFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB;
- const auto PMIRRORSWAPFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorSwapFB;
+ const auto PMIRRORFB = &m_RenderData.pCurrentMonData->mirrorFB;
+ const auto PMIRRORSWAPFB = &m_RenderData.pCurrentMonData->mirrorSwapFB;
- CFramebuffer* currentRenderToFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB;
+ CFramebuffer* currentRenderToFB = &m_RenderData.pCurrentMonData->primaryFB;
// declare the draw func
auto drawPass = [&](CShader* pShader, pixman_region32_t* pDamage) {
@@ -500,11 +471,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
// prep two shaders
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
- glUniform1f(glGetUniformLocation(pShader->program, "radius"), *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
+ glUniform1f(pShader->getUniformLocation("radius"), *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
if (pShader == &m_shBLUR1)
- glUniform2f(glGetUniformLocation(m_shBLUR1.program, "halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
+ glUniform2f(m_shBLUR1.getUniformLocation("halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
else
- glUniform2f(glGetUniformLocation(m_shBLUR2.program, "halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f));
+ glUniform2f(m_shBLUR2.getUniformLocation("halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f));
glUniform1i(pShader->tex, 0);
glVertexAttribPointer(pShader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -534,7 +505,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
// draw the things.
// first draw is prim -> mirr
PMIRRORFB->bind();
- glBindTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex.m_iTarget, m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex.m_iTexID);
+ 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;
@@ -566,14 +537,14 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
return currentRenderToFB;
}
-void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round, bool border) {
+void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
static auto *const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
static auto* const PNOBLUROVERSIZED = &g_pConfigManager->getConfigValuePtr("decoration:no_blur_on_oversized")->intValue;
if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBlur)) {
- renderTexture(tex, pBox, a, round, false, border, true);
+ renderTexture(tex, pBox, a, round, false, true);
return;
}
@@ -596,7 +567,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
}
if (!pixman_region32_not_empty(&inverseOpaque)) {
- renderTexture(tex, pBox, a, round, false, border); // reject blurring a fully opaque window
+ renderTexture(tex, pBox, a, round, false); // reject blurring a fully opaque window
return;
}
@@ -606,7 +577,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
pixman_region32_fini(&inverseOpaque);
// bind primary
- m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.bind();
+ m_RenderData.pCurrentMonData->primaryFB.bind();
// make a stencil for rounded corners to work with blur
scissor((wlr_box*)nullptr); // allow the entire window and stencil to render
@@ -630,7 +601,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
if (pixman_region32_not_empty(&damage)) {
// render our great blurred FB
static auto *const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur_ignore_opacity")->intValue;
- renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, false, true);
+ renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, true);
// render the window, but clear stencil
glClearStencil(0);
@@ -638,36 +609,11 @@ 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);
- glEnable(GL_STENCIL_TEST);
-
- // prep stencil for border
- glStencilFunc(GL_ALWAYS, 1, -1);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
- if (border) {
- // hacky fix to fix broken borders.
- // TODO: this is kinda slow... question mark?
- renderRectWithDamage(pBox, CColor(0,0,0,0), &damage, round);
- }
-
- // then stop
- glStencilFunc(GL_EQUAL, 1, -1);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true);
}
- // disable the stencil (if no border), finalize everything
- if (!border) {
- glStencilMask(-1);
- glStencilFunc(GL_ALWAYS, 1, 0xFF);
- } else {
- auto BORDERCOL = m_pCurrentWindow->m_cRealBorderColor.col();
- BORDERCOL.a *= a / 255.f;
- static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
- renderBorder(pBox, BORDERCOL, *PBORDERSIZE, round);
- }
-
- glDisable(GL_STENCIL_TEST);
+ glStencilMask(-1);
+ glStencilFunc(GL_ALWAYS, 1, 0xFF);
pixman_region32_fini(&damage);
scissor((wlr_box*)nullptr);
}
@@ -679,23 +625,67 @@ void pushVert2D(float x, float y, float* arr, int& counter, wlr_box* box) {
counter++;
}
-void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int thick, int round) {
+void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, 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()!");
- // this method assumes a set stencil and scaled box
- box->x -= thick;
- box->y -= thick;
- box->width += 2 * thick;
- box->height += 2 * thick;
+ static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
+ static auto *const PMULTISAMPLE = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
- round += thick; // cuz yeah
+ // adjust box
+ box->x -= *PBORDERSIZE;
+ box->y -= *PBORDERSIZE;
+ box->width += 2 * *PBORDERSIZE;
+ box->height += 2 * *PBORDERSIZE;
- // only draw on non-stencild.
- glStencilFunc(GL_NOTEQUAL, 1, -1);
+ round += *PBORDERSIZE;
- // draw a rounded rect
- renderRect(box, col, round);
+ float matrix[9];
+ wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
+
+ float glMatrix[9];
+ wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
+ wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
+
+ wlr_matrix_transpose(glMatrix, glMatrix);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glUseProgram(m_shBORDER1.program);
+
+ glUniformMatrix3fv(m_shBORDER1.proj, 1, GL_FALSE, glMatrix);
+ glUniform4f(m_shBORDER1.getUniformLocation("color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
+
+ const auto TOPLEFT = Vector2D(round, round);
+ const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
+ const auto FULLSIZE = Vector2D(box->width, box->height);
+
+ glUniform2f(m_shBORDER1.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
+ glUniform2f(m_shBORDER1.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
+ glUniform2f(m_shBORDER1.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
+ glUniform1f(m_shBORDER1.getUniformLocation("radius"), round);
+ glUniform1f(m_shBORDER1.getUniformLocation("thick"), *PBORDERSIZE);
+ glUniform1i(m_shBORDER1.getUniformLocation("primitiveMultisample"), *PMULTISAMPLE);
+
+ glVertexAttribPointer(m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
+ glVertexAttribPointer(m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
+
+ glEnableVertexAttribArray(m_shBORDER1.posAttrib);
+ glEnableVertexAttribArray(m_shBORDER1.texAttrib);
+
+ if (pixman_region32_not_empty(m_RenderData.pDamage)) {
+ PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
+ const auto RECT = RECTSARR[i];
+ scissor(&RECT);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ }
+ }
+
+ glDisableVertexAttribArray(m_shBORDER1.posAttrib);
+ glDisableVertexAttribArray(m_shBORDER1.texAttrib);
+
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
@@ -744,7 +734,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
clear(CColor(0, 0, 0, 0)); // JIC
wlr_box fullMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
- renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &fullMonBox, 255.f, 0);
+ renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &fullMonBox, 255.f, 0);
// restore original fb
#ifndef GLES2
@@ -823,12 +813,13 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
wlr_box windowBox;
// some mafs to figure out the correct box
- Vector2D scaleXY = Vector2D((PWINDOW->m_vRealSize.vec().x / PWINDOW->m_vOriginalClosedSize.x), (PWINDOW->m_vRealSize.vec().y / PWINDOW->m_vOriginalClosedSize.y));
+ // the originalClosedPos is relative to the monitor's pos
+ Vector2D scaleXY = Vector2D((PMONITOR->scale * PWINDOW->m_vRealSize.vec().x / (PWINDOW->m_vOriginalClosedSize.x * PMONITOR->scale)), (PMONITOR->scale * PWINDOW->m_vRealSize.vec().y / (PWINDOW->m_vOriginalClosedSize.y * PMONITOR->scale)));
windowBox.width = PMONITOR->vecPixelSize.x * scaleXY.x;
windowBox.height = PMONITOR->vecPixelSize.y * scaleXY.y;
- windowBox.x = (PWINDOW->m_vRealPosition.vec().x - PMONITOR->vecPosition.x) - ((PWINDOW->m_vOriginalClosedPos.x - PMONITOR->vecPosition.x) * scaleXY.x);
- windowBox.y = (PWINDOW->m_vRealPosition.vec().y - PMONITOR->vecPosition.y) - ((PWINDOW->m_vOriginalClosedPos.y - PMONITOR->vecPosition.y) * scaleXY.y);
+ 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->vecPixelSize.x, PMONITOR->vecPixelSize.y);
@@ -870,7 +861,6 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
static auto *const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue;
static auto *const PSHADOWPOWER = &g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power")->intValue;
- static auto *const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4);
@@ -891,20 +881,19 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
glUseProgram(m_shSHADOW.program);
glUniformMatrix3fv(m_shSHADOW.proj, 1, GL_FALSE, glMatrix);
- glUniform4f(glGetUniformLocation(m_shSHADOW.program, "color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
+ glUniform4f(m_shSHADOW.getUniformLocation("color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
const auto TOPLEFT = Vector2D(range + round, range + round);
const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round));
const auto FULLSIZE = Vector2D(box->width, box->height);
// Rounded corners
- glUniform2f(glGetUniformLocation(m_shSHADOW.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
- glUniform2f(glGetUniformLocation(m_shSHADOW.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
- glUniform2f(glGetUniformLocation(m_shSHADOW.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
- glUniform1f(glGetUniformLocation(m_shSHADOW.program, "radius"), range + round);
- glUniform1f(glGetUniformLocation(m_shSHADOW.program, "range"), range);
- glUniform1f(glGetUniformLocation(m_shSHADOW.program, "shadowPower"), SHADOWPOWER);
- glUniform1i(glGetUniformLocation(m_shSHADOW.program, "ignoreWindow"), *PSHADOWIGNOREWINDOW);
+ glUniform2f(m_shSHADOW.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
+ glUniform2f(m_shSHADOW.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
+ glUniform2f(m_shSHADOW.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
+ glUniform1f(m_shSHADOW.getUniformLocation("radius"), range + round);
+ glUniform1f(m_shSHADOW.getUniformLocation("range"), range);
+ glUniform1f(m_shSHADOW.getUniformLocation("shadowPower"), SHADOWPOWER);
glVertexAttribPointer(m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index 9d6e098d..292eba36 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -29,10 +29,20 @@ inline const float fanVertsFull[] = {
-1.0f, 1.0f
};
+struct SMonitorRenderData {
+ CFramebuffer primaryFB;
+ CFramebuffer mirrorFB;
+ CFramebuffer mirrorSwapFB;
+
+ CTexture stencilTex;
+};
+
struct SCurrentRenderData {
SMonitor* pMonitor = nullptr;
float projection[9];
+ SMonitorRenderData* pCurrentMonData = nullptr;
+
pixman_region32_t* pDamage = nullptr;
bool renderingPrimarySurface = false;
@@ -40,14 +50,6 @@ struct SCurrentRenderData {
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
};
-struct SMonitorRenderData {
- CFramebuffer primaryFB;
- CFramebuffer mirrorFB;
- CFramebuffer mirrorSwapFB;
-
- CTexture stencilTex;
-};
-
class CHyprOpenGLImpl {
public:
@@ -59,9 +61,10 @@ public:
void renderRect(wlr_box*, const CColor&, int round = 0);
void renderRectWithDamage(wlr_box*, const CColor&, pixman_region32_t* damage, int round = 0);
void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0);
- void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool border = false, bool allowPrimary = false);
- void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool border = false);
+ void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool allowPrimary = false);
+ void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0);
void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0);
+ void renderBorder(wlr_box*, const CColor&, int round);
void makeWindowSnapshot(CWindow*);
void makeLayerSnapshot(SLayerSurface*);
@@ -101,13 +104,14 @@ private:
bool m_bEndFrame = false;
// Shaders
- SQuad m_shQUAD;
+ CShader m_shQUAD;
CShader m_shRGBA;
CShader m_shRGBX;
CShader m_shEXT;
CShader m_shBLUR1;
CShader m_shBLUR2;
CShader m_shSHADOW;
+ CShader m_shBORDER1;
//
GLuint createProgram(const std::string&, const std::string&);
@@ -117,8 +121,7 @@ private:
// returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
- void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool border = false, bool noAA = false, bool allowPrimary = false);
- void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
+ void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowPrimary = false);
};
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL; \ No newline at end of file
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index f7328997..eaa3cd90 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -27,7 +27,13 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
if (RDATA->surface && surface == RDATA->surface) {
g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = true;
- g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, RDATA->decorate);
+ g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding);
+
+ if (RDATA->decorate) {
+ auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col();
+ col.a *= RDATA->fadeAlpha * RDATA->alpha / 255.f;
+ g_pHyprOpenGL->renderBorder(&windowBox, col, rounding);
+ }
}
else
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false);
@@ -68,11 +74,11 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
return true;
- for (auto& m : g_pCompositor->m_lMonitors) {
- if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m.ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))
+ for (auto& m : g_pCompositor->m_vMonitors) {
+ if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))
return true;
- if (m.specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
+ if (m->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
return true;
}
@@ -82,37 +88,37 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time) {
CWindow* pWorkspaceWindow = nullptr;
- for (auto& w : g_pCompositor->m_lWindows) {
- if (w.m_iWorkspaceID != pWorkspace->m_iID || !w.m_bIsFullscreen)
+ for (auto& w : g_pCompositor->m_vWindows) {
+ if (w->m_iWorkspaceID != pWorkspace->m_iID || !w->m_bIsFullscreen)
continue;
// found it!
- renderWindow(&w, pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL);
+ renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL);
- pWorkspaceWindow = &w;
+ pWorkspaceWindow = w.get();
}
// then render windows over fullscreen
- for (auto& w : g_pCompositor->m_lWindows) {
- if (w.m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w.m_bCreatedOverFullscreen || !w.m_bIsMapped)
+ for (auto& w : g_pCompositor->m_vWindows) {
+ if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w->m_bCreatedOverFullscreen || !w->m_bIsMapped)
continue;
- renderWindow(&w, pMonitor, time, true);
+ renderWindow(w.get(), pMonitor, time, true);
}
// and then special windows
- for (auto& w : g_pCompositor->m_lWindows) {
- if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
+ for (auto& w : g_pCompositor->m_vWindows) {
+ if (!g_pCompositor->windowValidMapped(w.get()) && !w->m_bFadingOut)
continue;
- if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
+ if (w->m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
continue;
- if (!shouldRenderWindow(&w, pMonitor))
+ if (!shouldRenderWindow(w.get(), pMonitor))
continue;
// render the bad boy
- renderWindow(&w, pMonitor, time, true);
+ renderWindow(w.get(), pMonitor, time, true);
}
// and the overlay layers
@@ -130,7 +136,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
renderDragIcon(pMonitor, time);
// if correct monitor draw hyprerror
- if (pMonitor == &g_pCompositor->m_lMonitors.front())
+ if (pMonitor == g_pCompositor->m_vMonitors.front().get())
g_pHyprError->draw();
}
@@ -155,7 +161,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
renderdata.dontRound = pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f);
renderdata.alpha = pWindow->m_bIsFullscreen ? g_pConfigManager->getFloat("decoration:fullscreen_opacity") : pWindow == g_pCompositor->m_pLastWindow ? g_pConfigManager->getFloat("decoration:active_opacity") : g_pConfigManager->getFloat("decoration:inactive_opacity");
- renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true);
+ renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true) && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL);
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
// apply window special data
@@ -166,8 +172,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
g_pHyprOpenGL->m_pCurrentWindow = pWindow;
- // render window decorations first
- for (auto& wd : pWindow->m_dWindowDecorations)
+ // render window decorations first, if not fullscreen full
+ if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) for (auto& wd : pWindow->m_dWindowDecorations)
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f);
if (!pWindow->m_bIsX11) {
@@ -238,54 +244,54 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
}
// Non-floating
- for (auto& w : g_pCompositor->m_lWindows) {
- if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
+ for (auto& w : g_pCompositor->m_vWindows) {
+ if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
- if (w.m_bIsFloating)
+ if (w->m_bIsFloating)
continue; // floating are in the second pass
- if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
+ if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
continue; // special are in the third pass
- if (!shouldRenderWindow(&w, PMONITOR))
+ if (!shouldRenderWindow(w.get(), PMONITOR))
continue;
// render the bad boy
- renderWindow(&w, PMONITOR, time, true);
+ renderWindow(w.get(), PMONITOR, time, true);
}
// floating on top
- for (auto& w : g_pCompositor->m_lWindows) {
- if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
+ for (auto& w : g_pCompositor->m_vWindows) {
+ if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
- if (!w.m_bIsFloating)
+ if (!w->m_bIsFloating)
continue;
- if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
+ if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
continue;
- if (!shouldRenderWindow(&w, PMONITOR))
+ if (!shouldRenderWindow(w.get(), PMONITOR))
continue;
// render the bad boy
- renderWindow(&w, PMONITOR, time, true);
+ renderWindow(w.get(), PMONITOR, time, true);
}
// and then special
- for (auto& w : g_pCompositor->m_lWindows) {
- if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
+ for (auto& w : g_pCompositor->m_vWindows) {
+ if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
- if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
+ if (w->m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
continue;
- if (!shouldRenderWindow(&w, PMONITOR))
+ if (!shouldRenderWindow(w.get(), PMONITOR))
continue;
// render the bad boy
- renderWindow(&w, PMONITOR, time, true);
+ renderWindow(w.get(), PMONITOR, time, true);
}
// Render surfaces above windows for monitor
@@ -545,14 +551,19 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
pixman_region32_init(&damageBox);
wlr_surface_get_effective_damage(pSurface, &damageBox);
+ if (!pixman_region32_not_empty(&damageBox)) {
+ pixman_region32_fini(&damageBox);
+ return;
+ }
+
pixman_region32_translate(&damageBox, x, y);
- for (auto& m : g_pCompositor->m_lMonitors) {
+ for (auto& m : g_pCompositor->m_vMonitors) {
double lx = 0, ly = 0;
- wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, m.output, &lx, &ly);
+ wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, m->output, &lx, &ly);
pixman_region32_translate(&damageBox, lx, ly);
- wlr_region_scale(&damageBox, &damageBox, m.scale);
- wlr_output_damage_add(m.damage, &damageBox);
+ wlr_region_scale(&damageBox, &damageBox, m->scale);
+ wlr_output_damage_add(m->damage, &damageBox);
pixman_region32_translate(&damageBox, -lx, -ly);
}
@@ -565,39 +576,17 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
}
void CHyprRenderer::damageWindow(CWindow* pWindow) {
- if (!pWindow->m_bIsFloating) {
- // damage by size & pos
- // TODO TEMP: revise when added shadows/etc
-
- wlr_box damageBox = pWindow->getFullWindowBoundingBox();
- for (auto& m : g_pCompositor->m_lMonitors) {
- wlr_box fixedDamageBox = damageBox;
- fixedDamageBox.x -= m.vecPosition.x;
- fixedDamageBox.y -= m.vecPosition.y;
- scaleBox(&fixedDamageBox, m.scale);
- wlr_output_damage_add_box(m.damage, &fixedDamageBox);
- }
-
- static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
-
- if (*PLOGDAMAGE)
- Debug::log(LOG, "Damage: Window floated (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
- } else {
- // damage by real size & pos + border size * 2 (JIC)
- wlr_box damageBox = pWindow->getFullWindowBoundingBox();
- for (auto& m : g_pCompositor->m_lMonitors) {
- wlr_box fixedDamageBox = damageBox;
- fixedDamageBox.x -= m.vecPosition.x;
- fixedDamageBox.y -= m.vecPosition.y;
- scaleBox(&fixedDamageBox, m.scale);
- wlr_output_damage_add_box(m.damage, &fixedDamageBox);
- }
+ wlr_box damageBox = pWindow->getFullWindowBoundingBox();
+ for (auto& m : g_pCompositor->m_vMonitors) {
+ wlr_box fixedDamageBox = {damageBox.x - m->vecPosition.x, damageBox.y - m->vecPosition.y, damageBox.width, damageBox.height};
+ scaleBox(&fixedDamageBox, m->scale);
+ wlr_output_damage_add_box(m->damage, &fixedDamageBox);
+ }
- static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
+ static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
- if (*PLOGDAMAGE)
- Debug::log(LOG, "Damage: Window tiled (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
- }
+ if (*PLOGDAMAGE)
+ Debug::log(LOG, "Damage: Window (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
}
void CHyprRenderer::damageMonitor(SMonitor* pMonitor) {
@@ -611,10 +600,10 @@ void CHyprRenderer::damageMonitor(SMonitor* pMonitor) {
}
void CHyprRenderer::damageBox(wlr_box* pBox) {
- for (auto& m : g_pCompositor->m_lMonitors) {
- wlr_box damageBox = {pBox->x - m.vecPosition.x, pBox->y - m.vecPosition.y, pBox->width, pBox->height};
- scaleBox(&damageBox, m.scale);
- wlr_output_damage_add_box(m.damage, &damageBox);
+ for (auto& m : g_pCompositor->m_vMonitors) {
+ wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
+ scaleBox(&damageBox, m->scale);
+ wlr_output_damage_add_box(m->damage, &damageBox);
}
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
@@ -638,6 +627,9 @@ void CHyprRenderer::renderDragIcon(SMonitor* pMonitor, timespec* time) {
renderdata.h = g_pInputManager->m_sDrag.dragIcon->surface->current.height;
wlr_surface_for_each_surface(g_pInputManager->m_sDrag.dragIcon->surface, renderSurface, &renderdata);
+
+ wlr_box box = {g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4, g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4};
+ g_pHyprRenderer->damageBox(&box);
}
DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string& mode) {
@@ -651,14 +643,23 @@ DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string&
return DAMAGE_TRACKING_INVALID;
}
-void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorRule, bool force) {
+bool CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorRule, bool force) {
Debug::log(LOG, "Applying monitor rule for %s", pMonitor->szName.c_str());
+ // if it's disabled, disable and ignore
+ if (pMonitorRule->disabled) {
+ wlr_output_enable(pMonitor->output, 0);
+ wlr_output_commit(pMonitor->output);
+
+ Events::listener_monitorDestroy(nullptr, pMonitor->output);
+ return false;
+ }
+
// Check if the rule isn't already applied
if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) && DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale && DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1) && pMonitor->transform == pMonitorRule->transform) {
Debug::log(LOG, "Not applying a new rule to %s because it's already applied!", pMonitor->szName.c_str());
- return;
+ return true;
}
wlr_output_set_scale(pMonitor->output, pMonitorRule->scale);
@@ -697,23 +698,32 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
}
if (!found) {
- const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
+ wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (int)pMonitorRule->refreshRate * 1000);
+ pMonitor->vecSize = pMonitorRule->resolution;
- if (!PREFERREDMODE) {
- Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f",
- (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
- return;
- }
+ if (!wlr_output_test(pMonitor->output)) {
+ Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
+
+ const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
- // Preferred is valid
- wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
+ if (!PREFERREDMODE) {
+ Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f",
+ (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
+ return true;
+ }
+
+ // Preferred is valid
+ wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
- Debug::log(ERR, "Monitor %s got an invalid requested mode: %ix%i@%2f, using the preferred one instead: %ix%i@%2f",
- pMonitor->output->name, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate,
- PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
+ Debug::log(ERR, "Monitor %s got an invalid requested mode: %ix%i@%2f, using the preferred one instead: %ix%i@%2f",
+ pMonitor->output->name, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate,
+ PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
- pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
- pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
+ pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
+ pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
+ } else {
+ Debug::log(LOG, "Set a custom mode %ix%i@%2f (mode not found in monitor modes)", (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
+ }
}
} else {
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (int)pMonitorRule->refreshRate * 1000);
@@ -730,7 +740,7 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
if (!wlr_output_commit(pMonitor->output)) {
Debug::log(ERR, "Couldn't commit output named %s", pMonitor->output->name);
- return;
+ return true;
}
int x, y;
@@ -752,6 +762,8 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
// frame skip
pMonitor->framesToSkip = 1;
+
+ return true;
}
void CHyprRenderer::ensureCursorRenderingMode() {
@@ -767,8 +779,8 @@ void CHyprRenderer::ensureCursorRenderingMode() {
Debug::log(LOG, "Hiding the cursor (timeout)");
- for (auto& m : g_pCompositor->m_lMonitors)
- g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area?
+ for (auto& m : g_pCompositor->m_vMonitors)
+ g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
} else if (*PCURSORTIMEOUT > PASSEDCURSORSECONDS && !m_bHasARenderedCursor) {
m_bHasARenderedCursor = true;
@@ -777,8 +789,8 @@ void CHyprRenderer::ensureCursorRenderingMode() {
Debug::log(LOG, "Showing the cursor (timeout)");
- for (auto& m : g_pCompositor->m_lMonitors)
- g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area?
+ for (auto& m : g_pCompositor->m_vMonitors)
+ g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
}
} else {
m_bHasARenderedCursor = true;
diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp
index 43a241ed..ff9fd4ea 100644
--- a/src/render/Renderer.hpp
+++ b/src/render/Renderer.hpp
@@ -28,7 +28,7 @@ public:
void damageBox(wlr_box*);
void damageBox(const int& x, const int& y, const int& w, const int& h);
void damageMonitor(SMonitor*);
- void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
+ bool applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
bool shouldRenderWindow(CWindow*, SMonitor*);
bool shouldRenderWindow(CWindow*);
void ensureCursorRenderingMode();
diff --git a/src/render/Shader.cpp b/src/render/Shader.cpp
index e69de29b..96b3caf7 100644
--- a/src/render/Shader.cpp
+++ b/src/render/Shader.cpp
@@ -0,0 +1,13 @@
+#include "Shader.hpp"
+
+GLint CShader::getUniformLocation(const std::string& unif) {
+ const auto itpos = m_muUniforms.find(unif);
+
+ if (itpos == m_muUniforms.end()) {
+ const auto unifLoc = glGetUniformLocation(program, unif.c_str());
+ m_muUniforms[unif] = unifLoc;
+ return unifLoc;
+ }
+
+ return itpos->second;
+} \ No newline at end of file
diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp
index 4d94358e..f996894b 100644
--- a/src/render/Shader.hpp
+++ b/src/render/Shader.hpp
@@ -1,22 +1,21 @@
#pragma once
#include "../defines.hpp"
-
-struct SQuad {
- GLuint program;
- GLint proj;
- GLint color;
- GLint posAttrib;
- GLint texAttrib;
-};
+#include <unordered_map>
class CShader {
public:
GLuint program;
GLint proj;
+ GLint color;
GLint tex;
GLint alpha;
GLint posAttrib;
GLint texAttrib;
GLint discardOpaque;
+
+ GLint getUniformLocation(const std::string&);
+
+private:
+ std::unordered_map<std::string, GLint> m_muUniforms;
}; \ No newline at end of file
diff --git a/src/render/Shaders.hpp b/src/render/Shaders.hpp
index ac7f9424..1849c621 100644
--- a/src/render/Shaders.hpp
+++ b/src/render/Shaders.hpp
@@ -1,4 +1,5 @@
#pragma once
#include "shaders/Textures.hpp"
-#include "shaders/Shadow.hpp" \ No newline at end of file
+#include "shaders/Shadow.hpp"
+#include "shaders/Border.hpp" \ No newline at end of file
diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp
index 6933e687..40051942 100644
--- a/src/render/decorations/CHyprDropShadowDecoration.cpp
+++ b/src/render/decorations/CHyprDropShadowDecoration.cpp
@@ -35,6 +35,17 @@ void CHyprDropShadowDecoration::damageEntire() {
void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) {
damageEntire();
+
+ const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
+
+ const auto WORKSPACEOFFSET = PWORKSPACE ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
+
+ if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
+ m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET;
+ m_vLastWindowSize = pWindow->m_vRealSize.vec();
+
+ damageEntire();
+ }
}
void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
@@ -45,22 +56,70 @@ void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
static auto *const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue;
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
+ static auto *const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
+ static auto *const PSHADOWOFFSET = &g_pConfigManager->getConfigValuePtr("decoration:shadow_offset")->strValue;
if (*PSHADOWS != 1)
return; // disabled
- // update the extents if needed
- if (*PSHADOWSIZE != m_seExtents.topLeft.x)
- m_seExtents = {{*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}, {*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}};
+ // get the real offset
+ Vector2D offset;
+ try {
+ if (const auto SPACEPOS = PSHADOWOFFSET->find(' '); SPACEPOS != std::string::npos) {
+ const auto X = PSHADOWOFFSET->substr(0, SPACEPOS);
+ const auto Y = PSHADOWOFFSET->substr(SPACEPOS + 1);
- m_vLastWindowPos = m_pWindow->m_vRealPosition.vec();
- m_vLastWindowSize = m_pWindow->m_vRealSize.vec();
+ if (isNumber(X, true) && isNumber(Y, true)) {
+ offset = Vector2D(std::stof(X), std::stof(Y));
+ }
+ }
+ } catch (std::exception& e) {
+ return; // cannot parse
+ }
+
+ // update the extents
+ m_seExtents = {{*PSHADOWSIZE + 2 - offset.x, *PSHADOWSIZE + 2 - offset.y}, {*PSHADOWSIZE + 2 + offset.x, *PSHADOWSIZE + 2 + offset.y}};
// draw the shadow
wlr_box fullBox = {m_vLastWindowPos.x - m_seExtents.topLeft.x + 2, m_vLastWindowPos.y - m_seExtents.topLeft.y + 2, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x - 4, m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y - 4};
fullBox.x -= pMonitor->vecPosition.x;
fullBox.y -= pMonitor->vecPosition.y;
-
+
+ if (fullBox.width < 1 || fullBox.height < 1)
+ return; // don't draw invisible shadows
+
+ if (*PSHADOWIGNOREWINDOW) {
+ glClearStencil(0);
+ glClear(GL_STENCIL_BUFFER_BIT);
+
+ glEnable(GL_STENCIL_TEST);
+
+ glStencilFunc(GL_ALWAYS, 1, -1);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
+ wlr_box windowBox = {m_vLastWindowPos.x - pMonitor->vecPosition.x, m_vLastWindowPos.y - pMonitor->vecPosition.y, m_vLastWindowSize.x, m_vLastWindowSize.y};
+
+ scaleBox(&windowBox, pMonitor->scale);
+
+ if (windowBox.width < 1 || windowBox.height < 1) {
+ glDisable(GL_STENCIL_TEST);
+ return; // prevent assert failed
+ }
+
+ g_pHyprOpenGL->renderRect(&windowBox, CColor(0,0,0,0), *PROUNDING);
+
+ glStencilFunc(GL_NOTEQUAL, 1, -1);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ }
+
+ scaleBox(&fullBox, pMonitor->scale);
g_pHyprOpenGL->renderRoundedShadow(&fullBox, *PROUNDING, *PSHADOWSIZE, a);
+
+ if (*PSHADOWIGNOREWINDOW) {
+ // cleanup
+ glClearStencil(0);
+ glClear(GL_STENCIL_BUFFER_BIT);
+ glDisable(GL_STENCIL_TEST);
+ }
}
diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp
index 2bb486ee..abb5d90c 100644
--- a/src/render/decorations/CHyprGroupBarDecoration.cpp
+++ b/src/render/decorations/CHyprGroupBarDecoration.cpp
@@ -21,14 +21,18 @@ eDecorationType CHyprGroupBarDecoration::getDecorationType() {
void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
damageEntire();
- if (pWindow->m_vRealPosition.vec() != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
+ const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
+
+ const auto WORKSPACEOFFSET = PWORKSPACE ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
+
+ if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
// we draw 3px above the window's border with 3px
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
m_seExtents.topLeft = Vector2D(0, BORDERSIZE + 3 + 3);
m_seExtents.bottomRight = Vector2D();
- m_vLastWindowPos = pWindow->m_vRealPosition.vec();
+ m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET;
m_vLastWindowSize = pWindow->m_vRealSize.vec();
}
diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp
index 21219b36..4066b6f3 100644
--- a/src/render/decorations/IHyprWindowDecoration.hpp
+++ b/src/render/decorations/IHyprWindowDecoration.hpp
@@ -16,7 +16,7 @@ struct SWindowDecorationExtents {
class CWindow;
struct SMonitor;
-class IHyprWindowDecoration {
+interface IHyprWindowDecoration {
public:
virtual ~IHyprWindowDecoration() = 0;
diff --git a/src/render/shaders/Border.hpp b/src/render/shaders/Border.hpp
new file mode 100644
index 00000000..69f1ad5b
--- /dev/null
+++ b/src/render/shaders/Border.hpp
@@ -0,0 +1,91 @@
+#pragma once
+
+#include <string>
+
+// makes a stencil without corners
+inline const std::string FRAGBORDER1 = R"#(
+precision mediump float;
+varying vec4 v_color;
+varying vec2 v_texcoord;
+
+uniform vec2 topLeft;
+uniform vec2 bottomRight;
+uniform vec2 fullSize;
+uniform float radius;
+uniform float thick;
+uniform int primitiveMultisample;
+
+float getOpacityForPixAndCorner(vec2 pix, vec2 corner) {
+
+ if (primitiveMultisample == 0) {
+ float dis = distance(pix + vec2(0.5, 0.5), corner);
+ return dis < radius && dis > radius - thick ? 1.0 : 0.0;
+ }
+
+ float distance1 = distance(pix + vec2(0.25, 0.25), corner);
+ float distance2 = distance(pix + vec2(0.75, 0.25), corner);
+ float distance3 = distance(pix + vec2(0.25, 0.75), corner);
+ float distance4 = distance(pix + vec2(0.75, 0.75), corner);
+
+ float v1 = distance1 < radius && distance1 > radius - thick ? 1.0 : 0.0;
+ float v2 = distance2 < radius && distance2 > radius - thick ? 1.0 : 0.0;
+ float v3 = distance3 < radius && distance3 > radius - thick ? 1.0 : 0.0;
+ float v4 = distance4 < radius && distance4 > radius - thick ? 1.0 : 0.0;
+
+ return (v1 + v2 + v3 + v4) / 4.0;
+}
+
+void main() {
+
+ vec2 pixCoord = fullSize * v_texcoord;
+
+ vec4 pixColor = v_color;
+
+ bool done = false;
+
+ // check for edges
+ if (pixCoord[0] < topLeft[0]) {
+ if (pixCoord[1] < topLeft[1]) {
+ // top left
+ pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, topLeft + vec2(1,1));
+ done = true;
+ } else if (pixCoord[1] > bottomRight[1]) {
+ // bottom left
+ pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, vec2(topLeft[0] + 1.0, bottomRight[1]));
+ done = true;
+ }
+ } else if (pixCoord[0] > bottomRight[0]) {
+ if (pixCoord[1] < topLeft[1]) {
+ // top right
+ pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, vec2(bottomRight[0], topLeft[1] + 1.0));
+ done = true;
+ } else if (pixCoord[1] > bottomRight[1]) {
+ // bottom right
+ pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, bottomRight);
+ done = true;
+ }
+ }
+
+ // now check for other shit
+ if (!done) {
+ // distance to all straight bb borders
+ float distanceT = pixCoord[1];
+ float distanceB = fullSize[1] - pixCoord[1];
+ float distanceL = pixCoord[0];
+ float distanceR = fullSize[0] - pixCoord[0];
+
+ // get the smallest
+ float smallest = min(min(distanceT, distanceB), min(distanceL, distanceR));
+
+ if (smallest > thick) {
+ discard; return;
+ }
+ }
+
+ if (pixColor[3] == 0.0) {
+ discard; return;
+ }
+
+ gl_FragColor = pixColor;
+}
+)#"; \ No newline at end of file
diff --git a/src/render/shaders/Shadow.hpp b/src/render/shaders/Shadow.hpp
index f54124fa..dca194c0 100644
--- a/src/render/shaders/Shadow.hpp
+++ b/src/render/shaders/Shadow.hpp
@@ -13,7 +13,6 @@ uniform vec2 fullSize;
uniform float radius;
uniform float range;
uniform float shadowPower;
-uniform int ignoreWindow;
float pixAlphaRoundedDistance(float distanceToCorner) {
if (distanceToCorner > radius) {
@@ -75,7 +74,7 @@ void main() {
}
}
- if (pixColor[3] == 0.0 || (ignoreWindow == 1 && pixColor[3] == originalAlpha)) {
+ if (pixColor[3] == 0.0) {
discard; return;
}