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

xserver-xorg-video-vmware: Changes to 'upstream-unstable'



Rebased ref, commits from common ancestor:
commit 0e94cd85b2fa1501d4d883de3c97074c5ea5c373
Author: Thomas Hellstrom <thellstrom@vmware.com>
Date:   Wed Nov 16 11:22:53 2016 +0700

    Bump minor for release.
    
    Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>

diff --git a/configure.ac b/configure.ac
index 9cd793d..9f259ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,7 +23,7 @@
 # Initialize Autoconf
 AC_PREREQ([2.60])
 AC_INIT([xf86-video-vmware],
-        [13.2.0],
+        [13.2.1],
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         [xf86-video-vmware])
 AC_CONFIG_SRCDIR([Makefile.am])

commit 3fd542b0394f9ab198b7750409ec2c0f16eb59da
Author: Thomas Hellstrom <thellstrom@vmware.com>
Date:   Wed Nov 16 11:35:58 2016 +0700

    vmware/vmwgfx: Add a missing source file for distribution
    
    Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
    Reviewed-by: Sinclair Yeh <syeh@vmware.com>
    (cherry picked from commit fade4f46e84e93153edc3472abb73635f87555e6)

diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am
index 19533e6..e486514 100644
--- a/vmwgfx/Makefile.am
+++ b/vmwgfx/Makefile.am
@@ -31,5 +31,6 @@ libvmwgfx_la_SOURCES = \
 	vmwgfx_xmir.c \
 	vmwgfx_xwayland.c \
 	vmwgfx_layout.c \
+	vmwgfx_rr_inlines.h \
 	wsbm_util.h
 endif

commit e53a7e42eb7597808a364f230a97ce64481f084b
Author: Hans de Goede <hdegoede@redhat.com>
Date:   Thu Sep 29 19:37:22 2016 +0200

    Adapt Block/WakeupHandler signature for ABI 23
    
    Signed-off-by: Hans de Goede <hdegoede@redhat.com>
    Acked-by: Thomas Hellstrom <thellstrom@vmware.com>
    (cherry picked from commit d64d01c7a599dc3c79125701f076a3e459cefdc2)

diff --git a/src/compat-api.h b/src/compat-api.h
index 205ac59..02876c5 100644
--- a/src/compat-api.h
+++ b/src/compat-api.h
@@ -75,8 +75,13 @@
 
 #define SCREEN_INIT_ARGS_DECL ScreenPtr pScreen, int argc, char **argv
 
+#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(23, 0)
+#define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer pTimeout
+#define BLOCKHANDLER_ARGS arg, pTimeout
+#else
 #define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer pTimeout, pointer pReadmask
 #define BLOCKHANDLER_ARGS arg, pTimeout, pReadmask
+#endif
 
 #define CLOSE_SCREEN_ARGS_DECL ScreenPtr pScreen
 #define CLOSE_SCREEN_ARGS pScreen

commit 0bcd4df1843f00f8e8507750401ec2a2a29330dc
Author: Thomas Hellstrom <thellstrom@vmware.com>
Date:   Thu Feb 11 09:45:58 2016 +0100

    vmware: Bump minor to signal availability of new features
    
    While this may never be an official release, bump minor to enable the
    new resolutionKMS functionality. This signals the availability of
    autolayout and resolutionKMS support.
    
    Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
    Reviewed-by: Brian Paul <brianp@vmware.com>

diff --git a/configure.ac b/configure.ac
index d33d6eb..9cd793d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,7 +23,7 @@
 # Initialize Autoconf
 AC_PREREQ([2.60])
 AC_INIT([xf86-video-vmware],
-        [13.0.2],
+        [13.2.0],
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         [xf86-video-vmware])
 AC_CONFIG_SRCDIR([Makefile.am])

commit 5036e9d11a899d831b1471f64132eefcf459b222
Author: Thomas Hellstrom <thellstrom@vmware.com>
Date:   Thu Feb 11 09:40:55 2016 +0100

    vmware/vmwgfx: Don't require screen objects to run
    
    Using the vmwgfx ldu backend works just as fine except that we're limited
    to implicit layout placement.
    
    With this test on, we may end up in the odd situation that the vmwgfx kernel
    module and the vwmare legacy Xorg driver are enabled simultaneously, and that
    is an unsupported configuration. It will also break resolutionKMS which will
    be enabled based on vmwgfx version but should be disabled since the legacy
    Xorg driver runs...
    
    Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
    Reviewed-by: Brian Paul <brianp@vmware.com>

diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c
index 693b5ef..b9ee1db 100644
--- a/vmwgfx/vmwgfx_driver.c
+++ b/vmwgfx/vmwgfx_driver.c
@@ -554,18 +554,6 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags)
 
     ms->check_fb_size = (vmwgfx_max_fb_size(ms->fd, &ms->max_fb_size) == 0);
 
-    if (vmwgfx_get_param(ms->fd, DRM_VMW_PARAM_HW_CAPS, &cap) != 0) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to detect device "
-		   "screen object capability.\n");
-	goto out_depth;
-    }
-
-    if ((cap & SVGA_CAP_SCREEN_OBJECT_2) == 0) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Device is not screen object "
-		   "capable.\n");
-	goto out_depth;
-    }
-
     switch (pScrn->depth) {
     case 15:
     case 16:

commit 57d4499cc252bd1c3362a569ca7fd99ba6b645ed
Author: Thomas Hellstrom <thellstrom@vmware.com>
Date:   Wed Jan 20 19:08:21 2016 +0100

    vmware/vmwgfx: Disable autolayout if we detect an old resolutionset
    
    While the autolayout feature should really avoid races both with the old
    resolutionSet RandR12 code and with new compositor layout code, let's
    disable the autolayout feature if someone tries to set the
    layout / resolution through the vmwarectrl interface.
    That's most likely an old resolutionSet.
    
    Autolayout is turned on on each new screen generation.
    
    Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
    Reviewed-by: Sinclair Yeh <syeh@vmware.com>

diff --git a/vmwgfx/vmwgfx_ctrl.c b/vmwgfx/vmwgfx_ctrl.c
index 811ca0a..5b11f37 100644
--- a/vmwgfx/vmwgfx_ctrl.c
+++ b/vmwgfx/vmwgfx_ctrl.c
@@ -121,6 +121,7 @@ VMwareCtrlDoSetRes(ScrnInfoPtr pScrn,
    rect.w = x;
    rect.h = y;
 
+   ms->autoLayout = FALSE;
    ret = vmwgfx_update_gui_layout(ms->fd, 1, &rect);
    return (ret == 0);
 }
@@ -226,6 +227,7 @@ VMwareCtrlDoSetTopology(ScrnInfoPtr pScrn,
       rects[i].h = extents[i].height;
    }
 
+   ms->autoLayout = FALSE;
    ret = vmwgfx_update_gui_layout(ms->fd, number, rects);
 
    free(rects);
diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c
index 301cf49..693b5ef 100644
--- a/vmwgfx/vmwgfx_driver.c
+++ b/vmwgfx/vmwgfx_driver.c
@@ -1033,6 +1033,7 @@ drv_screen_init(SCREEN_INIT_ARGS_DECL)
 
     xf86SetBlackWhitePixels(pScreen);
 
+    ms->autoLayout = TRUE;
     vmw_ctrl_ext_init(pScrn);
 
     if (ms->accelerate_render) {
diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h
index 8113b22..7c7177f 100644
--- a/vmwgfx/vmwgfx_driver.h
+++ b/vmwgfx/vmwgfx_driver.h
@@ -152,6 +152,7 @@ typedef struct _modesettingRec
     InputHandlerProc uevent_handler;
     struct vmwgfx_layout *layout;
 #endif
+    Bool autoLayout;
 } modesettingRec, *modesettingPtr;
 
 #define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate))
diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c
index 03ec310..486514a 100644
--- a/vmwgfx/vmwgfx_output.c
+++ b/vmwgfx/vmwgfx_output.c
@@ -785,7 +785,8 @@ vmwgfx_handle_uevents(int fd, void *closure)
     if (pScreen)
 	RRGetInfo(pScreen, TRUE);
 
-    vmwgfx_layout_handler(scrn);
+    if (ms->autoLayout)
+	vmwgfx_layout_handler(scrn);
 
     udev_device_unref(dev);
 }

commit 48fb82f13ca290e9fbb8c7f79aba5ee119a3ce7f
Author: Thomas Hellstrom <thellstrom@vmware.com>
Date:   Wed Jan 20 14:21:40 2016 +0100

    vmware/vmwgfx: Read the implicit output status from KMS if available.
    
    This information is used to switch to software cursors if we have
    multiple overlapping explicit outputs and thus might need to display
    two cursors simultaneously.
    
    Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
    Reviewed-by: Sinclair Yeh <syeh@vmware.com>

diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c
index c06cd66..03ec310 100644
--- a/vmwgfx/vmwgfx_output.c
+++ b/vmwgfx/vmwgfx_output.c
@@ -73,9 +73,9 @@ struct output_private
     int num_props;
     struct output_prop *props;
     int c;
-    Bool is_implicit;
     int suggested_x;
     int suggested_y;
+    int implicit_placement;
     xf86CrtcPtr saved_crtc;
     Bool saved_crtc_enabled;
 };
@@ -134,6 +134,24 @@ vmwgfx_output_origin(xf86OutputPtr output, int *x, int *y)
 }
 
 /**
+ * vmwgfx_output_is_implicit - Whether an output uses implicit placement
+ *
+ * output: The output to consider.
+ *
+ * Returns: TRUE if the output uses implicit placement. False otherwise.
+ */
+static Bool
+vmwgfx_output_is_implicit(xf86OutputPtr output)
+{
+    struct output_private *vmwgfx_output = output->driver_private;
+
+    if (vmwgfx_output->implicit_placement == -1)
+	return TRUE;
+
+    return !!vmwgfx_output->props[vmwgfx_output->implicit_placement].value;
+}
+
+/**
  * output_property_ignore - Function to determine whether to ignore or
  * to re-export a drm property.
  *
@@ -186,6 +204,8 @@ output_create_resources(xf86OutputPtr output)
 	    vmwgfx_output->suggested_x = j;
 	if (!strcmp(drmmode_prop->name,"suggested Y"))
 	    vmwgfx_output->suggested_y = j;
+	if (!strcmp(drmmode_prop->name,"implicit_placement"))
+	    vmwgfx_output->implicit_placement = j;
 	vmwgfx_output->num_props++;
 	j++;
     }
@@ -522,7 +542,6 @@ vmwgfx_output_explicit_overlap(ScrnInfoPtr pScrn)
     RegionRec output_union;
     RegionRec cur_output;
     RegionRec result;
-    struct output_private *priv;
     xf86CrtcPtr crtc;
     Bool overlap = FALSE;
     int i;
@@ -537,10 +556,9 @@ vmwgfx_output_explicit_overlap(ScrnInfoPtr pScrn)
      */
     for (i = 0; i < config->num_output; i++) {
 	output = config->output[i];
-	priv = output->driver_private;
 	crtc = output->crtc;
 
-	if (!crtc || !crtc->enabled || !priv->is_implicit)
+	if (!crtc || !crtc->enabled || !vmwgfx_output_is_implicit(output))
 	    continue;
 
 	REGION_RESET(pScreen, &cur_output, &crtc->bounds);
@@ -552,10 +570,9 @@ vmwgfx_output_explicit_overlap(ScrnInfoPtr pScrn)
      */
     for (i = 0; i < config->num_output; i++) {
 	output = config->output[i];
-	priv = output->driver_private;
 	crtc = output->crtc;
 
-	if (!crtc || !crtc->enabled || priv->is_implicit)
+	if (!crtc || !crtc->enabled || vmwgfx_output_is_implicit(output))
 	    continue;
 
 	REGION_RESET(pScreen, &cur_output, &crtc->bounds);
@@ -594,8 +611,6 @@ xorg_output_init(ScrnInfoPtr pScrn)
     }
 
     for (c = 0; c < res->count_connectors; c++) {
-	Bool is_implicit = TRUE;
-
 	drm_connector = drmModeGetConnector(ms->fd, res->connectors[c]);
 	if (!drm_connector)
 	    goto out;
@@ -620,9 +635,9 @@ xorg_output_init(ScrnInfoPtr pScrn)
 	    continue;
 	}
 
-	priv->is_implicit = is_implicit;
 	priv->suggested_x = -1;
 	priv->suggested_y = -1;
+	priv->implicit_placement = -1;
 
 	drm_encoder = drmModeGetEncoder(ms->fd, drm_connector->encoders[0]);
 	if (drm_encoder) {

commit a81e359d88151159e3a19ceb95027029fef0a9ba
Author: Thomas Hellstrom <thellstrom@vmware.com>
Date:   Wed Jan 20 14:04:13 2016 +0100

    vmware/vmwgfx: Avoid filling the log with modeline printouts
    
    There are specific debug options for that.
    
    Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
    Reviewed-by: Sinclair Yeh <syeh@vmware.com>

diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c
index ddd8d5c..c06cd66 100644
--- a/vmwgfx/vmwgfx_output.c
+++ b/vmwgfx/vmwgfx_output.c
@@ -322,7 +322,6 @@ output_get_modes(xf86OutputPtr output)
 		mode->type |= M_T_DRIVER;
 	    xf86SetModeDefaultName(mode);
 	    modes = xf86ModesAdd(modes, mode);
-	    xf86PrintModeline(0, mode);
 	}
     }
 

