rrcrtc.c revision 05b261ec
1/* 2 * Copyright © 2006 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23#include "randrstr.h" 24#include "swaprep.h" 25 26RESTYPE RRCrtcType; 27 28/* 29 * Notify the CRTC of some change 30 */ 31void 32RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged) 33{ 34 ScreenPtr pScreen = crtc->pScreen; 35 36 crtc->changed = TRUE; 37 if (pScreen) 38 { 39 rrScrPriv(pScreen); 40 41 pScrPriv->changed = TRUE; 42 /* 43 * Send ConfigureNotify on any layout change 44 */ 45 if (layoutChanged) 46 pScrPriv->layoutChanged = TRUE; 47 } 48} 49 50/* 51 * Create a CRTC 52 */ 53RRCrtcPtr 54RRCrtcCreate (ScreenPtr pScreen, void *devPrivate) 55{ 56 RRCrtcPtr crtc; 57 RRCrtcPtr *crtcs; 58 rrScrPrivPtr pScrPriv; 59 60 if (!RRInit()) 61 return NULL; 62 63 pScrPriv = rrGetScrPriv(pScreen); 64 65 /* make space for the crtc pointer */ 66 if (pScrPriv->numCrtcs) 67 crtcs = xrealloc (pScrPriv->crtcs, 68 (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr)); 69 else 70 crtcs = xalloc (sizeof (RRCrtcPtr)); 71 if (!crtcs) 72 return FALSE; 73 pScrPriv->crtcs = crtcs; 74 75 crtc = xalloc (sizeof (RRCrtcRec)); 76 if (!crtc) 77 return NULL; 78 crtc->id = FakeClientID (0); 79 crtc->pScreen = pScreen; 80 crtc->mode = NULL; 81 crtc->x = 0; 82 crtc->y = 0; 83 crtc->rotation = RR_Rotate_0; 84 crtc->rotations = RR_Rotate_0; 85 crtc->outputs = NULL; 86 crtc->numOutputs = 0; 87 crtc->gammaSize = 0; 88 crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL; 89 crtc->changed = FALSE; 90 crtc->devPrivate = devPrivate; 91 92 if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc)) 93 return NULL; 94 95 /* attach the screen and crtc together */ 96 crtc->pScreen = pScreen; 97 pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc; 98 99 return crtc; 100} 101 102/* 103 * Set the allowed rotations on a CRTC 104 */ 105void 106RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations) 107{ 108 crtc->rotations = rotations; 109} 110 111/* 112 * Notify the extension that the Crtc has been reconfigured, 113 * the driver calls this whenever it has updated the mode 114 */ 115Bool 116RRCrtcNotify (RRCrtcPtr crtc, 117 RRModePtr mode, 118 int x, 119 int y, 120 Rotation rotation, 121 int numOutputs, 122 RROutputPtr *outputs) 123{ 124 int i, j; 125 126 /* 127 * Check to see if any of the new outputs were 128 * not in the old list and mark them as changed 129 */ 130 for (i = 0; i < numOutputs; i++) 131 { 132 for (j = 0; j < crtc->numOutputs; j++) 133 if (outputs[i] == crtc->outputs[j]) 134 break; 135 if (j == crtc->numOutputs) 136 { 137 outputs[i]->crtc = crtc; 138 RROutputChanged (outputs[i], FALSE); 139 RRCrtcChanged (crtc, FALSE); 140 } 141 } 142 /* 143 * Check to see if any of the old outputs are 144 * not in the new list and mark them as changed 145 */ 146 for (j = 0; j < crtc->numOutputs; j++) 147 { 148 for (i = 0; i < numOutputs; i++) 149 if (outputs[i] == crtc->outputs[j]) 150 break; 151 if (i == numOutputs) 152 { 153 crtc->outputs[j]->crtc = NULL; 154 RROutputChanged (crtc->outputs[j], FALSE); 155 RRCrtcChanged (crtc, FALSE); 156 } 157 } 158 /* 159 * Reallocate the crtc output array if necessary 160 */ 161 if (numOutputs != crtc->numOutputs) 162 { 163 RROutputPtr *newoutputs; 164 165 if (numOutputs) 166 { 167 if (crtc->numOutputs) 168 newoutputs = xrealloc (crtc->outputs, 169 numOutputs * sizeof (RROutputPtr)); 170 else 171 newoutputs = xalloc (numOutputs * sizeof (RROutputPtr)); 172 if (!newoutputs) 173 return FALSE; 174 } 175 else 176 { 177 if (crtc->outputs) 178 xfree (crtc->outputs); 179 newoutputs = NULL; 180 } 181 crtc->outputs = newoutputs; 182 crtc->numOutputs = numOutputs; 183 } 184 /* 185 * Copy the new list of outputs into the crtc 186 */ 187 memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)); 188 /* 189 * Update remaining crtc fields 190 */ 191 if (mode != crtc->mode) 192 { 193 if (crtc->mode) 194 RRModeDestroy (crtc->mode); 195 crtc->mode = mode; 196 if (mode != NULL) 197 mode->refcnt++; 198 RRCrtcChanged (crtc, TRUE); 199 } 200 if (x != crtc->x) 201 { 202 crtc->x = x; 203 RRCrtcChanged (crtc, TRUE); 204 } 205 if (y != crtc->y) 206 { 207 crtc->y = y; 208 RRCrtcChanged (crtc, TRUE); 209 } 210 if (rotation != crtc->rotation) 211 { 212 crtc->rotation = rotation; 213 RRCrtcChanged (crtc, TRUE); 214 } 215 return TRUE; 216} 217 218void 219RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc) 220{ 221 ScreenPtr pScreen = pWin->drawable.pScreen; 222 rrScrPriv (pScreen); 223 xRRCrtcChangeNotifyEvent ce; 224 RRModePtr mode = crtc->mode; 225 226 ce.type = RRNotify + RREventBase; 227 ce.subCode = RRNotify_CrtcChange; 228 ce.sequenceNumber = client->sequence; 229 ce.timestamp = pScrPriv->lastSetTime.milliseconds; 230 ce.window = pWin->drawable.id; 231 ce.crtc = crtc->id; 232 ce.rotation = crtc->rotation; 233 if (mode) 234 { 235 ce.mode = mode->mode.id; 236 ce.x = crtc->x; 237 ce.y = crtc->y; 238 ce.width = mode->mode.width; 239 ce.height = mode->mode.height; 240 } 241 else 242 { 243 ce.mode = None; 244 ce.x = 0; 245 ce.y = 0; 246 ce.width = 0; 247 ce.height = 0; 248 } 249 WriteEventsToClient (client, 1, (xEvent *) &ce); 250} 251 252static Bool 253RRCrtcPendingProperties (RRCrtcPtr crtc) 254{ 255 ScreenPtr pScreen = crtc->pScreen; 256 rrScrPriv(pScreen); 257 int o; 258 259 for (o = 0; o < pScrPriv->numOutputs; o++) 260 { 261 RROutputPtr output = pScrPriv->outputs[o]; 262 if (output->crtc == crtc && output->pendingProperties) 263 return TRUE; 264 } 265 return FALSE; 266} 267 268/* 269 * Request that the Crtc be reconfigured 270 */ 271Bool 272RRCrtcSet (RRCrtcPtr crtc, 273 RRModePtr mode, 274 int x, 275 int y, 276 Rotation rotation, 277 int numOutputs, 278 RROutputPtr *outputs) 279{ 280 ScreenPtr pScreen = crtc->pScreen; 281 Bool ret = FALSE; 282 rrScrPriv(pScreen); 283 284 /* See if nothing changed */ 285 if (crtc->mode == mode && 286 crtc->x == x && 287 crtc->y == y && 288 crtc->rotation == rotation && 289 crtc->numOutputs == numOutputs && 290 !memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) && 291 !RRCrtcPendingProperties (crtc)) 292 { 293 ret = TRUE; 294 } 295 else 296 { 297#if RANDR_12_INTERFACE 298 if (pScrPriv->rrCrtcSet) 299 { 300 ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, 301 rotation, numOutputs, outputs); 302 } 303 else 304#endif 305 { 306#if RANDR_10_INTERFACE 307 if (pScrPriv->rrSetConfig) 308 { 309 RRScreenSize size; 310 RRScreenRate rate; 311 312 if (!mode) 313 { 314 RRCrtcNotify (crtc, NULL, x, y, rotation, 0, NULL); 315 ret = TRUE; 316 } 317 else 318 { 319 size.width = mode->mode.width; 320 size.height = mode->mode.height; 321 if (outputs[0]->mmWidth && outputs[0]->mmHeight) 322 { 323 size.mmWidth = outputs[0]->mmWidth; 324 size.mmHeight = outputs[0]->mmHeight; 325 } 326 else 327 { 328 size.mmWidth = pScreen->mmWidth; 329 size.mmHeight = pScreen->mmHeight; 330 } 331 size.nRates = 1; 332 rate.rate = RRVerticalRefresh (&mode->mode); 333 size.pRates = &rate; 334 ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size); 335 /* 336 * Old 1.0 interface tied screen size to mode size 337 */ 338 if (ret) 339 { 340 RRCrtcNotify (crtc, mode, x, y, rotation, 1, outputs); 341 RRScreenSizeNotify (pScreen); 342 } 343 } 344 } 345#endif 346 } 347 if (ret) 348 { 349 int o; 350 RRTellChanged (pScreen); 351 352 for (o = 0; o < numOutputs; o++) 353 RRPostPendingProperties (outputs[o]); 354 } 355 } 356 return ret; 357} 358 359/* 360 * Destroy a Crtc at shutdown 361 */ 362void 363RRCrtcDestroy (RRCrtcPtr crtc) 364{ 365 FreeResource (crtc->id, 0); 366} 367 368static int 369RRCrtcDestroyResource (pointer value, XID pid) 370{ 371 RRCrtcPtr crtc = (RRCrtcPtr) value; 372 ScreenPtr pScreen = crtc->pScreen; 373 374 if (pScreen) 375 { 376 rrScrPriv(pScreen); 377 int i; 378 379 for (i = 0; i < pScrPriv->numCrtcs; i++) 380 { 381 if (pScrPriv->crtcs[i] == crtc) 382 { 383 memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1, 384 (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr)); 385 --pScrPriv->numCrtcs; 386 break; 387 } 388 } 389 } 390 if (crtc->gammaRed) 391 xfree (crtc->gammaRed); 392 if (crtc->mode) 393 RRModeDestroy (crtc->mode); 394 xfree (crtc); 395 return 1; 396} 397 398/* 399 * Request that the Crtc gamma be changed 400 */ 401 402Bool 403RRCrtcGammaSet (RRCrtcPtr crtc, 404 CARD16 *red, 405 CARD16 *green, 406 CARD16 *blue) 407{ 408 Bool ret = TRUE; 409#if RANDR_12_INTERFACE 410 ScreenPtr pScreen = crtc->pScreen; 411#endif 412 413 memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16)); 414 memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16)); 415 memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16)); 416#if RANDR_12_INTERFACE 417 if (pScreen) 418 { 419 rrScrPriv(pScreen); 420 if (pScrPriv->rrCrtcSetGamma) 421 ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc); 422 } 423#endif 424 return ret; 425} 426 427/* 428 * Notify the extension that the Crtc gamma has been changed 429 * The driver calls this whenever it has changed the gamma values 430 * in the RRCrtcRec 431 */ 432 433Bool 434RRCrtcGammaNotify (RRCrtcPtr crtc) 435{ 436 return TRUE; /* not much going on here */ 437} 438 439/** 440 * Returns the width/height that the crtc scans out from the framebuffer 441 */ 442void 443RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height) 444{ 445 if (crtc->mode == NULL) { 446 *width = 0; 447 *height = 0; 448 return; 449 } 450 451 switch (crtc->rotation & 0xf) { 452 case RR_Rotate_0: 453 case RR_Rotate_180: 454 *width = crtc->mode->mode.width; 455 *height = crtc->mode->mode.height; 456 break; 457 case RR_Rotate_90: 458 case RR_Rotate_270: 459 *width = crtc->mode->mode.height; 460 *height = crtc->mode->mode.width; 461 break; 462 } 463} 464 465/* 466 * Set the size of the gamma table at server startup time 467 */ 468 469Bool 470RRCrtcGammaSetSize (RRCrtcPtr crtc, 471 int size) 472{ 473 CARD16 *gamma; 474 475 if (size == crtc->gammaSize) 476 return TRUE; 477 if (size) 478 { 479 gamma = xalloc (size * 3 * sizeof (CARD16)); 480 if (!gamma) 481 return FALSE; 482 } 483 else 484 gamma = NULL; 485 if (crtc->gammaRed) 486 xfree (crtc->gammaRed); 487 crtc->gammaRed = gamma; 488 crtc->gammaGreen = gamma + size; 489 crtc->gammaBlue = gamma + size*2; 490 crtc->gammaSize = size; 491 return TRUE; 492} 493 494/* 495 * Initialize crtc type 496 */ 497Bool 498RRCrtcInit (void) 499{ 500 RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource); 501 if (!RRCrtcType) 502 return FALSE; 503#ifdef XResExtension 504 RegisterResourceName (RRCrtcType, "CRTC"); 505#endif 506 return TRUE; 507} 508 509int 510ProcRRGetCrtcInfo (ClientPtr client) 511{ 512 REQUEST(xRRGetCrtcInfoReq); 513 xRRGetCrtcInfoReply rep; 514 RRCrtcPtr crtc; 515 CARD8 *extra; 516 unsigned long extraLen; 517 ScreenPtr pScreen; 518 rrScrPrivPtr pScrPriv; 519 RRModePtr mode; 520 RROutput *outputs; 521 RROutput *possible; 522 int i, j, k, n; 523 int width, height; 524 525 REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); 526 crtc = LookupCrtc(client, stuff->crtc, DixReadAccess); 527 528 if (!crtc) 529 return RRErrorBase + BadRRCrtc; 530 531 /* All crtcs must be associated with screens before client 532 * requests are processed 533 */ 534 pScreen = crtc->pScreen; 535 pScrPriv = rrGetScrPriv(pScreen); 536 537 mode = crtc->mode; 538 539 rep.type = X_Reply; 540 rep.status = RRSetConfigSuccess; 541 rep.sequenceNumber = client->sequence; 542 rep.length = 0; 543 rep.timestamp = pScrPriv->lastSetTime.milliseconds; 544 rep.x = crtc->x; 545 rep.y = crtc->y; 546 RRCrtcGetScanoutSize (crtc, &width, &height); 547 rep.width = width; 548 rep.height = height; 549 rep.mode = mode ? mode->mode.id : 0; 550 rep.rotation = crtc->rotation; 551 rep.rotations = crtc->rotations; 552 rep.nOutput = crtc->numOutputs; 553 k = 0; 554 for (i = 0; i < pScrPriv->numOutputs; i++) 555 for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) 556 if (pScrPriv->outputs[i]->crtcs[j] == crtc) 557 k++; 558 rep.nPossibleOutput = k; 559 560 rep.length = rep.nOutput + rep.nPossibleOutput; 561 562 extraLen = rep.length << 2; 563 if (extraLen) 564 { 565 extra = xalloc (extraLen); 566 if (!extra) 567 return BadAlloc; 568 } 569 else 570 extra = NULL; 571 572 outputs = (RROutput *) extra; 573 possible = (RROutput *) (outputs + rep.nOutput); 574 575 for (i = 0; i < crtc->numOutputs; i++) 576 { 577 outputs[i] = crtc->outputs[i]->id; 578 if (client->swapped) 579 swapl (&outputs[i], n); 580 } 581 k = 0; 582 for (i = 0; i < pScrPriv->numOutputs; i++) 583 for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) 584 if (pScrPriv->outputs[i]->crtcs[j] == crtc) 585 { 586 possible[k] = pScrPriv->outputs[i]->id; 587 if (client->swapped) 588 swapl (&possible[k], n); 589 k++; 590 } 591 592 if (client->swapped) { 593 swaps(&rep.sequenceNumber, n); 594 swapl(&rep.length, n); 595 swapl(&rep.timestamp, n); 596 swaps(&rep.x, n); 597 swaps(&rep.y, n); 598 swaps(&rep.width, n); 599 swaps(&rep.height, n); 600 swapl(&rep.mode, n); 601 swaps(&rep.rotation, n); 602 swaps(&rep.rotations, n); 603 swaps(&rep.nOutput, n); 604 swaps(&rep.nPossibleOutput, n); 605 } 606 WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep); 607 if (extraLen) 608 { 609 WriteToClient (client, extraLen, (char *) extra); 610 xfree (extra); 611 } 612 613 return client->noClientException; 614} 615 616int 617ProcRRSetCrtcConfig (ClientPtr client) 618{ 619 REQUEST(xRRSetCrtcConfigReq); 620 xRRSetCrtcConfigReply rep; 621 ScreenPtr pScreen; 622 rrScrPrivPtr pScrPriv; 623 RRCrtcPtr crtc; 624 RRModePtr mode; 625 int numOutputs; 626 RROutputPtr *outputs = NULL; 627 RROutput *outputIds; 628 TimeStamp configTime; 629 TimeStamp time; 630 Rotation rotation; 631 int i, j; 632 633 REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq); 634 numOutputs = (stuff->length - (SIZEOF (xRRSetCrtcConfigReq) >> 2)); 635 636 crtc = LookupIDByType (stuff->crtc, RRCrtcType); 637 if (!crtc) 638 { 639 client->errorValue = stuff->crtc; 640 return RRErrorBase + BadRRCrtc; 641 } 642 if (stuff->mode == None) 643 { 644 mode = NULL; 645 if (numOutputs > 0) 646 return BadMatch; 647 } 648 else 649 { 650 mode = LookupIDByType (stuff->mode, RRModeType); 651 if (!mode) 652 { 653 client->errorValue = stuff->mode; 654 return RRErrorBase + BadRRMode; 655 } 656 if (numOutputs == 0) 657 return BadMatch; 658 } 659 if (numOutputs) 660 { 661 outputs = xalloc (numOutputs * sizeof (RROutputPtr)); 662 if (!outputs) 663 return BadAlloc; 664 } 665 else 666 outputs = NULL; 667 668 outputIds = (RROutput *) (stuff + 1); 669 for (i = 0; i < numOutputs; i++) 670 { 671 outputs[i] = (RROutputPtr) LookupIDByType (outputIds[i], RROutputType); 672 if (!outputs[i]) 673 { 674 client->errorValue = outputIds[i]; 675 if (outputs) 676 xfree (outputs); 677 return RRErrorBase + BadRROutput; 678 } 679 /* validate crtc for this output */ 680 for (j = 0; j < outputs[i]->numCrtcs; j++) 681 if (outputs[i]->crtcs[j] == crtc) 682 break; 683 if (j == outputs[i]->numCrtcs) 684 { 685 if (outputs) 686 xfree (outputs); 687 return BadMatch; 688 } 689 /* validate mode for this output */ 690 for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++) 691 { 692 RRModePtr m = (j < outputs[i]->numModes ? 693 outputs[i]->modes[j] : 694 outputs[i]->userModes[j - outputs[i]->numModes]); 695 if (m == mode) 696 break; 697 } 698 if (j == outputs[i]->numModes + outputs[i]->numUserModes) 699 { 700 if (outputs) 701 xfree (outputs); 702 return BadMatch; 703 } 704 } 705 /* validate clones */ 706 for (i = 0; i < numOutputs; i++) 707 { 708 for (j = 0; j < numOutputs; j++) 709 { 710 int k; 711 if (i == j) 712 continue; 713 for (k = 0; k < outputs[i]->numClones; k++) 714 { 715 if (outputs[i]->clones[k] == outputs[j]) 716 break; 717 } 718 if (k == outputs[i]->numClones) 719 { 720 if (outputs) 721 xfree (outputs); 722 return BadMatch; 723 } 724 } 725 } 726 727 pScreen = crtc->pScreen; 728 pScrPriv = rrGetScrPriv(pScreen); 729 730 time = ClientTimeToServerTime(stuff->timestamp); 731 configTime = ClientTimeToServerTime(stuff->configTimestamp); 732 733 if (!pScrPriv) 734 { 735 time = currentTime; 736 rep.status = RRSetConfigFailed; 737 goto sendReply; 738 } 739 740#if 0 741 /* 742 * if the client's config timestamp is not the same as the last config 743 * timestamp, then the config information isn't up-to-date and 744 * can't even be validated 745 */ 746 if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0) 747 { 748 rep.status = RRSetConfigInvalidConfigTime; 749 goto sendReply; 750 } 751#endif 752 753 /* 754 * Validate requested rotation 755 */ 756 rotation = (Rotation) stuff->rotation; 757 758 /* test the rotation bits only! */ 759 switch (rotation & 0xf) { 760 case RR_Rotate_0: 761 case RR_Rotate_90: 762 case RR_Rotate_180: 763 case RR_Rotate_270: 764 break; 765 default: 766 /* 767 * Invalid rotation 768 */ 769 client->errorValue = stuff->rotation; 770 if (outputs) 771 xfree (outputs); 772 return BadValue; 773 } 774 775 if (mode) 776 { 777 if ((~crtc->rotations) & rotation) 778 { 779 /* 780 * requested rotation or reflection not supported by screen 781 */ 782 client->errorValue = stuff->rotation; 783 if (outputs) 784 xfree (outputs); 785 return BadMatch; 786 } 787 788#ifdef RANDR_12_INTERFACE 789 /* 790 * Check screen size bounds if the DDX provides a 1.2 interface 791 * for setting screen size. Else, assume the CrtcSet sets 792 * the size along with the mode 793 */ 794 if (pScrPriv->rrScreenSetSize) 795 { 796 int source_width = mode->mode.width; 797 int source_height = mode->mode.height; 798 799 if ((rotation & 0xf) == RR_Rotate_90 || (rotation & 0xf) == RR_Rotate_270) 800 { 801 source_width = mode->mode.height; 802 source_height = mode->mode.width; 803 } 804 if (stuff->x + source_width > pScreen->width) 805 { 806 client->errorValue = stuff->x; 807 if (outputs) 808 xfree (outputs); 809 return BadValue; 810 } 811 812 if (stuff->y + source_height > pScreen->height) 813 { 814 client->errorValue = stuff->y; 815 if (outputs) 816 xfree (outputs); 817 return BadValue; 818 } 819 } 820#endif 821 } 822 823 /* 824 * Make sure the requested set-time is not older than 825 * the last set-time 826 */ 827 if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) 828 { 829 rep.status = RRSetConfigInvalidTime; 830 goto sendReply; 831 } 832 833 if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y, 834 rotation, numOutputs, outputs)) 835 { 836 rep.status = RRSetConfigFailed; 837 goto sendReply; 838 } 839 rep.status = RRSetConfigSuccess; 840 841sendReply: 842 if (outputs) 843 xfree (outputs); 844 845 rep.type = X_Reply; 846 /* rep.status has already been filled in */ 847 rep.length = 0; 848 rep.sequenceNumber = client->sequence; 849 rep.newTimestamp = pScrPriv->lastConfigTime.milliseconds; 850 851 if (client->swapped) 852 { 853 int n; 854 swaps(&rep.sequenceNumber, n); 855 swapl(&rep.length, n); 856 swapl(&rep.newTimestamp, n); 857 } 858 WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep); 859 860 return client->noClientException; 861} 862 863int 864ProcRRGetCrtcGammaSize (ClientPtr client) 865{ 866 REQUEST(xRRGetCrtcGammaSizeReq); 867 xRRGetCrtcGammaSizeReply reply; 868 RRCrtcPtr crtc; 869 int n; 870 871 REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq); 872 crtc = LookupCrtc (client, stuff->crtc, DixReadAccess); 873 if (!crtc) 874 return RRErrorBase + BadRRCrtc; 875 876 reply.type = X_Reply; 877 reply.sequenceNumber = client->sequence; 878 reply.length = 0; 879 reply.size = crtc->gammaSize; 880 if (client->swapped) { 881 swaps (&reply.sequenceNumber, n); 882 swapl (&reply.length, n); 883 swaps (&reply.size, n); 884 } 885 WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply); 886 return client->noClientException; 887} 888 889int 890ProcRRGetCrtcGamma (ClientPtr client) 891{ 892 REQUEST(xRRGetCrtcGammaReq); 893 xRRGetCrtcGammaReply reply; 894 RRCrtcPtr crtc; 895 int n; 896 unsigned long len; 897 898 REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq); 899 crtc = LookupCrtc (client, stuff->crtc, DixReadAccess); 900 if (!crtc) 901 return RRErrorBase + BadRRCrtc; 902 903 len = crtc->gammaSize * 3 * 2; 904 905 reply.type = X_Reply; 906 reply.sequenceNumber = client->sequence; 907 reply.length = (len + 3) >> 2; 908 reply.size = crtc->gammaSize; 909 if (client->swapped) { 910 swaps (&reply.sequenceNumber, n); 911 swapl (&reply.length, n); 912 swaps (&reply.size, n); 913 } 914 WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply); 915 if (crtc->gammaSize) 916 { 917 client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; 918 WriteSwappedDataToClient (client, len, (char *) crtc->gammaRed); 919 } 920 return client->noClientException; 921} 922 923int 924ProcRRSetCrtcGamma (ClientPtr client) 925{ 926 REQUEST(xRRSetCrtcGammaReq); 927 RRCrtcPtr crtc; 928 unsigned long len; 929 CARD16 *red, *green, *blue; 930 931 REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq); 932 crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess); 933 if (!crtc) 934 return RRErrorBase + BadRRCrtc; 935 936 len = client->req_len - (sizeof (xRRSetCrtcGammaReq) >> 2); 937 if (len < (stuff->size * 3 + 1) >> 1) 938 return BadLength; 939 940 if (stuff->size != crtc->gammaSize) 941 return BadMatch; 942 943 red = (CARD16 *) (stuff + 1); 944 green = red + crtc->gammaSize; 945 blue = green + crtc->gammaSize; 946 947 RRCrtcGammaSet (crtc, red, green, blue); 948 949 return Success; 950} 951 952