Back to rendering rounded box as stencil mask

This commit is contained in:
Erik Reider 2023-01-09 22:27:22 +01:00
parent ae4f5fee9b
commit 2a5486184b
10 changed files with 37 additions and 86 deletions

View file

@ -113,12 +113,6 @@ void fx_renderer_clear(const float color[static 4]);
void fx_renderer_scissor(struct wlr_box *box); 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, 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], const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9],
struct decoration_data deco_data); struct decoration_data deco_data);

View file

@ -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, 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], const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9],
struct decoration_data deco_data) { 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); 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 // 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);
@ -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); glDisableVertexAttribArray(renderer->shaders.box_shadow.pos_attrib);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glDisable(GL_STENCIL_TEST);
} }

View file

@ -1001,8 +1001,6 @@ static void render_containers_linear(struct sway_output *output,
.has_titlebar = has_titlebar, .has_titlebar = has_titlebar,
}; };
fx_renderer_start_stenciling(true);
render_view(output, damage, child, colors, deco_data); render_view(output, damage, child, colors, deco_data);
if (has_titlebar) { if (has_titlebar) {
render_titlebar(output, damage, child, floor(state->x), floor(state->y), 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); render_top_border(output, damage, state, colors, deco_data.alpha, deco_data.corner_radius);
} }
fx_renderer_close_stenciling(true);
// render shadow // render shadow
if (child->shadow_enabled if (child->shadow_enabled
&& config->shadow_blur_sigma > 0 && config->shadow_blur_sigma > 0
&& config->shadow_color[3] > 0.0 && config->shadow_color[3] > 0.0) {
&& child->current.border != B_CSD) {
struct wlr_box box = { state->x, state->y, state->width, state->height }; struct wlr_box box = { state->x, state->y, state->width, state->height };
scale_box(&box, output->wlr_output->scale); scale_box(&box, output->wlr_output->scale);
render_box_shadow(output, damage, &box, config->shadow_color, render_box_shadow(output, damage, &box, config->shadow_color,
config->shadow_blur_sigma, deco_data.corner_radius, config->shadow_blur_sigma, deco_data.corner_radius,
state->border_thickness); state->border_thickness);
} }
fx_renderer_end_stenciling();
} else { } else {
render_container(output, damage, child, render_container(output, damage, child,
parent->focused || child->current.focused); 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; struct border_colors *current_colors = &config->border_colors.unfocused;
int tab_width = parent->box.width / parent->children->length; int tab_width = parent->box.width / parent->children->length;
fx_renderer_start_stenciling(true);
// Render tabs // Render tabs
for (int i = 0; i < parent->children->length; ++i) { for (int i = 0; i < parent->children->length; ++i) {
struct sway_container *child = parent->children->items[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); parent->focused || current->current.focused);
} }
fx_renderer_close_stenciling(true);
// render shadow // render shadow
if (current->shadow_enabled if (current->shadow_enabled
&& config->shadow_blur_sigma > 0 && config->shadow_blur_sigma > 0
&& config->shadow_color[3] > 0.0 && config->shadow_color[3] > 0.0) {
&& current->current.border != B_CSD) {
struct sway_container_state *state = &current->current; struct sway_container_state *state = &current->current;
struct wlr_box box = { state->x, state->y, state->width, state->height }; struct wlr_box box = { state->x, state->y, state->width, state->height };
scale_box(&box, output->wlr_output->scale); 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, config->shadow_blur_sigma, current->corner_radius,
state->border_thickness); 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; struct border_colors *current_colors = &config->border_colors.unfocused;
size_t titlebar_height = container_titlebar_height(); size_t titlebar_height = container_titlebar_height();
fx_renderer_start_stenciling(true);
// Render titles // Render titles
for (int i = 0; i < parent->children->length; ++i) { for (int i = 0; i < parent->children->length; ++i) {
struct sway_container *child = parent->children->items[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); parent->focused || current->current.focused);
} }
fx_renderer_close_stenciling(true);
// render shadow // render shadow
if (current->shadow_enabled if (current->shadow_enabled
&& config->shadow_blur_sigma > 0 && config->shadow_blur_sigma > 0
&& config->shadow_color[3] > 0.0 && config->shadow_color[3] > 0.0) {
&& current->current.border != B_CSD) {
struct sway_container_state *state = &current->current; struct sway_container_state *state = &current->current;
struct wlr_box box = { state->x, state->y, state->width, state->height }; struct wlr_box box = { state->x, state->y, state->width, state->height };
scale_box(&box, output->wlr_output->scale); 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, config->shadow_blur_sigma, current->corner_radius,
state->border_thickness); state->border_thickness);
} }
fx_renderer_end_stenciling();
} }
static void render_containers(struct sway_output *output, 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, .corner_radius = con->corner_radius,
.has_titlebar = has_titlebar, .has_titlebar = has_titlebar,
}; };
fx_renderer_start_stenciling(true);
render_view(soutput, damage, con, colors, deco_data); render_view(soutput, damage, con, colors, deco_data);
if (has_titlebar) { if (has_titlebar) {
render_titlebar(soutput, damage, con, floor(state->x), floor(state->y), 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); render_top_border(soutput, damage, state, colors, deco_data.alpha, deco_data.corner_radius);
} }
fx_renderer_close_stenciling(true);
// render shadow // render shadow
if (con->shadow_enabled if (con->shadow_enabled
&& config->shadow_blur_sigma > 0 && 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, config->shadow_blur_sigma, deco_data.corner_radius,
con->current.border_thickness); con->current.border_thickness);
} }
fx_renderer_end_stenciling();
} else { } else {
render_container(soutput, damage, con, state->focused); render_container(soutput, damage, con, state->focused);
} }