commit 5978597da92898a424837ee89e66f66a8120480c
Author: Thomas Hellstrom <thellstrom@vmware.com>
Date:   Wed Jan 20 13:01:21 2016 +0100

    vmware/vmwgfx: Add a layout handler v2
    
    Add a handler that, on hotplug events, scans for a new GUI layout and
    tries to set that layout using XRandR similar to what the RandR1.2 part of
    vmware tools resolutionSet module is doing today.
    
    v2: Address review comments
    - Keep the old layout in case of screen resizing errors
    - Fix the vmwgfx_layout handler() declaration.
    
    Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
    Reviewed-by: Sinclair Yeh <syeh@vmware.com>

diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am
index 81b9e08..19533e6 100644
--- a/vmwgfx/Makefile.am
+++ b/vmwgfx/Makefile.am
@@ -30,5 +30,6 @@ libvmwgfx_la_SOURCES = \
 	vmwgfx_hosted_priv.h \
 	vmwgfx_xmir.c \
 	vmwgfx_xwayland.c \
+	vmwgfx_layout.c \
 	wsbm_util.h
 endif
diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h
index 080ec8c..8113b22 100644
--- a/vmwgfx/vmwgfx_driver.h
+++ b/vmwgfx/vmwgfx_driver.h
@@ -88,6 +88,7 @@ enum xorg_throttling_reason {
 
 struct vmwgfx_hosted;
 struct xf86_platform_device;
+struct vmwgfx_layout;
 
 typedef struct _modesettingRec
 {
@@ -149,6 +150,7 @@ typedef struct _modesettingRec
 #ifdef HAVE_LIBUDEV
     struct udev_monitor *uevent_monitor;
     InputHandlerProc uevent_handler;
+    struct vmwgfx_layout *layout;
 #endif
 } modesettingRec, *modesettingPtr;
 
@@ -196,6 +198,24 @@ void
 vmwgfx_uevent_init(ScrnInfoPtr scrn, modesettingPtr ms);
 void
 vmwgfx_uevent_fini(ScrnInfoPtr scrn, modesettingPtr ms);
+Bool
+vmwgfx_output_has_origin(xf86OutputPtr output);
+void
+vmwgfx_output_origin(xf86OutputPtr output, int *x, int *y);
+void
+vmwgfx_outputs_off(ScrnInfoPtr pScrn);
+void
+vmwgfx_outputs_on(ScrnInfoPtr pScrn);
+
+/***********************************************************************
+ * vmwgfx_layout.c
+ */
+struct vmwgfx_layout *
+vmwgfx_layout_from_kms(ScrnInfoPtr pScrn);
+void
+vmwgfx_layout_configuration(ScrnInfoPtr pScrn, struct vmwgfx_layout *layout);
+void
+vmwgfx_layout_handler(ScrnInfoPtr pScrn);
 
 /***********************************************************************
  * xorg_xv.c
diff --git a/vmwgfx/vmwgfx_layout.c b/vmwgfx/vmwgfx_layout.c
new file mode 100644
index 0000000..2c67dd5
--- /dev/null
+++ b/vmwgfx/vmwgfx_layout.c
@@ -0,0 +1,265 @@
+/**************************************************************************
+ * Copyright © 2016 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_LIBUDEV
+#include "vmwgfx_driver.h"
+#include <xf86Crtc.h>
+#include "vmwgfx_rr_inlines.h"
+
+/**
+ * struct vmwgfx_layout_box - Struct representing a GUI layout rect
+ *
+ * @x: X value of the origin.
+ * @y: Y value of the origin.
+ * @width: Width of the rect.
+ * @height: Height of the rect.
+ */
+struct vmwgfx_layout_box {
+    int x, y, width, height;
+};
+
+/**
+ * struct vmwgfx_layout - Struct representing a complete GUI layout
+ *
+ * @connected: Number of connected outputs.
+ * @root_width: Width of full desktop.
+ * @root_height: Height of full desktop.
+ * @boxes: Array of GUI layout rects.
+ */
+struct vmwgfx_layout {
+    int connected;
+    int root_width;
+    int root_height;
+    struct vmwgfx_layout_box boxes[];
+};
+
+/**
+ * vmwgfx_layout_debug - Log debug info of a layout struct.
+ *
+ * @pScrn: ScrnInfoPtr: Pointer to the ScrnInfo struct for the screen the
+ * layout should be logged for.
+ * @l1: Pointer to a valid struct vmwgfx_layout.
+ */
+static void
+vmwgfx_layout_debug(ScrnInfoPtr pScrn, const struct vmwgfx_layout *l1)
+{
+    int i;
+
+    xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "New layout.\n");
+    for (i = 0; i < l1->connected; ++i)
+	xf86DrvMsg(pScrn->scrnIndex, X_DEBUG,
+		   "%d: %d %d %d %d\n", i, l1->boxes[i].x,
+		   l1->boxes[i].y, l1->boxes[i].width, l1->boxes[i].height);
+    xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "\n");
+}
+
+/**
+ * vmwgfx_layouts_equal - Determine whether two layouts are equal.
+ *
+ * @l1: Pointer to the first struct vmwgfx_layout.
+ * @l2: Pointer to the second struct vmwgfx_layout.
+ *
+ * Returns: TRUE if the layouts are equal. FALSE otherwise.
+ */
+static Bool
+vmwgfx_layouts_equal(const struct vmwgfx_layout *l1,
+		     const struct vmwgfx_layout *l2)
+{
+    if (l1->connected != l2->connected)
+	return FALSE;
+
+    if (!l1->connected)
+	return TRUE;
+
+    return !memcmp(l1->boxes, l2->boxes,
+		   l1->connected*sizeof(struct vmwgfx_layout_box));
+}
+
+/**
+ * vmwgfx_layout_from_kms - Construct a struct vmwgfx_layout from KMS info.
+ *
+ * @pScrn: Pointer to a ScrnInfo struct.
+ *
+ * Returns: A pointer to a newly allocated struct vmwgfx_layout if
+ * successful. NULL otherwise.
+ */
+struct vmwgfx_layout *
+vmwgfx_layout_from_kms(ScrnInfoPtr pScrn)
+{
+    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int i, connected;
+    struct vmwgfx_layout *layout;
+    size_t size;
+    int min_x = INT_MAX, max_x = INT_MIN, min_y = INT_MAX, max_y = INT_MIN;
+
+    for (i = 0; i < config->num_output; ++i) {
+	xf86OutputPtr output = config->output[i];
+
+	if (!vmwgfx_output_has_origin(output))
+	    return NULL;
+
+	if (output->status != XF86OutputStatusConnected)
+	    break;
+    }
+    connected = i;
+
+    size = offsetof(struct vmwgfx_layout, boxes) +
+	connected * sizeof(struct vmwgfx_layout_box);
+    layout = calloc(1, size);
+    if (!layout)
+	return NULL;
+
+    layout->connected = connected;
+    for (i = 0; i < connected; ++i) {
+	struct vmwgfx_layout_box *box = &layout->boxes[i];
+	xf86OutputPtr output = config->output[i];
+	DisplayModePtr mode = output->probed_modes;
+
+	if (mode == NULL) {
+	    free(layout);
+	    return NULL;
+	}
+
+	vmwgfx_output_origin(output, &box->x, &box->y);
+	box->width = output->probed_modes->HDisplay;
+	box->height = output->probed_modes->VDisplay;
+	min_x = min(min_x, box->x);
+	min_y = min(min_y, box->y);
+	max_x = max(max_x, box->x + box->width);
+	max_y = max(max_y, box->y + box->height);
+    }
+
+    layout->root_width = max_x;
+    layout->root_height = max_y;
+
+    return layout;
+}
+
+/**
+ * vmwgfx_layout_configuration - Set up the screen modesetting configuration
+ * from a struct vmwgfx_layout.
+ *
+ * @pScrn: Pointer to a ScrnInfo struct.
+ * @layout: Layout to use for the new configuration.
+ *
+ * Sets up a new modesetting configuration. Note that the configuration needs
+ * to be committed using xf86SetDesiredModes().
+ */
+void
+vmwgfx_layout_configuration(ScrnInfoPtr pScrn, struct vmwgfx_layout *layout)
+{
+    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+    struct vmwgfx_layout_box *box;
+    xf86OutputPtr output;
+    xf86CrtcPtr crtc;
+    int i, j;
+
+    for (j = 0; j < config->num_crtc; ++j) {
+	crtc = config->crtc[j];
+	crtc->enabled = FALSE;
+    }
+
+    for (i = 0, box = layout->boxes; i < config->num_output; ++i, ++box) {
+	output = config->output[i];
+	output->crtc = NULL;
+	if (i >= layout->connected)
+	    continue;
+
+	for (j = 0; j < config->num_crtc; ++j) {
+	    crtc = config->crtc[j];
+	    if (!crtc->enabled && (output->possible_crtcs & (1 << j))) {
+		crtc->enabled = TRUE;
+		output->crtc = crtc;
+		break;
+	    }
+	}
+
+	if (!output->crtc)
+	    continue;
+
+	crtc = output->crtc;
+	xf86SaveModeContents(&crtc->desiredMode, output->probed_modes);
+	crtc->desiredRotation = RR_Rotate_0;
+	crtc->desiredX = box->x;
+	crtc->desiredY = box->y;
+	crtc->desiredTransformPresent = FALSE;
+    }
+}
+
+/**
+ * vmwgfx_layout_handler - Obtain and set a new layout.
+ *
+ * @pScrn: Pointer to a ScrnInfo struct.
+ *
+ * Obtains a new layout from DRM. If the layout differs from the current one,
+ * Try to set the new layout. If that fails, (typically due to root pixmap
+ * resizing issues) try hard to revert to the old layout. Finally
+ * update RandR in a way that tries to block racing display managers
+ * from setting up the layout in a different way.
+ */
+void
+vmwgfx_layout_handler(ScrnInfoPtr pScrn)
+{
+
+    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct vmwgfx_layout *layout;
+
+    if (!pScreen)
+	return;
+
+    /*
+     * Construct a layout from the new information and determine whether we
+     * need to take action
+     */
+    layout = vmwgfx_layout_from_kms(pScrn);
+    if (layout && (!ms->layout || !vmwgfx_layouts_equal(ms->layout, layout))) {
+	vmwgfx_layout_debug(pScrn, layout);
+	vmwgfx_outputs_off(pScrn);
+	xf86DisableUnusedFunctions(pScrn);
+	if (!vmwgfx_rr_screen_set_size(pScreen, layout->root_width,
+				       layout->root_height)) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Resizing screen failed.\n");
+	    vmwgfx_outputs_on(pScrn);
+	    free(layout);
+	} else {
+	    vmwgfx_layout_configuration(pScrn, layout);
+	    if (ms->layout)
+	      free(ms->layout);
+	    ms->layout = layout;
+	}
+	xf86SetDesiredModes(pScrn);
+	vmwgfx_notify_rr(pScreen);
+    } else if (layout) {
+	free(layout);
+    }
+}
+
+#endif /* HAVE_LIBUDEV */
diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c
index eadb1a2..ddd8d5c 100644
--- a/vmwgfx/vmwgfx_output.c
+++ b/vmwgfx/vmwgfx_output.c
@@ -74,6 +74,10 @@ struct output_private
     struct output_prop *props;
     int c;
     Bool is_implicit;
