[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