forked from AuroraMiddleware/gtk
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!
This commit is contained in:
parent
18b65a2378
commit
81c487b841
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -127,6 +127,34 @@ gsk_vulkan_clip_intersect_rounded_rect (GskVulkanClip *dest,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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_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 GskRoundedRect *rect);
|
||||
|
||||
void gsk_vulkan_push_constants_push_vertex (const GskVulkanPushConstants *self,
|
||||
VkCommandBuffer command_buffer,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Binary file not shown.
@ -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;
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user