rroutput.c revision 4642e01f
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" 254642e01fSmrg#include "registry.h" 2605b261ecSmrg 2705b261ecSmrgRESTYPE RROutputType; 2805b261ecSmrg 2905b261ecSmrg/* 3005b261ecSmrg * Notify the output of some change 3105b261ecSmrg */ 3205b261ecSmrgvoid 3305b261ecSmrgRROutputChanged (RROutputPtr output, Bool configChanged) 3405b261ecSmrg{ 3505b261ecSmrg ScreenPtr pScreen = output->pScreen; 3605b261ecSmrg 3705b261ecSmrg output->changed = TRUE; 3805b261ecSmrg if (pScreen) 3905b261ecSmrg { 4005b261ecSmrg rrScrPriv (pScreen); 4105b261ecSmrg pScrPriv->changed = TRUE; 4205b261ecSmrg if (configChanged) 4305b261ecSmrg pScrPriv->configChanged = TRUE; 4405b261ecSmrg } 4505b261ecSmrg} 4605b261ecSmrg 4705b261ecSmrg/* 4805b261ecSmrg * Create an output 4905b261ecSmrg */ 5005b261ecSmrg 5105b261ecSmrgRROutputPtr 5205b261ecSmrgRROutputCreate (ScreenPtr pScreen, 5305b261ecSmrg const char *name, 5405b261ecSmrg int nameLength, 5505b261ecSmrg void *devPrivate) 5605b261ecSmrg{ 5705b261ecSmrg RROutputPtr output; 5805b261ecSmrg RROutputPtr *outputs; 5905b261ecSmrg rrScrPrivPtr pScrPriv; 6005b261ecSmrg 6105b261ecSmrg if (!RRInit()) 6205b261ecSmrg return NULL; 6305b261ecSmrg 6405b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 6505b261ecSmrg 6605b261ecSmrg if (pScrPriv->numOutputs) 6705b261ecSmrg outputs = xrealloc (pScrPriv->outputs, 6805b261ecSmrg (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr)); 6905b261ecSmrg else 7005b261ecSmrg outputs = xalloc (sizeof (RROutputPtr)); 7105b261ecSmrg if (!outputs) 7205b261ecSmrg return FALSE; 7305b261ecSmrg 7405b261ecSmrg pScrPriv->outputs = outputs; 7505b261ecSmrg 7605b261ecSmrg output = xalloc (sizeof (RROutputRec) + nameLength + 1); 7705b261ecSmrg if (!output) 7805b261ecSmrg return NULL; 7905b261ecSmrg output->id = FakeClientID (0); 8005b261ecSmrg output->pScreen = pScreen; 8105b261ecSmrg output->name = (char *) (output + 1); 8205b261ecSmrg output->nameLength = nameLength; 8305b261ecSmrg memcpy (output->name, name, nameLength); 8405b261ecSmrg output->name[nameLength] = '\0'; 8505b261ecSmrg output->connection = RR_UnknownConnection; 8605b261ecSmrg output->subpixelOrder = SubPixelUnknown; 8705b261ecSmrg output->mmWidth = 0; 8805b261ecSmrg output->mmHeight = 0; 8905b261ecSmrg output->crtc = NULL; 9005b261ecSmrg output->numCrtcs = 0; 9105b261ecSmrg output->crtcs = NULL; 9205b261ecSmrg output->numClones = 0; 9305b261ecSmrg output->clones = NULL; 9405b261ecSmrg output->numModes = 0; 9505b261ecSmrg output->numPreferred = 0; 9605b261ecSmrg output->modes = NULL; 9705b261ecSmrg output->numUserModes = 0; 9805b261ecSmrg output->userModes = NULL; 9905b261ecSmrg output->properties = NULL; 1004642e01fSmrg output->pendingProperties = FALSE; 10105b261ecSmrg output->changed = FALSE; 10205b261ecSmrg output->devPrivate = devPrivate; 10305b261ecSmrg 10405b261ecSmrg if (!AddResource (output->id, RROutputType, (pointer) output)) 10505b261ecSmrg return NULL; 10605b261ecSmrg 10705b261ecSmrg pScrPriv->outputs[pScrPriv->numOutputs++] = output; 10805b261ecSmrg return output; 10905b261ecSmrg} 11005b261ecSmrg 11105b261ecSmrg/* 11205b261ecSmrg * Notify extension that output parameters have been changed 11305b261ecSmrg */ 11405b261ecSmrgBool 11505b261ecSmrgRROutputSetClones (RROutputPtr output, 11605b261ecSmrg RROutputPtr *clones, 11705b261ecSmrg int numClones) 11805b261ecSmrg{ 11905b261ecSmrg RROutputPtr *newClones; 12005b261ecSmrg int i; 12105b261ecSmrg 12205b261ecSmrg if (numClones == output->numClones) 12305b261ecSmrg { 12405b261ecSmrg for (i = 0; i < numClones; i++) 12505b261ecSmrg if (output->clones[i] != clones[i]) 12605b261ecSmrg break; 12705b261ecSmrg if (i == numClones) 12805b261ecSmrg return TRUE; 12905b261ecSmrg } 13005b261ecSmrg if (numClones) 13105b261ecSmrg { 13205b261ecSmrg newClones = xalloc (numClones * sizeof (RROutputPtr)); 13305b261ecSmrg if (!newClones) 13405b261ecSmrg return FALSE; 13505b261ecSmrg } 13605b261ecSmrg else 13705b261ecSmrg newClones = NULL; 13805b261ecSmrg if (output->clones) 13905b261ecSmrg xfree (output->clones); 14005b261ecSmrg memcpy (newClones, clones, numClones * sizeof (RROutputPtr)); 14105b261ecSmrg output->clones = newClones; 14205b261ecSmrg output->numClones = numClones; 14305b261ecSmrg RROutputChanged (output, TRUE); 14405b261ecSmrg return TRUE; 14505b261ecSmrg} 14605b261ecSmrg 14705b261ecSmrgBool 14805b261ecSmrgRROutputSetModes (RROutputPtr output, 14905b261ecSmrg RRModePtr *modes, 15005b261ecSmrg int numModes, 15105b261ecSmrg int numPreferred) 15205b261ecSmrg{ 15305b261ecSmrg RRModePtr *newModes; 15405b261ecSmrg int i; 15505b261ecSmrg 15605b261ecSmrg if (numModes == output->numModes && numPreferred == output->numPreferred) 15705b261ecSmrg { 15805b261ecSmrg for (i = 0; i < numModes; i++) 15905b261ecSmrg if (output->modes[i] != modes[i]) 16005b261ecSmrg break; 16105b261ecSmrg if (i == numModes) 16205b261ecSmrg { 16305b261ecSmrg for (i = 0; i < numModes; i++) 16405b261ecSmrg RRModeDestroy (modes[i]); 16505b261ecSmrg return TRUE; 16605b261ecSmrg } 16705b261ecSmrg } 16805b261ecSmrg 16905b261ecSmrg if (numModes) 17005b261ecSmrg { 17105b261ecSmrg newModes = xalloc (numModes * sizeof (RRModePtr)); 17205b261ecSmrg if (!newModes) 17305b261ecSmrg return FALSE; 17405b261ecSmrg } 17505b261ecSmrg else 17605b261ecSmrg newModes = NULL; 17705b261ecSmrg if (output->modes) 17805b261ecSmrg { 17905b261ecSmrg for (i = 0; i < output->numModes; i++) 18005b261ecSmrg RRModeDestroy (output->modes[i]); 18105b261ecSmrg xfree (output->modes); 18205b261ecSmrg } 18305b261ecSmrg memcpy (newModes, modes, numModes * sizeof (RRModePtr)); 18405b261ecSmrg output->modes = newModes; 18505b261ecSmrg output->numModes = numModes; 18605b261ecSmrg output->numPreferred = numPreferred; 18705b261ecSmrg RROutputChanged (output, TRUE); 18805b261ecSmrg return TRUE; 18905b261ecSmrg} 19005b261ecSmrg 19105b261ecSmrgint 19205b261ecSmrgRROutputAddUserMode (RROutputPtr output, 19305b261ecSmrg RRModePtr mode) 19405b261ecSmrg{ 19505b261ecSmrg int m; 19605b261ecSmrg ScreenPtr pScreen = output->pScreen; 19705b261ecSmrg rrScrPriv(pScreen); 19805b261ecSmrg RRModePtr *newModes; 19905b261ecSmrg 20005b261ecSmrg /* Check to see if this mode is already listed for this output */ 20105b261ecSmrg for (m = 0; m < output->numModes + output->numUserModes; m++) 20205b261ecSmrg { 20305b261ecSmrg RRModePtr e = (m < output->numModes ? 20405b261ecSmrg output->modes[m] : 20505b261ecSmrg output->userModes[m - output->numModes]); 20605b261ecSmrg if (mode == e) 20705b261ecSmrg return Success; 20805b261ecSmrg } 20905b261ecSmrg 21005b261ecSmrg /* Check with the DDX to see if this mode is OK */ 21105b261ecSmrg if (pScrPriv->rrOutputValidateMode) 21205b261ecSmrg if (!pScrPriv->rrOutputValidateMode (pScreen, output, mode)) 21305b261ecSmrg return BadMatch; 21405b261ecSmrg 21505b261ecSmrg if (output->userModes) 21605b261ecSmrg newModes = xrealloc (output->userModes, 21705b261ecSmrg (output->numUserModes + 1) * sizeof (RRModePtr)); 21805b261ecSmrg else 21905b261ecSmrg newModes = xalloc (sizeof (RRModePtr)); 22005b261ecSmrg if (!newModes) 22105b261ecSmrg return BadAlloc; 22205b261ecSmrg 22305b261ecSmrg output->userModes = newModes; 22405b261ecSmrg output->userModes[output->numUserModes++] = mode; 22505b261ecSmrg ++mode->refcnt; 22605b261ecSmrg RROutputChanged (output, TRUE); 22705b261ecSmrg RRTellChanged (pScreen); 22805b261ecSmrg return Success; 22905b261ecSmrg} 23005b261ecSmrg 23105b261ecSmrgint 23205b261ecSmrgRROutputDeleteUserMode (RROutputPtr output, 23305b261ecSmrg RRModePtr mode) 23405b261ecSmrg{ 23505b261ecSmrg int m; 23605b261ecSmrg 23705b261ecSmrg /* Find this mode in the user mode list */ 23805b261ecSmrg for (m = 0; m < output->numUserModes; m++) 23905b261ecSmrg { 24005b261ecSmrg RRModePtr e = output->userModes[m]; 24105b261ecSmrg 24205b261ecSmrg if (mode == e) 24305b261ecSmrg break; 24405b261ecSmrg } 24505b261ecSmrg /* Not there, access error */ 24605b261ecSmrg if (m == output->numUserModes) 24705b261ecSmrg return BadAccess; 24805b261ecSmrg 24905b261ecSmrg /* make sure the mode isn't active for this output */ 25005b261ecSmrg if (output->crtc && output->crtc->mode == mode) 25105b261ecSmrg return BadMatch; 25205b261ecSmrg 25305b261ecSmrg memmove (output->userModes + m, output->userModes + m + 1, 25405b261ecSmrg (output->numUserModes - m - 1) * sizeof (RRModePtr)); 25505b261ecSmrg output->numUserModes--; 25605b261ecSmrg RRModeDestroy (mode); 25705b261ecSmrg return Success; 25805b261ecSmrg} 25905b261ecSmrg 26005b261ecSmrgBool 26105b261ecSmrgRROutputSetCrtcs (RROutputPtr output, 26205b261ecSmrg RRCrtcPtr *crtcs, 26305b261ecSmrg int numCrtcs) 26405b261ecSmrg{ 26505b261ecSmrg RRCrtcPtr *newCrtcs; 26605b261ecSmrg int i; 26705b261ecSmrg 26805b261ecSmrg if (numCrtcs == output->numCrtcs) 26905b261ecSmrg { 27005b261ecSmrg for (i = 0; i < numCrtcs; i++) 27105b261ecSmrg if (output->crtcs[i] != crtcs[i]) 27205b261ecSmrg break; 27305b261ecSmrg if (i == numCrtcs) 27405b261ecSmrg return TRUE; 27505b261ecSmrg } 27605b261ecSmrg if (numCrtcs) 27705b261ecSmrg { 27805b261ecSmrg newCrtcs = xalloc (numCrtcs * sizeof (RRCrtcPtr)); 27905b261ecSmrg if (!newCrtcs) 28005b261ecSmrg return FALSE; 28105b261ecSmrg } 28205b261ecSmrg else 28305b261ecSmrg newCrtcs = NULL; 28405b261ecSmrg if (output->crtcs) 28505b261ecSmrg xfree (output->crtcs); 28605b261ecSmrg memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr)); 28705b261ecSmrg output->crtcs = newCrtcs; 28805b261ecSmrg output->numCrtcs = numCrtcs; 28905b261ecSmrg RROutputChanged (output, TRUE); 29005b261ecSmrg return TRUE; 29105b261ecSmrg} 29205b261ecSmrg 29305b261ecSmrgBool 29405b261ecSmrgRROutputSetConnection (RROutputPtr output, 29505b261ecSmrg CARD8 connection) 29605b261ecSmrg{ 29705b261ecSmrg if (output->connection == connection) 29805b261ecSmrg return TRUE; 29905b261ecSmrg output->connection = connection; 30005b261ecSmrg RROutputChanged (output, TRUE); 30105b261ecSmrg return TRUE; 30205b261ecSmrg} 30305b261ecSmrg 30405b261ecSmrgBool 30505b261ecSmrgRROutputSetSubpixelOrder (RROutputPtr output, 30605b261ecSmrg int subpixelOrder) 30705b261ecSmrg{ 30805b261ecSmrg if (output->subpixelOrder == subpixelOrder) 30905b261ecSmrg return TRUE; 31005b261ecSmrg 31105b261ecSmrg output->subpixelOrder = subpixelOrder; 31205b261ecSmrg RROutputChanged (output, FALSE); 31305b261ecSmrg return TRUE; 31405b261ecSmrg} 31505b261ecSmrg 31605b261ecSmrgBool 31705b261ecSmrgRROutputSetPhysicalSize (RROutputPtr output, 31805b261ecSmrg int mmWidth, 31905b261ecSmrg int mmHeight) 32005b261ecSmrg{ 32105b261ecSmrg if (output->mmWidth == mmWidth && output->mmHeight == mmHeight) 32205b261ecSmrg return TRUE; 32305b261ecSmrg output->mmWidth = mmWidth; 32405b261ecSmrg output->mmHeight = mmHeight; 32505b261ecSmrg RROutputChanged (output, FALSE); 32605b261ecSmrg return TRUE; 32705b261ecSmrg} 32805b261ecSmrg 32905b261ecSmrg 33005b261ecSmrgvoid 33105b261ecSmrgRRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output) 33205b261ecSmrg{ 33305b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 33405b261ecSmrg rrScrPriv (pScreen); 33505b261ecSmrg xRROutputChangeNotifyEvent oe; 33605b261ecSmrg RRCrtcPtr crtc = output->crtc; 33705b261ecSmrg RRModePtr mode = crtc ? crtc->mode : 0; 33805b261ecSmrg 33905b261ecSmrg oe.type = RRNotify + RREventBase; 34005b261ecSmrg oe.subCode = RRNotify_OutputChange; 34105b261ecSmrg oe.sequenceNumber = client->sequence; 34205b261ecSmrg oe.timestamp = pScrPriv->lastSetTime.milliseconds; 34305b261ecSmrg oe.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 34405b261ecSmrg oe.window = pWin->drawable.id; 34505b261ecSmrg oe.output = output->id; 34605b261ecSmrg if (crtc) 34705b261ecSmrg { 34805b261ecSmrg oe.crtc = crtc->id; 34905b261ecSmrg oe.mode = mode ? mode->mode.id : None; 35005b261ecSmrg oe.rotation = crtc->rotation; 35105b261ecSmrg } 35205b261ecSmrg else 35305b261ecSmrg { 35405b261ecSmrg oe.crtc = None; 35505b261ecSmrg oe.mode = None; 35605b261ecSmrg oe.rotation = RR_Rotate_0; 35705b261ecSmrg } 35805b261ecSmrg oe.connection = output->connection; 35905b261ecSmrg oe.subpixelOrder = output->subpixelOrder; 36005b261ecSmrg WriteEventsToClient (client, 1, (xEvent *) &oe); 36105b261ecSmrg} 36205b261ecSmrg 36305b261ecSmrg/* 36405b261ecSmrg * Destroy a Output at shutdown 36505b261ecSmrg */ 36605b261ecSmrgvoid 36705b261ecSmrgRROutputDestroy (RROutputPtr output) 36805b261ecSmrg{ 36905b261ecSmrg FreeResource (output->id, 0); 37005b261ecSmrg} 37105b261ecSmrg 37205b261ecSmrgstatic int 37305b261ecSmrgRROutputDestroyResource (pointer value, XID pid) 37405b261ecSmrg{ 37505b261ecSmrg RROutputPtr output = (RROutputPtr) value; 37605b261ecSmrg ScreenPtr pScreen = output->pScreen; 37705b261ecSmrg int m; 37805b261ecSmrg 37905b261ecSmrg if (pScreen) 38005b261ecSmrg { 38105b261ecSmrg rrScrPriv(pScreen); 38205b261ecSmrg int i; 3834642e01fSmrg 3844642e01fSmrg if (pScrPriv->primaryOutput == output) 3854642e01fSmrg pScrPriv->primaryOutput = NULL; 38605b261ecSmrg 38705b261ecSmrg for (i = 0; i < pScrPriv->numOutputs; i++) 38805b261ecSmrg { 38905b261ecSmrg if (pScrPriv->outputs[i] == output) 39005b261ecSmrg { 39105b261ecSmrg memmove (pScrPriv->outputs + i, pScrPriv->outputs + i + 1, 39205b261ecSmrg (pScrPriv->numOutputs - (i + 1)) * sizeof (RROutputPtr)); 39305b261ecSmrg --pScrPriv->numOutputs; 39405b261ecSmrg break; 39505b261ecSmrg } 39605b261ecSmrg } 39705b261ecSmrg } 39805b261ecSmrg if (output->modes) 39905b261ecSmrg { 40005b261ecSmrg for (m = 0; m < output->numModes; m++) 40105b261ecSmrg RRModeDestroy (output->modes[m]); 40205b261ecSmrg xfree (output->modes); 40305b261ecSmrg } 40405b261ecSmrg 40505b261ecSmrg for (m = 0; m < output->numUserModes; m++) 40605b261ecSmrg RRModeDestroy (output->userModes[m]); 40705b261ecSmrg if (output->userModes) 40805b261ecSmrg xfree (output->userModes); 40905b261ecSmrg 41005b261ecSmrg if (output->crtcs) 41105b261ecSmrg xfree (output->crtcs); 41205b261ecSmrg if (output->clones) 41305b261ecSmrg xfree (output->clones); 41405b261ecSmrg RRDeleteAllOutputProperties (output); 41505b261ecSmrg xfree (output); 41605b261ecSmrg return 1; 41705b261ecSmrg} 41805b261ecSmrg 41905b261ecSmrg/* 42005b261ecSmrg * Initialize output type 42105b261ecSmrg */ 42205b261ecSmrgBool 42305b261ecSmrgRROutputInit (void) 42405b261ecSmrg{ 42505b261ecSmrg RROutputType = CreateNewResourceType (RROutputDestroyResource); 42605b261ecSmrg if (!RROutputType) 42705b261ecSmrg return FALSE; 4284642e01fSmrg RegisterResourceName (RROutputType, "OUTPUT"); 42905b261ecSmrg return TRUE; 43005b261ecSmrg} 43105b261ecSmrg 43205b261ecSmrg#define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32) 4334642e01fSmrg 43405b261ecSmrgint 43505b261ecSmrgProcRRGetOutputInfo (ClientPtr client) 43605b261ecSmrg{ 43705b261ecSmrg REQUEST(xRRGetOutputInfoReq); 43805b261ecSmrg xRRGetOutputInfoReply rep; 43905b261ecSmrg RROutputPtr output; 44005b261ecSmrg CARD8 *extra; 44105b261ecSmrg unsigned long extraLen; 44205b261ecSmrg ScreenPtr pScreen; 44305b261ecSmrg rrScrPrivPtr pScrPriv; 44405b261ecSmrg RRCrtc *crtcs; 44505b261ecSmrg RRMode *modes; 44605b261ecSmrg RROutput *clones; 44705b261ecSmrg char *name; 44805b261ecSmrg int i, n; 44905b261ecSmrg 45005b261ecSmrg REQUEST_SIZE_MATCH(xRRGetOutputInfoReq); 45105b261ecSmrg output = LookupOutput(client, stuff->output, DixReadAccess); 45205b261ecSmrg 45305b261ecSmrg if (!output) 45405b261ecSmrg { 45505b261ecSmrg client->errorValue = stuff->output; 45605b261ecSmrg return RRErrorBase + BadRROutput; 45705b261ecSmrg } 45805b261ecSmrg 45905b261ecSmrg pScreen = output->pScreen; 46005b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 46105b261ecSmrg 46205b261ecSmrg rep.type = X_Reply; 46305b261ecSmrg rep.sequenceNumber = client->sequence; 46405b261ecSmrg rep.length = OutputInfoExtra >> 2; 46505b261ecSmrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 46605b261ecSmrg rep.crtc = output->crtc ? output->crtc->id : None; 46705b261ecSmrg rep.mmWidth = output->mmWidth; 46805b261ecSmrg rep.mmHeight = output->mmHeight; 46905b261ecSmrg rep.connection = output->connection; 47005b261ecSmrg rep.subpixelOrder = output->subpixelOrder; 47105b261ecSmrg rep.nCrtcs = output->numCrtcs; 47205b261ecSmrg rep.nModes = output->numModes + output->numUserModes; 47305b261ecSmrg rep.nPreferred = output->numPreferred; 47405b261ecSmrg rep.nClones = output->numClones; 47505b261ecSmrg rep.nameLength = output->nameLength; 47605b261ecSmrg 47705b261ecSmrg extraLen = ((output->numCrtcs + 47805b261ecSmrg output->numModes + output->numUserModes + 47905b261ecSmrg output->numClones + 48005b261ecSmrg ((rep.nameLength + 3) >> 2)) << 2); 48105b261ecSmrg 48205b261ecSmrg if (extraLen) 48305b261ecSmrg { 48405b261ecSmrg rep.length += extraLen >> 2; 48505b261ecSmrg extra = xalloc (extraLen); 48605b261ecSmrg if (!extra) 48705b261ecSmrg return BadAlloc; 48805b261ecSmrg } 48905b261ecSmrg else 49005b261ecSmrg extra = NULL; 49105b261ecSmrg 49205b261ecSmrg crtcs = (RRCrtc *) extra; 49305b261ecSmrg modes = (RRMode *) (crtcs + output->numCrtcs); 49405b261ecSmrg clones = (RROutput *) (modes + output->numModes + output->numUserModes); 49505b261ecSmrg name = (char *) (clones + output->numClones); 49605b261ecSmrg 49705b261ecSmrg for (i = 0; i < output->numCrtcs; i++) 49805b261ecSmrg { 49905b261ecSmrg crtcs[i] = output->crtcs[i]->id; 50005b261ecSmrg if (client->swapped) 50105b261ecSmrg swapl (&crtcs[i], n); 50205b261ecSmrg } 50305b261ecSmrg for (i = 0; i < output->numModes + output->numUserModes; i++) 50405b261ecSmrg { 50505b261ecSmrg if (i < output->numModes) 50605b261ecSmrg modes[i] = output->modes[i]->mode.id; 50705b261ecSmrg else 50805b261ecSmrg modes[i] = output->userModes[i - output->numModes]->mode.id; 50905b261ecSmrg if (client->swapped) 51005b261ecSmrg swapl (&modes[i], n); 51105b261ecSmrg } 51205b261ecSmrg for (i = 0; i < output->numClones; i++) 51305b261ecSmrg { 51405b261ecSmrg clones[i] = output->clones[i]->id; 51505b261ecSmrg if (client->swapped) 51605b261ecSmrg swapl (&clones[i], n); 51705b261ecSmrg } 51805b261ecSmrg memcpy (name, output->name, output->nameLength); 51905b261ecSmrg if (client->swapped) { 52005b261ecSmrg swaps(&rep.sequenceNumber, n); 52105b261ecSmrg swapl(&rep.length, n); 52205b261ecSmrg swapl(&rep.timestamp, n); 52305b261ecSmrg swapl(&rep.crtc, n); 52405b261ecSmrg swapl(&rep.mmWidth, n); 52505b261ecSmrg swapl(&rep.mmHeight, n); 52605b261ecSmrg swaps(&rep.nCrtcs, n); 52705b261ecSmrg swaps(&rep.nModes, n); 52805b261ecSmrg swaps(&rep.nClones, n); 52905b261ecSmrg swaps(&rep.nameLength, n); 53005b261ecSmrg } 53105b261ecSmrg WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *)&rep); 53205b261ecSmrg if (extraLen) 53305b261ecSmrg { 53405b261ecSmrg WriteToClient (client, extraLen, (char *) extra); 53505b261ecSmrg xfree (extra); 53605b261ecSmrg } 53705b261ecSmrg 53805b261ecSmrg return client->noClientException; 53905b261ecSmrg} 5404642e01fSmrg 5414642e01fSmrgvoid 5424642e01fSmrgRRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv, 5434642e01fSmrg RROutputPtr output) 5444642e01fSmrg{ 5454642e01fSmrg if (pScrPriv->primaryOutput == output) 5464642e01fSmrg return; 5474642e01fSmrg 5484642e01fSmrg /* clear the old primary */ 5494642e01fSmrg if (pScrPriv->primaryOutput) { 5504642e01fSmrg RROutputChanged(pScrPriv->primaryOutput, 0); 5514642e01fSmrg pScrPriv->primaryOutput = NULL; 5524642e01fSmrg } 5534642e01fSmrg 5544642e01fSmrg /* set the new primary */ 5554642e01fSmrg if (output) { 5564642e01fSmrg pScrPriv->primaryOutput = output; 5574642e01fSmrg RROutputChanged(output, 0); 5584642e01fSmrg } 5594642e01fSmrg 5604642e01fSmrg pScrPriv->layoutChanged = TRUE; 5614642e01fSmrg 5624642e01fSmrg RRTellChanged(pScreen); 5634642e01fSmrg} 5644642e01fSmrg 5654642e01fSmrgint 5664642e01fSmrgProcRRSetOutputPrimary(ClientPtr client) 5674642e01fSmrg{ 5684642e01fSmrg REQUEST(xRRSetOutputPrimaryReq); 5694642e01fSmrg RROutputPtr output = NULL; 5704642e01fSmrg WindowPtr pWin; 5714642e01fSmrg rrScrPrivPtr pScrPriv; 5724642e01fSmrg 5734642e01fSmrg REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq); 5744642e01fSmrg 5754642e01fSmrg pWin = SecurityLookupIDByType(client, stuff->window, RT_WINDOW, 5764642e01fSmrg DixReadAccess); 5774642e01fSmrg 5784642e01fSmrg if (!pWin) { 5794642e01fSmrg client->errorValue = stuff->window; 5804642e01fSmrg return BadWindow; 5814642e01fSmrg } 5824642e01fSmrg 5834642e01fSmrg if (stuff->output) { 5844642e01fSmrg output = LookupOutput(client, stuff->output, DixReadAccess); 5854642e01fSmrg 5864642e01fSmrg if (!output) { 5874642e01fSmrg client->errorValue = stuff->output; 5884642e01fSmrg return RRErrorBase + BadRROutput; 5894642e01fSmrg } 5904642e01fSmrg 5914642e01fSmrg if (output->pScreen != pWin->drawable.pScreen) { 5924642e01fSmrg client->errorValue = stuff->window; 5934642e01fSmrg return BadMatch; 5944642e01fSmrg } 5954642e01fSmrg } 5964642e01fSmrg 5974642e01fSmrg pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); 5984642e01fSmrg RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output); 5994642e01fSmrg 6004642e01fSmrg return client->noClientException; 6014642e01fSmrg} 6024642e01fSmrg 6034642e01fSmrgint 6044642e01fSmrgProcRRGetOutputPrimary(ClientPtr client) 6054642e01fSmrg{ 6064642e01fSmrg REQUEST(xRRGetOutputPrimaryReq); 6074642e01fSmrg WindowPtr pWin; 6084642e01fSmrg rrScrPrivPtr pScrPriv; 6094642e01fSmrg xRRGetOutputPrimaryReply rep; 6104642e01fSmrg RROutputPtr primary = NULL; 6114642e01fSmrg 6124642e01fSmrg REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq); 6134642e01fSmrg 6144642e01fSmrg pWin = SecurityLookupIDByType(client, stuff->window, RT_WINDOW, 6154642e01fSmrg DixReadAccess); 6164642e01fSmrg 6174642e01fSmrg if (!pWin) { 6184642e01fSmrg client->errorValue = stuff->window; 6194642e01fSmrg return BadWindow; 6204642e01fSmrg } 6214642e01fSmrg 6224642e01fSmrg pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); 6234642e01fSmrg if (pScrPriv) 6244642e01fSmrg primary = pScrPriv->primaryOutput; 6254642e01fSmrg 6264642e01fSmrg memset(&rep, 0, sizeof(rep)); 6274642e01fSmrg rep.type = X_Reply; 6284642e01fSmrg rep.sequenceNumber = client->sequence; 6294642e01fSmrg rep.output = primary ? primary->id : None; 6304642e01fSmrg 6314642e01fSmrg if (client->swapped) { 6324642e01fSmrg int n; 6334642e01fSmrg swaps(&rep.sequenceNumber, n); 6344642e01fSmrg swapl(&rep.output, n); 6354642e01fSmrg } 6364642e01fSmrg 6374642e01fSmrg WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), &rep); 6384642e01fSmrg 6394642e01fSmrg return client->noClientException; 6404642e01fSmrg} 641