rroutput.c revision 35c4bbdf
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 2635c4bbdfSmrgRESTYPE RROutputType; 2705b261ecSmrg 2805b261ecSmrg/* 2905b261ecSmrg * Notify the output of some change 3005b261ecSmrg */ 3105b261ecSmrgvoid 3235c4bbdfSmrgRROutputChanged(RROutputPtr output, Bool configChanged) 3305b261ecSmrg{ 3435c4bbdfSmrg /* set changed bits on the master screen only */ 3535c4bbdfSmrg ScreenPtr pScreen = output->pScreen; 3635c4bbdfSmrg rrScrPrivPtr mastersp; 3735c4bbdfSmrg 3805b261ecSmrg output->changed = TRUE; 3935c4bbdfSmrg if (!pScreen) 4035c4bbdfSmrg return; 4135c4bbdfSmrg 4235c4bbdfSmrg if (pScreen->isGPU) { 4335c4bbdfSmrg ScreenPtr master = pScreen->current_master; 4435c4bbdfSmrg if (!master) 4535c4bbdfSmrg return; 4635c4bbdfSmrg mastersp = rrGetScrPriv(master); 4705b261ecSmrg } 4835c4bbdfSmrg else { 4935c4bbdfSmrg mastersp = rrGetScrPriv(pScreen); 5035c4bbdfSmrg } 5135c4bbdfSmrg 5235c4bbdfSmrg RRSetChanged(pScreen); 5335c4bbdfSmrg if (configChanged) 5435c4bbdfSmrg mastersp->configChanged = TRUE; 5505b261ecSmrg} 5605b261ecSmrg 5705b261ecSmrg/* 5805b261ecSmrg * Create an output 5905b261ecSmrg */ 6005b261ecSmrg 6105b261ecSmrgRROutputPtr 6235c4bbdfSmrgRROutputCreate(ScreenPtr pScreen, 6335c4bbdfSmrg const char *name, int nameLength, void *devPrivate) 6405b261ecSmrg{ 6535c4bbdfSmrg RROutputPtr output; 6635c4bbdfSmrg RROutputPtr *outputs; 6735c4bbdfSmrg rrScrPrivPtr pScrPriv; 6805b261ecSmrg 6905b261ecSmrg if (!RRInit()) 7035c4bbdfSmrg return NULL; 7135c4bbdfSmrg 7205b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 7305b261ecSmrg 7405b261ecSmrg if (pScrPriv->numOutputs) 7535c4bbdfSmrg outputs = reallocarray(pScrPriv->outputs, 7635c4bbdfSmrg pScrPriv->numOutputs + 1, sizeof(RROutputPtr)); 7705b261ecSmrg else 7835c4bbdfSmrg outputs = malloc(sizeof(RROutputPtr)); 7905b261ecSmrg if (!outputs) 8035c4bbdfSmrg return FALSE; 8105b261ecSmrg 8205b261ecSmrg pScrPriv->outputs = outputs; 8335c4bbdfSmrg 8435c4bbdfSmrg output = malloc(sizeof(RROutputRec) + nameLength + 1); 8505b261ecSmrg if (!output) 8635c4bbdfSmrg return NULL; 8735c4bbdfSmrg output->id = FakeClientID(0); 8805b261ecSmrg output->pScreen = pScreen; 8905b261ecSmrg output->name = (char *) (output + 1); 9005b261ecSmrg output->nameLength = nameLength; 9135c4bbdfSmrg memcpy(output->name, name, nameLength); 9205b261ecSmrg output->name[nameLength] = '\0'; 9305b261ecSmrg output->connection = RR_UnknownConnection; 9405b261ecSmrg output->subpixelOrder = SubPixelUnknown; 9505b261ecSmrg output->mmWidth = 0; 9605b261ecSmrg output->mmHeight = 0; 9705b261ecSmrg output->crtc = NULL; 9805b261ecSmrg output->numCrtcs = 0; 9905b261ecSmrg output->crtcs = NULL; 10005b261ecSmrg output->numClones = 0; 10105b261ecSmrg output->clones = NULL; 10205b261ecSmrg output->numModes = 0; 10305b261ecSmrg output->numPreferred = 0; 10405b261ecSmrg output->modes = NULL; 10505b261ecSmrg output->numUserModes = 0; 10605b261ecSmrg output->userModes = NULL; 10705b261ecSmrg output->properties = NULL; 1084642e01fSmrg output->pendingProperties = FALSE; 10905b261ecSmrg output->changed = FALSE; 11005b261ecSmrg output->devPrivate = devPrivate; 11135c4bbdfSmrg 11235c4bbdfSmrg if (!AddResource(output->id, RROutputType, (void *) output)) 11335c4bbdfSmrg return NULL; 11405b261ecSmrg 11505b261ecSmrg pScrPriv->outputs[pScrPriv->numOutputs++] = output; 11635c4bbdfSmrg 11735c4bbdfSmrg RRResourcesChanged(pScreen); 11835c4bbdfSmrg 11905b261ecSmrg return output; 12005b261ecSmrg} 12105b261ecSmrg 12205b261ecSmrg/* 12305b261ecSmrg * Notify extension that output parameters have been changed 12405b261ecSmrg */ 12505b261ecSmrgBool 12635c4bbdfSmrgRROutputSetClones(RROutputPtr output, RROutputPtr * clones, int numClones) 12705b261ecSmrg{ 12835c4bbdfSmrg RROutputPtr *newClones; 12935c4bbdfSmrg int i; 13035c4bbdfSmrg 13135c4bbdfSmrg if (numClones == output->numClones) { 13235c4bbdfSmrg for (i = 0; i < numClones; i++) 13335c4bbdfSmrg if (output->clones[i] != clones[i]) 13435c4bbdfSmrg break; 13535c4bbdfSmrg if (i == numClones) 13635c4bbdfSmrg return TRUE; 13705b261ecSmrg } 13835c4bbdfSmrg if (numClones) { 13935c4bbdfSmrg newClones = xallocarray(numClones, sizeof(RROutputPtr)); 14035c4bbdfSmrg if (!newClones) 14135c4bbdfSmrg return FALSE; 14205b261ecSmrg } 14305b261ecSmrg else 14435c4bbdfSmrg newClones = NULL; 1456747b715Smrg free(output->clones); 14635c4bbdfSmrg memcpy(newClones, clones, numClones * sizeof(RROutputPtr)); 14705b261ecSmrg output->clones = newClones; 14805b261ecSmrg output->numClones = numClones; 14935c4bbdfSmrg RROutputChanged(output, TRUE); 15005b261ecSmrg return TRUE; 15105b261ecSmrg} 15205b261ecSmrg 15305b261ecSmrgBool 15435c4bbdfSmrgRROutputSetModes(RROutputPtr output, 15535c4bbdfSmrg RRModePtr * modes, int numModes, int numPreferred) 15605b261ecSmrg{ 15735c4bbdfSmrg RRModePtr *newModes; 15835c4bbdfSmrg int i; 15935c4bbdfSmrg 16035c4bbdfSmrg if (numModes == output->numModes && numPreferred == output->numPreferred) { 16135c4bbdfSmrg for (i = 0; i < numModes; i++) 16235c4bbdfSmrg if (output->modes[i] != modes[i]) 16335c4bbdfSmrg break; 16435c4bbdfSmrg if (i == numModes) { 16535c4bbdfSmrg for (i = 0; i < numModes; i++) 16635c4bbdfSmrg RRModeDestroy(modes[i]); 16735c4bbdfSmrg return TRUE; 16835c4bbdfSmrg } 16905b261ecSmrg } 17005b261ecSmrg 17135c4bbdfSmrg if (numModes) { 17235c4bbdfSmrg newModes = xallocarray(numModes, sizeof(RRModePtr)); 17335c4bbdfSmrg if (!newModes) 17435c4bbdfSmrg return FALSE; 17505b261ecSmrg } 17605b261ecSmrg else 17735c4bbdfSmrg newModes = NULL; 17835c4bbdfSmrg if (output->modes) { 17935c4bbdfSmrg for (i = 0; i < output->numModes; i++) 18035c4bbdfSmrg RRModeDestroy(output->modes[i]); 18135c4bbdfSmrg free(output->modes); 18205b261ecSmrg } 18335c4bbdfSmrg memcpy(newModes, modes, numModes * sizeof(RRModePtr)); 18405b261ecSmrg output->modes = newModes; 18505b261ecSmrg output->numModes = numModes; 18605b261ecSmrg output->numPreferred = numPreferred; 18735c4bbdfSmrg RROutputChanged(output, TRUE); 18805b261ecSmrg return TRUE; 18905b261ecSmrg} 19005b261ecSmrg 19105b261ecSmrgint 19235c4bbdfSmrgRROutputAddUserMode(RROutputPtr output, RRModePtr mode) 19305b261ecSmrg{ 19435c4bbdfSmrg int m; 19535c4bbdfSmrg ScreenPtr pScreen = output->pScreen; 19635c4bbdfSmrg 19705b261ecSmrg rrScrPriv(pScreen); 19835c4bbdfSmrg RRModePtr *newModes; 19905b261ecSmrg 20005b261ecSmrg /* Check to see if this mode is already listed for this output */ 20135c4bbdfSmrg for (m = 0; m < output->numModes + output->numUserModes; m++) { 20235c4bbdfSmrg RRModePtr e = (m < output->numModes ? 20335c4bbdfSmrg output->modes[m] : 20435c4bbdfSmrg output->userModes[m - output->numModes]); 20535c4bbdfSmrg if (mode == e) 20635c4bbdfSmrg return Success; 20705b261ecSmrg } 20805b261ecSmrg 20905b261ecSmrg /* Check with the DDX to see if this mode is OK */ 21005b261ecSmrg if (pScrPriv->rrOutputValidateMode) 21135c4bbdfSmrg if (!pScrPriv->rrOutputValidateMode(pScreen, output, mode)) 21235c4bbdfSmrg return BadMatch; 21305b261ecSmrg 21405b261ecSmrg if (output->userModes) 21535c4bbdfSmrg newModes = reallocarray(output->userModes, 21635c4bbdfSmrg output->numUserModes + 1, sizeof(RRModePtr)); 21705b261ecSmrg else 21835c4bbdfSmrg newModes = malloc(sizeof(RRModePtr)); 21905b261ecSmrg if (!newModes) 22035c4bbdfSmrg return BadAlloc; 22105b261ecSmrg 22205b261ecSmrg output->userModes = newModes; 22305b261ecSmrg output->userModes[output->numUserModes++] = mode; 22405b261ecSmrg ++mode->refcnt; 22535c4bbdfSmrg RROutputChanged(output, TRUE); 22635c4bbdfSmrg RRTellChanged(pScreen); 22705b261ecSmrg return Success; 22805b261ecSmrg} 22905b261ecSmrg 23005b261ecSmrgint 23135c4bbdfSmrgRROutputDeleteUserMode(RROutputPtr output, RRModePtr mode) 23205b261ecSmrg{ 23335c4bbdfSmrg int m; 23435c4bbdfSmrg 23505b261ecSmrg /* Find this mode in the user mode list */ 23635c4bbdfSmrg for (m = 0; m < output->numUserModes; m++) { 23735c4bbdfSmrg RRModePtr e = output->userModes[m]; 23805b261ecSmrg 23935c4bbdfSmrg if (mode == e) 24035c4bbdfSmrg break; 24105b261ecSmrg } 24205b261ecSmrg /* Not there, access error */ 24305b261ecSmrg if (m == output->numUserModes) 24435c4bbdfSmrg return BadAccess; 24505b261ecSmrg 24605b261ecSmrg /* make sure the mode isn't active for this output */ 24705b261ecSmrg if (output->crtc && output->crtc->mode == mode) 24835c4bbdfSmrg return BadMatch; 24905b261ecSmrg 25035c4bbdfSmrg memmove(output->userModes + m, output->userModes + m + 1, 25135c4bbdfSmrg (output->numUserModes - m - 1) * sizeof(RRModePtr)); 25205b261ecSmrg output->numUserModes--; 25335c4bbdfSmrg RRModeDestroy(mode); 25405b261ecSmrg return Success; 25505b261ecSmrg} 25605b261ecSmrg 25705b261ecSmrgBool 25835c4bbdfSmrgRROutputSetCrtcs(RROutputPtr output, RRCrtcPtr * crtcs, int numCrtcs) 25905b261ecSmrg{ 26035c4bbdfSmrg RRCrtcPtr *newCrtcs; 26135c4bbdfSmrg int i; 26235c4bbdfSmrg 26335c4bbdfSmrg if (numCrtcs == output->numCrtcs) { 26435c4bbdfSmrg for (i = 0; i < numCrtcs; i++) 26535c4bbdfSmrg if (output->crtcs[i] != crtcs[i]) 26635c4bbdfSmrg break; 26735c4bbdfSmrg if (i == numCrtcs) 26835c4bbdfSmrg return TRUE; 26905b261ecSmrg } 27035c4bbdfSmrg if (numCrtcs) { 27135c4bbdfSmrg newCrtcs = xallocarray(numCrtcs, sizeof(RRCrtcPtr)); 27235c4bbdfSmrg if (!newCrtcs) 27335c4bbdfSmrg return FALSE; 27405b261ecSmrg } 27505b261ecSmrg else 27635c4bbdfSmrg newCrtcs = NULL; 2776747b715Smrg free(output->crtcs); 27835c4bbdfSmrg memcpy(newCrtcs, crtcs, numCrtcs * sizeof(RRCrtcPtr)); 27905b261ecSmrg output->crtcs = newCrtcs; 28005b261ecSmrg output->numCrtcs = numCrtcs; 28135c4bbdfSmrg RROutputChanged(output, TRUE); 28205b261ecSmrg return TRUE; 28305b261ecSmrg} 28405b261ecSmrg 28505b261ecSmrgBool 28635c4bbdfSmrgRROutputSetConnection(RROutputPtr output, CARD8 connection) 28705b261ecSmrg{ 28805b261ecSmrg if (output->connection == connection) 28935c4bbdfSmrg return TRUE; 29005b261ecSmrg output->connection = connection; 29135c4bbdfSmrg RROutputChanged(output, TRUE); 29205b261ecSmrg return TRUE; 29305b261ecSmrg} 29405b261ecSmrg 29505b261ecSmrgBool 29635c4bbdfSmrgRROutputSetSubpixelOrder(RROutputPtr output, int subpixelOrder) 29705b261ecSmrg{ 29805b261ecSmrg if (output->subpixelOrder == subpixelOrder) 29935c4bbdfSmrg return TRUE; 30005b261ecSmrg 30105b261ecSmrg output->subpixelOrder = subpixelOrder; 30235c4bbdfSmrg RROutputChanged(output, FALSE); 30305b261ecSmrg return TRUE; 30405b261ecSmrg} 30505b261ecSmrg 30605b261ecSmrgBool 30735c4bbdfSmrgRROutputSetPhysicalSize(RROutputPtr output, int mmWidth, int mmHeight) 30805b261ecSmrg{ 30905b261ecSmrg if (output->mmWidth == mmWidth && output->mmHeight == mmHeight) 31035c4bbdfSmrg return TRUE; 31105b261ecSmrg output->mmWidth = mmWidth; 31205b261ecSmrg output->mmHeight = mmHeight; 31335c4bbdfSmrg RROutputChanged(output, FALSE); 31405b261ecSmrg return TRUE; 31505b261ecSmrg} 31605b261ecSmrg 31705b261ecSmrgvoid 31805b261ecSmrgRRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output) 31905b261ecSmrg{ 32005b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 32135c4bbdfSmrg 32235c4bbdfSmrg rrScrPriv(pScreen); 32335c4bbdfSmrg RRCrtcPtr crtc = output->crtc; 32435c4bbdfSmrg RRModePtr mode = crtc ? crtc->mode : NULL; 32535c4bbdfSmrg 32635c4bbdfSmrg xRROutputChangeNotifyEvent oe = { 32735c4bbdfSmrg .type = RRNotify + RREventBase, 32835c4bbdfSmrg .subCode = RRNotify_OutputChange, 32935c4bbdfSmrg .timestamp = pScrPriv->lastSetTime.milliseconds, 33035c4bbdfSmrg .configTimestamp = pScrPriv->lastConfigTime.milliseconds, 33135c4bbdfSmrg .window = pWin->drawable.id, 33235c4bbdfSmrg .output = output->id, 33335c4bbdfSmrg .crtc = crtc ? crtc->id : None, 33435c4bbdfSmrg .mode = mode ? mode->mode.id : None, 33535c4bbdfSmrg .rotation = crtc ? crtc->rotation : RR_Rotate_0, 33635c4bbdfSmrg .connection = output->connection, 33735c4bbdfSmrg .subpixelOrder = output->subpixelOrder 33835c4bbdfSmrg }; 33935c4bbdfSmrg WriteEventsToClient(client, 1, (xEvent *) &oe); 34005b261ecSmrg} 34105b261ecSmrg 34205b261ecSmrg/* 34305b261ecSmrg * Destroy a Output at shutdown 34405b261ecSmrg */ 34505b261ecSmrgvoid 34635c4bbdfSmrgRROutputDestroy(RROutputPtr output) 34705b261ecSmrg{ 34835c4bbdfSmrg FreeResource(output->id, 0); 34905b261ecSmrg} 35005b261ecSmrg 35105b261ecSmrgstatic int 35235c4bbdfSmrgRROutputDestroyResource(void *value, XID pid) 35305b261ecSmrg{ 35435c4bbdfSmrg RROutputPtr output = (RROutputPtr) value; 35535c4bbdfSmrg ScreenPtr pScreen = output->pScreen; 35635c4bbdfSmrg int m; 35735c4bbdfSmrg 35835c4bbdfSmrg if (pScreen) { 35935c4bbdfSmrg rrScrPriv(pScreen); 36035c4bbdfSmrg int i; 36135c4bbdfSmrg 36235c4bbdfSmrg if (pScrPriv->primaryOutput == output) 36335c4bbdfSmrg pScrPriv->primaryOutput = NULL; 36435c4bbdfSmrg 36535c4bbdfSmrg for (i = 0; i < pScrPriv->numOutputs; i++) { 36635c4bbdfSmrg if (pScrPriv->outputs[i] == output) { 36735c4bbdfSmrg memmove(pScrPriv->outputs + i, pScrPriv->outputs + i + 1, 36835c4bbdfSmrg (pScrPriv->numOutputs - (i + 1)) * sizeof(RROutputPtr)); 36935c4bbdfSmrg --pScrPriv->numOutputs; 37035c4bbdfSmrg break; 37135c4bbdfSmrg } 37235c4bbdfSmrg } 37335c4bbdfSmrg 37435c4bbdfSmrg RRResourcesChanged(pScreen); 37505b261ecSmrg } 37635c4bbdfSmrg if (output->modes) { 37735c4bbdfSmrg for (m = 0; m < output->numModes; m++) 37835c4bbdfSmrg RRModeDestroy(output->modes[m]); 37935c4bbdfSmrg free(output->modes); 38005b261ecSmrg } 38135c4bbdfSmrg 38205b261ecSmrg for (m = 0; m < output->numUserModes; m++) 38335c4bbdfSmrg RRModeDestroy(output->userModes[m]); 3846747b715Smrg free(output->userModes); 38505b261ecSmrg 3866747b715Smrg free(output->crtcs); 3876747b715Smrg free(output->clones); 38835c4bbdfSmrg RRDeleteAllOutputProperties(output); 3896747b715Smrg free(output); 39005b261ecSmrg return 1; 39105b261ecSmrg} 39205b261ecSmrg 39305b261ecSmrg/* 39405b261ecSmrg * Initialize output type 39505b261ecSmrg */ 39605b261ecSmrgBool 39735c4bbdfSmrgRROutputInit(void) 39805b261ecSmrg{ 39935c4bbdfSmrg RROutputType = CreateNewResourceType(RROutputDestroyResource, "OUTPUT"); 40005b261ecSmrg if (!RROutputType) 40135c4bbdfSmrg return FALSE; 4026747b715Smrg 40305b261ecSmrg return TRUE; 40405b261ecSmrg} 40505b261ecSmrg 4066747b715Smrg/* 4076747b715Smrg * Initialize output type error value 4086747b715Smrg */ 4096747b715Smrgvoid 4106747b715SmrgRROutputInitErrorValue(void) 4116747b715Smrg{ 4126747b715Smrg SetResourceTypeErrorValue(RROutputType, RRErrorBase + BadRROutput); 4136747b715Smrg} 4146747b715Smrg 41505b261ecSmrg#define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32) 4164642e01fSmrg 41705b261ecSmrgint 41835c4bbdfSmrgProcRRGetOutputInfo(ClientPtr client) 41905b261ecSmrg{ 42005b261ecSmrg REQUEST(xRRGetOutputInfoReq); 42135c4bbdfSmrg xRRGetOutputInfoReply rep; 42235c4bbdfSmrg RROutputPtr output; 42335c4bbdfSmrg CARD8 *extra; 42435c4bbdfSmrg unsigned long extraLen; 42535c4bbdfSmrg ScreenPtr pScreen; 42635c4bbdfSmrg rrScrPrivPtr pScrPriv; 42735c4bbdfSmrg RRCrtc *crtcs; 42835c4bbdfSmrg RRMode *modes; 42935c4bbdfSmrg RROutput *clones; 43035c4bbdfSmrg char *name; 43135c4bbdfSmrg int i; 43235c4bbdfSmrg 43305b261ecSmrg REQUEST_SIZE_MATCH(xRRGetOutputInfoReq); 4346747b715Smrg VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); 43505b261ecSmrg 43605b261ecSmrg pScreen = output->pScreen; 43705b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 43805b261ecSmrg 43935c4bbdfSmrg rep = (xRRGetOutputInfoReply) { 44035c4bbdfSmrg .type = X_Reply, 44135c4bbdfSmrg .status = RRSetConfigSuccess, 44235c4bbdfSmrg .sequenceNumber = client->sequence, 44335c4bbdfSmrg .length = bytes_to_int32(OutputInfoExtra), 44435c4bbdfSmrg .timestamp = pScrPriv->lastSetTime.milliseconds, 44535c4bbdfSmrg .crtc = output->crtc ? output->crtc->id : None, 44635c4bbdfSmrg .mmWidth = output->mmWidth, 44735c4bbdfSmrg .mmHeight = output->mmHeight, 44835c4bbdfSmrg .connection = output->connection, 44935c4bbdfSmrg .subpixelOrder = output->subpixelOrder, 45035c4bbdfSmrg .nCrtcs = output->numCrtcs, 45135c4bbdfSmrg .nModes = output->numModes + output->numUserModes, 45235c4bbdfSmrg .nPreferred = output->numPreferred, 45335c4bbdfSmrg .nClones = output->numClones, 45435c4bbdfSmrg .nameLength = output->nameLength 45535c4bbdfSmrg }; 4566747b715Smrg extraLen = ((output->numCrtcs + 45735c4bbdfSmrg output->numModes + output->numUserModes + 45835c4bbdfSmrg output->numClones + bytes_to_int32(rep.nameLength)) << 2); 45935c4bbdfSmrg 46035c4bbdfSmrg if (extraLen) { 46135c4bbdfSmrg rep.length += bytes_to_int32(extraLen); 46235c4bbdfSmrg extra = malloc(extraLen); 46335c4bbdfSmrg if (!extra) 46435c4bbdfSmrg return BadAlloc; 46505b261ecSmrg } 46605b261ecSmrg else 46735c4bbdfSmrg extra = NULL; 46805b261ecSmrg 46905b261ecSmrg crtcs = (RRCrtc *) extra; 47005b261ecSmrg modes = (RRMode *) (crtcs + output->numCrtcs); 47105b261ecSmrg clones = (RROutput *) (modes + output->numModes + output->numUserModes); 47205b261ecSmrg name = (char *) (clones + output->numClones); 47335c4bbdfSmrg 47435c4bbdfSmrg for (i = 0; i < output->numCrtcs; i++) { 47535c4bbdfSmrg crtcs[i] = output->crtcs[i]->id; 47635c4bbdfSmrg if (client->swapped) 47735c4bbdfSmrg swapl(&crtcs[i]); 47805b261ecSmrg } 47935c4bbdfSmrg for (i = 0; i < output->numModes + output->numUserModes; i++) { 48035c4bbdfSmrg if (i < output->numModes) 48135c4bbdfSmrg modes[i] = output->modes[i]->mode.id; 48235c4bbdfSmrg else 48335c4bbdfSmrg modes[i] = output->userModes[i - output->numModes]->mode.id; 48435c4bbdfSmrg if (client->swapped) 48535c4bbdfSmrg swapl(&modes[i]); 48605b261ecSmrg } 48735c4bbdfSmrg for (i = 0; i < output->numClones; i++) { 48835c4bbdfSmrg clones[i] = output->clones[i]->id; 48935c4bbdfSmrg if (client->swapped) 49035c4bbdfSmrg swapl(&clones[i]); 49105b261ecSmrg } 49235c4bbdfSmrg memcpy(name, output->name, output->nameLength); 49305b261ecSmrg if (client->swapped) { 49435c4bbdfSmrg swaps(&rep.sequenceNumber); 49535c4bbdfSmrg swapl(&rep.length); 49635c4bbdfSmrg swapl(&rep.timestamp); 49735c4bbdfSmrg swapl(&rep.crtc); 49835c4bbdfSmrg swapl(&rep.mmWidth); 49935c4bbdfSmrg swapl(&rep.mmHeight); 50035c4bbdfSmrg swaps(&rep.nCrtcs); 50135c4bbdfSmrg swaps(&rep.nModes); 50235c4bbdfSmrg swaps(&rep.nPreferred); 50335c4bbdfSmrg swaps(&rep.nClones); 50435c4bbdfSmrg swaps(&rep.nameLength); 50505b261ecSmrg } 50635c4bbdfSmrg WriteToClient(client, sizeof(xRRGetOutputInfoReply), &rep); 50735c4bbdfSmrg if (extraLen) { 50835c4bbdfSmrg WriteToClient(client, extraLen, extra); 50935c4bbdfSmrg free(extra); 51005b261ecSmrg } 51135c4bbdfSmrg 5126747b715Smrg return Success; 51305b261ecSmrg} 5144642e01fSmrg 5156747b715Smrgstatic void 51635c4bbdfSmrgRRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv, RROutputPtr output) 5174642e01fSmrg{ 5184642e01fSmrg if (pScrPriv->primaryOutput == output) 51935c4bbdfSmrg return; 5204642e01fSmrg 5214642e01fSmrg /* clear the old primary */ 5224642e01fSmrg if (pScrPriv->primaryOutput) { 52335c4bbdfSmrg RROutputChanged(pScrPriv->primaryOutput, 0); 52435c4bbdfSmrg pScrPriv->primaryOutput = NULL; 5254642e01fSmrg } 5264642e01fSmrg 5274642e01fSmrg /* set the new primary */ 5284642e01fSmrg if (output) { 52935c4bbdfSmrg pScrPriv->primaryOutput = output; 53035c4bbdfSmrg RROutputChanged(output, 0); 5314642e01fSmrg } 5324642e01fSmrg 5334642e01fSmrg pScrPriv->layoutChanged = TRUE; 5344642e01fSmrg 5354642e01fSmrg RRTellChanged(pScreen); 5364642e01fSmrg} 5374642e01fSmrg 5384642e01fSmrgint 5394642e01fSmrgProcRRSetOutputPrimary(ClientPtr client) 5404642e01fSmrg{ 5414642e01fSmrg REQUEST(xRRSetOutputPrimaryReq); 5424642e01fSmrg RROutputPtr output = NULL; 5434642e01fSmrg WindowPtr pWin; 5444642e01fSmrg rrScrPrivPtr pScrPriv; 54535c4bbdfSmrg int ret; 54635c4bbdfSmrg ScreenPtr slave; 5474642e01fSmrg 5484642e01fSmrg REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq); 5494642e01fSmrg 55035c4bbdfSmrg ret = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 55135c4bbdfSmrg if (ret != Success) 55235c4bbdfSmrg return ret; 5534642e01fSmrg 5544642e01fSmrg if (stuff->output) { 55535c4bbdfSmrg VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); 55635c4bbdfSmrg 55735c4bbdfSmrg if (!output->pScreen->isGPU && output->pScreen != pWin->drawable.pScreen) { 55835c4bbdfSmrg client->errorValue = stuff->window; 55935c4bbdfSmrg return BadMatch; 56035c4bbdfSmrg } 56135c4bbdfSmrg if (output->pScreen->isGPU && output->pScreen->current_master != pWin->drawable.pScreen) { 56235c4bbdfSmrg client->errorValue = stuff->window; 56335c4bbdfSmrg return BadMatch; 56435c4bbdfSmrg } 5654642e01fSmrg } 5664642e01fSmrg 5674642e01fSmrg pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); 56835c4bbdfSmrg if (pScrPriv) 56935c4bbdfSmrg { 57035c4bbdfSmrg RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output); 57135c4bbdfSmrg 57235c4bbdfSmrg xorg_list_for_each_entry(slave, 57335c4bbdfSmrg &pWin->drawable.pScreen->output_slave_list, 57435c4bbdfSmrg output_head) { 57535c4bbdfSmrg rrScrPrivPtr pSlavePriv; 57635c4bbdfSmrg pSlavePriv = rrGetScrPriv(slave); 57735c4bbdfSmrg 57835c4bbdfSmrg RRSetPrimaryOutput(slave, pSlavePriv, output); 57935c4bbdfSmrg } 58035c4bbdfSmrg } 5814642e01fSmrg 5826747b715Smrg return Success; 5834642e01fSmrg} 5844642e01fSmrg 5854642e01fSmrgint 5864642e01fSmrgProcRRGetOutputPrimary(ClientPtr client) 5874642e01fSmrg{ 5884642e01fSmrg REQUEST(xRRGetOutputPrimaryReq); 5894642e01fSmrg WindowPtr pWin; 5904642e01fSmrg rrScrPrivPtr pScrPriv; 5914642e01fSmrg xRRGetOutputPrimaryReply rep; 5924642e01fSmrg RROutputPtr primary = NULL; 5936747b715Smrg int rc; 5944642e01fSmrg 5954642e01fSmrg REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq); 5964642e01fSmrg 5976747b715Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 5986747b715Smrg if (rc != Success) 59935c4bbdfSmrg return rc; 6004642e01fSmrg 6014642e01fSmrg pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); 6024642e01fSmrg if (pScrPriv) 60335c4bbdfSmrg primary = pScrPriv->primaryOutput; 6044642e01fSmrg 60535c4bbdfSmrg rep = (xRRGetOutputPrimaryReply) { 60635c4bbdfSmrg .type = X_Reply, 60735c4bbdfSmrg .sequenceNumber = client->sequence, 60835c4bbdfSmrg .output = primary ? primary->id : None 60935c4bbdfSmrg }; 6104642e01fSmrg 6114642e01fSmrg if (client->swapped) { 61235c4bbdfSmrg swaps(&rep.sequenceNumber); 61335c4bbdfSmrg swapl(&rep.output); 6144642e01fSmrg } 6154642e01fSmrg 6164642e01fSmrg WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), &rep); 6174642e01fSmrg 6186747b715Smrg return Success; 6194642e01fSmrg} 620