Compare commits

..

15 Commits

Author SHA1 Message Date
Matthias Clasen
c5988a22a4 gpu: Add a front cache
This copies the approach taken in the gl renderer to avoid much
of the hash table lookup overhead by means of a front cache.
2024-01-20 11:19:23 -05:00
Matthias Clasen
498bf67cec gpu: Print more detailed cache statistics
Print out stale glyphs and dead pixel ratios.
2024-01-20 08:50:50 -05:00
Matthias Clasen
65455cdb91 gpu: Rework glyph aging
Instead of counting atlas occupancy by itesm, count how many
dead pixels we have, and free the atlas if more than half of its
pixels are dead. This matches what the GL renderer does.

As part of this, change when glyphs are freed. We now keep them
in the hash table until their atlas is freed and we only do dead
pixel accounting when should_collect is called. This keeps the
glyphs available for use from the cache as long as are in the atlas.

If a stale glyph is sused, we 'revive' itby removing its pixels
from the dead.

This matches more closely what the gl renderer does.
2024-01-20 08:48:33 -05:00
Matthias Clasen
d4963ba2e5 gpu: Make cache freeing more robust
Currently, we only free an atlas when all its glyphs are gone,
but we might revisit that in the future, so be prepared for it.
2024-01-20 08:05:38 -05:00
Matthias Clasen
ec5fed6cc4 gpu: Fix atlas allocation logic
The code wasn't careful enough, and could make the last slice
higher than the atlas, or put the image into a too-narrow slice.

Add more assertions.
2024-01-20 08:05:38 -05:00
Matthias Clasen
b7ae5404a3 gsk: Reshuffle code a bit
Move the atlas allocation to the atlas section in the code.
2024-01-20 08:05:38 -05:00
Matthias Clasen
fb4f210430 gpu: Fix ordering problem in clear_cache()
We must free the glyphs before their atlases, since we now maintain
the item count of the atlas when glyphs are freed.
2024-01-20 08:05:30 -05:00
Matthias Clasen
82df109444 gpu: Fix atlas freeing
We need to unset current_atlas if we free that one.
2024-01-20 08:05:30 -05:00
Matthias Clasen
bd84142f43 gpu: Evict stale atlases from the cache
We evict atlases when they are old and unused.
2024-01-20 08:05:30 -05:00
Matthias Clasen
65074bbbac gpu: Count glyphs on atlases
That is the only way to know when its safe to gc an atlas. We can't
do that if there's still glyphs living on it.
2024-01-20 08:05:30 -05:00
Matthias Clasen
21fb5ec0b2 gpu: Evict stale glyphs from the cache 2024-01-20 08:05:30 -05:00
Matthias Clasen
e57f92b7e9 gpu: Fix texture eviction
If we gc a cached texture for which the GdkTexture is still alive,
the cached texture object will remain accessible via the render
data, so need to make sure not to leave a dangling pointer behind
here.
2024-01-20 08:05:30 -05:00
Matthias Clasen
e94e348ad5 gpu: Evict stale textures from the cache
Fixes: #6346
2024-01-20 08:05:30 -05:00
Matthias Clasen
91234e75f8 gpu: Start doing gc
Call gc periodically from a timeout.
2024-01-20 08:05:30 -05:00
Matthias Clasen
212e9a6957 gpu: Print some cache stats
This reuses the GLYPHCACHE debug flag that is used for the same
purpose in the gl renderer.
2024-01-20 08:05:30 -05:00
58 changed files with 940 additions and 1087 deletions

View File

