diff options
Diffstat (limited to 'xorg-server/randr/rrcrtc.c')
-rw-r--r-- | xorg-server/randr/rrcrtc.c | 2774 |
1 files changed, 1387 insertions, 1387 deletions
diff --git a/xorg-server/randr/rrcrtc.c b/xorg-server/randr/rrcrtc.c index a9eb2d262..2544903e9 100644 --- a/xorg-server/randr/rrcrtc.c +++ b/xorg-server/randr/rrcrtc.c @@ -1,1387 +1,1387 @@ -/* - * Copyright © 2006 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include "randrstr.h" -#include "swaprep.h" - -RESTYPE RRCrtcType; - -/* - * Notify the CRTC of some change - */ -void -RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged) -{ - ScreenPtr pScreen = crtc->pScreen; - - crtc->changed = TRUE; - if (pScreen) - { - rrScrPriv(pScreen); - - pScrPriv->changed = TRUE; - /* - * Send ConfigureNotify on any layout change - */ - if (layoutChanged) - pScrPriv->layoutChanged = TRUE; - } -} - -/* - * Create a CRTC - */ -RRCrtcPtr -RRCrtcCreate (ScreenPtr pScreen, void *devPrivate) -{ - RRCrtcPtr crtc; - RRCrtcPtr *crtcs; - rrScrPrivPtr pScrPriv; - - if (!RRInit()) - return NULL; - - pScrPriv = rrGetScrPriv(pScreen); - - /* make space for the crtc pointer */ - if (pScrPriv->numCrtcs) - crtcs = xrealloc (pScrPriv->crtcs, - (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr)); - else - crtcs = xalloc (sizeof (RRCrtcPtr)); - if (!crtcs) - return FALSE; - pScrPriv->crtcs = crtcs; - - crtc = xcalloc (1, sizeof (RRCrtcRec)); - if (!crtc) - return NULL; - crtc->id = FakeClientID (0); - crtc->pScreen = pScreen; - crtc->mode = NULL; - crtc->x = 0; - crtc->y = 0; - crtc->rotation = RR_Rotate_0; - crtc->rotations = RR_Rotate_0; - crtc->outputs = NULL; - crtc->numOutputs = 0; - crtc->gammaSize = 0; - crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL; - crtc->changed = FALSE; - crtc->devPrivate = devPrivate; - RRTransformInit (&crtc->client_pending_transform); - RRTransformInit (&crtc->client_current_transform); - pixman_transform_init_identity (&crtc->transform); - pixman_f_transform_init_identity (&crtc->f_transform); - pixman_f_transform_init_identity (&crtc->f_inverse); - - if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc)) - return NULL; - - /* attach the screen and crtc together */ - crtc->pScreen = pScreen; - pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc; - - return crtc; -} - -/* - * Set the allowed rotations on a CRTC - */ -void -RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations) -{ - crtc->rotations = rotations; -} - -/* - * Set whether transforms are allowed on a CRTC - */ -void -RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms) -{ - crtc->transforms = transforms; -} - -/* - * Notify the extension that the Crtc has been reconfigured, - * the driver calls this whenever it has updated the mode - */ -Bool -RRCrtcNotify (RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - RRTransformPtr transform, - int numOutputs, - RROutputPtr *outputs) -{ - int i, j; - - /* - * Check to see if any of the new outputs were - * not in the old list and mark them as changed - */ - for (i = 0; i < numOutputs; i++) - { - for (j = 0; j < crtc->numOutputs; j++) - if (outputs[i] == crtc->outputs[j]) - break; - if (j == crtc->numOutputs) - { - outputs[i]->crtc = crtc; - RROutputChanged (outputs[i], FALSE); - RRCrtcChanged (crtc, FALSE); - } - } - /* - * Check to see if any of the old outputs are - * not in the new list and mark them as changed - */ - for (j = 0; j < crtc->numOutputs; j++) - { - for (i = 0; i < numOutputs; i++) - if (outputs[i] == crtc->outputs[j]) - break; - if (i == numOutputs) - { - if (crtc->outputs[j]->crtc == crtc) - crtc->outputs[j]->crtc = NULL; - RROutputChanged (crtc->outputs[j], FALSE); - RRCrtcChanged (crtc, FALSE); - } - } - /* - * Reallocate the crtc output array if necessary - */ - if (numOutputs != crtc->numOutputs) - { - RROutputPtr *newoutputs; - - if (numOutputs) - { - if (crtc->numOutputs) - newoutputs = xrealloc (crtc->outputs, - numOutputs * sizeof (RROutputPtr)); - else - newoutputs = xalloc (numOutputs * sizeof (RROutputPtr)); - if (!newoutputs) - return FALSE; - } - else - { - if (crtc->outputs) - xfree (crtc->outputs); - newoutputs = NULL; - } - crtc->outputs = newoutputs; - crtc->numOutputs = numOutputs; - } - /* - * Copy the new list of outputs into the crtc - */ - memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)); - /* - * Update remaining crtc fields - */ - if (mode != crtc->mode) - { - if (crtc->mode) - RRModeDestroy (crtc->mode); - crtc->mode = mode; - if (mode != NULL) - mode->refcnt++; - RRCrtcChanged (crtc, TRUE); - } - if (x != crtc->x) - { - crtc->x = x; - RRCrtcChanged (crtc, TRUE); - } - if (y != crtc->y) - { - crtc->y = y; - RRCrtcChanged (crtc, TRUE); - } - if (rotation != crtc->rotation) - { - crtc->rotation = rotation; - RRCrtcChanged (crtc, TRUE); - } - if (!RRTransformEqual (transform, &crtc->client_current_transform)) { - RRTransformCopy (&crtc->client_current_transform, transform); - RRCrtcChanged (crtc, TRUE); - } - if (crtc->changed && mode) - { - RRTransformCompute (x, y, - mode->mode.width, mode->mode.height, - rotation, - &crtc->client_current_transform, - &crtc->transform, &crtc->f_transform, - &crtc->f_inverse); - } - return TRUE; -} - -void -RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - rrScrPriv (pScreen); - xRRCrtcChangeNotifyEvent ce; - RRModePtr mode = crtc->mode; - - ce.type = RRNotify + RREventBase; - ce.subCode = RRNotify_CrtcChange; - ce.sequenceNumber = client->sequence; - ce.timestamp = pScrPriv->lastSetTime.milliseconds; - ce.window = pWin->drawable.id; - ce.crtc = crtc->id; - ce.rotation = crtc->rotation; - if (mode) - { - ce.mode = mode->mode.id; - ce.x = crtc->x; - ce.y = crtc->y; - ce.width = mode->mode.width; - ce.height = mode->mode.height; - } - else - { - ce.mode = None; - ce.x = 0; - ce.y = 0; - ce.width = 0; - ce.height = 0; - } - WriteEventsToClient (client, 1, (xEvent *) &ce); -} - -static Bool -RRCrtcPendingProperties (RRCrtcPtr crtc) -{ - ScreenPtr pScreen = crtc->pScreen; - rrScrPriv(pScreen); - int o; - - for (o = 0; o < pScrPriv->numOutputs; o++) - { - RROutputPtr output = pScrPriv->outputs[o]; - if (output->crtc == crtc && output->pendingProperties) - return TRUE; - } - return FALSE; -} - -/* - * Request that the Crtc be reconfigured - */ -Bool -RRCrtcSet (RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - int numOutputs, - RROutputPtr *outputs) -{ - ScreenPtr pScreen = crtc->pScreen; - Bool ret = FALSE; - rrScrPriv(pScreen); - - /* See if nothing changed */ - if (crtc->mode == mode && - crtc->x == x && - crtc->y == y && - crtc->rotation == rotation && - crtc->numOutputs == numOutputs && - !memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) && - !RRCrtcPendingProperties (crtc) && - !RRCrtcPendingTransform (crtc)) - { - ret = TRUE; - } - else - { -#if RANDR_12_INTERFACE - if (pScrPriv->rrCrtcSet) - { - ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, - rotation, numOutputs, outputs); - } - else -#endif - { -#if RANDR_10_INTERFACE - if (pScrPriv->rrSetConfig) - { - RRScreenSize size; - RRScreenRate rate; - - if (!mode) - { - RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL); - ret = TRUE; - } - else - { - size.width = mode->mode.width; - size.height = mode->mode.height; - if (outputs[0]->mmWidth && outputs[0]->mmHeight) - { - size.mmWidth = outputs[0]->mmWidth; - size.mmHeight = outputs[0]->mmHeight; - } - else - { - size.mmWidth = pScreen->mmWidth; - size.mmHeight = pScreen->mmHeight; - } - size.nRates = 1; - rate.rate = RRVerticalRefresh (&mode->mode); - size.pRates = &rate; - ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size); - /* - * Old 1.0 interface tied screen size to mode size - */ - if (ret) - { - RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs); - RRScreenSizeNotify (pScreen); - } - } - } -#endif - } - if (ret) - { - int o; - RRTellChanged (pScreen); - - for (o = 0; o < numOutputs; o++) - RRPostPendingProperties (outputs[o]); - } - } - return ret; -} - -/* - * Return crtc transform - */ -RRTransformPtr -RRCrtcGetTransform (RRCrtcPtr crtc) -{ - RRTransformPtr transform = &crtc->client_pending_transform; - - if (pixman_transform_is_identity (&transform->transform)) - return NULL; - return transform; -} - -/* - * Check whether the pending and current transforms are the same - */ -Bool -RRCrtcPendingTransform (RRCrtcPtr crtc) -{ - return memcmp (&crtc->client_current_transform.transform, - &crtc->client_pending_transform.transform, - sizeof (PictTransform)) != 0; -} - -/* - * Destroy a Crtc at shutdown - */ -void -RRCrtcDestroy (RRCrtcPtr crtc) -{ - FreeResource (crtc->id, 0); -} - -static int -RRCrtcDestroyResource (pointer value, XID pid) -{ - RRCrtcPtr crtc = (RRCrtcPtr) value; - ScreenPtr pScreen = crtc->pScreen; - - if (pScreen) - { - rrScrPriv(pScreen); - int i; - - for (i = 0; i < pScrPriv->numCrtcs; i++) - { - if (pScrPriv->crtcs[i] == crtc) - { - memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1, - (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr)); - --pScrPriv->numCrtcs; - break; - } - } - } - if (crtc->gammaRed) - xfree (crtc->gammaRed); - if (crtc->mode) - RRModeDestroy (crtc->mode); - xfree (crtc); - return 1; -} - -/* - * Request that the Crtc gamma be changed - */ - -Bool -RRCrtcGammaSet (RRCrtcPtr crtc, - CARD16 *red, - CARD16 *green, - CARD16 *blue) -{ - Bool ret = TRUE; -#if RANDR_12_INTERFACE - ScreenPtr pScreen = crtc->pScreen; -#endif - - memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16)); - memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16)); - memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16)); -#if RANDR_12_INTERFACE - if (pScreen) - { - rrScrPriv(pScreen); - if (pScrPriv->rrCrtcSetGamma) - ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc); - } -#endif - return ret; -} - -/* - * Request current gamma back from the DDX (if possible). - * This includes gamma size. - */ -Bool -RRCrtcGammaGet(RRCrtcPtr crtc) -{ - Bool ret = TRUE; -#if RANDR_12_INTERFACE - ScreenPtr pScreen = crtc->pScreen; -#endif - -#if RANDR_12_INTERFACE - if (pScreen) - { - rrScrPriv(pScreen); - if (pScrPriv->rrCrtcGetGamma) - ret = (*pScrPriv->rrCrtcGetGamma) (pScreen, crtc); - } -#endif - return ret; -} - -/* - * Notify the extension that the Crtc gamma has been changed - * The driver calls this whenever it has changed the gamma values - * in the RRCrtcRec - */ - -Bool -RRCrtcGammaNotify (RRCrtcPtr crtc) -{ - return TRUE; /* not much going on here */ -} - -static void -RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform, - int *width, int *height) -{ - BoxRec box; - - if (mode == NULL) { - *width = 0; - *height = 0; - return; - } - - box.x1 = 0; - box.y1 = 0; - box.x2 = mode->mode.width; - box.y2 = mode->mode.height; - - pixman_transform_bounds (transform, &box); - *width = box.x2 - box.x1; - *height = box.y2 - box.y1; -} - -/** - * Returns the width/height that the crtc scans out from the framebuffer - */ -void -RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height) -{ - return RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height); -} - -/* - * Set the size of the gamma table at server startup time - */ - -Bool -RRCrtcGammaSetSize (RRCrtcPtr crtc, - int size) -{ - CARD16 *gamma; - - if (size == crtc->gammaSize) - return TRUE; - if (size) - { - gamma = xalloc (size * 3 * sizeof (CARD16)); - if (!gamma) - return FALSE; - } - else - gamma = NULL; - if (crtc->gammaRed) - xfree (crtc->gammaRed); - crtc->gammaRed = gamma; - crtc->gammaGreen = gamma + size; - crtc->gammaBlue = gamma + size*2; - crtc->gammaSize = size; - return TRUE; -} - -/* - * Set the pending CRTC transformation - */ - -int -RRCrtcTransformSet (RRCrtcPtr crtc, - PictTransformPtr transform, - struct pixman_f_transform *f_transform, - struct pixman_f_transform *f_inverse, - char *filter_name, - int filter_len, - xFixed *params, - int nparams) -{ - PictFilterPtr filter = NULL; - int width = 0, height = 0; - - if (!crtc->transforms) - return BadValue; - - if (filter_len) - { - filter = PictureFindFilter (crtc->pScreen, - filter_name, - filter_len); - if (!filter) - return BadName; - if (filter->ValidateParams) - { - if (!filter->ValidateParams (crtc->pScreen, filter->id, - params, nparams, &width, &height)) - return BadMatch; - } - else { - width = filter->width; - height = filter->height; - } - } - else - { - if (nparams) - return BadMatch; - } - if (!RRTransformSetFilter (&crtc->client_pending_transform, - filter, params, nparams, width, height)) - return BadAlloc; - - crtc->client_pending_transform.transform = *transform; - crtc->client_pending_transform.f_transform = *f_transform; - crtc->client_pending_transform.f_inverse = *f_inverse; - return Success; -} - -/* - * Initialize crtc type - */ -Bool -RRCrtcInit (void) -{ - RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource, "CRTC"); - if (!RRCrtcType) - return FALSE; - return TRUE; -} - -int -ProcRRGetCrtcInfo (ClientPtr client) -{ - REQUEST(xRRGetCrtcInfoReq); - xRRGetCrtcInfoReply rep; - RRCrtcPtr crtc; - CARD8 *extra; - unsigned long extraLen; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - RRModePtr mode; - RROutput *outputs; - RROutput *possible; - int i, j, k, n; - int width, height; - BoxRec panned_area; - - REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* All crtcs must be associated with screens before client - * requests are processed - */ - pScreen = crtc->pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - mode = crtc->mode; - - rep.type = X_Reply; - rep.status = RRSetConfigSuccess; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.timestamp = pScrPriv->lastSetTime.milliseconds; - if (pScrPriv->rrGetPanning && - pScrPriv->rrGetPanning (pScreen, crtc, &panned_area, NULL, NULL) && - (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1)) - { - rep.x = panned_area.x1; - rep.y = panned_area.y1; - rep.width = panned_area.x2 - panned_area.x1; - rep.height = panned_area.y2 - panned_area.y1; - } - else - { - RRCrtcGetScanoutSize (crtc, &width, &height); - rep.x = crtc->x; - rep.y = crtc->y; - rep.width = width; - rep.height = height; - } - rep.mode = mode ? mode->mode.id : 0; - rep.rotation = crtc->rotation; - rep.rotations = crtc->rotations; - rep.nOutput = crtc->numOutputs; - k = 0; - for (i = 0; i < pScrPriv->numOutputs; i++) - for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) - if (pScrPriv->outputs[i]->crtcs[j] == crtc) - k++; - rep.nPossibleOutput = k; - - rep.length = rep.nOutput + rep.nPossibleOutput; - - extraLen = rep.length << 2; - if (extraLen) - { - extra = xalloc (extraLen); - if (!extra) - return BadAlloc; - } - else - extra = NULL; - - outputs = (RROutput *) extra; - possible = (RROutput *) (outputs + rep.nOutput); - - for (i = 0; i < crtc->numOutputs; i++) - { - outputs[i] = crtc->outputs[i]->id; - if (client->swapped) - swapl (&outputs[i], n); - } - k = 0; - for (i = 0; i < pScrPriv->numOutputs; i++) - for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) - if (pScrPriv->outputs[i]->crtcs[j] == crtc) - { - possible[k] = pScrPriv->outputs[i]->id; - if (client->swapped) - swapl (&possible[k], n); - k++; - } - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.timestamp, n); - swaps(&rep.x, n); - swaps(&rep.y, n); - swaps(&rep.width, n); - swaps(&rep.height, n); - swapl(&rep.mode, n); - swaps(&rep.rotation, n); - swaps(&rep.rotations, n); - swaps(&rep.nOutput, n); - swaps(&rep.nPossibleOutput, n); - } - WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep); - if (extraLen) - { - WriteToClient (client, extraLen, (char *) extra); - xfree (extra); - } - - return client->noClientException; -} - -int -ProcRRSetCrtcConfig (ClientPtr client) -{ - REQUEST(xRRSetCrtcConfigReq); - xRRSetCrtcConfigReply rep; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - RRCrtcPtr crtc; - RRModePtr mode; - int numOutputs; - RROutputPtr *outputs = NULL; - RROutput *outputIds; - TimeStamp configTime; - TimeStamp time; - Rotation rotation; - int rc, i, j; - - REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq); - numOutputs = (stuff->length - bytes_to_int32(SIZEOF (xRRSetCrtcConfigReq))); - - VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess); - - if (stuff->mode == None) - { - mode = NULL; - if (numOutputs > 0) - return BadMatch; - } - else - { - VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess); - if (numOutputs == 0) - return BadMatch; - } - if (numOutputs) - { - outputs = xalloc (numOutputs * sizeof (RROutputPtr)); - if (!outputs) - return BadAlloc; - } - else - outputs = NULL; - - outputIds = (RROutput *) (stuff + 1); - for (i = 0; i < numOutputs; i++) - { - rc = dixLookupResourceByType((pointer *)(outputs + i), outputIds[i], - RROutputType, client, DixSetAttrAccess); - if (rc != Success) - { - if (outputs) - xfree (outputs); - return (rc == BadValue) ? RRErrorBase + BadRROutput : rc; - } - /* validate crtc for this output */ - for (j = 0; j < outputs[i]->numCrtcs; j++) - if (outputs[i]->crtcs[j] == crtc) - break; - if (j == outputs[i]->numCrtcs) - { - if (outputs) - xfree (outputs); - return BadMatch; - } - /* validate mode for this output */ - for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++) - { - RRModePtr m = (j < outputs[i]->numModes ? - outputs[i]->modes[j] : - outputs[i]->userModes[j - outputs[i]->numModes]); - if (m == mode) - break; - } - if (j == outputs[i]->numModes + outputs[i]->numUserModes) - { - if (outputs) - xfree (outputs); - return BadMatch; - } - } - /* validate clones */ - for (i = 0; i < numOutputs; i++) - { - for (j = 0; j < numOutputs; j++) - { - int k; - if (i == j) - continue; - for (k = 0; k < outputs[i]->numClones; k++) - { - if (outputs[i]->clones[k] == outputs[j]) - break; - } - if (k == outputs[i]->numClones) - { - if (outputs) - xfree (outputs); - return BadMatch; - } - } - } - - pScreen = crtc->pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - time = ClientTimeToServerTime(stuff->timestamp); - configTime = ClientTimeToServerTime(stuff->configTimestamp); - - if (!pScrPriv) - { - time = currentTime; - rep.status = RRSetConfigFailed; - goto sendReply; - } - -#if 0 - /* - * if the client's config timestamp is not the same as the last config - * timestamp, then the config information isn't up-to-date and - * can't even be validated - */ - if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0) - { - rep.status = RRSetConfigInvalidConfigTime; - goto sendReply; - } -#endif - - /* - * Validate requested rotation - */ - rotation = (Rotation) stuff->rotation; - - /* test the rotation bits only! */ - switch (rotation & 0xf) { - case RR_Rotate_0: - case RR_Rotate_90: - case RR_Rotate_180: - case RR_Rotate_270: - break; - default: - /* - * Invalid rotation - */ - client->errorValue = stuff->rotation; - if (outputs) - xfree (outputs); - return BadValue; - } - - if (mode) - { - if ((~crtc->rotations) & rotation) - { - /* - * requested rotation or reflection not supported by screen - */ - client->errorValue = stuff->rotation; - if (outputs) - xfree (outputs); - return BadMatch; - } - -#ifdef RANDR_12_INTERFACE - /* - * Check screen size bounds if the DDX provides a 1.2 interface - * for setting screen size. Else, assume the CrtcSet sets - * the size along with the mode. If the driver supports transforms, - * then it must allow crtcs to display a subset of the screen, so - * only do this check for drivers without transform support. - */ - if (pScrPriv->rrScreenSetSize && !crtc->transforms) - { - int source_width; - int source_height; - PictTransform transform; - struct pixman_f_transform f_transform, f_inverse; - - RRTransformCompute (stuff->x, stuff->y, - mode->mode.width, mode->mode.height, - rotation, - &crtc->client_pending_transform, - &transform, &f_transform, &f_inverse); - - RRModeGetScanoutSize (mode, &transform, &source_width, &source_height); - if (stuff->x + source_width > pScreen->width) - { - client->errorValue = stuff->x; - if (outputs) - xfree (outputs); - return BadValue; - } - - if (stuff->y + source_height > pScreen->height) - { - client->errorValue = stuff->y; - if (outputs) - xfree (outputs); - return BadValue; - } - } -#endif - } - - /* - * Make sure the requested set-time is not older than - * the last set-time - */ - if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) - { - rep.status = RRSetConfigInvalidTime; - goto sendReply; - } - - if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y, - rotation, numOutputs, outputs)) - { - rep.status = RRSetConfigFailed; - goto sendReply; - } - rep.status = RRSetConfigSuccess; - pScrPriv->lastSetTime = time; - -sendReply: - if (outputs) - xfree (outputs); - - rep.type = X_Reply; - /* rep.status has already been filled in */ - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; - - if (client->swapped) - { - int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.newTimestamp, n); - } - WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep); - - return client->noClientException; -} - -int -ProcRRGetPanning (ClientPtr client) -{ - REQUEST(xRRGetPanningReq); - xRRGetPanningReply rep; - RRCrtcPtr crtc; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - BoxRec total; - BoxRec tracking; - INT16 border[4]; - int n; - - REQUEST_SIZE_MATCH(xRRGetPanningReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* All crtcs must be associated with screens before client - * requests are processed - */ - pScreen = crtc->pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - if (!pScrPriv) - return RRErrorBase + BadRRCrtc; - - memset(&rep, 0, sizeof(rep)); - rep.type = X_Reply; - rep.status = RRSetConfigSuccess; - rep.sequenceNumber = client->sequence; - rep.length = 1; - rep.timestamp = pScrPriv->lastSetTime.milliseconds; - - if (pScrPriv->rrGetPanning && - pScrPriv->rrGetPanning (pScreen, crtc, &total, &tracking, border)) { - rep.left = total.x1; - rep.top = total.y1; - rep.width = total.x2 - total.x1; - rep.height = total.y2 - total.y1; - rep.track_left = tracking.x1; - rep.track_top = tracking.y1; - rep.track_width = tracking.x2 - tracking.x1; - rep.track_height = tracking.y2 - tracking.y1; - rep.border_left = border[0]; - rep.border_top = border[1]; - rep.border_right = border[2]; - rep.border_bottom = border[3]; - } - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.timestamp, n); - swaps(&rep.left, n); - swaps(&rep.top, n); - swaps(&rep.width, n); - swaps(&rep.height, n); - swaps(&rep.track_left, n); - swaps(&rep.track_top, n); - swaps(&rep.track_width, n); - swaps(&rep.track_height, n); - swaps(&rep.border_left, n); - swaps(&rep.border_top, n); - swaps(&rep.border_right, n); - swaps(&rep.border_bottom, n); - } - WriteToClient(client, sizeof(xRRGetPanningReply), (char *)&rep); - return client->noClientException; -} - -int -ProcRRSetPanning (ClientPtr client) -{ - REQUEST(xRRSetPanningReq); - xRRSetPanningReply rep; - RRCrtcPtr crtc; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - TimeStamp time; - BoxRec total; - BoxRec tracking; - INT16 border[4]; - int n; - - REQUEST_SIZE_MATCH(xRRSetPanningReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* All crtcs must be associated with screens before client - * requests are processed - */ - pScreen = crtc->pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - if (!pScrPriv) { - time = currentTime; - rep.status = RRSetConfigFailed; - goto sendReply; - } - - time = ClientTimeToServerTime(stuff->timestamp); - - /* - * Make sure the requested set-time is not older than - * the last set-time - */ - if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) - { - rep.status = RRSetConfigInvalidTime; - goto sendReply; - } - - if (!pScrPriv->rrGetPanning) - return RRErrorBase + BadRRCrtc; - - total.x1 = stuff->left; - total.y1 = stuff->top; - total.x2 = total.x1 + stuff->width; - total.y2 = total.y1 + stuff->height; - tracking.x1 = stuff->track_left; - tracking.y1 = stuff->track_top; - tracking.x2 = tracking.x1 + stuff->track_width; - tracking.y2 = tracking.y1 + stuff->track_height; - border[0] = stuff->border_left; - border[1] = stuff->border_top; - border[2] = stuff->border_right; - border[3] = stuff->border_bottom; - - if (! pScrPriv->rrSetPanning (pScreen, crtc, &total, &tracking, border)) - return BadMatch; - - pScrPriv->lastSetTime = time; - - rep.status = RRSetConfigSuccess; - -sendReply: - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.newTimestamp, n); - } - WriteToClient(client, sizeof(xRRSetPanningReply), (char *)&rep); - return client->noClientException; -} - -int -ProcRRGetCrtcGammaSize (ClientPtr client) -{ - REQUEST(xRRGetCrtcGammaSizeReq); - xRRGetCrtcGammaSizeReply reply; - RRCrtcPtr crtc; - int n; - - REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* Gamma retrieval failed, any better error? */ - if (!RRCrtcGammaGet(crtc)) - return RRErrorBase + BadRRCrtc; - - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = 0; - reply.size = crtc->gammaSize; - if (client->swapped) { - swaps (&reply.sequenceNumber, n); - swapl (&reply.length, n); - swaps (&reply.size, n); - } - WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply); - return client->noClientException; -} - -int -ProcRRGetCrtcGamma (ClientPtr client) -{ - REQUEST(xRRGetCrtcGammaReq); - xRRGetCrtcGammaReply reply; - RRCrtcPtr crtc; - int n; - unsigned long len; - char *extra = NULL; - - REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* Gamma retrieval failed, any better error? */ - if (!RRCrtcGammaGet(crtc)) - return RRErrorBase + BadRRCrtc; - - len = crtc->gammaSize * 3 * 2; - - if (crtc->gammaSize) { - extra = xalloc(len); - if (!extra) - return BadAlloc; - } - - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = bytes_to_int32(len); - reply.size = crtc->gammaSize; - if (client->swapped) { - swaps (&reply.sequenceNumber, n); - swapl (&reply.length, n); - swaps (&reply.size, n); - } - WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply); - if (crtc->gammaSize) - { - memcpy(extra, crtc->gammaRed, len); - client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; - WriteSwappedDataToClient (client, len, extra); - xfree(extra); - } - return client->noClientException; -} - -int -ProcRRSetCrtcGamma (ClientPtr client) -{ - REQUEST(xRRSetCrtcGammaReq); - RRCrtcPtr crtc; - unsigned long len; - CARD16 *red, *green, *blue; - - REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - len = client->req_len - bytes_to_int32(sizeof (xRRSetCrtcGammaReq)); - if (len < (stuff->size * 3 + 1) >> 1) - return BadLength; - - if (stuff->size != crtc->gammaSize) - return BadMatch; - - red = (CARD16 *) (stuff + 1); - green = red + crtc->gammaSize; - blue = green + crtc->gammaSize; - - RRCrtcGammaSet (crtc, red, green, blue); - - return Success; -} - -/* Version 1.3 additions */ - -int -ProcRRSetCrtcTransform (ClientPtr client) -{ - REQUEST(xRRSetCrtcTransformReq); - RRCrtcPtr crtc; - PictTransform transform; - struct pixman_f_transform f_transform, f_inverse; - char *filter; - int nbytes; - xFixed *params; - int nparams; - - REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - PictTransform_from_xRenderTransform (&transform, &stuff->transform); - pixman_f_transform_from_pixman_transform (&f_transform, &transform); - if (!pixman_f_transform_invert (&f_inverse, &f_transform)) - return BadMatch; - - filter = (char *) (stuff + 1); - nbytes = stuff->nbytesFilter; - params = (xFixed *) (filter + pad_to_int32(nbytes)); - nparams = ((xFixed *) stuff + client->req_len) - params; - if (nparams < 0) - return BadLength; - - return RRCrtcTransformSet (crtc, &transform, &f_transform, &f_inverse, - filter, nbytes, params, nparams); -} - - -#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32) - -static int -transform_filter_length (RRTransformPtr transform) -{ - int nbytes, nparams; - - if (transform->filter == NULL) - return 0; - nbytes = strlen (transform->filter->name); - nparams = transform->nparams; - return pad_to_int32(nbytes) + (nparams * sizeof (xFixed)); -} - -static int -transform_filter_encode (ClientPtr client, char *output, - CARD16 *nbytesFilter, - CARD16 *nparamsFilter, - RRTransformPtr transform) -{ - int nbytes, nparams; - int n; - - if (transform->filter == NULL) { - *nbytesFilter = 0; - *nparamsFilter = 0; - return 0; - } - nbytes = strlen (transform->filter->name); - nparams = transform->nparams; - *nbytesFilter = nbytes; - *nparamsFilter = nparams; - memcpy (output, transform->filter->name, nbytes); - while ((nbytes & 3) != 0) - output[nbytes++] = 0; - memcpy (output + nbytes, transform->params, nparams * sizeof (xFixed)); - if (client->swapped) { - swaps (nbytesFilter, n); - swaps (nparamsFilter, n); - SwapLongs ((CARD32 *) (output + nbytes), nparams); - } - nbytes += nparams * sizeof (xFixed); - return nbytes; -} - -static void -transform_encode (ClientPtr client, xRenderTransform *wire, PictTransform *pict) -{ - xRenderTransform_from_PictTransform (wire, pict); - if (client->swapped) - SwapLongs ((CARD32 *) wire, bytes_to_int32(sizeof(xRenderTransform))); -} - -int -ProcRRGetCrtcTransform (ClientPtr client) -{ - REQUEST(xRRGetCrtcTransformReq); - xRRGetCrtcTransformReply *reply; - RRCrtcPtr crtc; - int n, nextra; - RRTransformPtr current, pending; - char *extra; - - REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - pending = &crtc->client_pending_transform; - current = &crtc->client_current_transform; - - nextra = (transform_filter_length (pending) + - transform_filter_length (current)); - - reply = xalloc (sizeof (xRRGetCrtcTransformReply) + nextra); - if (!reply) - return BadAlloc; - - extra = (char *) (reply + 1); - reply->type = X_Reply; - reply->sequenceNumber = client->sequence; - reply->length = bytes_to_int32(CrtcTransformExtra + nextra); - - reply->hasTransforms = crtc->transforms; - - transform_encode (client, &reply->pendingTransform, &pending->transform); - extra += transform_filter_encode (client, extra, - &reply->pendingNbytesFilter, - &reply->pendingNparamsFilter, - pending); - - transform_encode (client, &reply->currentTransform, ¤t->transform); - extra += transform_filter_encode (client, extra, - &reply->currentNbytesFilter, - &reply->currentNparamsFilter, - current); - - if (client->swapped) { - swaps (&reply->sequenceNumber, n); - swapl (&reply->length, n); - } - WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply); - xfree(reply); - return client->noClientException; -} +/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "randrstr.h"
+#include "swaprep.h"
+
+RESTYPE RRCrtcType;
+
+/*
+ * Notify the CRTC of some change
+ */
+void
+RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
+{
+ ScreenPtr pScreen = crtc->pScreen;
+
+ crtc->changed = TRUE;
+ if (pScreen)
+ {
+ rrScrPriv(pScreen);
+
+ pScrPriv->changed = TRUE;
+ /*
+ * Send ConfigureNotify on any layout change
+ */
+ if (layoutChanged)
+ pScrPriv->layoutChanged = TRUE;
+ }
+}
+
+/*
+ * Create a CRTC
+ */
+RRCrtcPtr
+RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
+{
+ RRCrtcPtr crtc;
+ RRCrtcPtr *crtcs;
+ rrScrPrivPtr pScrPriv;
+
+ if (!RRInit())
+ return NULL;
+
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ /* make space for the crtc pointer */
+ if (pScrPriv->numCrtcs)
+ crtcs = realloc(pScrPriv->crtcs,
+ (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr));
+ else
+ crtcs = malloc(sizeof (RRCrtcPtr));
+ if (!crtcs)
+ return FALSE;
+ pScrPriv->crtcs = crtcs;
+
+ crtc = calloc(1, sizeof (RRCrtcRec));
+ if (!crtc)
+ return NULL;
+ crtc->id = FakeClientID (0);
+ crtc->pScreen = pScreen;
+ crtc->mode = NULL;
+ crtc->x = 0;
+ crtc->y = 0;
+ crtc->rotation = RR_Rotate_0;
+ crtc->rotations = RR_Rotate_0;
+ crtc->outputs = NULL;
+ crtc->numOutputs = 0;
+ crtc->gammaSize = 0;
+ crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL;
+ crtc->changed = FALSE;
+ crtc->devPrivate = devPrivate;
+ RRTransformInit (&crtc->client_pending_transform);
+ RRTransformInit (&crtc->client_current_transform);
+ pixman_transform_init_identity (&crtc->transform);
+ pixman_f_transform_init_identity (&crtc->f_transform);
+ pixman_f_transform_init_identity (&crtc->f_inverse);
+
+ if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
+ return NULL;
+
+ /* attach the screen and crtc together */
+ crtc->pScreen = pScreen;
+ pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
+
+ return crtc;
+}
+
+/*
+ * Set the allowed rotations on a CRTC
+ */
+void
+RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations)
+{
+ crtc->rotations = rotations;
+}
+
+/*
+ * Set whether transforms are allowed on a CRTC
+ */
+void
+RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms)
+{
+ crtc->transforms = transforms;
+}
+
+/*
+ * Notify the extension that the Crtc has been reconfigured,
+ * the driver calls this whenever it has updated the mode
+ */
+Bool
+RRCrtcNotify (RRCrtcPtr crtc,
+ RRModePtr mode,
+ int x,
+ int y,
+ Rotation rotation,
+ RRTransformPtr transform,
+ int numOutputs,
+ RROutputPtr *outputs)
+{
+ int i, j;
+
+ /*
+ * Check to see if any of the new outputs were
+ * not in the old list and mark them as changed
+ */
+ for (i = 0; i < numOutputs; i++)
+ {
+ for (j = 0; j < crtc->numOutputs; j++)
+ if (outputs[i] == crtc->outputs[j])
+ break;
+ if (j == crtc->numOutputs)
+ {
+ outputs[i]->crtc = crtc;
+ RROutputChanged (outputs[i], FALSE);
+ RRCrtcChanged (crtc, FALSE);
+ }
+ }
+ /*
+ * Check to see if any of the old outputs are
+ * not in the new list and mark them as changed
+ */
+ for (j = 0; j < crtc->numOutputs; j++)
+ {
+ for (i = 0; i < numOutputs; i++)
+ if (outputs[i] == crtc->outputs[j])
+ break;
+ if (i == numOutputs)
+ {
+ if (crtc->outputs[j]->crtc == crtc)
+ crtc->outputs[j]->crtc = NULL;
+ RROutputChanged (crtc->outputs[j], FALSE);
+ RRCrtcChanged (crtc, FALSE);
+ }
+ }
+ /*
+ * Reallocate the crtc output array if necessary
+ */
+ if (numOutputs != crtc->numOutputs)
+ {
+ RROutputPtr *newoutputs;
+
+ if (numOutputs)
+ {
+ if (crtc->numOutputs)
+ newoutputs = realloc(crtc->outputs,
+ numOutputs * sizeof (RROutputPtr));
+ else
+ newoutputs = malloc(numOutputs * sizeof (RROutputPtr));
+ if (!newoutputs)
+ return FALSE;
+ }
+ else
+ {
+ if (crtc->outputs)
+ free(crtc->outputs);
+ newoutputs = NULL;
+ }
+ crtc->outputs = newoutputs;
+ crtc->numOutputs = numOutputs;
+ }
+ /*
+ * Copy the new list of outputs into the crtc
+ */
+ memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr));
+ /*
+ * Update remaining crtc fields
+ */
+ if (mode != crtc->mode)
+ {
+ if (crtc->mode)
+ RRModeDestroy (crtc->mode);
+ crtc->mode = mode;
+ if (mode != NULL)
+ mode->refcnt++;
+ RRCrtcChanged (crtc, TRUE);
+ }
+ if (x != crtc->x)
+ {
+ crtc->x = x;
+ RRCrtcChanged (crtc, TRUE);
+ }
+ if (y != crtc->y)
+ {
+ crtc->y = y;
+ RRCrtcChanged (crtc, TRUE);
+ }
+ if (rotation != crtc->rotation)
+ {
+ crtc->rotation = rotation;
+ RRCrtcChanged (crtc, TRUE);
+ }
+ if (!RRTransformEqual (transform, &crtc->client_current_transform)) {
+ RRTransformCopy (&crtc->client_current_transform, transform);
+ RRCrtcChanged (crtc, TRUE);
+ }
+ if (crtc->changed && mode)
+ {
+ RRTransformCompute (x, y,
+ mode->mode.width, mode->mode.height,
+ rotation,
+ &crtc->client_current_transform,
+ &crtc->transform, &crtc->f_transform,
+ &crtc->f_inverse);
+ }
+ return TRUE;
+}
+
+void
+RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ rrScrPriv (pScreen);
+ xRRCrtcChangeNotifyEvent ce;
+ RRModePtr mode = crtc->mode;
+
+ ce.type = RRNotify + RREventBase;
+ ce.subCode = RRNotify_CrtcChange;
+ ce.sequenceNumber = client->sequence;
+ ce.timestamp = pScrPriv->lastSetTime.milliseconds;
+ ce.window = pWin->drawable.id;
+ ce.crtc = crtc->id;
+ ce.rotation = crtc->rotation;
+ if (mode)
+ {
+ ce.mode = mode->mode.id;
+ ce.x = crtc->x;
+ ce.y = crtc->y;
+ ce.width = mode->mode.width;
+ ce.height = mode->mode.height;
+ }
+ else
+ {
+ ce.mode = None;
+ ce.x = 0;
+ ce.y = 0;
+ ce.width = 0;
+ ce.height = 0;
+ }
+ WriteEventsToClient (client, 1, (xEvent *) &ce);
+}
+
+static Bool
+RRCrtcPendingProperties (RRCrtcPtr crtc)
+{
+ ScreenPtr pScreen = crtc->pScreen;
+ rrScrPriv(pScreen);
+ int o;
+
+ for (o = 0; o < pScrPriv->numOutputs; o++)
+ {
+ RROutputPtr output = pScrPriv->outputs[o];
+ if (output->crtc == crtc && output->pendingProperties)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Request that the Crtc be reconfigured
+ */
+Bool
+RRCrtcSet (RRCrtcPtr crtc,
+ RRModePtr mode,
+ int x,
+ int y,
+ Rotation rotation,
+ int numOutputs,
+ RROutputPtr *outputs)
+{
+ ScreenPtr pScreen = crtc->pScreen;
+ Bool ret = FALSE;
+ rrScrPriv(pScreen);
+
+ /* See if nothing changed */
+ if (crtc->mode == mode &&
+ crtc->x == x &&
+ crtc->y == y &&
+ crtc->rotation == rotation &&
+ crtc->numOutputs == numOutputs &&
+ !memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) &&
+ !RRCrtcPendingProperties (crtc) &&
+ !RRCrtcPendingTransform (crtc))
+ {
+ ret = TRUE;
+ }
+ else
+ {
+#if RANDR_12_INTERFACE
+ if (pScrPriv->rrCrtcSet)
+ {
+ ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y,
+ rotation, numOutputs, outputs);
+ }
+ else
+#endif
+ {
+#if RANDR_10_INTERFACE
+ if (pScrPriv->rrSetConfig)
+ {
+ RRScreenSize size;
+ RRScreenRate rate;
+
+ if (!mode)
+ {
+ RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL);
+ ret = TRUE;
+ }
+ else
+ {
+ size.width = mode->mode.width;
+ size.height = mode->mode.height;
+ if (outputs[0]->mmWidth && outputs[0]->mmHeight)
+ {
+ size.mmWidth = outputs[0]->mmWidth;
+ size.mmHeight = outputs[0]->mmHeight;
+ }
+ else
+ {
+ size.mmWidth = pScreen->mmWidth;
+ size.mmHeight = pScreen->mmHeight;
+ }
+ size.nRates = 1;
+ rate.rate = RRVerticalRefresh (&mode->mode);
+ size.pRates = &rate;
+ ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size);
+ /*
+ * Old 1.0 interface tied screen size to mode size
+ */
+ if (ret)
+ {
+ RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs);
+ RRScreenSizeNotify (pScreen);
+ }
+ }
+ }
+#endif
+ }
+ if (ret)
+ {
+ int o;
+ RRTellChanged (pScreen);
+
+ for (o = 0; o < numOutputs; o++)
+ RRPostPendingProperties (outputs[o]);
+ }
+ }
+ return ret;
+}
+
+/*
+ * Return crtc transform
+ */
+RRTransformPtr
+RRCrtcGetTransform (RRCrtcPtr crtc)
+{
+ RRTransformPtr transform = &crtc->client_pending_transform;
+
+ if (pixman_transform_is_identity (&transform->transform))
+ return NULL;
+ return transform;
+}
+
+/*
+ * Check whether the pending and current transforms are the same
+ */
+Bool
+RRCrtcPendingTransform (RRCrtcPtr crtc)
+{
+ return memcmp (&crtc->client_current_transform.transform,
+ &crtc->client_pending_transform.transform,
+ sizeof (PictTransform)) != 0;
+}
+
+/*
+ * Destroy a Crtc at shutdown
+ */
+void
+RRCrtcDestroy (RRCrtcPtr crtc)
+{
+ FreeResource (crtc->id, 0);
+}
+
+static int
+RRCrtcDestroyResource (pointer value, XID pid)
+{
+ RRCrtcPtr crtc = (RRCrtcPtr) value;
+ ScreenPtr pScreen = crtc->pScreen;
+
+ if (pScreen)
+ {
+ rrScrPriv(pScreen);
+ int i;
+
+ for (i = 0; i < pScrPriv->numCrtcs; i++)
+ {
+ if (pScrPriv->crtcs[i] == crtc)
+ {
+ memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1,
+ (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr));
+ --pScrPriv->numCrtcs;
+ break;
+ }
+ }
+ }
+ if (crtc->gammaRed)
+ free(crtc->gammaRed);
+ if (crtc->mode)
+ RRModeDestroy (crtc->mode);
+ free(crtc);
+ return 1;
+}
+
+/*
+ * Request that the Crtc gamma be changed
+ */
+
+Bool
+RRCrtcGammaSet (RRCrtcPtr crtc,
+ CARD16 *red,
+ CARD16 *green,
+ CARD16 *blue)
+{
+ Bool ret = TRUE;
+#if RANDR_12_INTERFACE
+ ScreenPtr pScreen = crtc->pScreen;
+#endif
+
+ memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16));
+ memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16));
+ memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16));
+#if RANDR_12_INTERFACE
+ if (pScreen)
+ {
+ rrScrPriv(pScreen);
+ if (pScrPriv->rrCrtcSetGamma)
+ ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc);
+ }
+#endif
+ return ret;
+}
+
+/*
+ * Request current gamma back from the DDX (if possible).
+ * This includes gamma size.
+ */
+Bool
+RRCrtcGammaGet(RRCrtcPtr crtc)
+{
+ Bool ret = TRUE;
+#if RANDR_12_INTERFACE
+ ScreenPtr pScreen = crtc->pScreen;
+#endif
+
+#if RANDR_12_INTERFACE
+ if (pScreen)
+ {
+ rrScrPriv(pScreen);
+ if (pScrPriv->rrCrtcGetGamma)
+ ret = (*pScrPriv->rrCrtcGetGamma) (pScreen, crtc);
+ }
+#endif
+ return ret;
+}
+
+/*
+ * Notify the extension that the Crtc gamma has been changed
+ * The driver calls this whenever it has changed the gamma values
+ * in the RRCrtcRec
+ */
+
+Bool
+RRCrtcGammaNotify (RRCrtcPtr crtc)
+{
+ return TRUE; /* not much going on here */
+}
+
+static void
+RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
+ int *width, int *height)
+{
+ BoxRec box;
+
+ if (mode == NULL) {
+ *width = 0;
+ *height = 0;
+ return;
+ }
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = mode->mode.width;
+ box.y2 = mode->mode.height;
+
+ pixman_transform_bounds (transform, &box);
+ *width = box.x2 - box.x1;
+ *height = box.y2 - box.y1;
+}
+
+/**
+ * Returns the width/height that the crtc scans out from the framebuffer
+ */
+void
+RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height)
+{
+ return RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height);
+}
+
+/*
+ * Set the size of the gamma table at server startup time
+ */
+
+Bool
+RRCrtcGammaSetSize (RRCrtcPtr crtc,
+ int size)
+{
+ CARD16 *gamma;
+
+ if (size == crtc->gammaSize)
+ return TRUE;
+ if (size)
+ {
+ gamma = malloc(size * 3 * sizeof (CARD16));
+ if (!gamma)
+ return FALSE;
+ }
+ else
+ gamma = NULL;
+ if (crtc->gammaRed)
+ free(crtc->gammaRed);
+ crtc->gammaRed = gamma;
+ crtc->gammaGreen = gamma + size;
+ crtc->gammaBlue = gamma + size*2;
+ crtc->gammaSize = size;
+ return TRUE;
+}
+
+/*
+ * Set the pending CRTC transformation
+ */
+
+int
+RRCrtcTransformSet (RRCrtcPtr crtc,
+ PictTransformPtr transform,
+ struct pixman_f_transform *f_transform,
+ struct pixman_f_transform *f_inverse,
+ char *filter_name,
+ int filter_len,
+ xFixed *params,
+ int nparams)
+{
+ PictFilterPtr filter = NULL;
+ int width = 0, height = 0;
+
+ if (!crtc->transforms)
+ return BadValue;
+
+ if (filter_len)
+ {
+ filter = PictureFindFilter (crtc->pScreen,
+ filter_name,
+ filter_len);
+ if (!filter)
+ return BadName;
+ if (filter->ValidateParams)
+ {
+ if (!filter->ValidateParams (crtc->pScreen, filter->id,
+ params, nparams, &width, &height))
+ return BadMatch;
+ }
+ else {
+ width = filter->width;
+ height = filter->height;
+ }
+ }
+ else
+ {
+ if (nparams)
+ return BadMatch;
+ }
+ if (!RRTransformSetFilter (&crtc->client_pending_transform,
+ filter, params, nparams, width, height))
+ return BadAlloc;
+
+ crtc->client_pending_transform.transform = *transform;
+ crtc->client_pending_transform.f_transform = *f_transform;
+ crtc->client_pending_transform.f_inverse = *f_inverse;
+ return Success;
+}
+
+/*
+ * Initialize crtc type
+ */
+Bool
+RRCrtcInit (void)
+{
+ RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource, "CRTC");
+ if (!RRCrtcType)
+ return FALSE;
+ return TRUE;
+}
+
+int
+ProcRRGetCrtcInfo (ClientPtr client)
+{
+ REQUEST(xRRGetCrtcInfoReq);
+ xRRGetCrtcInfoReply rep;
+ RRCrtcPtr crtc;
+ CARD8 *extra;
+ unsigned long extraLen;
+ ScreenPtr pScreen;
+ rrScrPrivPtr pScrPriv;
+ RRModePtr mode;
+ RROutput *outputs;
+ RROutput *possible;
+ int i, j, k, n;
+ int width, height;
+ BoxRec panned_area;
+
+ REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ /* All crtcs must be associated with screens before client
+ * requests are processed
+ */
+ pScreen = crtc->pScreen;
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ mode = crtc->mode;
+
+ rep.type = X_Reply;
+ rep.status = RRSetConfigSuccess;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+ if (pScrPriv->rrGetPanning &&
+ pScrPriv->rrGetPanning (pScreen, crtc, &panned_area, NULL, NULL) &&
+ (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1))
+ {
+ rep.x = panned_area.x1;
+ rep.y = panned_area.y1;
+ rep.width = panned_area.x2 - panned_area.x1;
+ rep.height = panned_area.y2 - panned_area.y1;
+ }
+ else
+ {
+ RRCrtcGetScanoutSize (crtc, &width, &height);
+ rep.x = crtc->x;
+ rep.y = crtc->y;
+ rep.width = width;
+ rep.height = height;
+ }
+ rep.mode = mode ? mode->mode.id : 0;
+ rep.rotation = crtc->rotation;
+ rep.rotations = crtc->rotations;
+ rep.nOutput = crtc->numOutputs;
+ k = 0;
+ for (i = 0; i < pScrPriv->numOutputs; i++)
+ for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
+ if (pScrPriv->outputs[i]->crtcs[j] == crtc)
+ k++;
+ rep.nPossibleOutput = k;
+
+ rep.length = rep.nOutput + rep.nPossibleOutput;
+
+ extraLen = rep.length << 2;
+ if (extraLen)
+ {
+ extra = malloc(extraLen);
+ if (!extra)
+ return BadAlloc;
+ }
+ else
+ extra = NULL;
+
+ outputs = (RROutput *) extra;
+ possible = (RROutput *) (outputs + rep.nOutput);
+
+ for (i = 0; i < crtc->numOutputs; i++)
+ {
+ outputs[i] = crtc->outputs[i]->id;
+ if (client->swapped)
+ swapl (&outputs[i], n);
+ }
+ k = 0;
+ for (i = 0; i < pScrPriv->numOutputs; i++)
+ for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
+ if (pScrPriv->outputs[i]->crtcs[j] == crtc)
+ {
+ possible[k] = pScrPriv->outputs[i]->id;
+ if (client->swapped)
+ swapl (&possible[k], n);
+ k++;
+ }
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.timestamp, n);
+ swaps(&rep.x, n);
+ swaps(&rep.y, n);
+ swaps(&rep.width, n);
+ swaps(&rep.height, n);
+ swapl(&rep.mode, n);
+ swaps(&rep.rotation, n);
+ swaps(&rep.rotations, n);
+ swaps(&rep.nOutput, n);
+ swaps(&rep.nPossibleOutput, n);
+ }
+ WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep);
+ if (extraLen)
+ {
+ WriteToClient (client, extraLen, (char *) extra);
+ free(extra);
+ }
+
+ return Success;
+}
+
+int
+ProcRRSetCrtcConfig (ClientPtr client)
+{
+ REQUEST(xRRSetCrtcConfigReq);
+ xRRSetCrtcConfigReply rep;
+ ScreenPtr pScreen;
+ rrScrPrivPtr pScrPriv;
+ RRCrtcPtr crtc;
+ RRModePtr mode;
+ int numOutputs;
+ RROutputPtr *outputs = NULL;
+ RROutput *outputIds;
+ TimeStamp configTime;
+ TimeStamp time;
+ Rotation rotation;
+ int rc, i, j;
+
+ REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq);
+ numOutputs = (stuff->length - bytes_to_int32(SIZEOF (xRRSetCrtcConfigReq)));
+
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess);
+
+ if (stuff->mode == None)
+ {
+ mode = NULL;
+ if (numOutputs > 0)
+ return BadMatch;
+ }
+ else
+ {
+ VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess);
+ if (numOutputs == 0)
+ return BadMatch;
+ }
+ if (numOutputs)
+ {
+ outputs = malloc(numOutputs * sizeof (RROutputPtr));
+ if (!outputs)
+ return BadAlloc;
+ }
+ else
+ outputs = NULL;
+
+ outputIds = (RROutput *) (stuff + 1);
+ for (i = 0; i < numOutputs; i++)
+ {
+ rc = dixLookupResourceByType((pointer *)(outputs + i), outputIds[i],
+ RROutputType, client, DixSetAttrAccess);
+ if (rc != Success)
+ {
+ if (outputs)
+ free(outputs);
+ return (rc == BadValue) ? RRErrorBase + BadRROutput : rc;
+ }
+ /* validate crtc for this output */
+ for (j = 0; j < outputs[i]->numCrtcs; j++)
+ if (outputs[i]->crtcs[j] == crtc)
+ break;
+ if (j == outputs[i]->numCrtcs)
+ {
+ if (outputs)
+ free(outputs);
+ return BadMatch;
+ }
+ /* validate mode for this output */
+ for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++)
+ {
+ RRModePtr m = (j < outputs[i]->numModes ?
+ outputs[i]->modes[j] :
+ outputs[i]->userModes[j - outputs[i]->numModes]);
+ if (m == mode)
+ break;
+ }
+ if (j == outputs[i]->numModes + outputs[i]->numUserModes)
+ {
+ if (outputs)
+ free(outputs);
+ return BadMatch;
+ }
+ }
+ /* validate clones */
+ for (i = 0; i < numOutputs; i++)
+ {
+ for (j = 0; j < numOutputs; j++)
+ {
+ int k;
+ if (i == j)
+ continue;
+ for (k = 0; k < outputs[i]->numClones; k++)
+ {
+ if (outputs[i]->clones[k] == outputs[j])
+ break;
+ }
+ if (k == outputs[i]->numClones)
+ {
+ if (outputs)
+ free(outputs);
+ return BadMatch;
+ }
+ }
+ }
+
+ pScreen = crtc->pScreen;
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ time = ClientTimeToServerTime(stuff->timestamp);
+ configTime = ClientTimeToServerTime(stuff->configTimestamp);
+
+ if (!pScrPriv)
+ {
+ time = currentTime;
+ rep.status = RRSetConfigFailed;
+ goto sendReply;
+ }
+
+#if 0
+ /*
+ * if the client's config timestamp is not the same as the last config
+ * timestamp, then the config information isn't up-to-date and
+ * can't even be validated
+ */
+ if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
+ {
+ rep.status = RRSetConfigInvalidConfigTime;
+ goto sendReply;
+ }
+#endif
+
+ /*
+ * Validate requested rotation
+ */
+ rotation = (Rotation) stuff->rotation;
+
+ /* test the rotation bits only! */
+ switch (rotation & 0xf) {
+ case RR_Rotate_0:
+ case RR_Rotate_90:
+ case RR_Rotate_180:
+ case RR_Rotate_270:
+ break;
+ default:
+ /*
+ * Invalid rotation
+ */
+ client->errorValue = stuff->rotation;
+ if (outputs)
+ free(outputs);
+ return BadValue;
+ }
+
+ if (mode)
+ {
+ if ((~crtc->rotations) & rotation)
+ {
+ /*
+ * requested rotation or reflection not supported by screen
+ */
+ client->errorValue = stuff->rotation;
+ if (outputs)
+ free(outputs);
+ return BadMatch;
+ }
+
+#ifdef RANDR_12_INTERFACE
+ /*
+ * Check screen size bounds if the DDX provides a 1.2 interface
+ * for setting screen size. Else, assume the CrtcSet sets
+ * the size along with the mode. If the driver supports transforms,
+ * then it must allow crtcs to display a subset of the screen, so
+ * only do this check for drivers without transform support.
+ */
+ if (pScrPriv->rrScreenSetSize && !crtc->transforms)
+ {
+ int source_width;
+ int source_height;
+ PictTransform transform;
+ struct pixman_f_transform f_transform, f_inverse;
+
+ RRTransformCompute (stuff->x, stuff->y,
+ mode->mode.width, mode->mode.height,
+ rotation,
+ &crtc->client_pending_transform,
+ &transform, &f_transform, &f_inverse);
+
+ RRModeGetScanoutSize (mode, &transform, &source_width, &source_height);
+ if (stuff->x + source_width > pScreen->width)
+ {
+ client->errorValue = stuff->x;
+ if (outputs)
+ free(outputs);
+ return BadValue;
+ }
+
+ if (stuff->y + source_height > pScreen->height)
+ {
+ client->errorValue = stuff->y;
+ if (outputs)
+ free(outputs);
+ return BadValue;
+ }
+ }
+#endif
+ }
+
+ /*
+ * Make sure the requested set-time is not older than
+ * the last set-time
+ */
+ if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
+ {
+ rep.status = RRSetConfigInvalidTime;
+ goto sendReply;
+ }
+
+ if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y,
+ rotation, numOutputs, outputs))
+ {
+ rep.status = RRSetConfigFailed;
+ goto sendReply;
+ }
+ rep.status = RRSetConfigSuccess;
+ pScrPriv->lastSetTime = time;
+
+sendReply:
+ if (outputs)
+ free(outputs);
+
+ rep.type = X_Reply;
+ /* rep.status has already been filled in */
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
+
+ if (client->swapped)
+ {
+ int n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.newTimestamp, n);
+ }
+ WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep);
+
+ return Success;
+}
+
+int
+ProcRRGetPanning (ClientPtr client)
+{
+ REQUEST(xRRGetPanningReq);
+ xRRGetPanningReply rep;
+ RRCrtcPtr crtc;
+ ScreenPtr pScreen;
+ rrScrPrivPtr pScrPriv;
+ BoxRec total;
+ BoxRec tracking;
+ INT16 border[4];
+ int n;
+
+ REQUEST_SIZE_MATCH(xRRGetPanningReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ /* All crtcs must be associated with screens before client
+ * requests are processed
+ */
+ pScreen = crtc->pScreen;
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ if (!pScrPriv)
+ return RRErrorBase + BadRRCrtc;
+
+ memset(&rep, 0, sizeof(rep));
+ rep.type = X_Reply;
+ rep.status = RRSetConfigSuccess;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 1;
+ rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+
+ if (pScrPriv->rrGetPanning &&
+ pScrPriv->rrGetPanning (pScreen, crtc, &total, &tracking, border)) {
+ rep.left = total.x1;
+ rep.top = total.y1;
+ rep.width = total.x2 - total.x1;
+ rep.height = total.y2 - total.y1;
+ rep.track_left = tracking.x1;
+ rep.track_top = tracking.y1;
+ rep.track_width = tracking.x2 - tracking.x1;
+ rep.track_height = tracking.y2 - tracking.y1;
+ rep.border_left = border[0];
+ rep.border_top = border[1];
+ rep.border_right = border[2];
+ rep.border_bottom = border[3];
+ }
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.timestamp, n);
+ swaps(&rep.left, n);
+ swaps(&rep.top, n);
+ swaps(&rep.width, n);
+ swaps(&rep.height, n);
+ swaps(&rep.track_left, n);
+ swaps(&rep.track_top, n);
+ swaps(&rep.track_width, n);
+ swaps(&rep.track_height, n);
+ swaps(&rep.border_left, n);
+ swaps(&rep.border_top, n);
+ swaps(&rep.border_right, n);
+ swaps(&rep.border_bottom, n);
+ }
+ WriteToClient(client, sizeof(xRRGetPanningReply), (char *)&rep);
+ return Success;
+}
+
+int
+ProcRRSetPanning (ClientPtr client)
+{
+ REQUEST(xRRSetPanningReq);
+ xRRSetPanningReply rep;
+ RRCrtcPtr crtc;
+ ScreenPtr pScreen;
+ rrScrPrivPtr pScrPriv;
+ TimeStamp time;
+ BoxRec total;
+ BoxRec tracking;
+ INT16 border[4];
+ int n;
+
+ REQUEST_SIZE_MATCH(xRRSetPanningReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ /* All crtcs must be associated with screens before client
+ * requests are processed
+ */
+ pScreen = crtc->pScreen;
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ if (!pScrPriv) {
+ time = currentTime;
+ rep.status = RRSetConfigFailed;
+ goto sendReply;
+ }
+
+ time = ClientTimeToServerTime(stuff->timestamp);
+
+ /*
+ * Make sure the requested set-time is not older than
+ * the last set-time
+ */
+ if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
+ {
+ rep.status = RRSetConfigInvalidTime;
+ goto sendReply;
+ }
+
+ if (!pScrPriv->rrGetPanning)
+ return RRErrorBase + BadRRCrtc;
+
+ total.x1 = stuff->left;
+ total.y1 = stuff->top;
+ total.x2 = total.x1 + stuff->width;
+ total.y2 = total.y1 + stuff->height;
+ tracking.x1 = stuff->track_left;
+ tracking.y1 = stuff->track_top;
+ tracking.x2 = tracking.x1 + stuff->track_width;
+ tracking.y2 = tracking.y1 + stuff->track_height;
+ border[0] = stuff->border_left;
+ border[1] = stuff->border_top;
+ border[2] = stuff->border_right;
+ border[3] = stuff->border_bottom;
+
+ if (! pScrPriv->rrSetPanning (pScreen, crtc, &total, &tracking, border))
+ return BadMatch;
+
+ pScrPriv->lastSetTime = time;
+
+ rep.status = RRSetConfigSuccess;
+
+sendReply:
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.newTimestamp, n);
+ }
+ WriteToClient(client, sizeof(xRRSetPanningReply), (char *)&rep);
+ return Success;
+}
+
+int
+ProcRRGetCrtcGammaSize (ClientPtr client)
+{
+ REQUEST(xRRGetCrtcGammaSizeReq);
+ xRRGetCrtcGammaSizeReply reply;
+ RRCrtcPtr crtc;
+ int n;
+
+ REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ /* Gamma retrieval failed, any better error? */
+ if (!RRCrtcGammaGet(crtc))
+ return RRErrorBase + BadRRCrtc;
+
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.length = 0;
+ reply.size = crtc->gammaSize;
+ if (client->swapped) {
+ swaps (&reply.sequenceNumber, n);
+ swapl (&reply.length, n);
+ swaps (&reply.size, n);
+ }
+ WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply);
+ return Success;
+}
+
+int
+ProcRRGetCrtcGamma (ClientPtr client)
+{
+ REQUEST(xRRGetCrtcGammaReq);
+ xRRGetCrtcGammaReply reply;
+ RRCrtcPtr crtc;
+ int n;
+ unsigned long len;
+ char *extra = NULL;
+
+ REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ /* Gamma retrieval failed, any better error? */
+ if (!RRCrtcGammaGet(crtc))
+ return RRErrorBase + BadRRCrtc;
+
+ len = crtc->gammaSize * 3 * 2;
+
+ if (crtc->gammaSize) {
+ extra = malloc(len);
+ if (!extra)
+ return BadAlloc;
+ }
+
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.length = bytes_to_int32(len);
+ reply.size = crtc->gammaSize;
+ if (client->swapped) {
+ swaps (&reply.sequenceNumber, n);
+ swapl (&reply.length, n);
+ swaps (&reply.size, n);
+ }
+ WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply);
+ if (crtc->gammaSize)
+ {
+ memcpy(extra, crtc->gammaRed, len);
+ client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write;
+ WriteSwappedDataToClient (client, len, extra);
+ free(extra);
+ }
+ return Success;
+}
+
+int
+ProcRRSetCrtcGamma (ClientPtr client)
+{
+ REQUEST(xRRSetCrtcGammaReq);
+ RRCrtcPtr crtc;
+ unsigned long len;
+ CARD16 *red, *green, *blue;
+
+ REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ len = client->req_len - bytes_to_int32(sizeof (xRRSetCrtcGammaReq));
+ if (len < (stuff->size * 3 + 1) >> 1)
+ return BadLength;
+
+ if (stuff->size != crtc->gammaSize)
+ return BadMatch;
+
+ red = (CARD16 *) (stuff + 1);
+ green = red + crtc->gammaSize;
+ blue = green + crtc->gammaSize;
+
+ RRCrtcGammaSet (crtc, red, green, blue);
+
+ return Success;
+}
+
+/* Version 1.3 additions */
+
+int
+ProcRRSetCrtcTransform (ClientPtr client)
+{
+ REQUEST(xRRSetCrtcTransformReq);
+ RRCrtcPtr crtc;
+ PictTransform transform;
+ struct pixman_f_transform f_transform, f_inverse;
+ char *filter;
+ int nbytes;
+ xFixed *params;
+ int nparams;
+
+ REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ PictTransform_from_xRenderTransform (&transform, &stuff->transform);
+ pixman_f_transform_from_pixman_transform (&f_transform, &transform);
+ if (!pixman_f_transform_invert (&f_inverse, &f_transform))
+ return BadMatch;
+
+ filter = (char *) (stuff + 1);
+ nbytes = stuff->nbytesFilter;
+ params = (xFixed *) (filter + pad_to_int32(nbytes));
+ nparams = ((xFixed *) stuff + client->req_len) - params;
+ if (nparams < 0)
+ return BadLength;
+
+ return RRCrtcTransformSet (crtc, &transform, &f_transform, &f_inverse,
+ filter, nbytes, params, nparams);
+}
+
+
+#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32)
+
+static int
+transform_filter_length (RRTransformPtr transform)
+{
+ int nbytes, nparams;
+
+ if (transform->filter == NULL)
+ return 0;
+ nbytes = strlen (transform->filter->name);
+ nparams = transform->nparams;
+ return pad_to_int32(nbytes) + (nparams * sizeof (xFixed));
+}
+
+static int
+transform_filter_encode (ClientPtr client, char *output,
+ CARD16 *nbytesFilter,
+ CARD16 *nparamsFilter,
+ RRTransformPtr transform)
+{
+ int nbytes, nparams;
+ int n;
+
+ if (transform->filter == NULL) {
+ *nbytesFilter = 0;
+ *nparamsFilter = 0;
+ return 0;
+ }
+ nbytes = strlen (transform->filter->name);
+ nparams = transform->nparams;
+ *nbytesFilter = nbytes;
+ *nparamsFilter = nparams;
+ memcpy (output, transform->filter->name, nbytes);
+ while ((nbytes & 3) != 0)
+ output[nbytes++] = 0;
+ memcpy (output + nbytes, transform->params, nparams * sizeof (xFixed));
+ if (client->swapped) {
+ swaps (nbytesFilter, n);
+ swaps (nparamsFilter, n);
+ SwapLongs ((CARD32 *) (output + nbytes), nparams);
+ }
+ nbytes += nparams * sizeof (xFixed);
+ return nbytes;
+}
+
+static void
+transform_encode (ClientPtr client, xRenderTransform *wire, PictTransform *pict)
+{
+ xRenderTransform_from_PictTransform (wire, pict);
+ if (client->swapped)
+ SwapLongs ((CARD32 *) wire, bytes_to_int32(sizeof(xRenderTransform)));
+}
+
+int
+ProcRRGetCrtcTransform (ClientPtr client)
+{
+ REQUEST(xRRGetCrtcTransformReq);
+ xRRGetCrtcTransformReply *reply;
+ RRCrtcPtr crtc;
+ int n, nextra;
+ RRTransformPtr current, pending;
+ char *extra;
+
+ REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ pending = &crtc->client_pending_transform;
+ current = &crtc->client_current_transform;
+
+ nextra = (transform_filter_length (pending) +
+ transform_filter_length (current));
+
+ reply = malloc(sizeof (xRRGetCrtcTransformReply) + nextra);
+ if (!reply)
+ return BadAlloc;
+
+ extra = (char *) (reply + 1);
+ reply->type = X_Reply;
+ reply->sequenceNumber = client->sequence;
+ reply->length = bytes_to_int32(CrtcTransformExtra + nextra);
+
+ reply->hasTransforms = crtc->transforms;
+
+ transform_encode (client, &reply->pendingTransform, &pending->transform);
+ extra += transform_filter_encode (client, extra,
+ &reply->pendingNbytesFilter,
+ &reply->pendingNparamsFilter,
+ pending);
+
+ transform_encode (client, &reply->currentTransform, ¤t->transform);
+ extra += transform_filter_encode (client, extra,
+ &reply->currentNbytesFilter,
+ &reply->currentNparamsFilter,
+ current);
+
+ if (client->swapped) {
+ swaps (&reply->sequenceNumber, n);
+ swapl (&reply->length, n);
+ }
+ WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply);
+ free(reply);
+ return Success;
+}
|