diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1a36b483..1e7fa458 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -45,6 +45,7 @@ void CConfigManager::setDefaultVars() { configValues["decoration:active_opacity"].floatValue = 1; configValues["decoration:inactive_opacity"].floatValue = 1; configValues["decoration:fullscreen_opacity"].floatValue = 1; + configValues["decoration:multisample_edges"].intValue = 1; configValues["dwindle:pseudotile"].intValue = 0; configValues["dwindle:col.group_border"].intValue = 0x66777700; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 061efc13..1cb5bae9 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -269,6 +269,7 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) { 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)(g_pConfigManager->getInt("decoration:multisample_edges") == 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); @@ -304,7 +305,7 @@ void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float al 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) { +void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool border, bool noAA) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!"); @@ -362,6 +363,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b 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)(g_pConfigManager->getInt("decoration:multisample_edges") == 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); @@ -598,7 +600,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, glStencilFunc(GL_ALWAYS, 1, -1); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - renderTextureInternalWithDamage(tex, pBox, a, &damage, round); + renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true); // then stop glStencilFunc(GL_EQUAL, 1, -1); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 34eef478..9a8084db 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -110,7 +110,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); + 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 renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0); }; diff --git a/src/render/Shaders.hpp b/src/render/Shaders.hpp index 11d40913..2dbbee3f 100644 --- a/src/render/Shaders.hpp +++ b/src/render/Shaders.hpp @@ -26,6 +26,8 @@ uniform vec2 bottomRight; uniform vec2 fullSize; uniform float radius; +uniform int primitiveMultisample; + void main() { if (radius == 0.0) { gl_FragColor = v_color; @@ -38,15 +40,57 @@ void main() { // we're close left if (pixCoord[1] < topLeft[1]) { // top - if (distance(topLeft, pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(topLeft, pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = v_color * distances; + return; + } } } else if (pixCoord[1] > bottomRight[1]) { // bottom - if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = v_color * distances; + return; + } } } } @@ -54,15 +98,57 @@ void main() { // we're close right if (pixCoord[1] < topLeft[1]) { // top - if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = v_color * distances; + return; + } } } else if (pixCoord[1] > bottomRight[1]) { // bottom - if (distance(bottomRight, pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(bottomRight, pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = v_color * distances; + return; + } } } } @@ -94,6 +180,8 @@ uniform float radius; uniform int discardOpaque; +uniform int primitiveMultisample; + void main() { vec4 pixColor = texture2D(tex, v_texcoord); @@ -109,15 +197,57 @@ void main() { // we're close left if (pixCoord[1] < topLeft[1]) { // top - if (distance(topLeft, pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(topLeft, pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = pixColor * distances; + return; + } } } else if (pixCoord[1] > bottomRight[1]) { // bottom - if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = pixColor * distances; + return; + } } } } @@ -125,15 +255,57 @@ void main() { // we're close right if (pixCoord[1] < topLeft[1]) { // top - if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = pixColor * distances; + return; + } } } else if (pixCoord[1] > bottomRight[1]) { // bottom - if (distance(bottomRight, pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(bottomRight, pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = pixColor * distances; + return; + } } } } @@ -154,12 +326,16 @@ uniform float radius; uniform int discardOpaque; +uniform int primitiveMultisample; + void main() { if (discardOpaque == 1 && alpha == 1.0) { discard; return; } + + vec4 pixColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0); vec2 pixCoord = fullSize * v_texcoord; @@ -167,15 +343,57 @@ void main() { // we're close left if (pixCoord[1] < topLeft[1]) { // top - if (distance(topLeft, pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(topLeft, pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = pixColor * distances; + return; + } } } else if (pixCoord[1] > bottomRight[1]) { // bottom - if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = pixColor * distances; + return; + } } } } @@ -183,20 +401,62 @@ void main() { // we're close right if (pixCoord[1] < topLeft[1]) { // top - if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = pixColor * distances; + return; + } } } else if (pixCoord[1] > bottomRight[1]) { // bottom - if (distance(bottomRight, pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(bottomRight, pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = pixColor * distances; + return; + } } } } - gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0) * alpha; + gl_FragColor = pixColor * alpha; })#"; inline const std::string FRAGBLUR1 = R"#( @@ -261,6 +521,8 @@ uniform float radius; uniform int discardOpaque; +uniform int primitiveMultisample; + void main() { vec4 pixColor = texture2D(texture0, v_texcoord); @@ -276,15 +538,57 @@ void main() { // we're close left if (pixCoord[1] < topLeft[1]) { // top - if (distance(topLeft, pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(topLeft, pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = pixColor * distances; + return; + } } } else if (pixCoord[1] > bottomRight[1]) { // bottom - if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = pixColor * distances; + return; + } } } } @@ -292,15 +596,57 @@ void main() { // we're close right if (pixCoord[1] < topLeft[1]) { // top - if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = pixColor * distances; + return; + } } } else if (pixCoord[1] > bottomRight[1]) { // bottom - if (distance(bottomRight, pixCoord) > radius) { - discard; - return; + + float topLeftDistance = distance(bottomRight, pixCoord); + + if (topLeftDistance > radius - 1.0) { + if (primitiveMultisample == 0 && topLeftDistance > radius) { + discard; + return; + } else if (primitiveMultisample == 1) { + float distances = 0.0; + if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; } + if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; } + if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; } + + if (distances == 0.0) { + discard; + return; + } + + distances = distances / 4.0; + + gl_FragColor = pixColor * distances; + return; + } } } }