[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