aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/randr
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/randr')
-rw-r--r--xorg-server/randr/Makefile.am2
-rw-r--r--xorg-server/randr/makefile2
-rw-r--r--xorg-server/randr/randr.c86
-rw-r--r--xorg-server/randr/randrstr.h135
-rw-r--r--xorg-server/randr/rrcrtc.c363
-rw-r--r--xorg-server/randr/rrdispatch.c21
-rw-r--r--xorg-server/randr/rrmode.c6
-rw-r--r--xorg-server/randr/rroutput.c23
-rw-r--r--xorg-server/randr/rrproperty.c30
-rw-r--r--xorg-server/randr/rrprovider.c411
-rw-r--r--xorg-server/randr/rrproviderproperty.c716
-rw-r--r--xorg-server/randr/rrscreen.c217
-rw-r--r--xorg-server/randr/rrxinerama.c44
13 files changed, 1933 insertions, 123 deletions
diff --git a/xorg-server/randr/Makefile.am b/xorg-server/randr/Makefile.am
index de338b972..ccaff3f02 100644
--- a/xorg-server/randr/Makefile.am
+++ b/xorg-server/randr/Makefile.am
@@ -18,6 +18,8 @@ librandr_la_SOURCES = \
rroutput.c \
rrpointer.c \
rrproperty.c \
+ rrprovider.c \
+ rrproviderproperty.c \
rrscreen.c \
rrsdispatch.c \
rrtransform.h \
diff --git a/xorg-server/randr/makefile b/xorg-server/randr/makefile
index 8dac78b7f..9f32cf77d 100644
--- a/xorg-server/randr/makefile
+++ b/xorg-server/randr/makefile
@@ -13,6 +13,8 @@ librandr_la_SOURCES = \
rroutput.c \
rrpointer.c \
rrproperty.c \
+ rrprovider.c \
+ rrproviderproperty.c \
rrscreen.c \
rrsdispatch.c \
rrtransform.h \
diff --git a/xorg-server/randr/randr.c b/xorg-server/randr/randr.c
index 103da48d7..da48c3f06 100644
--- a/xorg-server/randr/randr.c
+++ b/xorg-server/randr/randr.c
@@ -30,6 +30,7 @@
#endif
#include "randrstr.h"
+#include "extinit.h"
/* From render.h */
#ifndef SubPixelUnknown
@@ -94,6 +95,9 @@ RRCloseScreen(ScreenPtr pScreen)
for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
RROutputDestroy(pScrPriv->outputs[j]);
+ if (pScrPriv->provider)
+ RRProviderDestroy(pScrPriv->provider);
+
free(pScrPriv->crtcs);
free(pScrPriv->outputs);
free(pScrPriv);
@@ -176,6 +180,47 @@ SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent * from,
}
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
SRRNotifyEvent(xEvent *from, xEvent *to)
{
switch (from->u.u.detail) {
@@ -191,6 +236,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;
}
@@ -269,7 +325,7 @@ RRScreenInit(ScreenPtr pScreen)
wrap(pScrPriv, pScreen, CloseScreen, RRCloseScreen);
pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
-
+ pScreen->ReplaceScanoutPixmap = RRReplaceScanoutPixmap;
pScrPriv->numOutputs = 0;
pScrPriv->outputs = NULL;
pScrPriv->numCrtcs = 0;
@@ -356,7 +412,7 @@ RRExtensionInit(void)
RRModeInitErrorValue();
RRCrtcInitErrorValue();
RROutputInitErrorValue();
-
+ RRProviderInitErrorValue();
#ifdef PANORAMIX
RRXineramaExtensionInit();
#endif
@@ -412,25 +468,37 @@ TellChanged(WindowPtr pWin, pointer value)
void
RRTellChanged(ScreenPtr pScreen)
{
+ ScreenPtr master;
rrScrPriv(pScreen);
+ rrScrPrivPtr mastersp;
int i;
+ if (pScreen->isGPU) {
+ master = pScreen->current_master;
+ mastersp = rrGetScrPriv(master);
+ }
+ else {
+ master = pScreen;
+ mastersp = pScrPriv;
+ }
+
if (pScrPriv->changed) {
UpdateCurrentTimeIf();
- if (pScrPriv->configChanged) {
- pScrPriv->lastConfigTime = currentTime;
- pScrPriv->configChanged = FALSE;
+ if (mastersp->configChanged) {
+ mastersp->lastConfigTime = currentTime;
+ mastersp->configChanged = FALSE;
}
pScrPriv->changed = FALSE;
- WalkTree(pScreen, TellChanged, (pointer) pScreen);
+ mastersp->changed = FALSE;
+ WalkTree(master, TellChanged, (pointer) master);
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) {
+ if (mastersp->layoutChanged) {
pScrPriv->layoutChanged = FALSE;
- RRPointerScreenConfigured(pScreen);
- RRSendConfigNotify(pScreen);
+ RRPointerScreenConfigured(master);
+ RRSendConfigNotify(master);
}
}
}
diff --git a/xorg-server/randr/randrstr.h b/xorg-server/randr/randrstr.h
index 38fb10751..212b0a9be 100644
--- a/xorg-server/randr/randrstr.h
+++ b/xorg-server/randr/randrstr.h
@@ -62,6 +62,7 @@
typedef XID RRMode;
typedef XID RROutput;
typedef XID RRCrtc;
+typedef XID RRProvider;
extern _X_EXPORT int RREventBase, RRErrorBase;
@@ -78,6 +79,7 @@ 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;
struct _rrMode {
int refcnt;
@@ -125,6 +127,8 @@ struct _rrCrtc {
PictTransform transform;
struct pict_f_transform f_transform;
struct pict_f_transform f_inverse;
+
+ PixmapPtr scanout_pixmap;
};
struct _rrOutput {
@@ -152,6 +156,18 @@ struct _rrOutput {
void *devPrivate;
};
+struct _rrProvider {
+ RRProvider id;
+ ScreenPtr pScreen;
+ uint32_t capabilities;
+ char *name;
+ int nameLength;
+ RRPropertyPtr properties;
+ Bool pendingProperties;
+ struct _rrProvider *offload_sink;
+ struct _rrProvider *output_source;
+};
+
#if RANDR_12_INTERFACE
typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen,
CARD16 width,
@@ -197,9 +213,25 @@ typedef Bool (*RRSetPanningProcPtr) (ScreenPtr pScrn,
#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) (ScreenPtr pscreen);
+typedef Bool (*RRProviderSetOutputSourceProcPtr)(ScreenPtr pScreen,
+ RRProviderPtr provider,
+ RRProviderPtr output_source);
+
+typedef Bool (*RRProviderSetOffloadSinkProcPtr)(ScreenPtr pScreen,
+ RRProviderPtr provider,
+ RRProviderPtr offload_sink);
+
+
/* These are for 1.0 compatibility */
typedef struct _rrRefresh {
@@ -223,6 +255,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
@@ -246,7 +280,13 @@ typedef struct _rrScrPriv {
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
*/
@@ -288,6 +328,8 @@ typedef struct _rrScrPriv {
int size;
#endif
Bool discontiguous;
+
+ RRProviderPtr provider;
} rrScrPrivRec, *rrScrPrivPtr;
extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
@@ -331,7 +373,7 @@ extern _X_EXPORT RESTYPE RRClientType, RREventType; /* resource types for ev
extern _X_EXPORT DevPrivateKeyRec RRClientPrivateKeyRec;
#define RRClientPrivateKey (&RRClientPrivateKeyRec)
-extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType;
+extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType, RRProviderType;
#define VERIFY_RR_OUTPUT(id, ptr, a)\
{\
@@ -363,13 +405,19 @@ extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType;
}\
}
+#define VERIFY_RR_PROVIDER(id, ptr, a)\
+ {\
+ int rc = dixLookupResourceByType((pointer *)&(ptr), id,\
+ RRProviderType, client, a);\
+ if (rc != Success) {\
+ client->errorValue = id;\
+ return rc;\
+ }\
+ }
+
#define GetRRClient(pClient) ((RRClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RRClientPrivateKey))
#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
-/* Initialize the extension */
-extern _X_EXPORT void
- RRExtensionInit(void);
-
#ifdef RANDR_12_INTERFACE
/*
* Set the range of sizes for the screen
@@ -616,6 +664,15 @@ 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
*/
@@ -824,6 +881,74 @@ extern _X_EXPORT 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);
+
+/* 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,
+ pointer value, Bool sendevent, Bool pending);
+
+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 */
#ifdef XINERAMA
extern _X_EXPORT void
diff --git a/xorg-server/randr/rrcrtc.c b/xorg-server/randr/rrcrtc.c
index 0c596dd4c..859d19efe 100644
--- a/xorg-server/randr/rrcrtc.c
+++ b/xorg-server/randr/rrcrtc.c
@@ -239,26 +239,19 @@ RRDeliverCrtcEvent(ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
xRRCrtcChangeNotifyEvent ce;
RRModePtr mode = crtc->mode;
+
ce.type = RRNotify + RREventBase;
ce.subCode = RRNotify_CrtcChange;
ce.timestamp = pScrPriv->lastSetTime.milliseconds;
ce.window = pWin->drawable.id;
ce.crtc = crtc->id;
+ ce.mode = mode ? mode->mode.id : None;
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;
- }
+ ce.x = mode ? crtc->x : 0;
+ ce.y = mode ? crtc->y : 0;
+ ce.width = mode ? mode->mode.width : 0;
+ ce.height = mode ? mode->mode.height : 0;
+
WriteEventsToClient(client, 1, (xEvent *) &ce);
}
@@ -367,6 +360,154 @@ RRComputeContiguity(ScreenPtr pScreen)
pScrPriv->discontiguous = discontiguous;
}
+void
+RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc)
+{
+ ScreenPtr master = crtc->pScreen->current_master;
+ int ret;
+ PixmapPtr mscreenpix;
+ rrScrPriv(crtc->pScreen);
+
+ mscreenpix = master->GetScreenPixmap(master);
+
+ ret = pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL);
+ if (crtc->scanout_pixmap) {
+ master->StopPixmapTracking(mscreenpix, crtc->scanout_pixmap);
+ master->DestroyPixmap(crtc->scanout_pixmap->master_pixmap);
+ crtc->pScreen->DestroyPixmap(crtc->scanout_pixmap);
+ }
+ crtc->scanout_pixmap = NULL;
+ RRCrtcChanged(crtc, TRUE);
+}
+
+static Bool
+rrCreateSharedPixmap(RRCrtcPtr crtc, int width, int height,
+ int x, int y)
+{
+ PixmapPtr mpix, spix;
+ ScreenPtr master = crtc->pScreen->current_master;
+ Bool ret;
+ int depth;
+ PixmapPtr mscreenpix;
+ PixmapPtr protopix = crtc->pScreen->current_master->GetScreenPixmap(crtc->pScreen->current_master);
+ rrScrPriv(crtc->pScreen);
+
+ /* 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 = protopix->drawable.depth;
+
+ if (crtc->scanout_pixmap)
+ RRCrtcDetachScanoutPixmap(crtc);
+
+ if (width == 0 && height == 0) {
+ return TRUE;
+ }
+
+ mpix = master->CreatePixmap(master, width, height, depth,
+ CREATE_PIXMAP_USAGE_SHARED);
+ if (!mpix)
+ return FALSE;
+
+ spix = PixmapShareToSlave(mpix, crtc->pScreen);
+ if (spix == NULL) {
+ master->DestroyPixmap(mpix);
+ return FALSE;
+ }
+
+ ret = pScrPriv->rrCrtcSetScanoutPixmap(crtc, spix);
+ if (ret == FALSE) {
+ ErrorF("failed to set shadow slave pixmap\n");
+ return FALSE;
+ }
+
+ crtc->scanout_pixmap = spix;
+
+ master->StartPixmapTracking(mscreenpix, spix, x, y);
+ return TRUE;
+}
+
+static Bool
+rrCheckPixmapBounding(ScreenPtr pScreen,
+ RRCrtcPtr rr_crtc, int x, int y, int w, int h)
+{
+ RegionRec root_pixmap_region, total_region, new_crtc_region;
+ int i, 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++) {
+ if (pScrPriv->crtcs[c] == rr_crtc) {
+ newbox.x1 = x;
+ newbox.x2 = x + w;
+ newbox.y1 = y;
+ newbox.y2 = y + h;
+ } else {
+ if (!pScrPriv->crtcs[c]->mode)
+ continue;
+ newbox.x1 = pScrPriv->crtcs[c]->x;
+ newbox.x2 = pScrPriv->crtcs[c]->x + pScrPriv->crtcs[c]->mode->mode.width;
+ newbox.y1 = pScrPriv->crtcs[c]->y;
+ newbox.y2 = pScrPriv->crtcs[c]->y + pScrPriv->crtcs[c]->mode->mode.height;
+ }
+ 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) {
+ rrScrPriv(slave);
+ for (c = 0; c < pScrPriv->numCrtcs; c++)
+ if (pScrPriv->crtcs[c] == rr_crtc) {
+ newbox.x1 = x;
+ newbox.x2 = x + w;
+ newbox.y1 = y;
+ newbox.y2 = y + h;
+ }
+ else {
+ if (!pScrPriv->crtcs[c]->mode)
+ continue;
+ newbox.x1 = pScrPriv->crtcs[c]->x;
+ newbox.x2 = pScrPriv->crtcs[c]->x + pScrPriv->crtcs[c]->mode->mode.width;
+ newbox.y1 = pScrPriv->crtcs[c]->y;
+ newbox.y2 = pScrPriv->crtcs[c]->y + pScrPriv->crtcs[c]->mode->mode.height;
+ }
+ 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) {
+ ErrorF("adjust shatters %d %d\n", newsize->x1, newsize->x2);
+ } else {
+ int ret;
+ rrScrPriv(pScreen);
+ ret = pScrPriv->rrScreenSetSize(pScreen,
+ new_width, new_height, 0, 0);
+ }
+
+ /* set shatters TODO */
+ return TRUE;
+}
+
/*
* Request that the Crtc be reconfigured
*/
@@ -394,6 +535,26 @@ RRCrtcSet(RRCrtcPtr crtc,
ret = TRUE;
}
else {
+ if (pScreen->isGPU) {
+ ScreenPtr master = pScreen->current_master;
+ int width = 0, height = 0;
+
+ if (mode) {
+ width = mode->mode.width;
+ height = mode->mode.height;
+ }
+ ErrorF("have a master to look out for\n");
+ ret = rrCheckPixmapBounding(master, crtc,
+ x, y, width, height);
+ if (!ret)
+ return FALSE;
+
+ if (pScreen->current_master) {
+ ret = rrCreateSharedPixmap(crtc, width, height, x, y);
+ ErrorF("need to create shared pixmap %d", ret);
+
+ }
+ }
#if RANDR_12_INTERFACE
if (pScrPriv->rrCrtcSet) {
ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y,
@@ -508,6 +669,9 @@ RRCrtcDestroyResource(pointer value, XID pid)
}
}
}
+
+ if (crtc->scanout_pixmap)
+ RRCrtcDetachScanoutPixmap(crtc);
free(crtc->gammaRed);
if (crtc->mode)
RRModeDestroy(crtc->mode);
@@ -729,11 +893,13 @@ 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;
+
if (pScrPriv->rrGetPanning &&
pScrPriv->rrGetPanning(pScreen, crtc, &panned_area, NULL, NULL) &&
(panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1))
@@ -804,9 +970,9 @@ ProcRRGetCrtcInfo(ClientPtr client)
swaps(&rep.nOutput);
swaps(&rep.nPossibleOutput);
}
- WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *) &rep);
+ WriteToClient(client, sizeof(xRRGetCrtcInfoReply), &rep);
if (extraLen) {
- WriteToClient(client, extraLen, (char *) extra);
+ WriteToClient(client, extraLen, extra);
free(extra);
}
@@ -828,6 +994,7 @@ ProcRRSetCrtcConfig(ClientPtr client)
TimeStamp time;
Rotation rotation;
int ret, i, j;
+ CARD8 status;
REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq);
numOutputs = (stuff->length - bytes_to_int32(SIZEOF(xRRSetCrtcConfigReq)));
@@ -906,7 +1073,7 @@ ProcRRSetCrtcConfig(ClientPtr client)
if (!pScrPriv) {
time = currentTime;
- rep.status = RRSetConfigFailed;
+ status = RRSetConfigFailed;
goto sendReply;
}
@@ -954,6 +1121,16 @@ ProcRRSetCrtcConfig(ClientPtr client)
int source_height;
PictTransform transform;
struct pixman_f_transform f_transform, f_inverse;
+ int width, height;
+
+ if (pScreen->isGPU) {
+ width = pScreen->current_master->width;
+ height = pScreen->current_master->height;
+ }
+ else {
+ width = pScreen->width;
+ height = pScreen->height;
+ }
RRTransformCompute(stuff->x, stuff->y,
mode->mode.width, mode->mode.height,
@@ -963,13 +1140,13 @@ ProcRRSetCrtcConfig(ClientPtr client)
RRModeGetScanoutSize(mode, &transform, &source_width,
&source_height);
- if (stuff->x + source_width > pScreen->width) {
+ if (stuff->x + source_width > width) {
client->errorValue = stuff->x;
free(outputs);
return BadValue;
}
- if (stuff->y + source_height > pScreen->height) {
+ if (stuff->y + source_height > height) {
client->errorValue = stuff->y;
free(outputs);
return BadValue;
@@ -980,19 +1157,20 @@ ProcRRSetCrtcConfig(ClientPtr client)
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:
free(outputs);
+
rep.type = X_Reply;
- /* rep.status has already been filled in */
- rep.length = 0;
+ rep.status = status;
rep.sequenceNumber = client->sequence;
+ rep.length = 0;
rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
if (client->swapped) {
@@ -1000,7 +1178,7 @@ ProcRRSetCrtcConfig(ClientPtr client)
swapl(&rep.length);
swapl(&rep.newTimestamp);
}
- WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *) &rep);
+ WriteToClient(client, sizeof(xRRSetCrtcConfigReply), &rep);
return Success;
}
@@ -1069,7 +1247,7 @@ ProcRRGetPanning(ClientPtr client)
swaps(&rep.border_right);
swaps(&rep.border_bottom);
}
- WriteToClient(client, sizeof(xRRGetPanningReply), (char *) &rep);
+ WriteToClient(client, sizeof(xRRGetPanningReply), &rep);
return Success;
}
@@ -1085,6 +1263,7 @@ ProcRRSetPanning(ClientPtr client)
BoxRec total;
BoxRec tracking;
INT16 border[4];
+ CARD8 status;
REQUEST_SIZE_MATCH(xRRSetPanningReq);
VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
@@ -1097,7 +1276,7 @@ ProcRRSetPanning(ClientPtr client)
if (!pScrPriv) {
time = currentTime;
- rep.status = RRSetConfigFailed;
+ status = RRSetConfigFailed;
goto sendReply;
}
@@ -1124,10 +1303,12 @@ ProcRRSetPanning(ClientPtr client)
pScrPriv->lastSetTime = time;
- rep.status = RRSetConfigSuccess;
+ status = RRSetConfigSuccess;
sendReply:
+
rep.type = X_Reply;
+ rep.status = status;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
@@ -1137,7 +1318,7 @@ ProcRRSetPanning(ClientPtr client)
swapl(&rep.length);
swapl(&rep.newTimestamp);
}
- WriteToClient(client, sizeof(xRRSetPanningReply), (char *) &rep);
+ WriteToClient(client, sizeof(xRRSetPanningReply), &rep);
return Success;
}
@@ -1155,16 +1336,18 @@ ProcRRGetCrtcGammaSize(ClientPtr client)
if (!RRCrtcGammaGet(crtc))
return RRErrorBase + BadRRCrtc;
+
reply.type = X_Reply;
reply.sequenceNumber = client->sequence;
reply.length = 0;
reply.size = crtc->gammaSize;
+
if (client->swapped) {
swaps(&reply.sequenceNumber);
swapl(&reply.length);
swaps(&reply.size);
}
- WriteToClient(client, sizeof(xRRGetCrtcGammaSizeReply), (char *) &reply);
+ WriteToClient(client, sizeof(xRRGetCrtcGammaSizeReply), &reply);
return Success;
}
@@ -1192,16 +1375,18 @@ ProcRRGetCrtcGamma(ClientPtr client)
return BadAlloc;
}
+
reply.type = X_Reply;
reply.sequenceNumber = client->sequence;
reply.length = bytes_to_int32(len);
reply.size = crtc->gammaSize;
+
if (client->swapped) {
swaps(&reply.sequenceNumber);
swapl(&reply.length);
swaps(&reply.size);
}
- WriteToClient(client, sizeof(xRRGetCrtcGammaReply), (char *) &reply);
+ WriteToClient(client, sizeof(xRRGetCrtcGammaReply), &reply);
if (crtc->gammaSize) {
memcpy(extra, crtc->gammaRed, len);
client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
@@ -1342,7 +1527,7 @@ ProcRRGetCrtcTransform(ClientPtr client)
nextra = (transform_filter_length(pending) +
transform_filter_length(current));
- reply = malloc(sizeof(xRRGetCrtcTransformReply) + nextra);
+ reply = calloc(1, sizeof(xRRGetCrtcTransformReply) + nextra);
if (!reply)
return BadAlloc;
@@ -1367,24 +1552,15 @@ ProcRRGetCrtcTransform(ClientPtr client)
swaps(&reply->sequenceNumber);
swapl(&reply->length);
}
- WriteToClient(client, sizeof(xRRGetCrtcTransformReply) + nextra,
- (char *) reply);
+ WriteToClient(client, sizeof(xRRGetCrtcTransformReply) + nextra, reply);
free(reply);
return Success;
}
-void
-RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x,
- int *y)
+static Bool check_all_screen_crtcs(ScreenPtr pScreen, int *x, int *y)
{
rrScrPriv(pScreen);
int i;
-
- /* intentional dead space -> let it float */
- if (pScrPriv->discontiguous)
- return;
-
- /* if we're moving inside a crtc, we're fine */
for (i = 0; i < pScrPriv->numCrtcs; i++) {
RRCrtcPtr crtc = pScrPriv->crtcs[i];
@@ -1396,8 +1572,15 @@ RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x,
crtc_bounds(crtc, &left, &right, &top, &bottom);
if ((*x >= left) && (*x < right) && (*y >= top) && (*y < bottom))
- return;
+ return TRUE;
}
+ return FALSE;
+}
+
+static Bool constrain_all_screen_crtcs(DeviceIntPtr pDev, 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++) {
@@ -1421,7 +1604,101 @@ RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x,
if (*y >= bottom)
*y = bottom - 1;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void
+RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x,
+ int *y)
+{
+ rrScrPriv(pScreen);
+ Bool ret;
+ ScreenPtr slave;
+
+ /* 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;
+
+ xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) {
+ ret = check_all_screen_crtcs(slave, x, y);
+ if (ret == TRUE)
return;
+ }
+
+ /* if we're trying to escape, clamp to the CRTC we're coming from */
+ ret = constrain_all_screen_crtcs(pDev, pScreen, x, y);
+ if (ret == TRUE)
+ return;
+
+ 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;
+ }
+}
+
+Bool
+RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable)
+{
+ rrScrPriv(pDrawable->pScreen);
+ int i;
+ Bool size_fits = FALSE;
+ Bool changed = FALSE;
+ Bool ret = TRUE;
+
+ for (i = 0; i < pScrPriv->numCrtcs; i++) {
+ RRCrtcPtr crtc = pScrPriv->crtcs[i];
+
+ if (!crtc->mode && enable)
+ continue;
+
+ changed = FALSE;
+ if (crtc->mode && crtc->x == pDrawable->x &&
+ crtc->y == pDrawable->y &&
+ crtc->mode->mode.width == pDrawable->width &&
+ crtc->mode->mode.height == pDrawable->height)
+ size_fits = TRUE;
+
+ /* 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;
+ changed = TRUE;
+ } else {
+ /* if the size fits then we are already setup */
+ if (size_fits)
+ return TRUE;
+ /* if the size no longer fits then drop off */
+ crtc->scanout_pixmap = NULL;
+ changed = TRUE;
+ ret = FALSE;
+ }
+ } else {
+ if (!size_fits)
+ return FALSE;
+ if (enable) {
+ crtc->scanout_pixmap = pPixmap;
+ pScrPriv->rrCrtcSetScanoutPixmap(crtc, pPixmap);
+ changed = TRUE;
+ }
+ }
+
+ if (changed && pScrPriv->rrCrtcSet) {
+ pScrPriv->rrCrtcSetScanoutPixmap(crtc, crtc->scanout_pixmap);
+
+ (*pScrPriv->rrCrtcSet) (pDrawable->pScreen, crtc, crtc->mode, crtc->x, crtc->y,
+ crtc->rotation, crtc->numOutputs, crtc->outputs);
}
}
+ return ret;
}
diff --git a/xorg-server/randr/rrdispatch.c b/xorg-server/randr/rrdispatch.c
index 85cf03738..f9b26c137 100644
--- a/xorg-server/randr/rrdispatch.c
+++ b/xorg-server/randr/rrdispatch.c
@@ -35,16 +35,17 @@ RRClientKnowsRates(ClientPtr pClient)
static int
ProcRRQueryVersion(ClientPtr client)
{
- xRRQueryVersionReply rep = { 0 };
+ xRRQueryVersionReply rep;
REQUEST(xRRQueryVersionReq);
rrClientPriv(client);
REQUEST_SIZE_MATCH(xRRQueryVersionReq);
pRRClient->major_version = stuff->majorVersion;
pRRClient->minor_version = stuff->minorVersion;
+ memset(&rep, 0, sizeof(rep));
rep.type = X_Reply;
- rep.length = 0;
rep.sequenceNumber = client->sequence;
+ rep.length = 0;
if (version_compare(stuff->majorVersion, stuff->minorVersion,
SERVER_RANDR_MAJOR_VERSION,
@@ -63,7 +64,7 @@ ProcRRQueryVersion(ClientPtr client)
swapl(&rep.majorVersion);
swapl(&rep.minorVersion);
}
- WriteToClient(client, sizeof(xRRQueryVersionReply), (char *) &rep);
+ WriteToClient(client, sizeof(xRRQueryVersionReply), &rep);
return Success;
}
@@ -90,7 +91,8 @@ ProcRRSelectInput(ClientPtr client)
if (stuff->enable & (RRScreenChangeNotifyMask |
RRCrtcChangeNotifyMask |
RROutputChangeNotifyMask |
- RROutputPropertyNotifyMask)) {
+ RROutputPropertyNotifyMask |
+ RRProviderPropertyNotifyMask)) {
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv(pScreen);
@@ -241,4 +243,15 @@ int (*ProcRandrVector[RRNumberRequests]) (ClientPtr) = {
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 */
};
diff --git a/xorg-server/randr/rrmode.c b/xorg-server/randr/rrmode.c
index 49a45c7f6..ae1218e0e 100644
--- a/xorg-server/randr/rrmode.c
+++ b/xorg-server/randr/rrmode.c
@@ -282,7 +282,7 @@ int
ProcRRCreateMode(ClientPtr client)
{
REQUEST(xRRCreateModeReq);
- xRRCreateModeReply rep = { 0 };
+ xRRCreateModeReply rep;
WindowPtr pWin;
ScreenPtr pScreen;
xRRModeInfo *modeInfo;
@@ -310,8 +310,8 @@ ProcRRCreateMode(ClientPtr client)
if (!mode)
return error;
+ memset(&rep, 0, sizeof(rep));
rep.type = X_Reply;
- rep.pad0 = 0;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.mode = mode->mode.id;
@@ -320,7 +320,7 @@ ProcRRCreateMode(ClientPtr client)
swapl(&rep.length);
swapl(&rep.mode);
}
- WriteToClient(client, sizeof(xRRCreateModeReply), (char *) &rep);
+ WriteToClient(client, sizeof(xRRCreateModeReply), &rep);
/* Drop out reference to this mode */
RRModeDestroy(mode);
return Success;
diff --git a/xorg-server/randr/rroutput.c b/xorg-server/randr/rroutput.c
index fbd0e32b3..1eb071b4e 100644
--- a/xorg-server/randr/rroutput.c
+++ b/xorg-server/randr/rroutput.c
@@ -307,7 +307,8 @@ RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
rrScrPriv(pScreen);
xRROutputChangeNotifyEvent oe;
RRCrtcPtr crtc = output->crtc;
- RRModePtr mode = crtc ? crtc->mode : 0;
+ RRModePtr mode = crtc ? crtc->mode : NULL;
+
oe.type = RRNotify + RREventBase;
oe.subCode = RRNotify_OutputChange;
@@ -315,18 +316,12 @@ RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
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.crtc = crtc ? crtc->id : None;
+ oe.mode = mode ? mode->mode.id : None;
+ oe.rotation = crtc ? crtc->rotation : RR_Rotate_0;
oe.connection = output->connection;
oe.subpixelOrder = output->subpixelOrder;
+
WriteEventsToClient(client, 1, (xEvent *) &oe);
}
@@ -425,7 +420,9 @@ ProcRRGetOutputInfo(ClientPtr client)
pScreen = output->pScreen;
pScrPriv = rrGetScrPriv(pScreen);
+
rep.type = X_Reply;
+ rep.status = RRSetConfigSuccess;
rep.sequenceNumber = client->sequence;
rep.length = bytes_to_int32(OutputInfoExtra);
rep.timestamp = pScrPriv->lastSetTime.milliseconds;
@@ -489,9 +486,9 @@ ProcRRGetOutputInfo(ClientPtr client)
swaps(&rep.nClones);
swaps(&rep.nameLength);
}
- WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *) &rep);
+ WriteToClient(client, sizeof(xRRGetOutputInfoReply), &rep);
if (extraLen) {
- WriteToClient(client, extraLen, (char *) extra);
+ WriteToClient(client, extraLen, extra);
free(extra);
}
diff --git a/xorg-server/randr/rrproperty.c b/xorg-server/randr/rrproperty.c
index 75948fccb..dc4a9f7a3 100644
--- a/xorg-server/randr/rrproperty.c
+++ b/xorg-server/randr/rrproperty.c
@@ -66,7 +66,6 @@ static void
RRDeleteProperty(RROutputRec * output, RRPropertyRec * prop)
{
xRROutputPropertyNotifyEvent event;
-
event.type = RREventBase + RRNotify;
event.subCode = RRNotify_OutputProperty;
event.output = output->id;
@@ -138,7 +137,6 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type,
pointer value, Bool sendevent, Bool pending)
{
RRPropertyPtr prop;
- xRROutputPropertyNotifyEvent event;
rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen);
int size_in_bytes;
int total_size;
@@ -237,6 +235,7 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type,
output->pendingProperties = TRUE;
if (sendevent) {
+ xRROutputPropertyNotifyEvent event;
event.type = RREventBase + RRNotify;
event.subCode = RRNotify_OutputProperty;
event.output = output->id;
@@ -378,7 +377,7 @@ int
ProcRRListOutputProperties(ClientPtr client)
{
REQUEST(xRRListOutputPropertiesReq);
- Atom *pAtoms = NULL, *temppAtoms;
+ Atom *pAtoms = NULL;
xRRListOutputPropertiesReply rep;
int numProps = 0;
RROutputPtr output;
@@ -394,21 +393,25 @@ ProcRRListOutputProperties(ClientPtr client)
if (!(pAtoms = (Atom *) malloc(numProps * sizeof(Atom))))
return BadAlloc;
+
rep.type = X_Reply;
- rep.length = bytes_to_int32(numProps * sizeof(Atom));
rep.sequenceNumber = client->sequence;
+ rep.length = bytes_to_int32(numProps * sizeof(Atom));
rep.nAtoms = numProps;
+
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swaps(&rep.nAtoms);
}
- temppAtoms = pAtoms;
- for (prop = output->properties; prop; prop = prop->next)
- *temppAtoms++ = prop->propertyName;
+ WriteToClient(client, sizeof(xRRListOutputPropertiesReply), &rep);
- 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);
free(pAtoms);
@@ -438,17 +441,20 @@ ProcRRQueryOutputProperty(ClientPtr client)
if (!extra)
return BadAlloc;
}
+
+
rep.type = X_Reply;
- rep.length = prop->num_valid;
rep.sequenceNumber = client->sequence;
+ rep.length = prop->num_valid;
rep.pending = prop->is_pending;
rep.range = prop->range;
rep.immutable = prop->immutable;
+
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
}
- WriteToClient(client, sizeof(xRRQueryOutputPropertyReply), (char *) &rep);
+ WriteToClient(client, sizeof(xRRQueryOutputPropertyReply), &rep);
if (prop->num_valid) {
memcpy(extra, prop->valid_values, prop->num_valid * sizeof(INT32));
client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
@@ -594,8 +600,10 @@ ProcRRGetOutputProperty(ClientPtr client)
if (prop->propertyName == stuff->property)
break;
+
reply.type = X_Reply;
reply.sequenceNumber = client->sequence;
+
if (!prop) {
reply.nItems = 0;
reply.length = 0;
@@ -673,13 +681,13 @@ ProcRRGetOutputProperty(ClientPtr client)
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;
+
RRDeliverPropertyEvent(output->pScreen, (xEvent *) &event);
}
diff --git a/xorg-server/randr/rrprovider.c b/xorg-server/randr/rrprovider.c
new file mode 100644
index 000000000..c4fe36980
--- /dev/null
+++ b/xorg-server/randr/rrprovider.c
@@ -0,0 +1,411 @@
+/*
+ * 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)
+{
+ SetResourceTypeErrorValue(RRProviderType, RRErrorBase + BadRRProvider);
+}
+
+#define ADD_PROVIDER(_pScreen) do { \
+ pScrPriv = rrGetScrPriv((_pScreen)); \
+ if (pScrPriv->provider) { \
+ providers[count_providers] = pScrPriv->provider->id; \
+ if (client->swapped) \
+ swapl(&providers[count_providers]); \
+ 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;
+ ScreenPtr iter;
+
+ REQUEST_SIZE_MATCH(xRRGetProvidersReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ pScreen = pWin->drawable.pScreen;
+
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ if (pScrPriv->provider)
+ total_providers++;
+ 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;
+ }
+
+ pScrPriv = rrGetScrPriv(pScreen);
+ rep.pad = 0;
+
+ if (!pScrPriv)
+ {
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.timestamp = currentTime.milliseconds;
+ rep.nProviders = 0;
+ extra = NULL;
+ extraLen = 0;
+ } else {
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+ rep.nProviders = total_providers;
+ rep.length = total_providers;
+ extraLen = rep.length << 2;
+ if (extraLen) {
+ extra = malloc(extraLen);
+ if (!extra)
+ return BadAlloc;
+ } else
+ extra = NULL;
+
+ providers = (RRProvider *)extra;
+ ADD_PROVIDER(pScreen);
+ 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);
+ }
+ }
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.timestamp);
+ swaps(&rep.nProviders);
+ }
+ WriteToClient(client, sizeof(xRRGetProvidersReply), (char *)&rep);
+ if (extraLen)
+ {
+ WriteToClient (client, extraLen, (char *) extra);
+ free(extra);
+ }
+ return Success;
+}
+
+int
+ProcRRGetProviderInfo (ClientPtr client)
+{
+ REQUEST(xRRGetProviderInfoReq);
+ xRRGetProviderInfoReply rep;
+ rrScrPrivPtr pScrPriv, pScrProvPriv;
+ RRProviderPtr provider;
+ ScreenPtr pScreen;
+ CARD8 *extra;
+ unsigned int extraLen = 0;
+ RRCrtc *crtcs;
+ RROutput *outputs;
+ int i;
+ char *name;
+ ScreenPtr provscreen;
+ RRProvider *providers;
+ uint32_t *prov_cap;
+
+ REQUEST_SIZE_MATCH(xRRGetProviderInfoReq);
+ VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
+
+ pScreen = provider->pScreen;
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ rep.type = X_Reply;
+ rep.status = RRSetConfigSuccess;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.capabilities = provider->capabilities;
+ rep.nameLength = provider->nameLength;
+ rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+ rep.nCrtcs = pScrPriv->numCrtcs;
+ rep.nOutputs = pScrPriv->numOutputs;
+
+ /* count associated providers */
+ rep.nAssociatedProviders = 0;
+ if (provider->offload_sink)
+ rep.nAssociatedProviders++;
+ if (provider->output_source)
+ rep.nAssociatedProviders++;
+ 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++;
+
+ rep.length = (pScrPriv->numCrtcs + pScrPriv->numOutputs +
+ (rep.nAssociatedProviders * 2) + bytes_to_int32(rep.nameLength));
+
+ extraLen = rep.length << 2;
+ if (extraLen) {
+ extra = malloc(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]);
+ }
+
+ for (i = 0; i < pScrPriv->numOutputs; i++) {
+ outputs[i] = pScrPriv->outputs[i]->id;
+ if (client->swapped)
+ swapl(&outputs[i]);
+ }
+
+ i = 0;
+ if (provider->offload_sink) {
+ providers[i] = provider->offload_sink->id;
+ if (client->swapped)
+ swapl(&providers[i]);
+ prov_cap[i] = RR_Capability_SinkOffload;
+ if (client->swapped)
+ swapl(&prov_cap[i]);
+ i++;
+ }
+ if (provider->output_source) {
+ providers[i] = provider->output_source->id;
+ if (client->swapped)
+ swapl(&providers[i]);
+ prov_cap[i] = RR_Capability_SourceOutput;
+ swapl(&prov_cap[i]);
+ i++;
+ }
+ 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++;
+ }
+
+
+ memcpy(name, provider->name, rep.nameLength);
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.capabilities);
+ swaps(&rep.nCrtcs);
+ swaps(&rep.nOutputs);
+ swaps(&rep.nameLength);
+ }
+ WriteToClient(client, sizeof(xRRGetProviderInfoReply), (char *)&rep);
+ if (extraLen)
+ {
+ WriteToClient (client, extraLen, (char *) extra);
+ free(extra);
+ }
+ return Success;
+}
+
+int
+ProcRRSetProviderOutputSource(ClientPtr client)
+{
+ REQUEST(xRRSetProviderOutputSourceReq);
+ rrScrPrivPtr pScrPriv;
+ RRProviderPtr provider, source_provider = NULL;
+ ScreenPtr pScreen;
+
+ REQUEST_AT_LEAST_SIZE(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);
+
+ RRTellChanged (pScreen);
+
+ return Success;
+}
+
+int
+ProcRRSetProviderOffloadSink(ClientPtr client)
+{
+ REQUEST(xRRSetProviderOffloadSinkReq);
+ rrScrPrivPtr pScrPriv;
+ RRProviderPtr provider, sink_provider = NULL;
+ ScreenPtr pScreen;
+
+ REQUEST_AT_LEAST_SIZE(xRRSetProviderOffloadSinkReq);
+
+ VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
+ if (!(provider->capabilities & RR_Capability_SourceOffload))
+ return BadValue;
+
+ 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);
+
+ RRTellChanged (pScreen);
+
+ return Success;
+}
+
+RRProviderPtr
+RRProviderCreate(ScreenPtr pScreen, const char *name,
+ int nameLength)
+{
+ RRProviderPtr provider;
+ rrScrPrivPtr pScrPriv;
+
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ provider = calloc(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';
+
+ if (!AddResource (provider->id, RRProviderType, (pointer) 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 (pointer value, XID pid)
+{
+ RRProviderPtr provider = (RRProviderPtr)value;
+ ScreenPtr pScreen = provider->pScreen;
+
+ if (pScreen)
+ {
+ rrScrPriv(pScreen);
+
+ pScrPriv->provider = NULL;
+ }
+ free(provider);
+ return 1;
+}
+
+Bool
+RRProviderInit(void)
+{
+ RRProviderType = CreateNewResourceType(RRProviderDestroyResource, "Provider");
+ if (!RRProviderType)
+ return FALSE;
+
+ return TRUE;
+}
+
+extern _X_EXPORT Bool
+RRProviderLookup(XID id, RRProviderPtr *provider_p)
+{
+ int rc = dixLookupResourceByType((void **)provider_p, id,
+ RRProviderType, NullClient, DixReadAccess);
+ if (rc == Success)
+ return TRUE;
+ return FALSE;
+}
diff --git a/xorg-server/randr/rrproviderproperty.c b/xorg-server/randr/rrproviderproperty.c
new file mode 100644
index 000000000..5e04fab8f
--- /dev/null
+++ b/xorg-server/randr/rrproviderproperty.c
@@ -0,0 +1,716 @@
+/*
+ * 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;
+
+ dixLookupResourceByType((pointer *) &pHead, pWin->drawable.id,
+ RREventType, serverClient, DixReadAccess);
+ 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)
+{
+ free(prop->valid_values);
+ free(prop->current.data);
+ free(prop->pending.data);
+ free(prop);
+}
+
+static void
+RRDeleteProperty(RRProviderRec * provider, RRPropertyRec * prop)
+{
+ xRRProviderPropertyNotifyEvent event;
+
+ event.type = RREventBase + RRNotify;
+ event.subCode = RRNotify_ProviderProperty;
+ event.provider = provider->id;
+ event.state = PropertyDelete;
+ event.atom = prop->propertyName;
+ event.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) malloc(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,
+ pointer value, Bool sendevent, Bool pending)
+{
+ RRPropertyPtr prop;
+ xRRProviderPropertyNotifyEvent event;
+ 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) {
+ pointer new_data = NULL, old_data = NULL;
+
+ total_size = total_len * size_in_bytes;
+ new_value.data = (pointer) malloc(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 = (pointer) (((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 = (pointer) (((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)) {
+ free(new_value.data);
+ return BadValue;
+ }
+ free(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) {
+ event.type = RREventBase + RRNotify;
+ event.subCode = RRNotify_ProviderProperty;
+ event.provider = provider->id;
+ event.state = PropertyNewValue;
+ event.atom = prop->propertyName;
+ event.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))
+ return BadMatch;
+
+ new_values = malloc(num_values * sizeof(INT32));
+ if (!new_values && num_values)
+ 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) {
+ free(prop->pending.data);
+ RRInitProviderPropertyValue(&prop->pending);
+ }
+
+ prop->is_pending = pending;
+ prop->range = range;
+ prop->immutable = immutable;
+ prop->num_valid = num_values;
+ free(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;
+
+ REQUEST_SIZE_MATCH(xRRListProviderPropertiesReq);
+
+ VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
+
+ for (prop = provider->properties; prop; prop = prop->next)
+ numProps++;
+ if (numProps)
+ if (!(pAtoms = (Atom *) malloc(numProps * sizeof(Atom))))
+ return BadAlloc;
+
+ rep.type = X_Reply;
+ rep.length = bytes_to_int32(numProps * sizeof(Atom));
+ rep.sequenceNumber = client->sequence;
+ rep.nAtoms = numProps;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swaps(&rep.nAtoms);
+ }
+ 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);
+ free(pAtoms);
+ }
+ return Success;
+}
+
+int
+ProcRRQueryProviderProperty(ClientPtr client)
+{
+ REQUEST(xRRQueryProviderPropertyReq);
+ xRRQueryProviderPropertyReply rep;
+ RRProviderPtr provider;
+ RRPropertyPtr prop;
+ char *extra = NULL;
+
+ REQUEST_SIZE_MATCH(xRRQueryProviderPropertyReq);
+
+ VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
+
+ prop = RRQueryProviderProperty(provider, stuff->property);
+ if (!prop)
+ return BadName;
+
+ if (prop->num_valid) {
+ extra = malloc(prop->num_valid * sizeof(INT32));
+ 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) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ }
+ 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);
+ free(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, (pointer) &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;
+ 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;
+
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ if (!prop) {
+ reply.nItems = 0;
+ reply.length = 0;
+ reply.bytesAfter = 0;
+ reply.propertyType = None;
+ reply.format = 0;
+ if (client->swapped) {
+ swaps(&reply.sequenceNumber);
+ swapl(&reply.length);
+ swapl(&reply.propertyType);
+ swapl(&reply.bytesAfter);
+ swapl(&reply.nItems);
+ }
+ WriteToClient(client, sizeof(xRRGetProviderPropertyReply), &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);
+ swapl(&reply.length);
+ swapl(&reply.propertyType);
+ swapl(&reply.bytesAfter);
+ swapl(&reply.nItems);
+ }
+ WriteToClient(client, sizeof(xRRGetProviderPropertyReply), &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 = malloc(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;
+
+ event.type = RREventBase + RRNotify;
+ event.subCode = RRNotify_ProviderProperty;
+ event.provider = provider->id;
+ event.state = PropertyDelete;
+ event.atom = prop->propertyName;
+ event.timestamp = currentTime.milliseconds;
+ RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event);
+ }
+
+ if (client->swapped) {
+ swaps(&reply.sequenceNumber);
+ swapl(&reply.length);
+ swapl(&reply.propertyType);
+ swapl(&reply.bytesAfter);
+ swapl(&reply.nItems);
+ }
+ WriteToClient(client, sizeof(xGenericReply), &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);
+ free(extra);
+ }
+
+ if (stuff->delete && (reply.bytesAfter == 0)) { /* delete the Property */
+ *prev = prop->next;
+ RRDestroyProviderProperty(prop);
+ }
+ return Success;
+}
diff --git a/xorg-server/randr/rrscreen.c b/xorg-server/randr/rrscreen.c
index c564d1f96..8d562108a 100644
--- a/xorg-server/randr/rrscreen.c
+++ b/xorg-server/randr/rrscreen.c
@@ -22,8 +22,6 @@
#include "randrstr.h"
-static const int padlength[4] = { 0, 3, 2, 1 };
-
static CARD16
RR10CurrentSizeID(ScreenPtr pScreen);
@@ -46,8 +44,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);
@@ -72,8 +69,6 @@ RRSendConfigNotify(ScreenPtr pScreen)
{
WindowPtr pWin = pScreen->root;
xEvent event;
-
- event.u.u.type = ConfigureNotify;
event.u.configureNotify.window = pWin->drawable.id;
event.u.configureNotify.aboveSibling = None;
event.u.configureNotify.x = 0;
@@ -85,6 +80,7 @@ RRSendConfigNotify(ScreenPtr pScreen)
event.u.configureNotify.height = pWin->drawable.height;
event.u.configureNotify.borderWidth = wBorderWidth(pWin);
event.u.configureNotify.override = pWin->overrideRedirect;
+ event.u.u.type = ConfigureNotify;
DeliverEvents(pWin, &event, 1, NullWindow);
}
@@ -96,6 +92,7 @@ RRDeliverScreenEvent(ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
RRCrtcPtr crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL;
WindowPtr pRoot = pScreen->root;
+
se.type = RRScreenChangeNotify + RREventBase;
se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0);
se.timestamp = pScrPriv->lastSetTime.milliseconds;
@@ -106,6 +103,7 @@ RRDeliverScreenEvent(ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
se.sizeID = RR10CurrentSizeID(pScreen);
+
if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) {
se.widthInPixels = pScreen->height;
se.heightInPixels = pScreen->width;
@@ -203,6 +201,7 @@ ProcRRGetScreenSizeRange(ClientPtr client)
pScreen = pWin->drawable.pScreen;
pScrPriv = rrGetScrPriv(pScreen);
+
rep.type = X_Reply;
rep.pad = 0;
rep.sequenceNumber = client->sequence;
@@ -228,7 +227,7 @@ ProcRRGetScreenSizeRange(ClientPtr client)
swaps(&rep.maxWidth);
swaps(&rep.maxHeight);
}
- WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), (char *) &rep);
+ WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), &rep);
return Success;
}
@@ -292,6 +291,172 @@ ProcRRSetScreenSize(ClientPtr client)
return Success;
}
+
+#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; \
+ free(modes); \
+} while(0)
+
+static inline void swap_modeinfos(xRRModeInfo *modeinfos, int i)
+{
+ swapl(&modeinfos[i].id);
+ swaps(&modeinfos[i].width);
+ swaps(&modeinfos[i].height);
+ swapl(&modeinfos[i].dotClock);
+ swaps(&modeinfos[i].hSyncStart);
+ swaps(&modeinfos[i].hSyncEnd);
+ swaps(&modeinfos[i].hTotal);
+ swaps(&modeinfos[i].hSkew);
+ swaps(&modeinfos[i].vSyncStart);
+ swaps(&modeinfos[i].vSyncEnd);
+ swaps(&modeinfos[i].vTotal);
+ swaps(&modeinfos[i].nameLength);
+ swapl(&modeinfos[i].modeFlags);
+}
+
+#define update_arrays(gpuscreen, pScrPriv) do { \
+ for (j = 0; j < pScrPriv->numCrtcs; j++) { \
+ crtcs[crtc_count] = pScrPriv->crtcs[j]->id; \
+ if (client->swapped) \
+ swapl(&crtcs[crtc_count]); \
+ crtc_count++; \
+ } \
+ for (j = 0; j < pScrPriv->numOutputs; j++) { \
+ outputs[output_count] = pScrPriv->outputs[j]->id; \
+ if (client->swapped) \
+ swapl(&outputs[output_count]); \
+ 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++; \
+ } \
+ free(modes); \
+ } \
+ } while (0)
+
+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;
+ RROutput *outputs;
+ xRRModeInfo *modeinfos;
+ CARD8 *names;
+
+ /* 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);
+ }
+
+ ErrorF("reporting %d %d %d %d\n", total_crtcs, total_outputs, total_modes, total_name_len);
+
+ pScrPriv = rrGetScrPriv(pScreen);
+ rep.pad = 0;
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+ rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
+ rep.nCrtcs = total_crtcs;
+ rep.nOutputs = total_outputs;
+ rep.nModes = total_modes;
+ rep.nbytesNames = total_name_len;
+
+ rep.length = (total_crtcs + total_outputs + total_modes * bytes_to_int32(SIZEOF(xRRModeInfo)) +
+ bytes_to_int32(rep.nbytesNames));
+
+ extraLen = rep.length << 2;
+ if (extraLen) {
+ extra = malloc(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);
+
+ /* TODO primary */
+ crtc_count = 0;
+ output_count = 0;
+ mode_count = 0;
+
+ pScrPriv = rrGetScrPriv(pScreen);
+ update_arrays(pScreen, pScrPriv);
+
+ xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
+ pScrPriv = rrGetScrPriv(iter);
+
+ update_arrays(iter, pScrPriv);
+ }
+
+ assert(bytes_to_int32((char *) names - (char *) extra) == rep.length);
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.timestamp);
+ swapl(&rep.configTimestamp);
+ swaps(&rep.nCrtcs);
+ swaps(&rep.nOutputs);
+ swaps(&rep.nModes);
+ swaps(&rep.nbytesNames);
+ }
+ WriteToClient(client, sizeof(xRRGetScreenResourcesReply), &rep);
+ if (extraLen) {
+ WriteToClient(client, extraLen, extra);
+ free(extra);
+ }
+ return Success;
+}
+
static int
rrGetScreenResources(ClientPtr client, Bool query)
{
@@ -321,7 +486,11 @@ rrGetScreenResources(ClientPtr client, Bool query)
if (!RRGetInfo(pScreen, query))
return BadAlloc;
+ if (!xorg_list_is_empty(&pScreen->output_slave_list))
+ return rrGetMultiScreenResources(client, query, pScreen);
+
if (!pScrPriv) {
+
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
@@ -331,6 +500,7 @@ rrGetScreenResources(ClientPtr client, Bool query)
rep.nOutputs = 0;
rep.nModes = 0;
rep.nbytesNames = 0;
+
extra = NULL;
extraLen = 0;
}
@@ -342,6 +512,7 @@ rrGetScreenResources(ClientPtr client, Bool query)
if (!modes)
return BadAlloc;
+
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
@@ -352,6 +523,7 @@ rrGetScreenResources(ClientPtr client, Bool query)
rep.nModes = num_modes;
rep.nbytesNames = 0;
+
for (i = 0; i < num_modes; i++)
rep.nbytesNames += modes[i]->mode.nameLength;
@@ -584,6 +756,7 @@ ProcRRGetScreenInfo(ClientPtr client)
output = RRFirstOutput(pScreen);
if (!pScrPriv || !output) {
+
rep.type = X_Reply;
rep.setOfRotations = RR_Rotate_0;
rep.sequenceNumber = client->sequence;
@@ -596,6 +769,7 @@ ProcRRGetScreenInfo(ClientPtr client)
rep.rotation = RR_Rotate_0;
rep.rate = 0;
rep.nrateEnts = 0;
+
extra = 0;
extraLen = 0;
}
@@ -612,6 +786,7 @@ ProcRRGetScreenInfo(ClientPtr client)
if (!pData)
return BadAlloc;
+
rep.type = X_Reply;
rep.setOfRotations = output->crtc->rotations;
rep.sequenceNumber = client->sequence;
@@ -685,15 +860,16 @@ ProcRRGetScreenInfo(ClientPtr client)
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.timestamp);
+ swapl(&rep.configTimestamp);
swaps(&rep.rotation);
swaps(&rep.nSizes);
swaps(&rep.sizeID);
swaps(&rep.rate);
swaps(&rep.nrateEnts);
}
- WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *) &rep);
+ WriteToClient(client, sizeof(xRRGetScreenInfoReply), &rep);
if (extraLen) {
- WriteToClient(client, extraLen, (char *) extra);
+ WriteToClient(client, extraLen, extra);
free(extra);
}
return Success;
@@ -713,6 +889,7 @@ ProcRRSetScreenConfig(ClientPtr client)
Rotation rotation;
int rate;
Bool has_rate;
+ CARD8 status;
RROutputPtr output;
RRCrtcPtr crtc;
RRModePtr mode;
@@ -743,7 +920,7 @@ ProcRRSetScreenConfig(ClientPtr client)
if (!pScrPriv) {
time = currentTime;
- rep.status = RRSetConfigFailed;
+ status = RRSetConfigFailed;
goto sendReply;
}
if (!RRGetInfo(pScreen, FALSE))
@@ -752,7 +929,7 @@ ProcRRSetScreenConfig(ClientPtr client)
output = RRFirstOutput(pScreen);
if (!output) {
time = currentTime;
- rep.status = RRSetConfigFailed;
+ status = RRSetConfigFailed;
goto sendReply;
}
@@ -768,7 +945,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;
}
@@ -847,7 +1024,7 @@ ProcRRSetScreenConfig(ClientPtr client)
* the last set-time
*/
if (CompareTimeStamps(time, pScrPriv->lastSetTime) < 0) {
- rep.status = RRSetConfigInvalidTime;
+ status = RRSetConfigInvalidTime;
goto sendReply;
}
@@ -879,24 +1056,24 @@ ProcRRSetScreenConfig(ClientPtr client)
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;
}
/*
@@ -907,8 +1084,9 @@ ProcRRSetScreenConfig(ClientPtr client)
free(pData);
+
rep.type = X_Reply;
- /* rep.status has already been filled in */
+ rep.status = status;
rep.length = 0;
rep.sequenceNumber = client->sequence;
@@ -916,6 +1094,7 @@ ProcRRSetScreenConfig(ClientPtr client)
rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.root = pDraw->pScreen->root->drawable.id;
+
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
@@ -923,7 +1102,7 @@ ProcRRSetScreenConfig(ClientPtr client)
swapl(&rep.newConfigTimestamp);
swapl(&rep.root);
}
- WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *) &rep);
+ WriteToClient(client, sizeof(xRRSetScreenConfigReply), &rep);
return Success;
}
diff --git a/xorg-server/randr/rrxinerama.c b/xorg-server/randr/rrxinerama.c
index aa8a61eee..63e2a318b 100644
--- a/xorg-server/randr/rrxinerama.c
+++ b/xorg-server/randr/rrxinerama.c
@@ -93,8 +93,8 @@ ProcRRXineramaQueryVersion(ClientPtr client)
REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
rep.type = X_Reply;
- rep.length = 0;
rep.sequenceNumber = client->sequence;
+ rep.length = 0;
rep.majorVersion = SERVER_RRXINERAMA_MAJOR_VERSION;
rep.minorVersion = SERVER_RRXINERAMA_MINOR_VERSION;
if (client->swapped) {
@@ -103,7 +103,7 @@ ProcRRXineramaQueryVersion(ClientPtr client)
swaps(&rep.majorVersion);
swaps(&rep.minorVersion);
}
- WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *) &rep);
+ WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), &rep);
return Success;
}
@@ -130,17 +130,19 @@ ProcRRXineramaGetState(ClientPtr client)
active = TRUE;
}
+
rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
rep.state = active;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
rep.window = stuff->window;
+
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.window);
}
- WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *) &rep);
+ WriteToClient(client, sizeof(xPanoramiXGetStateReply), &rep);
return Success;
}
@@ -184,17 +186,19 @@ 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.sequenceNumber = client->sequence;
+ rep.length = 0;
rep.window = stuff->window;
+
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.window);
}
- WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *) &rep);
+ WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), &rep);
return Success;
}
@@ -215,13 +219,15 @@ ProcRRXineramaGetScreenSize(ClientPtr client)
pScreen = pWin->drawable.pScreen;
pRoot = pScreen->root;
+
rep.type = X_Reply;
- rep.length = 0;
rep.sequenceNumber = client->sequence;
+ rep.length = 0;
rep.width = pRoot->drawable.width;
rep.height = pRoot->drawable.height;
rep.window = stuff->window;
rep.screen = stuff->screen;
+
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
@@ -230,7 +236,7 @@ ProcRRXineramaGetScreenSize(ClientPtr client)
swapl(&rep.window);
swapl(&rep.screen);
}
- WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *) &rep);
+ WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), &rep);
return Success;
}
@@ -246,12 +252,13 @@ ProcRRXineramaIsActive(ClientPtr client)
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.state = RRXineramaScreenActive(screenInfo.screens[RR_XINERAMA_SCREEN]);
+
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.state);
}
- WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep);
+ WriteToClient(client, sizeof(xXineramaIsActiveReply), &rep);
return Success;
}
@@ -299,24 +306,29 @@ ProcRRXineramaQueryScreens(ClientPtr client)
{
xXineramaQueryScreensReply rep;
ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN];
+ int n = 0;
REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
- if (RRXineramaScreenActive(pScreen))
+ if (RRXineramaScreenActive(pScreen)) {
RRGetInfo(pScreen, FALSE);
+ n = RRXineramaScreenCount(pScreen);
+ }
+
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
- rep.number = RRXineramaScreenCount(pScreen);
- rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo);
+ rep.length = bytes_to_int32(n * sz_XineramaScreenInfo);
+ rep.number = n;
+
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.number);
}
- WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *) &rep);
+ WriteToClient(client, sizeof(xXineramaQueryScreensReply), &rep);
- if (rep.number) {
+ if (n) {
rrScrPriv(pScreen);
int i;
int has_primary = 0;