From 63450d69d38faee9aa2b6e7e419ee10a9d6d6d4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 24 Feb 2017 17:38:47 +0800 Subject: [PATCH] clutter: Add ability to scale stage views This commit adds the ability to set a scale on a scale view. This will cause the content in the stage view to be painted with the given scale, while still keeping the configured layout on the stage. In effect, for a stage view with scale 'n', this means the framebuffer of a given stage will 'n' times larger, keeping the same size on the stage. https://bugzilla.gnome.org/show_bug.cgi?id=777732 --- clutter/clutter/clutter-stage-view.c | 26 ++++++++++ clutter/clutter/clutter-stage-view.h | 3 ++ clutter/clutter/clutter-stage.c | 60 +++++++++++++---------- clutter/clutter/cogl/clutter-stage-cogl.c | 30 ++++++------ 4 files changed, 78 insertions(+), 41 deletions(-) diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c index e39927884..a584b81a5 100644 --- a/clutter/clutter/clutter-stage-view.c +++ b/clutter/clutter/clutter-stage-view.c @@ -28,6 +28,7 @@ enum PROP_LAYOUT, PROP_FRAMEBUFFER, PROP_OFFSCREEN, + PROP_SCALE, PROP_LAST }; @@ -37,6 +38,7 @@ static GParamSpec *obj_props[PROP_LAST]; typedef struct _ClutterStageViewPrivate { cairo_rectangle_int_t layout; + int scale; CoglFramebuffer *framebuffer; CoglOffscreen *offscreen; @@ -141,6 +143,15 @@ clutter_stage_view_blit_offscreen (ClutterStageView *view, cogl_framebuffer_pop_matrix (priv->framebuffer); } +int +clutter_stage_view_get_scale (ClutterStageView *view) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + return priv->scale; +} + gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view) { @@ -229,6 +240,9 @@ clutter_stage_view_get_property (GObject *object, case PROP_OFFSCREEN: g_value_set_boxed (value, priv->offscreen); break; + case PROP_SCALE: + g_value_set_int (value, priv->scale); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -257,6 +271,9 @@ clutter_stage_view_set_property (GObject *object, case PROP_OFFSCREEN: priv->offscreen = g_value_dup_boxed (value); break; + case PROP_SCALE: + priv->scale = g_value_get_int (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -284,6 +301,7 @@ clutter_stage_view_init (ClutterStageView *view) priv->dirty_viewport = TRUE; priv->dirty_projection = TRUE; + priv->scale = 1; } static void @@ -323,5 +341,13 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_props[PROP_SCALE] = + g_param_spec_int ("scale", + "View scale", + "The view scale", + 1, G_MAXINT, 1, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, PROP_LAST, obj_props); } diff --git a/clutter/clutter/clutter-stage-view.h b/clutter/clutter/clutter-stage-view.h index 3eb8da452..a358d4dd9 100644 --- a/clutter/clutter/clutter-stage-view.h +++ b/clutter/clutter/clutter-stage-view.h @@ -60,6 +60,9 @@ void clutter_stage_view_transform_to_onscreen (ClutterStageView *vie void clutter_stage_view_blit_offscreen (ClutterStageView *view, const cairo_rectangle_int_t *clip); +CLUTTER_AVAILABLE_IN_MUTTER +int clutter_stage_view_get_scale (ClutterStageView *view); + gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view); void clutter_stage_view_set_dirty_viewport (ClutterStageView *view, diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index 21968b973..a43f3b740 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -1380,6 +1380,8 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage, gint read_y; int window_scale; float fb_width, fb_height; + int view_scale; + int fb_scale; int viewport_offset_x; int viewport_offset_y; @@ -1387,10 +1389,12 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage, context = _clutter_context_get_default (); window_scale = _clutter_stage_window_get_scale_factor (priv->impl); + view_scale = clutter_stage_view_get_scale (view); + fb_scale = window_scale * view_scale; clutter_stage_view_get_layout (view, &view_layout); - fb_width = view_layout.width; - fb_height = view_layout.height; + fb_width = view_layout.width * view_scale; + fb_height = view_layout.height * view_scale; cogl_push_framebuffer (fb); /* needed for when a context switch happens */ @@ -1400,38 +1404,38 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage, * picking to not work at all, so setting it the whole framebuffer content * for now. */ cogl_framebuffer_push_scissor_clip (fb, 0, 0, - view_layout.width, - view_layout.height); + view_layout.width * view_scale, + view_layout.height * view_scale); _clutter_stage_window_get_dirty_pixel (priv->impl, view, &dirty_x, &dirty_y); if (G_LIKELY (!(clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS))) { CLUTTER_NOTE (PICK, "Pushing pick scissor clip x: %d, y: %d, 1x1", - dirty_x * window_scale, - dirty_y * window_scale); - cogl_framebuffer_push_scissor_clip (fb, dirty_x * window_scale, dirty_y * window_scale, 1, 1); + dirty_x * fb_scale, + dirty_y * fb_scale); + cogl_framebuffer_push_scissor_clip (fb, dirty_x * fb_scale, dirty_y * fb_scale, 1, 1); } - viewport_offset_x = x * window_scale - dirty_x * window_scale; - viewport_offset_y = y * window_scale - dirty_y * window_scale; + viewport_offset_x = x * fb_scale - dirty_x * fb_scale; + viewport_offset_y = y * fb_scale - dirty_y * fb_scale; CLUTTER_NOTE (PICK, "Setting viewport to %f, %f, %f, %f", - priv->viewport[0] * window_scale - viewport_offset_x, - priv->viewport[1] * window_scale - viewport_offset_y, - priv->viewport[2] * window_scale, - priv->viewport[3] * window_scale); - cogl_set_viewport (priv->viewport[0] * window_scale - viewport_offset_x, - priv->viewport[1] * window_scale - viewport_offset_y, - priv->viewport[2] * window_scale, - priv->viewport[3] * window_scale); + priv->viewport[0] * fb_scale - viewport_offset_x, + priv->viewport[1] * fb_scale - viewport_offset_y, + priv->viewport[2] * fb_scale, + priv->viewport[3] * fb_scale); + cogl_set_viewport (priv->viewport[0] * fb_scale - viewport_offset_x, + priv->viewport[1] * fb_scale - viewport_offset_y, + priv->viewport[2] * fb_scale, + priv->viewport[3] * fb_scale); - read_x = dirty_x * window_scale; - read_y = dirty_y * window_scale; + read_x = dirty_x * fb_scale; + read_y = dirty_y * fb_scale; - CLUTTER_NOTE (PICK, "Performing pick at %i,%i on view %dx%d+%d+%d", + CLUTTER_NOTE (PICK, "Performing pick at %i,%i on view %dx%d+%d+%d s: %d", x, y, view_layout.width, view_layout.height, - view_layout.x, view_layout.y); + view_layout.x, view_layout.y, view_scale); cogl_color_init_from_4ub (&stage_pick_id, 255, 255, 255, 255); cogl_clear (&stage_pick_id, COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH); @@ -3569,6 +3573,7 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage, cairo_rectangle_int_t view_layout; ClutterPerspective perspective; int window_scale; + int fb_scale; int viewport_offset_x; int viewport_offset_y; float z_2d; @@ -3579,14 +3584,15 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage, priv->viewport[3]); window_scale = _clutter_stage_window_get_scale_factor (priv->impl); + fb_scale = window_scale * clutter_stage_view_get_scale (view); clutter_stage_view_get_layout (view, &view_layout); - viewport_offset_x = view_layout.x * window_scale; - viewport_offset_y = view_layout.y * window_scale; - cogl_set_viewport (priv->viewport[0] * window_scale - viewport_offset_x, - priv->viewport[1] * window_scale - viewport_offset_y, - priv->viewport[2] * window_scale, - priv->viewport[3] * window_scale); + viewport_offset_x = view_layout.x * fb_scale; + viewport_offset_y = view_layout.y * fb_scale; + cogl_set_viewport (priv->viewport[0] * fb_scale - viewport_offset_x, + priv->viewport[1] * fb_scale - viewport_offset_y, + priv->viewport[2] * fb_scale, + priv->viewport[3] * fb_scale); perspective = priv->perspective; diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c index 2c525aff2..1d626f610 100644 --- a/clutter/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/clutter/cogl/clutter-stage-cogl.c @@ -504,6 +504,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, cairo_rectangle_int_t clip_region; gboolean clip_region_empty; int window_scale; + int fb_scale; wrapper = CLUTTER_ACTOR (stage_cogl->wrapper); @@ -558,6 +559,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, clip_region_empty = may_use_clipped_redraw && clip_region.width == 0; window_scale = _clutter_stage_window_get_scale_factor (stage_window); + fb_scale = window_scale * clutter_stage_view_get_scale (view); swap_with_damage = FALSE; if (has_buffer_age) @@ -628,13 +630,13 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, stage_cogl->using_clipped_redraw = TRUE; - scissor_x = (clip_region.x - view_rect.x) * window_scale; - scissor_y = (clip_region.y - view_rect.y) * window_scale; + scissor_x = (clip_region.x - view_rect.x) * fb_scale; + scissor_y = (clip_region.y - view_rect.y) * fb_scale; cogl_framebuffer_push_scissor_clip (fb, scissor_x, scissor_y, - clip_region.width * window_scale, - clip_region.height * window_scale); + clip_region.width * fb_scale, + clip_region.height * fb_scale); paint_stage (stage_cogl, view, &clip_region); cogl_framebuffer_pop_clip (fb); @@ -653,13 +655,13 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, int scissor_x; int scissor_y; - scissor_x = (clip_region.x - view_rect.x) * window_scale;; - scissor_y = (clip_region.y - view_rect.y) * window_scale; + scissor_x = (clip_region.x - view_rect.x) * fb_scale;; + scissor_y = (clip_region.y - view_rect.y) * fb_scale; cogl_framebuffer_push_scissor_clip (fb, scissor_x, scissor_y, - clip_region.width * window_scale, - clip_region.height * window_scale); + clip_region.width * fb_scale, + clip_region.height * fb_scale); paint_stage (stage_cogl, view, &clip_region); cogl_framebuffer_pop_clip (fb); } @@ -724,10 +726,10 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, else if (use_clipped_redraw) { swap_region = (cairo_rectangle_int_t) { - .x = (clip_region.x - view_rect.x) * window_scale, - .y = (clip_region.y - view_rect.y) * window_scale, - .width = clip_region.width * window_scale, - .height = clip_region.height * window_scale, + .x = (clip_region.x - view_rect.x) * fb_scale, + .y = (clip_region.y - view_rect.y) * fb_scale, + .width = clip_region.width * fb_scale, + .height = clip_region.height * fb_scale, }; g_assert (swap_region.width > 0); do_swap_buffer = TRUE; @@ -737,8 +739,8 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, swap_region = (cairo_rectangle_int_t) { .x = 0, .y = 0, - .width = view_rect.width * window_scale, - .height = view_rect.height * window_scale, + .width = view_rect.width * fb_scale, + .height = view_rect.height * fb_scale, }; do_swap_buffer = TRUE; }