+    int suggested_x;
+    int suggested_y;
+    xf86CrtcPtr saved_crtc;
+    Bool saved_crtc_enabled;
 };
 
 static const char *output_enum_list[] = {
@@ -96,6 +100,40 @@ static const char *output_enum_list[] = {
 };
 
 /**
+ * vmwgfx_output_has_origin - Whether we've detected layout info on the DRM
+ * connector.
+ *
+ * @output: The output to consider.
+ *
+ * Returns: TRUE if the corresponding DRM connector has layout info.
+ * FALSE otherwise.
+ */
+Bool
+vmwgfx_output_has_origin(xf86OutputPtr output)
+{
+    struct output_private *vmwgfx_output = output->driver_private;
+
+    return vmwgfx_output->suggested_x != -1 &&
+	vmwgfx_output->suggested_y != -1;
+}
+
+/**
+ * vmwgfx_output_origin - Get the origin for an output in the GUI layout.
+ *
+ * @output: The output to consider.
+ * @x: Outputs the x coordinate of the origin.
+ * @y: Outputs the y coordinate of the origin.
+ */
+void
+vmwgfx_output_origin(xf86OutputPtr output, int *x, int *y)
+{
+    struct output_private *vmwgfx_output = output->driver_private;
+
+    *x = vmwgfx_output->props[vmwgfx_output->suggested_x].value;
+    *y = vmwgfx_output->props[vmwgfx_output->suggested_y].value;
+}
+
+/**
  * output_property_ignore - Function to determine whether to ignore or
  * to re-export a drm property.
  *
@@ -144,6 +182,10 @@ output_create_resources(xf86OutputPtr output)
 	vmwgfx_output->props[j].index = i;
 	vmwgfx_output->props[j].mode_prop = drmmode_prop;
 	vmwgfx_output->props[j].value = drm_connector->prop_values[i];
+	if (!strcmp(drmmode_prop->name,"suggested X"))
+	    vmwgfx_output->suggested_x = j;
+	if (!strcmp(drmmode_prop->name,"suggested Y"))
+	    vmwgfx_output->suggested_y = j;
 	vmwgfx_output->num_props++;
 	j++;
     }
@@ -580,6 +622,8 @@ xorg_output_init(ScrnInfoPtr pScrn)
 	}
 
 	priv->is_implicit = is_implicit;
+	priv->suggested_x = -1;
+	priv->suggested_y = -1;
 
 	drm_encoder = drmModeGetEncoder(ms->fd, drm_connector->encoders[0]);
 	if (drm_encoder) {
@@ -650,6 +694,60 @@ vmwgfx_output_properties_scan(ScrnInfoPtr pScrn)
 }
 
 /**
+ * vmwgfx_outputs_off - Mark all crtc / output pairs as disabled and save
+ * their configuration.
+ *
+ * @pScrn: Pointer to a ScrnInfo struct.
+ *
+ * Note that to commit this to the display system, a call to this function
+ * should be followed by a call to xf86DisableUnusedFunctions()
+ */
+void
+vmwgfx_outputs_off(ScrnInfoPtr pScrn)
+{
+    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int i;
+
+    for (i = 0; i < config->num_output; ++i) {
+	xf86OutputPtr output = config->output[i];
+	struct output_private *vmwgfx_output = output->driver_private;
+
+	vmwgfx_output->saved_crtc = output->crtc;
+	if (output->crtc) {
+	    vmwgfx_output->saved_crtc_enabled = output->crtc->enabled;
+	    output->crtc->enabled = FALSE;
+	    output->crtc = NULL;
+	}
+    }
+}
+
+/**
+ * vmwgfx_outputs_on - Reset crtc / output pairs to a configuation saved
+ * using vmwgfx_output_off.
+ *
+ * @pScrn: Pointer to a ScrnInfo struct.
+ *
+ * Note that to commit the setup to the display system, a call to this
+ * function should be followed by a call to xf86SetDesiredModes().
+ */
+void
+vmwgfx_outputs_on(ScrnInfoPtr pScrn)
+{
+    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int i;
+
+    for (i = 0; i < config->num_output; ++i) {
+	xf86OutputPtr output = config->output[i];
+	struct output_private *vmwgfx_output = output->driver_private;
+
+	if (vmwgfx_output->saved_crtc) {
+	    output->crtc = vmwgfx_output->saved_crtc;
+	    output->crtc->enabled = vmwgfx_output->saved_crtc_enabled;
+	}
+    }
+}
+
+/**
  * vmwgfx_handle uevent - Property update callback
  *
  * @fd: File descriptor for the uevent
@@ -673,6 +771,8 @@ vmwgfx_handle_uevents(int fd, void *closure)
     if (pScreen)
 	RRGetInfo(pScreen, TRUE);
 
+    vmwgfx_layout_handler(scrn);
+
     udev_device_unref(dev);
 }
 #endif  /* HAVE_LIBUDEV */
diff --git a/vmwgfx/vmwgfx_rr_inlines.h b/vmwgfx/vmwgfx_rr_inlines.h
new file mode 100644
index 0000000..9608fd2
--- /dev/null
+++ b/vmwgfx/vmwgfx_rr_inlines.h
@@ -0,0 +1,92 @@
+/**************************************************************************
+ * Copyright © 2016 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * This file contains calls into the RandR1.2 code and modification of core
+ * RandR data structures that probably were never intended from drivers.
+ */
+
+#ifndef _VMWGFX_RR_INLINES_H_
+#define _VMWGFX_RR_INLINES_H_
+
+#include <xf86Crtc.h>
+#include <xf86RandR12.h>
+
+#define VMW_DPI 96.
+#define VMW_INCH_TO_MM 25.4
+
+/**
+ * vmwgfx_notify_rr - Notify RandR that our configuration has changed.
+ *
+ * @pScreen: Pointer to the affected screen.
+ *
+ * Normally screen configurations are typically only changed using RandR,
+ * so when we do it in an udev handler, we need to notify RandR that we've
+ * made a change, so that it can be propagated to all RandR clients.
+ */
+static inline void
+vmwgfx_notify_rr(ScreenPtr pScreen)
+{
+    rrScrPriv(pScreen);
+
+
+    /*
+     * We need to update the time-stamps, otherwise X clients that haven't
+     * yet read this config might just overwrite it.
+     * This effectively stops the desktop manager from trying to
+     * outsmart us, since RandR simply doesn't accept requests from
+     * clients that haven't read this config and tag their request with
+     * an earlier timestamp.
+     */
+    pScrPriv->lastSetTime = currentTime;
+    pScrPriv->lastConfigTime = currentTime;
+#ifdef RANDR_12_INTERFACE
+    xf86RandR12TellChanged(pScreen);
+#else
+    RRTellChanged(pScreen);
+#endif
+}
+
+/**
+ * vmwgfx_rr_screen_set_size - Use RandR to change the root pixmap dimensions.
+ *
+ * @pScreen: Pointer to the affected screen.
+ *
+ * Returns: TRUE if successful. False otherwise.
+ */
+static inline Bool
+vmwgfx_rr_screen_set_size(ScreenPtr pScreen, int width, int height)
+{
+    rrScrPriv(pScreen);
+    float mm_width, mm_height;
+
+    mm_width = ((float) width) * VMW_INCH_TO_MM / VMW_DPI + .5;
+    mm_height = ((float) height) * VMW_INCH_TO_MM / VMW_DPI + .5;
+
+    return pScrPriv->rrScreenSetSize(pScreen, width, height,
+				     (int) mm_width, (int) mm_height);
+}
+
+#endif

commit 885e360b16fd88b48b40930c6277637615aab188
Author: Thomas Hellstrom <thellstrom@vmware.com>
Date:   Wed Jan 20 12:09:22 2016 +0100

    vmware/vmwgfx: Update RandR output properties on hotplug events v2
    
    Update also RandR output properties when we receive hotplug events;
    the RRGetInfo function doesn't do this.
    
    This makes sure RandR sends out property change events to clients.
    Also remove some debugging printouts.
    
    v2: Address review comment from Sinclair Yeh;
    make sure struct output_private::drm_connector is always valid.
    
    Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
    Reviewed-by: Sinclair Yeh <syeh@vmware.com>

diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c
index 8803be5..eadb1a2 100644
--- a/vmwgfx/vmwgfx_output.c
+++ b/vmwgfx/vmwgfx_output.c
@@ -324,7 +324,7 @@ output_set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr valu
 		    value->size != 1)
 		return FALSE;
 	    val = *(uint32_t *)value->data;
-
+	    p->value = val;
 	    drmModeConnectorSetProperty
 		(ms->fd, vmwgfx_output->drm_connector->connector_id,
 		 p->mode_prop->prop_id, (uint64_t)val);
@@ -342,9 +342,10 @@ output_set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr valu
 	    /* search for matching name string, then set its value down */
 	    for (j = 0; j < p->mode_prop->count_enums; j++) {
 		if (!strcmp(p->mode_prop->enums[j].name, name)) {
+		    p->value = p->mode_prop->enums[j].value;
 		    drmModeConnectorSetProperty
 			(ms->fd, vmwgfx_output->drm_connector->connector_id,
-			 p->mode_prop->prop_id, p->mode_prop->enums[j].value);
+			 p->mode_prop->prop_id, p->value);
 		    return TRUE;
 		}
 	    }
@@ -355,54 +356,76 @@ output_set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr valu
 }
 #endif /* RANDR_12_INTERFACE */
 
+/**
+ * vmwgfx_output_property_scan - Update a single property on a single output
+ * @output: Pointer to the output to consider.
+ * @p: The property to update.
+ *
+ * Reads the property value from the drm connector corresponding to


Reply to: