diff --git a/include/sway/desktop/fx_renderer.h b/include/sway/desktop/fx_renderer.h index d1ce8f5e..1c3121cd 100644 --- a/include/sway/desktop/fx_renderer.h +++ b/include/sway/desktop/fx_renderer.h @@ -113,12 +113,6 @@ void fx_renderer_clear(const float color[static 4]); void fx_renderer_scissor(struct wlr_box *box); -void fx_renderer_start_stenciling(bool color_mask_write); - -void fx_renderer_close_stenciling(bool color_mask_write); - -void fx_renderer_end_stenciling(); - bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer, struct wlr_texture *wlr_texture, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9], struct decoration_data deco_data); diff --git a/sway/desktop/fx_renderer.c b/sway/desktop/fx_renderer.c index b5669927..03645b0f 100644 --- a/sway/desktop/fx_renderer.c +++ b/sway/desktop/fx_renderer.c @@ -395,34 +395,6 @@ void fx_renderer_scissor(struct wlr_box *box) { } } -void fx_renderer_start_stenciling(bool color_mask_write) { - glEnable(GL_STENCIL_TEST); - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - - glStencilFunc(GL_ALWAYS, 1, 0xFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - // Disable writing to color buffer - if (!color_mask_write) { - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - } -} - -void fx_renderer_close_stenciling(bool color_mask_write) { - glStencilFunc(GL_NOTEQUAL, 1, 0xFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - // Reenable writing to color buffer - if (!color_mask_write) { - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } -} - -void fx_renderer_end_stenciling() { - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - glDisable(GL_STENCIL_TEST); -} - bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer, struct wlr_texture *wlr_texture, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9], struct decoration_data deco_data) { @@ -692,6 +664,32 @@ void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *bo wlr_matrix_transpose(gl_matrix, gl_matrix); + // Init stencil work + // NOTE: Alpha needs to be set to 1.0 to be able to discard any "empty" pixels + const float col[4] = {0.0, 0.0, 0.0, 1.0}; + struct wlr_box inner_box; + memcpy(&inner_box, box, sizeof(struct wlr_box)); + inner_box.x += blur_sigma; + inner_box.y += blur_sigma; + inner_box.width -= blur_sigma * 2; + inner_box.height -= blur_sigma * 2; + + glEnable(GL_STENCIL_TEST); + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + + glStencilFunc(GL_ALWAYS, 1, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + // Disable writing to color buffer + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + // Draw the rounded rect as a mask + fx_render_rounded_rect(renderer, &inner_box, col, projection, corner_radius, ALL); + // Close the mask + glStencilFunc(GL_NOTEQUAL, 1, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + // Reenable writing to color buffer + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + // blending will practically always be needed (unless we have a madman // who uses opaque shadows with zero sigma), so just enable it glEnable(GL_BLEND); @@ -718,4 +716,8 @@ void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *bo glDisableVertexAttribArray(renderer->shaders.box_shadow.pos_attrib); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + glDisable(GL_STENCIL_TEST); } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index b7ddd664..fcd256eb 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -1001,8 +1001,6 @@ static void render_containers_linear(struct sway_output *output, .has_titlebar = has_titlebar, }; - fx_renderer_start_stenciling(true); - render_view(output, damage, child, colors, deco_data); if (has_titlebar) { render_titlebar(output, damage, child, floor(state->x), floor(state->y), @@ -1012,21 +1010,16 @@ static void render_containers_linear(struct sway_output *output, render_top_border(output, damage, state, colors, deco_data.alpha, deco_data.corner_radius); } - fx_renderer_close_stenciling(true); - // render shadow if (child->shadow_enabled && config->shadow_blur_sigma > 0 - && config->shadow_color[3] > 0.0 - && child->current.border != B_CSD) { + && config->shadow_color[3] > 0.0) { struct wlr_box box = { state->x, state->y, state->width, state->height }; scale_box(&box, output->wlr_output->scale); render_box_shadow(output, damage, &box, config->shadow_color, config->shadow_blur_sigma, deco_data.corner_radius, state->border_thickness); } - - fx_renderer_end_stenciling(); } else { render_container(output, damage, child, parent->focused || child->current.focused); @@ -1054,8 +1047,6 @@ static void render_containers_tabbed(struct sway_output *output, struct border_colors *current_colors = &config->border_colors.unfocused; int tab_width = parent->box.width / parent->children->length; - fx_renderer_start_stenciling(true); - // Render tabs for (int i = 0; i < parent->children->length; ++i) { struct sway_container *child = parent->children->items[i]; @@ -1122,13 +1113,10 @@ static void render_containers_tabbed(struct sway_output *output, parent->focused || current->current.focused); } - fx_renderer_close_stenciling(true); - // render shadow if (current->shadow_enabled && config->shadow_blur_sigma > 0 - && config->shadow_color[3] > 0.0 - && current->current.border != B_CSD) { + && config->shadow_color[3] > 0.0) { struct sway_container_state *state = ¤t->current; struct wlr_box box = { state->x, state->y, state->width, state->height }; scale_box(&box, output->wlr_output->scale); @@ -1136,8 +1124,6 @@ static void render_containers_tabbed(struct sway_output *output, config->shadow_blur_sigma, current->corner_radius, state->border_thickness); } - - fx_renderer_end_stenciling(); } /** @@ -1152,8 +1138,6 @@ static void render_containers_stacked(struct sway_output *output, struct border_colors *current_colors = &config->border_colors.unfocused; size_t titlebar_height = container_titlebar_height(); - fx_renderer_start_stenciling(true); - // Render titles for (int i = 0; i < parent->children->length; ++i) { struct sway_container *child = parent->children->items[i]; @@ -1215,13 +1199,10 @@ static void render_containers_stacked(struct sway_output *output, parent->focused || current->current.focused); } - fx_renderer_close_stenciling(true); - // render shadow if (current->shadow_enabled && config->shadow_blur_sigma > 0 - && config->shadow_color[3] > 0.0 - && current->current.border != B_CSD) { + && config->shadow_color[3] > 0.0) { struct sway_container_state *state = ¤t->current; struct wlr_box box = { state->x, state->y, state->width, state->height }; scale_box(&box, output->wlr_output->scale); @@ -1229,8 +1210,6 @@ static void render_containers_stacked(struct sway_output *output, config->shadow_blur_sigma, current->corner_radius, state->border_thickness); } - - fx_renderer_end_stenciling(); } static void render_containers(struct sway_output *output, @@ -1326,7 +1305,6 @@ static void render_floating_container(struct sway_output *soutput, .corner_radius = con->corner_radius, .has_titlebar = has_titlebar, }; - fx_renderer_start_stenciling(true); render_view(soutput, damage, con, colors, deco_data); if (has_titlebar) { render_titlebar(soutput, damage, con, floor(state->x), floor(state->y), @@ -1336,8 +1314,6 @@ static void render_floating_container(struct sway_output *soutput, render_top_border(soutput, damage, state, colors, deco_data.alpha, deco_data.corner_radius); } - fx_renderer_close_stenciling(true); - // render shadow if (con->shadow_enabled && config->shadow_blur_sigma > 0 @@ -1349,8 +1325,6 @@ static void render_floating_container(struct sway_output *soutput, config->shadow_blur_sigma, deco_data.corner_radius, con->current.border_thickness); } - - fx_renderer_end_stenciling(); } else { render_container(soutput, damage, con, state->focused); } diff --git a/sway/desktop/shaders/corner.frag b/sway/desktop/shaders/corner.frag index a8465d60..10810971 100644 --- a/sway/desktop/shaders/corner.frag +++ b/sway/desktop/shaders/corner.frag @@ -24,8 +24,7 @@ void main() { float smoothedAlphaInner = 1.0 - smoothstep(-1.0, 0.5, dist + half_thickness); gl_FragColor = mix(vec4(0), v_color, smoothedAlphaOuter - smoothedAlphaInner); - // Discards outside the curve and transparent pixels - if (dist > half_thickness || gl_FragColor.a == 0.0) { + if (gl_FragColor.a == 0.0) { discard; return; } diff --git a/sway/desktop/shaders/quad_round.frag b/sway/desktop/shaders/quad_round.frag index ad486651..ddd6fe9b 100644 --- a/sway/desktop/shaders/quad_round.frag +++ b/sway/desktop/shaders/quad_round.frag @@ -13,8 +13,7 @@ void main() { float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, dist); gl_FragColor = mix(vec4(0), v_color, smoothedAlpha); - // Discards outside the curve and transparent pixels - if (dist > 0.0 || gl_FragColor.a == 0.0) { + if (gl_FragColor.a == 0.0) { discard; } } diff --git a/sway/desktop/shaders/quad_round_tl.frag b/sway/desktop/shaders/quad_round_tl.frag index 76283679..77379418 100644 --- a/sway/desktop/shaders/quad_round_tl.frag +++ b/sway/desktop/shaders/quad_round_tl.frag @@ -12,8 +12,7 @@ void main() { float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, dist); gl_FragColor = mix(vec4(0), v_color, smoothedAlpha); - // Discards outside the curve and transparent pixels - if (dist > 0.0 || gl_FragColor.a == 0.0) { + if (gl_FragColor.a == 0.0) { discard; } } diff --git a/sway/desktop/shaders/quad_round_tr.frag b/sway/desktop/shaders/quad_round_tr.frag index 392af76e..b4daac01 100644 --- a/sway/desktop/shaders/quad_round_tr.frag +++ b/sway/desktop/shaders/quad_round_tr.frag @@ -12,8 +12,7 @@ void main() { float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, dist); gl_FragColor = mix(vec4(0), v_color, smoothedAlpha); - // Discards outside the curve and transparent pixels - if (dist > 0.0 || gl_FragColor.a == 0.0) { + if (gl_FragColor.a == 0.0) { discard; } } diff --git a/sway/desktop/shaders/tex_external.frag b/sway/desktop/shaders/tex_external.frag index 3d953bcd..502ed2a0 100644 --- a/sway/desktop/shaders/tex_external.frag +++ b/sway/desktop/shaders/tex_external.frag @@ -32,11 +32,6 @@ void main() { float dist = radius - distance(corner_distance, vec2(radius)); float smooth = smoothstep(-1.0f, 0.5f, dist); gl_FragColor = mix(vec4(0), gl_FragColor, smooth); - // Discards pixels outside the curve - if (dist < 0.0) { - discard; - return; - } } } diff --git a/sway/desktop/shaders/tex_rgba.frag b/sway/desktop/shaders/tex_rgba.frag index a5c21cef..441b920f 100644 --- a/sway/desktop/shaders/tex_rgba.frag +++ b/sway/desktop/shaders/tex_rgba.frag @@ -30,11 +30,6 @@ void main() { float dist = radius - distance(corner_distance, vec2(radius)); float smooth = smoothstep(-1.0f, 0.5f, dist); gl_FragColor = mix(vec4(0), gl_FragColor, smooth); - // Discards pixels outside the curve - if (dist < 0.0) { - discard; - return; - } } } diff --git a/sway/desktop/shaders/tex_rgbx.frag b/sway/desktop/shaders/tex_rgbx.frag index a7297620..599fc7f5 100644 --- a/sway/desktop/shaders/tex_rgbx.frag +++ b/sway/desktop/shaders/tex_rgbx.frag @@ -29,11 +29,6 @@ void main() { float dist = radius - distance(corner_distance, vec2(radius)); float smooth = smoothstep(-1.0f, 0.5f, dist); gl_FragColor = mix(vec4(0), gl_FragColor, smooth); - // Discards pixels outside the curve - if (dist < 0.0) { - discard; - return; - } } }