@@ -830,8 +830,8 @@ rounded_rect_scale_corners (const GskRoundedRect *rect,
{
for (guint i = 0; i < G_N_ELEMENTS (out_rect->corner); i++)
{
out_rect->corner[i].width = rect->corner[i].width * fabsf (scale_x);
out_rect->corner[i].height = rect->corner[i].height * fabsf (scale_y);
out_rect->corner[i].width = rect->corner[i].width * fabs (scale_x);
out_rect->corner[i].height = rect->corner[i].height * fabs (scale_y);
}
if (scale_x < 0)
@@ -1173,8 +1173,8 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
{
float scale_x = job->scale_x;
float scale_y = job->scale_y;
int surface_width = ceilf (node->bounds.size.width * fabsf (scale_x));
int surface_height = ceilf (node->bounds.size.height * fabsf (scale_y));
int surface_width = ceilf (node->bounds.size.width * fabs (scale_x));
int surface_height = ceilf (node->bounds.size.height * fabs (scale_y));
GdkTexture *texture;
cairo_surface_t *surface;
cairo_surface_t *rendered_surface;
@@ -1203,7 +1203,7 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
surface_width,
surface_height);
cairo_surface_set_device_scale (rendered_surface, fabsf (scale_x), fabsf (scale_y));
cairo_surface_set_device_scale (rendered_surface, fabs (scale_x), fabs (scale_y));
cr = cairo_create (rendered_surface);
cairo_save (cr);
@@ -1217,16 +1217,16 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
surface_width,
surface_height);
cairo_surface_set_device_scale (surface, fabsf (scale_x), fabsf (scale_y));
cairo_surface_set_device_scale (surface, fabs (scale_x), fabs (scale_y));
cr = cairo_create (surface);
/* We draw upside down here, so it matches what GL does. */
cairo_save (cr);
cairo_scale (cr, scale_x < 0 ? -1 : 1, scale_y < 0 ? 1 : -1);
cairo_translate (cr, scale_x < 0 ? - surface_width / fabsf (scale_x) : 0,
scale_y < 0 ? 0 : - surface_height / fabsf (scale_y));
cairo_translate (cr, scale_x < 0 ? - surface_width / fabs (scale_x) : 0,
scale_y < 0 ? 0 : - surface_height / fabs (scale_y));
cairo_set_source_surface (cr, rendered_surface, 0, 0);
cairo_rectangle (cr, 0, 0, surface_width / fabsf (scale_x), surface_height / fabsf (scale_y));
cairo_rectangle (cr, 0, 0, surface_width / fabs (scale_x), surface_height / fabs (scale_y));
cairo_fill (cr);
cairo_restore (cr);
cairo_destroy (cr);
@@ -1432,10 +1432,10 @@ blur_node (GskGLRenderJob *job,
offscreen->texture_id = blur_offscreen (job,
offscreen,
texture_width * fabsf (scale_x),
texture_height * fabsf (scale_y),
blur_radius * fabsf (scale_x),
blur_radius * fabsf (scale_y));
texture_width * fabs (scale_x),
texture_height * fabs (scale_y),
blur_radius * fabs (scale_x),
blur_radius * fabs (scale_y));
init_full_texture_region (offscreen);
}
@@ -2019,9 +2019,9 @@ result_is_axis_aligned (GskTransform *transform,
for (guint i = 0; i < 4; i++)
{
p = graphene_quad_get_point (&q, i);
if (fabsf (p->x - b1.x) > FLT_EPSILON && fabsf (p->x - b2.x) > FLT_EPSILON)
if (fabs (p->x - b1.x) > FLT_EPSILON && fabs (p->x - b2.x) > FLT_EPSILON)
return FALSE;
if (fabsf (p->y - b1.y) > FLT_EPSILON && fabsf (p->y - b2.y) > FLT_EPSILON)
if (fabs (p->y - b1.y) > FLT_EPSILON && fabs (p->y - b2.y) > FLT_EPSILON)
return FALSE;
}
@@ -2304,8 +2304,8 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
&offscreen,
texture_width,
texture_height,
blur_radius * fabsf (scale_x),
blur_radius * fabsf (scale_y));
blur_radius * fabs (scale_x),
blur_radius * fabs (scale_y));
gsk_gl_driver_release_render_target (job->driver, render_target, TRUE);
@@ -2501,8 +2501,8 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
do_slicing = TRUE;
}
texture_width = (int)ceilf ((scaled_outline.bounds.size.width + blur_extra) * scale_x);
texture_height = (int)ceilf ((scaled_outline.bounds.size.height + blur_extra) * scale_y);
texture_width = (int)ceil ((scaled_outline.bounds.size.width + blur_extra) * scale_x);
texture_height = (int)ceil ((scaled_outline.bounds.size.height + blur_extra) * scale_y);
scaled_outline.bounds.origin.x = extra_blur_pixels_x;
scaled_outline.bounds.origin.y = extra_blur_pixels_y;
@@ -2577,8 +2577,8 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
&offscreen,
texture_width,
texture_height,
blur_radius * fabsf (scale_x),
blur_radius * fabsf (scale_y));
blur_radius * fabs (scale_x),
blur_radius * fabs (scale_y));
gsk_gl_shadow_library_insert (job->driver->shadows_library,
&scaled_outline,
@@ -2834,7 +2834,7 @@ gsk_gl_render_job_visit_cross_fade_node (GskGLRenderJob *job,
offscreen_end.reset_clip = TRUE;
offscreen_end.bounds = &node->bounds;
gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, fabsf (job->scale_x), fabsf (job->scale_y)));
gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, fabs (job->scale_x), fabs (job->scale_y)));
if (!gsk_gl_render_job_visit_node_with_offscreen (job, start_node, &offscreen_start))
{
@@ -2964,7 +2964,7 @@ gsk_gl_render_job_visit_text_node (GskGLRenderJob *job,
const PangoFont *font = gsk_text_node_get_font (node);
const PangoGlyphInfo *glyphs = gsk_text_node_get_glyphs (node, NULL);
const graphene_point_t *offset = gsk_text_node_get_offset (node);
float text_scale = MAX (fabsf (job->scale_x), fabsf (job->scale_y)); /* TODO: Fix for uneven scales? */
float text_scale = MAX (fabs (job->scale_x), fabs (job->scale_y)); /* TODO: Fix for uneven scales? */
guint num_glyphs = gsk_text_node_get_num_glyphs (node);
float x = offset->x + job->offset_x;
float y = offset->y + job->offset_y;
@@ -3263,7 +3263,7 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
bottom_offscreen.force_offscreen = TRUE;
bottom_offscreen.reset_clip = TRUE;
gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, fabsf (job->scale_x), fabsf (job->scale_y)));
gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, fabs (job->scale_x), fabs (job->scale_y)));
/* TODO: We create 2 textures here as big as the blend node, but both the
* start and the end node might be a lot smaller than that. */
@@ -3344,8 +3344,8 @@ gsk_gl_render_job_texture_mask_for_color (GskGLRenderJob *job,
gboolean use_mipmap;
guint16 cc[4];
use_mipmap = (scale_x * fabsf (job->scale_x)) < 0.5 ||
(scale_y * fabsf (job->scale_y)) < 0.5;
use_mipmap = (scale_x * fabs (job->scale_x)) < 0.5 ||
(scale_y * fabs (job->scale_y)) < 0.5;
rgba_to_half (rgba, cc);
gsk_gl_render_job_upload_texture (job, texture, use_mipmap, &offscreen);
@@ -3396,7 +3396,7 @@ gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
mask_offscreen.reset_clip = TRUE;
mask_offscreen.do_not_cache = TRUE;
gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, fabsf (job->scale_x), fabsf (job->scale_y)));
gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, fabs (job->scale_x), fabs (job->scale_y)));
/* TODO: We create 2 textures here as big as the mask node, but both
* nodes might be a lot smaller than that.
@@ -3664,8 +3664,8 @@ gsk_gl_render_job_visit_texture (GskGLRenderJob *job,
float scale_y = bounds->size.height / texture->height;
gboolean use_mipmap;
use_mipmap = (scale_x * fabsf (job->scale_x)) < 0.5 ||
(scale_y * fabsf (job->scale_y)) < 0.5;
use_mipmap = (scale_x * fabs (job->scale_x)) < 0.5 ||
(scale_y * fabs (job->scale_y)) < 0.5;
if G_LIKELY (texture->width <= max_texture_size &&
texture->height <= max_texture_size)

View File

@@ -117,8 +117,9 @@ gsk_gl_texture_library_real_compact (GskGLTextureLibrary *self,
g_hash_table_iter_remove (&iter);
dropped++;
}
else if (periodic_scan)
entry->accessed = FALSE;
if (periodic_scan)
entry->accessed = FALSE;
}
}
@@ -439,6 +440,7 @@ gsk_gl_texture_library_pack (GskGLTextureLibrary *self,
entry->texture = texture;
entry->is_atlased = FALSE;
entry->accessed = TRUE;
entry->area.x = padding / (float) (padding + width + padding);
entry->area.y = padding / (float) (padding + height + padding);
entry->area.x2 = (padding + width) / (float) (padding + width + padding);

View File

@@ -60,7 +60,7 @@ gsk_gpu_blend_mode_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
GskGpuDescriptors *desc,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
float opacity,
GskBlendMode blend_mode,
guint32 bottom_descriptor,

View File

@@ -10,7 +10,7 @@ void gsk_gpu_blend_mode_op (GskGpuF
GskGpuShaderClip clip,
GskGpuDescriptors *desc,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
float opacity,
GskBlendMode blend_mode,
guint32 start_descriptor,

View File

@@ -63,9 +63,9 @@ gsk_gpu_blur_op_full (GskGpuFrame *frame,
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
const graphene_point_t *blur_direction,
const graphene_vec2_t *blur_direction,
const GdkRGBA *blur_color)
{
GskGpuBlurInstance *instance;
@@ -79,8 +79,7 @@ gsk_gpu_blur_op_full (GskGpuFrame *frame,
gsk_gpu_rect_to_float (rect, offset, instance->rect);
gsk_gpu_rect_to_float (tex_rect, offset, instance->tex_rect);
instance->blur_direction[0] = blur_direction->x;
instance->blur_direction[1] = blur_direction->y;
graphene_vec2_to_float (blur_direction, instance->blur_direction);
gsk_gpu_rgba_to_float (blur_color, instance->blur_color);
instance->tex_id = descriptor;
}
@@ -91,9 +90,9 @@ gsk_gpu_blur_op (GskGpuFrame *frame,
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
const graphene_point_t *blur_direction)
const graphene_vec2_t *blur_direction)
{
gsk_gpu_blur_op_full (frame,
0,
@@ -113,9 +112,9 @@ gsk_gpu_blur_shadow_op (GskGpuFrame *frame,
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
const graphene_point_t *blur_direction,
const graphene_vec2_t *blur_direction,
const GdkRGBA *shadow_color)
{
gsk_gpu_blur_op_full (frame,

View File

@@ -11,18 +11,18 @@ void gsk_gpu_blur_op (GskGpuF
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
const graphene_point_t *blur_direction);
const graphene_vec2_t *blur_direction);
void gsk_gpu_blur_shadow_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
const graphene_point_t *blur_direction,
const graphene_vec2_t *blur_direction,
const GdkRGBA *shadow_color);

View File

@@ -103,7 +103,7 @@ void
gsk_gpu_border_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
const GskRoundedRect *outline,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_point_t *inside_offset,
const float widths[4],
const GdkRGBA colors[4])
@@ -118,7 +118,7 @@ gsk_gpu_border_op (GskGpuFrame *frame,
NULL,
&instance);
gsk_gpu_rounded_rect_to_float (outline, offset, instance->outline);
gsk_rounded_rect_to_float (outline, offset, instance->outline);
for (i = 0; i < 4; i++)
{

View File

@@ -10,7 +10,7 @@ G_BEGIN_DECLS
void gsk_gpu_border_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
const GskRoundedRect *outline,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_point_t *inside_offset,
const float widths[4],
const GdkRGBA colors[4]);

View File

@@ -86,7 +86,7 @@ gsk_gpu_box_shadow_op (GskGpuFrame *frame,
const graphene_point_t *shadow_offset,
float spread,
float blur_radius,
const GskPoint *offset,
const graphene_point_t *offset,
const GdkRGBA *color)
{
GskGpuBoxshadowInstance *instance;
@@ -102,10 +102,11 @@ gsk_gpu_box_shadow_op (GskGpuFrame *frame,
&instance);
gsk_gpu_rect_to_float (bounds, offset, instance->bounds);
gsk_gpu_rounded_rect_to_float (outline, offset, instance->outline);
gsk_rounded_rect_to_float (outline, offset, instance->outline);
gsk_gpu_rgba_to_float (color, instance->color);
instance->shadow_offset[0] = shadow_offset->x;
instance->shadow_offset[1] = shadow_offset->y;
instance->shadow_spread = spread;
instance->blur_radius = blur_radius;
}

View File

@@ -15,7 +15,7 @@ void gsk_gpu_box_shadow_op (
const graphene_point_t *shadow_offset,
float spread,
float blur_radius,
const GskPoint *offset,
const graphene_point_t *offset,
const GdkRGBA *color);

View File

@@ -238,10 +238,12 @@ gsk_gpu_clip_transform (GskGpuClip *dest,
gboolean
gsk_gpu_clip_may_intersect_rect (const GskGpuClip *self,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *rect)
{
graphene_rect_t r = gsk_rect_add_offset (*rect, *offset);
graphene_rect_t r = *rect;
r.origin.x += offset->x;
r.origin.y += offset->y;
switch (self->type)
{
@@ -260,10 +262,12 @@ gsk_gpu_clip_may_intersect_rect (const GskGpuClip *self,
gboolean
gsk_gpu_clip_contains_rect (const GskGpuClip *self,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *rect)
{
graphene_rect_t r = gsk_rect_add_offset (*rect, *offset);
graphene_rect_t r = *rect;
r.origin.x += offset->x;
r.origin.y += offset->y;
switch (self->type)
{
@@ -284,7 +288,7 @@ gsk_gpu_clip_contains_rect (const GskGpuClip *self,
GskGpuShaderClip
gsk_gpu_clip_get_shader_clip (const GskGpuClip *self,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *rect)
{
if (self->type == GSK_GPU_CLIP_NONE ||

View File

@@ -59,15 +59,15 @@ gboolean gsk_gpu_clip_transform (GskGpuC
GskTransform *transform,
const graphene_rect_t *viewport) G_GNUC_WARN_UNUSED_RESULT;
gboolean gsk_gpu_clip_contains_rect (const GskGpuClip *self,
const GskPoint *offset,
gboolean gsk_gpu_clip_contains_rect (const GskGpuClip *self,
const graphene_point_t *offset,
const graphene_rect_t *rect) G_GNUC_WARN_UNUSED_RESULT;
gboolean gsk_gpu_clip_may_intersect_rect (const GskGpuClip *self,
const GskPoint *offset,
const graphene_rect_t *rect) G_GNUC_WARN_UNUSED_RESULT;
GskGpuShaderClip gsk_gpu_clip_get_shader_clip (const GskGpuClip *self,
const GskPoint *offset,
const graphene_rect_t *rect);
gboolean gsk_gpu_clip_may_intersect_rect (const GskGpuClip *self,
const graphene_point_t *offset,
const graphene_rect_t *rect) G_GNUC_WARN_UNUSED_RESULT;
GskGpuShaderClip gsk_gpu_clip_get_shader_clip (const GskGpuClip *self,
const graphene_point_t *offset,
const graphene_rect_t *rect);
G_END_DECLS

View File

@@ -59,7 +59,7 @@ gsk_gpu_colorize_op (GskGpuFrame *frame,
GskGpuDescriptors *descriptors,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
const GdkRGBA *color)
{

View File

@@ -11,7 +11,7 @@ void gsk_gpu_colorize_op (GskGpuF
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
const GdkRGBA *color);

View File

@@ -58,7 +58,7 @@ gsk_gpu_color_matrix_op (GskGpuFrame *frame,
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
const graphene_matrix_t *color_matrix,
const graphene_vec4_t *color_offset)
@@ -85,7 +85,7 @@ gsk_gpu_color_matrix_op_opacity (GskGpuFrame *frame,
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
float opacity)
{

View File

@@ -11,7 +11,7 @@ void gsk_gpu_color_matrix_op (GskGpuF
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
const graphene_matrix_t *color_matrix,
const graphene_vec4_t *color_offset);
@@ -21,7 +21,7 @@ void gsk_gpu_color_matrix_op_opacity (GskGpuF
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
float opacity);

View File

@@ -57,7 +57,7 @@ void
gsk_gpu_color_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const GdkRGBA *color)
{
GskGpuColorInstance *instance;

View File

@@ -9,7 +9,7 @@ G_BEGIN_DECLS
void gsk_gpu_color_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const GdkRGBA *color);

View File

@@ -59,7 +59,7 @@ gsk_gpu_conic_gradient_op (GskGpuFrame *frame,
const graphene_rect_t *rect,
const graphene_point_t *center,
float angle,
const GskPoint *offset,
const graphene_point_t *offset,
const GskColorStop *stops,
gsize n_stops)
{

View File

@@ -13,7 +13,7 @@ void gsk_gpu_conic_gradient_op (GskGpuF
const graphene_rect_t *rect,
const graphene_point_t *center,
float angle,
const GskPoint *offset,
const graphene_point_t *offset,
const GskColorStop *stops,
gsize n_stops);

View File

@@ -59,7 +59,7 @@ gsk_gpu_cross_fade_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
GskGpuDescriptors *desc,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
float opacity,
float progress,
guint32 start_descriptor,

View File

@@ -10,7 +10,7 @@ void gsk_gpu_cross_fade_op (GskGpuF
GskGpuShaderClip clip,
GskGpuDescriptors *desc,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
float opacity,
float progress,
guint32 start_descriptor,

View File

@@ -3,17 +3,28 @@
#include "gskgpudeviceprivate.h"
#include "gskgpuframeprivate.h"
#include "gskgpuimageprivate.h"
#include "gskgpuuploadopprivate.h"
#include "gdk/gdkdisplayprivate.h"
#include "gdk/gdktextureprivate.h"
#include "gsk/gskdebugprivate.h"
#define MAX_SLICES_PER_ATLAS 64
#define ATLAS_SIZE 1024
#define MAX_ATLAS_ITEM_SIZE 256
G_STATIC_ASSERT (MAX_ATLAS_ITEM_SIZE < ATLAS_SIZE);
#define MAX_DEAD_PIXELS (ATLAS_SIZE * ATLAS_SIZE / 2)
#define CACHE_GC_TIMEOUT 1 /* seconds */
#define CACHE_MAX_AGE (G_TIME_SPAN_SECOND * 4) /* 4 seconds, in µs */
typedef struct _GskGpuCached GskGpuCached;
typedef struct _GskGpuCachedClass GskGpuCachedClass;
typedef struct _GskGpuCachedAtlas GskGpuCachedAtlas;
@@ -21,6 +32,15 @@ typedef struct _GskGpuCachedGlyph GskGpuCachedGlyph;
typedef struct _GskGpuCachedTexture GskGpuCachedTexture;
typedef struct _GskGpuDevicePrivate GskGpuDevicePrivate;
typedef struct _GlyphKey GlyphKey;
struct _GlyphKey
{
PangoFont *font;
PangoGlyph glyph;
GskGpuGlyphLookupFlags flags;
float scale;
};
struct _GskGpuDevicePrivate
{
GdkDisplay *display;
@@ -34,6 +54,11 @@ struct _GskGpuDevicePrivate
GHashTable *glyph_cache;
GskGpuCachedAtlas *current_atlas;
struct {
GlyphKey key;
GskGpuCachedGlyph *value;
} front[256];
};
G_DEFINE_TYPE_WITH_PRIVATE (GskGpuDevice, gsk_gpu_device, G_TYPE_OBJECT)
@@ -54,12 +79,34 @@ struct _GskGpuCachedClass
struct _GskGpuCached
{
const GskGpuCachedClass *class;
GskGpuCachedAtlas *atlas;
GskGpuCached *next;
GskGpuCached *prev;
gint64 timestamp;
gboolean stale;
guint pixels; /* For glyphs, pixels. For atlases, dead pixels */
};
static inline void
mark_as_stale (GskGpuCached *cached,
gboolean stale)
{
if (cached->stale != stale)
{
cached->stale = stale;
if (cached->atlas)
{
if (stale)
((GskGpuCached *) cached->atlas)->pixels += cached->pixels;
else
((GskGpuCached *) cached->atlas)->pixels -= cached->pixels;
}
}
}
static void
gsk_gpu_cached_free (GskGpuDevice *device,
GskGpuCached *cached)
@@ -75,6 +122,8 @@ gsk_gpu_cached_free (GskGpuDevice *device,
else
priv->first_cached = cached->next;
mark_as_stale (cached, TRUE);
cached->class->free (device, cached);
}
@@ -114,7 +163,8 @@ gsk_gpu_cached_use (GskGpuDevice *device,
GskGpuCached *cached,
gint64 timestamp)
{
/* FIXME */
cached->timestamp = timestamp;
mark_as_stale (cached, FALSE);
}
/* }}} */
@@ -137,10 +187,23 @@ static void
gsk_gpu_cached_atlas_free (GskGpuDevice *device,
GskGpuCached *cached)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (device);
GskGpuCachedAtlas *self = (GskGpuCachedAtlas *) cached;
GskGpuCached *c, *next;
/* Free all remaining glyphs on this atlas */
for (c = priv->first_cached; c != NULL; c = next)
{
next = c->next;
if (c->atlas == self)
gsk_gpu_cached_free (device, c);
}
if (priv->current_atlas == self)
priv->current_atlas = NULL;
g_object_unref (self->image);
g_free (self);
}
@@ -149,8 +212,7 @@ gsk_gpu_cached_atlas_should_collect (GskGpuDevice *device,
GskGpuCached *cached,
gint64 timestamp)
{
/* FIXME */
return FALSE;
return cached->pixels > MAX_DEAD_PIXELS;
}
static const GskGpuCachedClass GSK_GPU_CACHED_ATLAS_CLASS =
@@ -171,298 +233,6 @@ gsk_gpu_cached_atlas_new (GskGpuDevice *device)
return self;
}
/* }}} */
/* {{{ CachedTexture */
struct _GskGpuCachedTexture
{
GskGpuCached parent;
/* atomic */ GdkTexture *texture;
GskGpuImage *image;
};
static void
gsk_gpu_cached_texture_free (GskGpuDevice *device,
GskGpuCached *cached)
{
GskGpuCachedTexture *self = (GskGpuCachedTexture *) cached;
gboolean texture_still_alive;
texture_still_alive = g_atomic_pointer_exchange (&self->texture, NULL) != NULL;
g_object_unref (self->image);
if (!texture_still_alive)
g_free (self);
}
static gboolean
gsk_gpu_cached_texture_should_collect (GskGpuDevice *device,
GskGpuCached *cached,
gint64 timestamp)
{
/* FIXME */
return FALSE;
}
static const GskGpuCachedClass GSK_GPU_CACHED_TEXTURE_CLASS =
{
sizeof (GskGpuCachedTexture),
gsk_gpu_cached_texture_free,
gsk_gpu_cached_texture_should_collect
};
static void
gsk_gpu_cached_texture_destroy_cb (gpointer data)
{
GskGpuCachedTexture *cache = data;
gboolean cache_still_alive;
cache_still_alive = g_atomic_pointer_exchange (&cache->texture, NULL) != NULL;
if (!cache_still_alive)
g_free (cache);
}
static GskGpuCachedTexture *
gsk_gpu_cached_texture_new (GskGpuDevice *device,
GdkTexture *texture,
GskGpuImage *image)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (device);
GskGpuCachedTexture *self;
if (gdk_texture_get_render_data (texture, device))
gdk_texture_clear_render_data (texture);
else if ((self = g_hash_table_lookup (priv->texture_cache, texture)))
{
g_hash_table_remove (priv->texture_cache, texture);
g_object_weak_unref (G_OBJECT (texture), (GWeakNotify) gsk_gpu_cached_texture_destroy_cb, self);
}
self = gsk_gpu_cached_new (device, &GSK_GPU_CACHED_TEXTURE_CLASS, NULL);
self->texture = texture;
self->image = g_object_ref (image);
if (!gdk_texture_set_render_data (texture, device, self, gsk_gpu_cached_texture_destroy_cb))
{
g_object_weak_ref (G_OBJECT (texture), (GWeakNotify) gsk_gpu_cached_texture_destroy_cb, self);
g_hash_table_insert (priv->texture_cache, texture, self);
}
return self;
}
/* }}} */
/* {{{ CachedGlyph */
struct _GskGpuCachedGlyph
{
GskGpuCached parent;
PangoFont *font;
PangoGlyph glyph;
GskGpuGlyphLookupFlags flags;
float scale;
GskGpuImage *image;
graphene_rect_t bounds;
graphene_point_t origin;
};
static void
gsk_gpu_cached_glyph_free (GskGpuDevice *device,
GskGpuCached *cached)
{
GskGpuCachedGlyph *self = (GskGpuCachedGlyph *) cached;
g_object_unref (self->font);
g_object_unref (self->image);
g_free (self);
}
static gboolean
gsk_gpu_cached_glyph_should_collect (GskGpuDevice *device,
GskGpuCached *cached,
gint64 timestamp)
{
/* FIXME */
return FALSE;
}
static guint
gsk_gpu_cached_glyph_hash (gconstpointer data)
{
const GskGpuCachedGlyph *glyph = data;
return GPOINTER_TO_UINT (glyph->font) ^
glyph->glyph ^
(glyph->flags << 24) ^
((guint) glyph->scale * PANGO_SCALE);
}
static gboolean
gsk_gpu_cached_glyph_equal (gconstpointer v1,
gconstpointer v2)
{
const GskGpuCachedGlyph *glyph1 = v1;
const GskGpuCachedGlyph *glyph2 = v2;
return glyph1->font == glyph2->font
&& glyph1->glyph == glyph2->glyph
&& glyph1->flags == glyph2->flags
&& glyph1->scale == glyph2->scale;
}
static const GskGpuCachedClass GSK_GPU_CACHED_GLYPH_CLASS =
{
sizeof (GskGpuCachedGlyph),
gsk_gpu_cached_glyph_free,
gsk_gpu_cached_glyph_should_collect
};
/* }}} */
/* {{{ GskGpuDevice */
void
gsk_gpu_device_gc (GskGpuDevice *self,
gint64 timestamp)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
GskGpuCached *cached, *next;
for (cached = priv->first_cached; cached != NULL; cached = next)
{
next = cached->next;
if (gsk_gpu_cached_should_collect (self, cached, timestamp))
gsk_gpu_cached_free (self, cached);
}
}
static void
gsk_gpu_device_clear_cache (GskGpuDevice *self)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
for (GskGpuCached *cached = priv->first_cached; cached; cached = cached->next)
{
if (cached->prev == NULL)
g_assert (priv->first_cached == cached);
else
g_assert (cached->prev->next == cached);
if (cached->next == NULL)
g_assert (priv->last_cached == cached);
else
g_assert (cached->next->prev == cached);
}
while (priv->first_cached)
gsk_gpu_cached_free (self, priv->first_cached);
g_assert (priv->last_cached == NULL);
}
static void
gsk_gpu_device_dispose (GObject *object)
{
GskGpuDevice *self = GSK_GPU_DEVICE (object);
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
gsk_gpu_device_clear_cache (self);
g_hash_table_unref (priv->glyph_cache);
g_hash_table_unref (priv->texture_cache);
G_OBJECT_CLASS (gsk_gpu_device_parent_class)->dispose (object);
}
static void
gsk_gpu_device_finalize (GObject *object)
{
GskGpuDevice *self = GSK_GPU_DEVICE (object);
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
g_object_unref (priv->display);
G_OBJECT_CLASS (gsk_gpu_device_parent_class)->finalize (object);
}
static void
gsk_gpu_device_class_init (GskGpuDeviceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gsk_gpu_device_dispose;
object_class->finalize = gsk_gpu_device_finalize;
}
static void
gsk_gpu_device_init (GskGpuDevice *self)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
priv->glyph_cache = g_hash_table_new (gsk_gpu_cached_glyph_hash,
gsk_gpu_cached_glyph_equal);
priv->texture_cache = g_hash_table_new (g_direct_hash,
g_direct_equal);
}
void
gsk_gpu_device_setup (GskGpuDevice *self,
GdkDisplay *display,
gsize max_image_size)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
priv->display = g_object_ref (display);
priv->max_image_size = max_image_size;
}
GdkDisplay *
gsk_gpu_device_get_display (GskGpuDevice *self)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
return priv->display;
}
gsize
gsk_gpu_device_get_max_image_size (GskGpuDevice *self)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
return priv->max_image_size;
}
GskGpuImage *
gsk_gpu_device_create_offscreen_image (GskGpuDevice *self,
gboolean with_mipmap,
GdkMemoryDepth depth,
gsize width,
gsize height)
{
return GSK_GPU_DEVICE_GET_CLASS (self)->create_offscreen_image (self, with_mipmap, depth, width, height);
}
GskGpuImage *
gsk_gpu_device_create_upload_image (GskGpuDevice *self,
gboolean with_mipmap,
GdkMemoryFormat format,
gsize width,
gsize height)
{
return GSK_GPU_DEVICE_GET_CLASS (self)->create_upload_image (self, with_mipmap, format, width, height);
}
GskGpuImage *
gsk_gpu_device_create_download_image (GskGpuDevice *self,
GdkMemoryDepth depth,
gsize width,
gsize height)
{
return GSK_GPU_DEVICE_GET_CLASS (self)->create_download_image (self, depth, width, height);
}
/* This rounds up to the next number that has <= 2 bits set:
* 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, ...
* That is roughly sqrt(2), so it should limit waste
@@ -520,25 +290,397 @@ gsk_gpu_cached_atlas_allocate (GskGpuCachedAtlas *atlas,
if (!can_add_slice)
return FALSE;
if (y + height > ATLAS_SIZE)
return FALSE;
atlas->n_slices++;
if (atlas->n_slices == MAX_SLICES_PER_ATLAS)
atlas->slices[i].height = ATLAS_SIZE - y;
else
atlas->slices[i].height = round_up_atlas_size (MAX (height, 4));
atlas->slices[i].height = MIN (round_up_atlas_size (MAX (height, 4)), ATLAS_SIZE - y);
atlas->slices[i].width = 0;
best_y = y;
best_slice = i;
}
g_assert (best_slice < MAX_SLICES_PER_ATLAS);
*out_x = atlas->slices[best_slice].width;
*out_y = best_y;
atlas->slices[best_slice].width += width;
g_assert (atlas->slices[best_slice].height >= height);
g_assert (atlas->slices[best_slice].width <= ATLAS_SIZE);
g_assert (best_y + atlas->slices[best_slice].height <= ATLAS_SIZE);
return TRUE;
}
/* }}} */
/* {{{ CachedTexture */
struct _GskGpuCachedTexture
{
GskGpuCached parent;
/* atomic */ GdkTexture *texture;
GskGpuImage *image;
};
static void
gsk_gpu_cached_texture_free (GskGpuDevice *device,
GskGpuCached *cached)
{
GskGpuCachedTexture *self = (GskGpuCachedTexture *) cached;
gboolean texture_still_alive;
texture_still_alive = g_atomic_pointer_exchange (&self->texture, NULL) != NULL;
g_clear_object (&self->image);
if (!texture_still_alive)
g_free (self);
}
static gboolean
gsk_gpu_cached_texture_should_collect (GskGpuDevice *device,
GskGpuCached *cached,
gint64 timestamp)
{
return timestamp - cached->timestamp > CACHE_MAX_AGE;
}
static const GskGpuCachedClass GSK_GPU_CACHED_TEXTURE_CLASS =
{
sizeof (GskGpuCachedTexture),
gsk_gpu_cached_texture_free,
gsk_gpu_cached_texture_should_collect
};
static void
gsk_gpu_cached_texture_destroy_cb (gpointer data)
{
GskGpuCachedTexture *cache = data;
gboolean cache_still_alive;
cache_still_alive = g_atomic_pointer_exchange (&cache->texture, NULL) != NULL;
if (!cache_still_alive)
g_free (cache);
}
static GskGpuCachedTexture *
gsk_gpu_cached_texture_new (GskGpuDevice *device,
GdkTexture *texture,
GskGpuImage *image)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (device);
GskGpuCachedTexture *self;
if (gdk_texture_get_render_data (texture, device))
gdk_texture_clear_render_data (texture);
else if ((self = g_hash_table_lookup (priv->texture_cache, texture)))
{
g_hash_table_remove (priv->texture_cache, texture);
g_object_weak_unref (G_OBJECT (texture), (GWeakNotify) gsk_gpu_cached_texture_destroy_cb, self);
}
self = gsk_gpu_cached_new (device, &GSK_GPU_CACHED_TEXTURE_CLASS, NULL);
self->texture = texture;
self->image = g_object_ref (image);
if (!gdk_texture_set_render_data (texture, device, self, gsk_gpu_cached_texture_destroy_cb))
{
g_object_weak_ref (G_OBJECT (texture), (GWeakNotify) gsk_gpu_cached_texture_destroy_cb, self);
g_hash_table_insert (priv->texture_cache, texture, self);
}
return self;
}
/* }}} */
/* {{{ CachedGlyph */
struct _GskGpuCachedGlyph
{
GskGpuCached parent;
GlyphKey key;
GskGpuImage *image;
graphene_rect_t bounds;
graphene_point_t origin;
};
static void
gsk_gpu_cached_glyph_free (GskGpuDevice *device,
GskGpuCached *cached)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (device);
GskGpuCachedGlyph *self = (GskGpuCachedGlyph *) cached;
g_hash_table_remove (priv->glyph_cache, self);
g_object_unref (self->key.font);
g_object_unref (self->image);
g_free (self);
}
static gboolean
gsk_gpu_cached_glyph_should_collect (GskGpuDevice *device,
GskGpuCached *cached,
gint64 timestamp)
{
if (timestamp - cached->timestamp > CACHE_MAX_AGE)
mark_as_stale (cached, TRUE);
/* Glyphs are only collected when their atlas is freed */
return FALSE;
}
static guint
gsk_gpu_cached_glyph_hash (gconstpointer data)
{
const GskGpuCachedGlyph *glyph = data;
return GPOINTER_TO_UINT (glyph->key.font) ^
glyph->key.glyph ^
(glyph->key.flags << 24) ^
((guint) glyph->key.scale * PANGO_SCALE);
}
static gboolean
gsk_gpu_cached_glyph_equal (gconstpointer v1,
gconstpointer v2)
{
const GskGpuCachedGlyph *glyph1 = v1;
const GskGpuCachedGlyph *glyph2 = v2;
return glyph1->key.font == glyph2->key.font
&& glyph1->key.glyph == glyph2->key.glyph
&& glyph1->key.flags == glyph2->key.flags
&& glyph1->key.scale == glyph2->key.scale;
}
static const GskGpuCachedClass GSK_GPU_CACHED_GLYPH_CLASS =
{
sizeof (GskGpuCachedGlyph),
gsk_gpu_cached_glyph_free,
gsk_gpu_cached_glyph_should_collect
};
/* }}} */
/* {{{ GskGpuDevice */
static void
print_cache_stats (GskGpuDevice *self)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
GskGpuCached *cached;
guint glyphs = 0;
guint stale_glyphs = 0;
guint textures = 0;
guint atlases = 0;
GString *ratios = g_string_new ("");
for (cached = priv->first_cached; cached != NULL; cached = cached->next)
{
if (cached->class == &GSK_GPU_CACHED_GLYPH_CLASS)
{
glyphs++;
if (cached->stale)
stale_glyphs++;
}
else if (cached->class == &GSK_GPU_CACHED_TEXTURE_CLASS)
textures++;
else if (cached->class == &GSK_GPU_CACHED_ATLAS_CLASS)
{
double ratio;
atlases++;
ratio = (double) cached->pixels / (double) (ATLAS_SIZE * ATLAS_SIZE);
if (ratios->len == 0)
g_string_append (ratios, " (ratios ");
else
g_string_append (ratios, ", ");
g_string_append_printf (ratios, "%.2f", ratio);
}
}
if (ratios->len > 0)
g_string_append (ratios, ")");
gdk_debug_message ("cached items\n"
" glyphs: %5u (%u stale)\n"
" textures: %5u\n"
" atlases: %5u%s",
glyphs, stale_glyphs, textures, atlases, ratios->str);
g_string_free (ratios, TRUE);
}
void
gsk_gpu_device_gc (GskGpuDevice *self,
gint64 timestamp)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
GskGpuCached *cached, *prev;
/* We walk the cache from the end so we don't end up with prev
* begin a leftover glyph on the atlas we are freeing
*/
for (cached = priv->last_cached; cached != NULL; cached = prev)
{
prev = cached->prev;
if (gsk_gpu_cached_should_collect (self, cached, timestamp))
gsk_gpu_cached_free (self, cached);
}
if (GSK_DEBUG_CHECK (GLYPH_CACHE))
print_cache_stats (self);
}
static void
gsk_gpu_device_clear_cache (GskGpuDevice *self)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
for (GskGpuCached *cached = priv->first_cached; cached; cached = cached->next)
{
if (cached->prev == NULL)
g_assert (priv->first_cached == cached);
else
g_assert (cached->prev->next == cached);
if (cached->next == NULL)
g_assert (priv->last_cached == cached);
else
g_assert (cached->next->prev == cached);
}
/* We clear the cache from the end so glyphs get freed before their atlas */
while (priv->last_cached)
gsk_gpu_cached_free (self, priv->last_cached);
g_assert (priv->last_cached == NULL);
}
static void
gsk_gpu_device_dispose (GObject *object)
{
GskGpuDevice *self = GSK_GPU_DEVICE (object);
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
gsk_gpu_device_clear_cache (self);
g_hash_table_unref (priv->glyph_cache);
g_hash_table_unref (priv->texture_cache);
g_clear_handle_id (&priv->cache_gc_source, g_source_remove);
G_OBJECT_CLASS (gsk_gpu_device_parent_class)->dispose (object);
}
static void
gsk_gpu_device_finalize (GObject *object)
{
GskGpuDevice *self = GSK_GPU_DEVICE (object);
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
g_object_unref (priv->display);
G_OBJECT_CLASS (gsk_gpu_device_parent_class)->finalize (object);
}
static void
gsk_gpu_device_class_init (GskGpuDeviceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gsk_gpu_device_dispose;
object_class->finalize = gsk_gpu_device_finalize;
}
static void
gsk_gpu_device_init (GskGpuDevice *self)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
priv->glyph_cache = g_hash_table_new (gsk_gpu_cached_glyph_hash,
gsk_gpu_cached_glyph_equal);
priv->texture_cache = g_hash_table_new (g_direct_hash,
g_direct_equal);
}
static gboolean
cache_gc_source_callback (gpointer data)
{
GskGpuDevice *self = data;
gsk_gpu_device_gc (self, g_get_monotonic_time ());
return G_SOURCE_CONTINUE;
}
void
gsk_gpu_device_setup (GskGpuDevice *self,
GdkDisplay *display,
gsize max_image_size)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
priv->display = g_object_ref (display);
priv->max_image_size = max_image_size;
priv->cache_gc_source = g_timeout_add_seconds (CACHE_GC_TIMEOUT, cache_gc_source_callback, self);
}
GdkDisplay *
gsk_gpu_device_get_display (GskGpuDevice *self)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
return priv->display;
}
gsize
gsk_gpu_device_get_max_image_size (GskGpuDevice *self)
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
return priv->max_image_size;
}
GskGpuImage *
gsk_gpu_device_create_offscreen_image (GskGpuDevice *self,
gboolean with_mipmap,
GdkMemoryDepth depth,
gsize width,
gsize height)
{
return GSK_GPU_DEVICE_GET_CLASS (self)->create_offscreen_image (self, with_mipmap, depth, width, height);
}
GskGpuImage *
gsk_gpu_device_create_upload_image (GskGpuDevice *self,
gboolean with_mipmap,
GdkMemoryFormat format,
gsize width,
gsize height)
{
return GSK_GPU_DEVICE_GET_CLASS (self)->create_upload_image (self, with_mipmap, format, width, height);
}
GskGpuImage *
gsk_gpu_device_create_download_image (GskGpuDevice *self,
GdkMemoryDepth depth,
gsize width,
gsize height)
{
return GSK_GPU_DEVICE_GET_CLASS (self)->create_download_image (self, depth, width, height);
}
static void
gsk_gpu_device_ensure_atlas (GskGpuDevice *self,
gboolean recreate,
@@ -576,20 +718,14 @@ gsk_gpu_device_add_atlas_image (GskGpuDevice *self,
return NULL;
gsk_gpu_device_ensure_atlas (self, FALSE, timestamp);
if (gsk_gpu_cached_atlas_allocate (priv->current_atlas, width, height, out_x, out_y))
{
gsk_gpu_cached_use (self, (GskGpuCached *) priv->current_atlas, timestamp);
return priv->current_atlas->image;
}
return priv->current_atlas->image;
gsk_gpu_device_ensure_atlas (self, TRUE, timestamp);
if (gsk_gpu_cached_atlas_allocate (priv->current_atlas, width, height, out_x, out_y))
{
gsk_gpu_cached_use (self, (GskGpuCached *) priv->current_atlas, timestamp);
return priv->current_atlas->image;
}
return priv->current_atlas->image;
return NULL;
}
@@ -606,10 +742,8 @@ gsk_gpu_device_lookup_texture_image (GskGpuDevice *self,
if (cache == NULL)
cache = g_hash_table_lookup (priv->texture_cache, texture);
if (cache)
{
return g_object_ref (cache->image);
}
if (cache && cache->image)
return g_object_ref (cache->image);
return NULL;
}
@@ -639,10 +773,10 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
GskGpuCachedGlyph lookup = {
.font = font,
.glyph = glyph,
.flags = flags,
.scale = scale
.key.font = font,
.key.glyph = glyph,
.key.flags = flags,
.key.scale = scale
};
GskGpuCachedGlyph *cache;
PangoRectangle ink_rect;
@@ -650,14 +784,32 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
graphene_point_t origin;
GskGpuImage *image;
gsize atlas_x, atlas_y, padding;
guint64 timestamp = gsk_gpu_frame_get_timestamp (frame);
guint front_index = glyph & 0xFF;
if (memcmp (&lookup.key, &priv->front[front_index], sizeof (GlyphKey)) == 0)
{
cache = priv->front[front_index].value;
gsk_gpu_cached_use (self, (GskGpuCached *) cache, timestamp);
*out_bounds = cache->bounds;
*out_origin = cache->origin;
return cache->image;
}
cache = g_hash_table_lookup (priv->glyph_cache, &lookup);
if (cache)
{
gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame));
memcpy (&priv->front[front_index].key, &lookup.key, sizeof (GlyphKey));
priv->front[front_index].value = cache;
gsk_gpu_cached_use (self, (GskGpuCached *) cache, timestamp);
*out_bounds = cache->bounds;
*out_origin = cache->origin;
return cache->image;
}
@@ -669,7 +821,7 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
padding = 1;
image = gsk_gpu_device_add_atlas_image (self,
gsk_gpu_frame_get_timestamp (frame),
timestamp,
rect.size.width + 2 * padding, rect.size.height + 2 * padding,
&atlas_x, &atlas_y);
if (image)
@@ -688,12 +840,13 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
cache = gsk_gpu_cached_new (self, &GSK_GPU_CACHED_GLYPH_CLASS, NULL);
}
cache->font = g_object_ref (font),
cache->glyph = glyph,
cache->flags = flags,
cache->scale = scale,
cache->key.font = g_object_ref (font),
cache->key.glyph = glyph,
cache->key.flags = flags,
cache->key.scale = scale,
cache->bounds = rect,
cache->image = image,
((GskGpuCached *) cache)->pixels = (rect.size.width + 2 * padding) * (rect.size.height + 2 * padding);
cache->origin = GRAPHENE_POINT_INIT (- origin.x + (flags & 3) / 4.f,
- origin.y + ((flags >> 2) & 3) / 4.f);
@@ -712,10 +865,14 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
cache->origin.y + padding));
g_hash_table_insert (priv->glyph_cache, cache, cache);
gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame));
gsk_gpu_cached_use (self, (GskGpuCached *) cache, timestamp);
memcpy (&priv->front[front_index].key, &lookup.key, sizeof (GlyphKey));
priv->front[front_index].value = cache;
*out_bounds = cache->bounds;
*out_origin = cache->origin;
return cache->image;
}

