summaryrefslogtreecommitdiff
path: root/xserver/randr
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2016-05-29 12:02:41 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2016-05-29 12:02:41 +0000
commit4a991716ac65d28a68f9943d54c4b74ad0b58f65 (patch)
treec037c3fe64bb15ea67dbf03a96783a8b04085371 /xserver/randr
parent549cb8bcb6bdd3a7d44f3b9fdc003df777b2b0d2 (diff)
Update to xserver 1.18.3. Tested by shadchin@ and naddy@.
Note that indirect GLX is now disbled by default.
Diffstat (limited to 'xserver/randr')
-rw-r--r--xserver/randr/Makefile.am1
-rw-r--r--xserver/randr/Makefile.in24
-rw-r--r--xserver/randr/randr.c4
-rw-r--r--xserver/randr/randrstr.h63
-rw-r--r--xserver/randr/rrcrtc.c94
-rw-r--r--xserver/randr/rrdispatch.c3
-rw-r--r--xserver/randr/rrinfo.c10
-rw-r--r--xserver/randr/rrmode.c4
-rw-r--r--xserver/randr/rrmonitor.c754
-rw-r--r--xserver/randr/rroutput.c48
-rw-r--r--xserver/randr/rrproperty.c12
-rw-r--r--xserver/randr/rrproviderproperty.c6
-rw-r--r--xserver/randr/rrscreen.c5
-rw-r--r--xserver/randr/rrsdispatch.c38
-rw-r--r--xserver/randr/rrtransform.c10
-rw-r--r--xserver/randr/rrxinerama.c123
16 files changed, 1016 insertions, 183 deletions
diff --git a/xserver/randr/Makefile.am b/xserver/randr/Makefile.am
index ccaff3f02..90dc9ec9a 100644
--- a/xserver/randr/Makefile.am
+++ b/xserver/randr/Makefile.am
@@ -15,6 +15,7 @@ librandr_la_SOURCES = \
rrdispatch.c \
rrinfo.c \
rrmode.c \
+ rrmonitor.c \
rroutput.c \
rrpointer.c \
rrproperty.c \
diff --git a/xserver/randr/Makefile.in b/xserver/randr/Makefile.in
index 6526f10e3..f356475ab 100644
--- a/xserver/randr/Makefile.in
+++ b/xserver/randr/Makefile.in
@@ -59,8 +59,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ac_define_dir.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
- $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/xorg-tls.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -77,14 +76,15 @@ CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
librandr_la_LIBADD =
am__librandr_la_SOURCES_DIST = randr.c randrstr.h rrcrtc.c \
- rrdispatch.c rrinfo.c rrmode.c rroutput.c rrpointer.c \
- rrproperty.c rrprovider.c rrproviderproperty.c rrscreen.c \
- rrsdispatch.c rrtransform.h rrtransform.c rrxinerama.c
+ rrdispatch.c rrinfo.c rrmode.c rrmonitor.c rroutput.c \
+ rrpointer.c rrproperty.c rrprovider.c rrproviderproperty.c \
+ rrscreen.c rrsdispatch.c rrtransform.h rrtransform.c \
+ rrxinerama.c
am__objects_1 = rrxinerama.lo
@XINERAMA_TRUE@am__objects_2 = $(am__objects_1)
am_librandr_la_OBJECTS = randr.lo rrcrtc.lo rrdispatch.lo rrinfo.lo \
- rrmode.lo rroutput.lo rrpointer.lo rrproperty.lo rrprovider.lo \
- rrproviderproperty.lo rrscreen.lo rrsdispatch.lo \
+ rrmode.lo rrmonitor.lo rroutput.lo rrpointer.lo rrproperty.lo \
+ rrprovider.lo rrproviderproperty.lo rrscreen.lo rrsdispatch.lo \
rrtransform.lo $(am__objects_2)
librandr_la_OBJECTS = $(am_librandr_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
@@ -256,7 +256,6 @@ GLAMOR_LIBS = @GLAMOR_LIBS@
GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@
GLX_DEFINES = @GLX_DEFINES@
GLX_SYS_LIBS = @GLX_SYS_LIBS@
-GLX_TLS = @GLX_TLS@
GL_CFLAGS = @GL_CFLAGS@
GL_LIBS = @GL_LIBS@
GREP = @GREP@
@@ -386,8 +385,6 @@ XEPHYR_INCS = @XEPHYR_INCS@
XEPHYR_LIBS = @XEPHYR_LIBS@
XF86CONFIGDIR = @XF86CONFIGDIR@
XF86CONFIGFILE = @XF86CONFIGFILE@
-XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@
-XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@
XKB_BASE_DIRECTORY = @XKB_BASE_DIRECTORY@
XKB_BIN_DIRECTORY = @XKB_BIN_DIRECTORY@
XKB_COMPILED_DIR = @XKB_COMPILED_DIR@
@@ -516,9 +513,9 @@ AM_CFLAGS = $(DIX_CFLAGS)
XINERAMA_SRCS = rrxinerama.c
@XORG_TRUE@sdk_HEADERS = randrstr.h rrtransform.h
librandr_la_SOURCES = randr.c randrstr.h rrcrtc.c rrdispatch.c \
- rrinfo.c rrmode.c rroutput.c rrpointer.c rrproperty.c \
- rrprovider.c rrproviderproperty.c rrscreen.c rrsdispatch.c \
- rrtransform.h rrtransform.c $(am__append_1)
+ rrinfo.c rrmode.c rrmonitor.c rroutput.c rrpointer.c \
+ rrproperty.c rrprovider.c rrproviderproperty.c rrscreen.c \
+ rrsdispatch.c rrtransform.h rrtransform.c $(am__append_1)
all: all-am
.SUFFIXES:
@@ -578,6 +575,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdispatch.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrinfo.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrmode.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrmonitor.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rroutput.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrpointer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrproperty.Plo@am__quote@
diff --git a/xserver/randr/randr.c b/xserver/randr/randr.c
index 6e3f14b4e..ad1dda227 100644
--- a/xserver/randr/randr.c
+++ b/xserver/randr/randr.c
@@ -98,6 +98,8 @@ RRCloseScreen(ScreenPtr pScreen)
if (pScrPriv->provider)
RRProviderDestroy(pScrPriv->provider);
+ RRMonitorClose(pScreen);
+
free(pScrPriv->crtcs);
free(pScrPriv->outputs);
free(pScrPriv);
@@ -333,6 +335,8 @@ RRScreenInit(ScreenPtr pScreen)
pScrPriv->numCrtcs = 0;
pScrPriv->crtcs = NULL;
+ RRMonitorInit(pScreen);
+
RRNScreens += 1; /* keep count of screens that implement randr */
return TRUE;
}
diff --git a/xserver/randr/randrstr.h b/xserver/randr/randrstr.h
index 13e6a8596..472721a5a 100644
--- a/xserver/randr/randrstr.h
+++ b/xserver/randr/randrstr.h
@@ -64,10 +64,10 @@ typedef XID RROutput;
typedef XID RRCrtc;
typedef XID RRProvider;
-extern _X_EXPORT int RREventBase, RRErrorBase;
+extern int RREventBase, RRErrorBase;
-extern _X_EXPORT int (*ProcRandrVector[RRNumberRequests]) (ClientPtr);
-extern _X_EXPORT int (*SProcRandrVector[RRNumberRequests]) (ClientPtr);
+extern int (*ProcRandrVector[RRNumberRequests]) (ClientPtr);
+extern int (*SProcRandrVector[RRNumberRequests]) (ClientPtr);
/*
* Modeline for a monitor. Name follows directly after this struct
@@ -80,6 +80,7 @@ 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;
@@ -169,6 +170,22 @@ struct _rrProvider {
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,
@@ -338,6 +355,9 @@ typedef struct _rrScrPriv {
RRProviderDestroyProcPtr rrProviderDestroy;
+ int numMonitors;
+ RRMonitorPtr *monitors;
+
} rrScrPrivRec, *rrScrPrivPtr;
extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
@@ -377,8 +397,8 @@ typedef struct _RRClient {
/* RRTimesRec times[0]; */
} RRClientRec, *RRClientPtr;
-extern _X_EXPORT RESTYPE RRClientType, RREventType; /* resource types for event masks */
-extern _X_EXPORT DevPrivateKeyRec RRClientPrivateKeyRec;
+extern RESTYPE RRClientType, RREventType; /* resource types for event masks */
+extern DevPrivateKeyRec RRClientPrivateKeyRec;
#define RRClientPrivateKey (&RRClientPrivateKeyRec)
extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType, RRProviderType;
@@ -981,6 +1001,39 @@ extern _X_EXPORT void
RRXineramaExtensionInit(void);
#endif
+void
+RRMonitorInit(ScreenPtr screen);
+
+Bool
+RRMonitorMakeList(ScreenPtr screen, Bool get_active, RRMonitorPtr *monitors_ret, int *nmon_ret);
+
+int
+RRMonitorCountList(ScreenPtr screen);
+
+void
+RRMonitorFreeList(RRMonitorPtr monitors, int nmon);
+
+void
+RRMonitorClose(ScreenPtr screen);
+
+RRMonitorPtr
+RRMonitorAlloc(int noutput);
+
+int
+RRMonitorAdd(ClientPtr client, ScreenPtr screen, RRMonitorPtr monitor);
+
+void
+RRMonitorFree(RRMonitorPtr monitor);
+
+int
+ProcRRGetMonitors(ClientPtr client);
+
+int
+ProcRRSetMonitor(ClientPtr client);
+
+int
+ProcRRDeleteMonitor(ClientPtr client);
+
#endif /* _RANDRSTR_H_ */
/*
diff --git a/xserver/randr/rrcrtc.c b/xserver/randr/rrcrtc.c
index 349874514..9bc456bdc 100644
--- a/xserver/randr/rrcrtc.c
+++ b/xserver/randr/rrcrtc.c
@@ -65,8 +65,8 @@ RRCrtcCreate(ScreenPtr pScreen, void *devPrivate)
/* make space for the crtc pointer */
if (pScrPriv->numCrtcs)
- crtcs = realloc(pScrPriv->crtcs,
- (pScrPriv->numCrtcs + 1) * sizeof(RRCrtcPtr));
+ crtcs = reallocarray(pScrPriv->crtcs,
+ pScrPriv->numCrtcs + 1, sizeof(RRCrtcPtr));
else
crtcs = malloc(sizeof(RRCrtcPtr));
if (!crtcs)
@@ -176,10 +176,10 @@ RRCrtcNotify(RRCrtcPtr crtc,
if (numOutputs) {
if (crtc->numOutputs)
- newoutputs = realloc(crtc->outputs,
- numOutputs * sizeof(RROutputPtr));
+ newoutputs = reallocarray(crtc->outputs,
+ numOutputs, sizeof(RROutputPtr));
else
- newoutputs = malloc(numOutputs * sizeof(RROutputPtr));
+ newoutputs = xallocarray(numOutputs, sizeof(RROutputPtr));
if (!newoutputs)
return FALSE;
}
@@ -387,14 +387,14 @@ RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc)
static Bool
rrCreateSharedPixmap(RRCrtcPtr crtc, int width, int height,
- int x, int y)
+ int x, int y, Rotation rotation)
{
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);
+ PixmapPtr protopix = master->GetScreenPixmap(master);
rrScrPriv(crtc->pScreen);
/* create a pixmap on the master screen,
@@ -434,13 +434,33 @@ rrCreateSharedPixmap(RRCrtcPtr crtc, int width, int height,
crtc->scanout_pixmap = spix;
- master->StartPixmapTracking(mscreenpix, spix, x, y);
+ 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, int x, int y, int w, int h)
+ RRCrtcPtr rr_crtc, Rotation rotation,
+ int x, int y, int w, int h)
{
RegionRec root_pixmap_region, total_region, new_crtc_region;
int c;
@@ -457,18 +477,23 @@ rrCheckPixmapBounding(ScreenPtr pScreen,
/* 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) {
+ RRCrtcPtr crtc = pScrPriv->crtcs[c];
+
+ if (crtc == rr_crtc) {
newbox.x1 = x;
- newbox.x2 = x + w;
newbox.y1 = y;
- newbox.y2 = y + h;
+ 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 (!pScrPriv->crtcs[c]->mode)
+ if (!crtc->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;
+ crtc_to_box(&newbox, crtc);
}
RegionInit(&new_crtc_region, &newbox, 1);
RegionUnion(&total_region, &total_region, &new_crtc_region);
@@ -477,19 +502,24 @@ rrCheckPixmapBounding(ScreenPtr pScreen,
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++) {
- if (slave_priv->crtcs[c] == rr_crtc) {
+ RRCrtcPtr slave_crtc = slave_priv->crtcs[c];
+
+ if (slave_crtc == rr_crtc) {
newbox.x1 = x;
- newbox.x2 = x + w;
newbox.y1 = y;
- newbox.y2 = y + h;
+ 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_priv->crtcs[c]->mode)
+ if (!slave_crtc->mode)
continue;
- newbox.x1 = slave_priv->crtcs[c]->x;
- newbox.x2 = slave_priv->crtcs[c]->x + slave_priv->crtcs[c]->mode->mode.width;
- newbox.y1 = slave_priv->crtcs[c]->y;
- newbox.y2 = slave_priv->crtcs[c]->y + slave_priv->crtcs[c]->mode->mode.height;
+ crtc_to_box(&newbox, slave_crtc);
}
RegionInit(&new_crtc_region, &newbox, 1);
RegionUnion(&total_region, &total_region, &new_crtc_region);
@@ -557,12 +587,12 @@ RRCrtcSet(RRCrtcPtr crtc,
height = mode->mode.height;
}
ret = rrCheckPixmapBounding(master, crtc,
- x, y, width, height);
+ rotation, x, y, width, height);
if (!ret)
return FALSE;
if (pScreen->current_master) {
- ret = rrCreateSharedPixmap(crtc, width, height, x, y);
+ ret = rrCreateSharedPixmap(crtc, width, height, x, y, rotation);
}
}
#if RANDR_12_INTERFACE
@@ -794,7 +824,7 @@ RRCrtcGammaSetSize(RRCrtcPtr crtc, int size)
if (size == crtc->gammaSize)
return TRUE;
if (size) {
- gamma = malloc(size * 3 * sizeof(CARD16));
+ gamma = xallocarray(size, 3 * sizeof(CARD16));
if (!gamma)
return FALSE;
}
@@ -1023,7 +1053,7 @@ ProcRRSetCrtcConfig(ClientPtr client)
return BadMatch;
}
if (numOutputs) {
- outputs = malloc(numOutputs * sizeof(RROutputPtr));
+ outputs = xallocarray(numOutputs, sizeof(RROutputPtr));
if (!outputs)
return BadAlloc;
}
@@ -1571,7 +1601,8 @@ ProcRRGetCrtcTransform(ClientPtr client)
return Success;
}
-static Bool check_all_screen_crtcs(ScreenPtr pScreen, int *x, int *y)
+static Bool
+check_all_screen_crtcs(ScreenPtr pScreen, int *x, int *y)
{
rrScrPriv(pScreen);
int i;
@@ -1591,7 +1622,8 @@ static Bool check_all_screen_crtcs(ScreenPtr pScreen, int *x, int *y)
return FALSE;
}
-static Bool constrain_all_screen_crtcs(DeviceIntPtr pDev, ScreenPtr pScreen, int *x, int *y)
+static Bool
+constrain_all_screen_crtcs(DeviceIntPtr pDev, ScreenPtr pScreen, int *x, int *y)
{
rrScrPriv(pScreen);
int i;
diff --git a/xserver/randr/rrdispatch.c b/xserver/randr/rrdispatch.c
index 7fee2bf9c..314e4ea52 100644
--- a/xserver/randr/rrdispatch.c
+++ b/xserver/randr/rrdispatch.c
@@ -256,4 +256,7 @@ int (*ProcRandrVector[RRNumberRequests]) (ClientPtr) = {
ProcRRChangeProviderProperty, /* 39 */
ProcRRDeleteProviderProperty, /* 40 */
ProcRRGetProviderProperty, /* 41 */
+ ProcRRGetMonitors, /* 42 */
+ ProcRRSetMonitor, /* 43 */
+ ProcRRDeleteMonitor, /* 44 */
};
diff --git a/xserver/randr/rrinfo.c b/xserver/randr/rrinfo.c
index fc57bd408..24245b7b6 100644
--- a/xserver/randr/rrinfo.c
+++ b/xserver/randr/rrinfo.c
@@ -55,8 +55,8 @@ RROldModeAdd(RROutputPtr output, RRScreenSizePtr size, int refresh)
}
if (output->numModes)
- modes = realloc(output->modes,
- (output->numModes + 1) * sizeof(RRModePtr));
+ modes = reallocarray(output->modes,
+ output->numModes + 1, sizeof(RRModePtr));
else
modes = malloc(sizeof(RRModePtr));
if (!modes) {
@@ -266,8 +266,8 @@ RRRegisterSize(ScreenPtr pScreen,
for (i = 0; i < pScrPriv->nSizes; i++)
if (RRScreenSizeMatches(&tmp, &pScrPriv->pSizes[i]))
return &pScrPriv->pSizes[i];
- pNew = realloc(pScrPriv->pSizes,
- (pScrPriv->nSizes + 1) * sizeof(RRScreenSize));
+ pNew = reallocarray(pScrPriv->pSizes,
+ pScrPriv->nSizes + 1, sizeof(RRScreenSize));
if (!pNew)
return 0;
pNew[pScrPriv->nSizes++] = tmp;
@@ -289,7 +289,7 @@ RRRegisterRate(ScreenPtr pScreen, RRScreenSizePtr pSize, int rate)
if (pSize->pRates[i].rate == rate)
return TRUE;
- pNew = realloc(pSize->pRates, (pSize->nRates + 1) * sizeof(RRScreenRate));
+ pNew = reallocarray(pSize->pRates, pSize->nRates + 1, sizeof(RRScreenRate));
if (!pNew)
return FALSE;
pRate = &pNew[pSize->nRates++];
diff --git a/xserver/randr/rrmode.c b/xserver/randr/rrmode.c
index befac4741..a7aa43320 100644
--- a/xserver/randr/rrmode.c
+++ b/xserver/randr/rrmode.c
@@ -79,7 +79,7 @@ RRModeCreate(xRRModeInfo * modeInfo, const char *name, ScreenPtr userScreen)
mode->userScreen = userScreen;
if (num_modes)
- newModes = realloc(modes, (num_modes + 1) * sizeof(RRModePtr));
+ newModes = reallocarray(modes, num_modes + 1, sizeof(RRModePtr));
else
newModes = malloc(sizeof(RRModePtr));
@@ -166,7 +166,7 @@ RRModesForScreen(ScreenPtr pScreen, int *num_ret)
RRModePtr *screen_modes;
int num_screen_modes = 0;
- screen_modes = malloc((num_modes ? num_modes : 1) * sizeof(RRModePtr));
+ screen_modes = xallocarray((num_modes ? num_modes : 1), sizeof(RRModePtr));
if (!screen_modes)
return NULL;
diff --git a/xserver/randr/rrmonitor.c b/xserver/randr/rrmonitor.c
new file mode 100644
index 000000000..ba310eaa4
--- /dev/null
+++ b/xserver/randr/rrmonitor.c
@@ -0,0 +1,754 @@
+/*
+ * 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"
+
+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 = calloc(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 = calloc(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;
+ ScreenPtr slave;
+
+ if (!RRGetInfo(screen, FALSE))
+ return FALSE;
+
+ /* Count the number of crtcs in this and any slave screens */
+ numCrtcs = pScrPriv->numCrtcs;
+ xorg_list_for_each_entry(slave, &screen->output_slave_list, output_head) {
+ rrScrPrivPtr pSlavePriv;
+ pSlavePriv = rrGetScrPriv(slave);
+ numCrtcs += pSlavePriv->numCrtcs;
+ }
+ mon_list->num_crtcs = numCrtcs;
+
+ mon_list->server_crtc = calloc(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];
+ }
+
+ 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];
+ }
+ }
+
+ /* 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)
+{
+ free(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 = calloc(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)
+{
+ free(monitor);
+}
+
+RRMonitorPtr
+RRMonitorAlloc(int noutput)
+{
+ RRMonitorPtr monitor;
+
+ monitor = calloc(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;
+ ScreenPtr slave;
+ 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;
+ }
+
+ xorg_list_for_each_entry(slave, &screen->output_slave_list, output_head) {
+ if (RRMonitorMatchesOutputName(slave, monitor->name)) {
+ client->errorValue = monitor->name;
+ return BadValue;
+ }
+ }
+
+ /* '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)
+ monitors = reallocarray(pScrPriv->monitors,
+ pScrPriv->numMonitors + 1,
+ sizeof (RRMonitorPtr));
+ else
+ monitors = malloc(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++)
+ free(monitors[m].outputs);
+ free(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]);
+ free(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;
+ Bool get_active;
+ REQUEST_SIZE_MATCH(xRRGetMonitorsReq);
+ r = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.timestamp);
+ swapl(&rep.nmonitors);
+ swapl(&rep.noutputs);
+ }
+ WriteToClient(client, sizeof(xRRGetMonitorsReply), &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);
+ swaps(&info.noutput);
+ swaps(&info.x);
+ swaps(&info.y);
+ swaps(&info.width);
+ swaps(&info.height);
+ swapl(&info.widthInMillimeters);
+ swapl(&info.heightInMillimeters);
+ }
+
+ WriteToClient(client, sizeof(xRRMonitorInfo), &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;
+
+ r = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
+ 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);
+ r = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
+ if (r != Success)
+ return r;
+ screen = window->drawable.pScreen;
+
+ if (!ValidAtom(stuff->name)) {
+ client->errorValue = stuff->name;
+ return BadAtom;
+ }
+
+ r = RRMonitorDelete(client, screen, stuff->name);
+ if (r == Success)
+ RRSendConfigNotify(screen);
+ return r;
+}
diff --git a/xserver/randr/rroutput.c b/xserver/randr/rroutput.c
index 548e07d1d..686ae49a6 100644
--- a/xserver/randr/rroutput.c
+++ b/xserver/randr/rroutput.c
@@ -31,15 +31,27 @@ 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);
- RRSetChanged(pScreen);
- if (configChanged)
- pScrPriv->configChanged = TRUE;
+ if (!pScreen)
+ return;
+
+ if (pScreen->isGPU) {
+ ScreenPtr master = pScreen->current_master;
+ if (!master)
+ return;
+ mastersp = rrGetScrPriv(master);
+ }
+ else {
+ mastersp = rrGetScrPriv(pScreen);
}
+
+ RRSetChanged(pScreen);
+ if (configChanged)
+ mastersp->configChanged = TRUE;
}
/*
@@ -60,8 +72,8 @@ RROutputCreate(ScreenPtr pScreen,
pScrPriv = rrGetScrPriv(pScreen);
if (pScrPriv->numOutputs)
- outputs = realloc(pScrPriv->outputs,
- (pScrPriv->numOutputs + 1) * sizeof(RROutputPtr));
+ outputs = reallocarray(pScrPriv->outputs,
+ pScrPriv->numOutputs + 1, sizeof(RROutputPtr));
else
outputs = malloc(sizeof(RROutputPtr));
if (!outputs)
@@ -124,7 +136,7 @@ RROutputSetClones(RROutputPtr output, RROutputPtr * clones, int numClones)
return TRUE;
}
if (numClones) {
- newClones = malloc(numClones * sizeof(RROutputPtr));
+ newClones = xallocarray(numClones, sizeof(RROutputPtr));
if (!newClones)
return FALSE;
}
@@ -157,7 +169,7 @@ RROutputSetModes(RROutputPtr output,
}
if (numModes) {
- newModes = malloc(numModes * sizeof(RRModePtr));
+ newModes = xallocarray(numModes, sizeof(RRModePtr));
if (!newModes)
return FALSE;
}
@@ -200,8 +212,8 @@ RROutputAddUserMode(RROutputPtr output, RRModePtr mode)
return BadMatch;
if (output->userModes)
- newModes = realloc(output->userModes,
- (output->numUserModes + 1) * sizeof(RRModePtr));
+ newModes = reallocarray(output->userModes,
+ output->numUserModes + 1, sizeof(RRModePtr));
else
newModes = malloc(sizeof(RRModePtr));
if (!newModes)
@@ -256,7 +268,7 @@ RROutputSetCrtcs(RROutputPtr output, RRCrtcPtr * crtcs, int numCrtcs)
return TRUE;
}
if (numCrtcs) {
- newCrtcs = malloc(numCrtcs * sizeof(RRCrtcPtr));
+ newCrtcs = xallocarray(numCrtcs, sizeof(RRCrtcPtr));
if (!newCrtcs)
return FALSE;
}
@@ -531,6 +543,7 @@ ProcRRSetOutputPrimary(ClientPtr client)
WindowPtr pWin;
rrScrPrivPtr pScrPriv;
int ret;
+ ScreenPtr slave;
REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq);
@@ -553,8 +566,19 @@ ProcRRSetOutputPrimary(ClientPtr client)
pScrPriv = rrGetScrPriv(pWin->drawable.pScreen);
if (pScrPriv)
+ {
RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output);
+ xorg_list_for_each_entry(slave,
+ &pWin->drawable.pScreen->output_slave_list,
+ output_head) {
+ rrScrPrivPtr pSlavePriv;
+ pSlavePriv = rrGetScrPriv(slave);
+
+ RRSetPrimaryOutput(slave, pSlavePriv, output);
+ }
+ }
+
return Success;
}
diff --git a/xserver/randr/rrproperty.c b/xserver/randr/rrproperty.c
index e385e15ab..e56626cd2 100644
--- a/xserver/randr/rrproperty.c
+++ b/xserver/randr/rrproperty.c
@@ -140,7 +140,6 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type,
RRPropertyPtr prop;
rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen);
int size_in_bytes;
- int total_size;
unsigned long total_len;
RRPropertyValuePtr prop_value;
RRPropertyValueRec new_value;
@@ -180,9 +179,8 @@ 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 *) malloc(total_size);
- if (!new_value.data && total_size) {
+ new_value.data = xallocarray(total_len, size_in_bytes);
+ if (!new_value.data && total_len && size_in_bytes) {
if (add)
RRDestroyOutputProperty(prop);
return BadAlloc;
@@ -350,7 +348,7 @@ RRConfigureOutputProperty(RROutputPtr output, Atom property,
return BadMatch;
}
- new_values = malloc(num_values * sizeof(INT32));
+ new_values = xallocarray(num_values, sizeof(INT32));
if (!new_values && num_values) {
if (add)
RRDestroyOutputProperty(prop);
@@ -400,7 +398,7 @@ ProcRRListOutputProperties(ClientPtr client)
for (prop = output->properties; prop; prop = prop->next)
numProps++;
if (numProps)
- if (!(pAtoms = (Atom *) malloc(numProps * sizeof(Atom))))
+ if (!(pAtoms = xallocarray(numProps, sizeof(Atom))))
return BadAlloc;
rep = (xRRListOutputPropertiesReply) {
@@ -447,7 +445,7 @@ ProcRRQueryOutputProperty(ClientPtr client)
return BadName;
if (prop->num_valid) {
- extra = malloc(prop->num_valid * sizeof(INT32));
+ extra = xallocarray(prop->num_valid, sizeof(INT32));
if (!extra)
return BadAlloc;
}
diff --git a/xserver/randr/rrproviderproperty.c b/xserver/randr/rrproviderproperty.c
index ff2c614d0..b79c17f9b 100644
--- a/xserver/randr/rrproviderproperty.c
+++ b/xserver/randr/rrproviderproperty.c
@@ -350,7 +350,7 @@ RRConfigureProviderProperty(RRProviderPtr provider, Atom property,
return BadMatch;
}
- new_values = malloc(num_values * sizeof(INT32));
+ new_values = xallocarray(num_values, sizeof(INT32));
if (!new_values && num_values) {
if (add)
RRDestroyProviderProperty(prop);
@@ -400,7 +400,7 @@ ProcRRListProviderProperties(ClientPtr client)
for (prop = provider->properties; prop; prop = prop->next)
numProps++;
if (numProps)
- if (!(pAtoms = (Atom *) malloc(numProps * sizeof(Atom))))
+ if (!(pAtoms = xallocarray(numProps, sizeof(Atom))))
return BadAlloc;
rep = (xRRListProviderPropertiesReply) {
@@ -445,7 +445,7 @@ ProcRRQueryProviderProperty(ClientPtr client)
return BadName;
if (prop->num_valid) {
- extra = malloc(prop->num_valid * sizeof(INT32));
+ extra = xallocarray(prop->num_valid, sizeof(INT32));
if (!extra)
return BadAlloc;
}
diff --git a/xserver/randr/rrscreen.c b/xserver/randr/rrscreen.c
index c2a7798e1..d0ca91e0e 100644
--- a/xserver/randr/rrscreen.c
+++ b/xserver/randr/rrscreen.c
@@ -413,8 +413,9 @@ rrGetMultiScreenResources(ClientPtr client, Bool query, ScreenPtr pScreen)
.nbytesNames = total_name_len
};
- rep.length = (total_crtcs + total_outputs + total_modes * bytes_to_int32(SIZEOF(xRRModeInfo)) +
- bytes_to_int32(rep.nbytesNames));
+ 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) {
diff --git a/xserver/randr/rrsdispatch.c b/xserver/randr/rrsdispatch.c
index 47558cf75..cf2a3b024 100644
--- a/xserver/randr/rrsdispatch.c
+++ b/xserver/randr/rrsdispatch.c
@@ -565,6 +565,41 @@ static int SProcRRGetProviderProperty(ClientPtr client)
return ProcRandrVector[stuff->randrReqType] (client);
}
+static int SProcRRGetMonitors(ClientPtr client) {
+ REQUEST(xRRGetMonitorsReq);
+
+ REQUEST_SIZE_MATCH(xRRGetMonitorsReq);
+ swaps(&stuff->length);
+ swapl(&stuff->window);
+ return ProcRandrVector[stuff->randrReqType] (client);
+}
+
+static int SProcRRSetMonitor(ClientPtr client) {
+ REQUEST(xRRSetMonitorReq);
+
+ REQUEST_AT_LEAST_SIZE(xRRGetMonitorsReq);
+ swaps(&stuff->length);
+ swapl(&stuff->window);
+ swapl(&stuff->monitor.name);
+ swaps(&stuff->monitor.noutput);
+ swaps(&stuff->monitor.x);
+ swaps(&stuff->monitor.y);
+ swaps(&stuff->monitor.width);
+ swaps(&stuff->monitor.height);
+ SwapRestL(stuff);
+ return ProcRandrVector[stuff->randrReqType] (client);
+}
+
+static int SProcRRDeleteMonitor(ClientPtr client) {
+ REQUEST(xRRDeleteMonitorReq);
+
+ REQUEST_SIZE_MATCH(xRRDeleteMonitorReq);
+ swaps(&stuff->length);
+ swapl(&stuff->window);
+ swapl(&stuff->name);
+ return ProcRandrVector[stuff->randrReqType] (client);
+}
+
int (*SProcRandrVector[RRNumberRequests]) (ClientPtr) = {
SProcRRQueryVersion, /* 0 */
/* we skip 1 to make old clients fail pretty immediately */
@@ -614,4 +649,7 @@ int (*SProcRandrVector[RRNumberRequests]) (ClientPtr) = {
SProcRRChangeProviderProperty, /* 39 */
SProcRRDeleteProviderProperty, /* 40 */
SProcRRGetProviderProperty, /* 41 */
+ SProcRRGetMonitors, /* 42 */
+ SProcRRSetMonitor, /* 43 */
+ SProcRRDeleteMonitor, /* 44 */
};
diff --git a/xserver/randr/rrtransform.c b/xserver/randr/rrtransform.c
index f3f1b1e65..d32b43aa3 100644
--- a/xserver/randr/rrtransform.c
+++ b/xserver/randr/rrtransform.c
@@ -70,7 +70,7 @@ RRTransformSetFilter(RRTransformPtr dst,
xFixed *new_params;
if (nparams) {
- new_params = malloc(nparams * sizeof(xFixed));
+ new_params = xallocarray(nparams, sizeof(xFixed));
if (!new_params)
return FALSE;
memcpy(new_params, params, nparams * sizeof(xFixed));
@@ -196,7 +196,7 @@ RRTransformCompute(int x,
f_rot_sin = 0;
f_rot_dx = width;
f_rot_dy = height;
- rot_cos = F(-1);
+ rot_cos = F(~0u);
rot_sin = F(0);
rot_dx = F(width);
rot_dy = F(height);
@@ -207,7 +207,7 @@ RRTransformCompute(int x,
f_rot_dx = 0;
f_rot_dy = width;
rot_cos = F(0);
- rot_sin = F(-1);
+ rot_sin = F(~0u);
rot_dx = F(0);
rot_dy = F(width);
break;
@@ -230,7 +230,7 @@ RRTransformCompute(int x,
scale_dy = 0;
if (rotation & RR_Reflect_X) {
f_scale_x = -1;
- scale_x = F(-1);
+ scale_x = F(~0u);
if (rotation & (RR_Rotate_0 | RR_Rotate_180)) {
f_scale_dx = width;
scale_dx = F(width);
@@ -242,7 +242,7 @@ RRTransformCompute(int x,
}
if (rotation & RR_Reflect_Y) {
f_scale_y = -1;
- scale_y = F(-1);
+ scale_y = F(~0u);
if (rotation & (RR_Rotate_0 | RR_Rotate_180)) {
f_scale_dy = height;
scale_dy = F(height);
diff --git a/xserver/randr/rrxinerama.c b/xserver/randr/rrxinerama.c
index b336bd7cd..b6e9586d7 100644
--- a/xserver/randr/rrxinerama.c
+++ b/xserver/randr/rrxinerama.c
@@ -84,6 +84,8 @@ static int ProcRRXineramaIsActive(ClientPtr client);
static int ProcRRXineramaQueryScreens(ClientPtr client);
static int SProcRRXineramaDispatch(ClientPtr client);
+Bool noRRXineramaExtension = FALSE;
+
/* Proc */
int
@@ -147,35 +149,10 @@ ProcRRXineramaGetState(ClientPtr client)
return Success;
}
-static Bool
-RRXineramaCrtcActive(RRCrtcPtr crtc)
-{
- return crtc->mode != NULL && crtc->numOutputs > 0;
-}
-
static int
RRXineramaScreenCount(ScreenPtr pScreen)
{
- int i, n;
- ScreenPtr slave;
-
- n = 0;
- if (rrGetScrPriv(pScreen)) {
- rrScrPriv(pScreen);
- for (i = 0; i < pScrPriv->numCrtcs; i++)
- if (RRXineramaCrtcActive(pScrPriv->crtcs[i]))
- n++;
- }
-
- xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) {
- rrScrPrivPtr pSlavePriv;
- pSlavePriv = rrGetScrPriv(slave);
- for (i = 0; i < pSlavePriv->numCrtcs; i++)
- if (RRXineramaCrtcActive(pSlavePriv->crtcs[i]))
- n++;
- }
-
- return n;
+ return RRMonitorCountList(pScreen);
}
static Bool
@@ -274,42 +251,16 @@ ProcRRXineramaIsActive(ClientPtr client)
}
static void
-RRXineramaWriteCrtc(ClientPtr client, RRCrtcPtr crtc)
+RRXineramaWriteMonitor(ClientPtr client, RRMonitorPtr monitor)
{
xXineramaScreenInfo scratch;
- if (RRXineramaCrtcActive(crtc)) {
- ScreenPtr pScreen = crtc->pScreen;
- rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
- BoxRec panned_area;
-
- /* Check to see if crtc is panned and return the full area when applicable. */
- if (pScrPriv && pScrPriv->rrGetPanning &&
- pScrPriv->rrGetPanning(pScreen, crtc, &panned_area, NULL, NULL) &&
- (panned_area.x2 > panned_area.x1) &&
- (panned_area.y2 > panned_area.y1)) {
- scratch.x_org = panned_area.x1;
- scratch.y_org = panned_area.y1;
- scratch.width = panned_area.x2 - panned_area.x1;
- scratch.height = panned_area.y2 - panned_area.y1;
- }
- else {
- int width, height;
-
- RRCrtcGetScanoutSize(crtc, &width, &height);
- scratch.x_org = crtc->x;
- scratch.y_org = crtc->y;
- scratch.width = width;
- scratch.height = height;
- }
- if (client->swapped) {
- swaps(&scratch.x_org);
- swaps(&scratch.y_org);
- swaps(&scratch.width);
- swaps(&scratch.height);
- }
- WriteToClient(client, sz_XineramaScreenInfo, &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, &scratch);
}
int
@@ -317,21 +268,23 @@ ProcRRXineramaQueryScreens(ClientPtr client)
{
xXineramaQueryScreensReply rep;
ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN];
- int n = 0;
- int i;
+ int m;
+ RRMonitorPtr monitors = NULL;
+ int nmonitors = 0;
REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
if (RRXineramaScreenActive(pScreen)) {
RRGetInfo(pScreen, FALSE);
- n = RRXineramaScreenCount(pScreen);
+ if (!RRMonitorMakeList(pScreen, TRUE, &monitors, &nmonitors))
+ return BadAlloc;
}
rep = (xXineramaQueryScreensReply) {
.type = X_Reply,
.sequenceNumber = client->sequence,
- .length = bytes_to_int32(n * sz_XineramaScreenInfo),
- .number = n
+ .length = bytes_to_int32(nmonitors * sz_XineramaScreenInfo),
+ .number = nmonitors
};
if (client->swapped) {
swaps(&rep.sequenceNumber);
@@ -340,40 +293,11 @@ ProcRRXineramaQueryScreens(ClientPtr client)
}
WriteToClient(client, sizeof(xXineramaQueryScreensReply), &rep);
- if (n) {
- ScreenPtr slave;
- rrScrPriv(pScreen);
- int has_primary = 0;
- RRCrtcPtr primary_crtc = NULL;
-
- if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) {
- has_primary = 1;
- primary_crtc = pScrPriv->primaryOutput->crtc;
- RRXineramaWriteCrtc(client, pScrPriv->primaryOutput->crtc);
- }
-
- for (i = 0; i < pScrPriv->numCrtcs; i++) {
- if (has_primary &&
- primary_crtc == pScrPriv->crtcs[i]) {
- has_primary = 0;
- continue;
- }
- RRXineramaWriteCrtc(client, pScrPriv->crtcs[i]);
- }
-
- xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) {
- rrScrPrivPtr pSlavePriv;
- pSlavePriv = rrGetScrPriv(slave);
- for (i = 0; i < pSlavePriv->numCrtcs; i++) {
- if (has_primary &&
- primary_crtc == pSlavePriv->crtcs[i]) {
- has_primary = 0;
- continue;
- }
- RRXineramaWriteCrtc(client, pSlavePriv->crtcs[i]);
- }
- }
- }
+ for (m = 0; m < nmonitors; m++)
+ RRXineramaWriteMonitor(client, &monitors[m]);
+
+ if (monitors)
+ RRMonitorFreeList(monitors, nmonitors);
return Success;
}
@@ -488,6 +412,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