[PATCH] dummy: Add support for custom resolutions (RandR 1.2)

Aaron Plattner aplattner at nvidia.com
Fri Nov 21 09:22:00 PST 2014


On 11/13/2014 10:33 AM, Nicolas Boichat wrote:
> Defining and setting custom resolutions at runtime is not
> currently possible with dummy, which is unconvenient for remote
> desktop applications, see:
> http://lists.x.org/archives/xorg-devel/2014-September/043928.html
>
> This patch adds support XRandR 1.2, which allows custom modes.
> This is done by using more recent initialization functions such
> as xf86CrtcConfigInit/xf86OutputCreate/xf86InitialConfiguration.
>
> Signed-off-by: Nicolas Boichat <drinkcat at chromium.org>
> ---
> I'm not 100% sure that I'm calling the right functions in the
> right order, or if other parts of Init/PreInit could be removed
> (e.g. do we still want DGA/cursor support?). Hoping somebody
> here can verify that.
>
> In any case, this works without glitches in my application.
>
> Thank you,
>
> Best,
>
>   src/dummy_driver.c | 213 ++++++++++++++++++++++++++++++++++++-----------------
>   1 file changed, 144 insertions(+), 69 deletions(-)
>
> diff --git a/src/dummy_driver.c b/src/dummy_driver.c
> index 6062c39..d15f77d 100644
> --- a/src/dummy_driver.c
> +++ b/src/dummy_driver.c
> @@ -34,6 +34,8 @@
>   #include <X11/extensions/Xv.h>
>   #endif
>
> +#include "xf86Crtc.h"
> +
>   /*
>    * Driver data structures.
>    */
> @@ -178,6 +180,115 @@ dummySetup(pointer module, pointer opts, int *errmaj, int *errmin)
>   #endif /* XFree86LOADER */
>
>   static Bool
> +size_valid(ScrnInfoPtr pScrn, int width, int height)
> +{
> +    /* Guard against invalid parameters */
> +    if (width == 0 || height == 0 ||
> +        width > DUMMY_MAX_WIDTH || height > DUMMY_MAX_HEIGHT)
> +        return FALSE;

Did you ever see this actually happen?  The server is supposed to reject 
requests to set sizes that are outside the range the driver specifies in 
xf86CrtcSetSizeRange.

> +    /* videoRam is in kb, divide first to avoid 32-bit int overflow */
> +    if ((width*height+1023)/1024*pScrn->bitsPerPixel/8 > pScrn->videoRam)

This seems okay for a first revision, but it would be nice if the driver 
just ignored videoRam and instead reallocated the screen memory to the 
appropriate size here.

> +        return FALSE;
> +
> +    return TRUE;
> +}
> +
> +static Bool
> +dummy_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height)
> +{
> +    int old_width, old_height;
> +
> +    old_width = pScrn->virtualX;
> +    old_height = pScrn->virtualY;
> +
> +    if (size_valid(pScrn, width, height)) {
> +        PixmapPtr rootPixmap;
> +        ScreenPtr pScreen = pScrn->pScreen;
> +
> +        pScrn->virtualX = width;
> +        pScrn->virtualY = height;
> +
> +        rootPixmap = pScreen->GetScreenPixmap(pScreen);
> +        if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height,
> +                                         -1, -1, -1, NULL)) {

This is really recomputing rootPixmap->devKind, right? 
xf86RandR12ScreenSetSize overrides the width and height later.  That's 
counterintuitive enough that it might be worth mentioning in a comment.

> +            pScrn->virtualX = old_width;
> +            pScrn->virtualY = old_height;
> +            return FALSE;
> +        }
> +
> +        pScrn->displayWidth = rootPixmap->devKind /
> +            (rootPixmap->drawable.bitsPerPixel / 8);
> +
> +        return TRUE;
> +    } else {
> +        return FALSE;
> +    }
> +}
> +
> +static const xf86CrtcConfigFuncsRec dummy_xf86crtc_config_funcs = {
> +    dummy_xf86crtc_resize
> +};
> +
> +static xf86OutputStatus
> +dummy_output_detect(xf86OutputPtr output)
> +{
> +    return XF86OutputStatusConnected;
> +}
> +
> +static int
> +dummy_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
> +{
> +    if (size_valid(output->scrn, pMode->HDisplay, pMode->VDisplay)) {
> +        return MODE_OK;
> +    } else {
> +        return MODE_MEM;
> +    }
> +}
> +
> +static DisplayModePtr
> +dummy_output_get_modes(xf86OutputPtr output)
> +{
> +    return NULL;
> +}
> +
> +static void
> +dummy_output_dpms(xf86OutputPtr output, int dpms)
> +{
> +    return;
> +}
> +
> +static const xf86OutputFuncsRec dummy_output_funcs = {
> +    .detect = dummy_output_detect,
> +    .mode_valid = dummy_output_mode_valid,
> +    .get_modes = dummy_output_get_modes,
> +    .dpms = dummy_output_dpms,
> +};

