Compare commits

..

3 Commits

Author SHA1 Message Date
Matthias Clasen
fcf504905a Add an simd implementation
This is strongly based on graphenes simd plumbing.
All three types get represented as graphene_simf4d_t,
scale as {x,y,0,0}, point as {x,y,0,0} and box as
{x0,y0,x1,y1}.
2024-01-24 22:01:28 -05:00
Matthias Clasen
b84150a580 wip: Use the new types
This is just converting the glyph node handling, for starters.
2024-01-24 21:58:07 -05:00
Matthias Clasen
415539b02f Add private Scale, Point, Box types
This is the most straightforward, plain C implementation one could
come up with, to start with something obviously correct.
2024-01-24 21:58:07 -05:00
19 changed files with 1176 additions and 336 deletions

View File

@@ -25,8 +25,6 @@ base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/main/"
[extra]
content_images = [
"../images/favicon.svg",
"../images/favicon-192x192.png",
"images/gtk-logo.svg",
]
urlmap_file = "urlmap.js"

View File

@@ -24,8 +24,6 @@ base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/main/"
[extra]
content_images = [
"../images/favicon.svg",
"../images/favicon-192x192.png",
"images/gtk-logo.svg",
]
urlmap_file = "urlmap.js"

View File

@@ -67,8 +67,6 @@ content_files = [
"macos.md",
]
content_images = [
"../images/favicon.svg",
"../images/favicon-192x192.png",
"images/gtk-logo.svg",
"images/rotated-text.png",
"images/default_cursor.png",

View File

@@ -36,8 +36,6 @@ content_files = [
"paths.md",
]
content_images = [
"../images/favicon.svg",
"../images/favicon-192x192.png",
"gtk-logo.svg",
"images/arc-dark.png",
"images/arc-light.png",

View File

@@ -85,8 +85,6 @@ content_files = [
"visual_index.md",
]
content_images = [
"../images/favicon.svg",
"../images/favicon-192x192.png",
"images/aboutdialog.png",
"images/action-bar.png",
"images/appchooserbutton.png",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.0" width="88.572334" height="96.050743" id="svg6843">
<defs id="defs6845"/>
<g transform="translate(-19.822308,-16.115941)" id="layer1">
<path d="M 20.88413,30.82696 53.816977,55.527708 107.33282,39.060543 70.587303,17.177763 20.88413,30.82696 z" id="path6976" style="fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"/>
<path d="m 22.94243,82.287118 -2.0583,-51.460158 32.932847,24.700748 0,55.577152 L 22.94243,82.287118 z" id="path6978" style="fill:#e40000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"/>
<path d="m 53.816977,111.10486 49.399213,-20.58416 4.11663,-51.460157 -53.515843,16.467165 0,55.577152 z" id="path6980" style="fill:#7fe719;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"/>
<path d="M 23.216626,81.319479 70.48573,67.361442 103.38422,90.444516" id="path6982" style="fill:none;stroke:#ffffff;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"/>
<path d="m 70.434539,17.875593 0,49.109284" id="path6984" style="fill:#babdb6;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

479
gsk/boxprivate.h Normal file
View File

@@ -0,0 +1,479 @@
#pragma once
#include <graphene.h>
#include <math.h>
#include "gsktypesprivate.h"
#include "scaleprivate.h"
#include "pointprivate.h"
#ifndef USE_SIMD
struct _Box
{
float x0, y0, x1, y1;
};
static inline float
box_x0 (const Box box)
{
return box.x0;
}
static inline float
box_y0 (const Box box)
{
return box.y0;
}
static inline float
box_x1 (const Box box)
{
return box.x1;
}
static inline float
box_y1 (const Box box)
{
return box.y1;
}
static inline float
box_width (const Box box)
{
return box.x1 - box.x0;
}
static inline float
box_height (const Box box)
{
return box.y1 - box.y0;
}
/* Assumes x0 <= x1 && y0 <= y1 */
static inline Box
box (float x0,
float y0,
float x1,
float y1)
{
return (Box) { .x0 = x0, .y0 = y0, .x1 = x1, .y1 = y1 };
}
static inline Box
box_from_rect (float x,
float y,
float w,
float h)
{
return box (x, y, x + w, y + h);
}
static inline Box
box_from_graphene (const graphene_rect_t *rect)
{
return box_from_rect (rect->origin.x,
rect->origin.y,
rect->size.width,
rect->size.height);
}
/* Assumes p0.x <= p1.x && p0.y <= p1.y */
static inline Box
box_from_points (Point p0,
Point p1)
{
return box (p0.x, p0.y, p1.x, p1.y);
}
static inline Point
box_origin (const Box box)
{
return point (box.x0, box.y0);
}
static inline Point
box_opposite (const Box box)
{
return point (box.x1, box.y1);
}
static inline void
box_to_float (const Box box,
float v[4])
{
v[0] = box.x0;
v[1] = box.y0;
v[2] = box.x1 - box.x0;
v[3] = box.y1 - box.y0;
}
static inline Box
box_inset (const Box box,
float dx,
float dy)
{
return (Box) { .x0 = box.x0 + dx, .y0 = box.y0 + dy,
.x1 = box.x1 - dx, .y1 = box.y1 - dy };
}
static inline gboolean
box_intersect (const Box box1,
const Box box2,
Box *box)
{
Box b;
b.x0 = MAX (box1.x0, box2.x0);
b.y0 = MAX (box1.y0, box2.y0);
b.x1 = MIN (box1.x1, box2.x1);
b.y1 = MIN (box1.y1, box2.y1);
if (b.x0 <= b.x1 && b.y0 <= b.x1)
{
if (box)
*box = b;
return TRUE;
}
return FALSE;
}
static inline gboolean
box_equal (const Box box1,
const Box box2)
{
return memcmp (&box1, &box2, sizeof (Box)) == 0;
}
static inline gboolean
box_contains (const Box box1,
const Box box2)
{
Box box;
if (box_intersect (box1, box2, &box))
return box_equal (box, box2);
return FALSE;
}
static inline gboolean
box_empty (const Box box)
{
return box.x0 == box.x1 || box.y0 == box.y1;
}
static inline Box
box_add (const Box box,
const Point offset)
{
return (Box) { .x0 = box.x0 + offset.x, .y0 = box.y0 + offset.y,
.x1 = box.x1 + offset.x, .y1 = box.y1 + offset.y };
}
static inline Box
box_sub (const Box box,
const Point offset)
{
return (Box) { .x0 = box.x0 - offset.x, .y0 = box.y0 - offset.y,
.x1 = box.x1 - offset.x, .y1 = box.y1 - offset.y };
}
static inline Box
box_mul (const Box box,
const Scale scale)
{
Box b = (Box) { .x0 = box.x0 * scale.x, .y0 = box.y0 * scale.y,
.x1 = box.x1 * scale.x, .y1 = box.y1 * scale.y };
if (G_UNLIKELY (scale.x < 0 || scale.y < 0))
return (Box) { .x0 = MIN (b.x0, b.x1), .y0 = MIN (b.y0, b.y1),
.x1 = MAX (b.x0, b.x1), .y1 = MAX (b.y0, b.y1) };
return b;
}
static inline Box
box_div (const Box box,
const Scale scale)
{
return box_mul (box, scale_inv (scale));
}
static inline void
box_offset_to_float (const Box box,
const Point offset,
float v[4])
{
box_to_float (box_add (box, offset), v);
}
static inline Box
box_round_larger (const Box box)
{
return (Box) { .x0 = floorf (box.x0), .y0 = floorf (box.y0),
.x1 = ceilf (box.x1), .y1 = ceilf (box.y1) };
}
static inline Box
box_round_to_pixels (const Box box,
const Scale scale,
const Point offset)
{
return box_sub (box_div (box_round_larger (box_mul (box_add (box, offset), scale)), scale), offset);
}
#else /* USE_SIMD */
struct _Box
{
GRAPHENE_ALIGNED_DECL (graphene_simd4f_t v, 16);
};
static inline float
box_x0 (const Box box)
{
return graphene_simd4f_get_x (box.v);
}
static inline float
box_y0 (const Box box)
{
return graphene_simd4f_get_y (box.v);
}
static inline float
box_x1 (const Box box)
{
return graphene_simd4f_get_z (box.v);
}
static inline float
box_y1 (const Box box)
{
return graphene_simd4f_get_w (box.v);
}
static inline float
box_width (const Box box)
{
return box_x1 (box) - box_x0 (box);
}
static inline float
box_height (const Box box)
{
return box_y1 (box) - box_y0 (box);
}
static inline Box
box (float x0,
float y0,
float x1,
float y1)
{
return (Box) { .v = graphene_simd4f_init (x0, y0, x1, y1) };
}
static inline Box
box_from_rect (float x,
float y,
float w,
float h)
{
return box (x, y, x + w, y + h);
}
static inline Box
box_from_graphene (const graphene_rect_t *rect)
{
return box_from_rect (rect->origin.x,
rect->origin.y,
rect->size.width,
rect->size.height);
}
/* { a[0], a[1], b[0], b[1] } */
# define graphene_simd4f_splat_xyxy(a,b) \
(__extension__ ({ \
(graphene_simd4f_t) _mm_shuffle_ps ((a), (b), _MM_SHUFFLE (1, 0, 1, 0)); \
}))
static inline Box
box_from_points (Point p0,
Point p1)
{
return (Box) { .v = graphene_simd4f_splat_xyxy (p0.v, p1.v) };
}
static inline Point
box_origin (const Box box)
{
return (Point) { .v = graphene_simd4f_zero_zw (box.v) };
}
static inline Point
box_opposite (const Box box)
{
return (Point) { .v = graphene_simd4f_zero_zw (graphene_simd4f_shuffle_zwxy (box.v)) };
}
static inline void
box_to_float (const Box box,
float v[4])
{
graphene_simd4f_dup_4f (box.v, v);
v[2] -= v[0];
v[3] -= v[1];
}
static inline Box
box_inset (const Box box,
float dx,
float dy)
{
return (Box) { .v = graphene_simd4f_add (box.v, graphene_simd4f_init (dx, dy, -dx, -dy)) };
}
/* return a[0] < b[0] && a[1] < b[1] */
#ifndef graphene_simd4f_cmple_xy
# define graphene_simd4f_cmple_xy(a,b) \
(__extension__ ({ \
__m128i __res = (__m128i) _mm_cmple_ps ((a), (b)); \
(bool) ((_mm_movemask_epi8 (__res) & 0xff) == 0xff); \
}))
#endif
static inline gboolean
box_intersect (const Box box1,
const Box box2,
Box *box)
{
graphene_simd4f_t s, t, t1;
s = graphene_simd4f_max (box1.v, box2.v);
t = graphene_simd4f_min (box1.v, box2.v);
t1 = graphene_simd4f_shuffle_zwxy (t);
if (graphene_simd4f_cmple_xy (s, t1))
{
if (box)
box->v = graphene_simd4f_splat_xyxy (s, t);
return TRUE;
}
return FALSE;
}
static inline gboolean
box_equal (const Box box1,
const Box box2)
{
return (gboolean) !!graphene_simd4f_cmp_eq (box1.v, box2.v);
}
static inline gboolean
box_contains (const Box box1,
const Box box2)
{
Box box;
if (box_intersect (box1, box2, &box))
return box_equal (box, box2);
return FALSE;
}
static inline gboolean
box_empty (const Box box)
{
/* FIXME simd */
return box_x0 (box) == box_x1 (box) || box_y0 (box) == box_y1 (box);
}
/* a splat variation */
#ifndef graphene_simd4f_shuffle_xyxy
# define graphene_simd4f_shuffle_xyxy(v) \
(__extension__ ({ \
(graphene_simd4f_t) _mm_shuffle_ps ((v), (v), _MM_SHUFFLE (1, 0, 1, 0)); \
}))
#endif
static inline Box
box_add (const Box box,
const Point offset)
{
return (Box) { .v = graphene_simd4f_add (box.v, graphene_simd4f_shuffle_xyxy (offset.v)) };
}
static inline Box
box_sub (const Box box,
const Point offset)
{
return (Box) { .v = graphene_simd4f_sub (box.v, graphene_simd4f_shuffle_xyxy (offset.v)) };
}
static inline Box
box_mul (const Box box,
const Scale scale)
{
Box b = (Box) { .v = graphene_simd4f_mul (box.v, graphene_simd4f_shuffle_xyxy (scale.v)) };
if (G_UNLIKELY (!graphene_simd4f_cmple_xy (graphene_simd4f_init (0, 0, 0, 0), scale.v)))
{
graphene_simd4f_t v = graphene_simd4f_shuffle_zwxy (b.v);
graphene_simd4f_t s = graphene_simd4f_min (b.v, v);
graphene_simd4f_t t = graphene_simd4f_max (b.v, v);
return (Box) { .v = graphene_simd4f_splat_xyxy (s, t) };
}
return b;
}
static inline Box
box_div (const Box box,
const Scale scale)
{
return box_mul (box, scale_inv (scale));
}
static inline void
box_offset_to_float (const Box box,
const Point offset,
float v[4])
{
box_to_float (box_add (box, offset), v);
}
#ifdef __SSE4_1__
static inline Box
box_round_larger (const Box box)
{
return { (Box) .v = graphene_simd4f_splat_xyxy (graphene_simd4f_floor (b.v), graphene_simd4f_ceil (b.v)) };
}
#else
static inline Box
box_round_larger (const Box b)
{
return box (floorf (box_x0 (b)),
floorf (box_y0 (b)),
ceilf (box_x1 (b)),
ceilf (box_y1 (b)));
}
#endif
static inline Box
box_round_to_pixels (const Box box,
const Scale scale,
const Point offset)
{
return box_sub (box_div (box_round_larger (box_mul (box_add (box, offset), scale)), scale), offset);
}
#endif

View File

@@ -301,3 +301,42 @@ gsk_gpu_clip_get_shader_clip (const GskGpuClip *self,
return GSK_GPU_SHADER_CLIP_ROUNDED;
}
gboolean
gsk_gpu_clip_contains_box (const GskGpuClip *self,
const Point *offset,
const Box *box)
{
Box b = box_add (*box, *offset);
switch (self->type)
{
default:
g_assert_not_reached();
case GSK_GPU_CLIP_ALL_CLIPPED:
return FALSE;
case GSK_GPU_CLIP_NONE:
case GSK_GPU_CLIP_CONTAINED:
case GSK_GPU_CLIP_RECT:
return box_contains (box_from_graphene (&self->rect.bounds), b);
case GSK_GPU_CLIP_ROUNDED:
return gsk_rounded_rect_contains_rect (&self->rect, &GRAPHENE_RECT_INIT (box_x0 (b), box_y0 (b), box_width (b), box_height (b)));
}
}
GskGpuShaderClip
gsk_gpu_clip_get_shader_clip2 (const GskGpuClip *self,
const Point *offset,
const Box *box)
{
if (self->type == GSK_GPU_CLIP_NONE ||
self->type == GSK_GPU_CLIP_CONTAINED ||
gsk_gpu_clip_contains_box (self, offset, box))
return GSK_GPU_SHADER_CLIP_NONE;
else if (self->type == GSK_GPU_CLIP_RECT)
return GSK_GPU_SHADER_CLIP_RECT;
else
return GSK_GPU_SHADER_CLIP_ROUNDED;
}

View File

@@ -5,6 +5,7 @@
#include <gdk/gdk.h>
#include <graphene.h>
#include <gsk/gskroundedrect.h>
#include "boxprivate.h"
G_BEGIN_DECLS
@@ -65,9 +66,16 @@ gboolean gsk_gpu_clip_contains_rect (const G
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,
GskGpuShaderClip gsk_gpu_clip_get_shader_clip (const GskGpuClip *self,
const graphene_point_t *offset,
const graphene_rect_t *rect);
gboolean gsk_gpu_clip_contains_box (const GskGpuClip *self,
const Point *offset,
const Box *box) G_GNUC_WARN_UNUSED_RESULT;
GskGpuShaderClip gsk_gpu_clip_get_shader_clip2 (const GskGpuClip *self,
const Point *offset,
const Box *box);
G_END_DECLS

View File

@@ -3,14 +3,10 @@
#include "gskgpudeviceprivate.h"
#include "gskgpuframeprivate.h"
#include "gskgpuimageprivate.h"
#include "gskgpuuploadopprivate.h"
#include "gdk/gdkdisplayprivate.h"
#include "gdk/gdktextureprivate.h"
#include "gdk/gdkprofilerprivate.h"
#include "gsk/gskdebugprivate.h"
#define MAX_SLICES_PER_ATLAS 64
@@ -18,14 +14,6 @@
#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 15 /* 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;
@@ -66,34 +54,12 @@ 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)
@@ -109,8 +75,6 @@ gsk_gpu_cached_free (GskGpuDevice *device,
else
priv->first_cached = cached->next;
mark_as_stale (cached, TRUE);
cached->class->free (device, cached);
}
@@ -150,8 +114,7 @@ gsk_gpu_cached_use (GskGpuDevice *device,
GskGpuCached *cached,
gint64 timestamp)
{
cached->timestamp = timestamp;
mark_as_stale (cached, FALSE);
/* FIXME */
}
/* }}} */
@@ -174,23 +137,10 @@ 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);
}
@@ -199,7 +149,8 @@ gsk_gpu_cached_atlas_should_collect (GskGpuDevice *device,
GskGpuCached *cached,
gint64 timestamp)
{
return cached->pixels > MAX_DEAD_PIXELS;
/* FIXME */
return FALSE;
}
static const GskGpuCachedClass GSK_GPU_CACHED_ATLAS_CLASS =
@@ -239,8 +190,8 @@ gsk_gpu_cached_texture_free (GskGpuDevice *device,
gboolean texture_still_alive;
texture_still_alive = g_atomic_pointer_exchange (&self->texture, NULL) != NULL;
g_clear_object (&self->image);
g_object_unref (self->image);
if (!texture_still_alive)
g_free (self);
}
@@ -250,7 +201,8 @@ gsk_gpu_cached_texture_should_collect (GskGpuDevice *device,
GskGpuCached *cached,
gint64 timestamp)
{
return timestamp - cached->timestamp > CACHE_MAX_AGE;
/* FIXME */
return FALSE;
}
static const GskGpuCachedClass GSK_GPU_CACHED_TEXTURE_CLASS =
@@ -322,11 +274,8 @@ 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->font);
g_object_unref (self->image);
@@ -338,10 +287,7 @@ 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 */
/* FIXME */
return FALSE;
}
@@ -379,77 +325,19 @@ static const GskGpuCachedClass GSK_GPU_CACHED_GLYPH_CLASS =
/* }}} */
/* {{{ 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;
gint64 before G_GNUC_UNUSED = GDK_PROFILER_CURRENT_TIME;
GskGpuCached *cached, *next;
/* We walk the cache from the end so we don't end up with prev
* being a leftover glyph on the atlas we are freeing
*/
for (cached = priv->last_cached; cached != NULL; cached = prev)
for (cached = priv->first_cached; cached != NULL; cached = next)
{
prev = cached->prev;
next = cached->next;
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);
gdk_profiler_end_mark (before, "Glyph cache GC", NULL);
}
static void
@@ -469,9 +357,8 @@ gsk_gpu_device_clear_cache (GskGpuDevice *self)
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);
while (priv->first_cached)
gsk_gpu_cached_free (self, priv->first_cached);
g_assert (priv->last_cached == NULL);
}
@@ -485,7 +372,6 @@ gsk_gpu_device_dispose (GObject *object)
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);
}
@@ -521,16 +407,6 @@ gsk_gpu_device_init (GskGpuDevice *self)
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,
@@ -540,8 +416,6 @@ gsk_gpu_device_setup (GskGpuDevice *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 *
@@ -708,14 +582,20 @@ 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))
return priv->current_atlas->image;
{
gsk_gpu_cached_use (self, (GskGpuCached *) priv->current_atlas, timestamp);
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))
return priv->current_atlas->image;
{
gsk_gpu_cached_use (self, (GskGpuCached *) priv->current_atlas, timestamp);
return priv->current_atlas->image;
}
return NULL;
}
@@ -732,8 +612,10 @@ gsk_gpu_device_lookup_texture_image (GskGpuDevice *self,
if (cache == NULL)
cache = g_hash_table_lookup (priv->texture_cache, texture);
if (cache && cache->image)
return g_object_ref (cache->image);
if (cache)
{
return g_object_ref (cache->image);
}
return NULL;
}
@@ -823,7 +705,6 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
cache->image = image,
cache->origin = GRAPHENE_POINT_INIT (- origin.x + subpixel_x,
- origin.y + subpixel_y);
((GskGpuCached *) cache)->pixels = (rect.size.width + 2 * padding) * (rect.size.height + 2 * padding);
gsk_gpu_upload_glyph_op (frame,
cache->image,

View File

@@ -43,6 +43,10 @@
#include "gdk/gdkrgbaprivate.h"
#include "scaleprivate.h"
#include "pointprivate.h"
#include "boxprivate.h"
/* A note about coordinate systems
*
* The rendering code keeps track of multiple coordinate systems to optimize rendering as
@@ -498,6 +502,18 @@ gsk_gpu_pattern_writer_append_rect (GskGpuPatternWriter *self,
gsk_gpu_pattern_writer_append (self, G_ALIGNOF (float), (guchar *) f, sizeof (f));
}
static void
gsk_gpu_pattern_writer_append_box (GskGpuPatternWriter *self,
const Box box,
const Point offset)
{
float f[4];
box_offset_to_float (box, offset, f);
gsk_gpu_pattern_writer_append (self, G_ALIGNOF (float), (guchar *) f, sizeof (f));
}
static void
gsk_gpu_pattern_writer_append_rgba (GskGpuPatternWriter *self,
const GdkRGBA *rgba)
@@ -2974,9 +2990,9 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
GskGpuDevice *device;
const PangoGlyphInfo *glyphs;
PangoFont *font;
graphene_point_t offset;
Point offset;
Scale scale, s4, pango_scale;
guint i, num_glyphs;
float scale, inv_scale;
GdkRGBA color;
gboolean glyph_align;
@@ -2995,31 +3011,33 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
num_glyphs = gsk_text_node_get_num_glyphs (node);
glyphs = gsk_text_node_get_glyphs (node, NULL);
font = gsk_text_node_get_font (node);
offset = *gsk_text_node_get_offset (node);
offset.x += self->offset.x;
offset.y += self->offset.y;
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
inv_scale = 1.f / scale;
offset = point_add (point_from_graphene (gsk_text_node_get_offset (node)),
point_from_graphene (&self->offset));
scale = scale_max (scale_from_graphene (&self->scale));
s4 = scale_mul (scale, scale_from_float (4));
pango_scale = scale_from_float (PANGO_SCALE);
for (i = 0; i < num_glyphs; i++)
{
GskGpuImage *image;
graphene_rect_t glyph_bounds, glyph_tex_rect;
graphene_point_t glyph_offset, glyph_origin;
graphene_rect_t glyph_bds;
graphene_point_t glyph_ofs;
Box glyph_bounds, glyph_tex_rect;
Point g_ofs, glyph_origin;
guint32 descriptor;
GskGpuGlyphLookupFlags flags;
glyph_origin = GRAPHENE_POINT_INIT (offset.x + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
offset.y + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
glyph_origin = point_add (offset, point_div (point (glyphs[i].geometry.x_offset, glyphs[i].geometry.y_offset), pango_scale));
if (glyph_align)
{
glyph_origin.x = roundf (glyph_origin.x * scale * 4);
glyph_origin.y = roundf (glyph_origin.y * scale * 4);
flags = ((int) glyph_origin.x & 3) |
(((int) glyph_origin.y & 3) << 2);
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
glyph_origin.y = 0.25 * inv_scale * glyph_origin.y;
glyph_origin = point_round (point_mul (glyph_origin, s4));
flags = ((int) point_x (glyph_origin) & 3) |
(((int) point_y (glyph_origin) & 3) << 2);
glyph_origin = point_div (glyph_origin, s4);
}
else
{
@@ -3031,34 +3049,37 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
font,
glyphs[i].glyph,
flags,
scale,
&glyph_bounds,
&glyph_offset);
scale_x (scale),
&glyph_bds,
&glyph_ofs);
glyph_tex_rect = box_div (box_from_rect (-glyph_bds.origin.x, -glyph_bds.origin.y, gsk_gpu_image_get_width (image), gsk_gpu_image_get_height (image)), scale);
glyph_bounds = box_div (box_from_rect (0, 0, glyph_bds.size.width, glyph_bds.size.height), scale);
g_ofs = point_from_graphene (&glyph_ofs);
glyph_origin = point_sub (glyph_origin, point_div (g_ofs, scale));
gsk_rect_scale (&GRAPHENE_RECT_INIT (-glyph_bounds.origin.x, -glyph_bounds.origin.y, gsk_gpu_image_get_width (image), gsk_gpu_image_get_height (image)), inv_scale, inv_scale, &glyph_tex_rect);
gsk_rect_scale (&GRAPHENE_RECT_INIT(0, 0, glyph_bounds.size.width, glyph_bounds.size.height), inv_scale, inv_scale, &glyph_bounds);
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
glyph_origin.y - glyph_offset.y * inv_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, &glyph_offset, &glyph_bounds),
gsk_gpu_clip_get_shader_clip2 (&self->clip, &g_ofs, &glyph_bounds),
self->desc,
descriptor,
&glyph_bounds,
&glyph_origin,
&glyph_tex_rect);
&GRAPHENE_RECT_INIT (box_x0 (glyph_bounds), box_y0 (glyph_bounds), box_width (glyph_bounds), box_height (glyph_bounds)),
&GRAPHENE_POINT_INIT (point_x (glyph_origin), point_y (glyph_origin)),
&GRAPHENE_RECT_INIT (box_x0 (glyph_tex_rect), box_y0 (glyph_tex_rect), box_width (glyph_tex_rect), box_height (glyph_tex_rect)));
else
gsk_gpu_colorize_op (self->frame,
gsk_gpu_clip_get_shader_clip (&self->clip, &glyph_offset, &glyph_bounds),
gsk_gpu_clip_get_shader_clip2 (&self->clip, &g_ofs, &glyph_bounds),
self->desc,
descriptor,
&glyph_bounds,
&glyph_origin,
&glyph_tex_rect,
&GRAPHENE_RECT_INIT (box_x0 (glyph_bounds), box_y0 (glyph_bounds), box_width (glyph_bounds), box_height (glyph_bounds)),
&GRAPHENE_POINT_INIT (point_x (glyph_origin), point_y (glyph_origin)),
&GRAPHENE_RECT_INIT (box_x0 (glyph_tex_rect), box_y0 (glyph_tex_rect), box_width (glyph_tex_rect), box_height (glyph_tex_rect)),
&color);
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
offset = point_add (offset, point (glyphs[i].geometry.width / (float)PANGO_SCALE, 0));
}
}
@@ -3071,10 +3092,10 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
PangoFont *font;
guint num_glyphs;
gsize i;
float scale, inv_scale;
Scale scale, pango_scale;
guint32 tex_id;
GskGpuImage *last_image;
graphene_point_t offset;
Point offset;
if (gsk_text_node_has_color_glyphs (node))
return FALSE;
@@ -3083,12 +3104,11 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
num_glyphs = gsk_text_node_get_num_glyphs (node);
glyphs = gsk_text_node_get_glyphs (node, NULL);
font = gsk_text_node_get_font (node);
offset = *gsk_text_node_get_offset (node);
offset.x += self->offset.x;
offset.y += self->offset.y;
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
inv_scale = 1.f / scale;
offset = point_add (point_from_graphene (gsk_text_node_get_offset (node)),
point_from_graphene (&self->offset));
scale = scale_max (scale_from_graphene (&self->scale));
pango_scale = scale_from_float (PANGO_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));
@@ -3098,17 +3118,20 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
for (i = 0; i < num_glyphs; i++)
{
GskGpuImage *image;
graphene_rect_t glyph_bounds;
graphene_point_t glyph_offset;
graphene_rect_t glyph_bds;
graphene_point_t glyph_ofs;
Point glyph_offset;
Box glyph_bounds;
Box glyph_tex_rect;
image = gsk_gpu_device_lookup_glyph_image (device,
self->frame,
font,
glyphs[i].glyph,
0,
scale,
&glyph_bounds,
&glyph_offset);
scale_x (scale),
&glyph_bds,
&glyph_ofs);
if (image != last_image)
{
@@ -3118,28 +3141,15 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
last_image = image;
}
glyph_offset = GRAPHENE_POINT_INIT (offset.x - glyph_offset.x * inv_scale + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
offset.y - glyph_offset.y * inv_scale + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
glyph_offset = point_add (point_sub (offset, point_div (glyph_offset, scale)), point_div (point (glyphs[i].geometry.x_offset, glyphs[i].geometry.y_offset), pango_scale));
glyph_bounds = box_div (box_from_rect (0, 0, glyph_bds.size.width, glyph_bds.size.height), scale);
glyph_tex_rect = box_div (box_from_rect (-glyph_bds.origin.x, - glyph_bds.origin.y, gsk_gpu_image_get_width (image), gsk_gpu_image_get_height (image)), scale);
gsk_gpu_pattern_writer_append_uint (self, tex_id);
gsk_gpu_pattern_writer_append_rect (self,
&GRAPHENE_RECT_INIT (
0,
0,
glyph_bounds.size.width * inv_scale,
glyph_bounds.size.height * inv_scale
),
&glyph_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);
gsk_gpu_pattern_writer_append_box (self, glyph_bounds, glyph_offset);
gsk_gpu_pattern_writer_append_box (self, glyph_tex_rect, glyph_offset);
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
offset = point_add (offset, point (glyphs[i].geometry.width / (float)PANGO_SCALE, 0));
}
return TRUE;

22
gsk/gsktypesprivate.h Normal file
View File

@@ -0,0 +1,22 @@
/* GSK - The GTK Scene Kit
* Copyright 2024 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
typedef struct _Scale Scale;
typedef struct _Point Point;
typedef struct _Box Box;

252
gsk/pointprivate.h Normal file
View File

@@ -0,0 +1,252 @@
#pragma once
#include "gsktypesprivate.h"
#include <graphene.h>
#include <math.h>
#include <smmintrin.h>
#include "scaleprivate.h"
#ifndef USE_SIMD
struct _Point
{
float x, y;
};
static inline float
point_x (const Point p)
{
return p.x;
}
static inline float
point_y (const Point p)
{
return p.y;
}
static inline Point
point (float x,
float y)
{
return (Point) { .x = x, .y = y };
}
static inline Point
point_from_graphene (const graphene_point_t *p)
{
return point (p->x, p->y);
}
static inline void
point_to_float (const Point p,
float v[2])
{
v[0] = p.x;
v[1] = p.y;
}
static inline Point
point_zero (void)
{
return point (0, 0);
}
static inline Point
point_neg (const Point p)
{
return (Point) { .x = -p.x, .y = -p.y };
}
static inline Point
point_mul (const Point p,
const Scale s)
{
return (Point) { .x = p.x * s.x, .y = p.y * s.y };
}
static inline Point
point_div (const Point p,
const Scale s)
{
return (Point) { .x = p.x / s.x, .y = p.y / s.y };
}
static inline Point
point_add (const Point p1,
const Point p2)
{
return (Point) { .x = p1.x + p2.x, .y = p1.y + p2.y };
}
static inline Point
point_sub (const Point p1,
const Point p2)
{
return (Point) { .x = p1.x - p2.x, .y = p1.y - p2.y };
}
static inline Point
point_floor (const Point p)
{
return (Point) { .x = floorf (p.x), .y = floorf (p.y) };
}
static inline Point
point_ceil (const Point p)
{
return (Point) { .x = ceilf (p.x), .y = ceilf (p.y) };
}
static inline Point
point_round (const Point p)
{
return (Point) { .x = roundf (p.x), .y = roundf (p.y) };
}
#else /* USE_SIMD */
#include <smmintrin.h>
struct _Point
{
GRAPHENE_ALIGNED_DECL (graphene_simd4f_t v, 16);
};
static inline float
point_x (const Point p)
{
return graphene_simd4f_get_x (p.v);
}
static inline float
point_y (const Point p)
{
return graphene_simd4f_get_y (p.v);
}
static inline Point
point (float x,
float y)
{
return (Point) { .v = graphene_simd4f_init (x, y, 0.f, 0.f) };
}
static inline Point
point_from_graphene (const graphene_point_t *p)
{
return point (p->x, p->y);
}
static inline void
point_to_float (const Point p,
float v[2])
{
graphene_simd4f_dup_2f (p.v, v);
}
static inline Point
point_zero (void)
{
return point (0, 0);
}
static inline Point
point_neg (const Point p)
{
return (Point) { .v = graphene_simd4f_neg (p.v) };
}
static inline Point
point_mul (const Point p,
const Scale s)
{
return (Point) { .v = graphene_simd4f_mul (p.v, s.v) };
}
static inline Point
point_div (const Point p,
const Scale s)
{
return (Point) { .v = graphene_simd4f_div (p.v, s.v) };
}
static inline Point
point_add (const Point p1,
const Point p2)
{
return (Point) { .v = graphene_simd4f_add (p1.v, p2.v) };
}
static inline Point
point_sub (const Point p1,
const Point p2)
{
return (Point) { .v = graphene_simd4f_sub (p1.v, p2.v) };
}
#ifdef __SSE4_1__
#ifndef graphene_simd4f_floor
# define graphene_simd4f_floor(v) \
(__extension__ ({ \
(graphene_simd4f_t) _mm_floor_ps ((v)); \
}))
#endif
#ifndef graphene_simd4f_ceil
# define graphene_simd4f_ceil(v) \
(__extension__ ({ \
(graphene_simd4f_t) _mm_ceil_ps ((v)); \
}))
#endif
#ifndef graphene_simd4f_round
# define graphene_simd4f_round(v) \
(__extension__ ({ \
(graphene_simd4f_t) _mm_round_ps ((v)); \
}))
#endif
static inline Point
point_floor (const Point p)
{
return (Point) { .v = graphene_simd4f_floor (p.v) };
}
static inline Point
point_ceil (const Point p)
{
return (Point) { .v = graphene_simd4f_ceil (p.v) };
}
static inline Point
point_round (const Point p)
{
return (Point) { .v = graphene_simd4f_round (p.v) };
}
#else
static inline Point
point_floor (const Point p)
{
return point (floorf (point_x (p)), floorf (point_y (p)));
}
static inline Point
point_ceil (const Point p)
{
return point (ceilf (point_x (p)), ceilf (point_y (p)));
}
static inline Point
point_round (const Point p)
{
return point (roundf (point_x (p)), roundf (point_y (p)));
}
#endif
#endif

183
gsk/scaleprivate.h Normal file
View File

@@ -0,0 +1,183 @@
#pragma once
#include "gsktypesprivate.h"
#include <graphene.h>
#include <math.h>
#ifndef USE_SIMD
struct _Scale
{
float x, y;
};
static inline float
scale_x (const Scale s)
{
return s.x;
}
static inline float
scale_y (const Scale s)
{
return s.y;
}
static inline Scale
scale (float x,
float y)
{
return (Scale) { .x = x, .y = y };
}
static inline Scale
scale_from_float (float s)
{
return scale (s, s);
}
static inline Scale
scale_from_graphene (const graphene_vec2_t *v)
{
return (Scale) { .x = graphene_vec2_get_x (v), .y = graphene_vec2_get_y (v) };
}
static inline void
scale_to_float (const Scale s,
float v[2])
{
v[0] = s.x;
v[1] = s.y;
}
static inline gboolean
scale_equal (const Scale s1,
const Scale s2)
{
return (gboolean) (s1.x == s2.x && s1.y == s2.y);
}
static inline Scale
scale_one (void)
{
return scale (1, 1);
}
static inline Scale
scale_inv (const Scale s)
{
return (Scale) { .x = 1 / s.x, .y = 1 / s.y };
}
static inline Scale
scale_mul (const Scale s1,
const Scale s2)
{
return (Scale) { .x = s1.x * s2.x, .y = s1.y * s2.y };
}
static inline Scale
scale_div (const Scale s1,
const Scale s2)
{
return (Scale) { .x = s1.x / s2.x, .y = s1.y / s2.y };
}
static inline Scale
scale_max (const Scale s)
{
return (Scale) { .x = MAX (s.x, s.y), .y = MAX (s.x, s.y) };
}
#else /* USE_SIMD */
struct _Scale
{
GRAPHENE_ALIGNED_DECL (graphene_simd4f_t v, 16);
};
static inline float
scale_x (const Scale s)
{
return graphene_simd4f_get_x (s.v);
}
static inline float
scale_y (const Scale s)
{
return graphene_simd4f_get_y (s.v);
}
static inline Scale
scale (float x,
float y)
{
return (Scale) { .v = graphene_simd4f_init (x, y, 0.f, 0.f) };
}
static inline Scale
scale_from_float (float s)
{
return scale (s, s);
}
static inline Scale
scale_from_graphene (const graphene_vec2_t *v)
{
return (Scale) { .v = v->__graphene_private_value };
}
static inline void
scale_to_float (const Scale s,
float v[2])
{
graphene_simd4f_dup_2f (s.v, v);
}
static inline gboolean
scale_equal (const Scale s1,
const Scale s2)
{
return (gboolean) graphene_simd4f_cmp_eq (s1.v, s2.v);
}
static inline Scale
scale_one (void)
{
return scale (1, 1);
}
static inline Scale
scale_inv (const Scale s)
{
return (Scale) { .v = graphene_simd4f_reciprocal (s.v) };
}
static inline Scale
scale_mul (const Scale s1,
const Scale s2)
{
return (Scale) { .v = graphene_simd4f_mul (s1.v, s2.v) };
}
static inline Scale
scale_div (const Scale s1,
const Scale s2)
{
return (Scale) { .v = graphene_simd4f_div (s1.v, s2.v) };
}
#ifndef graphene_simd4f_shuffle_yxzw
# define graphene_simd4f_shuffle_yxzw(v) \
(__extension__ ({ \
(graphene_simd4f_t) _mm_shuffle_ps ((v), (v), _MM_SHUFFLE (3, 2, 0, 1)); \
}))
#endif
static inline Scale
scale_max (const Scale s)
{
return (Scale) { .v = graphene_simd4f_max (graphene_simd4f_shuffle_yxzw (s.v), s.v) };
}
#endif

View File

@@ -1401,6 +1401,14 @@ gtk_at_spi_context_finalize (GObject *gobject)
G_OBJECT_CLASS (gtk_at_spi_context_parent_class)->finalize (gobject);
}
static void
gtk_at_spi_context_constructed (GObject *gobject)
{
GtkAtSpiContext *self G_GNUC_UNUSED = GTK_AT_SPI_CONTEXT (gobject);
G_OBJECT_CLASS (gtk_at_spi_context_parent_class)->constructed (gobject);
}
static const char *get_bus_address (GdkDisplay *display);
static void
@@ -1508,6 +1516,7 @@ gtk_at_spi_context_class_init (GtkAtSpiContextClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GtkATContextClass *context_class = GTK_AT_CONTEXT_CLASS (klass);
gobject_class->constructed = gtk_at_spi_context_constructed;
gobject_class->finalize = gtk_at_spi_context_finalize;
context_class->realize = gtk_at_spi_context_realize;

View File

@@ -96,7 +96,7 @@ gtk_at_spi_root_finalize (GObject *gobject)
g_free (self->desktop_name);
g_free (self->desktop_path);
G_OBJECT_CLASS (gtk_at_spi_root_parent_class)->finalize (gobject);
G_OBJECT_CLASS (gtk_at_spi_root_parent_class)->dispose (gobject);
}
static void

