Compare commits

...

25 Commits

Author SHA1 Message Date
Matthias Clasen
79b30bdf0a ci: Set some ubsan options
Hopefully, this makes the build survive.
2024-03-15 00:38:12 -04:00
Matthias Clasen
b832b3fd35 Drop -Werror=array-bounds for now
Until somebody fixes the code in gtkcssselector.c in a way
that makes the compiler happy, don't pass unhappiness-inducing
flags.
2024-03-15 00:14:17 -04:00
Matthias Clasen
c0391ce193 glcontext: Don't call get_instance_private (NULL)
ubsan does not like this.

See a9175e0c03 for a detailed explanation.
2024-03-14 23:33:29 -04:00
Simon McVittie
05d36b2ba4 testsuite: Force Mesa to use software GL when asserting about stderr
In an autobuilder environment, there will typically be no hardware GPU
available, so Mesa will fall back from hardware to Zink to software
rendering. Unfortunately, Zink logs to stderr during loading if no
hardware GPUs are available. This particular test asserts that stderr
has desired contents, which means Zink's extra output causes the test
to fail. We can bypass this by disabling use of Zink.

Resolves: https://gitlab.gnome.org/GNOME/gtk/-/issues/6478
Signed-off-by: Simon McVittie <smcv@debian.org>
2024-03-14 22:32:43 -04:00
Matthias Clasen
a904292bfb Drop an unintenionally added file 2024-03-14 22:32:24 -04:00
Matthias Clasen
65cf59408b ci: Use v50 of the Fedora image
This has dropped some unnecessary packages.
2024-03-14 15:30:51 -04:00
Matthias Clasen
b269a4712a ci: Use ubsan as well
We have libubsan in the ci image, so we may as well enable both
asan and ubsan.
2024-03-14 11:39:51 -04:00
Matthias Clasen
ebd74e112d ci: Drop some unnecessary packages
We don't use at, at-spi or the docbook stylesheets.
2024-03-14 11:37:55 -04:00
Changwoo Ryu
3c39c5259e Update Korean translation 2024-03-14 10:57:06 +00:00
Matthias Clasen
f5a6d93939 Merge branch 'wip/otte/who-framed-roger-rabbit' into 'main'
Don't reuse frames while they're in use

See merge request GNOME/gtk!7030
2024-03-14 10:21:34 +00:00
Benjamin Otte
30dddf2412 gpu: Refactor waiting for frames
Instead of having renderer API to wait for any number of frames, just
have gsk_gpu_frame_wait() to wait for a single frame.

This unifies behavior on Vulkan and GL, because unlike Vulkan, GL does
not allow waiting for multiple fences.

To make up for it, we replace waiting for multiple frames with finding
the frame with the earliest timestamp and waiting for that one.

Also implement wait() for GL.
2024-03-14 06:06:33 +01:00
Benjamin Otte
b43950d0f7 gpu: Don't reuse frames while they're in use
This copies the Vulkan idea of using a fence at the end of command
submission and waiting until it gets signaled before reusing the frame.

This frees up the GL driver from doing the work of making buffers etc
reusable and instead allocates new ones when they're still in use and is
a pretty massive performance win.
2024-03-14 04:53:12 +01:00
Matthias Clasen
6e5a183c98 Merge branch 'matthiasc/for-main' into 'main'
gtk-demo: Skip gl shader when necessary

Closes #6538

See merge request GNOME/gtk!7029
2024-03-14 01:29:32 +00:00
Matthias Clasen
d224110b48 gtk-demo: Skip the transitions demo when necessary
This demo uses GL shader nodes which only work with the GL renderer,
therefore skip the demo unless the GL renderer is in use.

Fixes: #6538
2024-03-13 21:02:17 -04:00
Matthias Clasen
8f356c2e8c gtk-demo: Skip gl shader when necessary
GL shader nodes only work with the GL renderer, therefore skip
the Shader in the list unless the GL renderer is in use.

Fixes: #6538
2024-03-13 21:02:10 -04:00
Matthias Clasen
139ed2c900 Merge branch 'textview-cursor-anchor' into 'main'
textview: Fix cursor/anchor mixup when retrieving surrounding text

Closes #6460

See merge request GNOME/gtk!6929
2024-03-14 00:07:41 +00:00
Matthias Clasen
32e21d5402 Merge branch 'speedup-inner-loop' into 'main'
Simplify our inner loop

See merge request GNOME/gtk!7026
2024-03-13 12:41:43 +00:00
Marek Kasik
fb3d8b8523 printing: Avoid accessing freed printers
Print backend can be disposed together with all its printers
as a reaction to user stopping enumeration of printers.
Adding a weak pointer help us to detect that the backend
was disposed and hence the backend and its printers should not
be used anymore.

