rrscreen.c revision b86d567b
105b261ecSmrg/* 205b261ecSmrg * Copyright © 2006 Keith Packard 305b261ecSmrg * 405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 605b261ecSmrg * the above copyright notice appear in all copies and that both that copyright 705b261ecSmrg * notice and this permission notice appear in supporting documentation, and 805b261ecSmrg * that the name of the copyright holders not be used in advertising or 905b261ecSmrg * publicity pertaining to distribution of the software without specific, 1005b261ecSmrg * written prior permission. The copyright holders make no representations 1105b261ecSmrg * about the suitability of this software for any purpose. It is provided "as 1205b261ecSmrg * is" without express or implied warranty. 1305b261ecSmrg * 1405b261ecSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1605b261ecSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2005b261ecSmrg * OF THIS SOFTWARE. 2105b261ecSmrg */ 2205b261ecSmrg 2305b261ecSmrg#include "randrstr.h" 2405b261ecSmrg 254642e01fSmrgstatic const int padlength[4] = {0, 3, 2, 1}; 2605b261ecSmrg 2705b261ecSmrgstatic CARD16 2805b261ecSmrgRR10CurrentSizeID (ScreenPtr pScreen); 2905b261ecSmrg 3005b261ecSmrg/* 3105b261ecSmrg * Edit connection information block so that new clients 3205b261ecSmrg * see the current screen size on connect 3305b261ecSmrg */ 3405b261ecSmrgstatic void 3505b261ecSmrgRREditConnectionInfo (ScreenPtr pScreen) 3605b261ecSmrg{ 3705b261ecSmrg xConnSetup *connSetup; 3805b261ecSmrg char *vendor; 3905b261ecSmrg xPixmapFormat *formats; 4005b261ecSmrg xWindowRoot *root; 4105b261ecSmrg xDepth *depth; 4205b261ecSmrg xVisualType *visual; 4305b261ecSmrg int screen = 0; 4405b261ecSmrg int d; 4505b261ecSmrg 4605b261ecSmrg connSetup = (xConnSetup *) ConnectionInfo; 4705b261ecSmrg vendor = (char *) connSetup + sizeof (xConnSetup); 4805b261ecSmrg formats = (xPixmapFormat *) ((char *) vendor + 4905b261ecSmrg connSetup->nbytesVendor + 5005b261ecSmrg padlength[connSetup->nbytesVendor & 3]); 5105b261ecSmrg root = (xWindowRoot *) ((char *) formats + 5205b261ecSmrg sizeof (xPixmapFormat) * screenInfo.numPixmapFormats); 5305b261ecSmrg while (screen != pScreen->myNum) 5405b261ecSmrg { 5505b261ecSmrg depth = (xDepth *) ((char *) root + 5605b261ecSmrg sizeof (xWindowRoot)); 5705b261ecSmrg for (d = 0; d < root->nDepths; d++) 5805b261ecSmrg { 5905b261ecSmrg visual = (xVisualType *) ((char *) depth + 6005b261ecSmrg sizeof (xDepth)); 6105b261ecSmrg depth = (xDepth *) ((char *) visual + 6205b261ecSmrg depth->nVisuals * sizeof (xVisualType)); 6305b261ecSmrg } 6405b261ecSmrg root = (xWindowRoot *) ((char *) depth); 6505b261ecSmrg screen++; 6605b261ecSmrg } 6705b261ecSmrg root->pixWidth = pScreen->width; 6805b261ecSmrg root->pixHeight = pScreen->height; 6905b261ecSmrg root->mmWidth = pScreen->mmWidth; 7005b261ecSmrg root->mmHeight = pScreen->mmHeight; 7105b261ecSmrg} 7205b261ecSmrg 7305b261ecSmrgvoid 7405b261ecSmrgRRSendConfigNotify (ScreenPtr pScreen) 7505b261ecSmrg{ 7605b261ecSmrg WindowPtr pWin = WindowTable[pScreen->myNum]; 7705b261ecSmrg xEvent event; 7805b261ecSmrg 7905b261ecSmrg event.u.u.type = ConfigureNotify; 8005b261ecSmrg event.u.configureNotify.window = pWin->drawable.id; 8105b261ecSmrg event.u.configureNotify.aboveSibling = None; 8205b261ecSmrg event.u.configureNotify.x = 0; 8305b261ecSmrg event.u.configureNotify.y = 0; 8405b261ecSmrg 8505b261ecSmrg /* XXX xinerama stuff ? */ 8605b261ecSmrg 8705b261ecSmrg event.u.configureNotify.width = pWin->drawable.width; 8805b261ecSmrg event.u.configureNotify.height = pWin->drawable.height; 8905b261ecSmrg event.u.configureNotify.borderWidth = wBorderWidth (pWin); 9005b261ecSmrg event.u.configureNotify.override = pWin->overrideRedirect; 9105b261ecSmrg DeliverEvents(pWin, &event, 1, NullWindow); 9205b261ecSmrg} 9305b261ecSmrg 9405b261ecSmrgvoid 9505b261ecSmrgRRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen) 9605b261ecSmrg{ 9705b261ecSmrg rrScrPriv (pScreen); 9805b261ecSmrg xRRScreenChangeNotifyEvent se; 9905b261ecSmrg RRCrtcPtr crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL; 10005b261ecSmrg WindowPtr pRoot = WindowTable[pScreen->myNum]; 10105b261ecSmrg 10205b261ecSmrg se.type = RRScreenChangeNotify + RREventBase; 10305b261ecSmrg se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0); 10405b261ecSmrg se.timestamp = pScrPriv->lastSetTime.milliseconds; 10505b261ecSmrg se.sequenceNumber = client->sequence; 10605b261ecSmrg se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 10705b261ecSmrg se.root = pRoot->drawable.id; 10805b261ecSmrg se.window = pWin->drawable.id; 10905b261ecSmrg#ifdef RENDER 11005b261ecSmrg se.subpixelOrder = PictureGetSubpixelOrder (pScreen); 11105b261ecSmrg#else 11205b261ecSmrg se.subpixelOrder = SubPixelUnknown; 11305b261ecSmrg#endif 11405b261ecSmrg 11505b261ecSmrg se.sequenceNumber = client->sequence; 11605b261ecSmrg se.sizeID = RR10CurrentSizeID (pScreen); 11705b261ecSmrg 11805b261ecSmrg if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) { 11905b261ecSmrg se.widthInPixels = pScreen->height; 12005b261ecSmrg se.heightInPixels = pScreen->width; 12105b261ecSmrg se.widthInMillimeters = pScreen->mmHeight; 12205b261ecSmrg se.heightInMillimeters = pScreen->mmWidth; 12305b261ecSmrg } else { 12405b261ecSmrg se.widthInPixels = pScreen->width; 12505b261ecSmrg se.heightInPixels = pScreen->height; 12605b261ecSmrg se.widthInMillimeters = pScreen->mmWidth; 12705b261ecSmrg se.heightInMillimeters = pScreen->mmHeight; 12805b261ecSmrg } 12905b261ecSmrg 13005b261ecSmrg WriteEventsToClient (client, 1, (xEvent *) &se); 13105b261ecSmrg} 13205b261ecSmrg 13305b261ecSmrg/* 13405b261ecSmrg * Notify the extension that the screen size has been changed. 13505b261ecSmrg * The driver is responsible for calling this whenever it has changed 13605b261ecSmrg * the size of the screen 13705b261ecSmrg */ 13805b261ecSmrgvoid 13905b261ecSmrgRRScreenSizeNotify (ScreenPtr pScreen) 14005b261ecSmrg{ 14105b261ecSmrg rrScrPriv(pScreen); 14205b261ecSmrg /* 14305b261ecSmrg * Deliver ConfigureNotify events when root changes 14405b261ecSmrg * pixel size 14505b261ecSmrg */ 14605b261ecSmrg if (pScrPriv->width == pScreen->width && 14705b261ecSmrg pScrPriv->height == pScreen->height && 14805b261ecSmrg pScrPriv->mmWidth == pScreen->mmWidth && 14905b261ecSmrg pScrPriv->mmHeight == pScreen->mmHeight) 15005b261ecSmrg return; 15105b261ecSmrg 15205b261ecSmrg pScrPriv->width = pScreen->width; 15305b261ecSmrg pScrPriv->height = pScreen->height; 15405b261ecSmrg pScrPriv->mmWidth = pScreen->mmWidth; 15505b261ecSmrg pScrPriv->mmHeight = pScreen->mmHeight; 15605b261ecSmrg pScrPriv->changed = TRUE; 15705b261ecSmrg/* pScrPriv->sizeChanged = TRUE; */ 15805b261ecSmrg 15905b261ecSmrg RRTellChanged (pScreen); 16005b261ecSmrg RRSendConfigNotify (pScreen); 16105b261ecSmrg RREditConnectionInfo (pScreen); 16205b261ecSmrg 16305b261ecSmrg RRPointerScreenConfigured (pScreen); 16405b261ecSmrg /* 16505b261ecSmrg * Fix pointer bounds and location 16605b261ecSmrg */ 16705b261ecSmrg ScreenRestructured (pScreen); 16805b261ecSmrg} 16905b261ecSmrg 17005b261ecSmrg/* 17105b261ecSmrg * Request that the screen be resized 17205b261ecSmrg */ 17305b261ecSmrgBool 17405b261ecSmrgRRScreenSizeSet (ScreenPtr pScreen, 17505b261ecSmrg CARD16 width, 17605b261ecSmrg CARD16 height, 17705b261ecSmrg CARD32 mmWidth, 17805b261ecSmrg CARD32 mmHeight) 17905b261ecSmrg{ 18005b261ecSmrg rrScrPriv(pScreen); 18105b261ecSmrg 18205b261ecSmrg#if RANDR_12_INTERFACE 18305b261ecSmrg if (pScrPriv->rrScreenSetSize) 18405b261ecSmrg { 18505b261ecSmrg return (*pScrPriv->rrScreenSetSize) (pScreen, 18605b261ecSmrg width, height, 18705b261ecSmrg mmWidth, mmHeight); 18805b261ecSmrg } 18905b261ecSmrg#endif 19005b261ecSmrg#if RANDR_10_INTERFACE 19105b261ecSmrg if (pScrPriv->rrSetConfig) 19205b261ecSmrg { 19305b261ecSmrg return TRUE; /* can't set size separately */ 19405b261ecSmrg } 19505b261ecSmrg#endif 19605b261ecSmrg return FALSE; 19705b261ecSmrg} 19805b261ecSmrg 19905b261ecSmrg/* 20005b261ecSmrg * Retrieve valid screen size range 20105b261ecSmrg */ 20205b261ecSmrgint 20305b261ecSmrgProcRRGetScreenSizeRange (ClientPtr client) 20405b261ecSmrg{ 20505b261ecSmrg REQUEST(xRRGetScreenSizeRangeReq); 20605b261ecSmrg xRRGetScreenSizeRangeReply rep; 20705b261ecSmrg WindowPtr pWin; 20805b261ecSmrg ScreenPtr pScreen; 20905b261ecSmrg rrScrPrivPtr pScrPriv; 21005b261ecSmrg int rc; 21105b261ecSmrg 21205b261ecSmrg REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); 21305b261ecSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); 21405b261ecSmrg if (rc != Success) 21505b261ecSmrg return rc; 21605b261ecSmrg 21705b261ecSmrg pScreen = pWin->drawable.pScreen; 21805b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 21905b261ecSmrg 22005b261ecSmrg rep.type = X_Reply; 22105b261ecSmrg rep.pad = 0; 22205b261ecSmrg rep.sequenceNumber = client->sequence; 22305b261ecSmrg rep.length = 0; 22405b261ecSmrg 22505b261ecSmrg if (pScrPriv) 22605b261ecSmrg { 2274642e01fSmrg if (!RRGetInfo (pScreen, FALSE)) 22805b261ecSmrg return BadAlloc; 22905b261ecSmrg rep.minWidth = pScrPriv->minWidth; 23005b261ecSmrg rep.minHeight = pScrPriv->minHeight; 23105b261ecSmrg rep.maxWidth = pScrPriv->maxWidth; 23205b261ecSmrg rep.maxHeight = pScrPriv->maxHeight; 23305b261ecSmrg } 23405b261ecSmrg else 23505b261ecSmrg { 23605b261ecSmrg rep.maxWidth = rep.minWidth = pScreen->width; 23705b261ecSmrg rep.maxHeight = rep.minHeight = pScreen->height; 23805b261ecSmrg } 23905b261ecSmrg if (client->swapped) 24005b261ecSmrg { 24105b261ecSmrg int n; 24205b261ecSmrg 24305b261ecSmrg swaps(&rep.sequenceNumber, n); 24405b261ecSmrg swapl(&rep.length, n); 24505b261ecSmrg swaps(&rep.minWidth, n); 24605b261ecSmrg swaps(&rep.minHeight, n); 24705b261ecSmrg swaps(&rep.maxWidth, n); 24805b261ecSmrg swaps(&rep.maxHeight, n); 24905b261ecSmrg } 25005b261ecSmrg WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), (char *)&rep); 25105b261ecSmrg return (client->noClientException); 25205b261ecSmrg} 25305b261ecSmrg 25405b261ecSmrgint 25505b261ecSmrgProcRRSetScreenSize (ClientPtr client) 25605b261ecSmrg{ 25705b261ecSmrg REQUEST(xRRSetScreenSizeReq); 25805b261ecSmrg WindowPtr pWin; 25905b261ecSmrg ScreenPtr pScreen; 26005b261ecSmrg rrScrPrivPtr pScrPriv; 26105b261ecSmrg int i, rc; 26205b261ecSmrg 26305b261ecSmrg REQUEST_SIZE_MATCH(xRRSetScreenSizeReq); 26405b261ecSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); 26505b261ecSmrg if (rc != Success) 26605b261ecSmrg return rc; 26705b261ecSmrg 26805b261ecSmrg pScreen = pWin->drawable.pScreen; 26905b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 27005b261ecSmrg if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width) 27105b261ecSmrg { 27205b261ecSmrg client->errorValue = stuff->width; 27305b261ecSmrg return BadValue; 27405b261ecSmrg } 27505b261ecSmrg if (stuff->height < pScrPriv->minHeight || 27605b261ecSmrg pScrPriv->maxHeight < stuff->height) 27705b261ecSmrg { 27805b261ecSmrg client->errorValue = stuff->height; 27905b261ecSmrg return BadValue; 28005b261ecSmrg } 28105b261ecSmrg for (i = 0; i < pScrPriv->numCrtcs; i++) 28205b261ecSmrg { 28305b261ecSmrg RRCrtcPtr crtc = pScrPriv->crtcs[i]; 28405b261ecSmrg RRModePtr mode = crtc->mode; 28505b261ecSmrg if (mode) 28605b261ecSmrg { 28705b261ecSmrg int source_width = mode->mode.width; 28805b261ecSmrg int source_height = mode->mode.height; 28905b261ecSmrg Rotation rotation = crtc->rotation; 29005b261ecSmrg 29105b261ecSmrg if (rotation == RR_Rotate_90 || rotation == RR_Rotate_270) 29205b261ecSmrg { 29305b261ecSmrg source_width = mode->mode.height; 29405b261ecSmrg source_height = mode->mode.width; 29505b261ecSmrg } 29605b261ecSmrg 29705b261ecSmrg if (crtc->x + source_width > stuff->width || 29805b261ecSmrg crtc->y + source_height > stuff->height) 29905b261ecSmrg return BadMatch; 30005b261ecSmrg } 30105b261ecSmrg } 30205b261ecSmrg if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0) 30305b261ecSmrg { 30405b261ecSmrg client->errorValue = 0; 30505b261ecSmrg return BadValue; 30605b261ecSmrg } 30705b261ecSmrg if (!RRScreenSizeSet (pScreen, 30805b261ecSmrg stuff->width, stuff->height, 30905b261ecSmrg stuff->widthInMillimeters, 31005b261ecSmrg stuff->heightInMillimeters)) 31105b261ecSmrg { 31205b261ecSmrg return BadMatch; 31305b261ecSmrg } 31405b261ecSmrg return Success; 31505b261ecSmrg} 31605b261ecSmrg 3174642e01fSmrgstatic int 3184642e01fSmrgrrGetScreenResources(ClientPtr client, Bool query) 31905b261ecSmrg{ 32005b261ecSmrg REQUEST(xRRGetScreenResourcesReq); 32105b261ecSmrg xRRGetScreenResourcesReply rep; 32205b261ecSmrg WindowPtr pWin; 32305b261ecSmrg ScreenPtr pScreen; 32405b261ecSmrg rrScrPrivPtr pScrPriv; 32505b261ecSmrg CARD8 *extra; 32605b261ecSmrg unsigned long extraLen; 3274642e01fSmrg int i, n, rc, has_primary = 0; 32805b261ecSmrg RRCrtc *crtcs; 32905b261ecSmrg RROutput *outputs; 33005b261ecSmrg xRRModeInfo *modeinfos; 33105b261ecSmrg CARD8 *names; 33205b261ecSmrg 33305b261ecSmrg REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq); 33405b261ecSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); 33505b261ecSmrg if (rc != Success) 33605b261ecSmrg return rc; 33705b261ecSmrg 33805b261ecSmrg pScreen = pWin->drawable.pScreen; 33905b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 34005b261ecSmrg rep.pad = 0; 34105b261ecSmrg 3424642e01fSmrg if (query && pScrPriv) 3434642e01fSmrg if (!RRGetInfo (pScreen, query)) 34405b261ecSmrg return BadAlloc; 34505b261ecSmrg 34605b261ecSmrg if (!pScrPriv) 34705b261ecSmrg { 34805b261ecSmrg rep.type = X_Reply; 34905b261ecSmrg rep.sequenceNumber = client->sequence; 35005b261ecSmrg rep.length = 0; 35105b261ecSmrg rep.timestamp = currentTime.milliseconds; 35205b261ecSmrg rep.configTimestamp = currentTime.milliseconds; 35305b261ecSmrg rep.nCrtcs = 0; 35405b261ecSmrg rep.nOutputs = 0; 35505b261ecSmrg rep.nModes = 0; 35605b261ecSmrg rep.nbytesNames = 0; 35705b261ecSmrg extra = NULL; 35805b261ecSmrg extraLen = 0; 35905b261ecSmrg } 36005b261ecSmrg else 36105b261ecSmrg { 36205b261ecSmrg RRModePtr *modes; 36305b261ecSmrg int num_modes; 36405b261ecSmrg 36505b261ecSmrg modes = RRModesForScreen (pScreen, &num_modes); 36605b261ecSmrg if (!modes) 36705b261ecSmrg return BadAlloc; 36805b261ecSmrg 36905b261ecSmrg rep.type = X_Reply; 37005b261ecSmrg rep.sequenceNumber = client->sequence; 37105b261ecSmrg rep.length = 0; 37205b261ecSmrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 37305b261ecSmrg rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 37405b261ecSmrg rep.nCrtcs = pScrPriv->numCrtcs; 37505b261ecSmrg rep.nOutputs = pScrPriv->numOutputs; 37605b261ecSmrg rep.nModes = num_modes; 37705b261ecSmrg rep.nbytesNames = 0; 37805b261ecSmrg 37905b261ecSmrg for (i = 0; i < num_modes; i++) 38005b261ecSmrg rep.nbytesNames += modes[i]->mode.nameLength; 38105b261ecSmrg 38205b261ecSmrg rep.length = (pScrPriv->numCrtcs + 38305b261ecSmrg pScrPriv->numOutputs + 38405b261ecSmrg num_modes * (SIZEOF(xRRModeInfo) >> 2) + 38505b261ecSmrg ((rep.nbytesNames + 3) >> 2)); 38605b261ecSmrg 38705b261ecSmrg extraLen = rep.length << 2; 38805b261ecSmrg if (extraLen) 38905b261ecSmrg { 39005b261ecSmrg extra = xalloc (extraLen); 39105b261ecSmrg if (!extra) 39205b261ecSmrg { 39305b261ecSmrg xfree (modes); 39405b261ecSmrg return BadAlloc; 39505b261ecSmrg } 39605b261ecSmrg } 39705b261ecSmrg else 39805b261ecSmrg extra = NULL; 39905b261ecSmrg 40005b261ecSmrg crtcs = (RRCrtc *) extra; 40105b261ecSmrg outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs); 40205b261ecSmrg modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs); 40305b261ecSmrg names = (CARD8 *) (modeinfos + num_modes); 4044642e01fSmrg 4054642e01fSmrg if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) 4064642e01fSmrg { 4074642e01fSmrg has_primary = 1; 4084642e01fSmrg crtcs[0] = pScrPriv->primaryOutput->crtc->id; 4094642e01fSmrg if (client->swapped) 4104642e01fSmrg swapl (&crtcs[0], n); 4114642e01fSmrg } 41205b261ecSmrg 41305b261ecSmrg for (i = 0; i < pScrPriv->numCrtcs; i++) 41405b261ecSmrg { 4154642e01fSmrg if (has_primary && 4164642e01fSmrg pScrPriv->primaryOutput->crtc == pScrPriv->crtcs[i]) 4174642e01fSmrg { 4184642e01fSmrg has_primary = 0; 4194642e01fSmrg continue; 4204642e01fSmrg } 4214642e01fSmrg crtcs[i + has_primary] = pScrPriv->crtcs[i]->id; 42205b261ecSmrg if (client->swapped) 4234642e01fSmrg swapl (&crtcs[i + has_primary], n); 42405b261ecSmrg } 42505b261ecSmrg 42605b261ecSmrg for (i = 0; i < pScrPriv->numOutputs; i++) 42705b261ecSmrg { 42805b261ecSmrg outputs[i] = pScrPriv->outputs[i]->id; 42905b261ecSmrg if (client->swapped) 43005b261ecSmrg swapl (&outputs[i], n); 43105b261ecSmrg } 43205b261ecSmrg 43305b261ecSmrg for (i = 0; i < num_modes; i++) 43405b261ecSmrg { 43505b261ecSmrg RRModePtr mode = modes[i]; 43605b261ecSmrg modeinfos[i] = mode->mode; 43705b261ecSmrg if (client->swapped) 43805b261ecSmrg { 43905b261ecSmrg swapl (&modeinfos[i].id, n); 44005b261ecSmrg swaps (&modeinfos[i].width, n); 44105b261ecSmrg swaps (&modeinfos[i].height, n); 44205b261ecSmrg swapl (&modeinfos[i].dotClock, n); 44305b261ecSmrg swaps (&modeinfos[i].hSyncStart, n); 44405b261ecSmrg swaps (&modeinfos[i].hSyncEnd, n); 44505b261ecSmrg swaps (&modeinfos[i].hTotal, n); 44605b261ecSmrg swaps (&modeinfos[i].hSkew, n); 44705b261ecSmrg swaps (&modeinfos[i].vSyncStart, n); 44805b261ecSmrg swaps (&modeinfos[i].vSyncEnd, n); 44905b261ecSmrg swaps (&modeinfos[i].vTotal, n); 45005b261ecSmrg swaps (&modeinfos[i].nameLength, n); 45105b261ecSmrg swapl (&modeinfos[i].modeFlags, n); 45205b261ecSmrg } 45305b261ecSmrg memcpy (names, mode->name, 45405b261ecSmrg mode->mode.nameLength); 45505b261ecSmrg names += mode->mode.nameLength; 45605b261ecSmrg } 45705b261ecSmrg xfree (modes); 45805b261ecSmrg assert (((((char *) names - (char *) extra) + 3) >> 2) == rep.length); 45905b261ecSmrg } 46005b261ecSmrg 46105b261ecSmrg if (client->swapped) { 46205b261ecSmrg swaps(&rep.sequenceNumber, n); 46305b261ecSmrg swapl(&rep.length, n); 46405b261ecSmrg swapl(&rep.timestamp, n); 46505b261ecSmrg swapl(&rep.configTimestamp, n); 46605b261ecSmrg swaps(&rep.nCrtcs, n); 46705b261ecSmrg swaps(&rep.nOutputs, n); 46805b261ecSmrg swaps(&rep.nModes, n); 46905b261ecSmrg swaps(&rep.nbytesNames, n); 47005b261ecSmrg } 47105b261ecSmrg WriteToClient(client, sizeof(xRRGetScreenResourcesReply), (char *)&rep); 47205b261ecSmrg if (extraLen) 47305b261ecSmrg { 47405b261ecSmrg WriteToClient (client, extraLen, (char *) extra); 47505b261ecSmrg xfree (extra); 47605b261ecSmrg } 47705b261ecSmrg return client->noClientException; 47805b261ecSmrg} 47905b261ecSmrg 4804642e01fSmrgint 4814642e01fSmrgProcRRGetScreenResources (ClientPtr client) 4824642e01fSmrg{ 4834642e01fSmrg return rrGetScreenResources(client, TRUE); 4844642e01fSmrg} 4854642e01fSmrg 4864642e01fSmrgint 4874642e01fSmrgProcRRGetScreenResourcesCurrent (ClientPtr client) 4884642e01fSmrg{ 4894642e01fSmrg return rrGetScreenResources(client, FALSE); 4904642e01fSmrg} 4914642e01fSmrg 49205b261ecSmrgtypedef struct _RR10Data { 49305b261ecSmrg RRScreenSizePtr sizes; 49405b261ecSmrg int nsize; 49505b261ecSmrg int nrefresh; 49605b261ecSmrg int size; 49705b261ecSmrg CARD16 refresh; 49805b261ecSmrg} RR10DataRec, *RR10DataPtr; 49905b261ecSmrg 50005b261ecSmrg/* 50105b261ecSmrg * Convert 1.2 monitor data into 1.0 screen data 50205b261ecSmrg */ 50305b261ecSmrgstatic RR10DataPtr 50405b261ecSmrgRR10GetData (ScreenPtr pScreen, RROutputPtr output) 50505b261ecSmrg{ 50605b261ecSmrg RR10DataPtr data; 50705b261ecSmrg RRScreenSizePtr size; 50805b261ecSmrg int nmode = output->numModes + output->numUserModes; 50905b261ecSmrg int o, os, l, r; 51005b261ecSmrg RRScreenRatePtr refresh; 51105b261ecSmrg CARD16 vRefresh; 51205b261ecSmrg RRModePtr mode; 51305b261ecSmrg Bool *used; 51405b261ecSmrg 51505b261ecSmrg /* Make sure there is plenty of space for any combination */ 51605b261ecSmrg data = malloc (sizeof (RR10DataRec) + 51705b261ecSmrg sizeof (RRScreenSize) * nmode + 51805b261ecSmrg sizeof (RRScreenRate) * nmode + 51905b261ecSmrg sizeof (Bool) * nmode); 52005b261ecSmrg if (!data) 52105b261ecSmrg return NULL; 52205b261ecSmrg size = (RRScreenSizePtr) (data + 1); 52305b261ecSmrg refresh = (RRScreenRatePtr) (size + nmode); 52405b261ecSmrg used = (Bool *) (refresh + nmode); 52505b261ecSmrg memset (used, '\0', sizeof (Bool) * nmode); 52605b261ecSmrg data->sizes = size; 52705b261ecSmrg data->nsize = 0; 52805b261ecSmrg data->nrefresh = 0; 52905b261ecSmrg data->size = 0; 53005b261ecSmrg data->refresh = 0; 53105b261ecSmrg 53205b261ecSmrg /* 53305b261ecSmrg * find modes not yet listed 53405b261ecSmrg */ 53505b261ecSmrg for (o = 0; o < output->numModes + output->numUserModes; o++) 53605b261ecSmrg { 53705b261ecSmrg if (used[o]) continue; 53805b261ecSmrg 53905b261ecSmrg if (o < output->numModes) 54005b261ecSmrg mode = output->modes[o]; 54105b261ecSmrg else 54205b261ecSmrg mode = output->userModes[o - output->numModes]; 54305b261ecSmrg 54405b261ecSmrg l = data->nsize; 54505b261ecSmrg size[l].id = data->nsize; 54605b261ecSmrg size[l].width = mode->mode.width; 54705b261ecSmrg size[l].height = mode->mode.height; 54805b261ecSmrg if (output->mmWidth && output->mmHeight) { 54905b261ecSmrg size[l].mmWidth = output->mmWidth; 55005b261ecSmrg size[l].mmHeight = output->mmHeight; 55105b261ecSmrg } else { 55205b261ecSmrg size[l].mmWidth = pScreen->mmWidth; 55305b261ecSmrg size[l].mmHeight = pScreen->mmHeight; 55405b261ecSmrg } 55505b261ecSmrg size[l].nRates = 0; 55605b261ecSmrg size[l].pRates = &refresh[data->nrefresh]; 55705b261ecSmrg data->nsize++; 55805b261ecSmrg 55905b261ecSmrg /* 56005b261ecSmrg * Find all modes with matching size 56105b261ecSmrg */ 56205b261ecSmrg for (os = o; os < output->numModes + output->numUserModes; os++) 56305b261ecSmrg { 56405b261ecSmrg if (os < output->numModes) 56505b261ecSmrg mode = output->modes[os]; 56605b261ecSmrg else 56705b261ecSmrg mode = output->userModes[os - output->numModes]; 56805b261ecSmrg if (mode->mode.width == size[l].width && 56905b261ecSmrg mode->mode.height == size[l].height) 57005b261ecSmrg { 57105b261ecSmrg vRefresh = RRVerticalRefresh (&mode->mode); 57205b261ecSmrg used[os] = TRUE; 57305b261ecSmrg 57405b261ecSmrg for (r = 0; r < size[l].nRates; r++) 57505b261ecSmrg if (vRefresh == size[l].pRates[r].rate) 57605b261ecSmrg break; 57705b261ecSmrg if (r == size[l].nRates) 57805b261ecSmrg { 57905b261ecSmrg size[l].pRates[r].rate = vRefresh; 58005b261ecSmrg size[l].pRates[r].mode = mode; 58105b261ecSmrg size[l].nRates++; 58205b261ecSmrg data->nrefresh++; 58305b261ecSmrg } 58405b261ecSmrg if (mode == output->crtc->mode) 58505b261ecSmrg { 58605b261ecSmrg data->size = l; 58705b261ecSmrg data->refresh = vRefresh; 58805b261ecSmrg } 58905b261ecSmrg } 59005b261ecSmrg } 59105b261ecSmrg } 59205b261ecSmrg return data; 59305b261ecSmrg} 59405b261ecSmrg 59505b261ecSmrgint 59605b261ecSmrgProcRRGetScreenInfo (ClientPtr client) 59705b261ecSmrg{ 59805b261ecSmrg REQUEST(xRRGetScreenInfoReq); 59905b261ecSmrg xRRGetScreenInfoReply rep; 60005b261ecSmrg WindowPtr pWin; 60105b261ecSmrg int n, rc; 60205b261ecSmrg ScreenPtr pScreen; 60305b261ecSmrg rrScrPrivPtr pScrPriv; 60405b261ecSmrg CARD8 *extra; 60505b261ecSmrg unsigned long extraLen; 60605b261ecSmrg RROutputPtr output; 60705b261ecSmrg 60805b261ecSmrg REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); 60905b261ecSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); 61005b261ecSmrg if (rc != Success) 61105b261ecSmrg return rc; 61205b261ecSmrg 61305b261ecSmrg pScreen = pWin->drawable.pScreen; 61405b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 61505b261ecSmrg rep.pad = 0; 61605b261ecSmrg 61705b261ecSmrg if (pScrPriv) 6184642e01fSmrg if (!RRGetInfo (pScreen, TRUE)) 61905b261ecSmrg return BadAlloc; 62005b261ecSmrg 62105b261ecSmrg output = RRFirstOutput (pScreen); 62205b261ecSmrg 62305b261ecSmrg if (!pScrPriv || !output) 62405b261ecSmrg { 62505b261ecSmrg rep.type = X_Reply; 6264642e01fSmrg rep.setOfRotations = RR_Rotate_0; 62705b261ecSmrg rep.sequenceNumber = client->sequence; 62805b261ecSmrg rep.length = 0; 62905b261ecSmrg rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; 63005b261ecSmrg rep.timestamp = currentTime.milliseconds; 63105b261ecSmrg rep.configTimestamp = currentTime.milliseconds; 63205b261ecSmrg rep.nSizes = 0; 63305b261ecSmrg rep.sizeID = 0; 63405b261ecSmrg rep.rotation = RR_Rotate_0; 63505b261ecSmrg rep.rate = 0; 63605b261ecSmrg rep.nrateEnts = 0; 63705b261ecSmrg extra = 0; 63805b261ecSmrg extraLen = 0; 63905b261ecSmrg } 64005b261ecSmrg else 64105b261ecSmrg { 64205b261ecSmrg int i, j; 64305b261ecSmrg xScreenSizes *size; 64405b261ecSmrg CARD16 *rates; 64505b261ecSmrg CARD8 *data8; 64605b261ecSmrg Bool has_rate = RRClientKnowsRates (client); 64705b261ecSmrg RR10DataPtr pData; 64805b261ecSmrg RRScreenSizePtr pSize; 64905b261ecSmrg 65005b261ecSmrg pData = RR10GetData (pScreen, output); 65105b261ecSmrg if (!pData) 65205b261ecSmrg return BadAlloc; 65305b261ecSmrg 65405b261ecSmrg rep.type = X_Reply; 65505b261ecSmrg rep.setOfRotations = output->crtc->rotations; 65605b261ecSmrg rep.sequenceNumber = client->sequence; 65705b261ecSmrg rep.length = 0; 65805b261ecSmrg rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; 65905b261ecSmrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 66005b261ecSmrg rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 66105b261ecSmrg rep.rotation = output->crtc->rotation; 66205b261ecSmrg rep.nSizes = pData->nsize; 66305b261ecSmrg rep.nrateEnts = pData->nrefresh + pData->nsize; 66405b261ecSmrg rep.sizeID = pData->size; 66505b261ecSmrg rep.rate = pData->refresh; 66605b261ecSmrg 667b86d567bSmrg extraLen = rep.nSizes * sizeof (xScreenSizes); 668b86d567bSmrg if (has_rate) 669b86d567bSmrg extraLen += rep.nrateEnts * sizeof (CARD16); 67005b261ecSmrg 67105b261ecSmrg if (extraLen) 67205b261ecSmrg { 67305b261ecSmrg extra = (CARD8 *) xalloc (extraLen); 67405b261ecSmrg if (!extra) 67505b261ecSmrg { 67605b261ecSmrg xfree (pData); 67705b261ecSmrg return BadAlloc; 67805b261ecSmrg } 67905b261ecSmrg } 68005b261ecSmrg else 68105b261ecSmrg extra = NULL; 68205b261ecSmrg 68305b261ecSmrg /* 68405b261ecSmrg * First comes the size information 68505b261ecSmrg */ 68605b261ecSmrg size = (xScreenSizes *) extra; 68705b261ecSmrg rates = (CARD16 *) (size + rep.nSizes); 68805b261ecSmrg for (i = 0; i < pData->nsize; i++) 68905b261ecSmrg { 69005b261ecSmrg pSize = &pData->sizes[i]; 69105b261ecSmrg size->widthInPixels = pSize->width; 69205b261ecSmrg size->heightInPixels = pSize->height; 69305b261ecSmrg size->widthInMillimeters = pSize->mmWidth; 69405b261ecSmrg size->heightInMillimeters = pSize->mmHeight; 69505b261ecSmrg if (client->swapped) 69605b261ecSmrg { 69705b261ecSmrg swaps (&size->widthInPixels, n); 69805b261ecSmrg swaps (&size->heightInPixels, n); 69905b261ecSmrg swaps (&size->widthInMillimeters, n); 70005b261ecSmrg swaps (&size->heightInMillimeters, n); 70105b261ecSmrg } 70205b261ecSmrg size++; 70305b261ecSmrg if (has_rate) 70405b261ecSmrg { 70505b261ecSmrg *rates = pSize->nRates; 70605b261ecSmrg if (client->swapped) 70705b261ecSmrg { 70805b261ecSmrg swaps (rates, n); 70905b261ecSmrg } 71005b261ecSmrg rates++; 71105b261ecSmrg for (j = 0; j < pSize->nRates; j++) 71205b261ecSmrg { 71305b261ecSmrg *rates = pSize->pRates[j].rate; 71405b261ecSmrg if (client->swapped) 71505b261ecSmrg { 71605b261ecSmrg swaps (rates, n); 71705b261ecSmrg } 71805b261ecSmrg rates++; 71905b261ecSmrg } 72005b261ecSmrg } 72105b261ecSmrg } 72205b261ecSmrg xfree (pData); 72305b261ecSmrg 72405b261ecSmrg data8 = (CARD8 *) rates; 72505b261ecSmrg 72605b261ecSmrg if (data8 - (CARD8 *) extra != extraLen) 72705b261ecSmrg FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n", 72805b261ecSmrg (unsigned long)(data8 - (CARD8 *) extra), extraLen); 72905b261ecSmrg rep.length = (extraLen + 3) >> 2; 73005b261ecSmrg } 73105b261ecSmrg if (client->swapped) { 73205b261ecSmrg swaps(&rep.sequenceNumber, n); 73305b261ecSmrg swapl(&rep.length, n); 73405b261ecSmrg swapl(&rep.timestamp, n); 73505b261ecSmrg swaps(&rep.rotation, n); 73605b261ecSmrg swaps(&rep.nSizes, n); 73705b261ecSmrg swaps(&rep.sizeID, n); 73805b261ecSmrg swaps(&rep.rate, n); 73905b261ecSmrg swaps(&rep.nrateEnts, n); 74005b261ecSmrg } 74105b261ecSmrg WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep); 74205b261ecSmrg if (extraLen) 74305b261ecSmrg { 74405b261ecSmrg WriteToClient (client, extraLen, (char *) extra); 74505b261ecSmrg xfree (extra); 74605b261ecSmrg } 74705b261ecSmrg return (client->noClientException); 74805b261ecSmrg} 74905b261ecSmrg 75005b261ecSmrgint 75105b261ecSmrgProcRRSetScreenConfig (ClientPtr client) 75205b261ecSmrg{ 75305b261ecSmrg REQUEST(xRRSetScreenConfigReq); 75405b261ecSmrg xRRSetScreenConfigReply rep; 75505b261ecSmrg DrawablePtr pDraw; 75605b261ecSmrg int n, rc; 75705b261ecSmrg ScreenPtr pScreen; 75805b261ecSmrg rrScrPrivPtr pScrPriv; 75905b261ecSmrg TimeStamp time; 76005b261ecSmrg int i; 76105b261ecSmrg Rotation rotation; 76205b261ecSmrg int rate; 76305b261ecSmrg Bool has_rate; 76405b261ecSmrg RROutputPtr output; 76505b261ecSmrg RRCrtcPtr crtc; 76605b261ecSmrg RRModePtr mode; 76705b261ecSmrg RR10DataPtr pData = NULL; 76805b261ecSmrg RRScreenSizePtr pSize; 76905b261ecSmrg int width, height; 77005b261ecSmrg 77105b261ecSmrg UpdateCurrentTime (); 77205b261ecSmrg 77305b261ecSmrg if (RRClientKnowsRates (client)) 77405b261ecSmrg { 77505b261ecSmrg REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); 77605b261ecSmrg has_rate = TRUE; 77705b261ecSmrg } 77805b261ecSmrg else 77905b261ecSmrg { 78005b261ecSmrg REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); 78105b261ecSmrg has_rate = FALSE; 78205b261ecSmrg } 78305b261ecSmrg 78405b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess); 78505b261ecSmrg if (rc != Success) 78605b261ecSmrg return rc; 78705b261ecSmrg 78805b261ecSmrg pScreen = pDraw->pScreen; 78905b261ecSmrg 79005b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 79105b261ecSmrg 79205b261ecSmrg time = ClientTimeToServerTime(stuff->timestamp); 79305b261ecSmrg 79405b261ecSmrg if (!pScrPriv) 79505b261ecSmrg { 79605b261ecSmrg time = currentTime; 79705b261ecSmrg rep.status = RRSetConfigFailed; 79805b261ecSmrg goto sendReply; 79905b261ecSmrg } 8004642e01fSmrg if (!RRGetInfo (pScreen, FALSE)) 80105b261ecSmrg return BadAlloc; 80205b261ecSmrg 80305b261ecSmrg output = RRFirstOutput (pScreen); 80405b261ecSmrg if (!output) 80505b261ecSmrg { 80605b261ecSmrg time = currentTime; 80705b261ecSmrg rep.status = RRSetConfigFailed; 80805b261ecSmrg goto sendReply; 80905b261ecSmrg } 81005b261ecSmrg 81105b261ecSmrg crtc = output->crtc; 81205b261ecSmrg 81305b261ecSmrg /* 81405b261ecSmrg * If the client's config timestamp is not the same as the last config 81505b261ecSmrg * timestamp, then the config information isn't up-to-date and 81605b261ecSmrg * can't even be validated. 81705b261ecSmrg * 81805b261ecSmrg * Note that the client only knows about the milliseconds part of the 81905b261ecSmrg * timestamp, so using CompareTimeStamps here would cause randr to suddenly 82005b261ecSmrg * stop working after several hours have passed (freedesktop bug #6502). 82105b261ecSmrg */ 82205b261ecSmrg if (stuff->configTimestamp != pScrPriv->lastConfigTime.milliseconds) 82305b261ecSmrg { 82405b261ecSmrg rep.status = RRSetConfigInvalidConfigTime; 82505b261ecSmrg goto sendReply; 82605b261ecSmrg } 82705b261ecSmrg 82805b261ecSmrg pData = RR10GetData (pScreen, output); 82905b261ecSmrg if (!pData) 83005b261ecSmrg return BadAlloc; 83105b261ecSmrg 83205b261ecSmrg if (stuff->sizeID >= pData->nsize) 83305b261ecSmrg { 83405b261ecSmrg /* 83505b261ecSmrg * Invalid size ID 83605b261ecSmrg */ 83705b261ecSmrg client->errorValue = stuff->sizeID; 83805b261ecSmrg xfree (pData); 83905b261ecSmrg return BadValue; 84005b261ecSmrg } 84105b261ecSmrg pSize = &pData->sizes[stuff->sizeID]; 84205b261ecSmrg 84305b261ecSmrg /* 84405b261ecSmrg * Validate requested rotation 84505b261ecSmrg */ 84605b261ecSmrg rotation = (Rotation) stuff->rotation; 84705b261ecSmrg 84805b261ecSmrg /* test the rotation bits only! */ 84905b261ecSmrg switch (rotation & 0xf) { 85005b261ecSmrg case RR_Rotate_0: 85105b261ecSmrg case RR_Rotate_90: 85205b261ecSmrg case RR_Rotate_180: 85305b261ecSmrg case RR_Rotate_270: 85405b261ecSmrg break; 85505b261ecSmrg default: 85605b261ecSmrg /* 85705b261ecSmrg * Invalid rotation 85805b261ecSmrg */ 85905b261ecSmrg client->errorValue = stuff->rotation; 86005b261ecSmrg xfree (pData); 86105b261ecSmrg return BadValue; 86205b261ecSmrg } 86305b261ecSmrg 86405b261ecSmrg if ((~crtc->rotations) & rotation) 86505b261ecSmrg { 86605b261ecSmrg /* 86705b261ecSmrg * requested rotation or reflection not supported by screen 86805b261ecSmrg */ 86905b261ecSmrg client->errorValue = stuff->rotation; 87005b261ecSmrg xfree (pData); 87105b261ecSmrg return BadMatch; 87205b261ecSmrg } 87305b261ecSmrg 87405b261ecSmrg /* 87505b261ecSmrg * Validate requested refresh 87605b261ecSmrg */ 87705b261ecSmrg if (has_rate) 87805b261ecSmrg rate = (int) stuff->rate; 87905b261ecSmrg else 88005b261ecSmrg rate = 0; 88105b261ecSmrg 88205b261ecSmrg if (rate) 88305b261ecSmrg { 88405b261ecSmrg for (i = 0; i < pSize->nRates; i++) 88505b261ecSmrg { 88605b261ecSmrg if (pSize->pRates[i].rate == rate) 88705b261ecSmrg break; 88805b261ecSmrg } 88905b261ecSmrg if (i == pSize->nRates) 89005b261ecSmrg { 89105b261ecSmrg /* 89205b261ecSmrg * Invalid rate 89305b261ecSmrg */ 89405b261ecSmrg client->errorValue = rate; 89505b261ecSmrg xfree (pData); 89605b261ecSmrg return BadValue; 89705b261ecSmrg } 89805b261ecSmrg mode = pSize->pRates[i].mode; 89905b261ecSmrg } 90005b261ecSmrg else 90105b261ecSmrg mode = pSize->pRates[0].mode; 90205b261ecSmrg 90305b261ecSmrg /* 90405b261ecSmrg * Make sure the requested set-time is not older than 90505b261ecSmrg * the last set-time 90605b261ecSmrg */ 90705b261ecSmrg if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) 90805b261ecSmrg { 90905b261ecSmrg rep.status = RRSetConfigInvalidTime; 91005b261ecSmrg goto sendReply; 91105b261ecSmrg } 91205b261ecSmrg 91305b261ecSmrg /* 91405b261ecSmrg * If the screen size is changing, adjust all of the other outputs 91505b261ecSmrg * to fit the new size, mirroring as much as possible 91605b261ecSmrg */ 91705b261ecSmrg width = mode->mode.width; 91805b261ecSmrg height = mode->mode.height; 91905b261ecSmrg if (rotation & (RR_Rotate_90|RR_Rotate_270)) 92005b261ecSmrg { 92105b261ecSmrg width = mode->mode.height; 92205b261ecSmrg height = mode->mode.width; 92305b261ecSmrg } 92405b261ecSmrg if (width != pScreen->width || height != pScreen->height) 92505b261ecSmrg { 92605b261ecSmrg int c; 92705b261ecSmrg 92805b261ecSmrg for (c = 0; c < pScrPriv->numCrtcs; c++) 92905b261ecSmrg { 93005b261ecSmrg if (!RRCrtcSet (pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0, 93105b261ecSmrg 0, NULL)) 93205b261ecSmrg { 93305b261ecSmrg rep.status = RRSetConfigFailed; 93405b261ecSmrg /* XXX recover from failure */ 93505b261ecSmrg goto sendReply; 93605b261ecSmrg } 93705b261ecSmrg } 93805b261ecSmrg if (!RRScreenSizeSet (pScreen, width, height, 93905b261ecSmrg pScreen->mmWidth, pScreen->mmHeight)) 94005b261ecSmrg { 94105b261ecSmrg rep.status = RRSetConfigFailed; 94205b261ecSmrg /* XXX recover from failure */ 94305b261ecSmrg goto sendReply; 94405b261ecSmrg } 94505b261ecSmrg } 94605b261ecSmrg 94705b261ecSmrg if (!RRCrtcSet (crtc, mode, 0, 0, stuff->rotation, 1, &output)) 94805b261ecSmrg rep.status = RRSetConfigFailed; 94952397711Smrg else { 95052397711Smrg pScrPriv->lastSetTime = time; 95105b261ecSmrg rep.status = RRSetConfigSuccess; 95252397711Smrg } 95305b261ecSmrg 95405b261ecSmrg /* 95505b261ecSmrg * XXX Configure other crtcs to mirror as much as possible 95605b261ecSmrg */ 95705b261ecSmrg 95805b261ecSmrgsendReply: 95905b261ecSmrg 96005b261ecSmrg if (pData) 96105b261ecSmrg xfree (pData); 96205b261ecSmrg 96305b261ecSmrg rep.type = X_Reply; 96405b261ecSmrg /* rep.status has already been filled in */ 96505b261ecSmrg rep.length = 0; 96605b261ecSmrg rep.sequenceNumber = client->sequence; 96705b261ecSmrg 96805b261ecSmrg rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; 96905b261ecSmrg rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds; 97005b261ecSmrg rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id; 97105b261ecSmrg 97205b261ecSmrg if (client->swapped) 97305b261ecSmrg { 97405b261ecSmrg swaps(&rep.sequenceNumber, n); 97505b261ecSmrg swapl(&rep.length, n); 97605b261ecSmrg swapl(&rep.newTimestamp, n); 97705b261ecSmrg swapl(&rep.newConfigTimestamp, n); 97805b261ecSmrg swapl(&rep.root, n); 97905b261ecSmrg } 98005b261ecSmrg WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep); 98105b261ecSmrg 98205b261ecSmrg return (client->noClientException); 98305b261ecSmrg} 98405b261ecSmrg 98505b261ecSmrgstatic CARD16 98605b261ecSmrgRR10CurrentSizeID (ScreenPtr pScreen) 98705b261ecSmrg{ 98805b261ecSmrg CARD16 sizeID = 0xffff; 98905b261ecSmrg RROutputPtr output = RRFirstOutput (pScreen); 99005b261ecSmrg 99105b261ecSmrg if (output) 99205b261ecSmrg { 99305b261ecSmrg RR10DataPtr data = RR10GetData (pScreen, output); 99405b261ecSmrg if (data) 99505b261ecSmrg { 99605b261ecSmrg int i; 99705b261ecSmrg for (i = 0; i < data->nsize; i++) 99805b261ecSmrg if (data->sizes[i].width == pScreen->width && 99905b261ecSmrg data->sizes[i].height == pScreen->height) 100005b261ecSmrg { 100105b261ecSmrg sizeID = (CARD16) i; 100205b261ecSmrg break; 100305b261ecSmrg } 100405b261ecSmrg xfree (data); 100505b261ecSmrg } 100605b261ecSmrg } 100705b261ecSmrg return sizeID; 100805b261ecSmrg} 1009