From 3d68d1f26709ecb5ce22a9baa0d3d8162574ed6a Mon Sep 17 00:00:00 2001 From: Siim Põder Date: Mon, 8 Jun 2015 22:14:12 +0000 Subject: vfb: add randr support (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The motivation for getting this is chrome remote desktop that runs under Xvfb and wants to use RANDR to adjust screen size according to the remote desktop client screen size. Apparently there are other use cases as well, the bug mentions gnome-settings-daemon testing. [ajax: massaged commit message] Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=26391 Reviewed-by: Adam Jackson Signed-off-by: Lambros Lambrou Signed-off-by: Mike Frysinger Signed-off-by: Michal Srb Signed-off-by: Siim Põder --- hw/vfb/InitOutput.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/hw/vfb/InitOutput.c b/hw/vfb/InitOutput.c index 8b867e3b9..9e8dd7a3b 100644 --- a/hw/vfb/InitOutput.c +++ b/hw/vfb/InitOutput.c @@ -66,6 +66,7 @@ from The Open Group. #include "dix.h" #include "miline.h" #include "glx_extinit.h" +#include "randrstr.h" #define VFB_DEFAULT_WIDTH 1280 #define VFB_DEFAULT_HEIGHT 1024 @@ -738,6 +739,125 @@ vfbCloseScreen(ScreenPtr pScreen) return pScreen->CloseScreen(pScreen); } +static Bool +vfbRROutputValidateMode(ScreenPtr pScreen, + RROutputPtr output, + RRModePtr mode) +{ + rrScrPriv(pScreen); + + if (pScrPriv->minWidth <= mode->mode.width && + pScrPriv->maxWidth >= mode->mode.width && + pScrPriv->minHeight <= mode->mode.height && + pScrPriv->maxHeight >= mode->mode.height) + return TRUE; + else + return FALSE; +} + +static Bool +vfbRRScreenSetSize(ScreenPtr pScreen, + CARD16 width, + CARD16 height, + CARD32 mmWidth, + CARD32 mmHeight) +{ + // Prevent screen updates while we change things around + SetRootClip(pScreen, FALSE); + + pScreen->width = width; + pScreen->height = height; + pScreen->mmWidth = mmWidth; + pScreen->mmHeight = mmHeight; + + // Restore the ability to update screen, now with new dimensions + SetRootClip(pScreen, TRUE); + + RRScreenSizeNotify (pScreen); + RRTellChanged(pScreen); + + return TRUE; +} + +static Bool +vfbRRCrtcSet(ScreenPtr pScreen, + RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + int numOutput, + RROutputPtr *outputs) +{ + return RRCrtcNotify(crtc, mode, x, y, rotation, NULL, numOutput, outputs); +} + +static Bool +vfbRRGetInfo(ScreenPtr pScreen, Rotation *rotations) +{ + return TRUE; +} + +static Bool +vfbRandRInit(ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; +#if RANDR_12_INTERFACE + RRModePtr mode; + RRCrtcPtr crtc; + RROutputPtr output; + xRRModeInfo modeInfo; + char name[64]; +#endif + + if (!RRScreenInit (pScreen)) + return FALSE; + pScrPriv = rrGetScrPriv(pScreen); + pScrPriv->rrGetInfo = vfbRRGetInfo; +#if RANDR_12_INTERFACE + pScrPriv->rrCrtcSet = vfbRRCrtcSet; + pScrPriv->rrScreenSetSize = vfbRRScreenSetSize; + pScrPriv->rrOutputSetProperty = NULL; +#if RANDR_13_INTERFACE + pScrPriv->rrOutputGetProperty = NULL; +#endif + pScrPriv->rrOutputValidateMode = vfbRROutputValidateMode; + pScrPriv->rrModeDestroy = NULL; + + RRScreenSetSizeRange (pScreen, + 1, 1, + pScreen->width, pScreen->height); + + sprintf (name, "%dx%d", pScreen->width, pScreen->height); + memset (&modeInfo, '\0', sizeof (modeInfo)); + modeInfo.width = pScreen->width; + modeInfo.height = pScreen->height; + modeInfo.nameLength = strlen (name); + + mode = RRModeGet (&modeInfo, name); + if (!mode) + return FALSE; + + crtc = RRCrtcCreate (pScreen, NULL); + if (!crtc) + return FALSE; + + output = RROutputCreate (pScreen, "screen", 6, NULL); + if (!output) + return FALSE; + if (!RROutputSetClones (output, NULL, 0)) + return FALSE; + if (!RROutputSetModes (output, &mode, 1, 0)) + return FALSE; + if (!RROutputSetCrtcs (output, &crtc, 1)) + return FALSE; + if (!RROutputSetConnection (output, RR_Connected)) + return FALSE; + RRCrtcNotify (crtc, mode, 0, 0, RR_Rotate_0, NULL, 1, &output); +#endif + return TRUE; +} + static Bool vfbScreenInit(ScreenPtr pScreen, int argc, char **argv) { @@ -811,6 +931,9 @@ vfbScreenInit(ScreenPtr pScreen, int argc, char **argv) if (!ret) return FALSE; + if (!vfbRandRInit(pScreen)) + return FALSE; + pScreen->InstallColormap = vfbInstallColormap; pScreen->SaveScreen = vfbSaveScreen; -- cgit v1.2.3