forked from AuroraMiddleware/gtk
81c487b841
As a side effect, the clipping data is now available inside shaders. Not that any shader would use them yet, but they could!
180 lines
5.0 KiB
C
180 lines
5.0 KiB
C
#include "config.h"
|
|
|
|
#include "gskvulkanclipprivate.h"
|
|
|
|
#include "gskroundedrectprivate.h"
|
|
|
|
void
|
|
gsk_vulkan_clip_init_empty (GskVulkanClip *clip,
|
|
const graphene_rect_t *rect)
|
|
{
|
|
clip->type = GSK_VULKAN_CLIP_NONE;
|
|
gsk_rounded_rect_init_from_rect (&clip->rect, rect, 0);
|
|
}
|
|
|
|
static void
|
|
gsk_vulkan_clip_init_copy (GskVulkanClip *self,
|
|
const GskVulkanClip *src)
|
|
{
|
|
self->type = src->type;
|
|
gsk_rounded_rect_init_copy (&self->rect, &src->rect);
|
|
}
|
|
|
|
gboolean
|
|
gsk_vulkan_clip_intersect_rect (GskVulkanClip *dest,
|
|
const GskVulkanClip *src,
|
|
const graphene_rect_t *rect)
|
|
{
|
|
if (graphene_rect_contains_rect (rect, &src->rect.bounds))
|
|
{
|
|
gsk_vulkan_clip_init_copy (dest, src);
|
|
return TRUE;
|
|
}
|
|
if (!graphene_rect_intersection (rect, &src->rect.bounds, NULL))
|
|
{
|
|
dest->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
|
|
return TRUE;
|
|
}
|
|
|
|
switch (src->type)
|
|
{
|
|
case GSK_VULKAN_CLIP_ALL_CLIPPED:
|
|
dest->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
|
|
break;
|
|
|
|
case GSK_VULKAN_CLIP_NONE:
|
|
gsk_vulkan_clip_init_copy (dest, src);
|
|
if (graphene_rect_intersection (&dest->rect.bounds, rect, &dest->rect.bounds))
|
|
dest->type = GSK_VULKAN_CLIP_RECT;
|
|
else
|
|
dest->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
|
|
break;
|
|
|
|
case GSK_VULKAN_CLIP_RECT:
|
|
gsk_vulkan_clip_init_copy (dest, src);
|
|
if (!graphene_rect_intersection (&dest->rect.bounds, rect, &dest->rect.bounds))
|
|
dest->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
|
|
break;
|
|
|
|
case GSK_VULKAN_CLIP_ROUNDED_CIRCULAR:
|
|
case GSK_VULKAN_CLIP_ROUNDED:
|
|
if (gsk_rounded_rect_contains_rect (&src->rect, rect))
|
|
{
|
|
dest->type = GSK_VULKAN_CLIP_RECT;
|
|
gsk_rounded_rect_init_from_rect (&dest->rect, rect, 0);
|
|
}
|
|
else
|
|
{
|
|
/* some points of rect are inside src's rounded rect,
|
|
* some are outside. */
|
|
/* XXX: If the 2 rects don't intersect on rounded corners,
|
|
* we could actually compute a new clip here.
|
|
*/
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
gsk_vulkan_clip_intersect_rounded_rect (GskVulkanClip *dest,
|
|
const GskVulkanClip *src,
|
|
const GskRoundedRect *rounded)
|
|
{
|
|
if (gsk_rounded_rect_contains_rect (rounded, &src->rect.bounds))
|
|
{
|
|
gsk_vulkan_clip_init_copy (dest, src);
|
|
return TRUE;
|
|
}
|
|
if (!graphene_rect_intersection (&rounded->bounds, &src->rect.bounds, NULL))
|
|
{
|
|
dest->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
|
|
return TRUE;
|
|
}
|
|
|
|
switch (src->type)
|
|
{
|
|
case GSK_VULKAN_CLIP_ALL_CLIPPED:
|
|
dest->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
|
|
break;
|
|
|
|
case GSK_VULKAN_CLIP_NONE:
|
|
dest->type = gsk_rounded_rect_is_circular (&dest->rect) ? GSK_VULKAN_CLIP_ROUNDED_CIRCULAR : GSK_VULKAN_CLIP_ROUNDED;
|
|
gsk_rounded_rect_init_copy (&dest->rect, rounded);
|
|
break;
|
|
|
|
case GSK_VULKAN_CLIP_RECT:
|
|
if (graphene_rect_contains_rect (&src->rect.bounds, &rounded->bounds))
|
|
{
|
|
dest->type = gsk_rounded_rect_is_circular (&dest->rect) ? GSK_VULKAN_CLIP_ROUNDED_CIRCULAR : GSK_VULKAN_CLIP_ROUNDED;
|
|
gsk_rounded_rect_init_copy (&dest->rect, rounded);
|
|
return TRUE;
|
|
}
|
|
/* some points of rect are inside src's rounded rect,
|
|
* some are outside. */
|
|
/* XXX: If the 2 rects don't intersect on rounded corners,
|
|
* we could actually compute a new clip here.
|
|
*/
|
|
return FALSE;
|
|
|
|
case GSK_VULKAN_CLIP_ROUNDED_CIRCULAR:
|
|
case GSK_VULKAN_CLIP_ROUNDED:
|
|
/* XXX: improve */
|
|
return FALSE;
|
|
}
|
|
|
|
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)
|
|
{
|
|
switch (self->type)
|
|
{
|
|
default:
|
|
g_assert_not_reached();
|
|
case GSK_VULKAN_CLIP_ALL_CLIPPED:
|
|
return FALSE;
|
|
|
|
case GSK_VULKAN_CLIP_NONE:
|
|
return TRUE;
|
|
|
|
case GSK_VULKAN_CLIP_RECT:
|
|
return graphene_rect_contains_rect (&self->rect.bounds, rect);
|
|
|
|
case GSK_VULKAN_CLIP_ROUNDED_CIRCULAR:
|
|
case GSK_VULKAN_CLIP_ROUNDED:
|
|
return gsk_rounded_rect_contains_rect (&self->rect, rect);
|
|
}
|
|
}
|