Fixes #6265
2024-03-13 11:17:42 +01:00
Matthias Clasen
380523b41b gsk: Eschew more divisions
Pull out a pango_scale_inv constant, and use it.
2024-03-13 01:26:14 -04:00
Matthias Clasen
2fda256bb0 gsk: Avoid some unnecessary calls
Most of the time, the image we get for the glyphs will be the
same (the atlas), so avoid adding it to the descriptor set over
and over, and check first if have to. This matches what the
pattern variant of this function already does.
2024-03-13 01:03:32 -04:00
Matthias Clasen
c71a66b6f6 gsk: Simplify our inner loop
Pull out the if-else and precompute things before the loop.
2024-03-13 01:03:31 -04:00
Matthias Clasen
cb92778478 gsk: Drop the glyph-align flag
It wasn't doing anymore what it was designed for, and we are not
sure that we need it.
2024-03-13 01:00:49 -04:00
Matthias Clasen
ab67936a64 Merge branch 'matthiasc/for-main' into 'main'
Drop an unused header

See merge request GNOME/gtk!7025
2024-03-13 04:44:07 +00:00
Matthias Clasen
0ae2c1a8a7 Drop an unused header
This came in with a GskPath-related merge, but it isn't used
anywhere. So drop it for now.
2024-03-12 22:14:31 -04:00
Sebastian Keller
575bd64698 textview: Fix cursor/anchor mixup when retrieving surrounding text
Previously the code for calculating the cursor and anchor for the
flipped case was mixed up with the logic for the non-flipped case.

Additionally make the code more readable by making the anchor/selection
bound the start and the cursor/insert the end of a selection. Thus a
selection made from left to right goes from start to end. Selections
from right to left, i.e. end to start are considered flipped.

Also update the test to use the correct cursor/anchor and change some
variable names to make it more readable.

Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/6460
2024-02-22 20:49:10 +01:00
24 changed files with 1242 additions and 779 deletions

View File

@@ -26,7 +26,7 @@ variables:
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Dbuild-testsuite=true -Dintrospection=enabled"
MESON_TEST_TIMEOUT_MULTIPLIER: 3
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v49"
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v50"
workflow:
rules:
@@ -422,7 +422,7 @@ asan-build:
- export PATH="$HOME/.local/bin:$PATH"
- CC=clang meson setup
--buildtype=debugoptimized
-Db_sanitize=address
-Db_sanitize=address,undefined
-Db_lundef=false
-Dbuild-demos=false
-Dbuild-tests=false

Binary file not shown.

View File

@@ -2,8 +2,6 @@ FROM fedora:39
RUN dnf -y install \
adwaita-icon-theme \
atk-devel \
at-spi2-atk-devel \
avahi-gobject-devel \
cairo-devel \
cairo-gobject-devel \
@@ -18,7 +16,6 @@ RUN dnf -y install \
dejavu-sans-mono-fonts \
desktop-file-utils \
diffutils \
docbook-style-xsl \
elfutils-libelf-devel \
expat-devel \
fribidi-devel \

View File

@@ -11,7 +11,7 @@ multiplier=${MESON_TEST_TIMEOUT_MULTIPLIER:-1}
# Ignore memory leaks lower in dependencies
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0:detect_leaks=0:allocator_may_return_null=1
export G_SLICE=always-malloc
export UBSAN_OPTIONS=silence_unsigned_overflow=1
case "${setup}" in
x11*)

View File

