From 06339c325c512a71a4344f4a05ddbc2f3dd162fb Mon Sep 17 00:00:00 2001 From: Will McKinnon Date: Sun, 30 Apr 2023 12:53:26 -0400 Subject: [PATCH 1/5] style: moved stencil mask to its own shader --- .../sway/desktop/fx_renderer/fx_renderer.h | 10 ++++ sway/desktop/fx_renderer/fx_renderer.c | 56 ++++++++++++++++++- sway/desktop/fx_renderer/shaders/meson.build | 1 + .../fx_renderer/shaders/quad_round.frag | 4 -- .../fx_renderer/shaders/stencil_mask.frag | 17 ++++++ 5 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 sway/desktop/fx_renderer/shaders/stencil_mask.frag diff --git a/include/sway/desktop/fx_renderer/fx_renderer.h b/include/sway/desktop/fx_renderer/fx_renderer.h index 109351e2..2aa38a7f 100644 --- a/include/sway/desktop/fx_renderer/fx_renderer.h +++ b/include/sway/desktop/fx_renderer/fx_renderer.h @@ -111,6 +111,16 @@ struct fx_renderer { struct rounded_quad_shader rounded_bl_quad; struct rounded_quad_shader rounded_br_quad; + struct { + GLuint program; + GLint proj; + GLint color; + GLint pos_attrib; + GLint half_size; + GLint position; + GLint radius; + } stencil_mask; + struct blur_shader blur1; struct blur_shader blur2; diff --git a/sway/desktop/fx_renderer/fx_renderer.c b/sway/desktop/fx_renderer/fx_renderer.c index 8de11874..18b847a6 100644 --- a/sway/desktop/fx_renderer/fx_renderer.c +++ b/sway/desktop/fx_renderer/fx_renderer.c @@ -25,6 +25,7 @@ #include "corner_frag_src.h" #include "quad_frag_src.h" #include "quad_round_frag_src.h" +#include "stencil_mask_frag_src.h" #include "tex_frag_src.h" static const GLfloat verts[] = { @@ -298,6 +299,19 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) { renderer->shaders.box_shadow.blur_sigma = glGetUniformLocation(prog, "blur_sigma"); renderer->shaders.box_shadow.corner_radius = glGetUniformLocation(prog, "corner_radius"); + // stencil mask shader + prog = link_program(stencil_mask_frag_src); + renderer->shaders.stencil_mask.program = prog; + if (!renderer->shaders.stencil_mask.program) { + goto error; + } + renderer->shaders.stencil_mask.proj = glGetUniformLocation(prog, "proj"); + renderer->shaders.stencil_mask.color = glGetUniformLocation(prog, "color"); + renderer->shaders.stencil_mask.pos_attrib = glGetAttribLocation(prog, "pos"); + renderer->shaders.stencil_mask.position = glGetUniformLocation(prog, "position"); + renderer->shaders.stencil_mask.radius = glGetUniformLocation(prog, "radius"); + renderer->shaders.stencil_mask.half_size = glGetUniformLocation(prog, "half_size"); + // Blur 1 prog = link_program(blur1_frag_src); renderer->shaders.blur1.program = prog; @@ -356,6 +370,7 @@ error: glDeleteProgram(renderer->shaders.rounded_bl_quad.program); glDeleteProgram(renderer->shaders.rounded_br_quad.program); glDeleteProgram(renderer->shaders.corner.program); + glDeleteProgram(renderer->shaders.stencil_mask.program); glDeleteProgram(renderer->shaders.box_shadow.program); glDeleteProgram(renderer->shaders.blur1.program); glDeleteProgram(renderer->shaders.blur2.program); @@ -684,6 +699,43 @@ void fx_render_border_corner(struct fx_renderer *renderer, const struct wlr_box glDisableVertexAttribArray(renderer->shaders.corner.pos_attrib); } +void fx_render_stencil_mask(struct fx_renderer *renderer, const struct wlr_box *box, + const float matrix[static 9], int corner_radius) { + if (box->width == 0 || box->height == 0) { + return; + } + assert(box->width > 0 && box->height > 0); + + // TODO: just pass gl_matrix? + float gl_matrix[9]; + wlr_matrix_multiply(gl_matrix, renderer->projection, matrix); + + // TODO: investigate why matrix is flipped prior to this cmd + // wlr_matrix_multiply(gl_matrix, flip_180, gl_matrix); + + wlr_matrix_transpose(gl_matrix, gl_matrix); + + glEnable(GL_BLEND); + + glUseProgram(renderer->shaders.stencil_mask.program); + + glUniformMatrix3fv(renderer->shaders.stencil_mask.proj, 1, GL_FALSE, gl_matrix); + + glUniform2f(renderer->shaders.stencil_mask.half_size, box->width * 0.5, box->height * 0.5); + glUniform2f(renderer->shaders.stencil_mask.position, box->x, box->y); + glUniform1f(renderer->shaders.stencil_mask.radius, corner_radius); + + glVertexAttribPointer(renderer->shaders.stencil_mask.pos_attrib, 2, GL_FLOAT, GL_FALSE, + 0, verts); + + glEnableVertexAttribArray(renderer->shaders.stencil_mask.pos_attrib); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glDisableVertexAttribArray(renderer->shaders.stencil_mask.pos_attrib); + +} + // TODO: alpha input arg? void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *box, const float color[static 4], const float matrix [static 9], int corner_radius, @@ -702,8 +754,6 @@ 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; @@ -720,7 +770,7 @@ void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *bo // 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, matrix, corner_radius, ALL); + fx_render_stencil_mask(renderer, &inner_box, matrix, corner_radius); // Close the mask glStencilFunc(GL_NOTEQUAL, 1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); diff --git a/sway/desktop/fx_renderer/shaders/meson.build b/sway/desktop/fx_renderer/shaders/meson.build index 83119963..7a27de80 100644 --- a/sway/desktop/fx_renderer/shaders/meson.build +++ b/sway/desktop/fx_renderer/shaders/meson.build @@ -8,6 +8,7 @@ shaders = [ 'corner.frag', 'quad.frag', 'quad_round.frag', + 'stencil_mask.frag', 'tex.frag', ] diff --git a/sway/desktop/fx_renderer/shaders/quad_round.frag b/sway/desktop/fx_renderer/shaders/quad_round.frag index 4099e60a..02e99028 100644 --- a/sway/desktop/fx_renderer/shaders/quad_round.frag +++ b/sway/desktop/fx_renderer/shaders/quad_round.frag @@ -36,8 +36,4 @@ void main() { float dist = min(max(q.x,q.y), 0.0) + length(max(q, 0.0)) - radius; float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, dist); gl_FragColor = mix(vec4(0), v_color, smoothedAlpha); - - if (gl_FragColor.a == 0.0) { - discard; - } } diff --git a/sway/desktop/fx_renderer/shaders/stencil_mask.frag b/sway/desktop/fx_renderer/shaders/stencil_mask.frag new file mode 100644 index 00000000..496981ef --- /dev/null +++ b/sway/desktop/fx_renderer/shaders/stencil_mask.frag @@ -0,0 +1,17 @@ +precision mediump float; +varying vec2 v_texcoord; + +uniform vec2 half_size; +uniform vec2 position; +uniform float radius; + +void main() { + vec2 q = abs(gl_FragCoord.xy - position - half_size) - half_size + radius; + float dist = min(max(q.x,q.y), 0.0) + length(max(q, 0.0)) - radius; + float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, dist); + gl_FragColor = mix(vec4(0.0), vec4(1.0), smoothedAlpha); + + if (gl_FragColor.a == 0.0) { + discard; + } +} From ace9a222b8557aa93ba2b6f3dac27424131574e4 Mon Sep 17 00:00:00 2001 From: Will McKinnon Date: Sun, 30 Apr 2023 13:03:09 -0400 Subject: [PATCH 2/5] style: created struct for each shader type --- .../sway/desktop/fx_renderer/fx_renderer.h | 146 +++---- sway/desktop/fx_renderer/fx_renderer.c | 356 ++++++++++-------- 2 files changed, 264 insertions(+), 238 deletions(-) diff --git a/include/sway/desktop/fx_renderer/fx_renderer.h b/include/sway/desktop/fx_renderer/fx_renderer.h index 2aa38a7f..bdbcefe1 100644 --- a/include/sway/desktop/fx_renderer/fx_renderer.h +++ b/include/sway/desktop/fx_renderer/fx_renderer.h @@ -35,7 +35,70 @@ struct decoration_data { bool blur; }; -struct gles2_tex_shader { +struct blur_shader { + GLuint program; + GLint proj; + GLint tex; + GLint pos_attrib; + GLint tex_attrib; + GLint radius; + GLint halfpixel; +}; + +struct box_shadow_shader { + GLuint program; + GLint proj; + GLint color; + GLint pos_attrib; + GLint position; + GLint size; + GLint blur_sigma; + GLint corner_radius; +}; + +struct corner_shader { + GLuint program; + GLint proj; + GLint color; + GLint pos_attrib; + GLint is_top_left; + GLint is_top_right; + GLint is_bottom_left; + GLint is_bottom_right; + GLint position; + GLint radius; + GLint half_size; + GLint half_thickness; +}; + +struct quad_shader { + GLuint program; + GLint proj; + GLint color; + GLint pos_attrib; +}; + +struct rounded_quad_shader { + GLuint program; + GLint proj; + GLint color; + GLint pos_attrib; + GLint size; + GLint position; + GLint radius; +}; + +struct stencil_mask_shader { + GLuint program; + GLint proj; + GLint color; + GLint pos_attrib; + GLint half_size; + GLint position; + GLint radius; +}; + +struct tex_shader { GLuint program; GLint proj; GLint tex; @@ -51,26 +114,6 @@ struct gles2_tex_shader { GLint has_titlebar; }; -struct rounded_quad_shader { - GLuint program; - GLint proj; - GLint color; - GLint pos_attrib; - GLint size; - GLint position; - GLint radius; -}; - -struct blur_shader { - GLuint program; - GLint proj; - GLint tex; - GLint pos_attrib; - GLint tex_attrib; - GLint radius; - GLint halfpixel; -}; - struct fx_renderer { float projection[9]; @@ -95,64 +138,21 @@ struct fx_renderer { PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; } procs; - - // Shaders struct { - struct { - GLuint program; - GLint proj; - GLint color; - GLint pos_attrib; - } quad; - + struct box_shadow_shader box_shadow; + struct blur_shader blur1; + struct blur_shader blur2; + struct corner_shader corner; + struct quad_shader quad; struct rounded_quad_shader rounded_quad; struct rounded_quad_shader rounded_tl_quad; struct rounded_quad_shader rounded_tr_quad; struct rounded_quad_shader rounded_bl_quad; struct rounded_quad_shader rounded_br_quad; - - struct { - GLuint program; - GLint proj; - GLint color; - GLint pos_attrib; - GLint half_size; - GLint position; - GLint radius; - } stencil_mask; - - struct blur_shader blur1; - struct blur_shader blur2; - - struct { - GLuint program; - GLint proj; - GLint color; - GLint pos_attrib; - GLint is_top_left; - GLint is_top_right; - GLint is_bottom_left; - GLint is_bottom_right; - GLint position; - GLint radius; - GLint half_size; - GLint half_thickness; - } corner; - - struct { - GLuint program; - GLint proj; - GLint color; - GLint pos_attrib; - GLint position; - GLint size; - GLint blur_sigma; - GLint corner_radius; - } box_shadow; - - struct gles2_tex_shader tex_rgba; - struct gles2_tex_shader tex_rgbx; - struct gles2_tex_shader tex_ext; + struct stencil_mask_shader stencil_mask; + struct tex_shader tex_rgba; + struct tex_shader tex_rgbx; + struct tex_shader tex_ext; } shaders; }; diff --git a/sway/desktop/fx_renderer/fx_renderer.c b/sway/desktop/fx_renderer/fx_renderer.c index 18b847a6..576d50c6 100644 --- a/sway/desktop/fx_renderer/fx_renderer.c +++ b/sway/desktop/fx_renderer/fx_renderer.c @@ -112,8 +112,115 @@ error: return 0; } -static bool link_tex_program(struct fx_renderer *renderer, - struct gles2_tex_shader *shader, enum fx_tex_shader_source source) { +static bool link_blur_program(struct blur_shader *shader, const char *shader_program) { + GLuint prog; + shader->program = prog = link_program(shader_program); + if (!shader->program) { + return false; + } + shader->proj = glGetUniformLocation(prog, "proj"); + shader->tex = glGetUniformLocation(prog, "tex"); + shader->pos_attrib = glGetAttribLocation(prog, "pos"); + shader->tex_attrib = glGetAttribLocation(prog, "texcoord"); + shader->radius = glGetUniformLocation(prog, "radius"); + shader->halfpixel = glGetUniformLocation(prog, "halfpixel"); + + return true; +} + +static bool link_box_shadow_program(struct box_shadow_shader *shader) { + GLuint prog; + shader->program = prog = link_program(box_shadow_frag_src); + if (!shader->program) { + return false; + } + shader->proj = glGetUniformLocation(prog, "proj"); + shader->color = glGetUniformLocation(prog, "color"); + shader->pos_attrib = glGetAttribLocation(prog, "pos"); + shader->position = glGetUniformLocation(prog, "position"); + shader->size = glGetUniformLocation(prog, "size"); + shader->blur_sigma = glGetUniformLocation(prog, "blur_sigma"); + shader->corner_radius = glGetUniformLocation(prog, "corner_radius"); + + return true; +} + +static bool link_corner_program(struct corner_shader *shader) { + GLuint prog; + shader->program = prog = link_program(corner_frag_src); + if (!shader->program) { + return false; + } + shader->proj = glGetUniformLocation(prog, "proj"); + shader->color = glGetUniformLocation(prog, "color"); + shader->pos_attrib = glGetAttribLocation(prog, "pos"); + shader->position = glGetUniformLocation(prog, "position"); + shader->half_size = glGetUniformLocation(prog, "half_size"); + shader->half_thickness = glGetUniformLocation(prog, "half_thickness"); + shader->radius = glGetUniformLocation(prog, "radius"); + shader->is_top_left = glGetUniformLocation(prog, "is_top_left"); + shader->is_top_right = glGetUniformLocation(prog, "is_top_right"); + shader->is_bottom_left = glGetUniformLocation(prog, "is_bottom_left"); + shader->is_bottom_right = glGetUniformLocation(prog, "is_bottom_right"); + + return true; +} + +static bool link_quad_program(struct quad_shader *shader) { + GLuint prog; + shader->program = prog = link_program(quad_frag_src); + if (!shader->program) { + return false; + } + + shader->proj = glGetUniformLocation(prog, "proj"); + shader->color = glGetUniformLocation(prog, "color"); + shader->pos_attrib = glGetAttribLocation(prog, "pos"); + + return true; +} + +static bool link_rounded_quad_program(struct rounded_quad_shader *shader, + enum fx_rounded_quad_shader_source source) { + GLchar quad_src[2048]; + snprintf(quad_src, sizeof(quad_src), + "#define SOURCE %d\n%s", source, quad_round_frag_src); + + GLuint prog; + shader->program = prog = link_program(quad_src); + if (!shader->program) { + return false; + } + + shader->proj = glGetUniformLocation(prog, "proj"); + shader->color = glGetUniformLocation(prog, "color"); + shader->pos_attrib = glGetAttribLocation(prog, "pos"); + shader->size = glGetUniformLocation(prog, "size"); + shader->position = glGetUniformLocation(prog, "position"); + shader->radius = glGetUniformLocation(prog, "radius"); + + return true; +} + +static bool link_stencil_mask_program(struct stencil_mask_shader *shader) { + GLuint prog; + shader->program = prog = link_program(stencil_mask_frag_src); + if (!shader->program) { + return false; + } + + shader->proj = glGetUniformLocation(prog, "proj"); + shader->color = glGetUniformLocation(prog, "color"); + shader->pos_attrib = glGetAttribLocation(prog, "pos"); + shader->position = glGetUniformLocation(prog, "position"); + shader->half_size = glGetUniformLocation(prog, "half_size"); + shader->radius = glGetUniformLocation(prog, "radius"); + + return true; +} + +static bool link_tex_program(struct tex_shader *shader, + enum fx_tex_shader_source source) { GLchar frag_src[2048]; snprintf(frag_src, sizeof(frag_src), "#define SOURCE %d\n%s", source, tex_frag_src); @@ -140,28 +247,6 @@ static bool link_tex_program(struct fx_renderer *renderer, return true; } -static bool link_rounded_quad_program(struct fx_renderer *renderer, - struct rounded_quad_shader *shader, enum fx_rounded_quad_shader_source source) { - GLchar quad_src[2048]; - snprintf(quad_src, sizeof(quad_src), - "#define SOURCE %d\n%s", source, quad_round_frag_src); - - GLuint prog; - shader->program = prog = link_program(quad_src); - if (!shader->program) { - return false; - } - - shader->proj = glGetUniformLocation(prog, "proj"); - shader->color = glGetUniformLocation(prog, "color"); - shader->pos_attrib = glGetAttribLocation(prog, "pos"); - shader->size = glGetUniformLocation(prog, "size"); - shader->position = glGetUniformLocation(prog, "position"); - shader->radius = glGetUniformLocation(prog, "radius"); - - return true; -} - static bool check_gl_ext(const char *exts, const char *ext) { size_t extlen = strlen(ext); const char *end = exts + strlen(exts); @@ -232,127 +317,61 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) { "glEGLImageTargetTexture2DOES"); } - // init shaders - GLuint prog; - - // quad fragment shader - prog = link_program(quad_frag_src); - renderer->shaders.quad.program = prog; - if (!renderer->shaders.quad.program) { + // blur shaders + if (!link_blur_program(&renderer->shaders.blur1, blur1_frag_src)) { + goto error; + } + if (!link_blur_program(&renderer->shaders.blur2, blur2_frag_src)) { + goto error; + } + // box shadow shader + if (!link_box_shadow_program(&renderer->shaders.box_shadow)) { + goto error; + } + // corner border shader + if (!link_corner_program(&renderer->shaders.corner)) { + goto error; + } + // quad fragment shader + if (!link_quad_program(&renderer->shaders.quad)) { goto error; } - renderer->shaders.quad.proj = glGetUniformLocation(prog, "proj"); - renderer->shaders.quad.color = glGetUniformLocation(prog, "color"); - renderer->shaders.quad.pos_attrib = glGetAttribLocation(prog, "pos"); - // rounded quad fragment shaders - if (!link_rounded_quad_program(renderer, &renderer->shaders.rounded_quad, + if (!link_rounded_quad_program(&renderer->shaders.rounded_quad, SHADER_SOURCE_QUAD_ROUND)) { goto error; } - if (!link_rounded_quad_program(renderer, &renderer->shaders.rounded_tl_quad, + if (!link_rounded_quad_program(&renderer->shaders.rounded_tl_quad, SHADER_SOURCE_QUAD_ROUND_TOP_LEFT)) { goto error; } - if (!link_rounded_quad_program(renderer, &renderer->shaders.rounded_tr_quad, + if (!link_rounded_quad_program(&renderer->shaders.rounded_tr_quad, SHADER_SOURCE_QUAD_ROUND_TOP_RIGHT)) { goto error; } - if (!link_rounded_quad_program(renderer, &renderer->shaders.rounded_bl_quad, + if (!link_rounded_quad_program(&renderer->shaders.rounded_bl_quad, SHADER_SOURCE_QUAD_ROUND_BOTTOM_LEFT)) { goto error; } - if (!link_rounded_quad_program(renderer, &renderer->shaders.rounded_br_quad, + if (!link_rounded_quad_program(&renderer->shaders.rounded_br_quad, SHADER_SOURCE_QUAD_ROUND_BOTTOM_RIGHT)) { goto error; } - - // Border corner shader - prog = link_program(corner_frag_src); - renderer->shaders.corner.program = prog; - if (!renderer->shaders.corner.program) { - goto error; - } - renderer->shaders.corner.proj = glGetUniformLocation(prog, "proj"); - renderer->shaders.corner.color = glGetUniformLocation(prog, "color"); - renderer->shaders.corner.pos_attrib = glGetAttribLocation(prog, "pos"); - renderer->shaders.corner.is_top_left = glGetUniformLocation(prog, "is_top_left"); - renderer->shaders.corner.is_top_right = glGetUniformLocation(prog, "is_top_right"); - renderer->shaders.corner.is_bottom_left = glGetUniformLocation(prog, "is_bottom_left"); - renderer->shaders.corner.is_bottom_right = glGetUniformLocation(prog, "is_bottom_right"); - renderer->shaders.corner.position = glGetUniformLocation(prog, "position"); - renderer->shaders.corner.radius = glGetUniformLocation(prog, "radius"); - renderer->shaders.corner.half_size = glGetUniformLocation(prog, "half_size"); - renderer->shaders.corner.half_thickness = glGetUniformLocation(prog, "half_thickness"); - - // box shadow shader - prog = link_program(box_shadow_frag_src); - renderer->shaders.box_shadow.program = prog; - if (!renderer->shaders.box_shadow.program) { - goto error; - } - renderer->shaders.box_shadow.proj = glGetUniformLocation(prog, "proj"); - renderer->shaders.box_shadow.color = glGetUniformLocation(prog, "color"); - renderer->shaders.box_shadow.pos_attrib = glGetAttribLocation(prog, "pos"); - renderer->shaders.box_shadow.position = glGetUniformLocation(prog, "position"); - renderer->shaders.box_shadow.size = glGetUniformLocation(prog, "size"); - renderer->shaders.box_shadow.blur_sigma = glGetUniformLocation(prog, "blur_sigma"); - renderer->shaders.box_shadow.corner_radius = glGetUniformLocation(prog, "corner_radius"); - // stencil mask shader - prog = link_program(stencil_mask_frag_src); - renderer->shaders.stencil_mask.program = prog; - if (!renderer->shaders.stencil_mask.program) { + if (!link_stencil_mask_program(&renderer->shaders.stencil_mask)) { goto error; } - renderer->shaders.stencil_mask.proj = glGetUniformLocation(prog, "proj"); - renderer->shaders.stencil_mask.color = glGetUniformLocation(prog, "color"); - renderer->shaders.stencil_mask.pos_attrib = glGetAttribLocation(prog, "pos"); - renderer->shaders.stencil_mask.position = glGetUniformLocation(prog, "position"); - renderer->shaders.stencil_mask.radius = glGetUniformLocation(prog, "radius"); - renderer->shaders.stencil_mask.half_size = glGetUniformLocation(prog, "half_size"); - - // Blur 1 - prog = link_program(blur1_frag_src); - renderer->shaders.blur1.program = prog; - if (!renderer->shaders.blur1.program) { - goto error; - } - renderer->shaders.blur1.proj = glGetUniformLocation(prog, "proj"); - renderer->shaders.blur1.tex = glGetUniformLocation(prog, "tex"); - renderer->shaders.blur1.pos_attrib = glGetAttribLocation(prog, "pos"); - renderer->shaders.blur1.tex_attrib = glGetAttribLocation(prog, "texcoord"); - renderer->shaders.blur1.radius = glGetUniformLocation(prog, "radius"); - renderer->shaders.blur1.halfpixel = glGetUniformLocation(prog, "halfpixel"); - - // Blur 2 - prog = link_program(blur2_frag_src); - renderer->shaders.blur2.program = prog; - if (!renderer->shaders.blur2.program) { - goto error; - } - renderer->shaders.blur2.proj = glGetUniformLocation(prog, "proj"); - renderer->shaders.blur2.tex = glGetUniformLocation(prog, "tex"); - renderer->shaders.blur2.pos_attrib = glGetAttribLocation(prog, "pos"); - renderer->shaders.blur2.tex_attrib = glGetAttribLocation(prog, "texcoord"); - renderer->shaders.blur2.radius = glGetUniformLocation(prog, "radius"); - renderer->shaders.blur2.halfpixel = glGetUniformLocation(prog, "halfpixel"); - // fragment shaders - if (!link_tex_program(renderer, &renderer->shaders.tex_rgba, - SHADER_SOURCE_TEXTURE_RGBA)) { + if (!link_tex_program(&renderer->shaders.tex_rgba, SHADER_SOURCE_TEXTURE_RGBA)) { goto error; } - if (!link_tex_program(renderer, &renderer->shaders.tex_rgbx, - SHADER_SOURCE_TEXTURE_RGBX)) { + if (!link_tex_program(&renderer->shaders.tex_rgbx, SHADER_SOURCE_TEXTURE_RGBX)) { goto error; } - if (!link_tex_program(renderer, &renderer->shaders.tex_ext, - SHADER_SOURCE_TEXTURE_EXTERNAL)) { + if (!link_tex_program(&renderer->shaders.tex_ext, SHADER_SOURCE_TEXTURE_EXTERNAL)) { goto error; } - if (!eglMakeCurrent(wlr_egl_get_display(egl), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) { sway_log(SWAY_ERROR, "GLES2 RENDERER: Could not unset current EGL"); @@ -363,17 +382,17 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) { return renderer; error: - glDeleteProgram(renderer->shaders.quad.program); - glDeleteProgram(renderer->shaders.rounded_quad.program); - glDeleteProgram(renderer->shaders.rounded_tl_quad.program); - glDeleteProgram(renderer->shaders.rounded_tr_quad.program); - glDeleteProgram(renderer->shaders.rounded_bl_quad.program); - glDeleteProgram(renderer->shaders.rounded_br_quad.program); - glDeleteProgram(renderer->shaders.corner.program); - glDeleteProgram(renderer->shaders.stencil_mask.program); - glDeleteProgram(renderer->shaders.box_shadow.program); glDeleteProgram(renderer->shaders.blur1.program); glDeleteProgram(renderer->shaders.blur2.program); + glDeleteProgram(renderer->shaders.box_shadow.program); + glDeleteProgram(renderer->shaders.corner.program); + glDeleteProgram(renderer->shaders.quad.program); + glDeleteProgram(renderer->shaders.rounded_quad.program); + glDeleteProgram(renderer->shaders.rounded_bl_quad.program); + glDeleteProgram(renderer->shaders.rounded_br_quad.program); + glDeleteProgram(renderer->shaders.rounded_tl_quad.program); + glDeleteProgram(renderer->shaders.rounded_tr_quad.program); + glDeleteProgram(renderer->shaders.stencil_mask.program); glDeleteProgram(renderer->shaders.tex_rgba.program); glDeleteProgram(renderer->shaders.tex_rgbx.program); glDeleteProgram(renderer->shaders.tex_ext.program); @@ -453,7 +472,7 @@ bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer, struct fx_te const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9], struct decoration_data deco_data) { - struct gles2_tex_shader *shader = NULL; + struct tex_shader *shader = NULL; switch (fx_texture->target) { case GL_TEXTURE_2D: @@ -576,19 +595,20 @@ void fx_render_rect(struct fx_renderer *renderer, const struct wlr_box *box, glEnable(GL_BLEND); } - glUseProgram(renderer->shaders.quad.program); + struct quad_shader shader = renderer->shaders.quad; + glUseProgram(shader.program); - glUniformMatrix3fv(renderer->shaders.quad.proj, 1, GL_FALSE, gl_matrix); - glUniform4f(renderer->shaders.quad.color, color[0], color[1], color[2], color[3]); + glUniformMatrix3fv(shader.proj, 1, GL_FALSE, gl_matrix); + glUniform4f(shader.color, color[0], color[1], color[2], color[3]); - glVertexAttribPointer(renderer->shaders.quad.pos_attrib, 2, GL_FLOAT, GL_FALSE, + glVertexAttribPointer(shader.pos_attrib, 2, GL_FLOAT, GL_FALSE, 0, verts); - glEnableVertexAttribArray(renderer->shaders.quad.pos_attrib); + glEnableVertexAttribArray(shader.pos_attrib); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glDisableVertexAttribArray(renderer->shaders.quad.pos_attrib); + glDisableVertexAttribArray(shader.pos_attrib); } void fx_render_rounded_rect(struct fx_renderer *renderer, const struct wlr_box *box, @@ -674,29 +694,31 @@ void fx_render_border_corner(struct fx_renderer *renderer, const struct wlr_box glEnable(GL_BLEND); } - glUseProgram(renderer->shaders.corner.program); + struct corner_shader shader = renderer->shaders.corner; - glUniformMatrix3fv(renderer->shaders.corner.proj, 1, GL_FALSE, gl_matrix); - glUniform4f(renderer->shaders.corner.color, color[0], color[1], color[2], color[3]); + glUseProgram(shader.program); - glUniform1f(renderer->shaders.corner.is_top_left, corner_location == TOP_LEFT); - glUniform1f(renderer->shaders.corner.is_top_right, corner_location == TOP_RIGHT); - glUniform1f(renderer->shaders.corner.is_bottom_left, corner_location == BOTTOM_LEFT); - glUniform1f(renderer->shaders.corner.is_bottom_right, corner_location == BOTTOM_RIGHT); + glUniformMatrix3fv(shader.proj, 1, GL_FALSE, gl_matrix); + glUniform4f(shader.color, color[0], color[1], color[2], color[3]); - glUniform2f(renderer->shaders.corner.position, box->x, box->y); - glUniform1f(renderer->shaders.corner.radius, radius); - glUniform2f(renderer->shaders.corner.half_size, box->width / 2.0, box->height / 2.0); - glUniform1f(renderer->shaders.corner.half_thickness, border_thickness / 2.0); + glUniform1f(shader.is_top_left, corner_location == TOP_LEFT); + glUniform1f(shader.is_top_right, corner_location == TOP_RIGHT); + glUniform1f(shader.is_bottom_left, corner_location == BOTTOM_LEFT); + glUniform1f(shader.is_bottom_right, corner_location == BOTTOM_RIGHT); - glVertexAttribPointer(renderer->shaders.corner.pos_attrib, 2, GL_FLOAT, GL_FALSE, + glUniform2f(shader.position, box->x, box->y); + glUniform1f(shader.radius, radius); + glUniform2f(shader.half_size, box->width / 2.0, box->height / 2.0); + glUniform1f(shader.half_thickness, border_thickness / 2.0); + + glVertexAttribPointer(shader.pos_attrib, 2, GL_FLOAT, GL_FALSE, 0, verts); - glEnableVertexAttribArray(renderer->shaders.corner.pos_attrib); + glEnableVertexAttribArray(shader.pos_attrib); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glDisableVertexAttribArray(renderer->shaders.corner.pos_attrib); + glDisableVertexAttribArray(shader.pos_attrib); } void fx_render_stencil_mask(struct fx_renderer *renderer, const struct wlr_box *box, @@ -717,28 +739,30 @@ void fx_render_stencil_mask(struct fx_renderer *renderer, const struct wlr_box * glEnable(GL_BLEND); - glUseProgram(renderer->shaders.stencil_mask.program); + struct stencil_mask_shader shader = renderer->shaders.stencil_mask; - glUniformMatrix3fv(renderer->shaders.stencil_mask.proj, 1, GL_FALSE, gl_matrix); + glUseProgram(shader.program); - glUniform2f(renderer->shaders.stencil_mask.half_size, box->width * 0.5, box->height * 0.5); - glUniform2f(renderer->shaders.stencil_mask.position, box->x, box->y); - glUniform1f(renderer->shaders.stencil_mask.radius, corner_radius); + glUniformMatrix3fv(shader.proj, 1, GL_FALSE, gl_matrix); - glVertexAttribPointer(renderer->shaders.stencil_mask.pos_attrib, 2, GL_FLOAT, GL_FALSE, + glUniform2f(shader.half_size, box->width * 0.5, box->height * 0.5); + glUniform2f(shader.position, box->x, box->y); + glUniform1f(shader.radius, corner_radius); + + glVertexAttribPointer(shader.pos_attrib, 2, GL_FLOAT, GL_FALSE, 0, verts); - glEnableVertexAttribArray(renderer->shaders.stencil_mask.pos_attrib); + glEnableVertexAttribArray(shader.pos_attrib); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glDisableVertexAttribArray(renderer->shaders.stencil_mask.pos_attrib); + glDisableVertexAttribArray(shader.pos_attrib); } // TODO: alpha input arg? void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *box, - const float color[static 4], const float matrix [static 9], int corner_radius, + const float color[static 4], const float matrix[static 9], int corner_radius, float blur_sigma) { if (box->width == 0 || box->height == 0) { return; @@ -783,24 +807,26 @@ void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *bo glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glUseProgram(renderer->shaders.box_shadow.program); + struct box_shadow_shader shader = renderer->shaders.box_shadow; - glUniformMatrix3fv(renderer->shaders.box_shadow.proj, 1, GL_FALSE, gl_matrix); - glUniform4f(renderer->shaders.box_shadow.color, color[0], color[1], color[2], color[3]); - glUniform1f(renderer->shaders.box_shadow.blur_sigma, blur_sigma); - glUniform1f(renderer->shaders.box_shadow.corner_radius, corner_radius); + glUseProgram(shader.program); - glUniform2f(renderer->shaders.box_shadow.size, box->width, box->height); - glUniform2f(renderer->shaders.box_shadow.position, box->x, box->y); + glUniformMatrix3fv(shader.proj, 1, GL_FALSE, gl_matrix); + glUniform4f(shader.color, color[0], color[1], color[2], color[3]); + glUniform1f(shader.blur_sigma, blur_sigma); + glUniform1f(shader.corner_radius, corner_radius); - glVertexAttribPointer(renderer->shaders.box_shadow.pos_attrib, 2, GL_FLOAT, GL_FALSE, + glUniform2f(shader.size, box->width, box->height); + glUniform2f(shader.position, box->x, box->y); + + glVertexAttribPointer(shader.pos_attrib, 2, GL_FLOAT, GL_FALSE, 0, verts); - glEnableVertexAttribArray(renderer->shaders.box_shadow.pos_attrib); + glEnableVertexAttribArray(shader.pos_attrib); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glDisableVertexAttribArray(renderer->shaders.box_shadow.pos_attrib); + glDisableVertexAttribArray(shader.pos_attrib); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); From d86e34929008f5a0f54e1561f3c6584248c9b192 Mon Sep 17 00:00:00 2001 From: Will McKinnon Date: Sun, 30 Apr 2023 14:03:51 -0400 Subject: [PATCH 3/5] fix: blurred region is rounded below titlebars --- sway/desktop/render.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 944775d6..46222784 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -307,7 +307,7 @@ void render_blur(bool optimized, struct sway_output *output, pixman_region32_t *output_damage, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, pixman_region32_t *opaque_region, int surface_width, int surface_height, int32_t surface_scale, - int corner_radius) { + int corner_radius, bool should_round_top) { struct wlr_output *wlr_output = output->wlr_output; struct fx_renderer *renderer = output->renderer; @@ -364,6 +364,7 @@ void render_blur(bool optimized, struct sway_output *output, struct decoration_data deco_data = get_undecorated_decoration_data(); deco_data.corner_radius = corner_radius; + deco_data.has_titlebar = should_round_top; render_texture(wlr_output, &damage, &buffer->texture, src_box, dst_box, matrix, deco_data); damage_finish: @@ -427,7 +428,8 @@ static void render_surface_iterator(struct sway_output *output, struct wlr_fbox blur_src_box = wlr_fbox_from_wlr_box(&monitor_box); bool is_floating = container_is_floating(view->container); render_blur(!is_floating, output, output_damage, &blur_src_box, &dst_box, &opaque_region, - surface->current.width, surface->current.height, surface->current.scale, deco_data.corner_radius); + surface->current.width, surface->current.height, surface->current.scale, + deco_data.corner_radius, deco_data.has_titlebar); } pixman_region32_fini(&opaque_region); @@ -831,7 +833,7 @@ static void render_saved_view(struct sway_view *view, struct sway_output *output struct wlr_fbox src_box = wlr_fbox_from_wlr_box(&monitor_box); bool is_floating = container_is_floating(view->container); render_blur(!is_floating, output, damage, &src_box, &dst_box, &opaque_region, - saved_buf->width, saved_buf->height, 1, deco_data.corner_radius); + saved_buf->width, saved_buf->height, 1, deco_data.corner_radius, deco_data.has_titlebar); pixman_region32_fini(&opaque_region); } From 15db638ccb95d613112786ab4ec34252a8e30c92 Mon Sep 17 00:00:00 2001 From: Will McKinnon Date: Sun, 30 Apr 2023 14:06:57 -0400 Subject: [PATCH 4/5] improved stenciling region --- sway/desktop/fx_renderer/shaders/stencil_mask.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/fx_renderer/shaders/stencil_mask.frag b/sway/desktop/fx_renderer/shaders/stencil_mask.frag index 496981ef..ee033070 100644 --- a/sway/desktop/fx_renderer/shaders/stencil_mask.frag +++ b/sway/desktop/fx_renderer/shaders/stencil_mask.frag @@ -11,7 +11,7 @@ void main() { float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, dist); gl_FragColor = mix(vec4(0.0), vec4(1.0), smoothedAlpha); - if (gl_FragColor.a == 0.0) { + if (gl_FragColor.a < 1.0) { discard; } } From 74e7012b21d48200cf67608f965befe5a308a8bb Mon Sep 17 00:00:00 2001 From: Will McKinnon Date: Sun, 30 Apr 2023 14:51:04 -0400 Subject: [PATCH 5/5] fix: smart_corners with shadow and titlebars --- sway/desktop/render.c | 69 ++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 46222784..18fcfaa6 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -880,7 +880,10 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, box.width = state->width; box.height = state->height; scale_box(&box, output_scale); - int scaled_corner_radius = (con->corner_radius + state->border_thickness) * output_scale; + int corner_radius = config->smart_corner_radius && + output->current.active_workspace->current_gaps.top == 0 + ? 0 : con->corner_radius; + int scaled_corner_radius = (corner_radius + state->border_thickness) * output_scale; render_box_shadow(output, damage, &box, config->shadow_color, config->shadow_blur_sigma, scaled_corner_radius); } @@ -1421,9 +1424,6 @@ static void render_containers_linear(struct sway_output *output, } bool has_titlebar = state->border == B_NORMAL; - int corner_radius = config->smart_corner_radius && - output->current.active_workspace->current_gaps.top == 0 - ? 0 : child->corner_radius; struct decoration_data deco_data = { .alpha = child->alpha, @@ -1432,7 +1432,9 @@ static void render_containers_linear(struct sway_output *output, : config->dim_inactive_colors.unfocused, .dim = child->current.focused || parent->focused ? 0.0f : child->dim, // no corner radius if no gaps (allows smart_gaps to work as expected) - .corner_radius = corner_radius, + .corner_radius = config->smart_corner_radius && + output->current.active_workspace->current_gaps.top == 0 + ? 0 : child->corner_radius, .saturation = child->saturation, .has_titlebar = has_titlebar, .blur = child->blur_enabled, @@ -1472,6 +1474,21 @@ 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; + struct decoration_data deco_data = { + .alpha = current->alpha, + .dim_color = view_is_urgent(current->view) + ? config->dim_inactive_colors.urgent + : config->dim_inactive_colors.unfocused, + .dim = current->current.focused || parent->focused ? 0.0f : current->dim, + // no corner radius if no gaps (allows smart_gaps to work as expected) + .corner_radius = config->smart_corner_radius && + output->current.active_workspace->current_gaps.top == 0 + ? 0 : current->corner_radius, + .saturation = current->saturation, + .has_titlebar = true, + .blur = current->blur_enabled, + }; + // Render tabs for (int i = 0; i < parent->children->length; ++i) { struct sway_container *child = parent->children->items[i]; @@ -1525,7 +1542,7 @@ static void render_containers_tabbed(struct sway_output *output, } render_titlebar(output, damage, child, x, parent->box.y, tab_width, colors, - child->alpha, child->corner_radius, corner_location, title_texture, marks_texture); + deco_data.alpha, deco_data.corner_radius, corner_location, title_texture, marks_texture); if (child == current) { current_colors = colors; @@ -1534,17 +1551,6 @@ static void render_containers_tabbed(struct sway_output *output, // Render surface and left/right/bottom borders if (current->view) { - struct decoration_data deco_data = { - .alpha = current->alpha, - .dim_color = view_is_urgent(current->view) - ? config->dim_inactive_colors.urgent - : config->dim_inactive_colors.unfocused, - .dim = current->current.focused || parent->focused ? 0.0f : current->dim, - .corner_radius = current->corner_radius, - .saturation = current->saturation, - .has_titlebar = true, - .blur = current->blur_enabled, - }; render_view(output, damage, current, current_colors, deco_data); } else { render_container(output, damage, current, @@ -1564,6 +1570,20 @@ 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(); + struct decoration_data deco_data = { + .alpha = current->alpha, + .dim_color = view_is_urgent(current->view) + ? config->dim_inactive_colors.urgent + : config->dim_inactive_colors.unfocused, + .dim = current->current.focused || parent->focused ? 0.0f : current->dim, + .saturation = current->saturation, + .corner_radius = config->smart_corner_radius && + output->current.active_workspace->current_gaps.top == 0 + ? 0 : current->corner_radius, + .has_titlebar = true, + .blur = current->blur_enabled, + }; + // Render titles for (int i = 0; i < parent->children->length; ++i) { struct sway_container *child = parent->children->items[i]; @@ -1598,9 +1618,9 @@ static void render_containers_stacked(struct sway_output *output, } int y = parent->box.y + titlebar_height * i; - int corner_radius = i != 0 ? 0 : child->corner_radius; + int corner_radius = i != 0 ? 0 : deco_data.corner_radius; render_titlebar(output, damage, child, parent->box.x, y, parent->box.width, - colors, child->alpha, corner_radius, ALL, title_texture, marks_texture); + colors, deco_data.alpha, corner_radius, ALL, title_texture, marks_texture); if (child == current) { current_colors = colors; @@ -1609,17 +1629,6 @@ static void render_containers_stacked(struct sway_output *output, // Render surface and left/right/bottom borders if (current->view) { - struct decoration_data deco_data = { - .alpha = current->alpha, - .dim_color = view_is_urgent(current->view) - ? config->dim_inactive_colors.urgent - : config->dim_inactive_colors.unfocused, - .dim = current->current.focused || parent->focused ? 0.0f : current->dim, - .saturation = current->saturation, - .corner_radius = current->corner_radius, - .has_titlebar = true, - .blur = current->blur_enabled, - }; render_view(output, damage, current, current_colors, deco_data); } else { render_container(output, damage, current,