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.
This commit is contained in:
Matthias Clasen
2024-06-15 00:05:38 -04:00
parent 0402a350e7
commit c3cc3cdacc
4 changed files with 72 additions and 28 deletions

View File

@@ -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);
}

View File

@@ -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,

View File

@@ -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)

View File

@@ -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,