rrscreen.c revision 6747b715
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{ 766747b715Smrg WindowPtr pWin = pScreen->root; 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; 1006747b715Smrg WindowPtr pRoot = pScreen->root; 10105b261ecSmrg 10205b261ecSmrg se.type = RRScreenChangeNotify + RREventBase; 10305b261ecSmrg se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0); 10405b261ecSmrg se.timestamp = pScrPriv->lastSetTime.milliseconds; 10505b261ecSmrg se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 10605b261ecSmrg se.root = pRoot->drawable.id; 10705b261ecSmrg se.window = pWin->drawable.id; 10805b261ecSmrg se.subpixelOrder = PictureGetSubpixelOrder (pScreen); 10905b261ecSmrg 11005b261ecSmrg se.sizeID = RR10CurrentSizeID (pScreen); 11105b261ecSmrg 11205b261ecSmrg if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) { 11305b261ecSmrg se.widthInPixels = pScreen->height; 11405b261ecSmrg se.heightInPixels = pScreen->width; 11505b261ecSmrg se.widthInMillimeters = pScreen->mmHeight; 11605b261ecSmrg se.heightInMillimeters = pScreen->mmWidth; 11705b261ecSmrg } else { 11805b261ecSmrg se.widthInPixels = pScreen->width; 11905b261ecSmrg se.heightInPixels = pScreen->height; 12005b261ecSmrg se.widthInMillimeters = pScreen->mmWidth; 12105b261ecSmrg se.heightInMillimeters = pScreen->mmHeight; 12205b261ecSmrg } 12305b261ecSmrg 12405b261ecSmrg WriteEventsToClient (client, 1, (xEvent *) &se); 12505b261ecSmrg} 12605b261ecSmrg 12705b261ecSmrg/* 12805b261ecSmrg * Notify the extension that the screen size has been changed. 12905b261ecSmrg * The driver is responsible for calling this whenever it has changed 13005b261ecSmrg * the size of the screen 13105b261ecSmrg */ 13205b261ecSmrgvoid 13305b261ecSmrgRRScreenSizeNotify (ScreenPtr pScreen) 13405b261ecSmrg{ 13505b261ecSmrg rrScrPriv(pScreen); 13605b261ecSmrg /* 13705b261ecSmrg * Deliver ConfigureNotify events when root changes 13805b261ecSmrg * pixel size 13905b261ecSmrg */ 14005b261ecSmrg if (pScrPriv->width == pScreen->width && 14105b261ecSmrg pScrPriv->height == pScreen->height && 14205b261ecSmrg pScrPriv->mmWidth == pScreen->mmWidth && 14305b261ecSmrg pScrPriv->mmHeight == pScreen->mmHeight) 14405b261ecSmrg return; 14505b261ecSmrg 14605b261ecSmrg pScrPriv->width = pScreen->width; 14705b261ecSmrg pScrPriv->height = pScreen->height; 14805b261ecSmrg pScrPriv->mmWidth = pScreen->mmWidth; 14905b261ecSmrg pScrPriv->mmHeight = pScreen->mmHeight; 15005b261ecSmrg pScrPriv->changed = TRUE; 15105b261ecSmrg/* pScrPriv->sizeChanged = TRUE; */ 15205b261ecSmrg 15305b261ecSmrg RRTellChanged (pScreen); 15405b261ecSmrg RRSendConfigNotify (pScreen); 15505b261ecSmrg RREditConnectionInfo (pScreen); 15605b261ecSmrg 15705b261ecSmrg RRPointerScreenConfigured (pScreen); 15805b261ecSmrg /* 15905b261ecSmrg * Fix pointer bounds and location 16005b261ecSmrg */ 16105b261ecSmrg ScreenRestructured (pScreen); 16205b261ecSmrg} 16305b261ecSmrg 16405b261ecSmrg/* 16505b261ecSmrg * Request that the screen be resized 16605b261ecSmrg */ 16705b261ecSmrgBool 16805b261ecSmrgRRScreenSizeSet (ScreenPtr pScreen, 16905b261ecSmrg CARD16 width, 17005b261ecSmrg CARD16 height, 17105b261ecSmrg CARD32 mmWidth, 17205b261ecSmrg CARD32 mmHeight) 17305b261ecSmrg{ 17405b261ecSmrg rrScrPriv(pScreen); 17505b261ecSmrg 17605b261ecSmrg#if RANDR_12_INTERFACE 17705b261ecSmrg if (pScrPriv->rrScreenSetSize) 17805b261ecSmrg { 17905b261ecSmrg return (*pScrPriv->rrScreenSetSize) (pScreen, 18005b261ecSmrg width, height, 18105b261ecSmrg mmWidth, mmHeight); 18205b261ecSmrg } 18305b261ecSmrg#endif 18405b261ecSmrg#if RANDR_10_INTERFACE 18505b261ecSmrg if (pScrPriv->rrSetConfig) 18605b261ecSmrg { 18705b261ecSmrg return TRUE; /* can't set size separately */ 18805b261ecSmrg } 18905b261ecSmrg#endif 19005b261ecSmrg return FALSE; 19105b261ecSmrg} 19205b261ecSmrg 19305b261ecSmrg/* 19405b261ecSmrg * Retrieve valid screen size range 19505b261ecSmrg */ 1966747b715Smrgint 19705b261ecSmrgProcRRGetScreenSizeRange (ClientPtr client) 19805b261ecSmrg{ 19905b261ecSmrg REQUEST(xRRGetScreenSizeRangeReq); 20005b261ecSmrg xRRGetScreenSizeRangeReply rep; 20105b261ecSmrg WindowPtr pWin; 20205b261ecSmrg ScreenPtr pScreen; 20305b261ecSmrg rrScrPrivPtr pScrPriv; 20405b261ecSmrg int rc; 20505b261ecSmrg 20605b261ecSmrg REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); 2076747b715Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 20805b261ecSmrg if (rc != Success) 20905b261ecSmrg return rc; 21005b261ecSmrg 21105b261ecSmrg pScreen = pWin->drawable.pScreen; 21205b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 21305b261ecSmrg 21405b261ecSmrg rep.type = X_Reply; 21505b261ecSmrg rep.pad = 0; 21605b261ecSmrg rep.sequenceNumber = client->sequence; 21705b261ecSmrg rep.length = 0; 21805b261ecSmrg 21905b261ecSmrg if (pScrPriv) 22005b261ecSmrg { 2214642e01fSmrg if (!RRGetInfo (pScreen, FALSE)) 22205b261ecSmrg return BadAlloc; 22305b261ecSmrg rep.minWidth = pScrPriv->minWidth; 22405b261ecSmrg rep.minHeight = pScrPriv->minHeight; 22505b261ecSmrg rep.maxWidth = pScrPriv->maxWidth; 22605b261ecSmrg rep.maxHeight = pScrPriv->maxHeight; 22705b261ecSmrg } 22805b261ecSmrg else 22905b261ecSmrg { 23005b261ecSmrg rep.maxWidth = rep.minWidth = pScreen->width; 23105b261ecSmrg rep.maxHeight = rep.minHeight = pScreen->height; 23205b261ecSmrg } 23305b261ecSmrg if (client->swapped) 23405b261ecSmrg { 23505b261ecSmrg int n; 23605b261ecSmrg 23705b261ecSmrg swaps(&rep.sequenceNumber, n); 23805b261ecSmrg swapl(&rep.length, n); 23905b261ecSmrg swaps(&rep.minWidth, n); 24005b261ecSmrg swaps(&rep.minHeight, n); 24105b261ecSmrg swaps(&rep.maxWidth, n); 24205b261ecSmrg swaps(&rep.maxHeight, n); 24305b261ecSmrg } 24405b261ecSmrg WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), (char *)&rep); 2456747b715Smrg return Success; 24605b261ecSmrg} 24705b261ecSmrg 24805b261ecSmrgint 24905b261ecSmrgProcRRSetScreenSize (ClientPtr client) 25005b261ecSmrg{ 25105b261ecSmrg REQUEST(xRRSetScreenSizeReq); 25205b261ecSmrg WindowPtr pWin; 25305b261ecSmrg ScreenPtr pScreen; 25405b261ecSmrg rrScrPrivPtr pScrPriv; 25505b261ecSmrg int i, rc; 25605b261ecSmrg 25705b261ecSmrg REQUEST_SIZE_MATCH(xRRSetScreenSizeReq); 2586747b715Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 25905b261ecSmrg if (rc != Success) 26005b261ecSmrg return rc; 26105b261ecSmrg 26205b261ecSmrg pScreen = pWin->drawable.pScreen; 26305b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 26405b261ecSmrg if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width) 26505b261ecSmrg { 26605b261ecSmrg client->errorValue = stuff->width; 26705b261ecSmrg return BadValue; 26805b261ecSmrg } 26905b261ecSmrg if (stuff->height < pScrPriv->minHeight || 27005b261ecSmrg pScrPriv->maxHeight < stuff->height) 27105b261ecSmrg { 27205b261ecSmrg client->errorValue = stuff->height; 27305b261ecSmrg return BadValue; 27405b261ecSmrg } 27505b261ecSmrg for (i = 0; i < pScrPriv->numCrtcs; i++) 27605b261ecSmrg { 27705b261ecSmrg RRCrtcPtr crtc = pScrPriv->crtcs[i]; 27805b261ecSmrg RRModePtr mode = crtc->mode; 27905b261ecSmrg if (mode) 28005b261ecSmrg { 28105b261ecSmrg int source_width = mode->mode.width; 28205b261ecSmrg int source_height = mode->mode.height; 28305b261ecSmrg Rotation rotation = crtc->rotation; 28405b261ecSmrg 28505b261ecSmrg if (rotation == RR_Rotate_90 || rotation == RR_Rotate_270) 28605b261ecSmrg { 28705b261ecSmrg source_width = mode->mode.height; 28805b261ecSmrg source_height = mode->mode.width; 28905b261ecSmrg } 29005b261ecSmrg 29105b261ecSmrg if (crtc->x + source_width > stuff->width || 29205b261ecSmrg crtc->y + source_height > stuff->height) 29305b261ecSmrg return BadMatch; 29405b261ecSmrg } 29505b261ecSmrg } 29605b261ecSmrg if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0) 29705b261ecSmrg { 29805b261ecSmrg client->errorValue = 0; 29905b261ecSmrg return BadValue; 30005b261ecSmrg } 30105b261ecSmrg if (!RRScreenSizeSet (pScreen, 30205b261ecSmrg stuff->width, stuff->height, 30305b261ecSmrg stuff->widthInMillimeters, 30405b261ecSmrg stuff->heightInMillimeters)) 30505b261ecSmrg { 30605b261ecSmrg return BadMatch; 30705b261ecSmrg } 30805b261ecSmrg return Success; 30905b261ecSmrg} 31005b261ecSmrg 3114642e01fSmrgstatic int 3124642e01fSmrgrrGetScreenResources(ClientPtr client, Bool query) 31305b261ecSmrg{ 31405b261ecSmrg REQUEST(xRRGetScreenResourcesReq); 31505b261ecSmrg xRRGetScreenResourcesReply rep; 31605b261ecSmrg WindowPtr pWin; 31705b261ecSmrg ScreenPtr pScreen; 31805b261ecSmrg rrScrPrivPtr pScrPriv; 31905b261ecSmrg CARD8 *extra; 32005b261ecSmrg unsigned long extraLen; 3214642e01fSmrg int i, n, rc, has_primary = 0; 32205b261ecSmrg RRCrtc *crtcs; 32305b261ecSmrg RROutput *outputs; 32405b261ecSmrg xRRModeInfo *modeinfos; 32505b261ecSmrg CARD8 *names; 32605b261ecSmrg 32705b261ecSmrg REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq); 3286747b715Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 32905b261ecSmrg if (rc != Success) 33005b261ecSmrg return rc; 33105b261ecSmrg 33205b261ecSmrg pScreen = pWin->drawable.pScreen; 33305b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 33405b261ecSmrg rep.pad = 0; 33505b261ecSmrg 3364642e01fSmrg if (query && pScrPriv) 3374642e01fSmrg if (!RRGetInfo (pScreen, query)) 33805b261ecSmrg return BadAlloc; 33905b261ecSmrg 34005b261ecSmrg if (!pScrPriv) 34105b261ecSmrg { 34205b261ecSmrg rep.type = X_Reply; 34305b261ecSmrg rep.sequenceNumber = client->sequence; 34405b261ecSmrg rep.length = 0; 34505b261ecSmrg rep.timestamp = currentTime.milliseconds; 34605b261ecSmrg rep.configTimestamp = currentTime.milliseconds; 34705b261ecSmrg rep.nCrtcs = 0; 34805b261ecSmrg rep.nOutputs = 0; 34905b261ecSmrg rep.nModes = 0; 35005b261ecSmrg rep.nbytesNames = 0; 35105b261ecSmrg extra = NULL; 35205b261ecSmrg extraLen = 0; 35305b261ecSmrg } 35405b261ecSmrg else 35505b261ecSmrg { 35605b261ecSmrg RRModePtr *modes; 35705b261ecSmrg int num_modes; 35805b261ecSmrg 35905b261ecSmrg modes = RRModesForScreen (pScreen, &num_modes); 36005b261ecSmrg if (!modes) 36105b261ecSmrg return BadAlloc; 36205b261ecSmrg 36305b261ecSmrg rep.type = X_Reply; 36405b261ecSmrg rep.sequenceNumber = client->sequence; 36505b261ecSmrg rep.length = 0; 36605b261ecSmrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 36705b261ecSmrg rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 36805b261ecSmrg rep.nCrtcs = pScrPriv->numCrtcs; 36905b261ecSmrg rep.nOutputs = pScrPriv->numOutputs; 37005b261ecSmrg rep.nModes = num_modes; 37105b261ecSmrg rep.nbytesNames = 0; 37205b261ecSmrg 37305b261ecSmrg for (i = 0; i < num_modes; i++) 37405b261ecSmrg rep.nbytesNames += modes[i]->mode.nameLength; 37505b261ecSmrg 37605b261ecSmrg rep.length = (pScrPriv->numCrtcs + 37705b261ecSmrg pScrPriv->numOutputs + 3786747b715Smrg num_modes * bytes_to_int32(SIZEOF(xRRModeInfo)) + 3796747b715Smrg bytes_to_int32(rep.nbytesNames)); 38005b261ecSmrg 38105b261ecSmrg extraLen = rep.length << 2; 38205b261ecSmrg if (extraLen) 38305b261ecSmrg { 3846747b715Smrg extra = malloc(extraLen); 38505b261ecSmrg if (!extra) 38605b261ecSmrg { 3876747b715Smrg free(modes); 38805b261ecSmrg return BadAlloc; 38905b261ecSmrg } 39005b261ecSmrg } 39105b261ecSmrg else 39205b261ecSmrg extra = NULL; 39305b261ecSmrg 39405b261ecSmrg crtcs = (RRCrtc *) extra; 39505b261ecSmrg outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs); 39605b261ecSmrg modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs); 39705b261ecSmrg names = (CARD8 *) (modeinfos + num_modes); 3984642e01fSmrg 3994642e01fSmrg if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) 4004642e01fSmrg { 4014642e01fSmrg has_primary = 1; 4024642e01fSmrg crtcs[0] = pScrPriv->primaryOutput->crtc->id; 4034642e01fSmrg if (client->swapped) 4044642e01fSmrg swapl (&crtcs[0], n); 4054642e01fSmrg } 40605b261ecSmrg 40705b261ecSmrg for (i = 0; i < pScrPriv->numCrtcs; i++) 40805b261ecSmrg { 4094642e01fSmrg if (has_primary && 4104642e01fSmrg pScrPriv->primaryOutput->crtc == pScrPriv->crtcs[i]) 4114642e01fSmrg { 4124642e01fSmrg has_primary = 0; 4134642e01fSmrg continue; 4144642e01fSmrg } 4154642e01fSmrg crtcs[i + has_primary] = pScrPriv->crtcs[i]->id; 41605b261ecSmrg if (client->swapped) 4174642e01fSmrg swapl (&crtcs[i + has_primary], n); 41805b261ecSmrg } 41905b261ecSmrg 42005b261ecSmrg for (i = 0; i < pScrPriv->numOutputs; i++) 42105b261ecSmrg { 42205b261ecSmrg outputs[i] = pScrPriv->outputs[i]->id; 42305b261ecSmrg if (client->swapped) 42405b261ecSmrg swapl (&outputs[i], n); 42505b261ecSmrg } 42605b261ecSmrg 42705b261ecSmrg for (i = 0; i < num_modes; i++) 42805b261ecSmrg { 42905b261ecSmrg RRModePtr mode = modes[i]; 43005b261ecSmrg modeinfos[i] = mode->mode; 43105b261ecSmrg if (client->swapped) 43205b261ecSmrg { 43305b261ecSmrg swapl (&modeinfos[i].id, n); 43405b261ecSmrg swaps (&modeinfos[i].width, n); 43505b261ecSmrg swaps (&modeinfos[i].height, n); 43605b261ecSmrg swapl (&modeinfos[i].dotClock, n); 43705b261ecSmrg swaps (&modeinfos[i].hSyncStart, n); 43805b261ecSmrg swaps (&modeinfos[i].hSyncEnd, n); 43905b261ecSmrg swaps (&modeinfos[i].hTotal, n); 44005b261ecSmrg swaps (&modeinfos[i].hSkew, n); 44105b261ecSmrg swaps (&modeinfos[i].vSyncStart, n); 44205b261ecSmrg swaps (&modeinfos[i].vSyncEnd, n); 44305b261ecSmrg swaps (&modeinfos[i].vTotal, n); 44405b261ecSmrg swaps (&modeinfos[i].nameLength, n); 44505b261ecSmrg swapl (&modeinfos[i].modeFlags, n); 44605b261ecSmrg } 44705b261ecSmrg memcpy (names, mode->name, 44805b261ecSmrg mode->mode.nameLength); 44905b261ecSmrg names += mode->mode.nameLength; 45005b261ecSmrg } 4516747b715Smrg free(modes); 4526747b715Smrg assert (bytes_to_int32((char *) names - (char *) extra) == rep.length); 45305b261ecSmrg } 45405b261ecSmrg 45505b261ecSmrg if (client->swapped) { 45605b261ecSmrg swaps(&rep.sequenceNumber, n); 45705b261ecSmrg swapl(&rep.length, n); 45805b261ecSmrg swapl(&rep.timestamp, n); 45905b261ecSmrg swapl(&rep.configTimestamp, n); 46005b261ecSmrg swaps(&rep.nCrtcs, n); 46105b261ecSmrg swaps(&rep.nOutputs, n); 46205b261ecSmrg swaps(&rep.nModes, n); 46305b261ecSmrg swaps(&rep.nbytesNames, n); 46405b261ecSmrg } 46505b261ecSmrg WriteToClient(client, sizeof(xRRGetScreenResourcesReply), (char *)&rep); 46605b261ecSmrg if (extraLen) 46705b261ecSmrg { 46805b261ecSmrg WriteToClient (client, extraLen, (char *) extra); 4696747b715Smrg free(extra); 47005b261ecSmrg } 4716747b715Smrg return Success; 47205b261ecSmrg} 47305b261ecSmrg 4744642e01fSmrgint 4754642e01fSmrgProcRRGetScreenResources (ClientPtr client) 4764642e01fSmrg{ 4774642e01fSmrg return rrGetScreenResources(client, TRUE); 4784642e01fSmrg} 4794642e01fSmrg 4804642e01fSmrgint 4814642e01fSmrgProcRRGetScreenResourcesCurrent (ClientPtr client) 4824642e01fSmrg{ 4834642e01fSmrg return rrGetScreenResources(client, FALSE); 4844642e01fSmrg} 4854642e01fSmrg 48605b261ecSmrgtypedef struct _RR10Data { 48705b261ecSmrg RRScreenSizePtr sizes; 48805b261ecSmrg int nsize; 48905b261ecSmrg int nrefresh; 49005b261ecSmrg int size; 49105b261ecSmrg CARD16 refresh; 49205b261ecSmrg} RR10DataRec, *RR10DataPtr; 49305b261ecSmrg 49405b261ecSmrg/* 49505b261ecSmrg * Convert 1.2 monitor data into 1.0 screen data 49605b261ecSmrg */ 49705b261ecSmrgstatic RR10DataPtr 49805b261ecSmrgRR10GetData (ScreenPtr pScreen, RROutputPtr output) 49905b261ecSmrg{ 50005b261ecSmrg RR10DataPtr data; 50105b261ecSmrg RRScreenSizePtr size; 50205b261ecSmrg int nmode = output->numModes + output->numUserModes; 50305b261ecSmrg int o, os, l, r; 50405b261ecSmrg RRScreenRatePtr refresh; 50505b261ecSmrg CARD16 vRefresh; 50605b261ecSmrg RRModePtr mode; 50705b261ecSmrg Bool *used; 50805b261ecSmrg 50905b261ecSmrg /* Make sure there is plenty of space for any combination */ 51005b261ecSmrg data = malloc (sizeof (RR10DataRec) + 51105b261ecSmrg sizeof (RRScreenSize) * nmode + 51205b261ecSmrg sizeof (RRScreenRate) * nmode + 51305b261ecSmrg sizeof (Bool) * nmode); 51405b261ecSmrg if (!data) 51505b261ecSmrg return NULL; 51605b261ecSmrg size = (RRScreenSizePtr) (data + 1); 51705b261ecSmrg refresh = (RRScreenRatePtr) (size + nmode); 51805b261ecSmrg used = (Bool *) (refresh + nmode); 51905b261ecSmrg memset (used, '\0', sizeof (Bool) * nmode); 52005b261ecSmrg data->sizes = size; 52105b261ecSmrg data->nsize = 0; 52205b261ecSmrg data->nrefresh = 0; 52305b261ecSmrg data->size = 0; 52405b261ecSmrg data->refresh = 0; 52505b261ecSmrg 52605b261ecSmrg /* 52705b261ecSmrg * find modes not yet listed 52805b261ecSmrg */ 52905b261ecSmrg for (o = 0; o < output->numModes + output->numUserModes; o++) 53005b261ecSmrg { 53105b261ecSmrg if (used[o]) continue; 53205b261ecSmrg 53305b261ecSmrg if (o < output->numModes) 53405b261ecSmrg mode = output->modes[o]; 53505b261ecSmrg else 53605b261ecSmrg mode = output->userModes[o - output->numModes]; 53705b261ecSmrg 53805b261ecSmrg l = data->nsize; 53905b261ecSmrg size[l].id = data->nsize; 54005b261ecSmrg size[l].width = mode->mode.width; 54105b261ecSmrg size[l].height = mode->mode.height; 54205b261ecSmrg if (output->mmWidth && output->mmHeight) { 54305b261ecSmrg size[l].mmWidth = output->mmWidth; 54405b261ecSmrg size[l].mmHeight = output->mmHeight; 54505b261ecSmrg } else { 54605b261ecSmrg size[l].mmWidth = pScreen->mmWidth; 54705b261ecSmrg size[l].mmHeight = pScreen->mmHeight; 54805b261ecSmrg } 54905b261ecSmrg size[l].nRates = 0; 55005b261ecSmrg size[l].pRates = &refresh[data->nrefresh]; 55105b261ecSmrg data->nsize++; 55205b261ecSmrg 55305b261ecSmrg /* 55405b261ecSmrg * Find all modes with matching size 55505b261ecSmrg */ 55605b261ecSmrg for (os = o; os < output->numModes + output->numUserModes; os++) 55705b261ecSmrg { 55805b261ecSmrg if (os < output->numModes) 55905b261ecSmrg mode = output->modes[os]; 56005b261ecSmrg else 56105b261ecSmrg mode = output->userModes[os - output->numModes]; 56205b261ecSmrg if (mode->mode.width == size[l].width && 56305b261ecSmrg mode->mode.height == size[l].height) 56405b261ecSmrg { 56505b261ecSmrg vRefresh = RRVerticalRefresh (&mode->mode); 56605b261ecSmrg used[os] = TRUE; 56705b261ecSmrg 56805b261ecSmrg for (r = 0; r < size[l].nRates; r++) 56905b261ecSmrg if (vRefresh == size[l].pRates[r].rate) 57005b261ecSmrg break; 57105b261ecSmrg if (r == size[l].nRates) 57205b261ecSmrg { 57305b261ecSmrg size[l].pRates[r].rate = vRefresh; 57405b261ecSmrg size[l].pRates[r].mode = mode; 57505b261ecSmrg size[l].nRates++; 57605b261ecSmrg data->nrefresh++; 57705b261ecSmrg } 57805b261ecSmrg if (mode == output->crtc->mode) 57905b261ecSmrg { 58005b261ecSmrg data->size = l; 58105b261ecSmrg data->refresh = vRefresh; 58205b261ecSmrg } 58305b261ecSmrg } 58405b261ecSmrg } 58505b261ecSmrg } 58605b261ecSmrg return data; 58705b261ecSmrg} 58805b261ecSmrg 58905b261ecSmrgint 59005b261ecSmrgProcRRGetScreenInfo (ClientPtr client) 59105b261ecSmrg{ 59205b261ecSmrg REQUEST(xRRGetScreenInfoReq); 59305b261ecSmrg xRRGetScreenInfoReply rep; 59405b261ecSmrg WindowPtr pWin; 59505b261ecSmrg int n, rc; 59605b261ecSmrg ScreenPtr pScreen; 59705b261ecSmrg rrScrPrivPtr pScrPriv; 59805b261ecSmrg CARD8 *extra; 59905b261ecSmrg unsigned long extraLen; 60005b261ecSmrg RROutputPtr output; 60105b261ecSmrg 60205b261ecSmrg REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); 6036747b715Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 60405b261ecSmrg if (rc != Success) 60505b261ecSmrg return rc; 60605b261ecSmrg 60705b261ecSmrg pScreen = pWin->drawable.pScreen; 60805b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 60905b261ecSmrg rep.pad = 0; 61005b261ecSmrg 61105b261ecSmrg if (pScrPriv) 6124642e01fSmrg if (!RRGetInfo (pScreen, TRUE)) 61305b261ecSmrg return BadAlloc; 61405b261ecSmrg 61505b261ecSmrg output = RRFirstOutput (pScreen); 61605b261ecSmrg 61705b261ecSmrg if (!pScrPriv || !output) 61805b261ecSmrg { 61905b261ecSmrg rep.type = X_Reply; 6204642e01fSmrg rep.setOfRotations = RR_Rotate_0; 62105b261ecSmrg rep.sequenceNumber = client->sequence; 62205b261ecSmrg rep.length = 0; 6236747b715Smrg rep.root = pWin->drawable.pScreen->root->drawable.id; 62405b261ecSmrg rep.timestamp = currentTime.milliseconds; 62505b261ecSmrg rep.configTimestamp = currentTime.milliseconds; 62605b261ecSmrg rep.nSizes = 0; 62705b261ecSmrg rep.sizeID = 0; 62805b261ecSmrg rep.rotation = RR_Rotate_0; 62905b261ecSmrg rep.rate = 0; 63005b261ecSmrg rep.nrateEnts = 0; 63105b261ecSmrg extra = 0; 63205b261ecSmrg extraLen = 0; 63305b261ecSmrg } 63405b261ecSmrg else 63505b261ecSmrg { 63605b261ecSmrg int i, j; 63705b261ecSmrg xScreenSizes *size; 63805b261ecSmrg CARD16 *rates; 63905b261ecSmrg CARD8 *data8; 64005b261ecSmrg Bool has_rate = RRClientKnowsRates (client); 64105b261ecSmrg RR10DataPtr pData; 64205b261ecSmrg RRScreenSizePtr pSize; 64305b261ecSmrg 64405b261ecSmrg pData = RR10GetData (pScreen, output); 64505b261ecSmrg if (!pData) 64605b261ecSmrg return BadAlloc; 64705b261ecSmrg 64805b261ecSmrg rep.type = X_Reply; 64905b261ecSmrg rep.setOfRotations = output->crtc->rotations; 65005b261ecSmrg rep.sequenceNumber = client->sequence; 65105b261ecSmrg rep.length = 0; 6526747b715Smrg rep.root = pWin->drawable.pScreen->root->drawable.id; 65305b261ecSmrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 65405b261ecSmrg rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 65505b261ecSmrg rep.rotation = output->crtc->rotation; 65605b261ecSmrg rep.nSizes = pData->nsize; 65705b261ecSmrg rep.nrateEnts = pData->nrefresh + pData->nsize; 65805b261ecSmrg rep.sizeID = pData->size; 65905b261ecSmrg rep.rate = pData->refresh; 66005b261ecSmrg 661b86d567bSmrg extraLen = rep.nSizes * sizeof (xScreenSizes); 662b86d567bSmrg if (has_rate) 663b86d567bSmrg extraLen += rep.nrateEnts * sizeof (CARD16); 66405b261ecSmrg 66505b261ecSmrg if (extraLen) 66605b261ecSmrg { 6676747b715Smrg extra = (CARD8 *) malloc(extraLen); 66805b261ecSmrg if (!extra) 66905b261ecSmrg { 6706747b715Smrg free(pData); 67105b261ecSmrg return BadAlloc; 67205b261ecSmrg } 67305b261ecSmrg } 67405b261ecSmrg else 67505b261ecSmrg extra = NULL; 67605b261ecSmrg 67705b261ecSmrg /* 67805b261ecSmrg * First comes the size information 67905b261ecSmrg */ 68005b261ecSmrg size = (xScreenSizes *) extra; 68105b261ecSmrg rates = (CARD16 *) (size + rep.nSizes); 68205b261ecSmrg for (i = 0; i < pData->nsize; i++) 68305b261ecSmrg { 68405b261ecSmrg pSize = &pData->sizes[i]; 68505b261ecSmrg size->widthInPixels = pSize->width; 68605b261ecSmrg size->heightInPixels = pSize->height; 68705b261ecSmrg size->widthInMillimeters = pSize->mmWidth; 68805b261ecSmrg size->heightInMillimeters = pSize->mmHeight; 68905b261ecSmrg if (client->swapped) 69005b261ecSmrg { 69105b261ecSmrg swaps (&size->widthInPixels, n); 69205b261ecSmrg swaps (&size->heightInPixels, n); 69305b261ecSmrg swaps (&size->widthInMillimeters, n); 69405b261ecSmrg swaps (&size->heightInMillimeters, n); 69505b261ecSmrg } 69605b261ecSmrg size++; 69705b261ecSmrg if (has_rate) 69805b261ecSmrg { 69905b261ecSmrg *rates = pSize->nRates; 70005b261ecSmrg if (client->swapped) 70105b261ecSmrg { 70205b261ecSmrg swaps (rates, n); 70305b261ecSmrg } 70405b261ecSmrg rates++; 70505b261ecSmrg for (j = 0; j < pSize->nRates; j++) 70605b261ecSmrg { 70705b261ecSmrg *rates = pSize->pRates[j].rate; 70805b261ecSmrg if (client->swapped) 70905b261ecSmrg { 71005b261ecSmrg swaps (rates, n); 71105b261ecSmrg } 71205b261ecSmrg rates++; 71305b261ecSmrg } 71405b261ecSmrg } 71505b261ecSmrg } 7166747b715Smrg free(pData); 71705b261ecSmrg 71805b261ecSmrg data8 = (CARD8 *) rates; 71905b261ecSmrg 72005b261ecSmrg if (data8 - (CARD8 *) extra != extraLen) 72105b261ecSmrg FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n", 72205b261ecSmrg (unsigned long)(data8 - (CARD8 *) extra), extraLen); 7236747b715Smrg rep.length = bytes_to_int32(extraLen); 72405b261ecSmrg } 72505b261ecSmrg if (client->swapped) { 72605b261ecSmrg swaps(&rep.sequenceNumber, n); 72705b261ecSmrg swapl(&rep.length, n); 72805b261ecSmrg swapl(&rep.timestamp, n); 72905b261ecSmrg swaps(&rep.rotation, n); 73005b261ecSmrg swaps(&rep.nSizes, n); 73105b261ecSmrg swaps(&rep.sizeID, n); 73205b261ecSmrg swaps(&rep.rate, n); 73305b261ecSmrg swaps(&rep.nrateEnts, n); 73405b261ecSmrg } 73505b261ecSmrg WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep); 73605b261ecSmrg if (extraLen) 73705b261ecSmrg { 73805b261ecSmrg WriteToClient (client, extraLen, (char *) extra); 7396747b715Smrg free(extra); 74005b261ecSmrg } 7416747b715Smrg return Success; 74205b261ecSmrg} 74305b261ecSmrg 74405b261ecSmrgint 74505b261ecSmrgProcRRSetScreenConfig (ClientPtr client) 74605b261ecSmrg{ 74705b261ecSmrg REQUEST(xRRSetScreenConfigReq); 74805b261ecSmrg xRRSetScreenConfigReply rep; 74905b261ecSmrg DrawablePtr pDraw; 75005b261ecSmrg int n, rc; 75105b261ecSmrg ScreenPtr pScreen; 75205b261ecSmrg rrScrPrivPtr pScrPriv; 75305b261ecSmrg TimeStamp time; 75405b261ecSmrg int i; 75505b261ecSmrg Rotation rotation; 75605b261ecSmrg int rate; 75705b261ecSmrg Bool has_rate; 75805b261ecSmrg RROutputPtr output; 75905b261ecSmrg RRCrtcPtr crtc; 76005b261ecSmrg RRModePtr mode; 76105b261ecSmrg RR10DataPtr pData = NULL; 76205b261ecSmrg RRScreenSizePtr pSize; 76305b261ecSmrg int width, height; 76405b261ecSmrg 76505b261ecSmrg UpdateCurrentTime (); 76605b261ecSmrg 76705b261ecSmrg if (RRClientKnowsRates (client)) 76805b261ecSmrg { 76905b261ecSmrg REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); 77005b261ecSmrg has_rate = TRUE; 77105b261ecSmrg } 77205b261ecSmrg else 77305b261ecSmrg { 77405b261ecSmrg REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); 77505b261ecSmrg has_rate = FALSE; 77605b261ecSmrg } 77705b261ecSmrg 77805b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess); 77905b261ecSmrg if (rc != Success) 78005b261ecSmrg return rc; 78105b261ecSmrg 78205b261ecSmrg pScreen = pDraw->pScreen; 78305b261ecSmrg 78405b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 78505b261ecSmrg 78605b261ecSmrg time = ClientTimeToServerTime(stuff->timestamp); 78705b261ecSmrg 78805b261ecSmrg if (!pScrPriv) 78905b261ecSmrg { 79005b261ecSmrg time = currentTime; 79105b261ecSmrg rep.status = RRSetConfigFailed; 79205b261ecSmrg goto sendReply; 79305b261ecSmrg } 7944642e01fSmrg if (!RRGetInfo (pScreen, FALSE)) 79505b261ecSmrg return BadAlloc; 79605b261ecSmrg 79705b261ecSmrg output = RRFirstOutput (pScreen); 79805b261ecSmrg if (!output) 79905b261ecSmrg { 80005b261ecSmrg time = currentTime; 80105b261ecSmrg rep.status = RRSetConfigFailed; 80205b261ecSmrg goto sendReply; 80305b261ecSmrg } 80405b261ecSmrg 80505b261ecSmrg crtc = output->crtc; 80605b261ecSmrg 80705b261ecSmrg /* 80805b261ecSmrg * If the client's config timestamp is not the same as the last config 80905b261ecSmrg * timestamp, then the config information isn't up-to-date and 81005b261ecSmrg * can't even be validated. 81105b261ecSmrg * 81205b261ecSmrg * Note that the client only knows about the milliseconds part of the 81305b261ecSmrg * timestamp, so using CompareTimeStamps here would cause randr to suddenly 81405b261ecSmrg * stop working after several hours have passed (freedesktop bug #6502). 81505b261ecSmrg */ 81605b261ecSmrg if (stuff->configTimestamp != pScrPriv->lastConfigTime.milliseconds) 81705b261ecSmrg { 81805b261ecSmrg rep.status = RRSetConfigInvalidConfigTime; 81905b261ecSmrg goto sendReply; 82005b261ecSmrg } 82105b261ecSmrg 82205b261ecSmrg pData = RR10GetData (pScreen, output); 82305b261ecSmrg if (!pData) 82405b261ecSmrg return BadAlloc; 82505b261ecSmrg 82605b261ecSmrg if (stuff->sizeID >= pData->nsize) 82705b261ecSmrg { 82805b261ecSmrg /* 82905b261ecSmrg * Invalid size ID 83005b261ecSmrg */ 83105b261ecSmrg client->errorValue = stuff->sizeID; 8326747b715Smrg free(pData); 83305b261ecSmrg return BadValue; 83405b261ecSmrg } 83505b261ecSmrg pSize = &pData->sizes[stuff->sizeID]; 83605b261ecSmrg 83705b261ecSmrg /* 83805b261ecSmrg * Validate requested rotation 83905b261ecSmrg */ 84005b261ecSmrg rotation = (Rotation) stuff->rotation; 84105b261ecSmrg 84205b261ecSmrg /* test the rotation bits only! */ 84305b261ecSmrg switch (rotation & 0xf) { 84405b261ecSmrg case RR_Rotate_0: 84505b261ecSmrg case RR_Rotate_90: 84605b261ecSmrg case RR_Rotate_180: 84705b261ecSmrg case RR_Rotate_270: 84805b261ecSmrg break; 84905b261ecSmrg default: 85005b261ecSmrg /* 85105b261ecSmrg * Invalid rotation 85205b261ecSmrg */ 85305b261ecSmrg client->errorValue = stuff->rotation; 8546747b715Smrg free(pData); 85505b261ecSmrg return BadValue; 85605b261ecSmrg } 85705b261ecSmrg 85805b261ecSmrg if ((~crtc->rotations) & rotation) 85905b261ecSmrg { 86005b261ecSmrg /* 86105b261ecSmrg * requested rotation or reflection not supported by screen 86205b261ecSmrg */ 86305b261ecSmrg client->errorValue = stuff->rotation; 8646747b715Smrg free(pData); 86505b261ecSmrg return BadMatch; 86605b261ecSmrg } 86705b261ecSmrg 86805b261ecSmrg /* 86905b261ecSmrg * Validate requested refresh 87005b261ecSmrg */ 87105b261ecSmrg if (has_rate) 87205b261ecSmrg rate = (int) stuff->rate; 87305b261ecSmrg else 87405b261ecSmrg rate = 0; 87505b261ecSmrg 87605b261ecSmrg if (rate) 87705b261ecSmrg { 87805b261ecSmrg for (i = 0; i < pSize->nRates; i++) 87905b261ecSmrg { 88005b261ecSmrg if (pSize->pRates[i].rate == rate) 88105b261ecSmrg break; 88205b261ecSmrg } 88305b261ecSmrg if (i == pSize->nRates) 88405b261ecSmrg { 88505b261ecSmrg /* 88605b261ecSmrg * Invalid rate 88705b261ecSmrg */ 88805b261ecSmrg client->errorValue = rate; 8896747b715Smrg free(pData); 89005b261ecSmrg return BadValue; 89105b261ecSmrg } 89205b261ecSmrg mode = pSize->pRates[i].mode; 89305b261ecSmrg } 89405b261ecSmrg else 89505b261ecSmrg mode = pSize->pRates[0].mode; 89605b261ecSmrg 89705b261ecSmrg /* 89805b261ecSmrg * Make sure the requested set-time is not older than 89905b261ecSmrg * the last set-time 90005b261ecSmrg */ 90105b261ecSmrg if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) 90205b261ecSmrg { 90305b261ecSmrg rep.status = RRSetConfigInvalidTime; 90405b261ecSmrg goto sendReply; 90505b261ecSmrg } 90605b261ecSmrg 90705b261ecSmrg /* 90805b261ecSmrg * If the screen size is changing, adjust all of the other outputs 90905b261ecSmrg * to fit the new size, mirroring as much as possible 91005b261ecSmrg */ 91105b261ecSmrg width = mode->mode.width; 91205b261ecSmrg height = mode->mode.height; 91305b261ecSmrg if (rotation & (RR_Rotate_90|RR_Rotate_270)) 91405b261ecSmrg { 91505b261ecSmrg width = mode->mode.height; 91605b261ecSmrg height = mode->mode.width; 91705b261ecSmrg } 91805b261ecSmrg if (width != pScreen->width || height != pScreen->height) 91905b261ecSmrg { 92005b261ecSmrg int c; 92105b261ecSmrg 92205b261ecSmrg for (c = 0; c < pScrPriv->numCrtcs; c++) 92305b261ecSmrg { 92405b261ecSmrg if (!RRCrtcSet (pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0, 92505b261ecSmrg 0, NULL)) 92605b261ecSmrg { 92705b261ecSmrg rep.status = RRSetConfigFailed; 92805b261ecSmrg /* XXX recover from failure */ 92905b261ecSmrg goto sendReply; 93005b261ecSmrg } 93105b261ecSmrg } 93205b261ecSmrg if (!RRScreenSizeSet (pScreen, width, height, 93305b261ecSmrg pScreen->mmWidth, pScreen->mmHeight)) 93405b261ecSmrg { 93505b261ecSmrg rep.status = RRSetConfigFailed; 93605b261ecSmrg /* XXX recover from failure */ 93705b261ecSmrg goto sendReply; 93805b261ecSmrg } 93905b261ecSmrg } 94005b261ecSmrg 94105b261ecSmrg if (!RRCrtcSet (crtc, mode, 0, 0, stuff->rotation, 1, &output)) 94205b261ecSmrg rep.status = RRSetConfigFailed; 94352397711Smrg else { 94452397711Smrg pScrPriv->lastSetTime = time; 94505b261ecSmrg rep.status = RRSetConfigSuccess; 94652397711Smrg } 94705b261ecSmrg 94805b261ecSmrg /* 94905b261ecSmrg * XXX Configure other crtcs to mirror as much as possible 95005b261ecSmrg */ 95105b261ecSmrg 95205b261ecSmrgsendReply: 95305b261ecSmrg 9546747b715Smrg free(pData); 95505b261ecSmrg 95605b261ecSmrg rep.type = X_Reply; 95705b261ecSmrg /* rep.status has already been filled in */ 95805b261ecSmrg rep.length = 0; 95905b261ecSmrg rep.sequenceNumber = client->sequence; 96005b261ecSmrg 96105b261ecSmrg rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; 96205b261ecSmrg rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds; 9636747b715Smrg rep.root = pDraw->pScreen->root->drawable.id; 96405b261ecSmrg 96505b261ecSmrg if (client->swapped) 96605b261ecSmrg { 96705b261ecSmrg swaps(&rep.sequenceNumber, n); 96805b261ecSmrg swapl(&rep.length, n); 96905b261ecSmrg swapl(&rep.newTimestamp, n); 97005b261ecSmrg swapl(&rep.newConfigTimestamp, n); 97105b261ecSmrg swapl(&rep.root, n); 97205b261ecSmrg } 97305b261ecSmrg WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep); 97405b261ecSmrg 9756747b715Smrg return Success; 97605b261ecSmrg} 97705b261ecSmrg 97805b261ecSmrgstatic CARD16 97905b261ecSmrgRR10CurrentSizeID (ScreenPtr pScreen) 98005b261ecSmrg{ 98105b261ecSmrg CARD16 sizeID = 0xffff; 98205b261ecSmrg RROutputPtr output = RRFirstOutput (pScreen); 98305b261ecSmrg 98405b261ecSmrg if (output) 98505b261ecSmrg { 98605b261ecSmrg RR10DataPtr data = RR10GetData (pScreen, output); 98705b261ecSmrg if (data) 98805b261ecSmrg { 98905b261ecSmrg int i; 99005b261ecSmrg for (i = 0; i < data->nsize; i++) 99105b261ecSmrg if (data->sizes[i].width == pScreen->width && 99205b261ecSmrg data->sizes[i].height == pScreen->height) 99305b261ecSmrg { 99405b261ecSmrg sizeID = (CARD16) i; 99505b261ecSmrg break; 99605b261ecSmrg } 9976747b715Smrg free(data); 99805b261ecSmrg } 99905b261ecSmrg } 100005b261ecSmrg return sizeID; 100105b261ecSmrg} 1002