[mutter] backends/x11/nested: Emulate per CRTC drawing



commit 9787b1cfd5c646b1280f2335f81a80ebda94b721
Author: Jonas Ådahl <jadahl gmail com>
Date:   Tue Mar 21 14:38:35 2017 +0800

    backends/x11/nested: Emulate per CRTC drawing
    
    Make the nested backend emulate how the real backends actually draw,
    i.e. by drawing each CRTC separately. This makes it possible to test
    different configuration paths that can take place on different
    hardware, without having said hardware.
    
    For example, by setting MUTTER_DEBUG_TILED_DUMMY_MONITORS and
    MUTTER_DEBUG_NESTED_OFFSCREEN_TRANSFORM to "1", one can test a system
    with MST (tiled) monitors where the GPU doesn't support some transform.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=777732

 src/backends/x11/meta-stage-x11-nested.c           |  182 ++++++++++++++++++--
 src/backends/x11/nested/meta-renderer-x11-nested.c |    1 +
 2 files changed, 170 insertions(+), 13 deletions(-)
---
diff --git a/src/backends/x11/meta-stage-x11-nested.c b/src/backends/x11/meta-stage-x11-nested.c
index b2732c3..cf3b920 100644
--- a/src/backends/x11/meta-stage-x11-nested.c
+++ b/src/backends/x11/meta-stage-x11-nested.c
@@ -27,6 +27,8 @@
 #include "backends/x11/meta-stage-x11-nested.h"
 
 #include "backends/meta-backend-private.h"
+#include "backends/meta-logical-monitor.h"
+#include "backends/meta-monitor.h"
 #include "backends/meta-renderer.h"
 #include "backends/x11/nested/meta-renderer-x11-nested.h"
 #include "clutter/clutter-mutter.h"
@@ -88,6 +90,149 @@ meta_stage_x11_nested_get_views (ClutterStageWindow *stage_window)
   return meta_renderer_get_views (renderer);
 }
 
