Compare commits
25 Commits
citadel
...
gbsneto/of
Author | SHA1 | Date | |
---|---|---|---|
![]() |
edf8a1e399 | ||
![]() |
dd80e623a0 | ||
![]() |
5e680fd43f | ||
![]() |
4226fa50da | ||
![]() |
e5ee6e1138 | ||
![]() |
47b88de3b6 | ||
![]() |
e9b9784c5c | ||
![]() |
1135a74e3e | ||
![]() |
ae14a0a677 | ||
![]() |
dbe0602c4c | ||
![]() |
f6c57366af | ||
![]() |
6ee3ece103 | ||
![]() |
be3743ec3f | ||
![]() |
59a3075f60 | ||
![]() |
5d7edde37d | ||
![]() |
96e8074a4f | ||
![]() |
c261eb736a | ||
![]() |
03be5ed9f1 | ||
![]() |
6f0719b3c7 | ||
![]() |
6be6f04456 | ||
![]() |
e0a8e824b3 | ||
![]() |
0d51678bbe | ||
![]() |
35af306acc | ||
![]() |
e8f9d093b1 | ||
![]() |
0f1289e534 |
@ -3737,7 +3737,7 @@ clutter_actor_paint (ClutterActor *self,
|
||||
if (!CLUTTER_ACTOR_IS_MAPPED (self))
|
||||
return;
|
||||
|
||||
actor_node = clutter_actor_node_new (self);
|
||||
actor_node = clutter_actor_node_new (self, -1);
|
||||
root_node = clutter_paint_node_ref (actor_node);
|
||||
|
||||
if (priv->has_clip)
|
||||
@ -3958,6 +3958,7 @@ clutter_actor_continue_paint (ClutterActor *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_autoptr (ClutterPaintNode) effect_node = NULL;
|
||||
ClutterEffect *old_current_effect;
|
||||
ClutterEffectPaintFlags run_flags = 0;
|
||||
|
||||
@ -3986,7 +3987,14 @@ clutter_actor_continue_paint (ClutterActor *self,
|
||||
run_flags & CLUTTER_EFFECT_PAINT_ACTOR_DIRTY)
|
||||
run_flags |= CLUTTER_EFFECT_PAINT_BYPASS_EFFECT;
|
||||
|
||||
_clutter_effect_paint (priv->current_effect, paint_context, run_flags);
|
||||
effect_node = clutter_effect_node_new (priv->current_effect);
|
||||
|
||||
_clutter_effect_paint (priv->current_effect,
|
||||
effect_node,
|
||||
paint_context,
|
||||
run_flags);
|
||||
|
||||
clutter_paint_node_paint (effect_node, paint_context);
|
||||
|
||||
priv->current_effect = old_current_effect;
|
||||
}
|
||||
|
@ -81,9 +81,6 @@ struct _ClutterBlurEffect
|
||||
|
||||
gint pixel_step_uniform;
|
||||
|
||||
gint tex_width;
|
||||
gint tex_height;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
};
|
||||
|
||||
@ -98,20 +95,42 @@ G_DEFINE_TYPE (ClutterBlurEffect,
|
||||
clutter_blur_effect,
|
||||
CLUTTER_TYPE_OFFSCREEN_EFFECT);
|
||||
|
||||
static CoglPipeline *
|
||||
clutter_blur_effect_create_pipeline (ClutterOffscreenEffect *effect,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
ClutterBlurEffect *blur_effect = CLUTTER_BLUR_EFFECT (effect);
|
||||
|
||||
if (blur_effect->pixel_step_uniform > -1)
|
||||
{
|
||||
float pixel_step[2];
|
||||
int tex_width, tex_height;
|
||||
|
||||
tex_width = cogl_texture_get_width (texture);
|
||||
tex_height = cogl_texture_get_height (texture);
|
||||
|
||||
pixel_step[0] = 1.0f / tex_width;
|
||||
pixel_step[1] = 1.0f / tex_height;
|
||||
|
||||
cogl_pipeline_set_uniform_float (blur_effect->pipeline,
|
||||
blur_effect->pixel_step_uniform,
|
||||
2, /* n_components */
|
||||
1, /* count */
|
||||
pixel_step);
|
||||
}
|
||||
|
||||
cogl_pipeline_set_layer_texture (blur_effect->pipeline, 0, texture);
|
||||
|
||||
return cogl_object_ref (blur_effect->pipeline);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_blur_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect);
|
||||
ClutterEffectClass *parent_class;
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||
return FALSE;
|
||||
|
||||
self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
if (self->actor == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
{
|
||||
/* if we don't have support for GLSL shaders then we
|
||||
@ -125,59 +144,7 @@ clutter_blur_effect_pre_paint (ClutterEffect *effect,
|
||||
}
|
||||
|
||||
parent_class = CLUTTER_EFFECT_CLASS (clutter_blur_effect_parent_class);
|
||||
if (parent_class->pre_paint (effect, paint_context))
|
||||
{
|
||||
ClutterOffscreenEffect *offscreen_effect =
|
||||
CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
CoglHandle texture;
|
||||
|
||||
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
|
||||
self->tex_width = cogl_texture_get_width (texture);
|
||||
self->tex_height = cogl_texture_get_height (texture);
|
||||
|
||||
if (self->pixel_step_uniform > -1)
|
||||
{
|
||||
gfloat pixel_step[2];
|
||||
|
||||
pixel_step[0] = 1.0f / self->tex_width;
|
||||
pixel_step[1] = 1.0f / self->tex_height;
|
||||
|
||||
cogl_pipeline_set_uniform_float (self->pipeline,
|
||||
self->pixel_step_uniform,
|
||||
2, /* n_components */
|
||||
1, /* count */
|
||||
pixel_step);
|
||||
}
|
||||
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blur_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect);
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
guint8 paint_opacity;
|
||||
|
||||
paint_opacity = clutter_actor_get_paint_opacity (self->actor);
|
||||
|
||||
cogl_pipeline_set_color4ub (self->pipeline,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
self->pipeline,
|
||||
0, 0,
|
||||
self->tex_width, self->tex_height);
|
||||
return parent_class->pre_paint (effect, node, paint_context);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -229,7 +196,7 @@ clutter_blur_effect_class_init (ClutterBlurEffectClass *klass)
|
||||
effect_class->modify_paint_volume = clutter_blur_effect_modify_paint_volume;
|
||||
|
||||
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
offscreen_class->paint_target = clutter_blur_effect_paint_target;
|
||||
offscreen_class->create_pipeline = clutter_blur_effect_create_pipeline;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -69,9 +69,6 @@ struct _ClutterBrightnessContrastEffect
|
||||
gint brightness_offset_uniform;
|
||||
gint contrast_uniform;
|
||||
|
||||
gint tex_width;
|
||||
gint tex_height;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
};
|
||||
|
||||
@ -129,16 +126,26 @@ will_have_no_effect (ClutterBrightnessContrastEffect *self)
|
||||
G_APPROX_VALUE (self->contrast_blue, no_change, FLT_EPSILON));
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
clutter_brightness_contrast_effect_create_pipeline (ClutterOffscreenEffect *effect,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
ClutterBrightnessContrastEffect *self =
|
||||
CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
|
||||
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
|
||||
|
||||
return cogl_object_ref (self->pipeline);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
|
||||
ClutterEffectClass *parent_class;
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||
return FALSE;
|
||||
|
||||
if (will_have_no_effect (self))
|
||||
return FALSE;
|
||||
|
||||
@ -157,47 +164,8 @@ clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect,
|
||||
|
||||
parent_class =
|
||||
CLUTTER_EFFECT_CLASS (clutter_brightness_contrast_effect_parent_class);
|
||||
if (parent_class->pre_paint (effect, paint_context))
|
||||
{
|
||||
ClutterOffscreenEffect *offscreen_effect =
|
||||
CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
CoglHandle texture;
|
||||
|
||||
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
|
||||
self->tex_width = cogl_texture_get_width (texture);
|
||||
self->tex_height = cogl_texture_get_height (texture);
|
||||
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_brightness_contrast_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
ClutterActor *actor;
|
||||
guint8 paint_opacity;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
paint_opacity = clutter_actor_get_paint_opacity (actor);
|
||||
|
||||
cogl_pipeline_set_color4ub (self->pipeline,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
self->pipeline,
|
||||
0, 0,
|
||||
self->tex_width, self->tex_height);
|
||||
return parent_class->pre_paint (effect, node, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -297,7 +265,7 @@ clutter_brightness_contrast_effect_class_init (ClutterBrightnessContrastEffectCl
|
||||
ClutterOffscreenEffectClass *offscreen_class;
|
||||
|
||||
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
offscreen_class->paint_target = clutter_brightness_contrast_effect_paint_target;
|
||||
offscreen_class->create_pipeline = clutter_brightness_contrast_effect_create_pipeline;
|
||||
|
||||
effect_class->pre_paint = clutter_brightness_contrast_effect_pre_paint;
|
||||
|
||||
|
@ -59,9 +59,6 @@ struct _ClutterColorizeEffect
|
||||
|
||||
gint tint_uniform;
|
||||
|
||||
gint tex_width;
|
||||
gint tex_height;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
};
|
||||
|
||||
@ -104,16 +101,24 @@ G_DEFINE_TYPE (ClutterColorizeEffect,
|
||||
clutter_colorize_effect,
|
||||
CLUTTER_TYPE_OFFSCREEN_EFFECT);
|
||||
|
||||
static CoglPipeline *
|
||||
clutter_colorize_effect_create_pipeline (ClutterOffscreenEffect *effect,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
ClutterColorizeEffect *colorize_effect = CLUTTER_COLORIZE_EFFECT (effect);
|
||||
|
||||
cogl_pipeline_set_layer_texture (colorize_effect->pipeline, 0, texture);
|
||||
|
||||
return cogl_object_ref (colorize_effect->pipeline);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_colorize_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect);
|
||||
ClutterEffectClass *parent_class;
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||
return FALSE;
|
||||
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
{
|
||||
/* if we don't have support for GLSL shaders then we
|
||||
@ -127,47 +132,7 @@ clutter_colorize_effect_pre_paint (ClutterEffect *effect,
|
||||
}
|
||||
|
||||
parent_class = CLUTTER_EFFECT_CLASS (clutter_colorize_effect_parent_class);
|
||||
if (parent_class->pre_paint (effect, paint_context))
|
||||
{
|
||||
ClutterOffscreenEffect *offscreen_effect =
|
||||
CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
CoglHandle texture;
|
||||
|
||||
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
|
||||
self->tex_width = cogl_texture_get_width (texture);
|
||||
self->tex_height = cogl_texture_get_height (texture);
|
||||
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_colorize_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect);
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
ClutterActor *actor;
|
||||
guint8 paint_opacity;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
paint_opacity = clutter_actor_get_paint_opacity (actor);
|
||||
|
||||
cogl_pipeline_set_color4ub (self->pipeline,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
self->pipeline,
|
||||
0, 0,
|
||||
self->tex_width, self->tex_height);
|
||||
return parent_class->pre_paint (effect, node, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -233,7 +198,7 @@ clutter_colorize_effect_class_init (ClutterColorizeEffectClass *klass)
|
||||
ClutterOffscreenEffectClass *offscreen_class;
|
||||
|
||||
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
offscreen_class->paint_target = clutter_colorize_effect_paint_target;
|
||||
offscreen_class->create_pipeline = clutter_colorize_effect_create_pipeline;
|
||||
|
||||
effect_class->pre_paint = clutter_colorize_effect_pre_paint;
|
||||
|
||||
|
@ -58,9 +58,12 @@
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include "clutter-color.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-enum-types.h"
|
||||
#include "clutter-offscreen-effect-private.h"
|
||||
#include "clutter-paint-node.h"
|
||||
#include "clutter-paint-nodes.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
#define DEFAULT_N_TILES 32
|
||||
@ -166,19 +169,16 @@ clutter_deform_effect_set_actor (ClutterActorMeta *meta,
|
||||
|
||||
static void
|
||||
clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect);
|
||||
ClutterDeformEffectPrivate *priv = self->priv;
|
||||
CoglHandle material;
|
||||
CoglPipeline *pipeline;
|
||||
CoglDepthState depth_state;
|
||||
CoglFramebuffer *fb =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
|
||||
if (priv->is_dirty)
|
||||
{
|
||||
graphene_rect_t rect;
|
||||
gboolean mapped_buffer;
|
||||
CoglVertexP3T2C4 *verts;
|
||||
ClutterActor *actor;
|
||||
@ -192,12 +192,7 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
/* if we don't have a target size, fall back to the actor's
|
||||
* allocation, though wrong it might be
|
||||
*/
|
||||
if (clutter_offscreen_effect_get_target_rect (effect, &rect))
|
||||
{
|
||||
width = graphene_rect_get_width (&rect);
|
||||
height = graphene_rect_get_height (&rect);
|
||||
}
|
||||
else
|
||||
if (!clutter_offscreen_effect_get_target_size (effect, &width, &height))
|
||||
clutter_actor_get_size (actor, &width, &height);
|
||||
|
||||
/* XXX ideally, the sub-classes should tell us what they
|
||||
@ -277,8 +272,7 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
priv->is_dirty = FALSE;
|
||||
}
|
||||
|
||||
material = clutter_offscreen_effect_get_target (effect);
|
||||
pipeline = COGL_PIPELINE (material);
|
||||
pipeline = clutter_offscreen_effect_get_pipeline (effect);
|
||||
|
||||
/* enable depth testing */
|
||||
cogl_depth_state_init (&depth_state);
|
||||
@ -292,12 +286,22 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
COGL_PIPELINE_CULL_FACE_MODE_BACK);
|
||||
|
||||
/* draw the front */
|
||||
if (material != NULL)
|
||||
cogl_framebuffer_draw_primitive (fb, pipeline, priv->primitive);
|
||||
if (pipeline != NULL)
|
||||
{
|
||||
ClutterPaintNode *front_node;
|
||||
|
||||
front_node = clutter_pipeline_node_new (pipeline);
|
||||
clutter_paint_node_set_static_name (front_node,
|
||||
"ClutterDeformEffect (front)");
|
||||
clutter_paint_node_add_child (node, front_node);
|
||||
clutter_paint_node_add_primitive (front_node, priv->primitive);
|
||||
clutter_paint_node_unref (front_node);
|
||||
}
|
||||
|
||||
/* draw the back */
|
||||
if (priv->back_pipeline != NULL)
|
||||
{
|
||||
ClutterPaintNode *back_node;
|
||||
CoglPipeline *back_pipeline;
|
||||
|
||||
/* We probably shouldn't be modifying the user's material so
|
||||
@ -307,20 +311,30 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
cogl_pipeline_set_cull_face_mode (back_pipeline,
|
||||
COGL_PIPELINE_CULL_FACE_MODE_FRONT);
|
||||
|
||||
cogl_framebuffer_draw_primitive (fb, back_pipeline, priv->primitive);
|
||||
|
||||
back_node = clutter_pipeline_node_new (back_pipeline);
|
||||
clutter_paint_node_set_static_name (back_node,
|
||||
"ClutterDeformEffect (back)");
|
||||
clutter_paint_node_add_child (node, back_node);
|
||||
clutter_paint_node_add_primitive (back_node, priv->primitive);
|
||||
|
||||
clutter_paint_node_unref (back_node);
|
||||
cogl_object_unref (back_pipeline);
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (priv->lines_primitive != NULL))
|
||||
{
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
CoglPipeline *lines_pipeline = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_color4f (lines_pipeline, 1.0, 0, 0, 1.0);
|
||||
cogl_framebuffer_draw_primitive (fb, lines_pipeline,
|
||||
priv->lines_primitive);
|
||||
cogl_object_unref (lines_pipeline);
|
||||
const ClutterColor *red;
|
||||
ClutterPaintNode *lines_node;
|
||||
|
||||
red = clutter_color_get_static (CLUTTER_COLOR_RED);
|
||||
|
||||
lines_node = clutter_color_node_new (red);
|
||||
clutter_paint_node_set_static_name (lines_node,
|
||||
"ClutterDeformEffect (lines)");
|
||||
clutter_paint_node_add_child (node, lines_node);
|
||||
clutter_paint_node_add_primitive (lines_node, priv->lines_primitive);
|
||||
clutter_paint_node_unref (lines_node);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,16 +111,25 @@ G_DEFINE_TYPE (ClutterDesaturateEffect,
|
||||
clutter_desaturate_effect,
|
||||
CLUTTER_TYPE_OFFSCREEN_EFFECT);
|
||||
|
||||
static CoglPipeline *
|
||||
clutter_desaturate_effect_create_pipeline (ClutterOffscreenEffect *effect,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
ClutterDesaturateEffect *desaturate_effect =
|
||||
CLUTTER_DESATURATE_EFFECT (effect);
|
||||
|
||||
cogl_pipeline_set_layer_texture (desaturate_effect->pipeline, 0, texture);
|
||||
|
||||
return cogl_object_ref (desaturate_effect->pipeline);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_desaturate_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect);
|
||||
ClutterEffectClass *parent_class;
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||
return FALSE;
|
||||
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
{
|
||||
/* if we don't have support for GLSL shaders then we
|
||||
@ -134,52 +143,7 @@ clutter_desaturate_effect_pre_paint (ClutterEffect *effect,
|
||||
}
|
||||
|
||||
parent_class = CLUTTER_EFFECT_CLASS (clutter_desaturate_effect_parent_class);
|
||||
if (parent_class->pre_paint (effect, paint_context))
|
||||
{
|
||||
ClutterOffscreenEffect *offscreen_effect =
|
||||
CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
CoglHandle texture;
|
||||
|
||||
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
|
||||
self->tex_width = cogl_texture_get_width (texture);
|
||||
self->tex_height = cogl_texture_get_height (texture);
|
||||
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_desaturate_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect);
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
ClutterActor *actor;
|
||||
CoglHandle texture;
|
||||
guint8 paint_opacity;
|
||||
|
||||
texture = clutter_offscreen_effect_get_texture (effect);
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
|
||||
|
||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
paint_opacity = clutter_actor_get_paint_opacity (actor);
|
||||
|
||||
cogl_pipeline_set_color4ub (self->pipeline,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
self->pipeline,
|
||||
0, 0,
|
||||
cogl_texture_get_width (texture),
|
||||
cogl_texture_get_height (texture));
|
||||
return parent_class->pre_paint (effect, node, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -254,7 +218,7 @@ clutter_desaturate_effect_class_init (ClutterDesaturateEffectClass *klass)
|
||||
ClutterOffscreenEffectClass *offscreen_class;
|
||||
|
||||
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
offscreen_class->paint_target = clutter_desaturate_effect_paint_target;
|
||||
offscreen_class->create_pipeline = clutter_desaturate_effect_create_pipeline;
|
||||
|
||||
effect_class->pre_paint = clutter_desaturate_effect_pre_paint;
|
||||
|
||||
|
@ -5,14 +5,11 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean _clutter_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintContext *paint_context);
|
||||
void _clutter_effect_post_paint (ClutterEffect *effect,
|
||||
ClutterPaintContext *paint_context);
|
||||
gboolean _clutter_effect_modify_paint_volume (ClutterEffect *effect,
|
||||
ClutterPaintVolume *volume);
|
||||
gboolean _clutter_effect_has_custom_paint_volume (ClutterEffect *effect);
|
||||
void _clutter_effect_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags);
|
||||
void _clutter_effect_pick (ClutterEffect *effect,
|
||||
|
@ -169,6 +169,8 @@
|
||||
#include "clutter-effect-private.h"
|
||||
#include "clutter-enum-types.h"
|
||||
#include "clutter-marshal.h"
|
||||
#include "clutter-paint-node-private.h"
|
||||
#include "clutter-paint-nodes.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-actor-private.h"
|
||||
|
||||
@ -178,6 +180,7 @@ G_DEFINE_ABSTRACT_TYPE (ClutterEffect,
|
||||
|
||||
static gboolean
|
||||
clutter_effect_real_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
return TRUE;
|
||||
@ -185,6 +188,7 @@ clutter_effect_real_pre_paint (ClutterEffect *effect,
|
||||
|
||||
static void
|
||||
clutter_effect_real_post_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
}
|
||||
@ -197,25 +201,40 @@ clutter_effect_real_modify_paint_volume (ClutterEffect *effect,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_effect_real_paint (ClutterEffect *effect,
|
||||
clutter_effect_real_paint_node (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags)
|
||||
{
|
||||
ClutterActorMeta *actor_meta = CLUTTER_ACTOR_META (effect);
|
||||
ClutterPaintNode *actor_node;
|
||||
ClutterActor *actor;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
|
||||
actor_node = clutter_actor_node_new (actor, -1);
|
||||
clutter_paint_node_add_child (node, actor_node);
|
||||
clutter_paint_node_unref (actor_node);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_effect_real_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags)
|
||||
{
|
||||
ClutterEffectClass *effect_class = CLUTTER_EFFECT_GET_CLASS (effect);
|
||||
gboolean pre_paint_succeeded;
|
||||
|
||||
/* The default implementation provides a compatibility wrapper for
|
||||
effects that haven't migrated to use the 'paint' virtual yet. This
|
||||
just calls the old pre and post virtuals before chaining on */
|
||||
|
||||
pre_paint_succeeded = _clutter_effect_pre_paint (effect, paint_context);
|
||||
pre_paint_succeeded = effect_class->pre_paint (effect, node,paint_context);
|
||||
|
||||
actor = clutter_actor_meta_get_actor (actor_meta);
|
||||
clutter_actor_continue_paint (actor, paint_context);
|
||||
effect_class->paint_node (effect, node, paint_context, flags);
|
||||
|
||||
if (pre_paint_succeeded)
|
||||
_clutter_effect_post_paint (effect, paint_context);
|
||||
effect_class->post_paint (effect, node, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -255,6 +274,7 @@ clutter_effect_class_init (ClutterEffectClass *klass)
|
||||
klass->post_paint = clutter_effect_real_post_paint;
|
||||
klass->modify_paint_volume = clutter_effect_real_modify_paint_volume;
|
||||
klass->paint = clutter_effect_real_paint;
|
||||
klass->paint_node = clutter_effect_real_paint_node;
|
||||
klass->pick = clutter_effect_real_pick;
|
||||
}
|
||||
|
||||
@ -263,32 +283,18 @@ clutter_effect_init (ClutterEffect *self)
|
||||
{
|
||||
}
|
||||
|
||||
gboolean
|
||||
_clutter_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE);
|
||||
|
||||
return CLUTTER_EFFECT_GET_CLASS (effect)->pre_paint (effect, paint_context);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_effect_post_paint (ClutterEffect *effect,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
|
||||
|
||||
CLUTTER_EFFECT_GET_CLASS (effect)->post_paint (effect, paint_context);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_effect_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
|
||||
|
||||
CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect, paint_context, flags);
|
||||
CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect,
|
||||
node,
|
||||
paint_context,
|
||||
flags);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -77,14 +77,21 @@ struct _ClutterEffectClass
|
||||
|
||||
/*< public >*/
|
||||
gboolean (* pre_paint) (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context);
|
||||
void (* post_paint) (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context);
|
||||
|
||||
gboolean (* modify_paint_volume) (ClutterEffect *effect,
|
||||
ClutterPaintVolume *volume);
|
||||
|
||||
void (* paint) (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags);
|
||||
void (* paint_node) (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags);
|
||||
void (* pick) (ClutterEffect *effect,
|
||||
|
@ -60,6 +60,30 @@
|
||||
* #ClutterOffscreenEffectClass.create_texture() virtual function; no chain up
|
||||
* to the #ClutterOffscreenEffect implementation is required in this
|
||||
* case.
|
||||
*
|
||||
* ## Paint nodes
|
||||
*
|
||||
* #ClutterOffscreenEffect is generates the following paint node tree:
|
||||
*
|
||||
* |[<!-- language="plain" -->
|
||||
* Effect
|
||||
* ├─────────┐
|
||||
* Layer Pipeline
|
||||
* │
|
||||
* Actor
|
||||
* ]|
|
||||
*
|
||||
* When the actor contents are cached, the generated paint node tree
|
||||
* looks like this:
|
||||
*
|
||||
* |[<!-- language="plain" -->
|
||||
* Effect
|
||||
* │
|
||||
* Pipeline
|
||||
* ]|
|
||||
*
|
||||
* In both cases, the "Pipeline" node is created with the return value
|
||||
* of #ClutterOffscreenEffectClass.create_pipeline().
|
||||
*/
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
@ -75,6 +99,8 @@
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-stage-private.h"
|
||||
#include "clutter-paint-context-private.h"
|
||||
#include "clutter-paint-node-private.h"
|
||||
#include "clutter-paint-nodes.h"
|
||||
#include "clutter-paint-volume-private.h"
|
||||
#include "clutter-actor-box-private.h"
|
||||
|
||||
@ -87,8 +113,6 @@ struct _ClutterOffscreenEffectPrivate
|
||||
ClutterActor *actor;
|
||||
ClutterActor *stage;
|
||||
|
||||
graphene_point3d_t position;
|
||||
|
||||
int fbo_offset_x;
|
||||
int fbo_offset_y;
|
||||
|
||||
@ -158,6 +182,25 @@ ensure_pipeline_filter_for_scale (ClutterOffscreenEffect *self,
|
||||
filter, filter);
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
clutter_offscreen_effect_real_create_pipeline (ClutterOffscreenEffect *effect,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
ClutterOffscreenEffectPrivate *priv = effect->priv;
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
CoglPipeline *pipeline;
|
||||
float resource_scale;
|
||||
|
||||
resource_scale = clutter_actor_get_real_resource_scale (priv->actor);
|
||||
|
||||
pipeline = cogl_pipeline_new (ctx);
|
||||
ensure_pipeline_filter_for_scale (effect, resource_scale);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, texture);
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_fbo (ClutterEffect *effect,
|
||||
int target_width,
|
||||
@ -166,6 +209,8 @@ update_fbo (ClutterEffect *effect,
|
||||
{
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
ClutterOffscreenEffectClass *offscreen_class =
|
||||
CLUTTER_OFFSCREEN_EFFECT_GET_CLASS (effect);
|
||||
|
||||
priv->stage = clutter_actor_get_stage (priv->actor);
|
||||
if (priv->stage == NULL)
|
||||
@ -185,15 +230,6 @@ update_fbo (ClutterEffect *effect,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (priv->pipeline == NULL)
|
||||
{
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
|
||||
priv->pipeline = cogl_pipeline_new (ctx);
|
||||
ensure_pipeline_filter_for_scale (self, resource_scale);
|
||||
}
|
||||
|
||||
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
|
||||
@ -202,8 +238,6 @@ update_fbo (ClutterEffect *effect,
|
||||
if (priv->texture == NULL)
|
||||
return FALSE;
|
||||
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->texture);
|
||||
|
||||
priv->target_width = target_width;
|
||||
priv->target_height = target_height;
|
||||
|
||||
@ -212,8 +246,7 @@ update_fbo (ClutterEffect *effect,
|
||||
{
|
||||
g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC);
|
||||
|
||||
cogl_object_unref (priv->pipeline);
|
||||
priv->pipeline = NULL;
|
||||
cogl_clear_object (&priv->pipeline);
|
||||
|
||||
priv->target_width = 0;
|
||||
priv->target_height = 0;
|
||||
@ -221,35 +254,33 @@ update_fbo (ClutterEffect *effect,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cogl_clear_object (&priv->pipeline);
|
||||
priv->pipeline = offscreen_class->create_pipeline (self, priv->texture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
ClutterActorBox raw_box, box;
|
||||
ClutterActor *stage;
|
||||
CoglMatrix projection, old_modelview, modelview;
|
||||
CoglMatrix projection, modelview;
|
||||
const ClutterPaintVolume *volume;
|
||||
CoglColor transparent;
|
||||
gfloat stage_width, stage_height;
|
||||
gfloat target_width = -1, target_height = -1;
|
||||
CoglFramebuffer *framebuffer;
|
||||
float resource_scale;
|
||||
float ceiled_resource_scale;
|
||||
graphene_point3d_t local_offset;
|
||||
gfloat old_viewport[4];
|
||||
|
||||
local_offset = GRAPHENE_POINT3D_INIT (0.0f, 0.0f, 0.0f);
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||
return FALSE;
|
||||
goto fail;
|
||||
|
||||
if (priv->actor == NULL)
|
||||
return FALSE;
|
||||
goto fail;
|
||||
|
||||
stage = _clutter_actor_get_stage_internal (priv->actor);
|
||||
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
||||
@ -294,12 +325,7 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
|
||||
/* First assert that the framebuffer is the right size... */
|
||||
if (!update_fbo (effect, target_width, target_height, resource_scale))
|
||||
return FALSE;
|
||||
|
||||
framebuffer = clutter_paint_context_get_framebuffer (paint_context);
|
||||
cogl_framebuffer_get_modelview_matrix (framebuffer, &old_modelview);
|
||||
|
||||
clutter_paint_context_push_framebuffer (paint_context, priv->offscreen);
|
||||
goto fail;
|
||||
|
||||
/* We don't want the FBO contents to be transformed. That could waste memory
|
||||
* (e.g. during zoom), or result in something that's not rectangular (clipped
|
||||
@ -311,13 +337,6 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
clutter_actor_get_transform (priv->stage, &modelview);
|
||||
cogl_framebuffer_set_modelview_matrix (priv->offscreen, &modelview);
|
||||
|
||||
/* Save the original viewport for calculating priv->position */
|
||||
_clutter_stage_get_viewport (CLUTTER_STAGE (priv->stage),
|
||||
&old_viewport[0],
|
||||
&old_viewport[1],
|
||||
&old_viewport[2],
|
||||
&old_viewport[3]);
|
||||
|
||||
/* Set up the viewport so that it has the same size as the stage (avoid
|
||||
* distortion), but translated to account for the FBO offset...
|
||||
*/
|
||||
@ -331,45 +350,22 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
_clutter_stage_get_projection_matrix (CLUTTER_STAGE (priv->stage),
|
||||
&projection);
|
||||
|
||||
/* Now save the global position of the effect (not just of the actor).
|
||||
* It doesn't appear anyone actually uses this yet, but get_target_rect is
|
||||
* documented as returning it. So we should...
|
||||
*/
|
||||
_clutter_util_fully_transform_vertices (&old_modelview,
|
||||
&projection,
|
||||
old_viewport,
|
||||
&local_offset,
|
||||
&priv->position,
|
||||
1);
|
||||
|
||||
cogl_framebuffer_set_projection_matrix (priv->offscreen, &projection);
|
||||
|
||||
cogl_color_init_from_4ub (&transparent, 0, 0, 0, 0);
|
||||
cogl_framebuffer_clear (priv->offscreen,
|
||||
COGL_BUFFER_BIT_COLOR |
|
||||
COGL_BUFFER_BIT_DEPTH,
|
||||
&transparent);
|
||||
|
||||
cogl_framebuffer_push_matrix (priv->offscreen);
|
||||
|
||||
/* Override the actor's opacity to fully opaque - we paint the offscreen
|
||||
* texture with the actor's paint opacity, so we need to do this to avoid
|
||||
* multiplying the opacity twice.
|
||||
*/
|
||||
priv->old_opacity_override =
|
||||
clutter_actor_get_opacity_override (priv->actor);
|
||||
clutter_actor_set_opacity_override (priv->actor, 0xff);
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
cogl_clear_object (&priv->offscreen);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterOffscreenEffectPrivate *priv = effect->priv;
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
ClutterPaintNode *pipeline_node;
|
||||
guint8 paint_opacity;
|
||||
|
||||
paint_opacity = clutter_actor_get_paint_opacity (priv->actor);
|
||||
@ -380,96 +376,122 @@ clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect,
|
||||
paint_opacity,
|
||||
paint_opacity);
|
||||
|
||||
pipeline_node = clutter_pipeline_node_new (priv->pipeline);
|
||||
clutter_paint_node_set_static_name (pipeline_node,
|
||||
"ClutterOffscreenEffect (pipeline)");
|
||||
clutter_paint_node_add_child (node, pipeline_node);
|
||||
|
||||
/* At this point we are in stage coordinates translated so if
|
||||
* we draw our texture using a textured quad the size of the paint
|
||||
* box then we will overlay where the actor would have drawn if it
|
||||
* hadn't been redirected offscreen.
|
||||
*/
|
||||
cogl_framebuffer_draw_textured_rectangle (framebuffer,
|
||||
priv->pipeline,
|
||||
0, 0,
|
||||
clutter_paint_node_add_rectangle (pipeline_node,
|
||||
&(ClutterActorBox) {
|
||||
0.f, 0.f,
|
||||
cogl_texture_get_width (priv->texture),
|
||||
cogl_texture_get_height (priv->texture),
|
||||
0.0, 0.0,
|
||||
1.0, 1.0);
|
||||
});
|
||||
|
||||
clutter_paint_node_unref (pipeline_node);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterOffscreenEffectPrivate *priv = effect->priv;
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
CoglMatrix modelview;
|
||||
CoglMatrix transform;
|
||||
float resource_scale;
|
||||
|
||||
cogl_framebuffer_push_matrix (framebuffer);
|
||||
|
||||
/* The current modelview matrix is *almost* perfect already. It's only
|
||||
* missing a correction for the expanded FBO and offset rendering within...
|
||||
*/
|
||||
cogl_framebuffer_get_modelview_matrix (framebuffer, &modelview);
|
||||
cogl_matrix_init_identity (&transform);
|
||||
|
||||
resource_scale = clutter_actor_get_resource_scale (priv->actor);
|
||||
|
||||
if (resource_scale != 1.0f)
|
||||
{
|
||||
float paint_scale = 1.0f / resource_scale;
|
||||
cogl_matrix_scale (&modelview, paint_scale, paint_scale, 1);
|
||||
cogl_matrix_scale (&transform, paint_scale, paint_scale, 1);
|
||||
}
|
||||
|
||||
cogl_matrix_translate (&modelview,
|
||||
cogl_matrix_translate (&transform,
|
||||
priv->fbo_offset_x,
|
||||
priv->fbo_offset_y,
|
||||
0.0f);
|
||||
cogl_framebuffer_set_modelview_matrix (framebuffer, &modelview);
|
||||
|
||||
if (!cogl_matrix_is_identity (&transform))
|
||||
{
|
||||
ClutterPaintNode *transform_node;
|
||||
|
||||
transform_node = clutter_transform_node_new (&transform);
|
||||
clutter_paint_node_set_static_name (transform_node,
|
||||
"ClutterOffscreenEffect (transform)");
|
||||
clutter_paint_node_add_child (node, transform_node);
|
||||
clutter_paint_node_unref (transform_node);
|
||||
|
||||
node = transform_node;
|
||||
}
|
||||
|
||||
/* paint the target material; this is virtualized for
|
||||
* sub-classes that require special hand-holding
|
||||
*/
|
||||
clutter_offscreen_effect_paint_target (effect, paint_context);
|
||||
|
||||
cogl_framebuffer_pop_matrix (framebuffer);
|
||||
clutter_offscreen_effect_paint_target (effect, node, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_post_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
CoglFramebuffer *framebuffer;
|
||||
|
||||
g_warn_if_fail (priv->offscreen);
|
||||
g_warn_if_fail (priv->pipeline);
|
||||
g_warn_if_fail (priv->actor);
|
||||
|
||||
/* Restore the previous opacity override */
|
||||
if (priv->actor)
|
||||
{
|
||||
clutter_actor_set_opacity_override (priv->actor,
|
||||
priv->old_opacity_override);
|
||||
clutter_offscreen_effect_paint_texture (self, node, paint_context);
|
||||
}
|
||||
|
||||
framebuffer = clutter_paint_context_get_framebuffer (paint_context);
|
||||
cogl_framebuffer_pop_matrix (framebuffer);
|
||||
clutter_paint_context_pop_framebuffer (paint_context);
|
||||
static void
|
||||
clutter_offscreen_effect_paint_node (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags)
|
||||
{
|
||||
ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
ClutterOffscreenEffectPrivate *priv = offscreen_effect->priv;
|
||||
ClutterPaintNode *layer_node;
|
||||
ClutterPaintNode *actor_node;
|
||||
|
||||
clutter_offscreen_effect_paint_texture (self, paint_context);
|
||||
layer_node = clutter_layer_node_new_with_framebuffer (priv->offscreen,
|
||||
priv->pipeline,
|
||||
255);
|
||||
clutter_paint_node_set_static_name (layer_node,
|
||||
"ClutterOffscreenEffect (actor offscreen)");
|
||||
clutter_paint_node_add_child (node, layer_node);
|
||||
clutter_paint_node_unref (layer_node);
|
||||
|
||||
actor_node = clutter_actor_node_new (priv->actor, 255);
|
||||
clutter_paint_node_add_child (layer_node, actor_node);
|
||||
clutter_paint_node_unref (actor_node);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags)
|
||||
{
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
ClutterEffectClass *parent_class =
|
||||
CLUTTER_EFFECT_CLASS (clutter_offscreen_effect_parent_class);
|
||||
|
||||
if (flags & CLUTTER_EFFECT_PAINT_BYPASS_EFFECT)
|
||||
{
|
||||
clutter_actor_continue_paint (priv->actor, paint_context);
|
||||
parent_class->paint_node (effect, node, paint_context, flags);
|
||||
cogl_clear_object (&priv->offscreen);
|
||||
return;
|
||||
}
|
||||
@ -478,21 +500,9 @@ clutter_offscreen_effect_paint (ClutterEffect *effect,
|
||||
* then we can just use the cached image in the FBO.
|
||||
*/
|
||||
if (priv->offscreen == NULL || (flags & CLUTTER_EFFECT_PAINT_ACTOR_DIRTY))
|
||||
{
|
||||
ClutterEffectClass *effect_class = CLUTTER_EFFECT_GET_CLASS (effect);
|
||||
gboolean pre_paint_succeeded;
|
||||
|
||||
pre_paint_succeeded = effect_class->pre_paint (effect, paint_context);
|
||||
|
||||
clutter_actor_continue_paint (priv->actor, paint_context);
|
||||
|
||||
if (pre_paint_succeeded)
|
||||
effect_class->post_paint (effect, paint_context);
|
||||
parent_class->paint (effect, node, paint_context, flags);
|
||||
else
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
}
|
||||
else
|
||||
clutter_offscreen_effect_paint_texture (self, paint_context);
|
||||
clutter_offscreen_effect_paint_texture (self, node, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -530,6 +540,7 @@ clutter_offscreen_effect_class_init (ClutterOffscreenEffectClass *klass)
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->create_texture = clutter_offscreen_effect_real_create_texture;
|
||||
klass->create_pipeline = clutter_offscreen_effect_real_create_pipeline;
|
||||
klass->paint_target = clutter_offscreen_effect_real_paint_target;
|
||||
|
||||
meta_class->set_actor = clutter_offscreen_effect_set_actor;
|
||||
@ -538,6 +549,7 @@ clutter_offscreen_effect_class_init (ClutterOffscreenEffectClass *klass)
|
||||
effect_class->pre_paint = clutter_offscreen_effect_pre_paint;
|
||||
effect_class->post_paint = clutter_offscreen_effect_post_paint;
|
||||
effect_class->paint = clutter_offscreen_effect_paint;
|
||||
effect_class->paint_node = clutter_offscreen_effect_paint_node;
|
||||
|
||||
gobject_class->finalize = clutter_offscreen_effect_finalize;
|
||||
}
|
||||
@ -578,33 +590,34 @@ clutter_offscreen_effect_get_texture (ClutterOffscreenEffect *effect)
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_offscreen_effect_get_target: (skip)
|
||||
* clutter_offscreen_effect_get_pipeline:
|
||||
* @effect: a #ClutterOffscreenEffect
|
||||
*
|
||||
* Retrieves the material used as a render target for the offscreen
|
||||
* Retrieves the pipeline used as a render target for the offscreen
|
||||
* buffer created by @effect
|
||||
*
|
||||
* You should only use the returned #CoglMaterial when painting. The
|
||||
* returned material might change between different frames.
|
||||
* You should only use the returned #CoglPipeline when painting. The
|
||||
* returned pipeline might change between different frames.
|
||||
*
|
||||
* Return value: (transfer none): a #CoglMaterial or %NULL. The
|
||||
* returned material is owned by Clutter and it should not be
|
||||
* modified or freed
|
||||
* Return value: (transfer none)(nullable): a #CoglPipeline. The
|
||||
* pipeline is owned by Clutter and it should not be modified
|
||||
* or freed
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
CoglMaterial *
|
||||
clutter_offscreen_effect_get_target (ClutterOffscreenEffect *effect)
|
||||
CoglPipeline *
|
||||
clutter_offscreen_effect_get_pipeline (ClutterOffscreenEffect *effect)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect),
|
||||
NULL);
|
||||
|
||||
return (CoglMaterial *)effect->priv->pipeline;
|
||||
return effect->priv->pipeline;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_offscreen_effect_paint_target:
|
||||
* @effect: a #ClutterOffscreenEffect
|
||||
* @node: a #ClutterPaintNode
|
||||
* @paint_context: a #ClutterPaintContext
|
||||
*
|
||||
* Calls the paint_target() virtual function of the @effect
|
||||
@ -613,11 +626,13 @@ clutter_offscreen_effect_get_target (ClutterOffscreenEffect *effect)
|
||||
*/
|
||||
void
|
||||
clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect));
|
||||
|
||||
CLUTTER_OFFSCREEN_EFFECT_GET_CLASS (effect)->paint_target (effect,
|
||||
node,
|
||||
paint_context);
|
||||
}
|
||||
|
||||
@ -665,8 +680,6 @@ clutter_offscreen_effect_create_texture (ClutterOffscreenEffect *effect,
|
||||
* and %FALSE otherwise
|
||||
*
|
||||
* Since: 1.8
|
||||
*
|
||||
* Deprecated: 1.14: Use clutter_offscreen_effect_get_target_rect() instead
|
||||
*/
|
||||
gboolean
|
||||
clutter_offscreen_effect_get_target_size (ClutterOffscreenEffect *effect,
|
||||
@ -690,43 +703,3 @@ clutter_offscreen_effect_get_target_size (ClutterOffscreenEffect *effect,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_offscreen_effect_get_target_rect:
|
||||
* @effect: a #ClutterOffscreenEffect
|
||||
* @rect: (out caller-allocates): return location for the target area
|
||||
*
|
||||
* Retrieves the origin and size of the offscreen buffer used by @effect to
|
||||
* paint the actor to which it has been applied.
|
||||
*
|
||||
* This function should only be called by #ClutterOffscreenEffect
|
||||
* implementations, from within the #ClutterOffscreenEffectClass.paint_target()
|
||||
* virtual function.
|
||||
*
|
||||
* Return value: %TRUE if the offscreen buffer has a valid rectangle,
|
||||
* and %FALSE otherwise
|
||||
*
|
||||
* Since: 1.14
|
||||
*/
|
||||
gboolean
|
||||
clutter_offscreen_effect_get_target_rect (ClutterOffscreenEffect *effect,
|
||||
graphene_rect_t *rect)
|
||||
{
|
||||
ClutterOffscreenEffectPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect), FALSE);
|
||||
g_return_val_if_fail (rect != NULL, FALSE);
|
||||
|
||||
priv = effect->priv;
|
||||
|
||||
if (priv->texture == NULL)
|
||||
return FALSE;
|
||||
|
||||
graphene_rect_init (rect,
|
||||
priv->position.x,
|
||||
priv->position.y,
|
||||
cogl_texture_get_width (priv->texture),
|
||||
cogl_texture_get_height (priv->texture));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -79,7 +79,10 @@ struct _ClutterOffscreenEffectClass
|
||||
CoglHandle (* create_texture) (ClutterOffscreenEffect *effect,
|
||||
gfloat width,
|
||||
gfloat height);
|
||||
CoglPipeline* (* create_pipeline) (ClutterOffscreenEffect *effect,
|
||||
CoglTexture *texture);
|
||||
void (* paint_target) (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context);
|
||||
|
||||
/*< private >*/
|
||||
@ -96,28 +99,25 @@ CLUTTER_EXPORT
|
||||
GType clutter_offscreen_effect_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
CoglMaterial * clutter_offscreen_effect_get_target (ClutterOffscreenEffect *effect);
|
||||
CoglPipeline * clutter_offscreen_effect_get_pipeline (ClutterOffscreenEffect *effect);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
CoglHandle clutter_offscreen_effect_get_texture (ClutterOffscreenEffect *effect);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context);
|
||||
CLUTTER_EXPORT
|
||||
CoglHandle clutter_offscreen_effect_create_texture (ClutterOffscreenEffect *effect,
|
||||
gfloat width,
|
||||
gfloat height);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR (clutter_offscreen_effect_get_target_rect)
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_offscreen_effect_get_target_size (ClutterOffscreenEffect *effect,
|
||||
gfloat *width,
|
||||
gfloat *height);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_offscreen_effect_get_target_rect (ClutterOffscreenEffect *effect,
|
||||
graphene_rect_t *rect);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_OFFSCREEN_EFFECT_H__ */
|
||||
|
@ -141,6 +141,26 @@ ClutterPaintNode * clutter_paint_node_get_last_child (Clutter
|
||||
G_GNUC_INTERNAL
|
||||
ClutterPaintNode * clutter_paint_node_get_parent (ClutterPaintNode *node);
|
||||
|
||||
|
||||
#define CLUTTER_TYPE_EFFECT_NODE (clutter_effect_node_get_type ())
|
||||
#define CLUTTER_EFFECT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_EFFECT_NODE, ClutterEffectNode))
|
||||
#define CLUTTER_IS_EFFECT_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_EFFECT_NODE))
|
||||
|
||||
/**
|
||||
* ClutterEffectNode:
|
||||
*
|
||||
* The #ClutterEffectNode structure is an opaque
|
||||
* type whose members cannot be directly accessed.
|
||||
*/
|
||||
typedef struct _ClutterEffectNode ClutterEffectNode;
|
||||
typedef struct _ClutterEffectNode ClutterEffectNodeClass;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GType clutter_effect_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_effect_node_new (ClutterEffect *actor);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_PAINT_NODE_PRIVATE_H__ */
|
||||
|
@ -551,7 +551,7 @@ clutter_pipeline_node_init (ClutterPipelineNode *self)
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pipeline_node_new: (skip)
|
||||
* clutter_pipeline_node_new:
|
||||
* @pipeline: (allow-none): a Cogl pipeline state object, or %NULL
|
||||
*
|
||||
* Creates a new #ClutterPaintNode that will use the @pipeline to
|
||||
@ -1115,6 +1115,8 @@ struct _ClutterActorNode
|
||||
ClutterPaintNode parent_instance;
|
||||
|
||||
ClutterActor *actor;
|
||||
int opacity_override;
|
||||
int old_opacity_override;
|
||||
};
|
||||
|
||||
struct _ClutterActorNodeClass
|
||||
@ -1130,6 +1132,14 @@ clutter_actor_node_pre_draw (ClutterPaintNode *node,
|
||||
{
|
||||
ClutterActorNode *actor_node = CLUTTER_ACTOR_NODE (node);
|
||||
|
||||
if (actor_node->opacity_override != -1)
|
||||
{
|
||||
actor_node->old_opacity_override =
|
||||
clutter_actor_get_opacity_override (actor_node->actor);
|
||||
clutter_actor_set_opacity_override (actor_node->actor,
|
||||
actor_node->opacity_override);
|
||||
}
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS (actor_node->actor, CLUTTER_IN_PAINT);
|
||||
|
||||
return TRUE;
|
||||
@ -1151,6 +1161,12 @@ clutter_actor_node_post_draw (ClutterPaintNode *node,
|
||||
ClutterActorNode *actor_node = CLUTTER_ACTOR_NODE (node);
|
||||
|
||||
CLUTTER_UNSET_PRIVATE_FLAGS (actor_node->actor, CLUTTER_IN_PAINT);
|
||||
|
||||
if (actor_node->opacity_override != -1)
|
||||
{
|
||||
clutter_actor_set_opacity_override (actor_node->actor,
|
||||
actor_node->old_opacity_override);
|
||||
}
|
||||
}
|
||||
|
||||
static JsonNode *
|
||||
@ -1192,6 +1208,7 @@ clutter_actor_node_init (ClutterActorNode *self)
|
||||
/*
|
||||
* clutter_actor_node_new:
|
||||
* @actor: the actor to paint
|
||||
* @opacity: opacity to draw the actor with, or -1 to use the actor's opacity
|
||||
*
|
||||
* Creates a new #ClutterActorNode.
|
||||
*
|
||||
@ -1203,7 +1220,8 @@ clutter_actor_node_init (ClutterActorNode *self)
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_actor_node_new (ClutterActor *actor)
|
||||
clutter_actor_node_new (ClutterActor *actor,
|
||||
int opacity)
|
||||
{
|
||||
ClutterActorNode *res;
|
||||
|
||||
@ -1211,11 +1229,96 @@ clutter_actor_node_new (ClutterActor *actor)
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_ACTOR_NODE);
|
||||
res->actor = actor;
|
||||
res->opacity_override = CLAMP (opacity, -1, 255);
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ClutterEffectNode
|
||||
*/
|
||||
|
||||
struct _ClutterEffectNode
|
||||
{
|
||||
ClutterPaintNode parent_instance;
|
||||
|
||||
ClutterEffect *effect;
|
||||
};
|
||||
|
||||
struct _ClutterEffectNodeClass
|
||||
{
|
||||
ClutterPaintNodeClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ClutterEffectNode, clutter_effect_node, CLUTTER_TYPE_PAINT_NODE)
|
||||
|
||||
static JsonNode *
|
||||
clutter_effect_node_serialize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterEffectNode *effect_node = CLUTTER_EFFECT_NODE (node);
|
||||
ClutterActorMeta *effect_meta = CLUTTER_ACTOR_META (effect_node->effect);
|
||||
g_autoptr (JsonBuilder) builder = NULL;
|
||||
g_autoptr (GString) string = NULL;
|
||||
const char *meta_name;
|
||||
|
||||
meta_name = clutter_actor_meta_get_name (effect_meta);
|
||||
|
||||
string = g_string_new (NULL);
|
||||
g_string_append (string, G_OBJECT_TYPE_NAME (effect_node->effect));
|
||||
g_string_append (string, " (");
|
||||
if (meta_name)
|
||||
g_string_append_printf (string, "\"%s\"", meta_name);
|
||||
else
|
||||
g_string_append (string, "unnamed");
|
||||
g_string_append (string, ")");
|
||||
|
||||
builder = json_builder_new ();
|
||||
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "effect");
|
||||
json_builder_add_string_value (builder, string->str);
|
||||
json_builder_end_object (builder);
|
||||
|
||||
return json_builder_get_root (builder);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_effect_node_class_init (ClutterEffectNodeClass *klass)
|
||||
{
|
||||
ClutterPaintNodeClass *node_class;
|
||||
|
||||
node_class = CLUTTER_PAINT_NODE_CLASS (klass);
|
||||
node_class->serialize = clutter_effect_node_serialize;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_effect_node_init (ClutterEffectNode *self)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* clutter_effect_node_new:
|
||||
* @actor: the actor to paint
|
||||
*
|
||||
* Creates a new #ClutterEffectNode.
|
||||
*
|
||||
* Return value: (transfer full): the newly created #ClutterEffectNode.
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_effect_node_new (ClutterEffect *effect)
|
||||
{
|
||||
ClutterEffectNode *res;
|
||||
|
||||
g_assert (effect != NULL);
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_EFFECT_NODE);
|
||||
res->effect = effect;
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
|
||||
/*
|
||||
* ClutterLayerNode
|
||||
*/
|
||||
@ -1235,6 +1338,7 @@ struct _ClutterLayerNode
|
||||
CoglFramebuffer *offscreen;
|
||||
|
||||
guint8 opacity;
|
||||
gboolean update_modelview;
|
||||
};
|
||||
|
||||
struct _ClutterLayerNodeClass
|
||||
@ -1249,8 +1353,6 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterLayerNode *lnode = (ClutterLayerNode *) node;
|
||||
CoglFramebuffer *framebuffer;
|
||||
CoglMatrix matrix;
|
||||
|
||||
/* if we were unable to create an offscreen buffer for this node, then
|
||||
* we simply ignore it
|
||||
@ -1258,18 +1360,16 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node,
|
||||
if (lnode->offscreen == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* if no geometry was submitted for this node then we simply ignore it */
|
||||
if (node->operations == NULL)
|
||||
return FALSE;
|
||||
if (lnode->update_modelview)
|
||||
{
|
||||
CoglFramebuffer *framebuffer;
|
||||
CoglMatrix matrix;
|
||||
|
||||
/* copy the same modelview from the current framebuffer to the one we
|
||||
* are going to use
|
||||
*/
|
||||
framebuffer = clutter_paint_context_get_framebuffer (paint_context);
|
||||
cogl_framebuffer_get_modelview_matrix (framebuffer, &matrix);
|
||||
|
||||
clutter_paint_context_push_framebuffer (paint_context, lnode->offscreen);
|
||||
|
||||
cogl_framebuffer_set_modelview_matrix (lnode->offscreen, &matrix);
|
||||
|
||||
cogl_framebuffer_set_viewport (lnode->offscreen,
|
||||
@ -1280,6 +1380,9 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node,
|
||||
|
||||
cogl_framebuffer_set_projection_matrix (lnode->offscreen,
|
||||
&lnode->projection);
|
||||
}
|
||||
|
||||
clutter_paint_context_push_framebuffer (paint_context, lnode->offscreen);
|
||||
|
||||
/* clear out the target framebuffer */
|
||||
cogl_framebuffer_clear4f (lnode->offscreen,
|
||||
@ -1307,6 +1410,10 @@ clutter_layer_node_post_draw (ClutterPaintNode *node,
|
||||
cogl_framebuffer_pop_matrix (lnode->offscreen);
|
||||
clutter_paint_context_pop_framebuffer (paint_context);
|
||||
|
||||
/* if no geometry was submitted for this node then we simply ignore it */
|
||||
if (node->operations == NULL)
|
||||
return;
|
||||
|
||||
fb = clutter_paint_context_get_framebuffer (paint_context);
|
||||
|
||||
for (i = 0; i < node->operations->len; i++)
|
||||
@ -1367,6 +1474,25 @@ clutter_layer_node_finalize (ClutterPaintNode *node)
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_layer_node_parent_class)->finalize (node);
|
||||
}
|
||||
|
||||
static JsonNode *
|
||||
clutter_layer_node_serialize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterLayerNode *layer_node = CLUTTER_LAYER_NODE (node);
|
||||
g_autoptr (JsonBuilder) builder = NULL;
|
||||
g_autofree char *framebuffer_ptr = NULL;
|
||||
|
||||
builder = json_builder_new ();
|
||||
|
||||
framebuffer_ptr = g_strdup_printf ("%p", layer_node->offscreen);
|
||||
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "framebuffer");
|
||||
json_builder_add_string_value (builder, framebuffer_ptr);
|
||||
json_builder_end_object (builder);
|
||||
|
||||
return json_builder_get_root (builder);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_layer_node_class_init (ClutterLayerNodeClass *klass)
|
||||
{
|
||||
@ -1376,6 +1502,7 @@ clutter_layer_node_class_init (ClutterLayerNodeClass *klass)
|
||||
node_class->pre_draw = clutter_layer_node_pre_draw;
|
||||
node_class->post_draw = clutter_layer_node_post_draw;
|
||||
node_class->finalize = clutter_layer_node_finalize;
|
||||
node_class->serialize = clutter_layer_node_serialize;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1418,6 +1545,7 @@ clutter_layer_node_new (const CoglMatrix *projection,
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
|
||||
|
||||
res->update_modelview = TRUE;
|
||||
res->projection = *projection;
|
||||
res->viewport = *viewport;
|
||||
res->fbo_width = width;
|
||||
@ -1458,3 +1586,245 @@ out:
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layer_node_new_with_framebuffer:
|
||||
* @framebuffer: a #CoglFramebuffer
|
||||
* @pipeline: a #CoglPipeline
|
||||
* @opacity: the opacity to be used when drawing the layer
|
||||
*
|
||||
* Creates a new #ClutterLayerNode with @framebuffer and
|
||||
* @pipeline. @framebuffer will then be painted using the
|
||||
* given @opacity.
|
||||
*
|
||||
* When using this constructor, the caller is responsible
|
||||
* for setting up the framebuffer's modelview and projection
|
||||
* matrices.
|
||||
*
|
||||
* Return value: (transfer full)(nullable): the newly created #ClutterLayerNode.
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_layer_node_new_with_framebuffer (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline,
|
||||
guint8 opacity)
|
||||
{
|
||||
ClutterLayerNode *res;
|
||||
CoglColor color;
|
||||
|
||||
g_return_val_if_fail (cogl_is_framebuffer (framebuffer), NULL);
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
|
||||
|
||||
res->update_modelview = FALSE;
|
||||
res->offscreen = cogl_object_ref (framebuffer);
|
||||
res->pipeline = cogl_pipeline_copy (pipeline);
|
||||
|
||||
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||
cogl_pipeline_set_color (res->pipeline, &color);
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
|
||||
/*
|
||||
* ClutterBlitNode
|
||||
*/
|
||||
|
||||
struct _ClutterBlitNode
|
||||
{
|
||||
ClutterPaintNode parent_instance;
|
||||
|
||||
CoglFramebuffer *source;
|
||||
CoglFramebuffer *dest;
|
||||
};
|
||||
|
||||
struct _ClutterBlitNodeClass
|
||||
{
|
||||
ClutterPaintNodeClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ClutterBlitNode, clutter_blit_node, CLUTTER_TYPE_PAINT_NODE)
|
||||
|
||||
static gboolean
|
||||
clutter_blit_node_pre_draw (ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blit_node_draw (ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterBlitNode *blit_node = CLUTTER_BLIT_NODE (node);
|
||||
g_autoptr (GError) error = NULL;
|
||||
CoglFramebuffer *source;
|
||||
guint i;
|
||||
|
||||
if (node->operations == NULL)
|
||||
return;
|
||||
|
||||
source = blit_node->source;
|
||||
if (!source)
|
||||
source = clutter_paint_context_get_framebuffer (paint_context);
|
||||
|
||||
for (i = 0; i < node->operations->len; i++)
|
||||
{
|
||||
const ClutterPaintOperation *op;
|
||||
float op_width, op_height;
|
||||
|
||||
op = &g_array_index (node->operations, ClutterPaintOperation, i);
|
||||
|
||||
switch (op->opcode)
|
||||
{
|
||||
case PAINT_OP_INVALID:
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECT:
|
||||
op_width = op->op.texrect[6] - op->op.texrect[4];
|
||||
op_height = op->op.texrect[7] - op->op.texrect[5];
|
||||
|
||||
cogl_blit_framebuffer (source,
|
||||
blit_node->dest,
|
||||
op->op.texrect[0],
|
||||
op->op.texrect[1],
|
||||
op->op.texrect[4],
|
||||
op->op.texrect[5],
|
||||
op_width,
|
||||
op_height,
|
||||
&error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Error blitting framebuffers: %s", error->message);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blit_node_finalize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterBlitNode *blit_node = CLUTTER_BLIT_NODE (node);
|
||||
|
||||
cogl_clear_object (&blit_node->source);
|
||||
cogl_clear_object (&blit_node->dest);
|
||||
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_layer_node_parent_class)->finalize (node);
|
||||
}
|
||||
|
||||
static JsonNode *
|
||||
clutter_blit_node_serialize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterBlitNode *blit_node = CLUTTER_BLIT_NODE (node);
|
||||
g_autoptr (JsonBuilder) builder = NULL;
|
||||
g_autofree char *source_ptr = NULL;
|
||||
g_autofree char *dest_ptr = NULL;
|
||||
|
||||
builder = json_builder_new ();
|
||||
|
||||
source_ptr = g_strdup_printf ("%p", blit_node->source);
|
||||
dest_ptr = g_strdup_printf ("%p", blit_node->dest);
|
||||
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "source");
|
||||
json_builder_add_string_value (builder, source_ptr);
|
||||
json_builder_end_object (builder);
|
||||
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "dest");
|
||||
json_builder_add_string_value (builder, dest_ptr);
|
||||
json_builder_end_object (builder);
|
||||
|
||||
return json_builder_get_root (builder);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blit_node_class_init (ClutterTransformNodeClass *klass)
|
||||
{
|
||||
ClutterPaintNodeClass *node_class;
|
||||
|
||||
node_class = CLUTTER_PAINT_NODE_CLASS (klass);
|
||||
node_class->pre_draw = clutter_blit_node_pre_draw;
|
||||
node_class->draw = clutter_blit_node_draw;
|
||||
node_class->finalize = clutter_blit_node_finalize;
|
||||
node_class->serialize = clutter_blit_node_serialize;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blit_node_init (ClutterBlitNode *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blit_node_new:
|
||||
* @source: (nullable): the source #CoglFramebuffer
|
||||
* @dest: the destination #CoglFramebuffer
|
||||
*
|
||||
* Creates a new #ClutterBlitNode that blits @source into @dest.
|
||||
*
|
||||
* If @source is %NULL, the most recent framebuffer stacked into a
|
||||
* #ClutterPaintContext is used.
|
||||
*
|
||||
* You must only add rectangles using clutter_blit_node_add_blit_rectangle().
|
||||
*
|
||||
* Return value: (transfer full): the newly created #ClutterBlitNode.
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_blit_node_new (CoglFramebuffer *source,
|
||||
CoglFramebuffer *dest)
|
||||
{
|
||||
ClutterBlitNode *res;
|
||||
|
||||
g_return_val_if_fail (cogl_is_framebuffer (dest), NULL);
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_BLIT_NODE);
|
||||
res->source = source ? cogl_object_ref (source) : NULL;
|
||||
res->dest = cogl_object_ref (dest);
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blit_node_add_blit_rectangle:
|
||||
* @blit_node: a #ClutterBlitNode
|
||||
* @src_x: Source x position
|
||||
* @src_y: Source y position
|
||||
* @dst_x: Destination x position
|
||||
* @dst_y: Destination y position
|
||||
* @width: Width of region to copy
|
||||
* @height: Height of region to copy
|
||||
*
|
||||
* Adds a new blit rectangle to the stack of rectangles. All the
|
||||
* constraints of cogl_blit_framebuffer() apply here.
|
||||
*/
|
||||
void
|
||||
clutter_blit_node_add_blit_rectangle (ClutterBlitNode *blit_node,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_BLIT_NODE (blit_node));
|
||||
|
||||
clutter_paint_node_add_texture_rectangle (CLUTTER_PAINT_NODE (blit_node),
|
||||
&(ClutterActorBox) {
|
||||
src_x,
|
||||
src_y,
|
||||
src_x + width,
|
||||
src_y + height,
|
||||
},
|
||||
dst_x,
|
||||
dst_y,
|
||||
dst_x + width,
|
||||
dst_y + height);
|
||||
}
|
||||
|
@ -160,7 +160,8 @@ CLUTTER_EXPORT
|
||||
GType clutter_actor_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_actor_node_new (ClutterActor *actor);
|
||||
ClutterPaintNode * clutter_actor_node_new (ClutterActor *actor,
|
||||
int opacity);
|
||||
|
||||
#define CLUTTER_TYPE_ROOT_NODE (clutter_root_node_get_type ())
|
||||
#define CLUTTER_ROOT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ROOT_NODE, ClutterRootNode))
|
||||
@ -208,6 +209,11 @@ ClutterPaintNode * clutter_layer_node_new (const CoglMatrix
|
||||
float height,
|
||||
guint8 opacity);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_layer_node_new_with_framebuffer (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline,
|
||||
guint8 opacity);
|
||||
|
||||
|
||||
#define CLUTTER_TYPE_TRANSFORM_NODE (clutter_transform_node_get_type ())
|
||||
#define CLUTTER_TRANSFORM_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TRANSFORM_NODE, ClutterTransformNode))
|
||||
@ -230,6 +236,38 @@ GType clutter_transform_node_get_type (void) G_GNUC_CONST;
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_transform_node_new (const CoglMatrix *projection);
|
||||
|
||||
#define CLUTTER_TYPE_BLIT_NODE (clutter_blit_node_get_type ())
|
||||
#define CLUTTER_BLIT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BLIT_NODE, ClutterBlitNode))
|
||||
#define CLUTTER_IS_BLIT_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BLIT_NODE))
|
||||
|
||||
/*
|
||||
* ClutterBlitNode:
|
||||
*
|
||||
* The #ClutterLayerNode structure is an opaque
|
||||
* type whose members cannot be directly accessed.
|
||||
*
|
||||
* Since: 1.10
|
||||
*/
|
||||
typedef struct _ClutterBlitNode ClutterBlitNode;
|
||||
typedef struct _ClutterPaintNodeClass ClutterBlitNodeClass;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GType clutter_blit_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_blit_node_new (CoglFramebuffer *source,
|
||||
CoglFramebuffer *dest);
|
||||
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_blit_node_add_blit_rectangle (ClutterBlitNode *blit_node,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_PAINT_NODES_H__ */
|
||||
|
@ -384,12 +384,13 @@ clutter_shader_effect_try_static_source (ClutterShaderEffect *self)
|
||||
|
||||
static void
|
||||
clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (effect);
|
||||
ClutterShaderEffectPrivate *priv = self->priv;
|
||||
ClutterOffscreenEffectClass *parent;
|
||||
CoglHandle material;
|
||||
CoglPipeline *pipeline;
|
||||
|
||||
/* If the source hasn't been set then we'll try to get it from the
|
||||
static source instead */
|
||||
@ -407,14 +408,14 @@ clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
|
||||
clutter_shader_effect_update_uniforms (CLUTTER_SHADER_EFFECT (effect));
|
||||
|
||||
/* associate the program to the offscreen target material */
|
||||
material = clutter_offscreen_effect_get_target (effect);
|
||||
cogl_pipeline_set_user_program (material, priv->program);
|
||||
/* associate the program to the offscreen target pipeline */
|
||||
pipeline = clutter_offscreen_effect_get_pipeline (effect);
|
||||
cogl_pipeline_set_user_program (pipeline, priv->program);
|
||||
|
||||
out:
|
||||
/* paint the offscreen buffer */
|
||||
parent = CLUTTER_OFFSCREEN_EFFECT_CLASS (clutter_shader_effect_parent_class);
|
||||
parent->paint_target (effect, paint_context);
|
||||
parent->paint_target (effect, node, paint_context);
|
||||
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@ G_DEFINE_TYPE (FooOldShaderEffect,
|
||||
|
||||
static void
|
||||
foo_old_shader_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
clutter_shader_effect_set_shader_source (CLUTTER_SHADER_EFFECT (effect),
|
||||
@ -47,7 +48,7 @@ foo_old_shader_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
1.0f, 0.0f, 0.0f);
|
||||
|
||||
CLUTTER_OFFSCREEN_EFFECT_CLASS (foo_old_shader_effect_parent_class)->
|
||||
paint_target (effect, paint_context);
|
||||
paint_target (effect, node, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -112,6 +113,7 @@ foo_new_shader_effect_get_static_source (ClutterShaderEffect *effect)
|
||||
|
||||
static void
|
||||
foo_new_shader_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect),
|
||||
@ -120,7 +122,7 @@ foo_new_shader_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
0.0f, 1.0f, 0.0f);
|
||||
|
||||
CLUTTER_OFFSCREEN_EFFECT_CLASS (foo_new_shader_effect_parent_class)->
|
||||
paint_target (effect, paint_context);
|
||||
paint_target (effect, node, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
x
Reference in New Issue
Block a user