[PATCH xserver 3/3] xwayland: add support for multiple outputs

Giovanni Campagna scampa.giovanni at gmail.com
Wed Aug 21 00:53:27 PDT 2013


From: Giovanni Campagna <gcampagn at redhat.com>

Drop xf86InitialConfiguration, which just gets in the way
of the compositor doing its own output arrangement, and transform
wayland events into the appropriate low-level xf86 calls to
keep the screen size updated.
---
 hw/xfree86/xwayland/xwayland-output.c  | 68 ++++++++++++++++++++++++++++++++--
 hw/xfree86/xwayland/xwayland-private.h |  1 +
 2 files changed, 65 insertions(+), 4 deletions(-)

diff --git a/hw/xfree86/xwayland/xwayland-output.c b/hw/xfree86/xwayland/xwayland-output.c
index 3cfeb7f..8f3ac02 100644
--- a/hw/xfree86/xwayland/xwayland-output.c
+++ b/hw/xfree86/xwayland/xwayland-output.c
@@ -36,6 +36,7 @@
 #include <cursorstr.h>
 #include <xf86Crtc.h>
 #include <mipointrst.h>
+#include <randrstr.h>
 
 #include "xwayland.h"
 #include "xwayland-private.h"
@@ -198,6 +199,7 @@ xwl_output_create(struct xwl_screen *xwl_screen)
     xf86output->possible_clones = 1;
 
     xf86crtc = xf86CrtcCreate(xwl_screen->scrninfo, &crtc_funcs);
+    xf86crtc->enabled = TRUE;
     xf86crtc->driver_private = xwl_output;
 
     xwl_output->xf86output = xf86output;
@@ -262,11 +264,48 @@ display_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
 		    int width, int height, int refresh)
 {
     struct xwl_output *xwl_output = data;
+    struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
+    ScreenPtr pScreen = xwl_screen->screen;
+    ScrnInfoPtr scrn = xwl_screen->scrninfo;
+    CARD16 width_mm, height_mm;
+    DisplayModePtr mode;
+    rrScrPrivPtr rp;
+
+    if (!(flags & WL_OUTPUT_MODE_CURRENT))
+	return;
 
-    if (flags & WL_OUTPUT_MODE_CURRENT) {
-	xwl_output->width = width;
-	xwl_output->height = height;
+    xwl_output->width = width;
+    xwl_output->height = height;
+
+    if (xwl_output->x + xwl_output->width > scrn->virtualX ||
+	xwl_output->y + xwl_output->height > scrn->virtualY) {
+	/* Fake a RandR request to resize the screen. It will bounce
+	   back to our crtc_resize, which does nothing.
+	*/
+	/* Preupdate virtualX / virtualY, so that crtc_resize returns TRUE */
+	scrn->virtualX = xwl_output->x + xwl_output->width;
+	scrn->virtualY = xwl_output->y + xwl_output->height;
+
+	/* Ignore the compositor provided values for mm_width/mm_height,
+	   as it doesn't make sense to sum the values of different outputs.
+	   Just make the DPI 96 */
+	width_mm = (scrn->virtualX / 96.0) * 25.4 + 0.5;
+	height_mm = (scrn->virtualY / 96.0) * 25.4 + 0.5;
+
+	/* But! When the server starts, the RandR stuff is not initialized,
+	   so we can't call rrGetScrPriv. We updated virtualX/Y anyway, let's
+	   hope it's enough.
+	*/
+	if (xwl_screen->outputs_initialized) {
+	    rp = rrGetScrPriv(pScreen);
+	    if (rp->rrScreenSetSize)
+		rp->rrScreenSetSize(pScreen, scrn->virtualX, scrn->virtualY, width_mm, height_mm);
+	}
     }
+
+    xwl_output->xf86crtc->enabled = TRUE;
+    mode = xf86CVTMode(width, height, 60, TRUE, FALSE);
+    xf86CrtcSetModeTransform(xwl_output->xf86crtc, mode, RR_Rotate_0, NULL, xwl_output->x, xwl_output->y);
 }
 
 static const struct wl_output_listener output_listener = {
@@ -324,6 +363,7 @@ void
 xwayland_screen_preinit_output(struct xwl_screen *xwl_screen, ScrnInfoPtr scrninfo)
 {
     int ret;
+    DisplayModePtr last, mode = NULL;
 
     xf86CrtcConfigInit(scrninfo, &config_funcs);
 
@@ -339,5 +379,25 @@ xwayland_screen_preinit_output(struct xwl_screen *xwl_screen, ScrnInfoPtr scrnin
             FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
     }
 
-    xf86InitialConfiguration(scrninfo, TRUE);
+    xwl_screen->outputs_initialized = TRUE;
+
+    if (!scrninfo->modes) {
+        scrninfo->modes = xf86ModesAdd(scrninfo->modes,
+				       xf86CVTMode(scrninfo->display->virtualX,
+						   scrninfo->display->virtualY,
+						   60, 0, 0));
+    }
+
+    /* For some reason, scrninfo->modes is circular, unlike the other mode
+     * lists.  How great is that?
+     */
+    for (last = scrninfo->modes; last && last->next; last = last->next);
+    last->next = scrninfo->modes;
+    scrninfo->modes->prev = last;
+    if (mode) {
+        while (scrninfo->modes != mode)
+            scrninfo->modes = scrninfo->modes->next;
+    }
+
+    scrninfo->currentMode = scrninfo->modes;
 }
diff --git a/hw/xfree86/xwayland/xwayland-private.h b/hw/xfree86/xwayland/xwayland-private.h
index 7005db2..ec858e7 100644
--- a/hw/xfree86/xwayland/xwayland-private.h
+++ b/hw/xfree86/xwayland/xwayland-private.h
@@ -63,6 +63,7 @@ struct xwl_screen {
     struct xorg_list		 window_list;
     struct xorg_list		 authenticate_client_list;
     uint32_t			 serial;
+    Bool                         outputs_initialized;
 
     CreateWindowProcPtr		 CreateWindow;
     DestroyWindowProcPtr	 DestroyWindow;
-- 
1.8.3.1



More information about the wayland-devel mailing list