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
This commit is contained in:
parent
f365484a5c
commit
d66e7dd49e
@ -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
|
* Shadows
|
||||||
|
@ -73,6 +73,8 @@ void _st_allocate_fill (StWidget *parent,
|
|||||||
void _st_set_text_from_style (ClutterText *text,
|
void _st_set_text_from_style (ClutterText *text,
|
||||||
StThemeNode *theme_node);
|
StThemeNode *theme_node);
|
||||||
|
|
||||||
|
CoglHandle _st_create_texture_material (CoglHandle src_texture);
|
||||||
|
|
||||||
/* Helper for widgets which need to draw additional shadows */
|
/* Helper for widgets which need to draw additional shadows */
|
||||||
CoglHandle _st_create_shadow_material (StShadow *shadow_spec,
|
CoglHandle _st_create_shadow_material (StShadow *shadow_spec,
|
||||||
CoglHandle src_texture);
|
CoglHandle src_texture);
|
||||||
|
@ -52,7 +52,7 @@ typedef struct {
|
|||||||
} StCornerSpec;
|
} StCornerSpec;
|
||||||
|
|
||||||
static CoglHandle
|
static CoglHandle
|
||||||
create_corner_texture (StCornerSpec *corner)
|
create_corner_material (StCornerSpec *corner)
|
||||||
{
|
{
|
||||||
CoglHandle texture;
|
CoglHandle texture;
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
@ -167,7 +167,7 @@ load_corner (StTextureCache *cache,
|
|||||||
{
|
{
|
||||||
LoadCornerData *data = datap;
|
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
|
/* 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,
|
st_theme_node_lookup_corner (StThemeNode *node,
|
||||||
StCorner corner_id)
|
StCorner corner_id)
|
||||||
{
|
{
|
||||||
CoglHandle texture;
|
CoglHandle texture, material;
|
||||||
char *key;
|
char *key;
|
||||||
StTextureCache *cache;
|
StTextureCache *cache;
|
||||||
StCornerSpec corner;
|
StCornerSpec corner;
|
||||||
@ -269,10 +269,12 @@ st_theme_node_lookup_corner (StThemeNode *node,
|
|||||||
data.node = node;
|
data.node = node;
|
||||||
data.corner = &corner;
|
data.corner = &corner;
|
||||||
texture = st_texture_cache_load (cache, key, ST_TEXTURE_CACHE_POLICY_NONE, load_corner, &data, NULL);
|
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);
|
g_free (key);
|
||||||
|
|
||||||
return texture;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -511,12 +513,14 @@ _st_theme_node_free_drawing_state (StThemeNode *node)
|
|||||||
cogl_handle_unref (node->background_shadow_material);
|
cogl_handle_unref (node->background_shadow_material);
|
||||||
if (node->border_texture != COGL_INVALID_HANDLE)
|
if (node->border_texture != COGL_INVALID_HANDLE)
|
||||||
cogl_handle_unref (node->border_texture);
|
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)
|
if (node->border_shadow_material != COGL_INVALID_HANDLE)
|
||||||
cogl_handle_unref (node->border_shadow_material);
|
cogl_handle_unref (node->border_shadow_material);
|
||||||
|
|
||||||
for (corner_id = 0; corner_id < 4; corner_id++)
|
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)
|
||||||
cogl_handle_unref (node->corner_texture[corner_id]);
|
cogl_handle_unref (node->corner_material[corner_id]);
|
||||||
|
|
||||||
_st_theme_node_init_drawing_state (node);
|
_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->background_shadow_material = COGL_INVALID_HANDLE;
|
||||||
node->border_shadow_material = COGL_INVALID_HANDLE;
|
node->border_shadow_material = COGL_INVALID_HANDLE;
|
||||||
node->border_texture = COGL_INVALID_HANDLE;
|
node->border_texture = COGL_INVALID_HANDLE;
|
||||||
|
node->border_material = COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
for (corner_id = 0; corner_id < 4; corner_id++)
|
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,
|
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);
|
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 (shadow_spec)
|
||||||
{
|
{
|
||||||
if (node->border_texture != COGL_INVALID_HANDLE)
|
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);
|
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);
|
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);
|
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);
|
st_theme_node_lookup_corner (node, ST_CORNER_BOTTOMLEFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
paint_texture_with_opacity (CoglHandle texture,
|
paint_material_with_opacity (CoglHandle material,
|
||||||
ClutterActorBox *box,
|
ClutterActorBox *box,
|
||||||
guint8 paint_opacity)
|
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,
|
cogl_material_set_color4ub (material,
|
||||||
paint_opacity, paint_opacity, paint_opacity, paint_opacity);
|
paint_opacity, paint_opacity, paint_opacity, paint_opacity);
|
||||||
|
|
||||||
cogl_set_source (material);
|
cogl_set_source (material);
|
||||||
cogl_rectangle (box->x1, box->y1, box->x2, box->y2);
|
cogl_rectangle (box->x1, box->y1, box->x2, box->y2);
|
||||||
|
|
||||||
cogl_handle_unref (material);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -678,7 +674,6 @@ st_theme_node_paint_borders (StThemeNode *node,
|
|||||||
int max_width_radius[4];
|
int max_width_radius[4];
|
||||||
int corner_id;
|
int corner_id;
|
||||||
ClutterColor border_color;
|
ClutterColor border_color;
|
||||||
CoglHandle material;
|
|
||||||
|
|
||||||
width = box->x2 - box->x1;
|
width = box->x2 - box->x1;
|
||||||
height = box->y2 - box->y1;
|
height = box->y2 - box->y1;
|
||||||
@ -753,19 +748,15 @@ st_theme_node_paint_borders (StThemeNode *node,
|
|||||||
/* corners */
|
/* corners */
|
||||||
if (max_border_radius > 0)
|
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++)
|
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;
|
continue;
|
||||||
|
|
||||||
cogl_material_set_layer (material,
|
cogl_material_set_color4ub (node->corner_material[corner_id],
|
||||||
0, node->corner_texture[corner_id]);
|
paint_opacity, paint_opacity,
|
||||||
|
paint_opacity, paint_opacity);
|
||||||
|
cogl_set_source (node->corner_material[corner_id]);
|
||||||
|
|
||||||
switch (corner_id)
|
switch (corner_id)
|
||||||
{
|
{
|
||||||
@ -791,7 +782,6 @@ st_theme_node_paint_borders (StThemeNode *node,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cogl_handle_unref (material);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* background color */
|
/* background color */
|
||||||
@ -930,8 +920,7 @@ st_theme_node_paint_sliced_border_image (StThemeNode *node,
|
|||||||
if (ey < 0)
|
if (ey < 0)
|
||||||
ey = border_bottom; /* FIXME ? */
|
ey = border_bottom; /* FIXME ? */
|
||||||
|
|
||||||
material = cogl_material_new ();
|
material = node->border_material;
|
||||||
cogl_material_set_layer (material, 0, node->border_texture);
|
|
||||||
cogl_material_set_color4ub (material,
|
cogl_material_set_color4ub (material,
|
||||||
paint_opacity, paint_opacity, paint_opacity, paint_opacity);
|
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_rectangles_with_texture_coords (rectangles, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_handle_unref (material);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1096,11 +1083,11 @@ st_theme_node_paint (StThemeNode *node,
|
|||||||
&allocation,
|
&allocation,
|
||||||
paint_opacity);
|
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 */
|
/* Gradients and border images are mutually exclusive at this time */
|
||||||
if (node->background_gradient_type != ST_GRADIENT_NONE)
|
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
|
else
|
||||||
st_theme_node_paint_sliced_border_image (node, &allocation, paint_opacity);
|
st_theme_node_paint_sliced_border_image (node, &allocation, paint_opacity);
|
||||||
}
|
}
|
||||||
@ -1133,7 +1120,7 @@ st_theme_node_paint (StThemeNode *node,
|
|||||||
&background_box,
|
&background_box,
|
||||||
paint_opacity);
|
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);
|
node->background_texture = cogl_handle_ref (other->background_texture);
|
||||||
if (other->border_texture)
|
if (other->border_texture)
|
||||||
node->border_texture = cogl_handle_ref (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++)
|
for (corner_id = 0; corner_id < 4; corner_id++)
|
||||||
if (other->corner_texture[corner_id])
|
if (other->corner_material[corner_id])
|
||||||
node->corner_texture[corner_id] = cogl_handle_ref (other->corner_texture[corner_id]);
|
node->corner_material[corner_id] = cogl_handle_ref (other->corner_material[corner_id]);
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,8 @@ struct _StThemeNode {
|
|||||||
CoglHandle border_shadow_material;
|
CoglHandle border_shadow_material;
|
||||||
CoglHandle background_texture;
|
CoglHandle background_texture;
|
||||||
CoglHandle border_texture;
|
CoglHandle border_texture;
|
||||||
CoglHandle corner_texture[4];
|
CoglHandle border_material;
|
||||||
|
CoglHandle corner_material[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _StThemeNodeClass {
|
struct _StThemeNodeClass {
|
||||||
|
Loading…
Reference in New Issue
Block a user