mirror of
https://github.com/brl/mutter.git
synced 2024-12-25 04:22:05 +00:00
clutter-actor: Add an 'offscreen-redirect' property
This adds a property which can be used to redirect the actor through an FBO before painting so that it becomes flattened in an image. The image can be used as a cache to avoid having to repaint the actor if something unrelated in the scene changes. It can also be used to implement correct opacity even if the actor has overlapping primitives. The property is an enum that takes three values: CLUTTER_OFFSCREEN_REDIRECT_NEVER: The default behaviour which is to never flatten the actor. CLUTTER_OFFSCREEN_REDIRECT_ALWAYS: The actor is always redirected through an FBO. CLUTTER_OFFSCREEN_REDIRECT_ONLY_FOR_OPACITY: The actor is only redirected through an FBO if the paint opacity is not 255. This value would be used if the actor wants correct opacity. It will avoid the overhead of using an FBO whenever the actor is fully opaque. The property is implemented by installing a ClutterFlattenEffect. ClutterFlattenEffect is a new internal class which subclasses ClutterOffscreen to redirect the painting to an FBO. When ClutterOffscreen paints, the effect sets an opacity override on the actor so that the image will always contain the actor at full opacity. The opacity is then applied to the resulting image before painting it to the stage. This means the actor does not need to be redrawn while the opacity is being animated. The effect has a high internal priority so that it will always occur before any other effects and it gets hidden from the application.
This commit is contained in:
parent
8df8d4ff0f
commit
7f78237ee5
@ -175,6 +175,7 @@ source_c = \
|
|||||||
$(srcdir)/clutter-feature.c \
|
$(srcdir)/clutter-feature.c \
|
||||||
$(srcdir)/clutter-fixed.c \
|
$(srcdir)/clutter-fixed.c \
|
||||||
$(srcdir)/clutter-fixed-layout.c \
|
$(srcdir)/clutter-fixed-layout.c \
|
||||||
|
$(srcdir)/clutter-flatten-effect.c \
|
||||||
$(srcdir)/clutter-flow-layout.c \
|
$(srcdir)/clutter-flow-layout.c \
|
||||||
$(srcdir)/clutter-frame-source.c \
|
$(srcdir)/clutter-frame-source.c \
|
||||||
$(srcdir)/clutter-group.c \
|
$(srcdir)/clutter-group.c \
|
||||||
@ -227,6 +228,7 @@ source_h_priv = \
|
|||||||
$(srcdir)/clutter-effect-private.h \
|
$(srcdir)/clutter-effect-private.h \
|
||||||
$(srcdir)/clutter-event-translator.h \
|
$(srcdir)/clutter-event-translator.h \
|
||||||
$(srcdir)/clutter-event-private.h \
|
$(srcdir)/clutter-event-private.h \
|
||||||
|
$(srcdir)/clutter-flatten-effect.h \
|
||||||
$(srcdir)/clutter-id-pool.h \
|
$(srcdir)/clutter-id-pool.h \
|
||||||
$(srcdir)/clutter-master-clock.h \
|
$(srcdir)/clutter-master-clock.h \
|
||||||
$(srcdir)/clutter-model-private.h \
|
$(srcdir)/clutter-model-private.h \
|
||||||
|
@ -299,6 +299,7 @@
|
|||||||
#include "clutter-enum-types.h"
|
#include "clutter-enum-types.h"
|
||||||
#include "clutter-main.h"
|
#include "clutter-main.h"
|
||||||
#include "clutter-marshal.h"
|
#include "clutter-marshal.h"
|
||||||
|
#include "clutter-flatten-effect.h"
|
||||||
#include "clutter-paint-volume-private.h"
|
#include "clutter-paint-volume-private.h"
|
||||||
#include "clutter-private.h"
|
#include "clutter-private.h"
|
||||||
#include "clutter-profile.h"
|
#include "clutter-profile.h"
|
||||||
@ -442,6 +443,12 @@ struct _ClutterActorPrivate
|
|||||||
guint8 opacity;
|
guint8 opacity;
|
||||||
gint opacity_override;
|
gint opacity_override;
|
||||||
|
|
||||||
|
ClutterOffscreenRedirect offscreen_redirect;
|
||||||
|
|
||||||
|
/* This is an internal effect used to implement the
|
||||||
|
offscreen-redirect property */
|
||||||
|
ClutterEffect *flatten_effect;
|
||||||
|
|
||||||
ClutterActor *parent_actor;
|
ClutterActor *parent_actor;
|
||||||
GList *children;
|
GList *children;
|
||||||
gint n_children;
|
gint n_children;
|
||||||
@ -545,6 +552,8 @@ enum
|
|||||||
|
|
||||||
PROP_OPACITY,
|
PROP_OPACITY,
|
||||||
|
|
||||||
|
PROP_OFFSCREEN_REDIRECT,
|
||||||
|
|
||||||
PROP_VISIBLE,
|
PROP_VISIBLE,
|
||||||
PROP_MAPPED,
|
PROP_MAPPED,
|
||||||
PROP_REALIZED,
|
PROP_REALIZED,
|
||||||
@ -3017,6 +3026,10 @@ clutter_actor_set_property (GObject *object,
|
|||||||
clutter_actor_set_opacity (actor, g_value_get_uint (value));
|
clutter_actor_set_opacity (actor, g_value_get_uint (value));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_OFFSCREEN_REDIRECT:
|
||||||
|
clutter_actor_set_offscreen_redirect (actor, g_value_get_enum (value));
|
||||||
|
break;
|
||||||
|
|
||||||
case PROP_NAME:
|
case PROP_NAME:
|
||||||
clutter_actor_set_name (actor, g_value_get_string (value));
|
clutter_actor_set_name (actor, g_value_get_string (value));
|
||||||
break;
|
break;
|
||||||
@ -3308,6 +3321,10 @@ clutter_actor_get_property (GObject *object,
|
|||||||
g_value_set_uint (value, priv->opacity);
|
g_value_set_uint (value, priv->opacity);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_OFFSCREEN_REDIRECT:
|
||||||
|
g_value_set_enum (value, priv->offscreen_redirect);
|
||||||
|
break;
|
||||||
|
|
||||||
case PROP_NAME:
|
case PROP_NAME:
|
||||||
g_value_set_string (value, priv->name);
|
g_value_set_string (value, priv->name);
|
||||||
break;
|
break;
|
||||||
@ -3544,6 +3561,12 @@ clutter_actor_dispose (GObject *object)
|
|||||||
priv->effects = NULL;
|
priv->effects = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->flatten_effect != NULL)
|
||||||
|
{
|
||||||
|
g_object_unref (priv->flatten_effect);
|
||||||
|
priv->flatten_effect = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
g_signal_emit (self, actor_signals[DESTROY], 0);
|
g_signal_emit (self, actor_signals[DESTROY], 0);
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_actor_parent_class)->dispose (object);
|
G_OBJECT_CLASS (clutter_actor_parent_class)->dispose (object);
|
||||||
@ -4016,6 +4039,26 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
|||||||
obj_props[PROP_OPACITY] = pspec;
|
obj_props[PROP_OPACITY] = pspec;
|
||||||
g_object_class_install_property (object_class, PROP_OPACITY, pspec);
|
g_object_class_install_property (object_class, PROP_OPACITY, pspec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterActor:offscreen-redirect:
|
||||||
|
*
|
||||||
|
* Whether to flatten the actor into a single image. See
|
||||||
|
* clutter_actor_set_offscreen_redirect() for details.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
pspec = g_param_spec_enum ("offscreen-redirect",
|
||||||
|
P_("Offscreen redirect"),
|
||||||
|
P_("Whether to flatten the actor into a "
|
||||||
|
"single image"),
|
||||||
|
CLUTTER_TYPE_OFFSCREEN_REDIRECT,
|
||||||
|
CLUTTER_OFFSCREEN_REDIRECT_NEVER,
|
||||||
|
CLUTTER_PARAM_READWRITE);
|
||||||
|
obj_props[PROP_OFFSCREEN_REDIRECT] = pspec;
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_OFFSCREEN_REDIRECT,
|
||||||
|
pspec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClutterActor:visible:
|
* ClutterActor:visible:
|
||||||
*
|
*
|
||||||
@ -5061,6 +5104,7 @@ clutter_actor_init (ClutterActor *self)
|
|||||||
priv->parent_actor = NULL;
|
priv->parent_actor = NULL;
|
||||||
priv->has_clip = FALSE;
|
priv->has_clip = FALSE;
|
||||||
priv->opacity = 0xff;
|
priv->opacity = 0xff;
|
||||||
|
priv->offscreen_redirect = CLUTTER_OFFSCREEN_REDIRECT_NEVER;
|
||||||
priv->id = _clutter_context_acquire_id (self);
|
priv->id = _clutter_context_acquire_id (self);
|
||||||
priv->pick_id = -1;
|
priv->pick_id = -1;
|
||||||
priv->scale_x = 1.0;
|
priv->scale_x = 1.0;
|
||||||
@ -7259,7 +7303,16 @@ clutter_actor_set_opacity (ClutterActor *self,
|
|||||||
{
|
{
|
||||||
priv->opacity = opacity;
|
priv->opacity = opacity;
|
||||||
|
|
||||||
clutter_actor_queue_redraw (self);
|
/* Queue a redraw from the flatten effect so that it can use
|
||||||
|
its cached image if available instead of having to redraw the
|
||||||
|
actual actor. If it doesn't end up using the FBO then the
|
||||||
|
effect is still able to continue the paint anyway. If there
|
||||||
|
is no flatten effect yet then this is equivalent to queueing
|
||||||
|
a full redraw */
|
||||||
|
_clutter_actor_queue_redraw_full (self,
|
||||||
|
0, /* flags */
|
||||||
|
NULL, /* clip */
|
||||||
|
priv->flatten_effect);
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_OPACITY]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_OPACITY]);
|
||||||
}
|
}
|
||||||
@ -7350,6 +7403,131 @@ clutter_actor_get_opacity (ClutterActor *self)
|
|||||||
return self->priv->opacity;
|
return self->priv->opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_actor_set_offscreen_redirect:
|
||||||
|
* @self: A #ClutterActor
|
||||||
|
* @redirect: New offscreen redirect value for the actor.
|
||||||
|
*
|
||||||
|
* Sets whether to redirect the actor into an offscreen image. The
|
||||||
|
* offscreen image is used to flatten the actor into a single image
|
||||||
|
* while painting for two main reasons. Firstly, when the actor is
|
||||||
|
* painted a second time without any of its contents changing it can
|
||||||
|
* simply repaint the cached image without descending further down the
|
||||||
|
* actor hierarchy. Secondly, it will make the opacity look correct
|
||||||
|
* even if there are overlapping primitives in the actor.
|
||||||
|
*
|
||||||
|
* Caching the actor could in some cases be a performance win and in
|
||||||
|
* some cases be a performance lose so it is important to determine
|
||||||
|
* which value is right for an actor before modifying this value. For
|
||||||
|
* example, there is never any reason to flatten an actor that is just
|
||||||
|
* a single texture (such as a ClutterTexture) because it is
|
||||||
|
* effectively already cached in an image so the offscreen would be
|
||||||
|
* redundant. Also if the actor contains primitives that are far apart
|
||||||
|
* with a large transparent area in the middle (such as a large
|
||||||
|
* CluterGroup with a small actor in the top left and a small actor in
|
||||||
|
* the bottom right) then the cached image will contain the entire
|
||||||
|
* image of the large area and the paint will waste time blending all
|
||||||
|
* of the transparent pixels in the middle.
|
||||||
|
*
|
||||||
|
* The default method of implementing opacity on a container simply
|
||||||
|
* forwards on the opacity to all of the children. If the children are
|
||||||
|
* overlapping then it will appear as if they are two separate glassy
|
||||||
|
* objects and there will be a break in the color where they
|
||||||
|
* overlap. By setting the offscreen-redirect to
|
||||||
|
* %CLUTTER_OFFSCREEN_REDIRECT_OPACITY_ONLY it will be as if the two
|
||||||
|
* opaque objects are combined into one and then made transparent
|
||||||
|
* which is usually what is expected.
|
||||||
|
*
|
||||||
|
* The image below demonstrates the difference between the fast
|
||||||
|
* default opacity and the correct but inefficient opacity achieved
|
||||||
|
* through the offscreen redirect. The image shows two Clutter groups,
|
||||||
|
* each containing a red and a green rectangle which overlap. The
|
||||||
|
* opacity on the group is set to 128 (which is 50%). When the
|
||||||
|
* offscreen redirect is not used, the red rectangle can be seen
|
||||||
|
* through the blue rectangle as if the two rectangles were separately
|
||||||
|
* transparent. When the redirect is used the group as a whole is
|
||||||
|
* transparent instead so the red rectangle is not visible where they
|
||||||
|
* overlap.
|
||||||
|
*
|
||||||
|
* <figure id="offscreen-redirect">
|
||||||
|
* <title>Sample of using an offscreen redirect for transparency</title>
|
||||||
|
* <graphic fileref="offscreen-redirect.png" format="PNG"/>
|
||||||
|
* </figure>
|
||||||
|
*
|
||||||
|
* The default value is %CLUTTER_OFFSCREEN_REDIRECT_NEVER.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_actor_set_offscreen_redirect (ClutterActor *self,
|
||||||
|
ClutterOffscreenRedirect redirect)
|
||||||
|
{
|
||||||
|
ClutterActorPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||||
|
|
||||||
|
priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->offscreen_redirect != redirect)
|
||||||
|
{
|
||||||
|
priv->offscreen_redirect = redirect;
|
||||||
|
|
||||||
|
if (priv->flatten_effect == NULL)
|
||||||
|
{
|
||||||
|
ClutterActorMeta *actor_meta;
|
||||||
|
gint priority;
|
||||||
|
|
||||||
|
priv->flatten_effect = _clutter_flatten_effect_new ();
|
||||||
|
/* Keep a reference to the effect so that we can queue
|
||||||
|
redraws from it */
|
||||||
|
g_object_ref_sink (priv->flatten_effect);
|
||||||
|
|
||||||
|
/* Set the priority of the effect to high so that it will
|
||||||
|
always be applied to the actor first. It uses an internal
|
||||||
|
priority so that it won't be visible to applications */
|
||||||
|
actor_meta = CLUTTER_ACTOR_META (priv->flatten_effect);
|
||||||
|
priority = CLUTTER_ACTOR_META_PRIORITY_INTERNAL_HIGH;
|
||||||
|
_clutter_actor_meta_set_priority (actor_meta, priority);
|
||||||
|
|
||||||
|
/* This will also queue a full redraw of the actor */
|
||||||
|
clutter_actor_add_effect (self, priv->flatten_effect);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Queue a redraw from the effect so that it can use its
|
||||||
|
cached image if available instead of having to redraw the
|
||||||
|
actual actor. If it doesn't end up using the FBO then the
|
||||||
|
effect is still able to continue the paint anyway */
|
||||||
|
_clutter_actor_queue_redraw_full (self,
|
||||||
|
0, /* flags */
|
||||||
|
NULL, /* clip */
|
||||||
|
priv->flatten_effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self),
|
||||||
|
obj_props[PROP_OFFSCREEN_REDIRECT]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_actor_get_offscreen_redirect:
|
||||||
|
* @self: a #ClutterActor
|
||||||
|
*
|
||||||
|
* Retrieves whether to redirect the actor to an offscreen buffer, as
|
||||||
|
* set by clutter_actor_set_offscreen_redirect().
|
||||||
|
*
|
||||||
|
* Return value: the value of the offscreen-redirect property of the actor
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
ClutterOffscreenRedirect
|
||||||
|
clutter_actor_get_offscreen_redirect (ClutterActor *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0);
|
||||||
|
|
||||||
|
return self->priv->offscreen_redirect;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_actor_set_name:
|
* clutter_actor_set_name:
|
||||||
* @self: A #ClutterActor
|
* @self: A #ClutterActor
|
||||||
|
@ -116,6 +116,26 @@ typedef enum
|
|||||||
CLUTTER_ACTOR_NO_LAYOUT = 1 << 5
|
CLUTTER_ACTOR_NO_LAYOUT = 1 << 5
|
||||||
} ClutterActorFlags;
|
} ClutterActorFlags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterOffscreenRedirect:
|
||||||
|
* @CLUTTER_OFFSCREEN_REDIRECT_NEVER: Never redirect the actor to an
|
||||||
|
* offscreen buffer.
|
||||||
|
* @CLUTTER_OFFSCREEN_REDIRECT_ALWAYS: Always redirect the actor to an
|
||||||
|
* offscreen buffer.
|
||||||
|
* @CLUTTER_OFFSCREEN_REDIRECT_OPACITY_ONLY: Only redirect the actor if
|
||||||
|
* it is semi-transparent.
|
||||||
|
*
|
||||||
|
* Possible values to pass to clutter_actor_set_offscreen_redirect().
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CLUTTER_OFFSCREEN_REDIRECT_NEVER,
|
||||||
|
CLUTTER_OFFSCREEN_REDIRECT_ALWAYS,
|
||||||
|
CLUTTER_OFFSCREEN_REDIRECT_OPACITY_ONLY
|
||||||
|
} ClutterOffscreenRedirect;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClutterAllocationFlags:
|
* ClutterAllocationFlags:
|
||||||
* @CLUTTER_ALLOCATION_NONE: No flag set
|
* @CLUTTER_ALLOCATION_NONE: No flag set
|
||||||
@ -424,6 +444,10 @@ guint8 clutter_actor_get_opacity (ClutterActor
|
|||||||
guint8 clutter_actor_get_paint_opacity (ClutterActor *self);
|
guint8 clutter_actor_get_paint_opacity (ClutterActor *self);
|
||||||
gboolean clutter_actor_get_paint_visibility (ClutterActor *self);
|
gboolean clutter_actor_get_paint_visibility (ClutterActor *self);
|
||||||
|
|
||||||
|
void clutter_actor_set_offscreen_redirect (ClutterActor *self,
|
||||||
|
ClutterOffscreenRedirect redirect);
|
||||||
|
ClutterOffscreenRedirect
|
||||||
|
clutter_actor_get_offscreen_redirect (ClutterActor *self);
|
||||||
|
|
||||||
void clutter_actor_set_name (ClutterActor *self,
|
void clutter_actor_set_name (ClutterActor *self,
|
||||||
const gchar *name);
|
const gchar *name);
|
||||||
|
151
clutter/clutter-flatten-effect.c
Normal file
151
clutter/clutter-flatten-effect.c
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Neil Roberts <neil@linux.intel.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This is an internal-only effect used to implement the
|
||||||
|
'flatness' property of ClutterActor */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "clutter-flatten-effect.h"
|
||||||
|
#include "clutter-private.h"
|
||||||
|
#include "clutter-actor-private.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
_clutter_flatten_effect_set_actor (ClutterActorMeta *meta,
|
||||||
|
ClutterActor *actor);
|
||||||
|
|
||||||
|
static void
|
||||||
|
_clutter_flatten_effect_run (ClutterEffect *effect,
|
||||||
|
ClutterEffectRunFlags flags);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ClutterFlattenEffect,
|
||||||
|
_clutter_flatten_effect,
|
||||||
|
CLUTTER_TYPE_OFFSCREEN_EFFECT);
|
||||||
|
|
||||||
|
#define CLUTTER_FLATTEN_EFFECT_GET_PRIVATE(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_FLATTEN_EFFECT, \
|
||||||
|
ClutterFlattenEffectPrivate))
|
||||||
|
|
||||||
|
struct _ClutterFlattenEffectPrivate
|
||||||
|
{
|
||||||
|
ClutterActor *actor;
|
||||||
|
|
||||||
|
/* This records whether the last paint went through the FBO or if it
|
||||||
|
was painted directly. We need to know this so we can force the
|
||||||
|
offscreen effect to clear its image when we switch from rendering
|
||||||
|
directly to rendering through the FBO */
|
||||||
|
gboolean last_paint_used_fbo;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
_clutter_flatten_effect_class_init (ClutterFlattenEffectClass *klass)
|
||||||
|
{
|
||||||
|
ClutterActorMetaClass *actor_meta_class = (ClutterActorMetaClass *) klass;
|
||||||
|
ClutterEffectClass *effect_class = (ClutterEffectClass *) klass;
|
||||||
|
|
||||||
|
actor_meta_class->set_actor = _clutter_flatten_effect_set_actor;
|
||||||
|
|
||||||
|
effect_class->run = _clutter_flatten_effect_run;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (ClutterFlattenEffectPrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_clutter_flatten_effect_init (ClutterFlattenEffect *self)
|
||||||
|
{
|
||||||
|
self->priv = CLUTTER_FLATTEN_EFFECT_GET_PRIVATE (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterEffect *
|
||||||
|
_clutter_flatten_effect_new (void)
|
||||||
|
{
|
||||||
|
return g_object_new (CLUTTER_TYPE_FLATTEN_EFFECT, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_clutter_flatten_effect_is_using_fbo (ClutterFlattenEffect *opacity_effect)
|
||||||
|
{
|
||||||
|
ClutterFlattenEffectPrivate *priv = opacity_effect->priv;
|
||||||
|
|
||||||
|
switch (clutter_actor_get_offscreen_redirect (priv->actor))
|
||||||
|
{
|
||||||
|
case CLUTTER_OFFSCREEN_REDIRECT_NEVER:
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case CLUTTER_OFFSCREEN_REDIRECT_ALWAYS:
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case CLUTTER_OFFSCREEN_REDIRECT_OPACITY_ONLY:
|
||||||
|
return clutter_actor_get_paint_opacity (priv->actor) < 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
_clutter_flatten_effect_set_actor (ClutterActorMeta *meta,
|
||||||
|
ClutterActor *actor)
|
||||||
|
{
|
||||||
|
ClutterFlattenEffect *opacity_effect = CLUTTER_FLATTEN_EFFECT (meta);
|
||||||
|
ClutterFlattenEffectPrivate *priv = opacity_effect->priv;
|
||||||
|
|
||||||
|
CLUTTER_ACTOR_META_CLASS (_clutter_flatten_effect_parent_class)->
|
||||||
|
set_actor (meta, actor);
|
||||||
|
|
||||||
|
/* we keep a back pointer here, to avoid going through the ActorMeta */
|
||||||
|
priv->actor = clutter_actor_meta_get_actor (meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_clutter_flatten_effect_run (ClutterEffect *effect,
|
||||||
|
ClutterEffectRunFlags flags)
|
||||||
|
{
|
||||||
|
ClutterFlattenEffect *opacity_effect = CLUTTER_FLATTEN_EFFECT (effect);
|
||||||
|
ClutterFlattenEffectPrivate *priv = opacity_effect->priv;
|
||||||
|
|
||||||
|
if (_clutter_flatten_effect_is_using_fbo (opacity_effect))
|
||||||
|
{
|
||||||
|
/* If the last paint bypassed the FBO then we'll pretend the
|
||||||
|
actor is dirty so that the offscreen will clear its image */
|
||||||
|
if (!priv->last_paint_used_fbo)
|
||||||
|
{
|
||||||
|
flags |= CLUTTER_EFFECT_RUN_ACTOR_DIRTY;
|
||||||
|
priv->last_paint_used_fbo = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let the offscreen effect paint the actor through the FBO */
|
||||||
|
CLUTTER_EFFECT_CLASS (_clutter_flatten_effect_parent_class)->
|
||||||
|
run (effect, flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Just let the actor paint directly to the stage */
|
||||||
|
clutter_actor_continue_paint (priv->actor);
|
||||||
|
|
||||||
|
priv->last_paint_used_fbo = FALSE;
|
||||||
|
}
|
||||||
|
}
|
75
clutter/clutter-flatten-effect.h
Normal file
75
clutter/clutter-flatten-effect.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Neil Roberts <neil@linux.intel.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_FLATTEN_EFFECT_H__
|
||||||
|
#define __CLUTTER_FLATTEN_EFFECT_H__
|
||||||
|
|
||||||
|
#include <clutter/clutter-offscreen-effect.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_FLATTEN_EFFECT \
|
||||||
|
(_clutter_flatten_effect_get_type())
|
||||||
|
#define CLUTTER_FLATTEN_EFFECT(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||||
|
CLUTTER_TYPE_FLATTEN_EFFECT, \
|
||||||
|
ClutterFlattenEffect))
|
||||||
|
#define CLUTTER_FLATTEN_EFFECT_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||||
|
CLUTTER_TYPE_FLATTEN_EFFECT, \
|
||||||
|
ClutterFlattenEffectClass))
|
||||||
|
#define CLUTTER_IS_FLATTEN_EFFECT(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||||
|
CLUTTER_TYPE_FLATTEN_EFFECT))
|
||||||
|
#define CLUTTER_IS_FLATTEN_EFFECT_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||||
|
CLUTTER_TYPE_FLATTEN_EFFECT))
|
||||||
|
#define CLUTTER_FLATTEN_EFFECT_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||||
|
CLUTTER_FLATTEN_EFFECT, \
|
||||||
|
ClutterFlattenEffectClass))
|
||||||
|
|
||||||
|
typedef struct _ClutterFlattenEffect ClutterFlattenEffect;
|
||||||
|
typedef struct _ClutterFlattenEffectClass ClutterFlattenEffectClass;
|
||||||
|
typedef struct _ClutterFlattenEffectPrivate ClutterFlattenEffectPrivate;
|
||||||
|
|
||||||
|
struct _ClutterFlattenEffectClass
|
||||||
|
{
|
||||||
|
ClutterOffscreenEffectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ClutterFlattenEffect
|
||||||
|
{
|
||||||
|
ClutterOffscreenEffect parent;
|
||||||
|
|
||||||
|
ClutterFlattenEffectPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType _clutter_flatten_effect_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
ClutterEffect *_clutter_flatten_effect_new (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_FLATTEN_EFFECT_H__ */
|
@ -122,7 +122,8 @@ HTML_IMAGES=\
|
|||||||
event-flow.png \
|
event-flow.png \
|
||||||
flow-layout-horizontal.png \
|
flow-layout-horizontal.png \
|
||||||
flow-layout-vertical.png \
|
flow-layout-vertical.png \
|
||||||
path-alpha-func.png
|
path-alpha-func.png \
|
||||||
|
offscreen-redirect.png
|
||||||
|
|
||||||
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
|
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
|
||||||
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
|
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
|
||||||
@ -179,4 +180,5 @@ EXTRA_DIST += \
|
|||||||
event-flow.png \
|
event-flow.png \
|
||||||
flow-layout-horizontal.png \
|
flow-layout-horizontal.png \
|
||||||
flow-layout-vertical.png \
|
flow-layout-vertical.png \
|
||||||
path-alpha-func.png
|
path-alpha-func.png \
|
||||||
|
offscreen-redirect.png
|
||||||
|
@ -341,6 +341,9 @@ clutter_actor_get_z_rotation_gravity
|
|||||||
clutter_actor_is_rotated
|
clutter_actor_is_rotated
|
||||||
clutter_actor_set_opacity
|
clutter_actor_set_opacity
|
||||||
clutter_actor_get_opacity
|
clutter_actor_get_opacity
|
||||||
|
ClutterOffscreenRedirect
|
||||||
|
clutter_actor_set_offscreen_redirect
|
||||||
|
clutter_actor_get_offscreen_redirect
|
||||||
clutter_actor_set_name
|
clutter_actor_set_name
|
||||||
clutter_actor_get_name
|
clutter_actor_get_name
|
||||||
clutter_actor_get_gid
|
clutter_actor_get_gid
|
||||||
|
BIN
doc/reference/clutter/offscreen-redirect.png
Normal file
BIN
doc/reference/clutter/offscreen-redirect.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
Loading…
Reference in New Issue
Block a user