mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-09 10:20:07 +00:00
gpu: Implement transform support for dihedral transforms
This allows handling them without ever needing to offscreen for losing the clip, because the clip can always be transformed. Also, all the optimizations keep working, like occlusion culling, clears, and so on. The main benefit of this work is the ability for offloading to now handle dihedral transforms of the video buffer. The other big advantage is that we can now start our rendering with a dihedral transform from the compositor.
This commit is contained in:
parent
b9ecae84f5
commit
ae3efb2d2f
@ -59,3 +59,9 @@ gdk_dihedral_combine (GdkDihedral first,
|
|||||||
((((first & 3) * (((second & 4) >> 1) + 1)) + second) & 3);
|
((((first & 3) * (((second & 4) >> 1) + 1)) + second) & 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GdkDihedral
|
||||||
|
gdk_dihedral_invert (GdkDihedral self)
|
||||||
|
{
|
||||||
|
return ((4 - self) * (((self & 4) >> 1) + 1) & 3) | (self & 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ void gdk_dihedral_get_mat2 (GdkDihedral
|
|||||||
|
|
||||||
GdkDihedral gdk_dihedral_combine (GdkDihedral first,
|
GdkDihedral gdk_dihedral_combine (GdkDihedral first,
|
||||||
GdkDihedral second);
|
GdkDihedral second);
|
||||||
|
GdkDihedral gdk_dihedral_invert (GdkDihedral self);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -168,12 +168,15 @@ gsk_gpu_clip_intersect_rounded_rect (GskGpuClip *dest,
|
|||||||
void
|
void
|
||||||
gsk_gpu_clip_scale (GskGpuClip *dest,
|
gsk_gpu_clip_scale (GskGpuClip *dest,
|
||||||
const GskGpuClip *src,
|
const GskGpuClip *src,
|
||||||
|
GdkDihedral dihedral,
|
||||||
float scale_x,
|
float scale_x,
|
||||||
float scale_y)
|
float scale_y)
|
||||||
{
|
{
|
||||||
|
GskRoundedRect tmp;
|
||||||
dest->type = src->type;
|
dest->type = src->type;
|
||||||
|
gsk_rounded_rect_dihedral (&tmp, &src->rect, dihedral);
|
||||||
gsk_rounded_rect_scale_affine (&dest->rect,
|
gsk_rounded_rect_scale_affine (&dest->rect,
|
||||||
&src->rect,
|
&tmp,
|
||||||
1.0f / scale_x, 1.0f / scale_y,
|
1.0f / scale_x, 1.0f / scale_y,
|
||||||
0, 0);
|
0, 0);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include <graphene.h>
|
#include <graphene.h>
|
||||||
#include <gsk/gskroundedrect.h>
|
#include <gsk/gskroundedrect.h>
|
||||||
|
|
||||||
|
#include "gdk/gdkdihedralprivate.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -51,12 +53,13 @@ gboolean gsk_gpu_clip_intersect_rect (GskGpuC
|
|||||||
gboolean gsk_gpu_clip_intersect_rounded_rect (GskGpuClip *dest,
|
gboolean gsk_gpu_clip_intersect_rounded_rect (GskGpuClip *dest,
|
||||||
const GskGpuClip *src,
|
const GskGpuClip *src,
|
||||||
const GskRoundedRect *rounded) G_GNUC_WARN_UNUSED_RESULT;
|
const GskRoundedRect *rounded) G_GNUC_WARN_UNUSED_RESULT;
|
||||||
void gsk_gpu_clip_scale (GskGpuClip *dest,
|
void gsk_gpu_clip_scale (GskGpuClip *dest,
|
||||||
const GskGpuClip *src,
|
const GskGpuClip *src,
|
||||||
|
GdkDihedral dihedral,
|
||||||
float scale_x,
|
float scale_x,
|
||||||
float scale_y);
|
float scale_y);
|
||||||
gboolean gsk_gpu_clip_transform (GskGpuClip *dest,
|
gboolean gsk_gpu_clip_transform (GskGpuClip *dest,
|
||||||
const GskGpuClip *src,
|
const GskGpuClip *src,
|
||||||
GskTransform *transform,
|
GskTransform *transform,
|
||||||
const graphene_rect_t *viewport) G_GNUC_WARN_UNUSED_RESULT;
|
const graphene_rect_t *viewport) G_GNUC_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
@ -1165,6 +1165,22 @@ gsk_gpu_node_processor_add_first_rounded_clip_node (GskGpuNodeProcessor
|
|||||||
gsk_rounded_clip_node_get_child (node));
|
gsk_rounded_clip_node_get_child (node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GskTransform *
|
||||||
|
gsk_transform_dihedral (GskTransform *transform,
|
||||||
|
GdkDihedral dihedral)
|
||||||
|
{
|
||||||
|
int rotate = dihedral & 3;
|
||||||
|
int flip = dihedral & 4;
|
||||||
|
|
||||||
|
if (flip)
|
||||||
|
transform = gsk_transform_scale (transform, -1.0, 1.0);
|
||||||
|
|
||||||
|
if (rotate)
|
||||||
|
transform = gsk_transform_rotate (transform, rotate * 90.0f);
|
||||||
|
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
||||||
GskRenderNode *node)
|
GskRenderNode *node)
|
||||||
@ -1205,7 +1221,7 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
|||||||
old_modelview = gsk_transform_ref (self->modelview);
|
old_modelview = gsk_transform_ref (self->modelview);
|
||||||
|
|
||||||
gsk_transform_to_affine (transform, &scale_x, &scale_y, &dx, &dy);
|
gsk_transform_to_affine (transform, &scale_x, &scale_y, &dx, &dy);
|
||||||
gsk_gpu_clip_scale (&self->clip, &old_clip, scale_x, scale_y);
|
gsk_gpu_clip_scale (&self->clip, &old_clip, GDK_DIHEDRAL_NORMAL, scale_x, scale_y);
|
||||||
self->offset.x = (self->offset.x + dx) / scale_x;
|
self->offset.x = (self->offset.x + dx) / scale_x;
|
||||||
self->offset.y = (self->offset.y + dy) / scale_y;
|
self->offset.y = (self->offset.y + dy) / scale_y;
|
||||||
graphene_vec2_init (&self->scale, fabs (scale_x), fabs (scale_y));
|
graphene_vec2_init (&self->scale, fabs (scale_x), fabs (scale_y));
|
||||||
@ -1217,6 +1233,32 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GSK_FINE_TRANSFORM_CATEGORY_2D_DIHEDRAL:
|
case GSK_FINE_TRANSFORM_CATEGORY_2D_DIHEDRAL:
|
||||||
|
{
|
||||||
|
GdkDihedral dihedral, inverted;
|
||||||
|
float xx, xy, yx, yy, dx, dy, scale_x, scale_y, old_scale_x, old_scale_y;
|
||||||
|
|
||||||
|
gsk_gpu_clip_init_copy (&old_clip, &self->clip);
|
||||||
|
old_offset = self->offset;
|
||||||
|
old_scale = self->scale;
|
||||||
|
old_modelview = gsk_transform_ref (self->modelview);
|
||||||
|
|
||||||
|
gsk_transform_to_dihedral (transform, &dihedral, &scale_x, &scale_y, &dx, &dy);
|
||||||
|
inverted = gdk_dihedral_invert (dihedral);
|
||||||
|
gdk_dihedral_get_mat2 (inverted, &xx, &xy, &yx, &yy);
|
||||||
|
gsk_gpu_clip_scale (&self->clip, &old_clip, inverted, scale_x, scale_y);
|
||||||
|
self->offset.x = (self->offset.x + dx) / scale_x;
|
||||||
|
self->offset.y = (self->offset.y + dy) / scale_y;
|
||||||
|
self->offset = GRAPHENE_POINT_INIT (xx * self->offset.x + xy * self->offset.y,
|
||||||
|
yx * self->offset.x + yy * self->offset.y);
|
||||||
|
old_scale_x = graphene_vec2_get_x (&old_scale);
|
||||||
|
old_scale_y = graphene_vec2_get_y (&old_scale);
|
||||||
|
graphene_vec2_init (&self->scale,
|
||||||
|
fabs (scale_x * (old_scale_x * xx + old_scale_y * yx)),
|
||||||
|
fabs (scale_y * (old_scale_x * xy + old_scale_y * yy)));
|
||||||
|
self->modelview = gsk_transform_dihedral (self->modelview, dihedral);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case GSK_FINE_TRANSFORM_CATEGORY_2D:
|
case GSK_FINE_TRANSFORM_CATEGORY_2D:
|
||||||
case GSK_FINE_TRANSFORM_CATEGORY_UNKNOWN:
|
case GSK_FINE_TRANSFORM_CATEGORY_UNKNOWN:
|
||||||
case GSK_FINE_TRANSFORM_CATEGORY_ANY:
|
case GSK_FINE_TRANSFORM_CATEGORY_ANY:
|
||||||
@ -1350,7 +1392,7 @@ gsk_gpu_node_processor_add_first_transform_node (GskGpuNodeProcessor *se
|
|||||||
old_offset = self->offset;
|
old_offset = self->offset;
|
||||||
old_scale = self->scale;
|
old_scale = self->scale;
|
||||||
|
|
||||||
gsk_gpu_clip_scale (&self->clip, &old_clip, scale_x, scale_y);
|
gsk_gpu_clip_scale (&self->clip, &old_clip, GDK_DIHEDRAL_NORMAL, scale_x, scale_y);
|
||||||
self->offset.x = (self->offset.x + dx) / scale_x;
|
self->offset.x = (self->offset.x + dx) / scale_x;
|
||||||
self->offset.y = (self->offset.y + dy) / scale_y;
|
self->offset.y = (self->offset.y + dy) / scale_y;
|
||||||
graphene_vec2_init (&self->scale, fabs (scale_x), fabs (scale_y));
|
graphene_vec2_init (&self->scale, fabs (scale_x), fabs (scale_y));
|
||||||
|
@ -321,6 +321,34 @@ gsk_rounded_rect_scale_affine (GskRoundedRect *dest,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_rounded_rect_dihedral (GskRoundedRect *dest,
|
||||||
|
const GskRoundedRect *src,
|
||||||
|
GdkDihedral dihedral)
|
||||||
|
{
|
||||||
|
guint flip = (dihedral & 2) + (dihedral >> 2);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
gsk_rect_dihedral (&src->bounds, dihedral, &dest->bounds);
|
||||||
|
|
||||||
|
if (dihedral & 1)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
dest->corner[i].width = src->corner[((i + 1) & 3) ^ flip].width;
|
||||||
|
dest->corner[i].height = src->corner[((i + 1) & 3) ^ flip].height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
dest->corner[i].width = src->corner[i ^ flip].height;
|
||||||
|
dest->corner[i].height = src->corner[i ^ flip].width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*<private>
|
/*<private>
|
||||||
* gsk_rounded_rect_is_circular:
|
* gsk_rounded_rect_is_circular:
|
||||||
* @self: the `GskRoundedRect` to check
|
* @self: the `GskRoundedRect` to check
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "gskroundedrect.h"
|
#include "gskroundedrect.h"
|
||||||
|
|
||||||
|
#include "gdk/gdkdihedralprivate.h"
|
||||||
|
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
@ -34,12 +36,15 @@ G_STATIC_ASSERT (OPPOSITE_CORNER_Y (GSK_CORNER_BOTTOM_RIGHT) == GSK_CORNER_TOP_R
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
||||||
void gsk_rounded_rect_scale_affine (GskRoundedRect *dest,
|
void gsk_rounded_rect_scale_affine (GskRoundedRect *dest,
|
||||||
const GskRoundedRect *src,
|
const GskRoundedRect *src,
|
||||||
float scale_x,
|
float scale_x,
|
||||||
float scale_y,
|
float scale_y,
|
||||||
float dx,
|
float dx,
|
||||||
float dy);
|
float dy);
|
||||||
|
void gsk_rounded_rect_dihedral (GskRoundedRect *dest,
|
||||||
|
const GskRoundedRect *src,
|
||||||
|
GdkDihedral dihedral);
|
||||||
|
|
||||||
gboolean gsk_rounded_rect_is_circular (const GskRoundedRect *self) G_GNUC_PURE;
|
gboolean gsk_rounded_rect_is_circular (const GskRoundedRect *self) G_GNUC_PURE;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user