From 91932ada63badf16dc86706be17fe720824dc195 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Fri, 5 Mar 2021 19:35:04 -0500 Subject: [PATCH] vulkan: Handle simple transforms in the clipping code Requires pushing the GskTransform into the clipping code so that we can actually look at its category. --- gsk/vulkan/gskvulkanclip.c | 61 +++++++++++++++++++--- gsk/vulkan/gskvulkanclipprivate.h | 2 +- gsk/vulkan/gskvulkanpushconstants.c | 9 +++- gsk/vulkan/gskvulkanpushconstantsprivate.h | 2 +- gsk/vulkan/gskvulkanrenderpass.c | 2 +- 5 files changed, 65 insertions(+), 11 deletions(-) diff --git a/gsk/vulkan/gskvulkanclip.c b/gsk/vulkan/gskvulkanclip.c index 83e3b63867..28efc76702 100644 --- a/gsk/vulkan/gskvulkanclip.c +++ b/gsk/vulkan/gskvulkanclip.c @@ -3,6 +3,7 @@ #include "gskvulkanclipprivate.h" #include "gskroundedrectprivate.h" +#include "gsktransform.h" void gsk_vulkan_clip_init_empty (GskVulkanClip *clip, @@ -137,10 +138,10 @@ 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) +gsk_vulkan_clip_transform (GskVulkanClip *dest, + const GskVulkanClip *src, + GskTransform *transform, + const graphene_rect_t *viewport) { switch (src->type) { @@ -159,8 +160,56 @@ gsk_vulkan_clip_transform (GskVulkanClip *dest, 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; + switch (gsk_transform_get_category (transform)) + { + case GSK_TRANSFORM_CATEGORY_IDENTITY: + gsk_vulkan_clip_init_copy (dest, src); + return TRUE; + + case GSK_TRANSFORM_CATEGORY_2D_TRANSLATE: + { + float dx, dy; + + gsk_transform_to_translate (transform, &dx, &dy); + gsk_vulkan_clip_init_copy (dest, src); + dest->rect.bounds.origin.x -= dx; + dest->rect.bounds.origin.y -= dy; + } + return TRUE; + + case GSK_TRANSFORM_CATEGORY_2D_AFFINE: + { + float dx, dy, scale_x, scale_y; + + gsk_transform_to_affine (transform, &scale_x, &scale_y, &dx, &dy); + scale_x = 1. / scale_x; + scale_y = 1. / scale_y; + gsk_vulkan_clip_init_copy (dest, src); + dest->rect.bounds.origin.x = (dest->rect.bounds.origin.x - dx) * scale_x; + dest->rect.bounds.origin.y = (dest->rect.bounds.origin.y - dy) * scale_y; + dest->rect.bounds.size.width *= scale_x; + dest->rect.bounds.size.height *= scale_y; + if (src->type != GSK_VULKAN_CLIP_RECT) + { + dest->rect.corner[0].width *= scale_x; + dest->rect.corner[0].height *= scale_y; + dest->rect.corner[1].width *= scale_x; + dest->rect.corner[1].height *= scale_y; + dest->rect.corner[2].width *= scale_x; + dest->rect.corner[2].height *= scale_y; + dest->rect.corner[3].width *= scale_x; + dest->rect.corner[3].height *= scale_y; + } + } + return TRUE; + + case GSK_TRANSFORM_CATEGORY_UNKNOWN: + case GSK_TRANSFORM_CATEGORY_ANY: + case GSK_TRANSFORM_CATEGORY_3D: + case GSK_TRANSFORM_CATEGORY_2D: + default: + return FALSE; + } } } diff --git a/gsk/vulkan/gskvulkanclipprivate.h b/gsk/vulkan/gskvulkanclipprivate.h index 10b89edcba..ebae166c14 100644 --- a/gsk/vulkan/gskvulkanclipprivate.h +++ b/gsk/vulkan/gskvulkanclipprivate.h @@ -46,7 +46,7 @@ gboolean gsk_vulkan_clip_intersect_rounded_rect (GskVulk const GskRoundedRect *rounded) G_GNUC_WARN_UNUSED_RESULT; gboolean gsk_vulkan_clip_transform (GskVulkanClip *dest, const GskVulkanClip *src, - const graphene_matrix_t*transform, + GskTransform *transform, const graphene_rect_t *viewport) G_GNUC_WARN_UNUSED_RESULT; gboolean gsk_vulkan_clip_contains_rect (const GskVulkanClip *self, diff --git a/gsk/vulkan/gskvulkanpushconstants.c b/gsk/vulkan/gskvulkanpushconstants.c index dc4ae404b9..e2bf63326b 100644 --- a/gsk/vulkan/gskvulkanpushconstants.c +++ b/gsk/vulkan/gskvulkanpushconstants.c @@ -3,6 +3,7 @@ #include "gskvulkanpushconstantsprivate.h" #include "gskroundedrectprivate.h" +#include "gsktransform.h" typedef struct _GskVulkanPushConstantsWire GskVulkanPushConstantsWire; @@ -33,14 +34,18 @@ gsk_vulkan_push_constants_init_copy (GskVulkanPushConstants *self, gboolean gsk_vulkan_push_constants_transform (GskVulkanPushConstants *self, const GskVulkanPushConstants *src, - const graphene_matrix_t *transform, + GskTransform *transform, const graphene_rect_t *viewport) { + graphene_matrix_t matrix; + if (!gsk_vulkan_clip_transform (&self->clip, &src->clip, transform, viewport)) return FALSE; - graphene_matrix_multiply (transform, &src->mvp, &self->mvp); + gsk_transform_to_matrix (transform, &matrix); + graphene_matrix_multiply (&matrix, &src->mvp, &self->mvp); + return TRUE; } diff --git a/gsk/vulkan/gskvulkanpushconstantsprivate.h b/gsk/vulkan/gskvulkanpushconstantsprivate.h index 897d9c61fc..4f6db24c5f 100644 --- a/gsk/vulkan/gskvulkanpushconstantsprivate.h +++ b/gsk/vulkan/gskvulkanpushconstantsprivate.h @@ -27,7 +27,7 @@ void gsk_vulkan_push_constants_init_copy (GskVulk gboolean gsk_vulkan_push_constants_transform (GskVulkanPushConstants *self, const GskVulkanPushConstants *src, - const graphene_matrix_t *transform, + GskTransform *transform, const graphene_rect_t *viewport); gboolean gsk_vulkan_push_constants_intersect_rect (GskVulkanPushConstants *self, const GskVulkanPushConstants *src, diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index a549e95cea..a6b427a632 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -558,7 +558,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, gsk_transform_to_matrix (gsk_transform_node_get_transform (node), &transform); graphene_matrix_init_from_matrix (&mv, &self->mv); graphene_matrix_multiply (&transform, &mv, &self->mv); - if (!gsk_vulkan_push_constants_transform (&op.constants.constants, constants, &transform, &child->bounds)) + if (!gsk_vulkan_push_constants_transform (&op.constants.constants, constants, gsk_transform_node_get_transform (node), &child->bounds)) FALLBACK ("Transform nodes can't deal with clip type %u", constants->clip.type); op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS; g_array_append_val (self->render_ops, op);