summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2023-03-10 23:38:50 +0000
committerMatthias Clasen <mclasen@redhat.com>2023-03-10 23:38:50 +0000
commitbf1a5d99cfd119c8c64228d0470a802e9fdabd83 (patch)
tree5706831476ecc6c38c9b41754ec0380437fa8cfc
parent4014e956cdd15867c0ac70071fc1eef120c89559 (diff)
parent89d131de561b02d0f022426e8541738391463d76 (diff)
downloadgtk+-bf1a5d99cfd119c8c64228d0470a802e9fdabd83.tar.gz
Merge branch 'cache-scaled-texture' into 'main'
gsk: Cache scaled texture Closes #5642 See merge request GNOME/gtk!5633
-rw-r--r--demos/gtk-demo/menu.c81
-rw-r--r--gsk/gl/gskglrenderjob.c15
2 files changed, 88 insertions, 8 deletions
diff --git a/demos/gtk-demo/menu.c b/demos/gtk-demo/menu.c
index 63610632c0..1669df9bb4 100644
--- a/demos/gtk-demo/menu.c
+++ b/demos/gtk-demo/menu.c
@@ -1,18 +1,75 @@
-/* Menu
- * #Keywords: action, zoom
- *
- * Demonstrates how to add a context menu to a custom widget
- * and connect it with widget actions.
+/* Image Scaling
+ * #Keywords: zoom, scale, filter, action, menu
*
* The custom widget we create here is similar to a GtkPicture,
- * but allows setting a zoom level for the displayed paintable.
+ * but allows setting a zoom level and filtering mode for the
+ * displayed paintable.
+ *
+ * It also demonstrates how to add a context menu to a custom
+ * widget and connect it with widget actions.
*
- * Our context menu has items to change the zoom level.
+ * The context menu has items to change the zoom level.
*/
#include <gtk/gtk.h>
#include "demo3widget.h"
+static void
+file_opened (GObject *source,
+ GAsyncResult *result,
+ void *data)
+{
+ GFile *file;
+ GError *error = NULL;
+ GdkTexture *texture;
+
+ file = gtk_file_dialog_open_finish (GTK_FILE_DIALOG (source), result, &error);
+
+ if (!file)
+ {
+ g_print ("%s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ texture = gdk_texture_new_from_file (file, &error);
+ g_object_unref (file);
+ if (!texture)
+ {
+ g_print ("%s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ g_object_set (G_OBJECT (data), "texture", texture, NULL);
+ g_object_unref (texture);
+}
+
+static void
+open_file (GtkWidget *picker,
+ GtkWidget *demo)
+{
+ GtkWindow *parent = GTK_WINDOW (gtk_widget_get_root (picker));
+ GtkFileDialog *dialog;
+ GtkFileFilter *filter;
+ GListStore *filters;
+
+ dialog = gtk_file_dialog_new ();
+
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_set_name (filter, "Images");
+ gtk_file_filter_add_pixbuf_formats (filter);
+ filters = g_list_store_new (GTK_TYPE_FILE_FILTER);
+ g_list_store_append (filters, filter);
+ g_object_unref (filter);
+
+ gtk_file_dialog_set_filters (dialog, G_LIST_MODEL (filters));
+ g_object_unref (filters);
+
+ gtk_file_dialog_open (dialog, parent, NULL, file_opened, demo);
+
+ g_object_unref (dialog);
+}
GtkWidget *
do_menu (GtkWidget *do_widget)
@@ -27,9 +84,10 @@ do_menu (GtkWidget *do_widget)
GtkWidget *widget;
GtkWidget *scale;
GtkWidget *dropdown;
+ GtkWidget *button;
window = gtk_window_new ();
- gtk_window_set_title (GTK_WINDOW (window), "Menu");
+ gtk_window_set_title (GTK_WINDOW (window), "Image Scaling");
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
@@ -48,12 +106,19 @@ do_menu (GtkWidget *do_widget)
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_append (GTK_BOX (box), box2);
+ button = gtk_button_new_from_icon_name ("document-open-symbolic");
+ gtk_widget_set_tooltip_text (button, "Open File");
+ g_signal_connect (button, "clicked", G_CALLBACK (open_file), widget);
+ gtk_box_append (GTK_BOX (box2), button);
+
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0.01, 10.0, 0.1);
+ gtk_widget_set_tooltip_text (scale, "Zoom");
gtk_range_set_value (GTK_RANGE (scale), 1.0);
gtk_widget_set_hexpand (scale, TRUE);
gtk_box_append (GTK_BOX (box2), scale);
dropdown = gtk_drop_down_new (G_LIST_MODEL (gtk_string_list_new ((const char *[]){ "Linear", "Nearest", "Trilinear", NULL })), NULL);
+ gtk_widget_set_tooltip_text (dropdown, "Filter");
gtk_box_append (GTK_BOX (box2), dropdown);
g_object_bind_property (dropdown, "selected", widget, "filter", G_BINDING_DEFAULT);
diff --git a/gsk/gl/gskglrenderjob.c b/gsk/gl/gskglrenderjob.c
index 1fcd13a1e2..433e38638c 100644
--- a/gsk/gl/gskglrenderjob.c
+++ b/gsk/gl/gskglrenderjob.c
@@ -3640,6 +3640,7 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
guint prev_fbo;
guint texture_id;
float u0, u1, v0, v1;
+ GskTextureKey key;
gsk_gl_render_job_untransform_bounds (job, &job->current_clip->rect.bounds, &clip_rect);
if (!graphene_rect_intersection (bounds, &clip_rect, &clip_rect))
@@ -3652,6 +3653,17 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
return;
}
+ key.pointer = node;
+ key.pointer_is_child = TRUE;
+ key.parent_rect = clip_rect;
+ key.scale_x = 1.;
+ key.scale_y = 1.;
+ key.filter = min_filter;
+
+ texture_id = gsk_gl_driver_lookup_texture (job->driver, &key);
+ if (texture_id != 0)
+ goto render_texture;
+
viewport = GRAPHENE_RECT_INIT (0, 0,
clip_rect.size.width,
clip_rect.size.height);
@@ -3707,6 +3719,9 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
texture_id = gsk_gl_driver_release_render_target (job->driver, render_target, FALSE);
+ gsk_gl_driver_cache_texture (job->driver, &key, texture_id);
+
+render_texture:
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
gsk_gl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,