[clutter/clutter-1.16] stage: Adjust drawing to include the window scaling factor
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter/clutter-1.16] stage: Adjust drawing to include the window scaling factor
- Date: Thu, 19 Sep 2013 22:11:35 +0000 (UTC)
commit 0d0cb13c8d54499d6a4a74e7cfe0db3190d04501
Author: Emmanuele Bassi <ebassi gnome org>
Date: Wed Aug 14 11:19:22 2013 +0100
stage: Adjust drawing to include the window scaling factor
In order to transparently support high DPI density displays, we must
maintain all coordinates and sizes exactly as they are now — but draw
them on a surface that is scaled up by a certain factor. In order to
do that we have to change the viewport and initial transformation
matrix so that they are scaled up by the same factor.
https://bugzilla.gnome.org/show_bug.cgi?id=705915
clutter/clutter-stage-private.h | 3 +
clutter/clutter-stage.c | 122 +++++++++++++++++++++++++++++----------
2 files changed, 94 insertions(+), 31 deletions(-)
---
diff --git a/clutter/clutter-stage-private.h b/clutter/clutter-stage-private.h
index 9ccba3f..890fcdc 100644
--- a/clutter/clutter-stage-private.h
+++ b/clutter/clutter-stage-private.h
@@ -119,6 +119,9 @@ gboolean _clutter_stage_update_state (ClutterStage *stag
ClutterStageState unset_state,
ClutterStageState set_state);
+void _clutter_stage_set_scale_factor (ClutterStage *stage,
+ int factor);
+
G_END_DECLS
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */
diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c
index 984c1d7..a7eba20 100644
--- a/clutter/clutter-stage.c
+++ b/clutter/clutter-stage.c
@@ -371,6 +371,7 @@ clutter_stage_allocate (ClutterActor *self,
float new_width, new_height;
float width, height;
cairo_rectangle_int_t window_size;
+ int scale_factor;
if (priv->impl == NULL)
return;
@@ -471,6 +472,12 @@ clutter_stage_allocate (ClutterActor *self,
* allocation.
*/
_clutter_stage_window_get_geometry (priv->impl, &window_size);
+
+ scale_factor = _clutter_stage_window_get_scale_factor (priv->impl);
+
+ window_size.width *= scale_factor;
+ window_size.height *= scale_factor;
+
cogl_onscreen_clutter_backend_set_size (window_size.width,
window_size.height);
@@ -481,10 +488,13 @@ clutter_stage_allocate (ClutterActor *self,
if (CLUTTER_NEARBYINT (old_width) != CLUTTER_NEARBYINT (new_width) ||
CLUTTER_NEARBYINT (old_height) != CLUTTER_NEARBYINT (new_height))
{
+ int real_width = CLUTTER_NEARBYINT (new_width);
+ int real_height = CLUTTER_NEARBYINT (new_height);
+
_clutter_stage_set_viewport (CLUTTER_STAGE (self),
0, 0,
- CLUTTER_NEARBYINT (new_width),
- CLUTTER_NEARBYINT (new_height));
+ real_width,
+ real_height);
/* Note: we don't assume that set_viewport will queue a full redraw
* since it may bail-out early if something preemptively set the
@@ -629,21 +639,29 @@ _clutter_stage_do_paint (ClutterStage *stage,
{
ClutterStagePrivate *priv = stage->priv;
float clip_poly[8];
+ float viewport[4];
cairo_rectangle_int_t geom;
+ int window_scale;
if (priv->impl == NULL)
return;
_clutter_stage_window_get_geometry (priv->impl, &geom);
+ window_scale = _clutter_stage_window_get_scale_factor (priv->impl);
+
+ viewport[0] = priv->viewport[0] * window_scale;
+ viewport[1] = priv->viewport[1] * window_scale;
+ viewport[2] = priv->viewport[2] * window_scale;
+ viewport[3] = priv->viewport[3] * window_scale;
if (clip)
{
- clip_poly[0] = MAX (clip->x, 0);
- clip_poly[1] = MAX (clip->y, 0);
- clip_poly[2] = MIN (clip->x + clip->width, geom.width);
+ clip_poly[0] = MAX (clip->x * window_scale, 0);
+ clip_poly[1] = MAX (clip->y * window_scale, 0);
+ clip_poly[2] = MIN ((clip->x + clip->width) * window_scale, geom.width * window_scale);
clip_poly[3] = clip_poly[1];
clip_poly[4] = clip_poly[2];
- clip_poly[5] = MIN (clip->y + clip->height, geom.height);
+ clip_poly[5] = MIN ((clip->y + clip->height) * window_scale, geom.height * window_scale);
clip_poly[6] = clip_poly[0];
clip_poly[7] = clip_poly[5];
}
@@ -651,12 +669,12 @@ _clutter_stage_do_paint (ClutterStage *stage,
{
clip_poly[0] = 0;
clip_poly[1] = 0;
- clip_poly[2] = geom.width;
+ clip_poly[2] = geom.width * window_scale;
clip_poly[3] = 0;
- clip_poly[4] = geom.width;
- clip_poly[5] = geom.height;
+ clip_poly[4] = geom.width * window_scale;
+ clip_poly[5] = geom.height * window_scale;
clip_poly[6] = 0;
- clip_poly[7] = geom.height;
+ clip_poly[7] = geom.height * window_scale;
}
CLUTTER_NOTE (CLIPPING, "Setting stage clip too: "
@@ -667,7 +685,7 @@ _clutter_stage_do_paint (ClutterStage *stage,
_cogl_util_get_eye_planes_for_screen_poly (clip_poly,
4,
- priv->viewport,
+ viewport,
&priv->projection,
&priv->inverse_projection,
priv->current_clip_planes);
@@ -1437,6 +1455,7 @@ _clutter_stage_do_pick (ClutterStage *stage,
gboolean is_clipped;
gint read_x;
gint read_y;
+ int window_scale;
CLUTTER_STATIC_COUNTER (do_pick_counter,
"_clutter_stage_do_pick counter",
@@ -1486,6 +1505,7 @@ _clutter_stage_do_pick (ClutterStage *stage,
context = _clutter_context_get_default ();
clutter_stage_ensure_current (stage);
+ window_scale = _clutter_stage_window_get_scale_factor (priv->impl);
/* It's possible that we currently have a static scene and have renderered a
* full, unclipped pick buffer. If so we can simply continue to read from
@@ -1493,7 +1513,9 @@ _clutter_stage_do_pick (ClutterStage *stage,
if (_clutter_stage_get_pick_buffer_valid (stage, mode))
{
CLUTTER_TIMER_START (_clutter_uprof_context, pick_read);
- cogl_read_pixels (x, y, 1, 1,
+ cogl_read_pixels (x * window_scale,
+ y * window_scale,
+ 1, 1,
COGL_READ_PIXELS_COLOR_BUFFER,
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
pixel);
@@ -1523,21 +1545,21 @@ _clutter_stage_do_pick (ClutterStage *stage,
_clutter_stage_window_get_dirty_pixel (priv->impl, &dirty_x, &dirty_y);
if (G_LIKELY (!(clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS)))
- cogl_clip_push_window_rectangle (dirty_x, dirty_y, 1, 1);
+ cogl_clip_push_window_rectangle (dirty_x * window_scale, dirty_y * window_scale, 1, 1);
- cogl_set_viewport (priv->viewport[0] - x + dirty_x,
- priv->viewport[1] - y + dirty_y,
- priv->viewport[2],
- priv->viewport[3]);
+ cogl_set_viewport (priv->viewport[0] * window_scale - x * window_scale + dirty_x * window_scale,
+ priv->viewport[1] * window_scale - y * window_scale + dirty_y * window_scale,
+ priv->viewport[2] * window_scale,
+ priv->viewport[3] * window_scale);
- read_x = dirty_x;
- read_y = dirty_y;
+ read_x = dirty_x * window_scale;
+ read_y = dirty_y * window_scale;
is_clipped = TRUE;
}
else
{
- read_x = x;
- read_y = y;
+ read_x = x * window_scale;
+ read_y = y * window_scale;
is_clipped = FALSE;
}
@@ -2259,6 +2281,7 @@ clutter_stage_init (ClutterStage *self)
ClutterStagePrivate *priv;
ClutterStageWindow *impl;
ClutterBackend *backend;
+ int window_scale = 1;
GError *error;
/* a stage is a top-level object */
@@ -2276,6 +2299,7 @@ clutter_stage_init (ClutterStage *self)
{
_clutter_stage_set_window (self, impl);
_clutter_stage_window_get_geometry (priv->impl, &geom);
+ window_scale = _clutter_stage_window_get_scale_factor (priv->impl);
}
else
{
@@ -2329,8 +2353,8 @@ clutter_stage_init (ClutterStage *self)
priv->perspective.aspect,
priv->perspective.z_near,
50, /* distance to 2d plane */
- geom.width,
- geom.height);
+ geom.width * window_scale,
+ geom.height * window_scale);
/* FIXME - remove for 2.0 */
@@ -2348,7 +2372,10 @@ clutter_stage_init (ClutterStage *self)
g_signal_connect (self, "notify::min-height",
G_CALLBACK (clutter_stage_notify_min_size), NULL);
- _clutter_stage_set_viewport (self, 0, 0, geom.width, geom.height);
+ _clutter_stage_set_viewport (self,
+ 0, 0,
+ geom.width,
+ geom.height);
_clutter_stage_set_pick_buffer_valid (self, FALSE, CLUTTER_PICK_ALL);
priv->picks_per_frame = 0;
@@ -3403,6 +3430,16 @@ clutter_stage_ensure_viewport (ClutterStage *stage)
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
}
+static void
+clutter_stage_apply_scale (ClutterStage *stage)
+{
+ int factor;
+
+ factor = _clutter_stage_window_get_scale_factor (stage->priv->impl);
+ if (factor != 1)
+ cogl_matrix_scale (&stage->priv->view, factor, factor, 1.f);
+}
+
# define _DEG_TO_RAD(d) ((d) * ((float) G_PI / 180.0f))
/* This calculates a distance into the view frustum to position the
@@ -3547,16 +3584,20 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage)
if (priv->dirty_viewport)
{
ClutterPerspective perspective;
+ int window_scale;
float z_2d;
CLUTTER_NOTE (PAINT,
"Setting up the viewport { w:%f, h:%f }",
- priv->viewport[2], priv->viewport[3]);
+ priv->viewport[2],
+ priv->viewport[3]);
- cogl_set_viewport (priv->viewport[0],
- priv->viewport[1],
- priv->viewport[2],
- priv->viewport[3]);
+ window_scale = _clutter_stage_window_get_scale_factor (priv->impl);
+
+ cogl_set_viewport (priv->viewport[0] * window_scale,
+ priv->viewport[1] * window_scale,
+ priv->viewport[2] * window_scale,
+ priv->viewport[3] * window_scale);
perspective = priv->perspective;
@@ -3587,8 +3628,10 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage)
perspective.aspect,
perspective.z_near,
z_2d,
- priv->viewport[2],
- priv->viewport[3]);
+ priv->viewport[2] * window_scale,
+ priv->viewport[3] * window_scale);
+
+ clutter_stage_apply_scale (stage);
priv->dirty_viewport = FALSE;
}
@@ -4652,3 +4695,20 @@ clutter_stage_invoke_paint_callback (ClutterStage *stage)
if (stage->priv->paint_callback != NULL)
stage->priv->paint_callback (stage, stage->priv->paint_data);
}
+
+void
+_clutter_stage_set_scale_factor (ClutterStage *stage,
+ int factor)
+{
+ ClutterStagePrivate *priv = stage->priv;
+
+ if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
+ return;
+
+ if (priv->impl == NULL)
+ return;
+
+ _clutter_stage_window_set_scale_factor (priv->impl, factor);
+
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]