From 1c94119ae26b94a60bb2c2b33494ed43c3b8a52f Mon Sep 17 00:00:00 2001 From: marha Date: Sun, 16 May 2010 20:50:58 +0000 Subject: svn merge -r588:HEAD ^/branches/released . --- xorg-server/randr/randr.c | 992 +++++++------- xorg-server/randr/rrcrtc.c | 2774 +++++++++++++++++++-------------------- xorg-server/randr/rrdispatch.c | 456 +++---- xorg-server/randr/rrinfo.c | 682 +++++----- xorg-server/randr/rrmode.c | 738 +++++------ xorg-server/randr/rroutput.c | 1252 +++++++++--------- xorg-server/randr/rrproperty.c | 56 +- xorg-server/randr/rrscreen.c | 2018 ++++++++++++++-------------- xorg-server/randr/rrtransform.c | 570 ++++---- xorg-server/randr/rrxinerama.c | 952 +++++++------- 10 files changed, 5245 insertions(+), 5245 deletions(-) (limited to 'xorg-server/randr') diff --git a/xorg-server/randr/randr.c b/xorg-server/randr/randr.c index b63a7f22e..b843f588d 100644 --- a/xorg-server/randr/randr.c +++ b/xorg-server/randr/randr.c @@ -1,496 +1,496 @@ -/* - * Copyright © 2000 Compaq Computer Corporation - * Copyright © 2002 Hewlett-Packard Company - * Copyright © 2006 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - * - * Author: Jim Gettys, Hewlett-Packard Company, Inc. - * Keith Packard, Intel Corporation - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "randrstr.h" - -/* From render.h */ -#ifndef SubPixelUnknown -#define SubPixelUnknown 0 -#endif - -#define RR_VALIDATE -static int RRNScreens; - -#define wrap(priv,real,mem,func) {\ - priv->mem = real->mem; \ - real->mem = func; \ -} - -#define unwrap(priv,real,mem) {\ - real->mem = priv->mem; \ -} - -static int ProcRRDispatch (ClientPtr pClient); -static int SProcRRDispatch (ClientPtr pClient); - -int RREventBase; -int RRErrorBase; -RESTYPE RRClientType, RREventType; /* resource types for event masks */ -static int RRClientPrivateKeyIndex; -DevPrivateKey RRClientPrivateKey = &RRClientPrivateKeyIndex; - -static int rrPrivKeyIndex; -DevPrivateKey rrPrivKey = &rrPrivKeyIndex; - -static void -RRClientCallback (CallbackListPtr *list, - pointer closure, - pointer data) -{ - NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; - ClientPtr pClient = clientinfo->client; - rrClientPriv(pClient); - RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1); - int i; - - pRRClient->major_version = 0; - pRRClient->minor_version = 0; - for (i = 0; i < screenInfo.numScreens; i++) - { - ScreenPtr pScreen = screenInfo.screens[i]; - rrScrPriv(pScreen); - - if (pScrPriv) - { - pTimes[i].setTime = pScrPriv->lastSetTime; - pTimes[i].configTime = pScrPriv->lastConfigTime; - } - } -} - -static Bool -RRCloseScreen (int i, ScreenPtr pScreen) -{ - rrScrPriv(pScreen); - int j; - - unwrap (pScrPriv, pScreen, CloseScreen); - for (j = pScrPriv->numCrtcs - 1; j >= 0; j--) - RRCrtcDestroy (pScrPriv->crtcs[j]); - for (j = pScrPriv->numOutputs - 1; j >= 0; j--) - RROutputDestroy (pScrPriv->outputs[j]); - - xfree (pScrPriv->crtcs); - xfree (pScrPriv->outputs); - xfree (pScrPriv); - RRNScreens -= 1; /* ok, one fewer screen with RandR running */ - return (*pScreen->CloseScreen) (i, pScreen); -} - -static void -SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from, - xRRScreenChangeNotifyEvent *to) -{ - to->type = from->type; - to->rotation = from->rotation; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->timestamp, to->timestamp); - cpswapl(from->configTimestamp, to->configTimestamp); - cpswapl(from->root, to->root); - cpswapl(from->window, to->window); - cpswaps(from->sizeID, to->sizeID); - cpswaps(from->subpixelOrder, to->subpixelOrder); - cpswaps(from->widthInPixels, to->widthInPixels); - cpswaps(from->heightInPixels, to->heightInPixels); - cpswaps(from->widthInMillimeters, to->widthInMillimeters); - cpswaps(from->heightInMillimeters, to->heightInMillimeters); -} - -static void -SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent *from, - xRRCrtcChangeNotifyEvent *to) -{ - to->type = from->type; - to->subCode = from->subCode; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->timestamp, to->timestamp); - cpswapl(from->window, to->window); - cpswapl(from->crtc, to->crtc); - cpswapl(from->mode, to->mode); - cpswaps(from->rotation, to->rotation); - /* pad1 */ - cpswaps(from->x, to->x); - cpswaps(from->y, to->y); - cpswaps(from->width, to->width); - cpswaps(from->height, to->height); -} - -static void -SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent *from, - xRROutputChangeNotifyEvent *to) -{ - to->type = from->type; - to->subCode = from->subCode; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->timestamp, to->timestamp); - cpswapl(from->configTimestamp, to->configTimestamp); - cpswapl(from->window, to->window); - cpswapl(from->output, to->output); - cpswapl(from->crtc, to->crtc); - cpswapl(from->mode, to->mode); - cpswaps(from->rotation, to->rotation); - to->connection = from->connection; - to->subpixelOrder = from->subpixelOrder; -} - -static void -SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent *from, - xRROutputPropertyNotifyEvent *to) -{ - to->type = from->type; - to->subCode = from->subCode; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->window, to->window); - cpswapl(from->output, to->output); - cpswapl(from->atom, to->atom); - cpswapl(from->timestamp, to->timestamp); - to->state = from->state; - /* pad1 */ - /* pad2 */ - /* pad3 */ - /* pad4 */ -} - -static void -SRRNotifyEvent (xEvent *from, - xEvent *to) -{ - switch (from->u.u.detail) { - case RRNotify_CrtcChange: - SRRCrtcChangeNotifyEvent ((xRRCrtcChangeNotifyEvent *) from, - (xRRCrtcChangeNotifyEvent *) to); - break; - case RRNotify_OutputChange: - SRROutputChangeNotifyEvent ((xRROutputChangeNotifyEvent *) from, - (xRROutputChangeNotifyEvent *) to); - break; - case RRNotify_OutputProperty: - SRROutputPropertyNotifyEvent ((xRROutputPropertyNotifyEvent *) from, - (xRROutputPropertyNotifyEvent *) to); - break; - default: - break; - } -} - -static int RRGeneration; - -Bool RRInit (void) -{ - if (RRGeneration != serverGeneration) - { - if (!RRModeInit ()) - return FALSE; - if (!RRCrtcInit ()) - return FALSE; - if (!RROutputInit ()) - return FALSE; - RRGeneration = serverGeneration; - } - return TRUE; -} - -Bool RRScreenInit(ScreenPtr pScreen) -{ - rrScrPrivPtr pScrPriv; - - if (!RRInit ()) - return FALSE; - - pScrPriv = (rrScrPrivPtr) xcalloc (1, sizeof (rrScrPrivRec)); - if (!pScrPriv) - return FALSE; - - SetRRScreen(pScreen, pScrPriv); - - /* - * Calling function best set these function vectors - */ - pScrPriv->rrGetInfo = 0; - pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width; - pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height; - - pScrPriv->width = pScreen->width; - pScrPriv->height = pScreen->height; - pScrPriv->mmWidth = pScreen->mmWidth; - pScrPriv->mmHeight = pScreen->mmHeight; -#if RANDR_12_INTERFACE - pScrPriv->rrScreenSetSize = NULL; - pScrPriv->rrCrtcSet = NULL; - pScrPriv->rrCrtcSetGamma = NULL; -#endif -#if RANDR_10_INTERFACE - pScrPriv->rrSetConfig = 0; - pScrPriv->rotations = RR_Rotate_0; - pScrPriv->reqWidth = pScreen->width; - pScrPriv->reqHeight = pScreen->height; - pScrPriv->nSizes = 0; - pScrPriv->pSizes = NULL; - pScrPriv->rotation = RR_Rotate_0; - pScrPriv->rate = 0; - pScrPriv->size = 0; -#endif - - /* - * This value doesn't really matter -- any client must call - * GetScreenInfo before reading it which will automatically update - * the time - */ - pScrPriv->lastSetTime = currentTime; - pScrPriv->lastConfigTime = currentTime; - - wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen); - - pScrPriv->numOutputs = 0; - pScrPriv->outputs = NULL; - pScrPriv->numCrtcs = 0; - pScrPriv->crtcs = NULL; - - RRNScreens += 1; /* keep count of screens that implement randr */ - return TRUE; -} - -/*ARGSUSED*/ -static int -RRFreeClient (pointer data, XID id) -{ - RREventPtr pRREvent; - WindowPtr pWin; - RREventPtr *pHead, pCur, pPrev; - - pRREvent = (RREventPtr) data; - pWin = pRREvent->window; - dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, - RREventType, serverClient, DixDestroyAccess); - if (pHead) { - pPrev = 0; - for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next) - pPrev = pCur; - if (pCur) - { - if (pPrev) - pPrev->next = pRREvent->next; - else - *pHead = pRREvent->next; - } - } - xfree ((pointer) pRREvent); - return 1; -} - -/*ARGSUSED*/ -static int -RRFreeEvents (pointer data, XID id) -{ - RREventPtr *pHead, pCur, pNext; - - pHead = (RREventPtr *) data; - for (pCur = *pHead; pCur; pCur = pNext) { - pNext = pCur->next; - FreeResource (pCur->clientResource, RRClientType); - xfree ((pointer) pCur); - } - xfree ((pointer) pHead); - return 1; -} - -void -RRExtensionInit (void) -{ - ExtensionEntry *extEntry; - - if (RRNScreens == 0) return; - - if (!dixRequestPrivate(RRClientPrivateKey, - sizeof (RRClientRec) + - screenInfo.numScreens * sizeof (RRTimesRec))) - return; - if (!AddCallback (&ClientStateCallback, RRClientCallback, 0)) - return; - - RRClientType = CreateNewResourceType(RRFreeClient, "RandRClient"); - if (!RRClientType) - return; - RREventType = CreateNewResourceType(RRFreeEvents, "RandREvent"); - if (!RREventType) - return; - extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors, - ProcRRDispatch, SProcRRDispatch, - NULL, StandardMinorOpcode); - if (!extEntry) - return; - RRErrorBase = extEntry->errorBase; - RREventBase = extEntry->eventBase; - EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) - SRRScreenChangeNotifyEvent; - EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr) - SRRNotifyEvent; -#ifdef PANORAMIX - RRXineramaExtensionInit(); -#endif -} - -static int -TellChanged (WindowPtr pWin, pointer value) -{ - RREventPtr *pHead, pRREvent; - ClientPtr client; - ScreenPtr pScreen = pWin->drawable.pScreen; - rrScrPriv(pScreen); - int i; - - dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, - RREventType, serverClient, DixReadAccess); - if (!pHead) - return WT_WALKCHILDREN; - - for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) - { - client = pRREvent->client; - if (client == serverClient || client->clientGone) - continue; - - if (pRREvent->mask & RRScreenChangeNotifyMask) - RRDeliverScreenEvent (client, pWin, pScreen); - - if (pRREvent->mask & RRCrtcChangeNotifyMask) - { - for (i = 0; i < pScrPriv->numCrtcs; i++) - { - RRCrtcPtr crtc = pScrPriv->crtcs[i]; - if (crtc->changed) - RRDeliverCrtcEvent (client, pWin, crtc); - } - } - - if (pRREvent->mask & RROutputChangeNotifyMask) - { - for (i = 0; i < pScrPriv->numOutputs; i++) - { - RROutputPtr output = pScrPriv->outputs[i]; - if (output->changed) - RRDeliverOutputEvent (client, pWin, output); - } - } - } - return WT_WALKCHILDREN; -} - -/* - * Something changed; send events and adjust pointer position - */ -void -RRTellChanged (ScreenPtr pScreen) -{ - rrScrPriv (pScreen); - int i; - - if (pScrPriv->changed) - { - UpdateCurrentTime (); - if (pScrPriv->configChanged) - { - pScrPriv->lastConfigTime = currentTime; - pScrPriv->configChanged = FALSE; - } - pScrPriv->changed = FALSE; - WalkTree (pScreen, TellChanged, (pointer) pScreen); - for (i = 0; i < pScrPriv->numOutputs; i++) - pScrPriv->outputs[i]->changed = FALSE; - for (i = 0; i < pScrPriv->numCrtcs; i++) - pScrPriv->crtcs[i]->changed = FALSE; - if (pScrPriv->layoutChanged) - { - pScrPriv->layoutChanged = FALSE; - RRPointerScreenConfigured (pScreen); - RRSendConfigNotify (pScreen); - } - } -} - -/* - * Return the first output which is connected to an active CRTC - * Used in emulating 1.0 behaviour - */ -RROutputPtr -RRFirstOutput (ScreenPtr pScreen) -{ - rrScrPriv(pScreen); - RROutputPtr output; - int i, j; - - if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) - return pScrPriv->primaryOutput; - - for (i = 0; i < pScrPriv->numCrtcs; i++) - { - RRCrtcPtr crtc = pScrPriv->crtcs[i]; - for (j = 0; j < pScrPriv->numOutputs; j++) - { - output = pScrPriv->outputs[j]; - if (output->crtc == crtc) - return output; - } - } - return NULL; -} - -CARD16 -RRVerticalRefresh (xRRModeInfo *mode) -{ - CARD32 refresh; - CARD32 dots = mode->hTotal * mode->vTotal; - if (!dots) - return 0; - refresh = (mode->dotClock + dots/2) / dots; - if (refresh > 0xffff) - refresh = 0xffff; - return (CARD16) refresh; -} - -static int -ProcRRDispatch (ClientPtr client) -{ - REQUEST(xReq); - if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data]) - return BadRequest; - return (*ProcRandrVector[stuff->data]) (client); -} - -static int -SProcRRDispatch (ClientPtr client) -{ - REQUEST(xReq); - if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data]) - return BadRequest; - return (*SProcRandrVector[stuff->data]) (client); -} - +/* + * Copyright © 2000 Compaq Computer Corporation + * Copyright © 2002 Hewlett-Packard Company + * Copyright © 2006 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + * + * Author: Jim Gettys, Hewlett-Packard Company, Inc. + * Keith Packard, Intel Corporation + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "randrstr.h" + +/* From render.h */ +#ifndef SubPixelUnknown +#define SubPixelUnknown 0 +#endif + +#define RR_VALIDATE +static int RRNScreens; + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +static int ProcRRDispatch (ClientPtr pClient); +static int SProcRRDispatch (ClientPtr pClient); + +int RREventBase; +int RRErrorBase; +RESTYPE RRClientType, RREventType; /* resource types for event masks */ +static int RRClientPrivateKeyIndex; +DevPrivateKey RRClientPrivateKey = &RRClientPrivateKeyIndex; + +static int rrPrivKeyIndex; +DevPrivateKey rrPrivKey = &rrPrivKeyIndex; + +static void +RRClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + rrClientPriv(pClient); + RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1); + int i; + + pRRClient->major_version = 0; + pRRClient->minor_version = 0; + for (i = 0; i < screenInfo.numScreens; i++) + { + ScreenPtr pScreen = screenInfo.screens[i]; + rrScrPriv(pScreen); + + if (pScrPriv) + { + pTimes[i].setTime = pScrPriv->lastSetTime; + pTimes[i].configTime = pScrPriv->lastConfigTime; + } + } +} + +static Bool +RRCloseScreen (int i, ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + int j; + + unwrap (pScrPriv, pScreen, CloseScreen); + for (j = pScrPriv->numCrtcs - 1; j >= 0; j--) + RRCrtcDestroy (pScrPriv->crtcs[j]); + for (j = pScrPriv->numOutputs - 1; j >= 0; j--) + RROutputDestroy (pScrPriv->outputs[j]); + + free(pScrPriv->crtcs); + free(pScrPriv->outputs); + free(pScrPriv); + RRNScreens -= 1; /* ok, one fewer screen with RandR running */ + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from, + xRRScreenChangeNotifyEvent *to) +{ + to->type = from->type; + to->rotation = from->rotation; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->configTimestamp, to->configTimestamp); + cpswapl(from->root, to->root); + cpswapl(from->window, to->window); + cpswaps(from->sizeID, to->sizeID); + cpswaps(from->subpixelOrder, to->subpixelOrder); + cpswaps(from->widthInPixels, to->widthInPixels); + cpswaps(from->heightInPixels, to->heightInPixels); + cpswaps(from->widthInMillimeters, to->widthInMillimeters); + cpswaps(from->heightInMillimeters, to->heightInMillimeters); +} + +static void +SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent *from, + xRRCrtcChangeNotifyEvent *to) +{ + to->type = from->type; + to->subCode = from->subCode; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->window, to->window); + cpswapl(from->crtc, to->crtc); + cpswapl(from->mode, to->mode); + cpswaps(from->rotation, to->rotation); + /* pad1 */ + cpswaps(from->x, to->x); + cpswaps(from->y, to->y); + cpswaps(from->width, to->width); + cpswaps(from->height, to->height); +} + +static void +SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent *from, + xRROutputChangeNotifyEvent *to) +{ + to->type = from->type; + to->subCode = from->subCode; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->configTimestamp, to->configTimestamp); + cpswapl(from->window, to->window); + cpswapl(from->output, to->output); + cpswapl(from->crtc, to->crtc); + cpswapl(from->mode, to->mode); + cpswaps(from->rotation, to->rotation); + to->connection = from->connection; + to->subpixelOrder = from->subpixelOrder; +} + +static void +SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent *from, + xRROutputPropertyNotifyEvent *to) +{ + to->type = from->type; + to->subCode = from->subCode; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->window, to->window); + cpswapl(from->output, to->output); + cpswapl(from->atom, to->atom); + cpswapl(from->timestamp, to->timestamp); + to->state = from->state; + /* pad1 */ + /* pad2 */ + /* pad3 */ + /* pad4 */ +} + +static void +SRRNotifyEvent (xEvent *from, + xEvent *to) +{ + switch (from->u.u.detail) { + case RRNotify_CrtcChange: + SRRCrtcChangeNotifyEvent ((xRRCrtcChangeNotifyEvent *) from, + (xRRCrtcChangeNotifyEvent *) to); + break; + case RRNotify_OutputChange: + SRROutputChangeNotifyEvent ((xRROutputChangeNotifyEvent *) from, + (xRROutputChangeNotifyEvent *) to); + break; + case RRNotify_OutputProperty: + SRROutputPropertyNotifyEvent ((xRROutputPropertyNotifyEvent *) from, + (xRROutputPropertyNotifyEvent *) to); + break; + default: + break; + } +} + +static int RRGeneration; + +Bool RRInit (void) +{ + if (RRGeneration != serverGeneration) + { + if (!RRModeInit ()) + return FALSE; + if (!RRCrtcInit ()) + return FALSE; + if (!RROutputInit ()) + return FALSE; + RRGeneration = serverGeneration; + } + return TRUE; +} + +Bool RRScreenInit(ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (!RRInit ()) + return FALSE; + + pScrPriv = (rrScrPrivPtr) calloc(1, sizeof (rrScrPrivRec)); + if (!pScrPriv) + return FALSE; + + SetRRScreen(pScreen, pScrPriv); + + /* + * Calling function best set these function vectors + */ + pScrPriv->rrGetInfo = 0; + pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width; + pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height; + + pScrPriv->width = pScreen->width; + pScrPriv->height = pScreen->height; + pScrPriv->mmWidth = pScreen->mmWidth; + pScrPriv->mmHeight = pScreen->mmHeight; +#if RANDR_12_INTERFACE + pScrPriv->rrScreenSetSize = NULL; + pScrPriv->rrCrtcSet = NULL; + pScrPriv->rrCrtcSetGamma = NULL; +#endif +#if RANDR_10_INTERFACE + pScrPriv->rrSetConfig = 0; + pScrPriv->rotations = RR_Rotate_0; + pScrPriv->reqWidth = pScreen->width; + pScrPriv->reqHeight = pScreen->height; + pScrPriv->nSizes = 0; + pScrPriv->pSizes = NULL; + pScrPriv->rotation = RR_Rotate_0; + pScrPriv->rate = 0; + pScrPriv->size = 0; +#endif + + /* + * This value doesn't really matter -- any client must call + * GetScreenInfo before reading it which will automatically update + * the time + */ + pScrPriv->lastSetTime = currentTime; + pScrPriv->lastConfigTime = currentTime; + + wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen); + + pScrPriv->numOutputs = 0; + pScrPriv->outputs = NULL; + pScrPriv->numCrtcs = 0; + pScrPriv->crtcs = NULL; + + RRNScreens += 1; /* keep count of screens that implement randr */ + return TRUE; +} + +/*ARGSUSED*/ +static int +RRFreeClient (pointer data, XID id) +{ + RREventPtr pRREvent; + WindowPtr pWin; + RREventPtr *pHead, pCur, pPrev; + + pRREvent = (RREventPtr) data; + pWin = pRREvent->window; + dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, + RREventType, serverClient, DixDestroyAccess); + if (pHead) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next) + pPrev = pCur; + if (pCur) + { + if (pPrev) + pPrev->next = pRREvent->next; + else + *pHead = pRREvent->next; + } + } + free((pointer) pRREvent); + return 1; +} + +/*ARGSUSED*/ +static int +RRFreeEvents (pointer data, XID id) +{ + RREventPtr *pHead, pCur, pNext; + + pHead = (RREventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource (pCur->clientResource, RRClientType); + free((pointer) pCur); + } + free((pointer) pHead); + return 1; +} + +void +RRExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (RRNScreens == 0) return; + + if (!dixRequestPrivate(RRClientPrivateKey, + sizeof (RRClientRec) + + screenInfo.numScreens * sizeof (RRTimesRec))) + return; + if (!AddCallback (&ClientStateCallback, RRClientCallback, 0)) + return; + + RRClientType = CreateNewResourceType(RRFreeClient, "RandRClient"); + if (!RRClientType) + return; + RREventType = CreateNewResourceType(RRFreeEvents, "RandREvent"); + if (!RREventType) + return; + extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors, + ProcRRDispatch, SProcRRDispatch, + NULL, StandardMinorOpcode); + if (!extEntry) + return; + RRErrorBase = extEntry->errorBase; + RREventBase = extEntry->eventBase; + EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) + SRRScreenChangeNotifyEvent; + EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr) + SRRNotifyEvent; +#ifdef PANORAMIX + RRXineramaExtensionInit(); +#endif +} + +static int +TellChanged (WindowPtr pWin, pointer value) +{ + RREventPtr *pHead, pRREvent; + ClientPtr client; + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv(pScreen); + int i; + + dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, + RREventType, serverClient, DixReadAccess); + if (!pHead) + return WT_WALKCHILDREN; + + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + { + client = pRREvent->client; + if (client == serverClient || client->clientGone) + continue; + + if (pRREvent->mask & RRScreenChangeNotifyMask) + RRDeliverScreenEvent (client, pWin, pScreen); + + if (pRREvent->mask & RRCrtcChangeNotifyMask) + { + for (i = 0; i < pScrPriv->numCrtcs; i++) + { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + if (crtc->changed) + RRDeliverCrtcEvent (client, pWin, crtc); + } + } + + if (pRREvent->mask & RROutputChangeNotifyMask) + { + for (i = 0; i < pScrPriv->numOutputs; i++) + { + RROutputPtr output = pScrPriv->outputs[i]; + if (output->changed) + RRDeliverOutputEvent (client, pWin, output); + } + } + } + return WT_WALKCHILDREN; +} + +/* + * Something changed; send events and adjust pointer position + */ +void +RRTellChanged (ScreenPtr pScreen) +{ + rrScrPriv (pScreen); + int i; + + if (pScrPriv->changed) + { + UpdateCurrentTime (); + if (pScrPriv->configChanged) + { + pScrPriv->lastConfigTime = currentTime; + pScrPriv->configChanged = FALSE; + } + pScrPriv->changed = FALSE; + WalkTree (pScreen, TellChanged, (pointer) pScreen); + for (i = 0; i < pScrPriv->numOutputs; i++) + pScrPriv->outputs[i]->changed = FALSE; + for (i = 0; i < pScrPriv->numCrtcs; i++) + pScrPriv->crtcs[i]->changed = FALSE; + if (pScrPriv->layoutChanged) + { + pScrPriv->layoutChanged = FALSE; + RRPointerScreenConfigured (pScreen); + RRSendConfigNotify (pScreen); + } + } +} + +/* + * Return the first output which is connected to an active CRTC + * Used in emulating 1.0 behaviour + */ +RROutputPtr +RRFirstOutput (ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + RROutputPtr output; + int i, j; + + if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) + return pScrPriv->primaryOutput; + + for (i = 0; i < pScrPriv->numCrtcs; i++) + { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + for (j = 0; j < pScrPriv->numOutputs; j++) + { + output = pScrPriv->outputs[j]; + if (output->crtc == crtc) + return output; + } + } + return NULL; +} + +CARD16 +RRVerticalRefresh (xRRModeInfo *mode) +{ + CARD32 refresh; + CARD32 dots = mode->hTotal * mode->vTotal; + if (!dots) + return 0; + refresh = (mode->dotClock + dots/2) / dots; + if (refresh > 0xffff) + refresh = 0xffff; + return (CARD16) refresh; +} + +static int +ProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data]) + return BadRequest; + return (*ProcRandrVector[stuff->data]) (client); +} + +static int +SProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data]) + return BadRequest; + return (*SProcRandrVector[stuff->data]) (client); +} + diff --git a/xorg-server/randr/rrcrtc.c b/xorg-server/randr/rrcrtc.c index 526354611..d22ad984b 100644 --- a/xorg-server/randr/rrcrtc.c +++ b/xorg-server/randr/rrcrtc.c @@ -1,1387 +1,1387 @@ -/* - * Copyright © 2006 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include "randrstr.h" -#include "swaprep.h" - -RESTYPE RRCrtcType; - -/* - * Notify the CRTC of some change - */ -void -RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged) -{ - ScreenPtr pScreen = crtc->pScreen; - - crtc->changed = TRUE; - if (pScreen) - { - rrScrPriv(pScreen); - - pScrPriv->changed = TRUE; - /* - * Send ConfigureNotify on any layout change - */ - if (layoutChanged) - pScrPriv->layoutChanged = TRUE; - } -} - -/* - * Create a CRTC - */ -RRCrtcPtr -RRCrtcCreate (ScreenPtr pScreen, void *devPrivate) -{ - RRCrtcPtr crtc; - RRCrtcPtr *crtcs; - rrScrPrivPtr pScrPriv; - - if (!RRInit()) - return NULL; - - pScrPriv = rrGetScrPriv(pScreen); - - /* make space for the crtc pointer */ - if (pScrPriv->numCrtcs) - crtcs = xrealloc (pScrPriv->crtcs, - (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr)); - else - crtcs = xalloc (sizeof (RRCrtcPtr)); - if (!crtcs) - return FALSE; - pScrPriv->crtcs = crtcs; - - crtc = xcalloc (1, sizeof (RRCrtcRec)); - if (!crtc) - return NULL; - crtc->id = FakeClientID (0); - crtc->pScreen = pScreen; - crtc->mode = NULL; - crtc->x = 0; - crtc->y = 0; - crtc->rotation = RR_Rotate_0; - crtc->rotations = RR_Rotate_0; - crtc->outputs = NULL; - crtc->numOutputs = 0; - crtc->gammaSize = 0; - crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL; - crtc->changed = FALSE; - crtc->devPrivate = devPrivate; - RRTransformInit (&crtc->client_pending_transform); - RRTransformInit (&crtc->client_current_transform); - pixman_transform_init_identity (&crtc->transform); - pixman_f_transform_init_identity (&crtc->f_transform); - pixman_f_transform_init_identity (&crtc->f_inverse); - - if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc)) - return NULL; - - /* attach the screen and crtc together */ - crtc->pScreen = pScreen; - pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc; - - return crtc; -} - -/* - * Set the allowed rotations on a CRTC - */ -void -RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations) -{ - crtc->rotations = rotations; -} - -/* - * Set whether transforms are allowed on a CRTC - */ -void -RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms) -{ - crtc->transforms = transforms; -} - -/* - * Notify the extension that the Crtc has been reconfigured, - * the driver calls this whenever it has updated the mode - */ -Bool -RRCrtcNotify (RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - RRTransformPtr transform, - int numOutputs, - RROutputPtr *outputs) -{ - int i, j; - - /* - * Check to see if any of the new outputs were - * not in the old list and mark them as changed - */ - for (i = 0; i < numOutputs; i++) - { - for (j = 0; j < crtc->numOutputs; j++) - if (outputs[i] == crtc->outputs[j]) - break; - if (j == crtc->numOutputs) - { - outputs[i]->crtc = crtc; - RROutputChanged (outputs[i], FALSE); - RRCrtcChanged (crtc, FALSE); - } - } - /* - * Check to see if any of the old outputs are - * not in the new list and mark them as changed - */ - for (j = 0; j < crtc->numOutputs; j++) - { - for (i = 0; i < numOutputs; i++) - if (outputs[i] == crtc->outputs[j]) - break; - if (i == numOutputs) - { - if (crtc->outputs[j]->crtc == crtc) - crtc->outputs[j]->crtc = NULL; - RROutputChanged (crtc->outputs[j], FALSE); - RRCrtcChanged (crtc, FALSE); - } - } - /* - * Reallocate the crtc output array if necessary - */ - if (numOutputs != crtc->numOutputs) - { - RROutputPtr *newoutputs; - - if (numOutputs) - { - if (crtc->numOutputs) - newoutputs = xrealloc (crtc->outputs, - numOutputs * sizeof (RROutputPtr)); - else - newoutputs = xalloc (numOutputs * sizeof (RROutputPtr)); - if (!newoutputs) - return FALSE; - } - else - { - if (crtc->outputs) - xfree (crtc->outputs); - newoutputs = NULL; - } - crtc->outputs = newoutputs; - crtc->numOutputs = numOutputs; - } - /* - * Copy the new list of outputs into the crtc - */ - memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)); - /* - * Update remaining crtc fields - */ - if (mode != crtc->mode) - { - if (crtc->mode) - RRModeDestroy (crtc->mode); - crtc->mode = mode; - if (mode != NULL) - mode->refcnt++; - RRCrtcChanged (crtc, TRUE); - } - if (x != crtc->x) - { - crtc->x = x; - RRCrtcChanged (crtc, TRUE); - } - if (y != crtc->y) - { - crtc->y = y; - RRCrtcChanged (crtc, TRUE); - } - if (rotation != crtc->rotation) - { - crtc->rotation = rotation; - RRCrtcChanged (crtc, TRUE); - } - if (!RRTransformEqual (transform, &crtc->client_current_transform)) { - RRTransformCopy (&crtc->client_current_transform, transform); - RRCrtcChanged (crtc, TRUE); - } - if (crtc->changed && mode) - { - RRTransformCompute (x, y, - mode->mode.width, mode->mode.height, - rotation, - &crtc->client_current_transform, - &crtc->transform, &crtc->f_transform, - &crtc->f_inverse); - } - return TRUE; -} - -void -RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - rrScrPriv (pScreen); - xRRCrtcChangeNotifyEvent ce; - RRModePtr mode = crtc->mode; - - ce.type = RRNotify + RREventBase; - ce.subCode = RRNotify_CrtcChange; - ce.sequenceNumber = client->sequence; - ce.timestamp = pScrPriv->lastSetTime.milliseconds; - ce.window = pWin->drawable.id; - ce.crtc = crtc->id; - ce.rotation = crtc->rotation; - if (mode) - { - ce.mode = mode->mode.id; - ce.x = crtc->x; - ce.y = crtc->y; - ce.width = mode->mode.width; - ce.height = mode->mode.height; - } - else - { - ce.mode = None; - ce.x = 0; - ce.y = 0; - ce.width = 0; - ce.height = 0; - } - WriteEventsToClient (client, 1, (xEvent *) &ce); -} - -static Bool -RRCrtcPendingProperties (RRCrtcPtr crtc) -{ - ScreenPtr pScreen = crtc->pScreen; - rrScrPriv(pScreen); - int o; - - for (o = 0; o < pScrPriv->numOutputs; o++) - { - RROutputPtr output = pScrPriv->outputs[o]; - if (output->crtc == crtc && output->pendingProperties) - return TRUE; - } - return FALSE; -} - -/* - * Request that the Crtc be reconfigured - */ -Bool -RRCrtcSet (RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - int numOutputs, - RROutputPtr *outputs) -{ - ScreenPtr pScreen = crtc->pScreen; - Bool ret = FALSE; - rrScrPriv(pScreen); - - /* See if nothing changed */ - if (crtc->mode == mode && - crtc->x == x && - crtc->y == y && - crtc->rotation == rotation && - crtc->numOutputs == numOutputs && - !memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) && - !RRCrtcPendingProperties (crtc) && - !RRCrtcPendingTransform (crtc)) - { - ret = TRUE; - } - else - { -#if RANDR_12_INTERFACE - if (pScrPriv->rrCrtcSet) - { - ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, - rotation, numOutputs, outputs); - } - else -#endif - { -#if RANDR_10_INTERFACE - if (pScrPriv->rrSetConfig) - { - RRScreenSize size; - RRScreenRate rate; - - if (!mode) - { - RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL); - ret = TRUE; - } - else - { - size.width = mode->mode.width; - size.height = mode->mode.height; - if (outputs[0]->mmWidth && outputs[0]->mmHeight) - { - size.mmWidth = outputs[0]->mmWidth; - size.mmHeight = outputs[0]->mmHeight; - } - else - { - size.mmWidth = pScreen->mmWidth; - size.mmHeight = pScreen->mmHeight; - } - size.nRates = 1; - rate.rate = RRVerticalRefresh (&mode->mode); - size.pRates = &rate; - ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size); - /* - * Old 1.0 interface tied screen size to mode size - */ - if (ret) - { - RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs); - RRScreenSizeNotify (pScreen); - } - } - } -#endif - } - if (ret) - { - int o; - RRTellChanged (pScreen); - - for (o = 0; o < numOutputs; o++) - RRPostPendingProperties (outputs[o]); - } - } - return ret; -} - -/* - * Return crtc transform - */ -RRTransformPtr -RRCrtcGetTransform (RRCrtcPtr crtc) -{ - RRTransformPtr transform = &crtc->client_pending_transform; - - if (pixman_transform_is_identity (&transform->transform)) - return NULL; - return transform; -} - -/* - * Check whether the pending and current transforms are the same - */ -Bool -RRCrtcPendingTransform (RRCrtcPtr crtc) -{ - return memcmp (&crtc->client_current_transform.transform, - &crtc->client_pending_transform.transform, - sizeof (PictTransform)) != 0; -} - -/* - * Destroy a Crtc at shutdown - */ -void -RRCrtcDestroy (RRCrtcPtr crtc) -{ - FreeResource (crtc->id, 0); -} - -static int -RRCrtcDestroyResource (pointer value, XID pid) -{ - RRCrtcPtr crtc = (RRCrtcPtr) value; - ScreenPtr pScreen = crtc->pScreen; - - if (pScreen) - { - rrScrPriv(pScreen); - int i; - - for (i = 0; i < pScrPriv->numCrtcs; i++) - { - if (pScrPriv->crtcs[i] == crtc) - { - memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1, - (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr)); - --pScrPriv->numCrtcs; - break; - } - } - } - if (crtc->gammaRed) - xfree (crtc->gammaRed); - if (crtc->mode) - RRModeDestroy (crtc->mode); - xfree (crtc); - return 1; -} - -/* - * Request that the Crtc gamma be changed - */ - -Bool -RRCrtcGammaSet (RRCrtcPtr crtc, - CARD16 *red, - CARD16 *green, - CARD16 *blue) -{ - Bool ret = TRUE; -#if RANDR_12_INTERFACE - ScreenPtr pScreen = crtc->pScreen; -#endif - - memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16)); - memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16)); - memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16)); -#if RANDR_12_INTERFACE - if (pScreen) - { - rrScrPriv(pScreen); - if (pScrPriv->rrCrtcSetGamma) - ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc); - } -#endif - return ret; -} - -/* - * Request current gamma back from the DDX (if possible). - * This includes gamma size. - */ -Bool -RRCrtcGammaGet(RRCrtcPtr crtc) -{ - Bool ret = TRUE; -#if RANDR_12_INTERFACE - ScreenPtr pScreen = crtc->pScreen; -#endif - -#if RANDR_12_INTERFACE - if (pScreen) - { - rrScrPriv(pScreen); - if (pScrPriv->rrCrtcGetGamma) - ret = (*pScrPriv->rrCrtcGetGamma) (pScreen, crtc); - } -#endif - return ret; -} - -/* - * Notify the extension that the Crtc gamma has been changed - * The driver calls this whenever it has changed the gamma values - * in the RRCrtcRec - */ - -Bool -RRCrtcGammaNotify (RRCrtcPtr crtc) -{ - return TRUE; /* not much going on here */ -} - -static void -RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform, - int *width, int *height) -{ - BoxRec box; - - if (mode == NULL) { - *width = 0; - *height = 0; - return; - } - - box.x1 = 0; - box.y1 = 0; - box.x2 = mode->mode.width; - box.y2 = mode->mode.height; - - pixman_transform_bounds (transform, &box); - *width = box.x2 - box.x1; - *height = box.y2 - box.y1; -} - -/** - * Returns the width/height that the crtc scans out from the framebuffer - */ -void -RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height) -{ - RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height); -} - -/* - * Set the size of the gamma table at server startup time - */ - -Bool -RRCrtcGammaSetSize (RRCrtcPtr crtc, - int size) -{ - CARD16 *gamma; - - if (size == crtc->gammaSize) - return TRUE; - if (size) - { - gamma = xalloc (size * 3 * sizeof (CARD16)); - if (!gamma) - return FALSE; - } - else - gamma = NULL; - if (crtc->gammaRed) - xfree (crtc->gammaRed); - crtc->gammaRed = gamma; - crtc->gammaGreen = gamma + size; - crtc->gammaBlue = gamma + size*2; - crtc->gammaSize = size; - return TRUE; -} - -/* - * Set the pending CRTC transformation - */ - -int -RRCrtcTransformSet (RRCrtcPtr crtc, - PictTransformPtr transform, - struct pixman_f_transform *f_transform, - struct pixman_f_transform *f_inverse, - char *filter_name, - int filter_len, - xFixed *params, - int nparams) -{ - PictFilterPtr filter = NULL; - int width = 0, height = 0; - - if (!crtc->transforms) - return BadValue; - - if (filter_len) - { - filter = PictureFindFilter (crtc->pScreen, - filter_name, - filter_len); - if (!filter) - return BadName; - if (filter->ValidateParams) - { - if (!filter->ValidateParams (crtc->pScreen, filter->id, - params, nparams, &width, &height)) - return BadMatch; - } - else { - width = filter->width; - height = filter->height; - } - } - else - { - if (nparams) - return BadMatch; - } - if (!RRTransformSetFilter (&crtc->client_pending_transform, - filter, params, nparams, width, height)) - return BadAlloc; - - crtc->client_pending_transform.transform = *transform; - crtc->client_pending_transform.f_transform = *f_transform; - crtc->client_pending_transform.f_inverse = *f_inverse; - return Success; -} - -/* - * Initialize crtc type - */ -Bool -RRCrtcInit (void) -{ - RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource, "CRTC"); - if (!RRCrtcType) - return FALSE; - return TRUE; -} - -int -ProcRRGetCrtcInfo (ClientPtr client) -{ - REQUEST(xRRGetCrtcInfoReq); - xRRGetCrtcInfoReply rep; - RRCrtcPtr crtc; - CARD8 *extra; - unsigned long extraLen; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - RRModePtr mode; - RROutput *outputs; - RROutput *possible; - int i, j, k, n; - int width, height; - BoxRec panned_area; - - REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* All crtcs must be associated with screens before client - * requests are processed - */ - pScreen = crtc->pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - mode = crtc->mode; - - rep.type = X_Reply; - rep.status = RRSetConfigSuccess; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.timestamp = pScrPriv->lastSetTime.milliseconds; - if (pScrPriv->rrGetPanning && - pScrPriv->rrGetPanning (pScreen, crtc, &panned_area, NULL, NULL) && - (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1)) - { - rep.x = panned_area.x1; - rep.y = panned_area.y1; - rep.width = panned_area.x2 - panned_area.x1; - rep.height = panned_area.y2 - panned_area.y1; - } - else - { - RRCrtcGetScanoutSize (crtc, &width, &height); - rep.x = crtc->x; - rep.y = crtc->y; - rep.width = width; - rep.height = height; - } - rep.mode = mode ? mode->mode.id : 0; - rep.rotation = crtc->rotation; - rep.rotations = crtc->rotations; - rep.nOutput = crtc->numOutputs; - k = 0; - for (i = 0; i < pScrPriv->numOutputs; i++) - for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) - if (pScrPriv->outputs[i]->crtcs[j] == crtc) - k++; - rep.nPossibleOutput = k; - - rep.length = rep.nOutput + rep.nPossibleOutput; - - extraLen = rep.length << 2; - if (extraLen) - { - extra = xalloc (extraLen); - if (!extra) - return BadAlloc; - } - else - extra = NULL; - - outputs = (RROutput *) extra; - possible = (RROutput *) (outputs + rep.nOutput); - - for (i = 0; i < crtc->numOutputs; i++) - { - outputs[i] = crtc->outputs[i]->id; - if (client->swapped) - swapl (&outputs[i], n); - } - k = 0; - for (i = 0; i < pScrPriv->numOutputs; i++) - for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) - if (pScrPriv->outputs[i]->crtcs[j] == crtc) - { - possible[k] = pScrPriv->outputs[i]->id; - if (client->swapped) - swapl (&possible[k], n); - k++; - } - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.timestamp, n); - swaps(&rep.x, n); - swaps(&rep.y, n); - swaps(&rep.width, n); - swaps(&rep.height, n); - swapl(&rep.mode, n); - swaps(&rep.rotation, n); - swaps(&rep.rotations, n); - swaps(&rep.nOutput, n); - swaps(&rep.nPossibleOutput, n); - } - WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep); - if (extraLen) - { - WriteToClient (client, extraLen, (char *) extra); - xfree (extra); - } - - return client->noClientException; -} - -int -ProcRRSetCrtcConfig (ClientPtr client) -{ - REQUEST(xRRSetCrtcConfigReq); - xRRSetCrtcConfigReply rep; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - RRCrtcPtr crtc; - RRModePtr mode; - int numOutputs; - RROutputPtr *outputs = NULL; - RROutput *outputIds; - TimeStamp configTime; - TimeStamp time; - Rotation rotation; - int rc, i, j; - - REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq); - numOutputs = (stuff->length - bytes_to_int32(SIZEOF (xRRSetCrtcConfigReq))); - - VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess); - - if (stuff->mode == None) - { - mode = NULL; - if (numOutputs > 0) - return BadMatch; - } - else - { - VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess); - if (numOutputs == 0) - return BadMatch; - } - if (numOutputs) - { - outputs = xalloc (numOutputs * sizeof (RROutputPtr)); - if (!outputs) - return BadAlloc; - } - else - outputs = NULL; - - outputIds = (RROutput *) (stuff + 1); - for (i = 0; i < numOutputs; i++) - { - rc = dixLookupResourceByType((pointer *)(outputs + i), outputIds[i], - RROutputType, client, DixSetAttrAccess); - if (rc != Success) - { - if (outputs) - xfree (outputs); - return (rc == BadValue) ? RRErrorBase + BadRROutput : rc; - } - /* validate crtc for this output */ - for (j = 0; j < outputs[i]->numCrtcs; j++) - if (outputs[i]->crtcs[j] == crtc) - break; - if (j == outputs[i]->numCrtcs) - { - if (outputs) - xfree (outputs); - return BadMatch; - } - /* validate mode for this output */ - for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++) - { - RRModePtr m = (j < outputs[i]->numModes ? - outputs[i]->modes[j] : - outputs[i]->userModes[j - outputs[i]->numModes]); - if (m == mode) - break; - } - if (j == outputs[i]->numModes + outputs[i]->numUserModes) - { - if (outputs) - xfree (outputs); - return BadMatch; - } - } - /* validate clones */ - for (i = 0; i < numOutputs; i++) - { - for (j = 0; j < numOutputs; j++) - { - int k; - if (i == j) - continue; - for (k = 0; k < outputs[i]->numClones; k++) - { - if (outputs[i]->clones[k] == outputs[j]) - break; - } - if (k == outputs[i]->numClones) - { - if (outputs) - xfree (outputs); - return BadMatch; - } - } - } - - pScreen = crtc->pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - time = ClientTimeToServerTime(stuff->timestamp); - configTime = ClientTimeToServerTime(stuff->configTimestamp); - - if (!pScrPriv) - { - time = currentTime; - rep.status = RRSetConfigFailed; - goto sendReply; - } - -#if 0 - /* - * if the client's config timestamp is not the same as the last config - * timestamp, then the config information isn't up-to-date and - * can't even be validated - */ - if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0) - { - rep.status = RRSetConfigInvalidConfigTime; - goto sendReply; - } -#endif - - /* - * Validate requested rotation - */ - rotation = (Rotation) stuff->rotation; - - /* test the rotation bits only! */ - switch (rotation & 0xf) { - case RR_Rotate_0: - case RR_Rotate_90: - case RR_Rotate_180: - case RR_Rotate_270: - break; - default: - /* - * Invalid rotation - */ - client->errorValue = stuff->rotation; - if (outputs) - xfree (outputs); - return BadValue; - } - - if (mode) - { - if ((~crtc->rotations) & rotation) - { - /* - * requested rotation or reflection not supported by screen - */ - client->errorValue = stuff->rotation; - if (outputs) - xfree (outputs); - return BadMatch; - } - -#ifdef RANDR_12_INTERFACE - /* - * Check screen size bounds if the DDX provides a 1.2 interface - * for setting screen size. Else, assume the CrtcSet sets - * the size along with the mode. If the driver supports transforms, - * then it must allow crtcs to display a subset of the screen, so - * only do this check for drivers without transform support. - */ - if (pScrPriv->rrScreenSetSize && !crtc->transforms) - { - int source_width; - int source_height; - PictTransform transform; - struct pixman_f_transform f_transform, f_inverse; - - RRTransformCompute (stuff->x, stuff->y, - mode->mode.width, mode->mode.height, - rotation, - &crtc->client_pending_transform, - &transform, &f_transform, &f_inverse); - - RRModeGetScanoutSize (mode, &transform, &source_width, &source_height); - if (stuff->x + source_width > pScreen->width) - { - client->errorValue = stuff->x; - if (outputs) - xfree (outputs); - return BadValue; - } - - if (stuff->y + source_height > pScreen->height) - { - client->errorValue = stuff->y; - if (outputs) - xfree (outputs); - return BadValue; - } - } -#endif - } - - /* - * Make sure the requested set-time is not older than - * the last set-time - */ - if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) - { - rep.status = RRSetConfigInvalidTime; - goto sendReply; - } - - if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y, - rotation, numOutputs, outputs)) - { - rep.status = RRSetConfigFailed; - goto sendReply; - } - rep.status = RRSetConfigSuccess; - pScrPriv->lastSetTime = time; - -sendReply: - if (outputs) - xfree (outputs); - - rep.type = X_Reply; - /* rep.status has already been filled in */ - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; - - if (client->swapped) - { - int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.newTimestamp, n); - } - WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep); - - return client->noClientException; -} - -int -ProcRRGetPanning (ClientPtr client) -{ - REQUEST(xRRGetPanningReq); - xRRGetPanningReply rep; - RRCrtcPtr crtc; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - BoxRec total; - BoxRec tracking; - INT16 border[4]; - int n; - - REQUEST_SIZE_MATCH(xRRGetPanningReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* All crtcs must be associated with screens before client - * requests are processed - */ - pScreen = crtc->pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - if (!pScrPriv) - return RRErrorBase + BadRRCrtc; - - memset(&rep, 0, sizeof(rep)); - rep.type = X_Reply; - rep.status = RRSetConfigSuccess; - rep.sequenceNumber = client->sequence; - rep.length = 1; - rep.timestamp = pScrPriv->lastSetTime.milliseconds; - - if (pScrPriv->rrGetPanning && - pScrPriv->rrGetPanning (pScreen, crtc, &total, &tracking, border)) { - rep.left = total.x1; - rep.top = total.y1; - rep.width = total.x2 - total.x1; - rep.height = total.y2 - total.y1; - rep.track_left = tracking.x1; - rep.track_top = tracking.y1; - rep.track_width = tracking.x2 - tracking.x1; - rep.track_height = tracking.y2 - tracking.y1; - rep.border_left = border[0]; - rep.border_top = border[1]; - rep.border_right = border[2]; - rep.border_bottom = border[3]; - } - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.timestamp, n); - swaps(&rep.left, n); - swaps(&rep.top, n); - swaps(&rep.width, n); - swaps(&rep.height, n); - swaps(&rep.track_left, n); - swaps(&rep.track_top, n); - swaps(&rep.track_width, n); - swaps(&rep.track_height, n); - swaps(&rep.border_left, n); - swaps(&rep.border_top, n); - swaps(&rep.border_right, n); - swaps(&rep.border_bottom, n); - } - WriteToClient(client, sizeof(xRRGetPanningReply), (char *)&rep); - return client->noClientException; -} - -int -ProcRRSetPanning (ClientPtr client) -{ - REQUEST(xRRSetPanningReq); - xRRSetPanningReply rep; - RRCrtcPtr crtc; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - TimeStamp time; - BoxRec total; - BoxRec tracking; - INT16 border[4]; - int n; - - REQUEST_SIZE_MATCH(xRRSetPanningReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* All crtcs must be associated with screens before client - * requests are processed - */ - pScreen = crtc->pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - if (!pScrPriv) { - time = currentTime; - rep.status = RRSetConfigFailed; - goto sendReply; - } - - time = ClientTimeToServerTime(stuff->timestamp); - - /* - * Make sure the requested set-time is not older than - * the last set-time - */ - if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) - { - rep.status = RRSetConfigInvalidTime; - goto sendReply; - } - - if (!pScrPriv->rrGetPanning) - return RRErrorBase + BadRRCrtc; - - total.x1 = stuff->left; - total.y1 = stuff->top; - total.x2 = total.x1 + stuff->width; - total.y2 = total.y1 + stuff->height; - tracking.x1 = stuff->track_left; - tracking.y1 = stuff->track_top; - tracking.x2 = tracking.x1 + stuff->track_width; - tracking.y2 = tracking.y1 + stuff->track_height; - border[0] = stuff->border_left; - border[1] = stuff->border_top; - border[2] = stuff->border_right; - border[3] = stuff->border_bottom; - - if (! pScrPriv->rrSetPanning (pScreen, crtc, &total, &tracking, border)) - return BadMatch; - - pScrPriv->lastSetTime = time; - - rep.status = RRSetConfigSuccess; - -sendReply: - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.newTimestamp, n); - } - WriteToClient(client, sizeof(xRRSetPanningReply), (char *)&rep); - return client->noClientException; -} - -int -ProcRRGetCrtcGammaSize (ClientPtr client) -{ - REQUEST(xRRGetCrtcGammaSizeReq); - xRRGetCrtcGammaSizeReply reply; - RRCrtcPtr crtc; - int n; - - REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* Gamma retrieval failed, any better error? */ - if (!RRCrtcGammaGet(crtc)) - return RRErrorBase + BadRRCrtc; - - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = 0; - reply.size = crtc->gammaSize; - if (client->swapped) { - swaps (&reply.sequenceNumber, n); - swapl (&reply.length, n); - swaps (&reply.size, n); - } - WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply); - return client->noClientException; -} - -int -ProcRRGetCrtcGamma (ClientPtr client) -{ - REQUEST(xRRGetCrtcGammaReq); - xRRGetCrtcGammaReply reply; - RRCrtcPtr crtc; - int n; - unsigned long len; - char *extra = NULL; - - REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* Gamma retrieval failed, any better error? */ - if (!RRCrtcGammaGet(crtc)) - return RRErrorBase + BadRRCrtc; - - len = crtc->gammaSize * 3 * 2; - - if (crtc->gammaSize) { - extra = xalloc(len); - if (!extra) - return BadAlloc; - } - - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = bytes_to_int32(len); - reply.size = crtc->gammaSize; - if (client->swapped) { - swaps (&reply.sequenceNumber, n); - swapl (&reply.length, n); - swaps (&reply.size, n); - } - WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply); - if (crtc->gammaSize) - { - memcpy(extra, crtc->gammaRed, len); - client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; - WriteSwappedDataToClient (client, len, extra); - xfree(extra); - } - return client->noClientException; -} - -int -ProcRRSetCrtcGamma (ClientPtr client) -{ - REQUEST(xRRSetCrtcGammaReq); - RRCrtcPtr crtc; - unsigned long len; - CARD16 *red, *green, *blue; - - REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - len = client->req_len - bytes_to_int32(sizeof (xRRSetCrtcGammaReq)); - if (len < (stuff->size * 3 + 1) >> 1) - return BadLength; - - if (stuff->size != crtc->gammaSize) - return BadMatch; - - red = (CARD16 *) (stuff + 1); - green = red + crtc->gammaSize; - blue = green + crtc->gammaSize; - - RRCrtcGammaSet (crtc, red, green, blue); - - return Success; -} - -/* Version 1.3 additions */ - -int -ProcRRSetCrtcTransform (ClientPtr client) -{ - REQUEST(xRRSetCrtcTransformReq); - RRCrtcPtr crtc; - PictTransform transform; - struct pixman_f_transform f_transform, f_inverse; - char *filter; - int nbytes; - xFixed *params; - int nparams; - - REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - PictTransform_from_xRenderTransform (&transform, &stuff->transform); - pixman_f_transform_from_pixman_transform (&f_transform, &transform); - if (!pixman_f_transform_invert (&f_inverse, &f_transform)) - return BadMatch; - - filter = (char *) (stuff + 1); - nbytes = stuff->nbytesFilter; - params = (xFixed *) (filter + pad_to_int32(nbytes)); - nparams = ((xFixed *) stuff + client->req_len) - params; - if (nparams < 0) - return BadLength; - - return RRCrtcTransformSet (crtc, &transform, &f_transform, &f_inverse, - filter, nbytes, params, nparams); -} - - -#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32) - -static int -transform_filter_length (RRTransformPtr transform) -{ - int nbytes, nparams; - - if (transform->filter == NULL) - return 0; - nbytes = strlen (transform->filter->name); - nparams = transform->nparams; - return pad_to_int32(nbytes) + (nparams * sizeof (xFixed)); -} - -static int -transform_filter_encode (ClientPtr client, char *output, - CARD16 *nbytesFilter, - CARD16 *nparamsFilter, - RRTransformPtr transform) -{ - int nbytes, nparams; - int n; - - if (transform->filter == NULL) { - *nbytesFilter = 0; - *nparamsFilter = 0; - return 0; - } - nbytes = strlen (transform->filter->name); - nparams = transform->nparams; - *nbytesFilter = nbytes; - *nparamsFilter = nparams; - memcpy (output, transform->filter->name, nbytes); - while ((nbytes & 3) != 0) - output[nbytes++] = 0; - memcpy (output + nbytes, transform->params, nparams * sizeof (xFixed)); - if (client->swapped) { - swaps (nbytesFilter, n); - swaps (nparamsFilter, n); - SwapLongs ((CARD32 *) (output + nbytes), nparams); - } - nbytes += nparams * sizeof (xFixed); - return nbytes; -} - -static void -transform_encode (ClientPtr client, xRenderTransform *wire, PictTransform *pict) -{ - xRenderTransform_from_PictTransform (wire, pict); - if (client->swapped) - SwapLongs ((CARD32 *) wire, bytes_to_int32(sizeof(xRenderTransform))); -} - -int -ProcRRGetCrtcTransform (ClientPtr client) -{ - REQUEST(xRRGetCrtcTransformReq); - xRRGetCrtcTransformReply *reply; - RRCrtcPtr crtc; - int n, nextra; - RRTransformPtr current, pending; - char *extra; - - REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - pending = &crtc->client_pending_transform; - current = &crtc->client_current_transform; - - nextra = (transform_filter_length (pending) + - transform_filter_length (current)); - - reply = xalloc (sizeof (xRRGetCrtcTransformReply) + nextra); - if (!reply) - return BadAlloc; - - extra = (char *) (reply + 1); - reply->type = X_Reply; - reply->sequenceNumber = client->sequence; - reply->length = bytes_to_int32(CrtcTransformExtra + nextra); - - reply->hasTransforms = crtc->transforms; - - transform_encode (client, &reply->pendingTransform, &pending->transform); - extra += transform_filter_encode (client, extra, - &reply->pendingNbytesFilter, - &reply->pendingNparamsFilter, - pending); - - transform_encode (client, &reply->currentTransform, ¤t->transform); - extra += transform_filter_encode (client, extra, - &reply->currentNbytesFilter, - &reply->currentNparamsFilter, - current); - - if (client->swapped) { - swaps (&reply->sequenceNumber, n); - swapl (&reply->length, n); - } - WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply); - xfree(reply); - return client->noClientException; -} +/* + * Copyright © 2006 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "randrstr.h" +#include "swaprep.h" + +RESTYPE RRCrtcType; + +/* + * Notify the CRTC of some change + */ +void +RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged) +{ + ScreenPtr pScreen = crtc->pScreen; + + crtc->changed = TRUE; + if (pScreen) + { + rrScrPriv(pScreen); + + pScrPriv->changed = TRUE; + /* + * Send ConfigureNotify on any layout change + */ + if (layoutChanged) + pScrPriv->layoutChanged = TRUE; + } +} + +/* + * Create a CRTC + */ +RRCrtcPtr +RRCrtcCreate (ScreenPtr pScreen, void *devPrivate) +{ + RRCrtcPtr crtc; + RRCrtcPtr *crtcs; + rrScrPrivPtr pScrPriv; + + if (!RRInit()) + return NULL; + + pScrPriv = rrGetScrPriv(pScreen); + + /* make space for the crtc pointer */ + if (pScrPriv->numCrtcs) + crtcs = realloc(pScrPriv->crtcs, + (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr)); + else + crtcs = malloc(sizeof (RRCrtcPtr)); + if (!crtcs) + return FALSE; + pScrPriv->crtcs = crtcs; + + crtc = calloc(1, sizeof (RRCrtcRec)); + if (!crtc) + return NULL; + crtc->id = FakeClientID (0); + crtc->pScreen = pScreen; + crtc->mode = NULL; + crtc->x = 0; + crtc->y = 0; + crtc->rotation = RR_Rotate_0; + crtc->rotations = RR_Rotate_0; + crtc->outputs = NULL; + crtc->numOutputs = 0; + crtc->gammaSize = 0; + crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL; + crtc->changed = FALSE; + crtc->devPrivate = devPrivate; + RRTransformInit (&crtc->client_pending_transform); + RRTransformInit (&crtc->client_current_transform); + pixman_transform_init_identity (&crtc->transform); + pixman_f_transform_init_identity (&crtc->f_transform); + pixman_f_transform_init_identity (&crtc->f_inverse); + + if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc)) + return NULL; + + /* attach the screen and crtc together */ + crtc->pScreen = pScreen; + pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc; + + return crtc; +} + +/* + * Set the allowed rotations on a CRTC + */ +void +RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations) +{ + crtc->rotations = rotations; +} + +/* + * Set whether transforms are allowed on a CRTC + */ +void +RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms) +{ + crtc->transforms = transforms; +} + +/* + * Notify the extension that the Crtc has been reconfigured, + * the driver calls this whenever it has updated the mode + */ +Bool +RRCrtcNotify (RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + RRTransformPtr transform, + int numOutputs, + RROutputPtr *outputs) +{ + int i, j; + + /* + * Check to see if any of the new outputs were + * not in the old list and mark them as changed + */ + for (i = 0; i < numOutputs; i++) + { + for (j = 0; j < crtc->numOutputs; j++) + if (outputs[i] == crtc->outputs[j]) + break; + if (j == crtc->numOutputs) + { + outputs[i]->crtc = crtc; + RROutputChanged (outputs[i], FALSE); + RRCrtcChanged (crtc, FALSE); + } + } + /* + * Check to see if any of the old outputs are + * not in the new list and mark them as changed + */ + for (j = 0; j < crtc->numOutputs; j++) + { + for (i = 0; i < numOutputs; i++) + if (outputs[i] == crtc->outputs[j]) + break; + if (i == numOutputs) + { + if (crtc->outputs[j]->crtc == crtc) + crtc->outputs[j]->crtc = NULL; + RROutputChanged (crtc->outputs[j], FALSE); + RRCrtcChanged (crtc, FALSE); + } + } + /* + * Reallocate the crtc output array if necessary + */ + if (numOutputs != crtc->numOutputs) + { + RROutputPtr *newoutputs; + + if (numOutputs) + { + if (crtc->numOutputs) + newoutputs = realloc(crtc->outputs, + numOutputs * sizeof (RROutputPtr)); + else + newoutputs = malloc(numOutputs * sizeof (RROutputPtr)); + if (!newoutputs) + return FALSE; + } + else + { + if (crtc->outputs) + free(crtc->outputs); + newoutputs = NULL; + } + crtc->outputs = newoutputs; + crtc->numOutputs = numOutputs; + } + /* + * Copy the new list of outputs into the crtc + */ + memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)); + /* + * Update remaining crtc fields + */ + if (mode != crtc->mode) + { + if (crtc->mode) + RRModeDestroy (crtc->mode); + crtc->mode = mode; + if (mode != NULL) + mode->refcnt++; + RRCrtcChanged (crtc, TRUE); + } + if (x != crtc->x) + { + crtc->x = x; + RRCrtcChanged (crtc, TRUE); + } + if (y != crtc->y) + { + crtc->y = y; + RRCrtcChanged (crtc, TRUE); + } + if (rotation != crtc->rotation) + { + crtc->rotation = rotation; + RRCrtcChanged (crtc, TRUE); + } + if (!RRTransformEqual (transform, &crtc->client_current_transform)) { + RRTransformCopy (&crtc->client_current_transform, transform); + RRCrtcChanged (crtc, TRUE); + } + if (crtc->changed && mode) + { + RRTransformCompute (x, y, + mode->mode.width, mode->mode.height, + rotation, + &crtc->client_current_transform, + &crtc->transform, &crtc->f_transform, + &crtc->f_inverse); + } + return TRUE; +} + +void +RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv (pScreen); + xRRCrtcChangeNotifyEvent ce; + RRModePtr mode = crtc->mode; + + ce.type = RRNotify + RREventBase; + ce.subCode = RRNotify_CrtcChange; + ce.sequenceNumber = client->sequence; + ce.timestamp = pScrPriv->lastSetTime.milliseconds; + ce.window = pWin->drawable.id; + ce.crtc = crtc->id; + ce.rotation = crtc->rotation; + if (mode) + { + ce.mode = mode->mode.id; + ce.x = crtc->x; + ce.y = crtc->y; + ce.width = mode->mode.width; + ce.height = mode->mode.height; + } + else + { + ce.mode = None; + ce.x = 0; + ce.y = 0; + ce.width = 0; + ce.height = 0; + } + WriteEventsToClient (client, 1, (xEvent *) &ce); +} + +static Bool +RRCrtcPendingProperties (RRCrtcPtr crtc) +{ + ScreenPtr pScreen = crtc->pScreen; + rrScrPriv(pScreen); + int o; + + for (o = 0; o < pScrPriv->numOutputs; o++) + { + RROutputPtr output = pScrPriv->outputs[o]; + if (output->crtc == crtc && output->pendingProperties) + return TRUE; + } + return FALSE; +} + +/* + * Request that the Crtc be reconfigured + */ +Bool +RRCrtcSet (RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + int numOutputs, + RROutputPtr *outputs) +{ + ScreenPtr pScreen = crtc->pScreen; + Bool ret = FALSE; + rrScrPriv(pScreen); + + /* See if nothing changed */ + if (crtc->mode == mode && + crtc->x == x && + crtc->y == y && + crtc->rotation == rotation && + crtc->numOutputs == numOutputs && + !memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) && + !RRCrtcPendingProperties (crtc) && + !RRCrtcPendingTransform (crtc)) + { + ret = TRUE; + } + else + { +#if RANDR_12_INTERFACE + if (pScrPriv->rrCrtcSet) + { + ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, + rotation, numOutputs, outputs); + } + else +#endif + { +#if RANDR_10_INTERFACE + if (pScrPriv->rrSetConfig) + { + RRScreenSize size; + RRScreenRate rate; + + if (!mode) + { + RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL); + ret = TRUE; + } + else + { + size.width = mode->mode.width; + size.height = mode->mode.height; + if (outputs[0]->mmWidth && outputs[0]->mmHeight) + { + size.mmWidth = outputs[0]->mmWidth; + size.mmHeight = outputs[0]->mmHeight; + } + else + { + size.mmWidth = pScreen->mmWidth; + size.mmHeight = pScreen->mmHeight; + } + size.nRates = 1; + rate.rate = RRVerticalRefresh (&mode->mode); + size.pRates = &rate; + ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size); + /* + * Old 1.0 interface tied screen size to mode size + */ + if (ret) + { + RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs); + RRScreenSizeNotify (pScreen); + } + } + } +#endif + } + if (ret) + { + int o; + RRTellChanged (pScreen); + + for (o = 0; o < numOutputs; o++) + RRPostPendingProperties (outputs[o]); + } + } + return ret; +} + +/* + * Return crtc transform + */ +RRTransformPtr +RRCrtcGetTransform (RRCrtcPtr crtc) +{ + RRTransformPtr transform = &crtc->client_pending_transform; + + if (pixman_transform_is_identity (&transform->transform)) + return NULL; + return transform; +} + +/* + * Check whether the pending and current transforms are the same + */ +Bool +RRCrtcPendingTransform (RRCrtcPtr crtc) +{ + return memcmp (&crtc->client_current_transform.transform, + &crtc->client_pending_transform.transform, + sizeof (PictTransform)) != 0; +} + +/* + * Destroy a Crtc at shutdown + */ +void +RRCrtcDestroy (RRCrtcPtr crtc) +{ + FreeResource (crtc->id, 0); +} + +static int +RRCrtcDestroyResource (pointer value, XID pid) +{ + RRCrtcPtr crtc = (RRCrtcPtr) value; + ScreenPtr pScreen = crtc->pScreen; + + if (pScreen) + { + rrScrPriv(pScreen); + int i; + + for (i = 0; i < pScrPriv->numCrtcs; i++) + { + if (pScrPriv->crtcs[i] == crtc) + { + memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1, + (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr)); + --pScrPriv->numCrtcs; + break; + } + } + } + if (crtc->gammaRed) + free(crtc->gammaRed); + if (crtc->mode) + RRModeDestroy (crtc->mode); + free(crtc); + return 1; +} + +/* + * Request that the Crtc gamma be changed + */ + +Bool +RRCrtcGammaSet (RRCrtcPtr crtc, + CARD16 *red, + CARD16 *green, + CARD16 *blue) +{ + Bool ret = TRUE; +#if RANDR_12_INTERFACE + ScreenPtr pScreen = crtc->pScreen; +#endif + + memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16)); + memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16)); + memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16)); +#if RANDR_12_INTERFACE + if (pScreen) + { + rrScrPriv(pScreen); + if (pScrPriv->rrCrtcSetGamma) + ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc); + } +#endif + return ret; +} + +/* + * Request current gamma back from the DDX (if possible). + * This includes gamma size. + */ +Bool +RRCrtcGammaGet(RRCrtcPtr crtc) +{ + Bool ret = TRUE; +#if RANDR_12_INTERFACE + ScreenPtr pScreen = crtc->pScreen; +#endif + +#if RANDR_12_INTERFACE + if (pScreen) + { + rrScrPriv(pScreen); + if (pScrPriv->rrCrtcGetGamma) + ret = (*pScrPriv->rrCrtcGetGamma) (pScreen, crtc); + } +#endif + return ret; +} + +/* + * Notify the extension that the Crtc gamma has been changed + * The driver calls this whenever it has changed the gamma values + * in the RRCrtcRec + */ + +Bool +RRCrtcGammaNotify (RRCrtcPtr crtc) +{ + return TRUE; /* not much going on here */ +} + +static void +RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform, + int *width, int *height) +{ + BoxRec box; + + if (mode == NULL) { + *width = 0; + *height = 0; + return; + } + + box.x1 = 0; + box.y1 = 0; + box.x2 = mode->mode.width; + box.y2 = mode->mode.height; + + pixman_transform_bounds (transform, &box); + *width = box.x2 - box.x1; + *height = box.y2 - box.y1; +} + +/** + * Returns the width/height that the crtc scans out from the framebuffer + */ +void +RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height) +{ + RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height); +} + +/* + * Set the size of the gamma table at server startup time + */ + +Bool +RRCrtcGammaSetSize (RRCrtcPtr crtc, + int size) +{ + CARD16 *gamma; + + if (size == crtc->gammaSize) + return TRUE; + if (size) + { + gamma = malloc(size * 3 * sizeof (CARD16)); + if (!gamma) + return FALSE; + } + else + gamma = NULL; + if (crtc->gammaRed) + free(crtc->gammaRed); + crtc->gammaRed = gamma; + crtc->gammaGreen = gamma + size; + crtc->gammaBlue = gamma + size*2; + crtc->gammaSize = size; + return TRUE; +} + +/* + * Set the pending CRTC transformation + */ + +int +RRCrtcTransformSet (RRCrtcPtr crtc, + PictTransformPtr transform, + struct pixman_f_transform *f_transform, + struct pixman_f_transform *f_inverse, + char *filter_name, + int filter_len, + xFixed *params, + int nparams) +{ + PictFilterPtr filter = NULL; + int width = 0, height = 0; + + if (!crtc->transforms) + return BadValue; + + if (filter_len) + { + filter = PictureFindFilter (crtc->pScreen, + filter_name, + filter_len); + if (!filter) + return BadName; + if (filter->ValidateParams) + { + if (!filter->ValidateParams (crtc->pScreen, filter->id, + params, nparams, &width, &height)) + return BadMatch; + } + else { + width = filter->width; + height = filter->height; + } + } + else + { + if (nparams) + return BadMatch; + } + if (!RRTransformSetFilter (&crtc->client_pending_transform, + filter, params, nparams, width, height)) + return BadAlloc; + + crtc->client_pending_transform.transform = *transform; + crtc->client_pending_transform.f_transform = *f_transform; + crtc->client_pending_transform.f_inverse = *f_inverse; + return Success; +} + +/* + * Initialize crtc type + */ +Bool +RRCrtcInit (void) +{ + RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource, "CRTC"); + if (!RRCrtcType) + return FALSE; + return TRUE; +} + +int +ProcRRGetCrtcInfo (ClientPtr client) +{ + REQUEST(xRRGetCrtcInfoReq); + xRRGetCrtcInfoReply rep; + RRCrtcPtr crtc; + CARD8 *extra; + unsigned long extraLen; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + RRModePtr mode; + RROutput *outputs; + RROutput *possible; + int i, j, k, n; + int width, height; + BoxRec panned_area; + + REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* All crtcs must be associated with screens before client + * requests are processed + */ + pScreen = crtc->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + mode = crtc->mode; + + rep.type = X_Reply; + rep.status = RRSetConfigSuccess; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + if (pScrPriv->rrGetPanning && + pScrPriv->rrGetPanning (pScreen, crtc, &panned_area, NULL, NULL) && + (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1)) + { + rep.x = panned_area.x1; + rep.y = panned_area.y1; + rep.width = panned_area.x2 - panned_area.x1; + rep.height = panned_area.y2 - panned_area.y1; + } + else + { + RRCrtcGetScanoutSize (crtc, &width, &height); + rep.x = crtc->x; + rep.y = crtc->y; + rep.width = width; + rep.height = height; + } + rep.mode = mode ? mode->mode.id : 0; + rep.rotation = crtc->rotation; + rep.rotations = crtc->rotations; + rep.nOutput = crtc->numOutputs; + k = 0; + for (i = 0; i < pScrPriv->numOutputs; i++) + for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) + if (pScrPriv->outputs[i]->crtcs[j] == crtc) + k++; + rep.nPossibleOutput = k; + + rep.length = rep.nOutput + rep.nPossibleOutput; + + extraLen = rep.length << 2; + if (extraLen) + { + extra = malloc(extraLen); + if (!extra) + return BadAlloc; + } + else + extra = NULL; + + outputs = (RROutput *) extra; + possible = (RROutput *) (outputs + rep.nOutput); + + for (i = 0; i < crtc->numOutputs; i++) + { + outputs[i] = crtc->outputs[i]->id; + if (client->swapped) + swapl (&outputs[i], n); + } + k = 0; + for (i = 0; i < pScrPriv->numOutputs; i++) + for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) + if (pScrPriv->outputs[i]->crtcs[j] == crtc) + { + possible[k] = pScrPriv->outputs[i]->id; + if (client->swapped) + swapl (&possible[k], n); + k++; + } + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swaps(&rep.x, n); + swaps(&rep.y, n); + swaps(&rep.width, n); + swaps(&rep.height, n); + swapl(&rep.mode, n); + swaps(&rep.rotation, n); + swaps(&rep.rotations, n); + swaps(&rep.nOutput, n); + swaps(&rep.nPossibleOutput, n); + } + WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep); + if (extraLen) + { + WriteToClient (client, extraLen, (char *) extra); + free(extra); + } + + return Success; +} + +int +ProcRRSetCrtcConfig (ClientPtr client) +{ + REQUEST(xRRSetCrtcConfigReq); + xRRSetCrtcConfigReply rep; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + RRCrtcPtr crtc; + RRModePtr mode; + int numOutputs; + RROutputPtr *outputs = NULL; + RROutput *outputIds; + TimeStamp configTime; + TimeStamp time; + Rotation rotation; + int rc, i, j; + + REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq); + numOutputs = (stuff->length - bytes_to_int32(SIZEOF (xRRSetCrtcConfigReq))); + + VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess); + + if (stuff->mode == None) + { + mode = NULL; + if (numOutputs > 0) + return BadMatch; + } + else + { + VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess); + if (numOutputs == 0) + return BadMatch; + } + if (numOutputs) + { + outputs = malloc(numOutputs * sizeof (RROutputPtr)); + if (!outputs) + return BadAlloc; + } + else + outputs = NULL; + + outputIds = (RROutput *) (stuff + 1); + for (i = 0; i < numOutputs; i++) + { + rc = dixLookupResourceByType((pointer *)(outputs + i), outputIds[i], + RROutputType, client, DixSetAttrAccess); + if (rc != Success) + { + if (outputs) + free(outputs); + return (rc == BadValue) ? RRErrorBase + BadRROutput : rc; + } + /* validate crtc for this output */ + for (j = 0; j < outputs[i]->numCrtcs; j++) + if (outputs[i]->crtcs[j] == crtc) + break; + if (j == outputs[i]->numCrtcs) + { + if (outputs) + free(outputs); + return BadMatch; + } + /* validate mode for this output */ + for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++) + { + RRModePtr m = (j < outputs[i]->numModes ? + outputs[i]->modes[j] : + outputs[i]->userModes[j - outputs[i]->numModes]); + if (m == mode) + break; + } + if (j == outputs[i]->numModes + outputs[i]->numUserModes) + { + if (outputs) + free(outputs); + return BadMatch; + } + } + /* validate clones */ + for (i = 0; i < numOutputs; i++) + { + for (j = 0; j < numOutputs; j++) + { + int k; + if (i == j) + continue; + for (k = 0; k < outputs[i]->numClones; k++) + { + if (outputs[i]->clones[k] == outputs[j]) + break; + } + if (k == outputs[i]->numClones) + { + if (outputs) + free(outputs); + return BadMatch; + } + } + } + + pScreen = crtc->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + time = ClientTimeToServerTime(stuff->timestamp); + configTime = ClientTimeToServerTime(stuff->configTimestamp); + + if (!pScrPriv) + { + time = currentTime; + rep.status = RRSetConfigFailed; + goto sendReply; + } + +#if 0 + /* + * if the client's config timestamp is not the same as the last config + * timestamp, then the config information isn't up-to-date and + * can't even be validated + */ + if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0) + { + rep.status = RRSetConfigInvalidConfigTime; + goto sendReply; + } +#endif + + /* + * Validate requested rotation + */ + rotation = (Rotation) stuff->rotation; + + /* test the rotation bits only! */ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_90: + case RR_Rotate_180: + case RR_Rotate_270: + break; + default: + /* + * Invalid rotation + */ + client->errorValue = stuff->rotation; + if (outputs) + free(outputs); + return BadValue; + } + + if (mode) + { + if ((~crtc->rotations) & rotation) + { + /* + * requested rotation or reflection not supported by screen + */ + client->errorValue = stuff->rotation; + if (outputs) + free(outputs); + return BadMatch; + } + +#ifdef RANDR_12_INTERFACE + /* + * Check screen size bounds if the DDX provides a 1.2 interface + * for setting screen size. Else, assume the CrtcSet sets + * the size along with the mode. If the driver supports transforms, + * then it must allow crtcs to display a subset of the screen, so + * only do this check for drivers without transform support. + */ + if (pScrPriv->rrScreenSetSize && !crtc->transforms) + { + int source_width; + int source_height; + PictTransform transform; + struct pixman_f_transform f_transform, f_inverse; + + RRTransformCompute (stuff->x, stuff->y, + mode->mode.width, mode->mode.height, + rotation, + &crtc->client_pending_transform, + &transform, &f_transform, &f_inverse); + + RRModeGetScanoutSize (mode, &transform, &source_width, &source_height); + if (stuff->x + source_width > pScreen->width) + { + client->errorValue = stuff->x; + if (outputs) + free(outputs); + return BadValue; + } + + if (stuff->y + source_height > pScreen->height) + { + client->errorValue = stuff->y; + if (outputs) + free(outputs); + return BadValue; + } + } +#endif + } + + /* + * Make sure the requested set-time is not older than + * the last set-time + */ + if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) + { + rep.status = RRSetConfigInvalidTime; + goto sendReply; + } + + if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y, + rotation, numOutputs, outputs)) + { + rep.status = RRSetConfigFailed; + goto sendReply; + } + rep.status = RRSetConfigSuccess; + pScrPriv->lastSetTime = time; + +sendReply: + if (outputs) + free(outputs); + + rep.type = X_Reply; + /* rep.status has already been filled in */ + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; + + if (client->swapped) + { + int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.newTimestamp, n); + } + WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep); + + return Success; +} + +int +ProcRRGetPanning (ClientPtr client) +{ + REQUEST(xRRGetPanningReq); + xRRGetPanningReply rep; + RRCrtcPtr crtc; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + BoxRec total; + BoxRec tracking; + INT16 border[4]; + int n; + + REQUEST_SIZE_MATCH(xRRGetPanningReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* All crtcs must be associated with screens before client + * requests are processed + */ + pScreen = crtc->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + if (!pScrPriv) + return RRErrorBase + BadRRCrtc; + + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.status = RRSetConfigSuccess; + rep.sequenceNumber = client->sequence; + rep.length = 1; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + + if (pScrPriv->rrGetPanning && + pScrPriv->rrGetPanning (pScreen, crtc, &total, &tracking, border)) { + rep.left = total.x1; + rep.top = total.y1; + rep.width = total.x2 - total.x1; + rep.height = total.y2 - total.y1; + rep.track_left = tracking.x1; + rep.track_top = tracking.y1; + rep.track_width = tracking.x2 - tracking.x1; + rep.track_height = tracking.y2 - tracking.y1; + rep.border_left = border[0]; + rep.border_top = border[1]; + rep.border_right = border[2]; + rep.border_bottom = border[3]; + } + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.timestamp, n); + swaps(&rep.left, n); + swaps(&rep.top, n); + swaps(&rep.width, n); + swaps(&rep.height, n); + swaps(&rep.track_left, n); + swaps(&rep.track_top, n); + swaps(&rep.track_width, n); + swaps(&rep.track_height, n); + swaps(&rep.border_left, n); + swaps(&rep.border_top, n); + swaps(&rep.border_right, n); + swaps(&rep.border_bottom, n); + } + WriteToClient(client, sizeof(xRRGetPanningReply), (char *)&rep); + return Success; +} + +int +ProcRRSetPanning (ClientPtr client) +{ + REQUEST(xRRSetPanningReq); + xRRSetPanningReply rep; + RRCrtcPtr crtc; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + TimeStamp time; + BoxRec total; + BoxRec tracking; + INT16 border[4]; + int n; + + REQUEST_SIZE_MATCH(xRRSetPanningReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* All crtcs must be associated with screens before client + * requests are processed + */ + pScreen = crtc->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + if (!pScrPriv) { + time = currentTime; + rep.status = RRSetConfigFailed; + goto sendReply; + } + + time = ClientTimeToServerTime(stuff->timestamp); + + /* + * Make sure the requested set-time is not older than + * the last set-time + */ + if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) + { + rep.status = RRSetConfigInvalidTime; + goto sendReply; + } + + if (!pScrPriv->rrGetPanning) + return RRErrorBase + BadRRCrtc; + + total.x1 = stuff->left; + total.y1 = stuff->top; + total.x2 = total.x1 + stuff->width; + total.y2 = total.y1 + stuff->height; + tracking.x1 = stuff->track_left; + tracking.y1 = stuff->track_top; + tracking.x2 = tracking.x1 + stuff->track_width; + tracking.y2 = tracking.y1 + stuff->track_height; + border[0] = stuff->border_left; + border[1] = stuff->border_top; + border[2] = stuff->border_right; + border[3] = stuff->border_bottom; + + if (! pScrPriv->rrSetPanning (pScreen, crtc, &total, &tracking, border)) + return BadMatch; + + pScrPriv->lastSetTime = time; + + rep.status = RRSetConfigSuccess; + +sendReply: + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.newTimestamp, n); + } + WriteToClient(client, sizeof(xRRSetPanningReply), (char *)&rep); + return Success; +} + +int +ProcRRGetCrtcGammaSize (ClientPtr client) +{ + REQUEST(xRRGetCrtcGammaSizeReq); + xRRGetCrtcGammaSizeReply reply; + RRCrtcPtr crtc; + int n; + + REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* Gamma retrieval failed, any better error? */ + if (!RRCrtcGammaGet(crtc)) + return RRErrorBase + BadRRCrtc; + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = 0; + reply.size = crtc->gammaSize; + if (client->swapped) { + swaps (&reply.sequenceNumber, n); + swapl (&reply.length, n); + swaps (&reply.size, n); + } + WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply); + return Success; +} + +int +ProcRRGetCrtcGamma (ClientPtr client) +{ + REQUEST(xRRGetCrtcGammaReq); + xRRGetCrtcGammaReply reply; + RRCrtcPtr crtc; + int n; + unsigned long len; + char *extra = NULL; + + REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* Gamma retrieval failed, any better error? */ + if (!RRCrtcGammaGet(crtc)) + return RRErrorBase + BadRRCrtc; + + len = crtc->gammaSize * 3 * 2; + + if (crtc->gammaSize) { + extra = malloc(len); + if (!extra) + return BadAlloc; + } + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = bytes_to_int32(len); + reply.size = crtc->gammaSize; + if (client->swapped) { + swaps (&reply.sequenceNumber, n); + swapl (&reply.length, n); + swaps (&reply.size, n); + } + WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply); + if (crtc->gammaSize) + { + memcpy(extra, crtc->gammaRed, len); + client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; + WriteSwappedDataToClient (client, len, extra); + free(extra); + } + return Success; +} + +int +ProcRRSetCrtcGamma (ClientPtr client) +{ + REQUEST(xRRSetCrtcGammaReq); + RRCrtcPtr crtc; + unsigned long len; + CARD16 *red, *green, *blue; + + REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + len = client->req_len - bytes_to_int32(sizeof (xRRSetCrtcGammaReq)); + if (len < (stuff->size * 3 + 1) >> 1) + return BadLength; + + if (stuff->size != crtc->gammaSize) + return BadMatch; + + red = (CARD16 *) (stuff + 1); + green = red + crtc->gammaSize; + blue = green + crtc->gammaSize; + + RRCrtcGammaSet (crtc, red, green, blue); + + return Success; +} + +/* Version 1.3 additions */ + +int +ProcRRSetCrtcTransform (ClientPtr client) +{ + REQUEST(xRRSetCrtcTransformReq); + RRCrtcPtr crtc; + PictTransform transform; + struct pixman_f_transform f_transform, f_inverse; + char *filter; + int nbytes; + xFixed *params; + int nparams; + + REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + PictTransform_from_xRenderTransform (&transform, &stuff->transform); + pixman_f_transform_from_pixman_transform (&f_transform, &transform); + if (!pixman_f_transform_invert (&f_inverse, &f_transform)) + return BadMatch; + + filter = (char *) (stuff + 1); + nbytes = stuff->nbytesFilter; + params = (xFixed *) (filter + pad_to_int32(nbytes)); + nparams = ((xFixed *) stuff + client->req_len) - params; + if (nparams < 0) + return BadLength; + + return RRCrtcTransformSet (crtc, &transform, &f_transform, &f_inverse, + filter, nbytes, params, nparams); +} + + +#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32) + +static int +transform_filter_length (RRTransformPtr transform) +{ + int nbytes, nparams; + + if (transform->filter == NULL) + return 0; + nbytes = strlen (transform->filter->name); + nparams = transform->nparams; + return pad_to_int32(nbytes) + (nparams * sizeof (xFixed)); +} + +static int +transform_filter_encode (ClientPtr client, char *output, + CARD16 *nbytesFilter, + CARD16 *nparamsFilter, + RRTransformPtr transform) +{ + int nbytes, nparams; + int n; + + if (transform->filter == NULL) { + *nbytesFilter = 0; + *nparamsFilter = 0; + return 0; + } + nbytes = strlen (transform->filter->name); + nparams = transform->nparams; + *nbytesFilter = nbytes; + *nparamsFilter = nparams; + memcpy (output, transform->filter->name, nbytes); + while ((nbytes & 3) != 0) + output[nbytes++] = 0; + memcpy (output + nbytes, transform->params, nparams * sizeof (xFixed)); + if (client->swapped) { + swaps (nbytesFilter, n); + swaps (nparamsFilter, n); + SwapLongs ((CARD32 *) (output + nbytes), nparams); + } + nbytes += nparams * sizeof (xFixed); + return nbytes; +} + +static void +transform_encode (ClientPtr client, xRenderTransform *wire, PictTransform *pict) +{ + xRenderTransform_from_PictTransform (wire, pict); + if (client->swapped) + SwapLongs ((CARD32 *) wire, bytes_to_int32(sizeof(xRenderTransform))); +} + +int +ProcRRGetCrtcTransform (ClientPtr client) +{ + REQUEST(xRRGetCrtcTransformReq); + xRRGetCrtcTransformReply *reply; + RRCrtcPtr crtc; + int n, nextra; + RRTransformPtr current, pending; + char *extra; + + REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + pending = &crtc->client_pending_transform; + current = &crtc->client_current_transform; + + nextra = (transform_filter_length (pending) + + transform_filter_length (current)); + + reply = malloc(sizeof (xRRGetCrtcTransformReply) + nextra); + if (!reply) + return BadAlloc; + + extra = (char *) (reply + 1); + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = bytes_to_int32(CrtcTransformExtra + nextra); + + reply->hasTransforms = crtc->transforms; + + transform_encode (client, &reply->pendingTransform, &pending->transform); + extra += transform_filter_encode (client, extra, + &reply->pendingNbytesFilter, + &reply->pendingNparamsFilter, + pending); + + transform_encode (client, &reply->currentTransform, ¤t->transform); + extra += transform_filter_encode (client, extra, + &reply->currentNbytesFilter, + &reply->currentNparamsFilter, + current); + + if (client->swapped) { + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + } + WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply); + free(reply); + return Success; +} diff --git a/xorg-server/randr/rrdispatch.c b/xorg-server/randr/rrdispatch.c index ffb46a48c..b54086bcb 100644 --- a/xorg-server/randr/rrdispatch.c +++ b/xorg-server/randr/rrdispatch.c @@ -1,228 +1,228 @@ -/* - * 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 (pRRClient->major_version > 1 || - (pRRClient->major_version == 1 && pRRClient->minor_version >= 1)); -} - -static int -ProcRRQueryVersion (ClientPtr client) -{ - xRRQueryVersionReply rep; - 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 ((stuff->majorVersion * 1000 + stuff->minorVersion) < - (SERVER_RANDR_MAJOR_VERSION * 1000 + SERVER_RANDR_MINOR_VERSION)) - { - 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 (client->noClientException); -} - -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) xalloc (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 *) xalloc (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 && (pRREvent->mask & RRScreenChangeNotifyMask)) - { - pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; - if (CompareTimeStamps (pTimes->setTime, - pScrPriv->lastSetTime) != 0 || - CompareTimeStamps (pTimes->configTime, - pScrPriv->lastConfigTime) != 0) - { - RRDeliverScreenEvent (client, pWin, pScreen); - } - } - } - 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; - xfree (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 (pRRClient->major_version > 1 || + (pRRClient->major_version == 1 && pRRClient->minor_version >= 1)); +} + +static int +ProcRRQueryVersion (ClientPtr client) +{ + xRRQueryVersionReply rep; + 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 ((stuff->majorVersion * 1000 + stuff->minorVersion) < + (SERVER_RANDR_MAJOR_VERSION * 1000 + SERVER_RANDR_MINOR_VERSION)) + { + 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 && (pRREvent->mask & RRScreenChangeNotifyMask)) + { + pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; + if (CompareTimeStamps (pTimes->setTime, + pScrPriv->lastSetTime) != 0 || + CompareTimeStamps (pTimes->configTime, + pScrPriv->lastConfigTime) != 0) + { + RRDeliverScreenEvent (client, pWin, pScreen); + } + } + } + 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 20066d5fc..04c1a6c98 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 = xrealloc (output->modes, - (output->numModes + 1) * sizeof (RRModePtr)); - else - modes = xalloc (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; - } - } - xfree (size->pRates); - } - else - { - mode = RROldModeAdd (output, size, 0); - if (i == pScrPriv->size) - newMode = mode; - } - } - if (pScrPriv->nSizes) - xfree (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 = xrealloc (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 = xrealloc (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/rrmode.c b/xorg-server/randr/rrmode.c index 139619367..7412e6f3e 100644 --- a/xorg-server/randr/rrmode.c +++ b/xorg-server/randr/rrmode.c @@ -1,369 +1,369 @@ -/* - * 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" - -RESTYPE RRModeType; - -static Bool -RRModeEqual (xRRModeInfo *a, xRRModeInfo *b) -{ - if (a->width != b->width) return FALSE; - if (a->height != b->height) return FALSE; - if (a->dotClock != b->dotClock) return FALSE; - if (a->hSyncStart != b->hSyncStart) return FALSE; - if (a->hSyncEnd != b->hSyncEnd) return FALSE; - if (a->hTotal != b->hTotal) return FALSE; - if (a->hSkew != b->hSkew) return FALSE; - if (a->vSyncStart != b->vSyncStart) return FALSE; - if (a->vSyncEnd != b->vSyncEnd) return FALSE; - if (a->vTotal != b->vTotal) return FALSE; - if (a->nameLength != b->nameLength) return FALSE; - if (a->modeFlags != b->modeFlags) return FALSE; - return TRUE; -} - -/* - * Keep a list so it's easy to find modes in the resource database. - */ -static int num_modes; -static RRModePtr *modes; - -static RRModePtr -RRModeCreate (xRRModeInfo *modeInfo, - const char *name, - ScreenPtr userScreen) -{ - RRModePtr mode, *newModes; - - if (!RRInit ()) - return NULL; - - mode = xalloc (sizeof (RRModeRec) + modeInfo->nameLength + 1); - if (!mode) - return NULL; - mode->refcnt = 1; - mode->mode = *modeInfo; - mode->name = (char *) (mode + 1); - memcpy (mode->name, name, modeInfo->nameLength); - mode->name[modeInfo->nameLength] = '\0'; - mode->userScreen = userScreen; - - if (num_modes) - newModes = xrealloc (modes, (num_modes + 1) * sizeof (RRModePtr)); - else - newModes = xalloc (sizeof (RRModePtr)); - - if (!newModes) - { - xfree (mode); - return NULL; - } - - mode->mode.id = FakeClientID(0); - if (!AddResource (mode->mode.id, RRModeType, (pointer) mode)) - return NULL; - modes = newModes; - modes[num_modes++] = mode; - - /* - * give the caller a reference to this mode - */ - ++mode->refcnt; - return mode; -} - -static RRModePtr -RRModeFindByName (const char *name, - CARD16 nameLength) -{ - int i; - RRModePtr mode; - - for (i = 0; i < num_modes; i++) - { - mode = modes[i]; - if (mode->mode.nameLength == nameLength && - !memcmp (name, mode->name, nameLength)) - { - return mode; - } - } - return NULL; -} - -RRModePtr -RRModeGet (xRRModeInfo *modeInfo, - const char *name) -{ - int i; - - for (i = 0; i < num_modes; i++) - { - RRModePtr mode = modes[i]; - if (RRModeEqual (&mode->mode, modeInfo) && - !memcmp (name, mode->name, modeInfo->nameLength)) - { - ++mode->refcnt; - return mode; - } - } - - return RRModeCreate (modeInfo, name, NULL); -} - -static RRModePtr -RRModeCreateUser (ScreenPtr pScreen, - xRRModeInfo *modeInfo, - const char *name, - int *error) -{ - RRModePtr mode; - - mode = RRModeFindByName (name, modeInfo->nameLength); - if (mode) - { - *error = BadName; - return NULL; - } - - mode = RRModeCreate (modeInfo, name, pScreen); - if (!mode) - { - *error = BadAlloc; - return NULL; - } - *error = Success; - return mode; -} - -RRModePtr * -RRModesForScreen (ScreenPtr pScreen, int *num_ret) -{ - rrScrPriv(pScreen); - int o, c, m; - RRModePtr *screen_modes; - int num_screen_modes = 0; - - screen_modes = xalloc ((num_modes ? num_modes : 1) * sizeof (RRModePtr)); - if (!screen_modes) - return NULL; - - /* - * Add modes from all outputs - */ - for (o = 0; o < pScrPriv->numOutputs; o++) - { - RROutputPtr output = pScrPriv->outputs[o]; - int m, n; - - for (m = 0; m < output->numModes + output->numUserModes; m++) - { - RRModePtr mode = (m < output->numModes ? - output->modes[m] : - output->userModes[m-output->numModes]); - for (n = 0; n < num_screen_modes; n++) - if (screen_modes[n] == mode) - break; - if (n == num_screen_modes) - screen_modes[num_screen_modes++] = mode; - } - } - /* - * Add modes from all crtcs. The goal is to - * make sure all available and active modes - * are visible to the client - */ - for (c = 0; c < pScrPriv->numCrtcs; c++) - { - RRCrtcPtr crtc = pScrPriv->crtcs[c]; - RRModePtr mode = crtc->mode; - int n; - - if (!mode) continue; - for (n = 0; n < num_screen_modes; n++) - if (screen_modes[n] == mode) - break; - if (n == num_screen_modes) - screen_modes[num_screen_modes++] = mode; - } - /* - * Add all user modes for this screen - */ - for (m = 0; m < num_modes; m++) - { - RRModePtr mode = modes[m]; - int n; - - if (mode->userScreen != pScreen) - continue; - for (n = 0; n < num_screen_modes; n++) - if (screen_modes[n] == mode) - break; - if (n == num_screen_modes) - screen_modes[num_screen_modes++] = mode; - } - - *num_ret = num_screen_modes; - return screen_modes; -} - -void -RRModeDestroy (RRModePtr mode) -{ - int m; - - if (--mode->refcnt > 0) - return; - for (m = 0; m < num_modes; m++) - { - if (modes[m] == mode) - { - memmove (modes + m, modes + m + 1, - (num_modes - m - 1) * sizeof (RRModePtr)); - num_modes--; - if (!num_modes) - { - xfree (modes); - modes = NULL; - } - break; - } - } - - xfree (mode); -} - -static int -RRModeDestroyResource (pointer value, XID pid) -{ - RRModeDestroy ((RRModePtr) value); - return 1; -} - -Bool -RRModeInit (void) -{ - assert (num_modes == 0); - assert (modes == NULL); - RRModeType = CreateNewResourceType (RRModeDestroyResource, "MODE"); - if (!RRModeType) - return FALSE; - return TRUE; -} - -int -ProcRRCreateMode (ClientPtr client) -{ - REQUEST(xRRCreateModeReq); - xRRCreateModeReply rep; - WindowPtr pWin; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - xRRModeInfo *modeInfo; - long units_after; - char *name; - int error, rc; - RRModePtr mode; - - REQUEST_AT_LEAST_SIZE (xRRCreateModeReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - pScreen = pWin->drawable.pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - modeInfo = &stuff->modeInfo; - name = (char *) (stuff + 1); - units_after = (stuff->length - bytes_to_int32(sizeof (xRRCreateModeReq))); - - /* check to make sure requested name fits within the data provided */ - if (bytes_to_int32(modeInfo->nameLength) > units_after) - return BadLength; - - mode = RRModeCreateUser (pScreen, modeInfo, name, &error); - if (!mode) - return error; - - rep.type = X_Reply; - rep.pad0 = 0; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.mode = mode->mode.id; - if (client->swapped) - { - int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.mode, n); - } - WriteToClient(client, sizeof(xRRCreateModeReply), (char *)&rep); - /* Drop out reference to this mode */ - RRModeDestroy (mode); - return client->noClientException; -} - -int -ProcRRDestroyMode (ClientPtr client) -{ - REQUEST(xRRDestroyModeReq); - RRModePtr mode; - - REQUEST_SIZE_MATCH(xRRDestroyModeReq); - VERIFY_RR_MODE(stuff->mode, mode, DixDestroyAccess); - - if (!mode->userScreen) - return BadMatch; - if (mode->refcnt > 1) - return BadAccess; - FreeResource (stuff->mode, 0); - return Success; -} - -int -ProcRRAddOutputMode (ClientPtr client) -{ - REQUEST(xRRAddOutputModeReq); - RRModePtr mode; - RROutputPtr output; - - REQUEST_SIZE_MATCH(xRRAddOutputModeReq); - VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); - VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess); - - return RROutputAddUserMode (output, mode); -} - -int -ProcRRDeleteOutputMode (ClientPtr client) -{ - REQUEST(xRRDeleteOutputModeReq); - RRModePtr mode; - RROutputPtr output; - - REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq); - VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); - VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess); - - return RROutputDeleteUserMode (output, mode); -} +/* + * 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" + +RESTYPE RRModeType; + +static Bool +RRModeEqual (xRRModeInfo *a, xRRModeInfo *b) +{ + if (a->width != b->width) return FALSE; + if (a->height != b->height) return FALSE; + if (a->dotClock != b->dotClock) return FALSE; + if (a->hSyncStart != b->hSyncStart) return FALSE; + if (a->hSyncEnd != b->hSyncEnd) return FALSE; + if (a->hTotal != b->hTotal) return FALSE; + if (a->hSkew != b->hSkew) return FALSE; + if (a->vSyncStart != b->vSyncStart) return FALSE; + if (a->vSyncEnd != b->vSyncEnd) return FALSE; + if (a->vTotal != b->vTotal) return FALSE; + if (a->nameLength != b->nameLength) return FALSE; + if (a->modeFlags != b->modeFlags) return FALSE; + return TRUE; +} + +/* + * Keep a list so it's easy to find modes in the resource database. + */ +static int num_modes; +static RRModePtr *modes; + +static RRModePtr +RRModeCreate (xRRModeInfo *modeInfo, + const char *name, + ScreenPtr userScreen) +{ + RRModePtr mode, *newModes; + + if (!RRInit ()) + return NULL; + + mode = malloc(sizeof (RRModeRec) + modeInfo->nameLength + 1); + if (!mode) + return NULL; + mode->refcnt = 1; + mode->mode = *modeInfo; + mode->name = (char *) (mode + 1); + memcpy (mode->name, name, modeInfo->nameLength); + mode->name[modeInfo->nameLength] = '\0'; + mode->userScreen = userScreen; + + if (num_modes) + newModes = realloc(modes, (num_modes + 1) * sizeof (RRModePtr)); + else + newModes = malloc(sizeof (RRModePtr)); + + if (!newModes) + { + free(mode); + return NULL; + } + + mode->mode.id = FakeClientID(0); + if (!AddResource (mode->mode.id, RRModeType, (pointer) mode)) + return NULL; + modes = newModes; + modes[num_modes++] = mode; + + /* + * give the caller a reference to this mode + */ + ++mode->refcnt; + return mode; +} + +static RRModePtr +RRModeFindByName (const char *name, + CARD16 nameLength) +{ + int i; + RRModePtr mode; + + for (i = 0; i < num_modes; i++) + { + mode = modes[i]; + if (mode->mode.nameLength == nameLength && + !memcmp (name, mode->name, nameLength)) + { + return mode; + } + } + return NULL; +} + +RRModePtr +RRModeGet (xRRModeInfo *modeInfo, + const char *name) +{ + int i; + + for (i = 0; i < num_modes; i++) + { + RRModePtr mode = modes[i]; + if (RRModeEqual (&mode->mode, modeInfo) && + !memcmp (name, mode->name, modeInfo->nameLength)) + { + ++mode->refcnt; + return mode; + } + } + + return RRModeCreate (modeInfo, name, NULL); +} + +static RRModePtr +RRModeCreateUser (ScreenPtr pScreen, + xRRModeInfo *modeInfo, + const char *name, + int *error) +{ + RRModePtr mode; + + mode = RRModeFindByName (name, modeInfo->nameLength); + if (mode) + { + *error = BadName; + return NULL; + } + + mode = RRModeCreate (modeInfo, name, pScreen); + if (!mode) + { + *error = BadAlloc; + return NULL; + } + *error = Success; + return mode; +} + +RRModePtr * +RRModesForScreen (ScreenPtr pScreen, int *num_ret) +{ + rrScrPriv(pScreen); + int o, c, m; + RRModePtr *screen_modes; + int num_screen_modes = 0; + + screen_modes = malloc((num_modes ? num_modes : 1) * sizeof (RRModePtr)); + if (!screen_modes) + return NULL; + + /* + * Add modes from all outputs + */ + for (o = 0; o < pScrPriv->numOutputs; o++) + { + RROutputPtr output = pScrPriv->outputs[o]; + int m, n; + + for (m = 0; m < output->numModes + output->numUserModes; m++) + { + RRModePtr mode = (m < output->numModes ? + output->modes[m] : + output->userModes[m-output->numModes]); + for (n = 0; n < num_screen_modes; n++) + if (screen_modes[n] == mode) + break; + if (n == num_screen_modes) + screen_modes[num_screen_modes++] = mode; + } + } + /* + * Add modes from all crtcs. The goal is to + * make sure all available and active modes + * are visible to the client + */ + for (c = 0; c < pScrPriv->numCrtcs; c++) + { + RRCrtcPtr crtc = pScrPriv->crtcs[c]; + RRModePtr mode = crtc->mode; + int n; + + if (!mode) continue; + for (n = 0; n < num_screen_modes; n++) + if (screen_modes[n] == mode) + break; + if (n == num_screen_modes) + screen_modes[num_screen_modes++] = mode; + } + /* + * Add all user modes for this screen + */ + for (m = 0; m < num_modes; m++) + { + RRModePtr mode = modes[m]; + int n; + + if (mode->userScreen != pScreen) + continue; + for (n = 0; n < num_screen_modes; n++) + if (screen_modes[n] == mode) + break; + if (n == num_screen_modes) + screen_modes[num_screen_modes++] = mode; + } + + *num_ret = num_screen_modes; + return screen_modes; +} + +void +RRModeDestroy (RRModePtr mode) +{ + int m; + + if (--mode->refcnt > 0) + return; + for (m = 0; m < num_modes; m++) + { + if (modes[m] == mode) + { + memmove (modes + m, modes + m + 1, + (num_modes - m - 1) * sizeof (RRModePtr)); + num_modes--; + if (!num_modes) + { + free(modes); + modes = NULL; + } + break; + } + } + + free(mode); +} + +static int +RRModeDestroyResource (pointer value, XID pid) +{ + RRModeDestroy ((RRModePtr) value); + return 1; +} + +Bool +RRModeInit (void) +{ + assert (num_modes == 0); + assert (modes == NULL); + RRModeType = CreateNewResourceType (RRModeDestroyResource, "MODE"); + if (!RRModeType) + return FALSE; + return TRUE; +} + +int +ProcRRCreateMode (ClientPtr client) +{ + REQUEST(xRRCreateModeReq); + xRRCreateModeReply rep; + WindowPtr pWin; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + xRRModeInfo *modeInfo; + long units_after; + char *name; + int error, rc; + RRModePtr mode; + + REQUEST_AT_LEAST_SIZE (xRRCreateModeReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + pScreen = pWin->drawable.pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + modeInfo = &stuff->modeInfo; + name = (char *) (stuff + 1); + units_after = (stuff->length - bytes_to_int32(sizeof (xRRCreateModeReq))); + + /* check to make sure requested name fits within the data provided */ + if (bytes_to_int32(modeInfo->nameLength) > units_after) + return BadLength; + + mode = RRModeCreateUser (pScreen, modeInfo, name, &error); + if (!mode) + return error; + + rep.type = X_Reply; + rep.pad0 = 0; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.mode = mode->mode.id; + if (client->swapped) + { + int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.mode, n); + } + WriteToClient(client, sizeof(xRRCreateModeReply), (char *)&rep); + /* Drop out reference to this mode */ + RRModeDestroy (mode); + return Success; +} + +int +ProcRRDestroyMode (ClientPtr client) +{ + REQUEST(xRRDestroyModeReq); + RRModePtr mode; + + REQUEST_SIZE_MATCH(xRRDestroyModeReq); + VERIFY_RR_MODE(stuff->mode, mode, DixDestroyAccess); + + if (!mode->userScreen) + return BadMatch; + if (mode->refcnt > 1) + return BadAccess; + FreeResource (stuff->mode, 0); + return Success; +} + +int +ProcRRAddOutputMode (ClientPtr client) +{ + REQUEST(xRRAddOutputModeReq); + RRModePtr mode; + RROutputPtr output; + + REQUEST_SIZE_MATCH(xRRAddOutputModeReq); + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); + VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess); + + return RROutputAddUserMode (output, mode); +} + +int +ProcRRDeleteOutputMode (ClientPtr client) +{ + REQUEST(xRRDeleteOutputModeReq); + RRModePtr mode; + RROutputPtr output; + + REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq); + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); + VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess); + + return RROutputDeleteUserMode (output, mode); +} diff --git a/xorg-server/randr/rroutput.c b/xorg-server/randr/rroutput.c index 79e16f0e8..669f50781 100644 --- a/xorg-server/randr/rroutput.c +++ b/xorg-server/randr/rroutput.c @@ -1,626 +1,626 @@ -/* - * Copyright © 2006 Keith Packard - * Copyright © 2008 Red Hat, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include "randrstr.h" - -/* From render.h */ -#ifndef SubPixelUnknown -#define SubPixelUnknown 0 -#endif - -RESTYPE RROutputType; - -/* - * Notify the output of some change - */ -void -RROutputChanged (RROutputPtr output, Bool configChanged) -{ - ScreenPtr pScreen = output->pScreen; - - output->changed = TRUE; - if (pScreen) - { - rrScrPriv (pScreen); - pScrPriv->changed = TRUE; - if (configChanged) - pScrPriv->configChanged = TRUE; - } -} - -/* - * Create an output - */ - -RROutputPtr -RROutputCreate (ScreenPtr pScreen, - const char *name, - int nameLength, - void *devPrivate) -{ - RROutputPtr output; - RROutputPtr *outputs; - rrScrPrivPtr pScrPriv; - - if (!RRInit()) - return NULL; - - pScrPriv = rrGetScrPriv(pScreen); - - if (pScrPriv->numOutputs) - outputs = xrealloc (pScrPriv->outputs, - (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr)); - else - outputs = xalloc (sizeof (RROutputPtr)); - if (!outputs) - return FALSE; - - pScrPriv->outputs = outputs; - - output = xalloc (sizeof (RROutputRec) + nameLength + 1); - if (!output) - return NULL; - output->id = FakeClientID (0); - output->pScreen = pScreen; - output->name = (char *) (output + 1); - output->nameLength = nameLength; - memcpy (output->name, name, nameLength); - output->name[nameLength] = '\0'; - output->connection = RR_UnknownConnection; - output->subpixelOrder = SubPixelUnknown; - output->mmWidth = 0; - output->mmHeight = 0; - output->crtc = NULL; - output->numCrtcs = 0; - output->crtcs = NULL; - output->numClones = 0; - output->clones = NULL; - output->numModes = 0; - output->numPreferred = 0; - output->modes = NULL; - output->numUserModes = 0; - output->userModes = NULL; - output->properties = NULL; - output->pendingProperties = FALSE; - output->changed = FALSE; - output->devPrivate = devPrivate; - - if (!AddResource (output->id, RROutputType, (pointer) output)) - return NULL; - - pScrPriv->outputs[pScrPriv->numOutputs++] = output; - return output; -} - -/* - * Notify extension that output parameters have been changed - */ -Bool -RROutputSetClones (RROutputPtr output, - RROutputPtr *clones, - int numClones) -{ - RROutputPtr *newClones; - int i; - - if (numClones == output->numClones) - { - for (i = 0; i < numClones; i++) - if (output->clones[i] != clones[i]) - break; - if (i == numClones) - return TRUE; - } - if (numClones) - { - newClones = xalloc (numClones * sizeof (RROutputPtr)); - if (!newClones) - return FALSE; - } - else - newClones = NULL; - if (output->clones) - xfree (output->clones); - memcpy (newClones, clones, numClones * sizeof (RROutputPtr)); - output->clones = newClones; - output->numClones = numClones; - RROutputChanged (output, TRUE); - return TRUE; -} - -Bool -RROutputSetModes (RROutputPtr output, - RRModePtr *modes, - int numModes, - int numPreferred) -{ - RRModePtr *newModes; - int i; - - if (numModes == output->numModes && numPreferred == output->numPreferred) - { - for (i = 0; i < numModes; i++) - if (output->modes[i] != modes[i]) - break; - if (i == numModes) - { - for (i = 0; i < numModes; i++) - RRModeDestroy (modes[i]); - return TRUE; - } - } - - if (numModes) - { - newModes = xalloc (numModes * sizeof (RRModePtr)); - if (!newModes) - return FALSE; - } - else - newModes = NULL; - if (output->modes) - { - for (i = 0; i < output->numModes; i++) - RRModeDestroy (output->modes[i]); - xfree (output->modes); - } - memcpy (newModes, modes, numModes * sizeof (RRModePtr)); - output->modes = newModes; - output->numModes = numModes; - output->numPreferred = numPreferred; - RROutputChanged (output, TRUE); - return TRUE; -} - -int -RROutputAddUserMode (RROutputPtr output, - RRModePtr mode) -{ - int m; - ScreenPtr pScreen = output->pScreen; - rrScrPriv(pScreen); - RRModePtr *newModes; - - /* Check to see if this mode is already listed for this output */ - for (m = 0; m < output->numModes + output->numUserModes; m++) - { - RRModePtr e = (m < output->numModes ? - output->modes[m] : - output->userModes[m - output->numModes]); - if (mode == e) - return Success; - } - - /* Check with the DDX to see if this mode is OK */ - if (pScrPriv->rrOutputValidateMode) - if (!pScrPriv->rrOutputValidateMode (pScreen, output, mode)) - return BadMatch; - - if (output->userModes) - newModes = xrealloc (output->userModes, - (output->numUserModes + 1) * sizeof (RRModePtr)); - else - newModes = xalloc (sizeof (RRModePtr)); - if (!newModes) - return BadAlloc; - - output->userModes = newModes; - output->userModes[output->numUserModes++] = mode; - ++mode->refcnt; - RROutputChanged (output, TRUE); - RRTellChanged (pScreen); - return Success; -} - -int -RROutputDeleteUserMode (RROutputPtr output, - RRModePtr mode) -{ - int m; - - /* Find this mode in the user mode list */ - for (m = 0; m < output->numUserModes; m++) - { - RRModePtr e = output->userModes[m]; - - if (mode == e) - break; - } - /* Not there, access error */ - if (m == output->numUserModes) - return BadAccess; - - /* make sure the mode isn't active for this output */ - if (output->crtc && output->crtc->mode == mode) - return BadMatch; - - memmove (output->userModes + m, output->userModes + m + 1, - (output->numUserModes - m - 1) * sizeof (RRModePtr)); - output->numUserModes--; - RRModeDestroy (mode); - return Success; -} - -Bool -RROutputSetCrtcs (RROutputPtr output, - RRCrtcPtr *crtcs, - int numCrtcs) -{ - RRCrtcPtr *newCrtcs; - int i; - - if (numCrtcs == output->numCrtcs) - { - for (i = 0; i < numCrtcs; i++) - if (output->crtcs[i] != crtcs[i]) - break; - if (i == numCrtcs) - return TRUE; - } - if (numCrtcs) - { - newCrtcs = xalloc (numCrtcs * sizeof (RRCrtcPtr)); - if (!newCrtcs) - return FALSE; - } - else - newCrtcs = NULL; - if (output->crtcs) - xfree (output->crtcs); - memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr)); - output->crtcs = newCrtcs; - output->numCrtcs = numCrtcs; - RROutputChanged (output, TRUE); - return TRUE; -} - -Bool -RROutputSetConnection (RROutputPtr output, - CARD8 connection) -{ - if (output->connection == connection) - return TRUE; - output->connection = connection; - RROutputChanged (output, TRUE); - return TRUE; -} - -Bool -RROutputSetSubpixelOrder (RROutputPtr output, - int subpixelOrder) -{ - if (output->subpixelOrder == subpixelOrder) - return TRUE; - - output->subpixelOrder = subpixelOrder; - RROutputChanged (output, FALSE); - return TRUE; -} - -Bool -RROutputSetPhysicalSize (RROutputPtr output, - int mmWidth, - int mmHeight) -{ - if (output->mmWidth == mmWidth && output->mmHeight == mmHeight) - return TRUE; - output->mmWidth = mmWidth; - output->mmHeight = mmHeight; - RROutputChanged (output, FALSE); - return TRUE; -} - - -void -RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - rrScrPriv (pScreen); - xRROutputChangeNotifyEvent oe; - RRCrtcPtr crtc = output->crtc; - RRModePtr mode = crtc ? crtc->mode : 0; - - oe.type = RRNotify + RREventBase; - oe.subCode = RRNotify_OutputChange; - oe.sequenceNumber = client->sequence; - oe.timestamp = pScrPriv->lastSetTime.milliseconds; - oe.configTimestamp = pScrPriv->lastConfigTime.milliseconds; - oe.window = pWin->drawable.id; - oe.output = output->id; - if (crtc) - { - oe.crtc = crtc->id; - oe.mode = mode ? mode->mode.id : None; - oe.rotation = crtc->rotation; - } - else - { - oe.crtc = None; - oe.mode = None; - oe.rotation = RR_Rotate_0; - } - oe.connection = output->connection; - oe.subpixelOrder = output->subpixelOrder; - WriteEventsToClient (client, 1, (xEvent *) &oe); -} - -/* - * Destroy a Output at shutdown - */ -void -RROutputDestroy (RROutputPtr output) -{ - FreeResource (output->id, 0); -} - -static int -RROutputDestroyResource (pointer value, XID pid) -{ - RROutputPtr output = (RROutputPtr) value; - ScreenPtr pScreen = output->pScreen; - int m; - - if (pScreen) - { - rrScrPriv(pScreen); - int i; - - if (pScrPriv->primaryOutput == output) - pScrPriv->primaryOutput = NULL; - - for (i = 0; i < pScrPriv->numOutputs; i++) - { - if (pScrPriv->outputs[i] == output) - { - memmove (pScrPriv->outputs + i, pScrPriv->outputs + i + 1, - (pScrPriv->numOutputs - (i + 1)) * sizeof (RROutputPtr)); - --pScrPriv->numOutputs; - break; - } - } - } - if (output->modes) - { - for (m = 0; m < output->numModes; m++) - RRModeDestroy (output->modes[m]); - xfree (output->modes); - } - - for (m = 0; m < output->numUserModes; m++) - RRModeDestroy (output->userModes[m]); - if (output->userModes) - xfree (output->userModes); - - if (output->crtcs) - xfree (output->crtcs); - if (output->clones) - xfree (output->clones); - RRDeleteAllOutputProperties (output); - xfree (output); - return 1; -} - -/* - * Initialize output type - */ -Bool -RROutputInit (void) -{ - RROutputType = CreateNewResourceType (RROutputDestroyResource, "OUTPUT"); - if (!RROutputType) - return FALSE; - return TRUE; -} - -#define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32) - -int -ProcRRGetOutputInfo (ClientPtr client) -{ - REQUEST(xRRGetOutputInfoReq); - xRRGetOutputInfoReply rep; - RROutputPtr output; - CARD8 *extra; - unsigned long extraLen; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - RRCrtc *crtcs; - RRMode *modes; - RROutput *clones; - char *name; - int i, n; - - REQUEST_SIZE_MATCH(xRRGetOutputInfoReq); - VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); - - pScreen = output->pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = bytes_to_int32(OutputInfoExtra); - rep.timestamp = pScrPriv->lastSetTime.milliseconds; - rep.crtc = output->crtc ? output->crtc->id : None; - rep.mmWidth = output->mmWidth; - rep.mmHeight = output->mmHeight; - rep.connection = output->connection; - rep.subpixelOrder = output->subpixelOrder; - rep.nCrtcs = output->numCrtcs; - rep.nModes = output->numModes + output->numUserModes; - rep.nPreferred = output->numPreferred; - rep.nClones = output->numClones; - rep.nameLength = output->nameLength; - - extraLen = ((output->numCrtcs + - output->numModes + output->numUserModes + - output->numClones + - bytes_to_int32(rep.nameLength)) << 2); - - if (extraLen) - { - rep.length += bytes_to_int32(extraLen); - extra = xalloc (extraLen); - if (!extra) - return BadAlloc; - } - else - extra = NULL; - - crtcs = (RRCrtc *) extra; - modes = (RRMode *) (crtcs + output->numCrtcs); - clones = (RROutput *) (modes + output->numModes + output->numUserModes); - name = (char *) (clones + output->numClones); - - for (i = 0; i < output->numCrtcs; i++) - { - crtcs[i] = output->crtcs[i]->id; - if (client->swapped) - swapl (&crtcs[i], n); - } - for (i = 0; i < output->numModes + output->numUserModes; i++) - { - if (i < output->numModes) - modes[i] = output->modes[i]->mode.id; - else - modes[i] = output->userModes[i - output->numModes]->mode.id; - if (client->swapped) - swapl (&modes[i], n); - } - for (i = 0; i < output->numClones; i++) - { - clones[i] = output->clones[i]->id; - if (client->swapped) - swapl (&clones[i], n); - } - memcpy (name, output->name, output->nameLength); - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.timestamp, n); - swapl(&rep.crtc, n); - swapl(&rep.mmWidth, n); - swapl(&rep.mmHeight, n); - swaps(&rep.nCrtcs, n); - swaps(&rep.nModes, n); - swaps(&rep.nClones, n); - swaps(&rep.nameLength, n); - } - WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *)&rep); - if (extraLen) - { - WriteToClient (client, extraLen, (char *) extra); - xfree (extra); - } - - return client->noClientException; -} - -static void -RRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv, - RROutputPtr output) -{ - if (pScrPriv->primaryOutput == output) - return; - - /* clear the old primary */ - if (pScrPriv->primaryOutput) { - RROutputChanged(pScrPriv->primaryOutput, 0); - pScrPriv->primaryOutput = NULL; - } - - /* set the new primary */ - if (output) { - pScrPriv->primaryOutput = output; - RROutputChanged(output, 0); - } - - pScrPriv->layoutChanged = TRUE; - - RRTellChanged(pScreen); -} - -int -ProcRRSetOutputPrimary(ClientPtr client) -{ - REQUEST(xRRSetOutputPrimaryReq); - RROutputPtr output = NULL; - WindowPtr pWin; - rrScrPrivPtr pScrPriv; - int rc; - - REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq); - - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - if (stuff->output) { - VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); - - if (output->pScreen != pWin->drawable.pScreen) { - client->errorValue = stuff->window; - return BadMatch; - } - } - - pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); - RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output); - - return client->noClientException; -} - -int -ProcRRGetOutputPrimary(ClientPtr client) -{ - REQUEST(xRRGetOutputPrimaryReq); - WindowPtr pWin; - rrScrPrivPtr pScrPriv; - xRRGetOutputPrimaryReply rep; - RROutputPtr primary = NULL; - int rc; - - REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq); - - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); - if (pScrPriv) - primary = pScrPriv->primaryOutput; - - memset(&rep, 0, sizeof(rep)); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.output = primary ? primary->id : None; - - if (client->swapped) { - int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.output, n); - } - - WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), &rep); - - return client->noClientException; -} +/* + * Copyright © 2006 Keith Packard + * Copyright © 2008 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "randrstr.h" + +/* From render.h */ +#ifndef SubPixelUnknown +#define SubPixelUnknown 0 +#endif + +RESTYPE RROutputType; + +/* + * Notify the output of some change + */ +void +RROutputChanged (RROutputPtr output, Bool configChanged) +{ + ScreenPtr pScreen = output->pScreen; + + output->changed = TRUE; + if (pScreen) + { + rrScrPriv (pScreen); + pScrPriv->changed = TRUE; + if (configChanged) + pScrPriv->configChanged = TRUE; + } +} + +/* + * Create an output + */ + +RROutputPtr +RROutputCreate (ScreenPtr pScreen, + const char *name, + int nameLength, + void *devPrivate) +{ + RROutputPtr output; + RROutputPtr *outputs; + rrScrPrivPtr pScrPriv; + + if (!RRInit()) + return NULL; + + pScrPriv = rrGetScrPriv(pScreen); + + if (pScrPriv->numOutputs) + outputs = realloc(pScrPriv->outputs, + (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr)); + else + outputs = malloc(sizeof (RROutputPtr)); + if (!outputs) + return FALSE; + + pScrPriv->outputs = outputs; + + output = malloc(sizeof (RROutputRec) + nameLength + 1); + if (!output) + return NULL; + output->id = FakeClientID (0); + output->pScreen = pScreen; + output->name = (char *) (output + 1); + output->nameLength = nameLength; + memcpy (output->name, name, nameLength); + output->name[nameLength] = '\0'; + output->connection = RR_UnknownConnection; + output->subpixelOrder = SubPixelUnknown; + output->mmWidth = 0; + output->mmHeight = 0; + output->crtc = NULL; + output->numCrtcs = 0; + output->crtcs = NULL; + output->numClones = 0; + output->clones = NULL; + output->numModes = 0; + output->numPreferred = 0; + output->modes = NULL; + output->numUserModes = 0; + output->userModes = NULL; + output->properties = NULL; + output->pendingProperties = FALSE; + output->changed = FALSE; + output->devPrivate = devPrivate; + + if (!AddResource (output->id, RROutputType, (pointer) output)) + return NULL; + + pScrPriv->outputs[pScrPriv->numOutputs++] = output; + return output; +} + +/* + * Notify extension that output parameters have been changed + */ +Bool +RROutputSetClones (RROutputPtr output, + RROutputPtr *clones, + int numClones) +{ + RROutputPtr *newClones; + int i; + + if (numClones == output->numClones) + { + for (i = 0; i < numClones; i++) + if (output->clones[i] != clones[i]) + break; + if (i == numClones) + return TRUE; + } + if (numClones) + { + newClones = malloc(numClones * sizeof (RROutputPtr)); + if (!newClones) + return FALSE; + } + else + newClones = NULL; + if (output->clones) + free(output->clones); + memcpy (newClones, clones, numClones * sizeof (RROutputPtr)); + output->clones = newClones; + output->numClones = numClones; + RROutputChanged (output, TRUE); + return TRUE; +} + +Bool +RROutputSetModes (RROutputPtr output, + RRModePtr *modes, + int numModes, + int numPreferred) +{ + RRModePtr *newModes; + int i; + + if (numModes == output->numModes && numPreferred == output->numPreferred) + { + for (i = 0; i < numModes; i++) + if (output->modes[i] != modes[i]) + break; + if (i == numModes) + { + for (i = 0; i < numModes; i++) + RRModeDestroy (modes[i]); + return TRUE; + } + } + + if (numModes) + { + newModes = malloc(numModes * sizeof (RRModePtr)); + if (!newModes) + return FALSE; + } + else + newModes = NULL; + if (output->modes) + { + for (i = 0; i < output->numModes; i++) + RRModeDestroy (output->modes[i]); + free(output->modes); + } + memcpy (newModes, modes, numModes * sizeof (RRModePtr)); + output->modes = newModes; + output->numModes = numModes; + output->numPreferred = numPreferred; + RROutputChanged (output, TRUE); + return TRUE; +} + +int +RROutputAddUserMode (RROutputPtr output, + RRModePtr mode) +{ + int m; + ScreenPtr pScreen = output->pScreen; + rrScrPriv(pScreen); + RRModePtr *newModes; + + /* Check to see if this mode is already listed for this output */ + for (m = 0; m < output->numModes + output->numUserModes; m++) + { + RRModePtr e = (m < output->numModes ? + output->modes[m] : + output->userModes[m - output->numModes]); + if (mode == e) + return Success; + } + + /* Check with the DDX to see if this mode is OK */ + if (pScrPriv->rrOutputValidateMode) + if (!pScrPriv->rrOutputValidateMode (pScreen, output, mode)) + return BadMatch; + + if (output->userModes) + newModes = realloc(output->userModes, + (output->numUserModes + 1) * sizeof (RRModePtr)); + else + newModes = malloc(sizeof (RRModePtr)); + if (!newModes) + return BadAlloc; + + output->userModes = newModes; + output->userModes[output->numUserModes++] = mode; + ++mode->refcnt; + RROutputChanged (output, TRUE); + RRTellChanged (pScreen); + return Success; +} + +int +RROutputDeleteUserMode (RROutputPtr output, + RRModePtr mode) +{ + int m; + + /* Find this mode in the user mode list */ + for (m = 0; m < output->numUserModes; m++) + { + RRModePtr e = output->userModes[m]; + + if (mode == e) + break; + } + /* Not there, access error */ + if (m == output->numUserModes) + return BadAccess; + + /* make sure the mode isn't active for this output */ + if (output->crtc && output->crtc->mode == mode) + return BadMatch; + + memmove (output->userModes + m, output->userModes + m + 1, + (output->numUserModes - m - 1) * sizeof (RRModePtr)); + output->numUserModes--; + RRModeDestroy (mode); + return Success; +} + +Bool +RROutputSetCrtcs (RROutputPtr output, + RRCrtcPtr *crtcs, + int numCrtcs) +{ + RRCrtcPtr *newCrtcs; + int i; + + if (numCrtcs == output->numCrtcs) + { + for (i = 0; i < numCrtcs; i++) + if (output->crtcs[i] != crtcs[i]) + break; + if (i == numCrtcs) + return TRUE; + } + if (numCrtcs) + { + newCrtcs = malloc(numCrtcs * sizeof (RRCrtcPtr)); + if (!newCrtcs) + return FALSE; + } + else + newCrtcs = NULL; + if (output->crtcs) + free(output->crtcs); + memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr)); + output->crtcs = newCrtcs; + output->numCrtcs = numCrtcs; + RROutputChanged (output, TRUE); + return TRUE; +} + +Bool +RROutputSetConnection (RROutputPtr output, + CARD8 connection) +{ + if (output->connection == connection) + return TRUE; + output->connection = connection; + RROutputChanged (output, TRUE); + return TRUE; +} + +Bool +RROutputSetSubpixelOrder (RROutputPtr output, + int subpixelOrder) +{ + if (output->subpixelOrder == subpixelOrder) + return TRUE; + + output->subpixelOrder = subpixelOrder; + RROutputChanged (output, FALSE); + return TRUE; +} + +Bool +RROutputSetPhysicalSize (RROutputPtr output, + int mmWidth, + int mmHeight) +{ + if (output->mmWidth == mmWidth && output->mmHeight == mmHeight) + return TRUE; + output->mmWidth = mmWidth; + output->mmHeight = mmHeight; + RROutputChanged (output, FALSE); + return TRUE; +} + + +void +RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv (pScreen); + xRROutputChangeNotifyEvent oe; + RRCrtcPtr crtc = output->crtc; + RRModePtr mode = crtc ? crtc->mode : 0; + + oe.type = RRNotify + RREventBase; + oe.subCode = RRNotify_OutputChange; + oe.sequenceNumber = client->sequence; + oe.timestamp = pScrPriv->lastSetTime.milliseconds; + oe.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + oe.window = pWin->drawable.id; + oe.output = output->id; + if (crtc) + { + oe.crtc = crtc->id; + oe.mode = mode ? mode->mode.id : None; + oe.rotation = crtc->rotation; + } + else + { + oe.crtc = None; + oe.mode = None; + oe.rotation = RR_Rotate_0; + } + oe.connection = output->connection; + oe.subpixelOrder = output->subpixelOrder; + WriteEventsToClient (client, 1, (xEvent *) &oe); +} + +/* + * Destroy a Output at shutdown + */ +void +RROutputDestroy (RROutputPtr output) +{ + FreeResource (output->id, 0); +} + +static int +RROutputDestroyResource (pointer value, XID pid) +{ + RROutputPtr output = (RROutputPtr) value; + ScreenPtr pScreen = output->pScreen; + int m; + + if (pScreen) + { + rrScrPriv(pScreen); + int i; + + if (pScrPriv->primaryOutput == output) + pScrPriv->primaryOutput = NULL; + + for (i = 0; i < pScrPriv->numOutputs; i++) + { + if (pScrPriv->outputs[i] == output) + { + memmove (pScrPriv->outputs + i, pScrPriv->outputs + i + 1, + (pScrPriv->numOutputs - (i + 1)) * sizeof (RROutputPtr)); + --pScrPriv->numOutputs; + break; + } + } + } + if (output->modes) + { + for (m = 0; m < output->numModes; m++) + RRModeDestroy (output->modes[m]); + free(output->modes); + } + + for (m = 0; m < output->numUserModes; m++) + RRModeDestroy (output->userModes[m]); + if (output->userModes) + free(output->userModes); + + if (output->crtcs) + free(output->crtcs); + if (output->clones) + free(output->clones); + RRDeleteAllOutputProperties (output); + free(output); + return 1; +} + +/* + * Initialize output type + */ +Bool +RROutputInit (void) +{ + RROutputType = CreateNewResourceType (RROutputDestroyResource, "OUTPUT"); + if (!RROutputType) + return FALSE; + return TRUE; +} + +#define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32) + +int +ProcRRGetOutputInfo (ClientPtr client) +{ + REQUEST(xRRGetOutputInfoReq); + xRRGetOutputInfoReply rep; + RROutputPtr output; + CARD8 *extra; + unsigned long extraLen; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + RRCrtc *crtcs; + RRMode *modes; + RROutput *clones; + char *name; + int i, n; + + REQUEST_SIZE_MATCH(xRRGetOutputInfoReq); + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); + + pScreen = output->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = bytes_to_int32(OutputInfoExtra); + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + rep.crtc = output->crtc ? output->crtc->id : None; + rep.mmWidth = output->mmWidth; + rep.mmHeight = output->mmHeight; + rep.connection = output->connection; + rep.subpixelOrder = output->subpixelOrder; + rep.nCrtcs = output->numCrtcs; + rep.nModes = output->numModes + output->numUserModes; + rep.nPreferred = output->numPreferred; + rep.nClones = output->numClones; + rep.nameLength = output->nameLength; + + extraLen = ((output->numCrtcs + + output->numModes + output->numUserModes + + output->numClones + + bytes_to_int32(rep.nameLength)) << 2); + + if (extraLen) + { + rep.length += bytes_to_int32(extraLen); + extra = malloc(extraLen); + if (!extra) + return BadAlloc; + } + else + extra = NULL; + + crtcs = (RRCrtc *) extra; + modes = (RRMode *) (crtcs + output->numCrtcs); + clones = (RROutput *) (modes + output->numModes + output->numUserModes); + name = (char *) (clones + output->numClones); + + for (i = 0; i < output->numCrtcs; i++) + { + crtcs[i] = output->crtcs[i]->id; + if (client->swapped) + swapl (&crtcs[i], n); + } + for (i = 0; i < output->numModes + output->numUserModes; i++) + { + if (i < output->numModes) + modes[i] = output->modes[i]->mode.id; + else + modes[i] = output->userModes[i - output->numModes]->mode.id; + if (client->swapped) + swapl (&modes[i], n); + } + for (i = 0; i < output->numClones; i++) + { + clones[i] = output->clones[i]->id; + if (client->swapped) + swapl (&clones[i], n); + } + memcpy (name, output->name, output->nameLength); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swapl(&rep.crtc, n); + swapl(&rep.mmWidth, n); + swapl(&rep.mmHeight, n); + swaps(&rep.nCrtcs, n); + swaps(&rep.nModes, n); + swaps(&rep.nClones, n); + swaps(&rep.nameLength, n); + } + WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *)&rep); + if (extraLen) + { + WriteToClient (client, extraLen, (char *) extra); + free(extra); + } + + return Success; +} + +static void +RRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv, + RROutputPtr output) +{ + if (pScrPriv->primaryOutput == output) + return; + + /* clear the old primary */ + if (pScrPriv->primaryOutput) { + RROutputChanged(pScrPriv->primaryOutput, 0); + pScrPriv->primaryOutput = NULL; + } + + /* set the new primary */ + if (output) { + pScrPriv->primaryOutput = output; + RROutputChanged(output, 0); + } + + pScrPriv->layoutChanged = TRUE; + + RRTellChanged(pScreen); +} + +int +ProcRRSetOutputPrimary(ClientPtr client) +{ + REQUEST(xRRSetOutputPrimaryReq); + RROutputPtr output = NULL; + WindowPtr pWin; + rrScrPrivPtr pScrPriv; + int rc; + + REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq); + + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + if (stuff->output) { + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); + + if (output->pScreen != pWin->drawable.pScreen) { + client->errorValue = stuff->window; + return BadMatch; + } + } + + pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); + RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output); + + return Success; +} + +int +ProcRRGetOutputPrimary(ClientPtr client) +{ + REQUEST(xRRGetOutputPrimaryReq); + WindowPtr pWin; + rrScrPrivPtr pScrPriv; + xRRGetOutputPrimaryReply rep; + RROutputPtr primary = NULL; + int rc; + + REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq); + + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); + if (pScrPriv) + primary = pScrPriv->primaryOutput; + + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.output = primary ? primary->id : None; + + if (client->swapped) { + int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.output, n); + } + + WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), &rep); + + return Success; +} diff --git a/xorg-server/randr/rrproperty.c b/xorg-server/randr/rrproperty.c index 96e27a9dc..20f07f42a 100644 --- a/xorg-server/randr/rrproperty.c +++ b/xorg-server/randr/rrproperty.c @@ -76,10 +76,10 @@ RRDeleteAllOutputProperties (RROutputPtr output) event.timestamp = currentTime.milliseconds; RRDeliverPropertyEvent (output->pScreen, (xEvent *)&event); if (prop->current.data) - xfree(prop->current.data); + free(prop->current.data); if (prop->pending.data) - xfree(prop->pending.data); - xfree(prop); + free(prop->pending.data); + free(prop); } } @@ -97,7 +97,7 @@ RRCreateOutputProperty (Atom property) { RRPropertyPtr prop; - prop = (RRPropertyPtr)xalloc(sizeof(RRPropertyRec)); + prop = (RRPropertyPtr)malloc(sizeof(RRPropertyRec)); if (!prop) return NULL; prop->next = NULL; @@ -116,14 +116,14 @@ static void RRDestroyOutputProperty (RRPropertyPtr prop) { if (prop->valid_values) - xfree (prop->valid_values); + free(prop->valid_values); if (prop->current.data) - xfree(prop->current.data); + free(prop->current.data); if (prop->pending.data) - xfree(prop->pending.data); + free(prop->pending.data); if (prop->valid_values) - xfree(prop->valid_values); - xfree(prop); + free(prop->valid_values); + free(prop); } void @@ -201,7 +201,7 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type, pointer new_data = NULL, old_data = NULL; total_size = total_len * size_in_bytes; - new_value.data = (pointer)xalloc (total_size); + new_value.data = (pointer)malloc(total_size); if (!new_value.data && total_size) { if (add) @@ -239,11 +239,11 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type, prop->propertyName, &new_value)) { if (new_value.data) - xfree (new_value.data); + free(new_value.data); return (BadValue); } if (prop_value->data) - xfree (prop_value->data); + free(prop_value->data); *prop_value = new_value; } @@ -372,7 +372,7 @@ RRConfigureOutputProperty (RROutputPtr output, Atom property, if (range && (num_values & 1)) return BadMatch; - new_values = xalloc (num_values * sizeof (INT32)); + new_values = malloc(num_values * sizeof (INT32)); if (!new_values && num_values) return BadAlloc; if (num_values) @@ -385,7 +385,7 @@ RRConfigureOutputProperty (RROutputPtr output, Atom property, if (prop->is_pending && !pending) { if (prop->pending.data) - xfree (prop->pending.data); + free(prop->pending.data); RRInitOutputPropertyValue (&prop->pending); } @@ -394,7 +394,7 @@ RRConfigureOutputProperty (RROutputPtr output, Atom property, prop->immutable = immutable; prop->num_valid = num_values; if (prop->valid_values) - xfree (prop->valid_values); + free(prop->valid_values); prop->valid_values = new_values; if (add) { @@ -422,7 +422,7 @@ ProcRRListOutputProperties (ClientPtr client) for (prop = output->properties; prop; prop = prop->next) numProps++; if (numProps) - if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom)))) + if(!(pAtoms = (Atom *)malloc(numProps * sizeof(Atom)))) return(BadAlloc); rep.type = X_Reply; @@ -445,9 +445,9 @@ ProcRRListOutputProperties (ClientPtr client) { client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); - xfree(pAtoms); + free(pAtoms); } - return(client->noClientException); + return Success; } int @@ -468,7 +468,7 @@ ProcRRQueryOutputProperty (ClientPtr client) return BadName; if (prop->num_valid) { - extra = xalloc(prop->num_valid * sizeof(INT32)); + extra = malloc(prop->num_valid * sizeof(INT32)); if (!extra) return BadAlloc; } @@ -491,9 +491,9 @@ ProcRRQueryOutputProperty (ClientPtr client) client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32), extra); - xfree(extra); + free(extra); } - return(client->noClientException); + return Success; } int @@ -566,7 +566,7 @@ ProcRRChangeOutputProperty (ClientPtr client) if (err != Success) return err; else - return client->noClientException; + return Success; } int @@ -587,7 +587,7 @@ ProcRRDeleteOutputProperty (ClientPtr client) RRDeleteOutputProperty(output, stuff->property); - return client->noClientException; + return Success; } int @@ -646,7 +646,7 @@ ProcRRGetOutputProperty (ClientPtr client) swapl(&reply.nItems, n); } WriteToClient(client, sizeof(xRRGetOutputPropertyReply), &reply); - return(client->noClientException); + return Success; } if (prop->immutable && stuff->delete) @@ -678,7 +678,7 @@ ProcRRGetOutputProperty (ClientPtr client) swapl(&reply.nItems, n); } WriteToClient(client, sizeof(xRRGetOutputPropertyReply), &reply); - return(client->noClientException); + return Success; } /* @@ -699,7 +699,7 @@ ProcRRGetOutputProperty (ClientPtr client) len = min(n - ind, 4 * stuff->longLength); if (len) { - extra = xalloc(len); + extra = malloc(len); if (!extra) return BadAlloc; } @@ -745,7 +745,7 @@ ProcRRGetOutputProperty (ClientPtr client) } WriteSwappedDataToClient(client, len, extra); - xfree(extra); + free(extra); } if (stuff->delete && (reply.bytesAfter == 0)) @@ -753,6 +753,6 @@ ProcRRGetOutputProperty (ClientPtr client) *prev = prop->next; RRDestroyOutputProperty (prop); } - return(client->noClientException); + return Success; } diff --git a/xorg-server/randr/rrscreen.c b/xorg-server/randr/rrscreen.c index 45e6ed724..8779ec66f 100644 --- a/xorg-server/randr/rrscreen.c +++ b/xorg-server/randr/rrscreen.c @@ -1,1009 +1,1009 @@ -/* - * 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}; -/* From render.h */ -#ifndef SubPixelUnknown -#define SubPixelUnknown 0 -#endif - - -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 = WindowTable[pScreen->myNum]; - 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 = WindowTable[pScreen->myNum]; - - se.type = RRScreenChangeNotify + RREventBase; - se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0); - se.timestamp = pScrPriv->lastSetTime.milliseconds; - se.sequenceNumber = client->sequence; - se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; - se.root = pRoot->drawable.id; - se.window = pWin->drawable.id; - se.subpixelOrder = PictureGetSubpixelOrder (pScreen); - - se.sequenceNumber = client->sequence; - 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 (client->noClientException); -} - -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 = xalloc (extraLen); - if (!extra) - { - xfree (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; - } - xfree (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); - xfree (extra); - } - return client->noClientException; -} - -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 = WindowTable[pWin->drawable.pScreen->myNum]->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 = WindowTable[pWin->drawable.pScreen->myNum]->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 *) xalloc (extraLen); - if (!extra) - { - xfree (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++; - } - } - } - xfree (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); - xfree (extra); - } - return (client->noClientException); -} - -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; - xfree (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; - xfree (pData); - return BadValue; - } - - if ((~crtc->rotations) & rotation) - { - /* - * requested rotation or reflection not supported by screen - */ - client->errorValue = stuff->rotation; - xfree (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; - xfree (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 (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: - - if (pData) - xfree (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 = WindowTable[pDraw->pScreen->myNum]->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 (client->noClientException); -} - -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; - } - xfree (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}; +/* From render.h */ +#ifndef SubPixelUnknown +#define SubPixelUnknown 0 +#endif + + +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 = WindowTable[pScreen->myNum]; + 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 = WindowTable[pScreen->myNum]; + + se.type = RRScreenChangeNotify + RREventBase; + se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0); + se.timestamp = pScrPriv->lastSetTime.milliseconds; + se.sequenceNumber = client->sequence; + se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + se.root = pRoot->drawable.id; + se.window = pWin->drawable.id; + se.subpixelOrder = PictureGetSubpixelOrder (pScreen); + + se.sequenceNumber = client->sequence; + 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 = WindowTable[pWin->drawable.pScreen->myNum]->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 = WindowTable[pWin->drawable.pScreen->myNum]->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 (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: + + if (pData) + 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 = WindowTable[pDraw->pScreen->myNum]->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/rrtransform.c b/xorg-server/randr/rrtransform.c index 06f62984d..6740e4825 100644 --- a/xorg-server/randr/rrtransform.c +++ b/xorg-server/randr/rrtransform.c @@ -1,285 +1,285 @@ -/* - * 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) -{ - if (transform->params) - xfree (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 = xalloc (nparams * sizeof (xFixed)); - if (!new_params) - return FALSE; - memcpy (new_params, params, nparams * sizeof (xFixed)); - } - else - new_params = NULL; - if (dst->params) - xfree (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-1; f_rot_dy = 0; - rot_cos = F ( 0); rot_sin = F ( 1); - rot_dx = F (height-1); rot_dy = F (0); - break; - case RR_Rotate_180: - f_rot_cos = -1; f_rot_sin = 0; - f_rot_dx = width - 1; f_rot_dy = height - 1; - rot_cos = F (-1); rot_sin = F ( 0); - rot_dx = F (width-1); rot_dy = F ( height-1); - break; - case RR_Rotate_270: - f_rot_cos = 0; f_rot_sin = -1; - f_rot_dx = 0; f_rot_dy = width-1; - rot_cos = F ( 0); rot_sin = F (-1); - rot_dx = F ( 0); rot_dy = F ( width-1); - 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-1; - scale_dx = F(width-1); - } else { - f_scale_dx = height-1; - scale_dx = F(height-1); - } - } - 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-1; - scale_dy = F(height-1); - } else { - f_scale_dy = width-1; - scale_dy = F(width-1); - } - } - - 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) +{ + if (transform->params) + 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; + if (dst->params) + 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-1; f_rot_dy = 0; + rot_cos = F ( 0); rot_sin = F ( 1); + rot_dx = F (height-1); rot_dy = F (0); + break; + case RR_Rotate_180: + f_rot_cos = -1; f_rot_sin = 0; + f_rot_dx = width - 1; f_rot_dy = height - 1; + rot_cos = F (-1); rot_sin = F ( 0); + rot_dx = F (width-1); rot_dy = F ( height-1); + break; + case RR_Rotate_270: + f_rot_cos = 0; f_rot_sin = -1; + f_rot_dx = 0; f_rot_dy = width-1; + rot_cos = F ( 0); rot_sin = F (-1); + rot_dx = F ( 0); rot_dy = F ( width-1); + 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-1; + scale_dx = F(width-1); + } else { + f_scale_dx = height-1; + scale_dx = F(height-1); + } + } + 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-1; + scale_dy = F(height-1); + } else { + f_scale_dy = width-1; + scale_dy = F(width-1); + } + } + + 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/rrxinerama.c b/xorg-server/randr/rrxinerama.c index 94c8e54e5..374789374 100644 --- a/xorg-server/randr/rrxinerama.c +++ b/xorg-server/randr/rrxinerama.c @@ -1,476 +1,476 @@ -/* - * 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. - */ -/* - * This Xinerama implementation comes from the SiS driver which has - * the following notice: - */ -/* - * SiS driver main code - * - * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1) Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2) Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3) The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Thomas Winischhofer - * - driver entirely rewritten since 2001, only basic structure taken from - * old code (except sis_dri.c, sis_shadow.c, sis_accel.c and parts of - * sis_dga.c; these were mostly taken over; sis_dri.c was changed for - * new versions of the DRI layer) - * - * This notice covers the entire driver code unless indicated otherwise. - * - * Formerly based on code which was - * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England. - * Written by: - * Alan Hourihane , - * Mike Chapman , - * Juanjo Santamarta , - * Mitani Hiroshi , - * David Thomas . - */ - -#include "randrstr.h" -#include "swaprep.h" -#include -#include "protocol-versions.h" - -/* Xinerama is not multi-screen capable; just report about screen 0 */ -#define RR_XINERAMA_SCREEN 0 - -static int ProcRRXineramaQueryVersion(ClientPtr client); -static int ProcRRXineramaGetState(ClientPtr client); -static int ProcRRXineramaGetScreenCount(ClientPtr client); -static int ProcRRXineramaGetScreenSize(ClientPtr client); -static int ProcRRXineramaIsActive(ClientPtr client); -static int ProcRRXineramaQueryScreens(ClientPtr client); -static int SProcRRXineramaDispatch(ClientPtr client); - -/* Proc */ - -int -ProcRRXineramaQueryVersion(ClientPtr client) -{ - xPanoramiXQueryVersionReply rep; - register int n; - - REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_RRXINERAMA_MAJOR_VERSION; - rep.minorVersion = SERVER_RRXINERAMA_MINOR_VERSION; - if(client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); - return (client->noClientException); -} - -int -ProcRRXineramaGetState(ClientPtr client) -{ - REQUEST(xPanoramiXGetStateReq); - WindowPtr pWin; - xPanoramiXGetStateReply rep; - register int n, rc; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - Bool active = FALSE; - - REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if(rc != Success) - return rc; - - pScreen = pWin->drawable.pScreen; - pScrPriv = rrGetScrPriv(pScreen); - if (pScrPriv) - { - /* XXX do we need more than this? */ - active = TRUE; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.state = active; - rep.window = stuff->window; - if(client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.window, n); - } - WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); - return client->noClientException; -} - -static Bool -RRXineramaCrtcActive (RRCrtcPtr crtc) -{ - return crtc->mode != NULL && crtc->numOutputs > 0; -} - -static int -RRXineramaScreenCount (ScreenPtr pScreen) -{ - int i, n; - - n = 0; - if (rrGetScrPriv (pScreen)) - { - rrScrPriv(pScreen); - for (i = 0; i < pScrPriv->numCrtcs; i++) - if (RRXineramaCrtcActive (pScrPriv->crtcs[i])) - n++; - } - return n; -} - -static Bool -RRXineramaScreenActive (ScreenPtr pScreen) -{ - return RRXineramaScreenCount (pScreen) > 0; -} - -int -ProcRRXineramaGetScreenCount(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenCountReq); - WindowPtr pWin; - xPanoramiXGetScreenCountReply rep; - register int n, rc; - - REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.ScreenCount = RRXineramaScreenCount (pWin->drawable.pScreen); - rep.window = stuff->window; - if(client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.window, n); - } - WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); - return client->noClientException; -} - -int -ProcRRXineramaGetScreenSize(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenSizeReq); - WindowPtr pWin, pRoot; - ScreenPtr pScreen; - xPanoramiXGetScreenSizeReply rep; - register int n, rc; - - REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - pScreen = pWin->drawable.pScreen; - pRoot = WindowTable[pScreen->myNum]; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.width = pRoot->drawable.width; - rep.height = pRoot->drawable.height; - rep.window = stuff->window; - rep.screen = stuff->screen; - if(client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.width, n); - swapl(&rep.height, n); - swapl(&rep.window, n); - swapl(&rep.screen, n); - } - WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); - return client->noClientException; -} - -int -ProcRRXineramaIsActive(ClientPtr client) -{ - xXineramaIsActiveReply rep; - - REQUEST_SIZE_MATCH(xXineramaIsActiveReq); - - memset(&rep, 0, sizeof(xXineramaIsActiveReply)); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.state = RRXineramaScreenActive (screenInfo.screens[RR_XINERAMA_SCREEN]); - if(client->swapped) { - register int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.state, n); - } - WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); - return client->noClientException; -} - -static void -RRXineramaWriteCrtc(ClientPtr client, RRCrtcPtr crtc) -{ - xXineramaScreenInfo scratch; - - if (RRXineramaCrtcActive (crtc)) - { - ScreenPtr pScreen = crtc->pScreen; - rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen); - BoxRec panned_area; - - /* Check to see if crtc is panned and return the full area when applicable. */ - if (pScrPriv && pScrPriv->rrGetPanning && - pScrPriv->rrGetPanning (pScreen, crtc, &panned_area, NULL, NULL) && - (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1)) { - scratch.x_org = panned_area.x1; - scratch.y_org = panned_area.y1; - scratch.width = panned_area.x2 - panned_area.x1; - scratch.height = panned_area.y2 - panned_area.y1; - } else { - int width, height; - RRCrtcGetScanoutSize (crtc, &width, &height); - scratch.x_org = crtc->x; - scratch.y_org = crtc->y; - scratch.width = width; - scratch.height = height; - } - if(client->swapped) { - register int n; - swaps(&scratch.x_org, n); - swaps(&scratch.y_org, n); - swaps(&scratch.width, n); - swaps(&scratch.height, n); - } - WriteToClient(client, sz_XineramaScreenInfo, &scratch); - } -} - -int -ProcRRXineramaQueryScreens(ClientPtr client) -{ - xXineramaQueryScreensReply rep; - ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN]; - - REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); - - if (RRXineramaScreenActive (pScreen)) - RRGetInfo (pScreen, FALSE); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.number = RRXineramaScreenCount (pScreen); - rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo); - if(client->swapped) { - register int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.number, n); - } - WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); - - if(rep.number) { - rrScrPriv(pScreen); - int i; - int has_primary = 0; - - if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) { - has_primary = 1; - RRXineramaWriteCrtc(client, pScrPriv->primaryOutput->crtc); - } - - for(i = 0; i < pScrPriv->numCrtcs; i++) { - if (has_primary && - pScrPriv->primaryOutput->crtc == pScrPriv->crtcs[i]) - { - has_primary = 0; - continue; - } - RRXineramaWriteCrtc(client, pScrPriv->crtcs[i]); - } - } - - return client->noClientException; -} - -static int -ProcRRXineramaDispatch(ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) { - case X_PanoramiXQueryVersion: - return ProcRRXineramaQueryVersion(client); - case X_PanoramiXGetState: - return ProcRRXineramaGetState(client); - case X_PanoramiXGetScreenCount: - return ProcRRXineramaGetScreenCount(client); - case X_PanoramiXGetScreenSize: - return ProcRRXineramaGetScreenSize(client); - case X_XineramaIsActive: - return ProcRRXineramaIsActive(client); - case X_XineramaQueryScreens: - return ProcRRXineramaQueryScreens(client); - } - return BadRequest; -} - -/* SProc */ - -static int -SProcRRXineramaQueryVersion (ClientPtr client) -{ - REQUEST(xPanoramiXQueryVersionReq); - register int n; - swaps(&stuff->length,n); - REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); - return ProcRRXineramaQueryVersion(client); -} - -static int -SProcRRXineramaGetState(ClientPtr client) -{ - REQUEST(xPanoramiXGetStateReq); - register int n; - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); - swapl (&stuff->window, n); - return ProcRRXineramaGetState(client); -} - -static int -SProcRRXineramaGetScreenCount(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenCountReq); - register int n; - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); - swapl (&stuff->window, n); - return ProcRRXineramaGetScreenCount(client); -} - -static int -SProcRRXineramaGetScreenSize(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenSizeReq); - register int n; - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); - swapl (&stuff->window, n); - swapl (&stuff->screen, n); - return ProcRRXineramaGetScreenSize(client); -} - -static int -SProcRRXineramaIsActive(ClientPtr client) -{ - REQUEST(xXineramaIsActiveReq); - register int n; - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xXineramaIsActiveReq); - return ProcRRXineramaIsActive(client); -} - -static int -SProcRRXineramaQueryScreens(ClientPtr client) -{ - REQUEST(xXineramaQueryScreensReq); - register int n; - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); - return ProcRRXineramaQueryScreens(client); -} - -int -SProcRRXineramaDispatch(ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) { - case X_PanoramiXQueryVersion: - return SProcRRXineramaQueryVersion(client); - case X_PanoramiXGetState: - return SProcRRXineramaGetState(client); - case X_PanoramiXGetScreenCount: - return SProcRRXineramaGetScreenCount(client); - case X_PanoramiXGetScreenSize: - return SProcRRXineramaGetScreenSize(client); - case X_XineramaIsActive: - return SProcRRXineramaIsActive(client); - case X_XineramaQueryScreens: - return SProcRRXineramaQueryScreens(client); - } - return BadRequest; -} - -void -RRXineramaExtensionInit(void) -{ -#ifdef PANORAMIX - if(!noPanoramiXExtension) - return; -#endif - - /* - * Xinerama isn't capable enough to have multiple protocol screens each - * with their own output geometry. So if there's more than one protocol - * screen, just don't even try. - */ - if (screenInfo.numScreens > 1) - return; - - (void) AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, - ProcRRXineramaDispatch, - SProcRRXineramaDispatch, - NULL, - StandardMinorOpcode); -} +/* + * 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. + */ +/* + * This Xinerama implementation comes from the SiS driver which has + * the following notice: + */ +/* + * SiS driver main code + * + * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1) Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2) Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3) The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Thomas Winischhofer + * - driver entirely rewritten since 2001, only basic structure taken from + * old code (except sis_dri.c, sis_shadow.c, sis_accel.c and parts of + * sis_dga.c; these were mostly taken over; sis_dri.c was changed for + * new versions of the DRI layer) + * + * This notice covers the entire driver code unless indicated otherwise. + * + * Formerly based on code which was + * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England. + * Written by: + * Alan Hourihane , + * Mike Chapman , + * Juanjo Santamarta , + * Mitani Hiroshi , + * David Thomas . + */ + +#include "randrstr.h" +#include "swaprep.h" +#include +#include "protocol-versions.h" + +/* Xinerama is not multi-screen capable; just report about screen 0 */ +#define RR_XINERAMA_SCREEN 0 + +static int ProcRRXineramaQueryVersion(ClientPtr client); +static int ProcRRXineramaGetState(ClientPtr client); +static int ProcRRXineramaGetScreenCount(ClientPtr client); +static int ProcRRXineramaGetScreenSize(ClientPtr client); +static int ProcRRXineramaIsActive(ClientPtr client); +static int ProcRRXineramaQueryScreens(ClientPtr client); +static int SProcRRXineramaDispatch(ClientPtr client); + +/* Proc */ + +int +ProcRRXineramaQueryVersion(ClientPtr client) +{ + xPanoramiXQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_RRXINERAMA_MAJOR_VERSION; + rep.minorVersion = SERVER_RRXINERAMA_MINOR_VERSION; + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); + return Success; +} + +int +ProcRRXineramaGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + WindowPtr pWin; + xPanoramiXGetStateReply rep; + register int n, rc; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + Bool active = FALSE; + + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if(rc != Success) + return rc; + + pScreen = pWin->drawable.pScreen; + pScrPriv = rrGetScrPriv(pScreen); + if (pScrPriv) + { + /* XXX do we need more than this? */ + active = TRUE; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = active; + rep.window = stuff->window; + if(client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.window, n); + } + WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); + return Success; +} + +static Bool +RRXineramaCrtcActive (RRCrtcPtr crtc) +{ + return crtc->mode != NULL && crtc->numOutputs > 0; +} + +static int +RRXineramaScreenCount (ScreenPtr pScreen) +{ + int i, n; + + n = 0; + if (rrGetScrPriv (pScreen)) + { + rrScrPriv(pScreen); + for (i = 0; i < pScrPriv->numCrtcs; i++) + if (RRXineramaCrtcActive (pScrPriv->crtcs[i])) + n++; + } + return n; +} + +static Bool +RRXineramaScreenActive (ScreenPtr pScreen) +{ + return RRXineramaScreenCount (pScreen) > 0; +} + +int +ProcRRXineramaGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + WindowPtr pWin; + xPanoramiXGetScreenCountReply rep; + register int n, rc; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.ScreenCount = RRXineramaScreenCount (pWin->drawable.pScreen); + rep.window = stuff->window; + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.window, n); + } + WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); + return Success; +} + +int +ProcRRXineramaGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + WindowPtr pWin, pRoot; + ScreenPtr pScreen; + xPanoramiXGetScreenSizeReply rep; + register int n, rc; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + pScreen = pWin->drawable.pScreen; + pRoot = WindowTable[pScreen->myNum]; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.width = pRoot->drawable.width; + rep.height = pRoot->drawable.height; + rep.window = stuff->window; + rep.screen = stuff->screen; + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.width, n); + swapl(&rep.height, n); + swapl(&rep.window, n); + swapl(&rep.screen, n); + } + WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); + return Success; +} + +int +ProcRRXineramaIsActive(ClientPtr client) +{ + xXineramaIsActiveReply rep; + + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + + memset(&rep, 0, sizeof(xXineramaIsActiveReply)); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = RRXineramaScreenActive (screenInfo.screens[RR_XINERAMA_SCREEN]); + if(client->swapped) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.state, n); + } + WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); + return Success; +} + +static void +RRXineramaWriteCrtc(ClientPtr client, RRCrtcPtr crtc) +{ + xXineramaScreenInfo scratch; + + if (RRXineramaCrtcActive (crtc)) + { + ScreenPtr pScreen = crtc->pScreen; + rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen); + BoxRec panned_area; + + /* Check to see if crtc is panned and return the full area when applicable. */ + if (pScrPriv && pScrPriv->rrGetPanning && + pScrPriv->rrGetPanning (pScreen, crtc, &panned_area, NULL, NULL) && + (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1)) { + scratch.x_org = panned_area.x1; + scratch.y_org = panned_area.y1; + scratch.width = panned_area.x2 - panned_area.x1; + scratch.height = panned_area.y2 - panned_area.y1; + } else { + int width, height; + RRCrtcGetScanoutSize (crtc, &width, &height); + scratch.x_org = crtc->x; + scratch.y_org = crtc->y; + scratch.width = width; + scratch.height = height; + } + if(client->swapped) { + register int n; + swaps(&scratch.x_org, n); + swaps(&scratch.y_org, n); + swaps(&scratch.width, n); + swaps(&scratch.height, n); + } + WriteToClient(client, sz_XineramaScreenInfo, &scratch); + } +} + +int +ProcRRXineramaQueryScreens(ClientPtr client) +{ + xXineramaQueryScreensReply rep; + ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN]; + + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + + if (RRXineramaScreenActive (pScreen)) + RRGetInfo (pScreen, FALSE); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.number = RRXineramaScreenCount (pScreen); + rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo); + if(client->swapped) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.number, n); + } + WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); + + if(rep.number) { + rrScrPriv(pScreen); + int i; + int has_primary = 0; + + if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) { + has_primary = 1; + RRXineramaWriteCrtc(client, pScrPriv->primaryOutput->crtc); + } + + for(i = 0; i < pScrPriv->numCrtcs; i++) { + if (has_primary && + pScrPriv->primaryOutput->crtc == pScrPriv->crtcs[i]) + { + has_primary = 0; + continue; + } + RRXineramaWriteCrtc(client, pScrPriv->crtcs[i]); + } + } + + return Success; +} + +static int +ProcRRXineramaDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_PanoramiXQueryVersion: + return ProcRRXineramaQueryVersion(client); + case X_PanoramiXGetState: + return ProcRRXineramaGetState(client); + case X_PanoramiXGetScreenCount: + return ProcRRXineramaGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return ProcRRXineramaGetScreenSize(client); + case X_XineramaIsActive: + return ProcRRXineramaIsActive(client); + case X_XineramaQueryScreens: + return ProcRRXineramaQueryScreens(client); + } + return BadRequest; +} + +/* SProc */ + +static int +SProcRRXineramaQueryVersion (ClientPtr client) +{ + REQUEST(xPanoramiXQueryVersionReq); + register int n; + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); + return ProcRRXineramaQueryVersion(client); +} + +static int +SProcRRXineramaGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + swapl (&stuff->window, n); + return ProcRRXineramaGetState(client); +} + +static int +SProcRRXineramaGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + swapl (&stuff->window, n); + return ProcRRXineramaGetScreenCount(client); +} + +static int +SProcRRXineramaGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + swapl (&stuff->window, n); + swapl (&stuff->screen, n); + return ProcRRXineramaGetScreenSize(client); +} + +static int +SProcRRXineramaIsActive(ClientPtr client) +{ + REQUEST(xXineramaIsActiveReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + return ProcRRXineramaIsActive(client); +} + +static int +SProcRRXineramaQueryScreens(ClientPtr client) +{ + REQUEST(xXineramaQueryScreensReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + return ProcRRXineramaQueryScreens(client); +} + +int +SProcRRXineramaDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_PanoramiXQueryVersion: + return SProcRRXineramaQueryVersion(client); + case X_PanoramiXGetState: + return SProcRRXineramaGetState(client); + case X_PanoramiXGetScreenCount: + return SProcRRXineramaGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return SProcRRXineramaGetScreenSize(client); + case X_XineramaIsActive: + return SProcRRXineramaIsActive(client); + case X_XineramaQueryScreens: + return SProcRRXineramaQueryScreens(client); + } + return BadRequest; +} + +void +RRXineramaExtensionInit(void) +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return; +#endif + + /* + * Xinerama isn't capable enough to have multiple protocol screens each + * with their own output geometry. So if there's more than one protocol + * screen, just don't even try. + */ + if (screenInfo.numScreens > 1) + return; + + (void) AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, + ProcRRXineramaDispatch, + SProcRRXineramaDispatch, + NULL, + StandardMinorOpcode); +} -- cgit v1.2.3