@@ -184,6 +184,12 @@ create_cogs (void)
return picture;
}
static gboolean
check_cogs (GtkFishbowl *fb)
{
return GSK_IS_GL_RENDERER (gtk_native_get_renderer (gtk_widget_get_native (GTK_WIDGET (fb))));
}
static void
mapped (GtkWidget *w)
{
@@ -218,36 +224,41 @@ create_graph (void)
static const struct {
const char *name;
GtkWidget * (*create_func) (void);
GtkWidget * (* create_func) (void);
gboolean (* check) (GtkFishbowl *fb);
} widget_types[] = {
{ "Icon", create_icon },
{ "Button", create_button },
{ "Blurbutton", create_blurred_button },
{ "Fontbutton", create_font_button },
{ "Levelbar", create_level_bar },
{ "Label", create_label },
{ "Spinner", create_spinner },
{ "Spinbutton", create_spinbutton },
{ "Video", create_video },
{ "Gears", create_gears },
{ "Switch", create_switch },
{ "Menubutton", create_menu_button },
{ "Shader", create_cogs },
{ "Tiger", create_tiger },
{ "Graph", create_graph },
{ "Icon", create_icon, NULL },
{ "Button", create_button, NULL },
{ "Blurbutton", create_blurred_button, NULL },
{ "Fontbutton", create_font_button, NULL },
{ "Levelbar", create_level_bar, NULL },
{ "Label", create_label, NULL },
{ "Spinner", create_spinner, NULL },
{ "Spinbutton", create_spinbutton, NULL },
{ "Video", create_video, NULL },
{ "Gears", create_gears, NULL },
{ "Switch", create_switch, NULL },
{ "Menubutton", create_menu_button, NULL },
{ "Shader", create_cogs, check_cogs },
{ "Tiger", create_tiger, NULL },
{ "Graph", create_graph, NULL },
};
static int selected_widget_type = -1;
static const int N_WIDGET_TYPES = G_N_ELEMENTS (widget_types);
static void
static gboolean
set_widget_type (GtkFishbowl *fishbowl,
int widget_type_index)
{
GtkWidget *window;
if (widget_type_index == selected_widget_type)
return;
return TRUE;
if (widget_types[widget_type_index].check != NULL &&
!widget_types[widget_type_index].check (fishbowl))
return FALSE;
selected_widget_type = widget_type_index;
@@ -257,6 +268,8 @@ set_widget_type (GtkFishbowl *fishbowl,
window = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (fishbowl)));
gtk_window_set_title (GTK_WINDOW (window),
widget_types[selected_widget_type].name);
return TRUE;
}
G_MODULE_EXPORT void
@@ -264,14 +277,17 @@ fishbowl_next_button_clicked_cb (GtkButton *source,
gpointer user_data)
{
GtkFishbowl *fishbowl = user_data;
int new_index;
int new_index = selected_widget_type;
if (selected_widget_type + 1 >= N_WIDGET_TYPES)
new_index = 0;
else
new_index = selected_widget_type + 1;
do
{
if (new_index + 1 >= N_WIDGET_TYPES)
new_index = 0;
else
new_index = new_index + 1;
set_widget_type (fishbowl, new_index);
}
while (!set_widget_type (fishbowl, new_index));
}
G_MODULE_EXPORT void
@@ -279,14 +295,18 @@ fishbowl_prev_button_clicked_cb (GtkButton *source,
gpointer user_data)
{
GtkFishbowl *fishbowl = user_data;
int new_index;
int new_index = selected_widget_type;
if (selected_widget_type - 1 < 0)
new_index = N_WIDGET_TYPES - 1;
else
new_index = selected_widget_type - 1;
do
{
if (new_index - 1 < 0)
new_index = N_WIDGET_TYPES - 1;
else
new_index = new_index - 1;
set_widget_type (fishbowl, new_index);
}
while (!set_widget_type (fishbowl, new_index));
}
G_MODULE_EXPORT void

View File

