Commit c2b1f489 authored by Mike Gabriel's avatar Mike Gabriel

Backport RANDR proto version 1.5 to nx-X11's Xserver.

Backported to X.org's /xorg/xserver Git hash level: a6b6e8ba026acedef6336b17adf06aebddd5f22f.
parent 2e5b9898
......@@ -35,6 +35,32 @@ static int nxagentRandRScreenSetSize(ScreenPtr pScreen, CARD16 width,
static int nxagentRandRInitSizes(ScreenPtr pScreen);
#if RANDR_14_INTERFACE
static Bool
nxagentRandRReplaceScanoutPixmap(DrawablePtr pDrawable,
PixmapPtr pPixmap,
Bool enable);
#endif
#if RANDR_13_INTERFACE
static Bool
nxagentRandROutputGetProperty(ScreenPtr pScreen,
RROutputPtr output,
Atom property);
static Bool
nxagentRandRGetPanning(ScreenPtr pScrn,
RRCrtcPtr crtc,
BoxPtr totalArea,
BoxPtr trackingArea,
INT16 *border);
static Bool
nxagentRandRSetPanning(ScreenPtr pScrn,
RRCrtcPtr crtc,
BoxPtr totalArea,
BoxPtr trackingArea,
INT16 *border);
#endif
#if RANDR_12_INTERFACE
static Bool nxagentRandRCrtcSet (ScreenPtr pScreen, RRCrtcPtr crtc,
RRModePtr mode, int x, int y,
......@@ -104,6 +130,29 @@ void nxagentInitRandRExtension(ScreenPtr pScreen)
pRandRScrPriv -> rrGetInfo = nxagentRandRGetInfo;
#if RANDR_15_INTERFACE
/* nothing to be assigned here, so far */
#endif
#if RANDR_14_INTERFACE
/* no pixmap sharing in nx-X11 */
pScreen->ReplaceScanoutPixmap = nxagentRandRReplaceScanoutPixmap;
pRandRScrPriv -> rrCrtcSetScanoutPixmap = NULL;
/* only fake provider support in nx-X11, so far */
pRandRScrPriv -> provider = RRProviderCreate(pScreen, "default", 7);
pRandRScrPriv -> rrProviderSetOutputSource = NULL;
pRandRScrPriv -> rrProviderSetOffloadSink;
pRandRScrPriv -> rrProviderGetProperty;
pRandRScrPriv -> rrProviderSetProperty;
#endif
#if RANDR_13_INTERFACE
pRandRScrPriv -> rrOutputGetProperty = nxagentRandROutputGetProperty;
pRandRScrPriv -> rrGetPanning = nxagentRandRGetPanning;
pRandRScrPriv -> rrSetPanning = nxagentRandRSetPanning;
#endif
#if RANDR_12_INTERFACE
pRandRScrPriv -> rrScreenSetSize = nxagentRandRScreenSetSize;
pRandRScrPriv -> rrCrtcSet = nxagentRandRCrtcSet;
......@@ -114,13 +163,70 @@ void nxagentInitRandRExtension(ScreenPtr pScreen)
#endif
}
void
RRResetProc (ExtensionEntry *extEntry)
#if RANDR_14_INTERFACE
static Bool
nxagentRandRReplaceScanoutPixmap(DrawablePtr pDrawable,
PixmapPtr pPixmap,
Bool enable)
{
/* FALSE means: not supported */
#ifdef DEBUG
fprintf(stderr, "nxagentRandRReplaceScanoutPixmap: NX's RANDR does not support scan-out pixmaps.\n");
#endif
return FALSE;
}
#endif
#if RANDR_13_INTERFACE
static Bool
nxagentRandROutputGetProperty(ScreenPtr pScreen,
RROutputPtr output,
Atom property)
{
fprintf(stderr, "RANDR going down - NX version\n");
/* FALSE means: no property required to be modified on the fly here */
return FALSE;
}
static Bool
nxagentRandRGetPanning(ScreenPtr pScrn,
RRCrtcPtr crtc,
BoxPtr totalArea,
BoxPtr trackingArea,
INT16 *border)
{
/* FALSE means: no, panning is not supported at the moment...
* Panning requires several modes to be available for
* the NX<n> output(s).
*
* FIXME: Add more modes per output than the current window size.
* At least when in fullscreen mode.
*/
#ifdef DEBUG
fprintf(stderr, "nxagentRandRGetPanning: RANDR Panning is currently not supported.\n");
#endif
return FALSE;
}
static Bool
nxagentRandRSetPanning(ScreenPtr pScrn,
RRCrtcPtr crtc,
BoxPtr totalArea,
BoxPtr trackingArea,
INT16 *border)
{
/* FALSE means: no, panning is not supported at the moment...
* Panning requires several modes to be available for
* the NX<n> output(s).
*
* FIXME: Add more modes per output than the current window size.
* At least when in fullscreen mode.
*/
#ifdef DEBUG
fprintf(stderr, "nxagentRandRSetPanning: RANDR Panning is currently not supported.\n");
#endif
return FALSE;
}
#endif
#if RANDR_12_INTERFACE
/*
......@@ -137,7 +243,7 @@ nxagentRandRCrtcSet (ScreenPtr pScreen,
int numOutputs,
RROutputPtr *outputs)
{
return RRCrtcNotify(crtc, mode, x, y, rotation, numOutputs, outputs);
return RRCrtcNotify(crtc, mode, x, y, rotation, NULL, numOutputs, outputs);
}
#endif
......
......@@ -209,8 +209,11 @@ DEFINES = -g $(OS_DEFINES) $(EXT_DEFINES) $(NX_DEFINES) \
-DNXAGENT_ARTSD \
-DNXAGENT_RANDR_MODE_PREFIX \
-UNX_DEBUG_INPUT \
-DRANDR_10_INTERFACE \
-DRANDR_12_INTERFACE \
-DRANDR_10_INTERFACE=1 \
-DRANDR_12_INTERFACE=1 \
-DRANDR_13_INTERFACE=1 \
-DRANDR_14_INTERFACE=1 \
-DRANDR_15_INTERFACE=1 \
-DPANORAMIX \
-UDEBUG_TREE
......
......@@ -3793,7 +3793,7 @@ int nxagentAdjustRandRXinerama(ScreenPtr pScreen)
* do this here it will be done implicitely later and add mode(s) to
* our crtc(s)!
*/
rrgetinfo = RRGetInfo(pScreen);
rrgetinfo = RRGetInfo(pScreen, FALSE);
fprintf(stderr, "nxagentAdjustRandRXinerama: RRGetInfo returned [%d]\n", rrgetinfo);
}
......
......@@ -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()
......
......@@ -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);
}
......@@ -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_ */
......@@ -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_ */
......@@ -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_ */
......
/*
* 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, &current->transform);
extra += transform_filter_encode(client, extra,
&reply->currentNbytesFilter,
&reply->currentNparamsFilter, current);
if (client->swapped) {
swaps(&reply->sequenceNumber, n);
swapl(&reply->length, n);
}
WriteToClient(client, sizeof(xRRGetCrtcTransformReply) + nextra,
(char *) reply);
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;
}
......@@ -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 */
};
......@@ -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++];
......
......@@ -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);
}
/*
* 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;
}
/*
* 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;
}
......@@ -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 */
}
}
......@@ -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;
}
/*
* 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);
}
/*
* 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;
}
......@@ -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
......
......@@ -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 */
};
/*
* 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;
}
}
/*
* 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_ */
......@@ -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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment