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

Nicolas Boichat drinkcat at chromium.org
Thu Nov 13 10:33:03 PST 2014


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;
+
+    /* videoRam is in kb, divide first to avoid 32-bit int overflow */
+    if ((width*height+1023)/1024*pScrn->bitsPerPixel/8 > pScrn->videoRam)
+        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)) {
+            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,
+};
+
+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;
-- 
2.1.3



More information about the xorg-devel mailing list