View File

@@ -12,8 +12,6 @@
#include "gskvulkandescriptorsprivate.h"
#endif
#include "gskrectprivate.h"
typedef struct _GskGpuGlobalsOp GskGpuGlobalsOp;
struct _GskGpuGlobalsOp
@@ -89,16 +87,15 @@ static const GskGpuOpClass GSK_GPU_GLOBALS_OP_CLASS = {
void
gsk_gpu_globals_op (GskGpuFrame *frame,
const GskScale *scale,
const graphene_vec2_t *scale,
const graphene_matrix_t *mvp,
const GskRoundedRect *clip)
{
GskGpuGlobalsOp *self;
GskPoint zero = gsk_point_init (0, 0);
self = (GskGpuGlobalsOp *) gsk_gpu_op_alloc (frame, &GSK_GPU_GLOBALS_OP_CLASS);
graphene_matrix_to_float (mvp, self->instance.mvp);
gsk_gpu_rounded_rect_to_float (clip, &zero, self->instance.clip);
gsk_scale_to_float (scale, self->instance.scale);
gsk_rounded_rect_to_float (clip, graphene_point_zero (), self->instance.clip);
graphene_vec2_to_float (scale, self->instance.scale);
}

View File

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

View File

@@ -64,7 +64,7 @@ gsk_gpu_linear_gradient_op (GskGpuFrame *frame,
const graphene_rect_t *rect,
const graphene_point_t *start,
const graphene_point_t *end,
const GskPoint *offset,
const graphene_point_t *offset,
const GskColorStop *stops,
gsize n_stops)
{

View File

@@ -14,7 +14,7 @@ void gsk_gpu_linear_gradient_op (GskGpuF
const graphene_rect_t *rect,
const graphene_point_t *start,
const graphene_point_t *end,
const GskPoint *offset,
const graphene_point_t *offset,
const GskColorStop *stops,
gsize n_stops);

View File

@@ -58,7 +58,7 @@ gsk_gpu_mask_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
GskGpuDescriptors *desc,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
float opacity,
GskMaskMode mask_mode,
guint32 source_descriptor,

View File

@@ -10,7 +10,7 @@ void gsk_gpu_mask_op (GskGpuF
GskGpuShaderClip clip,
GskGpuDescriptors *desc,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
float opacity,
GskMaskMode mask_mode,
guint32 source_descriptor,

View File

@@ -40,8 +40,6 @@
#include "gskroundedrectprivate.h"
#include "gskstrokeprivate.h"
#include "gsktransformprivate.h"
#include "gskscaleprivate.h"
#include "gskpointprivate.h"
#include "gdk/gdkrgbaprivate.h"
@@ -106,12 +104,12 @@ struct _GskGpuNodeProcessor
GskGpuFrame *frame;
GskGpuDescriptors *desc;
cairo_rectangle_int_t scissor;
GskGpuClip clip;
GskGpuBlend blend;
GskPoint offset;
GskScale scale;
GskTransform *modelview;
graphene_point_t offset;
graphene_matrix_t projection;
graphene_vec2_t scale;
GskTransform *modelview;
GskGpuClip clip;
float opacity;
GskGpuGlobals pending_globals;
@@ -131,8 +129,8 @@ struct _GskGpuPatternWriter
GskGpuDescriptors *desc;
graphene_rect_t bounds;
GskPoint offset;
GskScale scale;
graphene_point_t offset;
graphene_vec2_t scale;
guint stack;
PatternBuffer buffer;
@@ -177,20 +175,24 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self,
}
else
{
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);
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
));
}
self->modelview = NULL;
gsk_gpu_image_get_projection_matrix (target, &self->projection);
self->scale = gsk_scale_init (width / viewport->size.width,
height / viewport->size.height);
self->offset = gsk_point_init (-viewport->origin.x,
-viewport->origin.y);
graphene_vec2_init (&self->scale,
width / viewport->size.width,
height / viewport->size.height);
self->offset = GRAPHENE_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;
}
@@ -302,20 +304,42 @@ 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_vec2_t *pixel_scale,
const graphene_point_t *pixel_offset,
graphene_rect_t *dest)
{
float x, y, xscale, yscale, inv_xscale, inv_yscale;
xscale = graphene_vec2_get_x (pixel_scale);
yscale = graphene_vec2_get_y (pixel_scale);
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,
(ceil ((src->origin.x + pixel_offset->x + src->size.width) * xscale) - x) * inv_xscale,
(ceil ((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 GskScale *scale,
const graphene_rect_t *viewport)
gsk_gpu_node_processor_init_draw (GskGpuNodeProcessor *self,
GskGpuFrame *frame,
GdkMemoryDepth depth,
const graphene_vec2_t *scale,
const graphene_rect_t *viewport)
{
GskGpuImage *image;
cairo_rectangle_int_t area;
area.x = 0;
area.y = 0;
area.width = ceilf (gsk_scale_get_x (*scale) * viewport->size.width);
area.height = ceilf (gsk_scale_get_y (*scale) * viewport->size.height);
area.width = ceil (graphene_vec2_get_x (scale) * viewport->size.width);
area.height = ceil (graphene_vec2_get_y (scale) * viewport->size.height);
image = gsk_gpu_device_create_offscreen_image (gsk_gpu_frame_get_device (frame),
FALSE,
@@ -374,13 +398,16 @@ gsk_gpu_node_processor_process (GskGpuFrame *frame,
static void
gsk_gpu_pattern_writer_init (GskGpuPatternWriter *self,
GskGpuFrame *frame,
const GskScale *scale,
const GskPoint *offset,
const graphene_vec2_t *scale,
const graphene_point_t *offset,
const graphene_rect_t *bounds)
{
self->frame = frame;
self->desc = NULL;
self->bounds = gsk_rect_add_offset (*bounds, *offset);
self->bounds = GRAPHENE_RECT_INIT (bounds->origin.x + offset->x,
bounds->origin.y + offset->y,
bounds->size.width,
bounds->size.height);
self->offset = *offset;
self->scale = *scale;
self->stack = 0;
@@ -449,12 +476,12 @@ gsk_gpu_pattern_writer_append_vec4 (GskGpuPatternWriter *self,
static void
gsk_gpu_pattern_writer_append_point (GskGpuPatternWriter *self,
const graphene_point_t *point,
const GskPoint *offset)
const graphene_point_t *offset)
{
float f[2];
f[0] = point->x + gsk_point_get_x (*offset);
f[1] = point->y + gsk_point_get_y (*offset);
f[0] = point->x + offset->x;
f[1] = point->y + offset->y;
gsk_gpu_pattern_writer_append (self, G_ALIGNOF (float), (guchar *) f, sizeof (f));
}
@@ -462,7 +489,7 @@ gsk_gpu_pattern_writer_append_point (GskGpuPatternWriter *self,
static void
gsk_gpu_pattern_writer_append_rect (GskGpuPatternWriter *self,
const graphene_rect_t *rect,
const GskPoint *offset)
const graphene_point_t *offset)
{
float f[4];
@@ -526,14 +553,78 @@ 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,
cairo_rectangle_int_t *int_rect)
{
graphene_rect_t transformed_rect;
float scale_x = gsk_scale_get_x (self->scale);
float scale_y = gsk_scale_get_y (self->scale);
float scale_x = graphene_vec2_get_x (&self->scale);
float scale_y = graphene_vec2_get_y (&self->scale);
switch (gsk_transform_get_category (self->modelview))
{
@@ -571,8 +662,10 @@ static void
gsk_gpu_node_processor_get_clip_bounds (GskGpuNodeProcessor *self,
graphene_rect_t *out_bounds)
{
*out_bounds = gsk_rect_init_offset (self->clip.rect.bounds,
gsk_point_negate (self->offset));
graphene_rect_offset_r (&self->clip.rect.bounds,
- self->offset.x,
- self->offset.y,
out_bounds);
/* FIXME: We could try the scissor rect here.
* But how often is that smaller than the clip bounds?
@@ -665,7 +758,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 GskScale *scale,
const graphene_vec2_t *scale,
GskRenderNode *node,
graphene_rect_t *out_bounds)
{
@@ -845,7 +938,7 @@ gsk_gpu_node_processor_get_node_as_image (GskGpuNodeProcessor *self,
return NULL;
clip_bounds = &clip;
}
clip = gsk_rect_round_to_pixels (*clip_bounds, self->scale, self->offset);
rect_round_to_pixels (clip_bounds, &self->scale, &self->offset, &clip);
image = gsk_gpu_get_node_as_image (self->frame,
&clip,
@@ -887,8 +980,9 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
GskGpuNodeProcessor other;
GskGpuImage *intermediate;
guint32 intermediate_descriptor;
graphene_vec2_t direction;
graphene_rect_t clip_rect, intermediate_rect;
GskPoint real_offset;
graphene_point_t real_offset;
int width, height;
float clip_radius;
@@ -900,8 +994,8 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
if (!gsk_rect_intersection (rect, &clip_rect, &intermediate_rect))
return;
width = ceilf (gsk_scale_get_x (self->scale) * intermediate_rect.size.width);
height = ceilf (gsk_scale_get_y (self->scale) * intermediate_rect.size.height);
width = ceil (graphene_vec2_get_x (&self->scale) * intermediate_rect.size.width);
height = ceil (graphene_vec2_get_y (&self->scale) * intermediate_rect.size.height);
intermediate = gsk_gpu_device_create_offscreen_image (gsk_gpu_frame_get_device (self->frame),
FALSE,
@@ -922,6 +1016,7 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
gsk_gpu_node_processor_sync_globals (&other, 0);
graphene_vec2_init (&direction, blur_radius, 0.0f);
gsk_gpu_blur_op (other.frame,
gsk_gpu_clip_get_shader_clip (&other.clip, &other.offset, &intermediate_rect),
source_desc,
@@ -929,7 +1024,7 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
&intermediate_rect,
&other.offset,
source_rect,
&GRAPHENE_POINT_INIT (blur_radius, 0));
&direction);
gsk_gpu_render_pass_end_op (other.frame,
intermediate,
@@ -937,7 +1032,9 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
gsk_gpu_node_processor_finish (&other);
real_offset = gsk_point_add (self->offset, gsk_point_init (shadow_offset->x, shadow_offset->y));
real_offset = GRAPHENE_POINT_INIT (self->offset.x + shadow_offset->x,
self->offset.y + shadow_offset->y);
graphene_vec2_init (&direction, 0.0f, blur_radius);
intermediate_descriptor = gsk_gpu_node_processor_add_image (self, intermediate, GSK_GPU_SAMPLER_TRANSPARENT);
if (shadow_color)
{
@@ -948,7 +1045,7 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
rect,
&real_offset,
&intermediate_rect,
&GRAPHENE_POINT_INIT (0, blur_radius),
&direction,
shadow_color);
}
else
@@ -960,7 +1057,7 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
rect,
&real_offset,
&intermediate_rect,
&GRAPHENE_POINT_INIT (0, blur_radius));
&direction);
}
g_object_unref (intermediate);
@@ -976,7 +1073,7 @@ gsk_gpu_node_processor_add_fallback_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clipped_bounds))
return;
clipped_bounds = gsk_rect_round_to_pixels (clipped_bounds, self->scale, self->offset);
rect_round_to_pixels (&clipped_bounds, &self->scale, &self->offset, &clipped_bounds);
gsk_gpu_node_processor_sync_globals (self, 0);
@@ -1198,7 +1295,9 @@ gsk_gpu_node_processor_add_node_clipped (GskGpuNodeProcessor *self,
return;
}
clip = gsk_rect_add_offset (*clip_bounds, self->offset);
graphene_rect_offset_r (clip_bounds,
self->offset.x, self->offset.y,
&clip);
gsk_gpu_clip_init_copy (&old_clip, &self->clip);
@@ -1329,8 +1428,7 @@ 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;
clip_bounds = gsk_rect_round_to_pixels (clip_bounds, self->scale, self->offset);
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
child_image = gsk_gpu_node_processor_get_node_as_image (self,
0,
@@ -1407,7 +1505,7 @@ gsk_gpu_node_processor_add_rounded_clip_node (GskGpuNodeProcessor *self,
gsk_gpu_clip_init_copy (&old_clip, &self->clip);
clip = *original_clip;
gsk_rounded_rect_offset (&clip, gsk_point_get_x (self->offset), gsk_point_get_y (self->offset));
gsk_rounded_rect_offset (&clip, self->offset.x, self->offset.y);
if (!gsk_gpu_clip_intersect_rounded_rect (&self->clip, &old_clip, &clip))
{
@@ -1436,8 +1534,8 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
{
GskRenderNode *child;
GskTransform *transform;
GskPoint old_offset;
GskScale old_scale;
graphene_point_t old_offset;
graphene_vec2_t old_scale;
GskTransform *old_modelview;
GskGpuClip old_clip;
@@ -1452,7 +1550,8 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
float dx, dy;
gsk_transform_to_translate (transform, &dx, &dy);
old_offset = self->offset;
self->offset = gsk_point_add (self->offset, gsk_point_init (dx,dy));
self->offset.x += dx;
self->offset.y += dy;
gsk_gpu_node_processor_add_node (self, child);
self->offset = old_offset;
}
@@ -1469,11 +1568,13 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
gsk_transform_to_affine (transform, &scale_x, &scale_y, &dx, &dy);
gsk_gpu_clip_scale (&self->clip, &old_clip, scale_x, scale_y);
self->offset = gsk_point_divide (gsk_point_add (self->offset, gsk_point_init (dx, dy)), gsk_scale_init (scale_x, scale_y));
self->scale = gsk_scale_multiply (old_scale, gsk_scale_init (fabsf (scale_x), fabsf (scale_y)));
self->offset.x = (self->offset.x + dx) / scale_x;
self->offset.y = (self->offset.y + dy) / scale_y;
graphene_vec2_init (&self->scale, fabs (scale_x), fabs (scale_y));
graphene_vec2_multiply (&self->scale, &old_scale, &self->scale);
self->modelview = gsk_transform_scale (self->modelview,
scale_x / fabsf (scale_x),
scale_y / fabsf (scale_y));
scale_x / fabs (scale_x),
scale_y / fabs (scale_y));
}
break;
@@ -1483,10 +1584,9 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
case GSK_TRANSFORM_CATEGORY_3D:
{
GskTransform *clip_transform;
float old_pixels, new_pixels;
GskScale scale;
float scale_x, scale_y, old_pixels, new_pixels;
clip_transform = gsk_transform_transform (gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (gsk_point_get_x (self->offset), gsk_point_get_y (self->offset))), transform);
clip_transform = gsk_transform_transform (gsk_transform_translate (NULL, &self->offset), transform);
gsk_gpu_clip_init_copy (&old_clip, &self->clip);
if (gsk_gpu_clip_contains_rect (&self->clip, &self->offset, &node->bounds))
@@ -1531,25 +1631,26 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
old_modelview = gsk_transform_ref (self->modelview);
self->modelview = gsk_transform_scale (self->modelview,
gsk_scale_get_x (self->scale),
gsk_scale_get_y (self->scale));
graphene_vec2_get_x (&self->scale),
graphene_vec2_get_y (&self->scale));
self->modelview = gsk_transform_transform (self->modelview, clip_transform);
gsk_transform_unref (clip_transform);
scale = gsk_scale_extract_from_transform (self->modelview);
extract_scale_from_transform (self->modelview, &scale_x, &scale_y);
old_pixels = gsk_scale_get_x (old_scale) * gsk_scale_get_y (old_scale) *
old_pixels = graphene_vec2_get_x (&old_scale) * graphene_vec2_get_y (&old_scale) *
old_clip.rect.bounds.size.width * old_clip.rect.bounds.size.height;
new_pixels = gsk_scale_get_x (scale) * gsk_scale_get_y (scale) *
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)
scale = gsk_scale_multiply (scale, gsk_scale_init_uniform (2 * old_pixels / new_pixels));
{
float forced_downscale = 2 * old_pixels / new_pixels;
scale_x *= forced_downscale;
scale_y *= forced_downscale;
}
self->modelview = gsk_transform_scale (self->modelview,
1 / gsk_scale_get_x (scale),
1 / gsk_scale_get_y (scale));
self->scale = scale;
self->offset = gsk_point_init (0, 0);
self->modelview = gsk_transform_scale (self->modelview, 1 / scale_x, 1 / scale_y);
graphene_vec2_init (&self->scale, scale_x, scale_y);
self->offset = *graphene_point_zero ();
}
break;
@@ -1576,8 +1677,8 @@ gsk_gpu_node_processor_create_transform_pattern (GskGpuPatternWriter *self,
{
GskRenderNode *child;
GskTransform *transform;
GskPoint old_offset;
GskScale old_scale;
graphene_point_t old_offset;
graphene_vec2_t old_scale;
graphene_rect_t old_bounds;
gboolean result;
@@ -1596,7 +1697,8 @@ gsk_gpu_node_processor_create_transform_pattern (GskGpuPatternWriter *self,
{
float dx, dy;
gsk_transform_to_translate (transform, &dx, &dy);
self->offset = gsk_point_add (self->offset, gsk_point_init (dx, dy));
self->offset.x += dx;
self->offset.y += dy;
result = gsk_gpu_node_processor_create_node_pattern (self, child);
self->offset = old_offset;
return result;
@@ -1605,21 +1707,22 @@ gsk_gpu_node_processor_create_transform_pattern (GskGpuPatternWriter *self,
case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
{
float sx, sy, dx, dy, inv_sx, inv_sy;
GskPoint p;
graphene_vec4_t vec4;
if (!gsk_gpu_pattern_writer_push_stack (self))
return FALSE;
gsk_transform_to_affine (transform, &sx, &sy, &dx, &dy);
inv_sx = 1.f / sx;
inv_sy = 1.f / sy;
p = gsk_point_add (self->offset, gsk_point_init (dx, dy));
gsk_gpu_pattern_writer_append_uint (self, GSK_GPU_PATTERN_AFFINE);
graphene_vec4_init (&vec4, gsk_point_get_x (p), gsk_point_get_y (p), inv_sx, inv_sy);
graphene_vec4_init (&vec4, self->offset.x + dx, self->offset.y + dy, inv_sx, inv_sy);
gsk_gpu_pattern_writer_append_vec4 (self, &vec4);
self->bounds = gsk_rect_scale (gsk_rect_subtract_offset (self->bounds, p),
gsk_scale_init (inv_sx, inv_sy));
self->offset = gsk_point_init (0, 0);
self->scale = gsk_scale_multiply (gsk_scale_init (fabsf (sx), fabsf (sy)), old_scale);
self->bounds.origin.x = (self->bounds.origin.x - self->offset.x - dx) * inv_sx;
self->bounds.origin.y = (self->bounds.origin.y - self->offset.y - dy) * inv_sy;
self->bounds.size.width *= inv_sx;
self->bounds.size.height *= inv_sy;
self->offset = GRAPHENE_POINT_INIT (0, 0);
graphene_vec2_init (&self->scale, fabs (sx), fabs (sy));
graphene_vec2_multiply (&self->scale, &old_scale, &self->scale);
}
break;
@@ -1641,9 +1744,9 @@ gsk_gpu_node_processor_create_transform_pattern (GskGpuPatternWriter *self,
gsk_gpu_pattern_writer_append_uint (self, GSK_GPU_PATTERN_POSITION_POP);
gsk_gpu_pattern_writer_pop_stack (self);
self->scale = old_scale;
self->bounds = old_bounds;
self->offset = old_offset;
self->scale = old_scale;
self->bounds = old_bounds;
self->offset = old_offset;
return result;
}
@@ -1668,10 +1771,11 @@ gsk_gpu_node_processor_add_color_node (GskGpuNodeProcessor *self,
cairo_rectangle_int_t int_clipped;
graphene_rect_t rect, clipped;
const GdkRGBA *color;
GskPoint zero = gsk_point_init (0, 0);
color = gsk_color_node_get_color (node);
rect = gsk_rect_add_offset (node->bounds, self->offset);
graphene_rect_offset_r (&node->bounds,
self->offset.x, self->offset.y,
&rect);
gsk_rect_intersection (&self->clip.rect.bounds, &rect, &clipped);
if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_CLEAR) &&
@@ -1702,24 +1806,24 @@ gsk_gpu_node_processor_add_color_node (GskGpuNodeProcessor *self,
return;
}
scale_x = gsk_scale_get_x (self->scale);
scale_y = gsk_scale_get_y (self->scale);
scale_x = graphene_vec2_get_x (&self->scale);
scale_y = graphene_vec2_get_y (&self->scale);
clipped = GRAPHENE_RECT_INIT (int_clipped.x / scale_x, int_clipped.y / scale_y,
int_clipped.width / scale_x, int_clipped.height / scale_y);
shader_clip = gsk_gpu_clip_get_shader_clip (&self->clip, &zero, &clipped);
shader_clip = gsk_gpu_clip_get_shader_clip (&self->clip, graphene_point_zero(), &clipped);
if (shader_clip != GSK_GPU_SHADER_CLIP_NONE)
{
gsk_rounded_rect_get_largest_cover (&self->clip.rect, &clipped, &cover);
int_clipped.x = ceilf (cover.origin.x * scale_x);
int_clipped.y = ceilf (cover.origin.y * scale_y);
int_clipped.width = floorf ((cover.origin.x + cover.size.width) * scale_x) - int_clipped.x;
int_clipped.height = floorf ((cover.origin.y + cover.size.height) * scale_y) - int_clipped.y;
int_clipped.x = ceil (cover.origin.x * scale_x);
int_clipped.y = ceil (cover.origin.y * scale_y);
int_clipped.width = floor ((cover.origin.x + cover.size.width) * scale_x) - int_clipped.x;
int_clipped.height = floor ((cover.origin.y + cover.size.height) * scale_y) - int_clipped.y;
if (int_clipped.width == 0 || int_clipped.height == 0)
{
gsk_gpu_color_op (self->frame,
shader_clip,
&clipped,
&zero,
graphene_point_zero (),
color);
return;
}
@@ -1729,13 +1833,13 @@ gsk_gpu_node_processor_add_color_node (GskGpuNodeProcessor *self,
gsk_gpu_color_op (self->frame,
shader_clip,
&GRAPHENE_RECT_INIT (clipped.origin.x, clipped.origin.y, cover.origin.x - clipped.origin.x, clipped.size.height),
&zero,
graphene_point_zero (),
color);
if (clipped.origin.y != cover.origin.y)
gsk_gpu_color_op (self->frame,
shader_clip,
&GRAPHENE_RECT_INIT (clipped.origin.x, clipped.origin.y, clipped.size.width, cover.origin.y - clipped.origin.y),
&zero,
graphene_point_zero (),
color);
if (clipped.origin.x + clipped.size.width != cover.origin.x + cover.size.width)
gsk_gpu_color_op (self->frame,
@@ -1744,7 +1848,7 @@ gsk_gpu_node_processor_add_color_node (GskGpuNodeProcessor *self,
clipped.origin.y,
clipped.origin.x + clipped.size.width - cover.origin.x - cover.size.width,
clipped.size.height),
&zero,
graphene_point_zero (),
color);
if (clipped.origin.y + clipped.size.height != cover.origin.y + cover.size.height)
gsk_gpu_color_op (self->frame,
@@ -1753,7 +1857,7 @@ gsk_gpu_node_processor_add_color_node (GskGpuNodeProcessor *self,
cover.origin.y + cover.size.height,
clipped.size.width,
clipped.origin.y + clipped.size.height - cover.origin.y - cover.size.height),
&zero,
graphene_point_zero (),
color);
}
}
@@ -1830,8 +1934,8 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self,
}
if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) &&
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * gsk_scale_get_x (self->scale) ||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * gsk_scale_get_y (self->scale)))
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * graphene_vec2_get_x (&self->scale) ||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * graphene_vec2_get_y (&self->scale)))
{
guint32 descriptor;
@@ -1897,8 +2001,8 @@ gsk_gpu_node_processor_create_texture_pattern (GskGpuPatternWriter *self,
}
if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) &&
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * gsk_scale_get_x (self->scale) ||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * gsk_scale_get_y (self->scale)))
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * graphene_vec2_get_x (&self->scale) ||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * graphene_vec2_get_y (&self->scale)))
{
image = gsk_gpu_node_processor_ensure_image (self->frame,
image,
@@ -1941,18 +2045,18 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
guint32 descriptor;
gboolean need_mipmap, need_offscreen;
need_offscreen = self->modelview != NULL || !gsk_scale_is_one (self->scale);
need_offscreen = self->modelview != NULL ||
!graphene_vec2_equal (&self->scale, graphene_vec2_one ());
if (need_offscreen)
{
GskGpuImage *offscreen;
graphene_rect_t clip_bounds;
GskScale one = gsk_scale_init (1, 1);
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
return;
clip_bounds = gsk_rect_round_larger (clip_bounds);
gsk_rect_round_larger (&clip_bounds);
offscreen = gsk_gpu_render_pass_op_offscreen (self->frame,
&one,
graphene_vec2_one (),
&clip_bounds,
node);
descriptor = gsk_gpu_node_processor_add_image (self, offscreen, GSK_GPU_SAMPLER_DEFAULT);
@@ -2148,8 +2252,7 @@ gsk_gpu_node_processor_add_gradient_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &bounds))
return;
bounds = gsk_rect_round_to_pixels (bounds, self->scale, self->offset);
rect_round_to_pixels (&bounds, &self->scale, &self->offset, &bounds);
image = gsk_gpu_node_processor_init_draw (&other,
self->frame,
@@ -2444,7 +2547,8 @@ gsk_gpu_node_processor_add_shadow_node (GskGpuNodeProcessor *self,
const GskShadow *shadow = gsk_shadow_node_get_shadow (node, i);
if (shadow->radius == 0)
{
GskPoint shadow_offset = gsk_point_add (self->offset, gsk_point_init (shadow->dx, shadow->dy));
graphene_point_t shadow_offset = GRAPHENE_POINT_INIT (self->offset.x + shadow->dx,
self->offset.y + shadow->dy);
gsk_gpu_colorize_op (self->frame,
gsk_gpu_clip_get_shader_clip (&self->clip, &shadow_offset, &child->bounds),
desc,
@@ -2870,9 +2974,9 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
GskGpuDevice *device;
const PangoGlyphInfo *glyphs;
PangoFont *font;
GskPoint offset;
graphene_point_t offset;
guint i, num_glyphs;
GskScale scale, inv;
float scale, inv_scale;
GdkRGBA color;
if (self->opacity < 1.0 &&
@@ -2888,17 +2992,18 @@ 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_point_add (gsk_point_init_from_graphene (gsk_text_node_get_offset (node)), self->offset);
offset = *gsk_text_node_get_offset (node);
offset.x += self->offset.x;
offset.y += self->offset.y;
scale = gsk_scale_max (self->scale);
inv = gsk_scale_invert (scale);
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
inv_scale = 1.f / scale;
for (i = 0; i < num_glyphs; i++)
{
GskGpuImage *image;
graphene_rect_t glyph_bounds, glyph_tex_rect;
graphene_point_t glyph_offset;
GskPoint g_offset;
guint32 descriptor;
image = gsk_gpu_device_lookup_glyph_image (device,
@@ -2906,36 +3011,34 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
font,
glyphs[i].glyph,
0,
gsk_scale_get_x (scale),
scale,
&glyph_bounds,
&glyph_offset);
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);
g_offset = gsk_point_add (gsk_point_add (offset, gsk_point_divide (gsk_point_init_from_graphene (&glyph_offset), scale)),
gsk_point_init (glyphs[i].geometry.x_offset/(float)PANGO_SCALE,
glyphs[i].geometry.y_offset/(float)PANGO_SCALE));
graphene_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);
graphene_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);
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,
gsk_gpu_clip_get_shader_clip (&self->clip, &g_offset, &glyph_bounds),
gsk_gpu_clip_get_shader_clip (&self->clip, &glyph_offset, &glyph_bounds),
self->desc,
descriptor,
&glyph_bounds,
&g_offset,
&glyph_offset,
&glyph_tex_rect);
else
gsk_gpu_colorize_op (self->frame,
gsk_gpu_clip_get_shader_clip (&self->clip, &g_offset, &glyph_bounds),
gsk_gpu_clip_get_shader_clip (&self->clip, &glyph_offset, &glyph_bounds),
self->desc,
descriptor,
&glyph_bounds,
&g_offset,
&glyph_offset,
&glyph_tex_rect,
&color);
offset = gsk_point_add (offset, gsk_point_init ((float) glyphs[i].geometry.width / PANGO_SCALE, 0));
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
}
}
@@ -2948,10 +3051,10 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
PangoFont *font;
guint num_glyphs;
gsize i;
GskScale scale, inv;
float scale, inv_scale;
guint32 tex_id;
GskGpuImage *last_image;
GskPoint offset;
graphene_point_t offset;
if (gsk_text_node_has_color_glyphs (node))
return FALSE;
@@ -2960,10 +3063,12 @@ 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_point_add (gsk_point_init_from_graphene (gsk_text_node_get_offset (node)), self->offset);
offset = *gsk_text_node_get_offset (node);
offset.x += self->offset.x;
offset.y += self->offset.y;
scale = gsk_scale_max (self->scale);
inv = gsk_scale_invert (scale);
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
inv_scale = 1.f / 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));
@@ -2975,15 +3080,13 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
GskGpuImage *image;
graphene_rect_t glyph_bounds;
graphene_point_t glyph_offset;
GskPoint g_offset;
graphene_rect_t rect;
image = gsk_gpu_device_lookup_glyph_image (device,
self->frame,
font,
glyphs[i].glyph,
0,
gsk_scale_get_x (scale),
scale,
&glyph_bounds,
&glyph_offset);
@@ -2995,22 +3098,28 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
last_image = image;
}
g_offset = gsk_point_add (gsk_point_add (offset, gsk_point_divide (gsk_point_init_from_graphene (&glyph_offset), scale)),
gsk_point_init (glyphs[i].geometry.x_offset / (float)PANGO_SCALE,
glyphs[i].geometry.y_offset / (float)PANGO_SCALE));
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);
gsk_gpu_pattern_writer_append_uint (self, tex_id);
rect = gsk_rect_scale (GRAPHENE_RECT_INIT (0, 0, glyph_bounds.size.width, glyph_bounds.size.height),
inv);
gsk_gpu_pattern_writer_append_rect (self, &rect, &g_offset);
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);
gsk_gpu_pattern_writer_append_rect (self, &rect, &g_offset);
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_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_offset);
offset = gsk_point_add (offset, gsk_point_init ((float) glyphs[i].geometry.width / PANGO_SCALE, 0));
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
}
return TRUE;
@@ -3110,10 +3219,10 @@ gsk_gpu_node_processor_repeat_tile (GskGpuNodeProcessor *self,
graphene_rect_t clipped_child_bounds, offset_rect;
guint32 descriptor;
offset_rect = gsk_rect_init_offset (*rect,
gsk_point_multiply (gsk_point_init (child_bounds->size.width, child_bounds->size.height),
gsk_scale_init (-x, -y)));
gsk_rect_init_offset (&offset_rect,
rect,
- 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. */
@@ -3242,21 +3351,23 @@ gsk_gpu_node_processor_add_repeat_node (GskGpuNodeProcessor *self,
else
{
/* repeat in both directions */
GskPoint old_offset, offset;
graphene_point_t old_offset, offset;
graphene_rect_t clip_bounds;
float x, y, offset_x, offset_y;
float x, y;
old_offset = self->offset;
for (x = floorf (tile_left); x < ceilf (tile_right); x++)
{
offset_x = x * child_bounds->size.width;
offset.x = x * child_bounds->size.width;
for (y = floorf (tile_top); y < ceilf (tile_bottom); y++)
{
offset_y = y * child_bounds->size.height;
offset = gsk_point_init (offset_x, offset_y);
self->offset = gsk_point_add (old_offset, offset);
clip_bounds = gsk_rect_subtract_offset (bounds, offset);
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);
if (!gsk_rect_intersection (&clip_bounds, child_bounds, &clip_bounds))
continue;
gsk_gpu_node_processor_add_node_clipped (self,
@@ -3297,7 +3408,10 @@ 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 = gsk_rect_add_offset (*child_bounds, self->offset);
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);
if (!gsk_gpu_node_processor_create_node_pattern (self, child))
{
@@ -3369,8 +3483,7 @@ gsk_gpu_node_processor_add_fill_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
return;
clip_bounds = gsk_rect_round_to_pixels (clip_bounds, self->scale, self->offset);
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
child = gsk_fill_node_get_child (node);
@@ -3467,8 +3580,7 @@ gsk_gpu_node_processor_add_stroke_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
return;
clip_bounds = gsk_rect_round_to_pixels (clip_bounds, self->scale, self->offset);
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
child = gsk_stroke_node_get_child (node);
@@ -3542,9 +3654,15 @@ gsk_gpu_node_processor_add_subsurface_node (GskGpuNodeProcessor *self,
if (!gdk_subsurface_is_above_parent (subsurface))
{
cairo_rectangle_int_t int_rect;
graphene_rect_t r = gsk_rect_add_offset (node->bounds, self->offset);
if (!gsk_gpu_node_processor_rect_is_integer (self, &r, &int_rect))
if (!gsk_gpu_node_processor_rect_is_integer (self,
&GRAPHENE_RECT_INIT (
node->bounds.origin.x + self->offset.x,
node->bounds.origin.y + self->offset.y,
node->bounds.size.width,
node->bounds.size.height
),
&int_rect))
{
g_warning ("FIXME: non-integer aligned subsurface?!");
}
@@ -3798,7 +3916,6 @@ gsk_gpu_node_processor_add_node (GskGpuNodeProcessor *self,
* there's quaranteed to be at least 1 pixel that needs to be drawn */
if (node->bounds.size.width == 0 || node->bounds.size.height == 0)
return;
if (!gsk_gpu_clip_may_intersect_rect (&self->clip, &self->offset, &node->bounds))
return;
@@ -3862,9 +3979,15 @@ gsk_gpu_node_processor_create_node_pattern (GskGpuPatternWriter *self,
gsk_gpu_descriptors_set_size (self->desc, images_before, buffers_before);
}
bounds = gsk_rect_round_to_pixels (gsk_rect_subtract_offset (self->bounds, self->offset),
self->scale,
self->offset);
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);
image = gsk_gpu_get_node_as_image (self->frame,
&bounds,
&self->scale,

View File

@@ -66,12 +66,11 @@ gsk_gpu_radial_gradient_op (GskGpuFrame *frame,
const graphene_point_t *radius,
float start,
float end,
const GskPoint *offset,
const graphene_point_t *offset,
const GskColorStop *stops,
gsize n_stops)
{
GskGpuRadialgradientInstance *instance;
GskPoint zero = gsk_point_init (0, 0);
g_assert (n_stops > 1);
g_assert (n_stops <= 7);
@@ -86,7 +85,7 @@ gsk_gpu_radial_gradient_op (GskGpuFrame *frame,
gsk_gpu_rect_to_float (rect, offset, instance->rect);
gsk_gpu_point_to_float (center, offset, instance->center_radius);
gsk_gpu_point_to_float (radius, &zero, &instance->center_radius[2]);
gsk_gpu_point_to_float (radius, graphene_point_zero(), &instance->center_radius[2]);
instance->startend[0] = start;
instance->startend[1] = end;
gsk_gpu_rgba_to_float (&stops[MIN (n_stops - 1, 6)].color, instance->color6);

View File

@@ -16,7 +16,7 @@ void gsk_gpu_radial_gradient_op (GskGpuF
const graphene_point_t *radius,
float start,
float end,
const GskPoint *offset,
const graphene_point_t *offset,
const GskColorStop *stops,
gsize n_stops);

View File

@@ -335,16 +335,16 @@ gsk_gpu_render_pass_end_op (GskGpuFrame *frame,
}
GskGpuImage *
gsk_gpu_render_pass_op_offscreen (GskGpuFrame *frame,
const GskScale *scale,
const graphene_rect_t *viewport,
GskRenderNode *node)
gsk_gpu_render_pass_op_offscreen (GskGpuFrame *frame,
const graphene_vec2_t *scale,
const graphene_rect_t *viewport,
GskRenderNode *node)
{
GskGpuImage *image;
int width, height;
width = ceil (gsk_scale_get_x (*scale) * viewport->size.width);
height = ceil (gsk_scale_get_y (*scale) * viewport->size.height);
width = ceil (graphene_vec2_get_x (scale) * viewport->size.width);
height = ceil (graphene_vec2_get_y (scale) * viewport->size.height);
image = gsk_gpu_device_create_offscreen_image (gsk_gpu_frame_get_device (frame),
FALSE,

View File

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

View File

@@ -57,7 +57,7 @@ void
gsk_gpu_rounded_color_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
const GskRoundedRect *outline,
const GskPoint *offset,
const graphene_point_t *offset,
const GdkRGBA *color)
{
GskGpuRoundedcolorInstance *instance;
@@ -69,7 +69,7 @@ gsk_gpu_rounded_color_op (GskGpuFrame *frame,
NULL,
&instance);
gsk_gpu_rounded_rect_to_float (outline, offset, instance->outline);
gsk_rounded_rect_to_float (outline, offset, instance->outline);
gsk_gpu_rgba_to_float (color, instance->color);
}

View File

@@ -10,7 +10,7 @@ G_BEGIN_DECLS
void gsk_gpu_rounded_color_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
const GskRoundedRect *outline,
const GskPoint *offset,
const graphene_point_t *offset,
const GdkRGBA *color);

View File

@@ -3,7 +3,6 @@
#include "gskgpuopprivate.h"
#include "gskgputypesprivate.h"
#include "gskpointprivate.h"
G_BEGIN_DECLS
@@ -70,11 +69,11 @@ gsk_gpu_rgba_to_float (const GdkRGBA *rgba,
static inline void
gsk_gpu_point_to_float (const graphene_point_t *point,
const GskPoint *offset,
const graphene_point_t *offset,
float values[2])
{
values[0] = point->x + gsk_point_get_x (*offset);
values[1] = point->y + gsk_point_get_y (*offset);
values[0] = point->x + offset->x;
values[1] = point->y + offset->y;
}
G_END_DECLS

View File

@@ -62,7 +62,7 @@ gsk_gpu_straight_alpha_op (GskGpuFrame *frame,
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect)
{
GskGpuStraightalphaInstance *instance;

View File

@@ -12,7 +12,7 @@ void gsk_gpu_straight_alpha_op (GskGpuF
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect);

View File

@@ -58,7 +58,7 @@ gsk_gpu_texture_op (GskGpuFrame *frame,
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect)
{
GskGpuTextureInstance *instance;

View File

@@ -11,7 +11,7 @@ void gsk_gpu_texture_op (GskGpuF
GskGpuDescriptors *desc,
guint32 descriptor,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect);

View File

@@ -2,7 +2,6 @@
#include <gdk/gdk.h>
#include "gsk/gskenums.h"
#include "gsk/gsktypes.h"
#include "gdk/gdkmemoryformatprivate.h"

View File

@@ -56,7 +56,7 @@ void
gsk_gpu_uber_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
GskGpuDescriptors *desc,
guint32 pattern_id)
{

View File

@@ -9,7 +9,7 @@ G_BEGIN_DECLS
void gsk_gpu_uber_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
GskGpuDescriptors *desc,
guint32 pattern_id);

View File

@@ -451,12 +451,12 @@ static const GskGpuOpClass GSK_GPU_UPLOAD_CAIRO_OP_CLASS = {
};
GskGpuImage *
gsk_gpu_upload_cairo_op (GskGpuFrame *frame,
const GskScale *scale,
const graphene_rect_t *viewport,
GskGpuCairoFunc func,
gpointer user_data,
GDestroyNotify user_destroy)
gsk_gpu_upload_cairo_op (GskGpuFrame *frame,
const graphene_vec2_t *scale,
const graphene_rect_t *viewport,
GskGpuCairoFunc func,
gpointer user_data,
GDestroyNotify user_destroy)
{
GskGpuUploadCairoOp *self;
@@ -465,8 +465,8 @@ gsk_gpu_upload_cairo_op (GskGpuFrame *frame,
self->image = gsk_gpu_device_create_upload_image (gsk_gpu_frame_get_device (frame),
FALSE,
GDK_MEMORY_DEFAULT,
ceil (gsk_scale_get_x (*scale) * viewport->size.width),
ceil (gsk_scale_get_y (*scale) * viewport->size.height));
ceil (graphene_vec2_get_x (scale) * viewport->size.width),
ceil (graphene_vec2_get_y (scale) * viewport->size.height));
self->viewport = *viewport;
self->func = func;
self->user_data = user_data;

View File

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

View File

@@ -1,157 +1,20 @@
#pragma once
#include "gsktypes.h"
#include <graphene.h>
#include <math.h>
#include <smmintrin.h>
#include "gskscaleprivate.h"
struct _GskPoint
static inline void G_GNUC_PURE
gsk_point_interpolate (const graphene_point_t *p1,
const graphene_point_t *p2,
float t,
graphene_point_t *p)
{
GRAPHENE_ALIGNED_DECL (graphene_simd4f_t v, 16);
};
static inline float
gsk_point_get_x (const GskPoint p)
{
return graphene_simd4f_get_x (p.v);
p->x = p1->x * (1 - t) + p2->x * t;
p->Y = p1->y * (1 - t) + p2->y * t;
}
static inline float
gsk_point_get_y (const GskPoint p)
static inline float G_GNUC_PURE
gsk_point_distance (const graphene_point_t *p1,
const graphene_point_t *p2)
{
return graphene_simd4f_get_y (p.v);
return sqrtf ((p1->x - p2->x)*(p1->x - p2->x) + (p1->y - p2->y)*(p1->y - p2->y));
}
static inline GskPoint
gsk_point_init (float x,
float y)
{
GskPoint p;
p.v = graphene_simd4f_init (x, y, 0.f, 0.f);
return p;
}
static inline GskPoint
gsk_point_init_from_graphene (const graphene_point_t *p)
{
return gsk_point_init (p->x, p->y);
}
static inline void
gsk_point_to_float (const GskPoint *p,
float v[2])
{
graphene_simd4f_dup_2f (p->v, v);
}
static inline gboolean
gsk_point_is_zero (const GskPoint p)
{
return gsk_point_get_x (p) == 0 && gsk_point_get_y (p) == 0;
}
static inline GskPoint
gsk_point_negate (const GskPoint p)
{
GskPoint neg;
neg.v = graphene_simd4f_neg (p.v);
return neg;
}
static inline GskPoint
gsk_point_multiply (const GskPoint p,
const GskScale s)
{
GskPoint q;
q.v = graphene_simd4f_mul (p.v, s.v);
return q;
}
static inline GskPoint
gsk_point_divide (const GskPoint p,
const GskScale s)
{
GskPoint q;
q.v = graphene_simd4f_div (p.v, s.v);
return q;
}
static inline GskPoint
gsk_point_add (const GskPoint p1,
const GskPoint p2)
{
GskPoint p;
p.v = graphene_simd4f_add (p1.v, p2.v);
return p;
}
static inline GskPoint
gsk_point_subtract (const GskPoint p1,
const GskPoint p2)
{
GskPoint p;
p.v = graphene_simd4f_sub (p1.v, p2.v);
return p;
}
#ifdef HAVE_SSE4
# define graphene_simd4f_floor(v) \
(__extension__ ({ \
(graphene_simd4f_t) _mm_floor_ps ((v)); \
}))
# define graphene_simd4f_ceil(v) \
(__extension__ ({ \
(graphene_simd4f_t) _mm_ceil_ps ((v)); \
}))
static inline GskPoint
gsk_point_floor (const GskPoint p)
{
GskPoint q;
q.v = graphene_simd4f_floor (p.v);
return q;
}
static inline GskPoint
gsk_point_ceil (const GskPoint p)
{
GskPoint q;
q.v = graphene_simd4f_ceil (p.v);
return q;
}
#else
static inline GskPoint
gsk_point_floor (const GskPoint p)
{
return gsk_point_init (floorf (gsk_point_get_x (p)), floorf (gsk_point_get_y (p)));
}
static inline GskPoint
gsk_point_ceil (const GskPoint p)
{
return gsk_point_init (ceilf (gsk_point_get_x (p)), ceilf (gsk_point_get_y (p)));
}
#endif

View File

@@ -2,9 +2,6 @@
#include <graphene.h>
#include <math.h>
#include "gskscaleprivate.h"
#include "gskpointprivate.h"
static inline void
gsk_rect_init (graphene_rect_t *r,
@@ -26,14 +23,13 @@ gsk_rect_init_from_rect (graphene_rect_t *r,
gsk_rect_init (r, r1->origin.x, r1->origin.y, r1->size.width, r1->size.height);
}
static inline graphene_rect_t
gsk_rect_init_offset (const graphene_rect_t src,
const GskPoint offset)
static inline void
gsk_rect_init_offset (graphene_rect_t *r,
const graphene_rect_t *src,
float dx,
float dy)
{
return GRAPHENE_RECT_INIT (src.origin.x + gsk_point_get_x (offset),
src.origin.y + gsk_point_get_y (offset),
src.size.width,
src.size.height);
gsk_rect_init (r, src->origin.x + dx, src->origin.y + dy, src->size.width, src->size.height);
}
static inline gboolean G_GNUC_PURE
@@ -117,98 +113,22 @@ gsk_rect_equal (const graphene_rect_t *r1,
static inline void
gsk_gpu_rect_to_float (const graphene_rect_t *rect,
const GskPoint *offset,
const graphene_point_t *offset,
float values[4])
{
values[0] = rect->origin.x + gsk_point_get_x (*offset);
values[1] = rect->origin.y + gsk_point_get_y (*offset);
values[0] = rect->origin.x + offset->x;
values[1] = rect->origin.y + offset->y;
values[2] = rect->size.width;
values[3] = rect->size.height;
}
static inline graphene_rect_t
gsk_rect_round_larger (const graphene_rect_t rect)
static inline void
gsk_rect_round_larger (graphene_rect_t *rect)
{
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);
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);
}
static inline graphene_rect_t
gsk_rect_scale (const graphene_rect_t r,
const GskScale scale)
{
float sx = gsk_scale_get_x (scale);
float sy = gsk_scale_get_y (scale);
if (G_UNLIKELY (sx < 0 || sy < 0))
{
graphene_rect_t res;
graphene_rect_scale (&r, sx, sy, &res);
return res;
}
return GRAPHENE_RECT_INIT (r.origin.x * sx,
r.origin.y * sy,
r.size.width * sx,
r.size.height * sy);
}
static inline graphene_rect_t
gsk_rect_add_offset (const graphene_rect_t r,
const GskPoint offset)
{
return GRAPHENE_RECT_INIT (r.origin.x + gsk_point_get_x (offset),
r.origin.y + gsk_point_get_y (offset),
r.size.width,
r.size.height);
}
static inline graphene_rect_t
gsk_rect_subtract_offset (const graphene_rect_t r,
const GskPoint offset)
{
return GRAPHENE_RECT_INIT (r.origin.x - gsk_point_get_x (offset),
r.origin.y - gsk_point_get_y (offset),
r.size.width,
r.size.height);
}
static inline graphene_rect_t
gsk_rect_from_points (GskPoint p0,
GskPoint p1)
{
return GRAPHENE_RECT_INIT (gsk_point_get_x (p0),
gsk_point_get_y (p0),
gsk_point_get_x (p1) - gsk_point_get_x (p0),
gsk_point_get_y (p1) - gsk_point_get_y (p0));
}
static inline GskPoint
gsk_rect_get_origin (const graphene_rect_t rect)
{
return gsk_point_init (rect.origin.x, rect.origin.y);
}
static inline GskPoint
gsk_rect_get_opposite (const graphene_rect_t rect)
{
return gsk_point_init (rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
}
static inline graphene_rect_t
gsk_rect_round_to_pixels (const graphene_rect_t src,
const GskScale scale,
const GskPoint offset)
{
GskPoint p0, p1;
p0 = gsk_point_subtract (gsk_point_divide (gsk_point_floor (gsk_point_multiply (gsk_point_add (gsk_rect_get_origin (src), offset), scale)), scale), offset);
p1 = gsk_point_divide (gsk_point_subtract (gsk_point_ceil (gsk_point_multiply (gsk_point_add (gsk_rect_get_opposite (src), offset), scale)), p0), scale);
return gsk_rect_from_points (p0, p1);
}

View File

@@ -311,8 +311,8 @@ gsk_rounded_rect_scale_affine (GskRoundedRect *dest,
graphene_rect_scale (&src->bounds, scale_x, scale_y, &dest->bounds);
graphene_rect_offset (&dest->bounds, dx, dy);
scale_x = fabsf (scale_x);
scale_y = fabsf (scale_y);
scale_x = fabs (scale_x);
scale_y = fabs (scale_y);
for (guint i = 0; i < 4; i++)
{

View File

@@ -1,7 +1,6 @@
#pragma once
#include "gskroundedrect.h"
#include "gskrectprivate.h"
#include <cairo.h>
@@ -49,21 +48,6 @@ void gsk_rounded_rect_path (const GskRounde
void gsk_rounded_rect_to_float (const GskRoundedRect *self,
const graphene_point_t *offset,
float rect[12]);
static inline void
gsk_gpu_rounded_rect_to_float (const GskRoundedRect *self,
const GskPoint *offset,
float rect[12])
{
guint i;
gsk_gpu_rect_to_float (&self->bounds, offset, rect);
for (i = 0; i < 4; i++)
{
rect[4 + i] = self->corner[i].width;
rect[8 + i] = self->corner[i].height;
}
}
gboolean gsk_rounded_rect_equal (gconstpointer rect1,
gconstpointer rect2) G_GNUC_PURE;

View File

@@ -1,59 +0,0 @@
#include "config.h"
#include "gskscaleprivate.h"
#include "gsktransform.h"
GskScale
gsk_scale_extract_from_transform (GskTransform *transform)
{
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:
return gsk_scale_init (1, 1);
case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
{
float scale_x, scale_y, dx, dy;
gsk_transform_to_affine (transform, &scale_x, &scale_y, &dx, &dy);
return gsk_scale_init (fabsf (scale_x), fabsf (scale_y));
}
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);
return gsk_scale_init (fabsf (scale_x), fabsf (scale_y));
}
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);
return gsk_scale_init (fabsf (graphene_vec3_get_x (&matrix_scale)),
fabsf (graphene_vec3_get_y (&matrix_scale)));
}
}
}

View File

@@ -1,108 +0,0 @@
#pragma once
#include "gsktypes.h"
#include <graphene.h>
#include <math.h>
struct _GskScale
{
GRAPHENE_ALIGNED_DECL (graphene_simd4f_t v, 16);
};
static inline float
gsk_scale_get_x (const GskScale s)
{
return graphene_simd4f_get_x (s.v);
}
static inline float
gsk_scale_get_y (const GskScale s)
{
return graphene_simd4f_get_y (s.v);
}
static inline GskScale
gsk_scale_init (float x,
float y)
{
GskScale s;
s.v = graphene_simd4f_init (x, y, 0.f, 0.f);
return s;
}
static inline GskScale
gsk_scale_init_uniform (float x)
{
return gsk_scale_init (x, x);
}
static inline void
gsk_scale_to_float (const GskScale *s,
float v[2])
{
graphene_simd4f_dup_2f (s->v, v);
}
static inline gboolean
gsk_scale_is_one (const GskScale s)
{
return gsk_scale_get_x (s) == 1 && gsk_scale_get_y (s) == 1;
}
static inline gboolean
gsk_scale_is_uniform (const GskScale s)
{
return gsk_scale_get_x (s) == gsk_scale_get_y (s);
}
static inline GskScale
gsk_scale_invert (const GskScale s)
{
GskScale inv;
inv.v = graphene_simd4f_reciprocal (s.v);
return inv;
}
static inline GskScale
gsk_scale_multiply (const GskScale s1,
const GskScale s2)
{
GskScale s;
s.v = graphene_simd4f_mul (s1.v, s2.v);
return s;
}
static inline GskScale
gsk_scale_divide (const GskScale s1,
const GskScale s2)
{
GskScale s;
s.v = graphene_simd4f_div (s1.v, s2.v);
return s;
}
# define graphene_simd4f_shuffle_yxzw(v) \
(__extension__ ({ \
(graphene_simd4f_t) _mm_shuffle_ps ((v), (v), _MM_SHUFFLE (1, 0, 2, 3)); \
}))
static inline GskScale
gsk_scale_max (const GskScale s)
{
GskScale m;
m.v = graphene_simd4f_max (graphene_simd4f_shuffle_yxzw (s.v), s.v);
return m;
}
GskScale gsk_scale_extract_from_transform (GskTransform *transform);

View File

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

View File

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

View File

@@ -403,7 +403,7 @@ gtk_file_chooser_set_current_folder (GtkFileChooser *chooser,
GError **error)
{
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE);
g_return_val_if_fail (file == NULL || G_IS_FILE (file), FALSE);
g_return_val_if_fail (G_IS_FILE (file), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
return GTK_FILE_CHOOSER_GET_IFACE (chooser)->set_current_folder (chooser, file, error);

View File

@@ -44,15 +44,6 @@ void gtk_graphics_offload_set_child (GtkGraphicsOffload *
GDK_AVAILABLE_IN_4_14
GtkWidget * gtk_graphics_offload_get_child (GtkGraphicsOffload *self);
/**
* GtkGraphicsOffloadEnabled:
* @GTK_GRAPHICS_OFFLOAD_ENABLED: Graphics offloading is enabled.
* @GTK_GRAPHICS_OFFLOAD_DISABLED: Graphics offloading is disabled.
*
* Represents the state of graphics offlodading.
*
* Since: 4.14
*/
typedef enum
{
GTK_GRAPHICS_OFFLOAD_ENABLED,

View File

@@ -159,7 +159,7 @@
</object>
</child>
<child>
<object class="GtkCheckButton" id="verbose">
<object class="GtkCheckButton" id="verboe">
<property name="label">Verbose</property>
<signal name="toggled" handler="flag_toggled"/>
</object>

View File

@@ -22,8 +22,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gtk+.master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gtk/-/issues/\n"
"POT-Creation-Date: 2024-01-16 17:25+0000\n"
"PO-Revision-Date: 2024-01-16 22:49+0300\n"
"POT-Creation-Date: 2024-01-08 02:46+0000\n"
"PO-Revision-Date: 2024-01-08 15:00+0300\n"
"Last-Translator: Artur So <arturios2005@mail.ru>\n"
"Language-Team: Русский <gnome-cyr@gnome.org>\n"
"Language: ru\n"
@@ -867,11 +867,6 @@ msgid "This GLES %d.%d implementation does not support half-float vertex data"
msgstr ""
"Данная реализация GLES %d.%d не поддерживает полуплавающие вершинные данные"
#: gsk/gpu/gskgldevice.c:238
#, c-format
msgid "OpenGL ES 2.0 is not supported by this renderer."
msgstr "OpenGL ES 2.0 не поддерживается этим рендерером."
#: gtk/a11y/gtkatspiaction.c:239
msgctxt "accessibility"
msgid "Click"
@@ -2690,7 +2685,7 @@ msgstr "Вариации стилей"
msgid "Character Variations"
msgstr "Вариации символов"
#: gtk/gtkglarea.c:309
#: gtk/gtkglarea.c:305
msgid "OpenGL context creation failed"
msgstr "Не удалось создать контекст OpenGL"
@@ -7308,7 +7303,7 @@ msgid "Use style from CSS file"
msgstr "Использовать стиль из файла CSS"
#: tools/gtk-builder-tool-preview.c:187 tools/gtk-builder-tool-screenshot.c:370
#: tools/gtk-builder-tool-validate.c:268 tools/gtk-rendernode-tool-render.c:203
#: tools/gtk-builder-tool-validate.c:268 tools/gtk-rendernode-tool-render.c:204
#: tools/gtk-rendernode-tool-show.c:113
#, c-format
msgid "Could not initialize windowing system\n"
@@ -7354,13 +7349,13 @@ msgstr ""
"Используйте --force для перезаписи.\n"
#: tools/gtk-builder-tool-screenshot.c:332
#: tools/gtk-rendernode-tool-render.c:171
#: tools/gtk-rendernode-tool-render.c:172
#, c-format
msgid "Output written to %s.\n"
msgstr "Выход записывается в %s.\n"
#: tools/gtk-builder-tool-screenshot.c:336
#: tools/gtk-rendernode-tool-render.c:175
#: tools/gtk-rendernode-tool-render.c:176
#, c-format
msgid "Failed to save %s: %s\n"
msgstr "Не удалось сохранить %s: %s\n"
@@ -7378,7 +7373,7 @@ msgid "Overwrite existing file"
msgstr "Перезаписать существующий файл"
#: tools/gtk-builder-tool-screenshot.c:363
#: tools/gtk-rendernode-tool-render.c:196
#: tools/gtk-rendernode-tool-render.c:197
msgid "FILE…"
msgstr "ФАЙЛ…"
@@ -7849,7 +7844,6 @@ msgid ""
"Perform various tasks on GTK render nodes.\n"
"\n"
"Commands:\n"
" benchmark Benchmark rendering of a node\n"
" info Provide information about the node\n"
" show Show the node\n"
" render Take a screenshot of the node\n"
@@ -7861,7 +7855,6 @@ msgstr ""
"Выполнение различных задач на узлах рендеринга GTK.\n"
"\n"
"Команды:\n"
" benchmark Тест рендеринга узла\n"
" info Предоставить информацию об узле\n"
" show Показать узел\n"
" render Сделать снимок узла\n"
@@ -7891,7 +7884,7 @@ msgstr "Источник: %g %g\n"
msgid "Provide information about the render node."
msgstr "Предоставить информацию об узле рендеринга."
#: tools/gtk-rendernode-tool-info.c:236 tools/gtk-rendernode-tool-render.c:224
#: tools/gtk-rendernode-tool-info.c:236 tools/gtk-rendernode-tool-render.c:225
#: tools/gtk-rendernode-tool-show.c:134
#, c-format
msgid "No .node file specified\n"
@@ -7916,24 +7909,19 @@ msgstr ""
msgid "Failed to generate SVG: %s\n"
msgstr "Не удалось сгенерировать SVG: %s\n"
#: tools/gtk-rendernode-tool-render.c:150
#, c-format
msgid "Failed to create renderer: %s\n"
msgstr "Не удалось создать рендерер: %s\n"
#: tools/gtk-rendernode-tool-render.c:195
#: tools/gtk-rendernode-tool-render.c:196
msgid "Renderer to use"
msgstr "Используемый рендерер"
#: tools/gtk-rendernode-tool-render.c:195
#: tools/gtk-rendernode-tool-render.c:196
msgid "RENDERER"
msgstr "РЕНДЕРЕР"
#: tools/gtk-rendernode-tool-render.c:211
#: tools/gtk-rendernode-tool-render.c:212
msgid "Render a .node file to an image."
msgstr "Преобразование .node файла в изображение."
#: tools/gtk-rendernode-tool-render.c:230
#: tools/gtk-rendernode-tool-render.c:231
#, c-format
msgid "Can only render a single .node file to a single output file\n"
msgstr "Можно вывести только один файл .node в один выходной файл\n"
@@ -7951,12 +7939,12 @@ msgstr "Показать узел рендеринга."
msgid "Can only preview a single .node file\n"
msgstr "Можно предварительно просмотреть только один .node файл\n"
#: tools/gtk-rendernode-tool-utils.c:54
#: tools/gtk-rendernode-tool-utils.c:51
#, c-format
msgid "Error at %s: %s\n"
msgstr "Ошибка в %s: %s\n"
#: tools/gtk-rendernode-tool-utils.c:72
#: tools/gtk-rendernode-tool-utils.c:69
#, c-format
msgid "Failed to load node file: %s\n"
msgstr "Не удалось загрузить node файл: %s\n"