summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2016-12-24 04:58:51 +0100
committerBenjamin Otte <otte@redhat.com>2016-12-24 06:19:16 +0100
commit81c487b8415fed4990b069b03245b2aa11f12ab7 (patch)
tree2ab48d9138ac457a6e1cc6e04c4cf55d568d9c6d
parent18b65a23789008a68c53e0430aa2dffadcc259f4 (diff)
downloadgtk+-81c487b8415fed4990b069b03245b2aa11f12ab7.tar.gz
vulkan: Fold clip into push constants
As a side effect, the clipping data is now available inside shaders. Not that any shader would use them yet, but they could!
-rw-r--r--gsk/gskroundedrect.c30
-rw-r--r--gsk/gskroundedrectprivate.h2
-rw-r--r--gsk/gskvulkanclip.c28
-rw-r--r--gsk/gskvulkanclipprivate.h4
-rw-r--r--gsk/gskvulkanpushconstants.c44
-rw-r--r--gsk/gskvulkanpushconstantsprivate.h18
-rw-r--r--gsk/gskvulkanrenderpass.c76
-rw-r--r--gsk/resources/vulkan/blit.vert.glsl3
-rw-r--r--gsk/resources/vulkan/blit.vert.spvbin1104 -> 1252 bytes
-rw-r--r--gsk/resources/vulkan/color.vert.glsl3
-rw-r--r--gsk/resources/vulkan/color.vert.spvbin1632 -> 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
index 3deee1c8e2..5ce7a27f29 100644
--- a/gsk/resources/vulkan/blit.vert.spv
+++ b/gsk/resources/vulkan/blit.vert.spv
Binary files differ
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
index f4a8791bd7..0d571efc35 100644
--- a/gsk/resources/vulkan/color.vert.spv
+++ b/gsk/resources/vulkan/color.vert.spv
Binary files differ