summaryrefslogtreecommitdiff
path: root/src/render
diff options
context:
space:
mode:
authorxDarksome <dev@darkso.me>2022-06-24 18:58:11 +0300
committerGitHub <noreply@github.com>2022-06-24 18:58:11 +0300
commitbe460ea9547691eb136bf8b600b67b778af47e3f (patch)
treeb74869ad39dd804aec31694d4dd429822c223644 /src/render
parent776ca3baf269059e8c13ba8b625645215e71f78c (diff)
parente7467c60f9fe9e66c74dd8dc7c752a73ed4bc4db (diff)
Merge branch 'hyprwm:main' into main
Diffstat (limited to 'src/render')
-rw-r--r--src/render/OpenGL.cpp84
-rw-r--r--src/render/OpenGL.hpp9
-rw-r--r--src/render/Renderer.cpp32
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);