[PATCH xserver] randr: Add Border property support

Aaron Plattner aplattner at nvidia.com
Thu Aug 4 17:13:18 PDT 2011


Add helpers to RandR to allow the DDX (or rather the driver loaded by
the DDX, for xfree86) to specify how many dimensions of adjustments it
supports.  Check for this property and adjust the CRTC raster size
accordingly when computing the transformed framebuffer size read.

This implements the properties described in
http://lists.x.org/archives/xorg-devel/2011-August/024163.html

Signed-off-by: Aaron Plattner <aplattner at nvidia.com>
---
This can't get merged until randrproto 1.4.0 is released (and the merge window
opens), but I'd like to get early feedback now and it ought to be ready to go
once those conditions are met.

 configure.ac       |    2 +-
 randr/randrstr.h   |   28 +++++++++++++++
 randr/rrcrtc.c     |   26 ++++++++++++--
 randr/rrproperty.c |   96 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 147 insertions(+), 5 deletions(-)

diff --git a/configure.ac b/configure.ac
index 4f4bcf2..cde7c2f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -785,7 +785,7 @@ WINDOWSWMPROTO="windowswmproto"
 APPLEWMPROTO="applewmproto >= 1.4"
 
 dnl Core modules for most extensions, et al.
-SDK_REQUIRED_MODULES="[xproto >= 7.0.22] [randrproto >= 1.2.99.3] [renderproto >= 0.11] [xextproto >= 7.1.99] [inputproto >= 1.9.99.902] [kbproto >= 1.0.3] fontsproto"
+SDK_REQUIRED_MODULES="[xproto >= 7.0.22] [randrproto >= 1.4.0] [renderproto >= 0.11] [xextproto >= 7.1.99] [inputproto >= 1.9.99.902] [kbproto >= 1.0.3] fontsproto"
 # Make SDK_REQUIRED_MODULES available for inclusion in xorg-server.pc
 AC_SUBST(SDK_REQUIRED_MODULES)
 
diff --git a/randr/randrstr.h b/randr/randrstr.h
index d8dd37d..cc5c9b6 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -78,6 +78,7 @@ typedef struct _rrPropertyValue	RRPropertyValueRec, *RRPropertyValuePtr;
 typedef struct _rrProperty	RRPropertyRec, *RRPropertyPtr;
 typedef struct _rrCrtc		RRCrtcRec, *RRCrtcPtr;
 typedef struct _rrOutput	RROutputRec, *RROutputPtr;
+typedef struct _rrBorder	RRBorderRec, *RRBorderPtr;
 
 struct _rrMode {
     int		    refcnt;
@@ -150,6 +151,11 @@ struct _rrOutput {
     RRPropertyPtr   properties;
     Bool	    pendingProperties;
    void	    *devPrivate;
    int		    numBorderDimensions;
+};
+
+struct _rrBorder {
+    uint16_t	    left, top, right, bottom;
 };
 
 #if RANDR_12_INTERFACE
@@ -875,6 +881,28 @@ extern _X_EXPORT int
 RRConfigureOutputProperty (RROutputPtr output, Atom property,
 			   Bool pending, Bool range, Bool immutable,
 			   int num_values, INT32 *values);
+
+/*
+ * Create the RandR 1.4 "Border" and "BorderDimensions" properties with the
+ * specified number of supported dimensions.  num_dimensions should be one of 0,
+ * 1, 2, or 4.  This function is expected to be called by the DDX (or its
+ * drivers) that support border adjustments.
+ */
+extern _X_EXPORT Bool
+RRCreateBorderProperty (RROutputPtr output, int num_dimensions);
+
+/*
+ * Query the border dimensions requested by the client. This will always return
+ * all four dimensions, but some of them will be the same if the DDX called
+ * RRCreateBorderProperty with fewer than 4 dimensions.
+ *
+ * If 'pending' is TRUE, read the pending values of the property instead of the
+ * current values. This is necessary because the pending values are not promoted
+ * to current until after rrCrtcSet has completed.
+ */
+extern _X_EXPORT RRBorderRec
+RROutputGetBorderDimensions (RROutputPtr output, Bool pending);
+
 extern _X_EXPORT int
 ProcRRChangeOutputProperty (ClientPtr client);
 
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 0437795..07782b0 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -605,10 +605,12 @@ RRCrtcGammaNotify (RRCrtcPtr	crtc)
 }
 
 static void
-RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
-		      int *width, int *height)
+RRModeGetScanoutSize (RRModePtr mode, RRBorderRec border,
+		      PictTransformPtr transform, int *width, int *height)
 {
     BoxRec  box;
+    const int borderW = border.left + border.right;
+    const int borderH = border.top + border.bottom;
 
     if (mode == NULL) {
 	*width = 0;
@@ -621,6 +623,13 @@ RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
     box.x2 = mode->mode.width;
     box.y2 = mode->mode.height;
 
+    /* Adjust for borders */
+
+    if (borderW < box.x2)
+	box.x2 -= borderW;
+    if (borderH < box.y2)
+	box.y2 -= borderH;
+
     pixman_transform_bounds (transform, &box);
     *width = box.x2 - box.x1;
     *height = box.y2 - box.y1;
@@ -632,7 +641,11 @@ RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
 void
 RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height)
 {
-    RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height);
+    RROutputPtr firstOutput = crtc->numOutputs > 0 ? crtc->outputs[0] : NULL;
+
+    RRModeGetScanoutSize (crtc->mode,
+			  RROutputGetBorderDimensions(firstOutput, FALSE),
+			  &crtc->transform, width, height);
 }
 
 /*
@@ -1013,6 +1026,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	    int	source_height;
 	    PictTransform transform;
 	    struct pixman_f_transform f_transform, f_inverse;
+	    RROutputPtr firstOutput = outputs ? outputs[0] : NULL;
 
 	    RRTransformCompute (stuff->x, stuff->y,
 				mode->mode.width, mode->mode.height,
@@ -1020,7 +1034,11 @@ ProcRRSetCrtcConfig (ClientPtr client)
 				&crtc->client_pending_transform,
 				&transform, &f_transform, &f_inverse);
 
-	    RRModeGetScanoutSize (mode, &transform, &source_width, &source_height);
+	    /* Because we're about to perform a modeset, we want the pending
+	     * value of the border and not the current value */
+	    RRModeGetScanoutSize (mode,
+				  RROutputGetBorderDimensions(firstOutput, TRUE),
+				  &transform, &source_width, &source_height);
 	    if (stuff->x + source_width > pScreen->width)
 	    {
 		client->errorValue = stuff->x;
diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index 61e7bb4..93d9234 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -20,6 +20,8 @@
  * OF THIS SOFTWARE.
  */
 
+#include <X11/Xatom.h>
+
 #include "randrstr.h"
 #include "propertyst.h"
 #include "swaprep.h"
@@ -383,6 +385,100 @@ RRConfigureOutputProperty (RROutputPtr output, Atom property,
     return Success;
 }
 
+Bool
+RRCreateBorderProperty (RROutputPtr output, int num_dimensions)
+{
+    INT32 range[] = { 0, UINT16_MAX };
+    CARD16 zeroes[4] = { 0 };
+    Atom Border = MakeAtom(RR_PROPERTY_BORDER, strlen(RR_PROPERTY_BORDER),
+			   TRUE);
+    Atom BorderDims = MakeAtom(RR_PROPERTY_BORDER_DIMENSIONS,
+			       strlen(RR_PROPERTY_BORDER_DIMENSIONS), TRUE);
+
+    if (num_dimensions < 0 || num_dimensions > 4)
+	return FALSE;
+
+    if (Border == None || BorderDims == None)
+	return FALSE;
+
+    output->numBorderDimensions = num_dimensions;
+
+    RRConfigureOutputProperty(output, Border, TRUE, TRUE, TRUE, 2, range);
+    RRChangeOutputProperty(output, Border, XA_CARDINAL, 16, PropModeReplace,
+			   num_dimensions, zeroes, FALSE, FALSE);
+
+    RRConfigureOutputProperty(output, BorderDims, FALSE, FALSE, TRUE, 1,
+			      &num_dimensions);
+    RRChangeOutputProperty(output, BorderDims, XA_CARDINAL, 8, PropModeReplace,
+			   1, &num_dimensions, FALSE, FALSE);
+
+    return TRUE;
+}
+
+RRBorderRec
+RROutputGetBorderDimensions (RROutputPtr output, Bool pending)
+{
+    RRBorderRec dims = { 0, 0, 0, 0 };
+
+    if (output) {
+	Atom Border = MakeAtom(RR_PROPERTY_BORDER, strlen(RR_PROPERTY_BORDER),
+			       TRUE);
+	RRPropertyValuePtr prop_value;
+	long prop_size = 0;
+
+	if (Border != None &&
+	    (prop_value = RRGetOutputProperty(output, Border, pending)) &&
+	    prop_value && prop_value->type == XA_CARDINAL &&
+	    prop_value->format == 16)
+	{
+	    const uint16_t *data = (const uint16_t*)prop_value->data;
+
+	    prop_size = prop_value->size;
+
+	    switch (prop_size) {
+	    default:
+	    case 4:
+		dims.bottom = data[3];
+		/* fall through */
+	    case 3:
+		dims.right = data[2];
+		/* fall through */
+	    case 2:
+		dims.top = data[1];
+		/* fall through */
+	    case 1:
+		dims.left = data[0];
+		/* fall through */
+	    case 0:
+		break;
+	    }
+	}
+
+	/* If the client specified fewer than 4 adjustments or the driver
+	 * doesn't support all 4, propagate them to the remaining ones.   E.g.,
+	 * if a client specifies [ 1, 2, 3, 4 ] but only two dimensions are
+	 * supported, ignore the 3 & 4 values and return [ 1, 2, 1, 2 ]. */
+	switch (min(prop_size, output->numBorderDimensions)) {
+	case 0:
+	    dims.left = 0;
+	    /* fall through */
+	case 1:
+	    dims.top = dims.left;
+	    /* fall through */
+	case 2:
+	    dims.right = dims.left;
+	    /* fall through */
+	case 3:
+	    dims.bottom = dims.top;
+	    break;
+	default:
+	    break;
+	}
+    }
+
+    return dims;
+}
+
 int
 ProcRRListOutputProperties (ClientPtr client)
 {
-- 
1.7.1



More information about the xorg-devel mailing list