@@ -827,13 +827,25 @@ demo_search_changed_cb (GtkSearchEntry *entry,
gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
}
static gboolean
demo_can_run (GtkWidget *window,
const char *name)
{
if (name != NULL && strcmp (name, "gltransition") == 0)
return GSK_IS_GL_RENDERER (gtk_native_get_renderer (GTK_NATIVE (window)));
return TRUE;
}
static GListModel *
create_demo_model (void)
create_demo_model (GtkWidget *window)
{
GListStore *store = g_list_store_new (GTK_TYPE_DEMO);
DemoData *demo = gtk_demos;
GtkDemo *d;
gtk_widget_realize (window);
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
d->name = "main";
d->title = "GTK Demo";
@@ -845,16 +857,20 @@ create_demo_model (void)
while (demo->title)
{
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
DemoData *children = demo->children;
DemoData *children = demo->children;
d->name = demo->name;
d->title = demo->title;
d->keywords = demo->keywords;
d->filename = demo->filename;
d->func = demo->func;
if (demo_can_run (window, demo->name))
{
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
g_list_store_append (store, d);
d->name = demo->name;
d->title = demo->title;
d->keywords = demo->keywords;
d->filename = demo->filename;
d->func = demo->func;
g_list_store_append (store, d);
}
if (children)
{
@@ -862,15 +878,19 @@ create_demo_model (void)
while (children->title)
{
GtkDemo *child = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
if (demo_can_run (window, children->name))
{
GtkDemo *child = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
child->name = children->name;
child->title = children->title;
child->keywords = children->keywords;
child->filename = children->filename;
child->func = children->func;
child->name = children->name;
child->title = children->title;
child->keywords = children->keywords;
child->filename = children->filename;
child->func = children->func;
g_list_store_append (G_LIST_STORE (d->children_model), child);
}
g_list_store_append (G_LIST_STORE (d->children_model), child);
children++;
}
}
@@ -936,7 +956,7 @@ activate (GApplication *app)
search_bar = GTK_WIDGET (gtk_builder_get_object (builder, "searchbar"));
g_signal_connect (search_bar, "notify::search-mode-enabled", G_CALLBACK (clear_search), NULL);
listmodel = create_demo_model ();
listmodel = create_demo_model (window);
treemodel = gtk_tree_list_model_new (G_LIST_MODEL (listmodel),
FALSE,
TRUE,

View File

@@ -290,7 +290,7 @@ gdk_gl_context_create_egl_context (GdkGLContext *context,
GdkDisplay *display = gdk_gl_context_get_display (context);
EGLDisplay egl_display = gdk_display_get_egl_display (display);
GdkGLContext *share = gdk_display_get_gl_context (display);
GdkGLContextPrivate *share_priv = gdk_gl_context_get_instance_private (share);
GdkGLContextPrivate *share_priv = share ? gdk_gl_context_get_instance_private (share) : NULL;
EGLConfig egl_config;
EGLContext ctx;
EGLint context_attribs[N_EGL_ATTRS], i = 0, flags = 0;

View File

@@ -20,6 +20,7 @@ struct _GskGLFrame
GLuint globals_buffer_id;
guint next_texture_slot;
GLsync sync;
GHashTable *vaos;
};
@@ -34,7 +35,23 @@ G_DEFINE_TYPE (GskGLFrame, gsk_gl_frame, GSK_TYPE_GPU_FRAME)
static gboolean
gsk_gl_frame_is_busy (GskGpuFrame *frame)
{
return FALSE;
GskGLFrame *self = GSK_GL_FRAME (frame);
if (!self->sync)
return FALSE;
return glClientWaitSync (self->sync, 0, 0) == GL_TIMEOUT_EXPIRED;
}
static void
gsk_gl_frame_wait (GskGpuFrame *frame)
{
GskGLFrame *self = GSK_GL_FRAME (frame);
if (!self->sync)
return;
glClientWaitSync (self->sync, 0, G_MAXINT64);
}
static void
@@ -50,6 +67,12 @@ gsk_gl_frame_cleanup (GskGpuFrame *frame)
{
GskGLFrame *self = GSK_GL_FRAME (frame);
if (self->sync)
{
glClientWaitSync (self->sync, 0, -1);
glDeleteSync (self->sync);
}
self->next_texture_slot = 0;
GSK_GPU_FRAME_CLASS (gsk_gl_frame_parent_class)->cleanup (frame);
@@ -160,6 +183,8 @@ gsk_gl_frame_submit (GskGpuFrame *frame,
{
op = gsk_gpu_op_gl_command (op, frame, &state);
}
self->sync = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
}
static void
@@ -180,6 +205,7 @@ gsk_gl_frame_class_init (GskGLFrameClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
gpu_frame_class->is_busy = gsk_gl_frame_is_busy;
gpu_frame_class->wait = gsk_gl_frame_wait;
gpu_frame_class->setup = gsk_gl_frame_setup;
gpu_frame_class->cleanup = gsk_gl_frame_cleanup;
gpu_frame_class->upload_texture = gsk_gl_frame_upload_texture;

View File

@@ -505,6 +505,12 @@ gsk_gpu_frame_is_busy (GskGpuFrame *self)
return GSK_GPU_FRAME_GET_CLASS (self)->is_busy (self);
}
void
gsk_gpu_frame_wait (GskGpuFrame *self)
{
GSK_GPU_FRAME_GET_CLASS (self)->wait (self);
}
static void
copy_texture (gpointer user_data,
GdkTexture *texture)

View File

@@ -24,6 +24,7 @@ struct _GskGpuFrameClass
GObjectClass parent_class;
gboolean (* is_busy) (GskGpuFrame *self);
void (* wait) (GskGpuFrame *self);
void (* setup) (GskGpuFrame *self);
void (* cleanup) (GskGpuFrame *self);
GskGpuImage * (* upload_texture) (GskGpuFrame *self,
@@ -69,6 +70,7 @@ GskGpuBuffer * gsk_gpu_frame_write_storage_buffer (GskGpuF
gsize *out_offset);
gboolean gsk_gpu_frame_is_busy (GskGpuFrame *self);
void gsk_gpu_frame_wait (GskGpuFrame *self);
void gsk_gpu_frame_render (GskGpuFrame *self,
gint64 timestamp,

View File

@@ -3000,8 +3000,12 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
guint i, num_glyphs;
float scale, inv_scale;
GdkRGBA color;
gboolean glyph_align;
gboolean hinting;
float align_scale_x, align_scale_y;
float inv_align_scale_x, inv_align_scale_y;
unsigned int flags_mask;
GskGpuImage *last_image;
guint32 descriptor;
const float inv_pango_scale = 1.f / PANGO_SCALE;
if (self->opacity < 1.0 &&
gsk_text_node_has_color_glyphs (node))
@@ -3024,45 +3028,38 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
inv_scale = 1.f / scale;
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN);
hinting = gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE;
if (gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE)
{
align_scale_x = scale * 4;
align_scale_y = scale;
flags_mask = 3;
}
else
{
align_scale_x = align_scale_y = scale * 4;
flags_mask = 15;
}
inv_align_scale_x = 1 / align_scale_x;
inv_align_scale_y = 1 / align_scale_y;
last_image = NULL;
descriptor = 0;
for (i = 0; i < num_glyphs; i++)
{
GskGpuImage *image;
graphene_rect_t glyph_bounds, glyph_tex_rect;
graphene_point_t glyph_offset, 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 = GRAPHENE_POINT_INIT (offset.x + glyphs[i].geometry.x_offset * inv_pango_scale,
offset.y + glyphs[i].geometry.y_offset * inv_pango_scale);
if (hinting && glyph_align)
{
/* Force glyph_origin.y to be device pixel aligned.
* The hinter expects that.
*/
glyph_origin.x = floor (glyph_origin.x * scale * 4 + .5);
flags = ((int) glyph_origin.x & 3);
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
glyph_origin.y = floor (glyph_origin.y * scale + .5) * inv_scale;
}
else if (glyph_align)
{
glyph_origin.x = floor (glyph_origin.x * scale * 4 + .5);
glyph_origin.y = floor (glyph_origin.y * scale * 4 + .5);
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;
}
else
{
glyph_origin.x = floor (glyph_origin.x * scale + .5) * inv_scale;
glyph_origin.y = floor (glyph_origin.y * scale + .5) * inv_scale;
flags = 0;
}
glyph_origin.x = floorf (glyph_origin.x * align_scale_x + 0.5f);
glyph_origin.y = floorf (glyph_origin.y * align_scale_y + 0.5f);
flags = (((int) glyph_origin.x & 3) | (((int) glyph_origin.y & 3) << 2)) & flags_mask;
glyph_origin.x *= inv_align_scale_x;
glyph_origin.y *= inv_align_scale_y;
image = gsk_gpu_device_lookup_glyph_image (device,
self->frame,
@@ -3084,7 +3081,11 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
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 (image != last_image)
{
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
last_image = image;
}
if (glyphs[i].attr.is_color)
gsk_gpu_texture_op (self->frame,
@@ -3104,7 +3105,7 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
&glyph_tex_rect,
&color);
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
offset.x += glyphs[i].geometry.width * inv_pango_scale;
}
}
@@ -3121,8 +3122,10 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
guint32 tex_id;
GskGpuImage *last_image;
graphene_point_t offset;
gboolean glyph_align;
gboolean hinting;
float align_scale_x, align_scale_y;
float inv_align_scale_x, inv_align_scale_y;
unsigned int flags_mask;
const float inv_pango_scale = 1.f / PANGO_SCALE;
if (gsk_text_node_has_color_glyphs (node))
return FALSE;
@@ -3142,8 +3145,20 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
gsk_gpu_pattern_writer_append_rgba (self, gsk_text_node_get_color (node));
gsk_gpu_pattern_writer_append_uint (self, num_glyphs);
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN);
hinting = gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE;
if (gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE)
{
align_scale_x = scale * 4;
align_scale_y = scale;
flags_mask = 3;
}
else
{
align_scale_x = align_scale_y = scale * 4;
flags_mask = 15;
}
inv_align_scale_x = 1 / align_scale_x;
inv_align_scale_y = 1 / align_scale_y;
last_image = NULL;
for (i = 0; i < num_glyphs; i++)
@@ -3153,34 +3168,14 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
graphene_point_t glyph_offset, glyph_origin;
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 = GRAPHENE_POINT_INIT (offset.x + glyphs[i].geometry.x_offset * inv_pango_scale,
offset.y + glyphs[i].geometry.y_offset * inv_pango_scale);
if (hinting && glyph_align)
{
/* Force glyph_origin.y to be device pixel aligned.
* The hinter expects that.
*/
glyph_origin.x = roundf (glyph_origin.x * scale * 4);
flags = ((int) glyph_origin.x & 3);
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
glyph_origin.y = roundf (glyph_origin.y * scale) * inv_scale;
}
else 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;
}
else
{
glyph_origin.x = roundf (glyph_origin.x * scale) * inv_scale;
glyph_origin.y = roundf (glyph_origin.y * scale) * inv_scale;
flags = 0;
}
glyph_origin.x = floorf (glyph_origin.x * align_scale_x + 0.5f);
glyph_origin.y = floorf (glyph_origin.y * align_scale_y + 0.5f);
flags = (((int) glyph_origin.x & 3) | (((int) glyph_origin.y & 3) << 2)) & flags_mask;
glyph_origin.x *= inv_align_scale_x;
glyph_origin.y *= inv_align_scale_y;
image = gsk_gpu_device_lookup_glyph_image (device,
self->frame,
@@ -3220,7 +3215,7 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
),
&glyph_origin);
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
offset.x += glyphs[i].geometry.width * inv_pango_scale;
}
return TRUE;

View File

@@ -30,7 +30,6 @@ static const GdkDebugKey gsk_gpu_optimization_keys[] = {
{ "blit", GSK_GPU_OPTIMIZE_BLIT, "Use shaders instead of vkCmdBlit()/glBlitFramebuffer()" },
{ "gradients", GSK_GPU_OPTIMIZE_GRADIENTS, "Don't supersample gradients" },
{ "mipmap", GSK_GPU_OPTIMIZE_MIPMAP, "Avoid creating mipmaps" },
{ "glyph-align", GSK_GPU_OPTIMIZE_GLYPH_ALIGN, "Never align glyphs to the subpixel grid" },
{ "gl-baseinstance", GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE, "Assume no ARB/EXT_base_instance support" },
};
@@ -167,24 +166,36 @@ static GskGpuFrame *
gsk_gpu_renderer_get_frame (GskGpuRenderer *self)
{
GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self);
GskGpuFrame *earliest_frame = NULL;
gint64 earliest_time = G_MAXINT64;
guint i;
while (TRUE)
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
if (priv->frames[i] == NULL)
{
priv->frames[i] = gsk_gpu_renderer_create_frame (self);
return priv->frames[i];
}
gint64 timestamp;
if (!gsk_gpu_frame_is_busy (priv->frames[i]))
return priv->frames[i];
if (priv->frames[i] == NULL)
{
priv->frames[i] = gsk_gpu_renderer_create_frame (self);
return priv->frames[i];
}
GSK_GPU_RENDERER_GET_CLASS (self)->wait (self, priv->frames, GSK_GPU_MAX_FRAMES);
if (!gsk_gpu_frame_is_busy (priv->frames[i]))
return priv->frames[i];
timestamp = gsk_gpu_frame_get_timestamp (priv->frames[i]);
if (timestamp < earliest_time)
{
earliest_time = timestamp;
earliest_frame = priv->frames[i];
}
}
g_assert (earliest_frame);
gsk_gpu_frame_wait (earliest_frame);
return earliest_frame;
}
static gboolean
@@ -218,31 +229,17 @@ gsk_gpu_renderer_unrealize (GskRenderer *renderer)
{
GskGpuRenderer *self = GSK_GPU_RENDERER (renderer);
GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self);
gsize i, j;
gsize i;
gsk_gpu_renderer_make_current (self);
while (TRUE)
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
for (i = 0, j = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
if (priv->frames[i] == NULL)
break;
if (gsk_gpu_frame_is_busy (priv->frames[i]))
{
if (i > j)
{
priv->frames[j] = priv->frames[i];
priv->frames[i] = NULL;
}
j++;
continue;
}
g_clear_object (&priv->frames[i]);
}
if (j == 0)
if (priv->frames[i] == NULL)
break;
GSK_GPU_RENDERER_GET_CLASS (self)->wait (self, priv->frames, j);
if (gsk_gpu_frame_is_busy (priv->frames[i]))
gsk_gpu_frame_wait (priv->frames[i]);
g_clear_object (&priv->frames[i]);
}
g_clear_object (&priv->context);

