1706f2543Smrg/* 2706f2543Smrg * Copyright © 2006 Keith Packard 3706f2543Smrg * Copyright © 2008 Red Hat, Inc. 4706f2543Smrg * 5706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 7706f2543Smrg * the above copyright notice appear in all copies and that both that copyright 8706f2543Smrg * notice and this permission notice appear in supporting documentation, and 9706f2543Smrg * that the name of the copyright holders not be used in advertising or 10706f2543Smrg * publicity pertaining to distribution of the software without specific, 11706f2543Smrg * written prior permission. The copyright holders make no representations 12706f2543Smrg * about the suitability of this software for any purpose. It is provided "as 13706f2543Smrg * is" without express or implied warranty. 14706f2543Smrg * 15706f2543Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17706f2543Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 21706f2543Smrg * OF THIS SOFTWARE. 22706f2543Smrg */ 23706f2543Smrg 24706f2543Smrg#include "randrstr.h" 25706f2543Smrg 26706f2543SmrgRESTYPE RROutputType; 27706f2543Smrg 28706f2543Smrg/* 29706f2543Smrg * Notify the output of some change 30706f2543Smrg */ 31706f2543Smrgvoid 32706f2543SmrgRROutputChanged (RROutputPtr output, Bool configChanged) 33706f2543Smrg{ 34706f2543Smrg ScreenPtr pScreen = output->pScreen; 35706f2543Smrg 36706f2543Smrg output->changed = TRUE; 37706f2543Smrg if (pScreen) 38706f2543Smrg { 39706f2543Smrg rrScrPriv (pScreen); 40706f2543Smrg pScrPriv->changed = TRUE; 41706f2543Smrg if (configChanged) 42706f2543Smrg pScrPriv->configChanged = TRUE; 43706f2543Smrg } 44706f2543Smrg} 45706f2543Smrg 46706f2543Smrg/* 47706f2543Smrg * Create an output 48706f2543Smrg */ 49706f2543Smrg 50706f2543SmrgRROutputPtr 51706f2543SmrgRROutputCreate (ScreenPtr pScreen, 52706f2543Smrg const char *name, 53706f2543Smrg int nameLength, 54706f2543Smrg void *devPrivate) 55706f2543Smrg{ 56706f2543Smrg RROutputPtr output; 57706f2543Smrg RROutputPtr *outputs; 58706f2543Smrg rrScrPrivPtr pScrPriv; 59706f2543Smrg 60706f2543Smrg if (!RRInit()) 61706f2543Smrg return NULL; 62706f2543Smrg 63706f2543Smrg pScrPriv = rrGetScrPriv(pScreen); 64706f2543Smrg 65706f2543Smrg if (pScrPriv->numOutputs) 66706f2543Smrg outputs = realloc(pScrPriv->outputs, 67706f2543Smrg (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr)); 68706f2543Smrg else 69706f2543Smrg outputs = malloc(sizeof (RROutputPtr)); 70706f2543Smrg if (!outputs) 71706f2543Smrg return FALSE; 72706f2543Smrg 73706f2543Smrg pScrPriv->outputs = outputs; 74706f2543Smrg 75706f2543Smrg output = malloc(sizeof (RROutputRec) + nameLength + 1); 76706f2543Smrg if (!output) 77706f2543Smrg return NULL; 78706f2543Smrg output->id = FakeClientID (0); 79706f2543Smrg output->pScreen = pScreen; 80706f2543Smrg output->name = (char *) (output + 1); 81706f2543Smrg output->nameLength = nameLength; 82706f2543Smrg memcpy (output->name, name, nameLength); 83706f2543Smrg output->name[nameLength] = '\0'; 84706f2543Smrg output->connection = RR_UnknownConnection; 85706f2543Smrg output->subpixelOrder = SubPixelUnknown; 86706f2543Smrg output->mmWidth = 0; 87706f2543Smrg output->mmHeight = 0; 88706f2543Smrg output->crtc = NULL; 89706f2543Smrg output->numCrtcs = 0; 90706f2543Smrg output->crtcs = NULL; 91706f2543Smrg output->numClones = 0; 92706f2543Smrg output->clones = NULL; 93706f2543Smrg output->numModes = 0; 94706f2543Smrg output->numPreferred = 0; 95706f2543Smrg output->modes = NULL; 96706f2543Smrg output->numUserModes = 0; 97706f2543Smrg output->userModes = NULL; 98706f2543Smrg output->properties = NULL; 99706f2543Smrg output->pendingProperties = FALSE; 100706f2543Smrg output->changed = FALSE; 101706f2543Smrg output->devPrivate = devPrivate; 102706f2543Smrg 103706f2543Smrg if (!AddResource (output->id, RROutputType, (pointer) output)) 104706f2543Smrg return NULL; 105706f2543Smrg 106706f2543Smrg pScrPriv->outputs[pScrPriv->numOutputs++] = output; 107706f2543Smrg return output; 108706f2543Smrg} 109706f2543Smrg 110706f2543Smrg/* 111706f2543Smrg * Notify extension that output parameters have been changed 112706f2543Smrg */ 113706f2543SmrgBool 114706f2543SmrgRROutputSetClones (RROutputPtr output, 115706f2543Smrg RROutputPtr *clones, 116706f2543Smrg int numClones) 117706f2543Smrg{ 118706f2543Smrg RROutputPtr *newClones; 119706f2543Smrg int i; 120706f2543Smrg 121706f2543Smrg if (numClones == output->numClones) 122706f2543Smrg { 123706f2543Smrg for (i = 0; i < numClones; i++) 124706f2543Smrg if (output->clones[i] != clones[i]) 125706f2543Smrg break; 126706f2543Smrg if (i == numClones) 127706f2543Smrg return TRUE; 128706f2543Smrg } 129706f2543Smrg if (numClones) 130706f2543Smrg { 131706f2543Smrg newClones = malloc(numClones * sizeof (RROutputPtr)); 132706f2543Smrg if (!newClones) 133706f2543Smrg return FALSE; 134706f2543Smrg } 135706f2543Smrg else 136706f2543Smrg newClones = NULL; 137706f2543Smrg free(output->clones); 138706f2543Smrg memcpy (newClones, clones, numClones * sizeof (RROutputPtr)); 139706f2543Smrg output->clones = newClones; 140706f2543Smrg output->numClones = numClones; 141706f2543Smrg RROutputChanged (output, TRUE); 142706f2543Smrg return TRUE; 143706f2543Smrg} 144706f2543Smrg 145706f2543SmrgBool 146706f2543SmrgRROutputSetModes (RROutputPtr output, 147706f2543Smrg RRModePtr *modes, 148706f2543Smrg int numModes, 149706f2543Smrg int numPreferred) 150706f2543Smrg{ 151706f2543Smrg RRModePtr *newModes; 152706f2543Smrg int i; 153706f2543Smrg 154706f2543Smrg if (numModes == output->numModes && numPreferred == output->numPreferred) 155706f2543Smrg { 156706f2543Smrg for (i = 0; i < numModes; i++) 157706f2543Smrg if (output->modes[i] != modes[i]) 158706f2543Smrg break; 159706f2543Smrg if (i == numModes) 160706f2543Smrg { 161706f2543Smrg for (i = 0; i < numModes; i++) 162706f2543Smrg RRModeDestroy (modes[i]); 163706f2543Smrg return TRUE; 164706f2543Smrg } 165706f2543Smrg } 166706f2543Smrg 167706f2543Smrg if (numModes) 168706f2543Smrg { 169706f2543Smrg newModes = malloc(numModes * sizeof (RRModePtr)); 170706f2543Smrg if (!newModes) 171706f2543Smrg return FALSE; 172706f2543Smrg } 173706f2543Smrg else 174706f2543Smrg newModes = NULL; 175706f2543Smrg if (output->modes) 176706f2543Smrg { 177706f2543Smrg for (i = 0; i < output->numModes; i++) 178706f2543Smrg RRModeDestroy (output->modes[i]); 179706f2543Smrg free(output->modes); 180706f2543Smrg } 181706f2543Smrg memcpy (newModes, modes, numModes * sizeof (RRModePtr)); 182706f2543Smrg output->modes = newModes; 183706f2543Smrg output->numModes = numModes; 184706f2543Smrg output->numPreferred = numPreferred; 185706f2543Smrg RROutputChanged (output, TRUE); 186706f2543Smrg return TRUE; 187706f2543Smrg} 188706f2543Smrg 189706f2543Smrgint 190706f2543SmrgRROutputAddUserMode (RROutputPtr output, 191706f2543Smrg RRModePtr mode) 192706f2543Smrg{ 193706f2543Smrg int m; 194706f2543Smrg ScreenPtr pScreen = output->pScreen; 195706f2543Smrg rrScrPriv(pScreen); 196706f2543Smrg RRModePtr *newModes; 197706f2543Smrg 198706f2543Smrg /* Check to see if this mode is already listed for this output */ 199706f2543Smrg for (m = 0; m < output->numModes + output->numUserModes; m++) 200706f2543Smrg { 201706f2543Smrg RRModePtr e = (m < output->numModes ? 202706f2543Smrg output->modes[m] : 203706f2543Smrg output->userModes[m - output->numModes]); 204706f2543Smrg if (mode == e) 205706f2543Smrg return Success; 206706f2543Smrg } 207706f2543Smrg 208706f2543Smrg /* Check with the DDX to see if this mode is OK */ 209706f2543Smrg if (pScrPriv->rrOutputValidateMode) 210706f2543Smrg if (!pScrPriv->rrOutputValidateMode (pScreen, output, mode)) 211706f2543Smrg return BadMatch; 212706f2543Smrg 213706f2543Smrg if (output->userModes) 214706f2543Smrg newModes = realloc(output->userModes, 215706f2543Smrg (output->numUserModes + 1) * sizeof (RRModePtr)); 216706f2543Smrg else 217706f2543Smrg newModes = malloc(sizeof (RRModePtr)); 218706f2543Smrg if (!newModes) 219706f2543Smrg return BadAlloc; 220706f2543Smrg 221706f2543Smrg output->userModes = newModes; 222706f2543Smrg output->userModes[output->numUserModes++] = mode; 223706f2543Smrg ++mode->refcnt; 224706f2543Smrg RROutputChanged (output, TRUE); 225706f2543Smrg RRTellChanged (pScreen); 226706f2543Smrg return Success; 227706f2543Smrg} 228706f2543Smrg 229706f2543Smrgint 230706f2543SmrgRROutputDeleteUserMode (RROutputPtr output, 231706f2543Smrg RRModePtr mode) 232706f2543Smrg{ 233706f2543Smrg int m; 234706f2543Smrg 235706f2543Smrg /* Find this mode in the user mode list */ 236706f2543Smrg for (m = 0; m < output->numUserModes; m++) 237706f2543Smrg { 238706f2543Smrg RRModePtr e = output->userModes[m]; 239706f2543Smrg 240706f2543Smrg if (mode == e) 241706f2543Smrg break; 242706f2543Smrg } 243706f2543Smrg /* Not there, access error */ 244706f2543Smrg if (m == output->numUserModes) 245706f2543Smrg return BadAccess; 246706f2543Smrg 247706f2543Smrg /* make sure the mode isn't active for this output */ 248706f2543Smrg if (output->crtc && output->crtc->mode == mode) 249706f2543Smrg return BadMatch; 250706f2543Smrg 251706f2543Smrg memmove (output->userModes + m, output->userModes + m + 1, 252706f2543Smrg (output->numUserModes - m - 1) * sizeof (RRModePtr)); 253706f2543Smrg output->numUserModes--; 254706f2543Smrg RRModeDestroy (mode); 255706f2543Smrg return Success; 256706f2543Smrg} 257706f2543Smrg 258706f2543SmrgBool 259706f2543SmrgRROutputSetCrtcs (RROutputPtr output, 260706f2543Smrg RRCrtcPtr *crtcs, 261706f2543Smrg int numCrtcs) 262706f2543Smrg{ 263706f2543Smrg RRCrtcPtr *newCrtcs; 264706f2543Smrg int i; 265706f2543Smrg 266706f2543Smrg if (numCrtcs == output->numCrtcs) 267706f2543Smrg { 268706f2543Smrg for (i = 0; i < numCrtcs; i++) 269706f2543Smrg if (output->crtcs[i] != crtcs[i]) 270706f2543Smrg break; 271706f2543Smrg if (i == numCrtcs) 272706f2543Smrg return TRUE; 273706f2543Smrg } 274706f2543Smrg if (numCrtcs) 275706f2543Smrg { 276706f2543Smrg newCrtcs = malloc(numCrtcs * sizeof (RRCrtcPtr)); 277706f2543Smrg if (!newCrtcs) 278706f2543Smrg return FALSE; 279706f2543Smrg } 280706f2543Smrg else 281706f2543Smrg newCrtcs = NULL; 282706f2543Smrg free(output->crtcs); 283706f2543Smrg memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr)); 284706f2543Smrg output->crtcs = newCrtcs; 285706f2543Smrg output->numCrtcs = numCrtcs; 286706f2543Smrg RROutputChanged (output, TRUE); 287706f2543Smrg return TRUE; 288706f2543Smrg} 289706f2543Smrg 290706f2543SmrgBool 291706f2543SmrgRROutputSetConnection (RROutputPtr output, 292706f2543Smrg CARD8 connection) 293706f2543Smrg{ 294706f2543Smrg if (output->connection == connection) 295706f2543Smrg return TRUE; 296706f2543Smrg output->connection = connection; 297706f2543Smrg RROutputChanged (output, TRUE); 298706f2543Smrg return TRUE; 299706f2543Smrg} 300706f2543Smrg 301706f2543SmrgBool 302706f2543SmrgRROutputSetSubpixelOrder (RROutputPtr output, 303706f2543Smrg int subpixelOrder) 304706f2543Smrg{ 305706f2543Smrg if (output->subpixelOrder == subpixelOrder) 306706f2543Smrg return TRUE; 307706f2543Smrg 308706f2543Smrg output->subpixelOrder = subpixelOrder; 309706f2543Smrg RROutputChanged (output, FALSE); 310706f2543Smrg return TRUE; 311706f2543Smrg} 312706f2543Smrg 313706f2543SmrgBool 314706f2543SmrgRROutputSetPhysicalSize (RROutputPtr output, 315706f2543Smrg int mmWidth, 316706f2543Smrg int mmHeight) 317706f2543Smrg{ 318706f2543Smrg if (output->mmWidth == mmWidth && output->mmHeight == mmHeight) 319706f2543Smrg return TRUE; 320706f2543Smrg output->mmWidth = mmWidth; 321706f2543Smrg output->mmHeight = mmHeight; 322706f2543Smrg RROutputChanged (output, FALSE); 323706f2543Smrg return TRUE; 324706f2543Smrg} 325706f2543Smrg 326706f2543Smrg 327706f2543Smrgvoid 328706f2543SmrgRRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output) 329706f2543Smrg{ 330706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 331706f2543Smrg rrScrPriv (pScreen); 332706f2543Smrg xRROutputChangeNotifyEvent oe; 333706f2543Smrg RRCrtcPtr crtc = output->crtc; 334706f2543Smrg RRModePtr mode = crtc ? crtc->mode : 0; 335706f2543Smrg 336706f2543Smrg oe.type = RRNotify + RREventBase; 337706f2543Smrg oe.subCode = RRNotify_OutputChange; 338706f2543Smrg oe.timestamp = pScrPriv->lastSetTime.milliseconds; 339706f2543Smrg oe.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 340706f2543Smrg oe.window = pWin->drawable.id; 341706f2543Smrg oe.output = output->id; 342706f2543Smrg if (crtc) 343706f2543Smrg { 344706f2543Smrg oe.crtc = crtc->id; 345706f2543Smrg oe.mode = mode ? mode->mode.id : None; 346706f2543Smrg oe.rotation = crtc->rotation; 347706f2543Smrg } 348706f2543Smrg else 349706f2543Smrg { 350706f2543Smrg oe.crtc = None; 351706f2543Smrg oe.mode = None; 352706f2543Smrg oe.rotation = RR_Rotate_0; 353706f2543Smrg } 354706f2543Smrg oe.connection = output->connection; 355706f2543Smrg oe.subpixelOrder = output->subpixelOrder; 356706f2543Smrg WriteEventsToClient (client, 1, (xEvent *) &oe); 357706f2543Smrg} 358706f2543Smrg 359706f2543Smrg/* 360706f2543Smrg * Destroy a Output at shutdown 361706f2543Smrg */ 362706f2543Smrgvoid 363706f2543SmrgRROutputDestroy (RROutputPtr output) 364706f2543Smrg{ 365706f2543Smrg FreeResource (output->id, 0); 366706f2543Smrg} 367706f2543Smrg 368706f2543Smrgstatic int 369706f2543SmrgRROutputDestroyResource (pointer value, XID pid) 370706f2543Smrg{ 371706f2543Smrg RROutputPtr output = (RROutputPtr) value; 372706f2543Smrg ScreenPtr pScreen = output->pScreen; 373706f2543Smrg int m; 374706f2543Smrg 375706f2543Smrg if (pScreen) 376706f2543Smrg { 377706f2543Smrg rrScrPriv(pScreen); 378706f2543Smrg int i; 379706f2543Smrg 380706f2543Smrg if (pScrPriv->primaryOutput == output) 381706f2543Smrg pScrPriv->primaryOutput = NULL; 382706f2543Smrg 383706f2543Smrg for (i = 0; i < pScrPriv->numOutputs; i++) 384706f2543Smrg { 385706f2543Smrg if (pScrPriv->outputs[i] == output) 386706f2543Smrg { 387706f2543Smrg memmove (pScrPriv->outputs + i, pScrPriv->outputs + i + 1, 388706f2543Smrg (pScrPriv->numOutputs - (i + 1)) * sizeof (RROutputPtr)); 389706f2543Smrg --pScrPriv->numOutputs; 390706f2543Smrg break; 391706f2543Smrg } 392706f2543Smrg } 393706f2543Smrg } 394706f2543Smrg if (output->modes) 395706f2543Smrg { 396706f2543Smrg for (m = 0; m < output->numModes; m++) 397706f2543Smrg RRModeDestroy (output->modes[m]); 398706f2543Smrg free(output->modes); 399706f2543Smrg } 400706f2543Smrg 401706f2543Smrg for (m = 0; m < output->numUserModes; m++) 402706f2543Smrg RRModeDestroy (output->userModes[m]); 403706f2543Smrg free(output->userModes); 404706f2543Smrg 405706f2543Smrg free(output->crtcs); 406706f2543Smrg free(output->clones); 407706f2543Smrg RRDeleteAllOutputProperties (output); 408706f2543Smrg free(output); 409706f2543Smrg return 1; 410706f2543Smrg} 411706f2543Smrg 412706f2543Smrg/* 413706f2543Smrg * Initialize output type 414706f2543Smrg */ 415706f2543SmrgBool 416706f2543SmrgRROutputInit (void) 417706f2543Smrg{ 418706f2543Smrg RROutputType = CreateNewResourceType (RROutputDestroyResource, "OUTPUT"); 419706f2543Smrg if (!RROutputType) 420706f2543Smrg return FALSE; 421706f2543Smrg 422706f2543Smrg return TRUE; 423706f2543Smrg} 424706f2543Smrg 425706f2543Smrg/* 426706f2543Smrg * Initialize output type error value 427706f2543Smrg */ 428706f2543Smrgvoid 429706f2543SmrgRROutputInitErrorValue(void) 430706f2543Smrg{ 431706f2543Smrg SetResourceTypeErrorValue(RROutputType, RRErrorBase + BadRROutput); 432706f2543Smrg} 433706f2543Smrg 434706f2543Smrg#define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32) 435706f2543Smrg 436706f2543Smrgint 437706f2543SmrgProcRRGetOutputInfo (ClientPtr client) 438706f2543Smrg{ 439706f2543Smrg REQUEST(xRRGetOutputInfoReq); 440706f2543Smrg xRRGetOutputInfoReply rep; 441706f2543Smrg RROutputPtr output; 442706f2543Smrg CARD8 *extra; 443706f2543Smrg unsigned long extraLen; 444706f2543Smrg ScreenPtr pScreen; 445706f2543Smrg rrScrPrivPtr pScrPriv; 446706f2543Smrg RRCrtc *crtcs; 447706f2543Smrg RRMode *modes; 448706f2543Smrg RROutput *clones; 449706f2543Smrg char *name; 450706f2543Smrg int i, n; 451706f2543Smrg 452706f2543Smrg REQUEST_SIZE_MATCH(xRRGetOutputInfoReq); 453706f2543Smrg VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); 454706f2543Smrg 455706f2543Smrg pScreen = output->pScreen; 456706f2543Smrg pScrPriv = rrGetScrPriv(pScreen); 457706f2543Smrg 458706f2543Smrg rep.type = X_Reply; 459706f2543Smrg rep.sequenceNumber = client->sequence; 460706f2543Smrg rep.length = bytes_to_int32(OutputInfoExtra); 461706f2543Smrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 462706f2543Smrg rep.crtc = output->crtc ? output->crtc->id : None; 463706f2543Smrg rep.mmWidth = output->mmWidth; 464706f2543Smrg rep.mmHeight = output->mmHeight; 465706f2543Smrg rep.connection = output->connection; 466706f2543Smrg rep.subpixelOrder = output->subpixelOrder; 467706f2543Smrg rep.nCrtcs = output->numCrtcs; 468706f2543Smrg rep.nModes = output->numModes + output->numUserModes; 469706f2543Smrg rep.nPreferred = output->numPreferred; 470706f2543Smrg rep.nClones = output->numClones; 471706f2543Smrg rep.nameLength = output->nameLength; 472706f2543Smrg 473706f2543Smrg extraLen = ((output->numCrtcs + 474706f2543Smrg output->numModes + output->numUserModes + 475706f2543Smrg output->numClones + 476706f2543Smrg bytes_to_int32(rep.nameLength)) << 2); 477706f2543Smrg 478706f2543Smrg if (extraLen) 479706f2543Smrg { 480706f2543Smrg rep.length += bytes_to_int32(extraLen); 481706f2543Smrg extra = malloc(extraLen); 482706f2543Smrg if (!extra) 483706f2543Smrg return BadAlloc; 484706f2543Smrg } 485706f2543Smrg else 486706f2543Smrg extra = NULL; 487706f2543Smrg 488706f2543Smrg crtcs = (RRCrtc *) extra; 489706f2543Smrg modes = (RRMode *) (crtcs + output->numCrtcs); 490706f2543Smrg clones = (RROutput *) (modes + output->numModes + output->numUserModes); 491706f2543Smrg name = (char *) (clones + output->numClones); 492706f2543Smrg 493706f2543Smrg for (i = 0; i < output->numCrtcs; i++) 494706f2543Smrg { 495706f2543Smrg crtcs[i] = output->crtcs[i]->id; 496706f2543Smrg if (client->swapped) 497706f2543Smrg swapl (&crtcs[i], n); 498706f2543Smrg } 499706f2543Smrg for (i = 0; i < output->numModes + output->numUserModes; i++) 500706f2543Smrg { 501706f2543Smrg if (i < output->numModes) 502706f2543Smrg modes[i] = output->modes[i]->mode.id; 503706f2543Smrg else 504706f2543Smrg modes[i] = output->userModes[i - output->numModes]->mode.id; 505706f2543Smrg if (client->swapped) 506706f2543Smrg swapl (&modes[i], n); 507706f2543Smrg } 508706f2543Smrg for (i = 0; i < output->numClones; i++) 509706f2543Smrg { 510706f2543Smrg clones[i] = output->clones[i]->id; 511706f2543Smrg if (client->swapped) 512706f2543Smrg swapl (&clones[i], n); 513706f2543Smrg } 514706f2543Smrg memcpy (name, output->name, output->nameLength); 515706f2543Smrg if (client->swapped) { 516706f2543Smrg swaps(&rep.sequenceNumber, n); 517706f2543Smrg swapl(&rep.length, n); 518706f2543Smrg swapl(&rep.timestamp, n); 519706f2543Smrg swapl(&rep.crtc, n); 520706f2543Smrg swapl(&rep.mmWidth, n); 521706f2543Smrg swapl(&rep.mmHeight, n); 522706f2543Smrg swaps(&rep.nCrtcs, n); 523706f2543Smrg swaps(&rep.nModes, n); 524706f2543Smrg swaps(&rep.nClones, n); 525706f2543Smrg swaps(&rep.nameLength, n); 526706f2543Smrg } 527706f2543Smrg WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *)&rep); 528706f2543Smrg if (extraLen) 529706f2543Smrg { 530706f2543Smrg WriteToClient (client, extraLen, (char *) extra); 531706f2543Smrg free(extra); 532706f2543Smrg } 533706f2543Smrg 534706f2543Smrg return Success; 535706f2543Smrg} 536706f2543Smrg 537706f2543Smrgstatic void 538706f2543SmrgRRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv, 539706f2543Smrg RROutputPtr output) 540706f2543Smrg{ 541706f2543Smrg if (pScrPriv->primaryOutput == output) 542706f2543Smrg return; 543706f2543Smrg 544706f2543Smrg /* clear the old primary */ 545706f2543Smrg if (pScrPriv->primaryOutput) { 546706f2543Smrg RROutputChanged(pScrPriv->primaryOutput, 0); 547706f2543Smrg pScrPriv->primaryOutput = NULL; 548706f2543Smrg } 549706f2543Smrg 550706f2543Smrg /* set the new primary */ 551706f2543Smrg if (output) { 552706f2543Smrg pScrPriv->primaryOutput = output; 553706f2543Smrg RROutputChanged(output, 0); 554706f2543Smrg } 555706f2543Smrg 556706f2543Smrg pScrPriv->layoutChanged = TRUE; 557706f2543Smrg 558706f2543Smrg RRTellChanged(pScreen); 559706f2543Smrg} 560706f2543Smrg 561706f2543Smrgint 562706f2543SmrgProcRRSetOutputPrimary(ClientPtr client) 563706f2543Smrg{ 564706f2543Smrg REQUEST(xRRSetOutputPrimaryReq); 565706f2543Smrg RROutputPtr output = NULL; 566706f2543Smrg WindowPtr pWin; 567706f2543Smrg rrScrPrivPtr pScrPriv; 568706f2543Smrg int rc; 569706f2543Smrg 570706f2543Smrg REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq); 571706f2543Smrg 572706f2543Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 573706f2543Smrg if (rc != Success) 574706f2543Smrg return rc; 575706f2543Smrg 576706f2543Smrg if (stuff->output) { 577706f2543Smrg VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); 578706f2543Smrg 579706f2543Smrg if (output->pScreen != pWin->drawable.pScreen) { 580706f2543Smrg client->errorValue = stuff->window; 581706f2543Smrg return BadMatch; 582706f2543Smrg } 583706f2543Smrg } 584706f2543Smrg 585706f2543Smrg pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); 586706f2543Smrg RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output); 587706f2543Smrg 588706f2543Smrg return Success; 589706f2543Smrg} 590706f2543Smrg 591706f2543Smrgint 592706f2543SmrgProcRRGetOutputPrimary(ClientPtr client) 593706f2543Smrg{ 594706f2543Smrg REQUEST(xRRGetOutputPrimaryReq); 595706f2543Smrg WindowPtr pWin; 596706f2543Smrg rrScrPrivPtr pScrPriv; 597706f2543Smrg xRRGetOutputPrimaryReply rep; 598706f2543Smrg RROutputPtr primary = NULL; 599706f2543Smrg int rc; 600706f2543Smrg 601706f2543Smrg REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq); 602706f2543Smrg 603706f2543Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 604706f2543Smrg if (rc != Success) 605706f2543Smrg return rc; 606706f2543Smrg 607706f2543Smrg pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); 608706f2543Smrg if (pScrPriv) 609706f2543Smrg primary = pScrPriv->primaryOutput; 610706f2543Smrg 611706f2543Smrg memset(&rep, 0, sizeof(rep)); 612706f2543Smrg rep.type = X_Reply; 613706f2543Smrg rep.sequenceNumber = client->sequence; 614706f2543Smrg rep.output = primary ? primary->id : None; 615706f2543Smrg 616706f2543Smrg if (client->swapped) { 617706f2543Smrg int n; 618706f2543Smrg swaps(&rep.sequenceNumber, n); 619706f2543Smrg swapl(&rep.output, n); 620706f2543Smrg } 621706f2543Smrg 622706f2543Smrg WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), &rep); 623706f2543Smrg 624706f2543Smrg return Success; 625706f2543Smrg} 626