st-private: Update shadow APIs for Cogl deprecations

This commit is contained in:
Jasper St. Pierre 2015-02-20 17:09:20 -08:00
parent 8dab692f93
commit 1c1f63a7d7
6 changed files with 129 additions and 163 deletions

View File

@ -57,7 +57,7 @@ struct _StIconPrivate
gint theme_icon_size; /* icon size from theme node */
gint icon_size; /* icon size we are using */
CoglHandle shadow_material;
CoglPipeline *shadow_pipeline;
float shadow_width;
float shadow_height;
StShadow *shadow_spec;
@ -142,23 +142,9 @@ st_icon_dispose (GObject *gobject)
priv->pending_texture = NULL;
}
if (priv->gicon)
{
g_object_unref (priv->gicon);
priv->gicon = NULL;
}
if (priv->shadow_material)
{
cogl_handle_unref (priv->shadow_material);
priv->shadow_material = COGL_INVALID_HANDLE;
}
if (priv->shadow_spec)
{
st_shadow_unref (priv->shadow_spec);
priv->shadow_spec = NULL;
}
g_clear_object (&priv->gicon);
g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref);
g_clear_pointer (&priv->shadow_spec, st_shadow_unref);
G_OBJECT_CLASS (st_icon_parent_class)->dispose (gobject);
}
@ -172,7 +158,7 @@ st_icon_paint (ClutterActor *actor)
if (priv->icon_texture)
{
if (priv->shadow_material)
if (priv->shadow_pipeline)
{
ClutterActorBox allocation;
float width, height;
@ -181,7 +167,7 @@ st_icon_paint (ClutterActor *actor)
clutter_actor_box_get_size (&allocation, &width, &height);
_st_paint_shadow_with_opacity (priv->shadow_spec,
priv->shadow_material,
priv->shadow_pipeline,
&allocation,
clutter_actor_get_paint_opacity (priv->icon_texture));
}
@ -197,17 +183,8 @@ st_icon_style_changed (StWidget *widget)
StThemeNode *theme_node = st_widget_get_theme_node (widget);
StIconPrivate *priv = self->priv;
if (priv->shadow_spec)
{
st_shadow_unref (priv->shadow_spec);
priv->shadow_spec = NULL;
}
if (priv->shadow_material)
{
cogl_handle_unref (priv->shadow_material);
priv->shadow_material = COGL_INVALID_HANDLE;
}
g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref);
g_clear_pointer (&priv->shadow_spec, st_shadow_unref);
priv->shadow_spec = st_theme_node_get_shadow (theme_node, "icon-shadow");
@ -277,33 +254,26 @@ st_icon_init (StIcon *self)
self->priv->icon_size = DEFAULT_ICON_SIZE;
self->priv->prop_icon_size = -1;
self->priv->shadow_material = COGL_INVALID_HANDLE;
self->priv->shadow_pipeline = NULL;
self->priv->shadow_width = -1;
self->priv->shadow_height = -1;
}
static void
st_icon_update_shadow_material (StIcon *icon)
st_icon_update_shadow_pipeline (StIcon *icon)
{
StIconPrivate *priv = icon->priv;
if (priv->shadow_material)
{
cogl_handle_unref (priv->shadow_material);
priv->shadow_material = COGL_INVALID_HANDLE;
}
g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref);
if (priv->shadow_spec)
{
CoglHandle material;
gint width, height;
clutter_texture_get_base_size (CLUTTER_TEXTURE (priv->icon_texture),
&width, &height);
material = _st_create_shadow_material_from_actor (priv->shadow_spec,
priv->icon_texture);
priv->shadow_material = material;
priv->shadow_pipeline = _st_create_shadow_pipeline_from_actor (priv->shadow_spec, priv->icon_texture);
priv->shadow_width = width;
priv->shadow_height = height;
}
@ -313,7 +283,7 @@ static void
on_pixbuf_changed (ClutterTexture *texture,
StIcon *icon)
{
st_icon_update_shadow_material (icon);
st_icon_update_shadow_pipeline (icon);
}
static void
@ -338,7 +308,7 @@ st_icon_finish_update (StIcon *icon)
/* Remove the temporary ref we added */
g_object_unref (priv->icon_texture);
st_icon_update_shadow_material (icon);
st_icon_update_shadow_pipeline (icon);
/* "pixbuf-change" is actually a misnomer for "texture-changed" */
g_signal_connect_object (priv->icon_texture, "pixbuf-change",

View File

@ -60,7 +60,7 @@ struct _StLabelPrivate
{
ClutterActor *label;
CoglHandle text_shadow_material;
CoglPipeline *text_shadow_pipeline;
float shadow_width;
float shadow_height;
};
@ -118,11 +118,7 @@ st_label_style_changed (StWidget *self)
{
StLabelPrivate *priv = ST_LABEL(self)->priv;
if (priv->text_shadow_material != COGL_INVALID_HANDLE)
{
cogl_handle_unref (priv->text_shadow_material);
priv->text_shadow_material = COGL_INVALID_HANDLE;
}
g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
_st_set_text_from_style ((ClutterText *)priv->label, st_widget_get_theme_node (self));
@ -192,11 +188,7 @@ st_label_dispose (GObject *object)
priv->label = NULL;
}
if (priv->text_shadow_material != COGL_INVALID_HANDLE)
{
cogl_handle_unref (priv->text_shadow_material);
priv->text_shadow_material = COGL_INVALID_HANDLE;
}
g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
G_OBJECT_CLASS (st_label_parent_class)->dispose (object);
}
@ -218,26 +210,20 @@ st_label_paint (ClutterActor *actor)
clutter_actor_get_allocation_box (priv->label, &allocation);
clutter_actor_box_get_size (&allocation, &width, &height);
if (priv->text_shadow_material == COGL_INVALID_HANDLE ||
if (priv->text_shadow_pipeline == NULL ||
width != priv->shadow_width ||
height != priv->shadow_height)
{
CoglHandle material;
if (priv->text_shadow_material != COGL_INVALID_HANDLE)
cogl_handle_unref (priv->text_shadow_material);
material = _st_create_shadow_material_from_actor (shadow_spec,
priv->label);
g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
priv->shadow_width = width;
priv->shadow_height = height;
priv->text_shadow_material = material;
priv->text_shadow_pipeline = _st_create_shadow_pipeline_from_actor (shadow_spec, priv->label);
}
if (priv->text_shadow_material != COGL_INVALID_HANDLE)
if (priv->text_shadow_pipeline != NULL)
_st_paint_shadow_with_opacity (shadow_spec,
priv->text_shadow_material,
priv->text_shadow_pipeline,
&allocation,
clutter_actor_get_paint_opacity (priv->label));
}
@ -292,7 +278,7 @@ st_label_init (StLabel *label)
label->priv->label = g_object_new (CLUTTER_TYPE_TEXT,
"ellipsize", PANGO_ELLIPSIZE_END,
NULL);
label->priv->text_shadow_material = COGL_INVALID_HANDLE;
label->priv->text_shadow_pipeline = NULL;
label->priv->shadow_width = -1.;
label->priv->shadow_height = -1.;
@ -357,11 +343,7 @@ st_label_set_text (StLabel *label,
if (clutter_text_get_editable (ctext) ||
g_strcmp0 (clutter_text_get_text (ctext), text) != 0)
{
if (priv->text_shadow_material != COGL_INVALID_HANDLE)
{
cogl_handle_unref (priv->text_shadow_material);
priv->text_shadow_material = COGL_INVALID_HANDLE;
}
g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
clutter_text_set_text (ctext, text);

View File

@ -162,18 +162,20 @@ _st_set_text_from_style (ClutterText *text,
}
/**
* _st_create_texture_material:
* @src_texture: The CoglTexture for the material
* _st_create_texture_pipeline:
* @src_texture: The CoglTexture for the pipeline
*
* Creates a simple material which contains the given texture as a
* Creates a simple pipeline which contains the given texture as a
* single layer.
*/
CoglHandle
_st_create_texture_material (CoglHandle src_texture)
CoglPipeline *
_st_create_texture_pipeline (CoglTexture *src_texture)
{
static CoglPipeline *texture_pipeline_template = NULL;
CoglPipeline *pipeline;
g_return_val_if_fail (src_texture != NULL, NULL);
/* The only state used in the pipeline that would affect the shader
generation is the texture type on the layer. Therefore we create
a template pipeline which sets this state and all texture
@ -339,24 +341,23 @@ blur_pixels (guchar *pixels_in,
return pixels_out;
}
CoglHandle
_st_create_shadow_material (StShadow *shadow_spec,
CoglHandle src_texture)
CoglPipeline *
_st_create_shadow_pipeline (StShadow *shadow_spec,
CoglTexture *src_texture)
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
static CoglHandle shadow_material_template = COGL_INVALID_HANDLE;
static CoglPipeline *shadow_pipeline_template = NULL;
CoglHandle material;
CoglHandle texture;
guchar *pixels_in, *pixels_out;
gint width_in, height_in, rowstride_in;
gint width_out, height_out, rowstride_out;
CoglPipeline *pipeline;
CoglTexture *texture;
guchar *pixels_in, *pixels_out;
gint width_in, height_in, rowstride_in;
gint width_out, height_out, rowstride_out;
g_return_val_if_fail (shadow_spec != NULL, COGL_INVALID_HANDLE);
g_return_val_if_fail (src_texture != COGL_INVALID_HANDLE,
COGL_INVALID_HANDLE);
g_return_val_if_fail (shadow_spec != NULL, NULL);
g_return_val_if_fail (src_texture != NULL, NULL);
width_in = cogl_texture_get_width (src_texture);
height_in = cogl_texture_get_height (src_texture);
@ -380,84 +381,99 @@ _st_create_shadow_material (StShadow *shadow_spec,
g_free (pixels_out);
if (G_UNLIKELY (shadow_material_template == COGL_INVALID_HANDLE))
if (G_UNLIKELY (shadow_pipeline_template == NULL))
{
shadow_material_template = cogl_material_new ();
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
/* We set up the material to blend the shadow texture with the combine
shadow_pipeline_template = cogl_pipeline_new (ctx);
/* We set up the pipeline to blend the shadow texture with the combine
* constant, but defer setting the latter until painting, so that we can
* take the actor's overall opacity into account. */
cogl_material_set_layer_combine (shadow_material_template, 0,
cogl_pipeline_set_layer_combine (shadow_pipeline_template, 0,
"RGBA = MODULATE (CONSTANT, TEXTURE[A])",
NULL);
}
material = cogl_material_copy (shadow_material_template);
cogl_material_set_layer (material, 0, texture);
cogl_handle_unref (texture);
return material;
pipeline = cogl_pipeline_copy (shadow_pipeline_template);
cogl_pipeline_set_layer_texture (pipeline, 0, texture);
cogl_object_unref (texture);
return pipeline;
}
CoglHandle
_st_create_shadow_material_from_actor (StShadow *shadow_spec,
CoglPipeline *
_st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
ClutterActor *actor)
{
CoglHandle shadow_material = COGL_INVALID_HANDLE;
CoglPipeline *shadow_pipeline = NULL;
if (CLUTTER_IS_TEXTURE (actor))
{
CoglHandle texture;
CoglTexture *texture;
texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (actor));
shadow_material = _st_create_shadow_material (shadow_spec, texture);
shadow_pipeline = _st_create_shadow_pipeline (shadow_spec, texture);
}
else
{
CoglHandle buffer, offscreen;
CoglTexture *buffer;
CoglOffscreen *offscreen;
CoglFramebuffer *fb;
ClutterActorBox box;
CoglColor clear_color;
float width, height;
CoglError *catch_error = NULL;
clutter_actor_get_allocation_box (actor, &box);
clutter_actor_box_get_size (&box, &width, &height);
if (width == 0 || height == 0)
return COGL_INVALID_HANDLE;
return NULL;
buffer = cogl_texture_new_with_size (width,
height,
COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_ANY);
if (buffer == COGL_INVALID_HANDLE)
return COGL_INVALID_HANDLE;
if (buffer == NULL)
return NULL;
offscreen = cogl_offscreen_new_to_texture (buffer);
offscreen = cogl_offscreen_new_with_texture (buffer);
fb = COGL_FRAMEBUFFER (offscreen);
if (offscreen == COGL_INVALID_HANDLE)
if (!cogl_framebuffer_allocate (fb, &catch_error))
{
cogl_handle_unref (buffer);
return COGL_INVALID_HANDLE;
cogl_error_free (catch_error);
cogl_object_unref (buffer);
return NULL;
}
cogl_color_set_from_4ub (&clear_color, 0, 0, 0, 0);
cogl_push_framebuffer (offscreen);
cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
cogl_translate (-box.x1, -box.y1, 0);
cogl_ortho (0, width, height, 0, 0, 1.0);
cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
/* XXX: There's no way to render a ClutterActor to an offscreen
* as it uses the implicit API. */
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
cogl_push_framebuffer (fb);
G_GNUC_END_IGNORE_DEPRECATIONS;
cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR, &clear_color);
cogl_framebuffer_translate (fb, -box.x1, -box.y1, 0);
cogl_framebuffer_orthographic (fb, 0, width, height, 0, 0, 1.0);
clutter_actor_paint (actor);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
cogl_pop_framebuffer ();
cogl_handle_unref (offscreen);
G_GNUC_END_IGNORE_DEPRECATIONS;
shadow_material = _st_create_shadow_material (shadow_spec, buffer);
cogl_object_unref (fb);
cogl_handle_unref (buffer);
shadow_pipeline = _st_create_shadow_pipeline (shadow_spec, buffer);
cogl_object_unref (buffer);
}
return shadow_material;
return shadow_pipeline;
}
/**
@ -605,29 +621,27 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
void
_st_paint_shadow_with_opacity (StShadow *shadow_spec,
CoglHandle shadow_material,
CoglPipeline *shadow_pipeline,
ClutterActorBox *box,
guint8 paint_opacity)
{
CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
ClutterActorBox shadow_box;
CoglColor color;
CoglColor color;
g_return_if_fail (shadow_spec != NULL);
g_return_if_fail (shadow_material != COGL_INVALID_HANDLE);
g_return_if_fail (shadow_pipeline != NULL);
st_shadow_get_box (shadow_spec, box, &shadow_box);
cogl_color_set_from_4ub (&color,
shadow_spec->color.red * paint_opacity / 255,
shadow_spec->color.green * paint_opacity / 255,
shadow_spec->color.blue * paint_opacity / 255,
shadow_spec->color.alpha * paint_opacity / 255);
cogl_color_init_from_4ub (&color,
shadow_spec->color.red * paint_opacity / 255,
shadow_spec->color.green * paint_opacity / 255,
shadow_spec->color.blue * paint_opacity / 255,
shadow_spec->color.alpha * paint_opacity / 255);
cogl_color_premultiply (&color);
cogl_material_set_layer_combine_constant (shadow_material, 0, &color);
cogl_set_source (shadow_material);
cogl_rectangle_with_texture_coords (shadow_box.x1, shadow_box.y1,
shadow_box.x2, shadow_box.y2,
0, 0, 1, 1);
cogl_pipeline_set_layer_combine_constant (shadow_pipeline, 0, &color);
cogl_framebuffer_draw_rectangle (fb, shadow_pipeline,
shadow_box.x1, shadow_box.y1,
shadow_box.x2, shadow_box.y2);
}

View File

@ -59,18 +59,18 @@ void _st_actor_get_preferred_height (ClutterActor *actor,
void _st_set_text_from_style (ClutterText *text,
StThemeNode *theme_node);
CoglHandle _st_create_texture_material (CoglHandle src_texture);
CoglPipeline * _st_create_texture_pipeline (CoglTexture *src_texture);
/* Helper for widgets which need to draw additional shadows */
CoglHandle _st_create_shadow_material (StShadow *shadow_spec,
CoglHandle src_texture);
CoglHandle _st_create_shadow_material_from_actor (StShadow *shadow_spec,
ClutterActor *actor);
CoglPipeline * _st_create_shadow_pipeline (StShadow *shadow_spec,
CoglTexture *src_texture);
CoglPipeline * _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
ClutterActor *actor);
cairo_pattern_t *_st_create_shadow_cairo_pattern (StShadow *shadow_spec,
cairo_pattern_t *src_pattern);
void _st_paint_shadow_with_opacity (StShadow *shadow_spec,
CoglHandle shadow_material,
CoglPipeline *shadow_pipeline,
ClutterActorBox *box,
guint8 paint_opacity);