View File

@@ -35,9 +35,6 @@ struct _GskGpuRendererClass
void (* make_current) (GskGpuRenderer *self);
GskGpuImage * (* get_backbuffer) (GskGpuRenderer *self);
void (* wait) (GskGpuRenderer *self,
GskGpuFrame **frame,
gsize n_frames);
double (* get_scale) (GskGpuRenderer *self);
GdkDmabufFormats * (* get_dmabuf_formats) (GskGpuRenderer *self);

View File

@@ -118,8 +118,7 @@ typedef enum {
GSK_GPU_OPTIMIZE_BLIT = 1 << 3,
GSK_GPU_OPTIMIZE_GRADIENTS = 1 << 4,
GSK_GPU_OPTIMIZE_MIPMAP = 1 << 5,
GSK_GPU_OPTIMIZE_GLYPH_ALIGN = 1 << 6,
/* These require hardware support */
GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE = 1 << 7,
GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE = 1 << 6,
} GskGpuOptimizations;

View File

@@ -119,13 +119,6 @@ gsk_ngl_renderer_get_backbuffer (GskGpuRenderer *renderer)
return self->backbuffer;
}
static void
gsk_ngl_renderer_wait (GskGpuRenderer *self,
GskGpuFrame **frame,
gsize n_frames)
{
}
static double
gsk_ngl_renderer_get_scale (GskGpuRenderer *self)
{
@@ -164,7 +157,6 @@ gsk_ngl_renderer_class_init (GskNglRendererClass *klass)
gpu_renderer_class->create_context = gsk_ngl_renderer_create_context;
gpu_renderer_class->make_current = gsk_ngl_renderer_make_current;
gpu_renderer_class->get_backbuffer = gsk_ngl_renderer_get_backbuffer;
gpu_renderer_class->wait = gsk_ngl_renderer_wait;
gpu_renderer_class->get_scale = gsk_ngl_renderer_get_scale;
gpu_renderer_class->get_dmabuf_formats = gsk_ngl_renderer_get_dmabuf_formats;

View File

@@ -74,6 +74,21 @@ gsk_vulkan_frame_is_busy (GskGpuFrame *frame)
return vkGetFenceStatus (device, self->vk_fence) == VK_NOT_READY;
}
static void
gsk_vulkan_frame_wait (GskGpuFrame *frame)
{
GskVulkanFrame *self = GSK_VULKAN_FRAME (frame);
VkDevice vk_device;
vk_device = gsk_vulkan_device_get_vk_device (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)));
GSK_VK_CHECK (vkWaitForFences, vk_device,
1,
&self->vk_fence,
VK_FALSE,
INT64_MAX);
}
static void
gsk_vulkan_frame_setup (GskGpuFrame *frame)
{
@@ -387,6 +402,7 @@ gsk_vulkan_frame_class_init (GskVulkanFrameClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
gpu_frame_class->is_busy = gsk_vulkan_frame_is_busy;
gpu_frame_class->wait = gsk_vulkan_frame_wait;
gpu_frame_class->setup = gsk_vulkan_frame_setup;
gpu_frame_class->cleanup = gsk_vulkan_frame_cleanup;
gpu_frame_class->upload_texture = gsk_vulkan_frame_upload_texture;

View File

@@ -129,31 +129,6 @@ gsk_vulkan_renderer_get_backbuffer (GskGpuRenderer *renderer)
return self->targets[gdk_vulkan_context_get_draw_index (context)];
}
static void
gsk_vulkan_renderer_wait (GskGpuRenderer *renderer,
GskGpuFrame **frames,
gsize n_frames)
{
VkFence *fences;
VkDevice vk_device;
gsize i;
vk_device = gsk_vulkan_device_get_vk_device (GSK_VULKAN_DEVICE (gsk_gpu_renderer_get_device (renderer)));
fences = g_alloca (sizeof (VkFence) * n_frames);
for (i = 0; i < n_frames; i++)
{
fences[i] = gsk_vulkan_frame_get_vk_fence (GSK_VULKAN_FRAME (frames[i]));
}
GSK_VK_CHECK (vkWaitForFences, vk_device,
n_frames,
fences,
VK_FALSE,
INT64_MAX);
}
static GdkDmabufFormats *
gsk_vulkan_renderer_get_dmabuf_formats (GskGpuRenderer *renderer)
{
@@ -189,7 +164,6 @@ gsk_vulkan_renderer_class_init (GskVulkanRendererClass *klass)
gpu_renderer_class->create_context = gsk_vulkan_renderer_create_context;
gpu_renderer_class->make_current = gsk_vulkan_renderer_make_current;
gpu_renderer_class->get_backbuffer = gsk_vulkan_renderer_get_backbuffer;
gpu_renderer_class->wait = gsk_vulkan_renderer_wait;
gpu_renderer_class->get_dmabuf_formats = gsk_vulkan_renderer_get_dmabuf_formats;
renderer_class->unrealize = gsk_vulkan_renderer_unrealize;

View File

@@ -1,20 +0,0 @@
#pragma once
#include <graphene.h>
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)
{
p->x = p1->x * (1 - t) + p2->x * t;
p->Y = p1->y * (1 - t) + p2->y * t;
}
static inline float G_GNUC_PURE
gsk_point_distance (const graphene_point_t *p1,
const graphene_point_t *p2)
{
return sqrtf ((p1->x - p2->x)*(p1->x - p2->x) + (p1->y - p2->y)*(p1->y - p2->y));
}

View File

@@ -8754,11 +8754,11 @@ gtk_text_view_retrieve_surrounding_handler (GtkIMContext *context,
gboolean flip;
gtk_text_buffer_get_iter_at_mark (text_view->priv->buffer, &start,
gtk_text_buffer_get_insert (text_view->priv->buffer));
gtk_text_buffer_get_iter_at_mark (text_view->priv->buffer, &end,
gtk_text_buffer_get_selection_bound (text_view->priv->buffer));
gtk_text_buffer_get_iter_at_mark (text_view->priv->buffer, &end,
gtk_text_buffer_get_insert (text_view->priv->buffer));
flip = gtk_text_iter_compare (&start, &end) < 0;
flip = gtk_text_iter_compare (&start, &end) > 0;
gtk_text_iter_order (&start, &end);
@@ -8784,13 +8784,13 @@ gtk_text_view_retrieve_surrounding_handler (GtkIMContext *context,
if (flip)
{
anchor_pos = strlen (pre);
cursor_pos = anchor_pos + strlen (sel);
cursor_pos = strlen (pre);
anchor_pos = cursor_pos + strlen (sel);
}
else
{
cursor_pos = strlen (pre);
anchor_pos = cursor_pos + strlen (sel);
anchor_pos = strlen (pre);
cursor_pos = anchor_pos + strlen (sel);
}
text = g_strconcat (pre, sel, post, NULL);

View File

@@ -307,7 +307,6 @@ elif cc.get_id() == 'gcc' or cc.get_id() == 'clang'
extra_warnings = [
'address',
'array-bounds',
'empty-body',
'enum-int-mismatch',
'implicit',

View File

@@ -3639,6 +3639,19 @@ avahi_request_printer_list (GtkPrintBackendCups *cups_backend)
g_bus_get (G_BUS_TYPE_SYSTEM, cups_backend->avahi_cancellable, avahi_create_browsers, cups_backend);
}
/*
* Print backend can be disposed together with all its printers
* as a reaction to user stopping enumeration of printers.
*/
static void
backend_finalized_cb (gpointer data,
GObject *where_the_object_was)
{
gboolean *backend_finalized = data;
*backend_finalized = TRUE;
}
static void
cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
GtkCupsResult *result,
@@ -3651,6 +3664,7 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
GList *removed_printer_checklist;
char *remote_default_printer = NULL;
GList *iter;
gboolean backend_finalized = FALSE;
list_has_changed = FALSE;
@@ -3683,6 +3697,8 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
*/
removed_printer_checklist = gtk_print_backend_get_printer_list (backend);
g_object_weak_ref (G_OBJECT (backend), backend_finalized_cb, &backend_finalized);
response = gtk_cups_result_get_response (result);
for (attr = ippFirstAttribute (response); attr != NULL;
attr = ippNextAttribute (response))
@@ -3800,6 +3816,9 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
{
g_signal_emit_by_name (backend, "printer-added", printer);
if (backend_finalized)
break;
gtk_printer_set_is_new (printer, FALSE);
}
@@ -3837,36 +3856,44 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
break;
}
/* look at the removed printers checklist and mark any printer
as inactive if it is in the list, emitting a printer_removed signal */
if (removed_printer_checklist != NULL)
if (!backend_finalized)
{
for (iter = removed_printer_checklist; iter; iter = iter->next)
g_object_weak_unref (G_OBJECT (backend), backend_finalized_cb, &backend_finalized);
/* look at the removed printers checklist and mark any printer
as inactive if it is in the list, emitting a printer_removed signal */
if (removed_printer_checklist != NULL)
{
if (!GTK_PRINTER_CUPS (iter->data)->avahi_browsed)
for (iter = removed_printer_checklist; iter; iter = iter->next)
{
mark_printer_inactive (GTK_PRINTER (iter->data), backend);
list_has_changed = TRUE;
if (!GTK_PRINTER_CUPS (iter->data)->avahi_browsed)
{
mark_printer_inactive (GTK_PRINTER (iter->data), backend);
list_has_changed = TRUE;
}
}
}
g_list_free (removed_printer_checklist);
}
g_list_free (removed_printer_checklist);
done:
if (list_has_changed)
g_signal_emit_by_name (backend, "printer-list-changed");
gtk_print_backend_set_list_done (backend);
if (!cups_backend->got_default_printer && remote_default_printer != NULL)
if (!backend_finalized)
{
set_default_printer (cups_backend, remote_default_printer);
g_free (remote_default_printer);
}
if (list_has_changed)
g_signal_emit_by_name (backend, "printer-list-changed");
if (!cups_backend->got_default_printer && cups_backend->avahi_default_printer != NULL)
set_default_printer (cups_backend, cups_backend->avahi_default_printer);
gtk_print_backend_set_list_done (backend);
if (!cups_backend->got_default_printer && remote_default_printer != NULL)
{
set_default_printer (cups_backend, remote_default_printer);
g_free (remote_default_printer);
}
if (!cups_backend->got_default_printer && cups_backend->avahi_default_printer != NULL)
set_default_printer (cups_backend, cups_backend->avahi_default_printer);
}
}
static void

