st-theme-node: Move some allocation-independent textures back to the theme node
The background image, background image shadow and border image are allocation-indepedent, so we can keep these in the node. Given that these are are likely cached in the StTextureCache, the slight increase in code complexity may not be worth caching these textures and materials -- we might be better off just computing when we need to paint. https://bugzilla.gnome.org/show_bug.cgi?id=697274
This commit is contained in:
parent
49064ed56d
commit
c29aaa047d
@ -462,7 +462,6 @@ get_background_coordinates (StThemeNode *node,
|
||||
|
||||
static void
|
||||
get_background_position (StThemeNode *self,
|
||||
StThemeNodePaintState *state,
|
||||
const ClutterActorBox *allocation,
|
||||
ClutterActorBox *result,
|
||||
ClutterActorBox *texture_coords)
|
||||
@ -473,8 +472,8 @@ get_background_position (StThemeNode *self,
|
||||
gdouble scale_w, scale_h;
|
||||
|
||||
/* get the background image size */
|
||||
background_image_width = cogl_texture_get_width (state->background_texture);
|
||||
background_image_height = cogl_texture_get_height (state->background_texture);
|
||||
background_image_width = cogl_texture_get_width (self->background_texture);
|
||||
background_image_height = cogl_texture_get_height (self->background_texture);
|
||||
|
||||
/* get the painting area size */
|
||||
painting_area_width = allocation->x2 - allocation->x1;
|
||||
@ -1274,26 +1273,117 @@ static void st_theme_node_paint_borders (StThemeNode *node,
|
||||
const ClutterActorBox *box,
|
||||
guint8 paint_opacity);
|
||||
|
||||
void
|
||||
st_theme_node_invalidate_border_image (StThemeNode *node)
|
||||
{
|
||||
if (node->border_slices_texture != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (node->border_slices_texture);
|
||||
node->border_slices_texture = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (node->border_slices_material != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (node->border_slices_material);
|
||||
node->border_slices_material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
st_theme_node_load_border_image (StThemeNode *node)
|
||||
{
|
||||
if (node->border_slices_texture == COGL_INVALID_HANDLE)
|
||||
{
|
||||
StBorderImage *border_image;
|
||||
|
||||
border_image = st_theme_node_get_border_image (node);
|
||||
if (border_image == NULL)
|
||||
goto out;
|
||||
|
||||
const char *filename;
|
||||
filename = st_border_image_get_filename (border_image);
|
||||
node->border_slices_texture = st_texture_cache_load_file_to_cogl_texture (st_texture_cache_get_default (),
|
||||
filename);
|
||||
if (node->border_slices_texture == COGL_INVALID_HANDLE)
|
||||
goto out;
|
||||
|
||||
node->border_slices_material = _st_create_texture_material (node->border_slices_texture);
|
||||
}
|
||||
|
||||
out:
|
||||
return node->border_slices_texture != COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
void
|
||||
st_theme_node_invalidate_background_image (StThemeNode *node)
|
||||
{
|
||||
if (node->background_texture != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (node->background_texture);
|
||||
node->background_texture = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (node->background_material != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (node->background_material);
|
||||
node->background_material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (node->background_shadow_material != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (node->background_shadow_material);
|
||||
node->background_shadow_material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
st_theme_node_load_background_image (StThemeNode *node)
|
||||
{
|
||||
if (node->background_texture == COGL_INVALID_HANDLE)
|
||||
{
|
||||
const char *background_image;
|
||||
StShadow *background_image_shadow_spec;
|
||||
|
||||
background_image = st_theme_node_get_background_image (node);
|
||||
if (background_image == NULL)
|
||||
goto out;
|
||||
|
||||
background_image_shadow_spec = st_theme_node_get_background_image_shadow (node);
|
||||
node->background_texture = st_texture_cache_load_file_to_cogl_texture (st_texture_cache_get_default (),
|
||||
background_image);
|
||||
if (node->background_texture == COGL_INVALID_HANDLE)
|
||||
goto out;
|
||||
|
||||
node->background_material = _st_create_texture_material (node->background_texture);
|
||||
|
||||
if (node->background_repeat)
|
||||
cogl_material_set_layer_wrap_mode (node->background_material, 0, COGL_MATERIAL_WRAP_MODE_REPEAT);
|
||||
|
||||
if (background_image_shadow_spec)
|
||||
{
|
||||
node->background_shadow_material = _st_create_shadow_material (background_image_shadow_spec,
|
||||
node->background_texture);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return node->background_texture != COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
static void
|
||||
st_theme_node_render_resources (StThemeNode *node,
|
||||
StThemeNodePaintState *state,
|
||||
float width,
|
||||
float height)
|
||||
{
|
||||
StTextureCache *texture_cache;
|
||||
StBorderImage *border_image;
|
||||
gboolean has_border;
|
||||
gboolean has_border_radius;
|
||||
gboolean has_inset_box_shadow;
|
||||
gboolean has_large_corners;
|
||||
StShadow *box_shadow_spec;
|
||||
StShadow *background_image_shadow_spec;
|
||||
const char *background_image;
|
||||
|
||||
g_return_if_fail (width > 0 && height > 0);
|
||||
|
||||
texture_cache = st_texture_cache_get_default ();
|
||||
|
||||
/* FIXME - need to separate this into things that need to be recomputed on
|
||||
* geometry change versus things that can be cached regardless, such as
|
||||
* a background image.
|
||||
@ -1346,24 +1436,6 @@ st_theme_node_render_resources (StThemeNode *node,
|
||||
}
|
||||
}
|
||||
|
||||
/* Load referenced images from disk and draw anything we need with cairo now */
|
||||
background_image = st_theme_node_get_background_image (node);
|
||||
border_image = st_theme_node_get_border_image (node);
|
||||
|
||||
if (border_image)
|
||||
{
|
||||
const char *filename;
|
||||
|
||||
filename = st_border_image_get_filename (border_image);
|
||||
|
||||
state->border_slices_texture = st_texture_cache_load_file_to_cogl_texture (texture_cache, filename);
|
||||
}
|
||||
|
||||
if (state->border_slices_texture)
|
||||
state->border_slices_material = _st_create_texture_material (state->border_slices_texture);
|
||||
else
|
||||
state->border_slices_material = COGL_INVALID_HANDLE;
|
||||
|
||||
state->corner_material[ST_CORNER_TOPLEFT] =
|
||||
st_theme_node_lookup_corner (node, width, height, ST_CORNER_TOPLEFT);
|
||||
state->corner_material[ST_CORNER_TOPRIGHT] =
|
||||
@ -1384,7 +1456,7 @@ st_theme_node_render_resources (StThemeNode *node,
|
||||
*/
|
||||
if ((node->background_gradient_type != ST_GRADIENT_NONE)
|
||||
|| (has_inset_box_shadow && (has_border || node->background_color.alpha > 0))
|
||||
|| (background_image && (has_border || has_border_radius))
|
||||
|| (st_theme_node_get_background_image (node) && (has_border || has_border_radius))
|
||||
|| has_large_corners)
|
||||
state->prerendered_texture = st_theme_node_prerender_background (node, width, height);
|
||||
|
||||
@ -1395,9 +1467,9 @@ st_theme_node_render_resources (StThemeNode *node,
|
||||
|
||||
if (box_shadow_spec && !has_inset_box_shadow)
|
||||
{
|
||||
if (state->border_slices_texture != COGL_INVALID_HANDLE)
|
||||
if (st_theme_node_load_border_image (node))
|
||||
state->box_shadow_material = _st_create_shadow_material (box_shadow_spec,
|
||||
state->border_slices_texture);
|
||||
node->border_slices_texture);
|
||||
else if (state->prerendered_texture != COGL_INVALID_HANDLE)
|
||||
state->box_shadow_material = _st_create_shadow_material (box_shadow_spec,
|
||||
state->prerendered_texture);
|
||||
@ -1434,22 +1506,6 @@ st_theme_node_render_resources (StThemeNode *node,
|
||||
cogl_handle_unref (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
background_image_shadow_spec = st_theme_node_get_background_image_shadow (node);
|
||||
if (background_image != NULL && !has_border && !has_border_radius)
|
||||
{
|
||||
state->background_texture = st_texture_cache_load_file_to_cogl_texture (texture_cache, background_image);
|
||||
state->background_material = _st_create_texture_material (state->background_texture);
|
||||
|
||||
if (node->background_repeat)
|
||||
cogl_material_set_layer_wrap_mode (state->background_material, 0, COGL_MATERIAL_WRAP_MODE_REPEAT);
|
||||
|
||||
if (background_image_shadow_spec)
|
||||
{
|
||||
state->background_shadow_material = _st_create_shadow_material (background_image_shadow_spec,
|
||||
state->background_texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1738,7 +1794,6 @@ st_theme_node_paint_borders (StThemeNode *node,
|
||||
|
||||
static void
|
||||
st_theme_node_paint_sliced_border_image (StThemeNode *node,
|
||||
StThemeNodePaintState *state,
|
||||
float width,
|
||||
float height,
|
||||
guint8 paint_opacity)
|
||||
@ -1756,8 +1811,8 @@ st_theme_node_paint_sliced_border_image (StThemeNode *node,
|
||||
st_border_image_get_borders (border_image,
|
||||
&border_left, &border_right, &border_top, &border_bottom);
|
||||
|
||||
img_width = cogl_texture_get_width (state->border_slices_texture);
|
||||
img_height = cogl_texture_get_height (state->border_slices_texture);
|
||||
img_width = cogl_texture_get_width (node->border_slices_texture);
|
||||
img_height = cogl_texture_get_height (node->border_slices_texture);
|
||||
|
||||
tx1 = border_left / img_width;
|
||||
tx2 = (img_width - border_right) / img_width;
|
||||
@ -1772,7 +1827,7 @@ st_theme_node_paint_sliced_border_image (StThemeNode *node,
|
||||
if (ey < 0)
|
||||
ey = border_bottom; /* FIXME ? */
|
||||
|
||||
material = state->border_slices_material;
|
||||
material = node->border_slices_material;
|
||||
cogl_material_set_color4ub (material,
|
||||
paint_opacity, paint_opacity, paint_opacity, paint_opacity);
|
||||
|
||||
@ -1945,7 +2000,7 @@ st_theme_node_paint (StThemeNode *node,
|
||||
paint_opacity);
|
||||
|
||||
if (state->prerendered_material != COGL_INVALID_HANDLE ||
|
||||
state->border_slices_material != COGL_INVALID_HANDLE)
|
||||
st_theme_node_load_border_image (node))
|
||||
{
|
||||
if (state->prerendered_material != COGL_INVALID_HANDLE)
|
||||
{
|
||||
@ -1961,8 +2016,8 @@ st_theme_node_paint (StThemeNode *node,
|
||||
paint_opacity);
|
||||
}
|
||||
|
||||
if (state->border_slices_material != COGL_INVALID_HANDLE)
|
||||
st_theme_node_paint_sliced_border_image (node, state, width, height, paint_opacity);
|
||||
if (node->border_slices_material != COGL_INVALID_HANDLE)
|
||||
st_theme_node_paint_sliced_border_image (node, width, height, paint_opacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1971,7 +2026,8 @@ st_theme_node_paint (StThemeNode *node,
|
||||
|
||||
st_theme_node_paint_outline (node, box, paint_opacity);
|
||||
|
||||
if (state->background_texture != COGL_INVALID_HANDLE)
|
||||
if (state->prerendered_material == COGL_INVALID_HANDLE &&
|
||||
st_theme_node_load_background_image (node))
|
||||
{
|
||||
ClutterActorBox background_box;
|
||||
ClutterActorBox texture_coords;
|
||||
@ -1983,7 +2039,7 @@ st_theme_node_paint (StThemeNode *node,
|
||||
*/
|
||||
has_visible_outline = st_theme_node_has_visible_outline (node);
|
||||
|
||||
get_background_position (node, state, &allocation, &background_box, &texture_coords);
|
||||
get_background_position (node, &allocation, &background_box, &texture_coords);
|
||||
|
||||
if (has_visible_outline || node->background_repeat)
|
||||
cogl_clip_push_rectangle (allocation.x1, allocation.y1, allocation.x2, allocation.y2);
|
||||
@ -2001,13 +2057,13 @@ st_theme_node_paint (StThemeNode *node,
|
||||
* there is nothing (like a border, or the edge of the background color)
|
||||
* to logically confine it.
|
||||
*/
|
||||
if (state->background_shadow_material != COGL_INVALID_HANDLE)
|
||||
if (node->background_shadow_material != COGL_INVALID_HANDLE)
|
||||
_st_paint_shadow_with_opacity (node->background_image_shadow,
|
||||
state->background_shadow_material,
|
||||
node->background_shadow_material,
|
||||
&background_box,
|
||||
paint_opacity);
|
||||
|
||||
paint_material_with_opacity (state->background_material,
|
||||
paint_material_with_opacity (node->background_material,
|
||||
&background_box,
|
||||
&texture_coords,
|
||||
paint_opacity);
|
||||
@ -2022,16 +2078,6 @@ st_theme_node_paint_state_free (StThemeNodePaintState *state)
|
||||
{
|
||||
int corner_id;
|
||||
|
||||
if (state->background_texture != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (state->background_texture);
|
||||
if (state->background_material != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (state->background_material);
|
||||
if (state->background_shadow_material != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (state->background_shadow_material);
|
||||
if (state->border_slices_texture != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (state->border_slices_texture);
|
||||
if (state->border_slices_material != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (state->border_slices_material);
|
||||
if (state->prerendered_texture != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (state->prerendered_texture);
|
||||
if (state->prerendered_material != COGL_INVALID_HANDLE)
|
||||
@ -2051,12 +2097,7 @@ st_theme_node_paint_state_init (StThemeNodePaintState *state)
|
||||
{
|
||||
int corner_id;
|
||||
|
||||
state->background_texture = COGL_INVALID_HANDLE;
|
||||
state->background_material = COGL_INVALID_HANDLE;
|
||||
state->background_shadow_material = COGL_INVALID_HANDLE;
|
||||
state->box_shadow_material = COGL_INVALID_HANDLE;
|
||||
state->border_slices_texture = COGL_INVALID_HANDLE;
|
||||
state->border_slices_material = COGL_INVALID_HANDLE;
|
||||
state->prerendered_texture = COGL_INVALID_HANDLE;
|
||||
state->prerendered_material = COGL_INVALID_HANDLE;
|
||||
|
||||
@ -2078,18 +2119,8 @@ st_theme_node_paint_state_copy (StThemeNodePaintState *state,
|
||||
state->alloc_width = other->alloc_width;
|
||||
state->alloc_height = other->alloc_height;
|
||||
|
||||
if (other->background_shadow_material)
|
||||
state->background_shadow_material = cogl_handle_ref (other->background_shadow_material);
|
||||
if (other->box_shadow_material)
|
||||
state->box_shadow_material = cogl_handle_ref (other->box_shadow_material);
|
||||
if (other->background_texture)
|
||||
state->background_texture = cogl_handle_ref (other->background_texture);
|
||||
if (other->background_material)
|
||||
state->background_material = cogl_handle_ref (other->background_material);
|
||||
if (other->border_slices_texture)
|
||||
state->border_slices_texture = cogl_handle_ref (other->border_slices_texture);
|
||||
if (other->border_slices_material)
|
||||
state->border_slices_material = cogl_handle_ref (other->border_slices_material);
|
||||
if (other->prerendered_texture)
|
||||
state->prerendered_texture = cogl_handle_ref (other->prerendered_texture);
|
||||
if (other->prerendered_material)
|
||||
|
@ -99,6 +99,12 @@ struct _StThemeNode {
|
||||
guint background_image_shadow_computed : 1;
|
||||
guint text_shadow_computed : 1;
|
||||
guint link_type : 2;
|
||||
|
||||
CoglHandle border_slices_texture;
|
||||
CoglHandle border_slices_material;
|
||||
CoglHandle background_texture;
|
||||
CoglHandle background_material;
|
||||
CoglHandle background_shadow_material;
|
||||
};
|
||||
|
||||
struct _StThemeNodeClass {
|
||||
|
@ -49,6 +49,11 @@ static void
|
||||
st_theme_node_init (StThemeNode *node)
|
||||
{
|
||||
node->transition_duration = -1;
|
||||
node->background_texture = COGL_INVALID_HANDLE;
|
||||
node->background_material = COGL_INVALID_HANDLE;
|
||||
node->background_shadow_material = COGL_INVALID_HANDLE;
|
||||
node->border_slices_texture = COGL_INVALID_HANDLE;
|
||||
node->border_slices_material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -151,6 +156,17 @@ st_theme_node_finalize (GObject *object)
|
||||
if (node->background_image)
|
||||
g_free (node->background_image);
|
||||
|
||||
if (node->background_texture != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (node->background_texture);
|
||||
if (node->background_material != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (node->background_material);
|
||||
if (node->background_shadow_material != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (node->background_shadow_material);
|
||||
if (node->border_slices_texture != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (node->border_slices_texture);
|
||||
if (node->border_slices_material != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (node->border_slices_material);
|
||||
|
||||
G_OBJECT_CLASS (st_theme_node_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
@ -100,11 +100,6 @@ struct _StThemeNodePaintState {
|
||||
float alloc_width;
|
||||
float alloc_height;
|
||||
|
||||
CoglHandle background_texture;
|
||||
CoglHandle background_material;
|
||||
CoglHandle border_slices_texture;
|
||||
CoglHandle border_slices_material;
|
||||
CoglHandle background_shadow_material;
|
||||
CoglHandle box_shadow_material;
|
||||
CoglHandle prerendered_texture;
|
||||
CoglHandle prerendered_material;
|
||||
@ -271,11 +266,14 @@ void st_theme_node_paint (StThemeNode *node,
|
||||
const ClutterActorBox *box,
|
||||
guint8 paint_opacity);
|
||||
|
||||
void st_theme_node_invalidate_background_image (StThemeNode *node);
|
||||
void st_theme_node_invalidate_border_image (StThemeNode *node);
|
||||
|
||||
void st_theme_node_paint_state_init (StThemeNodePaintState *state);
|
||||
void st_theme_node_paint_state_free (StThemeNodePaintState *state);
|
||||
void st_theme_node_paint_state_copy (StThemeNodePaintState *state,
|
||||
StThemeNodePaintState *other);
|
||||
void st_theme_node_paint_state_invalidate (StThemeNodePaintState *node);
|
||||
void st_theme_node_paint_state_invalidate (StThemeNodePaintState *state);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -278,32 +278,42 @@ st_widget_texture_cache_changed (StTextureCache *cache,
|
||||
{
|
||||
StWidget *actor = ST_WIDGET (user_data);
|
||||
StThemeNode *node = actor->priv->theme_node;
|
||||
StBorderImage *border_image;
|
||||
char *path;
|
||||
gboolean changed;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
path = g_filename_from_uri (uri, NULL, NULL);
|
||||
|
||||
changed = g_strcmp0 (st_theme_node_get_background_image (node), path) == 0;
|
||||
if (g_strcmp0 (st_theme_node_get_background_image (node), path) == 0)
|
||||
{
|
||||
st_theme_node_invalidate_background_image (node);
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
border_image = st_theme_node_get_border_image (node);
|
||||
if (!changed && border_image)
|
||||
changed = strcmp (st_border_image_get_filename (border_image), path) == 0;
|
||||
|
||||
g_free (path);
|
||||
|
||||
if (!changed)
|
||||
return;
|
||||
if (g_strcmp0 (st_border_image_get_filename (st_theme_node_get_border_image (node)), path) == 0)
|
||||
{
|
||||
st_theme_node_invalidate_border_image (node);
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
/* If we prerender the background / border, we need to update
|
||||
* the paint state. We should probably implement a method to
|
||||
* the theme node to determine this, but for now, just wipe
|
||||
* the entire paint state.
|
||||
*/
|
||||
st_theme_node_paint_state_invalidate (&actor->priv->paint_state);
|
||||
|
||||
if (CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR (actor)))
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
|
||||
}
|
||||
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
static void
|
||||
st_widget_dispose (GObject *gobject)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user