[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