vulkan: Implement support for all fill children

If the fill is not with a color, render the path to an alpha mask and
then mask the child with it.
This commit is contained in:
Benjamin Otte
2023-07-22 01:11:41 +02:00
parent 66e3082e2e
commit 22590d24e1

View File

@@ -1221,6 +1221,10 @@ gsk_vulkan_render_pass_add_fill_node (GskVulkanRenderPass *self,
GskRenderNode *node)
{
GskRenderNode *child;
graphene_rect_t clipped, child_tex_rect;
GskVulkanImage *child_image, *mask_image;
graphene_matrix_t projection;
int width, height;
child = gsk_fill_node_get_child (node);
@@ -1236,7 +1240,62 @@ gsk_vulkan_render_pass_add_fill_node (GskVulkanRenderPass *self,
return TRUE;
}
FALLBACK ("Fill nodes without color fills aren't supported yet.");
graphene_rect_offset_r (&state->clip.rect.bounds, - state->offset.x, - state->offset.y, &clipped);
graphene_rect_intersection (&clipped, &node->bounds, &clipped);
if (clipped.size.width == 0 || clipped.size.height == 0)
return TRUE;
child_image = gsk_vulkan_render_pass_get_node_as_image (self,
render,
state,
child,
&child_tex_rect);
if (child_image == NULL)
return TRUE;
width = ceil (graphene_vec2_get_x (&state->scale) * clipped.size.width);
height = ceil (graphene_vec2_get_y (&state->scale) * clipped.size.height);
mask_image = gsk_vulkan_image_new_for_offscreen (gsk_vulkan_render_get_context (render),
gdk_memory_depth_get_alpha_format (gsk_render_node_get_preferred_depth (child)),
width, height);
gsk_vulkan_render_pass_begin_op (render,
mask_image,
&(cairo_rectangle_int_t) { 0, 0, width, height },
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
gsk_vulkan_scissor_op (render, &(cairo_rectangle_int_t) { 0, 0, width, height });
graphene_matrix_init_ortho (&projection,
0, width,
0, height,
2 * ORTHO_NEAR_PLANE - ORTHO_FAR_PLANE,
ORTHO_FAR_PLANE);
gsk_vulkan_push_constants_op (render, &state->scale, &projection, &GSK_ROUNDED_RECT_INIT_FROM_RECT (clipped));
gsk_vulkan_fill_op (render,
GSK_VULKAN_SHADER_CLIP_NONE,
&GRAPHENE_POINT_INIT (- clipped.origin.x, - clipped.origin.y),
&node->bounds,
gsk_fill_node_get_path (node),
gsk_fill_node_get_fill_rule (node),
&(GdkRGBA) { 1.0, 1.0, 1.0, 1.0 });
gsk_vulkan_render_pass_end_op (render,
mask_image,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
gsk_vulkan_mask_op (render,
gsk_vulkan_clip_get_shader_clip (&state->clip, &state->offset, &node->bounds),
&state->offset,
child_image,
&child->bounds,
&child_tex_rect,
mask_image,
&node->bounds,
&clipped,
GSK_MASK_MODE_ALPHA);
g_object_unref (mask_image);
return TRUE;
}
static inline gboolean