Moved stencil logic into fx_renderer.c

This commit is contained in:
Erik Reider 2022-12-28 21:38:41 +01:00 committed by Will McKinnon
parent f498e62b53
commit ada90917d4
2 changed files with 32 additions and 32 deletions

View file

@ -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); 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 // blending will practically always be needed (unless we have a madman
// who uses opaque shadows with zero sigma), so just enable it // who uses opaque shadows with zero sigma), so just enable it
glEnable(GL_BLEND); 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); glDisableVertexAttribArray(renderer->shaders.box_shadow.pos_attrib);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
// cleanup
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glDisable(GL_STENCIL_TEST);
} }

View file

@ -338,16 +338,8 @@ void render_box_shadow(struct sway_output *output, pixman_region32_t *output_dam
struct wlr_box box; struct wlr_box box;
memcpy(&box, _box, sizeof(struct wlr_box)); memcpy(&box, _box, sizeof(struct wlr_box));
box.x -= output->lx * wlr_output->scale; box.x -= output->lx * wlr_output->scale + blur_sigma;
box.y -= output->ly * wlr_output->scale; box.y -= output->ly * wlr_output->scale + blur_sigma;
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.width += 2 * blur_sigma; box.width += 2 * blur_sigma;
box.height += 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; goto damage_finish;
} }
// Init stencil work
glEnable(GL_STENCIL_TEST);
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
int nrects; int nrects;
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
for (int i = 0; i < nrects; ++i) { for (int i = 0; i < nrects; ++i) {
scissor_output(wlr_output, &rects[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, fx_render_box_shadow(renderer, &box, color,
wlr_output->transform_matrix, corner_radius, blur_sigma); wlr_output->transform_matrix, corner_radius, blur_sigma);
} }
// cleanup
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glDisable(GL_STENCIL_TEST);
damage_finish: damage_finish:
pixman_region32_fini(&damage); pixman_region32_fini(&damage);
} }