summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-09-09 13:55:09 -0400
committerMatthias Clasen <mclasen@redhat.com>2020-09-09 13:55:09 -0400
commit1057588a8ff55e8c43938fe528e46776ca5a1fb3 (patch)
treef1261e551cc6b5eaa2e15f7363150a0f02e4d583
parent9a927176dfb87b9be4de7ef4e2002324638fc0ae (diff)
downloadgtk+-1057588a8ff55e8c43938fe528e46776ca5a1fb3.tar.gz
gsk: Fix the gl texture cache
We need to include both the scale and the filtering in the key for the texture cache, since those affect the texture. This fixes misrendering in the recorder in the inspector whenever transforms are involved. An example where this was showing up is testrevealer's swing transition.
-rw-r--r--gsk/gl/gskgldriver.c44
-rw-r--r--gsk/gl/gskgldriverprivate.h13
-rw-r--r--gsk/gl/gskglrenderer.c59
3 files changed, 82 insertions, 34 deletions
diff --git a/gsk/gl/gskgldriver.c b/gsk/gl/gskgldriver.c
index 08e19a980f..8d101b93df 100644
--- a/gsk/gl/gskgldriver.c
+++ b/gsk/gl/gskgldriver.c
@@ -541,16 +541,37 @@ gsk_gl_driver_get_texture_for_texture (GskGLDriver *self,
return t->texture_id;
}
+static guint
+texture_key_hash (gconstpointer v)
+{
+ const GskTextureKey *k = (GskTextureKey *)v;
+
+ return GPOINTER_TO_UINT (k->pointer)
+ + (guint)(k->scale*100)
+ + (guint)k->filter;
+}
+
+static gboolean
+texture_key_equal (gconstpointer v1, gconstpointer v2)
+{
+ const GskTextureKey *k1 = (GskTextureKey *)v1;
+ const GskTextureKey *k2 = (GskTextureKey *)v2;
+
+ return k1->pointer == k2->pointer &&
+ k1->scale == k2->scale &&
+ k1->filter == k2->filter;
+}
+
int
-gsk_gl_driver_get_texture_for_pointer (GskGLDriver *self,
- gpointer pointer)
+gsk_gl_driver_get_texture_for_key (GskGLDriver *self,
+ GskTextureKey *key)
{
int id = 0;
if (G_UNLIKELY (self->pointer_textures == NULL))
- self->pointer_textures = g_hash_table_new (NULL, NULL);
+ self->pointer_textures = g_hash_table_new_full (texture_key_hash, texture_key_equal, g_free, NULL);
- id = GPOINTER_TO_INT (g_hash_table_lookup (self->pointer_textures, pointer));
+ id = GPOINTER_TO_INT (g_hash_table_lookup (self->pointer_textures, key));
if (id != 0)
{
@@ -566,14 +587,19 @@ gsk_gl_driver_get_texture_for_pointer (GskGLDriver *self,
}
void
-gsk_gl_driver_set_texture_for_pointer (GskGLDriver *self,
- gpointer pointer,
- int texture_id)
+gsk_gl_driver_set_texture_for_key (GskGLDriver *self,
+ GskTextureKey *key,
+ int texture_id)
{
+ GskTextureKey *k;
+
if (G_UNLIKELY (self->pointer_textures == NULL))
- self->pointer_textures = g_hash_table_new (NULL, NULL);
+ self->pointer_textures = g_hash_table_new_full (texture_key_hash, texture_key_equal, g_free, NULL);
+
+ k = g_new (GskTextureKey, 1);
+ *k = *key;
- g_hash_table_insert (self->pointer_textures, pointer, GINT_TO_POINTER (texture_id));
+ g_hash_table_insert (self->pointer_textures, k, GINT_TO_POINTER (texture_id));
}
int
diff --git a/gsk/gl/gskgldriverprivate.h b/gsk/gl/gskgldriverprivate.h
index 22c5ef8cb3..406b959372 100644
--- a/gsk/gl/gskgldriverprivate.h
+++ b/gsk/gl/gskgldriverprivate.h
@@ -21,6 +21,11 @@ typedef struct {
guint texture_id;
} TextureSlice;
+typedef struct {
+ gpointer pointer;
+ float scale;
+ int filter;
+} GskTextureKey;
GskGLDriver * gsk_gl_driver_new (GdkGLContext *context);
GdkGLContext *gsk_gl_driver_get_gl_context (GskGLDriver *driver);
@@ -34,10 +39,10 @@ int gsk_gl_driver_get_texture_for_texture (GskGLDriver *driver
GdkTexture *texture,
int min_filter,
int mag_filter);
-int gsk_gl_driver_get_texture_for_pointer (GskGLDriver *driver,
- gpointer pointer);
-void gsk_gl_driver_set_texture_for_pointer (GskGLDriver *driver,
- gpointer pointer,
+int gsk_gl_driver_get_texture_for_key (GskGLDriver *driver,
+ GskTextureKey *key);
+void gsk_gl_driver_set_texture_for_key (GskGLDriver *driver,
+ GskTextureKey *key,
int texture_id);
int gsk_gl_driver_create_texture (GskGLDriver *driver,
float width,
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 27d1c48cbd..edc2fd2618 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -572,12 +572,17 @@ render_fallback_node (GskGLRenderer *self,
cairo_t *cr;
int cached_id;
int texture_id;
+ GskTextureKey key;
if (surface_width <= 0 ||
surface_height <= 0)
return;
- cached_id = gsk_gl_driver_get_texture_for_pointer (self->gl_driver, node);
+ key.pointer = node;
+ key.scale = scale;
+ key.filter = GL_NEAREST;
+
+ cached_id = gsk_gl_driver_get_texture_for_key (self->gl_driver, &key);
if (cached_id != 0)
{
@@ -659,7 +664,7 @@ render_fallback_node (GskGLRenderer *self,
cairo_surface_destroy (surface);
cairo_surface_destroy (rendered_surface);
- gsk_gl_driver_set_texture_for_pointer (self->gl_driver, node, texture_id);
+ gsk_gl_driver_set_texture_for_key (self->gl_driver, &key, texture_id);
ops_set_program (builder, &self->programs->blit_program);
ops_set_texture (builder, texture_id);
@@ -1638,6 +1643,7 @@ render_blur_node (GskGLRenderer *self,
const float blur_radius = gsk_blur_node_get_radius (node);
GskRenderNode *child = gsk_blur_node_get_child (node);
TextureRegion blurred_region;
+ GskTextureKey key;
if (node_is_invisible (child))
return;
@@ -1648,7 +1654,10 @@ render_blur_node (GskGLRenderer *self,
return;
}
- blurred_region.texture_id = gsk_gl_driver_get_texture_for_pointer (self->gl_driver, node);
+ key.pointer = node;
+ key.scale = ops_get_scale (builder);
+ key.filter = GL_NEAREST;
+ blurred_region.texture_id = gsk_gl_driver_get_texture_for_key (self->gl_driver, &key);
if (blurred_region.texture_id == 0)
blur_node (self, child, builder, blur_radius, 0, &blurred_region, NULL);
@@ -1660,7 +1669,7 @@ render_blur_node (GskGLRenderer *self,
load_offscreen_vertex_data (ops_draw (builder, NULL), node, builder); /* Render result to screen */
/* Add to cache for the blur node */
- gsk_gl_driver_set_texture_for_pointer (self->gl_driver, node, blurred_region.texture_id);
+ gsk_gl_driver_set_texture_for_key (self->gl_driver, &key, blurred_region.texture_id);
}
static inline void
@@ -1698,13 +1707,17 @@ render_inset_shadow_node (GskGLRenderer *self,
float texture_width;
float texture_height;
int blurred_texture_id;
+ GskTextureKey key;
g_assert (blur_radius > 0);
texture_width = ceilf ((node_outline->bounds.size.width + blur_extra) * scale);
texture_height = ceilf ((node_outline->bounds.size.height + blur_extra) * scale);
- blurred_texture_id = gsk_gl_driver_get_texture_for_pointer (self->gl_driver, node);
+ key.pointer = node;
+ key.scale = scale;
+ key.filter = GL_NEAREST;
+ blurred_texture_id = gsk_gl_driver_get_texture_for_key (self->gl_driver, &key);
if (blurred_texture_id == 0)
{
const float spread = gsk_inset_shadow_node_get_spread (node) + (blur_extra / 2.0);
@@ -1800,7 +1813,7 @@ render_inset_shadow_node (GskGLRenderer *self,
const float ty1 = blur_extra / 2.0 * scale / texture_height;
const float ty2 = 1.0 - ty1;
- gsk_gl_driver_set_texture_for_pointer (self->gl_driver, node, blurred_texture_id);
+ gsk_gl_driver_set_texture_for_key (self->gl_driver, &key, blurred_texture_id);
if (needs_clip)
{
@@ -3400,6 +3413,8 @@ add_offscreen_ops (GskGLRenderer *self,
int texture_id = 0;
int max_texture_size;
int filter;
+ GskTextureKey key;
+ int cached_id;
if (node_is_invisible (child_node))
{
@@ -3421,18 +3436,24 @@ add_offscreen_ops (GskGLRenderer *self,
return TRUE;
}
+ if (flags & LINEAR_FILTER)
+ filter = GL_LINEAR;
+ else
+ filter = GL_NEAREST;
+
/* Check if we've already cached the drawn texture. */
- {
- const int cached_id = gsk_gl_driver_get_texture_for_pointer (self->gl_driver, child_node);
+ key.pointer = child_node;
+ key.scale = ops_get_scale (builder);
+ key.filter = filter;
+ cached_id = gsk_gl_driver_get_texture_for_key (self->gl_driver, &key);
- if (cached_id != 0)
- {
- init_full_texture_region (texture_region_out, cached_id);
- /* We didn't render it offscreen, but hand out an offscreen texture id */
- *is_offscreen = TRUE;
- return TRUE;
- }
- }
+ if (cached_id != 0)
+ {
+ init_full_texture_region (texture_region_out, cached_id);
+ /* We didn't render it offscreen, but hand out an offscreen texture id */
+ *is_offscreen = TRUE;
+ return TRUE;
+ }
scale = ops_get_scale (builder);
width = bounds->size.width;
@@ -3452,10 +3473,6 @@ add_offscreen_ops (GskGLRenderer *self,
width = ceilf (width * scale);
height = ceilf (height * scale);
- if (flags & LINEAR_FILTER)
- filter = GL_LINEAR;
- else
- filter = GL_NEAREST;
gsk_gl_driver_create_render_target (self->gl_driver,
width, height,
filter, filter,
@@ -3534,7 +3551,7 @@ add_offscreen_ops (GskGLRenderer *self,
init_full_texture_region (texture_region_out, texture_id);
if ((flags & NO_CACHE_PLZ) == 0)
- gsk_gl_driver_set_texture_for_pointer (self->gl_driver, child_node, texture_id);
+ gsk_gl_driver_set_texture_for_key (self->gl_driver, &key, texture_id);
return TRUE;
}