Blame SOURCES/0015-xwayland-add-support-for-multiple-outputs.patch

70130e
From b4354c5a6d8587c079f52e3363b339558f5832a7 Mon Sep 17 00:00:00 2001
70130e
From: Giovanni Campagna <gcampagn@redhat.com>
70130e
Date: Thu, 22 Aug 2013 16:23:48 +0200
70130e
Subject: [PATCH 15/39] xwayland: add support for multiple outputs
70130e
70130e
Drop xf86InitialConfiguration, which just gets in the way
70130e
of the compositor doing its own output arrangement, and transform
70130e
wayland events into the appropriate low-level xf86 calls to
70130e
keep the screen size updated.
70130e
70130e
Kristian: after the rebase it was crashing for me too, had to fix
70130e
the patch a bit. This one should work, and also gives sensible (though
70130e
not perfect) results for xrandr clients.
70130e
Tested with weston/x11 and mutter-wayland/kms.
70130e
---
70130e
 hw/xfree86/xwayland/xwayland-output.c  | 112 ++++++++++++++++++++++++++++++---
70130e
 hw/xfree86/xwayland/xwayland-private.h |   2 +
70130e
 2 files changed, 105 insertions(+), 9 deletions(-)
70130e
70130e
diff --git a/hw/xfree86/xwayland/xwayland-output.c b/hw/xfree86/xwayland/xwayland-output.c
70130e
index 46238f4..66c7d48 100644
70130e
--- a/hw/xfree86/xwayland/xwayland-output.c
70130e
+++ b/hw/xfree86/xwayland/xwayland-output.c
70130e
@@ -36,6 +36,7 @@
70130e
 #include <cursorstr.h>
70130e
 #include <xf86Crtc.h>
70130e
 #include <mipointrst.h>
70130e
+#include <randrstr.h>
70130e
 
70130e
 #include "xwayland.h"
70130e
 #include "xwayland-private.h"
70130e
@@ -182,6 +183,10 @@ xwl_output_create(struct xwl_screen *xwl_screen)
70130e
     struct xwl_output *xwl_output;
70130e
     xf86OutputPtr xf86output;
70130e
     xf86CrtcPtr xf86crtc;
70130e
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(xwl_screen->scrninfo);
70130e
+    int crtcId, outputId;
70130e
+    static int nameId;
70130e
+    char *name;
70130e
 
70130e
     xwl_output = calloc(sizeof *xwl_output, 1);
70130e
     if (xwl_output == NULL) {
70130e
@@ -189,19 +194,41 @@ xwl_output_create(struct xwl_screen *xwl_screen)
70130e
 	return NULL;
70130e
     }
70130e
 
70130e
+    nameId++;
70130e
+    if (asprintf(&name, "XWAYLAND-%d", nameId) < 0) {
70130e
+        ErrorF("create_output ENOMEM");
70130e
+        free(xwl_output);
70130e
+        return NULL;
70130e
+    }
70130e
+
70130e
     xwl_output->xwl_screen = xwl_screen;
70130e
 
70130e
+    xf86crtc = xf86CrtcCreate(xwl_screen->scrninfo, &crtc_funcs);
70130e
+    xf86crtc->enabled = TRUE;
70130e
+    xf86crtc->driver_private = xwl_output;
70130e
+
70130e
+    for (crtcId = 0; crtcId < xf86_config->num_crtc; crtcId++) {
70130e
+        if (xf86_config->crtc[crtcId] == xf86crtc)
70130e
+            break;
70130e
+    }
70130e
+
70130e
     xf86output = xf86OutputCreate(xwl_screen->scrninfo,
70130e
-				  &output_funcs, "XWAYLAND-1");
70130e
+				  &output_funcs, name);
70130e
     xf86output->driver_private = xwl_output;
70130e
-    xf86output->possible_crtcs = 1;
70130e
-    xf86output->possible_clones = 1;
70130e
+    xf86output->possible_crtcs = 1 << crtcId;
70130e
 
70130e
-    xf86crtc = xf86CrtcCreate(xwl_screen->scrninfo, &crtc_funcs);
70130e
-    xf86crtc->driver_private = xwl_output;
70130e
+    for (outputId = 0; outputId < xf86_config->num_output; outputId++) {
70130e
+        if (xf86_config->output[outputId] == xf86output)
70130e
+            break;
70130e
+    }
70130e
+
70130e
+    xf86output->possible_clones = 1 << outputId;
70130e
 
70130e
     xwl_output->xf86output = xf86output;
70130e
     xwl_output->xf86crtc = xf86crtc;
70130e
+    xwl_output->xf86output->crtc = xf86crtc;
70130e
+
70130e
+    free(name);
70130e
 
70130e
     return xwl_output;
70130e
 }
70130e
@@ -219,6 +246,32 @@ static const xf86CrtcConfigFuncsRec config_funcs = {
70130e
     resize
70130e
 };
70130e
 
70130e
+static Rotation
70130e
+wl_transform_to_xrandr (enum wl_output_transform transform)
70130e
+{
70130e
+  switch (transform)
70130e
+    {
70130e
+    case WL_OUTPUT_TRANSFORM_NORMAL:
70130e
+      return RR_Rotate_0;
70130e
+    case WL_OUTPUT_TRANSFORM_90:
70130e
+      return RR_Rotate_90;
70130e
+    case WL_OUTPUT_TRANSFORM_180:
70130e
+      return RR_Rotate_180;
70130e
+    case WL_OUTPUT_TRANSFORM_270:
70130e
+      return RR_Rotate_270;
70130e
+    case WL_OUTPUT_TRANSFORM_FLIPPED:
70130e
+      return RR_Reflect_X | RR_Rotate_0;
70130e
+    case WL_OUTPUT_TRANSFORM_FLIPPED_90:
70130e
+      return RR_Reflect_X | RR_Rotate_90;
70130e
+    case WL_OUTPUT_TRANSFORM_FLIPPED_180:
70130e
+      return RR_Reflect_X | RR_Rotate_180;
70130e
+    case WL_OUTPUT_TRANSFORM_FLIPPED_270:
70130e
+      return RR_Reflect_X | RR_Rotate_270;
70130e
+    }
70130e
+
70130e
+  return RR_Rotate_0;
70130e
+}
70130e
+
70130e
 static void