1474
po/ko.po

File diff suppressed because it is too large Load Diff

View File

@@ -73,9 +73,10 @@ test_textview_surrounding (void)
GtkTextBuffer *buffer;
GtkTextIter iter;
GtkTextIter start, end;
GtkTextIter bound, insert;
gboolean ret;
char *text;
int cursor_pos, selection_bound;
int anchor_pos, cursor_pos;
widget = gtk_text_view_new ();
controller = gtk_text_view_get_key_controller (GTK_TEXT_VIEW (widget));
@@ -89,12 +90,12 @@ test_textview_surrounding (void)
ret = gtk_im_context_get_surrounding_with_selection (context,
&text,
&cursor_pos,
&selection_bound);
&anchor_pos);
g_assert_true (ret);
g_assert_cmpstr (text, ==, "abcd\nefgh\nijkl");
g_assert_cmpint (cursor_pos, ==, 7);
g_assert_cmpint (selection_bound, ==, 7);
g_assert_cmpint (anchor_pos, ==, 7);
g_free (text);
@@ -122,19 +123,19 @@ test_textview_surrounding (void)
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
gtk_text_buffer_set_text (buffer, "ab cd\nef gh\nijkl", -1);
gtk_text_buffer_get_iter_at_line_offset (buffer, &start, 1, 4);
gtk_text_buffer_get_iter_at_line_offset (buffer, &end, 2, 2);
gtk_text_buffer_select_range (buffer, &start, &end);
gtk_text_buffer_get_iter_at_line_offset (buffer, &bound, 1, 4);
gtk_text_buffer_get_iter_at_line_offset (buffer, &insert, 2, 2);
gtk_text_buffer_select_range (buffer, &insert, &bound);
ret = gtk_im_context_get_surrounding_with_selection (context,
&text,
&cursor_pos,
&selection_bound);
&anchor_pos);
g_assert_true (ret);
g_assert_cmpstr (text, ==, "cd\nef gh\nijkl");
g_assert_cmpint (anchor_pos, ==, 7);
g_assert_cmpint (cursor_pos, ==, 11);
g_assert_cmpint (selection_bound, ==, 7);
g_free (text);

View File

@@ -4,6 +4,9 @@ GTK_BUILDER_TOOL=${GTK_BUILDER_TOOL:-gtk4-builder-tool}
TEST_DATA_DIR=${G_TEST_SRCDIR:-.}/validate-data
TEST_RESULT_DIR=${TEST_RESULT_DIR:-/tmp}/validate
# https://gitlab.freedesktop.org/mesa/mesa/-/issues/10293
export LIBGL_ALWAYS_SOFTWARE=true
mkdir -p "$TEST_RESULT_DIR"
shopt -s nullglob