From 9fe9ea34fd3eb2c99bf5565725f301555c9e0524 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 19 Mar 2024 01:33:32 +0100 Subject: [PATCH 1/3] vulkan: Handle generating mipmaps for 1x1 images Testcase included. --- gsk/gpu/gskgpurenderpassop.c | 4 +++- gsk/gpu/gskvulkanimageprivate.h | 2 +- testsuite/gsk/compare/mipmap-with-1x1.node | 7 +++++++ testsuite/gsk/compare/mipmap-with-1x1.png | Bin 0 -> 81 bytes testsuite/gsk/meson.build | 1 + 5 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 testsuite/gsk/compare/mipmap-with-1x1.node create mode 100644 testsuite/gsk/compare/mipmap-with-1x1.png diff --git a/gsk/gpu/gskgpurenderpassop.c b/gsk/gpu/gskgpurenderpassop.c index c9f7ee2615..4dbfea7aef 100644 --- a/gsk/gpu/gskgpurenderpassop.c +++ b/gsk/gpu/gskgpurenderpassop.c @@ -245,7 +245,9 @@ gsk_gpu_render_pass_end_op_vk_command (GskGpuOp *op, vkCmdEndRenderPass (state->vk_command_buffer); - if (gsk_gpu_image_get_flags (self->target) & GSK_GPU_IMAGE_CAN_MIPMAP) + if ((gsk_gpu_image_get_flags (self->target) & GSK_GPU_IMAGE_CAN_MIPMAP) && + (gsk_gpu_image_get_width (self->target) > 1 || + gsk_gpu_image_get_height (self->target) > 1)) { vkCmdPipelineBarrier (state->vk_command_buffer, gsk_vulkan_image_get_vk_pipeline_stage (GSK_VULKAN_IMAGE (self->target)), diff --git a/gsk/gpu/gskvulkanimageprivate.h b/gsk/gpu/gskvulkanimageprivate.h index 54f2754326..77df1e23b3 100644 --- a/gsk/gpu/gskvulkanimageprivate.h +++ b/gsk/gpu/gskvulkanimageprivate.h @@ -71,7 +71,7 @@ static inline guint gsk_vulkan_mipmap_levels (gsize width, gsize height) { - return g_bit_nth_msf (MAX (width, height) - 1, -1) + 1; + return g_bit_nth_msf (MAX (MAX (width, height) - 1, 1), -1) + 1; } G_END_DECLS diff --git a/testsuite/gsk/compare/mipmap-with-1x1.node b/testsuite/gsk/compare/mipmap-with-1x1.node new file mode 100644 index 0000000000..c52ed08bf9 --- /dev/null +++ b/testsuite/gsk/compare/mipmap-with-1x1.node @@ -0,0 +1,7 @@ +texture-scale { + bounds: 0 0 10 10; + filter: trilinear; + texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWP4z8DwHwAFAAH/q842\ +iQAAAABJRU5ErkJggg==\ +"); +} diff --git a/testsuite/gsk/compare/mipmap-with-1x1.png b/testsuite/gsk/compare/mipmap-with-1x1.png new file mode 100644 index 0000000000000000000000000000000000000000..6c5b2a45af316943253d5aedbbff28feeaa084e1 GIT binary patch literal 81 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4NqD+AhDc0J{&W7ohxv^h2V8m< e1-4!Z=3ua$!zA?eaNi4{8U{~SKbLh*2~7YB$QOJ7 literal 0 HcmV?d00001 diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index a1c3e9cd6d..28ffe5c286 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -104,6 +104,7 @@ compare_render_tests = [ 'mask-modes-with-alpha', 'mask-texture-color-alpha', 'mipmap-generation-later', + 'mipmap-with-1x1', 'nested-rounded-clips', 'offscreen-forced-downscale', 'offscreen-fractional-translate-nogl', From 3080e2974da2d30ba413e442b0dc83ab4a137235 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Fri, 22 Mar 2024 16:18:41 +0100 Subject: [PATCH 2/3] gpu: ceil() offscreen size before generating offscreen The goal is to generate an offscreen at 1x scale. When not ceil()ing the numbers the offscreen code would do it *and* adjust the scale accordingly, so we'd end up with something like a 1.01x scale. And that would cause the code to reenter this codepath with the goal to generate an offscreen at 1x scale. And indeed, this would lead to infinite recursion. Tests included. Fixes #6553 --- gsk/gpu/gskgpunodeprocessor.c | 2 ++ ...ture-scale-nearest-noninteger-scaled-nogl.node | 14 ++++++++++++++ ...xture-scale-nearest-noninteger-scaled-nogl.png | Bin 0 -> 82 bytes testsuite/gsk/meson.build | 1 + 4 files changed, 17 insertions(+) create mode 100644 testsuite/gsk/compare/texture-scale-nearest-noninteger-scaled-nogl.node create mode 100644 testsuite/gsk/compare/texture-scale-nearest-noninteger-scaled-nogl.png diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index 03308e1500..5c3125a2a4 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -2077,6 +2077,8 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, /* now intersect with actual node bounds */ if (!gsk_rect_intersection (&clip_bounds, &node->bounds, &clip_bounds)) return; + clip_bounds.size.width = ceilf (clip_bounds.size.width); + clip_bounds.size.height = ceilf (clip_bounds.size.height); offscreen = gsk_gpu_node_processor_create_offscreen (self->frame, graphene_vec2_one (), &clip_bounds, diff --git a/testsuite/gsk/compare/texture-scale-nearest-noninteger-scaled-nogl.node b/testsuite/gsk/compare/texture-scale-nearest-noninteger-scaled-nogl.node new file mode 100644 index 0000000000..6516dad845 --- /dev/null +++ b/testsuite/gsk/compare/texture-scale-nearest-noninteger-scaled-nogl.node @@ -0,0 +1,14 @@ +color { + bounds: 0 0 3 2; + color: rgb(0,0,0); +} +transform { + transform: scale(2); + child: texture-scale { + bounds: 0 0 1.5 1; + filter: nearest; + texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQImWNoYGAAAAGEAIGs40g+\ +AAAAAElFTkSuQmCC\ +"); + } +} diff --git a/testsuite/gsk/compare/texture-scale-nearest-noninteger-scaled-nogl.png b/testsuite/gsk/compare/texture-scale-nearest-noninteger-scaled-nogl.png new file mode 100644 index 0000000000000000000000000000000000000000..64a761cf996005e9037ae14dad73b685d3253794 GIT binary patch literal 82 zcmeAS@N?(olHy`uVBq!ia0vp^%s|YqnJsEEPS)z4*}Q$iB}g;f$= literal 0 HcmV?d00001 diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index 28ffe5c286..d8776c451a 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -171,6 +171,7 @@ compare_render_tests = [ 'texture-scale-filters-nocairo', 'texture-scale-magnify-10000x', 'texture-scale-magnify-rotate', + 'texture-scale-nearest-noninteger-scaled-nogl', 'texture-scale-nearest-vs-linear', 'texture-scale-offset', 'texture-scale-stripes', From 02d7817632351175d1dc6c98cc8f091c250997c9 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Fri, 22 Mar 2024 19:42:31 +0100 Subject: [PATCH 3/3] demo: Use get_fps() in fishbowl demo Hopefully that leads to somewhat more reliable fps measurements --- demos/gtk-demo/gtkfishbowl.c | 44 ++++++++++++++---------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/demos/gtk-demo/gtkfishbowl.c b/demos/gtk-demo/gtkfishbowl.c index abcb65e55b..feebf2d4be 100644 --- a/demos/gtk-demo/gtkfishbowl.c +++ b/demos/gtk-demo/gtkfishbowl.c @@ -456,43 +456,33 @@ gtk_fishbowl_do_update (GtkFishbowl *fishbowl) { GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl); GdkFrameClock *frame_clock; - GdkFrameTimings *start, *end; - gint64 start_counter, end_counter; - gint64 n_frames, expected_frames; - gint64 start_timestamp, end_timestamp; + GdkFrameTimings *end; + gint64 end_counter; + double fps, expected_fps; gint64 interval; frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (fishbowl)); if (frame_clock == NULL) return; - start_counter = gdk_frame_clock_get_history_start (frame_clock); - end_counter = gdk_frame_clock_get_frame_counter (frame_clock); - start = gdk_frame_clock_get_timings (frame_clock, start_counter); - for (end = gdk_frame_clock_get_timings (frame_clock, end_counter); - end_counter > start_counter && end != NULL && !gdk_frame_timings_get_complete (end); - end = gdk_frame_clock_get_timings (frame_clock, end_counter)) - end_counter--; - if (end_counter - start_counter < 4) + fps = gdk_frame_clock_get_fps (frame_clock); + if (fps <= 0.0) return; - start_timestamp = gdk_frame_timings_get_presentation_time (start); - end_timestamp = gdk_frame_timings_get_presentation_time (end); - if (start_timestamp == 0 || end_timestamp == 0) - { - start_timestamp = gdk_frame_timings_get_frame_time (start); - end_timestamp = gdk_frame_timings_get_frame_time (end); - } - - n_frames = end_counter - start_counter; - priv->framerate = ((double) n_frames) * G_USEC_PER_SEC / (end_timestamp - start_timestamp); - priv->framerate = ((int)(priv->framerate * 100))/100.0; - + priv->framerate = fps; g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_FRAMERATE]); if (!priv->benchmark) return; + end_counter = gdk_frame_clock_get_frame_counter (frame_clock); + for (end = gdk_frame_clock_get_timings (frame_clock, end_counter); + end != NULL && !gdk_frame_timings_get_complete (end); + end = gdk_frame_clock_get_timings (frame_clock, end_counter)) + end_counter--; + if (end == NULL) + return; + interval = gdk_frame_timings_get_refresh_interval (end); if (interval == 0) { @@ -500,16 +490,16 @@ gtk_fishbowl_do_update (GtkFishbowl *fishbowl) if (interval == 0) return; } - expected_frames = round ((double) (end_timestamp - start_timestamp) / interval); + expected_fps = (double) G_USEC_PER_SEC / interval; - if (n_frames >= expected_frames) + if (fps > (expected_fps - 1)) { if (priv->last_benchmark_change > 0) priv->last_benchmark_change *= 2; else priv->last_benchmark_change = 1; } - else if (n_frames + 1 < expected_frames) + else if (0.95 * fps < expected_fps) { if (priv->last_benchmark_change < 0) priv->last_benchmark_change--;