mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-11 13:10:07 +00:00
vulkan: Try really hard to use clear
Using clear avoids the shader engine (see last commit), so if we can get pixels out of it, we should. So we detect the overlap with the rounded corners of the clip region and emit shaders for those, but then use Clear() for the rest. With this in place, widget-factory on my integrated Intel TigerLake gets a 60% performance boost.
This commit is contained in:
parent
bb2cd7225e
commit
ce042f7ba1
@ -945,3 +945,44 @@ gsk_rounded_rect_to_string (const GskRoundedRect *self)
|
||||
self->corner[3].width,
|
||||
self->corner[3].height);
|
||||
}
|
||||
|
||||
/*
|
||||
* gsk_rounded_rect_get_largest_cover:
|
||||
* @self: the rounded rect to intersect with
|
||||
* @rect: the rectangle to intersect
|
||||
* @result: (out caller-allocates): The resulting rectangle
|
||||
*
|
||||
* Computes the largest rectangle that is fully covered by both
|
||||
* the given rect and the rounded rect.
|
||||
* In particular, this function respects corners, so
|
||||
* gsk_rounded_rect_get_largest_cover(self, &self->bounds, &rect)
|
||||
* can be used to compute a decomposition for a rounded rect itself.
|
||||
**/
|
||||
void
|
||||
gsk_rounded_rect_get_largest_cover (const GskRoundedRect *self,
|
||||
const graphene_rect_t *rect,
|
||||
graphene_rect_t *result)
|
||||
{
|
||||
graphene_rect_t wide, high;
|
||||
double start, end;
|
||||
|
||||
wide = self->bounds;
|
||||
start = MAX(self->corner[GSK_CORNER_TOP_LEFT].height, self->corner[GSK_CORNER_TOP_RIGHT].height);
|
||||
end = MAX(self->corner[GSK_CORNER_BOTTOM_LEFT].height, self->corner[GSK_CORNER_BOTTOM_RIGHT].height);
|
||||
wide.size.height -= MIN (wide.size.height, start + end);
|
||||
wide.origin.y += start;
|
||||
graphene_rect_intersection (&wide, rect, &wide);
|
||||
|
||||
high = self->bounds;
|
||||
start = MAX(self->corner[GSK_CORNER_TOP_LEFT].width, self->corner[GSK_CORNER_BOTTOM_LEFT].width);
|
||||
end = MAX(self->corner[GSK_CORNER_TOP_RIGHT].width, self->corner[GSK_CORNER_BOTTOM_RIGHT].width);
|
||||
high.size.width -= MIN (high.size.width, start + end);
|
||||
high.origin.x += start;
|
||||
graphene_rect_intersection (&high, rect, &high);
|
||||
|
||||
if (wide.size.width * wide.size.height > high.size.width * high.size.height)
|
||||
*result = wide;
|
||||
else
|
||||
*result = high;
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,10 @@ gboolean gsk_rounded_rect_equal (gconstpointer
|
||||
gconstpointer rect2) G_GNUC_PURE;
|
||||
char * gsk_rounded_rect_to_string (const GskRoundedRect *self) G_GNUC_MALLOC;
|
||||
|
||||
void gsk_rounded_rect_get_largest_cover (const GskRoundedRect *self,
|
||||
const graphene_rect_t *rect,
|
||||
graphene_rect_t *result);
|
||||
|
||||
typedef enum {
|
||||
GSK_INTERSECTION_EMPTY,
|
||||
GSK_INTERSECTION_NONEMPTY,
|
||||
|
@ -368,21 +368,70 @@ gsk_vulkan_render_pass_add_color_node (GskVulkanRenderPass *self,
|
||||
return TRUE;
|
||||
|
||||
/* we have handled the bounds, now do the corners */
|
||||
if (state->clip.type != GSK_VULKAN_CLIP_ROUNDED ||
|
||||
gsk_vulkan_clip_contains_rect (&state->clip,
|
||||
graphene_point_zero (),
|
||||
&GRAPHENE_RECT_INIT (
|
||||
int_clipped.x / graphene_vec2_get_x (&state->scale),
|
||||
int_clipped.y / graphene_vec2_get_y (&state->scale),
|
||||
int_clipped.width / graphene_vec2_get_x (&state->scale),
|
||||
int_clipped.height / graphene_vec2_get_y (&state->scale)
|
||||
)))
|
||||
if (state->clip.type == GSK_VULKAN_CLIP_ROUNDED)
|
||||
{
|
||||
gsk_vulkan_clear_op (render,
|
||||
&int_clipped,
|
||||
color);
|
||||
return TRUE;
|
||||
graphene_rect_t cover;
|
||||
const char *clip_type;
|
||||
float scale_x = graphene_vec2_get_x (&state->scale);
|
||||
float scale_y = graphene_vec2_get_y (&state->scale);
|
||||
clipped = GRAPHENE_RECT_INIT (int_clipped.x / scale_x, int_clipped.y / scale_y,
|
||||
int_clipped.width / scale_x, int_clipped.height / scale_y);
|
||||
clip_type = gsk_vulkan_clip_get_clip_type (&state->clip, graphene_point_zero(), &clipped);
|
||||
if (clip_type[0] != '\0')
|
||||
{
|
||||
gsk_rounded_rect_get_largest_cover (&state->clip.rect, &clipped, &cover);
|
||||
int_clipped.x = ceil (cover.origin.x * scale_x);
|
||||
int_clipped.y = ceil (cover.origin.y * scale_y);
|
||||
int_clipped.width = floor ((cover.origin.x + cover.size.width) * scale_x) - int_clipped.x;
|
||||
int_clipped.height = floor ((cover.origin.y + cover.size.height) * scale_y) - int_clipped.y;
|
||||
if (int_clipped.width == 0 || int_clipped.height == 0)
|
||||
{
|
||||
gsk_vulkan_color_op (render,
|
||||
clip_type,
|
||||
&clipped,
|
||||
graphene_point_zero (),
|
||||
color);
|
||||
return TRUE;
|
||||
}
|
||||
cover = GRAPHENE_RECT_INIT (int_clipped.x / scale_x, int_clipped.y / scale_y,
|
||||
int_clipped.width / scale_x, int_clipped.height / scale_y);
|
||||
if (clipped.origin.x != cover.origin.x)
|
||||
gsk_vulkan_color_op (render,
|
||||
clip_type,
|
||||
&GRAPHENE_RECT_INIT (clipped.origin.x, clipped.origin.y, cover.origin.x - clipped.origin.x, clipped.size.height),
|
||||
graphene_point_zero (),
|
||||
color);
|
||||
if (clipped.origin.y != cover.origin.y)
|
||||
gsk_vulkan_color_op (render,
|
||||
clip_type,
|
||||
&GRAPHENE_RECT_INIT (clipped.origin.x, clipped.origin.y, clipped.size.width, cover.origin.y - clipped.origin.y),
|
||||
graphene_point_zero (),
|
||||
color);
|
||||
if (clipped.origin.x + clipped.size.width != cover.origin.x + cover.size.width)
|
||||
gsk_vulkan_color_op (render,
|
||||
clip_type,
|
||||
&GRAPHENE_RECT_INIT (cover.origin.x + cover.size.width,
|
||||
clipped.origin.y,
|
||||
clipped.origin.x + clipped.size.width - cover.origin.x - cover.size.width,
|
||||
clipped.size.height),
|
||||
graphene_point_zero (),
|
||||
color);
|
||||
if (clipped.origin.y + clipped.size.height != cover.origin.y + cover.size.height)
|
||||
gsk_vulkan_color_op (render,
|
||||
clip_type,
|
||||
&GRAPHENE_RECT_INIT (clipped.origin.x,
|
||||
cover.origin.y + cover.size.height,
|
||||
clipped.size.width,
|
||||
clipped.origin.y + clipped.size.height - cover.origin.y - cover.size.height),
|
||||
graphene_point_zero (),
|
||||
color);
|
||||
}
|
||||
}
|
||||
|
||||
gsk_vulkan_clear_op (render,
|
||||
&int_clipped,
|
||||
color);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gsk_vulkan_color_op (render,
|
||||
|
Loading…
Reference in New Issue
Block a user