summaryrefslogtreecommitdiff
path: root/clutter/clutter-offscreen-effect.c
diff options
context:
space:
mode:
authorChris Lord <chris@linux.intel.com>2011-02-11 15:18:08 +0000
committerChris Lord <chris@linux.intel.com>2011-02-11 16:17:57 +0000
commita297fb039409733afa7df6eaeb2d28f1af1a93a3 (patch)
tree1dc2cc3a119ea8d5ccfbda8f9d1546a26fef3849 /clutter/clutter-offscreen-effect.c
parent442d8c3f2e2246187468bcebcb4de287181785d4 (diff)
downloadclutter-a297fb039409733afa7df6eaeb2d28f1af1a93a3.tar.gz
offscreen: Fix partially off-stage actors being clipped in the fbo
If an actor was partially off of the stage, it would be clipped because of the stage viewport. This produces problems if you use an offscreen effect that relies on the entire actor being rendered (e.g. shadows). Expand the viewport in this scenario so that the offscreen-rendering isn't clipped. This fixes http://bugzilla.clutter-project.org/show_bug.cgi?id=2550
Diffstat (limited to 'clutter/clutter-offscreen-effect.c')
-rw-r--r--clutter/clutter-offscreen-effect.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/clutter/clutter-offscreen-effect.c b/clutter/clutter-offscreen-effect.c
index db8da6a8e..1fbb17e95 100644
--- a/clutter/clutter-offscreen-effect.c
+++ b/clutter/clutter-offscreen-effect.c
@@ -196,6 +196,7 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
CoglMatrix modelview;
gfloat fbo_width, fbo_height;
gfloat width, height;
+ gfloat xexpand, yexpand;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
return FALSE;
@@ -234,13 +235,53 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
* framebuffer. */
clutter_actor_get_size (priv->stage, &width, &height);
clutter_actor_box_get_origin (&box, &priv->x_offset, &priv->y_offset);
- cogl_set_viewport (-priv->x_offset, -priv->y_offset, width, height);
+
+ /* Expand the viewport if the actor is partially off-stage,
+ * otherwise the actor will end up clipped to the stage viewport
+ */
+ xexpand = 0.f;
+ if (priv->x_offset < 0.f)
+ xexpand = -priv->x_offset;
+ if (priv->x_offset + fbo_width > width)
+ xexpand = MAX (xexpand, (priv->x_offset + fbo_width) - width);
+
+ yexpand = 0.f;
+ if (priv->y_offset < 0.f)
+ yexpand = -priv->y_offset;
+ if (priv->y_offset + fbo_height > height)
+ yexpand = MAX (yexpand, (priv->y_offset + fbo_height) - height);
+
+ /* Set the viewport */
+ cogl_set_viewport (-(priv->x_offset + xexpand), -(priv->y_offset + yexpand),
+ width + (2 * xexpand), height + (2 * yexpand));
/* Copy the stage's projection matrix across to the framebuffer */
_clutter_stage_get_projection_matrix (CLUTTER_STAGE (priv->stage),
&projection);
cogl_set_projection_matrix (&projection);
+ /* If we've expanded the viewport, make sure to scale the modelview
+ * matrix accordingly (as it's been initialised to work with the
+ * original viewport and not our expanded one).
+ */
+ if (xexpand > 0.f || yexpand > 0.f)
+ {
+ CoglMatrix correction;
+ gfloat new_width, new_height;
+
+ new_width = width + (2 * xexpand);
+ new_height = height + (2 * yexpand);
+
+ cogl_matrix_init_identity (&correction);
+ cogl_matrix_scale (&correction,
+ width / new_width,
+ height / new_height,
+ 1);
+
+ cogl_matrix_multiply (&correction, &correction, &modelview);
+ modelview = correction;
+ }
+
/* Copy the modelview that would have been used if rendering onscreen */
cogl_set_modelview_matrix (&modelview);