rroutput.c revision 6747b715
105b261ecSmrg/* 205b261ecSmrg * Copyright © 2006 Keith Packard 34642e01fSmrg * Copyright © 2008 Red Hat, Inc. 405b261ecSmrg * 505b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 705b261ecSmrg * the above copyright notice appear in all copies and that both that copyright 805b261ecSmrg * notice and this permission notice appear in supporting documentation, and 905b261ecSmrg * that the name of the copyright holders not be used in advertising or 1005b261ecSmrg * publicity pertaining to distribution of the software without specific, 1105b261ecSmrg * written prior permission. The copyright holders make no representations 1205b261ecSmrg * about the suitability of this software for any purpose. It is provided "as 1305b261ecSmrg * is" without express or implied warranty. 1405b261ecSmrg * 1505b261ecSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1605b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1705b261ecSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1805b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1905b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2005b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2105b261ecSmrg * OF THIS SOFTWARE. 2205b261ecSmrg */ 2305b261ecSmrg 2405b261ecSmrg#include "randrstr.h" 2505b261ecSmrg 2605b261ecSmrgRESTYPE RROutputType; 2705b261ecSmrg 2805b261ecSmrg/* 2905b261ecSmrg * Notify the output of some change 3005b261ecSmrg */ 3105b261ecSmrgvoid 3205b261ecSmrgRROutputChanged (RROutputPtr output, Bool configChanged) 3305b261ecSmrg{ 3405b261ecSmrg ScreenPtr pScreen = output->pScreen; 3505b261ecSmrg 3605b261ecSmrg output->changed = TRUE; 3705b261ecSmrg if (pScreen) 3805b261ecSmrg { 3905b261ecSmrg rrScrPriv (pScreen); 4005b261ecSmrg pScrPriv->changed = TRUE; 4105b261ecSmrg if (configChanged) 4205b261ecSmrg pScrPriv->configChanged = TRUE; 4305b261ecSmrg } 4405b261ecSmrg} 4505b261ecSmrg 4605b261ecSmrg/* 4705b261ecSmrg * Create an output 4805b261ecSmrg */ 4905b261ecSmrg 5005b261ecSmrgRROutputPtr 5105b261ecSmrgRROutputCreate (ScreenPtr pScreen, 5205b261ecSmrg const char *name, 5305b261ecSmrg int nameLength, 5405b261ecSmrg void *devPrivate) 5505b261ecSmrg{ 5605b261ecSmrg RROutputPtr output; 5705b261ecSmrg RROutputPtr *outputs; 5805b261ecSmrg rrScrPrivPtr pScrPriv; 5905b261ecSmrg 6005b261ecSmrg if (!RRInit()) 6105b261ecSmrg return NULL; 6205b261ecSmrg 6305b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 6405b261ecSmrg 6505b261ecSmrg if (pScrPriv->numOutputs) 666747b715Smrg outputs = realloc(pScrPriv->outputs, 6705b261ecSmrg (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr)); 6805b261ecSmrg else 696747b715Smrg outputs = malloc(sizeof (RROutputPtr)); 7005b261ecSmrg if (!outputs) 7105b261ecSmrg return FALSE; 7205b261ecSmrg 7305b261ecSmrg pScrPriv->outputs = outputs; 7405b261ecSmrg 756747b715Smrg output = malloc(sizeof (RROutputRec) + nameLength + 1); 7605b261ecSmrg if (!output) 7705b261ecSmrg return NULL; 7805b261ecSmrg output->id = FakeClientID (0); 7905b261ecSmrg output->pScreen = pScreen; 8005b261ecSmrg output->name = (char *) (output + 1); 8105b261ecSmrg output->nameLength = nameLength; 8205b261ecSmrg memcpy (output->name, name, nameLength); 8305b261ecSmrg output->name[nameLength] = '\0'; 8405b261ecSmrg output->connection = RR_UnknownConnection; 8505b261ecSmrg output->subpixelOrder = SubPixelUnknown; 8605b261ecSmrg output->mmWidth = 0; 8705b261ecSmrg output->mmHeight = 0; 8805b261ecSmrg output->crtc = NULL; 8905b261ecSmrg output->numCrtcs = 0; 9005b261ecSmrg output->crtcs = NULL; 9105b261ecSmrg output->numClones = 0; 9205b261ecSmrg output->clones = NULL; 9305b261ecSmrg output->numModes = 0; 9405b261ecSmrg output->numPreferred = 0; 9505b261ecSmrg output->modes = NULL; 9605b261ecSmrg output->numUserModes = 0; 9705b261ecSmrg output->userModes = NULL; 9805b261ecSmrg output->properties = NULL; 994642e01fSmrg output->pendingProperties = FALSE; 10005b261ecSmrg output->changed = FALSE; 10105b261ecSmrg output->devPrivate = devPrivate; 10205b261ecSmrg 10305b261ecSmrg if (!AddResource (output->id, RROutputType, (pointer) output)) 10405b261ecSmrg return NULL; 10505b261ecSmrg 10605b261ecSmrg pScrPriv->outputs[pScrPriv->numOutputs++] = output; 10705b261ecSmrg return output; 10805b261ecSmrg} 10905b261ecSmrg 11005b261ecSmrg/* 11105b261ecSmrg * Notify extension that output parameters have been changed 11205b261ecSmrg */ 11305b261ecSmrgBool 11405b261ecSmrgRROutputSetClones (RROutputPtr output, 11505b261ecSmrg RROutputPtr *clones, 11605b261ecSmrg int numClones) 11705b261ecSmrg{ 11805b261ecSmrg RROutputPtr *newClones; 11905b261ecSmrg int i; 12005b261ecSmrg 12105b261ecSmrg if (numClones == output->numClones) 12205b261ecSmrg { 12305b261ecSmrg for (i = 0; i < numClones; i++) 12405b261ecSmrg if (output->clones[i] != clones[i]) 12505b261ecSmrg break; 12605b261ecSmrg if (i == numClones) 12705b261ecSmrg return TRUE; 12805b261ecSmrg } 12905b261ecSmrg if (numClones) 13005b261ecSmrg { 1316747b715Smrg newClones = malloc(numClones * sizeof (RROutputPtr)); 13205b261ecSmrg if (!newClones) 13305b261ecSmrg return FALSE; 13405b261ecSmrg } 13505b261ecSmrg else 13605b261ecSmrg newClones = NULL; 1376747b715Smrg free(output->clones); 13805b261ecSmrg memcpy (newClones, clones, numClones * sizeof (RROutputPtr)); 13905b261ecSmrg output->clones = newClones; 14005b261ecSmrg output->numClones = numClones; 14105b261ecSmrg RROutputChanged (output, TRUE); 14205b261ecSmrg return TRUE; 14305b261ecSmrg} 14405b261ecSmrg 14505b261ecSmrgBool 14605b261ecSmrgRROutputSetModes (RROutputPtr output, 14705b261ecSmrg RRModePtr *modes, 14805b261ecSmrg int numModes, 14905b261ecSmrg int numPreferred) 15005b261ecSmrg{ 15105b261ecSmrg RRModePtr *newModes; 15205b261ecSmrg int i; 15305b261ecSmrg 15405b261ecSmrg if (numModes == output->numModes && numPreferred == output->numPreferred) 15505b261ecSmrg { 15605b261ecSmrg for (i = 0; i < numModes; i++) 15705b261ecSmrg if (output->modes[i] != modes[i]) 15805b261ecSmrg break; 15905b261ecSmrg if (i == numModes) 16005b261ecSmrg { 16105b261ecSmrg for (i = 0; i < numModes; i++) 16205b261ecSmrg RRModeDestroy (modes[i]); 16305b261ecSmrg return TRUE; 16405b261ecSmrg } 16505b261ecSmrg } 16605b261ecSmrg 16705b261ecSmrg if (numModes) 16805b261ecSmrg { 1696747b715Smrg newModes = malloc(numModes * sizeof (RRModePtr)); 17005b261ecSmrg if (!newModes) 17105b261ecSmrg return FALSE; 17205b261ecSmrg } 17305b261ecSmrg else 17405b261ecSmrg newModes = NULL; 17505b261ecSmrg if (output->modes) 17605b261ecSmrg { 17705b261ecSmrg for (i = 0; i < output->numModes; i++) 17805b261ecSmrg RRModeDestroy (output->modes[i]); 1796747b715Smrg free(output->modes); 18005b261ecSmrg } 18105b261ecSmrg memcpy (newModes, modes, numModes * sizeof (RRModePtr)); 18205b261ecSmrg output->modes = newModes; 18305b261ecSmrg output->numModes = numModes; 18405b261ecSmrg output->numPreferred = numPreferred; 18505b261ecSmrg RROutputChanged (output, TRUE); 18605b261ecSmrg return TRUE; 18705b261ecSmrg} 18805b261ecSmrg 18905b261ecSmrgint 19005b261ecSmrgRROutputAddUserMode (RROutputPtr output, 19105b261ecSmrg RRModePtr mode) 19205b261ecSmrg{ 19305b261ecSmrg int m; 19405b261ecSmrg ScreenPtr pScreen = output->pScreen; 19505b261ecSmrg rrScrPriv(pScreen); 19605b261ecSmrg RRModePtr *newModes; 19705b261ecSmrg 19805b261ecSmrg /* Check to see if this mode is already listed for this output */ 19905b261ecSmrg for (m = 0; m < output->numModes + output->numUserModes; m++) 20005b261ecSmrg { 20105b261ecSmrg RRModePtr e = (m < output->numModes ? 20205b261ecSmrg output->modes[m] : 20305b261ecSmrg output->userModes[m - output->numModes]); 20405b261ecSmrg if (mode == e) 20505b261ecSmrg return Success; 20605b261ecSmrg } 20705b261ecSmrg 20805b261ecSmrg /* Check with the DDX to see if this mode is OK */ 20905b261ecSmrg if (pScrPriv->rrOutputValidateMode) 21005b261ecSmrg if (!pScrPriv->rrOutputValidateMode (pScreen, output, mode)) 21105b261ecSmrg return BadMatch; 21205b261ecSmrg 21305b261ecSmrg if (output->userModes) 2146747b715Smrg newModes = realloc(output->userModes, 21505b261ecSmrg (output->numUserModes + 1) * sizeof (RRModePtr)); 21605b261ecSmrg else 2176747b715Smrg newModes = malloc(sizeof (RRModePtr)); 21805b261ecSmrg if (!newModes) 21905b261ecSmrg return BadAlloc; 22005b261ecSmrg 22105b261ecSmrg output->userModes = newModes; 22205b261ecSmrg output->userModes[output->numUserModes++] = mode; 22305b261ecSmrg ++mode->refcnt; 22405b261ecSmrg RROutputChanged (output, TRUE); 22505b261ecSmrg RRTellChanged (pScreen); 22605b261ecSmrg return Success; 22705b261ecSmrg} 22805b261ecSmrg 22905b261ecSmrgint 23005b261ecSmrgRROutputDeleteUserMode (RROutputPtr output, 23105b261ecSmrg RRModePtr mode) 23205b261ecSmrg{ 23305b261ecSmrg int m; 23405b261ecSmrg 23505b261ecSmrg /* Find this mode in the user mode list */ 23605b261ecSmrg for (m = 0; m < output->numUserModes; m++) 23705b261ecSmrg { 23805b261ecSmrg RRModePtr e = output->userModes[m]; 23905b261ecSmrg 24005b261ecSmrg if (mode == e) 24105b261ecSmrg break; 24205b261ecSmrg } 24305b261ecSmrg /* Not there, access error */ 24405b261ecSmrg if (m == output->numUserModes) 24505b261ecSmrg return BadAccess; 24605b261ecSmrg 24705b261ecSmrg /* make sure the mode isn't active for this output */ 24805b261ecSmrg if (output->crtc && output->crtc->mode == mode) 24905b261ecSmrg return BadMatch; 25005b261ecSmrg 25105b261ecSmrg memmove (output->userModes + m, output->userModes + m + 1, 25205b261ecSmrg (output->numUserModes - m - 1) * sizeof (RRModePtr)); 25305b261ecSmrg output->numUserModes--; 25405b261ecSmrg RRModeDestroy (mode); 25505b261ecSmrg return Success; 25605b261ecSmrg} 25705b261ecSmrg 25805b261ecSmrgBool 25905b261ecSmrgRROutputSetCrtcs (RROutputPtr output, 26005b261ecSmrg RRCrtcPtr *crtcs, 26105b261ecSmrg int numCrtcs) 26205b261ecSmrg{ 26305b261ecSmrg RRCrtcPtr *newCrtcs; 26405b261ecSmrg int i; 26505b261ecSmrg 26605b261ecSmrg if (numCrtcs == output->numCrtcs) 26705b261ecSmrg { 26805b261ecSmrg for (i = 0; i < numCrtcs; i++) 26905b261ecSmrg if (output->crtcs[i] != crtcs[i]) 27005b261ecSmrg break; 27105b261ecSmrg if (i == numCrtcs) 27205b261ecSmrg return TRUE; 27305b261ecSmrg } 27405b261ecSmrg if (numCrtcs) 27505b261ecSmrg { 2766747b715Smrg newCrtcs = malloc(numCrtcs * sizeof (RRCrtcPtr)); 27705b261ecSmrg if (!newCrtcs) 27805b261ecSmrg return FALSE; 27905b261ecSmrg } 28005b261ecSmrg else 28105b261ecSmrg newCrtcs = NULL; 2826747b715Smrg free(output->crtcs); 28305b261ecSmrg memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr)); 28405b261ecSmrg output->crtcs = newCrtcs; 28505b261ecSmrg output->numCrtcs = numCrtcs; 28605b261ecSmrg RROutputChanged (output, TRUE); 28705b261ecSmrg return TRUE; 28805b261ecSmrg} 28905b261ecSmrg 29005b261ecSmrgBool 29105b261ecSmrgRROutputSetConnection (RROutputPtr output, 29205b261ecSmrg CARD8 connection) 29305b261ecSmrg{ 29405b261ecSmrg if (output->connection == connection) 29505b261ecSmrg return TRUE; 29605b261ecSmrg output->connection = connection; 29705b261ecSmrg RROutputChanged (output, TRUE); 29805b261ecSmrg return TRUE; 29905b261ecSmrg} 30005b261ecSmrg 30105b261ecSmrgBool 30205b261ecSmrgRROutputSetSubpixelOrder (RROutputPtr output, 30305b261ecSmrg int subpixelOrder) 30405b261ecSmrg{ 30505b261ecSmrg if (output->subpixelOrder == subpixelOrder) 30605b261ecSmrg return TRUE; 30705b261ecSmrg 30805b261ecSmrg output->subpixelOrder = subpixelOrder; 30905b261ecSmrg RROutputChanged (output, FALSE); 31005b261ecSmrg return TRUE; 31105b261ecSmrg} 31205b261ecSmrg 31305b261ecSmrgBool 31405b261ecSmrgRROutputSetPhysicalSize (RROutputPtr output, 31505b261ecSmrg int mmWidth, 31605b261ecSmrg int mmHeight) 31705b261ecSmrg{ 31805b261ecSmrg if (output->mmWidth == mmWidth && output->mmHeight == mmHeight) 31905b261ecSmrg return TRUE; 32005b261ecSmrg output->mmWidth = mmWidth; 32105b261ecSmrg output->mmHeight = mmHeight; 32205b261ecSmrg RROutputChanged (output, FALSE); 32305b261ecSmrg return TRUE; 32405b261ecSmrg} 32505b261ecSmrg 32605b261ecSmrg 32705b261ecSmrgvoid 32805b261ecSmrgRRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output) 32905b261ecSmrg{ 33005b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 33105b261ecSmrg rrScrPriv (pScreen); 33205b261ecSmrg xRROutputChangeNotifyEvent oe; 33305b261ecSmrg RRCrtcPtr crtc = output->crtc; 33405b261ecSmrg RRModePtr mode = crtc ? crtc->mode : 0; 33505b261ecSmrg 33605b261ecSmrg oe.type = RRNotify + RREventBase; 33705b261ecSmrg oe.subCode = RRNotify_OutputChange; 33805b261ecSmrg oe.timestamp = pScrPriv->lastSetTime.milliseconds; 33905b261ecSmrg oe.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 34005b261ecSmrg oe.window = pWin->drawable.id; 34105b261ecSmrg oe.output = output->id; 34205b261ecSmrg if (crtc) 34305b261ecSmrg { 34405b261ecSmrg oe.crtc = crtc->id; 34505b261ecSmrg oe.mode = mode ? mode->mode.id : None; 34605b261ecSmrg oe.rotation = crtc->rotation; 34705b261ecSmrg } 34805b261ecSmrg else 34905b261ecSmrg { 35005b261ecSmrg oe.crtc = None; 35105b261ecSmrg oe.mode = None; 35205b261ecSmrg oe.rotation = RR_Rotate_0; 35305b261ecSmrg } 35405b261ecSmrg oe.connection = output->connection; 35505b261ecSmrg oe.subpixelOrder = output->subpixelOrder; 35605b261ecSmrg WriteEventsToClient (client, 1, (xEvent *) &oe); 35705b261ecSmrg} 35805b261ecSmrg 35905b261ecSmrg/* 36005b261ecSmrg * Destroy a Output at shutdown 36105b261ecSmrg */ 36205b261ecSmrgvoid 36305b261ecSmrgRROutputDestroy (RROutputPtr output) 36405b261ecSmrg{ 36505b261ecSmrg FreeResource (output->id, 0); 36605b261ecSmrg} 36705b261ecSmrg 36805b261ecSmrgstatic int 36905b261ecSmrgRROutputDestroyResource (pointer value, XID pid) 37005b261ecSmrg{ 37105b261ecSmrg RROutputPtr output = (RROutputPtr) value; 37205b261ecSmrg ScreenPtr pScreen = output->pScreen; 37305b261ecSmrg int m; 37405b261ecSmrg 37505b261ecSmrg if (pScreen) 37605b261ecSmrg { 37705b261ecSmrg rrScrPriv(pScreen); 37805b261ecSmrg int i; 3794642e01fSmrg 3804642e01fSmrg if (pScrPriv->primaryOutput == output) 3814642e01fSmrg pScrPriv->primaryOutput = NULL; 38205b261ecSmrg 38305b261ecSmrg for (i = 0; i < pScrPriv->numOutputs; i++) 38405b261ecSmrg { 38505b261ecSmrg if (pScrPriv->outputs[i] == output) 38605b261ecSmrg { 38705b261ecSmrg memmove (pScrPriv->outputs + i, pScrPriv->outputs + i + 1, 38805b261ecSmrg (pScrPriv->numOutputs - (i + 1)) * sizeof (RROutputPtr)); 38905b261ecSmrg --pScrPriv->numOutputs; 39005b261ecSmrg break; 39105b261ecSmrg } 39205b261ecSmrg } 39305b261ecSmrg } 39405b261ecSmrg if (output->modes) 39505b261ecSmrg { 39605b261ecSmrg for (m = 0; m < output->numModes; m++) 39705b261ecSmrg RRModeDestroy (output->modes[m]); 3986747b715Smrg free(output->modes); 39905b261ecSmrg } 40005b261ecSmrg 40105b261ecSmrg for (m = 0; m < output->numUserModes; m++) 40205b261ecSmrg RRModeDestroy (output->userModes[m]); 4036747b715Smrg free(output->userModes); 40405b261ecSmrg 4056747b715Smrg free(output->crtcs); 4066747b715Smrg free(output->clones); 40705b261ecSmrg RRDeleteAllOutputProperties (output); 4086747b715Smrg free(output); 40905b261ecSmrg return 1; 41005b261ecSmrg} 41105b261ecSmrg 41205b261ecSmrg/* 41305b261ecSmrg * Initialize output type 41405b261ecSmrg */ 41505b261ecSmrgBool 41605b261ecSmrgRROutputInit (void) 41705b261ecSmrg{ 4186747b715Smrg RROutputType = CreateNewResourceType (RROutputDestroyResource, "OUTPUT"); 41905b261ecSmrg if (!RROutputType) 42005b261ecSmrg return FALSE; 4216747b715Smrg 42205b261ecSmrg return TRUE; 42305b261ecSmrg} 42405b261ecSmrg 4256747b715Smrg/* 4266747b715Smrg * Initialize output type error value 4276747b715Smrg */ 4286747b715Smrgvoid 4296747b715SmrgRROutputInitErrorValue(void) 4306747b715Smrg{ 4316747b715Smrg SetResourceTypeErrorValue(RROutputType, RRErrorBase + BadRROutput); 4326747b715Smrg} 4336747b715Smrg 43405b261ecSmrg#define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32) 4354642e01fSmrg 43605b261ecSmrgint 43705b261ecSmrgProcRRGetOutputInfo (ClientPtr client) 43805b261ecSmrg{ 43905b261ecSmrg REQUEST(xRRGetOutputInfoReq); 44005b261ecSmrg xRRGetOutputInfoReply rep; 44105b261ecSmrg RROutputPtr output; 44205b261ecSmrg CARD8 *extra; 44305b261ecSmrg unsigned long extraLen; 44405b261ecSmrg ScreenPtr pScreen; 44505b261ecSmrg rrScrPrivPtr pScrPriv; 44605b261ecSmrg RRCrtc *crtcs; 44705b261ecSmrg RRMode *modes; 44805b261ecSmrg RROutput *clones; 44905b261ecSmrg char *name; 45005b261ecSmrg int i, n; 45105b261ecSmrg 45205b261ecSmrg REQUEST_SIZE_MATCH(xRRGetOutputInfoReq); 4536747b715Smrg VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); 45405b261ecSmrg 45505b261ecSmrg pScreen = output->pScreen; 45605b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 45705b261ecSmrg 45805b261ecSmrg rep.type = X_Reply; 45905b261ecSmrg rep.sequenceNumber = client->sequence; 4606747b715Smrg rep.length = bytes_to_int32(OutputInfoExtra); 46105b261ecSmrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 46205b261ecSmrg rep.crtc = output->crtc ? output->crtc->id : None; 46305b261ecSmrg rep.mmWidth = output->mmWidth; 46405b261ecSmrg rep.mmHeight = output->mmHeight; 46505b261ecSmrg rep.connection = output->connection; 46605b261ecSmrg rep.subpixelOrder = output->subpixelOrder; 46705b261ecSmrg rep.nCrtcs = output->numCrtcs; 46805b261ecSmrg rep.nModes = output->numModes + output->numUserModes; 46905b261ecSmrg rep.nPreferred = output->numPreferred; 47005b261ecSmrg rep.nClones = output->numClones; 47105b261ecSmrg rep.nameLength = output->nameLength; 47205b261ecSmrg 4736747b715Smrg extraLen = ((output->numCrtcs + 47405b261ecSmrg output->numModes + output->numUserModes + 47505b261ecSmrg output->numClones + 4766747b715Smrg bytes_to_int32(rep.nameLength)) << 2); 47705b261ecSmrg 47805b261ecSmrg if (extraLen) 47905b261ecSmrg { 4806747b715Smrg rep.length += bytes_to_int32(extraLen); 4816747b715Smrg extra = malloc(extraLen); 48205b261ecSmrg if (!extra) 48305b261ecSmrg return BadAlloc; 48405b261ecSmrg } 48505b261ecSmrg else 48605b261ecSmrg extra = NULL; 48705b261ecSmrg 48805b261ecSmrg crtcs = (RRCrtc *) extra; 48905b261ecSmrg modes = (RRMode *) (crtcs + output->numCrtcs); 49005b261ecSmrg clones = (RROutput *) (modes + output->numModes + output->numUserModes); 49105b261ecSmrg name = (char *) (clones + output->numClones); 49205b261ecSmrg 49305b261ecSmrg for (i = 0; i < output->numCrtcs; i++) 49405b261ecSmrg { 49505b261ecSmrg crtcs[i] = output->crtcs[i]->id; 49605b261ecSmrg if (client->swapped) 49705b261ecSmrg swapl (&crtcs[i], n); 49805b261ecSmrg } 49905b261ecSmrg for (i = 0; i < output->numModes + output->numUserModes; i++) 50005b261ecSmrg { 50105b261ecSmrg if (i < output->numModes) 50205b261ecSmrg modes[i] = output->modes[i]->mode.id; 50305b261ecSmrg else 50405b261ecSmrg modes[i] = output->userModes[i - output->numModes]->mode.id; 50505b261ecSmrg if (client->swapped) 50605b261ecSmrg swapl (&modes[i], n); 50705b261ecSmrg } 50805b261ecSmrg for (i = 0; i < output->numClones; i++) 50905b261ecSmrg { 51005b261ecSmrg clones[i] = output->clones[i]->id; 51105b261ecSmrg if (client->swapped) 51205b261ecSmrg swapl (&clones[i], n); 51305b261ecSmrg } 51405b261ecSmrg memcpy (name, output->name, output->nameLength); 51505b261ecSmrg if (client->swapped) { 51605b261ecSmrg swaps(&rep.sequenceNumber, n); 51705b261ecSmrg swapl(&rep.length, n); 51805b261ecSmrg swapl(&rep.timestamp, n); 51905b261ecSmrg swapl(&rep.crtc, n); 52005b261ecSmrg swapl(&rep.mmWidth, n); 52105b261ecSmrg swapl(&rep.mmHeight, n); 52205b261ecSmrg swaps(&rep.nCrtcs, n); 52305b261ecSmrg swaps(&rep.nModes, n); 52405b261ecSmrg swaps(&rep.nClones, n); 52505b261ecSmrg swaps(&rep.nameLength, n); 52605b261ecSmrg } 52705b261ecSmrg WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *)&rep); 52805b261ecSmrg if (extraLen) 52905b261ecSmrg { 53005b261ecSmrg WriteToClient (client, extraLen, (char *) extra); 5316747b715Smrg free(extra); 53205b261ecSmrg } 53305b261ecSmrg 5346747b715Smrg return Success; 53505b261ecSmrg} 5364642e01fSmrg 5376747b715Smrgstatic void 5384642e01fSmrgRRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv, 5394642e01fSmrg RROutputPtr output) 5404642e01fSmrg{ 5414642e01fSmrg if (pScrPriv->primaryOutput == output) 5424642e01fSmrg return; 5434642e01fSmrg 5444642e01fSmrg /* clear the old primary */ 5454642e01fSmrg if (pScrPriv->primaryOutput) { 5464642e01fSmrg RROutputChanged(pScrPriv->primaryOutput, 0); 5474642e01fSmrg pScrPriv->primaryOutput = NULL; 5484642e01fSmrg } 5494642e01fSmrg 5504642e01fSmrg /* set the new primary */ 5514642e01fSmrg if (output) { 5524642e01fSmrg pScrPriv->primaryOutput = output; 5534642e01fSmrg RROutputChanged(output, 0); 5544642e01fSmrg } 5554642e01fSmrg 5564642e01fSmrg pScrPriv->layoutChanged = TRUE; 5574642e01fSmrg 5584642e01fSmrg RRTellChanged(pScreen); 5594642e01fSmrg} 5604642e01fSmrg 5614642e01fSmrgint 5624642e01fSmrgProcRRSetOutputPrimary(ClientPtr client) 5634642e01fSmrg{ 5644642e01fSmrg REQUEST(xRRSetOutputPrimaryReq); 5654642e01fSmrg RROutputPtr output = NULL; 5664642e01fSmrg WindowPtr pWin; 5674642e01fSmrg rrScrPrivPtr pScrPriv; 5686747b715Smrg int rc; 5694642e01fSmrg 5704642e01fSmrg REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq); 5714642e01fSmrg 5726747b715Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 5736747b715Smrg if (rc != Success) 5746747b715Smrg return rc; 5754642e01fSmrg 5764642e01fSmrg if (stuff->output) { 5776747b715Smrg VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); 5784642e01fSmrg 5794642e01fSmrg if (output->pScreen != pWin->drawable.pScreen) { 5804642e01fSmrg client->errorValue = stuff->window; 5814642e01fSmrg return BadMatch; 5824642e01fSmrg } 5834642e01fSmrg } 5844642e01fSmrg 5854642e01fSmrg pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); 5864642e01fSmrg RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output); 5874642e01fSmrg 5886747b715Smrg return Success; 5894642e01fSmrg} 5904642e01fSmrg 5914642e01fSmrgint 5924642e01fSmrgProcRRGetOutputPrimary(ClientPtr client) 5934642e01fSmrg{ 5944642e01fSmrg REQUEST(xRRGetOutputPrimaryReq); 5954642e01fSmrg WindowPtr pWin; 5964642e01fSmrg rrScrPrivPtr pScrPriv; 5974642e01fSmrg xRRGetOutputPrimaryReply rep; 5984642e01fSmrg RROutputPtr primary = NULL; 5996747b715Smrg int rc; 6004642e01fSmrg 6014642e01fSmrg REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq); 6024642e01fSmrg 6036747b715Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 6046747b715Smrg if (rc != Success) 6056747b715Smrg return rc; 6064642e01fSmrg 6074642e01fSmrg pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); 6084642e01fSmrg if (pScrPriv) 6094642e01fSmrg primary = pScrPriv->primaryOutput; 6104642e01fSmrg 6114642e01fSmrg memset(&rep, 0, sizeof(rep)); 6124642e01fSmrg rep.type = X_Reply; 6134642e01fSmrg rep.sequenceNumber = client->sequence; 6144642e01fSmrg rep.output = primary ? primary->id : None; 6154642e01fSmrg 6164642e01fSmrg if (client->swapped) { 6174642e01fSmrg int n; 6184642e01fSmrg swaps(&rep.sequenceNumber, n); 6194642e01fSmrg swapl(&rep.output, n); 6204642e01fSmrg } 6214642e01fSmrg 6224642e01fSmrg WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), &rep); 6234642e01fSmrg 6246747b715Smrg return Success; 6254642e01fSmrg} 626