[gnome-shell] st-theme-node-drawing: Don't create lots of one-shot materials
- From: Neil Roberts <nroberts src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] st-theme-node-drawing: Don't create lots of one-shot materials
- Date: Thu, 28 Oct 2010 19:59:58 +0000 (UTC)
commit d66e7dd49edc589577477a98c2806b7930335e24
Author: Neil Roberts <neil linux intel com>
Date: Wed Oct 27 17:41:20 2010 +0100
st-theme-node-drawing: Don't create lots of one-shot materials
A few places in st-theme-node-drawing create one-shot material, paint
with it and then free it. This is suboptimal with current Cogl because
it will end up compiling an ARBfp program just for that single paint
and then it will throw it away when the material is destroyed.
There is a new function in st-private.c called
_st_create_texture_material. This creates a simple material for a
texture based on a common parent material that points to a dummy
texture. Any materials created with this function are likely to be
able to share the same program unless the material is further modified
to contain a different number of layers. It would be possible to use
cogl_set_source_texture for this instead except that it's not possible
to modify the material's color in that case so we couldn't render the
texture with opacity.
The corner textures are now stored as a handle to a material that
references the texture rather than storing the texure directly. There
is also a separate border_material member which always points to
border_texture as the only layer.
https://bugzilla.gnome.org/show_bug.cgi?id=633340
src/st/st-private.c | 43 ++++++++++++++++++++
src/st/st-private.h | 2 +
src/st/st-theme-node-drawing.c | 85 +++++++++++++++++----------------------
src/st/st-theme-node-private.h | 3 +-
4 files changed, 84 insertions(+), 49 deletions(-)
---
diff --git a/src/st/st-private.c b/src/st/st-private.c
index 264ed72..f1f3aab 100644
--- a/src/st/st-private.c
+++ b/src/st/st-private.c
@@ -324,6 +324,49 @@ _st_set_text_from_style (ClutterText *text,
}
}
+/**
+ * _st_create_texture_material:
+ * @src_texture: The CoglTexture for the material
+ *
+ * Creates a simple material which contains the given texture as a
+ * single layer.
+ */
+CoglHandle
+_st_create_texture_material (CoglHandle src_texture)
+{
+ static CoglHandle texture_material_template = COGL_INVALID_HANDLE;
+ CoglHandle material;
+
+ g_return_val_if_fail (src_texture != COGL_INVALID_HANDLE,
+ COGL_INVALID_HANDLE);
+
+ /* We use a material that has a dummy texture as a base for all
+ texture materials. The idea is that only the Cogl texture object
+ would be different in the children so it is likely that Cogl will
+ be able to share GL programs between all the textures. */
+ if (G_UNLIKELY (texture_material_template == COGL_INVALID_HANDLE))
+ {
+ static const guint8 white_pixel[] = { 0xff, 0xff, 0xff, 0xff };
+ CoglHandle dummy_texture;
+
+ dummy_texture =
+ cogl_texture_new_from_data (1, 1,
+ COGL_TEXTURE_NONE,
+ COGL_PIXEL_FORMAT_RGBA_8888_PRE,
+ COGL_PIXEL_FORMAT_ANY,
+ 4, white_pixel);
+
+ texture_material_template = cogl_material_new ();
+ cogl_material_set_layer (texture_material_template, 0, dummy_texture);
+ cogl_handle_unref (dummy_texture);
+ }
+
+ material = cogl_material_copy (texture_material_template);
+
+ cogl_material_set_layer (material, 0, src_texture);
+
+ return material;
+}
/*****
* Shadows
diff --git a/src/st/st-private.h b/src/st/st-private.h
index 33d58d4..0d0e642 100644
--- a/src/st/st-private.h
+++ b/src/st/st-private.h
@@ -73,6 +73,8 @@ void _st_allocate_fill (StWidget *parent,
void _st_set_text_from_style (ClutterText *text,
StThemeNode *theme_node);
+CoglHandle _st_create_texture_material (CoglHandle src_texture);
+
/* Helper for widgets which need to draw additional shadows */
CoglHandle _st_create_shadow_material (StShadow *shadow_spec,
CoglHandle src_texture);
diff --git a/src/st/st-theme-node-drawing.c b/src/st/st-theme-node-drawing.c
index 718a156..d28f03e 100644
--- a/src/st/st-theme-node-drawing.c
+++ b/src/st/st-theme-node-drawing.c
@@ -52,7 +52,7 @@ typedef struct {
} StCornerSpec;
static CoglHandle
-create_corner_texture (StCornerSpec *corner)
+create_corner_material (StCornerSpec *corner)
{
CoglHandle texture;
cairo_t *cr;
@@ -167,7 +167,7 @@ load_corner (StTextureCache *cache,
{
LoadCornerData *data = datap;
- return create_corner_texture (data->corner);
+ return create_corner_material (data->corner);
}
/* To match the CSS specification, we want the border to look like it was
@@ -222,7 +222,7 @@ static CoglHandle
st_theme_node_lookup_corner (StThemeNode *node,
StCorner corner_id)
{
- CoglHandle texture;
+ CoglHandle texture, material;
char *key;
StTextureCache *cache;
StCornerSpec corner;
@@ -269,10 +269,12 @@ st_theme_node_lookup_corner (StThemeNode *node,
data.node = node;
data.corner = &corner;
texture = st_texture_cache_load (cache, key, ST_TEXTURE_CACHE_POLICY_NONE, load_corner, &data, NULL);
+ material = _st_create_texture_material (texture);
+ cogl_handle_unref (texture);
g_free (key);
- return texture;
+ return material;
}
static void
@@ -511,12 +513,14 @@ _st_theme_node_free_drawing_state (StThemeNode *node)
cogl_handle_unref (node->background_shadow_material);
if (node->border_texture != COGL_INVALID_HANDLE)
cogl_handle_unref (node->border_texture);
+ if (node->border_material != COGL_INVALID_HANDLE)
+ cogl_handle_unref (node->border_material);
if (node->border_shadow_material != COGL_INVALID_HANDLE)
cogl_handle_unref (node->border_shadow_material);
for (corner_id = 0; corner_id < 4; corner_id++)
- if (node->corner_texture[corner_id] != COGL_INVALID_HANDLE)
- cogl_handle_unref (node->corner_texture[corner_id]);
+ if (node->corner_material[corner_id] != COGL_INVALID_HANDLE)
+ cogl_handle_unref (node->corner_material[corner_id]);
_st_theme_node_init_drawing_state (node);
}
@@ -530,9 +534,10 @@ _st_theme_node_init_drawing_state (StThemeNode *node)
node->background_shadow_material = COGL_INVALID_HANDLE;
node->border_shadow_material = COGL_INVALID_HANDLE;
node->border_texture = COGL_INVALID_HANDLE;
+ node->border_material = COGL_INVALID_HANDLE;
for (corner_id = 0; corner_id < 4; corner_id++)
- node->corner_texture[corner_id] = COGL_INVALID_HANDLE;
+ node->corner_material[corner_id] = COGL_INVALID_HANDLE;
}
static void st_theme_node_paint_borders (StThemeNode *node,
@@ -581,6 +586,11 @@ st_theme_node_render_resources (StThemeNode *node,
node->border_texture = st_theme_node_render_gradient (node);
}
+ if (node->border_texture)
+ node->border_material = _st_create_texture_material (node->border_texture);
+ else
+ node->border_material = COGL_INVALID_HANDLE;
+
if (shadow_spec)
{
if (node->border_texture != COGL_INVALID_HANDLE)
@@ -630,40 +640,26 @@ st_theme_node_render_resources (StThemeNode *node,
}
}
- node->corner_texture[ST_CORNER_TOPLEFT] =
+ node->corner_material[ST_CORNER_TOPLEFT] =
st_theme_node_lookup_corner (node, ST_CORNER_TOPLEFT);
- node->corner_texture[ST_CORNER_TOPRIGHT] =
+ node->corner_material[ST_CORNER_TOPRIGHT] =
st_theme_node_lookup_corner (node, ST_CORNER_TOPRIGHT);
- node->corner_texture[ST_CORNER_BOTTOMRIGHT] =
+ node->corner_material[ST_CORNER_BOTTOMRIGHT] =
st_theme_node_lookup_corner (node, ST_CORNER_BOTTOMRIGHT);
- node->corner_texture[ST_CORNER_BOTTOMLEFT] =
+ node->corner_material[ST_CORNER_BOTTOMLEFT] =
st_theme_node_lookup_corner (node, ST_CORNER_BOTTOMLEFT);
}
static void
-paint_texture_with_opacity (CoglHandle texture,
- ClutterActorBox *box,
- guint8 paint_opacity)
+paint_material_with_opacity (CoglHandle material,
+ ClutterActorBox *box,
+ guint8 paint_opacity)
{
- if (paint_opacity == 255)
- {
- /* Minor: optimization use the default material if we can */
- cogl_set_source_texture (texture);
- cogl_rectangle (box->x1, box->y1, box->x2, box->y2);
- return;
- }
-
- CoglHandle material;
-
- material = cogl_material_new ();
- cogl_material_set_layer (material, 0, texture);
cogl_material_set_color4ub (material,
paint_opacity, paint_opacity, paint_opacity, paint_opacity);
cogl_set_source (material);
cogl_rectangle (box->x1, box->y1, box->x2, box->y2);
-
- cogl_handle_unref (material);
}
static void
@@ -678,7 +674,6 @@ st_theme_node_paint_borders (StThemeNode *node,
int max_width_radius[4];
int corner_id;
ClutterColor border_color;
- CoglHandle material;
width = box->x2 - box->x1;
height = box->y2 - box->y1;
@@ -753,19 +748,15 @@ st_theme_node_paint_borders (StThemeNode *node,
/* corners */
if (max_border_radius > 0)
{
- material = cogl_material_new ();
- cogl_material_set_color4ub (material,
- paint_opacity, paint_opacity,
- paint_opacity, paint_opacity);
- cogl_set_source (material);
-
for (corner_id = 0; corner_id < 4; corner_id++)
{
- if (node->corner_texture[corner_id] == COGL_INVALID_HANDLE)
+ if (node->corner_material[corner_id] == COGL_INVALID_HANDLE)
continue;
- cogl_material_set_layer (material,
- 0, node->corner_texture[corner_id]);
+ cogl_material_set_color4ub (node->corner_material[corner_id],
+ paint_opacity, paint_opacity,
+ paint_opacity, paint_opacity);
+ cogl_set_source (node->corner_material[corner_id]);
switch (corner_id)
{
@@ -791,7 +782,6 @@ st_theme_node_paint_borders (StThemeNode *node,
break;
}
}
- cogl_handle_unref (material);
}
/* background color */
@@ -930,8 +920,7 @@ st_theme_node_paint_sliced_border_image (StThemeNode *node,
if (ey < 0)
ey = border_bottom; /* FIXME ? */
- material = cogl_material_new ();
- cogl_material_set_layer (material, 0, node->border_texture);
+ material = node->border_material;
cogl_material_set_color4ub (material,
paint_opacity, paint_opacity, paint_opacity, paint_opacity);
@@ -988,8 +977,6 @@ st_theme_node_paint_sliced_border_image (StThemeNode *node,
cogl_rectangles_with_texture_coords (rectangles, 9);
}
-
- cogl_handle_unref (material);
}
static void
@@ -1096,11 +1083,11 @@ st_theme_node_paint (StThemeNode *node,
&allocation,
paint_opacity);
- if (node->border_texture != COGL_INVALID_HANDLE)
+ if (node->border_material != COGL_INVALID_HANDLE)
{
/* Gradients and border images are mutually exclusive at this time */
if (node->background_gradient_type != ST_GRADIENT_NONE)
- paint_texture_with_opacity (node->border_texture, &allocation, paint_opacity);
+ paint_material_with_opacity (node->border_material, &allocation, paint_opacity);
else
st_theme_node_paint_sliced_border_image (node, &allocation, paint_opacity);
}
@@ -1133,7 +1120,7 @@ st_theme_node_paint (StThemeNode *node,
&background_box,
paint_opacity);
- paint_texture_with_opacity (node->background_texture, &background_box, paint_opacity);
+ paint_material_with_opacity (node->border_material, &background_box, paint_opacity);
}
}
@@ -1172,7 +1159,9 @@ st_theme_node_copy_cached_paint_state (StThemeNode *node,
node->background_texture = cogl_handle_ref (other->background_texture);
if (other->border_texture)
node->border_texture = cogl_handle_ref (other->border_texture);
+ if (other->border_material)
+ node->border_material = cogl_handle_ref (other->border_material);
for (corner_id = 0; corner_id < 4; corner_id++)
- if (other->corner_texture[corner_id])
- node->corner_texture[corner_id] = cogl_handle_ref (other->corner_texture[corner_id]);
+ if (other->corner_material[corner_id])
+ node->corner_material[corner_id] = cogl_handle_ref (other->corner_material[corner_id]);
}
diff --git a/src/st/st-theme-node-private.h b/src/st/st-theme-node-private.h
index 9267a6e..c6078fc 100644
--- a/src/st/st-theme-node-private.h
+++ b/src/st/st-theme-node-private.h
@@ -78,7 +78,8 @@ struct _StThemeNode {
CoglHandle border_shadow_material;
CoglHandle background_texture;
CoglHandle border_texture;
- CoglHandle corner_texture[4];
+ CoglHandle border_material;
+ CoglHandle corner_material[4];
};
struct _StThemeNodeClass {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]