[PATCH xserver] randr: Add Border property support
Stéphane Marchesin
stephane.marchesin at gmail.com
Fri Aug 12 20:25:36 PDT 2011
On Thu, Aug 4, 2011 at 17:13, Aaron Plattner <aplattner at nvidia.com> wrote:
> 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;
> +
Hmm. Somehow it feels weird to need the first output to get border dimensions.
> + 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;
> +
Maybe exclude num_dimensions == 3 here too? I know you handle it
properly later, but it seems counter-intuitive since the spec says it
doesn't work. Or adjust the spec?
> + 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
>
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
>
More information about the xorg-devel
mailing list