diff options
-rw-r--r-- | gsk/gskroundedrect.c | 30 | ||||
-rw-r--r-- | gsk/gskroundedrectprivate.h | 2 | ||||
-rw-r--r-- | gsk/gskvulkanclip.c | 28 | ||||
-rw-r--r-- | gsk/gskvulkanclipprivate.h | 4 | ||||
-rw-r--r-- | gsk/gskvulkanpushconstants.c | 44 | ||||
-rw-r--r-- | gsk/gskvulkanpushconstantsprivate.h | 18 | ||||
-rw-r--r-- | gsk/gskvulkanrenderpass.c | 76 | ||||
-rw-r--r-- | gsk/resources/vulkan/blit.vert.glsl | 3 | ||||
-rw-r--r-- | gsk/resources/vulkan/blit.vert.spv | bin | 1104 -> 1252 bytes | |||
-rw-r--r-- | gsk/resources/vulkan/color.vert.glsl | 3 | ||||
-rw-r--r-- | gsk/resources/vulkan/color.vert.spv | bin | 1632 -> 1780 bytes |
11 files changed, 164 insertions, 44 deletions
diff --git a/gsk/gskroundedrect.c b/gsk/gskroundedrect.c index 16ad85ef45..03f987e964 100644 --- a/gsk/gskroundedrect.c +++ b/gsk/gskroundedrect.c @@ -501,3 +501,33 @@ gsk_rounded_rect_path (const GskRoundedRect *self, cairo_close_path (cr); } +/* + * Converts to the format we use in our shaders: + * vec4 rect; + * vec4 corner_widths; + * vec4 corner_heights; + * rect is (x, y, width, height), the corners are the same + * order as in the rounded rect. + * + * This is so that shaders can use just the first vec4 for + * rectilinear rects, the 2nd vec4 for circular rects and + * only look at the last vec4 if they have to. + */ +void +gsk_rounded_rect_to_float (const GskRoundedRect *self, + float rect[12]) +{ + guint i; + + rect[0] = self->bounds.origin.x; + rect[1] = self->bounds.origin.y; + rect[2] = self->bounds.size.width; + rect[3] = self->bounds.size.height; + + for (i = 0; i < 4; i++) + { + rect[4 + i] = self->corner[i].width; + rect[8 + i] = self->corner[i].height; + } +} + diff --git a/gsk/gskroundedrectprivate.h b/gsk/gskroundedrectprivate.h index d11567ad28..5b40cb45bc 100644 --- a/gsk/gskroundedrectprivate.h +++ b/gsk/gskroundedrectprivate.h @@ -11,6 +11,8 @@ gboolean gsk_rounded_rect_is_circular (const GskRounde void gsk_rounded_rect_path (const GskRoundedRect *self, cairo_t *cr); +void gsk_rounded_rect_to_float (const GskRoundedRect *self, + float rect[12]); G_END_DECLS diff --git a/gsk/gskvulkanclip.c b/gsk/gskvulkanclip.c index 38755f5c24..9a3ad8696f 100644 --- a/gsk/gskvulkanclip.c +++ b/gsk/gskvulkanclip.c @@ -128,6 +128,34 @@ gsk_vulkan_clip_intersect_rounded_rect (GskVulkanClip *dest, } gboolean +gsk_vulkan_clip_transform (GskVulkanClip *dest, + const GskVulkanClip *src, + const graphene_matrix_t *transform, + const graphene_rect_t *viewport) +{ + switch (dest->type) + { + default: + g_assert_not_reached(); + return FALSE; + + case GSK_VULKAN_CLIP_ALL_CLIPPED: + gsk_vulkan_clip_init_copy (dest, src); + return TRUE; + + case GSK_VULKAN_CLIP_NONE: + gsk_vulkan_clip_init_empty (dest, viewport); + return TRUE; + + case GSK_VULKAN_CLIP_RECT: + case GSK_VULKAN_CLIP_ROUNDED_CIRCULAR: + case GSK_VULKAN_CLIP_ROUNDED: + /* FIXME: Handle 2D operations, in particular transform and scale */ + return FALSE; + } +} + +gboolean gsk_vulkan_clip_contains_rect (const GskVulkanClip *self, const graphene_rect_t *rect) { diff --git a/gsk/gskvulkanclipprivate.h b/gsk/gskvulkanclipprivate.h index 492ef4c2b1..99450afe4e 100644 --- a/gsk/gskvulkanclipprivate.h +++ b/gsk/gskvulkanclipprivate.h @@ -44,6 +44,10 @@ gboolean gsk_vulkan_clip_intersect_rect (GskVulk gboolean gsk_vulkan_clip_intersect_rounded_rect (GskVulkanClip *dest, const GskVulkanClip *src, const GskRoundedRect *rounded) G_GNUC_WARN_UNUSED_RESULT; +gboolean gsk_vulkan_clip_transform (GskVulkanClip *dest, + const GskVulkanClip *src, + const graphene_matrix_t*transform, + const graphene_rect_t *viewport) G_GNUC_WARN_UNUSED_RESULT; gboolean gsk_vulkan_clip_contains_rect (const GskVulkanClip *self, const graphene_rect_t *rect) G_GNUC_WARN_UNUSED_RESULT; diff --git a/gsk/gskvulkanpushconstants.c b/gsk/gskvulkanpushconstants.c index 4487687b6d..f7daf1acbf 100644 --- a/gsk/gskvulkanpushconstants.c +++ b/gsk/gskvulkanpushconstants.c @@ -2,13 +2,15 @@ #include "gskvulkanpushconstantsprivate.h" -#include <math.h> +#include "gskroundedrectprivate.h" void gsk_vulkan_push_constants_init (GskVulkanPushConstants *constants, - const graphene_matrix_t *mvp) + const graphene_matrix_t *mvp, + const graphene_rect_t *viewport) { graphene_matrix_init_from_matrix (&constants->mvp, mvp); + gsk_vulkan_clip_init_empty (&constants->clip, viewport); } void @@ -18,13 +20,42 @@ gsk_vulkan_push_constants_init_copy (GskVulkanPushConstants *self, *self = *src; } -void -gsk_vulkan_push_constants_init_transform (GskVulkanPushConstants *self, - const GskVulkanPushConstants *src, - const graphene_matrix_t *transform) +gboolean +gsk_vulkan_push_constants_transform (GskVulkanPushConstants *self, + const GskVulkanPushConstants *src, + const graphene_matrix_t *transform, + const graphene_rect_t *viewport) { + if (!gsk_vulkan_clip_transform (&self->clip, &src->clip, transform, viewport)) + return FALSE; + graphene_matrix_multiply (transform, &src->mvp, &self->mvp); + return TRUE; +} + +gboolean +gsk_vulkan_push_constants_intersect_rect (GskVulkanPushConstants *self, + const GskVulkanPushConstants *src, + const graphene_rect_t *rect) +{ + if (!gsk_vulkan_clip_intersect_rect (&self->clip, &src->clip, rect)) + return FALSE; + + graphene_matrix_init_from_matrix (&self->mvp, &src->mvp); + return TRUE; +} + +gboolean +gsk_vulkan_push_constants_intersect_rounded (GskVulkanPushConstants *self, + const GskVulkanPushConstants *src, + const GskRoundedRect *rect) +{ + if (!gsk_vulkan_clip_intersect_rounded_rect (&self->clip, &src->clip, rect)) + return FALSE; + + graphene_matrix_init_from_matrix (&self->mvp, &src->mvp); + return TRUE; } static void @@ -32,6 +63,7 @@ gsk_vulkan_push_constants_wire_init (GskVulkanPushConstantsWire *wire, const GskVulkanPushConstants *self) { graphene_matrix_to_float (&self->mvp, wire->vertex.mvp); + gsk_rounded_rect_to_float (&self->clip.rect, wire->vertex.clip); } void diff --git a/gsk/gskvulkanpushconstantsprivate.h b/gsk/gskvulkanpushconstantsprivate.h index bdfd111d52..4642d526a3 100644 --- a/gsk/gskvulkanpushconstantsprivate.h +++ b/gsk/gskvulkanpushconstantsprivate.h @@ -3,6 +3,7 @@ #include <gdk/gdk.h> #include <graphene.h> +#include <gsk/gskvulkanclipprivate.h> G_BEGIN_DECLS @@ -12,12 +13,14 @@ typedef struct _GskVulkanPushConstantsWire GskVulkanPushConstantsWire; struct _GskVulkanPushConstants { graphene_matrix_t mvp; + GskVulkanClip clip; }; struct _GskVulkanPushConstantsWire { struct { float mvp[16]; + float clip[12]; } vertex; #if 0 struct { @@ -30,12 +33,21 @@ const VkPushConstantRange * uint32_t gst_vulkan_push_constants_get_range_count (void) G_GNUC_PURE; void gsk_vulkan_push_constants_init (GskVulkanPushConstants *constants, - const graphene_matrix_t *mvp); + const graphene_matrix_t *mvp, + const graphene_rect_t *viewport); void gsk_vulkan_push_constants_init_copy (GskVulkanPushConstants *self, const GskVulkanPushConstants *src); -void gsk_vulkan_push_constants_init_transform (GskVulkanPushConstants *self, + +gboolean gsk_vulkan_push_constants_transform (GskVulkanPushConstants *self, + const GskVulkanPushConstants *src, + const graphene_matrix_t *transform, + const graphene_rect_t *viewport); +gboolean gsk_vulkan_push_constants_intersect_rect (GskVulkanPushConstants *self, + const GskVulkanPushConstants *src, + const graphene_rect_t *rect); +gboolean gsk_vulkan_push_constants_intersect_rounded (GskVulkanPushConstants *self, const GskVulkanPushConstants *src, - const graphene_matrix_t *transform); + const GskRoundedRect *rect); void gsk_vulkan_push_constants_push_vertex (const GskVulkanPushConstants *self, VkCommandBuffer command_buffer, diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c index 796ba62ade..dc26f31f1c 100644 --- a/gsk/gskvulkanrenderpass.c +++ b/gsk/gskvulkanrenderpass.c @@ -92,7 +92,6 @@ void gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, GskVulkanRender *render, const GskVulkanPushConstants *constants, - const GskVulkanClip *clip, GskRenderNode *node) { GskVulkanOp op = { @@ -111,24 +110,24 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, case GSK_CAIRO_NODE: if (gsk_cairo_node_get_surface (node) == NULL) return; - if (!gsk_vulkan_clip_contains_rect (clip, &node->bounds)) - FALLBACK ("Cairo nodes can't deal with clip type %u\n", clip->type); + if (!gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) + FALLBACK ("Cairo nodes can't deal with clip type %u\n", constants->clip.type); op.type = GSK_VULKAN_OP_SURFACE; op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_BLIT); g_array_append_val (self->render_ops, op); return; case GSK_TEXTURE_NODE: - if (!gsk_vulkan_clip_contains_rect (clip, &node->bounds)) - FALLBACK ("Texture nodes can't deal with clip type %u\n", clip->type); + if (!gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) + FALLBACK ("Texture nodes can't deal with clip type %u\n", constants->clip.type); op.type = GSK_VULKAN_OP_TEXTURE; op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_BLIT); g_array_append_val (self->render_ops, op); return; case GSK_COLOR_NODE: - if (!gsk_vulkan_clip_contains_rect (clip, &node->bounds)) - FALLBACK ("Color nodes can't deal with clip type %u\n", clip->type); + if (!gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) + FALLBACK ("Color nodes can't deal with clip type %u\n", constants->clip.type); op.type = GSK_VULKAN_OP_COLOR; op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_COLOR); g_array_append_val (self->render_ops, op); @@ -140,7 +139,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, for (i = 0; i < gsk_container_node_get_n_children (node); i++) { - gsk_vulkan_render_pass_add_node (self, render, constants, clip, gsk_container_node_get_child (node, i)); + gsk_vulkan_render_pass_add_node (self, render, constants, gsk_container_node_get_child (node, i)); } } return; @@ -148,21 +147,21 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, case GSK_TRANSFORM_NODE: { graphene_matrix_t transform; - GskVulkanClip new_clip; - graphene_rect_t rect; + GskRenderNode *child; +#if 0 if (!gsk_vulkan_clip_contains_rect (clip, &node->bounds)) FALLBACK ("Transform nodes can't deal with clip type %u\n", clip->type); +#endif gsk_transform_node_get_transform (node, &transform); + child = gsk_transform_node_get_child (node); + if (!gsk_vulkan_push_constants_transform (&op.constants.constants, constants, &transform, &child->bounds)) + FALLBACK ("Transform nodes can't deal with clip type %u\n", constants->clip.type); op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS; - gsk_vulkan_push_constants_init_transform (&op.constants.constants, constants, &transform); g_array_append_val (self->render_ops, op); - graphene_matrix_transform_bounds (&transform, &clip->rect.bounds, &rect); - gsk_vulkan_clip_init_empty (&new_clip, &rect); - - gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, &new_clip, gsk_transform_node_get_child (node)); + gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, child); gsk_vulkan_push_constants_init_copy (&op.constants.constants, constants); g_array_append_val (self->render_ops, op); } @@ -170,27 +169,37 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, case GSK_CLIP_NODE: { - GskVulkanClip new_clip; - - if (!gsk_vulkan_clip_intersect_rect (&new_clip, clip, gsk_clip_node_peek_clip (node))) - FALLBACK ("Failed to find intersection between clip of type %u and rectangle\n", clip->type); - if (new_clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED) + if (!gsk_vulkan_push_constants_intersect_rect (&op.constants.constants, constants, gsk_clip_node_peek_clip (node))) + FALLBACK ("Failed to find intersection between clip of type %u and rectangle\n", constants->clip.type); + if (&op.constants.constants.clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED) return; - gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, &new_clip, gsk_clip_node_get_child (node)); + op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS; + g_array_append_val (self->render_ops, op); + + gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, gsk_clip_node_get_child (node)); + + gsk_vulkan_push_constants_init_copy (&op.constants.constants, constants); + g_array_append_val (self->render_ops, op); } return; case GSK_ROUNDED_CLIP_NODE: { - GskVulkanClip new_clip; - - if (!gsk_vulkan_clip_intersect_rounded_rect (&new_clip, clip, gsk_rounded_clip_node_peek_clip (node))) - FALLBACK ("Failed to find intersection between clip of type %u and rounded rectangle\n", clip->type); - if (new_clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED) + if (!gsk_vulkan_push_constants_intersect_rounded (&op.constants.constants, + constants, + gsk_rounded_clip_node_peek_clip (node))) + FALLBACK ("Failed to find intersection between clip of type %u and rounded rectangle\n", constants->clip.type); + if (&op.constants.constants.clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED) return; - gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, &new_clip, gsk_rounded_clip_node_get_child (node)); + op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS; + g_array_append_val (self->render_ops, op); + + gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, gsk_rounded_clip_node_get_child (node)); + + gsk_vulkan_push_constants_init_copy (&op.constants.constants, constants); + g_array_append_val (self->render_ops, op); } return; } @@ -199,19 +208,19 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, return; fallback: - switch (clip->type) + switch (constants->clip.type) { case GSK_VULKAN_CLIP_NONE: op.type = GSK_VULKAN_OP_FALLBACK; break; case GSK_VULKAN_CLIP_RECT: op.type = GSK_VULKAN_OP_FALLBACK_CLIP; - gsk_rounded_rect_init_copy (&op.render.clip, &clip->rect); + gsk_rounded_rect_init_copy (&op.render.clip, &constants->clip.rect); break; case GSK_VULKAN_CLIP_ROUNDED_CIRCULAR: case GSK_VULKAN_CLIP_ROUNDED: op.type = GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP; - gsk_rounded_rect_init_copy (&op.render.clip, &clip->rect); + gsk_rounded_rect_init_copy (&op.render.clip, &constants->clip.rect); break; case GSK_VULKAN_CLIP_ALL_CLIPPED: default: @@ -231,15 +240,12 @@ gsk_vulkan_render_pass_add (GskVulkanRenderPass *self, GskRenderNode *node) { GskVulkanOp op = { 0, }; - GskVulkanClip clip; op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS; - gsk_vulkan_push_constants_init (&op.constants.constants, mvp); + gsk_vulkan_push_constants_init (&op.constants.constants, mvp, viewport); g_array_append_val (self->render_ops, op); - gsk_vulkan_clip_init_empty (&clip, viewport); - - gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, &clip, node); + gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, node); } static void diff --git a/gsk/resources/vulkan/blit.vert.glsl b/gsk/resources/vulkan/blit.vert.glsl index 2522b7e0ef..ca78688909 100644 --- a/gsk/resources/vulkan/blit.vert.glsl +++ b/gsk/resources/vulkan/blit.vert.glsl @@ -5,6 +5,9 @@ layout(location = 1) in vec2 inTexCoord; layout(push_constant) uniform PushConstants { mat4 mvp; + vec4 clip_bounds; + vec4 clip_widths; + vec4 clip_heights; } push; layout(location = 0) out vec2 outTexCoord; diff --git a/gsk/resources/vulkan/blit.vert.spv b/gsk/resources/vulkan/blit.vert.spv Binary files differindex 3deee1c8e2..5ce7a27f29 100644 --- a/gsk/resources/vulkan/blit.vert.spv +++ b/gsk/resources/vulkan/blit.vert.spv diff --git a/gsk/resources/vulkan/color.vert.glsl b/gsk/resources/vulkan/color.vert.glsl index 78bbfe1283..873ccfc949 100644 --- a/gsk/resources/vulkan/color.vert.glsl +++ b/gsk/resources/vulkan/color.vert.glsl @@ -5,6 +5,9 @@ layout(location = 1) in vec4 inColor; layout(push_constant) uniform PushConstants { mat4 mvp; + vec4 clip_bounds; + vec4 clip_widths; + vec4 clip_heights; } push; layout(location = 0) out vec4 outColor; diff --git a/gsk/resources/vulkan/color.vert.spv b/gsk/resources/vulkan/color.vert.spv Binary files differindex f4a8791bd7..0d571efc35 100644 --- a/gsk/resources/vulkan/color.vert.spv +++ b/gsk/resources/vulkan/color.vert.spv |