From c3cc3cdaccd58dfe293275e30b81c770d94f8b4f Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 15 Jun 2024 00:05:38 -0400 Subject: [PATCH] gpu: Improve texture caching Keep up to two different images per texture - that is enough to keep the original uploaded image and the one that has been converted to the compositing colorstate. --- gsk/gpu/gskgpudevice.c | 48 ++++++++++++++++++++++++++++++----- gsk/gpu/gskgpudeviceprivate.h | 4 +-- gsk/gpu/gskgpuframe.c | 4 +-- gsk/gpu/gskgpunodeprocessor.c | 44 +++++++++++++++++++------------- 4 files changed, 72 insertions(+), 28 deletions(-) diff --git a/gsk/gpu/gskgpudevice.c b/gsk/gpu/gskgpudevice.c index 992c1ef2ca..0c29c149ae 100644 --- a/gsk/gpu/gskgpudevice.c +++ b/gsk/gpu/gskgpudevice.c @@ -12,6 +12,7 @@ #include "gsk/gskdebugprivate.h" #include "gsk/gskprivate.h" +#include "gdk/gdkcolorstateprivate.h" #define MAX_SLICES_PER_ATLAS 64 @@ -253,6 +254,8 @@ struct _GskGpuCachedTexture GdkTexture *texture; GskGpuImage *image; GdkColorState *color_state; + GskGpuImage *image2; + GdkColorState *color_state2; }; static void @@ -265,6 +268,8 @@ gsk_gpu_cached_texture_free (GskGpuDevice *device, g_clear_object (&self->image); g_clear_pointer (&self->color_state, gdk_color_state_unref); + g_clear_object (&self->image2); + g_clear_pointer (&self->color_state2, gdk_color_state_unref); if (g_hash_table_steal_extended (priv->texture_cache, self->texture, &key, &value)) { @@ -344,6 +349,8 @@ gsk_gpu_cached_texture_new (GskGpuDevice *device, self->texture = texture; self->image = g_object_ref (image); self->color_state = gdk_color_state_ref (color_state); + self->image2 = NULL; + self->color_state2 = NULL; ((GskGpuCached *)self)->pixels = gsk_gpu_image_get_width (image) * gsk_gpu_image_get_height (image); self->dead_pixels_counter = &priv->dead_texture_pixels; self->use_count = 2; @@ -856,24 +863,30 @@ gsk_gpu_device_add_atlas_image (GskGpuDevice *self, GskGpuImage * gsk_gpu_device_lookup_texture_image (GskGpuDevice *self, GdkTexture *texture, - gint64 timestamp, - GdkColorState **out_color_state) + GdkColorState *color_state, + gint64 timestamp) { GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self); GskGpuCachedTexture *cache; + GskGpuImage *image; cache = gdk_texture_get_render_data (texture, self); if (cache == NULL) cache = g_hash_table_lookup (priv->texture_cache, texture); - if (!cache || !cache->image || gsk_gpu_cached_texture_is_invalid (cache)) + if (!cache || gsk_gpu_cached_texture_is_invalid (cache)) + return NULL; + + if (gdk_color_state_equal (color_state, cache->color_state)) + image = cache->image; + else if (cache->color_state2 && gdk_color_state_equal (color_state, cache->color_state2)) + image = cache->image2; + else return NULL; gsk_gpu_cached_use (self, (GskGpuCached *) cache, timestamp); - *out_color_state = cache->color_state; - - return g_object_ref (cache->image); + return g_object_ref (image); } void @@ -885,7 +898,28 @@ gsk_gpu_device_cache_texture_image (GskGpuDevice *self, { GskGpuCachedTexture *cache; - cache = gsk_gpu_cached_texture_new (self, texture, image, color_state); + cache = gdk_texture_get_render_data (texture, self); + if (cache) + { + if (gdk_color_state_equal (color_state, gdk_texture_get_color_state (texture))) + { + g_clear_pointer (&cache->color_state, gdk_color_state_unref); + g_clear_object (&cache->image); + cache->color_state = gdk_color_state_ref (color_state); + cache->image = g_object_ref (image); + } + else + { + g_clear_pointer (&cache->color_state2, gdk_color_state_unref); + g_clear_object (&cache->image2); + cache->color_state2 = gdk_color_state_ref (color_state); + cache->image2 = g_object_ref (image); + } + } + else + { + cache = gsk_gpu_cached_texture_new (self, texture, image, color_state); + } gsk_gpu_cached_use (self, (GskGpuCached *) cache, timestamp); } diff --git a/gsk/gpu/gskgpudeviceprivate.h b/gsk/gpu/gskgpudeviceprivate.h index 34719b5f99..3e8b3072fe 100644 --- a/gsk/gpu/gskgpudeviceprivate.h +++ b/gsk/gpu/gskgpudeviceprivate.h @@ -73,8 +73,8 @@ GskGpuImage * gsk_gpu_device_create_download_image (GskGpuD void gsk_gpu_device_make_current (GskGpuDevice *self); GskGpuImage * gsk_gpu_device_lookup_texture_image (GskGpuDevice *self, GdkTexture *texture, - gint64 timestamp, - GdkColorState **out_color_state); + GdkColorState *color_state, + gint64 timestamp); void gsk_gpu_device_cache_texture_image (GskGpuDevice *self, GdkTexture *texture, gint64 timestamp, diff --git a/gsk/gpu/gskgpuframe.c b/gsk/gpu/gskgpuframe.c index 1cfc40d163..ddfc194f66 100644 --- a/gsk/gpu/gskgpuframe.c +++ b/gsk/gpu/gskgpuframe.c @@ -17,6 +17,7 @@ #include "gdk/gdkdmabufdownloaderprivate.h" #include "gdk/gdktexturedownloaderprivate.h" +#include "gdk/gdkcolorstateprivate.h" #define DEFAULT_VERTEX_BUFFER_SIZE 128 * 1024 @@ -707,9 +708,8 @@ gsk_gpu_frame_download_texture (GskGpuFrame *self, { GskGpuFramePrivate *priv = gsk_gpu_frame_get_instance_private (self); GskGpuImage *image; - GdkColorState *color_state = NULL; - image = gsk_gpu_device_lookup_texture_image (priv->device, texture, timestamp, &color_state); + image = gsk_gpu_device_lookup_texture_image (priv->device, texture, gdk_color_state_get_srgb (), timestamp); if (image == NULL) image = gsk_gpu_frame_upload_texture (self, FALSE, texture); if (image == NULL) diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index ae131cfa14..86de310ab0 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -927,7 +927,6 @@ gsk_gpu_get_node_as_image (GskGpuFrame *frame, graphene_rect_t *out_bounds) { GskGpuImage *result; - GdkColorState *orig_color_state = NULL; switch ((guint) gsk_render_node_get_node_type (node)) { @@ -936,16 +935,21 @@ gsk_gpu_get_node_as_image (GskGpuFrame *frame, GdkTexture *texture = gsk_texture_node_get_texture (node); GskGpuDevice *device = gsk_gpu_frame_get_device (frame); gint64 timestamp = gsk_gpu_frame_get_timestamp (frame); - result = gsk_gpu_device_lookup_texture_image (device, texture, timestamp, &orig_color_state); + result = gsk_gpu_device_lookup_texture_image (device, texture, color_state, timestamp); if (result == NULL) { result = gsk_gpu_frame_upload_texture (frame, FALSE, texture); - orig_color_state = gdk_texture_get_color_state (texture); + + if (result && + !gdk_color_state_equal (gdk_texture_get_color_state (texture), color_state)) + { + result = gsk_gpu_color_convert (frame, result, gdk_texture_get_color_state (texture), color_state); + gsk_gpu_device_cache_texture_image (device, texture, timestamp, result, color_state); + } } if (result) { - result = gsk_gpu_color_convert (frame, result, orig_color_state, color_state); *out_bounds = node->bounds; return result; } @@ -2087,13 +2091,12 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self, GskGpuImage *image; GdkTexture *texture; gint64 timestamp; - GdkColorState *color_state = NULL; device = gsk_gpu_frame_get_device (self->frame); texture = gsk_texture_node_get_texture (node); timestamp = gsk_gpu_frame_get_timestamp (self->frame); - image = gsk_gpu_device_lookup_texture_image (device, texture, timestamp, &color_state); + image = gsk_gpu_device_lookup_texture_image (device, texture, self->color_state, timestamp); if (image == NULL) { image = gsk_gpu_frame_upload_texture (self->frame, FALSE, texture); @@ -2106,9 +2109,12 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self, gsk_gpu_node_processor_add_fallback_node (self, node); return; } - color_state = gdk_texture_get_color_state (texture); + if (!gdk_color_state_equal (gdk_texture_get_color_state (texture), self->color_state)) + { + image = gsk_gpu_color_convert (self->frame, image, gdk_texture_get_color_state (texture), self->color_state); + gsk_gpu_device_cache_texture_image (device, texture, timestamp, image, self->color_state); + } } - image = gsk_gpu_color_convert (self->frame, image, color_state, self->color_state); if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) && (gdk_texture_get_width (texture) > 2 * node->bounds.size.width * graphene_vec2_get_x (&self->scale) || @@ -2165,21 +2171,24 @@ gsk_gpu_node_processor_create_texture_pattern (GskGpuPatternWriter *self, guint32 descriptor; GskGpuImage *image; GskGpuSampler sampler; - GdkColorState *color_state = NULL; device = gsk_gpu_frame_get_device (self->frame); texture = gsk_texture_node_get_texture (node); timestamp = gsk_gpu_frame_get_timestamp (self->frame); - image = gsk_gpu_device_lookup_texture_image (device, texture, timestamp, &color_state); + image = gsk_gpu_device_lookup_texture_image (device, texture, self->color_state, timestamp); if (image == NULL) { image = gsk_gpu_frame_upload_texture (self->frame, FALSE, texture); if (image == NULL) return FALSE; - color_state = gdk_texture_get_color_state (texture); + + if (!gdk_color_state_equal (gdk_texture_get_color_state (texture), self->color_state)) + { + image = gsk_gpu_color_convert (self->frame, image, gdk_texture_get_color_state (texture), self->color_state); + gsk_gpu_device_cache_texture_image (device, texture, timestamp, image, self->color_state); + } } - image = gsk_gpu_color_convert (self->frame, image, color_state, self->color_state); if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) && (gdk_texture_get_width (texture) > 2 * node->bounds.size.width * graphene_vec2_get_x (&self->scale) || @@ -2226,7 +2235,6 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, gint64 timestamp; guint32 descriptor; gboolean need_mipmap, need_offscreen; - GdkColorState *color_state = NULL; need_offscreen = self->modelview != NULL || !graphene_vec2_equal (&self->scale, graphene_vec2_one ()); @@ -2271,7 +2279,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, timestamp = gsk_gpu_frame_get_timestamp (self->frame); need_mipmap = scaling_filter == GSK_SCALING_FILTER_TRILINEAR; - image = gsk_gpu_device_lookup_texture_image (device, texture, timestamp, &color_state); + image = gsk_gpu_device_lookup_texture_image (device, texture, self->color_state, timestamp); if (image == NULL) { image = gsk_gpu_frame_upload_texture (self->frame, need_mipmap, texture); @@ -2284,11 +2292,13 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, gsk_gpu_node_processor_add_fallback_node (self, node); return; } - color_state = gdk_texture_get_color_state (texture); + if (!gdk_color_state_equal (gdk_texture_get_color_state (texture), self->color_state)) + { + image = gsk_gpu_color_convert (self->frame, image, gdk_texture_get_color_state (texture), self->color_state); + gsk_gpu_device_cache_texture_image (device, texture, timestamp, image, self->color_state); + } } - image = gsk_gpu_color_convert (self->frame, image, color_state, self->color_state); - image = gsk_gpu_node_processor_ensure_image (self->frame, image, self->color_state,