vulkan: Split scale from matrix
authorBenjamin Otte <otte@redhat.com>
Fri, 12 May 2023 03:15:28 +0000 (05:15 +0200)
committerBenjamin Otte <otte@redhat.com>
Sun, 4 Jun 2023 17:42:01 +0000 (19:42 +0200)
Now, the scale is no longer part of the matrix. This allows shaders to
transform points by the scale which increases accuracy for antialiasing.

14 files changed:
gsk/vulkan/gskvulkanclip.c
gsk/vulkan/gskvulkanclipprivate.h
gsk/vulkan/gskvulkanrenderpass.c
gsk/vulkan/resources/blendmode.vert
gsk/vulkan/resources/blur.vert
gsk/vulkan/resources/border.vert
gsk/vulkan/resources/color-matrix.vert
gsk/vulkan/resources/color.vert
gsk/vulkan/resources/crossfade.vert
gsk/vulkan/resources/inset-shadow.vert
gsk/vulkan/resources/linear.vert
gsk/vulkan/resources/mask.vert
gsk/vulkan/resources/outset-shadow.vert
gsk/vulkan/resources/texture.vert

index 2dba6ebef0f32c3e5661d04882faff244a3b4c54..55271a0f8b355ccdd3f46ffab520816fdd69ac19 100644 (file)
@@ -143,6 +143,19 @@ gsk_vulkan_clip_intersect_rounded_rect (GskVulkanClip        *dest,
   return TRUE;
 }
 
+void
+gsk_vulkan_clip_scale (GskVulkanClip       *dest,
+                       const GskVulkanClip *src,
+                       float                scale_x,
+                       float                scale_y)
+{
+  dest->type = src->type;
+  gsk_rounded_rect_scale_affine (&dest->rect, 
+                                 &src->rect,
+                                 1.0f / scale_x, 1.0f / scale_y,
+                                 0, 0);
+}
+
 gboolean
 gsk_vulkan_clip_transform (GskVulkanClip         *dest,
                            const GskVulkanClip   *src,
index 6b90d78c73fffec75bb5b78110d3bc82075e7f97..7220b732bab7618ddea21f46265f95a577ab6ba3 100644 (file)
@@ -43,6 +43,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;
+void                    gsk_vulkan_clip_scale                           (GskVulkanClip          *dest,
+                                                                         const GskVulkanClip    *src,
+                                                                         float                   scale_x,
+                                                                         float                   scale_y);
 gboolean                gsk_vulkan_clip_transform                       (GskVulkanClip          *dest,
                                                                          const GskVulkanClip    *src,
                                                                          GskTransform           *transform,
index 9f26163793e30a262f4e8368afecd194867096dc..e20643eb43259570fac4f153bddcf4c24b5ff154 100644 (file)
@@ -538,9 +538,6 @@ gsk_vulkan_render_pass_add_transform_node (GskVulkanRenderPass       *self,
 {
   GskRenderNode *child;
   GskTransform *transform;
-  float scale_x;
-  float scale_y;
-  graphene_vec2_t scale;
   GskVulkanParseState new_state;
 
 #if 0
@@ -567,20 +564,47 @@ gsk_vulkan_render_pass_add_transform_node (GskVulkanRenderPass       *self,
 
     case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
       {
-        float dx, dy;
+        float dx, dy, scale_x, scale_y;
         gsk_transform_to_affine (transform, &scale_x, &scale_y, &dx, &dy);
+        gsk_vulkan_clip_scale (&new_state.clip, &state->clip, scale_x, scale_y);
+        new_state.offset.x = (state->offset.x + dx) / scale_x;
+        new_state.offset.y = (state->offset.y + dy) / scale_y;
+        graphene_vec2_init (&new_state.scale, scale_x, scale_y);
+        graphene_vec2_multiply (&new_state.scale, &state->scale, &new_state.scale);
+        new_state.modelview = gsk_transform_ref (state->modelview);
       }
       break;
 
     case GSK_TRANSFORM_CATEGORY_2D:
       {
-        float xx, xy, yx, yy, dx, dy;
+        float skew_x, skew_y, scale_x, scale_y, angle, dx, dy;
+        GskTransform *clip_transform;
 
-        gsk_transform_to_2d (transform,
-                             &xx, &xy, &yx, &yy, &dx, &dy);
+        clip_transform = gsk_transform_transform (gsk_transform_translate (NULL, &state->offset), transform);
+
+        if (!gsk_vulkan_clip_transform (&new_state.clip, &state->clip, clip_transform, &child->bounds))
+          {
+            gsk_transform_unref (clip_transform);
+            FALLBACK ("Transform nodes can't deal with clip type %u", state->clip.type);
+          }
 
-        scale_x = sqrtf (xx * xx + xy * xy);
-        scale_y = sqrtf (yx * yx + yy * yy);
+        new_state.modelview = gsk_transform_ref (state->modelview);
+        new_state.modelview = gsk_transform_scale (state->modelview,
+                                                   graphene_vec2_get_x (&state->scale),
+                                                   graphene_vec2_get_y (&state->scale));
+        new_state.modelview = gsk_transform_transform (new_state.modelview, clip_transform);
+        gsk_transform_unref (clip_transform);
+
+        gsk_transform_to_2d_components (new_state.modelview,
+                                        &skew_x, &skew_y,
+                                        &scale_x, &scale_y,
+                                        &angle,
+                                        &dx, &dy);
+        scale_x = fabs (scale_x);
+        scale_y = fabs (scale_y);
+        new_state.modelview = gsk_transform_scale (new_state.modelview, 1 / scale_x, 1 / scale_y);
+        graphene_vec2_init (&new_state.scale, scale_x, scale_y);
+        new_state.offset = *graphene_point_zero ();
       }
       break;
 
@@ -594,8 +618,25 @@ gsk_vulkan_render_pass_add_transform_node (GskVulkanRenderPass       *self,
         graphene_vec3_t translation;
         graphene_vec3_t matrix_scale;
         graphene_vec3_t shear;
+        GskTransform *clip_transform;
+        float scale_x, scale_y;
+
+        clip_transform = gsk_transform_transform (gsk_transform_translate (NULL, &state->offset), transform);
+
+        if (!gsk_vulkan_clip_transform (&new_state.clip, &state->clip, clip_transform, &child->bounds))
+          {
+            gsk_transform_unref (clip_transform);
+            FALLBACK ("Transform nodes can't deal with clip type %u", state->clip.type);
+          }
+
+        new_state.modelview = gsk_transform_ref (state->modelview);
+        new_state.modelview = gsk_transform_scale (state->modelview,
+                                                   graphene_vec2_get_x (&state->scale),
+                                                   graphene_vec2_get_y (&state->scale));                                                  
+        new_state.modelview = gsk_transform_transform (new_state.modelview, clip_transform);
+        gsk_transform_unref (clip_transform);
 
-        gsk_transform_to_matrix (transform, &matrix);
+        gsk_transform_to_matrix (new_state.modelview, &matrix);
         graphene_matrix_decompose (&matrix,
                                    &translation,
                                    &matrix_scale,
@@ -603,8 +644,11 @@ gsk_vulkan_render_pass_add_transform_node (GskVulkanRenderPass       *self,
                                    &shear,
                                    &perspective);
 
-        scale_x = graphene_vec3_get_x (&matrix_scale);
-        scale_y = graphene_vec3_get_y (&matrix_scale);
+        scale_x = fabs (graphene_vec3_get_x (&matrix_scale));
+        scale_y = fabs (graphene_vec3_get_y (&matrix_scale));
+        new_state.modelview = gsk_transform_scale (new_state.modelview, 1 / scale_x, 1 / scale_y);
+        graphene_vec2_init (&new_state.scale, scale_x, scale_y);
+        new_state.offset = *graphene_point_zero ();
       }
       break;
 
@@ -612,24 +656,10 @@ gsk_vulkan_render_pass_add_transform_node (GskVulkanRenderPass       *self,
       break;
     }
 
-  new_state.modelview = gsk_transform_ref (state->modelview);
-  new_state.modelview = gsk_transform_translate (new_state.modelview, &state->offset);
-  new_state.modelview = gsk_transform_transform (new_state.modelview, transform);
-
-  if (!gsk_vulkan_clip_transform (&new_state.clip, &state->clip, transform, &child->bounds))
-    {
-      gsk_transform_unref (new_state.modelview);
-      FALLBACK ("Transform nodes can't deal with clip type %u", state->clip.type);
-    }
-
   graphene_matrix_init_from_matrix (&new_state.projection, &state->projection);
 
   gsk_vulkan_render_pass_append_push_constants (self, node, &new_state);
 
-  new_state.offset = *graphene_point_zero ();
-  graphene_vec2_init (&scale, fabs (scale_x), fabs (scale_y));
-  graphene_vec2_multiply (&state->scale, &scale, &new_state.scale);
-
   gsk_vulkan_render_pass_add_node (self, render, &new_state, child);
 
   gsk_vulkan_render_pass_append_push_constants (self, node, state);
@@ -1056,9 +1086,7 @@ gsk_vulkan_render_pass_add (GskVulkanRenderPass     *self,
 {
   GskVulkanParseState state;
 
-  state.modelview = gsk_transform_scale (NULL,
-                                         graphene_vec2_get_x (&self->scale),
-                                         graphene_vec2_get_y (&self->scale));
+  state.modelview = NULL;
   graphene_matrix_init_ortho (&state.projection,
                               self->viewport.origin.x, self->viewport.origin.x + self->viewport.size.width,
                               self->viewport.origin.y, self->viewport.origin.y + self->viewport.size.height,
@@ -1071,8 +1099,6 @@ gsk_vulkan_render_pass_add (GskVulkanRenderPass     *self,
   gsk_vulkan_render_pass_append_push_constants (self, node, &state);
 
   gsk_vulkan_render_pass_add_node (self, render, &state, node);
-
-  gsk_transform_unref (state.modelview);
 }
 
 static GskVulkanImage *
index 6670475ed8a9731f5e8336a223668c78e6874c37..b4c890302a43e3a53d27162f00d6d0bdf41d2508 100644 (file)
@@ -22,7 +22,7 @@ vec2 offsets[6] = { vec2(0.0, 0.0),
 void main() {
   vec4 rect = clip (inRect);
   vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
-  gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+  gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
 
   outPos = pos;
 
index 10dccf7b7f07d402179fb35a11fa0bc651d4e6c3..7ba604685236729cf4fe7d174d9ba8f689a54258 100644 (file)
@@ -22,7 +22,7 @@ vec2 offsets[6] = { vec2(0.0, 0.0),
 void main() {
   vec4 rect = clip (inRect);
   vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
-  gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+  gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
 
   outPos = pos;
   outSize = inRect.zw;
index d0f328a2e1482019f66041fe32ebaf5ac32b52d7..56dfd1292d6b609426fd364fc62a3051a1f7a82a 100644 (file)
@@ -97,7 +97,7 @@ void main() {
     pos = mix (rect.bounds.xy, rect.bounds.zw, offsets[vert_index]);
   else
     pos = mix (rect.bounds.zy, rect.bounds.xw, offsets[vert_index]);
-  gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+  gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
   outColor = inBorderColors[((gl_VertexIndex / 3 + 15) / 4) % 4];
   outPos = pos;
   outRect = inRect;
index f264d10cdeeae827a401ba5973d59817e260ca5e..99487c9063d5fb6782bc28708c9e8defc117fb0c 100644 (file)
@@ -22,7 +22,7 @@ vec2 offsets[6] = { vec2(0.0, 0.0),
 void main() {
   vec4 rect = clip (inRect);
   vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
-  gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+  gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
 
   outPos = pos;
 
index cc2a853b5c3f1b928f67267164a1673d23a8d35f..6a09ff5f990aa20678a88dec0f225e70a0656ebe 100644 (file)
@@ -21,7 +21,7 @@ void main() {
   Rect rect = rect_round_larger (clip_rect (rect_from_gsk (inRect)));
 
   vec2 pos = mix (rect.bounds.xy, rect.bounds.zw, offsets[gl_VertexIndex]);
-  gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+  gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
   outPos = pos;
   outRect = rect_from_gsk (inRect);
   outColor = inColor;
index 837f0084eea30c6702fb12dc6e3715de2b90107c..eb7a00767a599232387343e6f672e6f8d71754c2 100644 (file)
@@ -22,7 +22,7 @@ vec2 offsets[6] = { vec2(0.0, 0.0),
 void main() {
   vec4 rect = clip (inRect);
   vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
-  gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+  gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
 
   outPos = pos;
 
index 5fd8623529a3e876f809f588e3befd2837b96b1f..13fa8d669f1bc8169d96ca9bda7dcf3bb896603d 100644 (file)
@@ -29,7 +29,7 @@ void main() {
   vec4 rect = clip (inOutline);
 
   vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
-  gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+  gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
   outPos = pos;
 
   outOutline = inOutline;
index 7453c0d884f1660baad5dd036f20cce13755a65a..3d14b876f65d72526e92fe922605e0aeb496b6ba 100644 (file)
@@ -48,7 +48,7 @@ get_gradient_pos (vec2 pos)
 void main() {
   vec4 rect = clip (inRect);
   vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
-  gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+  gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
   outPos = pos;
   outGradientPos = get_gradient_pos (pos);
   outRepeating = inRepeating;
index 03f0329278afb3a398613cc3ade218e8849a72f7..1406bfd1d1ad8fd04012c43cadcf6a3e37b0402e 100644 (file)
@@ -20,7 +20,7 @@ vec2 offsets[6] = { vec2(0.0, 0.0),
 void main() {
   vec4 rect = clip (inRect);
   vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
-  gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+  gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
 
   outPos = pos;
 
index 6fdaf1717125c61a91e30a27a045d33bd99169ca..18ec6f27740f0482963791e2f0a11bb399c75881 100644 (file)
@@ -38,7 +38,7 @@ void main() {
   clip (inOutline);
 
   vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
-  gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+  gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
   outPos = pos;
 
   outOutline = inOutline;
index e1e08bc21abd91141883f1c5a5a133fafc28cbec..443d6ecae9453f51eeefea1c478b743902c7ea9a 100644 (file)
@@ -18,7 +18,7 @@ vec2 offsets[6] = { vec2(0.0, 0.0),
 void main() {
   vec4 rect = clip (inRect);
   vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
-  gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+  gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
 
   outPos = pos;