clutter-offscreen-effect: Apply matrix expansion to proj not mv

When the viewport gets expanded because the actor extends off the edge
of the screen, instead of applying the transformation to the root of
the modelview transformation it is now applied to the end of the
projection transformation. This should end up with the same
transformation. This fixes a problem when the offscreen effects are
nested and the inner effect would try to pick up the current modelview
transformation to rescale it to fit the new viewport size. In this
case the modelview would have already been scaled for the size of the
outer viewport so it would end up wrong.

https://bugzilla.gnome.org/show_bug.cgi?id=659601

Reviewed-by: Emmanuele Bassi <ebassi@linux.intel.com>
Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
Neil Roberts 2011-09-21 16:36:30 +01:00
parent 9d8ad86165
commit c67d3e5b52

View File

@ -215,7 +215,6 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
ClutterActorBox box;
CoglMatrix projection;
CoglColor transparent;
CoglMatrix modelview;
gfloat fbo_width, fbo_height;
gfloat width, height;
gfloat xexpand, yexpand;
@ -249,19 +248,18 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
if (!update_fbo (effect, fbo_width, fbo_height))
return FALSE;
/* get the current modelview matrix so that we can copy it
* to the framebuffer
*/
cogl_get_modelview_matrix (&modelview);
/* Store the matrix that was last used when we updated the FBO so
that we can detect when we don't need to update the FBO to paint
a second time */
priv->last_matrix_drawn = modelview;
/* get the current modelview matrix so that we can copy it to the
* framebuffer. We also store the matrix that was last used when we
* updated the FBO so that we can detect when we don't need to
* update the FBO to paint a second time */
cogl_get_modelview_matrix (&priv->last_matrix_drawn);
/* let's draw offscreen */
cogl_push_framebuffer (priv->offscreen);
/* Copy the modelview that would have been used if rendering onscreen */
cogl_set_modelview_matrix (&priv->last_matrix_drawn);
/* Set up the viewport so that it has the same size as the stage,
* but offset it so that the actor of interest lands on our
* framebuffer. */
@ -289,32 +287,25 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
/* 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
/* If we've expanded the viewport, make sure to scale the projection
* 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,
cogl_matrix_scale (&projection,
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);
cogl_set_projection_matrix (&projection);
cogl_color_init_from_4ub (&transparent, 0, 0, 0, 0);
cogl_clear (&transparent,