diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2016-05-29 12:02:41 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2016-05-29 12:02:41 +0000 |
commit | 4a991716ac65d28a68f9943d54c4b74ad0b58f65 (patch) | |
tree | c037c3fe64bb15ea67dbf03a96783a8b04085371 /xserver/randr | |
parent | 549cb8bcb6bdd3a7d44f3b9fdc003df777b2b0d2 (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.am | 1 | ||||
-rw-r--r-- | xserver/randr/Makefile.in | 24 | ||||
-rw-r--r-- | xserver/randr/randr.c | 4 | ||||
-rw-r--r-- | xserver/randr/randrstr.h | 63 | ||||
-rw-r--r-- | xserver/randr/rrcrtc.c | 94 | ||||
-rw-r--r-- | xserver/randr/rrdispatch.c | 3 | ||||
-rw-r--r-- | xserver/randr/rrinfo.c | 10 | ||||
-rw-r--r-- | xserver/randr/rrmode.c | 4 | ||||
-rw-r--r-- | xserver/randr/rrmonitor.c | 754 | ||||
-rw-r--r-- | xserver/randr/rroutput.c | 48 | ||||
-rw-r--r-- | xserver/randr/rrproperty.c | 12 | ||||
-rw-r--r-- | xserver/randr/rrproviderproperty.c | 6 | ||||
-rw-r--r-- | xserver/randr/rrscreen.c | 5 | ||||
-rw-r--r-- | xserver/randr/rrsdispatch.c | 38 | ||||
-rw-r--r-- | xserver/randr/rrtransform.c | 10 | ||||
-rw-r--r-- | xserver/randr/rrxinerama.c | 123 |
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 |