2010-04-08 05:55:15 -04:00
|
|
|
|
/*
|
|
|
|
|
* Clutter.
|
|
|
|
|
*
|
|
|
|
|
* An OpenGL based 'interactive canvas' library.
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2010 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/>.
|
|
|
|
|
*
|
|
|
|
|
* Author:
|
|
|
|
|
* Emmanuele Bassi <ebassi@linux.intel.com>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* SECTION:clutter-effect
|
|
|
|
|
* @short_description: Base class for actor effects
|
|
|
|
|
*
|
|
|
|
|
* The #ClutterEffect class provides a default type and API for creating
|
|
|
|
|
* effects for generic actors.
|
|
|
|
|
*
|
|
|
|
|
* Effects are a #ClutterActorMeta sub-class that modify the way an actor
|
|
|
|
|
* is painted in a way that is not part of the actor's implementation.
|
|
|
|
|
*
|
|
|
|
|
* Effects should be the preferred way to affect the paint sequence of an
|
|
|
|
|
* actor without sub-classing the actor itself and overriding the
|
2012-04-19 11:00:23 -04:00
|
|
|
|
* #ClutterActorClass.paint()_ virtual function.
|
2010-04-08 05:55:15 -04:00
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* ## Implementing a ClutterEffect
|
|
|
|
|
*
|
|
|
|
|
* Creating a sub-class of #ClutterEffect requires overriding the
|
|
|
|
|
* #ClutterEffectClass.paint() method. The implementation of the function should look
|
|
|
|
|
* something like this:
|
|
|
|
|
*
|
|
|
|
|
* |[
|
2011-06-13 10:58:46 -04:00
|
|
|
|
* void effect_paint (ClutterEffect *effect, ClutterEffectPaintFlags flags)
|
2011-03-02 11:55:10 -05:00
|
|
|
|
* {
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* // Set up initialisation of the paint such as binding a
|
|
|
|
|
* // CoglOffscreen or other operations
|
2011-03-02 11:55:10 -05:00
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* // Chain to the next item in the paint sequence. This will either call
|
|
|
|
|
* // ‘paint’ on the next effect or just paint the actor if this is
|
|
|
|
|
* // the last effect.
|
2011-03-02 11:55:10 -05:00
|
|
|
|
* ClutterActor *actor =
|
|
|
|
|
* clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
2014-03-17 19:07:58 -04:00
|
|
|
|
*
|
2011-03-02 11:55:10 -05:00
|
|
|
|
* clutter_actor_continue_paint (actor);
|
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* // perform any cleanup of state, such as popping the CoglOffscreen
|
2011-03-02 11:55:10 -05:00
|
|
|
|
* }
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* ]|
|
|
|
|
|
*
|
|
|
|
|
* The effect can optionally avoid calling clutter_actor_continue_paint() to skip any
|
|
|
|
|
* further stages of the paint sequence. This is useful for example if the effect
|
|
|
|
|
* contains a cached image of the actor. In that case it can optimise painting by
|
|
|
|
|
* avoiding the actor paint and instead painting the cached image.
|
|
|
|
|
*
|
|
|
|
|
* The %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY flag is useful in this case. Clutter will set
|
|
|
|
|
* this flag when a redraw has been queued on the actor since it was last painted. The
|
|
|
|
|
* effect can use this information to decide if the cached image is still valid.
|
|
|
|
|
*
|
|
|
|
|
* ## A simple ClutterEffect implementation
|
|
|
|
|
*
|
|
|
|
|
* The example below creates two rectangles: one will be painted "behind" the actor,
|
|
|
|
|
* while another will be painted "on top" of the actor.
|
|
|
|
|
*
|
|
|
|
|
* The #ClutterActorMetaClass.set_actor() implementation will create the two materials
|
|
|
|
|
* used for the two different rectangles; the #ClutterEffectClass.paint() implementation
|
|
|
|
|
* will paint the first material using cogl_rectangle(), before continuing and then it
|
|
|
|
|
* will paint paint the second material after.
|
|
|
|
|
*
|
|
|
|
|
* |[
|
2010-04-08 05:55:15 -04:00
|
|
|
|
* typedef struct {
|
|
|
|
|
* ClutterEffect parent_instance;
|
|
|
|
|
*
|
|
|
|
|
* CoglHandle rect_1;
|
|
|
|
|
* CoglHandle rect_2;
|
|
|
|
|
* } MyEffect;
|
|
|
|
|
*
|
|
|
|
|
* typedef struct _ClutterEffectClass MyEffectClass;
|
|
|
|
|
*
|
|
|
|
|
* G_DEFINE_TYPE (MyEffect, my_effect, CLUTTER_TYPE_EFFECT);
|
|
|
|
|
*
|
|
|
|
|
* static void
|
|
|
|
|
* my_effect_set_actor (ClutterActorMeta *meta,
|
|
|
|
|
* ClutterActor *actor)
|
|
|
|
|
* {
|
|
|
|
|
* MyEffect *self = MY_EFFECT (meta);
|
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* // Clear the previous state //
|
|
|
|
|
* if (self->rect_1)
|
2010-04-08 05:55:15 -04:00
|
|
|
|
* {
|
2019-02-20 08:51:12 -05:00
|
|
|
|
* cogl_object_unref (self->rect_1);
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* self->rect_1 = NULL;
|
2010-04-08 05:55:15 -04:00
|
|
|
|
* }
|
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* if (self->rect_2)
|
2010-04-08 05:55:15 -04:00
|
|
|
|
* {
|
2019-02-20 08:51:12 -05:00
|
|
|
|
* cogl_object_unref (self->rect_2);
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* self->rect_2 = NULL;
|
2010-04-08 05:55:15 -04:00
|
|
|
|
* }
|
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* // Maintain a pointer to the actor
|
|
|
|
|
* self->actor = actor;
|
2010-04-08 05:55:15 -04:00
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* // If we've been detached by the actor then we should just bail out here
|
|
|
|
|
* if (self->actor == NULL)
|
2010-04-08 05:55:15 -04:00
|
|
|
|
* return;
|
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* // Create a red material
|
|
|
|
|
* self->rect_1 = cogl_material_new ();
|
|
|
|
|
* cogl_material_set_color4f (self->rect_1, 1.0, 0.0, 0.0, 1.0);
|
2010-04-08 05:55:15 -04:00
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* // Create a green material
|
|
|
|
|
* self->rect_2 = cogl_material_new ();
|
|
|
|
|
* cogl_material_set_color4f (self->rect_2, 0.0, 1.0, 0.0, 1.0);
|
2010-04-08 05:55:15 -04:00
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* static gboolean
|
2011-06-06 02:44:11 -04:00
|
|
|
|
* my_effect_paint (ClutterEffect *effect)
|
2010-04-08 05:55:15 -04:00
|
|
|
|
* {
|
|
|
|
|
* MyEffect *self = MY_EFFECT (effect);
|
|
|
|
|
* gfloat width, height;
|
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* clutter_actor_get_size (self->actor, &width, &height);
|
2010-04-08 05:55:15 -04:00
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* // Paint the first rectangle in the upper left quadrant
|
|
|
|
|
* cogl_set_source (self->rect_1);
|
2010-04-08 05:55:15 -04:00
|
|
|
|
* cogl_rectangle (0, 0, width / 2, height / 2);
|
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* // Continue to the rest of the paint sequence
|
|
|
|
|
* clutter_actor_continue_paint (self->actor);
|
2010-04-08 05:55:15 -04:00
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* // Paint the second rectangle in the lower right quadrant
|
|
|
|
|
* cogl_set_source (self->rect_2);
|
2010-04-08 05:55:15 -04:00
|
|
|
|
* cogl_rectangle (width / 2, height / 2, width, height);
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* static void
|
|
|
|
|
* my_effect_class_init (MyEffectClass *klass)
|
|
|
|
|
* {
|
|
|
|
|
* ClutterActorMetaClas *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
|
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* meta_class->set_actor = my_effect_set_actor;
|
2010-04-08 05:55:15 -04:00
|
|
|
|
*
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* klass->paint = my_effect_paint;
|
2010-04-08 05:55:15 -04:00
|
|
|
|
* }
|
2014-03-17 19:07:58 -04:00
|
|
|
|
* ]|
|
2010-04-08 05:55:15 -04:00
|
|
|
|
*
|
|
|
|
|
* #ClutterEffect is available since Clutter 1.4
|
|
|
|
|
*/
|
|
|
|
|
|
2016-05-05 10:21:51 -04:00
|
|
|
|
#include "clutter-build-config.h"
|
2010-04-08 05:55:15 -04:00
|
|
|
|
|
|
|
|
|
#include "clutter-effect.h"
|
|
|
|
|
|
|
|
|
|
#include "clutter-actor-meta-private.h"
|
|
|
|
|
#include "clutter-debug.h"
|
2011-02-18 11:00:39 -05:00
|
|
|
|
#include "clutter-effect-private.h"
|
2010-04-08 05:55:15 -04:00
|
|
|
|
#include "clutter-enum-types.h"
|
|
|
|
|
#include "clutter-marshal.h"
|
clutter/effect: Add paint_node vfunc
Introduce a new paint_node vfunc that, if implemented, allows
the effect to add nodes to a transient paint node that is
immediately painted. This is a transitional step until we
have fully delegated paint node rendering.
The most basic implementation of a ClutterEffect.paint_node
vfunc, and also the default implementation, is with an actor
node, as follows:
```
static void
foo_bar_paint_node (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags)
{
g_autoptr (ClutterPaintNode) actor_node = NULL;
actor_node = clutter_actor_node_new (effect->actor);
clutter_paint_node_add_child (node, actor_node);
}
```
This example gives the exact same behavior of simply calling
clutter_actor_continue_paint(). In the future, the paint node
itself will be a parameter of clutter_actor_continue_paint()
and we'll be able to simplify it event more.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1340>
2020-06-27 11:12:03 -04:00
|
|
|
|
#include "clutter-paint-node-private.h"
|
|
|
|
|
#include "clutter-paint-nodes.h"
|
2010-04-08 05:55:15 -04:00
|
|
|
|
#include "clutter-private.h"
|
2011-02-28 07:16:55 -05:00
|
|
|
|
#include "clutter-actor-private.h"
|
2010-04-08 05:55:15 -04:00
|
|
|
|
|
|
|
|
|
G_DEFINE_ABSTRACT_TYPE (ClutterEffect,
|
|
|
|
|
clutter_effect,
|
|
|
|
|
CLUTTER_TYPE_ACTOR_META);
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2019-11-13 16:21:58 -05:00
|
|
|
|
clutter_effect_real_pre_paint (ClutterEffect *effect,
|
2020-07-05 17:45:03 -04:00
|
|
|
|
ClutterPaintNode *node,
|
2019-11-13 16:21:58 -05:00
|
|
|
|
ClutterPaintContext *paint_context)
|
2010-04-08 05:55:15 -04:00
|
|
|
|
{
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2019-11-13 16:21:58 -05:00
|
|
|
|
clutter_effect_real_post_paint (ClutterEffect *effect,
|
2020-07-05 17:45:03 -04:00
|
|
|
|
ClutterPaintNode *node,
|
2019-11-13 16:21:58 -05:00
|
|
|
|
ClutterPaintContext *paint_context)
|
2010-04-08 05:55:15 -04:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-07 13:04:19 -04:00
|
|
|
|
static gboolean
|
2018-05-23 02:46:40 -04:00
|
|
|
|
clutter_effect_real_modify_paint_volume (ClutterEffect *effect,
|
|
|
|
|
ClutterPaintVolume *volume)
|
2010-08-16 12:02:15 -04:00
|
|
|
|
{
|
2010-09-07 13:04:19 -04:00
|
|
|
|
return TRUE;
|
2010-08-16 12:02:15 -04:00
|
|
|
|
}
|
|
|
|
|
|
clutter/effect: Add paint_node vfunc
Introduce a new paint_node vfunc that, if implemented, allows
the effect to add nodes to a transient paint node that is
immediately painted. This is a transitional step until we
have fully delegated paint node rendering.
The most basic implementation of a ClutterEffect.paint_node
vfunc, and also the default implementation, is with an actor
node, as follows:
```
static void
foo_bar_paint_node (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags)
{
g_autoptr (ClutterPaintNode) actor_node = NULL;
actor_node = clutter_actor_node_new (effect->actor);
clutter_paint_node_add_child (node, actor_node);
}
```
This example gives the exact same behavior of simply calling
clutter_actor_continue_paint(). In the future, the paint node
itself will be a parameter of clutter_actor_continue_paint()
and we'll be able to simplify it event more.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1340>
2020-06-27 11:12:03 -04:00
|
|
|
|
static void
|
2020-12-29 12:43:22 -05:00
|
|
|
|
add_actor_node (ClutterEffect *effect,
|
|
|
|
|
ClutterPaintNode *node)
|
clutter/effect: Add paint_node vfunc
Introduce a new paint_node vfunc that, if implemented, allows
the effect to add nodes to a transient paint node that is
immediately painted. This is a transitional step until we
have fully delegated paint node rendering.
The most basic implementation of a ClutterEffect.paint_node
vfunc, and also the default implementation, is with an actor
node, as follows:
```
static void
foo_bar_paint_node (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags)
{
g_autoptr (ClutterPaintNode) actor_node = NULL;
actor_node = clutter_actor_node_new (effect->actor);
clutter_paint_node_add_child (node, actor_node);
}
```
This example gives the exact same behavior of simply calling
clutter_actor_continue_paint(). In the future, the paint node
itself will be a parameter of clutter_actor_continue_paint()
and we'll be able to simplify it event more.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1340>
2020-06-27 11:12:03 -04:00
|
|
|
|
{
|
|
|
|
|
ClutterPaintNode *actor_node;
|
|
|
|
|
ClutterActor *actor;
|
|
|
|
|
|
|
|
|
|
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
|
|
|
|
|
2020-07-05 15:27:08 -04:00
|
|
|
|
actor_node = clutter_actor_node_new (actor, -1);
|
clutter/effect: Add paint_node vfunc
Introduce a new paint_node vfunc that, if implemented, allows
the effect to add nodes to a transient paint node that is
immediately painted. This is a transitional step until we
have fully delegated paint node rendering.
The most basic implementation of a ClutterEffect.paint_node
vfunc, and also the default implementation, is with an actor
node, as follows:
```
static void
foo_bar_paint_node (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags)
{
g_autoptr (ClutterPaintNode) actor_node = NULL;
actor_node = clutter_actor_node_new (effect->actor);
clutter_paint_node_add_child (node, actor_node);
}
```
This example gives the exact same behavior of simply calling
clutter_actor_continue_paint(). In the future, the paint node
itself will be a parameter of clutter_actor_continue_paint()
and we'll be able to simplify it event more.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1340>
2020-06-27 11:12:03 -04:00
|
|
|
|
clutter_paint_node_add_child (node, actor_node);
|
|
|
|
|
clutter_paint_node_unref (actor_node);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-29 12:43:22 -05:00
|
|
|
|
static void
|
|
|
|
|
clutter_effect_real_paint_node (ClutterEffect *effect,
|
|
|
|
|
ClutterPaintNode *node,
|
|
|
|
|
ClutterPaintContext *paint_context,
|
|
|
|
|
ClutterEffectPaintFlags flags)
|
|
|
|
|
{
|
|
|
|
|
add_actor_node (effect, node);
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-02 11:55:10 -05:00
|
|
|
|
static void
|
2011-06-13 10:58:46 -04:00
|
|
|
|
clutter_effect_real_paint (ClutterEffect *effect,
|
2020-07-05 17:45:03 -04:00
|
|
|
|
ClutterPaintNode *node,
|
2019-11-13 16:21:58 -05:00
|
|
|
|
ClutterPaintContext *paint_context,
|
2011-06-13 10:58:46 -04:00
|
|
|
|
ClutterEffectPaintFlags flags)
|
2011-03-02 11:55:10 -05:00
|
|
|
|
{
|
2020-06-26 22:11:36 -04:00
|
|
|
|
ClutterEffectClass *effect_class = CLUTTER_EFFECT_GET_CLASS (effect);
|
2011-03-02 11:55:10 -05:00
|
|
|
|
gboolean pre_paint_succeeded;
|
|
|
|
|
|
|
|
|
|
/* The default implementation provides a compatibility wrapper for
|
2011-06-06 02:44:11 -04:00
|
|
|
|
effects that haven't migrated to use the 'paint' virtual yet. This
|
2011-03-02 11:55:10 -05:00
|
|
|
|
just calls the old pre and post virtuals before chaining on */
|
|
|
|
|
|
2020-07-05 17:45:03 -04:00
|
|
|
|
pre_paint_succeeded = effect_class->pre_paint (effect, node,paint_context);
|
clutter/effect: Add paint_node vfunc
Introduce a new paint_node vfunc that, if implemented, allows
the effect to add nodes to a transient paint node that is
immediately painted. This is a transitional step until we
have fully delegated paint node rendering.
The most basic implementation of a ClutterEffect.paint_node
vfunc, and also the default implementation, is with an actor
node, as follows:
```
static void
foo_bar_paint_node (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags)
{
g_autoptr (ClutterPaintNode) actor_node = NULL;
actor_node = clutter_actor_node_new (effect->actor);
clutter_paint_node_add_child (node, actor_node);
}
```
This example gives the exact same behavior of simply calling
clutter_actor_continue_paint(). In the future, the paint node
itself will be a parameter of clutter_actor_continue_paint()
and we'll be able to simplify it event more.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1340>
2020-06-27 11:12:03 -04:00
|
|
|
|
|
2011-03-02 11:55:10 -05:00
|
|
|
|
if (pre_paint_succeeded)
|
2020-12-29 12:43:22 -05:00
|
|
|
|
{
|
|
|
|
|
effect_class->paint_node (effect, node, paint_context, flags);
|
|
|
|
|
effect_class->post_paint (effect, node, paint_context);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Just paint the actor as fallback */
|
|
|
|
|
add_actor_node (effect, node);
|
|
|
|
|
}
|
2011-03-02 11:55:10 -05:00
|
|
|
|
}
|
|
|
|
|
|
2011-06-02 08:16:23 -04:00
|
|
|
|
static void
|
2019-11-20 15:46:41 -05:00
|
|
|
|
clutter_effect_real_pick (ClutterEffect *effect,
|
|
|
|
|
ClutterPickContext *pick_context)
|
2011-06-02 08:16:23 -04:00
|
|
|
|
{
|
|
|
|
|
ClutterActorMeta *actor_meta = CLUTTER_ACTOR_META (effect);
|
|
|
|
|
ClutterActor *actor;
|
|
|
|
|
|
|
|
|
|
actor = clutter_actor_meta_get_actor (actor_meta);
|
2019-11-20 15:46:41 -05:00
|
|
|
|
clutter_actor_continue_pick (actor, pick_context);
|
2011-06-02 08:16:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2011-03-01 13:36:55 -05:00
|
|
|
|
static void
|
2020-04-08 11:02:28 -04:00
|
|
|
|
clutter_effect_set_enabled (ClutterActorMeta *meta,
|
|
|
|
|
gboolean is_enabled)
|
2011-03-01 13:36:55 -05:00
|
|
|
|
{
|
2020-04-08 11:02:28 -04:00
|
|
|
|
ClutterActorMetaClass *parent_class =
|
|
|
|
|
CLUTTER_ACTOR_META_CLASS (clutter_effect_parent_class);
|
|
|
|
|
ClutterActor *actor;
|
2011-03-01 13:36:55 -05:00
|
|
|
|
|
2020-04-08 11:02:28 -04:00
|
|
|
|
actor = clutter_actor_meta_get_actor (meta);
|
|
|
|
|
if (actor)
|
|
|
|
|
clutter_actor_queue_redraw (actor);
|
2011-03-01 13:36:55 -05:00
|
|
|
|
|
2020-04-08 11:02:28 -04:00
|
|
|
|
parent_class->set_enabled (meta, is_enabled);
|
2011-03-01 13:36:55 -05:00
|
|
|
|
}
|
|
|
|
|
|
2010-04-08 05:55:15 -04:00
|
|
|
|
static void
|
|
|
|
|
clutter_effect_class_init (ClutterEffectClass *klass)
|
|
|
|
|
{
|
2020-04-08 11:02:28 -04:00
|
|
|
|
ClutterActorMetaClass *actor_meta_class = CLUTTER_ACTOR_META_CLASS (klass);
|
2011-03-01 13:36:55 -05:00
|
|
|
|
|
2020-04-08 11:02:28 -04:00
|
|
|
|
actor_meta_class->set_enabled = clutter_effect_set_enabled;
|
2011-03-01 13:36:55 -05:00
|
|
|
|
|
2010-04-08 05:55:15 -04:00
|
|
|
|
klass->pre_paint = clutter_effect_real_pre_paint;
|
|
|
|
|
klass->post_paint = clutter_effect_real_post_paint;
|
2018-05-23 02:46:40 -04:00
|
|
|
|
klass->modify_paint_volume = clutter_effect_real_modify_paint_volume;
|
2011-06-06 02:44:11 -04:00
|
|
|
|
klass->paint = clutter_effect_real_paint;
|
clutter/effect: Add paint_node vfunc
Introduce a new paint_node vfunc that, if implemented, allows
the effect to add nodes to a transient paint node that is
immediately painted. This is a transitional step until we
have fully delegated paint node rendering.
The most basic implementation of a ClutterEffect.paint_node
vfunc, and also the default implementation, is with an actor
node, as follows:
```
static void
foo_bar_paint_node (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags)
{
g_autoptr (ClutterPaintNode) actor_node = NULL;
actor_node = clutter_actor_node_new (effect->actor);
clutter_paint_node_add_child (node, actor_node);
}
```
This example gives the exact same behavior of simply calling
clutter_actor_continue_paint(). In the future, the paint node
itself will be a parameter of clutter_actor_continue_paint()
and we'll be able to simplify it event more.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1340>
2020-06-27 11:12:03 -04:00
|
|
|
|
klass->paint_node = clutter_effect_real_paint_node;
|
2011-06-02 08:16:23 -04:00
|
|
|
|
klass->pick = clutter_effect_real_pick;
|
2010-04-08 05:55:15 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
clutter_effect_init (ClutterEffect *self)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-02 11:55:10 -05:00
|
|
|
|
void
|
2011-06-13 10:58:46 -04:00
|
|
|
|
_clutter_effect_paint (ClutterEffect *effect,
|
2020-07-05 18:17:09 -04:00
|
|
|
|
ClutterPaintNode *node,
|
2019-11-13 16:21:58 -05:00
|
|
|
|
ClutterPaintContext *paint_context,
|
2011-06-13 10:58:46 -04:00
|
|
|
|
ClutterEffectPaintFlags flags)
|
2011-03-02 11:55:10 -05:00
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
|
|
|
|
|
|
2020-07-05 17:45:03 -04:00
|
|
|
|
CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect,
|
|
|
|
|
node,
|
|
|
|
|
paint_context,
|
|
|
|
|
flags);
|
2011-03-02 11:55:10 -05:00
|
|
|
|
}
|
|
|
|
|
|
2011-06-02 08:16:23 -04:00
|
|
|
|
void
|
2019-11-20 15:46:41 -05:00
|
|
|
|
_clutter_effect_pick (ClutterEffect *effect,
|
|
|
|
|
ClutterPickContext *pick_context)
|
2011-06-02 08:16:23 -04:00
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
|
|
|
|
|
|
2019-11-20 15:46:41 -05:00
|
|
|
|
CLUTTER_EFFECT_GET_CLASS (effect)->pick (effect, pick_context);
|
2011-06-02 08:16:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2010-09-07 13:04:19 -04:00
|
|
|
|
gboolean
|
2018-05-23 02:46:40 -04:00
|
|
|
|
_clutter_effect_modify_paint_volume (ClutterEffect *effect,
|
|
|
|
|
ClutterPaintVolume *volume)
|
2010-08-16 12:02:15 -04:00
|
|
|
|
{
|
2010-09-07 13:04:19 -04:00
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE);
|
|
|
|
|
g_return_val_if_fail (volume != NULL, FALSE);
|
2010-08-16 12:02:15 -04:00
|
|
|
|
|
2018-05-23 02:46:40 -04:00
|
|
|
|
return CLUTTER_EFFECT_GET_CLASS (effect)->modify_paint_volume (effect,
|
|
|
|
|
volume);
|
2010-08-16 12:02:15 -04:00
|
|
|
|
}
|
2011-02-28 07:16:55 -05:00
|
|
|
|
|
2018-08-28 20:32:29 -04:00
|
|
|
|
gboolean
|
|
|
|
|
_clutter_effect_has_custom_paint_volume (ClutterEffect *effect)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE);
|
|
|
|
|
|
2018-05-23 02:46:40 -04:00
|
|
|
|
return CLUTTER_EFFECT_GET_CLASS (effect)->modify_paint_volume != clutter_effect_real_modify_paint_volume;
|
2018-08-28 20:32:29 -04:00
|
|
|
|
}
|
|
|
|
|
|
2011-02-28 07:16:55 -05:00
|
|
|
|
/**
|
2011-06-06 02:44:11 -04:00
|
|
|
|
* clutter_effect_queue_repaint:
|
2011-02-28 07:16:55 -05:00
|
|
|
|
* @effect: A #ClutterEffect which needs redrawing
|
|
|
|
|
*
|
2011-06-06 02:44:11 -04:00
|
|
|
|
* Queues a repaint of the effect. The effect can detect when the ‘paint’
|
2011-02-28 07:16:55 -05:00
|
|
|
|
* method is called as a result of this function because it will not
|
2011-09-12 08:12:14 -04:00
|
|
|
|
* have the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY flag set. In that case the
|
2011-02-28 07:16:55 -05:00
|
|
|
|
* effect is free to assume that the actor has not changed its
|
|
|
|
|
* appearance since the last time it was painted so it doesn't need to
|
|
|
|
|
* call clutter_actor_continue_paint() if it can draw a cached
|
|
|
|
|
* image. This is mostly intended for effects that are using a
|
|
|
|
|
* %CoglOffscreen to redirect the actor (such as
|
|
|
|
|
* %ClutterOffscreenEffect). In that case the effect can save a bit of
|
|
|
|
|
* rendering time by painting the cached texture without causing the
|
|
|
|
|
* entire actor to be painted.
|
|
|
|
|
*
|
|
|
|
|
* This function can be used by effects that have their own animatable
|
|
|
|
|
* parameters. For example, an effect which adds a varying degree of a
|
|
|
|
|
* red tint to an actor by redirecting it through a CoglOffscreen
|
|
|
|
|
* might have a property to specify the level of tint. When this value
|
|
|
|
|
* changes, the underlying actor doesn't need to be redrawn so the
|
2011-06-06 02:44:11 -04:00
|
|
|
|
* effect can call clutter_effect_queue_repaint() to make sure the
|
2011-02-28 07:16:55 -05:00
|
|
|
|
* effect is repainted.
|
|
|
|
|
*
|
|
|
|
|
* Note however that modifying the position of the parent of an actor
|
|
|
|
|
* may change the appearance of the actor because its transformation
|
|
|
|
|
* matrix would change. In this case a redraw wouldn't be queued on
|
2011-09-12 08:12:14 -04:00
|
|
|
|
* the actor itself so the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY would still
|
2011-02-28 07:16:55 -05:00
|
|
|
|
* not be set. The effect can detect this case by keeping track of the
|
|
|
|
|
* last modelview matrix that was used to render the actor and
|
2020-08-26 05:49:50 -04:00
|
|
|
|
* verifying that it remains the same in the next paint.
|
2011-02-28 07:16:55 -05:00
|
|
|
|
*
|
|
|
|
|
* Any other effects that are layered on top of the passed in effect
|
2011-09-12 08:12:14 -04:00
|
|
|
|
* will still be passed the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY flag. If
|
2011-02-28 07:16:55 -05:00
|
|
|
|
* anything queues a redraw on the actor without specifying an effect
|
|
|
|
|
* or with an effect that is lower in the chain of effects than this
|
|
|
|
|
* one then that will override this call. In that case this effect
|
2011-09-12 08:12:14 -04:00
|
|
|
|
* will instead be called with the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY
|
2011-02-28 07:16:55 -05:00
|
|
|
|
* flag set.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.8
|
|
|
|
|
*/
|
|
|
|
|
void
|
2011-06-06 02:44:11 -04:00
|
|
|
|
clutter_effect_queue_repaint (ClutterEffect *effect)
|
2011-02-28 07:16:55 -05:00
|
|
|
|
{
|
|
|
|
|
ClutterActor *actor;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
|
|
|
|
|
|
|
|
|
|
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
|
|
|
|
|
|
|
|
|
/* If the effect has no actor then nothing needs to be done */
|
|
|
|
|
if (actor != NULL)
|
|
|
|
|
_clutter_actor_queue_redraw_full (actor,
|
|
|
|
|
NULL, /* clip volume */
|
|
|
|
|
effect /* effect */);
|
|
|
|
|
}
|