clutter-actor: Add a 'has_overlaps' virtual

This adds a virtual to ClutterActor so that an actor subclass can
report whether it has overlapping primitives. ClutterActor uses this
to determine whether it needs to use ClutterFlattenEffect to implement
the opacity property. The default implementation of the virtual
returns TRUE which means that most actors will end up being redirected
offscreen when the opacity != 255. ClutterTexture and ClutterRectangle
override this to return FALSE because they should never need to be
redirected. ClutterClone overrides it to divert to the source.

The values for the ClutterOffscreenRedirect enum have changed to:

AUTOMATIC_FOR_OPACITY

 The actor will only be redirected if has_overlaps returns TRUE and
 the opacity is < 255

ALWAYS_FOR_OPACITY

 The actor will always be redirected if the opacity < 255 regardless
 of the return value of has_overlaps

ALWAYS

 The actor will always be redirected offscreen.

This means that the property can't be used to prevent the actor from
being redirected but only to increase the likelihood that it will be
redirected.

ClutterActor now adds and removes the flatten effect depending on
whether flattening is needed directly in clutter_actor_paint(). There
are new internal versions of add/remove_effect that don't queue a
redraw. This means that ClutterFlattenEffect is now just a no-op
subclass of ClutterOffscreen. It is only needed because
ClutterOffscreen is abstract. Removing the effect also makes it so
that the cached image will be freed as soon as an actor is repainted
without being flattened.
This commit is contained in:
Neil Roberts
2011-03-14 16:30:53 +00:00
parent 2a09a04c2a
commit 701440efd8
9 changed files with 272 additions and 183 deletions

View File

@@ -33,7 +33,7 @@ GType foo_actor_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (FooActor, foo_actor, CLUTTER_TYPE_ACTOR);
static void
foo_actor_class_paint (ClutterActor *actor)
foo_actor_paint (ClutterActor *actor)
{
FooActor *foo_actor = (FooActor *) actor;
ClutterActorBox allocation;
@@ -55,19 +55,26 @@ foo_actor_class_paint (ClutterActor *actor)
}
static gboolean
foo_actor_class_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
foo_actor_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
return clutter_paint_volume_set_from_allocation (volume, actor);
}
static gboolean
foo_actor_has_overlaps (ClutterActor *actor)
{
return FALSE;
}
static void
foo_actor_class_init (FooActorClass *klass)
{
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
actor_class->paint = foo_actor_class_paint;
actor_class->get_paint_volume = foo_actor_class_get_paint_volume;
actor_class->paint = foo_actor_paint;
actor_class->get_paint_volume = foo_actor_get_paint_volume;
actor_class->has_overlaps = foo_actor_has_overlaps;
}
static void
@@ -75,6 +82,40 @@ foo_actor_init (FooActor *self)
{
}
typedef struct _FooGroup FooGroup;
typedef struct _FooGroupClass FooGroupClass;
struct _FooGroupClass
{
ClutterGroupClass parent_class;
};
struct _FooGroup
{
ClutterGroup parent;
};
G_DEFINE_TYPE (FooGroup, foo_group, CLUTTER_TYPE_GROUP);
static gboolean
foo_group_has_overlaps (ClutterActor *actor)
{
return FALSE;
}
static void
foo_group_class_init (FooGroupClass *klass)
{
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
actor_class->has_overlaps = foo_group_has_overlaps;
}
static void
foo_group_init (FooGroup *self)
{
}
static void
verify_results (Data *data,
guint8 expected_color_red,
@@ -155,7 +196,7 @@ timeout_cb (gpointer user_data)
it needs to fill the cache first. It should be painted with full
opacity */
clutter_actor_set_offscreen_redirect
(data->container, CLUTTER_OFFSCREEN_REDIRECT_OPACITY_ONLY);
(data->container, CLUTTER_OFFSCREEN_REDIRECT_ALWAYS_FOR_OPACITY);
verify_results (data,
255, 127, 127,
1,
@@ -242,7 +283,7 @@ test_offscreen_redirect (TestConformSimpleFixture *fixture,
data.parent_container = clutter_group_new ();
data.container = clutter_group_new ();
data.container = g_object_new (foo_group_get_type (), NULL);
data.foo_actor = g_object_new (foo_actor_get_type (), NULL);
clutter_actor_set_size (CLUTTER_ACTOR (data.foo_actor), 100, 100);