actor: Make paint_node() and ::paint mutually exclusive

The ::paint signal is the old way to paint an actor; the paint_node()
virtual function is the new way. It's still not possible to traverse the
whole scene graph and build a render tree of PaintNode instances, but
with this change we simultaneously cut out the ::paint signal emission
from the critical path for actors that are using the new PaintNode-based
API, and we retain backward compatibility in the interim period between
1.10 and 2.0.
This commit is contained in:
Emmanuele Bassi 2012-03-05 18:32:16 +00:00
parent a58be8aad1
commit e54ee64380

View File

@ -3177,41 +3177,6 @@ add_or_remove_flatten_effect (ClutterActor *self)
} }
} }
static void
clutter_actor_paint_node (ClutterActor *actor,
ClutterPaintNode *root)
{
ClutterActorPrivate *priv = actor->priv;
if (priv->bg_color_set)
{
ClutterPaintNode *node;
ClutterColor bg_color;
bg_color = priv->bg_color;
bg_color.alpha = clutter_actor_get_paint_opacity_internal (actor)
* priv->bg_color.alpha
/ 255;
node = clutter_color_node_new (&bg_color);
clutter_paint_node_set_name (node, "backgroundColor");
clutter_paint_node_add_rectangle (node, &priv->allocation);
clutter_paint_node_add_child (root, node);
clutter_paint_node_unref (node);
}
if (priv->content != NULL)
_clutter_content_paint_content (priv->content, actor, root);
if (CLUTTER_ACTOR_GET_CLASS (actor)->paint_node != NULL)
CLUTTER_ACTOR_GET_CLASS (actor)->paint_node (actor, root);
if (clutter_paint_node_get_n_children (root) == 0)
return;
_clutter_paint_node_paint (root);
}
static void static void
clutter_actor_real_paint (ClutterActor *actor) clutter_actor_real_paint (ClutterActor *actor)
{ {
@ -3234,6 +3199,60 @@ clutter_actor_real_paint (ClutterActor *actor)
} }
} }
static gboolean
clutter_actor_paint_node (ClutterActor *actor,
ClutterPaintNode *root)
{
ClutterActorPrivate *priv = actor->priv;
if (priv->bg_color_set &&
!clutter_color_equal (&priv->bg_color, CLUTTER_COLOR_Transparent))
{
ClutterPaintNode *node;
ClutterColor bg_color;
ClutterActorBox box;
box.x1 = 0.f;
box.y1 = 0.f;
box.x2 = clutter_actor_box_get_width (&priv->allocation);
box.y2 = clutter_actor_box_get_height (&priv->allocation);
bg_color = priv->bg_color;
bg_color.alpha = clutter_actor_get_paint_opacity_internal (actor)
* priv->bg_color.alpha
/ 255;
node = clutter_color_node_new (&bg_color);
clutter_paint_node_set_name (node, "backgroundColor");
clutter_paint_node_add_rectangle (node, &box);
clutter_paint_node_add_child (root, node);
clutter_paint_node_unref (node);
}
if (priv->content != NULL)
_clutter_content_paint_content (priv->content, actor, root);
if (CLUTTER_ACTOR_GET_CLASS (actor)->paint_node != NULL)
CLUTTER_ACTOR_GET_CLASS (actor)->paint_node (actor, root);
if (clutter_paint_node_get_n_children (root) == 0)
return FALSE;
#ifdef CLUTTER_ENABLE_DEBUG
if (CLUTTER_HAS_DEBUG (PAINT))
{
/* dump the tree only if we have one */
_clutter_paint_node_dump_tree (root);
}
#endif /* CLUTTER_ENABLE_DEBUG */
_clutter_paint_node_paint (root);
CLUTTER_ACTOR_GET_CLASS (actor)->paint (actor);
return TRUE;
}
/** /**
* clutter_actor_paint: * clutter_actor_paint:
* @self: A #ClutterActor * @self: A #ClutterActor
@ -3510,6 +3529,7 @@ clutter_actor_continue_paint (ClutterActor *self)
if (_clutter_context_get_pick_mode () == CLUTTER_PICK_NONE) if (_clutter_context_get_pick_mode () == CLUTTER_PICK_NONE)
{ {
ClutterPaintNode *dummy; ClutterPaintNode *dummy;
gboolean emit_paint;
/* XXX - this will go away in 2.0, when we can get rid of this /* XXX - this will go away in 2.0, when we can get rid of this
* stuff and switch to a pure retained render tree of PaintNodes * stuff and switch to a pure retained render tree of PaintNodes
@ -3517,24 +3537,17 @@ clutter_actor_continue_paint (ClutterActor *self)
*/ */
dummy = _clutter_dummy_node_new (); dummy = _clutter_dummy_node_new ();
clutter_paint_node_set_name (dummy, "Root"); clutter_paint_node_set_name (dummy, "Root");
clutter_actor_paint_node (self, dummy); emit_paint = !clutter_actor_paint_node (self, dummy);
if (clutter_paint_node_get_n_children (dummy) != 0)
{
#ifdef CLUTTER_ENABLE_DEBUG
if (CLUTTER_HAS_DEBUG (PAINT))
{
/* dump the tree only if we have one */
_clutter_paint_node_dump_tree (dummy);
}
#endif /* CLUTTER_ENABLE_DEBUG */
_clutter_paint_node_paint (dummy);
}
clutter_paint_node_unref (dummy); clutter_paint_node_unref (dummy);
g_signal_emit (self, actor_signals[PAINT], 0); if (emit_paint || CLUTTER_ACTOR_IS_TOPLEVEL (self))
g_signal_emit (self, actor_signals[PAINT], 0);
else
{
CLUTTER_NOTE (PAINT, "The actor '%s' painted using PaintNodes, "
"skipping the emission of the paint signal.",
_clutter_actor_get_debug_name (self));
}
} }
else else
{ {
@ -17586,11 +17599,14 @@ clutter_actor_get_content_box (ClutterActor *self,
if (!clutter_actor_has_allocation (self)) if (!clutter_actor_has_allocation (self))
return; return;
box->x1 = 0.f;
box->y1 = 0.f;
box->x2 = priv->allocation.x2 - priv->allocation.x1;
box->y2 = priv->allocation.y2 - priv->allocation.y1;
if (priv->content == NULL) if (priv->content == NULL)
return; return;
*box = priv->allocation;
/* no need to do any more work */ /* no need to do any more work */
if (priv->content_gravity == CLUTTER_CONTENT_GRAVITY_RESIZE_FILL) if (priv->content_gravity == CLUTTER_CONTENT_GRAVITY_RESIZE_FILL)
return; return;