mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 01:20:42 -05:00
stage: Compute view perspective when parameters changed
Clutter stage used to compute the initial projection using a fixed z translation which wasn't matching the one we computed in calculate_z_translation(). This caused to have a wrong initial projection on startup which was then correctly recomputed only at the first paint. However, since this calculation doesn't depend on view, but only on viewport size, perspective's fovy and z_near we can safely do this at startup and only when any of those parameters change. Then we can move the computation out _clutter_stage_maybe_setup_viewport() since the cogl framebuffer viewport sizes aren't affecting this. Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1639 https://gitlab.gnome.org/GNOME/mutter/merge_requests/803
This commit is contained in:
parent
d7d2612218
commit
b69d2aa6a0
@ -226,6 +226,7 @@ static void capture_view_into (ClutterStage *stage,
|
||||
cairo_rectangle_int_t *rect,
|
||||
uint8_t *data,
|
||||
int stride);
|
||||
static void clutter_stage_update_view_perspective (ClutterStage *stage);
|
||||
|
||||
static void clutter_container_iface_init (ClutterContainerIface *iface);
|
||||
|
||||
@ -2354,29 +2355,6 @@ clutter_stage_init (ClutterStage *self)
|
||||
clutter_actor_set_background_color (CLUTTER_ACTOR (self),
|
||||
&default_stage_color);
|
||||
|
||||
priv->perspective.fovy = 60.0; /* 60 Degrees */
|
||||
priv->perspective.aspect = (float) geom.width / (float) geom.height;
|
||||
priv->perspective.z_near = 0.1;
|
||||
priv->perspective.z_far = 100.0;
|
||||
|
||||
cogl_matrix_init_identity (&priv->projection);
|
||||
cogl_matrix_perspective (&priv->projection,
|
||||
priv->perspective.fovy,
|
||||
priv->perspective.aspect,
|
||||
priv->perspective.z_near,
|
||||
priv->perspective.z_far);
|
||||
cogl_matrix_get_inverse (&priv->projection,
|
||||
&priv->inverse_projection);
|
||||
cogl_matrix_init_identity (&priv->view);
|
||||
cogl_matrix_view_2d_in_perspective (&priv->view,
|
||||
priv->perspective.fovy,
|
||||
priv->perspective.aspect,
|
||||
priv->perspective.z_near,
|
||||
50, /* distance to 2d plane */
|
||||
geom.width,
|
||||
geom.height);
|
||||
|
||||
|
||||
/* FIXME - remove for 2.0 */
|
||||
priv->fog.z_near = 1.0;
|
||||
priv->fog.z_far = 2.0;
|
||||
@ -2544,6 +2522,7 @@ clutter_stage_set_perspective (ClutterStage *stage,
|
||||
priv->has_custom_perspective = TRUE;
|
||||
|
||||
clutter_stage_set_perspective_internal (stage, perspective);
|
||||
clutter_stage_update_view_perspective (stage);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2670,6 +2649,7 @@ _clutter_stage_set_viewport (ClutterStage *stage,
|
||||
priv->viewport[2] = width;
|
||||
priv->viewport[3] = height;
|
||||
|
||||
clutter_stage_update_view_perspective (stage);
|
||||
_clutter_stage_dirty_viewport (stage);
|
||||
|
||||
queue_full_redraw (stage);
|
||||
@ -3506,6 +3486,50 @@ calculate_z_translation (float z_near)
|
||||
+ z_near;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_update_view_perspective (ClutterStage *stage)
|
||||
{
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
ClutterPerspective perspective;
|
||||
float z_2d;
|
||||
|
||||
perspective = priv->perspective;
|
||||
|
||||
/* Ideally we want to regenerate the perspective matrix whenever
|
||||
* the size changes but if the user has provided a custom matrix
|
||||
* then we don't want to override it */
|
||||
if (!priv->has_custom_perspective)
|
||||
{
|
||||
perspective.fovy = 60.0; /* 60 Degrees */
|
||||
perspective.z_near = 0.1;
|
||||
perspective.aspect = priv->viewport[2] / priv->viewport[3];
|
||||
z_2d = calculate_z_translation (perspective.z_near);
|
||||
|
||||
/* NB: z_2d is only enough room for 85% of the stage_height between
|
||||
* the stage and the z_near plane. For behind the stage plane we
|
||||
* want a more consistent gap of 10 times the stage_height before
|
||||
* hitting the far plane so we calculate that relative to the final
|
||||
* height of the stage plane at the z_2d_distance we got... */
|
||||
perspective.z_far = z_2d +
|
||||
tanf (_DEG_TO_RAD (perspective.fovy / 2.0f)) * z_2d * 20.0f;
|
||||
|
||||
clutter_stage_set_perspective_internal (stage, &perspective);
|
||||
}
|
||||
else
|
||||
{
|
||||
z_2d = calculate_z_translation (perspective.z_near);
|
||||
}
|
||||
|
||||
cogl_matrix_init_identity (&priv->view);
|
||||
cogl_matrix_view_2d_in_perspective (&priv->view,
|
||||
perspective.fovy,
|
||||
perspective.aspect,
|
||||
perspective.z_near,
|
||||
z_2d,
|
||||
priv->viewport[2],
|
||||
priv->viewport[3]);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_maybe_setup_viewport (ClutterStage *stage,
|
||||
ClutterStageView *view)
|
||||
@ -3516,7 +3540,6 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage,
|
||||
if (clutter_stage_view_is_dirty_viewport (view))
|
||||
{
|
||||
cairo_rectangle_int_t view_layout;
|
||||
ClutterPerspective perspective;
|
||||
float fb_scale;
|
||||
float viewport_offset_x;
|
||||
float viewport_offset_y;
|
||||
@ -3524,7 +3547,6 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage,
|
||||
float viewport_y;
|
||||
float viewport_width;
|
||||
float viewport_height;
|
||||
float z_2d;
|
||||
|
||||
CLUTTER_NOTE (PAINT,
|
||||
"Setting up the viewport { w:%f, h:%f }",
|
||||
@ -3544,38 +3566,6 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage,
|
||||
viewport_x, viewport_y,
|
||||
viewport_width, viewport_height);
|
||||
|
||||
perspective = priv->perspective;
|
||||
|
||||
/* Ideally we want to regenerate the perspective matrix whenever
|
||||
* the size changes but if the user has provided a custom matrix
|
||||
* then we don't want to override it */
|
||||
if (!priv->has_custom_perspective)
|
||||
{
|
||||
perspective.aspect = priv->viewport[2] / priv->viewport[3];
|
||||
z_2d = calculate_z_translation (perspective.z_near);
|
||||
|
||||
/* NB: z_2d is only enough room for 85% of the stage_height between
|
||||
* the stage and the z_near plane. For behind the stage plane we
|
||||
* want a more consistent gap of 10 times the stage_height before
|
||||
* hitting the far plane so we calculate that relative to the final
|
||||
* height of the stage plane at the z_2d_distance we got... */
|
||||
perspective.z_far = z_2d +
|
||||
tanf (_DEG_TO_RAD (perspective.fovy / 2.0f)) * z_2d * 20.0f;
|
||||
|
||||
clutter_stage_set_perspective_internal (stage, &perspective);
|
||||
}
|
||||
else
|
||||
z_2d = calculate_z_translation (perspective.z_near);
|
||||
|
||||
cogl_matrix_init_identity (&priv->view);
|
||||
cogl_matrix_view_2d_in_perspective (&priv->view,
|
||||
perspective.fovy,
|
||||
perspective.aspect,
|
||||
perspective.z_near,
|
||||
z_2d,
|
||||
priv->viewport[2],
|
||||
priv->viewport[3]);
|
||||
|
||||
clutter_stage_view_set_dirty_viewport (view, FALSE);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user