rrcrtc.c revision 6747b715
105b261ecSmrg/* 205b261ecSmrg * Copyright © 2006 Keith Packard 305b261ecSmrg * 405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 605b261ecSmrg * the above copyright notice appear in all copies and that both that copyright 705b261ecSmrg * notice and this permission notice appear in supporting documentation, and 805b261ecSmrg * that the name of the copyright holders not be used in advertising or 905b261ecSmrg * publicity pertaining to distribution of the software without specific, 1005b261ecSmrg * written prior permission. The copyright holders make no representations 1105b261ecSmrg * about the suitability of this software for any purpose. It is provided "as 1205b261ecSmrg * is" without express or implied warranty. 1305b261ecSmrg * 1405b261ecSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1605b261ecSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2005b261ecSmrg * OF THIS SOFTWARE. 2105b261ecSmrg */ 2205b261ecSmrg 2305b261ecSmrg#include "randrstr.h" 2405b261ecSmrg#include "swaprep.h" 2505b261ecSmrg 2605b261ecSmrgRESTYPE RRCrtcType; 2705b261ecSmrg 2805b261ecSmrg/* 2905b261ecSmrg * Notify the CRTC of some change 3005b261ecSmrg */ 3105b261ecSmrgvoid 3205b261ecSmrgRRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged) 3305b261ecSmrg{ 3405b261ecSmrg ScreenPtr pScreen = crtc->pScreen; 3505b261ecSmrg 3605b261ecSmrg crtc->changed = TRUE; 3705b261ecSmrg if (pScreen) 3805b261ecSmrg { 3905b261ecSmrg rrScrPriv(pScreen); 4005b261ecSmrg 4105b261ecSmrg pScrPriv->changed = TRUE; 4205b261ecSmrg /* 4305b261ecSmrg * Send ConfigureNotify on any layout change 4405b261ecSmrg */ 4505b261ecSmrg if (layoutChanged) 4605b261ecSmrg pScrPriv->layoutChanged = TRUE; 4705b261ecSmrg } 4805b261ecSmrg} 4905b261ecSmrg 5005b261ecSmrg/* 5105b261ecSmrg * Create a CRTC 5205b261ecSmrg */ 5305b261ecSmrgRRCrtcPtr 5405b261ecSmrgRRCrtcCreate (ScreenPtr pScreen, void *devPrivate) 5505b261ecSmrg{ 5605b261ecSmrg RRCrtcPtr crtc; 5705b261ecSmrg RRCrtcPtr *crtcs; 5805b261ecSmrg rrScrPrivPtr pScrPriv; 5905b261ecSmrg 6005b261ecSmrg if (!RRInit()) 6105b261ecSmrg return NULL; 6205b261ecSmrg 6305b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 6405b261ecSmrg 6505b261ecSmrg /* make space for the crtc pointer */ 6605b261ecSmrg if (pScrPriv->numCrtcs) 676747b715Smrg crtcs = realloc(pScrPriv->crtcs, 6805b261ecSmrg (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr)); 6905b261ecSmrg else 706747b715Smrg crtcs = malloc(sizeof (RRCrtcPtr)); 7105b261ecSmrg if (!crtcs) 7205b261ecSmrg return FALSE; 7305b261ecSmrg pScrPriv->crtcs = crtcs; 7405b261ecSmrg 756747b715Smrg crtc = calloc(1, sizeof (RRCrtcRec)); 7605b261ecSmrg if (!crtc) 7705b261ecSmrg return NULL; 7805b261ecSmrg crtc->id = FakeClientID (0); 7905b261ecSmrg crtc->pScreen = pScreen; 8005b261ecSmrg crtc->mode = NULL; 8105b261ecSmrg crtc->x = 0; 8205b261ecSmrg crtc->y = 0; 8305b261ecSmrg crtc->rotation = RR_Rotate_0; 8405b261ecSmrg crtc->rotations = RR_Rotate_0; 8505b261ecSmrg crtc->outputs = NULL; 8605b261ecSmrg crtc->numOutputs = 0; 8705b261ecSmrg crtc->gammaSize = 0; 8805b261ecSmrg crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL; 8905b261ecSmrg crtc->changed = FALSE; 9005b261ecSmrg crtc->devPrivate = devPrivate; 914642e01fSmrg RRTransformInit (&crtc->client_pending_transform); 924642e01fSmrg RRTransformInit (&crtc->client_current_transform); 934642e01fSmrg pixman_transform_init_identity (&crtc->transform); 944642e01fSmrg pixman_f_transform_init_identity (&crtc->f_transform); 954642e01fSmrg pixman_f_transform_init_identity (&crtc->f_inverse); 9605b261ecSmrg 9705b261ecSmrg if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc)) 9805b261ecSmrg return NULL; 9905b261ecSmrg 10005b261ecSmrg /* attach the screen and crtc together */ 10105b261ecSmrg crtc->pScreen = pScreen; 10205b261ecSmrg pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc; 10305b261ecSmrg 10405b261ecSmrg return crtc; 10505b261ecSmrg} 10605b261ecSmrg 10705b261ecSmrg/* 10805b261ecSmrg * Set the allowed rotations on a CRTC 10905b261ecSmrg */ 11005b261ecSmrgvoid 11105b261ecSmrgRRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations) 11205b261ecSmrg{ 11305b261ecSmrg crtc->rotations = rotations; 11405b261ecSmrg} 11505b261ecSmrg 1164642e01fSmrg/* 1174642e01fSmrg * Set whether transforms are allowed on a CRTC 1184642e01fSmrg */ 1194642e01fSmrgvoid 1204642e01fSmrgRRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms) 1214642e01fSmrg{ 1224642e01fSmrg crtc->transforms = transforms; 1234642e01fSmrg} 1244642e01fSmrg 12505b261ecSmrg/* 12605b261ecSmrg * Notify the extension that the Crtc has been reconfigured, 12705b261ecSmrg * the driver calls this whenever it has updated the mode 12805b261ecSmrg */ 12905b261ecSmrgBool 13005b261ecSmrgRRCrtcNotify (RRCrtcPtr crtc, 13105b261ecSmrg RRModePtr mode, 13205b261ecSmrg int x, 13305b261ecSmrg int y, 13405b261ecSmrg Rotation rotation, 1354642e01fSmrg RRTransformPtr transform, 13605b261ecSmrg int numOutputs, 13705b261ecSmrg RROutputPtr *outputs) 13805b261ecSmrg{ 13905b261ecSmrg int i, j; 14005b261ecSmrg 14105b261ecSmrg /* 14205b261ecSmrg * Check to see if any of the new outputs were 14305b261ecSmrg * not in the old list and mark them as changed 14405b261ecSmrg */ 14505b261ecSmrg for (i = 0; i < numOutputs; i++) 14605b261ecSmrg { 14705b261ecSmrg for (j = 0; j < crtc->numOutputs; j++) 14805b261ecSmrg if (outputs[i] == crtc->outputs[j]) 14905b261ecSmrg break; 15005b261ecSmrg if (j == crtc->numOutputs) 15105b261ecSmrg { 15205b261ecSmrg outputs[i]->crtc = crtc; 15305b261ecSmrg RROutputChanged (outputs[i], FALSE); 15405b261ecSmrg RRCrtcChanged (crtc, FALSE); 15505b261ecSmrg } 15605b261ecSmrg } 15705b261ecSmrg /* 15805b261ecSmrg * Check to see if any of the old outputs are 15905b261ecSmrg * not in the new list and mark them as changed 16005b261ecSmrg */ 16105b261ecSmrg for (j = 0; j < crtc->numOutputs; j++) 16205b261ecSmrg { 16305b261ecSmrg for (i = 0; i < numOutputs; i++) 16405b261ecSmrg if (outputs[i] == crtc->outputs[j]) 16505b261ecSmrg break; 16605b261ecSmrg if (i == numOutputs) 16705b261ecSmrg { 1684642e01fSmrg if (crtc->outputs[j]->crtc == crtc) 1694642e01fSmrg crtc->outputs[j]->crtc = NULL; 17005b261ecSmrg RROutputChanged (crtc->outputs[j], FALSE); 17105b261ecSmrg RRCrtcChanged (crtc, FALSE); 17205b261ecSmrg } 17305b261ecSmrg } 17405b261ecSmrg /* 17505b261ecSmrg * Reallocate the crtc output array if necessary 17605b261ecSmrg */ 17705b261ecSmrg if (numOutputs != crtc->numOutputs) 17805b261ecSmrg { 17905b261ecSmrg RROutputPtr *newoutputs; 18005b261ecSmrg 18105b261ecSmrg if (numOutputs) 18205b261ecSmrg { 18305b261ecSmrg if (crtc->numOutputs) 1846747b715Smrg newoutputs = realloc(crtc->outputs, 18505b261ecSmrg numOutputs * sizeof (RROutputPtr)); 18605b261ecSmrg else 1876747b715Smrg newoutputs = malloc(numOutputs * sizeof (RROutputPtr)); 18805b261ecSmrg if (!newoutputs) 18905b261ecSmrg return FALSE; 19005b261ecSmrg } 19105b261ecSmrg else 19205b261ecSmrg { 1936747b715Smrg free(crtc->outputs); 19405b261ecSmrg newoutputs = NULL; 19505b261ecSmrg } 19605b261ecSmrg crtc->outputs = newoutputs; 19705b261ecSmrg crtc->numOutputs = numOutputs; 19805b261ecSmrg } 19905b261ecSmrg /* 20005b261ecSmrg * Copy the new list of outputs into the crtc 20105b261ecSmrg */ 20205b261ecSmrg memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)); 20305b261ecSmrg /* 20405b261ecSmrg * Update remaining crtc fields 20505b261ecSmrg */ 20605b261ecSmrg if (mode != crtc->mode) 20705b261ecSmrg { 20805b261ecSmrg if (crtc->mode) 20905b261ecSmrg RRModeDestroy (crtc->mode); 21005b261ecSmrg crtc->mode = mode; 21105b261ecSmrg if (mode != NULL) 21205b261ecSmrg mode->refcnt++; 21305b261ecSmrg RRCrtcChanged (crtc, TRUE); 21405b261ecSmrg } 21505b261ecSmrg if (x != crtc->x) 21605b261ecSmrg { 21705b261ecSmrg crtc->x = x; 21805b261ecSmrg RRCrtcChanged (crtc, TRUE); 21905b261ecSmrg } 22005b261ecSmrg if (y != crtc->y) 22105b261ecSmrg { 22205b261ecSmrg crtc->y = y; 22305b261ecSmrg RRCrtcChanged (crtc, TRUE); 22405b261ecSmrg } 22505b261ecSmrg if (rotation != crtc->rotation) 22605b261ecSmrg { 22705b261ecSmrg crtc->rotation = rotation; 22805b261ecSmrg RRCrtcChanged (crtc, TRUE); 22905b261ecSmrg } 2304642e01fSmrg if (!RRTransformEqual (transform, &crtc->client_current_transform)) { 2314642e01fSmrg RRTransformCopy (&crtc->client_current_transform, transform); 2324642e01fSmrg RRCrtcChanged (crtc, TRUE); 2334642e01fSmrg } 2344642e01fSmrg if (crtc->changed && mode) 2354642e01fSmrg { 2364642e01fSmrg RRTransformCompute (x, y, 2374642e01fSmrg mode->mode.width, mode->mode.height, 2384642e01fSmrg rotation, 2394642e01fSmrg &crtc->client_current_transform, 2404642e01fSmrg &crtc->transform, &crtc->f_transform, 2414642e01fSmrg &crtc->f_inverse); 2424642e01fSmrg } 24305b261ecSmrg return TRUE; 24405b261ecSmrg} 24505b261ecSmrg 24605b261ecSmrgvoid 24705b261ecSmrgRRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc) 24805b261ecSmrg{ 24905b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 25005b261ecSmrg rrScrPriv (pScreen); 25105b261ecSmrg xRRCrtcChangeNotifyEvent ce; 25205b261ecSmrg RRModePtr mode = crtc->mode; 25305b261ecSmrg 25405b261ecSmrg ce.type = RRNotify + RREventBase; 25505b261ecSmrg ce.subCode = RRNotify_CrtcChange; 25605b261ecSmrg ce.timestamp = pScrPriv->lastSetTime.milliseconds; 25705b261ecSmrg ce.window = pWin->drawable.id; 25805b261ecSmrg ce.crtc = crtc->id; 25905b261ecSmrg ce.rotation = crtc->rotation; 26005b261ecSmrg if (mode) 26105b261ecSmrg { 26205b261ecSmrg ce.mode = mode->mode.id; 26305b261ecSmrg ce.x = crtc->x; 26405b261ecSmrg ce.y = crtc->y; 26505b261ecSmrg ce.width = mode->mode.width; 26605b261ecSmrg ce.height = mode->mode.height; 26705b261ecSmrg } 26805b261ecSmrg else 26905b261ecSmrg { 27005b261ecSmrg ce.mode = None; 27105b261ecSmrg ce.x = 0; 27205b261ecSmrg ce.y = 0; 27305b261ecSmrg ce.width = 0; 27405b261ecSmrg ce.height = 0; 27505b261ecSmrg } 27605b261ecSmrg WriteEventsToClient (client, 1, (xEvent *) &ce); 27705b261ecSmrg} 27805b261ecSmrg 27905b261ecSmrgstatic Bool 28005b261ecSmrgRRCrtcPendingProperties (RRCrtcPtr crtc) 28105b261ecSmrg{ 28205b261ecSmrg ScreenPtr pScreen = crtc->pScreen; 28305b261ecSmrg rrScrPriv(pScreen); 28405b261ecSmrg int o; 28505b261ecSmrg 28605b261ecSmrg for (o = 0; o < pScrPriv->numOutputs; o++) 28705b261ecSmrg { 28805b261ecSmrg RROutputPtr output = pScrPriv->outputs[o]; 28905b261ecSmrg if (output->crtc == crtc && output->pendingProperties) 29005b261ecSmrg return TRUE; 29105b261ecSmrg } 29205b261ecSmrg return FALSE; 29305b261ecSmrg} 29405b261ecSmrg 29505b261ecSmrg/* 29605b261ecSmrg * Request that the Crtc be reconfigured 29705b261ecSmrg */ 29805b261ecSmrgBool 29905b261ecSmrgRRCrtcSet (RRCrtcPtr crtc, 30005b261ecSmrg RRModePtr mode, 30105b261ecSmrg int x, 30205b261ecSmrg int y, 30305b261ecSmrg Rotation rotation, 30405b261ecSmrg int numOutputs, 30505b261ecSmrg RROutputPtr *outputs) 30605b261ecSmrg{ 30705b261ecSmrg ScreenPtr pScreen = crtc->pScreen; 30805b261ecSmrg Bool ret = FALSE; 30905b261ecSmrg rrScrPriv(pScreen); 31005b261ecSmrg 31105b261ecSmrg /* See if nothing changed */ 31205b261ecSmrg if (crtc->mode == mode && 31305b261ecSmrg crtc->x == x && 31405b261ecSmrg crtc->y == y && 31505b261ecSmrg crtc->rotation == rotation && 31605b261ecSmrg crtc->numOutputs == numOutputs && 31705b261ecSmrg !memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) && 3184642e01fSmrg !RRCrtcPendingProperties (crtc) && 3194642e01fSmrg !RRCrtcPendingTransform (crtc)) 32005b261ecSmrg { 32105b261ecSmrg ret = TRUE; 32205b261ecSmrg } 32305b261ecSmrg else 32405b261ecSmrg { 32505b261ecSmrg#if RANDR_12_INTERFACE 32605b261ecSmrg if (pScrPriv->rrCrtcSet) 32705b261ecSmrg { 32805b261ecSmrg ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, 32905b261ecSmrg rotation, numOutputs, outputs); 33005b261ecSmrg } 33105b261ecSmrg else 33205b261ecSmrg#endif 33305b261ecSmrg { 33405b261ecSmrg#if RANDR_10_INTERFACE 33505b261ecSmrg if (pScrPriv->rrSetConfig) 33605b261ecSmrg { 33705b261ecSmrg RRScreenSize size; 33805b261ecSmrg RRScreenRate rate; 33905b261ecSmrg 34005b261ecSmrg if (!mode) 34105b261ecSmrg { 3424642e01fSmrg RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL); 34305b261ecSmrg ret = TRUE; 34405b261ecSmrg } 34505b261ecSmrg else 34605b261ecSmrg { 34705b261ecSmrg size.width = mode->mode.width; 34805b261ecSmrg size.height = mode->mode.height; 34905b261ecSmrg if (outputs[0]->mmWidth && outputs[0]->mmHeight) 35005b261ecSmrg { 35105b261ecSmrg size.mmWidth = outputs[0]->mmWidth; 35205b261ecSmrg size.mmHeight = outputs[0]->mmHeight; 35305b261ecSmrg } 35405b261ecSmrg else 35505b261ecSmrg { 35605b261ecSmrg size.mmWidth = pScreen->mmWidth; 35705b261ecSmrg size.mmHeight = pScreen->mmHeight; 35805b261ecSmrg } 35905b261ecSmrg size.nRates = 1; 36005b261ecSmrg rate.rate = RRVerticalRefresh (&mode->mode); 36105b261ecSmrg size.pRates = &rate; 36205b261ecSmrg ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size); 36305b261ecSmrg /* 36405b261ecSmrg * Old 1.0 interface tied screen size to mode size 36505b261ecSmrg */ 36605b261ecSmrg if (ret) 36705b261ecSmrg { 3684642e01fSmrg RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs); 36905b261ecSmrg RRScreenSizeNotify (pScreen); 37005b261ecSmrg } 37105b261ecSmrg } 37205b261ecSmrg } 37305b261ecSmrg#endif 37405b261ecSmrg } 37505b261ecSmrg if (ret) 37605b261ecSmrg { 37705b261ecSmrg int o; 37805b261ecSmrg RRTellChanged (pScreen); 37905b261ecSmrg 38005b261ecSmrg for (o = 0; o < numOutputs; o++) 38105b261ecSmrg RRPostPendingProperties (outputs[o]); 38205b261ecSmrg } 38305b261ecSmrg } 38405b261ecSmrg return ret; 38505b261ecSmrg} 38605b261ecSmrg 3874642e01fSmrg/* 3884642e01fSmrg * Return crtc transform 3894642e01fSmrg */ 3904642e01fSmrgRRTransformPtr 3914642e01fSmrgRRCrtcGetTransform (RRCrtcPtr crtc) 3924642e01fSmrg{ 3934642e01fSmrg RRTransformPtr transform = &crtc->client_pending_transform; 3944642e01fSmrg 3954642e01fSmrg if (pixman_transform_is_identity (&transform->transform)) 3964642e01fSmrg return NULL; 3974642e01fSmrg return transform; 3984642e01fSmrg} 3994642e01fSmrg 4004642e01fSmrg/* 4014642e01fSmrg * Check whether the pending and current transforms are the same 4024642e01fSmrg */ 4034642e01fSmrgBool 4044642e01fSmrgRRCrtcPendingTransform (RRCrtcPtr crtc) 4054642e01fSmrg{ 4064642e01fSmrg return memcmp (&crtc->client_current_transform.transform, 4074642e01fSmrg &crtc->client_pending_transform.transform, 4084642e01fSmrg sizeof (PictTransform)) != 0; 4094642e01fSmrg} 4104642e01fSmrg 41105b261ecSmrg/* 41205b261ecSmrg * Destroy a Crtc at shutdown 41305b261ecSmrg */ 41405b261ecSmrgvoid 41505b261ecSmrgRRCrtcDestroy (RRCrtcPtr crtc) 41605b261ecSmrg{ 41705b261ecSmrg FreeResource (crtc->id, 0); 41805b261ecSmrg} 41905b261ecSmrg 42005b261ecSmrgstatic int 42105b261ecSmrgRRCrtcDestroyResource (pointer value, XID pid) 42205b261ecSmrg{ 42305b261ecSmrg RRCrtcPtr crtc = (RRCrtcPtr) value; 42405b261ecSmrg ScreenPtr pScreen = crtc->pScreen; 42505b261ecSmrg 42605b261ecSmrg if (pScreen) 42705b261ecSmrg { 42805b261ecSmrg rrScrPriv(pScreen); 42905b261ecSmrg int i; 43005b261ecSmrg 43105b261ecSmrg for (i = 0; i < pScrPriv->numCrtcs; i++) 43205b261ecSmrg { 43305b261ecSmrg if (pScrPriv->crtcs[i] == crtc) 43405b261ecSmrg { 43505b261ecSmrg memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1, 43605b261ecSmrg (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr)); 43705b261ecSmrg --pScrPriv->numCrtcs; 43805b261ecSmrg break; 43905b261ecSmrg } 44005b261ecSmrg } 44105b261ecSmrg } 4426747b715Smrg free(crtc->gammaRed); 44305b261ecSmrg if (crtc->mode) 44405b261ecSmrg RRModeDestroy (crtc->mode); 4456747b715Smrg free(crtc); 44605b261ecSmrg return 1; 44705b261ecSmrg} 44805b261ecSmrg 44905b261ecSmrg/* 45005b261ecSmrg * Request that the Crtc gamma be changed 45105b261ecSmrg */ 45205b261ecSmrg 45305b261ecSmrgBool 45405b261ecSmrgRRCrtcGammaSet (RRCrtcPtr crtc, 45505b261ecSmrg CARD16 *red, 45605b261ecSmrg CARD16 *green, 45705b261ecSmrg CARD16 *blue) 45805b261ecSmrg{ 45905b261ecSmrg Bool ret = TRUE; 46005b261ecSmrg#if RANDR_12_INTERFACE 46105b261ecSmrg ScreenPtr pScreen = crtc->pScreen; 46205b261ecSmrg#endif 46305b261ecSmrg 46405b261ecSmrg memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16)); 46505b261ecSmrg memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16)); 46605b261ecSmrg memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16)); 46705b261ecSmrg#if RANDR_12_INTERFACE 46805b261ecSmrg if (pScreen) 46905b261ecSmrg { 47005b261ecSmrg rrScrPriv(pScreen); 47105b261ecSmrg if (pScrPriv->rrCrtcSetGamma) 47205b261ecSmrg ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc); 47305b261ecSmrg } 47405b261ecSmrg#endif 47505b261ecSmrg return ret; 47605b261ecSmrg} 47705b261ecSmrg 4786747b715Smrg/* 4796747b715Smrg * Request current gamma back from the DDX (if possible). 4806747b715Smrg * This includes gamma size. 4816747b715Smrg */ 4826747b715SmrgBool 4836747b715SmrgRRCrtcGammaGet(RRCrtcPtr crtc) 4846747b715Smrg{ 4856747b715Smrg Bool ret = TRUE; 4866747b715Smrg#if RANDR_12_INTERFACE 4876747b715Smrg ScreenPtr pScreen = crtc->pScreen; 4886747b715Smrg#endif 4896747b715Smrg 4906747b715Smrg#if RANDR_12_INTERFACE 4916747b715Smrg if (pScreen) 4926747b715Smrg { 4936747b715Smrg rrScrPriv(pScreen); 4946747b715Smrg if (pScrPriv->rrCrtcGetGamma) 4956747b715Smrg ret = (*pScrPriv->rrCrtcGetGamma) (pScreen, crtc); 4966747b715Smrg } 4976747b715Smrg#endif 4986747b715Smrg return ret; 4996747b715Smrg} 5006747b715Smrg 50105b261ecSmrg/* 50205b261ecSmrg * Notify the extension that the Crtc gamma has been changed 50305b261ecSmrg * The driver calls this whenever it has changed the gamma values 50405b261ecSmrg * in the RRCrtcRec 50505b261ecSmrg */ 50605b261ecSmrg 50705b261ecSmrgBool 50805b261ecSmrgRRCrtcGammaNotify (RRCrtcPtr crtc) 50905b261ecSmrg{ 51005b261ecSmrg return TRUE; /* not much going on here */ 51105b261ecSmrg} 51205b261ecSmrg 5134642e01fSmrgstatic void 5144642e01fSmrgRRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform, 5154642e01fSmrg int *width, int *height) 51605b261ecSmrg{ 5174642e01fSmrg BoxRec box; 5184642e01fSmrg 5194642e01fSmrg if (mode == NULL) { 52005b261ecSmrg *width = 0; 52105b261ecSmrg *height = 0; 52205b261ecSmrg return; 52305b261ecSmrg } 52405b261ecSmrg 5254642e01fSmrg box.x1 = 0; 5264642e01fSmrg box.y1 = 0; 5274642e01fSmrg box.x2 = mode->mode.width; 5284642e01fSmrg box.y2 = mode->mode.height; 5294642e01fSmrg 5304642e01fSmrg pixman_transform_bounds (transform, &box); 5314642e01fSmrg *width = box.x2 - box.x1; 5324642e01fSmrg *height = box.y2 - box.y1; 5334642e01fSmrg} 5344642e01fSmrg 5354642e01fSmrg/** 5364642e01fSmrg * Returns the width/height that the crtc scans out from the framebuffer 5374642e01fSmrg */ 5384642e01fSmrgvoid 5394642e01fSmrgRRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height) 5404642e01fSmrg{ 5414642e01fSmrg return RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height); 54205b261ecSmrg} 54305b261ecSmrg 54405b261ecSmrg/* 54505b261ecSmrg * Set the size of the gamma table at server startup time 54605b261ecSmrg */ 54705b261ecSmrg 54805b261ecSmrgBool 54905b261ecSmrgRRCrtcGammaSetSize (RRCrtcPtr crtc, 55005b261ecSmrg int size) 55105b261ecSmrg{ 55205b261ecSmrg CARD16 *gamma; 55305b261ecSmrg 55405b261ecSmrg if (size == crtc->gammaSize) 55505b261ecSmrg return TRUE; 55605b261ecSmrg if (size) 55705b261ecSmrg { 5586747b715Smrg gamma = malloc(size * 3 * sizeof (CARD16)); 55905b261ecSmrg if (!gamma) 56005b261ecSmrg return FALSE; 56105b261ecSmrg } 56205b261ecSmrg else 56305b261ecSmrg gamma = NULL; 5646747b715Smrg free(crtc->gammaRed); 56505b261ecSmrg crtc->gammaRed = gamma; 56605b261ecSmrg crtc->gammaGreen = gamma + size; 56705b261ecSmrg crtc->gammaBlue = gamma + size*2; 56805b261ecSmrg crtc->gammaSize = size; 56905b261ecSmrg return TRUE; 57005b261ecSmrg} 57105b261ecSmrg 5724642e01fSmrg/* 5734642e01fSmrg * Set the pending CRTC transformation 5744642e01fSmrg */ 5754642e01fSmrg 5764642e01fSmrgint 5774642e01fSmrgRRCrtcTransformSet (RRCrtcPtr crtc, 5784642e01fSmrg PictTransformPtr transform, 5794642e01fSmrg struct pixman_f_transform *f_transform, 5804642e01fSmrg struct pixman_f_transform *f_inverse, 5814642e01fSmrg char *filter_name, 5824642e01fSmrg int filter_len, 5834642e01fSmrg xFixed *params, 5844642e01fSmrg int nparams) 5854642e01fSmrg{ 5864642e01fSmrg PictFilterPtr filter = NULL; 5874642e01fSmrg int width = 0, height = 0; 5884642e01fSmrg 5894642e01fSmrg if (!crtc->transforms) 5904642e01fSmrg return BadValue; 5914642e01fSmrg 5924642e01fSmrg if (filter_len) 5934642e01fSmrg { 5944642e01fSmrg filter = PictureFindFilter (crtc->pScreen, 5954642e01fSmrg filter_name, 5964642e01fSmrg filter_len); 5974642e01fSmrg if (!filter) 5984642e01fSmrg return BadName; 5994642e01fSmrg if (filter->ValidateParams) 6004642e01fSmrg { 6014642e01fSmrg if (!filter->ValidateParams (crtc->pScreen, filter->id, 6024642e01fSmrg params, nparams, &width, &height)) 6034642e01fSmrg return BadMatch; 6044642e01fSmrg } 6054642e01fSmrg else { 6064642e01fSmrg width = filter->width; 6074642e01fSmrg height = filter->height; 6084642e01fSmrg } 6094642e01fSmrg } 6104642e01fSmrg else 6114642e01fSmrg { 6124642e01fSmrg if (nparams) 6134642e01fSmrg return BadMatch; 6144642e01fSmrg } 6154642e01fSmrg if (!RRTransformSetFilter (&crtc->client_pending_transform, 6164642e01fSmrg filter, params, nparams, width, height)) 6174642e01fSmrg return BadAlloc; 6184642e01fSmrg 6194642e01fSmrg crtc->client_pending_transform.transform = *transform; 6204642e01fSmrg crtc->client_pending_transform.f_transform = *f_transform; 6214642e01fSmrg crtc->client_pending_transform.f_inverse = *f_inverse; 6224642e01fSmrg return Success; 6234642e01fSmrg} 6244642e01fSmrg 62505b261ecSmrg/* 62605b261ecSmrg * Initialize crtc type 62705b261ecSmrg */ 62805b261ecSmrgBool 62905b261ecSmrgRRCrtcInit (void) 63005b261ecSmrg{ 6316747b715Smrg RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource, "CRTC"); 63205b261ecSmrg if (!RRCrtcType) 63305b261ecSmrg return FALSE; 6346747b715Smrg 63505b261ecSmrg return TRUE; 63605b261ecSmrg} 63705b261ecSmrg 6386747b715Smrg/* 6396747b715Smrg * Initialize crtc type error value 6406747b715Smrg */ 6416747b715Smrgvoid 6426747b715SmrgRRCrtcInitErrorValue(void) 6436747b715Smrg{ 6446747b715Smrg SetResourceTypeErrorValue(RRCrtcType, RRErrorBase + BadRRCrtc); 6456747b715Smrg} 6466747b715Smrg 64705b261ecSmrgint 64805b261ecSmrgProcRRGetCrtcInfo (ClientPtr client) 64905b261ecSmrg{ 65005b261ecSmrg REQUEST(xRRGetCrtcInfoReq); 65105b261ecSmrg xRRGetCrtcInfoReply rep; 65205b261ecSmrg RRCrtcPtr crtc; 65305b261ecSmrg CARD8 *extra; 65405b261ecSmrg unsigned long extraLen; 65505b261ecSmrg ScreenPtr pScreen; 65605b261ecSmrg rrScrPrivPtr pScrPriv; 65705b261ecSmrg RRModePtr mode; 65805b261ecSmrg RROutput *outputs; 65905b261ecSmrg RROutput *possible; 66005b261ecSmrg int i, j, k, n; 66105b261ecSmrg int width, height; 6624642e01fSmrg BoxRec panned_area; 66305b261ecSmrg 66405b261ecSmrg REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); 6656747b715Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 66605b261ecSmrg 66705b261ecSmrg /* All crtcs must be associated with screens before client 66805b261ecSmrg * requests are processed 66905b261ecSmrg */ 67005b261ecSmrg pScreen = crtc->pScreen; 67105b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 67205b261ecSmrg 67305b261ecSmrg mode = crtc->mode; 67405b261ecSmrg 67505b261ecSmrg rep.type = X_Reply; 67605b261ecSmrg rep.status = RRSetConfigSuccess; 67705b261ecSmrg rep.sequenceNumber = client->sequence; 67805b261ecSmrg rep.length = 0; 67905b261ecSmrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 6804642e01fSmrg if (pScrPriv->rrGetPanning && 6814642e01fSmrg pScrPriv->rrGetPanning (pScreen, crtc, &panned_area, NULL, NULL) && 6824642e01fSmrg (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1)) 6834642e01fSmrg { 6844642e01fSmrg rep.x = panned_area.x1; 6854642e01fSmrg rep.y = panned_area.y1; 6864642e01fSmrg rep.width = panned_area.x2 - panned_area.x1; 6874642e01fSmrg rep.height = panned_area.y2 - panned_area.y1; 6884642e01fSmrg } 6894642e01fSmrg else 6904642e01fSmrg { 6914642e01fSmrg RRCrtcGetScanoutSize (crtc, &width, &height); 6924642e01fSmrg rep.x = crtc->x; 6934642e01fSmrg rep.y = crtc->y; 6944642e01fSmrg rep.width = width; 6954642e01fSmrg rep.height = height; 6964642e01fSmrg } 69705b261ecSmrg rep.mode = mode ? mode->mode.id : 0; 69805b261ecSmrg rep.rotation = crtc->rotation; 69905b261ecSmrg rep.rotations = crtc->rotations; 70005b261ecSmrg rep.nOutput = crtc->numOutputs; 70105b261ecSmrg k = 0; 70205b261ecSmrg for (i = 0; i < pScrPriv->numOutputs; i++) 70305b261ecSmrg for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) 70405b261ecSmrg if (pScrPriv->outputs[i]->crtcs[j] == crtc) 70505b261ecSmrg k++; 70605b261ecSmrg rep.nPossibleOutput = k; 70705b261ecSmrg 70805b261ecSmrg rep.length = rep.nOutput + rep.nPossibleOutput; 70905b261ecSmrg 71005b261ecSmrg extraLen = rep.length << 2; 71105b261ecSmrg if (extraLen) 71205b261ecSmrg { 7136747b715Smrg extra = malloc(extraLen); 71405b261ecSmrg if (!extra) 71505b261ecSmrg return BadAlloc; 71605b261ecSmrg } 71705b261ecSmrg else 71805b261ecSmrg extra = NULL; 71905b261ecSmrg 72005b261ecSmrg outputs = (RROutput *) extra; 72105b261ecSmrg possible = (RROutput *) (outputs + rep.nOutput); 72205b261ecSmrg 72305b261ecSmrg for (i = 0; i < crtc->numOutputs; i++) 72405b261ecSmrg { 72505b261ecSmrg outputs[i] = crtc->outputs[i]->id; 72605b261ecSmrg if (client->swapped) 72705b261ecSmrg swapl (&outputs[i], n); 72805b261ecSmrg } 72905b261ecSmrg k = 0; 73005b261ecSmrg for (i = 0; i < pScrPriv->numOutputs; i++) 73105b261ecSmrg for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) 73205b261ecSmrg if (pScrPriv->outputs[i]->crtcs[j] == crtc) 73305b261ecSmrg { 73405b261ecSmrg possible[k] = pScrPriv->outputs[i]->id; 73505b261ecSmrg if (client->swapped) 73605b261ecSmrg swapl (&possible[k], n); 73705b261ecSmrg k++; 73805b261ecSmrg } 73905b261ecSmrg 74005b261ecSmrg if (client->swapped) { 74105b261ecSmrg swaps(&rep.sequenceNumber, n); 74205b261ecSmrg swapl(&rep.length, n); 74305b261ecSmrg swapl(&rep.timestamp, n); 74405b261ecSmrg swaps(&rep.x, n); 74505b261ecSmrg swaps(&rep.y, n); 74605b261ecSmrg swaps(&rep.width, n); 74705b261ecSmrg swaps(&rep.height, n); 74805b261ecSmrg swapl(&rep.mode, n); 74905b261ecSmrg swaps(&rep.rotation, n); 75005b261ecSmrg swaps(&rep.rotations, n); 75105b261ecSmrg swaps(&rep.nOutput, n); 75205b261ecSmrg swaps(&rep.nPossibleOutput, n); 75305b261ecSmrg } 75405b261ecSmrg WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep); 75505b261ecSmrg if (extraLen) 75605b261ecSmrg { 75705b261ecSmrg WriteToClient (client, extraLen, (char *) extra); 7586747b715Smrg free(extra); 75905b261ecSmrg } 76005b261ecSmrg 7616747b715Smrg return Success; 76205b261ecSmrg} 76305b261ecSmrg 76405b261ecSmrgint 76505b261ecSmrgProcRRSetCrtcConfig (ClientPtr client) 76605b261ecSmrg{ 76705b261ecSmrg REQUEST(xRRSetCrtcConfigReq); 76805b261ecSmrg xRRSetCrtcConfigReply rep; 76905b261ecSmrg ScreenPtr pScreen; 77005b261ecSmrg rrScrPrivPtr pScrPriv; 77105b261ecSmrg RRCrtcPtr crtc; 77205b261ecSmrg RRModePtr mode; 77305b261ecSmrg int numOutputs; 77405b261ecSmrg RROutputPtr *outputs = NULL; 77505b261ecSmrg RROutput *outputIds; 77605b261ecSmrg TimeStamp configTime; 77705b261ecSmrg TimeStamp time; 77805b261ecSmrg Rotation rotation; 7796747b715Smrg int rc, i, j; 78005b261ecSmrg 78105b261ecSmrg REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq); 7826747b715Smrg numOutputs = (stuff->length - bytes_to_int32(SIZEOF (xRRSetCrtcConfigReq))); 78305b261ecSmrg 7846747b715Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess); 7856747b715Smrg 78605b261ecSmrg if (stuff->mode == None) 78705b261ecSmrg { 78805b261ecSmrg mode = NULL; 78905b261ecSmrg if (numOutputs > 0) 79005b261ecSmrg return BadMatch; 79105b261ecSmrg } 79205b261ecSmrg else 79305b261ecSmrg { 7946747b715Smrg VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess); 79505b261ecSmrg if (numOutputs == 0) 79605b261ecSmrg return BadMatch; 79705b261ecSmrg } 79805b261ecSmrg if (numOutputs) 79905b261ecSmrg { 8006747b715Smrg outputs = malloc(numOutputs * sizeof (RROutputPtr)); 80105b261ecSmrg if (!outputs) 80205b261ecSmrg return BadAlloc; 80305b261ecSmrg } 80405b261ecSmrg else 80505b261ecSmrg outputs = NULL; 80605b261ecSmrg 80705b261ecSmrg outputIds = (RROutput *) (stuff + 1); 80805b261ecSmrg for (i = 0; i < numOutputs; i++) 80905b261ecSmrg { 8106747b715Smrg rc = dixLookupResourceByType((pointer *)(outputs + i), outputIds[i], 8116747b715Smrg RROutputType, client, DixSetAttrAccess); 8126747b715Smrg if (rc != Success) 81305b261ecSmrg { 8146747b715Smrg free(outputs); 8156747b715Smrg return rc; 81605b261ecSmrg } 81705b261ecSmrg /* validate crtc for this output */ 81805b261ecSmrg for (j = 0; j < outputs[i]->numCrtcs; j++) 81905b261ecSmrg if (outputs[i]->crtcs[j] == crtc) 82005b261ecSmrg break; 82105b261ecSmrg if (j == outputs[i]->numCrtcs) 82205b261ecSmrg { 8236747b715Smrg free(outputs); 82405b261ecSmrg return BadMatch; 82505b261ecSmrg } 82605b261ecSmrg /* validate mode for this output */ 82705b261ecSmrg for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++) 82805b261ecSmrg { 82905b261ecSmrg RRModePtr m = (j < outputs[i]->numModes ? 83005b261ecSmrg outputs[i]->modes[j] : 83105b261ecSmrg outputs[i]->userModes[j - outputs[i]->numModes]); 83205b261ecSmrg if (m == mode) 83305b261ecSmrg break; 83405b261ecSmrg } 83505b261ecSmrg if (j == outputs[i]->numModes + outputs[i]->numUserModes) 83605b261ecSmrg { 8376747b715Smrg free(outputs); 83805b261ecSmrg return BadMatch; 83905b261ecSmrg } 84005b261ecSmrg } 84105b261ecSmrg /* validate clones */ 84205b261ecSmrg for (i = 0; i < numOutputs; i++) 84305b261ecSmrg { 84405b261ecSmrg for (j = 0; j < numOutputs; j++) 84505b261ecSmrg { 84605b261ecSmrg int k; 84705b261ecSmrg if (i == j) 84805b261ecSmrg continue; 84905b261ecSmrg for (k = 0; k < outputs[i]->numClones; k++) 85005b261ecSmrg { 85105b261ecSmrg if (outputs[i]->clones[k] == outputs[j]) 85205b261ecSmrg break; 85305b261ecSmrg } 85405b261ecSmrg if (k == outputs[i]->numClones) 85505b261ecSmrg { 8566747b715Smrg free(outputs); 85705b261ecSmrg return BadMatch; 85805b261ecSmrg } 85905b261ecSmrg } 86005b261ecSmrg } 86105b261ecSmrg 86205b261ecSmrg pScreen = crtc->pScreen; 86305b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 86405b261ecSmrg 86505b261ecSmrg time = ClientTimeToServerTime(stuff->timestamp); 86605b261ecSmrg configTime = ClientTimeToServerTime(stuff->configTimestamp); 86705b261ecSmrg 86805b261ecSmrg if (!pScrPriv) 86905b261ecSmrg { 87005b261ecSmrg time = currentTime; 87105b261ecSmrg rep.status = RRSetConfigFailed; 87205b261ecSmrg goto sendReply; 87305b261ecSmrg } 87405b261ecSmrg 87505b261ecSmrg /* 87605b261ecSmrg * Validate requested rotation 87705b261ecSmrg */ 87805b261ecSmrg rotation = (Rotation) stuff->rotation; 87905b261ecSmrg 88005b261ecSmrg /* test the rotation bits only! */ 88105b261ecSmrg switch (rotation & 0xf) { 88205b261ecSmrg case RR_Rotate_0: 88305b261ecSmrg case RR_Rotate_90: 88405b261ecSmrg case RR_Rotate_180: 88505b261ecSmrg case RR_Rotate_270: 88605b261ecSmrg break; 88705b261ecSmrg default: 88805b261ecSmrg /* 88905b261ecSmrg * Invalid rotation 89005b261ecSmrg */ 89105b261ecSmrg client->errorValue = stuff->rotation; 8926747b715Smrg free(outputs); 89305b261ecSmrg return BadValue; 89405b261ecSmrg } 89505b261ecSmrg 89605b261ecSmrg if (mode) 89705b261ecSmrg { 89805b261ecSmrg if ((~crtc->rotations) & rotation) 89905b261ecSmrg { 90005b261ecSmrg /* 90105b261ecSmrg * requested rotation or reflection not supported by screen 90205b261ecSmrg */ 90305b261ecSmrg client->errorValue = stuff->rotation; 9046747b715Smrg free(outputs); 90505b261ecSmrg return BadMatch; 90605b261ecSmrg } 90705b261ecSmrg 90805b261ecSmrg#ifdef RANDR_12_INTERFACE 90905b261ecSmrg /* 91005b261ecSmrg * Check screen size bounds if the DDX provides a 1.2 interface 91105b261ecSmrg * for setting screen size. Else, assume the CrtcSet sets 9124642e01fSmrg * the size along with the mode. If the driver supports transforms, 9134642e01fSmrg * then it must allow crtcs to display a subset of the screen, so 9144642e01fSmrg * only do this check for drivers without transform support. 91505b261ecSmrg */ 9164642e01fSmrg if (pScrPriv->rrScreenSetSize && !crtc->transforms) 91705b261ecSmrg { 9184642e01fSmrg int source_width; 9194642e01fSmrg int source_height; 9204642e01fSmrg PictTransform transform; 9214642e01fSmrg struct pixman_f_transform f_transform, f_inverse; 92205b261ecSmrg 9234642e01fSmrg RRTransformCompute (stuff->x, stuff->y, 9244642e01fSmrg mode->mode.width, mode->mode.height, 9254642e01fSmrg rotation, 9264642e01fSmrg &crtc->client_pending_transform, 9274642e01fSmrg &transform, &f_transform, &f_inverse); 9284642e01fSmrg 9294642e01fSmrg RRModeGetScanoutSize (mode, &transform, &source_width, &source_height); 93005b261ecSmrg if (stuff->x + source_width > pScreen->width) 93105b261ecSmrg { 93205b261ecSmrg client->errorValue = stuff->x; 9336747b715Smrg free(outputs); 93405b261ecSmrg return BadValue; 93505b261ecSmrg } 93605b261ecSmrg 93705b261ecSmrg if (stuff->y + source_height > pScreen->height) 93805b261ecSmrg { 93905b261ecSmrg client->errorValue = stuff->y; 9406747b715Smrg free(outputs); 94105b261ecSmrg return BadValue; 94205b261ecSmrg } 94305b261ecSmrg } 94405b261ecSmrg#endif 94505b261ecSmrg } 94605b261ecSmrg 94705b261ecSmrg if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y, 94805b261ecSmrg rotation, numOutputs, outputs)) 94905b261ecSmrg { 95005b261ecSmrg rep.status = RRSetConfigFailed; 95105b261ecSmrg goto sendReply; 95205b261ecSmrg } 95305b261ecSmrg rep.status = RRSetConfigSuccess; 95452397711Smrg pScrPriv->lastSetTime = time; 95505b261ecSmrg 95605b261ecSmrgsendReply: 9576747b715Smrg free(outputs); 95805b261ecSmrg 95905b261ecSmrg rep.type = X_Reply; 96005b261ecSmrg /* rep.status has already been filled in */ 96105b261ecSmrg rep.length = 0; 96205b261ecSmrg rep.sequenceNumber = client->sequence; 96352397711Smrg rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; 96405b261ecSmrg 96505b261ecSmrg if (client->swapped) 96605b261ecSmrg { 96705b261ecSmrg int n; 96805b261ecSmrg swaps(&rep.sequenceNumber, n); 96905b261ecSmrg swapl(&rep.length, n); 97005b261ecSmrg swapl(&rep.newTimestamp, n); 97105b261ecSmrg } 97205b261ecSmrg WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep); 97305b261ecSmrg 9746747b715Smrg return Success; 97505b261ecSmrg} 97605b261ecSmrg 9774642e01fSmrgint 9784642e01fSmrgProcRRGetPanning (ClientPtr client) 9794642e01fSmrg{ 9804642e01fSmrg REQUEST(xRRGetPanningReq); 9814642e01fSmrg xRRGetPanningReply rep; 9824642e01fSmrg RRCrtcPtr crtc; 9834642e01fSmrg ScreenPtr pScreen; 9844642e01fSmrg rrScrPrivPtr pScrPriv; 9854642e01fSmrg BoxRec total; 9864642e01fSmrg BoxRec tracking; 9874642e01fSmrg INT16 border[4]; 9884642e01fSmrg int n; 9894642e01fSmrg 9904642e01fSmrg REQUEST_SIZE_MATCH(xRRGetPanningReq); 9916747b715Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 9924642e01fSmrg 9934642e01fSmrg /* All crtcs must be associated with screens before client 9944642e01fSmrg * requests are processed 9954642e01fSmrg */ 9964642e01fSmrg pScreen = crtc->pScreen; 9974642e01fSmrg pScrPriv = rrGetScrPriv(pScreen); 9984642e01fSmrg 9994642e01fSmrg if (!pScrPriv) 10004642e01fSmrg return RRErrorBase + BadRRCrtc; 10014642e01fSmrg 10024642e01fSmrg memset(&rep, 0, sizeof(rep)); 10034642e01fSmrg rep.type = X_Reply; 10044642e01fSmrg rep.status = RRSetConfigSuccess; 10054642e01fSmrg rep.sequenceNumber = client->sequence; 10064642e01fSmrg rep.length = 1; 10074642e01fSmrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 10084642e01fSmrg 10094642e01fSmrg if (pScrPriv->rrGetPanning && 10104642e01fSmrg pScrPriv->rrGetPanning (pScreen, crtc, &total, &tracking, border)) { 10114642e01fSmrg rep.left = total.x1; 10124642e01fSmrg rep.top = total.y1; 10134642e01fSmrg rep.width = total.x2 - total.x1; 10144642e01fSmrg rep.height = total.y2 - total.y1; 10154642e01fSmrg rep.track_left = tracking.x1; 10164642e01fSmrg rep.track_top = tracking.y1; 10174642e01fSmrg rep.track_width = tracking.x2 - tracking.x1; 10184642e01fSmrg rep.track_height = tracking.y2 - tracking.y1; 10194642e01fSmrg rep.border_left = border[0]; 10204642e01fSmrg rep.border_top = border[1]; 10214642e01fSmrg rep.border_right = border[2]; 10224642e01fSmrg rep.border_bottom = border[3]; 10234642e01fSmrg } 10244642e01fSmrg 10254642e01fSmrg if (client->swapped) { 10264642e01fSmrg swaps(&rep.sequenceNumber, n); 10274642e01fSmrg swapl(&rep.length, n); 10284642e01fSmrg swaps(&rep.timestamp, n); 10294642e01fSmrg swaps(&rep.left, n); 10304642e01fSmrg swaps(&rep.top, n); 10314642e01fSmrg swaps(&rep.width, n); 10324642e01fSmrg swaps(&rep.height, n); 10334642e01fSmrg swaps(&rep.track_left, n); 10344642e01fSmrg swaps(&rep.track_top, n); 10354642e01fSmrg swaps(&rep.track_width, n); 10364642e01fSmrg swaps(&rep.track_height, n); 10374642e01fSmrg swaps(&rep.border_left, n); 10384642e01fSmrg swaps(&rep.border_top, n); 10394642e01fSmrg swaps(&rep.border_right, n); 10404642e01fSmrg swaps(&rep.border_bottom, n); 10414642e01fSmrg } 10424642e01fSmrg WriteToClient(client, sizeof(xRRGetPanningReply), (char *)&rep); 10436747b715Smrg return Success; 10444642e01fSmrg} 10454642e01fSmrg 10464642e01fSmrgint 10474642e01fSmrgProcRRSetPanning (ClientPtr client) 10484642e01fSmrg{ 10494642e01fSmrg REQUEST(xRRSetPanningReq); 10504642e01fSmrg xRRSetPanningReply rep; 10514642e01fSmrg RRCrtcPtr crtc; 10524642e01fSmrg ScreenPtr pScreen; 10534642e01fSmrg rrScrPrivPtr pScrPriv; 10544642e01fSmrg TimeStamp time; 10554642e01fSmrg BoxRec total; 10564642e01fSmrg BoxRec tracking; 10574642e01fSmrg INT16 border[4]; 10584642e01fSmrg int n; 10594642e01fSmrg 10604642e01fSmrg REQUEST_SIZE_MATCH(xRRSetPanningReq); 10616747b715Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 10624642e01fSmrg 10634642e01fSmrg /* All crtcs must be associated with screens before client 10644642e01fSmrg * requests are processed 10654642e01fSmrg */ 10664642e01fSmrg pScreen = crtc->pScreen; 10674642e01fSmrg pScrPriv = rrGetScrPriv(pScreen); 10684642e01fSmrg 10694642e01fSmrg if (!pScrPriv) { 10704642e01fSmrg time = currentTime; 10714642e01fSmrg rep.status = RRSetConfigFailed; 10724642e01fSmrg goto sendReply; 10734642e01fSmrg } 10744642e01fSmrg 10754642e01fSmrg time = ClientTimeToServerTime(stuff->timestamp); 10764642e01fSmrg 10774642e01fSmrg if (!pScrPriv->rrGetPanning) 10784642e01fSmrg return RRErrorBase + BadRRCrtc; 10794642e01fSmrg 10804642e01fSmrg total.x1 = stuff->left; 10814642e01fSmrg total.y1 = stuff->top; 10824642e01fSmrg total.x2 = total.x1 + stuff->width; 10834642e01fSmrg total.y2 = total.y1 + stuff->height; 10844642e01fSmrg tracking.x1 = stuff->track_left; 10854642e01fSmrg tracking.y1 = stuff->track_top; 10864642e01fSmrg tracking.x2 = tracking.x1 + stuff->track_width; 10874642e01fSmrg tracking.y2 = tracking.y1 + stuff->track_height; 10884642e01fSmrg border[0] = stuff->border_left; 10894642e01fSmrg border[1] = stuff->border_top; 10904642e01fSmrg border[2] = stuff->border_right; 10914642e01fSmrg border[3] = stuff->border_bottom; 10924642e01fSmrg 10934642e01fSmrg if (! pScrPriv->rrSetPanning (pScreen, crtc, &total, &tracking, border)) 10944642e01fSmrg return BadMatch; 10954642e01fSmrg 109652397711Smrg pScrPriv->lastSetTime = time; 109752397711Smrg 10984642e01fSmrg rep.status = RRSetConfigSuccess; 10994642e01fSmrg 11004642e01fSmrgsendReply: 11014642e01fSmrg rep.type = X_Reply; 11024642e01fSmrg rep.sequenceNumber = client->sequence; 11034642e01fSmrg rep.length = 0; 11044642e01fSmrg rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; 11054642e01fSmrg 11064642e01fSmrg if (client->swapped) { 11074642e01fSmrg swaps(&rep.sequenceNumber, n); 11084642e01fSmrg swapl(&rep.length, n); 11094642e01fSmrg swaps(&rep.newTimestamp, n); 11104642e01fSmrg } 11114642e01fSmrg WriteToClient(client, sizeof(xRRSetPanningReply), (char *)&rep); 11126747b715Smrg return Success; 11134642e01fSmrg} 11144642e01fSmrg 111505b261ecSmrgint 111605b261ecSmrgProcRRGetCrtcGammaSize (ClientPtr client) 111705b261ecSmrg{ 111805b261ecSmrg REQUEST(xRRGetCrtcGammaSizeReq); 111905b261ecSmrg xRRGetCrtcGammaSizeReply reply; 112005b261ecSmrg RRCrtcPtr crtc; 112105b261ecSmrg int n; 112205b261ecSmrg 112305b261ecSmrg REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq); 11246747b715Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 11256747b715Smrg 11266747b715Smrg /* Gamma retrieval failed, any better error? */ 11276747b715Smrg if (!RRCrtcGammaGet(crtc)) 11286747b715Smrg return RRErrorBase + BadRRCrtc; 11296747b715Smrg 113005b261ecSmrg reply.type = X_Reply; 113105b261ecSmrg reply.sequenceNumber = client->sequence; 113205b261ecSmrg reply.length = 0; 113305b261ecSmrg reply.size = crtc->gammaSize; 113405b261ecSmrg if (client->swapped) { 113505b261ecSmrg swaps (&reply.sequenceNumber, n); 113605b261ecSmrg swapl (&reply.length, n); 113705b261ecSmrg swaps (&reply.size, n); 113805b261ecSmrg } 113905b261ecSmrg WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply); 11406747b715Smrg return Success; 114105b261ecSmrg} 114205b261ecSmrg 114305b261ecSmrgint 114405b261ecSmrgProcRRGetCrtcGamma (ClientPtr client) 114505b261ecSmrg{ 114605b261ecSmrg REQUEST(xRRGetCrtcGammaReq); 114705b261ecSmrg xRRGetCrtcGammaReply reply; 114805b261ecSmrg RRCrtcPtr crtc; 114905b261ecSmrg int n; 115005b261ecSmrg unsigned long len; 11514642e01fSmrg char *extra = NULL; 115205b261ecSmrg 115305b261ecSmrg REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq); 11546747b715Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 11556747b715Smrg 11566747b715Smrg /* Gamma retrieval failed, any better error? */ 11576747b715Smrg if (!RRCrtcGammaGet(crtc)) 11586747b715Smrg return RRErrorBase + BadRRCrtc; 11596747b715Smrg 116005b261ecSmrg len = crtc->gammaSize * 3 * 2; 116105b261ecSmrg 11624642e01fSmrg if (crtc->gammaSize) { 11636747b715Smrg extra = malloc(len); 11644642e01fSmrg if (!extra) 11654642e01fSmrg return BadAlloc; 11664642e01fSmrg } 11674642e01fSmrg 116805b261ecSmrg reply.type = X_Reply; 116905b261ecSmrg reply.sequenceNumber = client->sequence; 11706747b715Smrg reply.length = bytes_to_int32(len); 117105b261ecSmrg reply.size = crtc->gammaSize; 117205b261ecSmrg if (client->swapped) { 117305b261ecSmrg swaps (&reply.sequenceNumber, n); 117405b261ecSmrg swapl (&reply.length, n); 117505b261ecSmrg swaps (&reply.size, n); 117605b261ecSmrg } 117705b261ecSmrg WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply); 117805b261ecSmrg if (crtc->gammaSize) 117905b261ecSmrg { 11804642e01fSmrg memcpy(extra, crtc->gammaRed, len); 118105b261ecSmrg client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; 11824642e01fSmrg WriteSwappedDataToClient (client, len, extra); 11836747b715Smrg free(extra); 118405b261ecSmrg } 11856747b715Smrg return Success; 118605b261ecSmrg} 118705b261ecSmrg 118805b261ecSmrgint 118905b261ecSmrgProcRRSetCrtcGamma (ClientPtr client) 119005b261ecSmrg{ 119105b261ecSmrg REQUEST(xRRSetCrtcGammaReq); 119205b261ecSmrg RRCrtcPtr crtc; 119305b261ecSmrg unsigned long len; 119405b261ecSmrg CARD16 *red, *green, *blue; 119505b261ecSmrg 119605b261ecSmrg REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq); 11976747b715Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 119805b261ecSmrg 11996747b715Smrg len = client->req_len - bytes_to_int32(sizeof (xRRSetCrtcGammaReq)); 120005b261ecSmrg if (len < (stuff->size * 3 + 1) >> 1) 120105b261ecSmrg return BadLength; 120205b261ecSmrg 120305b261ecSmrg if (stuff->size != crtc->gammaSize) 120405b261ecSmrg return BadMatch; 120505b261ecSmrg 120605b261ecSmrg red = (CARD16 *) (stuff + 1); 120705b261ecSmrg green = red + crtc->gammaSize; 120805b261ecSmrg blue = green + crtc->gammaSize; 120905b261ecSmrg 121005b261ecSmrg RRCrtcGammaSet (crtc, red, green, blue); 121105b261ecSmrg 121205b261ecSmrg return Success; 121305b261ecSmrg} 121405b261ecSmrg 12154642e01fSmrg/* Version 1.3 additions */ 12164642e01fSmrg 12174642e01fSmrgint 12184642e01fSmrgProcRRSetCrtcTransform (ClientPtr client) 12194642e01fSmrg{ 12204642e01fSmrg REQUEST(xRRSetCrtcTransformReq); 12214642e01fSmrg RRCrtcPtr crtc; 12224642e01fSmrg PictTransform transform; 12234642e01fSmrg struct pixman_f_transform f_transform, f_inverse; 12244642e01fSmrg char *filter; 12254642e01fSmrg int nbytes; 12264642e01fSmrg xFixed *params; 12274642e01fSmrg int nparams; 12284642e01fSmrg 12294642e01fSmrg REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq); 12306747b715Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 12314642e01fSmrg 12324642e01fSmrg PictTransform_from_xRenderTransform (&transform, &stuff->transform); 12334642e01fSmrg pixman_f_transform_from_pixman_transform (&f_transform, &transform); 12344642e01fSmrg if (!pixman_f_transform_invert (&f_inverse, &f_transform)) 12354642e01fSmrg return BadMatch; 12364642e01fSmrg 12374642e01fSmrg filter = (char *) (stuff + 1); 12384642e01fSmrg nbytes = stuff->nbytesFilter; 12396747b715Smrg params = (xFixed *) (filter + pad_to_int32(nbytes)); 12404642e01fSmrg nparams = ((xFixed *) stuff + client->req_len) - params; 12414642e01fSmrg if (nparams < 0) 12424642e01fSmrg return BadLength; 12434642e01fSmrg 12444642e01fSmrg return RRCrtcTransformSet (crtc, &transform, &f_transform, &f_inverse, 12454642e01fSmrg filter, nbytes, params, nparams); 12464642e01fSmrg} 12474642e01fSmrg 12484642e01fSmrg 12494642e01fSmrg#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32) 12504642e01fSmrg 12514642e01fSmrgstatic int 12524642e01fSmrgtransform_filter_length (RRTransformPtr transform) 12534642e01fSmrg{ 12544642e01fSmrg int nbytes, nparams; 12554642e01fSmrg 12564642e01fSmrg if (transform->filter == NULL) 12574642e01fSmrg return 0; 12584642e01fSmrg nbytes = strlen (transform->filter->name); 12594642e01fSmrg nparams = transform->nparams; 12606747b715Smrg return pad_to_int32(nbytes) + (nparams * sizeof (xFixed)); 12614642e01fSmrg} 12624642e01fSmrg 12634642e01fSmrgstatic int 12644642e01fSmrgtransform_filter_encode (ClientPtr client, char *output, 12654642e01fSmrg CARD16 *nbytesFilter, 12664642e01fSmrg CARD16 *nparamsFilter, 12674642e01fSmrg RRTransformPtr transform) 12684642e01fSmrg{ 12694642e01fSmrg int nbytes, nparams; 12704642e01fSmrg int n; 12714642e01fSmrg 12724642e01fSmrg if (transform->filter == NULL) { 12734642e01fSmrg *nbytesFilter = 0; 12744642e01fSmrg *nparamsFilter = 0; 12754642e01fSmrg return 0; 12764642e01fSmrg } 12774642e01fSmrg nbytes = strlen (transform->filter->name); 12784642e01fSmrg nparams = transform->nparams; 12794642e01fSmrg *nbytesFilter = nbytes; 12804642e01fSmrg *nparamsFilter = nparams; 12814642e01fSmrg memcpy (output, transform->filter->name, nbytes); 12824642e01fSmrg while ((nbytes & 3) != 0) 12834642e01fSmrg output[nbytes++] = 0; 12844642e01fSmrg memcpy (output + nbytes, transform->params, nparams * sizeof (xFixed)); 12854642e01fSmrg if (client->swapped) { 12864642e01fSmrg swaps (nbytesFilter, n); 12874642e01fSmrg swaps (nparamsFilter, n); 12884642e01fSmrg SwapLongs ((CARD32 *) (output + nbytes), nparams); 12894642e01fSmrg } 12904642e01fSmrg nbytes += nparams * sizeof (xFixed); 12914642e01fSmrg return nbytes; 12924642e01fSmrg} 12934642e01fSmrg 12944642e01fSmrgstatic void 12954642e01fSmrgtransform_encode (ClientPtr client, xRenderTransform *wire, PictTransform *pict) 12964642e01fSmrg{ 12974642e01fSmrg xRenderTransform_from_PictTransform (wire, pict); 12984642e01fSmrg if (client->swapped) 12996747b715Smrg SwapLongs ((CARD32 *) wire, bytes_to_int32(sizeof(xRenderTransform))); 13004642e01fSmrg} 13014642e01fSmrg 13024642e01fSmrgint 13034642e01fSmrgProcRRGetCrtcTransform (ClientPtr client) 13044642e01fSmrg{ 13054642e01fSmrg REQUEST(xRRGetCrtcTransformReq); 13064642e01fSmrg xRRGetCrtcTransformReply *reply; 13074642e01fSmrg RRCrtcPtr crtc; 13084642e01fSmrg int n, nextra; 13094642e01fSmrg RRTransformPtr current, pending; 13104642e01fSmrg char *extra; 13114642e01fSmrg 13124642e01fSmrg REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq); 13136747b715Smrg VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); 13144642e01fSmrg 13154642e01fSmrg pending = &crtc->client_pending_transform; 13164642e01fSmrg current = &crtc->client_current_transform; 13174642e01fSmrg 13184642e01fSmrg nextra = (transform_filter_length (pending) + 13194642e01fSmrg transform_filter_length (current)); 13204642e01fSmrg 13216747b715Smrg reply = malloc(sizeof (xRRGetCrtcTransformReply) + nextra); 13224642e01fSmrg if (!reply) 13234642e01fSmrg return BadAlloc; 13244642e01fSmrg 13254642e01fSmrg extra = (char *) (reply + 1); 13264642e01fSmrg reply->type = X_Reply; 13274642e01fSmrg reply->sequenceNumber = client->sequence; 13286747b715Smrg reply->length = bytes_to_int32(CrtcTransformExtra + nextra); 13294642e01fSmrg 13304642e01fSmrg reply->hasTransforms = crtc->transforms; 13314642e01fSmrg 13324642e01fSmrg transform_encode (client, &reply->pendingTransform, &pending->transform); 13334642e01fSmrg extra += transform_filter_encode (client, extra, 13344642e01fSmrg &reply->pendingNbytesFilter, 13354642e01fSmrg &reply->pendingNparamsFilter, 13364642e01fSmrg pending); 13374642e01fSmrg 13384642e01fSmrg transform_encode (client, &reply->currentTransform, ¤t->transform); 13394642e01fSmrg extra += transform_filter_encode (client, extra, 13404642e01fSmrg &reply->currentNbytesFilter, 13414642e01fSmrg &reply->currentNparamsFilter, 13424642e01fSmrg current); 13434642e01fSmrg 13444642e01fSmrg if (client->swapped) { 13454642e01fSmrg swaps (&reply->sequenceNumber, n); 13464642e01fSmrg swapl (&reply->length, n); 13474642e01fSmrg } 13484642e01fSmrg WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply); 13496747b715Smrg free(reply); 13506747b715Smrg return Success; 13514642e01fSmrg} 1352