diff --git a/sway/desktop/fx_renderer.c b/sway/desktop/fx_renderer.c index cdf762a4..aa18a4db 100644 --- a/sway/desktop/fx_renderer.c +++ b/sway/desktop/fx_renderer.c @@ -593,6 +593,31 @@ 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); + + // Use a rounded rect as a mask for the box shadow + glStencilFunc(GL_ALWAYS, 1, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + fx_render_rounded_rect(renderer, &inner_box, col, projection, corner_radius, ALL); + + glStencilFunc(GL_NOTEQUAL, 1, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + 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); @@ -620,4 +645,9 @@ 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); + + // cleanup + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + glDisable(GL_STENCIL_TEST); } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 4d79cbe6..0de870bf 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -338,16 +338,8 @@ void render_box_shadow(struct sway_output *output, pixman_region32_t *output_dam struct wlr_box box; memcpy(&box, _box, sizeof(struct wlr_box)); - box.x -= output->lx * wlr_output->scale; - box.y -= output->ly * wlr_output->scale; - - struct wlr_box inner_box; - memcpy(&inner_box, &box, sizeof(struct wlr_box)); - // 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}; - - box.x -= blur_sigma; - box.y -= blur_sigma; + box.x -= output->lx * wlr_output->scale + blur_sigma; + box.y -= output->ly * wlr_output->scale + blur_sigma; box.width += 2 * blur_sigma; box.height += 2 * blur_sigma; @@ -364,37 +356,15 @@ void render_box_shadow(struct sway_output *output, pixman_region32_t *output_dam goto damage_finish; } - // Init stencil work - glEnable(GL_STENCIL_TEST); - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - int nrects; pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { scissor_output(wlr_output, &rects[i]); - // Use a rounded rect as a mask for the box shadow - glStencilFunc(GL_ALWAYS, 1, 0xFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - - fx_render_rounded_rect(renderer, &inner_box, col, - wlr_output->transform_matrix, corner_radius, ALL); - - glStencilFunc(GL_NOTEQUAL, 1, 0xFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - fx_render_box_shadow(renderer, &box, color, wlr_output->transform_matrix, corner_radius, blur_sigma); } - // cleanup - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - glDisable(GL_STENCIL_TEST); - damage_finish: pixman_region32_fini(&damage); }