diff --git a/src/dummy.h b/src/dummy.h index c3fdd6e..9c74f56 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 @@ -72,6 +74,12 @@ typedef struct dummyRec pointer* FBBase; 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 2656602..069e330 100644 --- a/src/dummy_driver.c +++ b/src/dummy_driver.c @@ -34,6 +34,8 @@ #include #endif +#include "xf86Crtc.h" + /* * Driver data structures. */ @@ -141,6 +143,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 @@ -568,6 +783,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 */ + #ifdef USE_DGA DUMMYDGAInit(pScreen); #endif