View File

@ -190,7 +190,7 @@ st_shadow_get_box (StShadow *shadow,
struct _StShadowHelper {
StShadow *shadow;
CoglMaterial *material;
CoglPipeline *pipeline;
gfloat width;
gfloat height;
@ -224,14 +224,14 @@ st_shadow_helper_update (StShadowHelper *helper,
clutter_actor_get_size (source, &width, &height);
if (helper->material == NULL ||
if (helper->pipeline == NULL ||
helper->width != width ||
helper->height != height)
{
if (helper->material)
cogl_object_unref (helper->material);
if (helper->pipeline)
cogl_object_unref (helper->pipeline);
helper->material = _st_create_shadow_material_from_actor (helper->shadow, source);
helper->pipeline = _st_create_shadow_pipeline_from_actor (helper->shadow, source);
helper->width = width;
helper->height = height;
}
@ -250,8 +250,8 @@ st_shadow_helper_copy (StShadowHelper *helper)
copy = g_slice_new (StShadowHelper);
*copy = *helper;
if (copy->material)
cogl_object_ref (copy->material);
if (copy->pipeline)
cogl_object_ref (copy->pipeline);
st_shadow_ref (copy->shadow);
return copy;
@ -266,8 +266,8 @@ st_shadow_helper_copy (StShadowHelper *helper)
void
st_shadow_helper_free (StShadowHelper *helper)
{
if (helper->material)
cogl_object_unref (helper->material);
if (helper->pipeline)
cogl_object_unref (helper->pipeline);
st_shadow_unref (helper->shadow);
g_slice_free (StShadowHelper, helper);
@ -293,7 +293,7 @@ st_shadow_helper_paint (StShadowHelper *helper,
clutter_actor_box_get_size (actor_box, &width, &height);
_st_paint_shadow_with_opacity (helper->shadow,
helper->material,
helper->pipeline,
&allocation,
paint_opacity);
}

View File

@ -390,7 +390,7 @@ st_theme_node_lookup_corner (StThemeNode *node,
key = corner_to_string (&corner);
texture = st_texture_cache_load (cache, key, ST_TEXTURE_CACHE_POLICY_NONE, load_corner, &corner, NULL);
material = _st_create_texture_material (texture);
material = _st_create_texture_pipeline (texture);
cogl_handle_unref (texture);
g_free (key);
@ -1314,7 +1314,7 @@ st_theme_node_load_border_image (StThemeNode *node)
if (node->border_slices_texture == COGL_INVALID_HANDLE)
goto out;
node->border_slices_material = _st_create_texture_material (node->border_slices_texture);
node->border_slices_material = _st_create_texture_pipeline (node->border_slices_texture);
}
out:
@ -1364,14 +1364,14 @@ st_theme_node_load_background_image (StThemeNode *node)
if (node->background_texture == COGL_INVALID_HANDLE)
goto out;
node->background_material = _st_create_texture_material (node->background_texture);
node->background_material = _st_create_texture_pipeline (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_shadow_material = _st_create_shadow_pipeline (background_image_shadow_spec,
node->background_texture);
}
}
@ -1474,17 +1474,17 @@ st_theme_node_render_resources (StThemeNodePaintState *state,
state->prerendered_texture = st_theme_node_prerender_background (node, width, height);
if (state->prerendered_texture)
state->prerendered_material = _st_create_texture_material (state->prerendered_texture);
state->prerendered_material = _st_create_texture_pipeline (state->prerendered_texture);
else
state->prerendered_material = COGL_INVALID_HANDLE;
if (box_shadow_spec && !has_inset_box_shadow)
{
if (st_theme_node_load_border_image (node))
state->box_shadow_material = _st_create_shadow_material (box_shadow_spec,
state->box_shadow_material = _st_create_shadow_pipeline (box_shadow_spec,
node->border_slices_texture);
else if (state->prerendered_texture != COGL_INVALID_HANDLE)
state->box_shadow_material = _st_create_shadow_material (box_shadow_spec,
state->box_shadow_material = _st_create_shadow_pipeline (box_shadow_spec,
state->prerendered_texture);
else if (node->background_color.alpha > 0 || has_border)
st_theme_node_prerender_shadow (state);
@ -1546,7 +1546,7 @@ st_theme_node_update_resources (StThemeNodePaintState *state,
if (had_prerendered_texture)
{
state->prerendered_texture = st_theme_node_prerender_background (node, width, height);
state->prerendered_material = _st_create_texture_material (state->prerendered_texture);
state->prerendered_material = _st_create_texture_pipeline (state->prerendered_texture);
}
else
{
@ -1559,7 +1559,7 @@ st_theme_node_update_resources (StThemeNodePaintState *state,
}
if (had_box_shadow)
state->box_shadow_material = _st_create_shadow_material (box_shadow_spec,
state->box_shadow_material = _st_create_shadow_pipeline (box_shadow_spec,
state->prerendered_texture);
}
@ -2188,7 +2188,7 @@ st_theme_node_prerender_shadow (StThemeNodePaintState *state)
cogl_pop_framebuffer ();
cogl_handle_unref (offscreen);
state->box_shadow_material = _st_create_shadow_material (st_theme_node_get_box_shadow (node),
state->box_shadow_material = _st_create_shadow_pipeline (st_theme_node_get_box_shadow (node),
buffer);
}
cogl_handle_unref (buffer);