diff options
Diffstat (limited to 'xorg-server/randr')
-rw-r--r-- | xorg-server/randr/Makefile.am | 58 | ||||
-rw-r--r-- | xorg-server/randr/rrdispatch.c | 512 | ||||
-rw-r--r-- | xorg-server/randr/rrinfo.c | 682 | ||||
-rw-r--r-- | xorg-server/randr/rrscreen.c | 2026 | ||||
-rw-r--r-- | xorg-server/randr/rrsdispatch.c | 1006 | ||||
-rw-r--r-- | xorg-server/randr/rrtransform.c | 566 | ||||
-rw-r--r-- | xorg-server/randr/rrtransform.h | 150 |
7 files changed, 2500 insertions, 2500 deletions
diff --git a/xorg-server/randr/Makefile.am b/xorg-server/randr/Makefile.am index 4842df89c..de338b972 100644 --- a/xorg-server/randr/Makefile.am +++ b/xorg-server/randr/Makefile.am @@ -1,29 +1,29 @@ -noinst_LTLIBRARIES = librandr.la
-
-AM_CFLAGS = $(DIX_CFLAGS)
-
-XINERAMA_SRCS = rrxinerama.c
-
-if XORG
-sdk_HEADERS = randrstr.h rrtransform.h
-endif
-
-librandr_la_SOURCES = \
- randr.c \
- randrstr.h \
- rrcrtc.c \
- rrdispatch.c \
- rrinfo.c \
- rrmode.c \
- rroutput.c \
- rrpointer.c \
- rrproperty.c \
- rrscreen.c \
- rrsdispatch.c \
- rrtransform.h \
- rrtransform.c
-
-if XINERAMA
-librandr_la_SOURCES += ${XINERAMA_SRCS}
-endif
-
+noinst_LTLIBRARIES = librandr.la + +AM_CFLAGS = $(DIX_CFLAGS) + +XINERAMA_SRCS = rrxinerama.c + +if XORG +sdk_HEADERS = randrstr.h rrtransform.h +endif + +librandr_la_SOURCES = \ + randr.c \ + randrstr.h \ + rrcrtc.c \ + rrdispatch.c \ + rrinfo.c \ + rrmode.c \ + rroutput.c \ + rrpointer.c \ + rrproperty.c \ + rrscreen.c \ + rrsdispatch.c \ + rrtransform.h \ + rrtransform.c + +if XINERAMA +librandr_la_SOURCES += ${XINERAMA_SRCS} +endif + diff --git a/xorg-server/randr/rrdispatch.c b/xorg-server/randr/rrdispatch.c index 71f81385a..d1c99c288 100644 --- a/xorg-server/randr/rrdispatch.c +++ b/xorg-server/randr/rrdispatch.c @@ -1,256 +1,256 @@ -/*
- * 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 "protocol-versions.h"
-
-Bool
-RRClientKnowsRates (ClientPtr pClient)
-{
- rrClientPriv(pClient);
-
- return version_compare(pRRClient->major_version, pRRClient->minor_version,
- 1, 1) >= 0;
-}
-
-static int
-ProcRRQueryVersion (ClientPtr client)
-{
- xRRQueryVersionReply rep = {0};
- register int n;
- REQUEST(xRRQueryVersionReq);
- rrClientPriv(client);
-
- REQUEST_SIZE_MATCH(xRRQueryVersionReq);
- pRRClient->major_version = stuff->majorVersion;
- pRRClient->minor_version = stuff->minorVersion;
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
-
- if (version_compare(stuff->majorVersion, stuff->minorVersion,
- SERVER_RANDR_MAJOR_VERSION, SERVER_RANDR_MINOR_VERSION) < 0)
- {
- rep.majorVersion = stuff->majorVersion;
- rep.minorVersion = stuff->minorVersion;
- } else
- {
- rep.majorVersion = SERVER_RANDR_MAJOR_VERSION;
- rep.minorVersion = SERVER_RANDR_MINOR_VERSION;
- }
-
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.majorVersion, n);
- swapl(&rep.minorVersion, n);
- }
- WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
- return Success;
-}
-
-static int
-ProcRRSelectInput (ClientPtr client)
-{
- REQUEST(xRRSelectInputReq);
- rrClientPriv(client);
- RRTimesPtr pTimes;
- WindowPtr pWin;
- RREventPtr pRREvent, *pHead;
- XID clientResource;
- int rc;
-
- REQUEST_SIZE_MATCH(xRRSelectInputReq);
- rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess);
- if (rc != Success)
- return rc;
- rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
- RREventType, client, DixWriteAccess);
- if (rc != Success && rc != BadValue)
- return rc;
-
- if (stuff->enable & (RRScreenChangeNotifyMask|
- RRCrtcChangeNotifyMask|
- RROutputChangeNotifyMask|
- RROutputPropertyNotifyMask))
- {
- ScreenPtr pScreen = pWin->drawable.pScreen;
- rrScrPriv (pScreen);
-
- pRREvent = NULL;
- if (pHead)
- {
- /* check for existing entry. */
- for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
- if (pRREvent->client == client)
- break;
- }
-
- if (!pRREvent)
- {
- /* build the entry */
- pRREvent = (RREventPtr) malloc(sizeof (RREventRec));
- if (!pRREvent)
- return BadAlloc;
- pRREvent->next = 0;
- pRREvent->client = client;
- pRREvent->window = pWin;
- pRREvent->mask = stuff->enable;
- /*
- * add a resource that will be deleted when
- * the client goes away
- */
- clientResource = FakeClientID (client->index);
- pRREvent->clientResource = clientResource;
- if (!AddResource (clientResource, RRClientType, (pointer)pRREvent))
- return BadAlloc;
- /*
- * create a resource to contain a pointer to the list
- * of clients selecting input. This must be indirect as
- * the list may be arbitrarily rearranged which cannot be
- * done through the resource database.
- */
- if (!pHead)
- {
- pHead = (RREventPtr *) malloc(sizeof (RREventPtr));
- if (!pHead ||
- !AddResource (pWin->drawable.id, RREventType, (pointer)pHead))
- {
- FreeResource (clientResource, RT_NONE);
- return BadAlloc;
- }
- *pHead = 0;
- }
- pRREvent->next = *pHead;
- *pHead = pRREvent;
- }
- /*
- * Now see if the client needs an event
- */
- if (pScrPriv)
- {
- pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum];
- if (CompareTimeStamps (pTimes->setTime,
- pScrPriv->lastSetTime) != 0 ||
- CompareTimeStamps (pTimes->configTime,
- pScrPriv->lastConfigTime) != 0)
- {
- if (pRREvent->mask & RRScreenChangeNotifyMask)
- {
- RRDeliverScreenEvent (client, pWin, pScreen);
- }
-
- if (pRREvent->mask & RRCrtcChangeNotifyMask)
- {
- int i;
-
- for (i = 0; i < pScrPriv->numCrtcs; i++)
- {
- RRDeliverCrtcEvent (client, pWin, pScrPriv->crtcs[i]);
- }
- }
-
- if (pRREvent->mask & RROutputChangeNotifyMask)
- {
- int i;
-
- for (i = 0; i < pScrPriv->numOutputs; i++)
- {
- RRDeliverOutputEvent (client, pWin, pScrPriv->outputs[i]);
- }
- }
-
- /* We don't check for RROutputPropertyNotifyMask, as randrproto.txt doesn't
- * say if there ought to be notifications of changes to output properties
- * if those changes occurred before the time RRSelectInput is called.
- */
- }
- }
- }
- else if (stuff->enable == 0)
- {
- /* delete the interest */
- if (pHead) {
- RREventPtr pNewRREvent = 0;
- for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
- if (pRREvent->client == client)
- break;
- pNewRREvent = pRREvent;
- }
- if (pRREvent) {
- FreeResource (pRREvent->clientResource, RRClientType);
- if (pNewRREvent)
- pNewRREvent->next = pRREvent->next;
- else
- *pHead = pRREvent->next;
- free(pRREvent);
- }
- }
- }
- else
- {
- client->errorValue = stuff->enable;
- return BadValue;
- }
- return Success;
-}
-
-int (*ProcRandrVector[RRNumberRequests])(ClientPtr) = {
- ProcRRQueryVersion, /* 0 */
-/* we skip 1 to make old clients fail pretty immediately */
- NULL, /* 1 ProcRandrOldGetScreenInfo */
-/* V1.0 apps share the same set screen config request id */
- ProcRRSetScreenConfig, /* 2 */
- NULL, /* 3 ProcRandrOldScreenChangeSelectInput */
-/* 3 used to be ScreenChangeSelectInput; deprecated */
- ProcRRSelectInput, /* 4 */
- ProcRRGetScreenInfo, /* 5 */
-/* V1.2 additions */
- ProcRRGetScreenSizeRange, /* 6 */
- ProcRRSetScreenSize, /* 7 */
- ProcRRGetScreenResources, /* 8 */
- ProcRRGetOutputInfo, /* 9 */
- ProcRRListOutputProperties, /* 10 */
- ProcRRQueryOutputProperty, /* 11 */
- ProcRRConfigureOutputProperty, /* 12 */
- ProcRRChangeOutputProperty, /* 13 */
- ProcRRDeleteOutputProperty, /* 14 */
- ProcRRGetOutputProperty, /* 15 */
- ProcRRCreateMode, /* 16 */
- ProcRRDestroyMode, /* 17 */
- ProcRRAddOutputMode, /* 18 */
- ProcRRDeleteOutputMode, /* 19 */
- ProcRRGetCrtcInfo, /* 20 */
- ProcRRSetCrtcConfig, /* 21 */
- ProcRRGetCrtcGammaSize, /* 22 */
- ProcRRGetCrtcGamma, /* 23 */
- ProcRRSetCrtcGamma, /* 24 */
-/* V1.3 additions */
- ProcRRGetScreenResourcesCurrent, /* 25 */
- ProcRRSetCrtcTransform, /* 26 */
- ProcRRGetCrtcTransform, /* 27 */
- ProcRRGetPanning, /* 28 */
- ProcRRSetPanning, /* 29 */
- ProcRRSetOutputPrimary, /* 30 */
- ProcRRGetOutputPrimary, /* 31 */
-};
-
+/* + * 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 "protocol-versions.h" + +Bool +RRClientKnowsRates (ClientPtr pClient) +{ + rrClientPriv(pClient); + + return version_compare(pRRClient->major_version, pRRClient->minor_version, + 1, 1) >= 0; +} + +static int +ProcRRQueryVersion (ClientPtr client) +{ + xRRQueryVersionReply rep = {0}; + register int n; + REQUEST(xRRQueryVersionReq); + rrClientPriv(client); + + REQUEST_SIZE_MATCH(xRRQueryVersionReq); + pRRClient->major_version = stuff->majorVersion; + pRRClient->minor_version = stuff->minorVersion; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (version_compare(stuff->majorVersion, stuff->minorVersion, + SERVER_RANDR_MAJOR_VERSION, SERVER_RANDR_MINOR_VERSION) < 0) + { + rep.majorVersion = stuff->majorVersion; + rep.minorVersion = stuff->minorVersion; + } else + { + rep.majorVersion = SERVER_RANDR_MAJOR_VERSION; + rep.minorVersion = SERVER_RANDR_MINOR_VERSION; + } + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep); + return Success; +} + +static int +ProcRRSelectInput (ClientPtr client) +{ + REQUEST(xRRSelectInputReq); + rrClientPriv(client); + RRTimesPtr pTimes; + WindowPtr pWin; + RREventPtr pRREvent, *pHead; + XID clientResource; + int rc; + + REQUEST_SIZE_MATCH(xRRSelectInputReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess); + if (rc != Success) + return rc; + rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, + RREventType, client, DixWriteAccess); + if (rc != Success && rc != BadValue) + return rc; + + if (stuff->enable & (RRScreenChangeNotifyMask| + RRCrtcChangeNotifyMask| + RROutputChangeNotifyMask| + RROutputPropertyNotifyMask)) + { + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv (pScreen); + + pRREvent = NULL; + if (pHead) + { + /* check for existing entry. */ + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + if (pRREvent->client == client) + break; + } + + if (!pRREvent) + { + /* build the entry */ + pRREvent = (RREventPtr) malloc(sizeof (RREventRec)); + if (!pRREvent) + return BadAlloc; + pRREvent->next = 0; + pRREvent->client = client; + pRREvent->window = pWin; + pRREvent->mask = stuff->enable; + /* + * add a resource that will be deleted when + * the client goes away + */ + clientResource = FakeClientID (client->index); + pRREvent->clientResource = clientResource; + if (!AddResource (clientResource, RRClientType, (pointer)pRREvent)) + return BadAlloc; + /* + * create a resource to contain a pointer to the list + * of clients selecting input. This must be indirect as + * the list may be arbitrarily rearranged which cannot be + * done through the resource database. + */ + if (!pHead) + { + pHead = (RREventPtr *) malloc(sizeof (RREventPtr)); + if (!pHead || + !AddResource (pWin->drawable.id, RREventType, (pointer)pHead)) + { + FreeResource (clientResource, RT_NONE); + return BadAlloc; + } + *pHead = 0; + } + pRREvent->next = *pHead; + *pHead = pRREvent; + } + /* + * Now see if the client needs an event + */ + if (pScrPriv) + { + pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; + if (CompareTimeStamps (pTimes->setTime, + pScrPriv->lastSetTime) != 0 || + CompareTimeStamps (pTimes->configTime, + pScrPriv->lastConfigTime) != 0) + { + if (pRREvent->mask & RRScreenChangeNotifyMask) + { + RRDeliverScreenEvent (client, pWin, pScreen); + } + + if (pRREvent->mask & RRCrtcChangeNotifyMask) + { + int i; + + for (i = 0; i < pScrPriv->numCrtcs; i++) + { + RRDeliverCrtcEvent (client, pWin, pScrPriv->crtcs[i]); + } + } + + if (pRREvent->mask & RROutputChangeNotifyMask) + { + int i; + + for (i = 0; i < pScrPriv->numOutputs; i++) + { + RRDeliverOutputEvent (client, pWin, pScrPriv->outputs[i]); + } + } + + /* We don't check for RROutputPropertyNotifyMask, as randrproto.txt doesn't + * say if there ought to be notifications of changes to output properties + * if those changes occurred before the time RRSelectInput is called. + */ + } + } + } + else if (stuff->enable == 0) + { + /* delete the interest */ + if (pHead) { + RREventPtr pNewRREvent = 0; + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { + if (pRREvent->client == client) + break; + pNewRREvent = pRREvent; + } + if (pRREvent) { + FreeResource (pRREvent->clientResource, RRClientType); + if (pNewRREvent) + pNewRREvent->next = pRREvent->next; + else + *pHead = pRREvent->next; + free(pRREvent); + } + } + } + else + { + client->errorValue = stuff->enable; + return BadValue; + } + return Success; +} + +int (*ProcRandrVector[RRNumberRequests])(ClientPtr) = { + ProcRRQueryVersion, /* 0 */ +/* we skip 1 to make old clients fail pretty immediately */ + NULL, /* 1 ProcRandrOldGetScreenInfo */ +/* V1.0 apps share the same set screen config request id */ + ProcRRSetScreenConfig, /* 2 */ + NULL, /* 3 ProcRandrOldScreenChangeSelectInput */ +/* 3 used to be ScreenChangeSelectInput; deprecated */ + ProcRRSelectInput, /* 4 */ + ProcRRGetScreenInfo, /* 5 */ +/* V1.2 additions */ + ProcRRGetScreenSizeRange, /* 6 */ + ProcRRSetScreenSize, /* 7 */ + ProcRRGetScreenResources, /* 8 */ + ProcRRGetOutputInfo, /* 9 */ + ProcRRListOutputProperties, /* 10 */ + ProcRRQueryOutputProperty, /* 11 */ + ProcRRConfigureOutputProperty, /* 12 */ + ProcRRChangeOutputProperty, /* 13 */ + ProcRRDeleteOutputProperty, /* 14 */ + ProcRRGetOutputProperty, /* 15 */ + ProcRRCreateMode, /* 16 */ + ProcRRDestroyMode, /* 17 */ + ProcRRAddOutputMode, /* 18 */ + ProcRRDeleteOutputMode, /* 19 */ + ProcRRGetCrtcInfo, /* 20 */ + ProcRRSetCrtcConfig, /* 21 */ + ProcRRGetCrtcGammaSize, /* 22 */ + ProcRRGetCrtcGamma, /* 23 */ + ProcRRSetCrtcGamma, /* 24 */ +/* V1.3 additions */ + ProcRRGetScreenResourcesCurrent, /* 25 */ + ProcRRSetCrtcTransform, /* 26 */ + ProcRRGetCrtcTransform, /* 27 */ + ProcRRGetPanning, /* 28 */ + ProcRRSetPanning, /* 29 */ + ProcRRSetOutputPrimary, /* 30 */ + ProcRRGetOutputPrimary, /* 31 */ +}; + diff --git a/xorg-server/randr/rrinfo.c b/xorg-server/randr/rrinfo.c index 04c1a6c98..fdf372607 100644 --- a/xorg-server/randr/rrinfo.c +++ b/xorg-server/randr/rrinfo.c @@ -1,341 +1,341 @@ -/*
- * 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"
-
-#ifdef RANDR_10_INTERFACE
-static RRModePtr
-RROldModeAdd (RROutputPtr output, RRScreenSizePtr size, int refresh)
-{
- ScreenPtr pScreen = output->pScreen;
- rrScrPriv(pScreen);
- xRRModeInfo modeInfo;
- char name[100];
- RRModePtr mode;
- int i;
- RRModePtr *modes;
-
- memset (&modeInfo, '\0', sizeof (modeInfo));
- sprintf (name, "%dx%d", size->width, size->height);
-
- modeInfo.width = size->width;
- modeInfo.height = size->height;
- modeInfo.hTotal = size->width;
- modeInfo.vTotal = size->height;
- modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height *
- (CARD32) refresh);
- modeInfo.nameLength = strlen (name);
- mode = RRModeGet (&modeInfo, name);
- if (!mode)
- return NULL;
- for (i = 0; i < output->numModes; i++)
- if (output->modes[i] == mode)
- {
- RRModeDestroy (mode);
- return mode;
- }
-
- if (output->numModes)
- modes = realloc(output->modes,
- (output->numModes + 1) * sizeof (RRModePtr));
- else
- modes = malloc(sizeof (RRModePtr));
- if (!modes)
- {
- RRModeDestroy (mode);
- FreeResource (mode->mode.id, 0);
- return NULL;
- }
- modes[output->numModes++] = mode;
- output->modes = modes;
- output->changed = TRUE;
- pScrPriv->changed = TRUE;
- pScrPriv->configChanged = TRUE;
- return mode;
-}
-
-static void
-RRScanOldConfig (ScreenPtr pScreen, Rotation rotations)
-{
- rrScrPriv(pScreen);
- RROutputPtr output;
- RRCrtcPtr crtc;
- RRModePtr mode, newMode = NULL;
- int i;
- CARD16 minWidth = MAXSHORT, minHeight = MAXSHORT;
- CARD16 maxWidth = 0, maxHeight = 0;
-
- /*
- * First time through, create a crtc and output and hook
- * them together
- */
- if (pScrPriv->numOutputs == 0 &&
- pScrPriv->numCrtcs == 0)
- {
- crtc = RRCrtcCreate (pScreen, NULL);
- if (!crtc)
- return;
- output = RROutputCreate (pScreen, "default", 7, NULL);
- if (!output)
- return;
- RROutputSetCrtcs (output, &crtc, 1);
- RROutputSetConnection (output, RR_Connected);
- RROutputSetSubpixelOrder (output, PictureGetSubpixelOrder (pScreen));
- }
-
- output = pScrPriv->outputs[0];
- if (!output)
- return;
- crtc = pScrPriv->crtcs[0];
- if (!crtc)
- return;
-
- /* check rotations */
- if (rotations != crtc->rotations)
- {
- crtc->rotations = rotations;
- crtc->changed = TRUE;
- pScrPriv->changed = TRUE;
- }
-
- /* regenerate mode list */
- for (i = 0; i < pScrPriv->nSizes; i++)
- {
- RRScreenSizePtr size = &pScrPriv->pSizes[i];
- int r;
-
- if (size->nRates)
- {
- for (r = 0; r < size->nRates; r++)
- {
- mode = RROldModeAdd (output, size, size->pRates[r].rate);
- if (i == pScrPriv->size &&
- size->pRates[r].rate == pScrPriv->rate)
- {
- newMode = mode;
- }
- }
- free(size->pRates);
- }
- else
- {
- mode = RROldModeAdd (output, size, 0);
- if (i == pScrPriv->size)
- newMode = mode;
- }
- }
- if (pScrPriv->nSizes)
- free(pScrPriv->pSizes);
- pScrPriv->pSizes = NULL;
- pScrPriv->nSizes = 0;
-
- /* find size bounds */
- for (i = 0; i < output->numModes + output->numUserModes; i++)
- {
- RRModePtr mode = (i < output->numModes ?
- output->modes[i] :
- output->userModes[i-output->numModes]);
- CARD16 width = mode->mode.width;
- CARD16 height = mode->mode.height;
-
- if (width < minWidth) minWidth = width;
- if (width > maxWidth) maxWidth = width;
- if (height < minHeight) minHeight = height;
- if (height > maxHeight) maxHeight = height;
- }
-
- RRScreenSetSizeRange (pScreen, minWidth, minHeight, maxWidth, maxHeight);
-
- /* notice current mode */
- if (newMode)
- RRCrtcNotify (crtc, newMode, 0, 0, pScrPriv->rotation,
- NULL, 1, &output);
-}
-#endif
-
-/*
- * Poll the driver for changed information
- */
-Bool
-RRGetInfo (ScreenPtr pScreen, Bool force_query)
-{
- rrScrPriv (pScreen);
- Rotation rotations;
- int i;
-
- /* Return immediately if we don't need to re-query and we already have the
- * information.
- */
- if (!force_query) {
- if (pScrPriv->numCrtcs != 0 || pScrPriv->numOutputs != 0)
- return TRUE;
- }
-
- for (i = 0; i < pScrPriv->numOutputs; i++)
- pScrPriv->outputs[i]->changed = FALSE;
- for (i = 0; i < pScrPriv->numCrtcs; i++)
- pScrPriv->crtcs[i]->changed = FALSE;
-
- rotations = 0;
- pScrPriv->changed = FALSE;
- pScrPriv->configChanged = FALSE;
-
- if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
- return FALSE;
-
-#if RANDR_10_INTERFACE
- if (pScrPriv->nSizes)
- RRScanOldConfig (pScreen, rotations);
-#endif
- RRTellChanged (pScreen);
- return TRUE;
-}
-
-/*
- * Register the range of sizes for the screen
- */
-void
-RRScreenSetSizeRange (ScreenPtr pScreen,
- CARD16 minWidth,
- CARD16 minHeight,
- CARD16 maxWidth,
- CARD16 maxHeight)
-{
- rrScrPriv (pScreen);
-
- if (!pScrPriv)
- return;
- if (pScrPriv->minWidth == minWidth && pScrPriv->minHeight == minHeight &&
- pScrPriv->maxWidth == maxWidth && pScrPriv->maxHeight == maxHeight)
- {
- return;
- }
-
- pScrPriv->minWidth = minWidth;
- pScrPriv->minHeight = minHeight;
- pScrPriv->maxWidth = maxWidth;
- pScrPriv->maxHeight = maxHeight;
- pScrPriv->changed = TRUE;
- pScrPriv->configChanged = TRUE;
-}
-
-#ifdef RANDR_10_INTERFACE
-static Bool
-RRScreenSizeMatches (RRScreenSizePtr a,
- RRScreenSizePtr b)
-{
- if (a->width != b->width)
- return FALSE;
- if (a->height != b->height)
- return FALSE;
- if (a->mmWidth != b->mmWidth)
- return FALSE;
- if (a->mmHeight != b->mmHeight)
- return FALSE;
- return TRUE;
-}
-
-RRScreenSizePtr
-RRRegisterSize (ScreenPtr pScreen,
- short width,
- short height,
- short mmWidth,
- short mmHeight)
-{
- rrScrPriv (pScreen);
- int i;
- RRScreenSize tmp;
- RRScreenSizePtr pNew;
-
- if (!pScrPriv)
- return 0;
-
- tmp.id = 0;
- tmp.width = width;
- tmp.height= height;
- tmp.mmWidth = mmWidth;
- tmp.mmHeight = mmHeight;
- tmp.pRates = 0;
- tmp.nRates = 0;
- for (i = 0; i < pScrPriv->nSizes; i++)
- if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
- return &pScrPriv->pSizes[i];
- pNew = realloc(pScrPriv->pSizes,
- (pScrPriv->nSizes + 1) * sizeof (RRScreenSize));
- if (!pNew)
- return 0;
- pNew[pScrPriv->nSizes++] = tmp;
- pScrPriv->pSizes = pNew;
- return &pNew[pScrPriv->nSizes-1];
-}
-
-Bool RRRegisterRate (ScreenPtr pScreen,
- RRScreenSizePtr pSize,
- int rate)
-{
- rrScrPriv(pScreen);
- int i;
- RRScreenRatePtr pNew, pRate;
-
- if (!pScrPriv)
- return FALSE;
-
- for (i = 0; i < pSize->nRates; i++)
- if (pSize->pRates[i].rate == rate)
- return TRUE;
-
- pNew = realloc(pSize->pRates,
- (pSize->nRates + 1) * sizeof (RRScreenRate));
- if (!pNew)
- return FALSE;
- pRate = &pNew[pSize->nRates++];
- pRate->rate = rate;
- pSize->pRates = pNew;
- return TRUE;
-}
-
-Rotation
-RRGetRotation(ScreenPtr pScreen)
-{
- RROutputPtr output = RRFirstOutput (pScreen);
-
- if (!output)
- return RR_Rotate_0;
-
- return output->crtc->rotation;
-}
-
-void
-RRSetCurrentConfig (ScreenPtr pScreen,
- Rotation rotation,
- int rate,
- RRScreenSizePtr pSize)
-{
- rrScrPriv (pScreen);
-
- if (!pScrPriv)
- return;
- pScrPriv->size = pSize - pScrPriv->pSizes;
- pScrPriv->rotation = rotation;
- pScrPriv->rate = rate;
-}
-#endif
+/* + * 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" + +#ifdef RANDR_10_INTERFACE +static RRModePtr +RROldModeAdd (RROutputPtr output, RRScreenSizePtr size, int refresh) +{ + ScreenPtr pScreen = output->pScreen; + rrScrPriv(pScreen); + xRRModeInfo modeInfo; + char name[100]; + RRModePtr mode; + int i; + RRModePtr *modes; + + memset (&modeInfo, '\0', sizeof (modeInfo)); + sprintf (name, "%dx%d", size->width, size->height); + + modeInfo.width = size->width; + modeInfo.height = size->height; + modeInfo.hTotal = size->width; + modeInfo.vTotal = size->height; + modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height * + (CARD32) refresh); + modeInfo.nameLength = strlen (name); + mode = RRModeGet (&modeInfo, name); + if (!mode) + return NULL; + for (i = 0; i < output->numModes; i++) + if (output->modes[i] == mode) + { + RRModeDestroy (mode); + return mode; + } + + if (output->numModes) + modes = realloc(output->modes, + (output->numModes + 1) * sizeof (RRModePtr)); + else + modes = malloc(sizeof (RRModePtr)); + if (!modes) + { + RRModeDestroy (mode); + FreeResource (mode->mode.id, 0); + return NULL; + } + modes[output->numModes++] = mode; + output->modes = modes; + output->changed = TRUE; + pScrPriv->changed = TRUE; + pScrPriv->configChanged = TRUE; + return mode; +} + +static void +RRScanOldConfig (ScreenPtr pScreen, Rotation rotations) +{ + rrScrPriv(pScreen); + RROutputPtr output; + RRCrtcPtr crtc; + RRModePtr mode, newMode = NULL; + int i; + CARD16 minWidth = MAXSHORT, minHeight = MAXSHORT; + CARD16 maxWidth = 0, maxHeight = 0; + + /* + * First time through, create a crtc and output and hook + * them together + */ + if (pScrPriv->numOutputs == 0 && + pScrPriv->numCrtcs == 0) + { + crtc = RRCrtcCreate (pScreen, NULL); + if (!crtc) + return; + output = RROutputCreate (pScreen, "default", 7, NULL); + if (!output) + return; + RROutputSetCrtcs (output, &crtc, 1); + RROutputSetConnection (output, RR_Connected); + RROutputSetSubpixelOrder (output, PictureGetSubpixelOrder (pScreen)); + } + + output = pScrPriv->outputs[0]; + if (!output) + return; + crtc = pScrPriv->crtcs[0]; + if (!crtc) + return; + + /* check rotations */ + if (rotations != crtc->rotations) + { + crtc->rotations = rotations; + crtc->changed = TRUE; + pScrPriv->changed = TRUE; + } + + /* regenerate mode list */ + for (i = 0; i < pScrPriv->nSizes; i++) + { + RRScreenSizePtr size = &pScrPriv->pSizes[i]; + int r; + + if (size->nRates) + { + for (r = 0; r < size->nRates; r++) + { + mode = RROldModeAdd (output, size, size->pRates[r].rate); + if (i == pScrPriv->size && + size->pRates[r].rate == pScrPriv->rate) + { + newMode = mode; + } + } + free(size->pRates); + } + else + { + mode = RROldModeAdd (output, size, 0); + if (i == pScrPriv->size) + newMode = mode; + } + } + if (pScrPriv->nSizes) + free(pScrPriv->pSizes); + pScrPriv->pSizes = NULL; + pScrPriv->nSizes = 0; + + /* find size bounds */ + for (i = 0; i < output->numModes + output->numUserModes; i++) + { + RRModePtr mode = (i < output->numModes ? + output->modes[i] : + output->userModes[i-output->numModes]); + CARD16 width = mode->mode.width; + CARD16 height = mode->mode.height; + + if (width < minWidth) minWidth = width; + if (width > maxWidth) maxWidth = width; + if (height < minHeight) minHeight = height; + if (height > maxHeight) maxHeight = height; + } + + RRScreenSetSizeRange (pScreen, minWidth, minHeight, maxWidth, maxHeight); + + /* notice current mode */ + if (newMode) + RRCrtcNotify (crtc, newMode, 0, 0, pScrPriv->rotation, + NULL, 1, &output); +} +#endif + +/* + * Poll the driver for changed information + */ +Bool +RRGetInfo (ScreenPtr pScreen, Bool force_query) +{ + rrScrPriv (pScreen); + Rotation rotations; + int i; + + /* Return immediately if we don't need to re-query and we already have the + * information. + */ + if (!force_query) { + if (pScrPriv->numCrtcs != 0 || pScrPriv->numOutputs != 0) + return TRUE; + } + + for (i = 0; i < pScrPriv->numOutputs; i++) + pScrPriv->outputs[i]->changed = FALSE; + for (i = 0; i < pScrPriv->numCrtcs; i++) + pScrPriv->crtcs[i]->changed = FALSE; + + rotations = 0; + pScrPriv->changed = FALSE; + pScrPriv->configChanged = FALSE; + + if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations)) + return FALSE; + +#if RANDR_10_INTERFACE + if (pScrPriv->nSizes) + RRScanOldConfig (pScreen, rotations); +#endif + RRTellChanged (pScreen); + return TRUE; +} + +/* + * Register the range of sizes for the screen + */ +void +RRScreenSetSizeRange (ScreenPtr pScreen, + CARD16 minWidth, + CARD16 minHeight, + CARD16 maxWidth, + CARD16 maxHeight) +{ + rrScrPriv (pScreen); + + if (!pScrPriv) + return; + if (pScrPriv->minWidth == minWidth && pScrPriv->minHeight == minHeight && + pScrPriv->maxWidth == maxWidth && pScrPriv->maxHeight == maxHeight) + { + return; + } + + pScrPriv->minWidth = minWidth; + pScrPriv->minHeight = minHeight; + pScrPriv->maxWidth = maxWidth; + pScrPriv->maxHeight = maxHeight; + pScrPriv->changed = TRUE; + pScrPriv->configChanged = TRUE; +} + +#ifdef RANDR_10_INTERFACE +static Bool +RRScreenSizeMatches (RRScreenSizePtr a, + RRScreenSizePtr b) +{ + if (a->width != b->width) + return FALSE; + if (a->height != b->height) + return FALSE; + if (a->mmWidth != b->mmWidth) + return FALSE; + if (a->mmHeight != b->mmHeight) + return FALSE; + return TRUE; +} + +RRScreenSizePtr +RRRegisterSize (ScreenPtr pScreen, + short width, + short height, + short mmWidth, + short mmHeight) +{ + rrScrPriv (pScreen); + int i; + RRScreenSize tmp; + RRScreenSizePtr pNew; + + if (!pScrPriv) + return 0; + + tmp.id = 0; + tmp.width = width; + tmp.height= height; + tmp.mmWidth = mmWidth; + tmp.mmHeight = mmHeight; + tmp.pRates = 0; + tmp.nRates = 0; + for (i = 0; i < pScrPriv->nSizes; i++) + if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i])) + return &pScrPriv->pSizes[i]; + pNew = realloc(pScrPriv->pSizes, + (pScrPriv->nSizes + 1) * sizeof (RRScreenSize)); + if (!pNew) + return 0; + pNew[pScrPriv->nSizes++] = tmp; + pScrPriv->pSizes = pNew; + return &pNew[pScrPriv->nSizes-1]; +} + +Bool RRRegisterRate (ScreenPtr pScreen, + RRScreenSizePtr pSize, + int rate) +{ + rrScrPriv(pScreen); + int i; + RRScreenRatePtr pNew, pRate; + + if (!pScrPriv) + return FALSE; + + for (i = 0; i < pSize->nRates; i++) + if (pSize->pRates[i].rate == rate) + return TRUE; + + pNew = realloc(pSize->pRates, + (pSize->nRates + 1) * sizeof (RRScreenRate)); + if (!pNew) + return FALSE; + pRate = &pNew[pSize->nRates++]; + pRate->rate = rate; + pSize->pRates = pNew; + return TRUE; +} + +Rotation +RRGetRotation(ScreenPtr pScreen) +{ + RROutputPtr output = RRFirstOutput (pScreen); + + if (!output) + return RR_Rotate_0; + + return output->crtc->rotation; +} + +void +RRSetCurrentConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + rrScrPriv (pScreen); + + if (!pScrPriv) + return; + pScrPriv->size = pSize - pScrPriv->pSizes; + pScrPriv->rotation = rotation; + pScrPriv->rate = rate; +} +#endif diff --git a/xorg-server/randr/rrscreen.c b/xorg-server/randr/rrscreen.c index 6777a22ad..da6d48d6e 100644 --- a/xorg-server/randr/rrscreen.c +++ b/xorg-server/randr/rrscreen.c @@ -1,1013 +1,1013 @@ -/*
- * 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"
-
-static const int padlength[4] = {0, 3, 2, 1};
-
-static CARD16
-RR10CurrentSizeID (ScreenPtr pScreen);
-
-/*
- * Edit connection information block so that new clients
- * see the current screen size on connect
- */
-static void
-RREditConnectionInfo (ScreenPtr pScreen)
-{
- xConnSetup *connSetup;
- char *vendor;
- xPixmapFormat *formats;
- xWindowRoot *root;
- xDepth *depth;
- xVisualType *visual;
- int screen = 0;
- int d;
-
- connSetup = (xConnSetup *) ConnectionInfo;
- vendor = (char *) connSetup + sizeof (xConnSetup);
- formats = (xPixmapFormat *) ((char *) vendor +
- connSetup->nbytesVendor +
- padlength[connSetup->nbytesVendor & 3]);
- root = (xWindowRoot *) ((char *) formats +
- sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
- while (screen != pScreen->myNum)
- {
- depth = (xDepth *) ((char *) root +
- sizeof (xWindowRoot));
- for (d = 0; d < root->nDepths; d++)
- {
- visual = (xVisualType *) ((char *) depth +
- sizeof (xDepth));
- depth = (xDepth *) ((char *) visual +
- depth->nVisuals * sizeof (xVisualType));
- }
- root = (xWindowRoot *) ((char *) depth);
- screen++;
- }
- root->pixWidth = pScreen->width;
- root->pixHeight = pScreen->height;
- root->mmWidth = pScreen->mmWidth;
- root->mmHeight = pScreen->mmHeight;
-}
-
-void
-RRSendConfigNotify (ScreenPtr pScreen)
-{
- WindowPtr pWin = pScreen->root;
- xEvent event;
-
- event.u.u.type = ConfigureNotify;
- event.u.configureNotify.window = pWin->drawable.id;
- event.u.configureNotify.aboveSibling = None;
- event.u.configureNotify.x = 0;
- event.u.configureNotify.y = 0;
-
- /* XXX xinerama stuff ? */
-
- event.u.configureNotify.width = pWin->drawable.width;
- event.u.configureNotify.height = pWin->drawable.height;
- event.u.configureNotify.borderWidth = wBorderWidth (pWin);
- event.u.configureNotify.override = pWin->overrideRedirect;
- DeliverEvents(pWin, &event, 1, NullWindow);
-}
-
-void
-RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
-{
- rrScrPriv (pScreen);
- xRRScreenChangeNotifyEvent se;
- RRCrtcPtr crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL;
- WindowPtr pRoot = pScreen->root;
-
- se.type = RRScreenChangeNotify + RREventBase;
- se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0);
- se.timestamp = pScrPriv->lastSetTime.milliseconds;
- se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
- se.root = pRoot->drawable.id;
- se.window = pWin->drawable.id;
- se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
-
- se.sizeID = RR10CurrentSizeID (pScreen);
-
- if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) {
- se.widthInPixels = pScreen->height;
- se.heightInPixels = pScreen->width;
- se.widthInMillimeters = pScreen->mmHeight;
- se.heightInMillimeters = pScreen->mmWidth;
- } else {
- se.widthInPixels = pScreen->width;
- se.heightInPixels = pScreen->height;
- se.widthInMillimeters = pScreen->mmWidth;
- se.heightInMillimeters = pScreen->mmHeight;
- }
-
- WriteEventsToClient (client, 1, (xEvent *) &se);
-}
-
-/*
- * 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
- */
-void
-RRScreenSizeNotify (ScreenPtr pScreen)
-{
- rrScrPriv(pScreen);
- /*
- * Deliver ConfigureNotify events when root changes
- * pixel size
- */
- if (pScrPriv->width == pScreen->width &&
- pScrPriv->height == pScreen->height &&
- pScrPriv->mmWidth == pScreen->mmWidth &&
- pScrPriv->mmHeight == pScreen->mmHeight)
- return;
-
- pScrPriv->width = pScreen->width;
- pScrPriv->height = pScreen->height;
- pScrPriv->mmWidth = pScreen->mmWidth;
- pScrPriv->mmHeight = pScreen->mmHeight;
- pScrPriv->changed = TRUE;
-/* pScrPriv->sizeChanged = TRUE; */
-
- RRTellChanged (pScreen);
- RRSendConfigNotify (pScreen);
- RREditConnectionInfo (pScreen);
-
- RRPointerScreenConfigured (pScreen);
- /*
- * Fix pointer bounds and location
- */
- ScreenRestructured (pScreen);
-}
-
-/*
- * Request that the screen be resized
- */
-Bool
-RRScreenSizeSet (ScreenPtr pScreen,
- CARD16 width,
- CARD16 height,
- CARD32 mmWidth,
- CARD32 mmHeight)
-{
- rrScrPriv(pScreen);
-
-#if RANDR_12_INTERFACE
- if (pScrPriv->rrScreenSetSize)
- {
- return (*pScrPriv->rrScreenSetSize) (pScreen,
- width, height,
- mmWidth, mmHeight);
- }
-#endif
-#if RANDR_10_INTERFACE
- if (pScrPriv->rrSetConfig)
- {
- return TRUE; /* can't set size separately */
- }
-#endif
- return FALSE;
-}
-
-/*
- * Retrieve valid screen size range
- */
-int
-ProcRRGetScreenSizeRange (ClientPtr client)
-{
- REQUEST(xRRGetScreenSizeRangeReq);
- xRRGetScreenSizeRangeReply rep;
- WindowPtr pWin;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- int rc;
-
- REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
- rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- pScreen = pWin->drawable.pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
-
- rep.type = X_Reply;
- rep.pad = 0;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
-
- if (pScrPriv)
- {
- if (!RRGetInfo (pScreen, FALSE))
- return BadAlloc;
- rep.minWidth = pScrPriv->minWidth;
- rep.minHeight = pScrPriv->minHeight;
- rep.maxWidth = pScrPriv->maxWidth;
- rep.maxHeight = pScrPriv->maxHeight;
- }
- else
- {
- rep.maxWidth = rep.minWidth = pScreen->width;
- rep.maxHeight = rep.minHeight = pScreen->height;
- }
- if (client->swapped)
- {
- int n;
-
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swaps(&rep.minWidth, n);
- swaps(&rep.minHeight, n);
- swaps(&rep.maxWidth, n);
- swaps(&rep.maxHeight, n);
- }
- WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), (char *)&rep);
- return Success;
-}
-
-int
-ProcRRSetScreenSize (ClientPtr client)
-{
- REQUEST(xRRSetScreenSizeReq);
- WindowPtr pWin;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- int i, rc;
-
- REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
- rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- pScreen = pWin->drawable.pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
- if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width)
- {
- client->errorValue = stuff->width;
- return BadValue;
- }
- if (stuff->height < pScrPriv->minHeight ||
- pScrPriv->maxHeight < stuff->height)
- {
- client->errorValue = stuff->height;
- return BadValue;
- }
- for (i = 0; i < pScrPriv->numCrtcs; i++)
- {
- RRCrtcPtr crtc = pScrPriv->crtcs[i];
- RRModePtr mode = crtc->mode;
- if (mode)
- {
- int source_width = mode->mode.width;
- int source_height = mode->mode.height;
- Rotation rotation = crtc->rotation;
-
- if (rotation == RR_Rotate_90 || rotation == RR_Rotate_270)
- {
- source_width = mode->mode.height;
- source_height = mode->mode.width;
- }
-
- if (crtc->x + source_width > stuff->width ||
- crtc->y + source_height > stuff->height)
- return BadMatch;
- }
- }
- if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0)
- {
- client->errorValue = 0;
- return BadValue;
- }
- if (!RRScreenSizeSet (pScreen,
- stuff->width, stuff->height,
- stuff->widthInMillimeters,
- stuff->heightInMillimeters))
- {
- return BadMatch;
- }
- return Success;
-}
-
-static int
-rrGetScreenResources(ClientPtr client, Bool query)
-{
- REQUEST(xRRGetScreenResourcesReq);
- xRRGetScreenResourcesReply rep;
- WindowPtr pWin;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- CARD8 *extra;
- unsigned long extraLen;
- int i, n, rc, has_primary = 0;
- RRCrtc *crtcs;
- RROutput *outputs;
- xRRModeInfo *modeinfos;
- CARD8 *names;
-
- REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
- rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- pScreen = pWin->drawable.pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
- rep.pad = 0;
-
- if (query && pScrPriv)
- if (!RRGetInfo (pScreen, query))
- return BadAlloc;
-
- if (!pScrPriv)
- {
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.timestamp = currentTime.milliseconds;
- rep.configTimestamp = currentTime.milliseconds;
- rep.nCrtcs = 0;
- rep.nOutputs = 0;
- rep.nModes = 0;
- rep.nbytesNames = 0;
- extra = NULL;
- extraLen = 0;
- }
- else
- {
- RRModePtr *modes;
- int num_modes;
-
- modes = RRModesForScreen (pScreen, &num_modes);
- if (!modes)
- return BadAlloc;
-
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.timestamp = pScrPriv->lastSetTime.milliseconds;
- rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
- rep.nCrtcs = pScrPriv->numCrtcs;
- rep.nOutputs = pScrPriv->numOutputs;
- rep.nModes = num_modes;
- rep.nbytesNames = 0;
-
- for (i = 0; i < num_modes; i++)
- rep.nbytesNames += modes[i]->mode.nameLength;
-
- rep.length = (pScrPriv->numCrtcs +
- pScrPriv->numOutputs +
- num_modes * bytes_to_int32(SIZEOF(xRRModeInfo)) +
- bytes_to_int32(rep.nbytesNames));
-
- extraLen = rep.length << 2;
- if (extraLen)
- {
- extra = malloc(extraLen);
- if (!extra)
- {
- free(modes);
- return BadAlloc;
- }
- }
- else
- extra = NULL;
-
- crtcs = (RRCrtc *) extra;
- outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
- modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
- names = (CARD8 *) (modeinfos + num_modes);
-
- if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc)
- {
- has_primary = 1;
- crtcs[0] = pScrPriv->primaryOutput->crtc->id;
- if (client->swapped)
- swapl (&crtcs[0], n);
- }
-
- for (i = 0; i < pScrPriv->numCrtcs; i++)
- {
- if (has_primary &&
- pScrPriv->primaryOutput->crtc == pScrPriv->crtcs[i])
- {
- has_primary = 0;
- continue;
- }
- crtcs[i + has_primary] = pScrPriv->crtcs[i]->id;
- if (client->swapped)
- swapl (&crtcs[i + has_primary], n);
- }
-
- for (i = 0; i < pScrPriv->numOutputs; i++)
- {
- outputs[i] = pScrPriv->outputs[i]->id;
- if (client->swapped)
- swapl (&outputs[i], n);
- }
-
- for (i = 0; i < num_modes; i++)
- {
- RRModePtr mode = modes[i];
- modeinfos[i] = mode->mode;
- if (client->swapped)
- {
- swapl (&modeinfos[i].id, n);
- swaps (&modeinfos[i].width, n);
- swaps (&modeinfos[i].height, n);
- swapl (&modeinfos[i].dotClock, n);
- swaps (&modeinfos[i].hSyncStart, n);
- swaps (&modeinfos[i].hSyncEnd, n);
- swaps (&modeinfos[i].hTotal, n);
- swaps (&modeinfos[i].hSkew, n);
- swaps (&modeinfos[i].vSyncStart, n);
- swaps (&modeinfos[i].vSyncEnd, n);
- swaps (&modeinfos[i].vTotal, n);
- swaps (&modeinfos[i].nameLength, n);
- swapl (&modeinfos[i].modeFlags, n);
- }
- memcpy (names, mode->name,
- mode->mode.nameLength);
- names += mode->mode.nameLength;
- }
- free(modes);
- assert (bytes_to_int32((char *) names - (char *) extra) == rep.length);
- }
-
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.timestamp, n);
- swapl(&rep.configTimestamp, n);
- swaps(&rep.nCrtcs, n);
- swaps(&rep.nOutputs, n);
- swaps(&rep.nModes, n);
- swaps(&rep.nbytesNames, n);
- }
- WriteToClient(client, sizeof(xRRGetScreenResourcesReply), (char *)&rep);
- if (extraLen)
- {
- WriteToClient (client, extraLen, (char *) extra);
- free(extra);
- }
- return Success;
-}
-
-int
-ProcRRGetScreenResources (ClientPtr client)
-{
- return rrGetScreenResources(client, TRUE);
-}
-
-int
-ProcRRGetScreenResourcesCurrent (ClientPtr client)
-{
- return rrGetScreenResources(client, FALSE);
-}
-
-typedef struct _RR10Data {
- RRScreenSizePtr sizes;
- int nsize;
- int nrefresh;
- int size;
- CARD16 refresh;
-} RR10DataRec, *RR10DataPtr;
-
-/*
- * Convert 1.2 monitor data into 1.0 screen data
- */
-static RR10DataPtr
-RR10GetData (ScreenPtr pScreen, RROutputPtr output)
-{
- RR10DataPtr data;
- RRScreenSizePtr size;
- int nmode = output->numModes + output->numUserModes;
- int o, os, l, r;
- RRScreenRatePtr refresh;
- CARD16 vRefresh;
- RRModePtr mode;
- Bool *used;
-
- /* Make sure there is plenty of space for any combination */
- data = malloc (sizeof (RR10DataRec) +
- sizeof (RRScreenSize) * nmode +
- sizeof (RRScreenRate) * nmode +
- sizeof (Bool) * nmode);
- if (!data)
- return NULL;
- size = (RRScreenSizePtr) (data + 1);
- refresh = (RRScreenRatePtr) (size + nmode);
- used = (Bool *) (refresh + nmode);
- memset (used, '\0', sizeof (Bool) * nmode);
- data->sizes = size;
- data->nsize = 0;
- data->nrefresh = 0;
- data->size = 0;
- data->refresh = 0;
-
- /*
- * find modes not yet listed
- */
- for (o = 0; o < output->numModes + output->numUserModes; o++)
- {
- if (used[o]) continue;
-
- if (o < output->numModes)
- mode = output->modes[o];
- else
- mode = output->userModes[o - output->numModes];
-
- l = data->nsize;
- size[l].id = data->nsize;
- size[l].width = mode->mode.width;
- size[l].height = mode->mode.height;
- if (output->mmWidth && output->mmHeight) {
- size[l].mmWidth = output->mmWidth;
- size[l].mmHeight = output->mmHeight;
- } else {
- size[l].mmWidth = pScreen->mmWidth;
- size[l].mmHeight = pScreen->mmHeight;
- }
- size[l].nRates = 0;
- size[l].pRates = &refresh[data->nrefresh];
- data->nsize++;
-
- /*
- * Find all modes with matching size
- */
- for (os = o; os < output->numModes + output->numUserModes; os++)
- {
- if (os < output->numModes)
- mode = output->modes[os];
- else
- mode = output->userModes[os - output->numModes];
- if (mode->mode.width == size[l].width &&
- mode->mode.height == size[l].height)
- {
- vRefresh = RRVerticalRefresh (&mode->mode);
- used[os] = TRUE;
-
- for (r = 0; r < size[l].nRates; r++)
- if (vRefresh == size[l].pRates[r].rate)
- break;
- if (r == size[l].nRates)
- {
- size[l].pRates[r].rate = vRefresh;
- size[l].pRates[r].mode = mode;
- size[l].nRates++;
- data->nrefresh++;
- }
- if (mode == output->crtc->mode)
- {
- data->size = l;
- data->refresh = vRefresh;
- }
- }
- }
- }
- return data;
-}
-
-int
-ProcRRGetScreenInfo (ClientPtr client)
-{
- REQUEST(xRRGetScreenInfoReq);
- xRRGetScreenInfoReply rep;
- WindowPtr pWin;
- int n, rc;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- CARD8 *extra;
- unsigned long extraLen;
- RROutputPtr output;
-
- REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
- rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- pScreen = pWin->drawable.pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
- rep.pad = 0;
-
- if (pScrPriv)
- if (!RRGetInfo (pScreen, TRUE))
- return BadAlloc;
-
- output = RRFirstOutput (pScreen);
-
- if (!pScrPriv || !output)
- {
- rep.type = X_Reply;
- rep.setOfRotations = RR_Rotate_0;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.root = pWin->drawable.pScreen->root->drawable.id;
- rep.timestamp = currentTime.milliseconds;
- rep.configTimestamp = currentTime.milliseconds;
- rep.nSizes = 0;
- rep.sizeID = 0;
- rep.rotation = RR_Rotate_0;
- rep.rate = 0;
- rep.nrateEnts = 0;
- extra = 0;
- extraLen = 0;
- }
- else
- {
- int i, j;
- xScreenSizes *size;
- CARD16 *rates;
- CARD8 *data8;
- Bool has_rate = RRClientKnowsRates (client);
- RR10DataPtr pData;
- RRScreenSizePtr pSize;
-
- pData = RR10GetData (pScreen, output);
- if (!pData)
- return BadAlloc;
-
- rep.type = X_Reply;
- rep.setOfRotations = output->crtc->rotations;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.root = pWin->drawable.pScreen->root->drawable.id;
- rep.timestamp = pScrPriv->lastSetTime.milliseconds;
- rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
- rep.rotation = output->crtc->rotation;
- rep.nSizes = pData->nsize;
- rep.nrateEnts = pData->nrefresh + pData->nsize;
- rep.sizeID = pData->size;
- rep.rate = pData->refresh;
-
- extraLen = rep.nSizes * sizeof (xScreenSizes);
- if (has_rate)
- extraLen += rep.nrateEnts * sizeof (CARD16);
-
- if (extraLen)
- {
- extra = (CARD8 *) malloc(extraLen);
- if (!extra)
- {
- free(pData);
- return BadAlloc;
- }
- }
- else
- extra = NULL;
-
- /*
- * First comes the size information
- */
- size = (xScreenSizes *) extra;
- rates = (CARD16 *) (size + rep.nSizes);
- for (i = 0; i < pData->nsize; i++)
- {
- pSize = &pData->sizes[i];
- size->widthInPixels = pSize->width;
- size->heightInPixels = pSize->height;
- size->widthInMillimeters = pSize->mmWidth;
- size->heightInMillimeters = pSize->mmHeight;
- if (client->swapped)
- {
- swaps (&size->widthInPixels, n);
- swaps (&size->heightInPixels, n);
- swaps (&size->widthInMillimeters, n);
- swaps (&size->heightInMillimeters, n);
- }
- size++;
- if (has_rate)
- {
- *rates = pSize->nRates;
- if (client->swapped)
- {
- swaps (rates, n);
- }
- rates++;
- for (j = 0; j < pSize->nRates; j++)
- {
- *rates = pSize->pRates[j].rate;
- if (client->swapped)
- {
- swaps (rates, n);
- }
- rates++;
- }
- }
- }
- free(pData);
-
- data8 = (CARD8 *) rates;
-
- if (data8 - (CARD8 *) extra != extraLen)
- FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n",
- (unsigned long)(data8 - (CARD8 *) extra), extraLen);
- rep.length = bytes_to_int32(extraLen);
- }
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.timestamp, n);
- swaps(&rep.rotation, n);
- swaps(&rep.nSizes, n);
- swaps(&rep.sizeID, n);
- swaps(&rep.rate, n);
- swaps(&rep.nrateEnts, n);
- }
- WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep);
- if (extraLen)
- {
- WriteToClient (client, extraLen, (char *) extra);
- free(extra);
- }
- return Success;
-}
-
-int
-ProcRRSetScreenConfig (ClientPtr client)
-{
- REQUEST(xRRSetScreenConfigReq);
- xRRSetScreenConfigReply rep;
- DrawablePtr pDraw;
- int n, rc;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- TimeStamp time;
- int i;
- Rotation rotation;
- int rate;
- Bool has_rate;
- RROutputPtr output;
- RRCrtcPtr crtc;
- RRModePtr mode;
- RR10DataPtr pData = NULL;
- RRScreenSizePtr pSize;
- int width, height;
-
- UpdateCurrentTime ();
-
- if (RRClientKnowsRates (client))
- {
- REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
- has_rate = TRUE;
- }
- else
- {
- REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
- has_rate = FALSE;
- }
-
- rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess);
- if (rc != Success)
- return rc;
-
- pScreen = pDraw->pScreen;
-
- pScrPriv = rrGetScrPriv(pScreen);
-
- time = ClientTimeToServerTime(stuff->timestamp);
-
- if (!pScrPriv)
- {
- time = currentTime;
- rep.status = RRSetConfigFailed;
- goto sendReply;
- }
- if (!RRGetInfo (pScreen, FALSE))
- return BadAlloc;
-
- output = RRFirstOutput (pScreen);
- if (!output)
- {
- time = currentTime;
- rep.status = RRSetConfigFailed;
- goto sendReply;
- }
-
- crtc = output->crtc;
-
- /*
- * If the client's config timestamp is not the same as the last config
- * timestamp, then the config information isn't up-to-date and
- * can't even be validated.
- *
- * Note that the client only knows about the milliseconds part of the
- * timestamp, so using CompareTimeStamps here would cause randr to suddenly
- * stop working after several hours have passed (freedesktop bug #6502).
- */
- if (stuff->configTimestamp != pScrPriv->lastConfigTime.milliseconds)
- {
- rep.status = RRSetConfigInvalidConfigTime;
- goto sendReply;
- }
-
- pData = RR10GetData (pScreen, output);
- if (!pData)
- return BadAlloc;
-
- if (stuff->sizeID >= pData->nsize)
- {
- /*
- * Invalid size ID
- */
- client->errorValue = stuff->sizeID;
- free(pData);
- return BadValue;
- }
- pSize = &pData->sizes[stuff->sizeID];
-
- /*
- * 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(pData);
- return BadValue;
- }
-
- if ((~crtc->rotations) & rotation)
- {
- /*
- * requested rotation or reflection not supported by screen
- */
- client->errorValue = stuff->rotation;
- free(pData);
- return BadMatch;
- }
-
- /*
- * Validate requested refresh
- */
- if (has_rate)
- rate = (int) stuff->rate;
- else
- rate = 0;
-
- if (rate)
- {
- for (i = 0; i < pSize->nRates; i++)
- {
- if (pSize->pRates[i].rate == rate)
- break;
- }
- if (i == pSize->nRates)
- {
- /*
- * Invalid rate
- */
- client->errorValue = rate;
- free(pData);
- return BadValue;
- }
- mode = pSize->pRates[i].mode;
- }
- else
- mode = pSize->pRates[0].mode;
-
- /*
- * Make sure the requested set-time is not older than
- * the last set-time
- */
- if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
- {
- rep.status = RRSetConfigInvalidTime;
- goto sendReply;
- }
-
- /*
- * If the screen size is changing, adjust all of the other outputs
- * to fit the new size, mirroring as much as possible
- */
- width = mode->mode.width;
- height = mode->mode.height;
- if (width < pScrPriv->minWidth || pScrPriv->maxWidth < width) {
- client->errorValue = width;
- free(pData);
- return BadValue;
- }
- if (height < pScrPriv->minHeight || pScrPriv->maxHeight < height) {
- client->errorValue = height;
- free(pData);
- return BadValue;
- }
-
- if (rotation & (RR_Rotate_90|RR_Rotate_270))
- {
- width = mode->mode.height;
- height = mode->mode.width;
- }
-
- if (width != pScreen->width || height != pScreen->height)
- {
- int c;
-
- for (c = 0; c < pScrPriv->numCrtcs; c++)
- {
- if (!RRCrtcSet (pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0,
- 0, NULL))
- {
- rep.status = RRSetConfigFailed;
- /* XXX recover from failure */
- goto sendReply;
- }
- }
- if (!RRScreenSizeSet (pScreen, width, height,
- pScreen->mmWidth, pScreen->mmHeight))
- {
- rep.status = RRSetConfigFailed;
- /* XXX recover from failure */
- goto sendReply;
- }
- }
-
- if (!RRCrtcSet (crtc, mode, 0, 0, stuff->rotation, 1, &output))
- rep.status = RRSetConfigFailed;
- else {
- pScrPriv->lastSetTime = time;
- rep.status = RRSetConfigSuccess;
- }
-
- /*
- * XXX Configure other crtcs to mirror as much as possible
- */
-
-sendReply:
-
- free(pData);
-
- rep.type = X_Reply;
- /* rep.status has already been filled in */
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
-
- rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
- rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
- rep.root = pDraw->pScreen->root->drawable.id;
-
- if (client->swapped)
- {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.newTimestamp, n);
- swapl(&rep.newConfigTimestamp, n);
- swapl(&rep.root, n);
- }
- WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep);
-
- return Success;
-}
-
-static CARD16
-RR10CurrentSizeID (ScreenPtr pScreen)
-{
- CARD16 sizeID = 0xffff;
- RROutputPtr output = RRFirstOutput (pScreen);
-
- if (output)
- {
- RR10DataPtr data = RR10GetData (pScreen, output);
- if (data)
- {
- int i;
- for (i = 0; i < data->nsize; i++)
- if (data->sizes[i].width == pScreen->width &&
- data->sizes[i].height == pScreen->height)
- {
- sizeID = (CARD16) i;
- break;
- }
- free(data);
- }
- }
- return sizeID;
-}
+/* + * 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" + +static const int padlength[4] = {0, 3, 2, 1}; + +static CARD16 +RR10CurrentSizeID (ScreenPtr pScreen); + +/* + * Edit connection information block so that new clients + * see the current screen size on connect + */ +static void +RREditConnectionInfo (ScreenPtr pScreen) +{ + xConnSetup *connSetup; + char *vendor; + xPixmapFormat *formats; + xWindowRoot *root; + xDepth *depth; + xVisualType *visual; + int screen = 0; + int d; + + connSetup = (xConnSetup *) ConnectionInfo; + vendor = (char *) connSetup + sizeof (xConnSetup); + formats = (xPixmapFormat *) ((char *) vendor + + connSetup->nbytesVendor + + padlength[connSetup->nbytesVendor & 3]); + root = (xWindowRoot *) ((char *) formats + + sizeof (xPixmapFormat) * screenInfo.numPixmapFormats); + while (screen != pScreen->myNum) + { + depth = (xDepth *) ((char *) root + + sizeof (xWindowRoot)); + for (d = 0; d < root->nDepths; d++) + { + visual = (xVisualType *) ((char *) depth + + sizeof (xDepth)); + depth = (xDepth *) ((char *) visual + + depth->nVisuals * sizeof (xVisualType)); + } + root = (xWindowRoot *) ((char *) depth); + screen++; + } + root->pixWidth = pScreen->width; + root->pixHeight = pScreen->height; + root->mmWidth = pScreen->mmWidth; + root->mmHeight = pScreen->mmHeight; +} + +void +RRSendConfigNotify (ScreenPtr pScreen) +{ + WindowPtr pWin = pScreen->root; + xEvent event; + + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = 0; + event.u.configureNotify.y = 0; + + /* XXX xinerama stuff ? */ + + event.u.configureNotify.width = pWin->drawable.width; + event.u.configureNotify.height = pWin->drawable.height; + event.u.configureNotify.borderWidth = wBorderWidth (pWin); + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); +} + +void +RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen) +{ + rrScrPriv (pScreen); + xRRScreenChangeNotifyEvent se; + RRCrtcPtr crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL; + WindowPtr pRoot = pScreen->root; + + se.type = RRScreenChangeNotify + RREventBase; + se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0); + se.timestamp = pScrPriv->lastSetTime.milliseconds; + se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + se.root = pRoot->drawable.id; + se.window = pWin->drawable.id; + se.subpixelOrder = PictureGetSubpixelOrder (pScreen); + + se.sizeID = RR10CurrentSizeID (pScreen); + + if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) { + se.widthInPixels = pScreen->height; + se.heightInPixels = pScreen->width; + se.widthInMillimeters = pScreen->mmHeight; + se.heightInMillimeters = pScreen->mmWidth; + } else { + se.widthInPixels = pScreen->width; + se.heightInPixels = pScreen->height; + se.widthInMillimeters = pScreen->mmWidth; + se.heightInMillimeters = pScreen->mmHeight; + } + + WriteEventsToClient (client, 1, (xEvent *) &se); +} + +/* + * 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 + */ +void +RRScreenSizeNotify (ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + /* + * Deliver ConfigureNotify events when root changes + * pixel size + */ + if (pScrPriv->width == pScreen->width && + pScrPriv->height == pScreen->height && + pScrPriv->mmWidth == pScreen->mmWidth && + pScrPriv->mmHeight == pScreen->mmHeight) + return; + + pScrPriv->width = pScreen->width; + pScrPriv->height = pScreen->height; + pScrPriv->mmWidth = pScreen->mmWidth; + pScrPriv->mmHeight = pScreen->mmHeight; + pScrPriv->changed = TRUE; +/* pScrPriv->sizeChanged = TRUE; */ + + RRTellChanged (pScreen); + RRSendConfigNotify (pScreen); + RREditConnectionInfo (pScreen); + + RRPointerScreenConfigured (pScreen); + /* + * Fix pointer bounds and location + */ + ScreenRestructured (pScreen); +} + +/* + * Request that the screen be resized + */ +Bool +RRScreenSizeSet (ScreenPtr pScreen, + CARD16 width, + CARD16 height, + CARD32 mmWidth, + CARD32 mmHeight) +{ + rrScrPriv(pScreen); + +#if RANDR_12_INTERFACE + if (pScrPriv->rrScreenSetSize) + { + return (*pScrPriv->rrScreenSetSize) (pScreen, + width, height, + mmWidth, mmHeight); + } +#endif +#if RANDR_10_INTERFACE + if (pScrPriv->rrSetConfig) + { + return TRUE; /* can't set size separately */ + } +#endif + return FALSE; +} + +/* + * Retrieve valid screen size range + */ +int +ProcRRGetScreenSizeRange (ClientPtr client) +{ + REQUEST(xRRGetScreenSizeRangeReq); + xRRGetScreenSizeRangeReply rep; + WindowPtr pWin; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + int rc; + + REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + pScreen = pWin->drawable.pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + rep.type = X_Reply; + rep.pad = 0; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + if (pScrPriv) + { + if (!RRGetInfo (pScreen, FALSE)) + return BadAlloc; + rep.minWidth = pScrPriv->minWidth; + rep.minHeight = pScrPriv->minHeight; + rep.maxWidth = pScrPriv->maxWidth; + rep.maxHeight = pScrPriv->maxHeight; + } + else + { + rep.maxWidth = rep.minWidth = pScreen->width; + rep.maxHeight = rep.minHeight = pScreen->height; + } + if (client->swapped) + { + int n; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.minWidth, n); + swaps(&rep.minHeight, n); + swaps(&rep.maxWidth, n); + swaps(&rep.maxHeight, n); + } + WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), (char *)&rep); + return Success; +} + +int +ProcRRSetScreenSize (ClientPtr client) +{ + REQUEST(xRRSetScreenSizeReq); + WindowPtr pWin; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + int i, rc; + + REQUEST_SIZE_MATCH(xRRSetScreenSizeReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + pScreen = pWin->drawable.pScreen; + pScrPriv = rrGetScrPriv(pScreen); + if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width) + { + client->errorValue = stuff->width; + return BadValue; + } + if (stuff->height < pScrPriv->minHeight || + pScrPriv->maxHeight < stuff->height) + { + client->errorValue = stuff->height; + return BadValue; + } + for (i = 0; i < pScrPriv->numCrtcs; i++) + { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + RRModePtr mode = crtc->mode; + if (mode) + { + int source_width = mode->mode.width; + int source_height = mode->mode.height; + Rotation rotation = crtc->rotation; + + if (rotation == RR_Rotate_90 || rotation == RR_Rotate_270) + { + source_width = mode->mode.height; + source_height = mode->mode.width; + } + + if (crtc->x + source_width > stuff->width || + crtc->y + source_height > stuff->height) + return BadMatch; + } + } + if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0) + { + client->errorValue = 0; + return BadValue; + } + if (!RRScreenSizeSet (pScreen, + stuff->width, stuff->height, + stuff->widthInMillimeters, + stuff->heightInMillimeters)) + { + return BadMatch; + } + return Success; +} + +static int +rrGetScreenResources(ClientPtr client, Bool query) +{ + REQUEST(xRRGetScreenResourcesReq); + xRRGetScreenResourcesReply rep; + WindowPtr pWin; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + CARD8 *extra; + unsigned long extraLen; + int i, n, rc, has_primary = 0; + RRCrtc *crtcs; + RROutput *outputs; + xRRModeInfo *modeinfos; + CARD8 *names; + + REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + pScreen = pWin->drawable.pScreen; + pScrPriv = rrGetScrPriv(pScreen); + rep.pad = 0; + + if (query && pScrPriv) + if (!RRGetInfo (pScreen, query)) + return BadAlloc; + + if (!pScrPriv) + { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.timestamp = currentTime.milliseconds; + rep.configTimestamp = currentTime.milliseconds; + rep.nCrtcs = 0; + rep.nOutputs = 0; + rep.nModes = 0; + rep.nbytesNames = 0; + extra = NULL; + extraLen = 0; + } + else + { + RRModePtr *modes; + int num_modes; + + modes = RRModesForScreen (pScreen, &num_modes); + if (!modes) + return BadAlloc; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.nCrtcs = pScrPriv->numCrtcs; + rep.nOutputs = pScrPriv->numOutputs; + rep.nModes = num_modes; + rep.nbytesNames = 0; + + for (i = 0; i < num_modes; i++) + rep.nbytesNames += modes[i]->mode.nameLength; + + rep.length = (pScrPriv->numCrtcs + + pScrPriv->numOutputs + + num_modes * bytes_to_int32(SIZEOF(xRRModeInfo)) + + bytes_to_int32(rep.nbytesNames)); + + extraLen = rep.length << 2; + if (extraLen) + { + extra = malloc(extraLen); + if (!extra) + { + free(modes); + return BadAlloc; + } + } + else + extra = NULL; + + crtcs = (RRCrtc *) extra; + outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs); + modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs); + names = (CARD8 *) (modeinfos + num_modes); + + if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) + { + has_primary = 1; + crtcs[0] = pScrPriv->primaryOutput->crtc->id; + if (client->swapped) + swapl (&crtcs[0], n); + } + + for (i = 0; i < pScrPriv->numCrtcs; i++) + { + if (has_primary && + pScrPriv->primaryOutput->crtc == pScrPriv->crtcs[i]) + { + has_primary = 0; + continue; + } + crtcs[i + has_primary] = pScrPriv->crtcs[i]->id; + if (client->swapped) + swapl (&crtcs[i + has_primary], n); + } + + for (i = 0; i < pScrPriv->numOutputs; i++) + { + outputs[i] = pScrPriv->outputs[i]->id; + if (client->swapped) + swapl (&outputs[i], n); + } + + for (i = 0; i < num_modes; i++) + { + RRModePtr mode = modes[i]; + modeinfos[i] = mode->mode; + if (client->swapped) + { + swapl (&modeinfos[i].id, n); + swaps (&modeinfos[i].width, n); + swaps (&modeinfos[i].height, n); + swapl (&modeinfos[i].dotClock, n); + swaps (&modeinfos[i].hSyncStart, n); + swaps (&modeinfos[i].hSyncEnd, n); + swaps (&modeinfos[i].hTotal, n); + swaps (&modeinfos[i].hSkew, n); + swaps (&modeinfos[i].vSyncStart, n); + swaps (&modeinfos[i].vSyncEnd, n); + swaps (&modeinfos[i].vTotal, n); + swaps (&modeinfos[i].nameLength, n); + swapl (&modeinfos[i].modeFlags, n); + } + memcpy (names, mode->name, + mode->mode.nameLength); + names += mode->mode.nameLength; + } + free(modes); + assert (bytes_to_int32((char *) names - (char *) extra) == rep.length); + } + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swapl(&rep.configTimestamp, n); + swaps(&rep.nCrtcs, n); + swaps(&rep.nOutputs, n); + swaps(&rep.nModes, n); + swaps(&rep.nbytesNames, n); + } + WriteToClient(client, sizeof(xRRGetScreenResourcesReply), (char *)&rep); + if (extraLen) + { + WriteToClient (client, extraLen, (char *) extra); + free(extra); + } + return Success; +} + +int +ProcRRGetScreenResources (ClientPtr client) +{ + return rrGetScreenResources(client, TRUE); +} + +int +ProcRRGetScreenResourcesCurrent (ClientPtr client) +{ + return rrGetScreenResources(client, FALSE); +} + +typedef struct _RR10Data { + RRScreenSizePtr sizes; + int nsize; + int nrefresh; + int size; + CARD16 refresh; +} RR10DataRec, *RR10DataPtr; + +/* + * Convert 1.2 monitor data into 1.0 screen data + */ +static RR10DataPtr +RR10GetData (ScreenPtr pScreen, RROutputPtr output) +{ + RR10DataPtr data; + RRScreenSizePtr size; + int nmode = output->numModes + output->numUserModes; + int o, os, l, r; + RRScreenRatePtr refresh; + CARD16 vRefresh; + RRModePtr mode; + Bool *used; + + /* Make sure there is plenty of space for any combination */ + data = malloc (sizeof (RR10DataRec) + + sizeof (RRScreenSize) * nmode + + sizeof (RRScreenRate) * nmode + + sizeof (Bool) * nmode); + if (!data) + return NULL; + size = (RRScreenSizePtr) (data + 1); + refresh = (RRScreenRatePtr) (size + nmode); + used = (Bool *) (refresh + nmode); + memset (used, '\0', sizeof (Bool) * nmode); + data->sizes = size; + data->nsize = 0; + data->nrefresh = 0; + data->size = 0; + data->refresh = 0; + + /* + * find modes not yet listed + */ + for (o = 0; o < output->numModes + output->numUserModes; o++) + { + if (used[o]) continue; + + if (o < output->numModes) + mode = output->modes[o]; + else + mode = output->userModes[o - output->numModes]; + + l = data->nsize; + size[l].id = data->nsize; + size[l].width = mode->mode.width; + size[l].height = mode->mode.height; + if (output->mmWidth && output->mmHeight) { + size[l].mmWidth = output->mmWidth; + size[l].mmHeight = output->mmHeight; + } else { + size[l].mmWidth = pScreen->mmWidth; + size[l].mmHeight = pScreen->mmHeight; + } + size[l].nRates = 0; + size[l].pRates = &refresh[data->nrefresh]; + data->nsize++; + + /* + * Find all modes with matching size + */ + for (os = o; os < output->numModes + output->numUserModes; os++) + { + if (os < output->numModes) + mode = output->modes[os]; + else + mode = output->userModes[os - output->numModes]; + if (mode->mode.width == size[l].width && + mode->mode.height == size[l].height) + { + vRefresh = RRVerticalRefresh (&mode->mode); + used[os] = TRUE; + + for (r = 0; r < size[l].nRates; r++) + if (vRefresh == size[l].pRates[r].rate) + break; + if (r == size[l].nRates) + { + size[l].pRates[r].rate = vRefresh; + size[l].pRates[r].mode = mode; + size[l].nRates++; + data->nrefresh++; + } + if (mode == output->crtc->mode) + { + data->size = l; + data->refresh = vRefresh; + } + } + } + } + return data; +} + +int +ProcRRGetScreenInfo (ClientPtr client) +{ + REQUEST(xRRGetScreenInfoReq); + xRRGetScreenInfoReply rep; + WindowPtr pWin; + int n, rc; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + CARD8 *extra; + unsigned long extraLen; + RROutputPtr output; + + REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + pScreen = pWin->drawable.pScreen; + pScrPriv = rrGetScrPriv(pScreen); + rep.pad = 0; + + if (pScrPriv) + if (!RRGetInfo (pScreen, TRUE)) + return BadAlloc; + + output = RRFirstOutput (pScreen); + + if (!pScrPriv || !output) + { + rep.type = X_Reply; + rep.setOfRotations = RR_Rotate_0; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = pWin->drawable.pScreen->root->drawable.id; + rep.timestamp = currentTime.milliseconds; + rep.configTimestamp = currentTime.milliseconds; + rep.nSizes = 0; + rep.sizeID = 0; + rep.rotation = RR_Rotate_0; + rep.rate = 0; + rep.nrateEnts = 0; + extra = 0; + extraLen = 0; + } + else + { + int i, j; + xScreenSizes *size; + CARD16 *rates; + CARD8 *data8; + Bool has_rate = RRClientKnowsRates (client); + RR10DataPtr pData; + RRScreenSizePtr pSize; + + pData = RR10GetData (pScreen, output); + if (!pData) + return BadAlloc; + + rep.type = X_Reply; + rep.setOfRotations = output->crtc->rotations; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = pWin->drawable.pScreen->root->drawable.id; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.rotation = output->crtc->rotation; + rep.nSizes = pData->nsize; + rep.nrateEnts = pData->nrefresh + pData->nsize; + rep.sizeID = pData->size; + rep.rate = pData->refresh; + + extraLen = rep.nSizes * sizeof (xScreenSizes); + if (has_rate) + extraLen += rep.nrateEnts * sizeof (CARD16); + + if (extraLen) + { + extra = (CARD8 *) malloc(extraLen); + if (!extra) + { + free(pData); + return BadAlloc; + } + } + else + extra = NULL; + + /* + * First comes the size information + */ + size = (xScreenSizes *) extra; + rates = (CARD16 *) (size + rep.nSizes); + for (i = 0; i < pData->nsize; i++) + { + pSize = &pData->sizes[i]; + size->widthInPixels = pSize->width; + size->heightInPixels = pSize->height; + size->widthInMillimeters = pSize->mmWidth; + size->heightInMillimeters = pSize->mmHeight; + if (client->swapped) + { + swaps (&size->widthInPixels, n); + swaps (&size->heightInPixels, n); + swaps (&size->widthInMillimeters, n); + swaps (&size->heightInMillimeters, n); + } + size++; + if (has_rate) + { + *rates = pSize->nRates; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + for (j = 0; j < pSize->nRates; j++) + { + *rates = pSize->pRates[j].rate; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + } + } + } + free(pData); + + data8 = (CARD8 *) rates; + + if (data8 - (CARD8 *) extra != extraLen) + FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n", + (unsigned long)(data8 - (CARD8 *) extra), extraLen); + rep.length = bytes_to_int32(extraLen); + } + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swaps(&rep.rotation, n); + swaps(&rep.nSizes, n); + swaps(&rep.sizeID, n); + swaps(&rep.rate, n); + swaps(&rep.nrateEnts, n); + } + WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep); + if (extraLen) + { + WriteToClient (client, extraLen, (char *) extra); + free(extra); + } + return Success; +} + +int +ProcRRSetScreenConfig (ClientPtr client) +{ + REQUEST(xRRSetScreenConfigReq); + xRRSetScreenConfigReply rep; + DrawablePtr pDraw; + int n, rc; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + TimeStamp time; + int i; + Rotation rotation; + int rate; + Bool has_rate; + RROutputPtr output; + RRCrtcPtr crtc; + RRModePtr mode; + RR10DataPtr pData = NULL; + RRScreenSizePtr pSize; + int width, height; + + UpdateCurrentTime (); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + has_rate = TRUE; + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + has_rate = FALSE; + } + + rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess); + if (rc != Success) + return rc; + + pScreen = pDraw->pScreen; + + pScrPriv = rrGetScrPriv(pScreen); + + time = ClientTimeToServerTime(stuff->timestamp); + + if (!pScrPriv) + { + time = currentTime; + rep.status = RRSetConfigFailed; + goto sendReply; + } + if (!RRGetInfo (pScreen, FALSE)) + return BadAlloc; + + output = RRFirstOutput (pScreen); + if (!output) + { + time = currentTime; + rep.status = RRSetConfigFailed; + goto sendReply; + } + + crtc = output->crtc; + + /* + * If the client's config timestamp is not the same as the last config + * timestamp, then the config information isn't up-to-date and + * can't even be validated. + * + * Note that the client only knows about the milliseconds part of the + * timestamp, so using CompareTimeStamps here would cause randr to suddenly + * stop working after several hours have passed (freedesktop bug #6502). + */ + if (stuff->configTimestamp != pScrPriv->lastConfigTime.milliseconds) + { + rep.status = RRSetConfigInvalidConfigTime; + goto sendReply; + } + + pData = RR10GetData (pScreen, output); + if (!pData) + return BadAlloc; + + if (stuff->sizeID >= pData->nsize) + { + /* + * Invalid size ID + */ + client->errorValue = stuff->sizeID; + free(pData); + return BadValue; + } + pSize = &pData->sizes[stuff->sizeID]; + + /* + * 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(pData); + return BadValue; + } + + if ((~crtc->rotations) & rotation) + { + /* + * requested rotation or reflection not supported by screen + */ + client->errorValue = stuff->rotation; + free(pData); + return BadMatch; + } + + /* + * Validate requested refresh + */ + if (has_rate) + rate = (int) stuff->rate; + else + rate = 0; + + if (rate) + { + for (i = 0; i < pSize->nRates; i++) + { + if (pSize->pRates[i].rate == rate) + break; + } + if (i == pSize->nRates) + { + /* + * Invalid rate + */ + client->errorValue = rate; + free(pData); + return BadValue; + } + mode = pSize->pRates[i].mode; + } + else + mode = pSize->pRates[0].mode; + + /* + * Make sure the requested set-time is not older than + * the last set-time + */ + if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) + { + rep.status = RRSetConfigInvalidTime; + goto sendReply; + } + + /* + * If the screen size is changing, adjust all of the other outputs + * to fit the new size, mirroring as much as possible + */ + width = mode->mode.width; + height = mode->mode.height; + if (width < pScrPriv->minWidth || pScrPriv->maxWidth < width) { + client->errorValue = width; + free(pData); + return BadValue; + } + if (height < pScrPriv->minHeight || pScrPriv->maxHeight < height) { + client->errorValue = height; + free(pData); + return BadValue; + } + + if (rotation & (RR_Rotate_90|RR_Rotate_270)) + { + width = mode->mode.height; + height = mode->mode.width; + } + + if (width != pScreen->width || height != pScreen->height) + { + int c; + + for (c = 0; c < pScrPriv->numCrtcs; c++) + { + if (!RRCrtcSet (pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0, + 0, NULL)) + { + rep.status = RRSetConfigFailed; + /* XXX recover from failure */ + goto sendReply; + } + } + if (!RRScreenSizeSet (pScreen, width, height, + pScreen->mmWidth, pScreen->mmHeight)) + { + rep.status = RRSetConfigFailed; + /* XXX recover from failure */ + goto sendReply; + } + } + + if (!RRCrtcSet (crtc, mode, 0, 0, stuff->rotation, 1, &output)) + rep.status = RRSetConfigFailed; + else { + pScrPriv->lastSetTime = time; + rep.status = RRSetConfigSuccess; + } + + /* + * XXX Configure other crtcs to mirror as much as possible + */ + +sendReply: + + free(pData); + + rep.type = X_Reply; + /* rep.status has already been filled in */ + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; + rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.root = pDraw->pScreen->root->drawable.id; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.newTimestamp, n); + swapl(&rep.newConfigTimestamp, n); + swapl(&rep.root, n); + } + WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep); + + return Success; +} + +static CARD16 +RR10CurrentSizeID (ScreenPtr pScreen) +{ + CARD16 sizeID = 0xffff; + RROutputPtr output = RRFirstOutput (pScreen); + + if (output) + { + RR10DataPtr data = RR10GetData (pScreen, output); + if (data) + { + int i; + for (i = 0; i < data->nsize; i++) + if (data->sizes[i].width == pScreen->width && + data->sizes[i].height == pScreen->height) + { + sizeID = (CARD16) i; + break; + } + free(data); + } + } + return sizeID; +} diff --git a/xorg-server/randr/rrsdispatch.c b/xorg-server/randr/rrsdispatch.c index 0a9207bac..e16090a41 100644 --- a/xorg-server/randr/rrsdispatch.c +++ b/xorg-server/randr/rrsdispatch.c @@ -1,503 +1,503 @@ -/*
- * 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"
-
-static int
-SProcRRQueryVersion (ClientPtr client)
-{
- register int n;
- REQUEST(xRRQueryVersionReq);
-
- swaps(&stuff->length, n);
- swapl(&stuff->majorVersion, n);
- swapl(&stuff->minorVersion, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRGetScreenInfo (ClientPtr client)
-{
- register int n;
- REQUEST(xRRGetScreenInfoReq);
-
- swaps(&stuff->length, n);
- swapl(&stuff->window, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRSetScreenConfig (ClientPtr client)
-{
- register int n;
- REQUEST(xRRSetScreenConfigReq);
-
- if (RRClientKnowsRates (client))
- {
- REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
- swaps (&stuff->rate, n);
- }
- else
- {
- REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
- }
-
- swaps(&stuff->length, n);
- swapl(&stuff->drawable, n);
- swapl(&stuff->timestamp, n);
- swaps(&stuff->sizeID, n);
- swaps(&stuff->rotation, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRSelectInput (ClientPtr client)
-{
- register int n;
- REQUEST(xRRSelectInputReq);
-
- swaps(&stuff->length, n);
- swapl(&stuff->window, n);
- swaps(&stuff->enable, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRGetScreenSizeRange (ClientPtr client)
-{
- int n;
- REQUEST(xRRGetScreenSizeRangeReq);
-
- REQUEST_SIZE_MATCH(xRRGetScreenSizeRangeReq);
- swaps(&stuff->length, n);
- swapl(&stuff->window, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRSetScreenSize (ClientPtr client)
-{
- int n;
- REQUEST(xRRSetScreenSizeReq);
-
- REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
- swaps(&stuff->length, n);
- swapl(&stuff->window, n);
- swaps(&stuff->width, n);
- swaps(&stuff->height, n);
- swapl(&stuff->widthInMillimeters, n);
- swapl(&stuff->heightInMillimeters, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRGetScreenResources (ClientPtr client)
-{
- int n;
- REQUEST(xRRGetScreenResourcesReq);
-
- REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
- swaps(&stuff->length, n);
- swapl(&stuff->window, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRGetOutputInfo (ClientPtr client)
-{
- int n;
- REQUEST(xRRGetOutputInfoReq);
-
- REQUEST_SIZE_MATCH(xRRGetOutputInfoReq);
- swaps(&stuff->length, n);
- swapl(&stuff->output, n);
- swapl(&stuff->configTimestamp, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRListOutputProperties (ClientPtr client)
-{
- int n;
- REQUEST(xRRListOutputPropertiesReq);
-
- REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq);
- swaps(&stuff->length, n);
- swapl(&stuff->output, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRQueryOutputProperty (ClientPtr client)
-{
- int n;
- REQUEST(xRRQueryOutputPropertyReq);
-
- REQUEST_SIZE_MATCH(xRRQueryOutputPropertyReq);
- swaps(&stuff->length, n);
- swapl(&stuff->output, n);
- swapl(&stuff->property, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRConfigureOutputProperty (ClientPtr client)
-{
- int n;
- REQUEST(xRRConfigureOutputPropertyReq);
-
- swaps(&stuff->length, n);
- swapl(&stuff->output, n);
- swapl(&stuff->property, n);
- SwapRestL(stuff);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRChangeOutputProperty (ClientPtr client)
-{
- int n;
- REQUEST(xRRChangeOutputPropertyReq);
-
- REQUEST_AT_LEAST_SIZE (xRRChangeOutputPropertyReq);
- swaps(&stuff->length, n);
- swapl(&stuff->output, n);
- swapl(&stuff->property, n);
- swapl(&stuff->type, n);
- swapl(&stuff->nUnits, n);
- switch(stuff->format) {
- case 8:
- break;
- case 16:
- SwapRestS(stuff);
- break;
- case 32:
- SwapRestL(stuff);
- break;
- default:
- client->errorValue = stuff->format;
- return BadValue;
- }
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRDeleteOutputProperty (ClientPtr client)
-{
- int n;
- REQUEST(xRRDeleteOutputPropertyReq);
-
- REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq);
- swaps(&stuff->length, n);
- swapl(&stuff->output, n);
- swapl(&stuff->property, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRGetOutputProperty (ClientPtr client)
-{
- int n;
- REQUEST(xRRGetOutputPropertyReq);
-
- REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq);
- swaps(&stuff->length, n);
- swapl(&stuff->output, n);
- swapl(&stuff->property, n);
- swapl(&stuff->type, n);
- swapl(&stuff->longOffset, n);
- swapl(&stuff->longLength, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRCreateMode (ClientPtr client)
-{
- int n;
- xRRModeInfo *modeinfo;
- REQUEST(xRRCreateModeReq);
-
- REQUEST_AT_LEAST_SIZE(xRRCreateModeReq);
- swaps(&stuff->length, n);
- swapl(&stuff->window, n);
-
- modeinfo = &stuff->modeInfo;
- swapl(&modeinfo->id, n);
- swaps(&modeinfo->width, n);
- swaps(&modeinfo->height, n);
- swapl(&modeinfo->dotClock, n);
- swaps(&modeinfo->hSyncStart, n);
- swaps(&modeinfo->hSyncEnd, n);
- swaps(&modeinfo->hTotal, n);
- swaps(&modeinfo->vSyncStart, n);
- swaps(&modeinfo->vSyncEnd, n);
- swaps(&modeinfo->vTotal, n);
- swaps(&modeinfo->nameLength, n);
- swapl(&modeinfo->modeFlags, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRDestroyMode (ClientPtr client)
-{
- int n;
- REQUEST(xRRDestroyModeReq);
-
- REQUEST_SIZE_MATCH(xRRDestroyModeReq);
- swaps(&stuff->length, n);
- swapl(&stuff->mode, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRAddOutputMode (ClientPtr client)
-{
- int n;
- REQUEST(xRRAddOutputModeReq);
-
- REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
- swaps(&stuff->length, n);
- swapl(&stuff->output, n);
- swapl(&stuff->mode, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRDeleteOutputMode (ClientPtr client)
-{
- int n;
- REQUEST(xRRDeleteOutputModeReq);
-
- REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
- swaps(&stuff->length, n);
- swapl(&stuff->output, n);
- swapl(&stuff->mode, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRGetCrtcInfo (ClientPtr client)
-{
- int n;
- REQUEST(xRRGetCrtcInfoReq);
-
- REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq);
- swaps(&stuff->length, n);
- swapl(&stuff->crtc, n);
- swapl(&stuff->configTimestamp, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRSetCrtcConfig (ClientPtr client)
-{
- int n;
- REQUEST(xRRSetCrtcConfigReq);
-
- REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq);
- swaps(&stuff->length, n);
- swapl(&stuff->crtc, n);
- swapl(&stuff->timestamp, n);
- swapl(&stuff->configTimestamp, n);
- swaps(&stuff->x, n);
- swaps(&stuff->y, n);
- swapl(&stuff->mode, n);
- swaps(&stuff->rotation, n);
- SwapRestL(stuff);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRGetCrtcGammaSize (ClientPtr client)
-{
- int n;
- REQUEST(xRRGetCrtcGammaSizeReq);
-
- REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq);
- swaps(&stuff->length, n);
- swapl(&stuff->crtc, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRGetCrtcGamma (ClientPtr client)
-{
- int n;
- REQUEST(xRRGetCrtcGammaReq);
-
- REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq);
- swaps(&stuff->length, n);
- swapl(&stuff->crtc, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRSetCrtcGamma (ClientPtr client)
-{
- int n;
- REQUEST(xRRSetCrtcGammaReq);
-
- REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq);
- swaps(&stuff->length, n);
- swapl(&stuff->crtc, n);
- swaps(&stuff->size, n);
- SwapRestS(stuff);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRSetCrtcTransform (ClientPtr client)
-{
- int n, nparams;
- char *filter;
- CARD32 *params;
- REQUEST(xRRSetCrtcTransformReq);
-
- REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq);
- swaps(&stuff->length, n);
- swapl(&stuff->crtc, n);
- SwapLongs((CARD32 *)&stuff->transform, bytes_to_int32(sizeof(xRenderTransform)));
- swaps(&stuff->nbytesFilter, n);
- filter = (char *)(stuff + 1);
- params = (CARD32 *) (filter + pad_to_int32(stuff->nbytesFilter));
- nparams = ((CARD32 *) stuff + client->req_len) - params;
- if (nparams < 0)
- return BadLength;
-
- SwapLongs(params, nparams);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRGetCrtcTransform (ClientPtr client)
-{
- int n;
- REQUEST(xRRGetCrtcTransformReq);
-
- REQUEST_SIZE_MATCH(xRRGetCrtcTransformReq);
- swaps(&stuff->length, n);
- swapl(&stuff->crtc, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRGetPanning (ClientPtr client)
-{
- int n;
- REQUEST(xRRGetPanningReq);
-
- REQUEST_SIZE_MATCH(xRRGetPanningReq);
- swaps(&stuff->length, n);
- swapl(&stuff->crtc, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRSetPanning (ClientPtr client)
-{
- int n;
- REQUEST(xRRSetPanningReq);
-
- REQUEST_SIZE_MATCH(xRRSetPanningReq);
- swaps(&stuff->length, n);
- swapl(&stuff->crtc, n);
- swapl(&stuff->timestamp, n);
- swaps(&stuff->left, n);
- swaps(&stuff->top, n);
- swaps(&stuff->width, n);
- swaps(&stuff->height, n);
- swaps(&stuff->track_left, n);
- swaps(&stuff->track_top, n);
- swaps(&stuff->track_width, n);
- swaps(&stuff->track_height, n);
- swaps(&stuff->border_left, n);
- swaps(&stuff->border_top, n);
- swaps(&stuff->border_right, n);
- swaps(&stuff->border_bottom, n);
- return (*ProcRandrVector[stuff->randrReqType]) (client);
-}
-
-static int
-SProcRRSetOutputPrimary (ClientPtr client)
-{
- int n;
- REQUEST(xRRSetOutputPrimaryReq);
-
- REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq);
- swaps(&stuff->length, n);
- swapl(&stuff->window, n);
- swapl(&stuff->output, n);
- return ProcRandrVector[stuff->randrReqType](client);
-}
-
-static int
-SProcRRGetOutputPrimary (ClientPtr client)
-{
- int n;
- REQUEST(xRRGetOutputPrimaryReq);
-
- REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq);
- swaps(&stuff->length, n);
- swapl(&stuff->window, n);
- return ProcRandrVector[stuff->randrReqType](client);
-}
-
-int (*SProcRandrVector[RRNumberRequests])(ClientPtr) = {
- SProcRRQueryVersion, /* 0 */
-/* we skip 1 to make old clients fail pretty immediately */
- NULL, /* 1 SProcRandrOldGetScreenInfo */
-/* V1.0 apps share the same set screen config request id */
- SProcRRSetScreenConfig, /* 2 */
- NULL, /* 3 SProcRandrOldScreenChangeSelectInput */
-/* 3 used to be ScreenChangeSelectInput; deprecated */
- SProcRRSelectInput, /* 4 */
- SProcRRGetScreenInfo, /* 5 */
-/* V1.2 additions */
- SProcRRGetScreenSizeRange, /* 6 */
- SProcRRSetScreenSize, /* 7 */
- SProcRRGetScreenResources, /* 8 */
- SProcRRGetOutputInfo, /* 9 */
- SProcRRListOutputProperties,/* 10 */
- SProcRRQueryOutputProperty, /* 11 */
- SProcRRConfigureOutputProperty, /* 12 */
- SProcRRChangeOutputProperty,/* 13 */
- SProcRRDeleteOutputProperty,/* 14 */
- SProcRRGetOutputProperty, /* 15 */
- SProcRRCreateMode, /* 16 */
- SProcRRDestroyMode, /* 17 */
- SProcRRAddOutputMode, /* 18 */
- SProcRRDeleteOutputMode, /* 19 */
- SProcRRGetCrtcInfo, /* 20 */
- SProcRRSetCrtcConfig, /* 21 */
- SProcRRGetCrtcGammaSize, /* 22 */
- SProcRRGetCrtcGamma, /* 23 */
- SProcRRSetCrtcGamma, /* 24 */
-/* V1.3 additions */
- SProcRRGetScreenResources, /* 25 GetScreenResourcesCurrent */
- SProcRRSetCrtcTransform, /* 26 */
- SProcRRGetCrtcTransform, /* 27 */
- SProcRRGetPanning, /* 28 */
- SProcRRSetPanning, /* 29 */
- SProcRRSetOutputPrimary, /* 30 */
- SProcRRGetOutputPrimary, /* 31 */
-};
-
+/* + * 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" + +static int +SProcRRQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRRQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRGetScreenInfo (ClientPtr client) +{ + register int n; + REQUEST(xRRGetScreenInfoReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRSetScreenConfig (ClientPtr client) +{ + register int n; + REQUEST(xRRSetScreenConfigReq); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + swaps (&stuff->rate, n); + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + } + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + swapl(&stuff->timestamp, n); + swaps(&stuff->sizeID, n); + swaps(&stuff->rotation, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRSelectInput (ClientPtr client) +{ + register int n; + REQUEST(xRRSelectInputReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swaps(&stuff->enable, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRGetScreenSizeRange (ClientPtr client) +{ + int n; + REQUEST(xRRGetScreenSizeRangeReq); + + REQUEST_SIZE_MATCH(xRRGetScreenSizeRangeReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRSetScreenSize (ClientPtr client) +{ + int n; + REQUEST(xRRSetScreenSizeReq); + + REQUEST_SIZE_MATCH(xRRSetScreenSizeReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->widthInMillimeters, n); + swapl(&stuff->heightInMillimeters, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRGetScreenResources (ClientPtr client) +{ + int n; + REQUEST(xRRGetScreenResourcesReq); + + REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRGetOutputInfo (ClientPtr client) +{ + int n; + REQUEST(xRRGetOutputInfoReq); + + REQUEST_SIZE_MATCH(xRRGetOutputInfoReq); + swaps(&stuff->length, n); + swapl(&stuff->output, n); + swapl(&stuff->configTimestamp, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRListOutputProperties (ClientPtr client) +{ + int n; + REQUEST(xRRListOutputPropertiesReq); + + REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq); + swaps(&stuff->length, n); + swapl(&stuff->output, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRQueryOutputProperty (ClientPtr client) +{ + int n; + REQUEST(xRRQueryOutputPropertyReq); + + REQUEST_SIZE_MATCH(xRRQueryOutputPropertyReq); + swaps(&stuff->length, n); + swapl(&stuff->output, n); + swapl(&stuff->property, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRConfigureOutputProperty (ClientPtr client) +{ + int n; + REQUEST(xRRConfigureOutputPropertyReq); + + swaps(&stuff->length, n); + swapl(&stuff->output, n); + swapl(&stuff->property, n); + SwapRestL(stuff); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRChangeOutputProperty (ClientPtr client) +{ + int n; + REQUEST(xRRChangeOutputPropertyReq); + + REQUEST_AT_LEAST_SIZE (xRRChangeOutputPropertyReq); + swaps(&stuff->length, n); + swapl(&stuff->output, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->nUnits, n); + switch(stuff->format) { + case 8: + break; + case 16: + SwapRestS(stuff); + break; + case 32: + SwapRestL(stuff); + break; + default: + client->errorValue = stuff->format; + return BadValue; + } + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRDeleteOutputProperty (ClientPtr client) +{ + int n; + REQUEST(xRRDeleteOutputPropertyReq); + + REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq); + swaps(&stuff->length, n); + swapl(&stuff->output, n); + swapl(&stuff->property, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRGetOutputProperty (ClientPtr client) +{ + int n; + REQUEST(xRRGetOutputPropertyReq); + + REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq); + swaps(&stuff->length, n); + swapl(&stuff->output, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->longOffset, n); + swapl(&stuff->longLength, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRCreateMode (ClientPtr client) +{ + int n; + xRRModeInfo *modeinfo; + REQUEST(xRRCreateModeReq); + + REQUEST_AT_LEAST_SIZE(xRRCreateModeReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + + modeinfo = &stuff->modeInfo; + swapl(&modeinfo->id, n); + swaps(&modeinfo->width, n); + swaps(&modeinfo->height, n); + swapl(&modeinfo->dotClock, n); + swaps(&modeinfo->hSyncStart, n); + swaps(&modeinfo->hSyncEnd, n); + swaps(&modeinfo->hTotal, n); + swaps(&modeinfo->vSyncStart, n); + swaps(&modeinfo->vSyncEnd, n); + swaps(&modeinfo->vTotal, n); + swaps(&modeinfo->nameLength, n); + swapl(&modeinfo->modeFlags, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRDestroyMode (ClientPtr client) +{ + int n; + REQUEST(xRRDestroyModeReq); + + REQUEST_SIZE_MATCH(xRRDestroyModeReq); + swaps(&stuff->length, n); + swapl(&stuff->mode, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRAddOutputMode (ClientPtr client) +{ + int n; + REQUEST(xRRAddOutputModeReq); + + REQUEST_SIZE_MATCH(xRRAddOutputModeReq); + swaps(&stuff->length, n); + swapl(&stuff->output, n); + swapl(&stuff->mode, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRDeleteOutputMode (ClientPtr client) +{ + int n; + REQUEST(xRRDeleteOutputModeReq); + + REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq); + swaps(&stuff->length, n); + swapl(&stuff->output, n); + swapl(&stuff->mode, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRGetCrtcInfo (ClientPtr client) +{ + int n; + REQUEST(xRRGetCrtcInfoReq); + + REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); + swaps(&stuff->length, n); + swapl(&stuff->crtc, n); + swapl(&stuff->configTimestamp, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRSetCrtcConfig (ClientPtr client) +{ + int n; + REQUEST(xRRSetCrtcConfigReq); + + REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq); + swaps(&stuff->length, n); + swapl(&stuff->crtc, n); + swapl(&stuff->timestamp, n); + swapl(&stuff->configTimestamp, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swapl(&stuff->mode, n); + swaps(&stuff->rotation, n); + SwapRestL(stuff); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRGetCrtcGammaSize (ClientPtr client) +{ + int n; + REQUEST(xRRGetCrtcGammaSizeReq); + + REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq); + swaps(&stuff->length, n); + swapl(&stuff->crtc, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRGetCrtcGamma (ClientPtr client) +{ + int n; + REQUEST(xRRGetCrtcGammaReq); + + REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq); + swaps(&stuff->length, n); + swapl(&stuff->crtc, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRSetCrtcGamma (ClientPtr client) +{ + int n; + REQUEST(xRRSetCrtcGammaReq); + + REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq); + swaps(&stuff->length, n); + swapl(&stuff->crtc, n); + swaps(&stuff->size, n); + SwapRestS(stuff); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRSetCrtcTransform (ClientPtr client) +{ + int n, nparams; + char *filter; + CARD32 *params; + REQUEST(xRRSetCrtcTransformReq); + + REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq); + swaps(&stuff->length, n); + swapl(&stuff->crtc, n); + SwapLongs((CARD32 *)&stuff->transform, bytes_to_int32(sizeof(xRenderTransform))); + swaps(&stuff->nbytesFilter, n); + filter = (char *)(stuff + 1); + params = (CARD32 *) (filter + pad_to_int32(stuff->nbytesFilter)); + nparams = ((CARD32 *) stuff + client->req_len) - params; + if (nparams < 0) + return BadLength; + + SwapLongs(params, nparams); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRGetCrtcTransform (ClientPtr client) +{ + int n; + REQUEST(xRRGetCrtcTransformReq); + + REQUEST_SIZE_MATCH(xRRGetCrtcTransformReq); + swaps(&stuff->length, n); + swapl(&stuff->crtc, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRGetPanning (ClientPtr client) +{ + int n; + REQUEST(xRRGetPanningReq); + + REQUEST_SIZE_MATCH(xRRGetPanningReq); + swaps(&stuff->length, n); + swapl(&stuff->crtc, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRSetPanning (ClientPtr client) +{ + int n; + REQUEST(xRRSetPanningReq); + + REQUEST_SIZE_MATCH(xRRSetPanningReq); + swaps(&stuff->length, n); + swapl(&stuff->crtc, n); + swapl(&stuff->timestamp, n); + swaps(&stuff->left, n); + swaps(&stuff->top, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swaps(&stuff->track_left, n); + swaps(&stuff->track_top, n); + swaps(&stuff->track_width, n); + swaps(&stuff->track_height, n); + swaps(&stuff->border_left, n); + swaps(&stuff->border_top, n); + swaps(&stuff->border_right, n); + swaps(&stuff->border_bottom, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRSetOutputPrimary (ClientPtr client) +{ + int n; + REQUEST(xRRSetOutputPrimaryReq); + + REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->output, n); + return ProcRandrVector[stuff->randrReqType](client); +} + +static int +SProcRRGetOutputPrimary (ClientPtr client) +{ + int n; + REQUEST(xRRGetOutputPrimaryReq); + + REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRandrVector[stuff->randrReqType](client); +} + +int (*SProcRandrVector[RRNumberRequests])(ClientPtr) = { + SProcRRQueryVersion, /* 0 */ +/* we skip 1 to make old clients fail pretty immediately */ + NULL, /* 1 SProcRandrOldGetScreenInfo */ +/* V1.0 apps share the same set screen config request id */ + SProcRRSetScreenConfig, /* 2 */ + NULL, /* 3 SProcRandrOldScreenChangeSelectInput */ +/* 3 used to be ScreenChangeSelectInput; deprecated */ + SProcRRSelectInput, /* 4 */ + SProcRRGetScreenInfo, /* 5 */ +/* V1.2 additions */ + SProcRRGetScreenSizeRange, /* 6 */ + SProcRRSetScreenSize, /* 7 */ + SProcRRGetScreenResources, /* 8 */ + SProcRRGetOutputInfo, /* 9 */ + SProcRRListOutputProperties,/* 10 */ + SProcRRQueryOutputProperty, /* 11 */ + SProcRRConfigureOutputProperty, /* 12 */ + SProcRRChangeOutputProperty,/* 13 */ + SProcRRDeleteOutputProperty,/* 14 */ + SProcRRGetOutputProperty, /* 15 */ + SProcRRCreateMode, /* 16 */ + SProcRRDestroyMode, /* 17 */ + SProcRRAddOutputMode, /* 18 */ + SProcRRDeleteOutputMode, /* 19 */ + SProcRRGetCrtcInfo, /* 20 */ + SProcRRSetCrtcConfig, /* 21 */ + SProcRRGetCrtcGammaSize, /* 22 */ + SProcRRGetCrtcGamma, /* 23 */ + SProcRRSetCrtcGamma, /* 24 */ +/* V1.3 additions */ + SProcRRGetScreenResources, /* 25 GetScreenResourcesCurrent */ + SProcRRSetCrtcTransform, /* 26 */ + SProcRRGetCrtcTransform, /* 27 */ + SProcRRGetPanning, /* 28 */ + SProcRRSetPanning, /* 29 */ + SProcRRSetOutputPrimary, /* 30 */ + SProcRRGetOutputPrimary, /* 31 */ +}; + diff --git a/xorg-server/randr/rrtransform.c b/xorg-server/randr/rrtransform.c index 102a0f48e..e1620498b 100644 --- a/xorg-server/randr/rrtransform.c +++ b/xorg-server/randr/rrtransform.c @@ -1,283 +1,283 @@ -/*
- * Copyright © 2007 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 "rrtransform.h"
-
-void
-RRTransformInit (RRTransformPtr transform)
-{
- pixman_transform_init_identity (&transform->transform);
- pixman_f_transform_init_identity (&transform->f_transform);
- pixman_f_transform_init_identity (&transform->f_inverse);
- transform->filter = NULL;
- transform->params = NULL;
- transform->nparams = 0;
-}
-
-void
-RRTransformFini (RRTransformPtr transform)
-{
- free(transform->params);
-}
-
-Bool
-RRTransformEqual (RRTransformPtr a, RRTransformPtr b)
-{
- if (a && pixman_transform_is_identity (&a->transform))
- a = NULL;
- if (b && pixman_transform_is_identity (&b->transform))
- b = NULL;
- if (a == NULL && b == NULL)
- return TRUE;
- if (a == NULL || b == NULL)
- return FALSE;
- if (memcmp (&a->transform, &b->transform, sizeof (a->transform)) != 0)
- return FALSE;
- if (a->filter != b->filter)
- return FALSE;
- if (a->nparams != b->nparams)
- return FALSE;
- if (memcmp (a->params, b->params, a->nparams * sizeof (xFixed)) != 0)
- return FALSE;
- return TRUE;
-}
-
-Bool
-RRTransformSetFilter (RRTransformPtr dst,
- PictFilterPtr filter,
- xFixed *params,
- int nparams,
- int width,
- int height)
-{
- xFixed *new_params;
-
- if (nparams)
- {
- new_params = malloc(nparams * sizeof (xFixed));
- if (!new_params)
- return FALSE;
- memcpy (new_params, params, nparams * sizeof (xFixed));
- }
- else
- new_params = NULL;
- free(dst->params);
- dst->filter = filter;
- dst->params = new_params;
- dst->nparams = nparams;
- dst->width = width;
- dst->height = height;
- return TRUE;
-}
-
-Bool
-RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
-{
- if (src && pixman_transform_is_identity (&src->transform))
- src = NULL;
-
- if (src)
- {
- if (!RRTransformSetFilter (dst, src->filter,
- src->params, src->nparams, src->width, src->height))
- return FALSE;
- dst->transform = src->transform;
- dst->f_transform = src->f_transform;
- dst->f_inverse = src->f_inverse;
- }
- else
- {
- if (!RRTransformSetFilter (dst, NULL, NULL, 0, 0, 0))
- return FALSE;
- pixman_transform_init_identity (&dst->transform);
- pixman_f_transform_init_identity (&dst->f_transform);
- pixman_f_transform_init_identity (&dst->f_inverse);
- }
- return TRUE;
-}
-
-#define F(x) IntToxFixed(x)
-
-static void
-RRTransformRescale(struct pixman_f_transform *f_transform, double limit)
-{
- double max = 0, v, scale;
- int i, j;
-
- for (j = 0; j < 3; j++)
- for (i = 0; i < 3; i++)
- if ((v = abs (f_transform->m[j][i])) > max)
- max = v;
- scale = limit / max;
- for (j = 0; j < 3; j++)
- for (i = 0; i < 3; i++)
- f_transform->m[j][i] *= scale;
-}
-
-/*
- * 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.
- */
-Bool
-RRTransformCompute (int x,
- int y,
- int width,
- int height,
- Rotation rotation,
- RRTransformPtr rr_transform,
-
- PictTransformPtr transform,
- struct pixman_f_transform *f_transform,
- struct pixman_f_transform *f_inverse)
-{
- PictTransform t_transform, inverse;
- struct pixman_f_transform tf_transform, tf_inverse;
- Bool overflow = FALSE;
-
- if (!transform) transform = &t_transform;
- if (!f_transform) f_transform = &tf_transform;
- if (!f_inverse) f_inverse = &tf_inverse;
-
- pixman_transform_init_identity (transform);
- pixman_transform_init_identity (&inverse);
- pixman_f_transform_init_identity (f_transform);
- pixman_f_transform_init_identity (f_inverse);
- if (rotation != RR_Rotate_0)
- {
- double f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy;
- double f_scale_x, f_scale_y, f_scale_dx, f_scale_dy;
- xFixed rot_cos, rot_sin, rot_dx, rot_dy;
- xFixed scale_x, scale_y, scale_dx, scale_dy;
-
- /* rotation */
- switch (rotation & 0xf) {
- default:
- case RR_Rotate_0:
- f_rot_cos = 1; f_rot_sin = 0;
- f_rot_dx = 0; f_rot_dy = 0;
- rot_cos = F ( 1); rot_sin = F ( 0);
- rot_dx = F ( 0); rot_dy = F ( 0);
- break;
- case RR_Rotate_90:
- f_rot_cos = 0; f_rot_sin = 1;
- f_rot_dx = height; f_rot_dy = 0;
- rot_cos = F ( 0); rot_sin = F ( 1);
- rot_dx = F ( height); rot_dy = F (0);
- break;
- case RR_Rotate_180:
- f_rot_cos = -1; f_rot_sin = 0;
- f_rot_dx = width; f_rot_dy = height;
- rot_cos = F (-1); rot_sin = F ( 0);
- rot_dx = F (width); rot_dy = F ( height);
- break;
- case RR_Rotate_270:
- f_rot_cos = 0; f_rot_sin = -1;
- f_rot_dx = 0; f_rot_dy = width;
- rot_cos = F ( 0); rot_sin = F (-1);
- rot_dx = F ( 0); rot_dy = F ( width);
- break;
- }
-
- pixman_transform_rotate (transform, &inverse, rot_cos, rot_sin);
- pixman_transform_translate (transform, &inverse, rot_dx, rot_dy);
- pixman_f_transform_rotate (f_transform, f_inverse, f_rot_cos, f_rot_sin);
- pixman_f_transform_translate (f_transform, f_inverse, f_rot_dx, f_rot_dy);
-
- /* reflection */
- f_scale_x = 1;
- f_scale_dx = 0;
- f_scale_y = 1;
- f_scale_dy = 0;
- scale_x = F (1);
- scale_dx = 0;
- scale_y = F (1);
- scale_dy = 0;
- if (rotation & RR_Reflect_X)
- {
- f_scale_x = -1;
- scale_x = F(-1);
- if (rotation & (RR_Rotate_0|RR_Rotate_180)) {
- f_scale_dx = width;
- scale_dx = F(width);
- } else {
- f_scale_dx = height;
- scale_dx = F(height);
- }
- }
- if (rotation & RR_Reflect_Y)
- {
- f_scale_y = -1;
- scale_y = F(-1);
- if (rotation & (RR_Rotate_0|RR_Rotate_180)) {
- f_scale_dy = height;
- scale_dy = F(height);
- } else {
- f_scale_dy = width;
- scale_dy = F(width);
- }
- }
-
- pixman_transform_scale (transform, &inverse, scale_x, scale_y);
- pixman_f_transform_scale (f_transform, f_inverse, f_scale_x, f_scale_y);
- pixman_transform_translate (transform, &inverse, scale_dx, scale_dy);
- pixman_f_transform_translate (f_transform, f_inverse, f_scale_dx, f_scale_dy);
- }
-
-#ifdef RANDR_12_INTERFACE
- if (rr_transform)
- {
- if (!pixman_transform_multiply (transform, &rr_transform->transform, transform))
- overflow = TRUE;
- pixman_f_transform_multiply (f_transform, &rr_transform->f_transform, f_transform);
- pixman_f_transform_multiply (f_inverse, f_inverse, &rr_transform->f_inverse);
- }
-#endif
- /*
- * Compute the class of the resulting transform
- */
- if (!overflow && pixman_transform_is_identity (transform))
- {
- pixman_transform_init_translate (transform, F ( x), F ( y));
-
- pixman_f_transform_init_translate (f_transform, x, y);
- pixman_f_transform_init_translate (f_inverse, -x, -y);
- return FALSE;
- }
- else
- {
- pixman_f_transform_translate (f_transform, f_inverse, x, y);
- if (!pixman_transform_translate (transform, &inverse, F(x), F(y)))
- overflow = TRUE;
- if (overflow)
- {
- struct pixman_f_transform f_scaled;
- f_scaled = *f_transform;
- RRTransformRescale(&f_scaled, 16384.0);
- pixman_transform_from_pixman_f_transform(transform, &f_scaled);
- }
- return TRUE;
- }
-}
+/* + * Copyright © 2007 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 "rrtransform.h" + +void +RRTransformInit (RRTransformPtr transform) +{ + pixman_transform_init_identity (&transform->transform); + pixman_f_transform_init_identity (&transform->f_transform); + pixman_f_transform_init_identity (&transform->f_inverse); + transform->filter = NULL; + transform->params = NULL; + transform->nparams = 0; +} + +void +RRTransformFini (RRTransformPtr transform) +{ + free(transform->params); +} + +Bool +RRTransformEqual (RRTransformPtr a, RRTransformPtr b) +{ + if (a && pixman_transform_is_identity (&a->transform)) + a = NULL; + if (b && pixman_transform_is_identity (&b->transform)) + b = NULL; + if (a == NULL && b == NULL) + return TRUE; + if (a == NULL || b == NULL) + return FALSE; + if (memcmp (&a->transform, &b->transform, sizeof (a->transform)) != 0) + return FALSE; + if (a->filter != b->filter) + return FALSE; + if (a->nparams != b->nparams) + return FALSE; + if (memcmp (a->params, b->params, a->nparams * sizeof (xFixed)) != 0) + return FALSE; + return TRUE; +} + +Bool +RRTransformSetFilter (RRTransformPtr dst, + PictFilterPtr filter, + xFixed *params, + int nparams, + int width, + int height) +{ + xFixed *new_params; + + if (nparams) + { + new_params = malloc(nparams * sizeof (xFixed)); + if (!new_params) + return FALSE; + memcpy (new_params, params, nparams * sizeof (xFixed)); + } + else + new_params = NULL; + free(dst->params); + dst->filter = filter; + dst->params = new_params; + dst->nparams = nparams; + dst->width = width; + dst->height = height; + return TRUE; +} + +Bool +RRTransformCopy (RRTransformPtr dst, RRTransformPtr src) +{ + if (src && pixman_transform_is_identity (&src->transform)) + src = NULL; + + if (src) + { + if (!RRTransformSetFilter (dst, src->filter, + src->params, src->nparams, src->width, src->height)) + return FALSE; + dst->transform = src->transform; + dst->f_transform = src->f_transform; + dst->f_inverse = src->f_inverse; + } + else + { + if (!RRTransformSetFilter (dst, NULL, NULL, 0, 0, 0)) + return FALSE; + pixman_transform_init_identity (&dst->transform); + pixman_f_transform_init_identity (&dst->f_transform); + pixman_f_transform_init_identity (&dst->f_inverse); + } + return TRUE; +} + +#define F(x) IntToxFixed(x) + +static void +RRTransformRescale(struct pixman_f_transform *f_transform, double limit) +{ + double max = 0, v, scale; + int i, j; + + for (j = 0; j < 3; j++) + for (i = 0; i < 3; i++) + if ((v = abs (f_transform->m[j][i])) > max) + max = v; + scale = limit / max; + for (j = 0; j < 3; j++) + for (i = 0; i < 3; i++) + f_transform->m[j][i] *= scale; +} + +/* + * 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. + */ +Bool +RRTransformCompute (int x, + int y, + int width, + int height, + Rotation rotation, + RRTransformPtr rr_transform, + + PictTransformPtr transform, + struct pixman_f_transform *f_transform, + struct pixman_f_transform *f_inverse) +{ + PictTransform t_transform, inverse; + struct pixman_f_transform tf_transform, tf_inverse; + Bool overflow = FALSE; + + if (!transform) transform = &t_transform; + if (!f_transform) f_transform = &tf_transform; + if (!f_inverse) f_inverse = &tf_inverse; + + pixman_transform_init_identity (transform); + pixman_transform_init_identity (&inverse); + pixman_f_transform_init_identity (f_transform); + pixman_f_transform_init_identity (f_inverse); + if (rotation != RR_Rotate_0) + { + double f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy; + double f_scale_x, f_scale_y, f_scale_dx, f_scale_dy; + xFixed rot_cos, rot_sin, rot_dx, rot_dy; + xFixed scale_x, scale_y, scale_dx, scale_dy; + + /* rotation */ + switch (rotation & 0xf) { + default: + case RR_Rotate_0: + f_rot_cos = 1; f_rot_sin = 0; + f_rot_dx = 0; f_rot_dy = 0; + rot_cos = F ( 1); rot_sin = F ( 0); + rot_dx = F ( 0); rot_dy = F ( 0); + break; + case RR_Rotate_90: + f_rot_cos = 0; f_rot_sin = 1; + f_rot_dx = height; f_rot_dy = 0; + rot_cos = F ( 0); rot_sin = F ( 1); + rot_dx = F ( height); rot_dy = F (0); + break; + case RR_Rotate_180: + f_rot_cos = -1; f_rot_sin = 0; + f_rot_dx = width; f_rot_dy = height; + rot_cos = F (-1); rot_sin = F ( 0); + rot_dx = F (width); rot_dy = F ( height); + break; + case RR_Rotate_270: + f_rot_cos = 0; f_rot_sin = -1; + f_rot_dx = 0; f_rot_dy = width; + rot_cos = F ( 0); rot_sin = F (-1); + rot_dx = F ( 0); rot_dy = F ( width); + break; + } + + pixman_transform_rotate (transform, &inverse, rot_cos, rot_sin); + pixman_transform_translate (transform, &inverse, rot_dx, rot_dy); + pixman_f_transform_rotate (f_transform, f_inverse, f_rot_cos, f_rot_sin); + pixman_f_transform_translate (f_transform, f_inverse, f_rot_dx, f_rot_dy); + + /* reflection */ + f_scale_x = 1; + f_scale_dx = 0; + f_scale_y = 1; + f_scale_dy = 0; + scale_x = F (1); + scale_dx = 0; + scale_y = F (1); + scale_dy = 0; + if (rotation & RR_Reflect_X) + { + f_scale_x = -1; + scale_x = F(-1); + if (rotation & (RR_Rotate_0|RR_Rotate_180)) { + f_scale_dx = width; + scale_dx = F(width); + } else { + f_scale_dx = height; + scale_dx = F(height); + } + } + if (rotation & RR_Reflect_Y) + { + f_scale_y = -1; + scale_y = F(-1); + if (rotation & (RR_Rotate_0|RR_Rotate_180)) { + f_scale_dy = height; + scale_dy = F(height); + } else { + f_scale_dy = width; + scale_dy = F(width); + } + } + + pixman_transform_scale (transform, &inverse, scale_x, scale_y); + pixman_f_transform_scale (f_transform, f_inverse, f_scale_x, f_scale_y); + pixman_transform_translate (transform, &inverse, scale_dx, scale_dy); + pixman_f_transform_translate (f_transform, f_inverse, f_scale_dx, f_scale_dy); + } + +#ifdef RANDR_12_INTERFACE + if (rr_transform) + { + if (!pixman_transform_multiply (transform, &rr_transform->transform, transform)) + overflow = TRUE; + pixman_f_transform_multiply (f_transform, &rr_transform->f_transform, f_transform); + pixman_f_transform_multiply (f_inverse, f_inverse, &rr_transform->f_inverse); + } +#endif + /* + * Compute the class of the resulting transform + */ + if (!overflow && pixman_transform_is_identity (transform)) + { + pixman_transform_init_translate (transform, F ( x), F ( y)); + + pixman_f_transform_init_translate (f_transform, x, y); + pixman_f_transform_init_translate (f_inverse, -x, -y); + return FALSE; + } + else + { + pixman_f_transform_translate (f_transform, f_inverse, x, y); + if (!pixman_transform_translate (transform, &inverse, F(x), F(y))) + overflow = TRUE; + if (overflow) + { + struct pixman_f_transform f_scaled; + f_scaled = *f_transform; + RRTransformRescale(&f_scaled, 16384.0); + pixman_transform_from_pixman_f_transform(transform, &f_scaled); + } + return TRUE; + } +} diff --git a/xorg-server/randr/rrtransform.h b/xorg-server/randr/rrtransform.h index b09a84ca1..561762dfe 100644 --- a/xorg-server/randr/rrtransform.h +++ b/xorg-server/randr/rrtransform.h @@ -1,75 +1,75 @@ -/*
- * Copyright © 2007 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.
- */
-
-#ifndef _RRTRANSFORM_H_
-#define _RRTRANSFORM_H_
-
-#include <X11/extensions/randr.h>
-#include "picturestr.h"
-
-typedef struct _rrTransform RRTransformRec, *RRTransformPtr;
-
-struct _rrTransform {
- PictTransform transform;
- struct pict_f_transform f_transform;
- struct pict_f_transform f_inverse;
- PictFilterPtr filter;
- xFixed *params;
- int nparams;
- int width;
- int height;
-};
-
-extern _X_EXPORT void
-RRTransformInit (RRTransformPtr transform);
-
-extern _X_EXPORT void
-RRTransformFini (RRTransformPtr transform);
-
-extern _X_EXPORT Bool
-RRTransformEqual (RRTransformPtr a, RRTransformPtr b);
-
-extern _X_EXPORT Bool
-RRTransformSetFilter (RRTransformPtr dst,
- PictFilterPtr filter,
- xFixed *params,
- int nparams,
- int width,
- int height);
-
-extern _X_EXPORT Bool
-RRTransformCopy (RRTransformPtr dst, RRTransformPtr src);
-
-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);
-
-
-#endif /* _RRTRANSFORM_H_ */
+/* + * Copyright © 2007 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. + */ + +#ifndef _RRTRANSFORM_H_ +#define _RRTRANSFORM_H_ + +#include <X11/extensions/randr.h> +#include "picturestr.h" + +typedef struct _rrTransform RRTransformRec, *RRTransformPtr; + +struct _rrTransform { + PictTransform transform; + struct pict_f_transform f_transform; + struct pict_f_transform f_inverse; + PictFilterPtr filter; + xFixed *params; + int nparams; + int width; + int height; +}; + +extern _X_EXPORT void +RRTransformInit (RRTransformPtr transform); + +extern _X_EXPORT void +RRTransformFini (RRTransformPtr transform); + +extern _X_EXPORT Bool +RRTransformEqual (RRTransformPtr a, RRTransformPtr b); + +extern _X_EXPORT Bool +RRTransformSetFilter (RRTransformPtr dst, + PictFilterPtr filter, + xFixed *params, + int nparams, + int width, + int height); + +extern _X_EXPORT Bool +RRTransformCopy (RRTransformPtr dst, RRTransformPtr src); + +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); + + +#endif /* _RRTRANSFORM_H_ */ |