aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/randr
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/randr')
-rw-r--r--xorg-server/randr/randr.c1006
-rw-r--r--xorg-server/randr/randrstr.h1944
-rw-r--r--xorg-server/randr/rrcrtc.c2857
3 files changed, 2984 insertions, 2823 deletions
diff --git a/xorg-server/randr/randr.c b/xorg-server/randr/randr.c
index 607770520..1551c63b1 100644
--- a/xorg-server/randr/randr.c
+++ b/xorg-server/randr/randr.c
@@ -1,502 +1,504 @@
-/*
- * Copyright © 2000 Compaq Computer Corporation
- * Copyright © 2002 Hewlett-Packard Company
- * Copyright © 2006 Intel Corporation
- *
- * 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.
- *
- * Author: Jim Gettys, Hewlett-Packard Company, Inc.
- * Keith Packard, Intel Corporation
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "randrstr.h"
-
-/* From render.h */
-#ifndef SubPixelUnknown
-#define SubPixelUnknown 0
-#endif
-
-#define RR_VALIDATE
-static int RRNScreens;
-
-#define wrap(priv,real,mem,func) {\
- priv->mem = real->mem; \
- real->mem = func; \
-}
-
-#define unwrap(priv,real,mem) {\
- real->mem = priv->mem; \
-}
-
-static int ProcRRDispatch (ClientPtr pClient);
-static int SProcRRDispatch (ClientPtr pClient);
-
-int RREventBase;
-int RRErrorBase;
-RESTYPE RRClientType, RREventType; /* resource types for event masks */
-DevPrivateKeyRec RRClientPrivateKeyRec;
-
-DevPrivateKeyRec rrPrivKeyRec;
-
-static void
-RRClientCallback (CallbackListPtr *list,
- pointer closure,
- pointer data)
-{
- NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
- ClientPtr pClient = clientinfo->client;
- rrClientPriv(pClient);
- RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1);
- int i;
-
- pRRClient->major_version = 0;
- pRRClient->minor_version = 0;
- for (i = 0; i < screenInfo.numScreens; i++)
- {
- ScreenPtr pScreen = screenInfo.screens[i];
- rrScrPriv(pScreen);
-
- if (pScrPriv)
- {
- pTimes[i].setTime = pScrPriv->lastSetTime;
- pTimes[i].configTime = pScrPriv->lastConfigTime;
- }
- }
-}
-
-static Bool
-RRCloseScreen (int i, ScreenPtr pScreen)
-{
- rrScrPriv(pScreen);
- int j;
-
- unwrap (pScrPriv, pScreen, CloseScreen);
- for (j = pScrPriv->numCrtcs - 1; j >= 0; j--)
- RRCrtcDestroy (pScrPriv->crtcs[j]);
- for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
- RROutputDestroy (pScrPriv->outputs[j]);
-
- free(pScrPriv->crtcs);
- free(pScrPriv->outputs);
- free(pScrPriv);
- RRNScreens -= 1; /* ok, one fewer screen with RandR running */
- return (*pScreen->CloseScreen) (i, pScreen);
-}
-
-static void
-SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from,
- xRRScreenChangeNotifyEvent *to)
-{
- to->type = from->type;
- to->rotation = from->rotation;
- cpswaps(from->sequenceNumber, to->sequenceNumber);
- cpswapl(from->timestamp, to->timestamp);
- cpswapl(from->configTimestamp, to->configTimestamp);
- cpswapl(from->root, to->root);
- cpswapl(from->window, to->window);
- cpswaps(from->sizeID, to->sizeID);
- cpswaps(from->subpixelOrder, to->subpixelOrder);
- cpswaps(from->widthInPixels, to->widthInPixels);
- cpswaps(from->heightInPixels, to->heightInPixels);
- cpswaps(from->widthInMillimeters, to->widthInMillimeters);
- cpswaps(from->heightInMillimeters, to->heightInMillimeters);
-}
-
-static void
-SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent *from,
- xRRCrtcChangeNotifyEvent *to)
-{
- to->type = from->type;
- to->subCode = from->subCode;
- cpswaps(from->sequenceNumber, to->sequenceNumber);
- cpswapl(from->timestamp, to->timestamp);
- cpswapl(from->window, to->window);
- cpswapl(from->crtc, to->crtc);
- cpswapl(from->mode, to->mode);
- cpswaps(from->rotation, to->rotation);
- /* pad1 */
- cpswaps(from->x, to->x);
- cpswaps(from->y, to->y);
- cpswaps(from->width, to->width);
- cpswaps(from->height, to->height);
-}
-
-static void
-SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent *from,
- xRROutputChangeNotifyEvent *to)
-{
- to->type = from->type;
- to->subCode = from->subCode;
- cpswaps(from->sequenceNumber, to->sequenceNumber);
- cpswapl(from->timestamp, to->timestamp);
- cpswapl(from->configTimestamp, to->configTimestamp);
- cpswapl(from->window, to->window);
- cpswapl(from->output, to->output);
- cpswapl(from->crtc, to->crtc);
- cpswapl(from->mode, to->mode);
- cpswaps(from->rotation, to->rotation);
- to->connection = from->connection;
- to->subpixelOrder = from->subpixelOrder;
-}
-
-static void
-SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent *from,
- xRROutputPropertyNotifyEvent *to)
-{
- to->type = from->type;
- to->subCode = from->subCode;
- cpswaps(from->sequenceNumber, to->sequenceNumber);
- cpswapl(from->window, to->window);
- cpswapl(from->output, to->output);
- cpswapl(from->atom, to->atom);
- cpswapl(from->timestamp, to->timestamp);
- to->state = from->state;
- /* pad1 */
- /* pad2 */
- /* pad3 */
- /* pad4 */
-}
-
-static void
-SRRNotifyEvent (xEvent *from,
- xEvent *to)
-{
- switch (from->u.u.detail) {
- case RRNotify_CrtcChange:
- SRRCrtcChangeNotifyEvent ((xRRCrtcChangeNotifyEvent *) from,
- (xRRCrtcChangeNotifyEvent *) to);
- break;
- case RRNotify_OutputChange:
- SRROutputChangeNotifyEvent ((xRROutputChangeNotifyEvent *) from,
- (xRROutputChangeNotifyEvent *) to);
- break;
- case RRNotify_OutputProperty:
- SRROutputPropertyNotifyEvent ((xRROutputPropertyNotifyEvent *) from,
- (xRROutputPropertyNotifyEvent *) to);
- break;
- default:
- break;
- }
-}
-
-static int RRGeneration;
-
-Bool RRInit (void)
-{
- if (RRGeneration != serverGeneration)
- {
- if (!RRModeInit ())
- return FALSE;
- if (!RRCrtcInit ())
- return FALSE;
- if (!RROutputInit ())
- return FALSE;
- RRGeneration = serverGeneration;
- }
- if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- return TRUE;
-}
-
-Bool RRScreenInit(ScreenPtr pScreen)
-{
- rrScrPrivPtr pScrPriv;
-
- if (!RRInit ())
- return FALSE;
-
- pScrPriv = (rrScrPrivPtr) calloc(1, sizeof (rrScrPrivRec));
- if (!pScrPriv)
- return FALSE;
-
- SetRRScreen(pScreen, pScrPriv);
-
- /*
- * Calling function best set these function vectors
- */
- pScrPriv->rrGetInfo = 0;
- pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
- pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
-
- pScrPriv->width = pScreen->width;
- pScrPriv->height = pScreen->height;
- pScrPriv->mmWidth = pScreen->mmWidth;
- pScrPriv->mmHeight = pScreen->mmHeight;
-#if RANDR_12_INTERFACE
- pScrPriv->rrScreenSetSize = NULL;
- pScrPriv->rrCrtcSet = NULL;
- pScrPriv->rrCrtcSetGamma = NULL;
-#endif
-#if RANDR_10_INTERFACE
- pScrPriv->rrSetConfig = 0;
- pScrPriv->rotations = RR_Rotate_0;
- pScrPriv->reqWidth = pScreen->width;
- pScrPriv->reqHeight = pScreen->height;
- pScrPriv->nSizes = 0;
- pScrPriv->pSizes = NULL;
- pScrPriv->rotation = RR_Rotate_0;
- pScrPriv->rate = 0;
- pScrPriv->size = 0;
-#endif
-
- /*
- * This value doesn't really matter -- any client must call
- * GetScreenInfo before reading it which will automatically update
- * the time
- */
- pScrPriv->lastSetTime = currentTime;
- pScrPriv->lastConfigTime = currentTime;
-
- wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
-
- pScrPriv->numOutputs = 0;
- pScrPriv->outputs = NULL;
- pScrPriv->numCrtcs = 0;
- pScrPriv->crtcs = NULL;
-
- RRNScreens += 1; /* keep count of screens that implement randr */
- return TRUE;
-}
-
-/*ARGSUSED*/
-static int
-RRFreeClient (pointer data, XID id)
-{
- RREventPtr pRREvent;
- WindowPtr pWin;
- RREventPtr *pHead, pCur, pPrev;
-
- pRREvent = (RREventPtr) data;
- pWin = pRREvent->window;
- dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
- RREventType, serverClient, DixDestroyAccess);
- if (pHead) {
- pPrev = 0;
- for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next)
- pPrev = pCur;
- if (pCur)
- {
- if (pPrev)
- pPrev->next = pRREvent->next;
- else
- *pHead = pRREvent->next;
- }
- }
- free((pointer) pRREvent);
- return 1;
-}
-
-/*ARGSUSED*/
-static int
-RRFreeEvents (pointer data, XID id)
-{
- RREventPtr *pHead, pCur, pNext;
-
- pHead = (RREventPtr *) data;
- for (pCur = *pHead; pCur; pCur = pNext) {
- pNext = pCur->next;
- FreeResource (pCur->clientResource, RRClientType);
- free((pointer) pCur);
- }
- free((pointer) pHead);
- return 1;
-}
-
-void
-RRExtensionInit (void)
-{
- ExtensionEntry *extEntry;
-
- if (RRNScreens == 0) return;
-
- if (!dixRegisterPrivateKey(&RRClientPrivateKeyRec, PRIVATE_CLIENT,
- sizeof (RRClientRec) +
- screenInfo.numScreens * sizeof (RRTimesRec)))
- return;
- if (!AddCallback (&ClientStateCallback, RRClientCallback, 0))
- return;
-
- RRClientType = CreateNewResourceType(RRFreeClient, "RandRClient");
- if (!RRClientType)
- return;
- RREventType = CreateNewResourceType(RRFreeEvents, "RandREvent");
- if (!RREventType)
- return;
- extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors,
- ProcRRDispatch, SProcRRDispatch,
- NULL, StandardMinorOpcode);
- if (!extEntry)
- return;
- RRErrorBase = extEntry->errorBase;
- RREventBase = extEntry->eventBase;
- EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
- SRRScreenChangeNotifyEvent;
- EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
- SRRNotifyEvent;
-
- RRModeInitErrorValue();
- RRCrtcInitErrorValue();
- RROutputInitErrorValue();
-
-#ifdef PANORAMIX
- RRXineramaExtensionInit();
-#endif
-}
-
-static int
-TellChanged (WindowPtr pWin, pointer value)
-{
- RREventPtr *pHead, pRREvent;
- ClientPtr client;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- rrScrPriv(pScreen);
- int i;
-
- dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
- RREventType, serverClient, DixReadAccess);
- if (!pHead)
- return WT_WALKCHILDREN;
-
- for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
- {
- client = pRREvent->client;
- if (client == serverClient || client->clientGone)
- continue;
-
- if (pRREvent->mask & RRScreenChangeNotifyMask)
- RRDeliverScreenEvent (client, pWin, pScreen);
-
- if (pRREvent->mask & RRCrtcChangeNotifyMask)
- {
- for (i = 0; i < pScrPriv->numCrtcs; i++)
- {
- RRCrtcPtr crtc = pScrPriv->crtcs[i];
- if (crtc->changed)
- RRDeliverCrtcEvent (client, pWin, crtc);
- }
- }
-
- if (pRREvent->mask & RROutputChangeNotifyMask)
- {
- for (i = 0; i < pScrPriv->numOutputs; i++)
- {
- RROutputPtr output = pScrPriv->outputs[i];
- if (output->changed)
- RRDeliverOutputEvent (client, pWin, output);
- }
- }
- }
- return WT_WALKCHILDREN;
-}
-
-/*
- * Something changed; send events and adjust pointer position
- */
-void
-RRTellChanged (ScreenPtr pScreen)
-{
- rrScrPriv (pScreen);
- int i;
-
- if (pScrPriv->changed)
- {
- UpdateCurrentTime ();
- if (pScrPriv->configChanged)
- {
- pScrPriv->lastConfigTime = currentTime;
- pScrPriv->configChanged = FALSE;
- }
- pScrPriv->changed = FALSE;
- WalkTree (pScreen, TellChanged, (pointer) pScreen);
- for (i = 0; i < pScrPriv->numOutputs; i++)
- pScrPriv->outputs[i]->changed = FALSE;
- for (i = 0; i < pScrPriv->numCrtcs; i++)
- pScrPriv->crtcs[i]->changed = FALSE;
- if (pScrPriv->layoutChanged)
- {
- pScrPriv->layoutChanged = FALSE;
- RRPointerScreenConfigured (pScreen);
- RRSendConfigNotify (pScreen);
- }
- }
-}
-
-/*
- * Return the first output which is connected to an active CRTC
- * Used in emulating 1.0 behaviour
- */
-RROutputPtr
-RRFirstOutput (ScreenPtr pScreen)
-{
- rrScrPriv(pScreen);
- RROutputPtr output;
- int i, j;
-
- if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc)
- return pScrPriv->primaryOutput;
-
- for (i = 0; i < pScrPriv->numCrtcs; i++)
- {
- RRCrtcPtr crtc = pScrPriv->crtcs[i];
- for (j = 0; j < pScrPriv->numOutputs; j++)
- {
- output = pScrPriv->outputs[j];
- if (output->crtc == crtc)
- return output;
- }
- }
- return NULL;
-}
-
-CARD16
-RRVerticalRefresh (xRRModeInfo *mode)
-{
- CARD32 refresh;
- CARD32 dots = mode->hTotal * mode->vTotal;
- if (!dots)
- return 0;
- refresh = (mode->dotClock + dots/2) / dots;
- if (refresh > 0xffff)
- refresh = 0xffff;
- return (CARD16) refresh;
-}
-
-static int
-ProcRRDispatch (ClientPtr client)
-{
- REQUEST(xReq);
- if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
- return BadRequest;
- return (*ProcRandrVector[stuff->data]) (client);
-}
-
-static int
-SProcRRDispatch (ClientPtr client)
-{
- REQUEST(xReq);
- if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
- return BadRequest;
- return (*SProcRandrVector[stuff->data]) (client);
-}
-
+/*
+ * Copyright © 2000 Compaq Computer Corporation
+ * Copyright © 2002 Hewlett-Packard Company
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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.
+ *
+ * Author: Jim Gettys, Hewlett-Packard Company, Inc.
+ * Keith Packard, Intel Corporation
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "randrstr.h"
+
+/* From render.h */
+#ifndef SubPixelUnknown
+#define SubPixelUnknown 0
+#endif
+
+#define RR_VALIDATE
+static int RRNScreens;
+
+#define wrap(priv,real,mem,func) {\
+ priv->mem = real->mem; \
+ real->mem = func; \
+}
+
+#define unwrap(priv,real,mem) {\
+ real->mem = priv->mem; \
+}
+
+static int ProcRRDispatch (ClientPtr pClient);
+static int SProcRRDispatch (ClientPtr pClient);
+
+int RREventBase;
+int RRErrorBase;
+RESTYPE RRClientType, RREventType; /* resource types for event masks */
+DevPrivateKeyRec RRClientPrivateKeyRec;
+
+DevPrivateKeyRec rrPrivKeyRec;
+
+static void
+RRClientCallback (CallbackListPtr *list,
+ pointer closure,
+ pointer data)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
+ ClientPtr pClient = clientinfo->client;
+ rrClientPriv(pClient);
+ RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1);
+ int i;
+
+ pRRClient->major_version = 0;
+ pRRClient->minor_version = 0;
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ ScreenPtr pScreen = screenInfo.screens[i];
+ rrScrPriv(pScreen);
+
+ if (pScrPriv)
+ {
+ pTimes[i].setTime = pScrPriv->lastSetTime;
+ pTimes[i].configTime = pScrPriv->lastConfigTime;
+ }
+ }
+}
+
+static Bool
+RRCloseScreen (int i, ScreenPtr pScreen)
+{
+ rrScrPriv(pScreen);
+ int j;
+
+ unwrap (pScrPriv, pScreen, CloseScreen);
+ for (j = pScrPriv->numCrtcs - 1; j >= 0; j--)
+ RRCrtcDestroy (pScrPriv->crtcs[j]);
+ for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
+ RROutputDestroy (pScrPriv->outputs[j]);
+
+ free(pScrPriv->crtcs);
+ free(pScrPriv->outputs);
+ free(pScrPriv);
+ RRNScreens -= 1; /* ok, one fewer screen with RandR running */
+ return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+static void
+SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from,
+ xRRScreenChangeNotifyEvent *to)
+{
+ to->type = from->type;
+ to->rotation = from->rotation;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->timestamp, to->timestamp);
+ cpswapl(from->configTimestamp, to->configTimestamp);
+ cpswapl(from->root, to->root);
+ cpswapl(from->window, to->window);
+ cpswaps(from->sizeID, to->sizeID);
+ cpswaps(from->subpixelOrder, to->subpixelOrder);
+ cpswaps(from->widthInPixels, to->widthInPixels);
+ cpswaps(from->heightInPixels, to->heightInPixels);
+ cpswaps(from->widthInMillimeters, to->widthInMillimeters);
+ cpswaps(from->heightInMillimeters, to->heightInMillimeters);
+}
+
+static void
+SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent *from,
+ xRRCrtcChangeNotifyEvent *to)
+{
+ to->type = from->type;
+ to->subCode = from->subCode;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->timestamp, to->timestamp);
+ cpswapl(from->window, to->window);
+ cpswapl(from->crtc, to->crtc);
+ cpswapl(from->mode, to->mode);
+ cpswaps(from->rotation, to->rotation);
+ /* pad1 */
+ cpswaps(from->x, to->x);
+ cpswaps(from->y, to->y);
+ cpswaps(from->width, to->width);
+ cpswaps(from->height, to->height);
+}
+
+static void
+SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent *from,
+ xRROutputChangeNotifyEvent *to)
+{
+ to->type = from->type;
+ to->subCode = from->subCode;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->timestamp, to->timestamp);
+ cpswapl(from->configTimestamp, to->configTimestamp);
+ cpswapl(from->window, to->window);
+ cpswapl(from->output, to->output);
+ cpswapl(from->crtc, to->crtc);
+ cpswapl(from->mode, to->mode);
+ cpswaps(from->rotation, to->rotation);
+ to->connection = from->connection;
+ to->subpixelOrder = from->subpixelOrder;
+}
+
+static void
+SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent *from,
+ xRROutputPropertyNotifyEvent *to)
+{
+ to->type = from->type;
+ to->subCode = from->subCode;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->window, to->window);
+ cpswapl(from->output, to->output);
+ cpswapl(from->atom, to->atom);
+ cpswapl(from->timestamp, to->timestamp);
+ to->state = from->state;
+ /* pad1 */
+ /* pad2 */
+ /* pad3 */
+ /* pad4 */
+}
+
+static void
+SRRNotifyEvent (xEvent *from,
+ xEvent *to)
+{
+ switch (from->u.u.detail) {
+ case RRNotify_CrtcChange:
+ SRRCrtcChangeNotifyEvent ((xRRCrtcChangeNotifyEvent *) from,
+ (xRRCrtcChangeNotifyEvent *) to);
+ break;
+ case RRNotify_OutputChange:
+ SRROutputChangeNotifyEvent ((xRROutputChangeNotifyEvent *) from,
+ (xRROutputChangeNotifyEvent *) to);
+ break;
+ case RRNotify_OutputProperty:
+ SRROutputPropertyNotifyEvent ((xRROutputPropertyNotifyEvent *) from,
+ (xRROutputPropertyNotifyEvent *) to);
+ break;
+ default:
+ break;
+ }
+}
+
+static int RRGeneration;
+
+Bool RRInit (void)
+{
+ if (RRGeneration != serverGeneration)
+ {
+ if (!RRModeInit ())
+ return FALSE;
+ if (!RRCrtcInit ())
+ return FALSE;
+ if (!RROutputInit ())
+ return FALSE;
+ RRGeneration = serverGeneration;
+ }
+ if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0))
+ return FALSE;
+
+ return TRUE;
+}
+
+Bool RRScreenInit(ScreenPtr pScreen)
+{
+ rrScrPrivPtr pScrPriv;
+
+ if (!RRInit ())
+ return FALSE;
+
+ pScrPriv = (rrScrPrivPtr) calloc(1, sizeof (rrScrPrivRec));
+ if (!pScrPriv)
+ return FALSE;
+
+ SetRRScreen(pScreen, pScrPriv);
+
+ /*
+ * Calling function best set these function vectors
+ */
+ pScrPriv->rrGetInfo = 0;
+ pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
+ pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
+
+ pScrPriv->width = pScreen->width;
+ pScrPriv->height = pScreen->height;
+ pScrPriv->mmWidth = pScreen->mmWidth;
+ pScrPriv->mmHeight = pScreen->mmHeight;
+#if RANDR_12_INTERFACE
+ pScrPriv->rrScreenSetSize = NULL;
+ pScrPriv->rrCrtcSet = NULL;
+ pScrPriv->rrCrtcSetGamma = NULL;
+#endif
+#if RANDR_10_INTERFACE
+ pScrPriv->rrSetConfig = 0;
+ pScrPriv->rotations = RR_Rotate_0;
+ pScrPriv->reqWidth = pScreen->width;
+ pScrPriv->reqHeight = pScreen->height;
+ pScrPriv->nSizes = 0;
+ pScrPriv->pSizes = NULL;
+ pScrPriv->rotation = RR_Rotate_0;
+ pScrPriv->rate = 0;
+ pScrPriv->size = 0;
+#endif
+
+ /*
+ * This value doesn't really matter -- any client must call
+ * GetScreenInfo before reading it which will automatically update
+ * the time
+ */
+ pScrPriv->lastSetTime = currentTime;
+ pScrPriv->lastConfigTime = currentTime;
+
+ wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
+
+ pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
+
+ pScrPriv->numOutputs = 0;
+ pScrPriv->outputs = NULL;
+ pScrPriv->numCrtcs = 0;
+ pScrPriv->crtcs = NULL;
+
+ RRNScreens += 1; /* keep count of screens that implement randr */
+ return TRUE;
+}
+
+/*ARGSUSED*/
+static int
+RRFreeClient (pointer data, XID id)
+{
+ RREventPtr pRREvent;
+ WindowPtr pWin;
+ RREventPtr *pHead, pCur, pPrev;
+
+ pRREvent = (RREventPtr) data;
+ pWin = pRREvent->window;
+ dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
+ RREventType, serverClient, DixDestroyAccess);
+ if (pHead) {
+ pPrev = 0;
+ for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next)
+ pPrev = pCur;
+ if (pCur)
+ {
+ if (pPrev)
+ pPrev->next = pRREvent->next;
+ else
+ *pHead = pRREvent->next;
+ }
+ }
+ free((pointer) pRREvent);
+ return 1;
+}
+
+/*ARGSUSED*/
+static int
+RRFreeEvents (pointer data, XID id)
+{
+ RREventPtr *pHead, pCur, pNext;
+
+ pHead = (RREventPtr *) data;
+ for (pCur = *pHead; pCur; pCur = pNext) {
+ pNext = pCur->next;
+ FreeResource (pCur->clientResource, RRClientType);
+ free((pointer) pCur);
+ }
+ free((pointer) pHead);
+ return 1;
+}
+
+void
+RRExtensionInit (void)
+{
+ ExtensionEntry *extEntry;
+
+ if (RRNScreens == 0) return;
+
+ if (!dixRegisterPrivateKey(&RRClientPrivateKeyRec, PRIVATE_CLIENT,
+ sizeof (RRClientRec) +
+ screenInfo.numScreens * sizeof (RRTimesRec)))
+ return;
+ if (!AddCallback (&ClientStateCallback, RRClientCallback, 0))
+ return;
+
+ RRClientType = CreateNewResourceType(RRFreeClient, "RandRClient");
+ if (!RRClientType)
+ return;
+ RREventType = CreateNewResourceType(RRFreeEvents, "RandREvent");
+ if (!RREventType)
+ return;
+ extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors,
+ ProcRRDispatch, SProcRRDispatch,
+ NULL, StandardMinorOpcode);
+ if (!extEntry)
+ return;
+ RRErrorBase = extEntry->errorBase;
+ RREventBase = extEntry->eventBase;
+ EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
+ SRRScreenChangeNotifyEvent;
+ EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
+ SRRNotifyEvent;
+
+ RRModeInitErrorValue();
+ RRCrtcInitErrorValue();
+ RROutputInitErrorValue();
+
+#ifdef PANORAMIX
+ RRXineramaExtensionInit();
+#endif
+}
+
+static int
+TellChanged (WindowPtr pWin, pointer value)
+{
+ RREventPtr *pHead, pRREvent;
+ ClientPtr client;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ rrScrPriv(pScreen);
+ int i;
+
+ dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
+ RREventType, serverClient, DixReadAccess);
+ if (!pHead)
+ return WT_WALKCHILDREN;
+
+ for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
+ {
+ client = pRREvent->client;
+ if (client == serverClient || client->clientGone)
+ continue;
+
+ if (pRREvent->mask & RRScreenChangeNotifyMask)
+ RRDeliverScreenEvent (client, pWin, pScreen);
+
+ if (pRREvent->mask & RRCrtcChangeNotifyMask)
+ {
+ for (i = 0; i < pScrPriv->numCrtcs; i++)
+ {
+ RRCrtcPtr crtc = pScrPriv->crtcs[i];
+ if (crtc->changed)
+ RRDeliverCrtcEvent (client, pWin, crtc);
+ }
+ }
+
+ if (pRREvent->mask & RROutputChangeNotifyMask)
+ {
+ for (i = 0; i < pScrPriv->numOutputs; i++)
+ {
+ RROutputPtr output = pScrPriv->outputs[i];
+ if (output->changed)
+ RRDeliverOutputEvent (client, pWin, output);
+ }
+ }
+ }
+ return WT_WALKCHILDREN;
+}
+
+/*
+ * Something changed; send events and adjust pointer position
+ */
+void
+RRTellChanged (ScreenPtr pScreen)
+{
+ rrScrPriv (pScreen);
+ int i;
+
+ if (pScrPriv->changed)
+ {
+ UpdateCurrentTime ();
+ if (pScrPriv->configChanged)
+ {
+ pScrPriv->lastConfigTime = currentTime;
+ pScrPriv->configChanged = FALSE;
+ }
+ pScrPriv->changed = FALSE;
+ WalkTree (pScreen, TellChanged, (pointer) pScreen);
+ for (i = 0; i < pScrPriv->numOutputs; i++)
+ pScrPriv->outputs[i]->changed = FALSE;
+ for (i = 0; i < pScrPriv->numCrtcs; i++)
+ pScrPriv->crtcs[i]->changed = FALSE;
+ if (pScrPriv->layoutChanged)
+ {
+ pScrPriv->layoutChanged = FALSE;
+ RRPointerScreenConfigured (pScreen);
+ RRSendConfigNotify (pScreen);
+ }
+ }
+}
+
+/*
+ * Return the first output which is connected to an active CRTC
+ * Used in emulating 1.0 behaviour
+ */
+RROutputPtr
+RRFirstOutput (ScreenPtr pScreen)
+{
+ rrScrPriv(pScreen);
+ RROutputPtr output;
+ int i, j;
+
+ if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc)
+ return pScrPriv->primaryOutput;
+
+ for (i = 0; i < pScrPriv->numCrtcs; i++)
+ {
+ RRCrtcPtr crtc = pScrPriv->crtcs[i];
+ for (j = 0; j < pScrPriv->numOutputs; j++)
+ {
+ output = pScrPriv->outputs[j];
+ if (output->crtc == crtc)
+ return output;
+ }
+ }
+ return NULL;
+}
+
+CARD16
+RRVerticalRefresh (xRRModeInfo *mode)
+{
+ CARD32 refresh;
+ CARD32 dots = mode->hTotal * mode->vTotal;
+ if (!dots)
+ return 0;
+ refresh = (mode->dotClock + dots/2) / dots;
+ if (refresh > 0xffff)
+ refresh = 0xffff;
+ return (CARD16) refresh;
+}
+
+static int
+ProcRRDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+ if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
+ return BadRequest;
+ return (*ProcRandrVector[stuff->data]) (client);
+}
+
+static int
+SProcRRDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+ if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
+ return BadRequest;
+ return (*SProcRandrVector[stuff->data]) (client);
+}
+
diff --git a/xorg-server/randr/randrstr.h b/xorg-server/randr/randrstr.h
index 7ea608003..262a16420 100644
--- a/xorg-server/randr/randrstr.h
+++ b/xorg-server/randr/randrstr.h
@@ -1,970 +1,974 @@
-/*
- * Copyright © 2000 Compaq Computer Corporation
- * Copyright © 2002 Hewlett-Packard Company
- * Copyright © 2006 Intel Corporation
- * Copyright © 2008 Red Hat, Inc.
- *
- * 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.
- *
- * Author: Jim Gettys, Hewlett-Packard Company, Inc.
- * Keith Packard, Intel Corporation
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef _RANDRSTR_H_
-#define _RANDRSTR_H_
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "os.h"
-#include "dixstruct.h"
-#include "resource.h"
-#include "scrnintstr.h"
-#include "windowstr.h"
-#include "pixmapstr.h"
-#include "extnsionst.h"
-#include "servermd.h"
-#include "rrtransform.h"
-#include <X11/extensions/randr.h>
-#include <X11/extensions/randrproto.h>
-#include <X11/extensions/render.h> /* we share subpixel order information */
-#include "picturestr.h"
-#include <X11/Xfuncproto.h>
-
-/* required for ABI compatibility for now */
-#define RANDR_10_INTERFACE 1
-#define RANDR_12_INTERFACE 1
-#define RANDR_13_INTERFACE 1 /* requires RANDR_12_INTERFACE */
-#define RANDR_GET_CRTC_INTERFACE 1
-
-#define RANDR_INTERFACE_VERSION 0x0103
-
-typedef XID RRMode;
-typedef XID RROutput;
-typedef XID RRCrtc;
-
-extern _X_EXPORT int RREventBase, RRErrorBase;
-
-extern _X_EXPORT int (*ProcRandrVector[RRNumberRequests])(ClientPtr);
-extern _X_EXPORT int (*SProcRandrVector[RRNumberRequests])(ClientPtr);
-
-/*
- * Modeline for a monitor. Name follows directly after this struct
- */
-
-#define RRModeName(pMode) ((char *) (pMode + 1))
-typedef struct _rrMode RRModeRec, *RRModePtr;
-typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr;
-typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr;
-typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr;
-typedef struct _rrOutput RROutputRec, *RROutputPtr;
-
-struct _rrMode {
- int refcnt;
- xRRModeInfo mode;
- char *name;
- ScreenPtr userScreen;
-};
-
-struct _rrPropertyValue {
- Atom type; /* ignored by server */
- short format; /* format of data for swapping - 8,16,32 */
- long size; /* size of data in (format/8) bytes */
- pointer data; /* private to client */
-};
-
-struct _rrProperty {
- RRPropertyPtr next;
- ATOM propertyName;
- Bool is_pending;
- Bool range;
- Bool immutable;
- int num_valid;
- INT32 *valid_values;
- RRPropertyValueRec current, pending;
-};
-
-struct _rrCrtc {
- RRCrtc id;
- ScreenPtr pScreen;
- RRModePtr mode;
- int x, y;
- Rotation rotation;
- Rotation rotations;
- Bool changed;
- int numOutputs;
- RROutputPtr *outputs;
- int gammaSize;
- CARD16 *gammaRed;
- CARD16 *gammaBlue;
- CARD16 *gammaGreen;
- void *devPrivate;
- Bool transforms;
- RRTransformRec client_pending_transform;
- RRTransformRec client_current_transform;
- PictTransform transform;
- struct pict_f_transform f_transform;
- struct pict_f_transform f_inverse;
-};
-
-struct _rrOutput {
- RROutput id;
- ScreenPtr pScreen;
- char *name;
- int nameLength;
- CARD8 connection;
- CARD8 subpixelOrder;
- int mmWidth;
- int mmHeight;
- RRCrtcPtr crtc;
- int numCrtcs;
- RRCrtcPtr *crtcs;
- int numClones;
- RROutputPtr *clones;
- int numModes;
- int numPreferred;
- RRModePtr *modes;
- int numUserModes;
- RRModePtr *userModes;
- Bool changed;
- RRPropertyPtr properties;
- Bool pendingProperties;
- void *devPrivate;
-};
-
-#if RANDR_12_INTERFACE
-typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen,
- CARD16 width,
- CARD16 height,
- CARD32 mmWidth,
- CARD32 mmHeight);
-
-typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr pScreen,
- RRCrtcPtr crtc,
- RRModePtr mode,
- int x,
- int y,
- Rotation rotation,
- int numOutputs,
- RROutputPtr *outputs);
-
-typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr pScreen,
- RRCrtcPtr crtc);
-
-typedef Bool (*RRCrtcGetGammaProcPtr) (ScreenPtr pScreen,
- RRCrtcPtr crtc);
-
-typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr pScreen,
- RROutputPtr output,
- Atom property,
- RRPropertyValuePtr value);
-
-typedef Bool (*RROutputValidateModeProcPtr) (ScreenPtr pScreen,
- RROutputPtr output,
- RRModePtr mode);
-
-typedef void (*RRModeDestroyProcPtr) (ScreenPtr pScreen,
- RRModePtr mode);
-
-#endif
-
-#if RANDR_13_INTERFACE
-typedef Bool (*RROutputGetPropertyProcPtr) (ScreenPtr pScreen,
- RROutputPtr output,
- Atom property);
-typedef Bool (*RRGetPanningProcPtr) (ScreenPtr pScrn,
- RRCrtcPtr crtc,
- BoxPtr totalArea,
- BoxPtr trackingArea,
- INT16 *border);
-typedef Bool (*RRSetPanningProcPtr) (ScreenPtr pScrn,
- RRCrtcPtr crtc,
- BoxPtr totalArea,
- BoxPtr trackingArea,
- INT16 *border);
-
-#endif /* RANDR_13_INTERFACE */
-
-typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
-typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen);
-
-/* These are for 1.0 compatibility */
-
-typedef struct _rrRefresh {
- CARD16 rate;
- RRModePtr mode;
-} RRScreenRate, *RRScreenRatePtr;
-
-typedef struct _rrScreenSize {
- int id;
- short width, height;
- short mmWidth, mmHeight;
- int nRates;
- RRScreenRatePtr pRates;
-} RRScreenSize, *RRScreenSizePtr;
-
-#ifdef RANDR_10_INTERFACE
-
-typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen,
- Rotation rotation,
- int rate,
- RRScreenSizePtr pSize);
-
-#endif
-
-
-typedef struct _rrScrPriv {
- /*
- * 'public' part of the structure; DDXen fill this in
- * as they initialize
- */
-#if RANDR_10_INTERFACE
- RRSetConfigProcPtr rrSetConfig;
-#endif
- RRGetInfoProcPtr rrGetInfo;
-#if RANDR_12_INTERFACE
- RRScreenSetSizeProcPtr rrScreenSetSize;
- RRCrtcSetProcPtr rrCrtcSet;
- RRCrtcSetGammaProcPtr rrCrtcSetGamma;
- RRCrtcGetGammaProcPtr rrCrtcGetGamma;
- RROutputSetPropertyProcPtr rrOutputSetProperty;
- RROutputValidateModeProcPtr rrOutputValidateMode;
- RRModeDestroyProcPtr rrModeDestroy;
-#endif
-#if RANDR_13_INTERFACE
- RROutputGetPropertyProcPtr rrOutputGetProperty;
- RRGetPanningProcPtr rrGetPanning;
- RRSetPanningProcPtr rrSetPanning;
-#endif
-
- /*
- * Private part of the structure; not considered part of the ABI
- */
- TimeStamp lastSetTime; /* last changed by client */
- TimeStamp lastConfigTime; /* possible configs changed */
- RRCloseScreenProcPtr CloseScreen;
-
- Bool changed; /* some config changed */
- Bool configChanged; /* configuration changed */
- Bool layoutChanged; /* screen layout changed */
-
- CARD16 minWidth, minHeight;
- CARD16 maxWidth, maxHeight;
- CARD16 width, height; /* last known screen size */
- CARD16 mmWidth, mmHeight; /* last known screen size */
-
- int numOutputs;
- RROutputPtr *outputs;
- RROutputPtr primaryOutput;
-
- int numCrtcs;
- RRCrtcPtr *crtcs;
-
- /* Last known pointer position */
- RRCrtcPtr pointerCrtc;
-
-#ifdef RANDR_10_INTERFACE
- /*
- * Configuration information
- */
- Rotation rotations;
- CARD16 reqWidth, reqHeight;
-
- int nSizes;
- RRScreenSizePtr pSizes;
-
- Rotation rotation;
- int rate;
- int size;
-#endif
-} rrScrPrivRec, *rrScrPrivPtr;
-
-extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
-#define rrPrivKey (&rrPrivKeyRec)
-
-#define rrGetScrPriv(pScr) ((rrScrPrivPtr)dixLookupPrivate(&(pScr)->devPrivates, rrPrivKey))
-#define rrScrPriv(pScr) rrScrPrivPtr pScrPriv = rrGetScrPriv(pScr)
-#define SetRRScreen(s,p) dixSetPrivate(&(s)->devPrivates, rrPrivKey, p)
-
-/*
- * each window has a list of clients requesting
- * RRNotify events. Each client has a resource
- * for each window it selects RRNotify input for,
- * this resource is used to delete the RRNotifyRec
- * entry from the per-window queue.
- */
-
-typedef struct _RREvent *RREventPtr;
-
-typedef struct _RREvent {
- RREventPtr next;
- ClientPtr client;
- WindowPtr window;
- XID clientResource;
- int mask;
-} RREventRec;
-
-typedef struct _RRTimes {
- TimeStamp setTime;
- TimeStamp configTime;
-} RRTimesRec, *RRTimesPtr;
-
-typedef struct _RRClient {
- int major_version;
- int minor_version;
-/* RRTimesRec times[0]; */
-} RRClientRec, *RRClientPtr;
-
-extern _X_EXPORT RESTYPE RRClientType, RREventType; /* resource types for event masks */
-extern _X_EXPORT DevPrivateKeyRec RRClientPrivateKeyRec;
-#define RRClientPrivateKey (&RRClientPrivateKeyRec)
-extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType;
-
-#define VERIFY_RR_OUTPUT(id, ptr, a)\
- {\
- int rc = dixLookupResourceByType((pointer *)&(ptr), id,\
- RROutputType, client, a);\
- if (rc != Success) {\
- client->errorValue = id;\
- return rc;\
- }\
- }
-
-#define VERIFY_RR_CRTC(id, ptr, a)\
- {\
- int rc = dixLookupResourceByType((pointer *)&(ptr), id,\
- RRCrtcType, client, a);\
- if (rc != Success) {\
- client->errorValue = id;\
- return rc;\
- }\
- }
-
-#define VERIFY_RR_MODE(id, ptr, a)\
- {\
- int rc = dixLookupResourceByType((pointer *)&(ptr), id,\
- RRModeType, client, a);\
- if (rc != Success) {\
- client->errorValue = id;\
- return rc;\
- }\
- }
-
-#define GetRRClient(pClient) ((RRClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RRClientPrivateKey))
-#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
-
-/* Initialize the extension */
-extern _X_EXPORT void
-RRExtensionInit (void);
-
-#ifdef RANDR_12_INTERFACE
-/*
- * Set the range of sizes for the screen
- */
-extern _X_EXPORT void
-RRScreenSetSizeRange (ScreenPtr pScreen,
- CARD16 minWidth,
- CARD16 minHeight,
- CARD16 maxWidth,
- CARD16 maxHeight);
-#endif
-
-/* rrscreen.c */
-/*
- * Notify the extension that the screen size has been changed.
- * The driver is responsible for calling this whenever it has changed
- * the size of the screen
- */
-extern _X_EXPORT void
-RRScreenSizeNotify (ScreenPtr pScreen);
-
-/*
- * Request that the screen be resized
- */
-extern _X_EXPORT Bool
-RRScreenSizeSet (ScreenPtr pScreen,
- CARD16 width,
- CARD16 height,
- CARD32 mmWidth,
- CARD32 mmHeight);
-
-/*
- * Send ConfigureNotify event to root window when 'something' happens
- */
-extern _X_EXPORT void
-RRSendConfigNotify (ScreenPtr pScreen);
-
-/*
- * screen dispatch
- */
-extern _X_EXPORT int
-ProcRRGetScreenSizeRange (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRSetScreenSize (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRGetScreenResources (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRGetScreenResourcesCurrent (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRSetScreenConfig (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRGetScreenInfo (ClientPtr client);
-
-/*
- * Deliver a ScreenNotify event
- */
-extern _X_EXPORT void
-RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen);
-
-/* randr.c */
-/*
- * Send all pending events
- */
-extern _X_EXPORT void
-RRTellChanged (ScreenPtr pScreen);
-
-/*
- * Poll the driver for changed information
- */
-extern _X_EXPORT Bool
-RRGetInfo (ScreenPtr pScreen, Bool force_query);
-
-extern _X_EXPORT Bool RRInit (void);
-
-extern _X_EXPORT Bool RRScreenInit(ScreenPtr pScreen);
-
-extern _X_EXPORT RROutputPtr
-RRFirstOutput (ScreenPtr pScreen);
-
-extern _X_EXPORT Rotation
-RRGetRotation (ScreenPtr pScreen);
-
-extern _X_EXPORT CARD16
-RRVerticalRefresh (xRRModeInfo *mode);
-
-#ifdef RANDR_10_INTERFACE
-/*
- * This is the old interface, deprecated but left
- * around for compatibility
- */
-
-/*
- * Then, register the specific size with the screen
- */
-
-extern _X_EXPORT RRScreenSizePtr
-RRRegisterSize (ScreenPtr pScreen,
- short width,
- short height,
- short mmWidth,
- short mmHeight);
-
-extern _X_EXPORT Bool
-RRRegisterRate (ScreenPtr pScreen,
- RRScreenSizePtr pSize,
- int rate);
-
-/*
- * Finally, set the current configuration of the screen
- */
-
-extern _X_EXPORT void
-RRSetCurrentConfig (ScreenPtr pScreen,
- Rotation rotation,
- int rate,
- RRScreenSizePtr pSize);
-
-extern _X_EXPORT Bool RRScreenInit (ScreenPtr pScreen);
-
-extern _X_EXPORT Rotation
-RRGetRotation (ScreenPtr pScreen);
-
-#endif
-
-/* rrcrtc.c */
-
-/*
- * Notify the CRTC of some change; layoutChanged indicates that
- * some position or size element changed
- */
-extern _X_EXPORT void
-RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged);
-
-/*
- * Create a CRTC
- */
-extern _X_EXPORT RRCrtcPtr
-RRCrtcCreate (ScreenPtr pScreen, void *devPrivate);
-
-/*
- * Set the allowed rotations on a CRTC
- */
-extern _X_EXPORT void
-RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations);
-
-/*
- * Set whether transforms are allowed on a CRTC
- */
-extern _X_EXPORT void
-RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms);
-
-/*
- * Notify the extension that the Crtc has been reconfigured,
- * the driver calls this whenever it has updated the mode
- */
-extern _X_EXPORT Bool
-RRCrtcNotify (RRCrtcPtr crtc,
- RRModePtr mode,
- int x,
- int y,
- Rotation rotation,
- RRTransformPtr transform,
- int numOutputs,
- RROutputPtr *outputs);
-
-extern _X_EXPORT void
-RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc);
-
-/*
- * Request that the Crtc be reconfigured
- */
-extern _X_EXPORT Bool
-RRCrtcSet (RRCrtcPtr crtc,
- RRModePtr mode,
- int x,
- int y,
- Rotation rotation,
- int numOutput,
- RROutputPtr *outputs);
-
-/*
- * Request that the Crtc gamma be changed
- */
-
-extern _X_EXPORT Bool
-RRCrtcGammaSet (RRCrtcPtr crtc,
- CARD16 *red,
- CARD16 *green,
- CARD16 *blue);
-
-/*
- * Request current gamma back from the DDX (if possible).
- * This includes gamma size.
- */
-
-extern _X_EXPORT Bool
-RRCrtcGammaGet(RRCrtcPtr crtc);
-
-/*
- * Notify the extension that the Crtc gamma has been changed
- * The driver calls this whenever it has changed the gamma values
- * in the RRCrtcRec
- */
-
-extern _X_EXPORT Bool
-RRCrtcGammaNotify (RRCrtcPtr crtc);
-
-/*
- * Set the size of the gamma table at server startup time
- */
-
-extern _X_EXPORT Bool
-RRCrtcGammaSetSize (RRCrtcPtr crtc,
- int size);
-
-/*
- * Return the area of the frame buffer scanned out by the crtc,
- * taking into account the current mode and rotation
- */
-
-extern _X_EXPORT void
-RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
-
-/*
- * Compute the complete transformation matrix including
- * client-specified transform, rotation/reflection values and the crtc
- * offset.
- *
- * Return TRUE if the resulting transform is not a simple translation.
- */
-extern _X_EXPORT Bool
-RRTransformCompute (int x,
- int y,
- int width,
- int height,
- Rotation rotation,
- RRTransformPtr rr_transform,
-
- PictTransformPtr transform,
- struct pict_f_transform *f_transform,
- struct pict_f_transform *f_inverse);
-
-/*
- * Return crtc transform
- */
-extern _X_EXPORT RRTransformPtr
-RRCrtcGetTransform (RRCrtcPtr crtc);
-
-/*
- * Check whether the pending and current transforms are the same
- */
-extern _X_EXPORT Bool
-RRCrtcPendingTransform (RRCrtcPtr crtc);
-
-/*
- * Destroy a Crtc at shutdown
- */
-extern _X_EXPORT void
-RRCrtcDestroy (RRCrtcPtr crtc);
-
-
-/*
- * Set the pending CRTC transformation
- */
-
-extern _X_EXPORT int
-RRCrtcTransformSet (RRCrtcPtr crtc,
- PictTransformPtr transform,
- struct pict_f_transform *f_transform,
- struct pict_f_transform *f_inverse,
- char *filter,
- int filter_len,
- xFixed *params,
- int nparams);
-
-/*
- * Initialize crtc type
- */
-extern _X_EXPORT Bool
-RRCrtcInit (void);
-
-/*
- * Initialize crtc type error value
- */
-extern _X_EXPORT void
-RRCrtcInitErrorValue (void);
-
-/*
- * Crtc dispatch
- */
-
-extern _X_EXPORT int
-ProcRRGetCrtcInfo (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRSetCrtcConfig (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRGetCrtcGammaSize (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRGetCrtcGamma (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRSetCrtcGamma (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRSetCrtcTransform (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRGetCrtcTransform (ClientPtr client);
-
-int
-ProcRRGetPanning (ClientPtr client);
-
-int
-ProcRRSetPanning (ClientPtr client);
-
-/* rrdispatch.c */
-extern _X_EXPORT Bool
-RRClientKnowsRates (ClientPtr pClient);
-
-/* rrmode.c */
-/*
- * Find, and if necessary, create a mode
- */
-
-extern _X_EXPORT RRModePtr
-RRModeGet (xRRModeInfo *modeInfo,
- const char *name);
-
-/*
- * Destroy a mode.
- */
-
-extern _X_EXPORT void
-RRModeDestroy (RRModePtr mode);
-
-/*
- * Return a list of modes that are valid for some output in pScreen
- */
-extern _X_EXPORT RRModePtr *
-RRModesForScreen (ScreenPtr pScreen, int *num_ret);
-
-/*
- * Initialize mode type
- */
-extern _X_EXPORT Bool
-RRModeInit (void);
-
-/*
- * Initialize mode type error value
- */
-extern _X_EXPORT void
-RRModeInitErrorValue (void);
-
-extern _X_EXPORT int
-ProcRRCreateMode (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRDestroyMode (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRAddOutputMode (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRDeleteOutputMode (ClientPtr client);
-
-/* rroutput.c */
-
-/*
- * Notify the output of some change. configChanged indicates whether
- * any external configuration (mode list, clones, connected status)
- * has changed, or whether the change was strictly internal
- * (which crtc is in use)
- */
-extern _X_EXPORT void
-RROutputChanged (RROutputPtr output, Bool configChanged);
-
-/*
- * Create an output
- */
-
-extern _X_EXPORT RROutputPtr
-RROutputCreate (ScreenPtr pScreen,
- const char *name,
- int nameLength,
- void *devPrivate);
-
-/*
- * Notify extension that output parameters have been changed
- */
-extern _X_EXPORT Bool
-RROutputSetClones (RROutputPtr output,
- RROutputPtr *clones,
- int numClones);
-
-extern _X_EXPORT Bool
-RROutputSetModes (RROutputPtr output,
- RRModePtr *modes,
- int numModes,
- int numPreferred);
-
-extern _X_EXPORT int
-RROutputAddUserMode (RROutputPtr output,
- RRModePtr mode);
-
-extern _X_EXPORT int
-RROutputDeleteUserMode (RROutputPtr output,
- RRModePtr mode);
-
-extern _X_EXPORT Bool
-RROutputSetCrtcs (RROutputPtr output,
- RRCrtcPtr *crtcs,
- int numCrtcs);
-
-extern _X_EXPORT Bool
-RROutputSetConnection (RROutputPtr output,
- CARD8 connection);
-
-extern _X_EXPORT Bool
-RROutputSetSubpixelOrder (RROutputPtr output,
- int subpixelOrder);
-
-extern _X_EXPORT Bool
-RROutputSetPhysicalSize (RROutputPtr output,
- int mmWidth,
- int mmHeight);
-
-extern _X_EXPORT void
-RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output);
-
-extern _X_EXPORT void
-RROutputDestroy (RROutputPtr output);
-
-extern _X_EXPORT int
-ProcRRGetOutputInfo (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRSetOutputPrimary (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRGetOutputPrimary (ClientPtr client);
-
-/*
- * Initialize output type
- */
-extern _X_EXPORT Bool
-RROutputInit (void);
-
-/*
- * Initialize output type error value
- */
-extern _X_EXPORT void
-RROutputInitErrorValue (void);
-
-/* rrpointer.c */
-extern _X_EXPORT void
-RRPointerMoved (ScreenPtr pScreen, int x, int y);
-
-extern _X_EXPORT void
-RRPointerScreenConfigured (ScreenPtr pScreen);
-
-/* rrproperty.c */
-
-extern _X_EXPORT void
-RRDeleteAllOutputProperties (RROutputPtr output);
-
-extern _X_EXPORT RRPropertyValuePtr
-RRGetOutputProperty (RROutputPtr output, Atom property, Bool pending);
-
-extern _X_EXPORT RRPropertyPtr
-RRQueryOutputProperty (RROutputPtr output, Atom property);
-
-extern _X_EXPORT void
-RRDeleteOutputProperty (RROutputPtr output, Atom property);
-
-extern _X_EXPORT Bool
-RRPostPendingProperties (RROutputPtr output);
-
-extern _X_EXPORT int
-RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
- int format, int mode, unsigned long len,
- pointer value, Bool sendevent, Bool pending);
-
-extern _X_EXPORT int
-RRConfigureOutputProperty (RROutputPtr output, Atom property,
- Bool pending, Bool range, Bool immutable,
- int num_values, INT32 *values);
-extern _X_EXPORT int
-ProcRRChangeOutputProperty (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRGetOutputProperty (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRListOutputProperties (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRQueryOutputProperty (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRConfigureOutputProperty (ClientPtr client);
-
-extern _X_EXPORT int
-ProcRRDeleteOutputProperty (ClientPtr client);
-
-/* rrxinerama.c */
-#ifdef XINERAMA
-extern _X_EXPORT void
-RRXineramaExtensionInit(void);
-#endif
-
-#endif /* _RANDRSTR_H_ */
-
-/*
-
-randr extension implementation structure
-
-Query state:
- ProcRRGetScreenInfo/ProcRRGetScreenResources
- RRGetInfo
-
- • Request configuration from driver, either 1.0 or 1.2 style
- • These functions only record state changes, all
- other actions are pended until RRTellChanged is called
-
- ->rrGetInfo
- 1.0:
- RRRegisterSize
- RRRegisterRate
- RRSetCurrentConfig
- 1.2:
- RRScreenSetSizeRange
- RROutputSetCrtcs
- RRModeGet
- RROutputSetModes
- RROutputSetConnection
- RROutputSetSubpixelOrder
- RROutputSetClones
- RRCrtcNotify
-
- • Must delay scanning configuration until after ->rrGetInfo returns
- because some drivers will call SetCurrentConfig in the middle
- of the ->rrGetInfo operation.
-
- 1.0:
-
- • Scan old configuration, mirror to new structures
-
- RRScanOldConfig
- RRCrtcCreate
- RROutputCreate
- RROutputSetCrtcs
- RROutputSetConnection
- RROutputSetSubpixelOrder
- RROldModeAdd • This adds modes one-at-a-time
- RRModeGet
- RRCrtcNotify
-
- • send events, reset pointer if necessary
-
- RRTellChanged
- WalkTree (sending events)
-
- • when layout has changed:
- RRPointerScreenConfigured
- RRSendConfigNotify
-
-Asynchronous state setting (1.2 only)
- When setting state asynchronously, the driver invokes the
- ->rrGetInfo function and then calls RRTellChanged to flush
- the changes to the clients and reset pointer if necessary
-
-Set state
-
- ProcRRSetScreenConfig
- RRCrtcSet
- 1.2:
- ->rrCrtcSet
- RRCrtcNotify
- 1.0:
- ->rrSetConfig
- RRCrtcNotify
- RRTellChanged
- */
+/*
+ * Copyright © 2000 Compaq Computer Corporation
+ * Copyright © 2002 Hewlett-Packard Company
+ * Copyright © 2006 Intel Corporation
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Author: Jim Gettys, Hewlett-Packard Company, Inc.
+ * Keith Packard, Intel Corporation
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef _RANDRSTR_H_
+#define _RANDRSTR_H_
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "extnsionst.h"
+#include "servermd.h"
+#include "rrtransform.h"
+#include <X11/extensions/randr.h>
+#include <X11/extensions/randrproto.h>
+#include <X11/extensions/render.h> /* we share subpixel order information */
+#include "picturestr.h"
+#include <X11/Xfuncproto.h>
+
+/* required for ABI compatibility for now */
+#define RANDR_10_INTERFACE 1
+#define RANDR_12_INTERFACE 1
+#define RANDR_13_INTERFACE 1 /* requires RANDR_12_INTERFACE */
+#define RANDR_GET_CRTC_INTERFACE 1
+
+#define RANDR_INTERFACE_VERSION 0x0103
+
+typedef XID RRMode;
+typedef XID RROutput;
+typedef XID RRCrtc;
+
+extern _X_EXPORT int RREventBase, RRErrorBase;
+
+extern _X_EXPORT int (*ProcRandrVector[RRNumberRequests])(ClientPtr);
+extern _X_EXPORT int (*SProcRandrVector[RRNumberRequests])(ClientPtr);
+
+/*
+ * Modeline for a monitor. Name follows directly after this struct
+ */
+
+#define RRModeName(pMode) ((char *) (pMode + 1))
+typedef struct _rrMode RRModeRec, *RRModePtr;
+typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr;
+typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr;
+typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr;
+typedef struct _rrOutput RROutputRec, *RROutputPtr;
+
+struct _rrMode {
+ int refcnt;
+ xRRModeInfo mode;
+ char *name;
+ ScreenPtr userScreen;
+};
+
+struct _rrPropertyValue {
+ Atom type; /* ignored by server */
+ short format; /* format of data for swapping - 8,16,32 */
+ long size; /* size of data in (format/8) bytes */
+ pointer data; /* private to client */
+};
+
+struct _rrProperty {
+ RRPropertyPtr next;
+ ATOM propertyName;
+ Bool is_pending;
+ Bool range;
+ Bool immutable;
+ int num_valid;
+ INT32 *valid_values;
+ RRPropertyValueRec current, pending;
+};
+
+struct _rrCrtc {
+ RRCrtc id;
+ ScreenPtr pScreen;
+ RRModePtr mode;
+ int x, y;
+ Rotation rotation;
+ Rotation rotations;
+ Bool changed;
+ int numOutputs;
+ RROutputPtr *outputs;
+ int gammaSize;
+ CARD16 *gammaRed;
+ CARD16 *gammaBlue;
+ CARD16 *gammaGreen;
+ void *devPrivate;
+ Bool transforms;
+ RRTransformRec client_pending_transform;
+ RRTransformRec client_current_transform;
+ PictTransform transform;
+ struct pict_f_transform f_transform;
+ struct pict_f_transform f_inverse;
+};
+
+struct _rrOutput {
+ RROutput id;
+ ScreenPtr pScreen;
+ char *name;
+ int nameLength;
+ CARD8 connection;
+ CARD8 subpixelOrder;
+ int mmWidth;
+ int mmHeight;
+ RRCrtcPtr crtc;
+ int numCrtcs;
+ RRCrtcPtr *crtcs;
+ int numClones;
+ RROutputPtr *clones;
+ int numModes;
+ int numPreferred;
+ RRModePtr *modes;
+ int numUserModes;
+ RRModePtr *userModes;
+ Bool changed;
+ RRPropertyPtr properties;
+ Bool pendingProperties;
+ void *devPrivate;
+};
+
+#if RANDR_12_INTERFACE
+typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen,
+ CARD16 width,
+ CARD16 height,
+ CARD32 mmWidth,
+ CARD32 mmHeight);
+
+typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr pScreen,
+ RRCrtcPtr crtc,
+ RRModePtr mode,
+ int x,
+ int y,
+ Rotation rotation,
+ int numOutputs,
+ RROutputPtr *outputs);
+
+typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr pScreen,
+ RRCrtcPtr crtc);
+
+typedef Bool (*RRCrtcGetGammaProcPtr) (ScreenPtr pScreen,
+ RRCrtcPtr crtc);
+
+typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr pScreen,
+ RROutputPtr output,
+ Atom property,
+ RRPropertyValuePtr value);
+
+typedef Bool (*RROutputValidateModeProcPtr) (ScreenPtr pScreen,
+ RROutputPtr output,
+ RRModePtr mode);
+
+typedef void (*RRModeDestroyProcPtr) (ScreenPtr pScreen,
+ RRModePtr mode);
+
+#endif
+
+#if RANDR_13_INTERFACE
+typedef Bool (*RROutputGetPropertyProcPtr) (ScreenPtr pScreen,
+ RROutputPtr output,
+ Atom property);
+typedef Bool (*RRGetPanningProcPtr) (ScreenPtr pScrn,
+ RRCrtcPtr crtc,
+ BoxPtr totalArea,
+ BoxPtr trackingArea,
+ INT16 *border);
+typedef Bool (*RRSetPanningProcPtr) (ScreenPtr pScrn,
+ RRCrtcPtr crtc,
+ BoxPtr totalArea,
+ BoxPtr trackingArea,
+ INT16 *border);
+
+#endif /* RANDR_13_INTERFACE */
+
+typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
+typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen);
+
+/* These are for 1.0 compatibility */
+
+typedef struct _rrRefresh {
+ CARD16 rate;
+ RRModePtr mode;
+} RRScreenRate, *RRScreenRatePtr;
+
+typedef struct _rrScreenSize {
+ int id;
+ short width, height;
+ short mmWidth, mmHeight;
+ int nRates;
+ RRScreenRatePtr pRates;
+} RRScreenSize, *RRScreenSizePtr;
+
+#ifdef RANDR_10_INTERFACE
+
+typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen,
+ Rotation rotation,
+ int rate,
+ RRScreenSizePtr pSize);
+
+#endif
+
+
+typedef struct _rrScrPriv {
+ /*
+ * 'public' part of the structure; DDXen fill this in
+ * as they initialize
+ */
+#if RANDR_10_INTERFACE
+ RRSetConfigProcPtr rrSetConfig;
+#endif
+ RRGetInfoProcPtr rrGetInfo;
+#if RANDR_12_INTERFACE
+ RRScreenSetSizeProcPtr rrScreenSetSize;
+ RRCrtcSetProcPtr rrCrtcSet;
+ RRCrtcSetGammaProcPtr rrCrtcSetGamma;
+ RRCrtcGetGammaProcPtr rrCrtcGetGamma;
+ RROutputSetPropertyProcPtr rrOutputSetProperty;
+ RROutputValidateModeProcPtr rrOutputValidateMode;
+ RRModeDestroyProcPtr rrModeDestroy;
+#endif
+#if RANDR_13_INTERFACE
+ RROutputGetPropertyProcPtr rrOutputGetProperty;
+ RRGetPanningProcPtr rrGetPanning;
+ RRSetPanningProcPtr rrSetPanning;
+#endif
+
+ /*
+ * Private part of the structure; not considered part of the ABI
+ */
+ TimeStamp lastSetTime; /* last changed by client */
+ TimeStamp lastConfigTime; /* possible configs changed */
+ RRCloseScreenProcPtr CloseScreen;
+
+ Bool changed; /* some config changed */
+ Bool configChanged; /* configuration changed */
+ Bool layoutChanged; /* screen layout changed */
+
+ CARD16 minWidth, minHeight;
+ CARD16 maxWidth, maxHeight;
+ CARD16 width, height; /* last known screen size */
+ CARD16 mmWidth, mmHeight; /* last known screen size */
+
+ int numOutputs;
+ RROutputPtr *outputs;
+ RROutputPtr primaryOutput;
+
+ int numCrtcs;
+ RRCrtcPtr *crtcs;
+
+ /* Last known pointer position */
+ RRCrtcPtr pointerCrtc;
+
+#ifdef RANDR_10_INTERFACE
+ /*
+ * Configuration information
+ */
+ Rotation rotations;
+ CARD16 reqWidth, reqHeight;
+
+ int nSizes;
+ RRScreenSizePtr pSizes;
+
+ Rotation rotation;
+ int rate;
+ int size;
+#endif
+ Bool discontiguous;
+} rrScrPrivRec, *rrScrPrivPtr;
+
+extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
+#define rrPrivKey (&rrPrivKeyRec)
+
+#define rrGetScrPriv(pScr) ((rrScrPrivPtr)dixLookupPrivate(&(pScr)->devPrivates, rrPrivKey))
+#define rrScrPriv(pScr) rrScrPrivPtr pScrPriv = rrGetScrPriv(pScr)
+#define SetRRScreen(s,p) dixSetPrivate(&(s)->devPrivates, rrPrivKey, p)
+
+/*
+ * each window has a list of clients requesting
+ * RRNotify events. Each client has a resource
+ * for each window it selects RRNotify input for,
+ * this resource is used to delete the RRNotifyRec
+ * entry from the per-window queue.
+ */
+
+typedef struct _RREvent *RREventPtr;
+
+typedef struct _RREvent {
+ RREventPtr next;
+ ClientPtr client;
+ WindowPtr window;
+ XID clientResource;
+ int mask;
+} RREventRec;
+
+typedef struct _RRTimes {
+ TimeStamp setTime;
+ TimeStamp configTime;
+} RRTimesRec, *RRTimesPtr;
+
+typedef struct _RRClient {
+ int major_version;
+ int minor_version;
+/* RRTimesRec times[0]; */
+} RRClientRec, *RRClientPtr;
+
+extern _X_EXPORT RESTYPE RRClientType, RREventType; /* resource types for event masks */
+extern _X_EXPORT DevPrivateKeyRec RRClientPrivateKeyRec;
+#define RRClientPrivateKey (&RRClientPrivateKeyRec)
+extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType;
+
+#define VERIFY_RR_OUTPUT(id, ptr, a)\
+ {\
+ int rc = dixLookupResourceByType((pointer *)&(ptr), id,\
+ RROutputType, client, a);\
+ if (rc != Success) {\
+ client->errorValue = id;\
+ return rc;\
+ }\
+ }
+
+#define VERIFY_RR_CRTC(id, ptr, a)\
+ {\
+ int rc = dixLookupResourceByType((pointer *)&(ptr), id,\
+ RRCrtcType, client, a);\
+ if (rc != Success) {\
+ client->errorValue = id;\
+ return rc;\
+ }\
+ }
+
+#define VERIFY_RR_MODE(id, ptr, a)\
+ {\
+ int rc = dixLookupResourceByType((pointer *)&(ptr), id,\
+ RRModeType, client, a);\
+ if (rc != Success) {\
+ client->errorValue = id;\
+ return rc;\
+ }\
+ }
+
+#define GetRRClient(pClient) ((RRClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RRClientPrivateKey))
+#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
+
+/* Initialize the extension */
+extern _X_EXPORT void
+RRExtensionInit (void);
+
+#ifdef RANDR_12_INTERFACE
+/*
+ * Set the range of sizes for the screen
+ */
+extern _X_EXPORT void
+RRScreenSetSizeRange (ScreenPtr pScreen,
+ CARD16 minWidth,
+ CARD16 minHeight,
+ CARD16 maxWidth,
+ CARD16 maxHeight);
+#endif
+
+/* rrscreen.c */
+/*
+ * Notify the extension that the screen size has been changed.
+ * The driver is responsible for calling this whenever it has changed
+ * the size of the screen
+ */
+extern _X_EXPORT void
+RRScreenSizeNotify (ScreenPtr pScreen);
+
+/*
+ * Request that the screen be resized
+ */
+extern _X_EXPORT Bool
+RRScreenSizeSet (ScreenPtr pScreen,
+ CARD16 width,
+ CARD16 height,
+ CARD32 mmWidth,
+ CARD32 mmHeight);
+
+/*
+ * Send ConfigureNotify event to root window when 'something' happens
+ */
+extern _X_EXPORT void
+RRSendConfigNotify (ScreenPtr pScreen);
+
+/*
+ * screen dispatch
+ */
+extern _X_EXPORT int
+ProcRRGetScreenSizeRange (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRSetScreenSize (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRGetScreenResources (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRGetScreenResourcesCurrent (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRSetScreenConfig (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRGetScreenInfo (ClientPtr client);
+
+/*
+ * Deliver a ScreenNotify event
+ */
+extern _X_EXPORT void
+RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen);
+
+/* randr.c */
+/*
+ * Send all pending events
+ */
+extern _X_EXPORT void
+RRTellChanged (ScreenPtr pScreen);
+
+/*
+ * Poll the driver for changed information
+ */
+extern _X_EXPORT Bool
+RRGetInfo (ScreenPtr pScreen, Bool force_query);
+
+extern _X_EXPORT Bool RRInit (void);
+
+extern _X_EXPORT Bool RRScreenInit(ScreenPtr pScreen);
+
+extern _X_EXPORT RROutputPtr
+RRFirstOutput (ScreenPtr pScreen);
+
+extern _X_EXPORT Rotation
+RRGetRotation (ScreenPtr pScreen);
+
+extern _X_EXPORT CARD16
+RRVerticalRefresh (xRRModeInfo *mode);
+
+#ifdef RANDR_10_INTERFACE
+/*
+ * This is the old interface, deprecated but left
+ * around for compatibility
+ */
+
+/*
+ * Then, register the specific size with the screen
+ */
+
+extern _X_EXPORT RRScreenSizePtr
+RRRegisterSize (ScreenPtr pScreen,
+ short width,
+ short height,
+ short mmWidth,
+ short mmHeight);
+
+extern _X_EXPORT Bool
+RRRegisterRate (ScreenPtr pScreen,
+ RRScreenSizePtr pSize,
+ int rate);
+
+/*
+ * Finally, set the current configuration of the screen
+ */
+
+extern _X_EXPORT void
+RRSetCurrentConfig (ScreenPtr pScreen,
+ Rotation rotation,
+ int rate,
+ RRScreenSizePtr pSize);
+
+extern _X_EXPORT Bool RRScreenInit (ScreenPtr pScreen);
+
+extern _X_EXPORT Rotation
+RRGetRotation (ScreenPtr pScreen);
+
+#endif
+
+/* rrcrtc.c */
+
+/*
+ * Notify the CRTC of some change; layoutChanged indicates that
+ * some position or size element changed
+ */
+extern _X_EXPORT void
+RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged);
+
+/*
+ * Create a CRTC
+ */
+extern _X_EXPORT RRCrtcPtr
+RRCrtcCreate (ScreenPtr pScreen, void *devPrivate);
+
+/*
+ * Set the allowed rotations on a CRTC
+ */
+extern _X_EXPORT void
+RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations);
+
+/*
+ * Set whether transforms are allowed on a CRTC
+ */
+extern _X_EXPORT void
+RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms);
+
+/*
+ * Notify the extension that the Crtc has been reconfigured,
+ * the driver calls this whenever it has updated the mode
+ */
+extern _X_EXPORT Bool
+RRCrtcNotify (RRCrtcPtr crtc,
+ RRModePtr mode,
+ int x,
+ int y,
+ Rotation rotation,
+ RRTransformPtr transform,
+ int numOutputs,
+ RROutputPtr *outputs);
+
+extern _X_EXPORT void
+RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc);
+
+/*
+ * Request that the Crtc be reconfigured
+ */
+extern _X_EXPORT Bool
+RRCrtcSet (RRCrtcPtr crtc,
+ RRModePtr mode,
+ int x,
+ int y,
+ Rotation rotation,
+ int numOutput,
+ RROutputPtr *outputs);
+
+/*
+ * Request that the Crtc gamma be changed
+ */
+
+extern _X_EXPORT Bool
+RRCrtcGammaSet (RRCrtcPtr crtc,
+ CARD16 *red,
+ CARD16 *green,
+ CARD16 *blue);
+
+/*
+ * Request current gamma back from the DDX (if possible).
+ * This includes gamma size.
+ */
+
+extern _X_EXPORT Bool
+RRCrtcGammaGet(RRCrtcPtr crtc);
+
+/*
+ * Notify the extension that the Crtc gamma has been changed
+ * The driver calls this whenever it has changed the gamma values
+ * in the RRCrtcRec
+ */
+
+extern _X_EXPORT Bool
+RRCrtcGammaNotify (RRCrtcPtr crtc);
+
+/*
+ * Set the size of the gamma table at server startup time
+ */
+
+extern _X_EXPORT Bool
+RRCrtcGammaSetSize (RRCrtcPtr crtc,
+ int size);
+
+/*
+ * Return the area of the frame buffer scanned out by the crtc,
+ * taking into account the current mode and rotation
+ */
+
+extern _X_EXPORT void
+RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
+
+/*
+ * Compute the complete transformation matrix including
+ * client-specified transform, rotation/reflection values and the crtc
+ * offset.
+ *
+ * Return TRUE if the resulting transform is not a simple translation.
+ */
+extern _X_EXPORT Bool
+RRTransformCompute (int x,
+ int y,
+ int width,
+ int height,
+ Rotation rotation,
+ RRTransformPtr rr_transform,
+
+ PictTransformPtr transform,
+ struct pict_f_transform *f_transform,
+ struct pict_f_transform *f_inverse);
+
+/*
+ * Return crtc transform
+ */
+extern _X_EXPORT RRTransformPtr
+RRCrtcGetTransform (RRCrtcPtr crtc);
+
+/*
+ * Check whether the pending and current transforms are the same
+ */
+extern _X_EXPORT Bool
+RRCrtcPendingTransform (RRCrtcPtr crtc);
+
+/*
+ * Destroy a Crtc at shutdown
+ */
+extern _X_EXPORT void
+RRCrtcDestroy (RRCrtcPtr crtc);
+
+
+/*
+ * Set the pending CRTC transformation
+ */
+
+extern _X_EXPORT int
+RRCrtcTransformSet (RRCrtcPtr crtc,
+ PictTransformPtr transform,
+ struct pict_f_transform *f_transform,
+ struct pict_f_transform *f_inverse,
+ char *filter,
+ int filter_len,
+ xFixed *params,
+ int nparams);
+
+/*
+ * Initialize crtc type
+ */
+extern _X_EXPORT Bool
+RRCrtcInit (void);
+
+/*
+ * Initialize crtc type error value
+ */
+extern _X_EXPORT void
+RRCrtcInitErrorValue (void);
+
+/*
+ * Crtc dispatch
+ */
+
+extern _X_EXPORT int
+ProcRRGetCrtcInfo (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRSetCrtcConfig (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRGetCrtcGammaSize (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRGetCrtcGamma (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRSetCrtcGamma (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRSetCrtcTransform (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRGetCrtcTransform (ClientPtr client);
+
+int
+ProcRRGetPanning (ClientPtr client);
+
+int
+ProcRRSetPanning (ClientPtr client);
+
+void
+RRConstrainCursorHarder (DeviceIntPtr, ScreenPtr, int, int *, int *);
+
+/* rrdispatch.c */
+extern _X_EXPORT Bool
+RRClientKnowsRates (ClientPtr pClient);
+
+/* rrmode.c */
+/*
+ * Find, and if necessary, create a mode
+ */
+
+extern _X_EXPORT RRModePtr
+RRModeGet (xRRModeInfo *modeInfo,
+ const char *name);
+
+/*
+ * Destroy a mode.
+ */
+
+extern _X_EXPORT void
+RRModeDestroy (RRModePtr mode);
+
+/*
+ * Return a list of modes that are valid for some output in pScreen
+ */
+extern _X_EXPORT RRModePtr *
+RRModesForScreen (ScreenPtr pScreen, int *num_ret);
+
+/*
+ * Initialize mode type
+ */
+extern _X_EXPORT Bool
+RRModeInit (void);
+
+/*
+ * Initialize mode type error value
+ */
+extern _X_EXPORT void
+RRModeInitErrorValue (void);
+
+extern _X_EXPORT int
+ProcRRCreateMode (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRDestroyMode (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRAddOutputMode (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRDeleteOutputMode (ClientPtr client);
+
+/* rroutput.c */
+
+/*
+ * Notify the output of some change. configChanged indicates whether
+ * any external configuration (mode list, clones, connected status)
+ * has changed, or whether the change was strictly internal
+ * (which crtc is in use)
+ */
+extern _X_EXPORT void
+RROutputChanged (RROutputPtr output, Bool configChanged);
+
+/*
+ * Create an output
+ */
+
+extern _X_EXPORT RROutputPtr
+RROutputCreate (ScreenPtr pScreen,
+ const char *name,
+ int nameLength,
+ void *devPrivate);
+
+/*
+ * Notify extension that output parameters have been changed
+ */
+extern _X_EXPORT Bool
+RROutputSetClones (RROutputPtr output,
+ RROutputPtr *clones,
+ int numClones);
+
+extern _X_EXPORT Bool
+RROutputSetModes (RROutputPtr output,
+ RRModePtr *modes,
+ int numModes,
+ int numPreferred);
+
+extern _X_EXPORT int
+RROutputAddUserMode (RROutputPtr output,
+ RRModePtr mode);
+
+extern _X_EXPORT int
+RROutputDeleteUserMode (RROutputPtr output,
+ RRModePtr mode);
+
+extern _X_EXPORT Bool
+RROutputSetCrtcs (RROutputPtr output,
+ RRCrtcPtr *crtcs,
+ int numCrtcs);
+
+extern _X_EXPORT Bool
+RROutputSetConnection (RROutputPtr output,
+ CARD8 connection);
+
+extern _X_EXPORT Bool
+RROutputSetSubpixelOrder (RROutputPtr output,
+ int subpixelOrder);
+
+extern _X_EXPORT Bool
+RROutputSetPhysicalSize (RROutputPtr output,
+ int mmWidth,
+ int mmHeight);
+
+extern _X_EXPORT void
+RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output);
+
+extern _X_EXPORT void
+RROutputDestroy (RROutputPtr output);
+
+extern _X_EXPORT int
+ProcRRGetOutputInfo (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRSetOutputPrimary (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRGetOutputPrimary (ClientPtr client);
+
+/*
+ * Initialize output type
+ */
+extern _X_EXPORT Bool
+RROutputInit (void);
+
+/*
+ * Initialize output type error value
+ */
+extern _X_EXPORT void
+RROutputInitErrorValue (void);
+
+/* rrpointer.c */
+extern _X_EXPORT void
+RRPointerMoved (ScreenPtr pScreen, int x, int y);
+
+extern _X_EXPORT void
+RRPointerScreenConfigured (ScreenPtr pScreen);
+
+/* rrproperty.c */
+
+extern _X_EXPORT void
+RRDeleteAllOutputProperties (RROutputPtr output);
+
+extern _X_EXPORT RRPropertyValuePtr
+RRGetOutputProperty (RROutputPtr output, Atom property, Bool pending);
+
+extern _X_EXPORT RRPropertyPtr
+RRQueryOutputProperty (RROutputPtr output, Atom property);
+
+extern _X_EXPORT void
+RRDeleteOutputProperty (RROutputPtr output, Atom property);
+
+extern _X_EXPORT Bool
+RRPostPendingProperties (RROutputPtr output);
+
+extern _X_EXPORT int
+RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
+ int format, int mode, unsigned long len,
+ pointer value, Bool sendevent, Bool pending);
+
+extern _X_EXPORT int
+RRConfigureOutputProperty (RROutputPtr output, Atom property,
+ Bool pending, Bool range, Bool immutable,
+ int num_values, INT32 *values);
+extern _X_EXPORT int
+ProcRRChangeOutputProperty (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRGetOutputProperty (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRListOutputProperties (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRQueryOutputProperty (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRConfigureOutputProperty (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRDeleteOutputProperty (ClientPtr client);
+
+/* rrxinerama.c */
+#ifdef XINERAMA
+extern _X_EXPORT void
+RRXineramaExtensionInit(void);
+#endif
+
+#endif /* _RANDRSTR_H_ */
+
+/*
+
+randr extension implementation structure
+
+Query state:
+ ProcRRGetScreenInfo/ProcRRGetScreenResources
+ RRGetInfo
+
+ • Request configuration from driver, either 1.0 or 1.2 style
+ • These functions only record state changes, all
+ other actions are pended until RRTellChanged is called
+
+ ->rrGetInfo
+ 1.0:
+ RRRegisterSize
+ RRRegisterRate
+ RRSetCurrentConfig
+ 1.2:
+ RRScreenSetSizeRange
+ RROutputSetCrtcs
+ RRModeGet
+ RROutputSetModes
+ RROutputSetConnection
+ RROutputSetSubpixelOrder
+ RROutputSetClones
+ RRCrtcNotify
+
+ • Must delay scanning configuration until after ->rrGetInfo returns
+ because some drivers will call SetCurrentConfig in the middle
+ of the ->rrGetInfo operation.
+
+ 1.0:
+
+ • Scan old configuration, mirror to new structures
+
+ RRScanOldConfig
+ RRCrtcCreate
+ RROutputCreate
+ RROutputSetCrtcs
+ RROutputSetConnection
+ RROutputSetSubpixelOrder
+ RROldModeAdd • This adds modes one-at-a-time
+ RRModeGet
+ RRCrtcNotify
+
+ • send events, reset pointer if necessary
+
+ RRTellChanged
+ WalkTree (sending events)
+
+ • when layout has changed:
+ RRPointerScreenConfigured
+ RRSendConfigNotify
+
+Asynchronous state setting (1.2 only)
+ When setting state asynchronously, the driver invokes the
+ ->rrGetInfo function and then calls RRTellChanged to flush
+ the changes to the clients and reset pointer if necessary
+
+Set state
+
+ ProcRRSetScreenConfig
+ RRCrtcSet
+ 1.2:
+ ->rrCrtcSet
+ RRCrtcNotify
+ 1.0:
+ ->rrSetConfig
+ RRCrtcNotify
+ RRTellChanged
+ */
diff --git a/xorg-server/randr/rrcrtc.c b/xorg-server/randr/rrcrtc.c
index 98206a2b9..a846ad3d1 100644
--- a/xorg-server/randr/rrcrtc.c
+++ b/xorg-server/randr/rrcrtc.c
@@ -1,1351 +1,1506 @@
-/*
- * 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
- {
- 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.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;
- }
- }
- }
- 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;
- 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;
-}
-
-/*
- * Initialize crtc type error value
- */
-void
-RRCrtcInitErrorValue(void)
-{
- SetResourceTypeErrorValue(RRCrtcType, RRErrorBase + BadRRCrtc);
-}
-
-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)
- {
- free(outputs);
- return 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)
- {
- 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)
- {
- 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)
- {
- 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;
- }
-
- /*
- * 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;
- free(outputs);
- return BadValue;
- }
-
- if (mode)
- {
- if ((~crtc->rotations) & rotation)
- {
- /*
- * requested rotation or reflection not supported by screen
- */
- client->errorValue = stuff->rotation;
- 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;
- free(outputs);
- return BadValue;
- }
-
- if (stuff->y + source_height > pScreen->height)
- {
- client->errorValue = stuff->y;
- free(outputs);
- return BadValue;
- }
- }
-#endif
- }
-
- if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y,
- rotation, numOutputs, outputs))
- {
- rep.status = RRSetConfigFailed;
- goto sendReply;
- }
- rep.status = RRSetConfigSuccess;
- pScrPriv->lastSetTime = time;
-
-sendReply:
- 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);
-
- 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, &current->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;
-}
+/*
+ * Copyright © 2006 Keith Packard
+ * Copyright 2010 Red Hat, Inc
+ *
+ * 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"
+#include "mipointer.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
+ {
+ 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.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;
+}
+
+static void
+crtc_bounds(RRCrtcPtr crtc, int *left, int *right, int *top, int *bottom)
+{
+ *left = crtc->x;
+ *top = crtc->y;
+
+ switch (crtc->rotation) {
+ case RR_Rotate_0:
+ case RR_Rotate_180:
+ default:
+ *right = crtc->x + crtc->mode->mode.width;
+ *bottom = crtc->y + crtc->mode->mode.height;
+ return;
+ case RR_Rotate_90:
+ case RR_Rotate_270:
+ *right = crtc->x + crtc->mode->mode.height;
+ *bottom = crtc->y + crtc->mode->mode.width;
+ return;
+ }
+}
+
+/* overlapping counts as adjacent */
+static Bool
+crtcs_adjacent(const RRCrtcPtr a, const RRCrtcPtr b)
+{
+ /* left, right, top, bottom... */
+ int al, ar, at, ab;
+ int bl, br, bt, bb;
+ int cl, cr, ct, cb; /* the overlap, if any */
+
+ crtc_bounds(a, &al, &ar, &at, &ab);
+ crtc_bounds(b, &bl, &br, &bt, &bb);
+
+ cl = max(al, bl);
+ cr = min(ar, br);
+ ct = max(at, bt);
+ cb = min(ab, bb);
+
+ return (cl <= cr) && (ct <= cb);
+}
+
+/* Depth-first search and mark all CRTCs reachable from cur */
+static void
+mark_crtcs (rrScrPrivPtr pScrPriv, int *reachable, int cur)
+{
+ int i;
+ reachable[cur] = TRUE;
+ for (i = 0; i < pScrPriv->numCrtcs; ++i) {
+ if (reachable[i] || !pScrPriv->crtcs[i]->mode)
+ continue;
+ if (crtcs_adjacent(pScrPriv->crtcs[cur], pScrPriv->crtcs[i]))
+ mark_crtcs(pScrPriv, reachable, i);
+ }
+}
+
+static void
+RRComputeContiguity (ScreenPtr pScreen)
+{
+ rrScrPriv(pScreen);
+ Bool discontiguous = TRUE;
+ int i, n = pScrPriv->numCrtcs;
+
+ int *reachable = calloc(n, sizeof(int));
+ if (!reachable)
+ goto out;
+
+ /* Find first enabled CRTC and start search for reachable CRTCs from it */
+ for (i = 0; i < n; ++i) {
+ if (pScrPriv->crtcs[i]->mode) {
+ mark_crtcs(pScrPriv, reachable, i);
+ break;
+ }
+ }
+
+ /* Check that all enabled CRTCs were marked as reachable */
+ for (i = 0; i < n; ++i)
+ if (pScrPriv->crtcs[i]->mode && !reachable[i])
+ goto out;
+
+ discontiguous = FALSE;
+
+out:
+ free(reachable);
+ pScrPriv->discontiguous = discontiguous;
+}
+
+/*
+ * 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;
+ Bool recompute = TRUE;
+ 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))
+ {
+ recompute = FALSE;
+ 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]);
+ }
+ }
+
+ if (recompute)
+ RRComputeContiguity(pScreen);
+
+ 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;
+ }
+ }
+ }
+ 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;
+ 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;
+}
+
+/*
+ * Initialize crtc type error value
+ */
+void
+RRCrtcInitErrorValue(void)
+{
+ SetResourceTypeErrorValue(RRCrtcType, RRErrorBase + BadRRCrtc);
+}
+
+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)
+ {
+ free(outputs);
+ return 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)
+ {
+ 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)
+ {
+ 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)
+ {
+ 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;
+ }
+
+ /*
+ * 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;
+ free(outputs);
+ return BadValue;
+ }
+
+ if (mode)
+ {
+ if ((~crtc->rotations) & rotation)
+ {
+ /*
+ * requested rotation or reflection not supported by screen
+ */
+ client->errorValue = stuff->rotation;
+ 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;
+ free(outputs);
+ return BadValue;
+ }
+
+ if (stuff->y + source_height > pScreen->height)
+ {
+ client->errorValue = stuff->y;
+ free(outputs);
+ return BadValue;
+ }
+ }
+#endif
+ }
+
+ if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y,
+ rotation, numOutputs, outputs))
+ {
+ rep.status = RRSetConfigFailed;
+ goto sendReply;
+ }
+ rep.status = RRSetConfigSuccess;
+ pScrPriv->lastSetTime = time;
+
+sendReply:
+ 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);
+
+ 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, &current->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;
+}
+
+void
+RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x, int *y)
+{
+ rrScrPriv (pScreen);
+ int i;
+
+ /* intentional dead space -> let it float */
+ if (pScrPriv->discontiguous)
+ return;
+
+ /* if we're moving inside a crtc, we're fine */
+ for (i = 0; i < pScrPriv->numCrtcs; i++) {
+ RRCrtcPtr crtc = pScrPriv->crtcs[i];
+
+ int left, right, top, bottom;
+
+ if (!crtc->mode)
+ continue;
+
+ crtc_bounds(crtc, &left, &right, &top, &bottom);
+
+ if ((*x >= left) && (*x <= right) && (*y >= top) && (*y <= bottom))
+ return;
+ }
+
+ /* if we're trying to escape, clamp to the CRTC we're coming from */
+ for (i = 0; i < pScrPriv->numCrtcs; i++) {
+ RRCrtcPtr crtc = pScrPriv->crtcs[i];
+ int nx, ny;
+ int left, right, top, bottom;
+
+ if (!crtc->mode)
+ continue;
+
+ crtc_bounds(crtc, &left, &right, &top, &bottom);
+ miPointerGetPosition(pDev, &nx, &ny);
+
+ if ((nx >= left) && (nx <= right) && (ny >= top) && (ny <= bottom)) {
+ if ((*x <= left) || (*x >= right)) {
+ int dx = *x - nx;
+
+ if (dx > 0)
+ *x = right;
+ else if (dx < 0)
+ *x = left;
+ }
+
+ if ((*y <= top) || (*y >= bottom)) {
+ int dy = *y - ny;
+
+ if (dy > 0)
+ *y = bottom;
+ else if (dy < 0)
+ *y = top;
+ }
+
+ return;
+ }
+ }
+}