diff options
| author | xDarksome <dev@darkso.me> | 2022-06-24 18:58:11 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-06-24 18:58:11 +0300 |
| commit | be460ea9547691eb136bf8b600b67b778af47e3f (patch) | |
| tree | b74869ad39dd804aec31694d4dd429822c223644 /src/render | |
| parent | 776ca3baf269059e8c13ba8b625645215e71f78c (diff) | |
| parent | e7467c60f9fe9e66c74dd8dc7c752a73ed4bc4db (diff) | |
Merge branch 'hyprwm:main' into main
Diffstat (limited to 'src/render')
| -rw-r--r-- | src/render/OpenGL.cpp | 84 | ||||
| -rw-r--r-- | src/render/OpenGL.hpp | 9 | ||||
| -rw-r--r-- | src/render/Renderer.cpp | 32 |
3 files changed, 96 insertions, 29 deletions
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 6a82cb83..85dd29be 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -240,6 +240,10 @@ 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) { + renderRectWithDamage(box, col, m_RenderData.pDamage, round); +} + +void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixman_region32_t* 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()!"); @@ -279,8 +283,8 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) { glEnableVertexAttribArray(m_shQUAD.posAttrib); glEnableVertexAttribArray(m_shQUAD.texAttrib); - if (pixman_region32_not_empty(m_RenderData.pDamage)) { - PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) { + if (pixman_region32_not_empty(damage)) { + PIXMAN_DAMAGE_FOREACH(damage) { const auto RECT = RECTSARR[i]; scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); @@ -299,15 +303,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) { +void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool border, bool allowPrimary) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); - renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, border); + renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, border, 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) { +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) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!"); @@ -341,6 +345,23 @@ 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); @@ -357,8 +378,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b // so we need to do some maf const auto TOPLEFT = Vector2D(round, round); - const auto BOTTOMRIGHT = Vector2D(tex.m_vSize.x - round, tex.m_vSize.y - round); - const auto FULLSIZE = tex.m_vSize; + const auto BOTTOMRIGHT = Vector2D(pBox->width - round, pBox->height - round); + const auto FULLSIZE = Vector2D(pBox->width, pBox->height); static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue; // Rounded corners @@ -369,22 +390,23 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !border && !noAA)); glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); - glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); - glEnableVertexAttribArray(shader->posAttrib); - glEnableVertexAttribArray(shader->texAttrib); + if (allowPrimary && m_RenderData.renderingPrimarySurface && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) { + const float verts[] = { + m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right + m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left + m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom right + m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom left + }; - // 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); + glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, verts); + } else { + glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); } + glEnableVertexAttribArray(shader->posAttrib); + glEnableVertexAttribArray(shader->texAttrib); + if (pixman_region32_not_empty(m_RenderData.pDamage)) { PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) { const auto RECT = RECTSARR[i]; @@ -394,6 +416,8 @@ 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); } @@ -540,9 +564,10 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, 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) { - renderTexture(tex, pBox, a, round, false, border); + if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1))) { + renderTexture(tex, pBox, a, round, false, border, true); return; } @@ -599,17 +624,26 @@ 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); + renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, false, true); // render the window, but clear stencil glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); - // and write to it + // 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); - renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true); + 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); @@ -649,7 +683,7 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int thick, i box->width += 2 * thick; box->height += 2 * thick; - round += thick * m_RenderData.pMonitor->scale; // cuz yeah + round += thick; // cuz yeah // only draw on non-stencild. glStencilFunc(GL_NOTEQUAL, 1, -1); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 9a8084db..0648e73a 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -34,6 +34,10 @@ struct SCurrentRenderData { float projection[9]; pixman_region32_t* pDamage = nullptr; + + bool renderingPrimarySurface = false; + Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); + Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); }; struct SMonitorRenderData { @@ -53,8 +57,9 @@ public: 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 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); + 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 makeWindowSnapshot(CWindow*); @@ -110,7 +115,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); + 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); }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index eb29a65d..8118af48 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -23,8 +23,12 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding; - if (RDATA->surface && surface == RDATA->surface) + g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = false; + + 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); + } else g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false); @@ -142,6 +146,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); const auto REALPOS = pWindow->m_vRealPosition.vec() + PWORKSPACE->m_vRenderOffset.vec(); + static const auto PNOFLOATINGBORDERS = &g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue; + SRenderData renderdata = {pMonitor->output, time, REALPOS.x, REALPOS.y}; renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow); renderdata.w = std::clamp(pWindow->m_vRealSize.vec().x, (double)5, (double)1337420); // clamp the size to min 5, @@ -149,7 +155,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; + renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true); renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding; // apply window special data @@ -164,8 +170,30 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* for (auto& wd : pWindow->m_dWindowDecorations) wd->draw(pMonitor); + if (!pWindow->m_bIsX11) { + + // To everyone who makes apps with improperly aligned surfaces, + // For example chromium, or GTK devs who allow shadows on windows, + // a sincere FUCK YOU. + + wlr_box geom; + wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom); + + g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D((double)geom.x / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)geom.y / (double)pWindow->m_uSurface.xdg->surface->current.height); + g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D((double)(geom.width + geom.x) / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)(geom.y + geom.height) / (double)pWindow->m_uSurface.xdg->surface->current.height); + + if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D() && g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) { + // No special UV mods needed + g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); + g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); + } + } + wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata); + g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); + g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); + if (pWindow->m_bIsX11) { if (pWindow->m_uSurface.xwayland->surface) { wlr_surface_for_each_surface(pWindow->m_uSurface.xwayland->surface, renderSurface, &renderdata); |
