From 327a25c4c3ab0b79a1103794449a1f7ccd6faff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Tue, 16 Oct 2018 16:48:47 +0200 Subject: RandR support in dummy video driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Properly initialize RandR extension, mostly with stubs. It creates four virtual outputs (lets hope that nobody will need more at once...). By default only the first one is in "connected" state, with preferred mode from xorg.conf. Other outputs get "connected" at first mode set (and left connected forever - you can always not use it). So without any xrandr calls it should work as before. Signed-off-by: Marek Marczykowski-Górecki --- src/dummy.h | 8 ++ src/dummy_driver.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 273 insertions(+) diff --git a/src/dummy.h b/src/dummy.h index 8e7c43b..a7f0878 100644 --- a/src/dummy.h +++ b/src/dummy.h @@ -13,6 +13,8 @@ #include "compat-api.h" +#define DUMMY_MAX_SCREENS 4 + /* Supported chipsets */ typedef enum { DUMMY_CHIP @@ -52,6 +54,12 @@ typedef struct dummyRec dummy_colors colors[1024]; Bool (*CreateWindow)() ; /* wrapped CreateWindow */ Bool prop; + /* XRANDR support begin */ + int num_screens; + struct _xf86Crtc *paCrtcs[DUMMY_MAX_SCREENS]; + struct _xf86Output *paOutputs[DUMMY_MAX_SCREENS]; + int connected_outputs; + /* XRANDR support end */ } DUMMYRec, *DUMMYPtr; /* The privates of the DUMMY driver */ diff --git a/src/dummy_driver.c b/src/dummy_driver.c index b4b42f7..045de64 100644 --- a/src/dummy_driver.c +++ b/src/dummy_driver.c @@ -29,6 +29,8 @@ #include "picturestr.h" +#include "xf86Crtc.h" + /* * Driver data structures. */ @@ -132,6 +134,219 @@ static XF86ModuleVersionInfo dummyVersRec = {0,0,0,0} }; + +/************************ + * XRANDR support begin * + ************************/ + +static Bool dummy_config_resize(ScrnInfoPtr pScrn, int cw, int ch); +static Bool DUMMYAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height); + +static const xf86CrtcConfigFuncsRec DUMMYCrtcConfigFuncs = { + .resize = dummy_config_resize +}; + + +static void +dummy_crtc_dpms(xf86CrtcPtr crtc, int mode) +{ +} + +static Bool +dummy_crtc_lock (xf86CrtcPtr crtc) +{ + return FALSE; +} + +static Bool +dummy_crtc_mode_fixup (xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +static void +dummy_crtc_stub (xf86CrtcPtr crtc) +{ +} + +static void +dummy_crtc_gamma_set (xf86CrtcPtr crtc, CARD16 *red, + CARD16 *green, CARD16 *blue, int size) +{ +} + +static void * +dummy_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height) +{ + return NULL; +} + +static void +dummy_crtc_mode_set (xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode, int x, int y) +{ +} + +static const xf86CrtcFuncsRec DUMMYCrtcFuncs = { + .dpms = dummy_crtc_dpms, + .save = NULL, /* These two are never called by the server. */ + .restore = NULL, + .lock = dummy_crtc_lock, + .unlock = NULL, /* This will not be invoked if lock returns FALSE. */ + .mode_fixup = dummy_crtc_mode_fixup, + .prepare = dummy_crtc_stub, + .mode_set = dummy_crtc_mode_set, + .commit = dummy_crtc_stub, + .gamma_set = dummy_crtc_gamma_set, + .shadow_allocate = dummy_crtc_shadow_allocate, + .shadow_create = NULL, /* These two should not be invoked if allocate + returns NULL. */ + .shadow_destroy = NULL, + .set_cursor_colors = NULL, + .set_cursor_position = NULL, + .show_cursor = NULL, + .hide_cursor = NULL, + .load_cursor_argb = NULL, + .destroy = dummy_crtc_stub +}; + +static void +dummy_output_stub (xf86OutputPtr output) +{ +} + +static void +dummy_output_dpms (xf86OutputPtr output, int mode) +{ +} + +static int +dummy_output_mode_valid (xf86OutputPtr output, DisplayModePtr mode) +{ + return MODE_OK; +} + +static Bool +dummy_output_mode_fixup (xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +static void +dummy_output_mode_set (xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + DUMMYPtr dPtr = DUMMYPTR(output->scrn); + int index = (int64_t)output->driver_private; + + /* set to connected at first mode set */ + dPtr->connected_outputs |= 1 << index; +} + +/* The first virtual monitor is always connected. Others only after setting its + * mode */ +static xf86OutputStatus +dummy_output_detect (xf86OutputPtr output) +{ + DUMMYPtr dPtr = DUMMYPTR(output->scrn); + int index = (int64_t)output->driver_private; + + if (dPtr->connected_outputs & (1 << index)) + return XF86OutputStatusConnected; + else + return XF86OutputStatusDisconnected; +} + +static DisplayModePtr +dummy_output_get_modes (xf86OutputPtr output) +{ + DisplayModePtr pModes = NULL, pMode, pModeSrc; + + /* copy modes from config */ + for (pModeSrc = output->scrn->modes; pModeSrc; pModeSrc = pModeSrc->next) + { + pMode = xnfcalloc(1, sizeof(DisplayModeRec)); + memcpy(pMode, pModeSrc, sizeof(DisplayModeRec)); + pMode->next = NULL; + pMode->prev = NULL; + pMode->name = strdup(pModeSrc->name); + pModes = xf86ModesAdd(pModes, pMode); + if (pModeSrc->next == output->scrn->modes) + break; + } + return pModes; +} + + +static const xf86OutputFuncsRec DUMMYOutputFuncs = { + .create_resources = dummy_output_stub, + .dpms = dummy_output_dpms, + .save = NULL, /* These two are never called by the server. */ + .restore = NULL, + .mode_valid = dummy_output_mode_valid, + .mode_fixup = dummy_output_mode_fixup, + .prepare = dummy_output_stub, + .commit = dummy_output_stub, + .mode_set = dummy_output_mode_set, + .detect = dummy_output_detect, + .get_modes = dummy_output_get_modes, +#ifdef RANDR_12_INTERFACE + .set_property = NULL, +#endif + .destroy = dummy_output_stub +}; + +static Bool +dummy_config_resize(ScrnInfoPtr pScrn, int cw, int ch) +{ + if (!pScrn->vtSema) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "We do not own the active VT, exiting.\n"); + return TRUE; + } + return DUMMYAdjustScreenPixmap(pScrn, cw, ch); +} + +Bool DUMMYAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height) +{ + ScreenPtr pScreen = pScrn->pScreen; + PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen); + DUMMYPtr dPtr = DUMMYPTR(pScrn); + uint64_t cbLine = (width * xf86GetBppFromDepth(pScrn, pScrn->depth) / 8 + 3) & ~3; + int displayWidth = cbLine * 8 / xf86GetBppFromDepth(pScrn, pScrn->depth); + + if ( width == pScrn->virtualX + && height == pScrn->virtualY + && displayWidth == pScrn->displayWidth) + return TRUE; + if (!pPixmap) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to get the screen pixmap.\n"); + return FALSE; + } + if (cbLine > UINT32_MAX || cbLine * height >= pScrn->videoRam * 1024) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unable to set up a virtual screen size of %dx%d with %d Kb of video memory available. Please increase the video memory size.\n", + width, height, pScrn->videoRam); + return FALSE; + } + pScreen->ModifyPixmapHeader(pPixmap, width, height, + pScrn->depth, xf86GetBppFromDepth(pScrn, pScrn->depth), cbLine, + pPixmap->devPrivate.ptr); + pScrn->virtualX = width; + pScrn->virtualY = height; + pScrn->displayWidth = displayWidth; + + return TRUE; +} + +/********************** + * XRANDR support end * + **********************/ + /* * This is the module init data. * Its name has to be the driver name followed by ModuleData @@ -564,6 +779,56 @@ DUMMYScreenInit(SCREEN_INIT_ARGS_DECL) xf86SetBlackWhitePixels(pScreen); + /* initialize XRANDR */ + xf86CrtcConfigInit(pScrn, &DUMMYCrtcConfigFuncs); + /* FIXME */ + dPtr->num_screens = DUMMY_MAX_SCREENS; + + for (int i=0; i < dPtr->num_screens; i++) { + char szOutput[256]; + + dPtr->paCrtcs[i] = xf86CrtcCreate(pScrn, &DUMMYCrtcFuncs); + dPtr->paCrtcs[i]->driver_private = (void *)(uintptr_t)i; + + /* Set up our virtual outputs. */ + snprintf(szOutput, sizeof(szOutput), "DUMMY%u", i); + dPtr->paOutputs[i] = xf86OutputCreate(pScrn, &DUMMYOutputFuncs, + szOutput); + + + xf86OutputUseScreenMonitor(dPtr->paOutputs[i], FALSE); + dPtr->paOutputs[i]->possible_crtcs = 1 << i; + dPtr->paOutputs[i]->possible_clones = 0; + dPtr->paOutputs[i]->driver_private = (void *)(uintptr_t)i; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Created crtc (%p) and output %s (%p)\n", + (void *)dPtr->paCrtcs[i], szOutput, + (void *)dPtr->paOutputs[i]); + + } + + /* bitmask */ + dPtr->connected_outputs = 1; + + xf86CrtcSetSizeRange(pScrn, 64, 64, DUMMY_MAX_WIDTH, DUMMY_MAX_HEIGHT); + + + /* Now create our initial CRTC/output configuration. */ + if (!xf86InitialConfiguration(pScrn, TRUE)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Initial CRTC configuration failed!\n"); + return (FALSE); + } + + /* Initialise randr 1.2 mode-setting functions and set first mode. + * Note that the mode won't be usable until the server has resized the + * framebuffer to something reasonable. */ + if (!xf86CrtcScreenInit(pScreen)) { + return FALSE; + } + if (!xf86SetDesiredModes(pScrn)) { + return FALSE; + } + + /* XRANDR initialization end */ if (dPtr->swCursor) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using Software Cursor.\n"); -- cgit v1.2.3