gsk: Introduce GskScale

Use a separate type for a 2d scale that the compiler won't confuse
with graphene_point_t. We can also move some of the generic scale/
transform code form gskgpunodeprocessor.c here.
This commit is contained in:
Matthias Clasen
2024-01-20 23:51:27 -05:00
parent 2ede31b682
commit 501095452a
12 changed files with 357 additions and 208 deletions

View File

@@ -89,7 +89,7 @@ static const GskGpuOpClass GSK_GPU_GLOBALS_OP_CLASS = {
void
gsk_gpu_globals_op (GskGpuFrame *frame,
const graphene_point_t *scale,
const GskScale *scale,
const graphene_matrix_t *mvp,
const GskRoundedRect *clip)
{
@@ -99,5 +99,5 @@ gsk_gpu_globals_op (GskGpuFrame *frame,
graphene_matrix_to_float (mvp, self->instance.mvp);
gsk_rounded_rect_to_float (clip, graphene_point_zero (), self->instance.clip);
gsk_point_to_float (scale, self->instance.scale);
gsk_scale_to_float (scale, self->instance.scale);
}

View File

@@ -3,6 +3,7 @@
#include "gskgpuopprivate.h"
#include <gsk/gskroundedrect.h>
#include "gsk/gskscaleprivate.h"
#include <graphene.h>
G_BEGIN_DECLS
@@ -17,7 +18,7 @@ struct _GskGpuGlobalsInstance
};
void gsk_gpu_globals_op (GskGpuFrame *frame,
const graphene_point_t *scale,
const GskScale *scale,
const graphene_matrix_t *mvp,
const GskRoundedRect *clip);

View File

@@ -40,6 +40,7 @@
#include "gskroundedrectprivate.h"
#include "gskstrokeprivate.h"
#include "gsktransformprivate.h"
#include "gskscaleprivate.h"
#include "gdk/gdkrgbaprivate.h"
@@ -107,7 +108,7 @@ struct _GskGpuNodeProcessor
GskGpuClip clip;
GskGpuBlend blend;
graphene_point_t offset;
graphene_point_t scale;
GskScale scale;
GskTransform *modelview;
graphene_matrix_t projection;
float opacity;
@@ -130,7 +131,7 @@ struct _GskGpuPatternWriter
graphene_rect_t bounds;
graphene_point_t offset;
graphene_point_t scale;
GskScale scale;
guint stack;
PatternBuffer buffer;
@@ -175,23 +176,20 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self,
}
else
{
float scale_x = viewport->size.width / width;
float scale_y = viewport->size.height / height;
gsk_gpu_clip_init_rect (&self->clip,
&GRAPHENE_RECT_INIT (
scale_x * clip->x,
scale_y * clip->y,
scale_x * clip->width,
scale_y * clip->height
));
graphene_rect_t rect;
rect = gsk_rect_scale (GRAPHENE_RECT_INIT (clip->x, clip->y, clip->width, clip->height),
gsk_scale_init (viewport->size.width / width,
viewport->size.height / height));
gsk_gpu_clip_init_rect (&self->clip, &rect);
}
self->modelview = NULL;
gsk_gpu_image_get_projection_matrix (target, &self->projection);
self->scale = GRAPHENE_POINT_INIT (width / viewport->size.width,
height / viewport->size.height);
self->offset = GRAPHENE_POINT_INIT (-viewport->origin.x,
-viewport->origin.y);
self->scale = gsk_scale_init (width / viewport->size.width,
height / viewport->size.height);
self->offset = gsk_point_init (-viewport->origin.x,
-viewport->origin.y);
self->opacity = 1.0;
self->pending_globals = GSK_GPU_GLOBAL_MATRIX | GSK_GPU_GLOBAL_SCALE | GSK_GPU_GLOBAL_CLIP | GSK_GPU_GLOBAL_SCISSOR | GSK_GPU_GLOBAL_BLEND;
}
@@ -303,33 +301,11 @@ gsk_gpu_node_processor_add_images (GskGpuNodeProcessor *self,
while (desc != self->desc);
}
static void
rect_round_to_pixels (const graphene_rect_t *src,
const graphene_point_t *pixel_scale,
const graphene_point_t *pixel_offset,
graphene_rect_t *dest)
{
float x, y, xscale, yscale, inv_xscale, inv_yscale;
xscale = pixel_scale->x;
yscale = pixel_scale->y;
inv_xscale = 1.0f / xscale;
inv_yscale = 1.0f / yscale;
x = floorf ((src->origin.x + pixel_offset->x) * xscale);
y = floorf ((src->origin.y + pixel_offset->y) * yscale);
*dest = GRAPHENE_RECT_INIT (
x * inv_xscale - pixel_offset->x,
y * inv_yscale - pixel_offset->y,
(ceilf ((src->origin.x + pixel_offset->x + src->size.width) * xscale) - x) * inv_xscale,
(ceilf ((src->origin.y + pixel_offset->y + src->size.height) * yscale) - y) * inv_yscale);
}
static GskGpuImage *
gsk_gpu_node_processor_init_draw (GskGpuNodeProcessor *self,
GskGpuFrame *frame,
GdkMemoryDepth depth,
const graphene_point_t *scale,
const GskScale *scale,
const graphene_rect_t *viewport)
{
GskGpuImage *image;
@@ -397,7 +373,7 @@ gsk_gpu_node_processor_process (GskGpuFrame *frame,
static void
gsk_gpu_pattern_writer_init (GskGpuPatternWriter *self,
GskGpuFrame *frame,
const graphene_point_t *scale,
const GskScale *scale,
const graphene_point_t *offset,
const graphene_rect_t *bounds)
{
@@ -552,70 +528,6 @@ gsk_gpu_pattern_writer_add_image (GskGpuPatternWriter *self,
return gsk_gpu_descriptors_add_image (self->desc, image, sampler, out_descriptor);
}
static void
extract_scale_from_transform (GskTransform *transform,
float *out_scale_x,
float *out_scale_y)
{
switch (gsk_transform_get_category (transform))
{
default:
g_assert_not_reached ();
G_GNUC_FALLTHROUGH;
case GSK_TRANSFORM_CATEGORY_IDENTITY:
case GSK_TRANSFORM_CATEGORY_2D_TRANSLATE:
*out_scale_x = 1.0f;
*out_scale_y = 1.0f;
return;
case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
{
float scale_x, scale_y, dx, dy;
gsk_transform_to_affine (transform, &scale_x, &scale_y, &dx, &dy);
*out_scale_x = fabs (scale_x);
*out_scale_y = fabs (scale_y);
}
return;
case GSK_TRANSFORM_CATEGORY_2D:
{
float skew_x, skew_y, scale_x, scale_y, angle, dx, dy;
gsk_transform_to_2d_components (transform,
&skew_x, &skew_y,
&scale_x, &scale_y,
&angle,
&dx, &dy);
*out_scale_x = fabs (scale_x);
*out_scale_y = fabs (scale_y);
}
return;
case GSK_TRANSFORM_CATEGORY_UNKNOWN:
case GSK_TRANSFORM_CATEGORY_ANY:
case GSK_TRANSFORM_CATEGORY_3D:
{
graphene_quaternion_t rotation;
graphene_matrix_t matrix;
graphene_vec4_t perspective;
graphene_vec3_t translation;
graphene_vec3_t matrix_scale;
graphene_vec3_t shear;
gsk_transform_to_matrix (transform, &matrix);
graphene_matrix_decompose (&matrix,
&translation,
&matrix_scale,
&rotation,
&shear,
&perspective);
*out_scale_x = fabs (graphene_vec3_get_x (&matrix_scale));
*out_scale_y = fabs (graphene_vec3_get_y (&matrix_scale));
}
return;
}
}
static gboolean
gsk_gpu_node_processor_rect_is_integer (GskGpuNodeProcessor *self,
const graphene_rect_t *rect,
@@ -661,10 +573,10 @@ static void
gsk_gpu_node_processor_get_clip_bounds (GskGpuNodeProcessor *self,
graphene_rect_t *out_bounds)
{
graphene_rect_offset_r (&self->clip.rect.bounds,
- self->offset.x,
- self->offset.y,
out_bounds);
gsk_rect_init_offset (out_bounds,
&self->clip.rect.bounds,
&GRAPHENE_POINT_INIT (- self->offset.x,
- self->offset.y));
/* FIXME: We could try the scissor rect here.
* But how often is that smaller than the clip bounds?
@@ -757,7 +669,7 @@ gsk_gpu_node_processor_image_op (GskGpuNodeProcessor *self,
static GskGpuImage *
gsk_gpu_get_node_as_image (GskGpuFrame *frame,
const graphene_rect_t *clip_bounds,
const graphene_point_t *scale,
const GskScale *scale,
GskRenderNode *node,
graphene_rect_t *out_bounds)
{
@@ -937,7 +849,7 @@ gsk_gpu_node_processor_get_node_as_image (GskGpuNodeProcessor *self,
return NULL;
clip_bounds = &clip;
}
rect_round_to_pixels (clip_bounds, &self->scale, &self->offset, &clip);
clip = gsk_rect_round_to_pixels (*clip_bounds, self->scale, self->offset);
image = gsk_gpu_get_node_as_image (self->frame,
&clip,
@@ -1069,7 +981,7 @@ gsk_gpu_node_processor_add_fallback_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clipped_bounds))
return;
rect_round_to_pixels (&clipped_bounds, &self->scale, &self->offset, &clipped_bounds);
clipped_bounds = gsk_rect_round_to_pixels (clipped_bounds, self->scale, self->offset);
gsk_gpu_node_processor_sync_globals (self, 0);
@@ -1424,7 +1336,8 @@ gsk_gpu_node_processor_add_rounded_clip_node_with_mask (GskGpuNodeProcessor *sel
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
return;
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
clip_bounds = gsk_rect_round_to_pixels (clip_bounds, self->scale, self->offset);
child_image = gsk_gpu_node_processor_get_node_as_image (self,
0,
@@ -1531,7 +1444,7 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
GskRenderNode *child;
GskTransform *transform;
graphene_point_t old_offset;
graphene_point_t old_scale;
GskScale old_scale;
GskTransform *old_modelview;
GskGpuClip old_clip;
@@ -1566,8 +1479,8 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
gsk_gpu_clip_scale (&self->clip, &old_clip, scale_x, scale_y);
self->offset = GRAPHENE_POINT_INIT ((self->offset.x + dx) / scale_x,
(self->offset.y + dy) / scale_y);
self->scale = GRAPHENE_POINT_INIT (fabsf (scale_x) * old_scale.x,
fabsf (scale_y) * old_scale.y);
self->scale = GSK_SCALE_INIT (fabsf (scale_x) * old_scale.x,
fabsf (scale_y) * old_scale.y);
self->modelview = gsk_transform_scale (self->modelview,
scale_x / fabsf (scale_x),
scale_y / fabsf (scale_y));
@@ -1580,7 +1493,8 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
case GSK_TRANSFORM_CATEGORY_3D:
{
GskTransform *clip_transform;
float scale_x, scale_y, old_pixels, new_pixels;
float old_pixels, new_pixels;
GskScale scale;
clip_transform = gsk_transform_transform (gsk_transform_translate (NULL, &self->offset), transform);
gsk_gpu_clip_init_copy (&old_clip, &self->clip);
@@ -1631,20 +1545,20 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
self->modelview = gsk_transform_transform (self->modelview, clip_transform);
gsk_transform_unref (clip_transform);
extract_scale_from_transform (self->modelview, &scale_x, &scale_y);
gsk_scale_extract_from_transform (self->modelview, &scale);
old_pixels = old_scale.x * old_scale.y *
old_clip.rect.bounds.size.width * old_clip.rect.bounds.size.height;
new_pixels = scale_x * scale_y * self->clip.rect.bounds.size.width * self->clip.rect.bounds.size.height;
new_pixels = scale.x * scale.y * self->clip.rect.bounds.size.width * self->clip.rect.bounds.size.height;
if (new_pixels > 2 * old_pixels)
{
float forced_downscale = 2 * old_pixels / new_pixels;
scale_x *= forced_downscale;
scale_y *= forced_downscale;
scale.x *= forced_downscale;
scale.y *= forced_downscale;
}
self->modelview = gsk_transform_scale (self->modelview, 1 / scale_x, 1 / scale_y);
self->scale = GRAPHENE_POINT_INIT (scale_x, scale_y);
self->modelview = gsk_transform_scale (self->modelview, 1 / scale.x, 1 / scale.y);
self->scale = scale;
self->offset = *graphene_point_zero ();
}
break;
@@ -1673,7 +1587,7 @@ gsk_gpu_node_processor_create_transform_pattern (GskGpuPatternWriter *self,
GskRenderNode *child;
GskTransform *transform;
graphene_point_t old_offset;
graphene_point_t old_scale;
GskScale old_scale;
graphene_rect_t old_bounds;
gboolean result;
@@ -1716,7 +1630,7 @@ gsk_gpu_node_processor_create_transform_pattern (GskGpuPatternWriter *self,
self->bounds.size.width *= inv_sx;
self->bounds.size.height *= inv_sy;
self->offset = GRAPHENE_POINT_INIT (0, 0);
self->scale = GRAPHENE_POINT_INIT (fabsf (sx) * old_scale.x, fabsf (sy) * old_scale.y);
self->scale = GSK_SCALE_INIT(fabsf (sx) * old_scale.x, fabsf (sy) * old_scale.y);
}
break;
@@ -2039,8 +1953,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
guint32 descriptor;
gboolean need_mipmap, need_offscreen;
need_offscreen = self->modelview != NULL ||
(self->scale.x != 1 || self->scale.y != 1);
need_offscreen = self->modelview != NULL || !gsk_scale_is_one (self->scale);
if (need_offscreen)
{
GskGpuImage *offscreen;
@@ -2048,9 +1961,9 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
return;
gsk_rect_round_larger (&clip_bounds);
clip_bounds = gsk_rect_round_larger (clip_bounds);
offscreen = gsk_gpu_render_pass_op_offscreen (self->frame,
&GRAPHENE_POINT_INIT (1, 1),
&GSK_SCALE_INIT (1, 1),
&clip_bounds,
node);
descriptor = gsk_gpu_node_processor_add_image (self, offscreen, GSK_GPU_SAMPLER_DEFAULT);
@@ -2246,7 +2159,8 @@ gsk_gpu_node_processor_add_gradient_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &bounds))
return;
rect_round_to_pixels (&bounds, &self->scale, &self->offset, &bounds);
bounds = gsk_rect_round_to_pixels (bounds, self->scale, self->offset);
image = gsk_gpu_node_processor_init_draw (&other,
self->frame,
@@ -2970,7 +2884,7 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
PangoFont *font;
graphene_point_t offset;
guint i, num_glyphs;
float scale, inv_scale;
GskScale scale, inv;
GdkRGBA color;
if (self->opacity < 1.0 &&
@@ -2986,12 +2900,10 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
num_glyphs = gsk_text_node_get_num_glyphs (node);
glyphs = gsk_text_node_get_glyphs (node, NULL);
font = gsk_text_node_get_font (node);
offset = *gsk_text_node_get_offset (node);
offset.x += self->offset.x;
offset.y += self->offset.y;
offset = gsk_point_add (*gsk_text_node_get_offset (node), self->offset);
scale = MAX (self->scale.x, self->scale.y);
inv_scale = 1.f / scale;
scale = gsk_scale_max (self->scale);
inv = gsk_scale_invert (scale);
for (i = 0; i < num_glyphs; i++)
{
@@ -3005,14 +2917,16 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
font,
glyphs[i].glyph,
0,
scale,
scale.x,
&glyph_bounds,
&glyph_offset);
gsk_rect_scale (&GRAPHENE_RECT_INIT (-glyph_bounds.origin.x, -glyph_bounds.origin.y, gsk_gpu_image_get_width (image), gsk_gpu_image_get_height (image)), inv_scale, inv_scale, &glyph_tex_rect);
gsk_rect_scale (&GRAPHENE_RECT_INIT(0, 0, glyph_bounds.size.width, glyph_bounds.size.height), inv_scale, inv_scale, &glyph_bounds);
glyph_offset = GRAPHENE_POINT_INIT (offset.x - glyph_offset.x * inv_scale + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
offset.y - glyph_offset.y * inv_scale + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
glyph_tex_rect = gsk_rect_scale (GRAPHENE_RECT_INIT (-glyph_bounds.origin.x, -glyph_bounds.origin.y, gsk_gpu_image_get_width (image), gsk_gpu_image_get_height (image)), inv);
glyph_bounds = gsk_rect_scale (GRAPHENE_RECT_INIT (0, 0, glyph_bounds.size.width, glyph_bounds.size.height), inv);
glyph_offset = gsk_point_add (gsk_point_add (offset, gsk_point_divide (glyph_offset, scale)),
gsk_point_init (glyphs[i].geometry.x_offset/(float)PANGO_SCALE,
glyphs[i].geometry.y_offset/(float)PANGO_SCALE));
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
if (glyphs[i].attr.is_color)
gsk_gpu_texture_op (self->frame,
@@ -3045,7 +2959,7 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
PangoFont *font;
guint num_glyphs;
gsize i;
float scale, inv_scale;
GskScale scale, inv;
guint32 tex_id;
GskGpuImage *last_image;
graphene_point_t offset;
@@ -3057,12 +2971,10 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
num_glyphs = gsk_text_node_get_num_glyphs (node);
glyphs = gsk_text_node_get_glyphs (node, NULL);
font = gsk_text_node_get_font (node);
offset = *gsk_text_node_get_offset (node);
offset.x += self->offset.x;
offset.y += self->offset.y;
offset = gsk_point_add (*gsk_text_node_get_offset (node), self->offset);
scale = MAX (self->scale.x, self->scale.y);
inv_scale = 1.f / scale;
scale = gsk_scale_max (self->scale);
inv = gsk_scale_invert (scale);
gsk_gpu_pattern_writer_append_uint (self, GSK_GPU_PATTERN_GLYPHS);
gsk_gpu_pattern_writer_append_rgba (self, gsk_text_node_get_color (node));
@@ -3080,7 +2992,7 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
font,
glyphs[i].glyph,
0,
scale,
scale.x,
&glyph_bounds,
&glyph_offset);
@@ -3092,24 +3004,25 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
last_image = image;
}
glyph_offset = GRAPHENE_POINT_INIT (offset.x - glyph_offset.x * inv_scale + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
offset.y - glyph_offset.y * inv_scale + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
glyph_offset = gsk_point_add (gsk_point_add (offset, gsk_point_divide (glyph_offset, scale)),
gsk_point_init (glyphs[i].geometry.x_offset / (float)PANGO_SCALE,
glyphs[i].geometry.y_offset / (float)PANGO_SCALE));
gsk_gpu_pattern_writer_append_uint (self, tex_id);
gsk_gpu_pattern_writer_append_rect (self,
&GRAPHENE_RECT_INIT (
0,
0,
glyph_bounds.size.width * inv_scale,
glyph_bounds.size.height * inv_scale
glyph_bounds.size.width * inv.x,
glyph_bounds.size.height * inv.y
),
&glyph_offset);
gsk_gpu_pattern_writer_append_rect (self,
&GRAPHENE_RECT_INIT (
- glyph_bounds.origin.x * inv_scale,
- glyph_bounds.origin.y * inv_scale,
gsk_gpu_image_get_width (image) * inv_scale,
gsk_gpu_image_get_height (image) * inv_scale
- glyph_bounds.origin.x * inv.x,
- glyph_bounds.origin.y * inv.y,
gsk_gpu_image_get_width (image) * inv.x,
gsk_gpu_image_get_height (image) * inv.y
),
&glyph_offset);
@@ -3215,8 +3128,8 @@ gsk_gpu_node_processor_repeat_tile (GskGpuNodeProcessor *self,
gsk_rect_init_offset (&offset_rect,
rect,
- x * child_bounds->size.width,
- y * child_bounds->size.height);
&GRAPHENE_POINT_INIT (- x * child_bounds->size.width,
- y * child_bounds->size.height));
if (!gsk_rect_intersection (&offset_rect, child_bounds, &clipped_child_bounds))
{
/* The math has gone wrong probably, someone should look at this. */
@@ -3357,11 +3270,8 @@ gsk_gpu_node_processor_add_repeat_node (GskGpuNodeProcessor *self,
for (y = floorf (tile_top); y < ceilf (tile_bottom); y++)
{
offset.y = y * child_bounds->size.height;
self->offset = GRAPHENE_POINT_INIT (old_offset.x + offset.x, old_offset.y + offset.y);
clip_bounds = GRAPHENE_RECT_INIT (bounds.origin.x - offset.x,
bounds.origin.y - offset.y,
bounds.size.width,
bounds.size.height);
self->offset = gsk_point_add (old_offset, offset);
clip_bounds = gsk_rect_subtract_offset (bounds, offset);
if (!gsk_rect_intersection (&clip_bounds, child_bounds, &clip_bounds))
continue;
gsk_gpu_node_processor_add_node_clipped (self,
@@ -3402,10 +3312,7 @@ gsk_gpu_node_processor_create_repeat_pattern (GskGpuPatternWriter *self,
gsk_gpu_pattern_writer_append_rect (self, child_bounds, &self->offset);
old_bounds = self->bounds;
self->bounds = GRAPHENE_RECT_INIT (child_bounds->origin.x + self->offset.x,
child_bounds->origin.y + self->offset.y,
child_bounds->size.width,
child_bounds->size.height);
self->bounds = gsk_rect_add_offset (*child_bounds, self->offset);
if (!gsk_gpu_node_processor_create_node_pattern (self, child))
{
@@ -3477,7 +3384,8 @@ gsk_gpu_node_processor_add_fill_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
return;
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
clip_bounds = gsk_rect_round_to_pixels (clip_bounds, self->scale, self->offset);
child = gsk_fill_node_get_child (node);
@@ -3574,7 +3482,8 @@ gsk_gpu_node_processor_add_stroke_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
return;
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
clip_bounds = gsk_rect_round_to_pixels (clip_bounds, self->scale, self->offset);
child = gsk_stroke_node_get_child (node);
@@ -3973,15 +3882,9 @@ gsk_gpu_node_processor_create_node_pattern (GskGpuPatternWriter *self,
gsk_gpu_descriptors_set_size (self->desc, images_before, buffers_before);
}
rect_round_to_pixels (&GRAPHENE_RECT_INIT (
self->bounds.origin.x - self->offset.x,
self->bounds.origin.y - self->offset.y,
self->bounds.size.width,
self->bounds.size.height
),
&self->scale,
&self->offset,
&bounds);
bounds = gsk_rect_round_to_pixels (gsk_rect_subtract_offset (self->bounds, self->offset),
self->scale,
self->offset);
image = gsk_gpu_get_node_as_image (self->frame,
&bounds,
&self->scale,

View File

@@ -336,7 +336,7 @@ gsk_gpu_render_pass_end_op (GskGpuFrame *frame,
GskGpuImage *
gsk_gpu_render_pass_op_offscreen (GskGpuFrame *frame,
const graphene_point_t *scale,
const GskScale *scale,
const graphene_rect_t *viewport,
GskRenderNode *node)
{

View File

@@ -6,6 +6,8 @@
#include <graphene.h>
#include "gsk/gskscaleprivate.h"
G_BEGIN_DECLS
/* We only need this for the final VkImageLayout, but don't tell anyone */
@@ -24,7 +26,7 @@ void gsk_gpu_render_pass_end_op (GskGpuF
GskRenderPassType pass_type);
GskGpuImage * gsk_gpu_render_pass_op_offscreen (GskGpuFrame *frame,
const graphene_point_t *scale,
const GskScale *scale,
const graphene_rect_t *viewport,
GskRenderNode *node);

View File

@@ -452,7 +452,7 @@ static const GskGpuOpClass GSK_GPU_UPLOAD_CAIRO_OP_CLASS = {
GskGpuImage *
gsk_gpu_upload_cairo_op (GskGpuFrame *frame,
const graphene_point_t *scale,
const GskScale *scale,
const graphene_rect_t *viewport,
GskGpuCairoFunc func,
gpointer user_data,

View File

@@ -3,6 +3,7 @@
#include "gskgpuopprivate.h"
#include "gsktypes.h"
#include "gsk/gskscaleprivate.h"
G_BEGIN_DECLS
@@ -14,7 +15,7 @@ GskGpuImage * gsk_gpu_upload_texture_op_try (GskGpuF
GdkTexture *texture);
GskGpuImage * gsk_gpu_upload_cairo_op (GskGpuFrame *frame,
const graphene_point_t *scale,
const GskScale *scale,
const graphene_rect_t *viewport,
GskGpuCairoFunc func,
gpointer user_data,

View File

@@ -2,6 +2,7 @@
#include <graphene.h>
#include <math.h>
#include "gskscaleprivate.h"
static inline void
gsk_rect_init (graphene_rect_t *r,
@@ -24,12 +25,11 @@ gsk_rect_init_from_rect (graphene_rect_t *r,
}
static inline void
gsk_rect_init_offset (graphene_rect_t *r,
const graphene_rect_t *src,
float dx,
float dy)
gsk_rect_init_offset (graphene_rect_t *r,
const graphene_rect_t *src,
const graphene_point_t *offset)
{
gsk_rect_init (r, src->origin.x + dx, src->origin.y + dy, src->size.width, src->size.height);
gsk_rect_init (r, src->origin.x + offset->x, src->origin.y + offset->y, src->size.width, src->size.height);
}
static inline gboolean G_GNUC_PURE
@@ -130,31 +130,71 @@ gsk_point_to_float (const graphene_point_t *point,
values[1] = point->y;
}
static inline void
gsk_rect_round_larger (graphene_rect_t *rect)
static inline graphene_rect_t
gsk_rect_round_larger (const graphene_rect_t rect)
{
float x = floor (rect->origin.x);
float y = floor (rect->origin.y);
*rect = GRAPHENE_RECT_INIT (x, y,
ceil (rect->origin.x + rect->size.width) - x,
ceil (rect->origin.y + rect->size.height) - y);
float x = floorf (rect.origin.x);
float y = floorf (rect.origin.y);
return GRAPHENE_RECT_INIT (x, y,
ceilf (rect.origin.x + rect.size.width) - x,
ceilf (rect.origin.y + rect.size.height) - y);
}
static inline void
gsk_rect_scale (const graphene_rect_t *r,
float sx,
float sy,
graphene_rect_t *res)
static inline graphene_rect_t
gsk_rect_scale (const graphene_rect_t r,
const GskScale scale)
{
if (G_UNLIKELY (sx < 0 || sy < 0))
if (G_UNLIKELY (scale.x < 0 || scale.y < 0))
{
graphene_rect_scale (r, sx, sy, res);
return;
graphene_rect_t res;
graphene_rect_scale (&r, scale.x, scale.y, &res);
return res;
}
res->origin.x = r->origin.x * sx;
res->origin.y = r->origin.y * sy;
res->size.width = r->size.width * sx;
res->size.height = r->size.height * sy;
return GRAPHENE_RECT_INIT (r.origin.x * scale.x,
r.origin.y * scale.y,
r.size.width * scale.x,
r.size.height * scale.y);
}
static inline graphene_rect_t
gsk_rect_add_offset (const graphene_rect_t r,
const graphene_point_t offset)
{
return GRAPHENE_RECT_INIT (r.origin.x + offset.x,
r.origin.y + offset.y,
r.size.width,
r.size.height);
}
static inline graphene_rect_t
gsk_rect_subtract_offset (const graphene_rect_t r,
const graphene_point_t offset)
{
return GRAPHENE_RECT_INIT (r.origin.x - offset.x,
r.origin.y - offset.y,
r.size.width,
r.size.height);
}
static inline graphene_rect_t
gsk_rect_from_points (const graphene_point_t p0,
const graphene_point_t p1)
{
return GRAPHENE_RECT_INIT (p0.x, p0.y, p1.x - p0.x, p1.y - p0.y);
}
static inline graphene_rect_t
gsk_rect_round_to_pixels (const graphene_rect_t src,
const GskScale scale,
const graphene_point_t offset)
{
graphene_point_t p0, p1;
p0 = gsk_point_subtract (gsk_point_divide (gsk_point_floor (gsk_point_multiply (gsk_point_add (src.origin, offset), scale)), scale), offset);
p1 = gsk_point_divide (gsk_point_subtract (gsk_point_ceil (gsk_point_multiply (gsk_point_add (gsk_point_add (src.origin, offset), gsk_point_init (src.size.width, src.size.height)), scale)), p0), scale);
return gsk_rect_from_points (p0, p1);
}

65
gsk/gskscale.c Normal file
View File

@@ -0,0 +1,65 @@
#include "config.h"
#include "gskscaleprivate.h"
#include "gsktransform.h"
void
gsk_scale_extract_from_transform (GskTransform *transform,
GskScale *scale)
{
switch (gsk_transform_get_category (transform))
{
default:
g_assert_not_reached ();
G_GNUC_FALLTHROUGH;
case GSK_TRANSFORM_CATEGORY_IDENTITY:
case GSK_TRANSFORM_CATEGORY_2D_TRANSLATE:
*scale = gsk_scale_init (1, 1);
return;
case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
{
float scale_x, scale_y, dx, dy;
gsk_transform_to_affine (transform, &scale_x, &scale_y, &dx, &dy);
*scale = gsk_scale_init (fabsf (scale_x), fabsf (scale_y));
}
return;
case GSK_TRANSFORM_CATEGORY_2D:
{
float skew_x, skew_y, scale_x, scale_y, angle, dx, dy;
gsk_transform_to_2d_components (transform,
&skew_x, &skew_y,
&scale_x, &scale_y,
&angle,
&dx, &dy);
*scale = gsk_scale_init (fabsf (scale_x), fabsf (scale_y));
}
return;
case GSK_TRANSFORM_CATEGORY_UNKNOWN:
case GSK_TRANSFORM_CATEGORY_ANY:
case GSK_TRANSFORM_CATEGORY_3D:
{
graphene_quaternion_t rotation;
graphene_matrix_t matrix;
graphene_vec4_t perspective;
graphene_vec3_t translation;
graphene_vec3_t matrix_scale;
graphene_vec3_t shear;
gsk_transform_to_matrix (transform, &matrix);
graphene_matrix_decompose (&matrix,
&translation,
&matrix_scale,
&rotation,
&shear,
&perspective);
*scale = gsk_scale_init (fabsf (graphene_vec3_get_x (&matrix_scale)),
fabsf (graphene_vec3_get_y (&matrix_scale)));
}
return;
}
}

136
gsk/gskscaleprivate.h Normal file
View File

@@ -0,0 +1,136 @@
#pragma once
#include "gsktypes.h"
#include <graphene.h>
#include <math.h>
struct _GskScale
{
float x;
float y;
};
#define GSK_SCALE_INIT(x,y) (GskScale) { (x), (y) }
static inline GskScale
gsk_scale_init (float x,
float y)
{
return (GskScale) { x, y };
}
static inline GskScale
gsk_scale_init_uniform (float s)
{
return gsk_scale_init (s, s);
}
static inline void
gsk_scale_to_float (const GskScale *scale,
float values[2])
{
values[0] = scale->x;
values[1] = scale->y;
}
static inline gboolean
gsk_scale_is_one (const GskScale scale)
{
return scale.x == 1 && scale.y == 1;
}
static inline gboolean
gsk_scale_is_uniform (const GskScale scale)
{
return scale.x == scale.y;
}
static inline GskScale
gsk_scale_invert (const GskScale scale)
{
return (GskScale) { 1 / scale.x, 1 / scale.y };
}
static inline GskScale
gsk_scale_multiply (const GskScale scale1,
const GskScale scale2)
{
return (GskScale) { scale1.x * scale2.x, scale1.y * scale2.y };
}
static inline GskScale
gsk_scale_divide (const GskScale scale1,
const GskScale scale2)
{
return (GskScale) { scale1.x / scale2.x, scale1.y / scale2.y };
}
static inline GskScale
gsk_scale_max (const GskScale scale)
{
float s = MAX (scale.x, scale.y);
return (GskScale) { s, s };
}
static inline graphene_point_t
gsk_point_init (float x,
float y)
{
return (graphene_point_t) { x, y };
}
static inline gboolean
gsk_point_is_zero (const graphene_point_t point)
{
return point.x == 0 && point.y == 0;
}
static inline graphene_point_t
gsk_point_negate (const graphene_point_t point)
{
return (graphene_point_t) { - point.x, - point.y };
}
static inline graphene_point_t
gsk_point_multiply (const graphene_point_t point,
const GskScale scale)
{
return (graphene_point_t) { point.x * scale.x, point.y * scale.y };
}
static inline graphene_point_t
gsk_point_divide (const graphene_point_t point,
const GskScale scale)
{
return (graphene_point_t) { point.x / scale.x, point.y / scale.y };
}
static inline graphene_point_t
gsk_point_add (const graphene_point_t point1,
const graphene_point_t point2)
{
return (graphene_point_t) { point1.x + point2.x, point1.y + point2.y };
}
static inline graphene_point_t
gsk_point_subtract (const graphene_point_t point1,
const graphene_point_t point2)
{
return (graphene_point_t) { point1.x - point2.x, point1.y - point2.y };
}
static inline graphene_point_t
gsk_point_floor (const graphene_point_t point)
{
return (graphene_point_t) { floorf (point.x), floorf (point.y) };
}
static inline graphene_point_t
gsk_point_ceil (const graphene_point_t point)
{
return (graphene_point_t) { ceilf (point.x), ceilf (point.y) };
}
void
gsk_scale_extract_from_transform (GskTransform *transform,
GskScale *scale);

View File

@@ -34,4 +34,4 @@ typedef struct _GskRenderNode GskRenderNode;
typedef struct _GskRoundedRect GskRoundedRect;
typedef struct _GskStroke GskStroke;
typedef struct _GskTransform GskTransform;
typedef struct _GskScale GskScale;

View File

@@ -51,6 +51,7 @@ gsk_private_sources = files([
'gskdebug.c',
'gskprivate.c',
'gskprofiler.c',
'gskscale.c',
'gl/gskglattachmentstate.c',
'gl/gskglbuffer.c',
'gl/gskglcommandqueue.c',