diff --git a/examples/scene-graph.c b/examples/scene-graph.c index 910d60bd..7e5162c3 100644 --- a/examples/scene-graph.c +++ b/examples/scene-graph.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -145,7 +144,7 @@ static void server_handle_new_surface(struct wl_listener *listener, surface->scene_surface = wlr_scene_surface_create(&server->scene->tree, wlr_surface); wlr_scene_buffer_set_corner_radius( - surface->scene_surface->buffer, corner_radius, CORNER_LOCATION_ALL); + surface->scene_surface->buffer, corner_radius); wlr_scene_node_set_position(&surface->scene_surface->buffer->node, pos + border_width, pos + border_width); diff --git a/include/render/fx_renderer/shaders.h b/include/render/fx_renderer/shaders.h index 0a1b3660..a08b76b5 100644 --- a/include/render/fx_renderer/shaders.h +++ b/include/render/fx_renderer/shaders.h @@ -3,6 +3,7 @@ #include #include +#include "scenefx/types/fx/clipped_region.h" struct fx_renderer; @@ -20,6 +21,27 @@ enum fx_tex_shader_source { SHADER_SOURCE_TEXTURE_EXTERNAL = 3, }; +struct shader_corner_radii { + GLint top_left; + GLint top_right; + GLint bottom_left; + GLint bottom_right; +}; + +void uniform_corner_radii_set_location( + struct shader_corner_radii *corners, + GLuint program, + const char *top_left, + const char *top_right, + const char *bottom_left, + const char *bottom_right +); + +void uniform_corner_radii_set( + struct shader_corner_radii *uniform, + struct fx_corner_fradii *corners +); + struct quad_shader { GLuint program; GLint proj; @@ -28,10 +50,7 @@ struct quad_shader { GLint clip_size; GLint clip_position; - GLint clip_radius_top_left; - GLint clip_radius_top_right; - GLint clip_radius_bottom_left; - GLint clip_radius_bottom_right; + struct shader_corner_radii clip_radius; }; bool link_quad_program(struct quad_shader *shader, GLint client_version); @@ -62,17 +81,11 @@ struct quad_round_shader { GLint size; GLint position; - GLint radius_top_left; - GLint radius_top_right; - GLint radius_bottom_left; - GLint radius_bottom_right; + struct shader_corner_radii radius; GLint clip_size; GLint clip_position; - GLint clip_radius_top_left; - GLint clip_radius_top_right; - GLint clip_radius_bottom_left; - GLint clip_radius_bottom_right; + struct shader_corner_radii clip_radius; }; bool link_quad_round_program(struct quad_round_shader *shader, GLint client_version); @@ -94,10 +107,7 @@ struct quad_grad_round_shader { GLint count; GLint blend; - GLint radius_top_left; - GLint radius_top_right; - GLint radius_bottom_left; - GLint radius_bottom_right; + struct shader_corner_radii radius; int max_len; }; @@ -113,19 +123,13 @@ struct tex_shader { GLint pos_attrib; GLint size; GLint position; - GLint radius_top_left; - GLint radius_top_right; - GLint radius_bottom_left; - GLint radius_bottom_right; + struct shader_corner_radii radius; GLint discard_transparent; GLint clip_size; GLint clip_position; - GLint clip_radius_top_left; - GLint clip_radius_top_right; - GLint clip_radius_bottom_left; - GLint clip_radius_bottom_right; + struct shader_corner_radii clip_radius; }; bool link_tex_program(struct tex_shader *shader, GLint client_version, enum fx_tex_shader_source source); @@ -142,10 +146,7 @@ struct box_shadow_shader { GLint clip_position; GLint clip_size; - GLint clip_radius_top_left; - GLint clip_radius_top_right; - GLint clip_radius_bottom_left; - GLint clip_radius_bottom_right; + struct shader_corner_radii clip_radius; }; bool link_box_shadow_program(struct box_shadow_shader *shader, GLint client_version); diff --git a/include/scenefx/render/pass.h b/include/scenefx/render/pass.h index cb40911e..28ef1eec 100644 --- a/include/scenefx/render/pass.h +++ b/include/scenefx/render/pass.h @@ -8,7 +8,6 @@ #include "render/egl.h" #include "scenefx/types/fx/clipped_region.h" -#include "scenefx/types/fx/corner_location.h" struct fx_gles_render_pass { struct wlr_render_pass base; @@ -55,15 +54,14 @@ struct fx_gradient { struct fx_render_texture_options { struct wlr_render_texture_options base; const struct wlr_box *clip_box; // Used to clip csd. Ignored if NULL - enum corner_location corners; - int corner_radius; + struct fx_corner_fradii corners; bool discard_transparent; - struct clipped_region clipped_region; + struct clipped_fregion clipped_region; }; struct fx_render_rect_options { struct wlr_render_rect_options base; - struct clipped_region clipped_region; + struct clipped_fregion clipped_region; }; struct fx_render_rect_grad_options { @@ -73,21 +71,19 @@ struct fx_render_rect_grad_options { struct fx_render_rounded_rect_options { struct wlr_render_rect_options base; - int corner_radius; - enum corner_location corners; - struct clipped_region clipped_region; + struct fx_corner_fradii corners; + struct clipped_fregion clipped_region; }; struct fx_render_rounded_rect_grad_options { struct wlr_render_rect_options base; struct fx_gradient gradient; - int corner_radius; - enum corner_location corners; + struct fx_corner_fradii corners; }; struct fx_render_box_shadow_options { struct wlr_box box; - struct clipped_region clipped_region; + struct clipped_fregion clipped_region; /* Clip region, leave NULL to disable clipping */ const pixman_region32_t *clip; @@ -104,9 +100,8 @@ struct fx_render_blur_pass_options { bool use_optimized_blur; bool ignore_transparent; float blur_strength; - int corner_radius; - enum corner_location corners; - struct clipped_region clipped_region; + struct fx_corner_radii corners; + struct clipped_fregion clipped_region; }; /** diff --git a/include/scenefx/types/fx/clipped_region.h b/include/scenefx/types/fx/clipped_region.h index 84490047..378d4b70 100644 --- a/include/scenefx/types/fx/clipped_region.h +++ b/include/scenefx/types/fx/clipped_region.h @@ -3,12 +3,119 @@ #include -#include "scenefx/types/fx/corner_location.h" +// uint16_t is a reasonable enough range for corner radius +// and makes it 8 bytes wide, making it cheap with optimisations +// Note: layout is on purpose to be clockwise +struct fx_corner_radii { + uint16_t top_left; + uint16_t top_right; + uint16_t bottom_right; + uint16_t bottom_left; +}; + +struct fx_corner_fradii { + float top_left; + float top_right; + float bottom_right; + float bottom_left; +}; + +#define CORNER_RADIUS_MAX (UINT16_MAX) + +static __always_inline uint16_t corner_radius_clamp(int radius) { + if (radius <= 0) { + return 0; + } + + if (radius > CORNER_RADIUS_MAX) { + return CORNER_RADIUS_MAX; + } + + return radius; +} + +static __always_inline struct fx_corner_radii corner_radii_new(int top_left, int top_right, int bottom_right, int bottom_left) { + return (struct fx_corner_radii) { + corner_radius_clamp(top_left), + corner_radius_clamp(top_right), + corner_radius_clamp(bottom_right), + corner_radius_clamp(bottom_left), + }; +} + +static __always_inline struct fx_corner_radii corner_radii_all(int radius) { + return corner_radii_new(radius, radius, radius, radius); +} + +static __always_inline struct fx_corner_radii corner_radii_none() { + return corner_radii_all(0); +} + +static __always_inline struct fx_corner_radii corner_radii_top(int radius) { + return corner_radii_new(radius, radius, 0, 0); +} + +static __always_inline struct fx_corner_radii corner_radii_bottom(int radius) { + return corner_radii_new(0, 0, radius, radius); +} + +static __always_inline struct fx_corner_radii corner_radii_left(int radius) { + return corner_radii_new(radius, 0, 0, radius); +} + +static __always_inline struct fx_corner_radii corner_radii_right(int radius) { + return corner_radii_new(0, radius, radius, 0); +} + +struct fx_corner_radii fx_corner_radii_extend(struct fx_corner_radii corners, int extend); + +void fx_corner_radii_transform(enum wl_output_transform transform, + struct fx_corner_radii *corners); + +struct fx_corner_fradii fx_corner_radii_scale(struct fx_corner_radii, float scale); + +bool fx_corner_radii_eq(struct fx_corner_radii lhs, struct fx_corner_radii rhs); + +/** + * Retains the corner values from `input` based on if the corresponding corner value in `filter` is non-zero + * + * This can be compared to an `AND` operation + */ +static __always_inline struct fx_corner_radii fx_corner_radii_filter(struct fx_corner_radii input, struct fx_corner_radii filter) { + return corner_radii_new( + input.top_left && filter.top_left ? input.top_left : 0, + input.top_right && filter.top_right ? input.top_right : 0, + input.bottom_right && filter.bottom_right ? input.bottom_right : 0, + input.bottom_left && filter.bottom_left ? input.bottom_left : 0 + ); +}; + +/** + * Picks the value of the corner from `lhs` if non-zero, otherwise picks the corner value from `rhs` + * + * This can be compared to an `OR` operation + */ +static __always_inline struct fx_corner_radii fx_corner_radii_pick(struct fx_corner_radii lhs, struct fx_corner_radii rhs) { + return corner_radii_new( + lhs.top_left ? lhs.top_left : rhs.top_left, + lhs.top_right ? lhs.top_right : rhs.top_right, + lhs.bottom_right ? lhs.bottom_right : rhs.bottom_right, + lhs.bottom_left ? lhs.bottom_left : rhs.bottom_left + ); +}; + +bool fx_corner_radii_is_empty(const struct fx_corner_radii* corners); + +bool fx_corner_fradii_is_empty(const struct fx_corner_fradii* corners); struct clipped_region { struct wlr_box area; - int corner_radius; - enum corner_location corners; + struct fx_corner_radii corners; +}; + +struct clipped_fregion { + struct wlr_box area; + struct fx_corner_fradii corners; }; struct clipped_region clipped_region_get_default(void); diff --git a/include/scenefx/types/fx/corner_location.h b/include/scenefx/types/fx/corner_location.h deleted file mode 100644 index cd940469..00000000 --- a/include/scenefx/types/fx/corner_location.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef TYPES_FX_CORNER_LOCATION_H -#define TYPES_FX_CORNER_LOCATION_H - -#include - -#define CORNER_LOCATION_LAST (1 << 3) + 1 -#define CORNER_LOCATION_COUNT 5 - -enum corner_location { - CORNER_LOCATION_NONE = 0, - CORNER_LOCATION_TOP_LEFT = 1 << 0, - CORNER_LOCATION_TOP_RIGHT = 1 << 1, - CORNER_LOCATION_BOTTOM_RIGHT = 1 << 2, - CORNER_LOCATION_BOTTOM_LEFT = 1 << 3, - CORNER_LOCATION_TOP = CORNER_LOCATION_TOP_LEFT | CORNER_LOCATION_TOP_RIGHT, - CORNER_LOCATION_BOTTOM = CORNER_LOCATION_BOTTOM_LEFT | CORNER_LOCATION_BOTTOM_RIGHT, - CORNER_LOCATION_LEFT = CORNER_LOCATION_TOP_LEFT | CORNER_LOCATION_BOTTOM_LEFT, - CORNER_LOCATION_RIGHT = CORNER_LOCATION_TOP_RIGHT | CORNER_LOCATION_BOTTOM_RIGHT, - CORNER_LOCATION_ALL = CORNER_LOCATION_TOP_LEFT | CORNER_LOCATION_TOP_RIGHT - | CORNER_LOCATION_BOTTOM_LEFT | CORNER_LOCATION_BOTTOM_RIGHT, -}; - -void corner_location_transform(enum wl_output_transform transform, - enum corner_location *corners); - -#endif // !TYPES_FX_CORNER_LOCATION_H diff --git a/include/scenefx/types/wlr_scene.h b/include/scenefx/types/wlr_scene.h index 594a7ab2..65aeac0e 100644 --- a/include/scenefx/types/wlr_scene.h +++ b/include/scenefx/types/wlr_scene.h @@ -30,7 +30,6 @@ #include "scenefx/types/fx/blur_data.h" #include "scenefx/types/fx/clipped_region.h" -#include "scenefx/types/fx/corner_location.h" #include "scenefx/types/linked_node.h" struct wlr_output; @@ -149,8 +148,7 @@ struct wlr_scene_rect { struct wlr_scene_node node; int width, height; float color[4]; - int corner_radius; - enum corner_location corners; + struct fx_corner_radii corners; bool accepts_input; struct clipped_region clipped_region; @@ -170,9 +168,8 @@ struct wlr_scene_shadow { struct wlr_scene_blur { struct wlr_scene_node node; int width, height; - int corner_radius; - enum corner_location corners; + struct fx_corner_radii corners; struct clipped_region clipped_region; float strength; @@ -227,8 +224,7 @@ struct wlr_scene_buffer { */ struct wlr_scene_output *primary_output; - int corner_radius; - enum corner_location corners; + struct fx_corner_radii corners; float opacity; enum wlr_scale_filter_mode filter_mode; @@ -516,10 +512,14 @@ struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_tree *parent, void wlr_scene_rect_set_size(struct wlr_scene_rect *rect, int width, int height); /** - * Change the corner radius of an existing rectangle node. + * Change the corner radius of all corners of an existing rectangle node. + */ +void wlr_scene_rect_set_corner_radius(struct wlr_scene_rect *rect, int corner_radius); + +/** + * Change the rounded corners of an existing rectangle node. */ -void wlr_scene_rect_set_corner_radius(struct wlr_scene_rect *rect, int corner_radius, - enum corner_location corners); +void wlr_scene_rect_set_corner_radii(struct wlr_scene_rect *rect, struct fx_corner_radii); /** * Sets the region where to clip the rect. @@ -589,10 +589,14 @@ struct wlr_scene_blur *wlr_scene_blur_create(struct wlr_scene_tree *parent, void wlr_scene_blur_set_size(struct wlr_scene_blur *blur, int width, int height); /** - * Change the corner radius of an existing blur node. + * Change the corner radius of all corners of an existing blur node. */ -void wlr_scene_blur_set_corner_radius(struct wlr_scene_blur *blur, int corner_radius, - enum corner_location corners); +void wlr_scene_blur_set_corner_radius(struct wlr_scene_blur *blur, int corner_radius); + +/** + * Change the corners of an existing blur node. + */ +void wlr_scene_blur_set_corner_radii(struct wlr_scene_blur *blur, struct fx_corner_radii); /** * Make the blur node only blur the bottom layer of the scene @@ -768,11 +772,16 @@ void wlr_scene_buffer_set_filter_mode(struct wlr_scene_buffer *scene_buffer, enum wlr_scale_filter_mode filter_mode); /** -* Sets the corner radius and which corners to round of this buffer +* Sets the corner radius of all corners to round of this buffer */ void wlr_scene_buffer_set_corner_radius(struct wlr_scene_buffer *scene_buffer, - int radii, enum corner_location corners); + int radii); +/** +* Sets the corner radii of this buffer +*/ +void wlr_scene_buffer_set_corner_radii(struct wlr_scene_buffer *scene_buffer, + struct fx_corner_radii corner_radii); /** * Calls the buffer's frame_done signal. */ diff --git a/render/fx_renderer/fx_pass.c b/render/fx_renderer/fx_pass.c index da7c3905..3d99ee0b 100644 --- a/render/fx_renderer/fx_pass.c +++ b/render/fx_renderer/fx_pass.c @@ -17,7 +17,6 @@ #include "render/pass.h" #include "scenefx/render/fx_renderer/fx_renderer.h" #include "scenefx/render/fx_renderer/fx_effect_framebuffers.h" -#include "scenefx/types/fx/corner_location.h" #include "scenefx/types/fx/blur_data.h" #include "util/matrix.h" @@ -26,8 +25,7 @@ struct fx_render_texture_options fx_render_texture_options_default( const struct wlr_render_texture_options *base) { struct fx_render_texture_options options = { - .corner_radius = 0, - .corners = CORNER_LOCATION_NONE, + .corners = {0}, .discard_transparent = false, .clip_box = NULL, .clipped_region = {0}, @@ -42,8 +40,7 @@ struct fx_render_rect_options fx_render_rect_options_default( .base = *base, .clipped_region = { .area = { .0, .0, .0, .0 }, - .corner_radius = 0, - .corners = CORNER_LOCATION_NONE, + .corners = {0}, }, }; return options; @@ -277,6 +274,30 @@ static void setup_blending(enum wlr_render_blend_mode mode) { } } +static bool apply_clip_region(pixman_region32_t *clip_region, + const struct wlr_box *clipped_region_box, const struct fx_corner_fradii *corners) { + if (!wlr_box_empty(clipped_region_box)) { + float top = fmax(corners->top_left, corners->top_right); + float bottom = fmax(corners->bottom_left, corners->bottom_right); + float left = fmax(corners->top_left, corners->bottom_left); + float right = fmax(corners->top_right, corners->bottom_right); + + pixman_region32_t user_clip_region; + pixman_region32_init_rect( + &user_clip_region, + clipped_region_box->x + (left * 0.3), + clipped_region_box->y + (top * 0.3), + fmax(clipped_region_box->width - (left + right) * 0.3, 0), + fmax(clipped_region_box->height - (top + bottom) * 0.3, 0) + ); + pixman_region32_subtract(clip_region, clip_region, &user_clip_region); + pixman_region32_fini(&user_clip_region); + return true; + } + + return false; +} + void fx_render_pass_add_texture(struct fx_gles_render_pass *pass, const struct fx_render_texture_options *fx_options) { const struct wlr_render_texture_options *options = &fx_options->base; @@ -343,7 +364,7 @@ void fx_render_pass_add_texture(struct fx_gles_render_pass *pass, bool has_alpha = texture->has_alpha || alpha < 1.0 - || fx_options->corner_radius > 0 + || !fx_corner_fradii_is_empty(&fx_options->corners) || fx_options->discard_transparent; setup_blending(!has_alpha ? WLR_RENDER_BLEND_MODE_NONE : options->blend_mode); @@ -355,21 +376,8 @@ void fx_render_pass_add_texture(struct fx_gles_render_pass *pass, pixman_region32_init_rect(&clip_region, dst_box.x, dst_box.y, dst_box.width, dst_box.height); } const struct wlr_box clipped_region_box = fx_options->clipped_region.area; - enum corner_location clipped_region_corners = fx_options->clipped_region.corners; - int clipped_region_corner_radius = clipped_region_corners != CORNER_LOCATION_NONE ? - fx_options->clipped_region.corner_radius : 0; - if (!wlr_box_empty(&clipped_region_box)) { - pixman_region32_t user_clip_region; - pixman_region32_init_rect( - &user_clip_region, - clipped_region_box.x + clipped_region_corner_radius * 0.3, - clipped_region_box.y + clipped_region_corner_radius * 0.3, - fmax(clipped_region_box.width - clipped_region_corner_radius * 0.6, 0), - fmax(clipped_region_box.height - clipped_region_corner_radius * 0.6, 0) - ); - pixman_region32_subtract(&clip_region, &clip_region, &user_clip_region); - pixman_region32_fini(&user_clip_region); - } + struct fx_corner_fradii clipped_region_corners = fx_options->clipped_region.corners; + apply_clip_region(&clip_region, &clipped_region_box, &clipped_region_corners); glUseProgram(shader->program); @@ -387,32 +395,18 @@ void fx_render_pass_add_texture(struct fx_gles_render_pass *pass, break; } - enum corner_location corners = fx_options->corners; + struct fx_corner_fradii corners = fx_options->corners; glUniform1i(shader->tex, 0); glUniform1f(shader->alpha, alpha); glUniform2f(shader->size, clip_box->width, clip_box->height); glUniform2f(shader->position, clip_box->x, clip_box->y); glUniform1f(shader->discard_transparent, fx_options->discard_transparent); - glUniform1f(shader->radius_top_left, (CORNER_LOCATION_TOP_LEFT & corners) == CORNER_LOCATION_TOP_LEFT ? - fx_options->corner_radius : 0); - glUniform1f(shader->radius_top_right, (CORNER_LOCATION_TOP_RIGHT & corners) == CORNER_LOCATION_TOP_RIGHT ? - fx_options->corner_radius : 0); - glUniform1f(shader->radius_bottom_left, (CORNER_LOCATION_BOTTOM_LEFT & corners) == CORNER_LOCATION_BOTTOM_LEFT ? - fx_options->corner_radius : 0); - glUniform1f(shader->radius_bottom_right, (CORNER_LOCATION_BOTTOM_RIGHT & corners) == CORNER_LOCATION_BOTTOM_RIGHT ? - fx_options->corner_radius : 0); + uniform_corner_radii_set(&shader->radius, &corners); glUniform2f(shader->clip_size, clipped_region_box.width, clipped_region_box.height); glUniform2f(shader->clip_position, clipped_region_box.x, clipped_region_box.y); - glUniform1f(shader->clip_radius_top_left, (CORNER_LOCATION_TOP_LEFT & clipped_region_corners) == CORNER_LOCATION_TOP_LEFT ? - clipped_region_corner_radius : 0); - glUniform1f(shader->clip_radius_top_right, (CORNER_LOCATION_TOP_RIGHT & clipped_region_corners) == CORNER_LOCATION_TOP_RIGHT ? - clipped_region_corner_radius : 0); - glUniform1f(shader->clip_radius_bottom_left, (CORNER_LOCATION_BOTTOM_LEFT & clipped_region_corners) == CORNER_LOCATION_BOTTOM_LEFT ? - clipped_region_corner_radius : 0); - glUniform1f(shader->clip_radius_bottom_right, (CORNER_LOCATION_BOTTOM_RIGHT & clipped_region_corners) == CORNER_LOCATION_BOTTOM_RIGHT ? - clipped_region_corner_radius : 0); + uniform_corner_radii_set(&shader->clip_radius, &clipped_region_corners); set_proj_matrix(shader->proj, pass->projection_matrix, &dst_box); set_tex_matrix(shader->tex_proj, options->transform, &src_fbox); @@ -442,24 +436,8 @@ void fx_render_pass_add_rect(struct fx_gles_render_pass *pass, pixman_region32_init_rect(&clip_region, box.x, box.y, box.width, box.height); } const struct wlr_box clipped_region_box = fx_options->clipped_region.area; - enum corner_location clipped_region_corners = fx_options->clipped_region.corners; - int clipped_region_corner_radius = clipped_region_corners != CORNER_LOCATION_NONE ? - fx_options->clipped_region.corner_radius : 0; - if (!wlr_box_empty(&clipped_region_box)) { - pixman_region32_t user_clip_region; - pixman_region32_init_rect( - &user_clip_region, - clipped_region_box.x + clipped_region_corner_radius * 0.3, - clipped_region_box.y + clipped_region_corner_radius * 0.3, - fmax(clipped_region_box.width - clipped_region_corner_radius * 0.6, 0), - fmax(clipped_region_box.height - clipped_region_corner_radius * 0.6, 0) - ); - pixman_region32_subtract(&clip_region, &clip_region, &user_clip_region); - pixman_region32_fini(&user_clip_region); - - push_fx_debug(renderer); - setup_blending(options->blend_mode); - } else { + struct fx_corner_fradii clipped_region_corners = fx_options->clipped_region.corners; + if (!apply_clip_region(&clip_region, &clipped_region_box, &clipped_region_corners)) { push_fx_debug(renderer); setup_blending(color->a == 1.0 ? WLR_RENDER_BLEND_MODE_NONE : options->blend_mode); } @@ -470,14 +448,7 @@ void fx_render_pass_add_rect(struct fx_gles_render_pass *pass, glUniform4f(shader.color, color->r, color->g, color->b, color->a); glUniform2f(shader.clip_size, clipped_region_box.width, clipped_region_box.height); glUniform2f(shader.clip_position, clipped_region_box.x, clipped_region_box.y); - glUniform1f(shader.clip_radius_top_left, (CORNER_LOCATION_TOP_LEFT & clipped_region_corners) == CORNER_LOCATION_TOP_LEFT ? - clipped_region_corner_radius : 0); - glUniform1f(shader.clip_radius_top_right, (CORNER_LOCATION_TOP_RIGHT & clipped_region_corners) == CORNER_LOCATION_TOP_RIGHT ? - clipped_region_corner_radius : 0); - glUniform1f(shader.clip_radius_bottom_left, (CORNER_LOCATION_BOTTOM_LEFT & clipped_region_corners) == CORNER_LOCATION_BOTTOM_LEFT ? - clipped_region_corner_radius : 0); - glUniform1f(shader.clip_radius_bottom_right, (CORNER_LOCATION_BOTTOM_RIGHT & clipped_region_corners) == CORNER_LOCATION_BOTTOM_RIGHT ? - clipped_region_corner_radius : 0); + uniform_corner_radii_set(&shader.clip_radius, &clipped_region_corners); render(&box, &clip_region, renderer->shaders.quad.pos_attrib); pixman_region32_fini(&clip_region); @@ -546,21 +517,8 @@ void fx_render_pass_add_rounded_rect(struct fx_gles_render_pass *pass, pixman_region32_init_rect(&clip_region, box.x, box.y, box.width, box.height); } const struct wlr_box clipped_region_box = fx_options->clipped_region.area; - enum corner_location clipped_region_corners = fx_options->clipped_region.corners; - int clipped_region_corner_radius = clipped_region_corners != CORNER_LOCATION_NONE ? - fx_options->clipped_region.corner_radius : 0; - if (!wlr_box_empty(&clipped_region_box)) { - pixman_region32_t user_clip_region; - pixman_region32_init_rect( - &user_clip_region, - clipped_region_box.x + clipped_region_corner_radius * 0.3, - clipped_region_box.y + clipped_region_corner_radius * 0.3, - fmax(clipped_region_box.width - clipped_region_corner_radius * 0.6, 0), - fmax(clipped_region_box.height - clipped_region_corner_radius * 0.6, 0) - ); - pixman_region32_subtract(&clip_region, &clip_region, &user_clip_region); - pixman_region32_fini(&user_clip_region); - } + struct fx_corner_fradii clipped_region_corners = fx_options->clipped_region.corners; + apply_clip_region(&clip_region, &clipped_region_box, &clipped_region_corners); push_fx_debug(renderer); setup_blending(WLR_RENDER_BLEND_MODE_PREMULTIPLIED); @@ -576,24 +534,10 @@ void fx_render_pass_add_rounded_rect(struct fx_gles_render_pass *pass, glUniform2f(shader.position, box.x, box.y); glUniform2f(shader.clip_size, clipped_region_box.width, clipped_region_box.height); glUniform2f(shader.clip_position, clipped_region_box.x, clipped_region_box.y); - glUniform1f(shader.clip_radius_top_left, (CORNER_LOCATION_TOP_LEFT & clipped_region_corners) == CORNER_LOCATION_TOP_LEFT ? - clipped_region_corner_radius : 0); - glUniform1f(shader.clip_radius_top_right, (CORNER_LOCATION_TOP_RIGHT & clipped_region_corners) == CORNER_LOCATION_TOP_RIGHT ? - clipped_region_corner_radius : 0); - glUniform1f(shader.clip_radius_bottom_left, (CORNER_LOCATION_BOTTOM_LEFT & clipped_region_corners) == CORNER_LOCATION_BOTTOM_LEFT ? - clipped_region_corner_radius : 0); - glUniform1f(shader.clip_radius_bottom_right, (CORNER_LOCATION_BOTTOM_RIGHT & clipped_region_corners) == CORNER_LOCATION_BOTTOM_RIGHT ? - clipped_region_corner_radius : 0); - - enum corner_location corners = fx_options->corners; - glUniform1f(shader.radius_top_left, (CORNER_LOCATION_TOP_LEFT & corners) == CORNER_LOCATION_TOP_LEFT ? - fx_options->corner_radius : 0); - glUniform1f(shader.radius_top_right, (CORNER_LOCATION_TOP_RIGHT & corners) == CORNER_LOCATION_TOP_RIGHT ? - fx_options->corner_radius : 0); - glUniform1f(shader.radius_bottom_left, (CORNER_LOCATION_BOTTOM_LEFT & corners) == CORNER_LOCATION_BOTTOM_LEFT ? - fx_options->corner_radius : 0); - glUniform1f(shader.radius_bottom_right, (CORNER_LOCATION_BOTTOM_RIGHT & corners) == CORNER_LOCATION_BOTTOM_RIGHT ? - fx_options->corner_radius : 0); + uniform_corner_radii_set(&shader.clip_radius, &clipped_region_corners); + + struct fx_corner_fradii corners = fx_options->corners; + uniform_corner_radii_set(&shader.radius, &corners); render(&box, &clip_region, renderer->shaders.quad_round.pos_attrib); pixman_region32_fini(&clip_region); @@ -642,15 +586,8 @@ void fx_render_pass_add_rounded_rect_grad(struct fx_gles_render_pass *pass, glUniform2f(shader.grad_box, fx_options->gradient.range.x, fx_options->gradient.range.y); glUniform2f(shader.origin, fx_options->gradient.origin[0], fx_options->gradient.origin[1]); - enum corner_location corners = fx_options->corners; - glUniform1f(shader.radius_top_left, (CORNER_LOCATION_TOP_LEFT & corners) == CORNER_LOCATION_TOP_LEFT ? - fx_options->corner_radius : 0); - glUniform1f(shader.radius_top_right, (CORNER_LOCATION_TOP_RIGHT & corners) == CORNER_LOCATION_TOP_RIGHT ? - fx_options->corner_radius : 0); - glUniform1f(shader.radius_bottom_left, (CORNER_LOCATION_BOTTOM_LEFT & corners) == CORNER_LOCATION_BOTTOM_LEFT ? - fx_options->corner_radius : 0); - glUniform1f(shader.radius_bottom_right, (CORNER_LOCATION_BOTTOM_RIGHT & corners) == CORNER_LOCATION_BOTTOM_RIGHT ? - fx_options->corner_radius : 0); + struct fx_corner_fradii corners = fx_options->corners; + uniform_corner_radii_set(&shader.radius, &corners); render(&box, options->clip, shader.pos_attrib); @@ -672,21 +609,8 @@ void fx_render_pass_add_box_shadow(struct fx_gles_render_pass *pass, pixman_region32_init_rect(&clip_region, box.x, box.y, box.width, box.height); } const struct wlr_box clipped_region_box = options->clipped_region.area; - enum corner_location clipped_region_corners = options->clipped_region.corners; - int clipped_region_corner_radius = clipped_region_corners != CORNER_LOCATION_NONE ? - options->clipped_region.corner_radius : 0; - if (!wlr_box_empty(&clipped_region_box)) { - pixman_region32_t user_clip_region; - pixman_region32_init_rect( - &user_clip_region, - clipped_region_box.x + clipped_region_corner_radius * 0.3, - clipped_region_box.y + clipped_region_corner_radius * 0.3, - fmax(clipped_region_box.width - clipped_region_corner_radius * 0.6, 0), - fmax(clipped_region_box.height - clipped_region_corner_radius * 0.6, 0) - ); - pixman_region32_subtract(&clip_region, &clip_region, &user_clip_region); - pixman_region32_fini(&user_clip_region); - } + struct fx_corner_fradii clipped_region_corners = options->clipped_region.corners; + apply_clip_region(&clip_region, &clipped_region_box, &clipped_region_corners); push_fx_debug(renderer); // blending will practically always be needed (unless we have a madman @@ -704,18 +628,7 @@ void fx_render_pass_add_box_shadow(struct fx_gles_render_pass *pass, glUniform2f(renderer->shaders.box_shadow.position, box.x, box.y); glUniform1f(renderer->shaders.box_shadow.corner_radius, options->corner_radius); - glUniform1f(renderer->shaders.box_shadow.clip_radius_top_left, - (CORNER_LOCATION_TOP_LEFT & clipped_region_corners) == CORNER_LOCATION_TOP_LEFT ? - clipped_region_corner_radius : 0); - glUniform1f(renderer->shaders.box_shadow.clip_radius_top_right, - (CORNER_LOCATION_TOP_RIGHT & clipped_region_corners) == CORNER_LOCATION_TOP_RIGHT ? - clipped_region_corner_radius : 0); - glUniform1f(renderer->shaders.box_shadow.clip_radius_bottom_left, - (CORNER_LOCATION_BOTTOM_LEFT & clipped_region_corners) == CORNER_LOCATION_BOTTOM_LEFT ? - clipped_region_corner_radius : 0); - glUniform1f(renderer->shaders.box_shadow.clip_radius_bottom_right, - (CORNER_LOCATION_BOTTOM_RIGHT & clipped_region_corners) == CORNER_LOCATION_BOTTOM_RIGHT ? - clipped_region_corner_radius : 0); + uniform_corner_radii_set(&renderer->shaders.box_shadow.clip_radius, &clipped_region_corners); glUniform2f(renderer->shaders.box_shadow.clip_position, clipped_region_box.x, clipped_region_box.y); glUniform2f(renderer->shaders.box_shadow.clip_size, clipped_region_box.width, clipped_region_box.height); diff --git a/render/fx_renderer/shaders.c b/render/fx_renderer/shaders.c index 5f02f2ee..e0946b68 100644 --- a/render/fx_renderer/shaders.c +++ b/render/fx_renderer/shaders.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "render/fx_renderer/shaders.h" @@ -115,6 +116,29 @@ void load_gl_proc(void *proc_ptr, const char *name) { *(void **)proc_ptr = proc; } + +void uniform_corner_radii_set_location( + struct shader_corner_radii *corners, + GLuint program, + const char *top_left, + const char *top_right, + const char *bottom_left, + const char *bottom_right) { + corners->top_left = glGetUniformLocation(program, top_left); + corners->top_right = glGetUniformLocation(program, top_right); + corners->bottom_left = glGetUniformLocation(program, bottom_left); + corners->bottom_right = glGetUniformLocation(program, bottom_right); +} + +void uniform_corner_radii_set( + struct shader_corner_radii *uniform, + struct fx_corner_fradii *corners +) { + glUniform1f(uniform->top_left, corners->top_left); + glUniform1f(uniform->top_right, corners->top_right); + glUniform1f(uniform->bottom_left, corners->bottom_left); + glUniform1f(uniform->bottom_right, corners->bottom_right); +} // Shaders bool link_quad_program(struct quad_shader *shader, GLint client_version) { @@ -138,10 +162,14 @@ bool link_quad_program(struct quad_shader *shader, GLint client_version) { shader->pos_attrib = glGetAttribLocation(prog, "pos"); shader->clip_size = glGetUniformLocation(prog, "clip_size"); shader->clip_position = glGetUniformLocation(prog, "clip_position"); - shader->clip_radius_top_left = glGetUniformLocation(prog, "clip_radius_top_left"); - shader->clip_radius_top_right = glGetUniformLocation(prog, "clip_radius_top_right"); - shader->clip_radius_bottom_left = glGetUniformLocation(prog, "clip_radius_bottom_left"); - shader->clip_radius_bottom_right = glGetUniformLocation(prog, "clip_radius_bottom_right"); + uniform_corner_radii_set_location( + &shader->clip_radius, + prog, + "clip_radius_top_left", + "clip_radius_top_right", + "clip_radius_bottom_left", + "clip_radius_bottom_right" + ); return true; } @@ -204,17 +232,25 @@ bool link_quad_round_program(struct quad_round_shader *shader, GLint client_vers shader->pos_attrib = glGetAttribLocation(prog, "pos"); shader->size = glGetUniformLocation(prog, "size"); shader->position = glGetUniformLocation(prog, "position"); - shader->radius_top_left = glGetUniformLocation(prog, "radius_top_left"); - shader->radius_top_right = glGetUniformLocation(prog, "radius_top_right"); - shader->radius_bottom_left = glGetUniformLocation(prog, "radius_bottom_left"); - shader->radius_bottom_right = glGetUniformLocation(prog, "radius_bottom_right"); + uniform_corner_radii_set_location( + &shader->radius, + prog, + "radius_top_left", + "radius_top_right", + "radius_bottom_left", + "radius_bottom_right" + ); shader->clip_size = glGetUniformLocation(prog, "clip_size"); shader->clip_position = glGetUniformLocation(prog, "clip_position"); - shader->clip_radius_top_left = glGetUniformLocation(prog, "clip_radius_top_left"); - shader->clip_radius_top_right = glGetUniformLocation(prog, "clip_radius_top_right"); - shader->clip_radius_bottom_left = glGetUniformLocation(prog, "clip_radius_bottom_left"); - shader->clip_radius_bottom_right = glGetUniformLocation(prog, "clip_radius_bottom_right"); + uniform_corner_radii_set_location( + &shader->clip_radius, + prog, + "clip_radius_top_left", + "clip_radius_top_right", + "clip_radius_bottom_left", + "clip_radius_bottom_right" + ); return true; } @@ -245,10 +281,14 @@ bool link_quad_grad_round_program(struct quad_grad_round_shader *shader, GLint c shader->pos_attrib = glGetAttribLocation(prog, "pos"); shader->size = glGetUniformLocation(prog, "size"); shader->position = glGetUniformLocation(prog, "position"); - shader->radius_top_left = glGetUniformLocation(prog, "radius_top_left"); - shader->radius_top_right = glGetUniformLocation(prog, "radius_top_right"); - shader->radius_bottom_left = glGetUniformLocation(prog, "radius_bottom_left"); - shader->radius_bottom_right = glGetUniformLocation(prog, "radius_bottom_right"); + uniform_corner_radii_set_location( + &shader->radius, + prog, + "radius_top_left", + "radius_top_right", + "radius_bottom_left", + "radius_bottom_right" + ); shader->grad_size = glGetUniformLocation(prog, "grad_size"); shader->colors = glGetUniformLocation(prog, "colors"); @@ -292,18 +332,27 @@ bool link_tex_program(struct tex_shader *shader, GLint client_version, enum fx_t shader->tex_proj = glGetUniformLocation(prog, "tex_proj"); shader->size = glGetUniformLocation(prog, "size"); shader->position = glGetUniformLocation(prog, "position"); - shader->radius_top_left = glGetUniformLocation(prog, "radius_top_left"); - shader->radius_top_right = glGetUniformLocation(prog, "radius_top_right"); - shader->radius_bottom_left = glGetUniformLocation(prog, "radius_bottom_left"); - shader->radius_bottom_right = glGetUniformLocation(prog, "radius_bottom_right"); + uniform_corner_radii_set_location( + &shader->radius, + prog, + "radius_top_left", + "radius_top_right", + "radius_bottom_left", + "radius_bottom_right" + ); + shader->discard_transparent = glGetUniformLocation(prog, "discard_transparent"); shader->clip_size = glGetUniformLocation(prog, "clip_size"); shader->clip_position = glGetUniformLocation(prog, "clip_position"); - shader->clip_radius_top_left = glGetUniformLocation(prog, "clip_radius_top_left"); - shader->clip_radius_top_right = glGetUniformLocation(prog, "clip_radius_top_right"); - shader->clip_radius_bottom_left = glGetUniformLocation(prog, "clip_radius_bottom_left"); - shader->clip_radius_bottom_right = glGetUniformLocation(prog, "clip_radius_bottom_right"); + uniform_corner_radii_set_location( + &shader->clip_radius, + prog, + "clip_radius_top_left", + "clip_radius_top_right", + "clip_radius_bottom_left", + "clip_radius_bottom_right" + ); return true; } @@ -332,10 +381,14 @@ bool link_box_shadow_program(struct box_shadow_shader *shader, GLint client_vers shader->corner_radius = glGetUniformLocation(prog, "corner_radius"); shader->clip_position = glGetUniformLocation(prog, "clip_position"); shader->clip_size = glGetUniformLocation(prog, "clip_size"); - shader->clip_radius_top_left = glGetUniformLocation(prog, "clip_radius_top_left"); - shader->clip_radius_top_right = glGetUniformLocation(prog, "clip_radius_top_right"); - shader->clip_radius_bottom_left = glGetUniformLocation(prog, "clip_radius_bottom_left"); - shader->clip_radius_bottom_right = glGetUniformLocation(prog, "clip_radius_bottom_right"); + uniform_corner_radii_set_location( + &shader->clip_radius, + prog, + "clip_radius_top_left", + "clip_radius_top_right", + "clip_radius_bottom_left", + "clip_radius_bottom_right" + ); return true; } diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 56aacd84..274b4611 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -610,8 +609,7 @@ static void xdg_toplevel_commit(struct wl_listener *listener, void *data) { wlr_scene_rect_set_size(toplevel->border, border_width, border_height); wlr_scene_rect_set_clipped_region(toplevel->border, (struct clipped_region) { - .corner_radius = toplevel->corner_radius, - .corners = CORNER_LOCATION_ALL, + .corners = corner_radii_all(toplevel->corner_radius), .area = { BORDER_THICKNESS, BORDER_THICKNESS, geometry->width, geometry->height } }); @@ -620,8 +618,7 @@ static void xdg_toplevel_commit(struct wl_listener *listener, void *data) { border_width + (blur_sigma * 2), border_height + (blur_sigma * 2)); wlr_scene_shadow_set_clipped_region(toplevel->shadow, (struct clipped_region) { - .corner_radius = toplevel->corner_radius + BORDER_THICKNESS, - .corners = CORNER_LOCATION_ALL, + .corners = corner_radii_all(toplevel->corner_radius + BORDER_THICKNESS), .area = { blur_sigma, blur_sigma, border_width, border_height } }); } @@ -655,8 +652,8 @@ static void output_configure_scene(struct wlr_scene_node *node, wlr_scene_buffer_set_opacity(buffer, toplevel->opacity); if (!wlr_subsurface_try_from_wlr_surface(xdg_surface->surface)) { - wlr_scene_buffer_set_corner_radius( - buffer, toplevel->corner_radius, CORNER_LOCATION_BOTTOM); + wlr_scene_buffer_set_corner_radii( + buffer, corner_radii_bottom(toplevel->corner_radius)); } } } else if (node->type == WLR_SCENE_NODE_TREE) { @@ -805,8 +802,7 @@ static void iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int sx, wlr_scene_buffer_set_opacity(buffer, toplevel->opacity); if (!wlr_subsurface_try_from_wlr_surface(xdg_surface->surface)) { - wlr_scene_buffer_set_corner_radius(buffer, toplevel->corner_radius, - CORNER_LOCATION_BOTTOM); + wlr_scene_buffer_set_corner_radii(buffer, corner_radii_bottom(toplevel->corner_radius)); wlr_scene_blur_set_transparency_mask_source(toplevel->blur, buffer); } @@ -963,8 +959,8 @@ static void server_new_xdg_toplevel(struct wl_listener *listener, void *data) { toplevel->border = wlr_scene_rect_create(toplevel->scene_tree, 0, 0, (float[4]){ 1.0f, 0.f, 0.f, 1.0f }); - wlr_scene_rect_set_corner_radius(toplevel->border, - toplevel->corner_radius + BORDER_THICKNESS, CORNER_LOCATION_BOTTOM); + wlr_scene_rect_set_corner_radii(toplevel->border, + corner_radii_bottom(toplevel->corner_radius + BORDER_THICKNESS)); wlr_scene_node_set_position(&toplevel->border->node, -BORDER_THICKNESS, -BORDER_THICKNESS); float blur_sigma = 20.0f; @@ -1147,8 +1143,7 @@ int main(int argc, char *argv[]) { struct wlr_scene_rect *rect = wlr_scene_rect_create(server.layers.toplevel_layer, 200, 200, top_rect_color); wlr_scene_rect_set_clipped_region(rect, (struct clipped_region) { - .corner_radius = 12, - .corners = CORNER_LOCATION_TOP, + .corners = {12, 12, 0, 0}, .area = { .x = 50, .y = 50, diff --git a/types/fx/clipped_region.c b/types/fx/clipped_region.c index b12b0d10..81bd264b 100644 --- a/types/fx/clipped_region.c +++ b/types/fx/clipped_region.c @@ -1,10 +1,70 @@ #include "scenefx/types/fx/clipped_region.h" -#include "scenefx/types/fx/corner_location.h" + +struct fx_corner_radii fx_corner_radii_extend(struct fx_corner_radii corners, int extend) { + return (struct fx_corner_radii) { + .top_left = corners.top_left == 0 ? 0 : (corners.top_left + extend), + .top_right = corners.top_right == 0 ? 0 : (corners.top_right + extend), + .bottom_left = corners.bottom_left == 0 ? 0 : (corners.bottom_left + extend), + .bottom_right = corners.bottom_right == 0 ? 0 : (corners.bottom_right + extend), + }; +} + +void fx_corner_radii_transform(enum wl_output_transform transform, + struct fx_corner_radii *corners) { + if (transform & WL_OUTPUT_TRANSFORM_FLIPPED) { + *corners = (struct fx_corner_radii){ + corners->top_right, + corners->top_left, + corners->bottom_left, + corners->bottom_right + }; + } + + unsigned int turns = transform & (WL_OUTPUT_TRANSFORM_90 | WL_OUTPUT_TRANSFORM_180 | WL_OUTPUT_TRANSFORM_270); + if (turns > 0) { + uint16_t points[4] = {corners->top_left, corners->top_right, corners->bottom_right, corners->bottom_left}; + *corners = (struct fx_corner_radii){ + points[turns % 4], + points[(turns + 1) % 4], + points[(turns + 2) % 4], + points[(turns + 3) % 4], + }; + } +} + +struct fx_corner_fradii fx_corner_radii_scale(struct fx_corner_radii corners, float scale) { + return (struct fx_corner_fradii) { + (float)corners.top_left * scale, + (float)corners.top_right * scale, + (float)corners.bottom_right * scale, + (float)corners.bottom_left * scale, + }; +} + +bool fx_corner_radii_eq(const struct fx_corner_radii lhs, const struct fx_corner_radii rhs) { + return lhs.top_left == rhs.top_left + && lhs.top_right == rhs.top_right + && lhs.bottom_right == rhs.bottom_right + && lhs.bottom_left == rhs.bottom_left; +} + +bool fx_corner_radii_is_empty(const struct fx_corner_radii* corners) { + return corners->top_left == 0 + && corners->top_right == 0 + && corners->bottom_right == 0 + && corners->bottom_left == 0; +} + +bool fx_corner_fradii_is_empty(const struct fx_corner_fradii* corners) { + return corners->top_left == 0.0 + && corners->top_right == 0.0 + && corners->bottom_right == 0.0 + && corners->bottom_left == 0.0; +} struct clipped_region clipped_region_get_default(void) { return (struct clipped_region) { - .corner_radius = 0, - .corners = CORNER_LOCATION_NONE, + .corners = {0}, .area = (struct wlr_box) {0}, }; } diff --git a/types/fx/corner_location.c b/types/fx/corner_location.c deleted file mode 100644 index e7069f2b..00000000 --- a/types/fx/corner_location.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "scenefx/types/fx/corner_location.h" - -// Maps the corners to its correct transformed corner -static const enum corner_location corner_transform[8][CORNER_LOCATION_LAST] = { - [WL_OUTPUT_TRANSFORM_NORMAL] = { - [CORNER_LOCATION_TOP_LEFT] = CORNER_LOCATION_TOP_LEFT, - [CORNER_LOCATION_TOP_RIGHT] = CORNER_LOCATION_TOP_RIGHT, - [CORNER_LOCATION_BOTTOM_RIGHT] = CORNER_LOCATION_BOTTOM_RIGHT, - [CORNER_LOCATION_BOTTOM_LEFT] = CORNER_LOCATION_BOTTOM_LEFT, - }, - [WL_OUTPUT_TRANSFORM_90] = { - [CORNER_LOCATION_TOP_LEFT] = CORNER_LOCATION_BOTTOM_LEFT, - [CORNER_LOCATION_TOP_RIGHT] = CORNER_LOCATION_TOP_LEFT, - [CORNER_LOCATION_BOTTOM_RIGHT] = CORNER_LOCATION_TOP_RIGHT, - [CORNER_LOCATION_BOTTOM_LEFT] = CORNER_LOCATION_BOTTOM_RIGHT, - }, - [WL_OUTPUT_TRANSFORM_180] = { - [CORNER_LOCATION_TOP_LEFT] = CORNER_LOCATION_BOTTOM_RIGHT, - [CORNER_LOCATION_TOP_RIGHT] = CORNER_LOCATION_BOTTOM_LEFT, - [CORNER_LOCATION_BOTTOM_RIGHT] = CORNER_LOCATION_TOP_LEFT, - [CORNER_LOCATION_BOTTOM_LEFT] = CORNER_LOCATION_TOP_RIGHT, - }, - [WL_OUTPUT_TRANSFORM_270] = { - [CORNER_LOCATION_TOP_LEFT] = CORNER_LOCATION_TOP_RIGHT, - [CORNER_LOCATION_TOP_RIGHT] = CORNER_LOCATION_BOTTOM_RIGHT, - [CORNER_LOCATION_BOTTOM_RIGHT] = CORNER_LOCATION_BOTTOM_LEFT, - [CORNER_LOCATION_BOTTOM_LEFT] = CORNER_LOCATION_TOP_LEFT, - }, - [WL_OUTPUT_TRANSFORM_FLIPPED] = { - [CORNER_LOCATION_TOP_LEFT] = CORNER_LOCATION_TOP_RIGHT, - [CORNER_LOCATION_TOP_RIGHT] = CORNER_LOCATION_TOP_LEFT, - [CORNER_LOCATION_BOTTOM_RIGHT] = CORNER_LOCATION_BOTTOM_LEFT, - [CORNER_LOCATION_BOTTOM_LEFT] = CORNER_LOCATION_BOTTOM_RIGHT, - }, - [WL_OUTPUT_TRANSFORM_FLIPPED_90] = { - [CORNER_LOCATION_TOP_LEFT] = CORNER_LOCATION_TOP_LEFT, - [CORNER_LOCATION_TOP_RIGHT] = CORNER_LOCATION_BOTTOM_LEFT, - [CORNER_LOCATION_BOTTOM_RIGHT] = CORNER_LOCATION_BOTTOM_RIGHT, - [CORNER_LOCATION_BOTTOM_LEFT] = CORNER_LOCATION_TOP_RIGHT, - }, - [WL_OUTPUT_TRANSFORM_FLIPPED_180] = { - [CORNER_LOCATION_TOP_LEFT] = CORNER_LOCATION_BOTTOM_LEFT, - [CORNER_LOCATION_TOP_RIGHT] = CORNER_LOCATION_BOTTOM_RIGHT, - [CORNER_LOCATION_BOTTOM_RIGHT] = CORNER_LOCATION_TOP_RIGHT, - [CORNER_LOCATION_BOTTOM_LEFT] = CORNER_LOCATION_TOP_LEFT, - }, - [WL_OUTPUT_TRANSFORM_FLIPPED_270] = { - [CORNER_LOCATION_TOP_LEFT] = CORNER_LOCATION_BOTTOM_RIGHT, - [CORNER_LOCATION_TOP_RIGHT] = CORNER_LOCATION_TOP_RIGHT, - [CORNER_LOCATION_BOTTOM_RIGHT] = CORNER_LOCATION_TOP_LEFT, - [CORNER_LOCATION_BOTTOM_LEFT] = CORNER_LOCATION_BOTTOM_LEFT, - }, -}; - -void corner_location_transform(enum wl_output_transform transform, - enum corner_location *corners) { - enum corner_location result = CORNER_LOCATION_NONE; - - int bitmask = 1 << (CORNER_LOCATION_COUNT - 1); - int mask = 1; - while (bitmask) { - switch (*corners & mask) { - case CORNER_LOCATION_NONE: - case CORNER_LOCATION_ALL: - break; - default: - result |= corner_transform[transform][*corners & mask]; - break; - } - - bitmask &= ~mask; - mask <<= 1; - } - - *corners = result; -} diff --git a/types/fx/meson.build b/types/fx/meson.build index 749d01df..e22e4a8d 100644 --- a/types/fx/meson.build +++ b/types/fx/meson.build @@ -1,5 +1,4 @@ scenefx_files += files( 'blur_data.c', - 'corner_location.c', 'clipped_region.c', ) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index be37beb5..2558bc3a 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -23,7 +23,6 @@ #include "scenefx/render/pass.h" #include "scenefx/types/fx/blur_data.h" #include "scenefx/types/fx/clipped_region.h" -#include "scenefx/types/fx/corner_location.h" #include "types/wlr_output.h" #include "types/wlr_scene.h" #include "util/array.h" @@ -301,7 +300,7 @@ static void scene_node_opaque_region(struct wlr_scene_node *node, int x, int y, if (node->type == WLR_SCENE_NODE_RECT) { struct wlr_scene_rect *scene_rect = wlr_scene_rect_from_node(node); - if (scene_rect->corner_radius > 0) { + if (!fx_corner_radii_is_empty(&scene_rect->corners)) { // TODO: this is incorrect return; } @@ -335,7 +334,7 @@ static void scene_node_opaque_region(struct wlr_scene_node *node, int x, int y, return; } - if (scene_buffer->corner_radius > 0) { + if (!fx_corner_radii_is_empty(&scene_buffer->corners)) { // TODO: this is incorrect return; } @@ -817,8 +816,7 @@ struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_tree *parent, scene_rect->width = width; scene_rect->height = height; memcpy(scene_rect->color, color, sizeof(scene_rect->color)); - scene_rect->corner_radius = 0; - scene_rect->corners = CORNER_LOCATION_NONE; + scene_rect->corners = (struct fx_corner_radii){0}; scene_rect->accepts_input = true; scene_rect->clipped_region = clipped_region_get_default(); @@ -916,29 +914,26 @@ static void scene_buffer_set_wait_timeline(struct wlr_scene_buffer *scene_buffer } } -void wlr_scene_rect_set_corner_radius(struct wlr_scene_rect *rect, int corner_radius, - enum corner_location corners) { - if (rect->corner_radius == corner_radius && rect->corners == corners) { +inline void wlr_scene_rect_set_corner_radius(struct wlr_scene_rect *rect, int corner_radius) { + wlr_scene_rect_set_corner_radii(rect, corner_radii_all(corner_radius)); +} + +void wlr_scene_rect_set_corner_radii(struct wlr_scene_rect *rect, struct fx_corner_radii corners) { + if (fx_corner_radii_eq(rect->corners, corners)) { return; } - rect->corner_radius = corner_radius; rect->corners = corners; scene_node_update(&rect->node, NULL); } void wlr_scene_rect_set_clipped_region(struct wlr_scene_rect *rect, struct clipped_region clipped_region) { - if (rect->clipped_region.corner_radius == clipped_region.corner_radius && - rect->clipped_region.corners == clipped_region.corners && + if (fx_corner_radii_eq(rect->clipped_region.corners, clipped_region.corners) && wlr_box_equal(&rect->clipped_region.area, &clipped_region.area)) { return; } - if (clipped_region.corner_radius && clipped_region.corners == CORNER_LOCATION_NONE) { - wlr_log(WLR_ERROR, "Applying corner radius without specifying which" - " corners to round for rect: %p", rect); - } rect->clipped_region = clipped_region; scene_node_update(&rect->node, NULL); } @@ -1004,16 +999,11 @@ void wlr_scene_shadow_set_color(struct wlr_scene_shadow *shadow, const float col void wlr_scene_shadow_set_clipped_region(struct wlr_scene_shadow *shadow, struct clipped_region clipped_region) { - if (shadow->clipped_region.corner_radius == clipped_region.corner_radius && - shadow->clipped_region.corners == clipped_region.corners && + if (fx_corner_radii_eq(shadow->clipped_region.corners, clipped_region.corners) && wlr_box_equal(&shadow->clipped_region.area, &clipped_region.area)) { return; } - if (clipped_region.corner_radius && clipped_region.corners == CORNER_LOCATION_NONE) { - wlr_log(WLR_ERROR, "Applying corner radius without specifying which" - " corners to round for shadow: %p", shadow); - } shadow->clipped_region = clipped_region; scene_node_update(&shadow->node, NULL); } @@ -1042,9 +1032,8 @@ struct wlr_scene_blur *wlr_scene_blur_create(struct wlr_scene_tree *parent, blur->alpha = 1.0f; blur->strength = 1.0f; - blur->corner_radius = 0; blur->clipped_region = (struct clipped_region){0}; - blur->corners = CORNER_LOCATION_NONE; + blur->corners = corner_radii_all(0); blur->should_only_blur_bottom_layer = false; blur->transparency_mask_source = linked_node_init();; blur->width = width; @@ -1066,13 +1055,15 @@ void wlr_scene_blur_set_size(struct wlr_scene_blur *blur, int width, int height) scene_node_update(&blur->node, NULL); } -void wlr_scene_blur_set_corner_radius(struct wlr_scene_blur *blur, int corner_radius, - enum corner_location corners) { - if (blur->corner_radius == corner_radius && blur->corners == corners) { +inline void wlr_scene_blur_set_corner_radius(struct wlr_scene_blur *blur, int corner_radius) { + wlr_scene_blur_set_corner_radii(blur, corner_radii_all(corner_radius)); +} + +void wlr_scene_blur_set_corner_radii(struct wlr_scene_blur *blur, struct fx_corner_radii corners) { + if (fx_corner_radii_eq(blur->corners, corners)) { return; } - blur->corner_radius = corner_radius; blur->corners = corners; scene_node_update(&blur->node, NULL); } @@ -1138,16 +1129,11 @@ void wlr_scene_blur_set_strength(struct wlr_scene_blur *blur, float strength) { void wlr_scene_blur_set_clipped_region(struct wlr_scene_blur *blur, struct clipped_region clipped_region) { - if (blur->clipped_region.corner_radius == clipped_region.corner_radius && - blur->clipped_region.corners == clipped_region.corners && + if (fx_corner_radii_eq(blur->clipped_region.corners, clipped_region.corners) && wlr_box_equal(&blur->clipped_region.area, &clipped_region.area)) { return; - } - - if (clipped_region.corner_radius && clipped_region.corners == CORNER_LOCATION_NONE) { - wlr_log(WLR_ERROR, "Applying corner radius without specifying which" - " corners to round for blur source: %p", blur); } + blur->clipped_region = clipped_region; scene_node_update(&blur->node, NULL); } @@ -1297,8 +1283,7 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, wl_list_init(&scene_buffer->renderer_destroy.link); scene_buffer->opacity = 1; - scene_buffer->corner_radius = 0; - scene_buffer->corners = CORNER_LOCATION_NONE; + scene_buffer->corners = corner_radii_none(); scene_buffer->blur = linked_node_init(); @@ -1560,15 +1545,18 @@ void wlr_scene_buffer_set_filter_mode(struct wlr_scene_buffer *scene_buffer, scene_node_update(&scene_buffer->node, NULL); } -void wlr_scene_buffer_set_corner_radius(struct wlr_scene_buffer *scene_buffer, - int radii, enum corner_location corners) { - if (scene_buffer->corner_radius == radii - && scene_buffer->corners == corners) { +inline void wlr_scene_buffer_set_corner_radius(struct wlr_scene_buffer *scene_buffer, + int radii) { + wlr_scene_buffer_set_corner_radii(scene_buffer, corner_radii_all(radii)); +} + +void wlr_scene_buffer_set_corner_radii(struct wlr_scene_buffer *scene_buffer, + struct fx_corner_radii corner_radii) { + if (fx_corner_radii_eq(scene_buffer->corners, corner_radii)) { return; } - scene_buffer->corner_radius = radii; - scene_buffer->corners = corners; + scene_buffer->corners = corner_radii; scene_node_update(&scene_buffer->node, NULL); } @@ -1901,20 +1889,19 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren break; case WLR_SCENE_NODE_RECT:; struct wlr_scene_rect *scene_rect = wlr_scene_rect_from_node(node); - enum corner_location rect_corners = scene_rect->corners; + struct fx_corner_radii rect_corners = scene_rect->corners; - corner_location_transform(node_transform, &rect_corners); + fx_corner_radii_transform(node_transform, &rect_corners); struct wlr_box rect_clipped_region_box = scene_rect->clipped_region.area; - int rect_clipped_region_corner_radius = scene_rect->clipped_region.corner_radius; - enum corner_location rect_clipped_corners = scene_rect->clipped_region.corners; + struct fx_corner_radii rect_clipped_corners = scene_rect->clipped_region.corners; // Node relative -> Root relative rect_clipped_region_box.x += x; rect_clipped_region_box.y += y; transform_output_box(&rect_clipped_region_box, data); - corner_location_transform(node_transform, &rect_clipped_corners); + fx_corner_radii_transform(node_transform, &rect_clipped_corners); struct fx_render_rect_options rect_options = { .base = { @@ -1929,16 +1916,14 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren }, .clipped_region = { .area = rect_clipped_region_box, - .corner_radius = rect_clipped_region_corner_radius * data->scale, - .corners = rect_clipped_corners, + .corners = fx_corner_radii_scale(rect_clipped_corners, data->scale), }, }; - if (scene_rect->corner_radius && rect_corners != CORNER_LOCATION_NONE) { + if (!fx_corner_radii_is_empty(&rect_corners)) { struct fx_render_rounded_rect_options rounded_rect_options = { .base = rect_options.base, - .corner_radius = scene_rect->corner_radius * data->scale, - .corners = rect_corners, + .corners = fx_corner_radii_scale(rect_corners, data->scale), .clipped_region = rect_options.clipped_region, }; fx_render_pass_add_rounded_rect(data->render_pass, &rounded_rect_options); @@ -1964,7 +1949,6 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren .dst_box = dst_box, }, .clip_box = &dst_box, - .corner_radius = 0, .discard_transparent = false, .clipped_region = {0} }, @@ -1981,22 +1965,20 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren struct wlr_scene_shadow *scene_shadow = wlr_scene_shadow_from_node(node); struct wlr_box shadow_clipped_region_box = scene_shadow->clipped_region.area; - int shadow_clipped_region_corner_radius = scene_shadow->clipped_region.corner_radius; - enum corner_location shadow_clipped_corners = scene_shadow->clipped_region.corners; + struct fx_corner_radii shadow_clipped_corners = scene_shadow->clipped_region.corners; // Node relative -> Root relative shadow_clipped_region_box.x += x; shadow_clipped_region_box.y += y; transform_output_box(&shadow_clipped_region_box, data); - corner_location_transform(node_transform, &shadow_clipped_corners); + fx_corner_radii_transform(node_transform, &shadow_clipped_corners); struct fx_render_box_shadow_options shadow_options = { .box = dst_box, .clipped_region = { .area = shadow_clipped_region_box, - .corner_radius = shadow_clipped_region_corner_radius * data->scale, - .corners = shadow_clipped_corners, + .corners = fx_corner_radii_scale(shadow_clipped_corners, data->scale), }, .blur_sigma = scene_shadow->blur_sigma, .corner_radius = scene_shadow->corner_radius * data->scale, @@ -2012,7 +1994,7 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren break; case WLR_SCENE_NODE_BUFFER:; struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); - enum corner_location buffer_corners = scene_buffer->corners; + struct fx_corner_radii buffer_corners = scene_buffer->corners; if (scene_buffer->is_single_pixel_buffer) { // TODO: Render blur/rounded corners/etc here: @@ -2042,7 +2024,7 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren enum wl_output_transform transform = wlr_output_transform_invert(scene_buffer->transform); transform = wlr_output_transform_compose(transform, data->transform); - corner_location_transform(transform, &buffer_corners); + fx_corner_radii_transform(transform, &buffer_corners); struct fx_render_texture_options tex_options = { .base = (struct wlr_render_texture_options){ @@ -2060,8 +2042,7 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren .wait_point = scene_buffer->wait_point, }, .clip_box = &dst_box, - .corners = buffer_corners, - .corner_radius = scene_buffer->corner_radius * data->scale, + .corners = fx_corner_radii_scale(buffer_corners, data->scale), .clipped_region = {0}, }; @@ -2089,6 +2070,9 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren tex = scene_buffer_get_texture(mask, data->output->output->renderer); } + struct fx_corner_radii blur_corners = blur->corners; + fx_corner_radii_transform(node_transform, &blur_corners); + struct fx_render_blur_pass_options blur_options = { .tex_options = { .base = (struct wlr_render_texture_options) { @@ -2102,8 +2086,7 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren .blend_mode = WLR_RENDER_BLEND_MODE_PREMULTIPLIED, }, .clip_box = &dst_box, - .corner_radius = blur->corner_radius * data->scale, - .corners = blur->corners, + .corners = fx_corner_radii_scale(blur_corners, data->scale), .discard_transparent = false, }, .opaque_region = NULL,