actor: Move the ShaderData out of the private data
Let's try and start reducing the size of ClutterActorPrivate by moving some optional, out-of-band data from it to GObject data. The ShaderData structure is a prime candidate for this migration: it does not need to be inspected by the actor, and its relationship with an actor is transient and optional. By attaching it to the actor's instance through g_object_set_data() we neatly tie its lifetime to the instance, and we don't have to care cleaning it up in the finalize()/dispose() implementation of ClutterActor itself.
This commit is contained in:
parent
9ea2567a2f
commit
fc89513295
@ -451,8 +451,6 @@ struct _ClutterActorPrivate
|
|||||||
|
|
||||||
AnchorCoord scale_center;
|
AnchorCoord scale_center;
|
||||||
|
|
||||||
ShaderData *shader_data;
|
|
||||||
|
|
||||||
PangoContext *pango_context;
|
PangoContext *pango_context;
|
||||||
|
|
||||||
ClutterTextDirection text_direction;
|
ClutterTextDirection text_direction;
|
||||||
@ -607,8 +605,6 @@ static void clutter_actor_shader_pre_paint (ClutterActor *actor,
|
|||||||
gboolean repeat);
|
gboolean repeat);
|
||||||
static void clutter_actor_shader_post_paint (ClutterActor *actor);
|
static void clutter_actor_shader_post_paint (ClutterActor *actor);
|
||||||
|
|
||||||
static void destroy_shader_data (ClutterActor *self);
|
|
||||||
|
|
||||||
/* These setters are all static for now, maybe they should be in the
|
/* These setters are all static for now, maybe they should be in the
|
||||||
* public API, but they are perhaps obscure enough to leave only as
|
* public API, but they are perhaps obscure enough to leave only as
|
||||||
* properties
|
* properties
|
||||||
@ -667,6 +663,8 @@ static ClutterPaintVolume *_clutter_actor_get_paint_volume_mutable (ClutterActor
|
|||||||
{ _transform; } \
|
{ _transform; } \
|
||||||
cogl_matrix_translate ((m), -_tx, -_ty, -_tz); } G_STMT_END
|
cogl_matrix_translate ((m), -_tx, -_ty, -_tz); } G_STMT_END
|
||||||
|
|
||||||
|
static GQuark quark_shader_data = 0;
|
||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ClutterActor,
|
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ClutterActor,
|
||||||
clutter_actor,
|
clutter_actor,
|
||||||
G_TYPE_INITIALLY_UNOWNED,
|
G_TYPE_INITIALLY_UNOWNED,
|
||||||
@ -2533,6 +2531,12 @@ cull_actor (ClutterActor *self)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline gboolean
|
||||||
|
actor_has_shader_data (ClutterActor *self)
|
||||||
|
{
|
||||||
|
return g_object_get_qdata (G_OBJECT (self), quark_shader_data) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_actor_paint:
|
* clutter_actor_paint:
|
||||||
* @self: A #ClutterActor
|
* @self: A #ClutterActor
|
||||||
@ -2688,7 +2692,7 @@ clutter_actor_paint (ClutterActor *self)
|
|||||||
|
|
||||||
if (priv->effects != NULL)
|
if (priv->effects != NULL)
|
||||||
effect_painted = _clutter_actor_effects_pre_paint (self);
|
effect_painted = _clutter_actor_effects_pre_paint (self);
|
||||||
else if (priv->shader_data != NULL)
|
else if (actor_has_shader_data (self))
|
||||||
clutter_actor_shader_pre_paint (self, FALSE);
|
clutter_actor_shader_pre_paint (self, FALSE);
|
||||||
|
|
||||||
priv->propagated_one_redraw = FALSE;
|
priv->propagated_one_redraw = FALSE;
|
||||||
@ -2696,7 +2700,7 @@ clutter_actor_paint (ClutterActor *self)
|
|||||||
|
|
||||||
if (effect_painted)
|
if (effect_painted)
|
||||||
_clutter_actor_effects_post_paint (self);
|
_clutter_actor_effects_post_paint (self);
|
||||||
else if (priv->shader_data != NULL)
|
else if (actor_has_shader_data (self))
|
||||||
clutter_actor_shader_post_paint (self);
|
clutter_actor_shader_post_paint (self);
|
||||||
|
|
||||||
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_VOLUMES))
|
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_VOLUMES))
|
||||||
@ -3348,8 +3352,6 @@ clutter_actor_dispose (GObject *object)
|
|||||||
g_assert (!CLUTTER_ACTOR_IS_REALIZED (self));
|
g_assert (!CLUTTER_ACTOR_IS_REALIZED (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy_shader_data (self);
|
|
||||||
|
|
||||||
if (priv->pango_context)
|
if (priv->pango_context)
|
||||||
{
|
{
|
||||||
g_object_unref (priv->pango_context);
|
g_object_unref (priv->pango_context);
|
||||||
@ -3460,6 +3462,8 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
|||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
GParamSpec *pspec;
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
quark_shader_data = g_quark_from_static_string ("-clutter-actor-shader-data");
|
||||||
|
|
||||||
object_class->set_property = clutter_actor_set_property;
|
object_class->set_property = clutter_actor_set_property;
|
||||||
object_class->get_property = clutter_actor_get_property;
|
object_class->get_property = clutter_actor_get_property;
|
||||||
object_class->dispose = clutter_actor_dispose;
|
object_class->dispose = clutter_actor_dispose;
|
||||||
@ -4886,17 +4890,16 @@ clutter_actor_init (ClutterActor *self)
|
|||||||
self->priv = priv = CLUTTER_ACTOR_GET_PRIVATE (self);
|
self->priv = priv = CLUTTER_ACTOR_GET_PRIVATE (self);
|
||||||
|
|
||||||
priv->parent_actor = NULL;
|
priv->parent_actor = NULL;
|
||||||
priv->has_clip = FALSE;
|
priv->has_clip = FALSE;
|
||||||
priv->opacity = 0xff;
|
priv->opacity = 0xff;
|
||||||
priv->id = clutter_id_pool_add (CLUTTER_CONTEXT()->id_pool, self);
|
priv->id = clutter_id_pool_add (CLUTTER_CONTEXT()->id_pool, self);
|
||||||
priv->scale_x = 1.0;
|
priv->scale_x = 1.0;
|
||||||
priv->scale_y = 1.0;
|
priv->scale_y = 1.0;
|
||||||
priv->shader_data = NULL;
|
|
||||||
priv->show_on_set_parent = TRUE;
|
priv->show_on_set_parent = TRUE;
|
||||||
|
|
||||||
priv->needs_width_request = TRUE;
|
priv->needs_width_request = TRUE;
|
||||||
priv->needs_height_request = TRUE;
|
priv->needs_height_request = TRUE;
|
||||||
priv->needs_allocation = TRUE;
|
priv->needs_allocation = TRUE;
|
||||||
|
|
||||||
priv->cached_width_age = 1;
|
priv->cached_width_age = 1;
|
||||||
priv->cached_height_age = 1;
|
priv->cached_height_age = 1;
|
||||||
@ -9395,12 +9398,13 @@ G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterVertex, clutter_vertex,
|
|||||||
clutter_vertex_free,
|
clutter_vertex_free,
|
||||||
CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_vertex_progress));
|
CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_vertex_progress));
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
struct _ShaderData
|
struct _ShaderData
|
||||||
{
|
{
|
||||||
ClutterShader *shader;
|
ClutterShader *shader;
|
||||||
|
|
||||||
|
/* back pointer to the actor */
|
||||||
|
ClutterActor *actor;
|
||||||
|
|
||||||
/* list of values that should be set on the shader
|
/* list of values that should be set on the shader
|
||||||
* before each paint cycle
|
* before each paint cycle
|
||||||
*/
|
*/
|
||||||
@ -9416,28 +9420,26 @@ shader_value_free (gpointer data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy_shader_data (ClutterActor *self)
|
destroy_shader_data (gpointer data)
|
||||||
{
|
{
|
||||||
ClutterActorPrivate *actor_priv = self->priv;
|
ShaderData *shader_data = data;
|
||||||
ShaderData *shader_data = actor_priv->shader_data;
|
|
||||||
|
|
||||||
if (shader_data == NULL)
|
if (shader_data == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (shader_data->shader)
|
if (shader_data->shader != NULL)
|
||||||
{
|
{
|
||||||
g_object_unref (shader_data->shader);
|
g_object_unref (shader_data->shader);
|
||||||
shader_data->shader = NULL;
|
shader_data->shader = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shader_data->value_hash)
|
if (shader_data->value_hash != NULL)
|
||||||
{
|
{
|
||||||
g_hash_table_destroy (shader_data->value_hash);
|
g_hash_table_destroy (shader_data->value_hash);
|
||||||
shader_data->value_hash = NULL;
|
shader_data->value_hash = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_slice_free (ShaderData, shader_data);
|
g_slice_free (ShaderData, shader_data);
|
||||||
actor_priv->shader_data = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -9455,18 +9457,15 @@ destroy_shader_data (ClutterActor *self)
|
|||||||
ClutterShader *
|
ClutterShader *
|
||||||
clutter_actor_get_shader (ClutterActor *self)
|
clutter_actor_get_shader (ClutterActor *self)
|
||||||
{
|
{
|
||||||
ClutterActorPrivate *actor_priv;
|
ShaderData *shader_data;
|
||||||
ShaderData *shader_data;
|
|
||||||
|
|
||||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL);
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL);
|
||||||
|
|
||||||
actor_priv = self->priv;
|
shader_data = g_object_get_qdata (G_OBJECT (self), quark_shader_data);
|
||||||
shader_data = actor_priv->shader_data;
|
if (shader_data != NULL)
|
||||||
|
return shader_data->shader;
|
||||||
|
|
||||||
if (shader_data == NULL)
|
return NULL;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return shader_data->shader;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9476,10 +9475,14 @@ clutter_actor_get_shader (ClutterActor *self)
|
|||||||
*
|
*
|
||||||
* Sets the #ClutterShader to be used when rendering @self.
|
* Sets the #ClutterShader to be used when rendering @self.
|
||||||
*
|
*
|
||||||
* If @shader is %NULL it will unset any currently set shader
|
* If @shader is %NULL this function will unset any currently set shader
|
||||||
* for the actor.
|
* for the actor.
|
||||||
*
|
*
|
||||||
|
* <note>Any #ClutterEffect applied to @self will take the precedence
|
||||||
|
* over the #ClutterShader set using this function.</note>
|
||||||
|
*
|
||||||
* Return value: %TRUE if the shader was successfully applied
|
* Return value: %TRUE if the shader was successfully applied
|
||||||
|
* or removed
|
||||||
*
|
*
|
||||||
* Since: 0.6
|
* Since: 0.6
|
||||||
*/
|
*/
|
||||||
@ -9487,8 +9490,7 @@ gboolean
|
|||||||
clutter_actor_set_shader (ClutterActor *self,
|
clutter_actor_set_shader (ClutterActor *self,
|
||||||
ClutterShader *shader)
|
ClutterShader *shader)
|
||||||
{
|
{
|
||||||
ClutterActorPrivate *actor_priv;
|
ShaderData *shader_data;
|
||||||
ShaderData *shader_data;
|
|
||||||
|
|
||||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
|
||||||
g_return_val_if_fail (shader == NULL || CLUTTER_IS_SHADER (shader), FALSE);
|
g_return_val_if_fail (shader == NULL || CLUTTER_IS_SHADER (shader), FALSE);
|
||||||
@ -9498,22 +9500,26 @@ clutter_actor_set_shader (ClutterActor *self,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* if shader passed in is NULL we destroy the shader */
|
/* if shader passed in is NULL we destroy the shader */
|
||||||
destroy_shader_data (self);
|
g_object_set_qdata (G_OBJECT (self), quark_shader_data, NULL);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
actor_priv = self->priv;
|
shader_data = g_object_get_qdata (G_OBJECT (self), quark_shader_data);
|
||||||
shader_data = actor_priv->shader_data;
|
|
||||||
|
|
||||||
if (shader_data == NULL)
|
if (shader_data == NULL)
|
||||||
{
|
{
|
||||||
actor_priv->shader_data = shader_data = g_slice_new (ShaderData);
|
shader_data = g_slice_new (ShaderData);
|
||||||
|
shader_data->actor = self;
|
||||||
shader_data->shader = NULL;
|
shader_data->shader = NULL;
|
||||||
shader_data->value_hash =
|
shader_data->value_hash =
|
||||||
g_hash_table_new_full (g_str_hash, g_str_equal,
|
g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
g_free,
|
g_free,
|
||||||
shader_value_free);
|
shader_value_free);
|
||||||
|
|
||||||
|
g_object_set_qdata_full (G_OBJECT (self), quark_shader_data,
|
||||||
|
shader_data,
|
||||||
|
destroy_shader_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shader_data->shader != NULL)
|
if (shader_data->shader != NULL)
|
||||||
g_object_unref (shader_data->shader);
|
g_object_unref (shader_data->shader);
|
||||||
|
|
||||||
@ -9530,31 +9536,29 @@ set_each_param (gpointer key,
|
|||||||
gpointer value,
|
gpointer value,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
ClutterShader *shader = user_data;
|
ClutterShader *shader = user_data;
|
||||||
GValue *var = value;
|
const gchar *uniform = key;
|
||||||
|
GValue *var = value;
|
||||||
|
|
||||||
clutter_shader_set_uniform (shader, (const gchar *)key, var);
|
clutter_shader_set_uniform (shader, uniform, var);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_actor_shader_pre_paint (ClutterActor *actor,
|
clutter_actor_shader_pre_paint (ClutterActor *actor,
|
||||||
gboolean repeat)
|
gboolean repeat)
|
||||||
{
|
{
|
||||||
ClutterActorPrivate *priv;
|
ShaderData *shader_data;
|
||||||
ShaderData *shader_data;
|
ClutterShader *shader;
|
||||||
ClutterShader *shader;
|
ClutterMainContext *context;
|
||||||
ClutterMainContext *context;
|
|
||||||
|
|
||||||
priv = actor->priv;
|
shader_data = g_object_get_qdata (G_OBJECT (actor), quark_shader_data);
|
||||||
shader_data = priv->shader_data;
|
if (shader_data == NULL)
|
||||||
|
|
||||||
if (!shader_data)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
context = _clutter_context_get_default ();
|
||||||
shader = shader_data->shader;
|
shader = shader_data->shader;
|
||||||
|
|
||||||
if (shader)
|
if (shader != NULL)
|
||||||
{
|
{
|
||||||
clutter_shader_set_is_enabled (shader, TRUE);
|
clutter_shader_set_is_enabled (shader, TRUE);
|
||||||
|
|
||||||
@ -9568,21 +9572,18 @@ clutter_actor_shader_pre_paint (ClutterActor *actor,
|
|||||||
static void
|
static void
|
||||||
clutter_actor_shader_post_paint (ClutterActor *actor)
|
clutter_actor_shader_post_paint (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
ClutterActorPrivate *priv;
|
ShaderData *shader_data;
|
||||||
ShaderData *shader_data;
|
ClutterShader *shader;
|
||||||
ClutterShader *shader;
|
ClutterMainContext *context;
|
||||||
ClutterMainContext *context;
|
|
||||||
|
|
||||||
priv = actor->priv;
|
shader_data = g_object_get_qdata (G_OBJECT (actor), quark_shader_data);
|
||||||
shader_data = priv->shader_data;
|
if (shader_data == NULL)
|
||||||
|
|
||||||
if (!shader_data)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
context = _clutter_context_get_default ();
|
||||||
shader = shader_data->shader;
|
shader = shader_data->shader;
|
||||||
|
|
||||||
if (shader)
|
if (shader != NULL)
|
||||||
{
|
{
|
||||||
clutter_shader_set_is_enabled (shader, FALSE);
|
clutter_shader_set_is_enabled (shader, FALSE);
|
||||||
|
|
||||||
@ -9614,7 +9615,6 @@ clutter_actor_set_shader_param (ClutterActor *self,
|
|||||||
const gchar *param,
|
const gchar *param,
|
||||||
const GValue *value)
|
const GValue *value)
|
||||||
{
|
{
|
||||||
ClutterActorPrivate *priv;
|
|
||||||
ShaderData *shader_data;
|
ShaderData *shader_data;
|
||||||
GValue *var;
|
GValue *var;
|
||||||
|
|
||||||
@ -9626,10 +9626,8 @@ clutter_actor_set_shader_param (ClutterActor *self,
|
|||||||
G_VALUE_HOLDS_FLOAT (value) ||
|
G_VALUE_HOLDS_FLOAT (value) ||
|
||||||
G_VALUE_HOLDS_INT (value));
|
G_VALUE_HOLDS_INT (value));
|
||||||
|
|
||||||
priv = self->priv;
|
shader_data = g_object_get_qdata (G_OBJECT (self), quark_shader_data);
|
||||||
shader_data = priv->shader_data;
|
if (shader_data == NULL)
|
||||||
|
|
||||||
if (!shader_data)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var = g_slice_new0 (GValue);
|
var = g_slice_new0 (GValue);
|
||||||
|
@ -310,8 +310,10 @@ test_shader_main (gint argc, gchar *argv[])
|
|||||||
|
|
||||||
clutter_init (&argc, &argv);
|
clutter_init (&argc, &argv);
|
||||||
|
|
||||||
stage = clutter_stage_get_default ();
|
stage = clutter_stage_new ();
|
||||||
|
clutter_stage_set_title (CLUTTER_STAGE (stage), "Shaders");
|
||||||
clutter_actor_set_size (stage, 512, 384);
|
clutter_actor_set_size (stage, 512, 384);
|
||||||
|
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||||
|
|
||||||
g_print ("applying shaders[%i] named '%s'\n",
|
g_print ("applying shaders[%i] named '%s'\n",
|
||||||
shader_no,
|
shader_no,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user