It seems unfortunate that you have to deal with outputs at all.  You can 
delete all of this stuff if you stop calling xf86InitialConfiguration() 
and construct a dummy DisplayModeRec that just has a width and a height.

> +static Bool
> +dummy_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
> +			  Rotation rotation, int x, int y)
> +{
> +    crtc->mode = *mode;
> +    crtc->x = x;
> +    crtc->y = y;
> +    crtc->rotation = rotation;
> +
> +    return TRUE;
> +}
> +
> +static void
> +dummy_crtc_dpms(xf86CrtcPtr output, int dpms)
> +{
> +    return;
> +}
> +
> +static const xf86CrtcFuncsRec dummy_crtc_funcs = {
> +    .set_mode_major = dummy_crtc_set_mode_major,
> +    .dpms = dummy_crtc_dpms,
> +};
> +
> +static Bool
>   DUMMYGetRec(ScrnInfoPtr pScrn)
>   {
>       /*
> @@ -283,6 +394,8 @@ DUMMYPreInit(ScrnInfoPtr pScrn, int flags)
>       DUMMYPtr dPtr;
>       int maxClock = 230000;
>       GDevPtr device = xf86GetEntityInfo(pScrn->entityList[0])->device;
> +    xf86OutputPtr output;
> +    xf86CrtcPtr crtc;
>
>       if (flags & PROBE_DETECT)
>   	return TRUE;
> @@ -346,13 +459,6 @@ DUMMYPreInit(ScrnInfoPtr pScrn, int flags)
>       if (!xf86SetDefaultVisual(pScrn, -1))
>   	return FALSE;
>
> -    if (pScrn->depth > 1) {
> -	Gamma zeros = {0.0, 0.0, 0.0};
> -
> -	if (!xf86SetGamma(pScrn, zeros))
> -	    return FALSE;
> -    }
> -
>       xf86CollectOptions(pScrn, device->options);
>       /* Process the options */
>       if (!(dPtr->Options = malloc(sizeof(DUMMYOptions))))
> @@ -382,64 +488,45 @@ DUMMYPreInit(ScrnInfoPtr pScrn, int flags)
>   		   maxClock);
>       }
>
> -    pScrn->progClock = TRUE;
> -    /*
> -     * Setup the ClockRanges, which describe what clock ranges are available,
> -     * and what sort of modes they can be used for.
> -     */
> -    clockRanges = (ClockRangePtr)xnfcalloc(sizeof(ClockRange), 1);
> -    clockRanges->next = NULL;
> -    clockRanges->ClockMulFactor = 1;
> -    clockRanges->minClock = 11000;   /* guessed ยงยงยง */
> -    clockRanges->maxClock = 300000;
> -    clockRanges->clockIndex = -1;		/* programmable */
> -    clockRanges->interlaceAllowed = TRUE;
> -    clockRanges->doubleScanAllowed = TRUE;
> -
> -    /* Subtract memory for HW cursor */
> -
> -
> -    {
> -	int apertureSize = (pScrn->videoRam * 1024);
> -	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
> -			      pScrn->display->modes, clockRanges,
> -			      NULL, 256, DUMMY_MAX_WIDTH,
> -			      (8 * pScrn->bitsPerPixel),
> -			      128, DUMMY_MAX_HEIGHT, pScrn->display->virtualX,
> -			      pScrn->display->virtualY, apertureSize,
> -			      LOOKUP_BEST_REFRESH);
> -
> -       if (i == -1)
> -           RETURN;
> -    }
> +    xf86CrtcConfigInit(pScrn, &dummy_xf86crtc_config_funcs);
> +
> +    xf86CrtcSetSizeRange(pScrn, 256, 256, DUMMY_MAX_WIDTH, DUMMY_MAX_HEIGHT);
> +
> +    crtc = xf86CrtcCreate(pScrn, &dummy_crtc_funcs);
> +
> +    output = xf86OutputCreate(pScrn, &dummy_output_funcs, "default");
> +
> +    output->possible_crtcs = 0x7f;
>
> -    /* Prune the modes marked as invalid */
> -    xf86PruneDriverModes(pScrn);
> +    xf86InitialConfiguration(pScrn, TRUE);
> +
> +    if (pScrn->depth > 1) {
> +	Gamma zeros = {0.0, 0.0, 0.0};
> +
> +	if (!xf86SetGamma(pScrn, zeros))
> +	    return FALSE;
> +    }
>
> -    if (i == 0 || pScrn->modes == NULL) {
> +    if (pScrn->modes == NULL) {
>   	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
>   	RETURN;
>       }
>
> -    /*
> -     * Set the CRTC parameters for all of the modes based on the type
> -     * of mode, and the chipset's interlace requirements.
> -     *
> -     * Calling this is required if the mode->Crtc* values are used by the
> -     * driver and if the driver doesn't provide code to set them.  They
> -     * are not pre-initialised at all.
> -     */
> -    xf86SetCrtcForModes(pScrn, 0);
> -
>       /* Set the current mode to the first in the list */
>       pScrn->currentMode = pScrn->modes;
>
> -    /* Print the list of modes being used */
> -    xf86PrintModes(pScrn);
> +    /* Set default mode in CRTC */
> +    crtc->funcs->set_mode_major(crtc, pScrn->currentMode, RR_Rotate_0, 0, 0);
>
>       /* If monitor resolution is set on the command line, use it */
>       xf86SetDpi(pScrn, 0, 0);
>
> +    /* Set monitor size based on DPI */
> +    output->mm_width = pScrn->xDpi > 0 ?
> +        (pScrn->virtualX * 254 / (10*pScrn->xDpi)) : 0;
> +    output->mm_height = pScrn->yDpi > 0 ?
> +        (pScrn->virtualY * 254 / (10*pScrn->yDpi)) : 0;
> +
>       if (xf86LoadSubModule(pScrn, "fb") == NULL) {
>   	RETURN;
>       }
> @@ -559,6 +646,8 @@ DUMMYScreenInit(SCREEN_INIT_ARGS_DECL)
>
>       if (!miSetPixmapDepths ()) return FALSE;
>
> +    pScrn->displayWidth = pScrn->virtualX;
> +
>       /*
>        * Call the framebuffer layer's ScreenInit function, and fill in other
>        * pScreen fields.
> @@ -597,23 +686,6 @@ DUMMYScreenInit(SCREEN_INIT_ARGS_DECL)
>       if (dPtr->swCursor)
>   	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using Software Cursor.\n");
>
> -    {
> -
> -	
> -	BoxRec AvailFBArea;
> -	int lines = pScrn->videoRam * 1024 /
> -	    (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
> -	AvailFBArea.x1 = 0;
> -	AvailFBArea.y1 = 0;
> -	AvailFBArea.x2 = pScrn->displayWidth;
> -	AvailFBArea.y2 = lines;
> -	xf86InitFBManager(pScreen, &AvailFBArea);
> -	
> -	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
> -		   "Using %i scanlines of offscreen memory \n"
> -		   , lines - pScrn->virtualY);
> -    }
> -
>       xf86SetBackingStore(pScreen);
>       xf86SetSilkenMouse(pScreen);
>   	
> @@ -640,6 +712,9 @@ DUMMYScreenInit(SCREEN_INIT_ARGS_DECL)
>   			     | CMAP_RELOAD_ON_MODE_SWITCH))
>   	return FALSE;
>
> +    if (!xf86CrtcScreenInit(pScreen))
> +        return FALSE;
> +
>   /*     DUMMYInitVideo(pScreen); */
>
>       pScreen->SaveScreen = DUMMYSaveScreen;
>


-- 
Aaron


More information about the xorg-devel mailing list