70130e
 display_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
70130e
 			int physical_width, int physical_height, int subpixel,
70130e
@@ -253,6 +306,7 @@ display_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
70130e
 
70130e
     xwl_output->x = x;
70130e
     xwl_output->y = y;
70130e
+    xwl_output->rotation = wl_transform_to_xrandr (transform);
70130e
 
70130e
     xorg_list_append (&xwl_output->link, &xwl_screen->output_list);
70130e
 }
70130e
@@ -262,11 +316,49 @@ display_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
70130e
 		    int width, int height, int refresh)
70130e
 {
70130e
     struct xwl_output *xwl_output = data;
70130e
+    struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
70130e
+    ScreenPtr pScreen = xwl_screen->screen;
70130e
+    ScrnInfoPtr scrn = xwl_screen->scrninfo;
70130e
+    CARD16 width_mm, height_mm;
70130e
+    DisplayModePtr mode;
70130e
+    rrScrPrivPtr rp;
70130e
 
70130e
-    if (flags & WL_OUTPUT_MODE_CURRENT) {
70130e
-	xwl_output->width = width;
70130e
-	xwl_output->height = height;
70130e
+    if (!(flags & WL_OUTPUT_MODE_CURRENT))
70130e
+	return;
70130e
+
70130e
+    xwl_output->width = width;
70130e
+    xwl_output->height = height;
70130e
+
70130e
+    if (xwl_output->x + xwl_output->width > scrn->virtualX ||
70130e
+	xwl_output->y + xwl_output->height > scrn->virtualY) {
70130e
+	/* Fake a RandR request to resize the screen. It will bounce
70130e
+	   back to our crtc_resize, which does nothing.
70130e
+	*/
70130e
+	/* Preupdate virtualX / virtualY, so that crtc_resize returns TRUE */
70130e
+	scrn->virtualX = xwl_output->x + xwl_output->width;
70130e
+	scrn->virtualY = xwl_output->y + xwl_output->height;
70130e
+
70130e
+	/* Ignore the compositor provided values for mm_width/mm_height,
70130e
+	   as it doesn't make sense to sum the values of different outputs.
70130e
+	   Just make the DPI 96 */
70130e
+	width_mm = (scrn->virtualX / 96.0) * 25.4 + 0.5;
70130e
+	height_mm = (scrn->virtualY / 96.0) * 25.4 + 0.5;
70130e
+
70130e
+	/* But! When the server starts, the RandR stuff is not initialized,
70130e
+	   so we can't call rrGetScrPriv. We updated virtualX/Y anyway, let's
70130e
+	   hope it's enough.
70130e
+	*/
70130e
+	if (xwl_screen->outputs_initialized) {
70130e
+	    rp = rrGetScrPriv(pScreen);
70130e
+	    if (rp->rrScreenSetSize)
70130e
+		rp->rrScreenSetSize(pScreen, scrn->virtualX, scrn->virtualY, width_mm, height_mm);
70130e
+	}
70130e
     }
70130e
+
70130e
+    xwl_output->xf86crtc->enabled = TRUE;
70130e
+    mode = xf86CVTMode(width, height, refresh, TRUE, FALSE);
70130e
+    xf86CrtcSetModeTransform(xwl_output->xf86crtc, mode, xwl_output->rotation,
70130e
+                             NULL, xwl_output->x, xwl_output->y);
70130e
 }
70130e
 
70130e
 static const struct wl_output_listener output_listener = {
70130e
@@ -339,5 +431,7 @@ xwayland_screen_preinit_output(struct xwl_screen *xwl_screen, ScrnInfoPtr scrnin
70130e
             FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
70130e
     }
70130e
 
70130e
-    xf86InitialConfiguration(scrninfo, TRUE);
70130e
+    xwl_screen->outputs_initialized = TRUE;
70130e
+
70130e
+    xf86SetScrnInfoModes(scrninfo);
70130e
 }
70130e
diff --git a/hw/xfree86/xwayland/xwayland-private.h b/hw/xfree86/xwayland/xwayland-private.h
70130e
index 7005db2..b0b2201 100644
70130e
--- a/hw/xfree86/xwayland/xwayland-private.h
70130e
+++ b/hw/xfree86/xwayland/xwayland-private.h
70130e
@@ -63,6 +63,7 @@ struct xwl_screen {
70130e
     struct xorg_list		 window_list;
70130e
     struct xorg_list		 authenticate_client_list;
70130e
     uint32_t			 serial;
70130e
+    Bool                         outputs_initialized;
70130e
 
70130e
     CreateWindowProcPtr		 CreateWindow;
70130e
     DestroyWindowProcPtr	 DestroyWindow;
70130e
@@ -82,6 +83,7 @@ struct xwl_output {
70130e
     xf86OutputPtr		 xf86output;
70130e
     xf86CrtcPtr			 xf86crtc;
70130e
     int32_t                      name;
70130e
+    Rotation                     rotation;
70130e
 };
70130e
 
70130e
 
70130e
-- 
70130e
1.8.3.1
70130e