View file

@ -24,8 +24,7 @@ void main() {
float smoothedAlphaInner = 1.0 - smoothstep(-1.0, 0.5, dist + half_thickness); float smoothedAlphaInner = 1.0 - smoothstep(-1.0, 0.5, dist + half_thickness);
gl_FragColor = mix(vec4(0), v_color, smoothedAlphaOuter - smoothedAlphaInner); gl_FragColor = mix(vec4(0), v_color, smoothedAlphaOuter - smoothedAlphaInner);
// Discards outside the curve and transparent pixels if (gl_FragColor.a == 0.0) {
if (dist > half_thickness || gl_FragColor.a == 0.0) {
discard; discard;
return; return;
} }

View file

@ -13,8 +13,7 @@ void main() {
float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, dist); float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, dist);
gl_FragColor = mix(vec4(0), v_color, smoothedAlpha); gl_FragColor = mix(vec4(0), v_color, smoothedAlpha);
// Discards outside the curve and transparent pixels if (gl_FragColor.a == 0.0) {
if (dist > 0.0 || gl_FragColor.a == 0.0) {
discard; discard;
} }
} }

View file

@ -12,8 +12,7 @@ void main() {
float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, dist); float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, dist);
gl_FragColor = mix(vec4(0), v_color, smoothedAlpha); gl_FragColor = mix(vec4(0), v_color, smoothedAlpha);
// Discards outside the curve and transparent pixels if (gl_FragColor.a == 0.0) {
if (dist > 0.0 || gl_FragColor.a == 0.0) {
discard; discard;
} }
} }

View file

@ -12,8 +12,7 @@ void main() {
float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, dist); float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, dist);
gl_FragColor = mix(vec4(0), v_color, smoothedAlpha); gl_FragColor = mix(vec4(0), v_color, smoothedAlpha);
// Discards outside the curve and transparent pixels if (gl_FragColor.a == 0.0) {
if (dist > 0.0 || gl_FragColor.a == 0.0) {
discard; discard;
} }
} }

View file

@ -32,11 +32,6 @@ void main() {
float dist = radius - distance(corner_distance, vec2(radius)); float dist = radius - distance(corner_distance, vec2(radius));
float smooth = smoothstep(-1.0f, 0.5f, dist); float smooth = smoothstep(-1.0f, 0.5f, dist);
gl_FragColor = mix(vec4(0), gl_FragColor, smooth); gl_FragColor = mix(vec4(0), gl_FragColor, smooth);
// Discards pixels outside the curve
if (dist < 0.0) {
discard;
return;
}
} }
} }

View file

@ -30,11 +30,6 @@ void main() {
float dist = radius - distance(corner_distance, vec2(radius)); float dist = radius - distance(corner_distance, vec2(radius));
float smooth = smoothstep(-1.0f, 0.5f, dist); float smooth = smoothstep(-1.0f, 0.5f, dist);
gl_FragColor = mix(vec4(0), gl_FragColor, smooth); gl_FragColor = mix(vec4(0), gl_FragColor, smooth);
// Discards pixels outside the curve
if (dist < 0.0) {
discard;
return;
}
} }
} }

View file

@ -29,11 +29,6 @@ void main() {
float dist = radius - distance(corner_distance, vec2(radius)); float dist = radius - distance(corner_distance, vec2(radius));
float smooth = smoothstep(-1.0f, 0.5f, dist); float smooth = smoothstep(-1.0f, 0.5f, dist);
gl_FragColor = mix(vec4(0), gl_FragColor, smooth); gl_FragColor = mix(vec4(0), gl_FragColor, smooth);
// Discards pixels outside the curve
if (dist < 0.0) {
discard;
return;
}
} }
} }