+typedef struct
+{
+  MetaStageX11Nested *stage_nested;
+  CoglTexture *texture;
+  ClutterStageView *view;
+  MetaLogicalMonitor *logical_monitor;
+} DrawCrtcData;
+
+static gboolean
+draw_crtc (MetaMonitor         *monitor,
+           MetaMonitorMode     *monitor_mode,
+           MetaMonitorCrtcMode *monitor_crtc_mode,
+           gpointer             user_data,
+           GError             **error)
+{
+  DrawCrtcData *data = user_data;
+  ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (data->stage_nested);
+  CoglFramebuffer *onscreen = COGL_FRAMEBUFFER (stage_x11->onscreen);
+  CoglTexture *texture = data->texture;
+  MetaLogicalMonitor *logical_monitor = data->logical_monitor;
+  MetaOutput *output = monitor_crtc_mode->output;
+  MetaCrtc *crtc = output->crtc;
+  MetaRendererView *renderer_view = META_RENDERER_VIEW (data->view);
+  MetaMonitorTransform view_transform;
+  MetaMonitorTransform layout_transform = META_MONITOR_TRANSFORM_NORMAL;
+  cairo_rectangle_int_t view_layout;
+  CoglMatrix projection_matrix;
+  CoglMatrix transform;
+  float texture_width, texture_height;
+  float sample_x, sample_y, sample_width, sample_height;
+  int viewport_x, viewport_y;
+  int viewport_width, viewport_height;
+  float s_1, t_1, s_2, t_2;
+
+  texture_width = cogl_texture_get_width (texture);
+  texture_height = cogl_texture_get_height (texture);
+
+  clutter_stage_view_get_layout (data->view, &view_layout);
+  sample_x = crtc->rect.x - view_layout.x;
+  sample_y = crtc->rect.y - view_layout.y;
+  sample_width = crtc->rect.width;
+  sample_height = crtc->rect.height;
+
+  clutter_stage_view_get_offscreen_transformation_matrix (data->view,
+                                                          &transform);
+
+  cogl_framebuffer_push_matrix (onscreen);
+  cogl_matrix_init_identity (&projection_matrix);
+  cogl_matrix_translate (&projection_matrix, -1, 1, 0);
+  cogl_matrix_scale (&projection_matrix, 2, -2, 0);
+
+  cogl_matrix_multiply (&projection_matrix, &projection_matrix, &transform);
+  cogl_framebuffer_set_projection_matrix (onscreen, &projection_matrix);
+
+  s_1 = sample_x / texture_width;
+  t_1 = sample_y / texture_height;
+  s_2 = (sample_x + sample_width) / texture_width;
+  t_2 = (sample_y + sample_height) / texture_height;
+
+  view_transform = meta_renderer_view_get_transform (renderer_view);
+
+  if (view_transform == logical_monitor->transform)
+    {
+      switch (view_transform)
+        {
+        case META_MONITOR_TRANSFORM_NORMAL:
+        case META_MONITOR_TRANSFORM_FLIPPED:
+          layout_transform = META_MONITOR_TRANSFORM_NORMAL;
+          break;
+        case META_MONITOR_TRANSFORM_270:
+        case META_MONITOR_TRANSFORM_FLIPPED_270:
+          layout_transform = META_MONITOR_TRANSFORM_90;
+          break;
+        case META_MONITOR_TRANSFORM_180:
+        case META_MONITOR_TRANSFORM_FLIPPED_180:
+          layout_transform = META_MONITOR_TRANSFORM_180;
+          break;
+        case META_MONITOR_TRANSFORM_90:
+        case META_MONITOR_TRANSFORM_FLIPPED_90:
+          layout_transform = META_MONITOR_TRANSFORM_270;
+          break;
+        }
+    }
+  else
+    {
+      layout_transform = logical_monitor->transform;
+    }
+
+  meta_monitor_calculate_crtc_pos (monitor, monitor_mode, output,
+                                   layout_transform,
+                                   &viewport_x,
+                                   &viewport_y);
+  viewport_x += logical_monitor->rect.x;
+  viewport_y += logical_monitor->rect.y;
+  if (meta_monitor_transform_is_rotated (logical_monitor->transform))
+    {
+      viewport_width = monitor_crtc_mode->crtc_mode->height;
+      viewport_height = monitor_crtc_mode->crtc_mode->width;
+    }
+  else
+    {
+      viewport_width = monitor_crtc_mode->crtc_mode->width;
+      viewport_height = monitor_crtc_mode->crtc_mode->height;
+    }
+  cogl_framebuffer_set_viewport (onscreen,
+                                 viewport_x, viewport_y,
+                                 viewport_width, viewport_height);
+
+  cogl_framebuffer_draw_textured_rectangle (onscreen,
+                                            data->stage_nested->pipeline,
+                                            0, 0, 1, 1,
+                                            s_1, t_1, s_2, t_2);
+
+  cogl_framebuffer_pop_matrix (onscreen);
+  return TRUE;
+}
+
+static void
+draw_logical_monitor (MetaStageX11Nested    *stage_nested,
+                      MetaLogicalMonitor    *logical_monitor,
+                      CoglTexture           *texture,
+                      ClutterStageView      *view,
+                      cairo_rectangle_int_t *view_layout)
+{
+  MetaMonitor *monitor;
+  MetaMonitorMode *current_mode;
+
+  cogl_pipeline_set_layer_wrap_mode (stage_nested->pipeline, 0,
+                                     COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+
+  monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
+  current_mode = meta_monitor_get_current_mode (monitor);
+  meta_monitor_mode_foreach_crtc (monitor, current_mode,
+                                  draw_crtc,
+                                  &(DrawCrtcData) {
+                                    .stage_nested = stage_nested,
+                                    .texture = texture,
+                                    .view = view,
+                                    .logical_monitor = logical_monitor
+                                  },
+                                  NULL);
+}
+
 static void
 meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window)
 {
@@ -109,29 +254,40 @@ meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window)
   for (l = meta_renderer_get_views (renderer); l; l = l->next)
     {
       ClutterStageView *view = l->data;
+      MetaRendererView *renderer_view = META_RENDERER_VIEW (view);
+      MetaLogicalMonitor *logical_monitor;
       cairo_rectangle_int_t view_layout;
       CoglFramebuffer *framebuffer;
       CoglTexture *texture;
-      CoglMatrix matrix;
 
       clutter_stage_view_get_layout (view, &view_layout);
 
       framebuffer = clutter_stage_view_get_onscreen (view);
       texture = cogl_offscreen_get_texture (COGL_OFFSCREEN (framebuffer));
 
-      clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
-      cogl_matrix_get_inverse (&matrix, &matrix);
-      cogl_pipeline_set_layer_matrix (stage_nested->pipeline, 0, &matrix);
-
-      cogl_framebuffer_set_viewport (onscreen,
-                                     view_layout.x,
-                                     view_layout.y,
-                                     view_layout.width,
-                                     view_layout.height);
       cogl_pipeline_set_layer_texture (stage_nested->pipeline, 0, texture);
-      cogl_framebuffer_draw_rectangle (onscreen,
-                                       stage_nested->pipeline,
-                                       -1, 1, 1, -1);
+
+      logical_monitor = meta_renderer_view_get_logical_monitor (renderer_view);
+      if (logical_monitor)
+        {
+          draw_logical_monitor (stage_nested, logical_monitor, texture, view, &view_layout);
+        }
+      else
+        {
+          MetaMonitorManager *monitor_manager =
+            meta_backend_get_monitor_manager (backend);
+          GList *logical_monitors;
+          GList *k;
+
+          logical_monitors =
+            meta_monitor_manager_get_logical_monitors (monitor_manager);
+          for (k = logical_monitors; k; k = k->next)
+            {
+              logical_monitor = k->data;
+
+              draw_logical_monitor (stage_nested, logical_monitor, texture, view, &view_layout);
+            }
+        }
     }
 
   cogl_onscreen_swap_buffers (stage_x11->onscreen);
diff --git a/src/backends/x11/nested/meta-renderer-x11-nested.c 
b/src/backends/x11/nested/meta-renderer-x11-nested.c
index 8162062..8843252 100644
--- a/src/backends/x11/nested/meta-renderer-x11-nested.c
+++ b/src/backends/x11/nested/meta-renderer-x11-nested.c
@@ -211,6 +211,7 @@ meta_renderer_x11_nested_create_view (MetaRenderer       *renderer,
                        "offscreen", COGL_FRAMEBUFFER (offscreen),
                        "transform", view_transform,
                        "scale", view_scale,
+                       "logical-monitor", logical_monitor,
                        NULL);
 }
 


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