forked from AuroraMiddleware/gtk
gl renderer: Fix render node texture cache
We're caching two things, either a node itself being rendered, or a parent storing a cached version of a child as rendered to an offscreen the size and location of the parent. If both the parent and child uses the cache this will cause a conflict in the cache as it is currently use keying of a node pointer which will have the same value for the node-as-itself and the child-node-of-the-parent. We fix this by adding another part to the key "pointer_is_child" which means we can have the same node pointer twice in the cache. Additionally, in the child-is-rendered-offscreen case the offscreen result actually depends on the position and size of the parent viewport, so we need to store the parent bounds in that case.
This commit is contained in:
parent
e9885f9cde
commit
e14d2be1e8
@ -587,7 +587,8 @@ texture_key_hash (gconstpointer v)
|
||||
|
||||
return GPOINTER_TO_UINT (k->pointer)
|
||||
+ (guint)(k->scale*100)
|
||||
+ (guint)k->filter;
|
||||
+ (guint)k->filter * 2 +
|
||||
+ (guint)k->pointer_is_child;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -598,7 +599,9 @@ texture_key_equal (gconstpointer v1, gconstpointer v2)
|
||||
|
||||
return k1->pointer == k2->pointer &&
|
||||
k1->scale == k2->scale &&
|
||||
k1->filter == k2->filter;
|
||||
k1->filter == k2->filter &&
|
||||
k1->pointer_is_child == k2->pointer_is_child &&
|
||||
(!k1->pointer_is_child || graphene_rect_equal (&k1->parent_rect, &k2->parent_rect));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -25,6 +25,8 @@ typedef struct {
|
||||
gpointer pointer;
|
||||
float scale;
|
||||
int filter;
|
||||
int pointer_is_child;
|
||||
graphene_rect_t parent_rect; /* Only set if pointer_is_child */
|
||||
} GskTextureKey;
|
||||
|
||||
GskGLDriver * gsk_gl_driver_new (GdkGLContext *context);
|
||||
|
@ -626,6 +626,7 @@ render_fallback_node (GskGLRenderer *self,
|
||||
return;
|
||||
|
||||
key.pointer = node;
|
||||
key.pointer_is_child = FALSE;
|
||||
key.scale = scale;
|
||||
key.filter = GL_NEAREST;
|
||||
|
||||
@ -1922,6 +1923,7 @@ render_blur_node (GskGLRenderer *self,
|
||||
}
|
||||
|
||||
key.pointer = node;
|
||||
key.pointer_is_child = FALSE;
|
||||
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);
|
||||
@ -1982,6 +1984,7 @@ render_inset_shadow_node (GskGLRenderer *self,
|
||||
texture_height = ceilf ((node_outline->bounds.size.height + blur_extra) * scale);
|
||||
|
||||
key.pointer = node;
|
||||
key.pointer_is_child = FALSE;
|
||||
key.scale = scale;
|
||||
key.filter = GL_NEAREST;
|
||||
blurred_texture_id = gsk_gl_driver_get_texture_for_key (self->gl_driver, &key);
|
||||
@ -3812,7 +3815,6 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
(flags & FORCE_OFFSCREEN) == 0)
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (child_node);
|
||||
|
||||
upload_texture (self, texture, texture_region_out);
|
||||
*is_offscreen = FALSE;
|
||||
return TRUE;
|
||||
@ -3825,6 +3827,7 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
|
||||
/* Check if we've already cached the drawn texture. */
|
||||
key.pointer = child_node;
|
||||
key.pointer_is_child = TRUE; /* Don't conflict with the child using the cache too */
|
||||
key.scale = ops_get_scale (builder);
|
||||
key.filter = filter;
|
||||
cached_id = gsk_gl_driver_get_texture_for_key (self->gl_driver, &key);
|
||||
|
Loading…
Reference in New Issue
Block a user