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) { - if (G_UNLIKELY (self->pointer_textures == NULL)) - self->pointer_textures = g_hash_table_new (NULL, NULL); + GskTextureKey *k; - g_hash_table_insert (self->pointer_textures, pointer, GINT_TO_POINTER (texture_id)); + if (G_UNLIKELY (self->pointer_textures == 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, 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; } - /* 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); + if (flags & LINEAR_FILTER) + filter = GL_LINEAR; + else + filter = GL_NEAREST; - 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; - } - } + /* Check if we've already cached the drawn texture. */ + 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; + } 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; }