View File

@@ -604,10 +604,14 @@ static const struct {
GtkAccessible *accessible,
GdkDisplay *display);
} a11y_backends[] = {
#if defined(GDK_WINDOWING_WAYLAND) || defined(GDK_WINDOWING_X11)
{ "AT-SPI", "atspi", gtk_at_spi_create_context },
#if defined(GDK_WINDOWING_WAYLAND)
{ "AT-SPI (Wayland)", "atspi", gtk_at_spi_create_context },
#endif
#if defined(GDK_WINDOWING_X11)
{ "AT-SPI (X11)", "atspi", gtk_at_spi_create_context },
#endif
{ "Test", "test", gtk_test_at_context_new },
{ NULL, NULL, NULL },
};
/**
@@ -630,7 +634,6 @@ gtk_at_context_create (GtkAccessibleRole accessible_role,
GdkDisplay *display)
{
static const char *gtk_a11y_env;
GtkATContext *res = NULL;
if (gtk_a11y_env == NULL)
{
@@ -658,9 +661,12 @@ gtk_at_context_create (GtkAccessibleRole accessible_role,
if (g_ascii_strcasecmp (gtk_a11y_env, "none") == 0)
return NULL;
for (size_t i = 0; i < G_N_ELEMENTS (a11y_backends); i++)
GtkATContext *res = NULL;
for (guint i = 0; i < G_N_ELEMENTS (a11y_backends); i++)
{
g_assert (a11y_backends[i].name != NULL);
if (a11y_backends[i].name == NULL)
break;
if (a11y_backends[i].create_context != NULL &&
(*gtk_a11y_env == '0' || g_ascii_strcasecmp (a11y_backends[i].env_name, gtk_a11y_env) == 0))

165
po/he.po
View File

@@ -6,23 +6,23 @@
# Gil Osher <dolfin@rpg.org.il>, 2004.
# Yair Hershkovitz <yairhr@gmail.com>, 2006.
# Yaron Shahrabani <sh.yaron@gmail.com>, 2011, 2012.
# Yosef Or Boczko <yoseforb@gmail.com>, 2013-2024.
# Yosef Or Boczko <yoseforb@gmail.com>, 2013-2023.
#
msgid ""
msgstr ""
"Project-Id-Version: gtk+.HEAD.he\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gtk/-/issues/\n"
"POT-Creation-Date: 2024-01-22 13:47+0000\n"
"PO-Revision-Date: 2024-01-25 13:34+0200\n"
"Last-Translator: Yosef Or Boczko <yoseforb@gmail.com>\n"
"Language-Team: Hebrew\n"
"POT-Creation-Date: 2023-12-27 22:15+0000\n"
"PO-Revision-Date: 2023-12-28 13:40+0200\n"
"Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\n"
"Language-Team: Hebrew <yoseforb@gmail.com>\n"
"Language: he\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : n==2 ? 1 : n>10 && n%10==0 ? "
"2 : 3)\n"
"X-Generator: Gtranslator 45.3\n"
"2 : 3);\n"
"X-Generator: Poedit 3.4.1\n"
"X-Project-Style: default\n"
#: gdk/broadway/gdkbroadway-server.c:135
@@ -34,11 +34,11 @@ msgstr "סוג תצוגת ה־broadway אינה נתמכת: %s"
msgid "This clipboard cannot store data."
msgstr "לוח גזירים זה לא יכול לאחסן נתונים."
#: gdk/gdkclipboard.c:287 gdk/gdkclipboard.c:786 gdk/gdkclipboard.c:1086
#: gdk/gdkclipboard.c:287 gdk/gdkclipboard.c:785 gdk/gdkclipboard.c:1085
msgid "Cannot read from empty clipboard."
msgstr "אי אפשר לקרוא מלוח גזירים ריק."
#: gdk/gdkclipboard.c:318 gdk/gdkclipboard.c:1136 gdk/gdkdrag.c:618
#: gdk/gdkclipboard.c:318 gdk/gdkclipboard.c:1135 gdk/gdkdrag.c:618
msgid "No compatible formats to transfer clipboard contents."
msgstr "אין תצורות תואמות להעברת תכני לוח גזירים."
@@ -57,31 +57,31 @@ msgstr "לא ניתן לספק תוכן בתור %s"
msgid "The current backend does not support OpenGL"
msgstr "המנשק הנוכחי אינו תומך ב־OpenGL"
#: gdk/gdkdisplay.c:1296 gdk/gdkvulkancontext.c:1581
#: gdk/gdkdisplay.c:1278 gdk/gdksurface.c:1268 gdk/gdkvulkancontext.c:1479
msgid "Vulkan support disabled via GDK_DEBUG"
msgstr "התמיכה ב־Vulkan מושבתת דרך GDK_DEBUG"
#: gdk/gdkdisplay.c:1350
#: gdk/gdkdisplay.c:1310
msgid "GL support disabled via GDK_DEBUG"
msgstr "התמיכה ב־GL הושבתה דרך GDK_DEBUG"
#: gdk/gdkdisplay.c:1646
#: gdk/gdkdisplay.c:1606
msgid "No EGL configuration available"
msgstr "אין תצורת EGL זמינה"
#: gdk/gdkdisplay.c:1654
#: gdk/gdkdisplay.c:1614
msgid "Failed to get EGL configurations"
msgstr "קבלת תצורות EGL נכשלה"
#: gdk/gdkdisplay.c:1684
#: gdk/gdkdisplay.c:1644
msgid "No EGL configuration with required features found"
msgstr "לא נמצאה תצורת EGL עם היכולות הנדרשות"
#: gdk/gdkdisplay.c:1691
#: gdk/gdkdisplay.c:1651
msgid "No perfect EGL configuration found"
msgstr "לא נמצאה תצורת EGL מושלמת"
#: gdk/gdkdisplay.c:1733
#: gdk/gdkdisplay.c:1693
#, c-format
msgid "EGL implementation is missing extension %s"
msgid_plural "EGL implementation is missing %2$d extensions: %1$s"
@@ -90,23 +90,23 @@ msgstr[1] "למימוש ה־EGL חסרות שתי הרחבות: %1$s"
msgstr[2] "למימוש ה־EGL חסרות %2$d הרחבות: %1$s"
msgstr[3] "למימוש ה־EGL חסרות %2$d הרחבות: %1$s"
#: gdk/gdkdisplay.c:1782
#: gdk/gdkdisplay.c:1743
msgid "libEGL not available in this sandbox"
msgstr "libEGL אינו זמין בארגז חול זה"
#: gdk/gdkdisplay.c:1783
#: gdk/gdkdisplay.c:1744
msgid "libEGL not available"
msgstr "libEGL לא זמין"
#: gdk/gdkdisplay.c:1793
#: gdk/gdkdisplay.c:1754
msgid "Failed to create EGL display"
msgstr "יצירת תצוגת EGL נכשלה"
#: gdk/gdkdisplay.c:1802
#: gdk/gdkdisplay.c:1764
msgid "Could not initialize EGL display"
msgstr "לא ניתן להפעיל תצוגת EGL"
#: gdk/gdkdisplay.c:1812
#: gdk/gdkdisplay.c:1775
#, c-format
msgid "EGL version %d.%d is too old. GTK requires %d.%d"
msgstr "גרסת ה־EGL %d.%d ישנה מדי. GTK דורש %d.%d"
@@ -144,7 +144,7 @@ msgstr "היישום אינו תומך ב־API %s"
#. translators: This is about OpenGL backend names, like
#. * "Trying to use X11 GLX, but EGL is already in use"
#: gdk/gdkglcontext.c:2115
#: gdk/gdkglcontext.c:2123
#, c-format
msgid "Trying to use %s, but %s is already in use"
msgstr "מתבצע ניסיון להשתמש ב־%s אך %s כבר בשימוש"
@@ -542,7 +542,7 @@ msgstr "שגיאה בפענוח קובץ תמונת JPEG (%s)"
msgid "Unsupported JPEG colorspace (%d)"
msgstr "מרחב הצבעים של ה־JPEG אינו נתמך (%d)"
#: gdk/loaders/gdkjpeg.c:203 gdk/loaders/gdkpng.c:286 gdk/loaders/gdktiff.c:472
#: gdk/loaders/gdkjpeg.c:203 gdk/loaders/gdkpng.c:280 gdk/loaders/gdktiff.c:472
#, c-format
msgid "Not enough memory for image size %ux%u"
msgstr "אין מספיק זיכרון לתמונה בגודל %u×%u"
@@ -552,22 +552,16 @@ msgstr "אין מספיק זיכרון לתמונה בגודל %u×%u"
msgid "Error reading png (%s)"
msgstr "שגיאה בקריאת png (%s)"
#: gdk/loaders/gdkpng.c:212
#: gdk/loaders/gdkpng.c:211
#, c-format
msgid "Unsupported depth %u in png image"
msgstr "העומק %u אינו נתמך בתמונות png"
#: gdk/loaders/gdkpng.c:262
#: gdk/loaders/gdkpng.c:261
#, c-format
msgid "Unsupported color type %u in png image"
msgstr "סוג הצבע %u אינו נתמך בתמונות png"
#: gdk/loaders/gdkpng.c:272
#, fuzzy, c-format
#| msgid "Not enough memory for image size %ux%u"
msgid "Image stride too large for image size %ux%u"
msgstr "אין מספיק זיכרון לתמונה בגודל %u×%u"
#: gdk/loaders/gdktiff.c:358
msgid "Failed to load RGB data from TIFF file"
msgstr "טעינת נתוני RGB מקובץ TIFF נכשלה"
@@ -832,16 +826,11 @@ msgstr "תצורות שגויות בהמרת טקסט מרוכב."
msgid "Unsupported encoding “%s”"
msgstr "הקידוד „%s” אינו נתמך"
#: gsk/gl/gskglrenderer.c:204
#: gsk/gl/gskglrenderer.c:210
#, c-format
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 ""
#: gtk/a11y/gtkatspiaction.c:239
msgctxt "accessibility"
msgid "Click"
@@ -1039,7 +1028,7 @@ msgid "Invalid"
msgstr "בלתי תקני"
#. This label is displayed in a treeview cell displaying an accelerator
#. * when the cell is clicked to change the accelerator.
#. * when the cell is clicked to change the acelerator.
#.
#: gtk/deprecated/gtkcellrendereraccel.c:436
#: gtk/deprecated/gtkcellrendereraccel.c:729
@@ -2385,7 +2374,7 @@ msgid "If you delete an item, it will be permanently lost."
msgstr "אם פריט ימחק, הוא יאבד לצמיתות."
#: gtk/gtkfilechooserwidget.c:1183 gtk/gtkfilechooserwidget.c:1781
#: gtk/gtklabel.c:5702 gtk/gtktext.c:6147 gtk/gtktextview.c:9018
#: gtk/gtklabel.c:5695 gtk/gtktext.c:6147 gtk/gtktextview.c:9018
msgid "_Delete"
msgstr "מ_חיקה"
@@ -2714,7 +2703,7 @@ msgstr "מאפייני סגנון"
msgid "Character Variations"
msgstr "הגווני תו"
#: gtk/gtkglarea.c:309
#: gtk/gtkglarea.c:305
msgid "OpenGL context creation failed"
msgstr "יצירת הקשר OpenGL נכשלה"
@@ -2727,32 +2716,32 @@ msgstr "סגירה"
msgid "Close the infobar"
msgstr "סגירת פס המידע"
#: gtk/gtklabel.c:5699 gtk/gtktext.c:6135 gtk/gtktextview.c:9006
#: gtk/gtklabel.c:5692 gtk/gtktext.c:6135 gtk/gtktextview.c:9006
msgid "Cu_t"
msgstr "_גזירה"
#: gtk/gtklabel.c:5700 gtk/gtktext.c:6139 gtk/gtktextview.c:9010
#: gtk/gtklabel.c:5693 gtk/gtktext.c:6139 gtk/gtktextview.c:9010
msgid "_Copy"
msgstr "ה_עתקה"
#: gtk/gtklabel.c:5701 gtk/gtktext.c:6143 gtk/gtktextview.c:9014
#: gtk/gtklabel.c:5694 gtk/gtktext.c:6143 gtk/gtktextview.c:9014
msgid "_Paste"
msgstr "ה_דבקה"
#: gtk/gtklabel.c:5707 gtk/gtktext.c:6156 gtk/gtktextview.c:9039
#: gtk/gtklabel.c:5700 gtk/gtktext.c:6156 gtk/gtktextview.c:9039
msgid "Select _All"
msgstr "בחירה בה_כול"
#: gtk/gtklabel.c:5712
#: gtk/gtklabel.c:5705
msgid "_Open Link"
msgstr "_פתיחת קישור"
#: gtk/gtklabel.c:5716
#: gtk/gtklabel.c:5709
msgid "Copy _Link Address"
msgstr "העתקת כתובת ה_קישור"
# msgctxt "OpenType layout"
#: gtk/gtklabel.c:5760 gtk/gtktext.c:2716 gtk/gtktextview.c:9088
#: gtk/gtklabel.c:5753 gtk/gtktext.c:2716 gtk/gtktextview.c:9088
msgid "Context menu"
msgstr "תפריט הקשר"
@@ -3662,7 +3651,7 @@ msgstr "החלקה ימינה"
#. Translators: This is placeholder text for the search entry in the shortcuts window
#: gtk/gtkshortcutswindow.c:879 gtk/gtkshortcutswindow.c:946
#: gtk/gtkshortcutswindow.c:952
#: gtk/gtkshortcutswindow.c:951
msgid "Search Shortcuts"
msgstr "חיפוש קיצורי מקשים"
@@ -3676,12 +3665,12 @@ msgstr "צירופי מקשים"
msgid "Search Results"
msgstr "תוצאות חיפוש"
#: gtk/gtkshortcutswindow.c:1014 gtk/ui/gtkemojichooser.ui:349
#: gtk/gtkshortcutswindow.c:1013 gtk/ui/gtkemojichooser.ui:349
#: gtk/ui/gtkfilechooserwidget.ui:239
msgid "No Results Found"
msgstr "לא נמצאו תוצאות"
#: gtk/gtkshortcutswindow.c:1025 gtk/ui/gtkemojichooser.ui:362
#: gtk/gtkshortcutswindow.c:1024 gtk/ui/gtkemojichooser.ui:362
#: gtk/ui/gtkfilechooserwidget.ui:252 gtk/ui/gtkplacesview.ui:218
msgid "Try a different search"
msgstr "יש לנסות חיפוש שונה"
@@ -3895,37 +3884,37 @@ msgstr "מחלקות סגנון"
msgid "CSS Property"
msgstr "מאפיין CSS"
#: gtk/inspector/general.c:363
#: gtk/inspector/general.c:349
msgctxt "GL version"
msgid "None"
msgstr "ללא"
#: gtk/inspector/general.c:441
#: gtk/inspector/general.c:426
msgctxt "GL version"
msgid "Unknown"
msgstr "לא ידוע"
#: gtk/inspector/general.c:503
#: gtk/inspector/general.c:491
msgctxt "Vulkan device"
msgid "Disabled"
msgstr "מושבת"
#: gtk/inspector/general.c:504 gtk/inspector/general.c:505
#: gtk/inspector/general.c:492 gtk/inspector/general.c:493
msgctxt "Vulkan version"
msgid "Disabled"
msgstr "מושבת"
#: gtk/inspector/general.c:555
#: gtk/inspector/general.c:549
msgctxt "Vulkan device"
msgid "None"
msgstr "ללא"
#: gtk/inspector/general.c:556 gtk/inspector/general.c:557
#: gtk/inspector/general.c:550 gtk/inspector/general.c:551
msgctxt "Vulkan version"
msgid "None"
msgstr "ללא"
#: gtk/inspector/general.c:895
#: gtk/inspector/general.c:882
msgid "IM Context is hardcoded by GTK_IM_MODULE"
msgstr "IM Context קשיחה בקוד על ידי GTK_IM_MODULE"
@@ -3977,51 +3966,43 @@ msgstr "RGBA חזותי"
msgid "Composited"
msgstr "מורכב"
#: gtk/inspector/general.ui:538
msgid "Protocols"
msgstr "פרוטוקולים"
#: gtk/inspector/general.ui:594
#: gtk/inspector/general.ui:559
msgid "GL Version"
msgstr "גרסת GL"
#: gtk/inspector/general.ui:621
#: gtk/inspector/general.ui:586
msgid "GL Backend Version"
msgstr "גרסת מנגנון GL"
#: gtk/inspector/general.ui:671
#: gtk/inspector/general.ui:636
msgid "GL Backend Vendor"
msgstr "ספק מנגנון GL"
#: gtk/inspector/general.ui:698
#: gtk/inspector/general.ui:663
msgid "GL_VENDOR"
msgstr "GL_VENDOR"
#: gtk/inspector/general.ui:727
#: gtk/inspector/general.ui:692
msgid "GL_RENDERER"
msgstr "GL_RENDERER"
#: gtk/inspector/general.ui:756
#: gtk/inspector/general.ui:721
msgid "GL_VERSION"
msgstr "GL_VERSION"
#: gtk/inspector/general.ui:785
#: gtk/inspector/general.ui:750
msgid "GL_SHADING_LANGUAGE_VERSION"
msgstr "GL_SHADING_LANGUAGE_VERSION"
#: gtk/inspector/general.ui:813 gtk/inspector/general.ui:929
msgid "Extensions"
msgstr "הרחבות"
#: gtk/inspector/general.ui:849
#: gtk/inspector/general.ui:789
msgid "Vulkan Device"
msgstr "התקן Vulkan"
#: gtk/inspector/general.ui:876
#: gtk/inspector/general.ui:816
msgid "Vulkan API version"
msgstr "גרסת API של Vulkan"
#: gtk/inspector/general.ui:903
#: gtk/inspector/general.ui:843
msgid "Vulkan driver version"
msgstr "גרסת מנהל התקן של Vulkan"
@@ -7329,7 +7310,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"
@@ -7375,13 +7356,13 @@ msgstr ""
"Use --force to overwrite.\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 "Output written to %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 "Failed to save %s: %s\n"
@@ -7399,7 +7380,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 "FILE…"
@@ -7876,7 +7857,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"
@@ -7888,7 +7868,6 @@ msgstr ""
"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"
@@ -7918,7 +7897,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"
@@ -7943,25 +7922,19 @@ msgstr ""
msgid "Failed to generate SVG: %s\n"
msgstr "יצירת SVG נכשלה: %s\n"
#: tools/gtk-rendernode-tool-render.c:150
#, fuzzy, c-format
#| msgid "Failed to rewrite header\n"
msgid "Failed to create renderer: %s\n"
msgstr "Failed to rewrite header\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"
@@ -7979,12 +7952,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 "טעינת קובץ המצב נכשלה: %s\n"
@@ -8155,8 +8128,8 @@ msgstr ""
#~ msgid "Switch to list view"
#~ msgstr "החלפה לתצוגת רשימה"
#~ msgid "default:LTR"
#~ msgstr "default:RTL"
msgid "default:LTR"
msgstr "default:RTL"
#~ msgid "Other application…"
#~ msgstr "יישום אחר…"