[mutter] clutter: Add ability to scale stage views



commit 63450d69d38faee9aa2b6e7e419ee10a9d6d6d4b
Author: Jonas Ådahl <jadahl gmail com>
Date:   Fri Feb 24 17:38:47 2017 +0800

    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           |   64 ++++++++++++++++-------------
 clutter/clutter/cogl/clutter-stage-cogl.c |   30 +++++++------
 4 files changed, 80 insertions(+), 43 deletions(-)
---
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
index e399278..a584b81 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 3eb8da4..a358d4d 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 21968b9..a43f3b7 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);
-
-  read_x = dirty_x * window_scale;
-  read_y = dirty_y * window_scale;
-
-  CLUTTER_NOTE (PICK, "Performing pick at %i,%i on view %dx%d+%d+%d",
+                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 * fb_scale;
+  read_y = dirty_y * fb_scale;
+
+  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 2c525af..1d626f6 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;
         }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]