1706f2543Smrg/* 2706f2543Smrg * Copyright © 2006 Keith Packard 3706f2543Smrg * 4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 6706f2543Smrg * the above copyright notice appear in all copies and that both that copyright 7706f2543Smrg * notice and this permission notice appear in supporting documentation, and 8706f2543Smrg * that the name of the copyright holders not be used in advertising or 9706f2543Smrg * publicity pertaining to distribution of the software without specific, 10706f2543Smrg * written prior permission. The copyright holders make no representations 11706f2543Smrg * about the suitability of this software for any purpose. It is provided "as 12706f2543Smrg * is" without express or implied warranty. 13706f2543Smrg * 14706f2543Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16706f2543Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20706f2543Smrg * OF THIS SOFTWARE. 21706f2543Smrg */ 22706f2543Smrg 23706f2543Smrg#include "randrstr.h" 24706f2543Smrg#include "swaprep.h" 25706f2543Smrg 26706f2543SmrgRESTYPE RRCrtcType; 27706f2543Smrg 28706f2543Smrg/* 29706f2543Smrg * Notify the CRTC of some change 30706f2543Smrg */ 31706f2543Smrgvoid 32706f2543SmrgRRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged) 33706f2543Smrg{ 34706f2543Smrg ScreenPtr pScreen = crtc->pScreen; 35706f2543Smrg 36706f2543Smrg crtc->changed = TRUE; 37706f2543Smrg if (pScreen) 38706f2543Smrg { 39706f2543Smrg rrScrPriv(pScreen); 40706f2543Smrg 41706f2543Smrg pScrPriv->changed = TRUE; 42706f2543Smrg /* 43706f2543Smrg * Send ConfigureNotify on any layout change 44706f2543Smrg */ 45706f2543Smrg if (layoutChanged) 46706f2543Smrg pScrPriv->layoutChanged = TRUE; 47706f2543Smrg } 48706f2543Smrg} 49706f2543Smrg 50706f2543Smrg/* 51706f2543Smrg * Create a CRTC 52706f2543Smrg */ 53706f2543SmrgRRCrtcPtr 54706f2543SmrgRRCrtcCreate (ScreenPtr pScreen, void *devPrivate) 55706f2543Smrg{ 56706f2543Smrg RRCrtcPtr crtc; 57706f2543Smrg RRCrtcPtr *crtcs; 58706f2543Smrg rrScrPrivPtr pScrPriv; 59706f2543Smrg 60706f2543Smrg if (!RRInit()) 61706f2543Smrg return NULL; 62706f2543Smrg 63706f2543Smrg pScrPriv = rrGetScrPriv(pScreen); 64706f2543Smrg 65706f2543Smrg /* make space for the crtc pointer */ 66706f2543Smrg if (pScrPriv->numCrtcs) 67706f2543Smrg crtcs = realloc(pScrPriv->crtcs, 68706f2543Smrg (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr)); 69706f2543Smrg else 70706f2543Smrg crtcs = malloc(sizeof (RRCrtcPtr)); 71706f2543Smrg if (!crtcs) 72706f2543Smrg return FALSE; 73706f2543Smrg pScrPriv->crtcs = crtcs; 74706f2543Smrg 75706f2543Smrg crtc = calloc(1, sizeof (RRCrtcRec)); 76706f2543Smrg if (!crtc) 77706f2543Smrg return NULL; 78706f2543Smrg crtc->id = FakeClientID (0); 79706f2543Smrg crtc->pScreen = pScreen; 80706f2543Smrg crtc->mode = NULL; 81706f2543Smrg crtc->x = 0; 82706f2543Smrg crtc->y = 0; 83706f2543Smrg crtc->rotation = RR_Rotate_0; 84706f2543Smrg crtc->rotations = RR_Rotate_0; 85706f2543Smrg crtc->outputs = NULL; 86706f2543Smrg crtc->numOutputs = 0; 87706f2543Smrg crtc->gammaSize = 0; 88706f2543Smrg crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL; 89706f2543Smrg crtc->changed = FALSE; 90706f2543Smrg crtc->devPrivate = devPrivate; 91706f2543Smrg RRTransformInit (&crtc->client_pending_transform); 92706f2543Smrg RRTransformInit (&crtc->client_current_transform); 93706f2543Smrg pixman_transform_init_identity (&crtc->transform); 94706f2543Smrg pixman_f_transform_init_identity (&crtc->f_transform); 95706f2543Smrg pixman_f_transform_init_identity (&crtc->f_inverse); 96706f2543Smrg 97706f2543Smrg if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc)) 98706f2543Smrg return NULL; 99706f2543Smrg 100706f2543Smrg /* attach the screen and crtc together */ 101706f2543Smrg crtc->pScreen = pScreen; 102706f2543Smrg pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc; 103706f2543Smrg 104706f2543Smrg return crtc; 105706f2543Smrg} 106706f2543Smrg 107706f2543Smrg/* 108706f2543Smrg * Set the allowed rotations on a CRTC 109706f2543Smrg */ 110706f2543Smrgvoid 111706f2543SmrgRRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations) 112706f2543Smrg{ 113706f2543Smrg crtc->rotations = rotations; 114706f2543Smrg} 115706f2543Smrg 116706f2543Smrg/* 117706f2543Smrg * Set whether transforms are allowed on a CRTC 118706f2543Smrg */ 119706f2543Smrgvoid 120706f2543SmrgRRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms) 121706f2543Smrg{ 122706f2543Smrg crtc->transforms = transforms; 123706f2543Smrg} 124706f2543Smrg 125706f2543Smrg/* 126706f2543Smrg * Notify the extension that the Crtc has been reconfigured, 127706f2543Smrg * the driver calls this whenever it has updated the mode 128706f2543Smrg */ 129706f2543SmrgBool 130706f2543SmrgRRCrtcNotify (RRCrtcPtr crtc, 131706f2543Smrg RRModePtr mode, 132706f2543Smrg int x, 133706f2543Smrg int y, 134706f2543Smrg Rotation rotation, 135706f2543Smrg RRTransformPtr transform, 136706f2543Smrg int numOutputs, 137706f2543Smrg RROutputPtr *outputs) 138706f2543Smrg{ 139706f2543Smrg int i, j; 140706f2543Smrg 141706f2543Smrg /* 142706f2543Smrg * Check to see if any of the new outputs were 143706f2543Smrg * not in the old list and mark them as changed 144706f2543Smrg */ 145706f2543Smrg for (i = 0; i < numOutputs; i++) 146706f2543Smrg { 147706f2543Smrg for (j = 0; j < crtc->numOutputs; j++) 148706f2543Smrg if (outputs[i] == crtc->outputs[j]) 149706f2543Smrg break; 150706f2543Smrg if (j == crtc->numOutputs) 151706f2543Smrg { 152706f2543Smrg outputs[i]->crtc = crtc; 153706f2543Smrg RROutputChanged (outputs[i], FALSE); 154706f2543Smrg RRCrtcChanged (crtc, FALSE); 155706f2543Smrg } 156706f2543Smrg } 157706f2543Smrg /* 158706f2543Smrg * Check to see if any of the old outputs are 159706f2543Smrg * not in the new list and mark them as changed 160706f2543Smrg */ 161706f2543Smrg for (j = 0; j < crtc->numOutputs; j++) 162706f2543Smrg { 163706f2543Smrg for (i = 0; i < numOutputs; i++) 164706f2543Smrg if (outputs[i] == crtc->outputs[j]) 165706f2543Smrg break; 166706f2543Smrg if (i == numOutputs) 167706f2543Smrg { 168706f2543Smrg if (crtc->outputs[j]->crtc == crtc) 169706f2543Smrg crtc->outputs[j]->crtc = NULL; 170706f2543Smrg RROutputChanged (crtc->outputs[j], FALSE); 171706f2543Smrg RRCrtcChanged (crtc, FALSE); 172706f2543Smrg } 173706f2543Smrg } 174706f2543Smrg /* 175706f2543Smrg * Reallocate the crtc output array if necessary 176706f2543Smrg */ 177706f2543Smrg if (numOutputs != crtc->numOutputs) 178706f2543Smrg { 179706f2543Smrg RROutputPtr *newoutputs; 180706f2543Smrg 181706f2543Smrg if (numOutputs) 182706f2543Smrg { 183706f2543Smrg if (crtc->numOutputs) 184706f2543Smrg newoutputs = realloc(crtc->outputs, 185706f2543Smrg numOutputs * sizeof (RROutputPtr)); 186706f2543Smrg else 187706f2543Smrg newoutputs = malloc(numOutputs * sizeof (RROutputPtr)); 188706f2543Smrg if (!newoutputs) 189706f2543Smrg return FALSE; 190706f2543Smrg } 191706f2543Smrg else 192706f2543Smrg { 193706f2543Smrg free(crtc->outputs); 194706f2543Smrg newoutputs = NULL; 195706f2543Smrg } 196706f2543Smrg crtc->outputs = newoutputs; 197706f2543Smrg crtc->numOutputs = numOutputs; 198706f2543Smrg } 199706f2543Smrg /* 200706f2543Smrg * Copy the new list of outputs into the crtc 201706f2543Smrg */ 202706f2543Smrg memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)); 203706f2543Smrg /* 204706f2543Smrg * Update remaining crtc fields 205706f2543Smrg */ 206706f2543Smrg if (mode != crtc->mode) 207706f2543Smrg { 208706f2543Smrg if (crtc->mode) 209706f2543Smrg RRModeDestroy (crtc->mode); 210706f2543Smrg crtc->mode = mode; 211706f2543Smrg if (mode != NULL) 212706f2543Smrg mode->refcnt++; 213706f2543Smrg RRCrtcChanged (crtc, TRUE); 214706f2543Smrg } 215706f2543Smrg if (x != crtc->x) 216706f2543Smrg { 217706f2543Smrg crtc->x = x; 218706f2543Smrg RRCrtcChanged (crtc, TRUE); 219706f2543Smrg } 220706f2543Smrg if (y != crtc->y) 221706f2543Smrg { 222706f2543Smrg crtc->y = y; 223706f2543Smrg RRCrtcChanged (crtc, TRUE); 224706f2543Smrg } 225706f2543Smrg if (rotation != crtc->rotation) 226706f2543Smrg { 227706f2543Smrg crtc->rotation = rotation; 228706f2543Smrg RRCrtcChanged (crtc, TRUE); 229706f2543Smrg } 230706f2543Smrg if (!RRTransformEqual (transform, &crtc->client_current_transform)) { 231706f2543Smrg RRTransformCopy (&crtc->client_current_transform, transform); 232706f2543Smrg RRCrtcChanged (crtc, TRUE); 233706f2543Smrg } 234706f2543Smrg if (crtc->changed && mode) 235706f2543Smrg { 236706f2543Smrg RRTransformCompute (x, y, 237706f2543Smrg mode->mode.width, mode->mode.height, 238706f2543Smrg rotation, 239706f2543Smrg &crtc->client_current_transform, 240706f2543Smrg &crtc->transform, &crtc->f_transform, 241706f2543Smrg &crtc->f_inverse); 242706f2543Smrg } 243706f2543Smrg return TRUE; 244706f2543Smrg} 245706f2543Smrg 246706f2543Smrgvoid 247706f2543SmrgRRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc) 248706f2543Smrg{ 249706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 250706f2543Smrg rrScrPriv (pScreen); 251706f2543Smrg xRRCrtcChangeNotifyEvent ce; 252706f2543Smrg RRModePtr mode = crtc->mode; 253706f2543Smrg 254706f2543Smrg ce.type = RRNotify + RREventBase; 255706f2543Smrg ce.subCode = RRNotify_CrtcChange; 256706f2543Smrg ce.timestamp = pScrPriv->lastSetTime.milliseconds; 257706f2543Smrg ce.window = pWin->drawable.id; 258706f2543Smrg ce.crtc = crtc->id; 259706f2543Smrg ce.rotation = crtc->rotation; 260706f2543Smrg if (mode) 261706f2543Smrg { 262706f2543Smrg ce.mode = mode->mode.id; 263706f2543Smrg ce.x = crtc->x; 264706f2543Smrg ce.y = crtc->y; 265706f2543Smrg ce.width = mode->mode.width; 266706f2543Smrg ce.height = mode->mode.height; 267706f2543Smrg } 268706f2543Smrg else 269706f2543Smrg { 270706f2543Smrg ce.mode = None; 271706f2543Smrg ce.x = 0; 272706f2543Smrg ce.y = 0; 273706f2543Smrg ce.width = 0; 274706f2543Smrg ce.height = 0; 275706f2543Smrg } 276706f2543Smrg WriteEventsToClient (client, 1, (xEvent *) &ce); 277706f2543Smrg} 278706f2543Smrg 279706f2543Smrgstatic Bool 280706f2543SmrgRRCrtcPendingProperties (RRCrtcPtr crtc) 281706f2543Smrg{ 282706f2543Smrg ScreenPtr pScreen = crtc->pScreen; 283706f2543Smrg rrScrPriv(pScreen); 284706f2543Smrg int o; 285706f2543Smrg 286706f2543Smrg for (o = 0; o < pScrPriv->numOutputs; o++) 287706f2543Smrg { 288706f2543Smrg RROutputPtr output = pScrPriv->outputs[o]; 289706f2543Smrg if (output->crtc == crtc && output->pendingProperties) 290706f2543Smrg return TRUE; 291706f2543Smrg } 292706f2543Smrg return FALSE; 293706f2543Smrg} 294706f2543Smrg 295706f2543Smrg/* 296706f2543Smrg * Request that the Crtc be reconfigured 297706f2543Smrg */ 298706f2543SmrgBool 299706f2543SmrgRRCrtcSet (RRCrtcPtr crtc, 300706f2543Smrg RRModePtr mode, 301706f2543Smrg int x, 302706f2543Smrg int y, 303706f2543Smrg Rotation rotation, 304706f2543Smrg int numOutputs, 305706f2543Smrg RROutputPtr *outputs) 306706f2543Smrg{ 307706f2543Smrg ScreenPtr pScreen = crtc->pScreen; 308706f2543Smrg Bool ret = FALSE; 309706f2543Smrg rrScrPriv(pScreen); 310706f2543Smrg 311706f2543Smrg /* See if nothing changed */ 312706f2543Smrg if (crtc->mode == mode && 313706f2543Smrg crtc->x == x && 314706f2543Smrg crtc->y == y && 315706f2543Smrg crtc->rotation == rotation && 316706f2543Smrg crtc->numOutputs == numOutputs && 317706f2543Smrg !memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) && 318706f2543Smrg !RRCrtcPendingProperties (crtc) && 319706f2543Smrg !RRCrtcPendingTransform (crtc)) 320706f2543Smrg { 321706f2543Smrg ret = TRUE; 322706f2543Smrg } 323706f2543Smrg else 324706f2543Smrg { 325706f2543Smrg#if RANDR_12_INTERFACE 326706f2543Smrg if (pScrPriv->rrCrtcSet) 327706f2543Smrg { 328706f2543Smrg ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, 329706f2543Smrg rotation, numOutputs, outputs); 330706f2543Smrg } 331706f2543Smrg else 332706f2543Smrg#endif 333706f2543Smrg { 334706f2543Smrg#if RANDR_10_INTERFACE 335706f2543Smrg if (pScrPriv->rrSetConfig) 336706f2543Smrg { 337706f2543Smrg RRScreenSize size; 338706f2543Smrg RRScreenRate rate; 339706f2543Smrg 340706f2543Smrg if (!mode) 341706f2543Smrg { 342706f2543Smrg RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL); 343706f2543Smrg ret = TRUE; 344706f2543Smrg } 345706f2543Smrg else 346706f2543Smrg { 347706f2543Smrg size.width = mode->mode.width; 348706f2543Smrg size.height = mode->mode.height; 349706f2543Smrg if (outputs[0]->mmWidth && outputs[0]->mmHeight) 350706f2543Smrg { 351706f2543Smrg size.mmWidth = outputs[0]->mmWidth; 352706f2543Smrg size.mmHeight = outputs[0]->mmHeight; 353706f2543Smrg } 354706f2543Smrg else 355706f2543Smrg { 356706f2543Smrg size.mmWidth = pScreen->mmWidth; 357706f2543Smrg size.mmHeight = pScreen->mmHeight; 358706f2543Smrg } 359706f2543Smrg size.nRates = 1; 360706f2543Smrg rate.rate = RRVerticalRefresh (&mode->mode); 361706f2543Smrg size.pRates = &rate; 362706f2543Smrg ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size); 363706f2543Smrg /* 364706f2543Smrg * Old 1.0 interface tied screen size to mode size 365706f2543Smrg */ 366706f2543Smrg if (ret) 367706f2543Smrg { 368706f2543Smrg RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs); 369706f2543Smrg RRScreenSizeNotify (pScreen); 370706f2543Smrg } 371706f2543Smrg } 372706f2543Smrg } 373706f2543Smrg#endif 374706f2543Smrg } 375706f2543Smrg if (ret) 376706f2543Smrg { 377706f2543Smrg int o; 378706f2543Smrg RRTellChanged (pScreen); 379706f2543Smrg 380706f2543Smrg for (o = 0; o < numOutputs; o++) 381706f2543Smrg RRPostPendingProperties (outputs[o]); 382706f2543Smrg } 383706f2543Smrg } 384706f2543Smrg return ret; 385706f2543Smrg} 386706f2543Smrg 387706f2543Smrg/* 388706f2543Smrg * Return crtc transform 389706f2543Smrg */ 390706f2543SmrgRRTransformPtr 391706f2543SmrgRRCrtcGetTransform (RRCrtcPtr crtc) 392706f2543Smrg{ 393706f2543Smrg RRTransformPtr transform = &crtc->client_pending_transform; 394706f2543Smrg 395706f2543Smrg if (pixman_transform_is_identity (&transform->transform)) 396706f2543Smrg return NULL; 397706f2543Smrg return transform; 398706f2543Smrg} 399706f2543Smrg 400706f2543Smrg/* 401706f2543Smrg * Check whether the pending and current transforms are the same 402706f2543Smrg */ 403706f2543SmrgBool 404706f2543SmrgRRCrtcPendingTransform (RRCrtcPtr crtc) 405706f2543Smrg{ 406706f2543Smrg return memcmp (&crtc->client_current_transform.transform, 407706f2543Smrg &crtc->client_pending_transform.transform, 408706f2543Smrg sizeof (PictTransform)) != 0; 409706f2543Smrg} 410706f2543Smrg 411706f2543Smrg/* 412706f2543Smrg * Destroy a Crtc at shutdown 413706f2543Smrg */ 414706f2543Smrgvoid 415706f2543SmrgRRCrtcDestroy (RRCrtcPtr crtc) 416706f2543Smrg{ 417706f2543Smrg FreeResource (crtc->id, 0); 418706f2543Smrg} 419706f2543Smrg 420706f2543Smrgstatic int 421706f2543SmrgRRCrtcDestroyResource (pointer value, XID pid) 422706f2543Smrg{ 423706f2543Smrg RRCrtcPtr crtc = (RRCrtcPtr) value; 424706f2543Smrg ScreenPtr pScreen = crtc->pScreen; 425706f2543Smrg 426706f2543Smrg if (pScreen) 427706f2543Smrg { 428706f2543Smrg rrScrPriv(pScreen); 429706f2543Smrg int i; 430706f2543Smrg 431706f2543Smrg for (i = 0; i < pScrPriv->numCrtcs; i++) 432706f2543Smrg { 433706f2543Smrg if (pScrPriv->crtcs[i] == crtc) 434706f2543Smrg { 435706f2543Smrg memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1, 436706f2543Smrg (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr)); 437706f2543Smrg --pScrPriv->numCrtcs; 438706f2543Smrg break; 439706f2543Smrg } 440706f2543Smrg } 441706f2543Smrg } 442706f2543Smrg free(crtc->gammaRed); 443706f2543Smrg if (crtc->mode) 444706f2543Smrg RRModeDestroy (crtc->mode); 445706f2543Smrg free(crtc); 446706f2543Smrg return 1; 447706f2543Smrg} 448706f2543Smrg 449706f2543Smrg/* 450706f2543Smrg * Request that the Crtc gamma be changed 451706f2543Smrg */ 452706f2543Smrg 453706f2543SmrgBool 454706f2543SmrgRRCrtcGammaSet (RRCrtcPtr crtc, 455706f2543Smrg CARD16 *red, 456706f2543Smrg CARD16 *green, 457706f2543Smrg CARD16 *blue) 458706f2543Smrg{ 459706f2543Smrg Bool ret = TRUE; 460706f2543Smrg#if RANDR_12_INTERFACE 461706f2543Smrg ScreenPtr pScreen = crtc->pScreen; 462706f2543Smrg#endif 463706f2543Smrg 464706f2543Smrg memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16)); 465706f2543Smrg memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16)); 466706f2543Smrg memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16)); 467706f2543Smrg#if RANDR_12_INTERFACE 468706f2543Smrg if (pScreen) 469706f2543Smrg { 470706f2543Smrg rrScrPriv(pScreen); 471706f2543Smrg if (pScrPriv->rrCrtcSetGamma) 472706f2543Smrg ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc); 473706f2543Smrg } 474706f2543Smrg#endif 475706f2543Smrg return ret; 476706f2543Smrg} 477706f2543Smrg 478706f2543Smrg/* 479706f2543Smrg * Request current gamma back from the DDX (if possible). 480706f2543Smrg * This includes gamma size. 481706f2543Smrg */ 482706f2543SmrgBool 483706f2543SmrgRRCrtcGammaGet(RRCrtcPtr crtc) 484706f2543Smrg{ 485706f2543Smrg Bool ret = TRUE; 486706f2543Smrg#if RANDR_12_INTERFACE 487706f2543Smrg ScreenPtr pScreen = crtc->pScreen; 488706f2543Smrg#endif 489706f2543Smrg 490706f2543Smrg#if RANDR_12_INTERFACE 491706f2543Smrg if (pScreen) 492706f2543Smrg { 493706f2543Smrg rrScrPriv(pScreen); 494706f2543Smrg if (pScrPriv->rrCrtcGetGamma) 495706f2543Smrg ret = (*pScrPriv->rrCrtcGetGamma) (pScreen, crtc); 496706f2543Smrg } 497706f2543Smrg#endif 498706f2543Smrg return ret; 499706f2543Smrg} 500706f2543Smrg 501706f2543Smrg/* 502706f2543Smrg * Notify the extension that the Crtc gamma has been changed 503706f2543Smrg * The driver calls this whenever it has changed the gamma values 504706f2543Smrg * in the RRCrtcRec 505706f2543Smrg */ 506706f2543Smrg 507706f2543SmrgBool 508706f2543SmrgRRCrtcGammaNotify (RRCrtcPtr crtc) 509706f2543Smrg{ 510706f2543Smrg return TRUE; /* not much going on here */ 511706f2543Smrg} 512706f2543Smrg 513706f2543Smrgstatic void 514706f2543SmrgRRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform, 515706f2543Smrg int *width, int *height) 516706f2543Smrg{ 517706f2543Smrg BoxRec box; 518706f2543Smrg 519706f2543Smrg if (mode == NULL) { 520706f2543Smrg *width = 0; 521706f2543Smrg *height = 0; 522706f2543Smrg return; 523706f2543Smrg } 524706f2543Smrg 525706f2543Smrg box.x1 = 0; 526706f2543Smrg box.y1 = 0; 527706f2543Smrg box.x2 = mode->mode.width; 528706f2543Smrg box.y2 = mode->mode.height; 529706f2543Smrg 530706f2543Smrg pixman_transform_bounds (transform, &box); 531706f2543Smrg *width = box.x2 - box.x1; 532706f2543Smrg *height = box.y2 - box.y1; 533706f2543Smrg} 534706f2543Smrg 535706f2543Smrg/** 536706f2543Smrg * Returns the width/height that the crtc scans out from the framebuffer 537706f2543Smrg */ 538706f2543Smrgvoid 539706f2543SmrgRRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height) 540706f2543Smrg{ 541706f2543Smrg RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height); 542706f2543Smrg} 543706f2543Smrg 544706f2543Smrg/* 545706f2543Smrg * Set the size of the gamma table at server startup time 546706f2543Smrg */ 547706f2543Smrg 548706f2543SmrgBool 549706f2543SmrgRRCrtcGammaSetSize (RRCrtcPtr crtc, 550706f2543Smrg int size) 551706f2543Smrg{ 552706f2543Smrg CARD16 *gamma; 553706f2543Smrg 554706f2543Smrg if (size == crtc->gammaSize) 555706f2543Smrg return TRUE; 556706f2543Smrg if (size) 557706f2543Smrg { 558706f2543Smrg gamma = malloc(size * 3 * sizeof (CARD16)); 559706f2543Smrg if (!gamma) 560706f2543Smrg return FALSE; 561706f2543Smrg } 562706f2543Smrg else 563706f2543Smrg gamma = NULL; 564706f2543Smrg free(crtc->gammaRed); 565706f2543Smrg crtc->gammaRed = gamma; 566706f2543Smrg crtc->gammaGreen = gamma + size; 567706f2543Smrg crtc->gammaBlue = gamma + size*2; 568706f2543Smrg crtc->gammaSize = size; 569706f2543Smrg return TRUE; 570706f2543Smrg} 571706f2543Smrg 572706f2543Smrg/* 573706f2543Smrg * Set the pending CRTC transformation 574706f2543Smrg */ 575706f2543Smrg 576706f2543Smrgint 577706f2543SmrgRRCrtcTransformSet (RRCrtcPtr crtc, 578706f2543Smrg PictTransformPtr transform, 579706f2543Smrg struct pixman_f_transform *f_transform, 580706f2543Smrg struct pixman_f_transform *f_inverse, 581706f2543Smrg char *filter_name, 582706f2543Smrg int filter_len, 583706f2543Smrg xFixed *params, 584706f2543Smrg int nparams) 585706f2543Smrg{ 586706f2543Smrg PictFilterPtr filter = NULL; 587706f2543Smrg int width = 0, height = 0; 588706f2543Smrg 589706f2543Smrg if (!crtc->transforms) 590706f2543Smrg return BadValue; 591706f2543Smrg 592706f2543Smrg if (filter_len) 593706f2543Smrg { 594706f2543Smrg filter = PictureFindFilter (crtc->pScreen, 595706f2543Smrg filter_name, 596706f2543Smrg filter_len); 597706f2543Smrg if (!filter) 598706f2543Smrg return BadName; 599706f2543Smrg if (filter->ValidateParams) 600706f2543Smrg { 601706f2543Smrg if (!filter->ValidateParams (crtc->pScreen, filter->id, 602706f2543Smrg params, nparams, &width, &height)) 603706f2543Smrg return BadMatch; 604706f2543Smrg } 605706f2543Smrg else { 606706f2543Smrg width = filter->width; 607706f2543Smrg height = filter->height; 608706f2543Smrg } 609706f2543Smrg } 610706f2543Smrg else 611706f2543Smrg { 612706f2543Smrg if (nparams) 613706f2543Smrg return BadMatch; 614706f2543Smrg } 615706f2543Smrg if (!RRTransformSetFilter (&crtc->client_pending_transform, 616706f2543Smrg filter, params, nparams, width, height)) 617706f2543Smrg return BadAlloc; 618706f2543Smrg 619706f2543Smrg crtc->client_pending_transform.transform = *transform; 620706f2543Smrg crtc->client_pending_transform.f_transform = *f_transform; 621706f2543Smrg crtc->client_pending_transform.f_inverse = *f_inverse; 622706f2543Smrg return Success; 623706f2543Smrg} 624706f2543Smrg 625706f2543Smrg/* 626706f2543Smrg * Initialize crtc type 627706f2543Smrg */ 628706f2543SmrgBool 629706f2543SmrgRRCrtcInit (void) 630706f2543Smrg{ 631706f2543Smrg RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource, "CRTC"); 632706f2543Smrg if (!RRCrtcType) 633706f2543Smrg return FALSE; 634706f2543Smrg 635706f2543Smrg return TRUE; 636706f2543Smrg} 637706f2543Smrg 638706f2543Smrg/* 639706f2543Smrg * Initialize crtc type error value 640706f2543Smrg */ 641706f2543Smrgvoid 642706f2543SmrgRRCrtcInitErrorValue(void) 643706f2543Smrg{ 644706f2543Smrg SetResourceTypeErrorValue(RRCrtcType, RRErrorBase + BadRRCrtc); 645706f2543Smrg} 646706f2543Smrg 647706f2543Smrgint 648706f2543SmrgProcRRGetCrtcInfo (ClientPtr client) 649706f2543Smrg{ 650706f2543Smrg REQUEST(xRRGetCrtcInfoReq); 651706f2543Smrg xRRGetCrtcInfoReply rep; 652706f2543Smrg RRCrtcPtr crtc; 653706f2543Smrg CARD8 *extra; 654706f2543Smrg unsigned long extraLen; 655706f2543Smrg ScreenPtr pScreen; 656706f2543Smrg rrScrPrivPtr pScrPriv; 657706f2543Smrg RRModePtr mode; 658706f2543Smrg RROutput *outputs; 659706f2543Smrg RROutput *possible; 660706f2543Smrg int i, j, k, n; 661706f2543Smrg int width, height; 662706f2543Smrg BoxRec panned_area; 663706f2543Smrg 664706f2543Smrg REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); 665706f2543Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 666706f2543Smrg 667706f2543Smrg /* All crtcs must be associated with screens before client 668706f2543Smrg * requests are processed 669706f2543Smrg */ 670706f2543Smrg pScreen = crtc->pScreen; 671706f2543Smrg pScrPriv = rrGetScrPriv(pScreen); 672706f2543Smrg 673706f2543Smrg mode = crtc->mode; 674706f2543Smrg 675706f2543Smrg rep.type = X_Reply; 676706f2543Smrg rep.status = RRSetConfigSuccess; 677706f2543Smrg rep.sequenceNumber = client->sequence; 678706f2543Smrg rep.length = 0; 679706f2543Smrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 680706f2543Smrg if (pScrPriv->rrGetPanning && 681706f2543Smrg pScrPriv->rrGetPanning (pScreen, crtc, &panned_area, NULL, NULL) && 682706f2543Smrg (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1)) 683706f2543Smrg { 684706f2543Smrg rep.x = panned_area.x1; 685706f2543Smrg rep.y = panned_area.y1; 686706f2543Smrg rep.width = panned_area.x2 - panned_area.x1; 687706f2543Smrg rep.height = panned_area.y2 - panned_area.y1; 688706f2543Smrg } 689706f2543Smrg else 690706f2543Smrg { 691706f2543Smrg RRCrtcGetScanoutSize (crtc, &width, &height); 692706f2543Smrg rep.x = crtc->x; 693706f2543Smrg rep.y = crtc->y; 694706f2543Smrg rep.width = width; 695706f2543Smrg rep.height = height; 696706f2543Smrg } 697706f2543Smrg rep.mode = mode ? mode->mode.id : 0; 698706f2543Smrg rep.rotation = crtc->rotation; 699706f2543Smrg rep.rotations = crtc->rotations; 700706f2543Smrg rep.nOutput = crtc->numOutputs; 701706f2543Smrg k = 0; 702706f2543Smrg for (i = 0; i < pScrPriv->numOutputs; i++) 703706f2543Smrg for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) 704706f2543Smrg if (pScrPriv->outputs[i]->crtcs[j] == crtc) 705706f2543Smrg k++; 706706f2543Smrg rep.nPossibleOutput = k; 707706f2543Smrg 708706f2543Smrg rep.length = rep.nOutput + rep.nPossibleOutput; 709706f2543Smrg 710706f2543Smrg extraLen = rep.length << 2; 711706f2543Smrg if (extraLen) 712706f2543Smrg { 713706f2543Smrg extra = malloc(extraLen); 714706f2543Smrg if (!extra) 715706f2543Smrg return BadAlloc; 716706f2543Smrg } 717706f2543Smrg else 718706f2543Smrg extra = NULL; 719706f2543Smrg 720706f2543Smrg outputs = (RROutput *) extra; 721706f2543Smrg possible = (RROutput *) (outputs + rep.nOutput); 722706f2543Smrg 723706f2543Smrg for (i = 0; i < crtc->numOutputs; i++) 724706f2543Smrg { 725706f2543Smrg outputs[i] = crtc->outputs[i]->id; 726706f2543Smrg if (client->swapped) 727706f2543Smrg swapl (&outputs[i], n); 728706f2543Smrg } 729706f2543Smrg k = 0; 730706f2543Smrg for (i = 0; i < pScrPriv->numOutputs; i++) 731706f2543Smrg for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) 732706f2543Smrg if (pScrPriv->outputs[i]->crtcs[j] == crtc) 733706f2543Smrg { 734706f2543Smrg possible[k] = pScrPriv->outputs[i]->id; 735706f2543Smrg if (client->swapped) 736706f2543Smrg swapl (&possible[k], n); 737706f2543Smrg k++; 738706f2543Smrg } 739706f2543Smrg 740706f2543Smrg if (client->swapped) { 741706f2543Smrg swaps(&rep.sequenceNumber, n); 742706f2543Smrg swapl(&rep.length, n); 743706f2543Smrg swapl(&rep.timestamp, n); 744706f2543Smrg swaps(&rep.x, n); 745706f2543Smrg swaps(&rep.y, n); 746706f2543Smrg swaps(&rep.width, n); 747706f2543Smrg swaps(&rep.height, n); 748706f2543Smrg swapl(&rep.mode, n); 749706f2543Smrg swaps(&rep.rotation, n); 750706f2543Smrg swaps(&rep.rotations, n); 751706f2543Smrg swaps(&rep.nOutput, n); 752706f2543Smrg swaps(&rep.nPossibleOutput, n); 753706f2543Smrg } 754706f2543Smrg WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep); 755706f2543Smrg if (extraLen) 756706f2543Smrg { 757706f2543Smrg WriteToClient (client, extraLen, (char *) extra); 758706f2543Smrg free(extra); 759706f2543Smrg } 760706f2543Smrg 761706f2543Smrg return Success; 762706f2543Smrg} 763706f2543Smrg 764706f2543Smrgint 765706f2543SmrgProcRRSetCrtcConfig (ClientPtr client) 766706f2543Smrg{ 767706f2543Smrg REQUEST(xRRSetCrtcConfigReq); 768706f2543Smrg xRRSetCrtcConfigReply rep; 769706f2543Smrg ScreenPtr pScreen; 770706f2543Smrg rrScrPrivPtr pScrPriv; 771706f2543Smrg RRCrtcPtr crtc; 772706f2543Smrg RRModePtr mode; 773706f2543Smrg int numOutputs; 774706f2543Smrg RROutputPtr *outputs = NULL; 775706f2543Smrg RROutput *outputIds; 776706f2543Smrg TimeStamp configTime; 777706f2543Smrg TimeStamp time; 778706f2543Smrg Rotation rotation; 779706f2543Smrg int rc, i, j; 780706f2543Smrg 781706f2543Smrg REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq); 782706f2543Smrg numOutputs = (stuff->length - bytes_to_int32(SIZEOF (xRRSetCrtcConfigReq))); 783706f2543Smrg 784706f2543Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess); 785706f2543Smrg 786706f2543Smrg if (stuff->mode == None) 787706f2543Smrg { 788706f2543Smrg mode = NULL; 789706f2543Smrg if (numOutputs > 0) 790706f2543Smrg return BadMatch; 791706f2543Smrg } 792706f2543Smrg else 793706f2543Smrg { 794706f2543Smrg VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess); 795706f2543Smrg if (numOutputs == 0) 796706f2543Smrg return BadMatch; 797706f2543Smrg } 798706f2543Smrg if (numOutputs) 799706f2543Smrg { 800706f2543Smrg outputs = malloc(numOutputs * sizeof (RROutputPtr)); 801706f2543Smrg if (!outputs) 802706f2543Smrg return BadAlloc; 803706f2543Smrg } 804706f2543Smrg else 805706f2543Smrg outputs = NULL; 806706f2543Smrg 807706f2543Smrg outputIds = (RROutput *) (stuff + 1); 808706f2543Smrg for (i = 0; i < numOutputs; i++) 809706f2543Smrg { 810706f2543Smrg rc = dixLookupResourceByType((pointer *)(outputs + i), outputIds[i], 811706f2543Smrg RROutputType, client, DixSetAttrAccess); 812706f2543Smrg if (rc != Success) 813706f2543Smrg { 814706f2543Smrg free(outputs); 815706f2543Smrg return rc; 816706f2543Smrg } 817706f2543Smrg /* validate crtc for this output */ 818706f2543Smrg for (j = 0; j < outputs[i]->numCrtcs; j++) 819706f2543Smrg if (outputs[i]->crtcs[j] == crtc) 820706f2543Smrg break; 821706f2543Smrg if (j == outputs[i]->numCrtcs) 822706f2543Smrg { 823706f2543Smrg free(outputs); 824706f2543Smrg return BadMatch; 825706f2543Smrg } 826706f2543Smrg /* validate mode for this output */ 827706f2543Smrg for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++) 828706f2543Smrg { 829706f2543Smrg RRModePtr m = (j < outputs[i]->numModes ? 830706f2543Smrg outputs[i]->modes[j] : 831706f2543Smrg outputs[i]->userModes[j - outputs[i]->numModes]); 832706f2543Smrg if (m == mode) 833706f2543Smrg break; 834706f2543Smrg } 835706f2543Smrg if (j == outputs[i]->numModes + outputs[i]->numUserModes) 836706f2543Smrg { 837706f2543Smrg free(outputs); 838706f2543Smrg return BadMatch; 839706f2543Smrg } 840706f2543Smrg } 841706f2543Smrg /* validate clones */ 842706f2543Smrg for (i = 0; i < numOutputs; i++) 843706f2543Smrg { 844706f2543Smrg for (j = 0; j < numOutputs; j++) 845706f2543Smrg { 846706f2543Smrg int k; 847706f2543Smrg if (i == j) 848706f2543Smrg continue; 849706f2543Smrg for (k = 0; k < outputs[i]->numClones; k++) 850706f2543Smrg { 851706f2543Smrg if (outputs[i]->clones[k] == outputs[j]) 852706f2543Smrg break; 853706f2543Smrg } 854706f2543Smrg if (k == outputs[i]->numClones) 855706f2543Smrg { 856706f2543Smrg free(outputs); 857706f2543Smrg return BadMatch; 858706f2543Smrg } 859706f2543Smrg } 860706f2543Smrg } 861706f2543Smrg 862706f2543Smrg pScreen = crtc->pScreen; 863706f2543Smrg pScrPriv = rrGetScrPriv(pScreen); 864706f2543Smrg 865706f2543Smrg time = ClientTimeToServerTime(stuff->timestamp); 866706f2543Smrg configTime = ClientTimeToServerTime(stuff->configTimestamp); 867706f2543Smrg 868706f2543Smrg if (!pScrPriv) 869706f2543Smrg { 870706f2543Smrg time = currentTime; 871706f2543Smrg rep.status = RRSetConfigFailed; 872706f2543Smrg goto sendReply; 873706f2543Smrg } 874706f2543Smrg 875706f2543Smrg /* 876706f2543Smrg * Validate requested rotation 877706f2543Smrg */ 878706f2543Smrg rotation = (Rotation) stuff->rotation; 879706f2543Smrg 880706f2543Smrg /* test the rotation bits only! */ 881706f2543Smrg switch (rotation & 0xf) { 882706f2543Smrg case RR_Rotate_0: 883706f2543Smrg case RR_Rotate_90: 884706f2543Smrg case RR_Rotate_180: 885706f2543Smrg case RR_Rotate_270: 886706f2543Smrg break; 887706f2543Smrg default: 888706f2543Smrg /* 889706f2543Smrg * Invalid rotation 890706f2543Smrg */ 891706f2543Smrg client->errorValue = stuff->rotation; 892706f2543Smrg free(outputs); 893706f2543Smrg return BadValue; 894706f2543Smrg } 895706f2543Smrg 896706f2543Smrg if (mode) 897706f2543Smrg { 898706f2543Smrg if ((~crtc->rotations) & rotation) 899706f2543Smrg { 900706f2543Smrg /* 901706f2543Smrg * requested rotation or reflection not supported by screen 902706f2543Smrg */ 903706f2543Smrg client->errorValue = stuff->rotation; 904706f2543Smrg free(outputs); 905706f2543Smrg return BadMatch; 906706f2543Smrg } 907706f2543Smrg 908706f2543Smrg#ifdef RANDR_12_INTERFACE 909706f2543Smrg /* 910706f2543Smrg * Check screen size bounds if the DDX provides a 1.2 interface 911706f2543Smrg * for setting screen size. Else, assume the CrtcSet sets 912706f2543Smrg * the size along with the mode. If the driver supports transforms, 913706f2543Smrg * then it must allow crtcs to display a subset of the screen, so 914706f2543Smrg * only do this check for drivers without transform support. 915706f2543Smrg */ 916706f2543Smrg if (pScrPriv->rrScreenSetSize && !crtc->transforms) 917706f2543Smrg { 918706f2543Smrg int source_width; 919706f2543Smrg int source_height; 920706f2543Smrg PictTransform transform; 921706f2543Smrg struct pixman_f_transform f_transform, f_inverse; 922706f2543Smrg 923706f2543Smrg RRTransformCompute (stuff->x, stuff->y, 924706f2543Smrg mode->mode.width, mode->mode.height, 925706f2543Smrg rotation, 926706f2543Smrg &crtc->client_pending_transform, 927706f2543Smrg &transform, &f_transform, &f_inverse); 928706f2543Smrg 929706f2543Smrg RRModeGetScanoutSize (mode, &transform, &source_width, &source_height); 930706f2543Smrg if (stuff->x + source_width > pScreen->width) 931706f2543Smrg { 932706f2543Smrg client->errorValue = stuff->x; 933706f2543Smrg free(outputs); 934706f2543Smrg return BadValue; 935706f2543Smrg } 936706f2543Smrg 937706f2543Smrg if (stuff->y + source_height > pScreen->height) 938706f2543Smrg { 939706f2543Smrg client->errorValue = stuff->y; 940706f2543Smrg free(outputs); 941706f2543Smrg return BadValue; 942706f2543Smrg } 943706f2543Smrg } 944706f2543Smrg#endif 945706f2543Smrg } 946706f2543Smrg 947706f2543Smrg if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y, 948706f2543Smrg rotation, numOutputs, outputs)) 949706f2543Smrg { 950706f2543Smrg rep.status = RRSetConfigFailed; 951706f2543Smrg goto sendReply; 952706f2543Smrg } 953706f2543Smrg rep.status = RRSetConfigSuccess; 954706f2543Smrg pScrPriv->lastSetTime = time; 955706f2543Smrg 956706f2543SmrgsendReply: 957706f2543Smrg free(outputs); 958706f2543Smrg 959706f2543Smrg rep.type = X_Reply; 960706f2543Smrg /* rep.status has already been filled in */ 961706f2543Smrg rep.length = 0; 962706f2543Smrg rep.sequenceNumber = client->sequence; 963706f2543Smrg rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; 964706f2543Smrg 965706f2543Smrg if (client->swapped) 966706f2543Smrg { 967706f2543Smrg int n; 968706f2543Smrg swaps(&rep.sequenceNumber, n); 969706f2543Smrg swapl(&rep.length, n); 970706f2543Smrg swapl(&rep.newTimestamp, n); 971706f2543Smrg } 972706f2543Smrg WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep); 973706f2543Smrg 974706f2543Smrg return Success; 975706f2543Smrg} 976706f2543Smrg 977706f2543Smrgint 978706f2543SmrgProcRRGetPanning (ClientPtr client) 979706f2543Smrg{ 980706f2543Smrg REQUEST(xRRGetPanningReq); 981706f2543Smrg xRRGetPanningReply rep; 982706f2543Smrg RRCrtcPtr crtc; 983706f2543Smrg ScreenPtr pScreen; 984706f2543Smrg rrScrPrivPtr pScrPriv; 985706f2543Smrg BoxRec total; 986706f2543Smrg BoxRec tracking; 987706f2543Smrg INT16 border[4]; 988706f2543Smrg int n; 989706f2543Smrg 990706f2543Smrg REQUEST_SIZE_MATCH(xRRGetPanningReq); 991706f2543Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 992706f2543Smrg 993706f2543Smrg /* All crtcs must be associated with screens before client 994706f2543Smrg * requests are processed 995706f2543Smrg */ 996706f2543Smrg pScreen = crtc->pScreen; 997706f2543Smrg pScrPriv = rrGetScrPriv(pScreen); 998706f2543Smrg 999706f2543Smrg if (!pScrPriv) 1000706f2543Smrg return RRErrorBase + BadRRCrtc; 1001706f2543Smrg 1002706f2543Smrg memset(&rep, 0, sizeof(rep)); 1003706f2543Smrg rep.type = X_Reply; 1004706f2543Smrg rep.status = RRSetConfigSuccess; 1005706f2543Smrg rep.sequenceNumber = client->sequence; 1006706f2543Smrg rep.length = 1; 1007706f2543Smrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 1008706f2543Smrg 1009706f2543Smrg if (pScrPriv->rrGetPanning && 1010706f2543Smrg pScrPriv->rrGetPanning (pScreen, crtc, &total, &tracking, border)) { 1011706f2543Smrg rep.left = total.x1; 1012706f2543Smrg rep.top = total.y1; 1013706f2543Smrg rep.width = total.x2 - total.x1; 1014706f2543Smrg rep.height = total.y2 - total.y1; 1015706f2543Smrg rep.track_left = tracking.x1; 1016706f2543Smrg rep.track_top = tracking.y1; 1017706f2543Smrg rep.track_width = tracking.x2 - tracking.x1; 1018706f2543Smrg rep.track_height = tracking.y2 - tracking.y1; 1019706f2543Smrg rep.border_left = border[0]; 1020706f2543Smrg rep.border_top = border[1]; 1021706f2543Smrg rep.border_right = border[2]; 1022706f2543Smrg rep.border_bottom = border[3]; 1023706f2543Smrg } 1024706f2543Smrg 1025706f2543Smrg if (client->swapped) { 1026706f2543Smrg swaps(&rep.sequenceNumber, n); 1027706f2543Smrg swapl(&rep.length, n); 1028706f2543Smrg swaps(&rep.timestamp, n); 1029706f2543Smrg swaps(&rep.left, n); 1030706f2543Smrg swaps(&rep.top, n); 1031706f2543Smrg swaps(&rep.width, n); 1032706f2543Smrg swaps(&rep.height, n); 1033706f2543Smrg swaps(&rep.track_left, n); 1034706f2543Smrg swaps(&rep.track_top, n); 1035706f2543Smrg swaps(&rep.track_width, n); 1036706f2543Smrg swaps(&rep.track_height, n); 1037706f2543Smrg swaps(&rep.border_left, n); 1038706f2543Smrg swaps(&rep.border_top, n); 1039706f2543Smrg swaps(&rep.border_right, n); 1040706f2543Smrg swaps(&rep.border_bottom, n); 1041706f2543Smrg } 1042706f2543Smrg WriteToClient(client, sizeof(xRRGetPanningReply), (char *)&rep); 1043706f2543Smrg return Success; 1044706f2543Smrg} 1045706f2543Smrg 1046706f2543Smrgint 1047706f2543SmrgProcRRSetPanning (ClientPtr client) 1048706f2543Smrg{ 1049706f2543Smrg REQUEST(xRRSetPanningReq); 1050706f2543Smrg xRRSetPanningReply rep; 1051706f2543Smrg RRCrtcPtr crtc; 1052706f2543Smrg ScreenPtr pScreen; 1053706f2543Smrg rrScrPrivPtr pScrPriv; 1054706f2543Smrg TimeStamp time; 1055706f2543Smrg BoxRec total; 1056706f2543Smrg BoxRec tracking; 1057706f2543Smrg INT16 border[4]; 1058706f2543Smrg int n; 1059706f2543Smrg 1060706f2543Smrg REQUEST_SIZE_MATCH(xRRSetPanningReq); 1061706f2543Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 1062706f2543Smrg 1063706f2543Smrg /* All crtcs must be associated with screens before client 1064706f2543Smrg * requests are processed 1065706f2543Smrg */ 1066706f2543Smrg pScreen = crtc->pScreen; 1067706f2543Smrg pScrPriv = rrGetScrPriv(pScreen); 1068706f2543Smrg 1069706f2543Smrg if (!pScrPriv) { 1070706f2543Smrg time = currentTime; 1071706f2543Smrg rep.status = RRSetConfigFailed; 1072706f2543Smrg goto sendReply; 1073706f2543Smrg } 1074706f2543Smrg 1075706f2543Smrg time = ClientTimeToServerTime(stuff->timestamp); 1076706f2543Smrg 1077706f2543Smrg if (!pScrPriv->rrGetPanning) 1078706f2543Smrg return RRErrorBase + BadRRCrtc; 1079706f2543Smrg 1080706f2543Smrg total.x1 = stuff->left; 1081706f2543Smrg total.y1 = stuff->top; 1082706f2543Smrg total.x2 = total.x1 + stuff->width; 1083706f2543Smrg total.y2 = total.y1 + stuff->height; 1084706f2543Smrg tracking.x1 = stuff->track_left; 1085706f2543Smrg tracking.y1 = stuff->track_top; 1086706f2543Smrg tracking.x2 = tracking.x1 + stuff->track_width; 1087706f2543Smrg tracking.y2 = tracking.y1 + stuff->track_height; 1088706f2543Smrg border[0] = stuff->border_left; 1089706f2543Smrg border[1] = stuff->border_top; 1090706f2543Smrg border[2] = stuff->border_right; 1091706f2543Smrg border[3] = stuff->border_bottom; 1092706f2543Smrg 1093706f2543Smrg if (! pScrPriv->rrSetPanning (pScreen, crtc, &total, &tracking, border)) 1094706f2543Smrg return BadMatch; 1095706f2543Smrg 1096706f2543Smrg pScrPriv->lastSetTime = time; 1097706f2543Smrg 1098706f2543Smrg rep.status = RRSetConfigSuccess; 1099706f2543Smrg 1100706f2543SmrgsendReply: 1101706f2543Smrg rep.type = X_Reply; 1102706f2543Smrg rep.sequenceNumber = client->sequence; 1103706f2543Smrg rep.length = 0; 1104706f2543Smrg rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; 1105706f2543Smrg 1106706f2543Smrg if (client->swapped) { 1107706f2543Smrg swaps(&rep.sequenceNumber, n); 1108706f2543Smrg swapl(&rep.length, n); 1109706f2543Smrg swaps(&rep.newTimestamp, n); 1110706f2543Smrg } 1111706f2543Smrg WriteToClient(client, sizeof(xRRSetPanningReply), (char *)&rep); 1112706f2543Smrg return Success; 1113706f2543Smrg} 1114706f2543Smrg 1115706f2543Smrgint 1116706f2543SmrgProcRRGetCrtcGammaSize (ClientPtr client) 1117706f2543Smrg{ 1118706f2543Smrg REQUEST(xRRGetCrtcGammaSizeReq); 1119706f2543Smrg xRRGetCrtcGammaSizeReply reply; 1120706f2543Smrg RRCrtcPtr crtc; 1121706f2543Smrg int n; 1122706f2543Smrg 1123706f2543Smrg REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq); 1124706f2543Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 1125706f2543Smrg 1126706f2543Smrg /* Gamma retrieval failed, any better error? */ 1127706f2543Smrg if (!RRCrtcGammaGet(crtc)) 1128706f2543Smrg return RRErrorBase + BadRRCrtc; 1129706f2543Smrg 1130706f2543Smrg reply.type = X_Reply; 1131706f2543Smrg reply.sequenceNumber = client->sequence; 1132706f2543Smrg reply.length = 0; 1133706f2543Smrg reply.size = crtc->gammaSize; 1134706f2543Smrg if (client->swapped) { 1135706f2543Smrg swaps (&reply.sequenceNumber, n); 1136706f2543Smrg swapl (&reply.length, n); 1137706f2543Smrg swaps (&reply.size, n); 1138706f2543Smrg } 1139706f2543Smrg WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply); 1140706f2543Smrg return Success; 1141706f2543Smrg} 1142706f2543Smrg 1143706f2543Smrgint 1144706f2543SmrgProcRRGetCrtcGamma (ClientPtr client) 1145706f2543Smrg{ 1146706f2543Smrg REQUEST(xRRGetCrtcGammaReq); 1147706f2543Smrg xRRGetCrtcGammaReply reply; 1148706f2543Smrg RRCrtcPtr crtc; 1149706f2543Smrg int n; 1150706f2543Smrg unsigned long len; 1151706f2543Smrg char *extra = NULL; 1152706f2543Smrg 1153706f2543Smrg REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq); 1154706f2543Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 1155706f2543Smrg 1156706f2543Smrg /* Gamma retrieval failed, any better error? */ 1157706f2543Smrg if (!RRCrtcGammaGet(crtc)) 1158706f2543Smrg return RRErrorBase + BadRRCrtc; 1159706f2543Smrg 1160706f2543Smrg len = crtc->gammaSize * 3 * 2; 1161706f2543Smrg 1162706f2543Smrg if (crtc->gammaSize) { 1163706f2543Smrg extra = malloc(len); 1164706f2543Smrg if (!extra) 1165706f2543Smrg return BadAlloc; 1166706f2543Smrg } 1167706f2543Smrg 1168706f2543Smrg reply.type = X_Reply; 1169706f2543Smrg reply.sequenceNumber = client->sequence; 1170706f2543Smrg reply.length = bytes_to_int32(len); 1171706f2543Smrg reply.size = crtc->gammaSize; 1172706f2543Smrg if (client->swapped) { 1173706f2543Smrg swaps (&reply.sequenceNumber, n); 1174706f2543Smrg swapl (&reply.length, n); 1175706f2543Smrg swaps (&reply.size, n); 1176706f2543Smrg } 1177706f2543Smrg WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply); 1178706f2543Smrg if (crtc->gammaSize) 1179706f2543Smrg { 1180706f2543Smrg memcpy(extra, crtc->gammaRed, len); 1181706f2543Smrg client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; 1182706f2543Smrg WriteSwappedDataToClient (client, len, extra); 1183706f2543Smrg free(extra); 1184706f2543Smrg } 1185706f2543Smrg return Success; 1186706f2543Smrg} 1187706f2543Smrg 1188706f2543Smrgint 1189706f2543SmrgProcRRSetCrtcGamma (ClientPtr client) 1190706f2543Smrg{ 1191706f2543Smrg REQUEST(xRRSetCrtcGammaReq); 1192706f2543Smrg RRCrtcPtr crtc; 1193706f2543Smrg unsigned long len; 1194706f2543Smrg CARD16 *red, *green, *blue; 1195706f2543Smrg 1196706f2543Smrg REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq); 1197706f2543Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 1198706f2543Smrg 1199706f2543Smrg len = client->req_len - bytes_to_int32(sizeof (xRRSetCrtcGammaReq)); 1200706f2543Smrg if (len < (stuff->size * 3 + 1) >> 1) 1201706f2543Smrg return BadLength; 1202706f2543Smrg 1203706f2543Smrg if (stuff->size != crtc->gammaSize) 1204706f2543Smrg return BadMatch; 1205706f2543Smrg 1206706f2543Smrg red = (CARD16 *) (stuff + 1); 1207706f2543Smrg green = red + crtc->gammaSize; 1208706f2543Smrg blue = green + crtc->gammaSize; 1209706f2543Smrg 1210706f2543Smrg RRCrtcGammaSet (crtc, red, green, blue); 1211706f2543Smrg 1212706f2543Smrg return Success; 1213706f2543Smrg} 1214706f2543Smrg 1215706f2543Smrg/* Version 1.3 additions */ 1216706f2543Smrg 1217706f2543Smrgint 1218706f2543SmrgProcRRSetCrtcTransform (ClientPtr client) 1219706f2543Smrg{ 1220706f2543Smrg REQUEST(xRRSetCrtcTransformReq); 1221706f2543Smrg RRCrtcPtr crtc; 1222706f2543Smrg PictTransform transform; 1223706f2543Smrg struct pixman_f_transform f_transform, f_inverse; 1224706f2543Smrg char *filter; 1225706f2543Smrg int nbytes; 1226706f2543Smrg xFixed *params; 1227706f2543Smrg int nparams; 1228706f2543Smrg 1229706f2543Smrg REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq); 1230706f2543Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 1231706f2543Smrg 1232706f2543Smrg PictTransform_from_xRenderTransform (&transform, &stuff->transform); 1233706f2543Smrg pixman_f_transform_from_pixman_transform (&f_transform, &transform); 1234706f2543Smrg if (!pixman_f_transform_invert (&f_inverse, &f_transform)) 1235706f2543Smrg return BadMatch; 1236706f2543Smrg 1237706f2543Smrg filter = (char *) (stuff + 1); 1238706f2543Smrg nbytes = stuff->nbytesFilter; 1239706f2543Smrg params = (xFixed *) (filter + pad_to_int32(nbytes)); 1240706f2543Smrg nparams = ((xFixed *) stuff + client->req_len) - params; 1241706f2543Smrg if (nparams < 0) 1242706f2543Smrg return BadLength; 1243706f2543Smrg 1244706f2543Smrg return RRCrtcTransformSet (crtc, &transform, &f_transform, &f_inverse, 1245706f2543Smrg filter, nbytes, params, nparams); 1246706f2543Smrg} 1247706f2543Smrg 1248706f2543Smrg 1249706f2543Smrg#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32) 1250706f2543Smrg 1251706f2543Smrgstatic int 1252706f2543Smrgtransform_filter_length (RRTransformPtr transform) 1253706f2543Smrg{ 1254706f2543Smrg int nbytes, nparams; 1255706f2543Smrg 1256706f2543Smrg if (transform->filter == NULL) 1257706f2543Smrg return 0; 1258706f2543Smrg nbytes = strlen (transform->filter->name); 1259706f2543Smrg nparams = transform->nparams; 1260706f2543Smrg return pad_to_int32(nbytes) + (nparams * sizeof (xFixed)); 1261706f2543Smrg} 1262706f2543Smrg 1263706f2543Smrgstatic int 1264706f2543Smrgtransform_filter_encode (ClientPtr client, char *output, 1265706f2543Smrg CARD16 *nbytesFilter, 1266706f2543Smrg CARD16 *nparamsFilter, 1267706f2543Smrg RRTransformPtr transform) 1268706f2543Smrg{ 1269706f2543Smrg int nbytes, nparams; 1270706f2543Smrg int n; 1271706f2543Smrg 1272706f2543Smrg if (transform->filter == NULL) { 1273706f2543Smrg *nbytesFilter = 0; 1274706f2543Smrg *nparamsFilter = 0; 1275706f2543Smrg return 0; 1276706f2543Smrg } 1277706f2543Smrg nbytes = strlen (transform->filter->name); 1278706f2543Smrg nparams = transform->nparams; 1279706f2543Smrg *nbytesFilter = nbytes; 1280706f2543Smrg *nparamsFilter = nparams; 1281706f2543Smrg memcpy (output, transform->filter->name, nbytes); 1282706f2543Smrg while ((nbytes & 3) != 0) 1283706f2543Smrg output[nbytes++] = 0; 1284706f2543Smrg memcpy (output + nbytes, transform->params, nparams * sizeof (xFixed)); 1285706f2543Smrg if (client->swapped) { 1286706f2543Smrg swaps (nbytesFilter, n); 1287706f2543Smrg swaps (nparamsFilter, n); 1288706f2543Smrg SwapLongs ((CARD32 *) (output + nbytes), nparams); 1289706f2543Smrg } 1290706f2543Smrg nbytes += nparams * sizeof (xFixed); 1291706f2543Smrg return nbytes; 1292706f2543Smrg} 1293706f2543Smrg 1294706f2543Smrgstatic void 1295706f2543Smrgtransform_encode (ClientPtr client, xRenderTransform *wire, PictTransform *pict) 1296706f2543Smrg{ 1297706f2543Smrg xRenderTransform_from_PictTransform (wire, pict); 1298706f2543Smrg if (client->swapped) 1299706f2543Smrg SwapLongs ((CARD32 *) wire, bytes_to_int32(sizeof(xRenderTransform))); 1300706f2543Smrg} 1301706f2543Smrg 1302706f2543Smrgint 1303706f2543SmrgProcRRGetCrtcTransform (ClientPtr client) 1304706f2543Smrg{ 1305706f2543Smrg REQUEST(xRRGetCrtcTransformReq); 1306706f2543Smrg xRRGetCrtcTransformReply *reply; 1307706f2543Smrg RRCrtcPtr crtc; 1308706f2543Smrg int n, nextra; 1309706f2543Smrg RRTransformPtr current, pending; 1310706f2543Smrg char *extra; 1311706f2543Smrg 1312706f2543Smrg REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq); 1313706f2543Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 1314706f2543Smrg 1315706f2543Smrg pending = &crtc->client_pending_transform; 1316706f2543Smrg current = &crtc->client_current_transform; 1317706f2543Smrg 1318706f2543Smrg nextra = (transform_filter_length (pending) + 1319706f2543Smrg transform_filter_length (current)); 1320706f2543Smrg 1321706f2543Smrg reply = malloc(sizeof (xRRGetCrtcTransformReply) + nextra); 1322706f2543Smrg if (!reply) 1323706f2543Smrg return BadAlloc; 1324706f2543Smrg 1325706f2543Smrg extra = (char *) (reply + 1); 1326706f2543Smrg reply->type = X_Reply; 1327706f2543Smrg reply->sequenceNumber = client->sequence; 1328706f2543Smrg reply->length = bytes_to_int32(CrtcTransformExtra + nextra); 1329706f2543Smrg 1330706f2543Smrg reply->hasTransforms = crtc->transforms; 1331706f2543Smrg 1332706f2543Smrg transform_encode (client, &reply->pendingTransform, &pending->transform); 1333706f2543Smrg extra += transform_filter_encode (client, extra, 1334706f2543Smrg &reply->pendingNbytesFilter, 1335706f2543Smrg &reply->pendingNparamsFilter, 1336706f2543Smrg pending); 1337706f2543Smrg 1338706f2543Smrg transform_encode (client, &reply->currentTransform, ¤t->transform); 1339706f2543Smrg extra += transform_filter_encode (client, extra, 1340706f2543Smrg &reply->currentNbytesFilter, 1341706f2543Smrg &reply->currentNparamsFilter, 1342706f2543Smrg current); 1343706f2543Smrg 1344706f2543Smrg if (client->swapped) { 1345706f2543Smrg swaps (&reply->sequenceNumber, n); 1346706f2543Smrg swapl (&reply->length, n); 1347706f2543Smrg } 1348706f2543Smrg WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply); 1349706f2543Smrg free(reply); 1350706f2543Smrg return Success; 1351706f2543Smrg} 1352