diff options
Diffstat (limited to 'nx-X11/programs/Xserver/randr')
20 files changed, 6432 insertions, 944 deletions
diff --git a/nx-X11/programs/Xserver/randr/Imakefile b/nx-X11/programs/Xserver/randr/Imakefile index 312dfb438..8dc8de1b7 100644 --- a/nx-X11/programs/Xserver/randr/Imakefile +++ b/nx-X11/programs/Xserver/randr/Imakefile @@ -24,11 +24,15 @@ XCOMM $XFree86: xc/programs/Xserver/randr/Imakefile,v 1.1 2001/05/23 03:29:44 ke rrdispatch.c \ rrinfo.c \ rrmode.c \ + rrmonitor.c \ rroutput.c \ rrpointer.c \ rrproperty.c \ + rrprovider.c \ + rrproviderproperty.c \ rrscreen.c \ rrsdispatch.c \ + rrtransform.c \ rrxinerama.c \ $(NULL) @@ -37,11 +41,15 @@ XCOMM $XFree86: xc/programs/Xserver/randr/Imakefile,v 1.1 2001/05/23 03:29:44 ke rrdispatch.o \ rrinfo.o \ rrmode.o \ + rrmonitor.o \ rroutput.o \ rrpointer.o \ rrproperty.o \ + rrprovider.o \ + rrproviderproperty.o \ rrscreen.o \ rrsdispatch.o \ + rrtransform.o \ rrxinerama.o \ $(NULL) @@ -50,9 +58,20 @@ XCOMM $XFree86: xc/programs/Xserver/randr/Imakefile,v 1.1 2001/05/23 03:29:44 ke -I../render \ `pkg-config --cflags-only-I pixman-1` +#if defined(BuildXinerama) + PNRX_DEFINES = -DXINERAMA -DPANORAMIX +#endif + +#if defined(NXAgentServer) + NX_DEFINES = -DNXAGENT_SERVER +#endif + LINTLIBS = ../dix/llib-ldix.ln ../os/llib-los.ln - DEFINES = -DNXAGENT_SERVER + DEFINES = \ + $(PNRX_DEFINES) \ + $(NX_DEFINES) \ + $(NULL) NormalLibraryTarget(randr,$(OBJS)) NormalLibraryObjectRule() diff --git a/nx-X11/programs/Xserver/randr/randr.c b/nx-X11/programs/Xserver/randr/randr.c index 1cb7e5b77..b78a947c8 100644 --- a/nx-X11/programs/Xserver/randr/randr.c +++ b/nx-X11/programs/Xserver/randr/randr.c @@ -50,6 +50,10 @@ #include "randrstr.h" +#ifndef NXAGENT_SERVER +#include "extinit.h" +#endif + /* From render.h */ #ifndef SubPixelUnknown #define SubPixelUnknown 0 @@ -59,12 +63,12 @@ static int RRNScreens; #define wrap(priv,real,mem,func) {\ - priv->mem = real->mem; \ - real->mem = func; \ + ((ScreenPtr)priv)->mem = ((ScreenPtr)real)->mem; \ + ((ScreenPtr)real)->mem = func; \ } #define unwrap(priv,real,mem) {\ - real->mem = priv->mem; \ + ((ScreenPtr)real)->mem = ((ScreenPtr)priv)->mem; \ } static int ProcRRDispatch(ClientPtr pClient); @@ -106,13 +110,12 @@ RRClientCallback(CallbackListPtr *list, void *closure, void *data) } } -static void -RRResetProc(ExtensionEntry * extEntry) -{ -} - static Bool -RRCloseScreen(int i, ScreenPtr pScreen) +RRCloseScreen( +#ifdef NXAGENT_SERVER + int i, +#endif + ScreenPtr pScreen) { rrScrPriv(pScreen); int j; @@ -123,6 +126,11 @@ RRCloseScreen(int i, ScreenPtr pScreen) for (j = pScrPriv->numOutputs - 1; j >= 0; j--) RROutputDestroy(pScrPriv->outputs[j]); + if (pScrPriv->provider) + RRProviderDestroy(pScrPriv->provider); + + RRMonitorClose(pScreen); + xfree(pScrPriv->crtcs); xfree(pScrPriv->outputs); xfree(pScrPriv); @@ -142,11 +150,11 @@ SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent * from, 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); - cpswaps(from->subpixelOrder, to->subpixelOrder); } static void @@ -160,8 +168,8 @@ SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent * from, cpswapl(from->window, to->window); cpswapl(from->crtc, to->crtc); cpswapl(from->mode, to->mode); - cpswapl(from->window, to->window); cpswaps(from->rotation, to->rotation); + /* pad1 */ cpswaps(from->x, to->x); cpswaps(from->y, to->y); cpswaps(from->width, to->width); @@ -182,6 +190,8 @@ SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent * from, 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 @@ -195,6 +205,52 @@ SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent * from, 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 +SRRProviderChangeNotifyEvent(xRRProviderChangeNotifyEvent * from, + xRRProviderChangeNotifyEvent * 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->provider, to->provider); +} + +static void +SRRProviderPropertyNotifyEvent(xRRProviderPropertyNotifyEvent * from, + xRRProviderPropertyNotifyEvent * to) +{ + to->type = from->type; + to->subCode = from->subCode; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->window, to->window); + cpswapl(from->provider, to->provider); + cpswapl(from->atom, to->atom); + cpswapl(from->timestamp, to->timestamp); + to->state = from->state; + /* pad1 */ + /* pad2 */ + /* pad3 */ + /* pad4 */ +} + +static void +SRRResourceChangeNotifyEvent(xRRResourceChangeNotifyEvent * from, + xRRResourceChangeNotifyEvent * to) +{ + to->type = from->type; + to->subCode = from->subCode; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->window, to->window); } static void @@ -213,6 +269,17 @@ SRRNotifyEvent(xEvent *from, xEvent *to) SRROutputPropertyNotifyEvent((xRROutputPropertyNotifyEvent *) from, (xRROutputPropertyNotifyEvent *) to); break; + case RRNotify_ProviderChange: + SRRProviderChangeNotifyEvent((xRRProviderChangeNotifyEvent *) from, + (xRRProviderChangeNotifyEvent *) to); + break; + case RRNotify_ProviderProperty: + SRRProviderPropertyNotifyEvent((xRRProviderPropertyNotifyEvent *) from, + (xRRProviderPropertyNotifyEvent *) to); + break; + case RRNotify_ResourceChange: + SRRResourceChangeNotifyEvent((xRRResourceChangeNotifyEvent *) from, + (xRRResourceChangeNotifyEvent *) to); default: break; } @@ -234,8 +301,15 @@ RRInit(void) return FALSE; if (!RROutputInit()) return FALSE; + if (!RRProviderInit()) + return FALSE; RRGeneration = serverGeneration; } +#ifndef NXAGENT_SERVER + if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; +#endif /* !defined(NXAGENT_SERVER) */ + return TRUE; } @@ -291,11 +365,15 @@ RRScreenInit(ScreenPtr pScreen) wrap(pScrPriv, pScreen, CloseScreen, RRCloseScreen); + pScreen->ConstrainCursorHarder = RRConstrainCursorHarder; + pScreen->ReplaceScanoutPixmap = RRReplaceScanoutPixmap; pScrPriv->numOutputs = 0; pScrPriv->outputs = NULL; pScrPriv->numCrtcs = 0; pScrPriv->crtcs = NULL; + RRMonitorInit(pScreen); + RRNScreens += 1; /* keep count of screens that implement randr */ return TRUE; } @@ -309,7 +387,13 @@ RRFreeClient(void *data, XID id) pRREvent = (RREventPtr) data; pWin = pRREvent->window; +#ifndef NXAGENT_SERVER + dixLookupResourceByType((void **) &pHead, pWin->drawable.id, + RREventType, serverClient, DixDestroyAccess); +#else /* !defined(NXAGENT_SERVER) */ pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, RREventType); +#endif /* !defined(NXAGENT_SERVER) */ + if (pHead) { pPrev = 0; for (pCur = *pHead; pCur && pCur != pRREvent; pCur = pCur->next) @@ -349,29 +433,38 @@ RRExtensionInit(void) return; #ifndef NXAGENT_SERVER - if (!dixRequestPrivate(RRClientPrivateKey, - sizeof(RRClientRec) + - screenInfo.numScreens * sizeof(RRTimesRec))) + if (!dixRegisterPrivateKey(&RRClientPrivateKeyRec, PRIVATE_CLIENT, + sizeof(RRClientRec) + + screenInfo.numScreens * sizeof(RRTimesRec))) return; -#else +#else /* !defined(NXAGENT_SERVER) */ RRClientPrivateIndex = AllocateClientPrivateIndex(); if (!AllocateClientPrivate(RRClientPrivateIndex, sizeof(RRClientRec) + screenInfo.numScreens * sizeof(RRTimesRec))) return; -#endif +#endif /* !defined(NXAGENT_SERVER) */ + if (!AddCallback(&ClientStateCallback, RRClientCallback, 0)) return; - RRClientType = CreateNewResourceType(RRFreeClient); + RRClientType = CreateNewResourceType(RRFreeClient +#ifndef NXAGENT_SERVER + , "RandRClient" +#endif + ); if (!RRClientType) return; - RREventType = CreateNewResourceType(RRFreeEvents); + RREventType = CreateNewResourceType(RRFreeEvents +#ifndef NXAGENT_SERVER + , "RandREvent" +#endif + ); if (!RREventType) return; extEntry = AddExtension(RANDR_NAME, RRNumberEvents, RRNumberErrors, ProcRRDispatch, SProcRRDispatch, - RRResetProc, StandardMinorOpcode); + NULL, StandardMinorOpcode); if (!extEntry) return; RRErrorBase = extEntry->errorBase; @@ -380,11 +473,45 @@ RRExtensionInit(void) SRRScreenChangeNotifyEvent; EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr) SRRNotifyEvent; + + RRModeInitErrorValue(); + RRCrtcInitErrorValue(); + RROutputInitErrorValue(); + RRProviderInitErrorValue(); #ifdef PANORAMIX RRXineramaExtensionInit(); #endif } +void +RRResourcesChanged(ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + pScrPriv->resourcesChanged = TRUE; + + RRSetChanged(pScreen); +} + +static void +RRDeliverResourceEvent(ClientPtr client, WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + rrScrPriv(pScreen); + + xRRResourceChangeNotifyEvent re = { + .type = RRNotify + RREventBase, + .subCode = RRNotify_ResourceChange, +#ifdef NXAGENT_SERVER + .sequenceNumber = client->sequence, +#endif + .timestamp = pScrPriv->lastSetTime.milliseconds, + .window = pWin->drawable.id + }; + + WriteEventsToClient(client, 1, (xEvent *) &re); +} + static int TellChanged(WindowPtr pWin, void *value) { @@ -392,10 +519,20 @@ TellChanged(WindowPtr pWin, void *value) ClientPtr client; ScreenPtr pScreen = pWin->drawable.pScreen; +#ifndef NXAGENT_SERVER + ScreenPtr iter; + rrScrPrivPtr pSlaveScrPriv; +#endif + rrScrPriv(pScreen); int i; +#ifndef NXAGENT_SERVER + dixLookupResourceByType((void **) &pHead, pWin->drawable.id, + RREventType, serverClient, DixReadAccess); +#else /* !defined(NXAGENT_SERVER) */ pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, RREventType); +#endif /* !defined(NXAGENT_SERVER) */ if (!pHead) return WT_WALKCHILDREN; @@ -414,6 +551,18 @@ TellChanged(WindowPtr pWin, void *value) if (crtc->changed) RRDeliverCrtcEvent(client, pWin, crtc); } + +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) { + pSlaveScrPriv = rrGetScrPriv(iter); + for (i = 0; i < pSlaveScrPriv->numCrtcs; i++) { + RRCrtcPtr crtc = pSlaveScrPriv->crtcs[i]; + + if (crtc->changed) + RRDeliverCrtcEvent(client, pWin, crtc); + } + } +#endif } if (pRREvent->mask & RROutputChangeNotifyMask) { @@ -423,36 +572,146 @@ TellChanged(WindowPtr pWin, void *value) if (output->changed) RRDeliverOutputEvent(client, pWin, output); } + +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) { + pSlaveScrPriv = rrGetScrPriv(iter); + for (i = 0; i < pSlaveScrPriv->numOutputs; i++) { + RROutputPtr output = pSlaveScrPriv->outputs[i]; + + if (output->changed) + RRDeliverOutputEvent(client, pWin, output); + } + } +#endif + } + +#ifndef NXAGENT_SERVER + if (pRREvent->mask & RRProviderChangeNotifyMask) { + xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) { + pSlaveScrPriv = rrGetScrPriv(iter); + if (pSlaveScrPriv->provider->changed) + RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider); + } + xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) { + pSlaveScrPriv = rrGetScrPriv(iter); + if (pSlaveScrPriv->provider->changed) + RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider); + } + xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) { + pSlaveScrPriv = rrGetScrPriv(iter); + if (pSlaveScrPriv->provider->changed) + RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider); + } + } +#endif + + if (pRREvent->mask & RRResourceChangeNotifyMask) { + if (pScrPriv->resourcesChanged) { + RRDeliverResourceEvent(client, pWin); + } } } return WT_WALKCHILDREN; } +void +RRSetChanged(ScreenPtr pScreen) +{ +#ifndef NXAGENT_SERVER + /* set changed bits on the master screen only */ + ScreenPtr master; + + rrScrPriv(pScreen); + rrScrPrivPtr mastersp; + + if (pScreen->isGPU) { + master = pScreen->current_master; + if (!master) + return; + mastersp = rrGetScrPriv(master); + } + else + { + master = pScreen; + mastersp = pScrPriv; + } + + mastersp->changed = TRUE; +#else /* !defined(NXAGENT_SERVER) */ + rrScrPriv(pScreen); + pScrPriv->changed = TRUE; +#endif +} + /* * Something changed; send events and adjust pointer position */ void RRTellChanged(ScreenPtr pScreen) { + ScreenPtr master; rrScrPriv(pScreen); + rrScrPrivPtr mastersp; int i; +#ifndef NXAGENT_SERVER + ScreenPtr iter; + rrScrPrivPtr pSlaveScrPriv; +#endif - if (pScrPriv->changed) { - UpdateCurrentTime(); - if (pScrPriv->configChanged) { - pScrPriv->lastConfigTime = currentTime; - pScrPriv->configChanged = FALSE; +#ifndef NXAGENT_SERVER + if (pScreen->isGPU) { + master = pScreen->current_master; + mastersp = rrGetScrPriv(master); + } + else +#endif + { + master = pScreen; + mastersp = pScrPriv; + } + + if (mastersp->changed) { + UpdateCurrentTimeIf(); + if (mastersp->configChanged) { + mastersp->lastConfigTime = currentTime; + mastersp->configChanged = FALSE; } pScrPriv->changed = FALSE; - WalkTree(pScreen, TellChanged, (void *) pScreen); + mastersp->changed = FALSE; + + WalkTree(master, TellChanged, (void *) master); + + mastersp->resourcesChanged = FALSE; + 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) { + +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(iter, &master->output_slave_list, output_head) { + pSlaveScrPriv = rrGetScrPriv(iter); + pSlaveScrPriv->provider->changed = FALSE; + for (i = 0; i < pSlaveScrPriv->numOutputs; i++) + pSlaveScrPriv->outputs[i]->changed = FALSE; + for (i = 0; i < pSlaveScrPriv->numCrtcs; i++) + pSlaveScrPriv->crtcs[i]->changed = FALSE; + } + xorg_list_for_each_entry(iter, &master->offload_slave_list, offload_head) { + pSlaveScrPriv = rrGetScrPriv(iter); + pSlaveScrPriv->provider->changed = FALSE; + } + xorg_list_for_each_entry(iter, &master->unattached_list, unattached_head) { + pSlaveScrPriv = rrGetScrPriv(iter); + pSlaveScrPriv->provider->changed = FALSE; + } +#endif /* !defined(NXAGENT_SERVER) */ + + if (mastersp->layoutChanged) { pScrPriv->layoutChanged = FALSE; - RRPointerScreenConfigured(pScreen); - RRSendConfigNotify(pScreen); + RRPointerScreenConfigured(master); + RRSendConfigNotify(master); } } } @@ -468,6 +727,12 @@ RRFirstOutput(ScreenPtr pScreen) RROutputPtr output; int i, j; + if (!pScrPriv) + return NULL; + + if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) + return pScrPriv->primaryOutput; + for (i = 0; i < pScrPriv->numCrtcs; i++) { RRCrtcPtr crtc = pScrPriv->crtcs[i]; @@ -500,6 +765,7 @@ ProcRRDispatch(ClientPtr client) REQUEST(xReq); if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data]) return BadRequest; + UpdateCurrentTimeIf(); return (*ProcRandrVector[stuff->data]) (client); } @@ -507,7 +773,8 @@ static int SProcRRDispatch(ClientPtr client) { REQUEST(xReq); - if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data]) + if (stuff->data >= RRNumberRequests || !SProcRandrVector[stuff->data]) return BadRequest; + UpdateCurrentTimeIf(); return (*SProcRandrVector[stuff->data]) (client); } diff --git a/nx-X11/programs/Xserver/randr/randr.h b/nx-X11/programs/Xserver/randr/randr.h index a3ef56c77..2018b372e 100644 --- a/nx-X11/programs/Xserver/randr/randr.h +++ b/nx-X11/programs/Xserver/randr/randr.h @@ -2,6 +2,7 @@ * Copyright © 2000 Compaq Computer Corporation * Copyright © 2002 Hewlett Packard Company * Copyright © 2006 Intel Corporation + * Copyright © 2008 Red Hat, Inc. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -39,11 +40,11 @@ typedef unsigned long XRandrModeFlags; #define RANDR_NAME "RANDR" #define RANDR_MAJOR 1 -#define RANDR_MINOR 2 +#define RANDR_MINOR 5 -#define RRNumberErrors 3 +#define RRNumberErrors 4 #define RRNumberEvents 2 -#define RRNumberRequests 25 +#define RRNumberRequests 45 #define X_RRQueryVersion 0 /* we skip 1 to make old clients fail pretty immediately */ @@ -77,12 +78,47 @@ typedef unsigned long XRandrModeFlags; #define X_RRGetCrtcGamma 23 #define X_RRSetCrtcGamma 24 +/* V1.3 additions */ +#define X_RRGetScreenResourcesCurrent 25 +#define X_RRSetCrtcTransform 26 +#define X_RRGetCrtcTransform 27 +#define X_RRGetPanning 28 +#define X_RRSetPanning 29 +#define X_RRSetOutputPrimary 30 +#define X_RRGetOutputPrimary 31 + +#define RRTransformUnit (1L << 0) +#define RRTransformScaleUp (1L << 1) +#define RRTransformScaleDown (1L << 2) +#define RRTransformProjective (1L << 3) + +/* v1.4 */ +#define X_RRGetProviders 32 +#define X_RRGetProviderInfo 33 +#define X_RRSetProviderOffloadSink 34 +#define X_RRSetProviderOutputSource 35 +#define X_RRListProviderProperties 36 +#define X_RRQueryProviderProperty 37 +#define X_RRConfigureProviderProperty 38 +#define X_RRChangeProviderProperty 39 +#define X_RRDeleteProviderProperty 40 +#define X_RRGetProviderProperty 41 + +/* v1.5 */ +#define X_RRGetMonitors 42 +#define X_RRSetMonitor 43 +#define X_RRDeleteMonitor 44 + /* Event selection bits */ #define RRScreenChangeNotifyMask (1L << 0) /* V1.2 additions */ #define RRCrtcChangeNotifyMask (1L << 1) #define RROutputChangeNotifyMask (1L << 2) #define RROutputPropertyNotifyMask (1L << 3) +/* V1.4 additions */ +#define RRProviderChangeNotifyMask (1L << 4) +#define RRProviderPropertyNotifyMask (1L << 5) +#define RRResourceChangeNotifyMask (1L << 6) /* Event codes */ #define RRScreenChangeNotify 0 @@ -92,7 +128,9 @@ typedef unsigned long XRandrModeFlags; #define RRNotify_CrtcChange 0 #define RRNotify_OutputChange 1 #define RRNotify_OutputProperty 2 - +#define RRNotify_ProviderChange 3 +#define RRNotify_ProviderProperty 4 +#define RRNotify_ResourceChange 5 /* used in the rotation field; rotation and reflection in 0.1 proto. */ #define RR_Rotate_0 1 #define RR_Rotate_90 2 @@ -133,9 +171,28 @@ typedef unsigned long XRandrModeFlags; #define BadRROutput 0 #define BadRRCrtc 1 #define BadRRMode 2 +#define BadRRProvider 3 /* Conventional RandR output properties */ -#define RR_PROPERTY_RANDR_EDID "RANDR_EDID" +#define RR_PROPERTY_BACKLIGHT "Backlight" +#define RR_PROPERTY_RANDR_EDID "EDID" +#define RR_PROPERTY_SIGNAL_FORMAT "SignalFormat" +#define RR_PROPERTY_SIGNAL_PROPERTIES "SignalProperties" +#define RR_PROPERTY_CONNECTOR_TYPE "ConnectorType" +#define RR_PROPERTY_CONNECTOR_NUMBER "ConnectorNumber" +#define RR_PROPERTY_COMPATIBILITY_LIST "CompatibilityList" +#define RR_PROPERTY_CLONE_LIST "CloneList" +#define RR_PROPERTY_BORDER "Border" +#define RR_PROPERTY_BORDER_DIMENSIONS "BorderDimensions" +#define RR_PROPERTY_GUID "GUID" +#define RR_PROPERTY_RANDR_TILE "TILE" + +/* roles this device can carry out */ +#define RR_Capability_None 0 +#define RR_Capability_SourceOutput 1 +#define RR_Capability_SinkOutput 2 +#define RR_Capability_SourceOffload 4 +#define RR_Capability_SinkOffload 8 #endif /* _RANDR_H_ */ diff --git a/nx-X11/programs/Xserver/randr/randrproto.h b/nx-X11/programs/Xserver/randr/randrproto.h index be5b7adb5..116666ff5 100644 --- a/nx-X11/programs/Xserver/randr/randrproto.h +++ b/nx-X11/programs/Xserver/randr/randrproto.h @@ -2,6 +2,7 @@ * Copyright © 2000 Compaq Computer Corporation * Copyright © 2002 Hewlett-Packard Company * Copyright © 2006 Intel Corporation + * Copyright © 2008 Red Hat, Inc. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -30,8 +31,8 @@ #ifndef _XRANDRP_H_ #define _XRANDRP_H_ -/*#include <nx-X11/extensions/randr.h>*/ #include "randr.h" +#include <nx-X11/extensions/renderproto.h> #define Window CARD32 #define Drawable CARD32 @@ -47,7 +48,9 @@ #define RROutput CARD32 #define RRMode CARD32 #define RRCrtc CARD32 +#define RRProvider CARD32 #define RRModeFlags CARD32 +#define Atom CARD32 #define Rotation CARD16 #define SizeID CARD16 @@ -602,6 +605,296 @@ typedef struct { #define sz_xRRSetCrtcGammaReq 12 /* + * Additions for V1.3 + */ + +typedef xRRGetScreenResourcesReq xRRGetScreenResourcesCurrentReq; + +#define sz_xRRGetScreenResourcesCurrentReq sz_xRRGetScreenResourcesReq + +typedef xRRGetScreenResourcesReply xRRGetScreenResourcesCurrentReply; + +#define sz_xRRGetScreenResourcesCurrentReply sz_xRRGetScreenResourcesReply + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + RRCrtc crtc B32; + xRenderTransform transform; + CARD16 nbytesFilter; /* number of bytes in filter name */ + CARD16 pad B16; +} xRRSetCrtcTransformReq; + +#define sz_xRRSetCrtcTransformReq 48 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + RRCrtc crtc B32; +} xRRGetCrtcTransformReq; + +#define sz_xRRGetCrtcTransformReq 8 + +typedef struct { + BYTE type; + CARD8 status; + CARD16 sequenceNumber B16; + CARD32 length B32; + xRenderTransform pendingTransform; + BYTE hasTransforms; + CARD8 pad0; + CARD16 pad1 B16; + xRenderTransform currentTransform; + CARD32 pad2 B32; + CARD16 pendingNbytesFilter B16; /* number of bytes in filter name */ + CARD16 pendingNparamsFilter B16; /* number of filter params */ + CARD16 currentNbytesFilter B16; /* number of bytes in filter name */ + CARD16 currentNparamsFilter B16; /* number of filter params */ +} xRRGetCrtcTransformReply; + +#define sz_xRRGetCrtcTransformReply 96 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + Window window B32; + RROutput output B32; +} xRRSetOutputPrimaryReq; + +#define sz_xRRSetOutputPrimaryReq 12 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + Window window B32; +} xRRGetOutputPrimaryReq; + +#define sz_xRRGetOutputPrimaryReq 8 + +typedef struct { + BYTE type; + CARD8 pad; + CARD16 sequenceNumber B16; + CARD32 length B32; + RROutput output B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xRRGetOutputPrimaryReply; + +#define sz_xRRGetOutputPrimaryReply 32 + +/* + * Additions for V1.4 + */ + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + Window window B32; +} xRRGetProvidersReq; + +#define sz_xRRGetProvidersReq 8 + +typedef struct { + BYTE type; + CARD8 pad; + CARD16 sequenceNumber B16; + CARD32 length B32; + Time timestamp B32; + CARD16 nProviders; + CARD16 pad1 B16; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xRRGetProvidersReply; + +#define sz_xRRGetProvidersReply 32 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + RRProvider provider B32; + Time configTimestamp B32; +} xRRGetProviderInfoReq; + +#define sz_xRRGetProviderInfoReq 12 + +typedef struct { + BYTE type; + CARD8 status; + CARD16 sequenceNumber B16; + CARD32 length B32; + Time timestamp B32; + CARD32 capabilities B32; + CARD16 nCrtcs B16; + CARD16 nOutputs B16; + CARD16 nAssociatedProviders B16; + CARD16 nameLength B16; + CARD32 pad1 B32; + CARD32 pad2 B32; +} xRRGetProviderInfoReply; + +#define sz_xRRGetProviderInfoReply 32 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + RRProvider provider B32; + RRProvider source_provider B32; + Time configTimestamp B32; +} xRRSetProviderOutputSourceReq; + +#define sz_xRRSetProviderOutputSourceReq 16 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + RRProvider provider B32; + RRProvider sink_provider B32; + Time configTimestamp B32; +} xRRSetProviderOffloadSinkReq; + +#define sz_xRRSetProviderOffloadSinkReq 16 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + RRProvider provider B32; +} xRRListProviderPropertiesReq; + +#define sz_xRRListProviderPropertiesReq 8 + +typedef struct { + BYTE type; + CARD8 pad0; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 nAtoms B16; + CARD16 pad1 B16; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xRRListProviderPropertiesReply; + +#define sz_xRRListProviderPropertiesReply 32 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + RRProvider provider B32; + Atom property B32; +} xRRQueryProviderPropertyReq; + +#define sz_xRRQueryProviderPropertyReq 12 + +typedef struct { + BYTE type; + BYTE pad0; + CARD16 sequenceNumber B16; + CARD32 length B32; + BOOL pending; + BOOL range; + BOOL immutable; + BYTE pad1; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xRRQueryProviderPropertyReply; + +#define sz_xRRQueryProviderPropertyReply 32 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + RRProvider provider B32; + Atom property B32; + BOOL pending; + BOOL range; + CARD16 pad B16; +} xRRConfigureProviderPropertyReq; + +#define sz_xRRConfigureProviderPropertyReq 16 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + RRProvider provider B32; + Atom property B32; + Atom type B32; + CARD8 format; + CARD8 mode; + CARD16 pad; + CARD32 nUnits B32; +} xRRChangeProviderPropertyReq; + +#define sz_xRRChangeProviderPropertyReq 24 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + RRProvider provider B32; + Atom property B32; +} xRRDeleteProviderPropertyReq; + +#define sz_xRRDeleteProviderPropertyReq 12 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + RRProvider provider B32; + Atom property B32; + Atom type B32; + CARD32 longOffset B32; + CARD32 longLength B32; +#ifdef __cplusplus + BOOL _delete; +#else + BOOL delete; +#endif + BOOL pending; + CARD16 pad1 B16; +} xRRGetProviderPropertyReq; + +#define sz_xRRGetProviderPropertyReq 28 + +typedef struct { + BYTE type; + CARD8 format; + CARD16 sequenceNumber B16; + CARD32 length B32; + Atom propertyType B32; + CARD32 bytesAfter B32; + CARD32 nItems B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; +} xRRGetProviderPropertyReply; + +#define sz_xRRGetProviderPropertyReply 32 + +/* * event */ typedef struct { @@ -644,8 +937,8 @@ typedef struct { CARD8 type; /* always evBase + RRNotify */ CARD8 subCode; /* RRNotify_OutputChange */ CARD16 sequenceNumber B16; - Time timestamp B32; /* time crtc was changed */ - Time configTimestamp B32; /* time crtc was changed */ + Time timestamp B32; /* time output was changed */ + Time configTimestamp B32; /* time config was changed */ Window window B32; /* window requesting notification */ RROutput output B32; /* affected output */ RRCrtc crtc B32; /* current crtc */ @@ -674,12 +967,190 @@ typedef struct { #define sz_xRROutputPropertyNotifyEvent 32 +typedef struct { + CARD8 type; /* always evBase + RRNotify */ + CARD8 subCode; /* RRNotify_ProviderChange */ + CARD16 sequenceNumber B16; + Time timestamp B32; /* time provider was changed */ + Window window B32; /* window requesting notification */ + RRProvider provider B32; /* affected provider */ + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; +} xRRProviderChangeNotifyEvent; + +#define sz_xRRProviderChangeNotifyEvent 32 + +typedef struct { + CARD8 type; /* always evBase + RRNotify */ + CARD8 subCode; /* RRNotify_ProviderProperty */ + CARD16 sequenceNumber B16; + Window window B32; /* window requesting notification */ + RRProvider provider B32; /* affected provider */ + Atom atom B32; /* property name */ + Time timestamp B32; /* time provider was changed */ + CARD8 state; /* NewValue or Deleted */ + CARD8 pad1; + CARD16 pad2 B16; + CARD32 pad3 B32; + CARD32 pad4 B32; +} xRRProviderPropertyNotifyEvent; + +#define sz_xRRProviderPropertyNotifyEvent 32 + +typedef struct { + CARD8 type; /* always evBase + RRNotify */ + CARD8 subCode; /* RRNotify_ResourceChange */ + CARD16 sequenceNumber B16; + Time timestamp B32; /* time resource was changed */ + Window window B32; /* window requesting notification */ + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xRRResourceChangeNotifyEvent; + +#define sz_xRRResourceChangeNotifyEvent 32 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + RRCrtc crtc B32; +} xRRGetPanningReq; + +#define sz_xRRGetPanningReq 8 + +typedef struct { + BYTE type; + CARD8 status; + CARD16 sequenceNumber B16; + CARD32 length B32; + Time timestamp B32; + CARD16 left B16; + CARD16 top B16; + CARD16 width B16; + CARD16 height B16; + CARD16 track_left B16; + CARD16 track_top B16; + CARD16 track_width B16; + CARD16 track_height B16; + INT16 border_left B16; + INT16 border_top B16; + INT16 border_right B16; + INT16 border_bottom B16; +} xRRGetPanningReply; + +#define sz_xRRGetPanningReply 36 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + RRCrtc crtc B32; + Time timestamp B32; + CARD16 left B16; + CARD16 top B16; + CARD16 width B16; + CARD16 height B16; + CARD16 track_left B16; + CARD16 track_top B16; + CARD16 track_width B16; + CARD16 track_height B16; + INT16 border_left B16; + INT16 border_top B16; + INT16 border_right B16; + INT16 border_bottom B16; +} xRRSetPanningReq; + +#define sz_xRRSetPanningReq 36 + +typedef struct { + BYTE type; + CARD8 status; + CARD16 sequenceNumber B16; + CARD32 length B32; + Time newTimestamp B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xRRSetPanningReply; + +#define sz_xRRSetPanningReply 32 + +typedef struct { + Atom name B32; + BOOL primary; + BOOL automatic; + CARD16 noutput B16; + INT16 x B16; + INT16 y B16; + CARD16 width B16; + CARD16 height B16; + CARD32 widthInMillimeters B32; + CARD32 heightInMillimeters B32; +} xRRMonitorInfo; + +#define sz_xRRMonitorInfo 24 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + Window window B32; + BOOL get_active; + CARD8 pad; + CARD16 pad2; +} xRRGetMonitorsReq; + +#define sz_xRRGetMonitorsReq 12 + +typedef struct { + BYTE type; + CARD8 status; + CARD16 sequenceNumber B16; + CARD32 length B32; + Time timestamp B32; + CARD32 nmonitors B32; + CARD32 noutputs B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; +} xRRGetMonitorsReply; + +#define sz_xRRGetMonitorsReply 32 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + Window window B32; + xRRMonitorInfo monitor; +} xRRSetMonitorReq; + +#define sz_xRRSetMonitorReq 32 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + Window window B32; + Atom name B32; +} xRRDeleteMonitorReq; + +#define sz_xRRDeleteMonitorReq 12 + #undef RRModeFlags #undef RRCrtc #undef RRMode #undef RROutput #undef RRMode #undef RRCrtc +#undef RRProvider #undef Drawable #undef Window #undef Font @@ -694,5 +1165,6 @@ typedef struct { #undef Rotation #undef SizeID #undef SubpixelOrder +#undef Atom #endif /* _XRANDRP_H_ */ diff --git a/nx-X11/programs/Xserver/randr/randrstr.h b/nx-X11/programs/Xserver/randr/randrstr.h index 8e9107c9f..1bd0b9535 100644 --- a/nx-X11/programs/Xserver/randr/randrstr.h +++ b/nx-X11/programs/Xserver/randr/randrstr.h @@ -2,6 +2,7 @@ * Copyright © 2000 Compaq Computer Corporation * Copyright © 2002 Hewlett-Packard Company * Copyright © 2006 Intel Corporation + * Copyright © 2008 Red Hat, Inc. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -32,6 +33,10 @@ #ifndef _RANDRSTR_H_ #define _RANDRSTR_H_ +#ifndef NXAGENT_SERVER +#include "list.h" +#endif + #include <nx-X11/X.h> #include <nx-X11/Xproto.h> #include "misc.h" @@ -43,26 +48,26 @@ #include "pixmapstr.h" #include "extnsionst.h" #include "servermd.h" -#ifndef NXAGENT_SERVER -#include <nx-X11/extensions/randr.h> -#include <nx-X11/extensions/randrproto.h> -#else +#include "rrtransform.h" #include "randr.h" #include "randrproto.h" -#endif -#ifdef RENDER #include <nx-X11/extensions/render.h> /* we share subpixel order information */ #include "picturestr.h" -#endif #include <nx-X11/Xfuncproto.h> /* required for ABI compatibility for now */ #define RANDR_10_INTERFACE 1 #define RANDR_12_INTERFACE 1 +#define RANDR_13_INTERFACE 1 /* requires RANDR_12_INTERFACE */ +#define RANDR_15_INTERFACE 1 +#define RANDR_GET_CRTC_INTERFACE 1 + +#define RANDR_INTERFACE_VERSION 0x0104 typedef XID RRMode; typedef XID RROutput; typedef XID RRCrtc; +typedef XID RRProvider; extern int RREventBase, RRErrorBase; @@ -79,6 +84,8 @@ typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr; typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr; typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr; typedef struct _rrOutput RROutputRec, *RROutputPtr; +typedef struct _rrProvider RRProviderRec, *RRProviderPtr; +typedef struct _rrMonitor RRMonitorRec, *RRMonitorPtr; struct _rrMode { int refcnt; @@ -120,6 +127,14 @@ struct _rrCrtc { CARD16 *gammaBlue; CARD16 *gammaGreen; void *devPrivate; + Bool transforms; + RRTransformRec client_pending_transform; + RRTransformRec client_current_transform; + PictTransform transform; + struct pict_f_transform f_transform; + struct pict_f_transform f_inverse; + + PixmapPtr scanout_pixmap; }; struct _rrOutput { @@ -147,6 +162,35 @@ struct _rrOutput { void *devPrivate; }; +struct _rrProvider { + RRProvider id; + ScreenPtr pScreen; + uint32_t capabilities; + char *name; + int nameLength; + RRPropertyPtr properties; + Bool pendingProperties; + Bool changed; + struct _rrProvider *offload_sink; + struct _rrProvider *output_source; +}; + +typedef struct _rrMonitorGeometry { + BoxRec box; + CARD32 mmWidth; + CARD32 mmHeight; +} RRMonitorGeometryRec, *RRMonitorGeometryPtr; + +struct _rrMonitor { + Atom name; + ScreenPtr pScreen; + int numOutputs; + RROutput *outputs; + Bool primary; + Bool automatic; + RRMonitorGeometryRec geometry; +}; + #if RANDR_12_INTERFACE typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen, CARD16 width, @@ -163,6 +207,8 @@ typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr pScreen, typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr pScreen, RRCrtcPtr crtc); +typedef Bool (*RRCrtcGetGammaProcPtr) (ScreenPtr pScreen, RRCrtcPtr crtc); + typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr pScreen, RROutputPtr output, Atom property, @@ -176,8 +222,41 @@ typedef void (*RRModeDestroyProcPtr) (ScreenPtr pScreen, RRModePtr mode); #endif +#if RANDR_13_INTERFACE +typedef Bool (*RROutputGetPropertyProcPtr) (ScreenPtr pScreen, + RROutputPtr output, Atom property); +typedef Bool (*RRGetPanningProcPtr) (ScreenPtr pScrn, + RRCrtcPtr crtc, + BoxPtr totalArea, + BoxPtr trackingArea, INT16 *border); +typedef Bool (*RRSetPanningProcPtr) (ScreenPtr pScrn, + RRCrtcPtr crtc, + BoxPtr totalArea, + BoxPtr trackingArea, INT16 *border); + +#endif /* RANDR_13_INTERFACE */ + +typedef Bool (*RRProviderGetPropertyProcPtr) (ScreenPtr pScreen, + RRProviderPtr provider, + Atom property); +typedef Bool (*RRProviderSetPropertyProcPtr) (ScreenPtr pScreen, + RRProviderPtr provider, + Atom property, + RRPropertyValuePtr value); + typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation * rotations); -typedef Bool (*RRCloseScreenProcPtr) (int i, ScreenPtr pscreen); +typedef Bool (*RRCloseScreenProcPtr) (ScreenPtr pscreen); + +typedef Bool (*RRProviderSetOutputSourceProcPtr) (ScreenPtr pScreen, + RRProviderPtr provider, + RRProviderPtr output_source); + +typedef Bool (*RRProviderSetOffloadSinkProcPtr) (ScreenPtr pScreen, + RRProviderPtr provider, + RRProviderPtr offload_sink); + +typedef void (*RRProviderDestroyProcPtr) (ScreenPtr pScreen, + RRProviderPtr provider); /* These are for 1.0 compatibility */ @@ -202,6 +281,8 @@ typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen, #endif +typedef Bool (*RRCrtcSetScanoutPixmapProcPtr) (RRCrtcPtr crtc, PixmapPtr pixmap); + typedef struct _rrScrPriv { /* * 'public' part of the structure; DDXen fill this in @@ -215,10 +296,23 @@ typedef struct _rrScrPriv { RRScreenSetSizeProcPtr rrScreenSetSize; RRCrtcSetProcPtr rrCrtcSet; RRCrtcSetGammaProcPtr rrCrtcSetGamma; + RRCrtcGetGammaProcPtr rrCrtcGetGamma; RROutputSetPropertyProcPtr rrOutputSetProperty; RROutputValidateModeProcPtr rrOutputValidateMode; RRModeDestroyProcPtr rrModeDestroy; #endif +#if RANDR_13_INTERFACE + RROutputGetPropertyProcPtr rrOutputGetProperty; + RRGetPanningProcPtr rrGetPanning; + RRSetPanningProcPtr rrSetPanning; +#endif + /* TODO #if RANDR_15_INTERFACE */ + RRCrtcSetScanoutPixmapProcPtr rrCrtcSetScanoutPixmap; + + RRProviderSetOutputSourceProcPtr rrProviderSetOutputSource; + RRProviderSetOffloadSinkProcPtr rrProviderSetOffloadSink; + RRProviderGetPropertyProcPtr rrProviderGetProperty; + RRProviderSetPropertyProcPtr rrProviderSetProperty; /* * Private part of the structure; not considered part of the ABI @@ -230,6 +324,7 @@ typedef struct _rrScrPriv { Bool changed; /* some config changed */ Bool configChanged; /* configuration changed */ Bool layoutChanged; /* screen layout changed */ + Bool resourcesChanged; /* screen resources change */ CARD16 minWidth, minHeight; CARD16 maxWidth, maxHeight; @@ -238,6 +333,7 @@ typedef struct _rrScrPriv { int numOutputs; RROutputPtr *outputs; + RROutputPtr primaryOutput; int numCrtcs; RRCrtcPtr *crtcs; @@ -259,9 +355,21 @@ typedef struct _rrScrPriv { int rate; int size; #endif + Bool discontiguous; + + RRProviderPtr provider; + + RRProviderDestroyProcPtr rrProviderDestroy; + + int numMonitors; + RRMonitorPtr *monitors; + } rrScrPrivRec, *rrScrPrivPtr; #ifndef NXAGENT_SERVER +extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec; + +#define rrPrivKey (&rrPrivKeyRec) extern DevPrivateKey rrPrivKey; #else extern int rrPrivIndex; @@ -269,17 +377,17 @@ extern int rrPrivIndex; #ifndef NXAGENT_SERVER -#define rrGetScrPriv(pScr) ((rrScrPrivPtr)dixLookupPrivate(&(pScr)->devPrivates, rrPrivKey)) -#define rrScrPriv(pScr) rrScrPrivPtr pScrPriv = rrGetScrPriv(pScr) +#define rrGetScrPriv(pScr) ((rrScrPrivPtr)dixLookupPrivate(&(pScr)->devPrivates, rrPrivKey)) +#define rrScrPriv(pScr) rrScrPrivPtr pScrPriv = rrGetScrPriv(pScr) #define SetRRScreen(s,p) dixSetPrivate(&(s)->devPrivates, rrPrivKey, p) -#else +#else /* !defined(NXAGENT_SERVER) */ -#define rrGetScrPriv(pScr) ((rrScrPrivPtr) (pScr)->devPrivates[rrPrivIndex].ptr) -#define rrScrPriv(pScr) rrScrPrivPtr pScrPriv = rrGetScrPriv(pScr) +#define rrGetScrPriv(pScr) ((rrScrPrivPtr) (pScr)->devPrivates[rrPrivIndex].ptr) +#define rrScrPriv(pScr) rrScrPrivPtr pScrPriv = rrGetScrPriv(pScr) #define SetRRScreen(s,p) ((s)->devPrivates[rrPrivIndex].ptr = (void *) (p)) -#endif +#endif /* !defined(NXAGENT_SERVER) */ /* * each window has a list of clients requesting @@ -317,43 +425,132 @@ extern DevPrivateKey RRClientPrivateKey; #else extern int RRClientPrivateIndex; #endif -extern RESTYPE RRCrtcType, RRModeType, RROutputType; + +extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType, RRProviderType; + +#ifdef NXAGENT_SERVER #define LookupOutput(client,id,a) ((RROutputPtr) \ - (SecurityLookupIDByType (client, id, \ - RROutputType, a))) + (SecurityLookupIDByType (client, id, \ + RROutputType, a))) #define LookupCrtc(client,id,a) ((RRCrtcPtr) \ - (SecurityLookupIDByType (client, id, \ - RRCrtcType, a))) + (SecurityLookupIDByType (client, id, \ + RRCrtcType, a))) #define LookupMode(client,id,a) ((RRModePtr) \ - (SecurityLookupIDByType (client, id, \ - RRModeType, a))) -#ifndef NXAGENT_SERVER - -#define GetRRClient(pClient) ((RRClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RRClientPrivateKey)) -#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) - -#else - -#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr) -#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) + (SecurityLookupIDByType (client, id, \ + RRModeType, a))) +#define LookupProvider(client,id,a) ((RRProviderPtr) \ + (SecurityLookupIDByType (client, id, \ + RRProviderType, a))) #define DixUnknownAccess SecurityUnknownAccess #define DixReadAccess SecurityReadAccess #define DixWriteAccess SecurityWriteAccess +#define DixSetAttrAccess SecurityWriteAccess +#define DixUseAccess SecurityWriteAccess #define DixDestroyAccess SecurityDestroyAccess #endif +#ifndef NXAGENT_SERVER + +#define RRClientPrivateKey (&RRClientPrivateKeyRec) +#define GetRRClient(pClient) ((RRClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RRClientPrivateKey)) + +#else /* !defined/NXAGENT_SERVER) */ + +#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr) + +#endif /* !defined(NXAGENT_SERVER) */ +#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) + /* Initialize the extension */ void RRExtensionInit(void); +#ifndef NXAGENT_SERVER +#define VERIFY_RR_OUTPUT(id, ptr, a)\ + {\ + int rc = dixLookupResourceByType((void **)&(ptr), id,\ + RROutputType, client, a);\ + if (rc != Success) {\ + client->errorValue = id;\ + return rc;\ + }\ + } + +#define VERIFY_RR_CRTC(id, ptr, a)\ + {\ + int rc = dixLookupResourceByType((void **)&(ptr), id,\ + RRCrtcType, client, a);\ + if (rc != Success) {\ + client->errorValue = id;\ + return rc;\ + }\ + } + +#define VERIFY_RR_MODE(id, ptr, a)\ + {\ + int rc = dixLookupResourceByType((void **)&(ptr), id,\ + RRModeType, client, a);\ + if (rc != Success) {\ + client->errorValue = id;\ + return rc;\ + }\ + } + +#define VERIFY_RR_PROVIDER(id, ptr, a)\ + {\ + int rc = dixLookupResourceByType((void **)&(ptr), id,\ + RRProviderType, client, a);\ + if (rc != Success) {\ + client->errorValue = id;\ + return rc;\ + }\ + } +#else /* !defined(NXAGENT_SERVER) */ +#define VERIFY_RR_OUTPUT(id, ptr, a)\ + {\ + ptr = LookupOutput(client, id, a);\ + if (!ptr) {\ + client->errorValue = id;\ + return RRErrorBase + BadRROutput;\ + }\ + } + +#define VERIFY_RR_CRTC(id, ptr, a)\ + {\ + ptr = LookupCrtc (client, id, a);\ + if (!ptr) {\ + client->errorValue = id;\ + return RRErrorBase + BadRRCrtc;\ + }\ + } + +#define VERIFY_RR_MODE(id, ptr, a)\ + {\ + ptr = LookupMode (client, id, a);\ + if (!ptr) {\ + client->errorValue = id;\ + return RRErrorBase + BadRRMode;\ + }\ + } + +#define VERIFY_RR_PROVIDER(id, ptr, a)\ + {\ + ptr = LookupProvider (client, id, a);\ + if (!ptr) {\ + client->errorValue = id;\ + return RRErrorBase + BadRRProvider;\ + }\ + } +#endif /* !defined(NXAGENT_SERVER) */ + #ifdef RANDR_12_INTERFACE /* * Set the range of sizes for the screen */ -void +extern _X_EXPORT void RRScreenSetSizeRange(ScreenPtr pScreen, CARD16 minWidth, @@ -366,13 +563,13 @@ RRScreenSetSizeRange(ScreenPtr pScreen, * The driver is responsible for calling this whenever it has changed * the size of the screen */ -void +extern _X_EXPORT void RRScreenSizeNotify(ScreenPtr pScreen); /* * Request that the screen be resized */ -Bool +extern _X_EXPORT Bool RRScreenSizeSet(ScreenPtr pScreen, CARD16 width, CARD16 height, CARD32 mmWidth, CARD32 mmHeight); @@ -380,85 +577,63 @@ RRScreenSizeSet(ScreenPtr pScreen, /* * Send ConfigureNotify event to root window when 'something' happens */ -void +extern _X_EXPORT void RRSendConfigNotify(ScreenPtr pScreen); /* * screen dispatch */ -int +extern _X_EXPORT int ProcRRGetScreenSizeRange(ClientPtr client); -int +extern _X_EXPORT int ProcRRSetScreenSize(ClientPtr client); -int +extern _X_EXPORT int ProcRRGetScreenResources(ClientPtr client); -int +extern _X_EXPORT int + ProcRRGetScreenResourcesCurrent(ClientPtr client); + +extern _X_EXPORT int ProcRRSetScreenConfig(ClientPtr client); -int +extern _X_EXPORT int ProcRRGetScreenInfo(ClientPtr client); /* * Deliver a ScreenNotify event */ -void +extern _X_EXPORT void RRDeliverScreenEvent(ClientPtr client, WindowPtr pWin, ScreenPtr pScreen); -/* mirandr.c */ -Bool - miRandRInit(ScreenPtr pScreen); - -Bool - miRRGetInfo(ScreenPtr pScreen, Rotation * rotations); - -Bool - miRRGetScreenInfo(ScreenPtr pScreen); - -Bool - -miRRCrtcSet(ScreenPtr pScreen, - RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, Rotation rotation, int numOutput, RROutputPtr * outputs); - -Bool - -miRROutputSetProperty(ScreenPtr pScreen, - RROutputPtr output, - Atom property, RRPropertyValuePtr value); - -Bool - miRROutputValidateMode(ScreenPtr pScreen, RROutputPtr output, RRModePtr mode); - -void - miRRModeDestroy(ScreenPtr pScreen, RRModePtr mode); +extern _X_EXPORT void + RRResourcesChanged(ScreenPtr pScreen); /* randr.c */ +/* set a screen change on the primary screen */ +extern _X_EXPORT void + RRSetChanged(ScreenPtr pScreen); + /* * Send all pending events */ -void +extern _X_EXPORT void RRTellChanged(ScreenPtr pScreen); /* * Poll the driver for changed information */ -Bool - RRGetInfo(ScreenPtr pScreen); +extern _X_EXPORT Bool + RRGetInfo(ScreenPtr pScreen, Bool force_query); -Bool RRInit(void); +extern _X_EXPORT Bool RRInit(void); -Bool RRScreenInit(ScreenPtr pScreen); +extern _X_EXPORT Bool RRScreenInit(ScreenPtr pScreen); -RROutputPtr RRFirstOutput(ScreenPtr pScreen); +extern _X_EXPORT RROutputPtr RRFirstOutput(ScreenPtr pScreen); -Rotation RRGetRotation(ScreenPtr pScreen); - -CARD16 +extern _X_EXPORT CARD16 RRVerticalRefresh(xRRModeInfo * mode); #ifdef RANDR_10_INTERFACE @@ -471,29 +646,24 @@ CARD16 * Then, register the specific size with the screen */ -RRScreenSizePtr +extern _X_EXPORT RRScreenSizePtr RRRegisterSize(ScreenPtr pScreen, short width, short height, short mmWidth, short mmHeight); -Bool RRRegisterRate(ScreenPtr pScreen, RRScreenSizePtr pSize, int rate); +extern _X_EXPORT Bool + RRRegisterRate(ScreenPtr pScreen, RRScreenSizePtr pSize, int rate); /* * Finally, set the current configuration of the screen */ -void +extern _X_EXPORT void + RRSetCurrentConfig(ScreenPtr pScreen, Rotation rotation, int rate, RRScreenSizePtr pSize); -Bool RRScreenInit(ScreenPtr pScreen); - -Rotation RRGetRotation(ScreenPtr pScreen); - -int - -RRSetScreenConfig(ScreenPtr pScreen, - Rotation rotation, int rate, RRScreenSizePtr pSize); +extern _X_EXPORT Rotation RRGetRotation(ScreenPtr pScreen); #endif @@ -503,38 +673,46 @@ RRSetScreenConfig(ScreenPtr pScreen, * Notify the CRTC of some change; layoutChanged indicates that * some position or size element changed */ -void +extern _X_EXPORT void RRCrtcChanged(RRCrtcPtr crtc, Bool layoutChanged); /* * Create a CRTC */ -RRCrtcPtr RRCrtcCreate(ScreenPtr pScreen, void *devPrivate); +extern _X_EXPORT RRCrtcPtr RRCrtcCreate(ScreenPtr pScreen, void *devPrivate); /* * Set the allowed rotations on a CRTC */ -void +extern _X_EXPORT void RRCrtcSetRotations(RRCrtcPtr crtc, Rotation rotations); /* + * Set whether transforms are allowed on a CRTC + */ +extern _X_EXPORT void + RRCrtcSetTransformSupport(RRCrtcPtr crtc, Bool transforms); + +/* * Notify the extension that the Crtc has been reconfigured, * the driver calls this whenever it has updated the mode */ -Bool +extern _X_EXPORT Bool RRCrtcNotify(RRCrtcPtr crtc, RRModePtr mode, int x, - int y, Rotation rotation, int numOutputs, RROutputPtr * outputs); + int y, + Rotation rotation, + RRTransformPtr transform, int numOutputs, RROutputPtr * outputs); -void +extern _X_EXPORT void RRDeliverCrtcEvent(ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc); /* * Request that the Crtc be reconfigured */ -Bool +extern _X_EXPORT Bool RRCrtcSet(RRCrtcPtr crtc, RRModePtr mode, @@ -545,23 +723,31 @@ RRCrtcSet(RRCrtcPtr crtc, * Request that the Crtc gamma be changed */ -Bool +extern _X_EXPORT Bool RRCrtcGammaSet(RRCrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue); /* + * Request current gamma back from the DDX (if possible). + * This includes gamma size. + */ + +extern _X_EXPORT Bool + RRCrtcGammaGet(RRCrtcPtr crtc); + +/* * Notify the extension that the Crtc gamma has been changed * The driver calls this whenever it has changed the gamma values * in the RRCrtcRec */ -Bool +extern _X_EXPORT Bool RRCrtcGammaNotify(RRCrtcPtr crtc); /* * Set the size of the gamma table at server startup time */ -Bool +extern _X_EXPORT Bool RRCrtcGammaSetSize(RRCrtcPtr crtc, int size); /* @@ -569,42 +755,99 @@ Bool * taking into account the current mode and rotation */ -void +extern _X_EXPORT void RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height); /* + * Return crtc transform + */ +extern _X_EXPORT RRTransformPtr RRCrtcGetTransform(RRCrtcPtr crtc); + +/* + * Check whether the pending and current transforms are the same + */ +extern _X_EXPORT Bool + RRCrtcPendingTransform(RRCrtcPtr crtc); + +/* * Destroy a Crtc at shutdown */ -void +extern _X_EXPORT void RRCrtcDestroy(RRCrtcPtr crtc); /* + * Set the pending CRTC transformation + */ + +extern _X_EXPORT int + +RRCrtcTransformSet(RRCrtcPtr crtc, + PictTransformPtr transform, + struct pict_f_transform *f_transform, + struct pict_f_transform *f_inverse, + char *filter, int filter_len, xFixed * params, int nparams); + +/* * Initialize crtc type */ -Bool +extern _X_EXPORT Bool RRCrtcInit(void); /* + * Initialize crtc type error value + */ +extern _X_EXPORT void + RRCrtcInitErrorValue(void); + +/* + * Detach and free a scanout pixmap + */ +extern _X_EXPORT void + RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc); + +extern _X_EXPORT Bool + RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable); + +/* * Crtc dispatch */ -int +extern _X_EXPORT int ProcRRGetCrtcInfo(ClientPtr client); -int +extern _X_EXPORT int ProcRRSetCrtcConfig(ClientPtr client); -int +extern _X_EXPORT int ProcRRGetCrtcGammaSize(ClientPtr client); -int +extern _X_EXPORT int ProcRRGetCrtcGamma(ClientPtr client); -int +extern _X_EXPORT int ProcRRSetCrtcGamma(ClientPtr client); +extern _X_EXPORT int + ProcRRSetCrtcTransform(ClientPtr client); + +extern _X_EXPORT int + ProcRRGetCrtcTransform(ClientPtr client); + +int + ProcRRGetPanning(ClientPtr client); + +int + ProcRRSetPanning(ClientPtr client); + +void + RRConstrainCursorHarder( +#ifndef NXAGENT_SERVER + DeviceIntPtr, +#endif /* !defined(NXAGENT_SERVER) */ + ScreenPtr, int, int *, int *); + /* rrdispatch.c */ -Bool +extern _X_EXPORT Bool RRClientKnowsRates(ClientPtr pClient); /* rrmode.c */ @@ -612,39 +855,42 @@ Bool * Find, and if necessary, create a mode */ -RRModePtr RRModeGet(xRRModeInfo * modeInfo, const char *name); - -void - RRModePruneUnused(ScreenPtr pScreen); +extern _X_EXPORT RRModePtr RRModeGet(xRRModeInfo * modeInfo, const char *name); /* * Destroy a mode. */ -void +extern _X_EXPORT void RRModeDestroy(RRModePtr mode); /* * Return a list of modes that are valid for some output in pScreen */ -RRModePtr *RRModesForScreen(ScreenPtr pScreen, int *num_ret); +extern _X_EXPORT RRModePtr *RRModesForScreen(ScreenPtr pScreen, int *num_ret); /* * Initialize mode type */ -Bool +extern _X_EXPORT Bool RRModeInit(void); -int +/* + * Initialize mode type error value + */ +extern _X_EXPORT void + RRModeInitErrorValue(void); + +extern _X_EXPORT int ProcRRCreateMode(ClientPtr client); -int +extern _X_EXPORT int ProcRRDestroyMode(ClientPtr client); -int +extern _X_EXPORT int ProcRRAddOutputMode(ClientPtr client); -int +extern _X_EXPORT int ProcRRDeleteOutputMode(ClientPtr client); /* rroutput.c */ @@ -655,116 +901,245 @@ int * has changed, or whether the change was strictly internal * (which crtc is in use) */ -void +extern _X_EXPORT void RROutputChanged(RROutputPtr output, Bool configChanged); /* * Create an output */ -RROutputPtr +extern _X_EXPORT RROutputPtr RROutputCreate(ScreenPtr pScreen, const char *name, int nameLength, void *devPrivate); /* * Notify extension that output parameters have been changed */ -Bool +extern _X_EXPORT Bool RROutputSetClones(RROutputPtr output, RROutputPtr * clones, int numClones); -Bool +extern _X_EXPORT Bool RROutputSetModes(RROutputPtr output, RRModePtr * modes, int numModes, int numPreferred); -int +extern _X_EXPORT int RROutputAddUserMode(RROutputPtr output, RRModePtr mode); -int +extern _X_EXPORT int RROutputDeleteUserMode(RROutputPtr output, RRModePtr mode); -Bool +extern _X_EXPORT Bool RROutputSetCrtcs(RROutputPtr output, RRCrtcPtr * crtcs, int numCrtcs); -Bool +extern _X_EXPORT Bool RROutputSetConnection(RROutputPtr output, CARD8 connection); -Bool +extern _X_EXPORT Bool RROutputSetSubpixelOrder(RROutputPtr output, int subpixelOrder); -Bool +extern _X_EXPORT Bool RROutputSetPhysicalSize(RROutputPtr output, int mmWidth, int mmHeight); -void +extern _X_EXPORT void RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output); -void +extern _X_EXPORT void RROutputDestroy(RROutputPtr output); -int +extern _X_EXPORT int ProcRRGetOutputInfo(ClientPtr client); +extern _X_EXPORT int + ProcRRSetOutputPrimary(ClientPtr client); + +extern _X_EXPORT int + ProcRRGetOutputPrimary(ClientPtr client); + /* * Initialize output type */ -Bool +extern _X_EXPORT Bool RROutputInit(void); +/* + * Initialize output type error value + */ +extern _X_EXPORT void + RROutputInitErrorValue(void); + /* rrpointer.c */ -void +extern _X_EXPORT void RRPointerMoved(ScreenPtr pScreen, int x, int y); -void +extern _X_EXPORT void RRPointerScreenConfigured(ScreenPtr pScreen); /* rrproperty.c */ -void +extern _X_EXPORT void RRDeleteAllOutputProperties(RROutputPtr output); -RRPropertyValuePtr +extern _X_EXPORT RRPropertyValuePtr RRGetOutputProperty(RROutputPtr output, Atom property, Bool pending); -RRPropertyPtr RRQueryOutputProperty(RROutputPtr output, Atom property); +extern _X_EXPORT RRPropertyPtr +RRQueryOutputProperty(RROutputPtr output, Atom property); -void +extern _X_EXPORT void RRDeleteOutputProperty(RROutputPtr output, Atom property); -Bool +extern _X_EXPORT Bool RRPostPendingProperties(RROutputPtr output); -int +extern _X_EXPORT int RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type, int format, int mode, unsigned long len, void *value, Bool sendevent, Bool pending); -int +extern _X_EXPORT int RRConfigureOutputProperty(RROutputPtr output, Atom property, Bool pending, Bool range, Bool immutable, int num_values, INT32 *values); -int +extern _X_EXPORT int ProcRRChangeOutputProperty(ClientPtr client); -int +extern _X_EXPORT int ProcRRGetOutputProperty(ClientPtr client); -int +extern _X_EXPORT int ProcRRListOutputProperties(ClientPtr client); -int +extern _X_EXPORT int ProcRRQueryOutputProperty(ClientPtr client); -int +extern _X_EXPORT int ProcRRConfigureOutputProperty(ClientPtr client); -int +extern _X_EXPORT int ProcRRDeleteOutputProperty(ClientPtr client); +/* rrprovider.c */ +extern _X_EXPORT void + RRProviderInitErrorValue(void); + +extern _X_EXPORT int + ProcRRGetProviders(ClientPtr client); + +extern _X_EXPORT int + ProcRRGetProviderInfo(ClientPtr client); + +extern _X_EXPORT int + ProcRRSetProviderOutputSource(ClientPtr client); + +extern _X_EXPORT int + ProcRRSetProviderOffloadSink(ClientPtr client); + +extern _X_EXPORT Bool + RRProviderInit(void); + +extern _X_EXPORT RRProviderPtr +RRProviderCreate(ScreenPtr pScreen, const char *name, int nameLength); + +extern _X_EXPORT void + RRProviderDestroy(RRProviderPtr provider); + +extern _X_EXPORT void + RRProviderSetCapabilities(RRProviderPtr provider, uint32_t capabilities); + +extern _X_EXPORT Bool + RRProviderLookup(XID id, RRProviderPtr * provider_p); + +extern _X_EXPORT void + +RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider); + +/* rrproviderproperty.c */ + +extern _X_EXPORT void + RRDeleteAllProviderProperties(RRProviderPtr provider); + +extern _X_EXPORT RRPropertyValuePtr +RRGetProviderProperty(RRProviderPtr provider, Atom property, Bool pending); + +extern _X_EXPORT RRPropertyPtr +RRQueryProviderProperty(RRProviderPtr provider, Atom property); + +extern _X_EXPORT void + RRDeleteProviderProperty(RRProviderPtr provider, Atom property); + +extern _X_EXPORT int +RRChangeProviderProperty(RRProviderPtr provider, Atom property, Atom type, + int format, int mode, unsigned long len, + void *value, Bool sendevent, Bool pending); + +extern _X_EXPORT int +RRConfigureProviderProperty(RRProviderPtr provider, Atom property, + Bool pending, Bool range, Bool immutable, + int num_values, INT32 *values); + +extern _X_EXPORT Bool + RRPostProviderPendingProperties(RRProviderPtr provider); + +extern _X_EXPORT int + ProcRRGetProviderProperty(ClientPtr client); + +extern _X_EXPORT int + ProcRRListProviderProperties(ClientPtr client); + +extern _X_EXPORT int + ProcRRQueryProviderProperty(ClientPtr client); + +extern _X_EXPORT int + ProcRRConfigureProviderProperty(ClientPtr client); + +extern _X_EXPORT int + ProcRRChangeProviderProperty(ClientPtr client); + +extern _X_EXPORT int + ProcRRDeleteProviderProperty(ClientPtr client); + /* rrxinerama.c */ -void +#ifdef XINERAMA +extern _X_EXPORT void RRXineramaExtensionInit(void); +#endif + +void + RRMonitorInit(ScreenPtr screen); + +Bool + +RRMonitorMakeList(ScreenPtr screen, Bool get_active, RRMonitorPtr * monitors_ret, int *nmon_ret); + +int + RRMonitorCountList(ScreenPtr screen); + +void + RRMonitorFreeList(RRMonitorPtr monitors, int nmon); + +void + RRMonitorClose(ScreenPtr screen); + +RRMonitorPtr +RRMonitorAlloc(int noutput); + +int + RRMonitorAdd(ClientPtr client, ScreenPtr screen, RRMonitorPtr monitor); + +void + RRMonitorFree(RRMonitorPtr monitor); + +int + ProcRRGetMonitors(ClientPtr client); + +int + ProcRRSetMonitor(ClientPtr client); + +int + ProcRRDeleteMonitor(ClientPtr client); #endif /* _RANDRSTR_H_ */ diff --git a/nx-X11/programs/Xserver/randr/rrcrtc.c b/nx-X11/programs/Xserver/randr/rrcrtc.c index 76b4c64f9..d69b5ec08 100644 --- a/nx-X11/programs/Xserver/randr/rrcrtc.c +++ b/nx-X11/programs/Xserver/randr/rrcrtc.c @@ -1,5 +1,6 @@ /* * Copyright © 2006 Keith Packard + * Copyright 2010 Red Hat, Inc * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -39,7 +40,7 @@ #include "randrstr.h" #include "swaprep.h" -#include "registry.h" +#include "mipointer.h" RESTYPE RRCrtcType; @@ -55,7 +56,7 @@ RRCrtcChanged(RRCrtcPtr crtc, Bool layoutChanged) if (pScreen) { rrScrPriv(pScreen); - pScrPriv->changed = TRUE; + RRSetChanged(pScreen); /* * Send ConfigureNotify on any layout change */ @@ -81,8 +82,13 @@ RRCrtcCreate(ScreenPtr pScreen, void *devPrivate) /* make space for the crtc pointer */ if (pScrPriv->numCrtcs) +#ifndef NXAGENT_SERVER + crtcs = reallocarray(pScrPriv->crtcs, + pScrPriv->numCrtcs + 1, sizeof(RRCrtcPtr)); +#else /* !defined(NXAGENT_SERVER) */ crtcs = xrealloc(pScrPriv->crtcs, (pScrPriv->numCrtcs + 1) * sizeof(RRCrtcPtr)); +#endif /* !defined(NXAGENT_SERVER) */ else crtcs = xalloc(sizeof(RRCrtcPtr)); if (!crtcs) @@ -105,6 +111,11 @@ RRCrtcCreate(ScreenPtr pScreen, void *devPrivate) 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, (void *) crtc)) return NULL; @@ -113,6 +124,8 @@ RRCrtcCreate(ScreenPtr pScreen, void *devPrivate) crtc->pScreen = pScreen; pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc; + RRResourcesChanged(pScreen); + return crtc; } @@ -126,6 +139,15 @@ RRCrtcSetRotations(RRCrtcPtr crtc, Rotation 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 */ @@ -133,7 +155,9 @@ Bool RRCrtcNotify(RRCrtcPtr crtc, RRModePtr mode, int x, - int y, Rotation rotation, int numOutputs, RROutputPtr * outputs) + int y, + Rotation rotation, + RRTransformPtr transform, int numOutputs, RROutputPtr * outputs) { int i, j; @@ -174,16 +198,24 @@ RRCrtcNotify(RRCrtcPtr crtc, if (numOutputs) { if (crtc->numOutputs) +#ifndef NXAGENT_SERVER + newoutputs = reallocarray(crtc->outputs, + numOutputs, sizeof(RROutputPtr)); +#else /* !defined(NXAGENT_SERVER) */ newoutputs = xrealloc(crtc->outputs, numOutputs * sizeof(RROutputPtr)); +#endif /* !defined(NXAGENT_SERVER) */ else +#ifndef NXAGENT_SERVER + newoutputs = xallocarray(numOutputs, sizeof(RROutputPtr)); +#else /* !defined(NXAGENT_SERVER) */ newoutputs = xalloc(numOutputs * sizeof(RROutputPtr)); +#endif /* !defined(NXAGENT_SERVER) */ if (!newoutputs) return FALSE; } else { - if (crtc->outputs) - xfree(crtc->outputs); + xfree(crtc->outputs); newoutputs = NULL; } crtc->outputs = newoutputs; @@ -216,6 +248,18 @@ RRCrtcNotify(RRCrtcPtr crtc, 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; } @@ -225,30 +269,24 @@ 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; - } + xRRCrtcChangeNotifyEvent ce = { + .type = RRNotify + RREventBase, + .subCode = RRNotify_CrtcChange, +#ifdef NXAGENT_SERVER + .sequenceNumber = client->sequence, +#endif + .timestamp = pScrPriv->lastSetTime.milliseconds, + .window = pWin->drawable.id, + .crtc = crtc->id, + .mode = mode ? mode->mode.id : None, + .rotation = crtc->rotation, + .x = mode ? crtc->x : 0, + .y = mode ? crtc->y : 0, + .width = mode ? mode->mode.width : 0, + .height = mode ? mode->mode.height : 0 + }; WriteEventsToClient(client, 1, (xEvent *) &ce); } @@ -269,6 +307,302 @@ RRCrtcPendingProperties(RRCrtcPtr crtc) return FALSE; } +static void +crtc_bounds(RRCrtcPtr crtc, int *left, int *right, int *top, int *bottom) +{ + *left = crtc->x; + *top = crtc->y; + + switch (crtc->rotation) { + case RR_Rotate_0: + case RR_Rotate_180: + default: + *right = crtc->x + crtc->mode->mode.width; + *bottom = crtc->y + crtc->mode->mode.height; + return; + case RR_Rotate_90: + case RR_Rotate_270: + *right = crtc->x + crtc->mode->mode.height; + *bottom = crtc->y + crtc->mode->mode.width; + return; + } +} + +/* overlapping counts as adjacent */ +static Bool +crtcs_adjacent(const RRCrtcPtr a, const RRCrtcPtr b) +{ + /* left, right, top, bottom... */ + int al, ar, at, ab; + int bl, br, bt, bb; + int cl, cr, ct, cb; /* the overlap, if any */ + + crtc_bounds(a, &al, &ar, &at, &ab); + crtc_bounds(b, &bl, &br, &bt, &bb); + + cl = max(al, bl); + cr = min(ar, br); + ct = max(at, bt); + cb = min(ab, bb); + + return (cl <= cr) && (ct <= cb); +} + +/* Depth-first search and mark all CRTCs reachable from cur */ +static void +mark_crtcs(rrScrPrivPtr pScrPriv, int *reachable, int cur) +{ + int i; + + reachable[cur] = TRUE; + for (i = 0; i < pScrPriv->numCrtcs; ++i) { + if (reachable[i] || !pScrPriv->crtcs[i]->mode) + continue; + if (crtcs_adjacent(pScrPriv->crtcs[cur], pScrPriv->crtcs[i])) + mark_crtcs(pScrPriv, reachable, i); + } +} + +static void +RRComputeContiguity(ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + Bool discontiguous = TRUE; + int i, n = pScrPriv->numCrtcs; + + int *reachable = xcalloc(n, sizeof(int)); + + if (!reachable) + goto out; + + /* Find first enabled CRTC and start search for reachable CRTCs from it */ + for (i = 0; i < n; ++i) { + if (pScrPriv->crtcs[i]->mode) { + mark_crtcs(pScrPriv, reachable, i); + break; + } + } + + /* Check that all enabled CRTCs were marked as reachable */ + for (i = 0; i < n; ++i) + if (pScrPriv->crtcs[i]->mode && !reachable[i]) + goto out; + + discontiguous = FALSE; + + out: + xfree(reachable); + pScrPriv->discontiguous = discontiguous; +} + +static void +rrDestroySharedPixmap(RRCrtcPtr crtc, PixmapPtr pPixmap) { +#ifndef NXAGENT_SERVER + ScreenPtr master = crtc->pScreen->current_master; + + if (master && pPixmap->master_pixmap) { + PixmapPtr mscreenpix = master->GetScreenPixmap(master); + + master->StopPixmapTracking(mscreenpix, pPixmap); + /* + * Unref the pixmap twice: once for the original reference, and once + * for the reference implicitly added by PixmapShareToSlave. + */ + master->DestroyPixmap(pPixmap->master_pixmap); + master->DestroyPixmap(pPixmap->master_pixmap); + } +#endif + + crtc->pScreen->DestroyPixmap(pPixmap); +} + +void +RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc) +{ + rrScrPriv(crtc->pScreen); + + pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL); + if (crtc->scanout_pixmap) { + rrDestroySharedPixmap(crtc, crtc->scanout_pixmap); + } + crtc->scanout_pixmap = NULL; + RRCrtcChanged(crtc, TRUE); +} + +#ifndef NXAGENT_SERVER +static PixmapPtr +rrCreateSharedPixmap(RRCrtcPtr crtc, ScreenPtr master, + int width, int height, int depth, + int x, int y, Rotation rotation) +{ + Bool ret; + PixmapPtr mpix, spix; + rrScrPriv(crtc->pScreen); + + mpix = master->CreatePixmap(master, width, height, depth, + CREATE_PIXMAP_USAGE_SHARED); + if (!mpix) + return NULL; + + spix = PixmapShareToSlave(mpix, crtc->pScreen); + if (spix == NULL) { + master->DestroyPixmap(mpix); + return NULL; + } + + ret = pScrPriv->rrCrtcSetScanoutPixmap(crtc, spix); + if (ret == FALSE) { + rrDestroySharedPixmap(crtc, spix); + ErrorF("randr: failed to set shadow slave pixmap\n"); + return NULL; + } + + return spix; +} + +static Bool +rrSetupPixmapSharing(RRCrtcPtr crtc, int width, int height, + int x, int y, Rotation rotation) +{ + ScreenPtr master = crtc->pScreen->current_master; + int depth; + PixmapPtr mscreenpix; + PixmapPtr spix; + + /* create a pixmap on the master screen, + then get a shared handle for it + create a shared pixmap on the slave screen using the handle + set the master screen to do dirty updates to the shared pixmap + from the screen pixmap. + set slave screen to scanout shared linear pixmap + */ + + mscreenpix = master->GetScreenPixmap(master); + depth = mscreenpix->drawable.depth; + + if (crtc->scanout_pixmap) + RRCrtcDetachScanoutPixmap(crtc); + + if (width == 0 && height == 0) { + return TRUE; + } + + spix = rrCreateSharedPixmap(crtc, master, + width, height, depth, + x, y, rotation); + if (spix == NULL) { + return FALSE; + } + + crtc->scanout_pixmap = spix; + + master->StartPixmapTracking(mscreenpix, spix, x, y, 0, 0, rotation); + return TRUE; +} + +static void crtc_to_box(BoxPtr box, RRCrtcPtr crtc) +{ + box->x1 = crtc->x; + box->y1 = crtc->y; + switch (crtc->rotation) { + case RR_Rotate_0: + case RR_Rotate_180: + default: + box->x2 = crtc->x + crtc->mode->mode.width; + box->y2 = crtc->y + crtc->mode->mode.height; + break; + case RR_Rotate_90: + case RR_Rotate_270: + box->x2 = crtc->x + crtc->mode->mode.height; + box->y2 = crtc->y + crtc->mode->mode.width; + break; + } +} + +static Bool +rrCheckPixmapBounding(ScreenPtr pScreen, + RRCrtcPtr rr_crtc, Rotation rotation, + int x, int y, int w, int h) +{ + RegionRec root_pixmap_region, total_region, new_crtc_region; + int c; + BoxRec newbox; + BoxPtr newsize; + ScreenPtr slave; + int new_width, new_height; + PixmapPtr screen_pixmap = pScreen->GetScreenPixmap(pScreen); + rrScrPriv(pScreen); + + PixmapRegionInit(&root_pixmap_region, screen_pixmap); + RegionInit(&total_region, NULL, 0); + + /* have to iterate all the crtcs of the attached gpu masters + and all their output slaves */ + for (c = 0; c < pScrPriv->numCrtcs; c++) { + RRCrtcPtr crtc = pScrPriv->crtcs[c]; + + if (crtc == rr_crtc) { + newbox.x1 = x; + newbox.y1 = y; + if (rotation == RR_Rotate_90 || + rotation == RR_Rotate_270) { + newbox.x2 = x + h; + newbox.y2 = y + w; + } else { + newbox.x2 = x + w; + newbox.y2 = y + h; + } + } else { + if (!crtc->mode) + continue; + crtc_to_box(&newbox, crtc); + } + RegionInit(&new_crtc_region, &newbox, 1); + RegionUnion(&total_region, &total_region, &new_crtc_region); + } + + xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) { + rrScrPrivPtr slave_priv = rrGetScrPriv(slave); + for (c = 0; c < slave_priv->numCrtcs; c++) { + RRCrtcPtr slave_crtc = slave_priv->crtcs[c]; + + if (slave_crtc == rr_crtc) { + newbox.x1 = x; + newbox.y1 = y; + if (rotation == RR_Rotate_90 || + rotation == RR_Rotate_270) { + newbox.x2 = x + h; + newbox.y2 = y + w; + } else { + newbox.x2 = x + w; + newbox.y2 = y + h; + } + } + else { + if (!slave_crtc->mode) + continue; + crtc_to_box(&newbox, slave_crtc); + } + RegionInit(&new_crtc_region, &newbox, 1); + RegionUnion(&total_region, &total_region, &new_crtc_region); + } + } + + newsize = RegionExtents(&total_region); + new_width = newsize->x2 - newsize->x1; + new_height = newsize->y2 - newsize->y1; + + if (new_width == screen_pixmap->drawable.width && + new_height == screen_pixmap->drawable.height) { + } else { + pScrPriv->rrScreenSetSize(pScreen, new_width, new_height, 0, 0); + } + + /* set shatters TODO */ + return TRUE; +} +#endif /* !defined(NXAGENT_SERVER) */ + /* * Request that the Crtc be reconfigured */ @@ -280,9 +614,20 @@ RRCrtcSet(RRCrtcPtr crtc, { ScreenPtr pScreen = crtc->pScreen; Bool ret = FALSE; + Bool recompute = TRUE; + Bool crtcChanged; + int o; rrScrPriv(pScreen); + crtcChanged = FALSE; + for (o = 0; o < numOutputs; o++) { + if (outputs[o] && outputs[o]->crtc != crtc) { + crtcChanged = TRUE; + break; + } + } + /* See if nothing changed */ if (crtc->mode == mode && crtc->x == x && @@ -290,10 +635,31 @@ RRCrtcSet(RRCrtcPtr crtc, crtc->rotation == rotation && crtc->numOutputs == numOutputs && !memcmp(crtc->outputs, outputs, numOutputs * sizeof(RROutputPtr)) && - !RRCrtcPendingProperties(crtc)) { + !RRCrtcPendingProperties(crtc) && !RRCrtcPendingTransform(crtc) && + !crtcChanged) { + recompute = FALSE; ret = TRUE; } else { +#ifndef NXAGENT_SERVER + if (pScreen->isGPU) { + ScreenPtr master = pScreen->current_master; + int width = 0, height = 0; + + if (mode) { + width = mode->mode.width; + height = mode->mode.height; + } + ret = rrCheckPixmapBounding(master, crtc, + rotation, x, y, width, height); + if (!ret) + return FALSE; + + if (pScreen->current_master) { + ret = rrSetupPixmapSharing(crtc, width, height, x, y, rotation); + } + } +#endif #if RANDR_12_INTERFACE if (pScrPriv->rrCrtcSet) { ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, @@ -308,7 +674,7 @@ RRCrtcSet(RRCrtcPtr crtc, RRScreenRate rate; if (!mode) { - RRCrtcNotify(crtc, NULL, x, y, rotation, 0, NULL); + RRCrtcNotify(crtc, NULL, x, y, rotation, NULL, 0, NULL); ret = TRUE; } else { @@ -332,7 +698,8 @@ RRCrtcSet(RRCrtcPtr crtc, * Old 1.0 interface tied screen size to mode size */ if (ret) { - RRCrtcNotify(crtc, mode, x, y, rotation, 1, outputs); + RRCrtcNotify(crtc, mode, x, y, rotation, NULL, 1, + outputs); RRScreenSizeNotify(pScreen); } } @@ -340,7 +707,6 @@ RRCrtcSet(RRCrtcPtr crtc, #endif } if (ret) { - int o; RRTellChanged(pScreen); @@ -348,10 +714,38 @@ RRCrtcSet(RRCrtcPtr crtc, RRPostPendingProperties(outputs[o]); } } + + if (recompute) + RRComputeContiguity(pScreen); + return ret; } /* + * Return crtc transform + */ +RRTransformPtr +RRCrtcGetTransform(RRCrtcPtr crtc) +{ + RRTransformPtr transform = &crtc->client_pending_transform; + + if (pixman_transform_is_identity(&transform->transform)) + return NULL; + return transform; +} + +/* + * Check whether the pending and current transforms are the same + */ +Bool +RRCrtcPendingTransform(RRCrtcPtr crtc) +{ + return memcmp(&crtc->client_current_transform.transform, + &crtc->client_pending_transform.transform, + sizeof(PictTransform)) != 0; +} + +/* * Destroy a Crtc at shutdown */ void @@ -378,9 +772,13 @@ RRCrtcDestroyResource(void *value, XID pid) break; } } + + RRResourcesChanged(pScreen); } - if (crtc->gammaRed) - xfree(crtc->gammaRed); + + if (crtc->scanout_pixmap) + RRCrtcDetachScanoutPixmap(crtc); + xfree(crtc->gammaRed); if (crtc->mode) RRModeDestroy(crtc->mode); xfree(crtc); @@ -414,6 +812,29 @@ RRCrtcGammaSet(RRCrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue) } /* + * 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 @@ -425,30 +846,35 @@ RRCrtcGammaNotify(RRCrtcPtr crtc) return TRUE; /* not much going on here */ } -/** - * Returns the width/height that the crtc scans out from the framebuffer - */ -void -RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height) +static void +RRModeGetScanoutSize(RRModePtr mode, PictTransformPtr transform, + int *width, int *height) { - if (crtc->mode == NULL) { + BoxRec box; + + if (mode == NULL) { *width = 0; *height = 0; return; } - switch (crtc->rotation & 0xf) { - case RR_Rotate_0: - case RR_Rotate_180: - *width = crtc->mode->mode.width; - *height = crtc->mode->mode.height; - break; - case RR_Rotate_90: - case RR_Rotate_270: - *width = crtc->mode->mode.height; - *height = crtc->mode->mode.width; - break; - } + 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); } /* @@ -463,14 +889,17 @@ RRCrtcGammaSetSize(RRCrtcPtr crtc, int size) if (size == crtc->gammaSize) return TRUE; if (size) { +#ifndef NXAGENT_SERVER + gamma = xallocarray(size, 3 * sizeof(CARD16)); +#else /* !defined(NXAGENT_SERVER) */ gamma = xalloc(size * 3 * sizeof(CARD16)); +#endif /* !defined(NXAGENT_SERVER) */ if (!gamma) return FALSE; } else gamma = NULL; - if (crtc->gammaRed) - xfree(crtc->gammaRed); + xfree(crtc->gammaRed); crtc->gammaRed = gamma; crtc->gammaGreen = gamma + size; crtc->gammaBlue = gamma + size * 2; @@ -479,18 +908,79 @@ RRCrtcGammaSetSize(RRCrtcPtr crtc, int size) } /* + * 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); + RRCrtcType = CreateNewResourceType(RRCrtcDestroyResource +#ifndef NXAGENT_SERVER + , "CRTC" +#endif + ); if (!RRCrtcType) return FALSE; - RegisterResourceName(RRCrtcType, "CRTC"); + return TRUE; } +/* + * Initialize crtc type error value + */ +void +RRCrtcInitErrorValue(void) +{ +#ifndef NXAGENT_SERVER + SetResourceTypeErrorValue(RRCrtcType, RRErrorBase + BadRRCrtc); +#endif +} + int ProcRRGetCrtcInfo(ClientPtr client) { @@ -504,14 +994,13 @@ ProcRRGetCrtcInfo(ClientPtr client) RRModePtr mode; RROutput *outputs; RROutput *possible; - int i, j, k, n; + int i, j, k; int width, height; + BoxRec panned_area; + int n; REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); - crtc = LookupCrtc(client, stuff->crtc, DixReadAccess); - - if (!crtc) - return RRErrorBase + BadRRCrtc; + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); /* All crtcs must be associated with screens before client * requests are processed @@ -521,16 +1010,28 @@ ProcRRGetCrtcInfo(ClientPtr client) mode = crtc->mode; - rep.type = X_Reply; - rep.status = RRSetConfigSuccess; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.timestamp = pScrPriv->lastSetTime.milliseconds; - rep.x = crtc->x; - rep.y = crtc->y; - RRCrtcGetScanoutSize(crtc, &width, &height); - rep.width = width; - rep.height = height; + rep = (xRRGetCrtcInfoReply) { + .type = X_Reply, + .status = RRSetConfigSuccess, + .sequenceNumber = client->sequence, + .length = 0, + .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; @@ -591,7 +1092,7 @@ ProcRRGetCrtcInfo(ClientPtr client) xfree(extra); } - return client->noClientException; + return Success; } int @@ -608,32 +1109,35 @@ ProcRRSetCrtcConfig(ClientPtr client) RROutput *outputIds; TimeStamp time; Rotation rotation; - int i, j; + int +#ifndef NXAGENT_SERVER + ret, +#endif + i, j; + CARD8 status; + int n; REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq); - numOutputs = (stuff->length - (SIZEOF(xRRSetCrtcConfigReq) >> 2)); + numOutputs = (stuff->length - bytes_to_int32(SIZEOF(xRRSetCrtcConfigReq))); + + VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess); - crtc = LookupIDByType(stuff->crtc, RRCrtcType); - if (!crtc) { - client->errorValue = stuff->crtc; - return RRErrorBase + BadRRCrtc; - } if (stuff->mode == None) { mode = NULL; if (numOutputs > 0) return BadMatch; } else { - mode = LookupIDByType(stuff->mode, RRModeType); - if (!mode) { - client->errorValue = stuff->mode; - return RRErrorBase + BadRRMode; - } + VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess); if (numOutputs == 0) return BadMatch; } if (numOutputs) { +#ifndef NXAGENT_SERVER + outputs = xallocarray(numOutputs, sizeof(RROutputPtr)); +#else /* !defined(NXAGENT_SERVER) */ outputs = xalloc(numOutputs * sizeof(RROutputPtr)); +#endif /* !defined(NXAGENT_SERVER) */ if (!outputs) return BadAlloc; } @@ -642,6 +1146,15 @@ ProcRRSetCrtcConfig(ClientPtr client) outputIds = (RROutput *) (stuff + 1); for (i = 0; i < numOutputs; i++) { +#ifndef NXAGENT_SERVER + ret = dixLookupResourceByType((void **) (outputs + i), outputIds[i], + RROutputType, client, DixSetAttrAccess); + + if (ret != Success) { + xfree(outputs); + return ret; + } +#else /* !defined(NXAGENT_SERVER) */ outputs[i] = (RROutputPtr) LookupIDByType(outputIds[i], RROutputType); if (!outputs[i]) { client->errorValue = outputIds[i]; @@ -649,13 +1162,13 @@ ProcRRSetCrtcConfig(ClientPtr client) xfree(outputs); return RRErrorBase + BadRROutput; } +#endif /* !defined(NXAGENT_SERVER) */ /* 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); + xfree(outputs); return BadMatch; } /* validate mode for this output */ @@ -667,8 +1180,7 @@ ProcRRSetCrtcConfig(ClientPtr client) break; } if (j == outputs[i]->numModes + outputs[i]->numUserModes) { - if (outputs) - xfree(outputs); + xfree(outputs); return BadMatch; } } @@ -684,8 +1196,7 @@ ProcRRSetCrtcConfig(ClientPtr client) break; } if (k == outputs[i]->numClones) { - if (outputs) - xfree(outputs); + xfree(outputs); return BadMatch; } } @@ -698,7 +1209,7 @@ ProcRRSetCrtcConfig(ClientPtr client) if (!pScrPriv) { time = currentTime; - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; goto sendReply; } @@ -719,8 +1230,7 @@ ProcRRSetCrtcConfig(ClientPtr client) * Invalid rotation */ client->errorValue = stuff->rotation; - if (outputs) - xfree(outputs); + xfree(outputs); return BadValue; } @@ -730,8 +1240,7 @@ ProcRRSetCrtcConfig(ClientPtr client) * requested rotation or reflection not supported by screen */ client->errorValue = stuff->rotation; - if (outputs) - xfree(outputs); + xfree(outputs); return BadMatch; } @@ -739,71 +1248,220 @@ ProcRRSetCrtcConfig(ClientPtr client) /* * 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 + * 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) { - int source_width = mode->mode.width; - int source_height = mode->mode.height; - - if ((rotation & 0xf) == RR_Rotate_90 || - (rotation & 0xf) == RR_Rotate_270) { - source_width = mode->mode.height; - source_height = mode->mode.width; + if (pScrPriv->rrScreenSetSize && !crtc->transforms) { + int source_width; + int source_height; + PictTransform transform; + struct pixman_f_transform f_transform, f_inverse; + int width, height; + +#ifndef NXAGENT_SERVER + if (pScreen->isGPU) { + width = pScreen->current_master->width; + height = pScreen->current_master->height; } - if (stuff->x + source_width > pScreen->width) { + else +#else /* !defined(NXAGENT_SERVER) */ + { + width = pScreen->width; + height = pScreen->height; + } +#endif /* !defined(NXAGENT_SERVER) */ + + 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 > width) { client->errorValue = stuff->x; - if (outputs) - xfree(outputs); + xfree(outputs); return BadValue; } - if (stuff->y + source_height > pScreen->height) { + if (stuff->y + source_height > height) { client->errorValue = stuff->y; - if (outputs) - xfree(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; + status = RRSetConfigFailed; goto sendReply; } - rep.status = RRSetConfigSuccess; + status = RRSetConfigSuccess; pScrPriv->lastSetTime = time; sendReply: - if (outputs) - xfree(outputs); + xfree(outputs); + + rep = (xRRSetCrtcConfigReply) { + .type = X_Reply, + .status = status, + .sequenceNumber = client->sequence, + .length = 0, + .newTimestamp = pScrPriv->lastSetTime.milliseconds + }; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.newTimestamp, n); + } + WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *) &rep); - rep.type = X_Reply; - /* rep.status has already been filled in */ - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; + 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; + + rep = (xRRGetPanningReply) { + .type = X_Reply, + .status = RRSetConfigSuccess, + .sequenceNumber = client->sequence, + .length = 1, + .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) { - int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&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]; + CARD8 status; + 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; + status = RRSetConfigFailed; + goto sendReply; + } + + time = ClientTimeToServerTime(stuff->timestamp); + + if (!pScrPriv->rrGetPanning) + return RRErrorBase + BadRRCrtc; + + total.x1 = stuff->left; + total.y1 = stuff->top; + total.x2 = total.x1 + stuff->width; + total.y2 = total.y1 + stuff->height; + tracking.x1 = stuff->track_left; + tracking.y1 = stuff->track_top; + tracking.x2 = tracking.x1 + stuff->track_width; + tracking.y2 = tracking.y1 + stuff->track_height; + border[0] = stuff->border_left; + border[1] = stuff->border_top; + border[2] = stuff->border_right; + border[3] = stuff->border_bottom; + + if (!pScrPriv->rrSetPanning(pScreen, crtc, &total, &tracking, border)) + return BadMatch; + + pScrPriv->lastSetTime = time; + status = RRSetConfigSuccess; + + sendReply: + rep = (xRRSetPanningReply) { + .type = X_Reply, + .status = status, + .sequenceNumber = client->sequence, + .length = 0, + .newTimestamp = pScrPriv->lastSetTime.milliseconds + }; + if (client->swapped) { swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); swapl(&rep.newTimestamp, n); } - WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *) &rep); - - return client->noClientException; + WriteToClient(client, sizeof(xRRSetPanningReply), (char *) &rep); + return Success; } int @@ -815,21 +1473,25 @@ ProcRRGetCrtcGammaSize(ClientPtr client) int n; REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq); - crtc = LookupCrtc(client, stuff->crtc, DixReadAccess); - if (!crtc) + 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; + reply = (xRRGetCrtcGammaSizeReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .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; + return Success; } int @@ -838,13 +1500,15 @@ ProcRRGetCrtcGamma(ClientPtr client) REQUEST(xRRGetCrtcGammaReq); xRRGetCrtcGammaReply reply; RRCrtcPtr crtc; - int n; unsigned long len; - char *extra; + char *extra = NULL; + int n; REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq); - crtc = LookupCrtc(client, stuff->crtc, DixReadAccess); - if (!crtc) + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* Gamma retrieval failed, any better error? */ + if (!RRCrtcGammaGet(crtc)) return RRErrorBase + BadRRCrtc; len = crtc->gammaSize * 3 * 2; @@ -855,10 +1519,12 @@ ProcRRGetCrtcGamma(ClientPtr client) return BadAlloc; } - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = (len + 3) >> 2; - reply.size = crtc->gammaSize; + reply = (xRRGetCrtcGammaReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = bytes_to_int32(len), + .size = crtc->gammaSize + }; if (client->swapped) { swaps(&reply.sequenceNumber, n); swapl(&reply.length, n); @@ -871,7 +1537,7 @@ ProcRRGetCrtcGamma(ClientPtr client) WriteSwappedDataToClient(client, len, extra); xfree(extra); } - return client->noClientException; + return Success; } int @@ -883,11 +1549,9 @@ ProcRRSetCrtcGamma(ClientPtr client) CARD16 *red, *green, *blue; REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq); - crtc = LookupCrtc(client, stuff->crtc, DixWriteAccess); - if (!crtc) - return RRErrorBase + BadRRCrtc; + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - len = client->req_len - (sizeof(xRRSetCrtcGammaReq) >> 2); + len = client->req_len - bytes_to_int32(sizeof(xRRSetCrtcGammaReq)); if (len < (stuff->size * 3 + 1) >> 1) return BadLength; @@ -902,3 +1566,335 @@ ProcRRSetCrtcGamma(ClientPtr client) 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 nextra; + RRTransformPtr current, pending; + char *extra; + int n; + + 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 = xcalloc(1, 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 Success; +} + +static Bool +check_all_screen_crtcs(ScreenPtr pScreen, int *x, int *y) +{ + rrScrPriv(pScreen); + int i; + for (i = 0; i < pScrPriv->numCrtcs; i++) { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + + int left, right, top, bottom; + + if (!crtc->mode) + continue; + + crtc_bounds(crtc, &left, &right, &top, &bottom); + + if ((*x >= left) && (*x < right) && (*y >= top) && (*y < bottom)) + return TRUE; + } + return FALSE; +} + +static Bool +constrain_all_screen_crtcs( +#ifndef NXAGENT_SERVER + DeviceIntPtr pDev, +#endif /* !defined(NXAGENT_SERVER) */ + ScreenPtr pScreen, int *x, int *y) +{ + rrScrPriv(pScreen); + int i; + + /* if we're trying to escape, clamp to the CRTC we're coming from */ + for (i = 0; i < pScrPriv->numCrtcs; i++) { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + int nx, ny; + int left, right, top, bottom; + + if (!crtc->mode) + continue; + + crtc_bounds(crtc, &left, &right, &top, &bottom); +#ifndef NXAGENT_SERVER + miPointerGetPosition(pDev, &nx, &ny); +#else /* !defined(NXAGENT_SERVER) */ + + miPointerPosition(&nx, &ny); +#endif /* !defined(NXAGENT_SERVER) */ + + if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom)) { + if (*x < left) + *x = left; + if (*x >= right) + *x = right - 1; + if (*y < top) + *y = top; + if (*y >= bottom) + *y = bottom - 1; + + return TRUE; + } + } + return FALSE; +} + +void +RRConstrainCursorHarder( +#ifndef NXAGENT_SERVER + DeviceIntPtr pDev, +#endif /* !defined(NXAGENT_SERVER) */ + ScreenPtr pScreen, int mode, int *x, + int *y) +{ + rrScrPriv(pScreen); + Bool ret; +#ifndef NXAGENT_SERVER + ScreenPtr slave; +#endif + + /* intentional dead space -> let it float */ + if (pScrPriv->discontiguous) + return; + + /* if we're moving inside a crtc, we're fine */ + ret = check_all_screen_crtcs(pScreen, x, y); + if (ret == TRUE) + return; + +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) { + ret = check_all_screen_crtcs(slave, x, y); + if (ret == TRUE) + return; + } +#endif /* !defined(NXAGENT_SERVER) */ + + /* if we're trying to escape, clamp to the CRTC we're coming from */ + ret = constrain_all_screen_crtcs( +#ifndef NXAGENT_SERVER + pDev, +#endif /* !defined(NXAGENT_SERVER) */ + pScreen, x, y); + if (ret == TRUE) + return; + +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) { + ret = constrain_all_screen_crtcs(pDev, slave, x, y); + if (ret == TRUE) + return; + } +#endif /* !defined(NXAGENT_SERVER) */ +} + +Bool +RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable) +{ + rrScrPriv(pDrawable->pScreen); + Bool ret = TRUE; + PixmapPtr *saved_scanout_pixmap; + int i; + + saved_scanout_pixmap = xalloc(sizeof(PixmapPtr) * pScrPriv->numCrtcs); + if (saved_scanout_pixmap == NULL) + return FALSE; + + for (i = 0; i < pScrPriv->numCrtcs; i++) { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + Bool size_fits; + + saved_scanout_pixmap[i] = crtc->scanout_pixmap; + + if (!crtc->mode && enable) + continue; + if (!crtc->scanout_pixmap && !enable) + continue; + + size_fits = (crtc->mode && + crtc->x == pDrawable->x && + crtc->y == pDrawable->y && + crtc->mode->mode.width == pDrawable->width && + crtc->mode->mode.height == pDrawable->height); + + /* is the pixmap already set? */ + if (crtc->scanout_pixmap == pPixmap) { + /* if its a disable then don't care about size */ + if (enable == FALSE) { + /* set scanout to NULL */ + crtc->scanout_pixmap = NULL; + } + else if (!size_fits) { + /* if the size no longer fits then drop off */ + crtc->scanout_pixmap = NULL; + pScrPriv->rrCrtcSetScanoutPixmap(crtc, crtc->scanout_pixmap); + + (*pScrPriv->rrCrtcSet) (pDrawable->pScreen, crtc, crtc->mode, crtc->x, crtc->y, + crtc->rotation, crtc->numOutputs, crtc->outputs); + saved_scanout_pixmap[i] = crtc->scanout_pixmap; + ret = FALSE; + } + else { + /* if the size fits then we are already setup */ + } + } + else { + if (!size_fits) + ret = FALSE; + else if (enable) + crtc->scanout_pixmap = pPixmap; + else + /* reject an attempt to disable someone else's scanout_pixmap */ + ret = FALSE; + } + } + + for (i = 0; i < pScrPriv->numCrtcs; i++) { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + + if (crtc->scanout_pixmap == saved_scanout_pixmap[i]) + continue; + + if (ret) { + pScrPriv->rrCrtcSetScanoutPixmap(crtc, crtc->scanout_pixmap); + + (*pScrPriv->rrCrtcSet) (pDrawable->pScreen, crtc, crtc->mode, + crtc->x, crtc->y, crtc->rotation, + crtc->numOutputs, crtc->outputs); + } + else + crtc->scanout_pixmap = saved_scanout_pixmap[i]; + } + xfree(saved_scanout_pixmap); + + return ret; +} diff --git a/nx-X11/programs/Xserver/randr/rrdispatch.c b/nx-X11/programs/Xserver/randr/rrdispatch.c index a8fa6965f..a8ca35d16 100644 --- a/nx-X11/programs/Xserver/randr/rrdispatch.c +++ b/nx-X11/programs/Xserver/randr/rrdispatch.c @@ -21,48 +21,62 @@ */ #include "randrstr.h" - -#define SERVER_RANDR_MAJOR 1 -#define SERVER_RANDR_MINOR 2 +#ifndef NXAGENT_SERVER +#include "protocol-versions.h" +#else +#define SERVER_RANDR_MAJOR_VERSION 1 +#define SERVER_RANDR_MINOR_VERSION 5 +#endif Bool RRClientKnowsRates(ClientPtr pClient) { rrClientPriv(pClient); - return (pRRClient->major_version > 1 || - (pRRClient->major_version == 1 && pRRClient->minor_version >= 1)); + return version_compare(pRRClient->major_version, pRRClient->minor_version, + 1, 1) >= 0; } static int ProcRRQueryVersion(ClientPtr client) { - xRRQueryVersionReply rep; - register int n; + int n; + xRRQueryVersionReply rep = { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0 + }; 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; - /* - * Report the current version; the current - * spec says they're all compatible after 1.0 - */ - rep.majorVersion = SERVER_RANDR_MAJOR; - rep.minorVersion = SERVER_RANDR_MINOR; + + if (version_compare(stuff->majorVersion, stuff->minorVersion, + SERVER_RANDR_MAJOR_VERSION, + SERVER_RANDR_MINOR_VERSION) < 0) { + rep.majorVersion = stuff->majorVersion; + rep.minorVersion = stuff->minorVersion; + } + else { + rep.majorVersion = SERVER_RANDR_MAJOR_VERSION; + rep.minorVersion = SERVER_RANDR_MINOR_VERSION; + } + if (client->swapped) { swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); swapl(&rep.majorVersion, n); swapl(&rep.minorVersion, n); } +#ifndef NXAGENT_SERVER + WriteToClient(client, sizeof(xRRQueryVersionReply), &rep); +#else WriteToClient(client, sizeof(xRRQueryVersionReply), (char *) &rep); - return (client->noClientException); +#endif + return Success; } static int @@ -78,19 +92,30 @@ ProcRRSelectInput(ClientPtr client) REQUEST_SIZE_MATCH(xRRSelectInputReq); #ifndef NXAGENT_SERVER - rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess); + rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess); #else pWin = SecurityLookupWindow(stuff->window, client, SecurityWriteAccess); rc = pWin ? Success : BadWindow; #endif if (rc != Success) return rc; - pHead = (RREventPtr *) SecurityLookupIDByType(client, - pWin->drawable.id, - RREventType, DixWriteAccess); +#ifndef NXAGENT_SERVER + rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id, + RREventType, client, DixWriteAccess); +#else /* !defined(NXAGENT_SERVER) */ + pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, RREventType); +#endif /* !defined(NXAGENT_SERVER) */ + + if (rc != Success && rc != BadValue) + return rc; if (stuff->enable & (RRScreenChangeNotifyMask | - RRCrtcChangeNotifyMask | RROutputChangeNotifyMask)) { + RRCrtcChangeNotifyMask | + RROutputChangeNotifyMask | + RROutputPropertyNotifyMask | + RRProviderChangeNotifyMask | + RRProviderPropertyNotifyMask | + RRResourceChangeNotifyMask)) { ScreenPtr pScreen = pWin->drawable.pScreen; rrScrPriv(pScreen); @@ -142,13 +167,37 @@ ProcRRSelectInput(ClientPtr client) /* * Now see if the client needs an event */ - if (pScrPriv && (pRREvent->mask & RRScreenChangeNotifyMask)) { + if (pScrPriv) { pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; if (CompareTimeStamps(pTimes->setTime, pScrPriv->lastSetTime) != 0 || CompareTimeStamps(pTimes->configTime, pScrPriv->lastConfigTime) != 0) { - RRDeliverScreenEvent(client, pWin, pScreen); + if (pRREvent->mask & RRScreenChangeNotifyMask) { + RRDeliverScreenEvent(client, pWin, pScreen); + } + + if (pRREvent->mask & RRCrtcChangeNotifyMask) { + int i; + + for (i = 0; i < pScrPriv->numCrtcs; i++) { + RRDeliverCrtcEvent(client, pWin, pScrPriv->crtcs[i]); + } + } + + if (pRREvent->mask & RROutputChangeNotifyMask) { + int i; + + for (i = 0; i < pScrPriv->numOutputs; i++) { + RRDeliverOutputEvent(client, pWin, + pScrPriv->outputs[i]); + } + } + + /* We don't check for RROutputPropertyNotifyMask, as randrproto.txt doesn't + * say if there ought to be notifications of changes to output properties + * if those changes occurred before the time RRSelectInput is called. + */ } } } @@ -209,4 +258,26 @@ int (*ProcRandrVector[RRNumberRequests]) (ClientPtr) = { ProcRRGetCrtcGammaSize, /* 22 */ ProcRRGetCrtcGamma, /* 23 */ ProcRRSetCrtcGamma, /* 24 */ +/* V1.3 additions */ + ProcRRGetScreenResourcesCurrent, /* 25 */ + ProcRRSetCrtcTransform, /* 26 */ + ProcRRGetCrtcTransform, /* 27 */ + ProcRRGetPanning, /* 28 */ + ProcRRSetPanning, /* 29 */ + ProcRRSetOutputPrimary, /* 30 */ + ProcRRGetOutputPrimary, /* 31 */ +/* V1.4 additions */ + ProcRRGetProviders, /* 32 */ + ProcRRGetProviderInfo, /* 33 */ + ProcRRSetProviderOffloadSink, /* 34 */ + ProcRRSetProviderOutputSource, /* 35 */ + ProcRRListProviderProperties, /* 36 */ + ProcRRQueryProviderProperty, /* 37 */ + ProcRRConfigureProviderProperty, /* 38 */ + ProcRRChangeProviderProperty, /* 39 */ + ProcRRDeleteProviderProperty, /* 40 */ + ProcRRGetProviderProperty, /* 41 */ + ProcRRGetMonitors, /* 42 */ + ProcRRSetMonitor, /* 43 */ + ProcRRDeleteMonitor, /* 44 */ }; diff --git a/nx-X11/programs/Xserver/randr/rrinfo.c b/nx-X11/programs/Xserver/randr/rrinfo.c index 070f5ca0c..df9b79986 100644 --- a/nx-X11/programs/Xserver/randr/rrinfo.c +++ b/nx-X11/programs/Xserver/randr/rrinfo.c @@ -36,7 +36,7 @@ RROldModeAdd(RROutputPtr output, RRScreenSizePtr size, int refresh) RRModePtr *modes; memset(&modeInfo, '\0', sizeof(modeInfo)); - sprintf(name, "%dx%d", size->width, size->height); + snprintf(name, sizeof(name), "%dx%d", size->width, size->height); modeInfo.width = size->width; modeInfo.height = size->height; @@ -55,8 +55,13 @@ RROldModeAdd(RROutputPtr output, RRScreenSizePtr size, int refresh) } if (output->numModes) +#ifndef NXAGENT_SERVER + modes = reallocarray(output->modes, + output->numModes + 1, sizeof(RRModePtr)); +#else /* !defined(NXAGENT_SERVER) */ modes = xrealloc(output->modes, (output->numModes + 1) * sizeof(RRModePtr)); +#endif /* !defined(NXAGENT_SERVER) */ else modes = xalloc(sizeof(RRModePtr)); if (!modes) { @@ -97,9 +102,7 @@ RRScanOldConfig(ScreenPtr pScreen, Rotation rotations) return; RROutputSetCrtcs(output, &crtc, 1); RROutputSetConnection(output, RR_Connected); -#ifdef RENDER RROutputSetSubpixelOrder(output, PictureGetSubpixelOrder(pScreen)); -#endif } output = pScrPriv->outputs[0]; @@ -145,7 +148,8 @@ RRScanOldConfig(ScreenPtr pScreen, Rotation rotations) /* find size bounds */ for (i = 0; i < output->numModes + output->numUserModes; i++) { mode = (i < output->numModes ? - output->modes[i] : output->userModes[i - output->numModes]); + output->modes[i] : + output->userModes[i - output->numModes]); width = mode->mode.width; height = mode->mode.height; @@ -163,7 +167,7 @@ RRScanOldConfig(ScreenPtr pScreen, Rotation rotations) /* notice current mode */ if (newMode) - RRCrtcNotify(crtc, newMode, 0, 0, pScrPriv->rotation, 1, &output); + RRCrtcNotify(crtc, newMode, 0, 0, pScrPriv->rotation, NULL, 1, &output); } #endif @@ -171,12 +175,20 @@ RRScanOldConfig(ScreenPtr pScreen, Rotation rotations) * Poll the driver for changed information */ Bool -RRGetInfo(ScreenPtr pScreen) +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++) @@ -218,7 +230,7 @@ RRScreenSetSizeRange(ScreenPtr pScreen, pScrPriv->minHeight = minHeight; pScrPriv->maxWidth = maxWidth; pScrPriv->maxHeight = maxHeight; - pScrPriv->changed = TRUE; + RRSetChanged(pScreen); pScrPriv->configChanged = TRUE; } @@ -259,8 +271,13 @@ RRRegisterSize(ScreenPtr pScreen, for (i = 0; i < pScrPriv->nSizes; i++) if (RRScreenSizeMatches(&tmp, &pScrPriv->pSizes[i])) return &pScrPriv->pSizes[i]; +#ifndef NXAGENT_SERVER + pNew = reallocarray(pScrPriv->pSizes, + pScrPriv->nSizes + 1, sizeof(RRScreenSize)); +#else /* !defined(NXAGENT_SERVER) */ pNew = xrealloc(pScrPriv->pSizes, (pScrPriv->nSizes + 1) * sizeof(RRScreenSize)); +#endif /* !defined(NXAGENT_SERVER) */ if (!pNew) return 0; pNew[pScrPriv->nSizes++] = tmp; @@ -282,7 +299,11 @@ RRRegisterRate(ScreenPtr pScreen, RRScreenSizePtr pSize, int rate) if (pSize->pRates[i].rate == rate) return TRUE; +#ifndef NXAGENT_SERVER + pNew = reallocarray(pSize->pRates, pSize->nRates + 1, sizeof(RRScreenRate)); +#else /* !defined(NXAGENT_SERVER) */ pNew = xrealloc(pSize->pRates, (pSize->nRates + 1) * sizeof(RRScreenRate)); +#endif /* !defined(NXAGENT_SERVER) */ if (!pNew) return FALSE; pRate = &pNew[pSize->nRates++]; diff --git a/nx-X11/programs/Xserver/randr/rrmode.c b/nx-X11/programs/Xserver/randr/rrmode.c index 4fe116400..918e0f221 100644 --- a/nx-X11/programs/Xserver/randr/rrmode.c +++ b/nx-X11/programs/Xserver/randr/rrmode.c @@ -38,7 +38,6 @@ /**************************************************************************/ #include "randrstr.h" -#include "registry.h" RESTYPE RRModeType; @@ -97,7 +96,12 @@ RRModeCreate(xRRModeInfo * modeInfo, const char *name, ScreenPtr userScreen) mode->userScreen = userScreen; if (num_modes) +#ifndef NXAGENT_SERVER + newModes = reallocarray(modes, num_modes + 1, sizeof(RRModePtr)); +#else /* !defined(NXAGENT_SERVER) */ newModes = xrealloc(modes, (num_modes + 1) * sizeof(RRModePtr)); +#endif /* !defined(NXAGENT_SERVER) */ + else newModes = xalloc(sizeof(RRModePtr)); @@ -113,6 +117,7 @@ RRModeCreate(xRRModeInfo * modeInfo, const char *name, ScreenPtr userScreen) } modes = newModes; modes[num_modes++] = mode; + /* * give the caller a reference to this mode */ @@ -203,7 +208,11 @@ RRModesForScreen(ScreenPtr pScreen, int *num_ret) RRModePtr *screen_modes; int num_screen_modes = 0; +#ifndef NXAGENT_SERVER + screen_modes = xallocarray((num_modes ? num_modes : 1), sizeof(RRModePtr)); +#else /* !defined(NXAGENT_SERVER) */ screen_modes = xalloc((num_modes ? num_modes : 1) * sizeof(RRModePtr)); +#endif /* !defined(NXAGENT_SERVER) */ if (!screen_modes) return NULL; @@ -268,13 +277,8 @@ RRModeDestroy(RRModePtr mode) { int m; - if (--mode->refcnt > 0) { -#ifdef DEBUG - fprintf(stderr, "RRModeDestroy: mode [%s] ([%p]) refcnt [%d -> %d]\n", - mode->name, mode, mode->refcnt + 1, mode->refcnt); -#endif + if (--mode->refcnt > 0) return; - } for (m = 0; m < num_modes; m++) { if (modes[m] == mode) { memmove(modes + m, modes + m + 1, @@ -288,37 +292,46 @@ RRModeDestroy(RRModePtr mode) } } -#ifdef DEBUG - fprintf(stderr, "RRModeDestroy: destroyed mode [%s] ([%p])\n", mode->name, - mode); -#endif xfree(mode); } static int RRModeDestroyResource(void *value, XID pid) { -#ifdef DEBUG - fprintf(stderr, "RRModeDestroyResource: mode [%s] ([%p]) refcnt [%d]\n", - ((RRModePtr) value)->name, (RRModePtr) value, - ((RRModePtr) value)->refcnt); -#endif RRModeDestroy((RRModePtr) value); return 1; } +/* + * Initialize mode type + */ Bool RRModeInit(void) { assert(num_modes == 0); assert(modes == NULL); - RRModeType = CreateNewResourceType(RRModeDestroyResource); + RRModeType = CreateNewResourceType(RRModeDestroyResource +#ifndef NXAGENT_SERVER + , "MODE" +#endif + ); if (!RRModeType) return FALSE; - RegisterResourceName(RRModeType, "MODE"); + return TRUE; } +/* + * Initialize mode type error value + */ +void +RRModeInitErrorValue(void) +{ +#ifndef NXAGENT_SERVER + SetResourceTypeErrorValue(RRModeType, RRErrorBase + BadRRMode); +#endif +} + int ProcRRCreateMode(ClientPtr client) { @@ -331,10 +344,11 @@ ProcRRCreateMode(ClientPtr client) char *name; int error, rc; RRModePtr mode; + int n; REQUEST_AT_LEAST_SIZE(xRRCreateModeReq); #ifndef NXAGENT_SERVER - rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); #else pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess); rc = pWin ? Success : BadWindow; @@ -346,24 +360,23 @@ ProcRRCreateMode(ClientPtr client) modeInfo = &stuff->modeInfo; name = (char *) (stuff + 1); - units_after = (stuff->length - (sizeof(xRRCreateModeReq) >> 2)); + units_after = (stuff->length - bytes_to_int32(sizeof(xRRCreateModeReq))); /* check to make sure requested name fits within the data provided */ - if ((int) (modeInfo->nameLength + 3) >> 2 > units_after) + 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; + rep = (xRRCreateModeReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .mode = mode->mode.id + }; if (client->swapped) { - int n; - swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); swapl(&rep.mode, n); @@ -371,7 +384,7 @@ ProcRRCreateMode(ClientPtr client) WriteToClient(client, sizeof(xRRCreateModeReply), (char *) &rep); /* Drop out reference to this mode */ RRModeDestroy(mode); - return client->noClientException; + return Success; } int @@ -381,11 +394,8 @@ ProcRRDestroyMode(ClientPtr client) RRModePtr mode; REQUEST_SIZE_MATCH(xRRDestroyModeReq); - mode = LookupIDByType(stuff->mode, RRModeType); - if (!mode) { - client->errorValue = stuff->mode; - return RRErrorBase + BadRRMode; - } + VERIFY_RR_MODE(stuff->mode, mode, DixDestroyAccess); + if (!mode->userScreen) return BadMatch; if (mode->refcnt > 1) @@ -402,18 +412,8 @@ ProcRRAddOutputMode(ClientPtr client) RROutputPtr output; REQUEST_SIZE_MATCH(xRRAddOutputModeReq); - output = LookupOutput(client, stuff->output, DixReadAccess); - - if (!output) { - client->errorValue = stuff->output; - return RRErrorBase + BadRROutput; - } - - mode = LookupIDByType(stuff->mode, RRModeType); - if (!mode) { - client->errorValue = stuff->mode; - return RRErrorBase + BadRRMode; - } + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); + VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess); return RROutputAddUserMode(output, mode); } @@ -426,18 +426,8 @@ ProcRRDeleteOutputMode(ClientPtr client) RROutputPtr output; REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq); - output = LookupOutput(client, stuff->output, DixReadAccess); - - if (!output) { - client->errorValue = stuff->output; - return RRErrorBase + BadRROutput; - } - - mode = LookupIDByType(stuff->mode, RRModeType); - if (!mode) { - client->errorValue = stuff->mode; - return RRErrorBase + BadRRMode; - } + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); + VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess); return RROutputDeleteUserMode(output, mode); } diff --git a/nx-X11/programs/Xserver/randr/rrmonitor.c b/nx-X11/programs/Xserver/randr/rrmonitor.c new file mode 100644 index 000000000..fc9b9295b --- /dev/null +++ b/nx-X11/programs/Xserver/randr/rrmonitor.c @@ -0,0 +1,792 @@ +/* + * Copyright © 2014 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" +#ifndef NXAGENT_SERVER +#include "list.h" +#endif + +static Atom +RRMonitorCrtcName(RRCrtcPtr crtc) +{ + char name[20]; + + if (crtc->numOutputs) { + RROutputPtr output = crtc->outputs[0]; + return MakeAtom(output->name, output->nameLength, TRUE); + } + sprintf(name, "Monitor-%08lx", (unsigned long int) crtc->id); + return MakeAtom(name, strlen(name), TRUE); +} + +static Bool +RRMonitorCrtcPrimary(RRCrtcPtr crtc) +{ + ScreenPtr screen = crtc->pScreen; + rrScrPrivPtr pScrPriv = rrGetScrPriv(screen); + int o; + + for (o = 0; o < crtc->numOutputs; o++) + if (crtc->outputs[o] == pScrPriv->primaryOutput) + return TRUE; + return FALSE; +} + +#define DEFAULT_PIXELS_PER_MM (96.0 / 25.4) + +static void +RRMonitorGetCrtcGeometry(RRCrtcPtr crtc, RRMonitorGeometryPtr geometry) +{ + ScreenPtr screen = crtc->pScreen; + rrScrPrivPtr pScrPriv = rrGetScrPriv(screen); + BoxRec panned_area; + + /* Check to see if crtc is panned and return the full area when applicable. */ + if (pScrPriv && pScrPriv->rrGetPanning && + pScrPriv->rrGetPanning(screen, crtc, &panned_area, NULL, NULL) && + (panned_area.x2 > panned_area.x1) && + (panned_area.y2 > panned_area.y1)) { + geometry->box = panned_area; + } + else { + int width, height; + + RRCrtcGetScanoutSize(crtc, &width, &height); + geometry->box.x1 = crtc->x; + geometry->box.y1 = crtc->y; + geometry->box.x2 = geometry->box.x1 + width; + geometry->box.y2 = geometry->box.y1 + height; + } + if (crtc->numOutputs && crtc->outputs[0]->mmWidth && crtc->outputs[0]->mmHeight) { + RROutputPtr output = crtc->outputs[0]; + geometry->mmWidth = output->mmWidth; + geometry->mmHeight = output->mmHeight; + } else { + geometry->mmWidth = floor((geometry->box.x2 - geometry->box.x1) / DEFAULT_PIXELS_PER_MM + 0.5); + geometry->mmHeight = floor((geometry->box.y2 - geometry->box.y1) / DEFAULT_PIXELS_PER_MM + 0.5); + } +} + +static Bool +RRMonitorSetFromServer(RRCrtcPtr crtc, RRMonitorPtr monitor) +{ + int o; + + monitor->name = RRMonitorCrtcName(crtc); + monitor->pScreen = crtc->pScreen; + monitor->numOutputs = crtc->numOutputs; + monitor->outputs = xcalloc(crtc->numOutputs, sizeof(RRCrtc)); + if (!monitor->outputs) + return FALSE; + for (o = 0; o < crtc->numOutputs; o++) + monitor->outputs[o] = crtc->outputs[o]->id; + monitor->primary = RRMonitorCrtcPrimary(crtc); + monitor->automatic = TRUE; + RRMonitorGetCrtcGeometry(crtc, &monitor->geometry); + return TRUE; +} + +static Bool +RRMonitorAutomaticGeometry(RRMonitorPtr monitor) +{ + return (monitor->geometry.box.x1 == 0 && + monitor->geometry.box.y1 == 0 && + monitor->geometry.box.x2 == 0 && + monitor->geometry.box.y2 == 0); +} + +static void +RRMonitorGetGeometry(RRMonitorPtr monitor, RRMonitorGeometryPtr geometry) +{ + if (RRMonitorAutomaticGeometry(monitor) && monitor->numOutputs > 0) { + ScreenPtr screen = monitor->pScreen; + rrScrPrivPtr pScrPriv = rrGetScrPriv(screen); + RRMonitorGeometryRec first = { .box = {0, 0, 0, 0}, .mmWidth = 0, .mmHeight = 0 }; + RRMonitorGeometryRec this; + int c, o, co; + int active_crtcs = 0; + + *geometry = first; + for (o = 0; o < monitor->numOutputs; o++) { + RRCrtcPtr crtc = NULL; + Bool in_use = FALSE; + + for (c = 0; !in_use && c < pScrPriv->numCrtcs; c++) { + crtc = pScrPriv->crtcs[c]; + if (!crtc->mode) + continue; + for (co = 0; !in_use && co < crtc->numOutputs; co++) + if (monitor->outputs[o] == crtc->outputs[co]->id) + in_use = TRUE; + } + + if (!in_use) + continue; + + RRMonitorGetCrtcGeometry(crtc, &this); + + if (active_crtcs == 0) { + first = this; + *geometry = this; + } else { + geometry->box.x1 = min(this.box.x1, geometry->box.x1); + geometry->box.x2 = max(this.box.x2, geometry->box.x2); + geometry->box.y1 = min(this.box.y1, geometry->box.y1); + geometry->box.y2 = max(this.box.y2, geometry->box.y2); + } + active_crtcs++; + } + + /* Adjust physical sizes to account for total area */ + if (active_crtcs > 1 && first.box.x2 != first.box.x1 && first.box.y2 != first.box.y1) { + geometry->mmWidth = (this.box.x2 - this.box.x1) / (first.box.x2 - first.box.x1) * first.mmWidth; + geometry->mmHeight = (this.box.y2 - this.box.y1) / (first.box.y2 - first.box.y1) * first.mmHeight; + } + } else { + *geometry = monitor->geometry; + } +} + +static Bool +RRMonitorSetFromClient(RRMonitorPtr client_monitor, RRMonitorPtr monitor) +{ + monitor->name = client_monitor->name; + monitor->pScreen = client_monitor->pScreen; + monitor->numOutputs = client_monitor->numOutputs; + monitor->outputs = xcalloc(client_monitor->numOutputs, sizeof(RROutput)); + if (!monitor->outputs && client_monitor->numOutputs) + return FALSE; + memcpy(monitor->outputs, client_monitor->outputs, client_monitor->numOutputs * sizeof(RROutput)); + monitor->primary = client_monitor->primary; + monitor->automatic = client_monitor->automatic; + RRMonitorGetGeometry(client_monitor, &monitor->geometry); + return TRUE; +} + +typedef struct _rrMonitorList { + int num_client; + int num_server; + RRCrtcPtr *server_crtc; + int num_crtcs; + int client_primary; + int server_primary; +} RRMonitorListRec, *RRMonitorListPtr; + +static Bool +RRMonitorInitList(ScreenPtr screen, RRMonitorListPtr mon_list, Bool get_active) +{ + rrScrPrivPtr pScrPriv = rrGetScrPriv(screen); + int m, o, c, sc; + int numCrtcs; +#ifndef NXAGENT_SERVER + ScreenPtr slave; +#endif + + if (!RRGetInfo(screen, FALSE)) + return FALSE; + + /* Count the number of crtcs in this and any slave screens */ + numCrtcs = pScrPriv->numCrtcs; +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(slave, &screen->output_slave_list, output_head) { + rrScrPrivPtr pSlavePriv; + pSlavePriv = rrGetScrPriv(slave); + numCrtcs += pSlavePriv->numCrtcs; + } +#endif + mon_list->num_crtcs = numCrtcs; + + mon_list->server_crtc = xcalloc(numCrtcs * 2, sizeof(RRCrtcPtr)); + if (!mon_list->server_crtc) + return FALSE; + + /* Collect pointers to all of the active crtcs */ + c = 0; + for (sc = 0; sc < pScrPriv->numCrtcs; sc++, c++) { + if (pScrPriv->crtcs[sc]->mode != NULL) + mon_list->server_crtc[c] = pScrPriv->crtcs[sc]; + } + +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(slave, &screen->output_slave_list, output_head) { + rrScrPrivPtr pSlavePriv; + pSlavePriv = rrGetScrPriv(slave); + for (sc = 0; sc < pSlavePriv->numCrtcs; sc++, c++) { + if (pSlavePriv->crtcs[sc]->mode != NULL) + mon_list->server_crtc[c] = pSlavePriv->crtcs[sc]; + } + } +#endif + + /* Walk the list of client-defined monitors, clearing the covered + * CRTCs from the full list and finding whether one of the + * monitors is primary + */ + mon_list->num_client = pScrPriv->numMonitors; + mon_list->client_primary = -1; + + for (m = 0; m < pScrPriv->numMonitors; m++) { + RRMonitorPtr monitor = pScrPriv->monitors[m]; + if (get_active) { + RRMonitorGeometryRec geom; + + RRMonitorGetGeometry(monitor, &geom); + if (geom.box.x2 - geom.box.x1 == 0 || + geom.box.y2 - geom.box.y1 == 0) { + mon_list->num_client--; + continue; + } + } + if (monitor->primary && mon_list->client_primary == -1) + mon_list->client_primary = m; + for (o = 0; o < monitor->numOutputs; o++) { + for (c = 0; c < numCrtcs; c++) { + RRCrtcPtr crtc = mon_list->server_crtc[c]; + if (crtc) { + int co; + for (co = 0; co < crtc->numOutputs; co++) + if (crtc->outputs[co]->id == monitor->outputs[o]) { + mon_list->server_crtc[c] = NULL; + break; + } + } + } + } + } + + /* Now look at the active CRTCs, and count + * those not covered by a client monitor, as well + * as finding whether one of them is marked primary + */ + mon_list->num_server = 0; + mon_list->server_primary = -1; + + for (c = 0; c < mon_list->num_crtcs; c++) { + RRCrtcPtr crtc = mon_list->server_crtc[c]; + + if (!crtc) + continue; + + mon_list->num_server++; + + if (RRMonitorCrtcPrimary(crtc) && mon_list->server_primary == -1) + mon_list->server_primary = c; + } + return TRUE; +} + +static void +RRMonitorFiniList(RRMonitorListPtr list) +{ + xfree(list->server_crtc); +} + +/* Construct a complete list of protocol-visible monitors, including + * the manually generated ones as well as those generated + * automatically from the remaining CRCTs + */ + +Bool +RRMonitorMakeList(ScreenPtr screen, Bool get_active, RRMonitorPtr * monitors_ret, int *nmon_ret) +{ + rrScrPrivPtr pScrPriv = rrGetScrPriv(screen); + RRMonitorListRec list; + int m, c; + RRMonitorPtr mon, monitors; + Bool has_primary = FALSE; + + if (!pScrPriv) + return FALSE; + + if (!RRMonitorInitList(screen, &list, get_active)) + return FALSE; + + monitors = xcalloc(list.num_client + list.num_server, sizeof(RRMonitorRec)); + if (!monitors) { + RRMonitorFiniList(&list); + return FALSE; + } + + mon = monitors; + + /* Fill in the primary monitor data first + */ + if (list.client_primary >= 0) { + RRMonitorSetFromClient(pScrPriv->monitors[list.client_primary], mon); + mon++; + } else if (list.server_primary >= 0) { + RRMonitorSetFromServer(list.server_crtc[list.server_primary], mon); + mon++; + } + + /* Fill in the client-defined monitors next + */ + for (m = 0; m < pScrPriv->numMonitors; m++) { + if (m == list.client_primary) + continue; + if (get_active) { + RRMonitorGeometryRec geom; + + RRMonitorGetGeometry(pScrPriv->monitors[m], &geom); + if (geom.box.x2 - geom.box.x1 == 0 || + geom.box.y2 - geom.box.y1 == 0) { + continue; + } + } + RRMonitorSetFromClient(pScrPriv->monitors[m], mon); + if (has_primary) + mon->primary = FALSE; + else if (mon->primary) + has_primary = TRUE; + mon++; + } + + /* And finish with the list of crtc-inspired monitors + */ + for (c = 0; c < list.num_crtcs; c++) { + RRCrtcPtr crtc = list.server_crtc[c]; + if (c == list.server_primary && list.client_primary < 0) + continue; + + if (!list.server_crtc[c]) + continue; + + RRMonitorSetFromServer(crtc, mon); + if (has_primary) + mon->primary = FALSE; + else if (mon->primary) + has_primary = TRUE; + mon++; + } + + RRMonitorFiniList(&list); + *nmon_ret = list.num_client + list.num_server; + *monitors_ret = monitors; + return TRUE; +} + +int +RRMonitorCountList(ScreenPtr screen) +{ + RRMonitorListRec list; + int nmon; + + if (!RRMonitorInitList(screen, &list, FALSE)) + return -1; + nmon = list.num_client + list.num_server; + RRMonitorFiniList(&list); + return nmon; +} + +void +RRMonitorFree(RRMonitorPtr monitor) +{ + xfree(monitor); +} + +RRMonitorPtr +RRMonitorAlloc(int noutput) +{ + RRMonitorPtr monitor; + + monitor = xcalloc(1, sizeof(RRMonitorRec) + noutput * sizeof(RROutput)); + if (!monitor) + return NULL; + monitor->numOutputs = noutput; + monitor->outputs = (RROutput *) (monitor + 1); + return monitor; +} + +static int +RRMonitorDelete(ClientPtr client, ScreenPtr screen, Atom name) +{ + rrScrPrivPtr pScrPriv = rrGetScrPriv(screen); + int m; + + if (!pScrPriv) { + client->errorValue = name; + return BadAtom; + } + + for (m = 0; m < pScrPriv->numMonitors; m++) { + RRMonitorPtr monitor = pScrPriv->monitors[m]; + if (monitor->name == name) { + memmove(pScrPriv->monitors + m, pScrPriv->monitors + m + 1, + (pScrPriv->numMonitors - (m + 1)) * sizeof(RRMonitorPtr)); + --pScrPriv->numMonitors; + RRMonitorFree(monitor); + return Success; + } + } + + client->errorValue = name; + return BadValue; +} + +static Bool +RRMonitorMatchesOutputName(ScreenPtr screen, Atom name) +{ + rrScrPrivPtr pScrPriv = rrGetScrPriv(screen); + int o; + const char *str = NameForAtom(name); + int len = strlen(str); + + for (o = 0; o < pScrPriv->numOutputs; o++) { + RROutputPtr output = pScrPriv->outputs[o]; + + if (output->nameLength == len && !memcmp(output->name, str, len)) + return TRUE; + } + return FALSE; +} + +int +RRMonitorAdd(ClientPtr client, ScreenPtr screen, RRMonitorPtr monitor) +{ + rrScrPrivPtr pScrPriv = rrGetScrPriv(screen); + int m; +#ifndef NXAGENT_SERVER + ScreenPtr slave; +#endif + RRMonitorPtr *monitors; + + if (!pScrPriv) + return BadAlloc; + + /* 'name' must not match the name of any Output on the screen, or + * a Value error results. + */ + + if (RRMonitorMatchesOutputName(screen, monitor->name)) { + client->errorValue = monitor->name; + return BadValue; + } + +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(slave, &screen->output_slave_list, output_head) { + if (RRMonitorMatchesOutputName(slave, monitor->name)) { + client->errorValue = monitor->name; + return BadValue; + } + } +#endif + + /* 'name' must not match the name of any Monitor on the screen, or + * a Value error results. + */ + + for (m = 0; m < pScrPriv->numMonitors; m++) { + if (pScrPriv->monitors[m]->name == monitor->name) { + client->errorValue = monitor->name; + return BadValue; + } + } + + /* Allocate space for the new pointer. This is done before + * removing matching monitors as it may fail, and the request + * needs to not have any side-effects on failure + */ + if (pScrPriv->numMonitors) +#ifndef NXAGENT_SERVER + monitors = reallocarray(pScrPriv->monitors, + pScrPriv->numMonitors + 1, + sizeof(RRMonitorPtr)); +#else /* !defined(NXAGENT_SERVER) */ + monitors = xrealloc(pScrPriv->monitors, + (pScrPriv->numMonitors + 1) * sizeof(RRMonitorPtr)); +#endif /* !defined(NXAGENT_SERVER) */ + else + monitors = xalloc(sizeof(RRMonitorPtr)); + + if (!monitors) + return BadAlloc; + + pScrPriv->monitors = monitors; + + for (m = 0; m < pScrPriv->numMonitors; m++) { + RRMonitorPtr existing = pScrPriv->monitors[m]; + int o, eo; + + /* If 'name' matches an existing Monitor on the screen, the + * existing one will be deleted as if RRDeleteMonitor were called. + */ + if (existing->name == monitor->name) { + (void) RRMonitorDelete(client, screen, existing->name); + continue; + } + + /* For each output in 'info.outputs', each one is removed from all + * pre-existing Monitors. If removing the output causes the list + * of outputs for that Monitor to become empty, then that + * Monitor will be deleted as if RRDeleteMonitor were called. + */ + + for (eo = 0; eo < existing->numOutputs; eo++) { + for (o = 0; o < monitor->numOutputs; o++) { + if (monitor->outputs[o] == existing->outputs[eo]) { + memmove(existing->outputs + eo, existing->outputs + eo + 1, + (existing->numOutputs - (eo + 1)) * sizeof(RROutput)); + --existing->numOutputs; + --eo; + break; + } + } + if (existing->numOutputs == 0) { + (void) RRMonitorDelete(client, screen, existing->name); + break; + } + } + if (monitor->primary) + existing->primary = FALSE; + } + + /* Add the new one to the list + */ + pScrPriv->monitors[pScrPriv->numMonitors++] = monitor; + + return Success; +} + +void +RRMonitorFreeList(RRMonitorPtr monitors, int nmon) +{ + int m; + + for (m = 0; m < nmon; m++) + xfree(monitors[m].outputs); + xfree(monitors); +} + +void +RRMonitorInit(ScreenPtr screen) +{ + rrScrPrivPtr pScrPriv = rrGetScrPriv(screen); + + if (!pScrPriv) + return; + + pScrPriv->numMonitors = 0; + pScrPriv->monitors = NULL; +} + +void +RRMonitorClose(ScreenPtr screen) +{ + rrScrPrivPtr pScrPriv = rrGetScrPriv(screen); + int m; + + if (!pScrPriv) + return; + + for (m = 0; m < pScrPriv->numMonitors; m++) + RRMonitorFree(pScrPriv->monitors[m]); + xfree(pScrPriv->monitors); + pScrPriv->monitors = NULL; + pScrPriv->numMonitors = 0; +} + +static CARD32 +RRMonitorTimestamp(ScreenPtr screen) +{ + rrScrPrivPtr pScrPriv = rrGetScrPriv(screen); + + /* XXX should take client monitor changes into account */ + return pScrPriv->lastConfigTime.milliseconds; +} + +int +ProcRRGetMonitors(ClientPtr client) +{ + REQUEST(xRRGetMonitorsReq); + xRRGetMonitorsReply rep = { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + }; + WindowPtr window; + ScreenPtr screen; + int r; + RRMonitorPtr monitors; + int nmonitors; + int noutputs; + int m, n; + Bool get_active; + + REQUEST_SIZE_MATCH(xRRGetMonitorsReq); +#ifndef NXAGENT_SERVER + r = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess); +#else + window = SecurityLookupWindow(stuff->window, client, SecurityReadAccess); + r = window ? Success : BadWindow; +#endif + + if (r != Success) + return r; + screen = window->drawable.pScreen; + + get_active = stuff->get_active; + if (!RRMonitorMakeList(screen, get_active, &monitors, &nmonitors)) + return BadAlloc; + + rep.timestamp = RRMonitorTimestamp(screen); + + noutputs = 0; + for (m = 0; m < nmonitors; m++) { + rep.length += SIZEOF(xRRMonitorInfo) >> 2; + rep.length += monitors[m].numOutputs; + noutputs += monitors[m].numOutputs; + } + + rep.nmonitors = nmonitors; + rep.noutputs = noutputs; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swapl(&rep.nmonitors, n); + swapl(&rep.noutputs, n); + } + WriteToClient(client, sizeof(xRRGetMonitorsReply), (char *) &rep); + + client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; + + for (m = 0; m < nmonitors; m++) { + RRMonitorPtr monitor = &monitors[m]; + xRRMonitorInfo info = { + .name = monitor->name, + .primary = monitor->primary, + .automatic = monitor->automatic, + .noutput = monitor->numOutputs, + .x = monitor->geometry.box.x1, + .y = monitor->geometry.box.y1, + .width = monitor->geometry.box.x2 - monitor->geometry.box.x1, + .height = monitor->geometry.box.y2 - monitor->geometry.box.y1, + .widthInMillimeters = monitor->geometry.mmWidth, + .heightInMillimeters = monitor->geometry.mmHeight, + }; + if (client->swapped) { + swapl(&info.name, n); + swaps(&info.noutput, n); + swaps(&info.x, n); + swaps(&info.y, n); + swaps(&info.width, n); + swaps(&info.height, n); + swapl(&info.widthInMillimeters, n); + swapl(&info.heightInMillimeters, n); + } + + WriteToClient(client, sizeof(xRRMonitorInfo), (char *) &info); + WriteSwappedDataToClient(client, monitor->numOutputs * sizeof(RROutput), + monitor->outputs); + } + + RRMonitorFreeList(monitors, nmonitors); + + return Success; +} + +int +ProcRRSetMonitor(ClientPtr client) +{ + REQUEST(xRRSetMonitorReq); + WindowPtr window; + ScreenPtr screen; + RRMonitorPtr monitor; + int r; + + REQUEST_AT_LEAST_SIZE(xRRSetMonitorReq); + + if (stuff->monitor.noutput != stuff->length - (SIZEOF(xRRSetMonitorReq) >> 2)) + return BadLength; + +#ifndef NXAGENT_SERVER + r = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess); +#else + window = SecurityLookupWindow(stuff->window, client, SecurityReadAccess); + r = window ? Success : BadWindow; +#endif + + if (r != Success) + return r; + screen = window->drawable.pScreen; + + if (!ValidAtom(stuff->monitor.name)) + return BadAtom; + + /* Allocate the new monitor */ + monitor = RRMonitorAlloc(stuff->monitor.noutput); + if (!monitor) + return BadAlloc; + + /* Fill in the bits from the request */ + monitor->pScreen = screen; + monitor->name = stuff->monitor.name; + monitor->primary = stuff->monitor.primary; + monitor->automatic = FALSE; + memcpy(monitor->outputs, stuff + 1, stuff->monitor.noutput * sizeof(RROutput)); + monitor->geometry.box.x1 = stuff->monitor.x; + monitor->geometry.box.y1 = stuff->monitor.y; + monitor->geometry.box.x2 = stuff->monitor.x + stuff->monitor.width; + monitor->geometry.box.y2 = stuff->monitor.y + stuff->monitor.height; + monitor->geometry.mmWidth = stuff->monitor.widthInMillimeters; + monitor->geometry.mmHeight = stuff->monitor.heightInMillimeters; + + r = RRMonitorAdd(client, screen, monitor); + if (r == Success) + RRSendConfigNotify(screen); + else + RRMonitorFree(monitor); + return r; +} + +int +ProcRRDeleteMonitor(ClientPtr client) +{ + REQUEST(xRRDeleteMonitorReq); + WindowPtr window; + ScreenPtr screen; + int r; + + REQUEST_SIZE_MATCH(xRRDeleteMonitorReq); +#ifndef NXAGENT_SERVER + r = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess); +#else + window = SecurityLookupWindow(stuff->window, client, SecurityReadAccess); + r = window ? Success : BadWindow; +#endif + + if (r != Success) + return r; + screen = window->drawable.pScreen; + + if (!ValidAtom(stuff->name)) { + client->errorValue = stuff->name; + return BadAtom; + } + + r = RRMonitorDelete(client, screen, stuff->name); + if (r == Success) + RRSendConfigNotify(screen); + return r; +} diff --git a/nx-X11/programs/Xserver/randr/rroutput.c b/nx-X11/programs/Xserver/randr/rroutput.c index 523ee55d8..2628fabb0 100644 --- a/nx-X11/programs/Xserver/randr/rroutput.c +++ b/nx-X11/programs/Xserver/randr/rroutput.c @@ -1,5 +1,6 @@ /* * 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 @@ -21,7 +22,6 @@ */ #include "randrstr.h" -#include "registry.h" RESTYPE RROutputType; @@ -31,15 +31,30 @@ RESTYPE RROutputType; void RROutputChanged(RROutputPtr output, Bool configChanged) { + /* set changed bits on the master screen only */ ScreenPtr pScreen = output->pScreen; + rrScrPrivPtr mastersp; output->changed = TRUE; - if (pScreen) { - rrScrPriv(pScreen); - pScrPriv->changed = TRUE; - if (configChanged) - pScrPriv->configChanged = TRUE; + if (!pScreen) + return; + +#ifndef NXAGENT_SERVER + if (pScreen->isGPU) { + ScreenPtr master = pScreen->current_master; + if (!master) + return; + mastersp = rrGetScrPriv(master); } + else +#endif + { + mastersp = rrGetScrPriv(pScreen); + } + + RRSetChanged(pScreen); + if (configChanged) + mastersp->configChanged = TRUE; } /* @@ -60,8 +75,13 @@ RROutputCreate(ScreenPtr pScreen, pScrPriv = rrGetScrPriv(pScreen); if (pScrPriv->numOutputs) +#ifndef NXAGENT_SERVER + outputs = reallocarray(pScrPriv->outputs, + pScrPriv->numOutputs + 1, sizeof(RROutputPtr)); +#else /* !defined(NXAGENT_SERVER) */ outputs = xrealloc(pScrPriv->outputs, (pScrPriv->numOutputs + 1) * sizeof(RROutputPtr)); +#endif /* !defined(NXAGENT_SERVER) */ else outputs = xalloc(sizeof(RROutputPtr)); if (!outputs) @@ -101,6 +121,9 @@ RROutputCreate(ScreenPtr pScreen, return NULL; pScrPriv->outputs[pScrPriv->numOutputs++] = output; + + RRResourcesChanged(pScreen); + return output; } @@ -121,14 +144,17 @@ RROutputSetClones(RROutputPtr output, RROutputPtr * clones, int numClones) return TRUE; } if (numClones) { +#ifndef NXAGENT_SERVER + newClones = xallocarray(numClones, sizeof(RROutputPtr)); +#else /* !defined(NXAGENT_SERVER) */ newClones = xalloc(numClones * sizeof(RROutputPtr)); +#endif /* !defined(NXAGENT_SERVER) */ if (!newClones) return FALSE; } else newClones = NULL; - if (output->clones) - xfree(output->clones); + xfree(output->clones); memcpy(newClones, clones, numClones * sizeof(RROutputPtr)); output->clones = newClones; output->numClones = numClones; @@ -155,7 +181,11 @@ RROutputSetModes(RROutputPtr output, } if (numModes) { +#ifndef NXAGENT_SERVER + newModes = xallocarray(numModes, sizeof(RRModePtr)); +#else /* !defined(NXAGENT_SERVER) */ newModes = xalloc(numModes * sizeof(RRModePtr)); +#endif /* !defined(NXAGENT_SERVER) */ if (!newModes) return FALSE; } @@ -198,8 +228,13 @@ RROutputAddUserMode(RROutputPtr output, RRModePtr mode) return BadMatch; if (output->userModes) +#ifndef NXAGENT_SERVER + newModes = reallocarray(output->userModes, + output->numUserModes + 1, sizeof(RRModePtr)); +#else /* !defined(NXAGENT_SERVER) */ newModes = xrealloc(output->userModes, (output->numUserModes + 1) * sizeof(RRModePtr)); +#endif /* !defined(NXAGENT_SERVER) */ else newModes = xalloc(sizeof(RRModePtr)); if (!newModes) @@ -254,14 +289,17 @@ RROutputSetCrtcs(RROutputPtr output, RRCrtcPtr * crtcs, int numCrtcs) return TRUE; } if (numCrtcs) { +#ifndef NXAGENT_SERVER + newCrtcs = xallocarray(numCrtcs, sizeof(RRCrtcPtr)); +#else /* !defined(NXAGENT_SERVER) */ newCrtcs = xalloc(numCrtcs * sizeof(RRCrtcPtr)); +#endif /* !defined(NXAGENT_SERVER) */ if (!newCrtcs) return FALSE; } else newCrtcs = NULL; - if (output->crtcs) - xfree(output->crtcs); + xfree(output->crtcs); memcpy(newCrtcs, crtcs, numCrtcs * sizeof(RRCrtcPtr)); output->crtcs = newCrtcs; output->numCrtcs = numCrtcs; @@ -307,29 +345,25 @@ 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; + RRModePtr mode = crtc ? crtc->mode : NULL; + + xRROutputChangeNotifyEvent oe = { + .type = RRNotify + RREventBase, + .subCode = RRNotify_OutputChange, +#ifdef NXAGENT_SERVER + .sequenceNumber = client->sequence, +#endif + .timestamp = pScrPriv->lastSetTime.milliseconds, + .configTimestamp = pScrPriv->lastConfigTime.milliseconds, + .window = pWin->drawable.id, + .output = output->id, + .crtc = crtc ? crtc->id : None, + .mode = mode ? mode->mode.id : None, + .rotation = crtc ? crtc->rotation : RR_Rotate_0, + .connection = output->connection, + .subpixelOrder = output->subpixelOrder + }; WriteEventsToClient(client, 1, (xEvent *) &oe); } @@ -353,6 +387,9 @@ RROutputDestroyResource(void *value, XID pid) 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, @@ -361,6 +398,8 @@ RROutputDestroyResource(void *value, XID pid) break; } } + + RRResourcesChanged(pScreen); } if (output->modes) { for (m = 0; m < output->numModes; m++) @@ -370,13 +409,10 @@ RROutputDestroyResource(void *value, XID pid) for (m = 0; m < output->numUserModes; m++) RRModeDestroy(output->userModes[m]); - if (output->userModes) - xfree(output->userModes); + xfree(output->userModes); - if (output->crtcs) - xfree(output->crtcs); - if (output->clones) - xfree(output->clones); + xfree(output->crtcs); + xfree(output->clones); RRDeleteAllOutputProperties(output); xfree(output); return 1; @@ -388,13 +424,28 @@ RROutputDestroyResource(void *value, XID pid) Bool RROutputInit(void) { - RROutputType = CreateNewResourceType(RROutputDestroyResource); + RROutputType = CreateNewResourceType(RROutputDestroyResource +#ifndef NXAGENT_SERVER + , "OUTPUT" +#endif + ); if (!RROutputType) return FALSE; - RegisterResourceName(RROutputType, "OUTPUT"); + return TRUE; } +/* + * Initialize output type error value + */ +void +RROutputInitErrorValue(void) +{ +#ifndef NXAGENT_SERVER + SetResourceTypeErrorValue(RROutputType, RRErrorBase + BadRROutput); +#endif +} + #define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32) int @@ -411,41 +462,38 @@ ProcRRGetOutputInfo(ClientPtr client) RRMode *modes; RROutput *clones; char *name; - int i, n; + int i; + int n; REQUEST_SIZE_MATCH(xRRGetOutputInfoReq); - output = LookupOutput(client, stuff->output, DixReadAccess); - - if (!output) { - client->errorValue = stuff->output; - return RRErrorBase + BadRROutput; - } + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); pScreen = output->pScreen; pScrPriv = rrGetScrPriv(pScreen); - rep.type = X_Reply; - rep.status = RRSetConfigSuccess; - rep.sequenceNumber = client->sequence; - rep.length = OutputInfoExtra >> 2; - 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; - + rep = (xRRGetOutputInfoReply) { + .type = X_Reply, + .status = RRSetConfigSuccess, + .sequenceNumber = client->sequence, + .length = bytes_to_int32(OutputInfoExtra), + .timestamp = pScrPriv->lastSetTime.milliseconds, + .crtc = output->crtc ? output->crtc->id : None, + .mmWidth = output->mmWidth, + .mmHeight = output->mmHeight, + .connection = output->connection, + .subpixelOrder = output->subpixelOrder, + .nCrtcs = output->numCrtcs, + .nModes = output->numModes + output->numUserModes, + .nPreferred = output->numPreferred, + .nClones = output->numClones, + .nameLength = output->nameLength + }; extraLen = ((output->numCrtcs + - output->numModes + output->numUserModes + - output->numClones + ((rep.nameLength + 3) >> 2)) << 2); + output->numModes + output->numUserModes + + output->numClones + bytes_to_int32(rep.nameLength)) << 2); if (extraLen) { - rep.length += extraLen >> 2; + rep.length += bytes_to_int32(extraLen); extra = xalloc(extraLen); if (!extra) return BadAlloc; @@ -486,6 +534,7 @@ ProcRRGetOutputInfo(ClientPtr client) swapl(&rep.mmHeight, n); swaps(&rep.nCrtcs, n); swaps(&rep.nModes, n); + swaps(&rep.nPreferred, n); swaps(&rep.nClones, n); swaps(&rep.nameLength, n); } @@ -495,5 +544,130 @@ ProcRRGetOutputInfo(ClientPtr client) xfree(extra); } - return client->noClientException; + 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 ret; +#ifndef NXAGENT_SERVER + ScreenPtr slave; +#endif + + REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq); + +#ifndef NXAGENT_SERVER + ret = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); +#else + pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess); + ret = pWin ? Success : BadWindow; +#endif + + if (ret != Success) + return ret; + + if (stuff->output) { + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); + +#ifndef NXAGENT_SERVER + if (!output->pScreen->isGPU && output->pScreen != pWin->drawable.pScreen) { + client->errorValue = stuff->window; + return BadMatch; + } + if (output->pScreen->isGPU && + output->pScreen->current_master != pWin->drawable.pScreen) { + client->errorValue = stuff->window; + return BadMatch; + } +#endif + } + + pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); + if (pScrPriv) + { + RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output); + +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(slave, + &pWin->drawable.pScreen->output_slave_list, + output_head) { + rrScrPrivPtr pSlavePriv; + pSlavePriv = rrGetScrPriv(slave); + + RRSetPrimaryOutput(slave, pSlavePriv, output); + } +#endif + } + + return Success; +} + +int +ProcRRGetOutputPrimary(ClientPtr client) +{ + REQUEST(xRRGetOutputPrimaryReq); + WindowPtr pWin; + rrScrPrivPtr pScrPriv; + xRRGetOutputPrimaryReply rep; + RROutputPtr primary = NULL; + int rc; + int n; + + REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq); + +#ifndef NXAGENT_SERVER + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); +#else + pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess); + rc = pWin ? Success : BadWindow; +#endif + + if (rc != Success) + return rc; + + pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); + if (pScrPriv) + primary = pScrPriv->primaryOutput; + + rep = (xRRGetOutputPrimaryReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .output = primary ? primary->id : None + }; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.output, n); + } + + WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), (char *) &rep); + + return Success; } diff --git a/nx-X11/programs/Xserver/randr/rrpointer.c b/nx-X11/programs/Xserver/randr/rrpointer.c index 811310985..ace7d36a2 100644 --- a/nx-X11/programs/Xserver/randr/rrpointer.c +++ b/nx-X11/programs/Xserver/randr/rrpointer.c @@ -21,6 +21,7 @@ */ #include "randrstr.h" +#include "inputstr.h" /* * When the pointer moves, check to see if the specified position is outside @@ -51,7 +52,11 @@ RRCrtcContainsPosition(RRCrtcPtr crtc, int x, int y) * Find the CRTC nearest the specified position, ignoring 'skip' */ static void -RRPointerToNearestCrtc(ScreenPtr pScreen, int x, int y, RRCrtcPtr skip) +RRPointerToNearestCrtc( +#ifndef NXAGENT_SERVER + DeviceIntPtr pDev, +#endif /* !defined(NXAGENT_SERVER) */ + ScreenPtr pScreen, int x, int y, RRCrtcPtr skip) { rrScrPriv(pScreen); int c; @@ -75,25 +80,31 @@ RRPointerToNearestCrtc(ScreenPtr pScreen, int x, int y, RRCrtcPtr skip) if (x < crtc->x) dx = crtc->x - x; - else if (x > crtc->x + scan_width) - dx = x - (crtc->x + scan_width); + else if (x > crtc->x + scan_width - 1) + dx = crtc->x + (scan_width - 1) - x; else dx = 0; if (y < crtc->y) - dy = crtc->y - x; - else if (y > crtc->y + scan_height) - dy = y - (crtc->y + scan_height); + dy = crtc->y - y; + else if (y > crtc->y + scan_height - 1) + dy = crtc->y + (scan_height - 1) - y; else dy = 0; - dist = dx + dy; + dist = dx * dx + dy * dy; if (!nearest || dist < best) { nearest = crtc; best_dx = dx; best_dy = dy; + best = dist; } } if (best_dx || best_dy) - (*pScreen->SetCursorPosition) (pScreen, x + best_dx, y + best_dy, TRUE); + (*pScreen->SetCursorPosition) ( +#ifndef NXAGENT_SERVER + pDev, +#endif /* !defined(NXAGENT_SERVER) */ + pScreen, x + best_dx, y + best_dy, + TRUE); pScrPriv->pointerCrtc = nearest; } @@ -120,22 +131,52 @@ RRPointerMoved(ScreenPtr pScreen, int x, int y) } /* None contain pointer, find nearest */ - RRPointerToNearestCrtc(pScreen, x, y, pointerCrtc); + ErrorF("RRPointerMoved: Untested, may cause \"bogus pointer event\"\n"); + RRPointerToNearestCrtc( +#ifndef NXAGENT_SERVER + inputInfo.pointer, +#endif /* !defined(NXAGENT_SERVER) */ + pScreen, x, y, pointerCrtc); } /* - * When the screen is reconfigured, move the pointer to the nearest + * When the screen is reconfigured, move all pointers to the nearest * CRTC */ void RRPointerScreenConfigured(ScreenPtr pScreen) { - WindowPtr pRoot = GetCurrentRootWindow(); - ScreenPtr pCurrentScreen = pRoot ? pRoot->drawable.pScreen : NULL; + WindowPtr pRoot; + ScreenPtr pCurrentScreen; int x, y; - if (pScreen != pCurrentScreen) - return; - GetSpritePosition(&x, &y); - RRPointerToNearestCrtc(pScreen, x, y, NULL); +#ifndef NXAGENT_SERVER + DeviceIntPtr pDev; + + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { + if (IsPointerDevice(pDev)) { +#endif /* NXAGENT_SERVER */ + pRoot = GetCurrentRootWindow( +#ifndef NXAGENT_SERVER + pDev +#endif /* NXAGENT_SERVER */ + ); + pCurrentScreen = pRoot ? pRoot->drawable.pScreen : NULL; + + if (pScreen == pCurrentScreen) { + GetSpritePosition( +#ifndef NXAGENT_SERVER + pDev, +#endif /* NXAGENT_SERVER */ + &x, &y); + RRPointerToNearestCrtc( +#ifndef NXAGENT_SERVER + pDev, +#endif /* NXAGENT_SERVER */ + pScreen, x, y, NULL); +#ifndef NXAGENT_SERVER + } + } +#endif /* NXAGENT_SERVER */ + } } diff --git a/nx-X11/programs/Xserver/randr/rrproperty.c b/nx-X11/programs/Xserver/randr/rrproperty.c index 0bccb0c68..741d0310e 100644 --- a/nx-X11/programs/Xserver/randr/rrproperty.c +++ b/nx-X11/programs/Xserver/randr/rrproperty.c @@ -24,33 +24,76 @@ #include "propertyst.h" #include "swaprep.h" +static int +DeliverPropertyEvent(WindowPtr pWin, void *value) +{ + xRROutputPropertyNotifyEvent *event = value; + RREventPtr *pHead, pRREvent; + +#ifndef NXAGENT_SERVER + dixLookupResourceByType((void **) &pHead, pWin->drawable.id, + RREventType, serverClient, DixReadAccess); +#else /* !defined(NXAGENT_SERVER) */ + pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, RREventType); +#endif /* !defined(NXAGENT_SERVER) */ + if (!pHead) + return WT_WALKCHILDREN; + + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { + if (!(pRREvent->mask & RROutputPropertyNotifyMask)) + continue; + +#ifdef NXAGENT_SERVER + event->sequenceNumber = pRREvent->client->sequence; +#endif + event->window = pRREvent->window->drawable.id; + WriteEventsToClient(pRREvent->client, 1, (xEvent *) event); + } + + return WT_WALKCHILDREN; +} + static void -RRDeliverEvent(ScreenPtr pScreen, xEvent *event, CARD32 mask) +RRDeliverPropertyEvent(ScreenPtr pScreen, xEvent *event) { + if (!(dispatchException & (DE_RESET | DE_TERMINATE))) + WalkTree(pScreen, DeliverPropertyEvent, event); +} +static void +RRDestroyOutputProperty(RRPropertyPtr prop) +{ + xfree(prop->valid_values); + xfree(prop->current.data); + xfree(prop->pending.data); + xfree(prop); +} + +static void +RRDeleteProperty(RROutputRec * output, RRPropertyRec * prop) +{ + xRROutputPropertyNotifyEvent event = { + .type = RREventBase + RRNotify, + .subCode = RRNotify_OutputProperty, + .output = output->id, + .state = PropertyDelete, + .atom = prop->propertyName, + .timestamp = currentTime.milliseconds + }; + + RRDeliverPropertyEvent(output->pScreen, (xEvent *) &event); + + RRDestroyOutputProperty(prop); } void RRDeleteAllOutputProperties(RROutputPtr output) { RRPropertyPtr prop, next; - xRROutputPropertyNotifyEvent event; for (prop = output->properties; prop; prop = next) { next = prop->next; - event.type = RREventBase + RRNotify; - event.subCode = RRNotify_OutputProperty; - event.output = output->id; - event.state = PropertyDelete; - event.atom = prop->propertyName; - event.timestamp = currentTime.milliseconds; - RRDeliverEvent(output->pScreen, (xEvent *) &event, - RROutputPropertyNotifyMask); - if (prop->current.data) - xfree(prop->current.data); - if (prop->pending.data) - xfree(prop->pending.data); - xfree(prop); + RRDeleteProperty(output, prop); } } @@ -83,39 +126,17 @@ RRCreateOutputProperty(Atom property) return prop; } -static void -RRDestroyOutputProperty(RRPropertyPtr prop) -{ - if (prop->valid_values) - xfree(prop->valid_values); - if (prop->current.data) - xfree(prop->current.data); - if (prop->pending.data) - xfree(prop->pending.data); - xfree(prop); -} - void RRDeleteOutputProperty(RROutputPtr output, Atom property) { - RRPropertyPtr prop, *prev; - xRROutputPropertyNotifyEvent event; + RRPropertyRec *prop, **prev; for (prev = &output->properties; (prop = *prev); prev = &(prop->next)) - if (prop->propertyName == property) - break; - if (prop) { - *prev = prop->next; - event.type = RREventBase + RRNotify; - event.subCode = RRNotify_OutputProperty; - event.output = output->id; - event.state = PropertyDelete; - event.atom = prop->propertyName; - event.timestamp = currentTime.milliseconds; - RRDeliverEvent(output->pScreen, (xEvent *) &event, - RROutputPropertyNotifyMask); - RRDestroyOutputProperty(prop); - } + if (prop->propertyName == property) { + *prev = prop->next; + RRDeleteProperty(output, prop); + return; + } } int @@ -124,10 +145,8 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type, void *value, Bool sendevent, Bool pending) { RRPropertyPtr prop; - xRROutputPropertyNotifyEvent event; rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen); int size_in_bytes; - int total_size; unsigned long total_len; RRPropertyValuePtr prop_value; RRPropertyValueRec new_value; @@ -140,7 +159,7 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type, if (!prop) { /* just add to list */ prop = RRCreateOutputProperty(property); if (!prop) - return (BadAlloc); + return BadAlloc; add = TRUE; mode = PropModeReplace; } @@ -155,9 +174,9 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type, "PropModeReplace" since they will be written over. */ if ((format != prop_value->format) && (mode != PropModeReplace)) - return (BadMatch); + return BadMatch; if ((prop_value->type != type) && (mode != PropModeReplace)) - return (BadMatch); + return BadMatch; new_value = *prop_value; if (mode == PropModeReplace) total_len = len; @@ -167,9 +186,12 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type, if (mode == PropModeReplace || len > 0) { void *new_data = NULL, *old_data = NULL; - total_size = total_len * size_in_bytes; - new_value.data = (void *) xalloc(total_size); - if (!new_value.data && total_size) { +#ifndef NXAGENT_SERVER + new_value.data = xallocarray(total_len, size_in_bytes); +#else /* !defined(NXAGENT_SERVER) */ + new_value.data = xalloc(total_len * size_in_bytes); +#endif /* !defined(NXAGENT_SERVER) */ + if (!new_value.data && total_len && size_in_bytes) { if (add) RRDestroyOutputProperty(prop); return BadAlloc; @@ -203,12 +225,12 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type, if (pending && pScrPriv->rrOutputSetProperty && !pScrPriv->rrOutputSetProperty(output->pScreen, output, prop->propertyName, &new_value)) { - if (new_value.data) - xfree(new_value.data); - return (BadValue); + xfree(new_value.data); + if (add) + RRDestroyOutputProperty(prop); + return BadValue; } - if (prop_value->data) - xfree(prop_value->data); + xfree(prop_value->data); *prop_value = new_value; } @@ -225,16 +247,17 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type, output->pendingProperties = TRUE; if (sendevent) { - event.type = RREventBase + RRNotify; - event.subCode = RRNotify_OutputProperty; - event.output = output->id; - event.state = PropertyNewValue; - event.atom = prop->propertyName; - event.timestamp = currentTime.milliseconds; - RRDeliverEvent(output->pScreen, (xEvent *) &event, - RROutputPropertyNotifyMask); - } - return (Success); + xRROutputPropertyNotifyEvent event = { + .type = RREventBase + RRNotify, + .subCode = RRNotify_OutputProperty, + .output = output->id, + .state = PropertyNewValue, + .atom = prop->propertyName, + .timestamp = currentTime.milliseconds + }; + RRDeliverPropertyEvent(output->pScreen, (xEvent *) &event); + } + return Success; } Bool @@ -265,7 +288,7 @@ RRPostPendingProperties(RROutputPtr output) pending_value->format == current_value->format && pending_value->size == current_value->size && !memcmp(pending_value->data, current_value->data, - pending_value->size)) + pending_value->size * (pending_value->format / 8))) continue; if (RRChangeOutputProperty(output, property->propertyName, @@ -292,13 +315,21 @@ RRPropertyValuePtr RRGetOutputProperty(RROutputPtr output, Atom property, Bool pending) { RRPropertyPtr prop = RRQueryOutputProperty(output, property); + rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen); if (!prop) return NULL; if (pending && prop->is_pending) return &prop->pending; - else + else { +#if RANDR_13_INTERFACE + /* If we can, try to update the property value first */ + if (pScrPriv->rrOutputGetProperty) + pScrPriv->rrOutputGetProperty(output->pScreen, output, + prop->propertyName); +#endif return &prop->current; + } } int @@ -313,21 +344,31 @@ RRConfigureOutputProperty(RROutputPtr output, Atom property, if (!prop) { prop = RRCreateOutputProperty(property); if (!prop) - return (BadAlloc); + return BadAlloc; add = TRUE; } else if (prop->immutable && !immutable) - return (BadAccess); + return BadAccess; /* * ranges must have even number of values */ - if (range && (num_values & 1)) + if (range && (num_values & 1)) { + if (add) + RRDestroyOutputProperty(prop); return BadMatch; + } +#ifndef NXAGENT_SERVER + new_values = xallocarray(num_values, sizeof(INT32)); +#else /* !defined(NXAGENT_SERVER) */ new_values = xalloc(num_values * sizeof(INT32)); - if (!new_values && num_values) +#endif /* !defined(NXAGENT_SERVER) */ + if (!new_values && num_values) { + if (add) + RRDestroyOutputProperty(prop); return BadAlloc; + } if (num_values) memcpy(new_values, values, num_values * sizeof(INT32)); @@ -336,8 +377,7 @@ RRConfigureOutputProperty(RROutputPtr output, Atom property, * loses any pending values */ if (prop->is_pending && !pending) { - if (prop->pending.data) - xfree(prop->pending.data); + xfree(prop->pending.data); RRInitOutputPropertyValue(&prop->pending); } @@ -345,8 +385,7 @@ RRConfigureOutputProperty(RROutputPtr output, Atom property, prop->range = range; prop->immutable = immutable; prop->num_valid = num_values; - if (prop->valid_values) - xfree(prop->valid_values); + xfree(prop->valid_values); prop->valid_values = new_values; if (add) { @@ -361,47 +400,51 @@ int ProcRRListOutputProperties(ClientPtr client) { REQUEST(xRRListOutputPropertiesReq); - Atom *pAtoms = NULL, *temppAtoms; + Atom *pAtoms = NULL; xRRListOutputPropertiesReply rep; int numProps = 0; RROutputPtr output; RRPropertyPtr prop; + int n; REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq); - output = LookupOutput(client, stuff->output, DixReadAccess); - - if (!output) - return RRErrorBase + BadRROutput; + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); for (prop = output->properties; prop; prop = prop->next) numProps++; if (numProps) - if (!(pAtoms = (Atom *) xalloc(numProps * sizeof(Atom)))) - return (BadAlloc); +#ifndef NXAGENT_SERVER + if (!(pAtoms = xallocarray(numProps, sizeof(Atom)))) +#else /* !defined(NXAGENT_SERVER) */ + if (!(pAtoms = xalloc(numProps * sizeof(Atom)))) +#endif /* !defined(NXAGENT_SERVER) */ + return BadAlloc; - rep.type = X_Reply; - rep.length = (numProps * sizeof(Atom)) >> 2; - rep.sequenceNumber = client->sequence; - rep.nAtoms = numProps; + rep = (xRRListOutputPropertiesReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = bytes_to_int32(numProps * sizeof(Atom)), + .nAtoms = numProps + }; if (client->swapped) { - int n; - swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); swaps(&rep.nAtoms, n); } - temppAtoms = pAtoms; - for (prop = output->properties; prop; prop = prop->next) - *temppAtoms++ = prop->propertyName; - WriteToClient(client, sizeof(xRRListOutputPropertiesReply), (char *) &rep); + if (numProps) { + /* Copy property name atoms to reply buffer */ + Atom *temppAtoms = pAtoms; + for (prop = output->properties; prop; prop = prop->next) + *temppAtoms++ = prop->propertyName; + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); xfree(pAtoms); } - return (client->noClientException); + return Success; } int @@ -411,33 +454,36 @@ ProcRRQueryOutputProperty(ClientPtr client) xRRQueryOutputPropertyReply rep; RROutputPtr output; RRPropertyPtr prop; - char *extra; + char *extra = NULL; + int n; REQUEST_SIZE_MATCH(xRRQueryOutputPropertyReq); - output = LookupOutput(client, stuff->output, DixReadAccess); - - if (!output) - return RRErrorBase + BadRROutput; + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); prop = RRQueryOutputProperty(output, stuff->property); if (!prop) return BadName; if (prop->num_valid) { +#ifndef NXAGENT_SERVER + extra = xallocarray(prop->num_valid, sizeof(INT32)); +#else /* !defined(NXAGENT_SERVER) */ extra = xalloc(prop->num_valid * sizeof(INT32)); +#endif /* !defined(NXAGENT_SERVER) */ if (!extra) return BadAlloc; } - rep.type = X_Reply; - rep.length = prop->num_valid; - rep.sequenceNumber = client->sequence; - rep.pending = prop->is_pending; - rep.range = prop->range; - rep.immutable = prop->immutable; - if (client->swapped) { - int n; + rep = (xRRQueryOutputPropertyReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = prop->num_valid, + .pending = prop->is_pending, + .range = prop->range, + .immutable = prop->immutable + }; + if (client->swapped) { swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); } @@ -449,7 +495,7 @@ ProcRRQueryOutputProperty(ClientPtr client) extra); xfree(extra); } - return (client->noClientException); + return Success; } int @@ -461,15 +507,13 @@ ProcRRConfigureOutputProperty(ClientPtr client) REQUEST_AT_LEAST_SIZE(xRRConfigureOutputPropertyReq); - output = LookupOutput(client, stuff->output, DixReadAccess); - - if (!output) - return RRErrorBase + BadRROutput; + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); - num_valid = stuff->length - (sizeof(xRRConfigureOutputPropertyReq) >> 2); - return RRConfigureOutputProperty(output, stuff->property, - stuff->pending, stuff->range, - FALSE, num_valid, (INT32 *) (stuff + 1)); + num_valid = + stuff->length - bytes_to_int32(sizeof(xRRConfigureOutputPropertyReq)); + return RRConfigureOutputProperty(output, stuff->property, stuff->pending, + stuff->range, FALSE, num_valid, + (INT32 *) (stuff + 1)); } int @@ -497,23 +541,21 @@ ProcRRChangeOutputProperty(ClientPtr client) return BadValue; } len = stuff->nUnits; - if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2)) + if (len > bytes_to_int32((0xffffffff - sizeof(xChangePropertyReq)))) return BadLength; sizeInBytes = format >> 3; totalSize = len * sizeInBytes; REQUEST_FIXED_SIZE(xRRChangeOutputPropertyReq, totalSize); - output = LookupOutput(client, stuff->output, DixWriteAccess); - if (!output) - return RRErrorBase + BadRROutput; + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); if (!ValidAtom(stuff->property)) { client->errorValue = stuff->property; - return (BadAtom); + return BadAtom; } if (!ValidAtom(stuff->type)) { client->errorValue = stuff->type; - return (BadAtom); + return BadAtom; } err = RRChangeOutputProperty(output, stuff->property, @@ -523,7 +565,7 @@ ProcRRChangeOutputProperty(ClientPtr client) if (err != Success) return err; else - return client->noClientException; + return Success; } int @@ -531,20 +573,30 @@ ProcRRDeleteOutputProperty(ClientPtr client) { REQUEST(xRRDeleteOutputPropertyReq); RROutputPtr output; + RRPropertyPtr prop; REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq); UpdateCurrentTime(); - output = LookupOutput(client, stuff->output, DixWriteAccess); - if (!output) - return RRErrorBase + BadRROutput; + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); if (!ValidAtom(stuff->property)) { client->errorValue = stuff->property; - return (BadAtom); + return BadAtom; + } + + prop = RRQueryOutputProperty(output, stuff->property); + if (!prop) { + client->errorValue = stuff->property; + return BadName; + } + + if (prop->immutable) { + client->errorValue = stuff->property; + return BadAccess; } RRDeleteOutputProperty(output, stuff->property); - return client->noClientException; + return Success; } int @@ -556,35 +608,36 @@ ProcRRGetOutputProperty(ClientPtr client) unsigned long n, len, ind; RROutputPtr output; xRRGetOutputPropertyReply reply; - char *extra; + char *extra = NULL; + int m; REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq); if (stuff->delete) UpdateCurrentTime(); - output = LookupOutput(client, stuff->output, - stuff->delete ? DixWriteAccess : DixReadAccess); - if (!output) - return RRErrorBase + BadRROutput; + VERIFY_RR_OUTPUT(stuff->output, output, + stuff->delete ? DixWriteAccess : DixReadAccess); if (!ValidAtom(stuff->property)) { client->errorValue = stuff->property; - return (BadAtom); + return BadAtom; } if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) { client->errorValue = stuff->delete; - return (BadValue); + return BadValue; } if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) { client->errorValue = stuff->type; - return (BadAtom); + return BadAtom; } for (prev = &output->properties; (prop = *prev); prev = &prop->next) if (prop->propertyName == stuff->property) break; - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; + reply = (xRRGetOutputPropertyReply) { + .type = X_Reply, + .sequenceNumber = client->sequence + }; if (!prop) { reply.nItems = 0; reply.length = 0; @@ -592,25 +645,23 @@ ProcRRGetOutputProperty(ClientPtr client) reply.propertyType = None; reply.format = 0; if (client->swapped) { - int n; - - swaps(&reply.sequenceNumber, n); - swapl(&reply.length, n); - swapl(&reply.propertyType, n); - swapl(&reply.bytesAfter, n); - swapl(&reply.nItems, n); + swaps(&reply.sequenceNumber, m); + swapl(&reply.length, m); + swapl(&reply.propertyType, m); + swapl(&reply.bytesAfter, m); + swapl(&reply.nItems, m); } - WriteToClient(client, sizeof(xRRGetOutputPropertyReply), &reply); - return (client->noClientException); + WriteToClient(client, sizeof(xRRGetOutputPropertyReply), + (char *) &reply); + return Success; } if (prop->immutable && stuff->delete) return BadAccess; - if (stuff->pending && prop->is_pending) - prop_value = &prop->pending; - else - prop_value = &prop->current; + prop_value = RRGetOutputProperty(output, stuff->property, stuff->pending); + if (!prop_value) + return BadAtom; /* If the request type and actual type don't match. Return the property information, but not the data. */ @@ -623,16 +674,15 @@ ProcRRGetOutputProperty(ClientPtr client) reply.nItems = 0; reply.propertyType = prop_value->type; if (client->swapped) { - int n; - swaps(&reply.sequenceNumber, n); swapl(&reply.length, n); swapl(&reply.propertyType, n); swapl(&reply.bytesAfter, n); swapl(&reply.nItems, n); } - WriteToClient(client, sizeof(xRRGetOutputPropertyReply), &reply); - return (client->noClientException); + WriteToClient(client, sizeof(xRRGetOutputPropertyReply), + (char *) &reply); + return Success; } /* @@ -658,7 +708,7 @@ ProcRRGetOutputProperty(ClientPtr client) } reply.bytesAfter = n - (ind + len); reply.format = prop_value->format; - reply.length = (len + 3) >> 2; + reply.length = bytes_to_int32(len); if (prop_value->format) reply.nItems = len / (prop_value->format / 8); else @@ -666,28 +716,25 @@ ProcRRGetOutputProperty(ClientPtr client) reply.propertyType = prop_value->type; if (stuff->delete && (reply.bytesAfter == 0)) { - xRROutputPropertyNotifyEvent event; - - event.type = RREventBase + RRNotify; - event.subCode = RRNotify_OutputProperty; - event.output = output->id; - event.state = PropertyDelete; - event.atom = prop->propertyName; - event.timestamp = currentTime.milliseconds; - RRDeliverEvent(output->pScreen, (xEvent *) &event, - RROutputPropertyNotifyMask); + xRROutputPropertyNotifyEvent event = { + .type = RREventBase + RRNotify, + .subCode = RRNotify_OutputProperty, + .output = output->id, + .state = PropertyDelete, + .atom = prop->propertyName, + .timestamp = currentTime.milliseconds + }; + RRDeliverPropertyEvent(output->pScreen, (xEvent *) &event); } if (client->swapped) { - int n; - swaps(&reply.sequenceNumber, n); swapl(&reply.length, n); swapl(&reply.propertyType, n); swapl(&reply.bytesAfter, n); swapl(&reply.nItems, n); } - WriteToClient(client, sizeof(xGenericReply), &reply); + WriteToClient(client, sizeof(xGenericReply), (char *) &reply); if (len) { memcpy(extra, (char *) prop_value->data + ind, len); switch (reply.format) { @@ -709,5 +756,5 @@ ProcRRGetOutputProperty(ClientPtr client) *prev = prop->next; RRDestroyOutputProperty(prop); } - return (client->noClientException); + return Success; } diff --git a/nx-X11/programs/Xserver/randr/rrprovider.c b/nx-X11/programs/Xserver/randr/rrprovider.c new file mode 100644 index 000000000..b2251b682 --- /dev/null +++ b/nx-X11/programs/Xserver/randr/rrprovider.c @@ -0,0 +1,484 @@ +/* + * Copyright © 2012 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. + * + * Authors: Dave Airlie + */ + +#include "randrstr.h" +#include "swaprep.h" + +RESTYPE RRProviderType; + +/* + * Initialize provider type error value + */ +void +RRProviderInitErrorValue(void) +{ +#ifndef NXAGENT_SERVER + SetResourceTypeErrorValue(RRProviderType, RRErrorBase + BadRRProvider); +#endif +} + +#define ADD_PROVIDER(_pScreen) do { \ + pScrPriv = rrGetScrPriv((_pScreen)); \ + if (pScrPriv->provider) { \ + providers[count_providers] = pScrPriv->provider->id; \ + if (client->swapped) \ + swapl(&providers[count_providers], n); \ + count_providers++; \ + } \ + } while(0) + +int +ProcRRGetProviders(ClientPtr client) +{ + REQUEST(xRRGetProvidersReq); + xRRGetProvidersReply rep; + WindowPtr pWin; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + int rc; + CARD8 *extra; + unsigned int extraLen; + RRProvider *providers; + int total_providers = 0, count_providers = 0; +#ifndef NXAGENT_SERVER + ScreenPtr iter; +#endif + int n; + + REQUEST_SIZE_MATCH(xRRGetProvidersReq); +#ifndef NXAGENT_SERVER + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); +#else + pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess); + rc = pWin ? Success : BadWindow; +#endif + + if (rc != Success) + return rc; + + pScreen = pWin->drawable.pScreen; + + pScrPriv = rrGetScrPriv(pScreen); + + if (pScrPriv->provider) + total_providers++; +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) { + pScrPriv = rrGetScrPriv(iter); + total_providers += pScrPriv->provider ? 1 : 0; + } + xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) { + pScrPriv = rrGetScrPriv(iter); + total_providers += pScrPriv->provider ? 1 : 0; + } + xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) { + pScrPriv = rrGetScrPriv(iter); + total_providers += pScrPriv->provider ? 1 : 0; + } +#endif + + pScrPriv = rrGetScrPriv(pScreen); + + if (!pScrPriv) + { + rep = (xRRGetProvidersReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .timestamp = currentTime.milliseconds, + .nProviders = 0 + }; + extra = NULL; + extraLen = 0; + } else { + rep = (xRRGetProvidersReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .timestamp = pScrPriv->lastSetTime.milliseconds, + .nProviders = total_providers, + .length = total_providers + }; + extraLen = rep.length << 2; + if (extraLen) { + extra = xalloc(extraLen); + if (!extra) + return BadAlloc; + } else + extra = NULL; + + providers = (RRProvider *) extra; + ADD_PROVIDER(pScreen); +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) { + ADD_PROVIDER(iter); + } + xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) { + ADD_PROVIDER(iter); + } + xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) { + ADD_PROVIDER(iter); + } +#endif + } + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swaps(&rep.nProviders, n); + } + WriteToClient(client, sizeof(xRRGetProvidersReply), (char *) &rep); + if (extraLen) + { + WriteToClient(client, extraLen, (char *) extra); + xfree(extra); + } + return Success; +} + +int +ProcRRGetProviderInfo(ClientPtr client) +{ + REQUEST(xRRGetProviderInfoReq); + xRRGetProviderInfoReply rep; + rrScrPrivPtr pScrPriv; +#ifndef NXAGENT_SERVER + rrScrPrivPtr pScrProvPriv; +#endif + RRProviderPtr provider; + ScreenPtr pScreen; + CARD8 *extra; + unsigned int extraLen = 0; + RRCrtc *crtcs; + RROutput *outputs; + int i; + char *name; +#ifndef NXAGENT_SERVER + ScreenPtr provscreen; +#endif + RRProvider *providers; + uint32_t *prov_cap; + int n; + + REQUEST_SIZE_MATCH(xRRGetProviderInfoReq); + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + pScreen = provider->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + rep = (xRRGetProviderInfoReply) { + .type = X_Reply, + .status = RRSetConfigSuccess, + .sequenceNumber = client->sequence, + .length = 0, + .capabilities = provider->capabilities, + .nameLength = provider->nameLength, + .timestamp = pScrPriv->lastSetTime.milliseconds, + .nCrtcs = pScrPriv->numCrtcs, + .nOutputs = pScrPriv->numOutputs, + .nAssociatedProviders = 0 + }; + + /* count associated providers */ + if (provider->offload_sink) + rep.nAssociatedProviders++; + if (provider->output_source) + rep.nAssociatedProviders++; +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(provscreen, &pScreen->output_slave_list, output_head) + rep.nAssociatedProviders++; + xorg_list_for_each_entry(provscreen, &pScreen->offload_slave_list, offload_head) + rep.nAssociatedProviders++; +#endif + + rep.length = (pScrPriv->numCrtcs + pScrPriv->numOutputs + + (rep.nAssociatedProviders * 2) + bytes_to_int32(rep.nameLength)); + + extraLen = rep.length << 2; + if (extraLen) { + extra = xalloc(extraLen); + if (!extra) + return BadAlloc; + } + else + extra = NULL; + + crtcs = (RRCrtc *) extra; + outputs = (RROutput *) (crtcs + rep.nCrtcs); + providers = (RRProvider *) (outputs + rep.nOutputs); + prov_cap = (unsigned int *) (providers + rep.nAssociatedProviders); + name = (char *) (prov_cap + rep.nAssociatedProviders); + + for (i = 0; i < pScrPriv->numCrtcs; i++) { + crtcs[i] = pScrPriv->crtcs[i]->id; + if (client->swapped) + swapl(&crtcs[i], n); + } + + for (i = 0; i < pScrPriv->numOutputs; i++) { + outputs[i] = pScrPriv->outputs[i]->id; + if (client->swapped) + swapl(&outputs[i], n); + } + + i = 0; + if (provider->offload_sink) { + providers[i] = provider->offload_sink->id; + if (client->swapped) + swapl(&providers[i], n); + prov_cap[i] = RR_Capability_SinkOffload; + if (client->swapped) + swapl(&prov_cap[i], n); + i++; + } + if (provider->output_source) { + providers[i] = provider->output_source->id; + if (client->swapped) + swapl(&providers[i], n); + prov_cap[i] = RR_Capability_SourceOutput; + swapl(&prov_cap[i], n); + i++; + } +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(provscreen, &pScreen->output_slave_list, output_head) { + pScrProvPriv = rrGetScrPriv(provscreen); + providers[i] = pScrProvPriv->provider->id; + if (client->swapped) + swapl(&providers[i]); + prov_cap[i] = RR_Capability_SinkOutput; + if (client->swapped) + swapl(&prov_cap[i]); + i++; + } + xorg_list_for_each_entry(provscreen, &pScreen->offload_slave_list, offload_head) { + pScrProvPriv = rrGetScrPriv(provscreen); + providers[i] = pScrProvPriv->provider->id; + if (client->swapped) + swapl(&providers[i]); + prov_cap[i] = RR_Capability_SourceOffload; + if (client->swapped) + swapl(&prov_cap[i]); + i++; + } +#endif + memcpy(name, provider->name, rep.nameLength); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.capabilities, n); + swaps(&rep.nCrtcs, n); + swaps(&rep.nOutputs, n); + swaps(&rep.nameLength, n); + } + WriteToClient(client, sizeof(xRRGetProviderInfoReply), (char *) &rep); + if (extraLen) + { + WriteToClient(client, extraLen, (char *) extra); + xfree(extra); + } + return Success; +} + +int +ProcRRSetProviderOutputSource(ClientPtr client) +{ + REQUEST(xRRSetProviderOutputSourceReq); + rrScrPrivPtr pScrPriv; + RRProviderPtr provider, source_provider = NULL; + ScreenPtr pScreen; + + REQUEST_SIZE_MATCH(xRRSetProviderOutputSourceReq); + + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + if (!(provider->capabilities & RR_Capability_SinkOutput)) + return BadValue; + + if (stuff->source_provider) { + VERIFY_RR_PROVIDER(stuff->source_provider, source_provider, DixReadAccess); + + if (!(source_provider->capabilities & RR_Capability_SourceOutput)) + return BadValue; + } + + pScreen = provider->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + pScrPriv->rrProviderSetOutputSource(pScreen, provider, source_provider); + + provider->changed = TRUE; + RRSetChanged(pScreen); + + RRTellChanged(pScreen); + + return Success; +} + +int +ProcRRSetProviderOffloadSink(ClientPtr client) +{ + REQUEST(xRRSetProviderOffloadSinkReq); + rrScrPrivPtr pScrPriv; + RRProviderPtr provider, sink_provider = NULL; + ScreenPtr pScreen; + + REQUEST_SIZE_MATCH(xRRSetProviderOffloadSinkReq); + + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + if (!(provider->capabilities & RR_Capability_SourceOffload)) + return BadValue; +#ifndef NXAGENT_SERVER + if (!provider->pScreen->isGPU) + return BadValue; +#endif /* !defined(NXAGENT_SERVER) */ + + if (stuff->sink_provider) { + VERIFY_RR_PROVIDER(stuff->sink_provider, sink_provider, DixReadAccess); + if (!(sink_provider->capabilities & RR_Capability_SinkOffload)) + return BadValue; + } + pScreen = provider->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + pScrPriv->rrProviderSetOffloadSink(pScreen, provider, sink_provider); + + provider->changed = TRUE; + RRSetChanged(pScreen); + + RRTellChanged(pScreen); + + return Success; +} + +RRProviderPtr +RRProviderCreate(ScreenPtr pScreen, const char *name, + int nameLength) +{ + RRProviderPtr provider; + rrScrPrivPtr pScrPriv; + + pScrPriv = rrGetScrPriv(pScreen); + + provider = xcalloc(1, sizeof(RRProviderRec) + nameLength + 1); + if (!provider) + return NULL; + + provider->id = FakeClientID(0); + provider->pScreen = pScreen; + provider->name = (char *) (provider + 1); + provider->nameLength = nameLength; + memcpy(provider->name, name, nameLength); + provider->name[nameLength] = '\0'; + provider->changed = FALSE; + + if (!AddResource(provider->id, RRProviderType, (void *) provider)) + return NULL; + pScrPriv->provider = provider; + return provider; +} + +/* + * Destroy a provider at shutdown + */ +void +RRProviderDestroy(RRProviderPtr provider) +{ + FreeResource(provider->id, 0); +} + +void +RRProviderSetCapabilities(RRProviderPtr provider, uint32_t capabilities) +{ + provider->capabilities = capabilities; +} + +static int +RRProviderDestroyResource(void *value, XID pid) +{ + RRProviderPtr provider = (RRProviderPtr) value; + ScreenPtr pScreen = provider->pScreen; + + if (pScreen) + { + rrScrPriv(pScreen); + + if (pScrPriv->rrProviderDestroy) + (*pScrPriv->rrProviderDestroy) (pScreen, provider); + pScrPriv->provider = NULL; + } + xfree(provider); + return 1; +} + +Bool +RRProviderInit(void) +{ + RRProviderType = CreateNewResourceType(RRProviderDestroyResource +#ifndef NXAGENT_SERVER + , "Provider" +#endif /* !defined(NXAGENT_SERVER) */ + ); + if (!RRProviderType) + return FALSE; + + return TRUE; +} + +extern _X_EXPORT Bool +RRProviderLookup(XID id, RRProviderPtr * provider_p) +{ +#ifndef NXAGENT_SERVER + int rc = dixLookupResourceByType((void **) provider_p, id, + RRProviderType, NullClient, DixReadAccess); + if (rc == Success) + return TRUE; +#else /* !defined(NXAGENT_SERVER) */ + provider_p = (RRProviderPtr *) LookupIDByType(id, RREventType); + if (provider_p) + return TRUE; +#endif /* !defined(NXAGENT_SERVER) */ + + return FALSE; +} + +void +RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + rrScrPriv(pScreen); + + xRRProviderChangeNotifyEvent pe = { + .type = RRNotify + RREventBase, + .subCode = RRNotify_ProviderChange, +#ifdef NXAGENT_SERVER + .sequenceNumber = client->sequence, +#endif + .timestamp = pScrPriv->lastSetTime.milliseconds, + .window = pWin->drawable.id, + .provider = provider->id + }; + + WriteEventsToClient(client, 1, (xEvent *) &pe); +} diff --git a/nx-X11/programs/Xserver/randr/rrproviderproperty.c b/nx-X11/programs/Xserver/randr/rrproviderproperty.c new file mode 100644 index 000000000..a68a94ff2 --- /dev/null +++ b/nx-X11/programs/Xserver/randr/rrproviderproperty.c @@ -0,0 +1,752 @@ +/* + * 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 "propertyst.h" +#include "swaprep.h" + +static int +DeliverPropertyEvent(WindowPtr pWin, void *value) +{ + xRRProviderPropertyNotifyEvent *event = value; + RREventPtr *pHead, pRREvent; + +#ifndef NXAGENT_SERVER + dixLookupResourceByType((void **) &pHead, pWin->drawable.id, + RREventType, serverClient, DixReadAccess); +#else /* !defined(NXAGENT_SERVER) */ + pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, RREventType); +#endif /* !defined(NXAGENT_SERVER) */ + if (!pHead) + return WT_WALKCHILDREN; + + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { + if (!(pRREvent->mask & RRProviderPropertyNotifyMask)) + continue; + + event->window = pRREvent->window->drawable.id; + WriteEventsToClient(pRREvent->client, 1, (xEvent *) event); + } + + return WT_WALKCHILDREN; +} + +static void +RRDeliverPropertyEvent(ScreenPtr pScreen, xEvent *event) +{ + if (!(dispatchException & (DE_RESET | DE_TERMINATE))) + WalkTree(pScreen, DeliverPropertyEvent, event); +} + +static void +RRDestroyProviderProperty(RRPropertyPtr prop) +{ + xfree(prop->valid_values); + xfree(prop->current.data); + xfree(prop->pending.data); + xfree(prop); +} + +static void +RRDeleteProperty(RRProviderRec * provider, RRPropertyRec * prop) +{ + xRRProviderPropertyNotifyEvent event = { + .type = RREventBase + RRNotify, + .subCode = RRNotify_ProviderProperty, + .provider = provider->id, + .state = PropertyDelete, + .atom = prop->propertyName, + .timestamp = currentTime.milliseconds + }; + + RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event); + + RRDestroyProviderProperty(prop); +} + +void +RRDeleteAllProviderProperties(RRProviderPtr provider) +{ + RRPropertyPtr prop, next; + + for (prop = provider->properties; prop; prop = next) { + next = prop->next; + RRDeleteProperty(provider, prop); + } +} + +static void +RRInitProviderPropertyValue(RRPropertyValuePtr property_value) +{ + property_value->type = None; + property_value->format = 0; + property_value->size = 0; + property_value->data = NULL; +} + +static RRPropertyPtr +RRCreateProviderProperty(Atom property) +{ + RRPropertyPtr prop; + + prop = (RRPropertyPtr) xalloc(sizeof(RRPropertyRec)); + if (!prop) + return NULL; + prop->next = NULL; + prop->propertyName = property; + prop->is_pending = FALSE; + prop->range = FALSE; + prop->immutable = FALSE; + prop->num_valid = 0; + prop->valid_values = NULL; + RRInitProviderPropertyValue(&prop->current); + RRInitProviderPropertyValue(&prop->pending); + return prop; +} + +void +RRDeleteProviderProperty(RRProviderPtr provider, Atom property) +{ + RRPropertyRec *prop, **prev; + + for (prev = &provider->properties; (prop = *prev); prev = &(prop->next)) + if (prop->propertyName == property) { + *prev = prop->next; + RRDeleteProperty(provider, prop); + return; + } +} + +int +RRChangeProviderProperty(RRProviderPtr provider, Atom property, Atom type, + int format, int mode, unsigned long len, + void *value, Bool sendevent, Bool pending) +{ + RRPropertyPtr prop; + rrScrPrivPtr pScrPriv = rrGetScrPriv(provider->pScreen); + int size_in_bytes; + int total_size; + unsigned long total_len; + RRPropertyValuePtr prop_value; + RRPropertyValueRec new_value; + Bool add = FALSE; + + size_in_bytes = format >> 3; + + /* first see if property already exists */ + prop = RRQueryProviderProperty(provider, property); + if (!prop) { /* just add to list */ + prop = RRCreateProviderProperty(property); + if (!prop) + return BadAlloc; + add = TRUE; + mode = PropModeReplace; + } + if (pending && prop->is_pending) + prop_value = &prop->pending; + else + prop_value = &prop->current; + + /* To append or prepend to a property the request format and type + must match those of the already defined property. The + existing format and type are irrelevant when using the mode + "PropModeReplace" since they will be written over. */ + + if ((format != prop_value->format) && (mode != PropModeReplace)) + return BadMatch; + if ((prop_value->type != type) && (mode != PropModeReplace)) + return BadMatch; + new_value = *prop_value; + if (mode == PropModeReplace) + total_len = len; + else + total_len = prop_value->size + len; + + if (mode == PropModeReplace || len > 0) { + void *new_data = NULL, *old_data = NULL; + + total_size = total_len * size_in_bytes; + new_value.data = (void *) xalloc(total_size); + if (!new_value.data && total_size) { + if (add) + RRDestroyProviderProperty(prop); + return BadAlloc; + } + new_value.size = len; + new_value.type = type; + new_value.format = format; + + switch (mode) { + case PropModeReplace: + new_data = new_value.data; + old_data = NULL; + break; + case PropModeAppend: + new_data = (void *) (((char *) new_value.data) + + (prop_value->size * size_in_bytes)); + old_data = new_value.data; + break; + case PropModePrepend: + new_data = new_value.data; + old_data = (void *) (((char *) new_value.data) + + (prop_value->size * size_in_bytes)); + break; + } + if (new_data) + memcpy((char *) new_data, (char *) value, len * size_in_bytes); + if (old_data) + memcpy((char *) old_data, (char *) prop_value->data, + prop_value->size * size_in_bytes); + + if (pending && pScrPriv->rrProviderSetProperty && + !pScrPriv->rrProviderSetProperty(provider->pScreen, provider, + prop->propertyName, &new_value)) { + if (add) + RRDestroyProviderProperty(prop); + xfree(new_value.data); + return BadValue; + } + xfree(prop_value->data); + *prop_value = new_value; + } + + else if (len == 0) { + /* do nothing */ + } + + if (add) { + prop->next = provider->properties; + provider->properties = prop; + } + + if (pending && prop->is_pending) + provider->pendingProperties = TRUE; + + if (sendevent) { + xRRProviderPropertyNotifyEvent event = { + .type = RREventBase + RRNotify, + .subCode = RRNotify_ProviderProperty, + .provider = provider->id, + .state = PropertyNewValue, + .atom = prop->propertyName, + .timestamp = currentTime.milliseconds + }; + RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event); + } + return Success; +} + +Bool +RRPostProviderPendingProperties(RRProviderPtr provider) +{ + RRPropertyValuePtr pending_value; + RRPropertyValuePtr current_value; + RRPropertyPtr property; + Bool ret = TRUE; + + if (!provider->pendingProperties) + return TRUE; + + provider->pendingProperties = FALSE; + for (property = provider->properties; property; property = property->next) { + /* Skip non-pending properties */ + if (!property->is_pending) + continue; + + pending_value = &property->pending; + current_value = &property->current; + + /* + * If the pending and current values are equal, don't mark it + * as changed (which would deliver an event) + */ + if (pending_value->type == current_value->type && + pending_value->format == current_value->format && + pending_value->size == current_value->size && + !memcmp(pending_value->data, current_value->data, + pending_value->size * (pending_value->format / 8))) + continue; + + if (RRChangeProviderProperty(provider, property->propertyName, + pending_value->type, pending_value->format, + PropModeReplace, pending_value->size, + pending_value->data, TRUE, FALSE) != Success) + ret = FALSE; + } + return ret; +} + +RRPropertyPtr +RRQueryProviderProperty(RRProviderPtr provider, Atom property) +{ + RRPropertyPtr prop; + + for (prop = provider->properties; prop; prop = prop->next) + if (prop->propertyName == property) + return prop; + return NULL; +} + +RRPropertyValuePtr +RRGetProviderProperty(RRProviderPtr provider, Atom property, Bool pending) +{ + RRPropertyPtr prop = RRQueryProviderProperty(provider, property); + rrScrPrivPtr pScrPriv = rrGetScrPriv(provider->pScreen); + + if (!prop) + return NULL; + if (pending && prop->is_pending) + return &prop->pending; + else { +#if RANDR_13_INTERFACE + /* If we can, try to update the property value first */ + if (pScrPriv->rrProviderGetProperty) + pScrPriv->rrProviderGetProperty(provider->pScreen, provider, + prop->propertyName); +#endif + return &prop->current; + } +} + +int +RRConfigureProviderProperty(RRProviderPtr provider, Atom property, + Bool pending, Bool range, Bool immutable, + int num_values, INT32 *values) +{ + RRPropertyPtr prop = RRQueryProviderProperty(provider, property); + Bool add = FALSE; + INT32 *new_values; + + if (!prop) { + prop = RRCreateProviderProperty(property); + if (!prop) + return BadAlloc; + add = TRUE; + } + else if (prop->immutable && !immutable) + return BadAccess; + + /* + * ranges must have even number of values + */ + if (range && (num_values & 1)) { + if (add) + RRDestroyProviderProperty(prop); + return BadMatch; + } + +#ifndef NXAGENT_SERVER + new_values = xallocarray(num_values, sizeof(INT32)); +#else /* !defined(NXAGENT_SERVER) */ + new_values = xalloc(num_values * sizeof(INT32)); +#endif /* !defined(NXAGENT_SERVER) */ + + if (!new_values && num_values) { + if (add) + RRDestroyProviderProperty(prop); + return BadAlloc; + } + if (num_values) + memcpy(new_values, values, num_values * sizeof(INT32)); + + /* + * Property moving from pending to non-pending + * loses any pending values + */ + if (prop->is_pending && !pending) { + xfree(prop->pending.data); + RRInitProviderPropertyValue(&prop->pending); + } + + prop->is_pending = pending; + prop->range = range; + prop->immutable = immutable; + prop->num_valid = num_values; + xfree(prop->valid_values); + prop->valid_values = new_values; + + if (add) { + prop->next = provider->properties; + provider->properties = prop; + } + + return Success; +} + +int +ProcRRListProviderProperties(ClientPtr client) +{ + REQUEST(xRRListProviderPropertiesReq); + Atom *pAtoms = NULL, *temppAtoms; + xRRListProviderPropertiesReply rep; + int numProps = 0; + RRProviderPtr provider; + RRPropertyPtr prop; + int n; + + REQUEST_SIZE_MATCH(xRRListProviderPropertiesReq); + + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + for (prop = provider->properties; prop; prop = prop->next) + numProps++; + if (numProps) +#ifndef NXAGENT_SERVER + if (!(pAtoms = xallocarray(numProps, sizeof(Atom)))) +#else /* !defined(NXAGENT_SERVER) */ + if (!(pAtoms = xalloc(numProps * sizeof(Atom)))) +#endif /* !defined(NXAGENT_SERVER) */ + return BadAlloc; + + rep = (xRRListProviderPropertiesReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = bytes_to_int32(numProps * sizeof(Atom)), + .nAtoms = numProps + }; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.nAtoms, n); + } + temppAtoms = pAtoms; + for (prop = provider->properties; prop; prop = prop->next) + *temppAtoms++ = prop->propertyName; + + WriteToClient(client, sizeof(xRRListProviderPropertiesReply), + (char *) &rep); + if (numProps) { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); + xfree(pAtoms); + } + return Success; +} + +int +ProcRRQueryProviderProperty(ClientPtr client) +{ + REQUEST(xRRQueryProviderPropertyReq); + xRRQueryProviderPropertyReply rep; + RRProviderPtr provider; + RRPropertyPtr prop; + char *extra = NULL; + int n; + + REQUEST_SIZE_MATCH(xRRQueryProviderPropertyReq); + + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + prop = RRQueryProviderProperty(provider, stuff->property); + if (!prop) + return BadName; + + if (prop->num_valid) { +#ifndef NXAGENT_SERVER + extra = xallocarray(prop->num_valid, sizeof(INT32)); +#else /* !defined(NXAGENT_SERVER) */ + extra = xalloc(prop->num_valid * sizeof(INT32)); +#endif /* !defined(NXAGENT_SERVER) */ + if (!extra) + return BadAlloc; + } + rep = (xRRQueryProviderPropertyReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = prop->num_valid, + .pending = prop->is_pending, + .range = prop->range, + .immutable = prop->immutable + }; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof(xRRQueryProviderPropertyReply), (char *) &rep); + if (prop->num_valid) { + memcpy(extra, prop->valid_values, prop->num_valid * sizeof(INT32)); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32), + extra); + xfree(extra); + } + return Success; +} + +int +ProcRRConfigureProviderProperty(ClientPtr client) +{ + REQUEST(xRRConfigureProviderPropertyReq); + RRProviderPtr provider; + int num_valid; + + REQUEST_AT_LEAST_SIZE(xRRConfigureProviderPropertyReq); + + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + num_valid = + stuff->length - bytes_to_int32(sizeof(xRRConfigureProviderPropertyReq)); + return RRConfigureProviderProperty(provider, stuff->property, stuff->pending, + stuff->range, FALSE, num_valid, + (INT32 *) (stuff + 1)); +} + +int +ProcRRChangeProviderProperty(ClientPtr client) +{ + REQUEST(xRRChangeProviderPropertyReq); + RRProviderPtr provider; + char format, mode; + unsigned long len; + int sizeInBytes; + int totalSize; + int err; + + REQUEST_AT_LEAST_SIZE(xRRChangeProviderPropertyReq); + UpdateCurrentTime(); + format = stuff->format; + mode = stuff->mode; + if ((mode != PropModeReplace) && (mode != PropModeAppend) && + (mode != PropModePrepend)) { + client->errorValue = mode; + return BadValue; + } + if ((format != 8) && (format != 16) && (format != 32)) { + client->errorValue = format; + return BadValue; + } + len = stuff->nUnits; + if (len > bytes_to_int32((0xffffffff - sizeof(xChangePropertyReq)))) + return BadLength; + sizeInBytes = format >> 3; + totalSize = len * sizeInBytes; + REQUEST_FIXED_SIZE(xRRChangeProviderPropertyReq, totalSize); + + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + if (!ValidAtom(stuff->property)) { + client->errorValue = stuff->property; + return BadAtom; + } + if (!ValidAtom(stuff->type)) { + client->errorValue = stuff->type; + return BadAtom; + } + + err = RRChangeProviderProperty(provider, stuff->property, + stuff->type, (int) format, + (int) mode, len, (void *) &stuff[1], TRUE, + TRUE); + if (err != Success) + return err; + else + return Success; +} + +int +ProcRRDeleteProviderProperty(ClientPtr client) +{ + REQUEST(xRRDeleteProviderPropertyReq); + RRProviderPtr provider; + RRPropertyPtr prop; + + REQUEST_SIZE_MATCH(xRRDeleteProviderPropertyReq); + UpdateCurrentTime(); + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + if (!ValidAtom(stuff->property)) { + client->errorValue = stuff->property; + return BadAtom; + } + + prop = RRQueryProviderProperty(provider, stuff->property); + if (!prop) { + client->errorValue = stuff->property; + return BadName; + } + + if (prop->immutable) { + client->errorValue = stuff->property; + return BadAccess; + } + + RRDeleteProviderProperty(provider, stuff->property); + return Success; +} + +int +ProcRRGetProviderProperty(ClientPtr client) +{ + REQUEST(xRRGetProviderPropertyReq); + RRPropertyPtr prop, *prev; + RRPropertyValuePtr prop_value; + unsigned long n, len, ind; + RRProviderPtr provider; + xRRGetProviderPropertyReply reply = { + .type = X_Reply, + .sequenceNumber = client->sequence + }; + char *extra = NULL; + + REQUEST_SIZE_MATCH(xRRGetProviderPropertyReq); + if (stuff->delete) + UpdateCurrentTime(); + VERIFY_RR_PROVIDER(stuff->provider, provider, + stuff->delete ? DixWriteAccess : DixReadAccess); + + if (!ValidAtom(stuff->property)) { + client->errorValue = stuff->property; + return BadAtom; + } + if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) { + client->errorValue = stuff->delete; + return BadValue; + } + if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) { + client->errorValue = stuff->type; + return BadAtom; + } + + for (prev = &provider->properties; (prop = *prev); prev = &prop->next) + if (prop->propertyName == stuff->property) + break; + + if (!prop) { + reply.nItems = 0; + reply.length = 0; + reply.bytesAfter = 0; + reply.propertyType = None; + reply.format = 0; + if (client->swapped) { + swaps(&reply.sequenceNumber, n); + swapl(&reply.length, n); + swapl(&reply.propertyType, n); + swapl(&reply.bytesAfter, n); + swapl(&reply.nItems, n); + } + WriteToClient(client, sizeof(xRRGetProviderPropertyReply), + (char *) &reply); + return Success; + } + + if (prop->immutable && stuff->delete) + return BadAccess; + + prop_value = RRGetProviderProperty(provider, stuff->property, stuff->pending); + if (!prop_value) + return BadAtom; + + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((stuff->type != prop_value->type) && (stuff->type != AnyPropertyType)) + ) { + reply.bytesAfter = prop_value->size; + reply.format = prop_value->format; + reply.length = 0; + reply.nItems = 0; + reply.propertyType = prop_value->type; + if (client->swapped) { + swaps(&reply.sequenceNumber, n); + swapl(&reply.length, n); + swapl(&reply.propertyType, n); + swapl(&reply.bytesAfter, n); + swapl(&reply.nItems, n); + } + WriteToClient(client, sizeof(xRRGetProviderPropertyReply), + (char *) &reply); + return Success; + } + +/* + * Return type, format, value to client + */ + n = (prop_value->format / 8) * prop_value->size; /* size (bytes) of prop */ + ind = stuff->longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) { + client->errorValue = stuff->longOffset; + return BadValue; + } + + len = min(n - ind, 4 * stuff->longLength); + + if (len) { + extra = xalloc(len); + if (!extra) + return BadAlloc; + } + reply.bytesAfter = n - (ind + len); + reply.format = prop_value->format; + reply.length = bytes_to_int32(len); + if (prop_value->format) + reply.nItems = len / (prop_value->format / 8); + else + reply.nItems = 0; + reply.propertyType = prop_value->type; + + if (stuff->delete && (reply.bytesAfter == 0)) { + xRRProviderPropertyNotifyEvent event = { + .type = RREventBase + RRNotify, + .subCode = RRNotify_ProviderProperty, + .provider = provider->id, + .state = PropertyDelete, + .atom = prop->propertyName, + .timestamp = currentTime.milliseconds + }; + RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event); + } + + if (client->swapped) { + swaps(&reply.sequenceNumber, n); + swapl(&reply.length, n); + swapl(&reply.propertyType, n); + swapl(&reply.bytesAfter, n); + swapl(&reply.nItems, n); + } + WriteToClient(client, sizeof(xGenericReply), (char *) &reply); + if (len) { + memcpy(extra, (char *) prop_value->data + ind, len); + switch (reply.format) { + case 32: + client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; + break; + case 16: + client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write; + break; + default: + client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient; + break; + } + WriteSwappedDataToClient(client, len, extra); + xfree(extra); + } + + if (stuff->delete && (reply.bytesAfter == 0)) { /* delete the Property */ + *prev = prop->next; + RRDestroyProviderProperty(prop); + } + return Success; +} diff --git a/nx-X11/programs/Xserver/randr/rrscreen.c b/nx-X11/programs/Xserver/randr/rrscreen.c index 458416c1f..af54d66f5 100644 --- a/nx-X11/programs/Xserver/randr/rrscreen.c +++ b/nx-X11/programs/Xserver/randr/rrscreen.c @@ -39,10 +39,6 @@ #include "randrstr.h" -extern char *ConnectionInfo; - -static int padlength[4] = { 0, 3, 2, 1 }; - static CARD16 RR10CurrentSizeID(ScreenPtr pScreen); @@ -65,8 +61,7 @@ RREditConnectionInfo(ScreenPtr pScreen) connSetup = (xConnSetup *) ConnectionInfo; vendor = (char *) connSetup + sizeof(xConnSetup); formats = (xPixmapFormat *) ((char *) vendor + - connSetup->nbytesVendor + - padlength[connSetup->nbytesVendor & 3]); + pad_to_int32(connSetup->nbytesVendor)); root = (xWindowRoot *) ((char *) formats + sizeof(xPixmapFormat) * screenInfo.numPixmapFormats); @@ -89,21 +84,21 @@ RREditConnectionInfo(ScreenPtr pScreen) void RRSendConfigNotify(ScreenPtr pScreen) { - WindowPtr pWin = WindowTable[pScreen->myNum]; - xEvent event; - + WindowPtr pWin = pScreen->root; + xEvent event = { + .u.configureNotify.window = pWin->drawable.id, + .u.configureNotify.aboveSibling = None, + .u.configureNotify.x = 0, + .u.configureNotify.y = 0, + + /* XXX xinerama stuff ? */ + + .u.configureNotify.width = pWin->drawable.width, + .u.configureNotify.height = pWin->drawable.height, + .u.configureNotify.borderWidth = wBorderWidth(pWin), + .u.configureNotify.override = pWin->overrideRedirect + }; 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); } @@ -111,25 +106,23 @@ 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; -#ifdef RENDER - se.subpixelOrder = PictureGetSubpixelOrder(pScreen); -#else - se.subpixelOrder = SubPixelUnknown; + WindowPtr pRoot = pScreen->root; + + xRRScreenChangeNotifyEvent se = { + .type = RRScreenChangeNotify + RREventBase, +#ifdef NXAGENT_SERVER + .sequenceNumber = client->sequence, #endif + .rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0), + .timestamp = pScrPriv->lastSetTime.milliseconds, + .configTimestamp = pScrPriv->lastConfigTime.milliseconds, + .root = pRoot->drawable.id, + .window = pWin->drawable.id, + .subpixelOrder = PictureGetSubpixelOrder(pScreen), - se.sequenceNumber = client->sequence; - se.sizeID = RR10CurrentSizeID(pScreen); + .sizeID = RR10CurrentSizeID(pScreen) + }; if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) { se.widthInPixels = pScreen->height; @@ -144,7 +137,7 @@ RRDeliverScreenEvent(ClientPtr client, WindowPtr pWin, ScreenPtr pScreen) se.heightInMillimeters = pScreen->mmHeight; } - WriteEventsToClient(client, 1, (xEvent *) &se); + WriteEventsToClient(client, 1, (xEvent *) (char *) &se); } /* @@ -170,7 +163,7 @@ RRScreenSizeNotify(ScreenPtr pScreen) pScrPriv->height = pScreen->height; pScrPriv->mmWidth = pScreen->mmWidth; pScrPriv->mmHeight = pScreen->mmHeight; - pScrPriv->changed = TRUE; + RRSetChanged(pScreen); /* pScrPriv->sizeChanged = TRUE; */ RRTellChanged(pScreen); @@ -219,27 +212,31 @@ ProcRRGetScreenSizeRange(ClientPtr client) ScreenPtr pScreen; rrScrPrivPtr pScrPriv; int rc; + int n; REQUEST_SIZE_MATCH(xRRGetScreenSizeRangeReq); #ifndef NXAGENT_SERVER - rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); #else pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess); rc = pWin ? Success : BadWindow; #endif + 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; + rep = (xRRGetScreenSizeRangeReply) { + .type = X_Reply, + .pad = 0, + .sequenceNumber = client->sequence, + .length = 0 + }; if (pScrPriv) { - if (!RRGetInfo(pScreen)) + if (!RRGetInfo(pScreen, FALSE)) return BadAlloc; rep.minWidth = pScrPriv->minWidth; rep.minHeight = pScrPriv->minHeight; @@ -251,8 +248,6 @@ ProcRRGetScreenSizeRange(ClientPtr client) rep.maxHeight = rep.minHeight = pScreen->height; } if (client->swapped) { - int n; - swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); swaps(&rep.minWidth, n); @@ -261,7 +256,7 @@ ProcRRGetScreenSizeRange(ClientPtr client) swaps(&rep.maxHeight, n); } WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), (char *) &rep); - return (client->noClientException); + return Success; } int @@ -275,7 +270,7 @@ ProcRRSetScreenSize(ClientPtr client) REQUEST_SIZE_MATCH(xRRSetScreenSizeReq); #ifndef NXAGENT_SERVER - rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); #else pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess); rc = pWin ? Success : BadWindow; @@ -285,6 +280,9 @@ ProcRRSetScreenSize(ClientPtr client) pScreen = pWin->drawable.pScreen; pScrPriv = rrGetScrPriv(pScreen); + if (!pScrPriv) + return BadMatch; + if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width) { client->errorValue = stuff->width; return BadValue; @@ -326,8 +324,194 @@ ProcRRSetScreenSize(ClientPtr client) return Success; } -int -ProcRRGetScreenResources(ClientPtr client) + +#define update_totals(gpuscreen, pScrPriv) do { \ + total_crtcs += pScrPriv->numCrtcs; \ + total_outputs += pScrPriv->numOutputs; \ + modes = RRModesForScreen(gpuscreen, &num_modes); \ + if (!modes) \ + return BadAlloc; \ + for (j = 0; j < num_modes; j++) \ + total_name_len += modes[j]->mode.nameLength; \ + total_modes += num_modes; \ + xfree(modes); \ +} while(0) + +static inline void +swap_modeinfos(xRRModeInfo * modeinfos, int i) +{ + int n; + + 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); +} + +#define update_arrays(gpuscreen, pScrPriv, primary_crtc, has_primary) do { \ + for (j = 0; j < pScrPriv->numCrtcs; j++) { \ + if (has_primary && \ + primary_crtc == pScrPriv->crtcs[j]) { \ + has_primary = 0; \ + continue; \ + }\ + crtcs[crtc_count] = pScrPriv->crtcs[j]->id; \ + if (client->swapped) \ + swapl(&crtcs[crtc_count], n); \ + crtc_count++; \ + } \ + for (j = 0; j < pScrPriv->numOutputs; j++) { \ + outputs[output_count] = pScrPriv->outputs[j]->id; \ + if (client->swapped) \ + swapl(&outputs[output_count], n); \ + output_count++; \ + } \ + { \ + RRModePtr mode; \ + modes = RRModesForScreen(gpuscreen, &num_modes); \ + for (j = 0; j < num_modes; j++) { \ + mode = modes[j]; \ + modeinfos[mode_count] = mode->mode; \ + if (client->swapped) { \ + swap_modeinfos(modeinfos, mode_count); \ + } \ + memcpy(names, mode->name, mode->mode.nameLength); \ + names += mode->mode.nameLength; \ + mode_count++; \ + } \ + xfree(modes); \ + } \ + } while (0) + +#ifndef NXAGENT_SERVER +static int +rrGetMultiScreenResources(ClientPtr client, Bool query, ScreenPtr pScreen) +{ + int j; + int total_crtcs, total_outputs, total_modes, total_name_len; + int crtc_count, output_count, mode_count; + ScreenPtr iter; + rrScrPrivPtr pScrPriv; + int num_modes; + RRModePtr *modes; + xRRGetScreenResourcesReply rep; + unsigned long extraLen; + CARD8 *extra; + RRCrtc *crtcs; + RRCrtcPtr primary_crtc = NULL; + RROutput *outputs; + xRRModeInfo *modeinfos; + CARD8 *names; + int has_primary = 0; + int n; + + /* we need to iterate all the GPU masters and all their output slaves */ + total_crtcs = 0; + total_outputs = 0; + total_modes = 0; + total_name_len = 0; + + pScrPriv = rrGetScrPriv(pScreen); + + if (query && pScrPriv) + if (!RRGetInfo(pScreen, query)) + return BadAlloc; + + update_totals(pScreen, pScrPriv); + + xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) { + pScrPriv = rrGetScrPriv(iter); + + if (query) + if (!RRGetInfo(iter, query)) + return BadAlloc; + update_totals(iter, pScrPriv); + } + + pScrPriv = rrGetScrPriv(pScreen); + rep = (xRRGetScreenResourcesReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .timestamp = pScrPriv->lastSetTime.milliseconds, + .configTimestamp = pScrPriv->lastConfigTime.milliseconds, + .nCrtcs = total_crtcs, + .nOutputs = total_outputs, + .nModes = total_modes, + .nbytesNames = total_name_len + }; + + rep.length = (total_crtcs + total_outputs + + total_modes * bytes_to_int32(SIZEOF(xRRModeInfo)) + + bytes_to_int32(total_name_len)); + + extraLen = rep.length << 2; + if (extraLen) { + extra = xalloc(extraLen); + if (!extra) { + return BadAlloc; + } + } + else + extra = NULL; + + crtcs = (RRCrtc *) extra; + outputs = (RROutput *) (crtcs + total_crtcs); + modeinfos = (xRRModeInfo *) (outputs + total_outputs); + names = (CARD8 *) (modeinfos + total_modes); + + crtc_count = 0; + output_count = 0; + mode_count = 0; + + pScrPriv = rrGetScrPriv(pScreen); + if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) { + has_primary = 1; + primary_crtc = pScrPriv->primaryOutput->crtc; + crtcs[0] = pScrPriv->primaryOutput->crtc->id; + if (client->swapped) + swapl(&crtcs[0], n); + crtc_count = 1; + } + update_arrays(pScreen, pScrPriv, primary_crtc, has_primary); + + xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) { + pScrPriv = rrGetScrPriv(iter); + + update_arrays(iter, pScrPriv, primary_crtc, has_primary); + } + + 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 Success; +} +#endif /* !defined(NXAGENT_SERVER) */ + +static int +rrGetScreenResources(ClientPtr client, Bool query) { REQUEST(xRRGetScreenResourcesReq); xRRGetScreenResourcesReply rep; @@ -336,15 +520,17 @@ ProcRRGetScreenResources(ClientPtr client) rrScrPrivPtr pScrPriv; CARD8 *extra; unsigned long extraLen; - int i, n, rc; + int i, rc, has_primary = 0; RRCrtc *crtcs; RROutput *outputs; xRRModeInfo *modeinfos; CARD8 *names; + int n; REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq); + #ifndef NXAGENT_SERVER - rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); #else pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess); rc = pWin ? Success : BadWindow; @@ -354,22 +540,28 @@ ProcRRGetScreenResources(ClientPtr client) pScreen = pWin->drawable.pScreen; pScrPriv = rrGetScrPriv(pScreen); - rep.pad = 0; - if (pScrPriv) - if (!RRGetInfo(pScreen)) + if (query && pScrPriv) + if (!RRGetInfo(pScreen, query)) return BadAlloc; +#ifndef NXAGENT_SERVER + if (!xorg_list_is_empty(&pScreen->output_slave_list)) + return rrGetMultiScreenResources(client, query, pScreen); +#endif + 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; + rep = (xRRGetScreenResourcesReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .timestamp = currentTime.milliseconds, + .configTimestamp = currentTime.milliseconds, + .nCrtcs = 0, + .nOutputs = 0, + .nModes = 0, + .nbytesNames = 0 + }; extra = NULL; extraLen = 0; } @@ -381,23 +573,25 @@ ProcRRGetScreenResources(ClientPtr client) 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; + rep = (xRRGetScreenResourcesReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .timestamp = pScrPriv->lastSetTime.milliseconds, + .configTimestamp = pScrPriv->lastConfigTime.milliseconds, + .nCrtcs = pScrPriv->numCrtcs, + .nOutputs = pScrPriv->numOutputs, + .nModes = num_modes, + .nbytesNames = 0 + }; for (i = 0; i < num_modes; i++) rep.nbytesNames += modes[i]->mode.nameLength; rep.length = (pScrPriv->numCrtcs + pScrPriv->numOutputs + - num_modes * (SIZEOF(xRRModeInfo) >> 2) + - ((rep.nbytesNames + 3) >> 2)); + num_modes * bytes_to_int32(SIZEOF(xRRModeInfo)) + + bytes_to_int32(rep.nbytesNames)); extraLen = rep.length << 2; if (extraLen) { @@ -415,10 +609,22 @@ ProcRRGetScreenResources(ClientPtr client) 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++) { - crtcs[i] = pScrPriv->crtcs[i]->id; + 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], n); + swapl(&crtcs[i + has_primary], n); } for (i = 0; i < pScrPriv->numOutputs; i++) { @@ -450,7 +656,7 @@ ProcRRGetScreenResources(ClientPtr client) names += mode->mode.nameLength; } xfree(modes); - assert(((((char *) names - (char *) extra) + 3) >> 2) == rep.length); + assert(bytes_to_int32((char *) names - (char *) extra) == rep.length); } if (client->swapped) { @@ -463,12 +669,25 @@ ProcRRGetScreenResources(ClientPtr client) swaps(&rep.nModes, n); swaps(&rep.nbytesNames, n); } - WriteToClient(client, sizeof(xRRGetScreenResourcesReply), (char *) &rep); + WriteToClient(client, sizeof(xRRGetScreenResourcesReply), + (char *) (char *) &rep); if (extraLen) { - WriteToClient(client, extraLen, (char *) extra); + WriteToClient(client, extraLen, (char *) (char *) extra); xfree(extra); } - return client->noClientException; + return Success; +} + +int +ProcRRGetScreenResources(ClientPtr client) +{ + return rrGetScreenResources(client, TRUE); +} + +int +ProcRRGetScreenResourcesCurrent(ClientPtr client) +{ + return rrGetScreenResources(client, FALSE); } typedef struct _RR10Data { @@ -495,7 +714,7 @@ RR10GetData(ScreenPtr pScreen, RROutputPtr output) Bool *used; /* Make sure there is plenty of space for any combination */ - data = malloc(sizeof(RR10DataRec) + + data = xalloc(sizeof(RR10DataRec) + sizeof(RRScreenSize) * nmode + sizeof(RRScreenRate) * nmode + sizeof(Bool) * nmode); if (!data) @@ -576,46 +795,49 @@ ProcRRGetScreenInfo(ClientPtr client) REQUEST(xRRGetScreenInfoReq); xRRGetScreenInfoReply rep; WindowPtr pWin; - int n, rc; + int rc; ScreenPtr pScreen; rrScrPrivPtr pScrPriv; CARD8 *extra; unsigned long extraLen; RROutputPtr output; + int n; REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); #ifndef NXAGENT_SERVER - rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); #else pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess); rc = pWin ? Success : BadWindow; #endif + if (rc != Success) return rc; pScreen = pWin->drawable.pScreen; pScrPriv = rrGetScrPriv(pScreen); - rep.pad = 0; if (pScrPriv) - if (!RRGetInfo(pScreen)) + 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; + rep = (xRRGetScreenInfoReply) { + .type = X_Reply, + .setOfRotations = RR_Rotate_0, + .sequenceNumber = client->sequence, + .length = 0, + .root = pWin->drawable.pScreen->root->drawable.id, + .timestamp = currentTime.milliseconds, + .configTimestamp = currentTime.milliseconds, + .nSizes = 0, + .sizeID = 0, + .rotation = RR_Rotate_0, + .rate = 0, + .nrateEnts = 0 + }; extra = 0; extraLen = 0; } @@ -632,18 +854,20 @@ ProcRRGetScreenInfo(ClientPtr client) 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; + rep = (xRRGetScreenInfoReply) { + .type = X_Reply, + .setOfRotations = output->crtc->rotations, + .sequenceNumber = client->sequence, + .length = 0, + .root = pWin->drawable.pScreen->root->drawable.id, + .timestamp = pScrPriv->lastSetTime.milliseconds, + .configTimestamp = pScrPriv->lastConfigTime.milliseconds, + .rotation = output->crtc->rotation, + .nSizes = pData->nsize, + .nrateEnts = pData->nrefresh + pData->nsize, + .sizeID = pData->size, + .rate = pData->refresh + }; extraLen = rep.nSizes * sizeof(xScreenSizes); if (has_rate) @@ -699,7 +923,7 @@ ProcRRGetScreenInfo(ClientPtr client) if (data8 - (CARD8 *) extra != extraLen) FatalError("RRGetScreenInfo bad extra len %ld != %ld\n", (unsigned long) (data8 - (CARD8 *) extra), extraLen); - rep.length = (extraLen + 3) >> 2; + rep.length = bytes_to_int32(extraLen); } if (client->swapped) { swaps(&rep.sequenceNumber, n); @@ -717,7 +941,7 @@ ProcRRGetScreenInfo(ClientPtr client) WriteToClient(client, extraLen, (char *) extra); xfree(extra); } - return (client->noClientException); + return Success; } int @@ -726,7 +950,7 @@ ProcRRSetScreenConfig(ClientPtr client) REQUEST(xRRSetScreenConfigReq); xRRSetScreenConfigReply rep; DrawablePtr pDraw; - int n, rc; + int rc; ScreenPtr pScreen; rrScrPrivPtr pScrPriv; TimeStamp time; @@ -734,12 +958,14 @@ ProcRRSetScreenConfig(ClientPtr client) Rotation rotation; int rate; Bool has_rate; + CARD8 status; RROutputPtr output; RRCrtcPtr crtc; RRModePtr mode; RR10DataPtr pData = NULL; RRScreenSizePtr pSize; int width, height; + int n; UpdateCurrentTime(); @@ -754,11 +980,12 @@ ProcRRSetScreenConfig(ClientPtr client) #ifndef NXAGENT_SERVER rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess); -#else +#else /* !defined(NXAGENT_SERVER) */ pDraw = SecurityLookupDrawable(stuff->drawable, client, SecurityWriteAccess); rc = pDraw ? Success : BadDrawable; -#endif +#endif /* !defined(NXAGENT_SERVER) */ + if (rc != Success) return rc; @@ -770,16 +997,16 @@ ProcRRSetScreenConfig(ClientPtr client) if (!pScrPriv) { time = currentTime; - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; goto sendReply; } - if (!RRGetInfo(pScreen)) + if (!RRGetInfo(pScreen, FALSE)) return BadAlloc; output = RRFirstOutput(pScreen); if (!output) { time = currentTime; - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; goto sendReply; } @@ -795,7 +1022,7 @@ ProcRRSetScreenConfig(ClientPtr client) * stop working after several hours have passed (freedesktop bug #6502). */ if (stuff->configTimestamp != pScrPriv->lastConfigTime.milliseconds) { - rep.status = RRSetConfigInvalidConfigTime; + status = RRSetConfigInvalidConfigTime; goto sendReply; } @@ -874,7 +1101,7 @@ ProcRRSetScreenConfig(ClientPtr client) * the last set-time */ if (CompareTimeStamps(time, pScrPriv->lastSetTime) < 0) { - rep.status = RRSetConfigInvalidTime; + status = RRSetConfigInvalidTime; goto sendReply; } @@ -884,11 +1111,6 @@ ProcRRSetScreenConfig(ClientPtr client) */ 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 < pScrPriv->minWidth || pScrPriv->maxWidth < width) { client->errorValue = width; xfree(pData); @@ -900,30 +1122,35 @@ ProcRRSetScreenConfig(ClientPtr client) return BadValue; } + if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { + width = mode->mode.height; + height = mode->mode.width; + } + if (width != pScreen->width || height != pScreen->height) { int c; for (c = 0; c < pScrPriv->numCrtcs; c++) { if (!RRCrtcSet(pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0, 0, NULL)) { - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; /* XXX recover from failure */ goto sendReply; } } if (!RRScreenSizeSet(pScreen, width, height, pScreen->mmWidth, pScreen->mmHeight)) { - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; /* XXX recover from failure */ goto sendReply; } } if (!RRCrtcSet(crtc, mode, 0, 0, stuff->rotation, 1, &output)) - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; else { pScrPriv->lastSetTime = time; - rep.status = RRSetConfigSuccess; + status = RRSetConfigSuccess; } /* @@ -932,17 +1159,18 @@ ProcRRSetScreenConfig(ClientPtr client) sendReply: - if (pData) - xfree(pData); - - rep.type = X_Reply; - /* rep.status has already been filled in */ - rep.length = 0; - rep.sequenceNumber = client->sequence; + xfree(pData); - rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; - rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds; - rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + rep = (xRRSetScreenConfigReply) { + .type = X_Reply, + .status = status, + .sequenceNumber = client->sequence, + .length = 0, + .newTimestamp = pScrPriv->lastSetTime.milliseconds, + .newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds, + .root = pDraw->pScreen->root->drawable.id, + /* .subpixelOrder = ?? */ + }; if (client->swapped) { swaps(&rep.sequenceNumber, n); @@ -953,7 +1181,7 @@ ProcRRSetScreenConfig(ClientPtr client) } WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *) &rep); - return (client->noClientException); + return Success; } static CARD16 diff --git a/nx-X11/programs/Xserver/randr/rrsdispatch.c b/nx-X11/programs/Xserver/randr/rrsdispatch.c index 3175340fa..6ac394344 100644 --- a/nx-X11/programs/Xserver/randr/rrsdispatch.c +++ b/nx-X11/programs/Xserver/randr/rrsdispatch.c @@ -25,7 +25,7 @@ static int SProcRRQueryVersion(ClientPtr client) { - register int n; + int n; REQUEST(xRRQueryVersionReq); @@ -39,7 +39,7 @@ SProcRRQueryVersion(ClientPtr client) static int SProcRRGetScreenInfo(ClientPtr client) { - register int n; + int n; REQUEST(xRRGetScreenInfoReq); @@ -52,7 +52,7 @@ SProcRRGetScreenInfo(ClientPtr client) static int SProcRRSetScreenConfig(ClientPtr client) { - register int n; + int n; REQUEST(xRRSetScreenConfigReq); @@ -75,7 +75,7 @@ SProcRRSetScreenConfig(ClientPtr client) static int SProcRRSelectInput(ClientPtr client) { - register int n; + int n; REQUEST(xRRSelectInputReq); @@ -134,7 +134,7 @@ SProcRRGetOutputInfo(ClientPtr client) { int n; - REQUEST(xRRGetOutputInfoReq);; + REQUEST(xRRGetOutputInfoReq); REQUEST_SIZE_MATCH(xRRGetOutputInfoReq); swaps(&stuff->length, n); @@ -177,6 +177,7 @@ SProcRRConfigureOutputProperty(ClientPtr client) REQUEST(xRRConfigureOutputPropertyReq); + REQUEST_AT_LEAST_SIZE(xRRConfigureOutputPropertyReq); swaps(&stuff->length, n); swapl(&stuff->output, n); swapl(&stuff->property, n); @@ -248,6 +249,7 @@ static int SProcRRCreateMode(ClientPtr client) { int n; + xRRModeInfo *modeinfo; REQUEST(xRRCreateModeReq); @@ -388,6 +390,315 @@ SProcRRSetCrtcGamma(ClientPtr client) return (*ProcRandrVector[stuff->randrReqType]) (client); } +static int +SProcRRSetCrtcTransform(ClientPtr client) +{ + int nparams; + char *filter; + CARD32 *params; + int n; + + REQUEST(xRRSetCrtcTransformReq); + + REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq); + swaps(&stuff->length, n); + swapl(&stuff->crtc, n); + SwapLongs((CARD32 *) &stuff->transform, + bytes_to_int32(sizeof(xRenderTransform))); + swaps(&stuff->nbytesFilter, n); + filter = (char *) (stuff + 1); + params = (CARD32 *) (filter + pad_to_int32(stuff->nbytesFilter)); + nparams = ((CARD32 *) stuff + client->req_len) - params; + if (nparams < 0) + return BadLength; + + SwapLongs(params, nparams); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRGetCrtcTransform(ClientPtr client) +{ + int n; + + REQUEST(xRRGetCrtcTransformReq); + + REQUEST_SIZE_MATCH(xRRGetCrtcTransformReq); + swaps(&stuff->length, n); + swapl(&stuff->crtc, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRGetPanning(ClientPtr client) +{ + int n; + + REQUEST(xRRGetPanningReq); + + REQUEST_SIZE_MATCH(xRRGetPanningReq); + swaps(&stuff->length, n); + swapl(&stuff->crtc, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRSetPanning(ClientPtr client) +{ + int n; + + REQUEST(xRRSetPanningReq); + + REQUEST_SIZE_MATCH(xRRSetPanningReq); + swaps(&stuff->length, n); + swapl(&stuff->crtc, n); + swapl(&stuff->timestamp, n); + swaps(&stuff->left, n); + swaps(&stuff->top, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swaps(&stuff->track_left, n); + swaps(&stuff->track_top, n); + swaps(&stuff->track_width, n); + swaps(&stuff->track_height, n); + swaps(&stuff->border_left, n); + swaps(&stuff->border_top, n); + swaps(&stuff->border_right, n); + swaps(&stuff->border_bottom, n); + return (*ProcRandrVector[stuff->randrReqType]) (client); +} + +static int +SProcRRSetOutputPrimary(ClientPtr client) +{ + int n; + + REQUEST(xRRSetOutputPrimaryReq); + + REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->output, n); + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRGetOutputPrimary(ClientPtr client) +{ + int n; + + REQUEST(xRRGetOutputPrimaryReq); + + REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRGetProviders(ClientPtr client) +{ + int n; + + REQUEST(xRRGetProvidersReq); + + REQUEST_SIZE_MATCH(xRRGetProvidersReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRGetProviderInfo(ClientPtr client) +{ + int n; + + REQUEST(xRRGetProviderInfoReq); + + REQUEST_SIZE_MATCH(xRRGetProviderInfoReq); + swaps(&stuff->length, n); + swapl(&stuff->provider, n); + swapl(&stuff->configTimestamp, n); + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRSetProviderOffloadSink(ClientPtr client) +{ + int n; + + REQUEST(xRRSetProviderOffloadSinkReq); + + REQUEST_SIZE_MATCH(xRRSetProviderOffloadSinkReq); + swaps(&stuff->length, n); + swapl(&stuff->provider, n); + swapl(&stuff->sink_provider, n); + swapl(&stuff->configTimestamp, n); + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRSetProviderOutputSource(ClientPtr client) +{ + int n; + + REQUEST(xRRSetProviderOutputSourceReq); + + REQUEST_SIZE_MATCH(xRRSetProviderOutputSourceReq); + swaps(&stuff->length, n); + swapl(&stuff->provider, n); + swapl(&stuff->source_provider, n); + swapl(&stuff->configTimestamp, n); + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRListProviderProperties(ClientPtr client) +{ + int n; + + REQUEST(xRRListProviderPropertiesReq); + + REQUEST_SIZE_MATCH(xRRListProviderPropertiesReq); + swaps(&stuff->length, n); + swapl(&stuff->provider, n); + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRQueryProviderProperty(ClientPtr client) +{ + int n; + + REQUEST(xRRQueryProviderPropertyReq); + + REQUEST_SIZE_MATCH(xRRQueryProviderPropertyReq); + swaps(&stuff->length, n); + swapl(&stuff->provider, n); + swapl(&stuff->property, n); + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRConfigureProviderProperty(ClientPtr client) +{ + int n; + + REQUEST(xRRConfigureProviderPropertyReq); + + REQUEST_AT_LEAST_SIZE(xRRConfigureProviderPropertyReq); + swaps(&stuff->length, n); + swapl(&stuff->provider, n); + swapl(&stuff->property, n); + /* TODO: no way to specify format? */ + SwapRestL(stuff); + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRChangeProviderProperty(ClientPtr client) +{ + int n; + + REQUEST(xRRChangeProviderPropertyReq); + + REQUEST_AT_LEAST_SIZE(xRRChangeProviderPropertyReq); + swaps(&stuff->length, n); + swapl(&stuff->provider, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->nUnits, n); + switch (stuff->format) { + case 8: + break; + case 16: + SwapRestS(stuff); + break; + case 32: + SwapRestL(stuff); + break; + } + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRDeleteProviderProperty(ClientPtr client) +{ + int n; + + REQUEST(xRRDeleteProviderPropertyReq); + + REQUEST_SIZE_MATCH(xRRDeleteProviderPropertyReq); + swaps(&stuff->length, n); + swapl(&stuff->provider, n); + swapl(&stuff->property, n); + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRGetProviderProperty(ClientPtr client) +{ + int n; + + REQUEST(xRRGetProviderPropertyReq); + + REQUEST_SIZE_MATCH(xRRGetProviderPropertyReq); + swaps(&stuff->length, n); + swapl(&stuff->provider, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->longOffset, n); + swapl(&stuff->longLength, n); + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRGetMonitors(ClientPtr client) +{ + int n; + + REQUEST(xRRGetMonitorsReq); + + REQUEST_SIZE_MATCH(xRRGetMonitorsReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRSetMonitor(ClientPtr client) +{ + int n; + + REQUEST(xRRSetMonitorReq); + + REQUEST_AT_LEAST_SIZE(xRRGetMonitorsReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->monitor.name, n); + swaps(&stuff->monitor.noutput, n); + swaps(&stuff->monitor.x, n); + swaps(&stuff->monitor.y, n); + swaps(&stuff->monitor.width, n); + swaps(&stuff->monitor.height, n); + SwapRestL(stuff); + return ProcRandrVector[stuff->randrReqType] (client); +} + +static int +SProcRRDeleteMonitor(ClientPtr client) +{ + int n; + + REQUEST(xRRDeleteMonitorReq); + + REQUEST_SIZE_MATCH(xRRDeleteMonitorReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->name, n); + return ProcRandrVector[stuff->randrReqType] (client); +} + int (*SProcRandrVector[RRNumberRequests]) (ClientPtr) = { SProcRRQueryVersion, /* 0 */ /* we skip 1 to make old clients fail pretty immediately */ @@ -418,4 +729,26 @@ int (*SProcRandrVector[RRNumberRequests]) (ClientPtr) = { SProcRRGetCrtcGammaSize, /* 22 */ SProcRRGetCrtcGamma, /* 23 */ SProcRRSetCrtcGamma, /* 24 */ +/* V1.3 additions */ + SProcRRGetScreenResources, /* 25 GetScreenResourcesCurrent */ + SProcRRSetCrtcTransform, /* 26 */ + SProcRRGetCrtcTransform, /* 27 */ + SProcRRGetPanning, /* 28 */ + SProcRRSetPanning, /* 29 */ + SProcRRSetOutputPrimary, /* 30 */ + SProcRRGetOutputPrimary, /* 31 */ +/* V1.4 additions */ + SProcRRGetProviders, /* 32 */ + SProcRRGetProviderInfo, /* 33 */ + SProcRRSetProviderOffloadSink, /* 34 */ + SProcRRSetProviderOutputSource, /* 35 */ + SProcRRListProviderProperties, /* 36 */ + SProcRRQueryProviderProperty, /* 37 */ + SProcRRConfigureProviderProperty, /* 38 */ + SProcRRChangeProviderProperty, /* 39 */ + SProcRRDeleteProviderProperty, /* 40 */ + SProcRRGetProviderProperty, /* 41 */ + SProcRRGetMonitors, /* 42 */ + SProcRRSetMonitor, /* 43 */ + SProcRRDeleteMonitor, /* 44 */ }; diff --git a/nx-X11/programs/Xserver/randr/rrtransform.c b/nx-X11/programs/Xserver/randr/rrtransform.c new file mode 100644 index 000000000..4377d09aa --- /dev/null +++ b/nx-X11/programs/Xserver/randr/rrtransform.c @@ -0,0 +1,301 @@ +/* + * 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) +{ + 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) { +#ifndef NXAGENT_SERVER + new_params = xallocarray(nparams, sizeof(xFixed)); +#else /* !defined(NXAGENT_SERVER) */ + new_params = xalloc(nparams * sizeof(xFixed)); +#endif /* !defined(NXAGENT_SERVER) */ + if (!new_params) + return FALSE; + memcpy(new_params, params, nparams * sizeof(xFixed)); + } + else + new_params = NULL; + 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 = fabs(f_transform->m[j][i])) > max) + max = v; + scale = limit / max; + for (j = 0; j < 3; j++) + for (i = 0; i < 3; i++) + f_transform->m[j][i] *= scale; +} + +/* + * Compute the complete transformation matrix including + * client-specified transform, rotation/reflection values and the crtc + * offset. + * + * Return TRUE if the resulting transform is not a simple translation. + */ +Bool +RRTransformCompute(int x, + int y, + int width, + int height, + Rotation rotation, + RRTransformPtr rr_transform, + PictTransformPtr transform, + struct pixman_f_transform *f_transform, + struct pixman_f_transform *f_inverse) +{ + PictTransform t_transform, inverse; + struct pixman_f_transform tf_transform, tf_inverse; + Bool overflow = FALSE; + + if (!transform) + transform = &t_transform; + if (!f_transform) + f_transform = &tf_transform; + if (!f_inverse) + f_inverse = &tf_inverse; + + pixman_transform_init_identity(transform); + pixman_transform_init_identity(&inverse); + pixman_f_transform_init_identity(f_transform); + pixman_f_transform_init_identity(f_inverse); + if (rotation != RR_Rotate_0) { + double f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy; + double f_scale_x, f_scale_y, f_scale_dx, f_scale_dy; + xFixed rot_cos, rot_sin, rot_dx, rot_dy; + xFixed scale_x, scale_y, scale_dx, scale_dy; + + /* rotation */ + switch (rotation & 0xf) { + default: + case RR_Rotate_0: + f_rot_cos = 1; + f_rot_sin = 0; + f_rot_dx = 0; + f_rot_dy = 0; + rot_cos = F(1); + rot_sin = F(0); + rot_dx = F(0); + rot_dy = F(0); + break; + case RR_Rotate_90: + f_rot_cos = 0; + f_rot_sin = 1; + f_rot_dx = height; + f_rot_dy = 0; + rot_cos = F(0); + rot_sin = F(1); + rot_dx = F(height); + rot_dy = F(0); + break; + case RR_Rotate_180: + f_rot_cos = -1; + f_rot_sin = 0; + f_rot_dx = width; + f_rot_dy = height; + rot_cos = F(~0u); + rot_sin = F(0); + rot_dx = F(width); + rot_dy = F(height); + break; + case RR_Rotate_270: + f_rot_cos = 0; + f_rot_sin = -1; + f_rot_dx = 0; + f_rot_dy = width; + rot_cos = F(0); + rot_sin = F(~0u); + rot_dx = F(0); + rot_dy = F(width); + break; + } + + pixman_transform_rotate(transform, &inverse, rot_cos, rot_sin); + pixman_transform_translate(transform, &inverse, rot_dx, rot_dy); + pixman_f_transform_rotate(f_transform, f_inverse, f_rot_cos, f_rot_sin); + pixman_f_transform_translate(f_transform, f_inverse, f_rot_dx, + f_rot_dy); + + /* reflection */ + f_scale_x = 1; + f_scale_dx = 0; + f_scale_y = 1; + f_scale_dy = 0; + scale_x = F(1); + scale_dx = 0; + scale_y = F(1); + scale_dy = 0; + if (rotation & RR_Reflect_X) { + f_scale_x = -1; + scale_x = F(~0u); + if (rotation & (RR_Rotate_0 | RR_Rotate_180)) { + f_scale_dx = width; + scale_dx = F(width); + } + else { + f_scale_dx = height; + scale_dx = F(height); + } + } + if (rotation & RR_Reflect_Y) { + f_scale_y = -1; + scale_y = F(~0u); + if (rotation & (RR_Rotate_0 | RR_Rotate_180)) { + f_scale_dy = height; + scale_dy = F(height); + } + else { + f_scale_dy = width; + scale_dy = F(width); + } + } + + pixman_transform_scale(transform, &inverse, scale_x, scale_y); + pixman_f_transform_scale(f_transform, f_inverse, f_scale_x, f_scale_y); + pixman_transform_translate(transform, &inverse, scale_dx, scale_dy); + pixman_f_transform_translate(f_transform, f_inverse, f_scale_dx, + f_scale_dy); + } + +#ifdef RANDR_12_INTERFACE + if (rr_transform) { + if (!pixman_transform_multiply + (transform, &rr_transform->transform, transform)) + overflow = TRUE; + pixman_f_transform_multiply(f_transform, &rr_transform->f_transform, + f_transform); + pixman_f_transform_multiply(f_inverse, f_inverse, + &rr_transform->f_inverse); + } +#endif + /* + * Compute the class of the resulting transform + */ + if (!overflow && pixman_transform_is_identity(transform)) { + pixman_transform_init_translate(transform, F(x), F(y)); + + pixman_f_transform_init_translate(f_transform, x, y); + pixman_f_transform_init_translate(f_inverse, -x, -y); + return FALSE; + } + else { + pixman_f_transform_translate(f_transform, f_inverse, x, y); + if (!pixman_transform_translate(transform, &inverse, F(x), F(y))) + overflow = TRUE; + if (overflow) { + struct pixman_f_transform f_scaled; + + f_scaled = *f_transform; + RRTransformRescale(&f_scaled, 16384.0); + pixman_transform_from_pixman_f_transform(transform, &f_scaled); + } + return TRUE; + } +} diff --git a/nx-X11/programs/Xserver/randr/rrtransform.h b/nx-X11/programs/Xserver/randr/rrtransform.h new file mode 100644 index 000000000..2433a0f73 --- /dev/null +++ b/nx-X11/programs/Xserver/randr/rrtransform.h @@ -0,0 +1,79 @@ +/* + * Copyright © 2007 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _RRTRANSFORM_H_ +#define _RRTRANSFORM_H_ + +#include "randr.h" +#include "picturestr.h" + +typedef struct _rrTransform RRTransformRec, *RRTransformPtr; + +struct _rrTransform { + PictTransform transform; + struct pict_f_transform f_transform; + struct pict_f_transform f_inverse; + PictFilterPtr filter; + xFixed *params; + int nparams; + int width; + int height; +}; + +extern _X_EXPORT void + RRTransformInit(RRTransformPtr transform); + +extern _X_EXPORT void + RRTransformFini(RRTransformPtr transform); + +extern _X_EXPORT Bool + RRTransformEqual(RRTransformPtr a, RRTransformPtr b); + +extern _X_EXPORT Bool + +RRTransformSetFilter(RRTransformPtr dst, + PictFilterPtr filter, + xFixed * params, int nparams, int width, int height); + +extern _X_EXPORT Bool + RRTransformCopy(RRTransformPtr dst, RRTransformPtr src); + +/* + * Compute the complete transformation matrix including + * client-specified transform, rotation/reflection values and the crtc + * offset. + * + * Return TRUE if the resulting transform is not a simple translation. + */ +extern _X_EXPORT Bool + +RRTransformCompute(int x, + int y, + int width, + int height, + Rotation rotation, + RRTransformPtr rr_transform, + PictTransformPtr transform, + struct pict_f_transform *f_transform, + struct pict_f_transform *f_inverse); + +#endif /* _RRTRANSFORM_H_ */ diff --git a/nx-X11/programs/Xserver/randr/rrxinerama.c b/nx-X11/programs/Xserver/randr/rrxinerama.c index 31b750d64..9a164578f 100644 --- a/nx-X11/programs/Xserver/randr/rrxinerama.c +++ b/nx-X11/programs/Xserver/randr/rrxinerama.c @@ -87,15 +87,14 @@ #include "randrstr.h" #include "swaprep.h" +#include "panoramiXproto.h" #ifndef NXAGENT_SERVER -#include <nx-X11/extensions/panoramiXproto.h> +#include "protocol-versions.h" #else -#include "panoramiXproto.h" +#define SERVER_RRXINERAMA_MAJOR_VERSION 1 +#define SERVER_RRXINERAMA_MINOR_VERSION 1 #endif -#define RR_XINERAMA_MAJOR_VERSION 1 -#define RR_XINERAMA_MINOR_VERSION 1 - /* Xinerama is not multi-screen capable; just report about screen 0 */ #define RR_XINERAMA_SCREEN 0 @@ -114,15 +113,17 @@ extern Bool noRRXineramaExtension; int ProcRRXineramaQueryVersion(ClientPtr client) { - xPanoramiXQueryVersionReply rep; - register int n; + int n; + + xPanoramiXQueryVersionReply rep = { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .majorVersion = SERVER_RRXINERAMA_MAJOR_VERSION, + .minorVersion = SERVER_RRXINERAMA_MINOR_VERSION + }; REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = RR_XINERAMA_MAJOR_VERSION; - rep.minorVersion = RR_XINERAMA_MINOR_VERSION; if (client->swapped) { swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); @@ -130,7 +131,7 @@ ProcRRXineramaQueryVersion(ClientPtr client) swaps(&rep.minorVersion, n); } WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *) &rep); - return (client->noClientException); + return Success; } int @@ -139,10 +140,11 @@ ProcRRXineramaGetState(ClientPtr client) REQUEST(xPanoramiXGetStateReq); WindowPtr pWin; xPanoramiXGetStateReply rep; - register int n, rc; + register int rc; ScreenPtr pScreen; rrScrPrivPtr pScrPriv; Bool active = FALSE; + int n; REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); #ifndef NXAGENT_SERVER @@ -151,6 +153,7 @@ ProcRRXineramaGetState(ClientPtr client) pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess); rc = pWin ? Success : BadWindow; #endif + if (rc != Success) return rc; @@ -161,39 +164,26 @@ ProcRRXineramaGetState(ClientPtr client) active = TRUE; } - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.state = active; - rep.window = stuff->window; + rep = (xPanoramiXGetStateReply) { + .type = X_Reply, + .state = active, + .sequenceNumber = client->sequence, + .length = 0, + .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; + return Success; } 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; + return RRMonitorCountList(pScreen); } static Bool @@ -208,9 +198,11 @@ ProcRRXineramaGetScreenCount(ClientPtr client) REQUEST(xPanoramiXGetScreenCountReq); WindowPtr pWin; xPanoramiXGetScreenCountReply rep; - register int n, rc; + register int rc; + int n; REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + #ifndef NXAGENT_SERVER rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); #else @@ -220,18 +212,20 @@ ProcRRXineramaGetScreenCount(ClientPtr client) 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; + rep = (xPanoramiXGetScreenCountReply) { + .type = X_Reply, + .ScreenCount = RRXineramaScreenCount(pWin->drawable.pScreen), + .sequenceNumber = client->sequence, + .length = 0, + .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; + return Success; } int @@ -241,7 +235,8 @@ ProcRRXineramaGetScreenSize(ClientPtr client) WindowPtr pWin, pRoot; ScreenPtr pScreen; xPanoramiXGetScreenSizeReply rep; - register int n, rc; + register int rc; + int n; REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); #ifndef NXAGENT_SERVER @@ -250,19 +245,22 @@ ProcRRXineramaGetScreenSize(ClientPtr client) pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess); rc = pWin ? Success : BadWindow; #endif + 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; + pRoot = pScreen->root; + + rep = (xPanoramiXGetScreenSizeReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .width = pRoot->drawable.width, + .height = pRoot->drawable.height, + .window = stuff->window, + .screen = stuff->screen + }; if (client->swapped) { swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); @@ -272,30 +270,43 @@ ProcRRXineramaGetScreenSize(ClientPtr client) swapl(&rep.screen, n); } WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *) &rep); - return client->noClientException; + return Success; } int ProcRRXineramaIsActive(ClientPtr client) { xXineramaIsActiveReply rep; + int n; 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]); + rep = (xXineramaIsActiveReply) { + .type = X_Reply, + .length = 0, + .sequenceNumber = client->sequence, + .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; + return Success; +} + +static void +RRXineramaWriteMonitor(ClientPtr client, RRMonitorPtr monitor) +{ + xXineramaScreenInfo scratch; + + scratch.x_org = monitor->geometry.box.x1; + scratch.y_org = monitor->geometry.box.y1; + scratch.width = monitor->geometry.box.x2 - monitor->geometry.box.x1; + scratch.height = monitor->geometry.box.y2 - monitor->geometry.box.y1; + + WriteToClient(client, sz_XineramaScreenInfo, (char *) &scratch); } int @@ -303,58 +314,39 @@ ProcRRXineramaQueryScreens(ClientPtr client) { xXineramaQueryScreensReply rep; ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN]; + int m; + RRMonitorPtr monitors = NULL; + int nmonitors = 0; + int n; REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); if (RRXineramaScreenActive(pScreen)) { - rrScrPriv(pScreen); - if (pScrPriv->numCrtcs == 0 || pScrPriv->numOutputs == 0) - RRGetInfo(pScreen); + RRGetInfo(pScreen, FALSE); + if (!RRMonitorMakeList(pScreen, TRUE, &monitors, &nmonitors)) + return BadAlloc; } - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.number = RRXineramaScreenCount(pScreen); - rep.length = rep.number * sz_XineramaScreenInfo >> 2; + rep = (xXineramaQueryScreensReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = bytes_to_int32(nmonitors * sz_XineramaScreenInfo), + .number = nmonitors + }; 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); - xXineramaScreenInfo scratch; - int i; - - for (i = 0; i < pScrPriv->numCrtcs; i++) { - RRCrtcPtr crtc = pScrPriv->crtcs[i]; - - if (RRXineramaCrtcActive(crtc)) { - 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, (char *) &scratch); - } - } - } + for (m = 0; m < nmonitors; m++) + RRXineramaWriteMonitor(client, &monitors[m]); + + if (monitors) + RRMonitorFreeList(monitors, nmonitors); - return client->noClientException; + return Success; } static int @@ -383,9 +375,9 @@ ProcRRXineramaDispatch(ClientPtr client) static int SProcRRXineramaQueryVersion(ClientPtr client) { - REQUEST(xPanoramiXQueryVersionReq); - register int n; + int n; + REQUEST(xPanoramiXQueryVersionReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); return ProcRRXineramaQueryVersion(client); @@ -394,9 +386,9 @@ SProcRRXineramaQueryVersion(ClientPtr client) static int SProcRRXineramaGetState(ClientPtr client) { - REQUEST(xPanoramiXGetStateReq); - register int n; + int n; + REQUEST(xPanoramiXGetStateReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); swapl(&stuff->window, n); @@ -406,9 +398,9 @@ SProcRRXineramaGetState(ClientPtr client) static int SProcRRXineramaGetScreenCount(ClientPtr client) { - REQUEST(xPanoramiXGetScreenCountReq); - register int n; + int n; + REQUEST(xPanoramiXGetScreenCountReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); swapl(&stuff->window, n); @@ -418,9 +410,9 @@ SProcRRXineramaGetScreenCount(ClientPtr client) static int SProcRRXineramaGetScreenSize(ClientPtr client) { - REQUEST(xPanoramiXGetScreenSizeReq); - register int n; + int n; + REQUEST(xPanoramiXGetScreenSizeReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); swapl(&stuff->window, n); @@ -431,9 +423,9 @@ SProcRRXineramaGetScreenSize(ClientPtr client) static int SProcRRXineramaIsActive(ClientPtr client) { - REQUEST(xXineramaIsActiveReq); - register int n; + int n; + REQUEST(xXineramaIsActiveReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xXineramaIsActiveReq); return ProcRRXineramaIsActive(client); @@ -442,9 +434,9 @@ SProcRRXineramaIsActive(ClientPtr client) static int SProcRRXineramaQueryScreens(ClientPtr client) { - REQUEST(xXineramaQueryScreensReq); - register int n; + int n; + REQUEST(xXineramaQueryScreensReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); return ProcRRXineramaQueryScreens(client); @@ -471,11 +463,6 @@ SProcRRXineramaDispatch(ClientPtr client) return BadRequest; } -static void -RRXineramaResetProc(ExtensionEntry * extEntry) -{ -} - void RRXineramaExtensionInit(void) { @@ -484,6 +471,9 @@ RRXineramaExtensionInit(void) return; #endif + if (noRRXineramaExtension) + return; + /* * Xinerama isn't capable enough to have multiple protocol screens each * with their own output geometry. So if there's more than one protocol @@ -494,6 +484,5 @@ RRXineramaExtensionInit(void) (void) AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0, ProcRRXineramaDispatch, - SProcRRXineramaDispatch, - RRXineramaResetProc, StandardMinorOpcode); + SProcRRXineramaDispatch, NULL, StandardMinorOpcode); } |