Merge remote-tracking branch 'airlied/for-keithp'
This commit is contained in:
commit
e608f3521e
|
@ -3026,6 +3026,27 @@ xf86OutputSetEDIDProperty(xf86OutputPtr output, void *data, int data_len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TILE_ATOM_NAME "TILE"
|
||||||
|
/* changing this in the future could be tricky as people may hardcode 8 */
|
||||||
|
#define TILE_PROP_NUM_ITEMS 8
|
||||||
|
static void
|
||||||
|
xf86OutputSetTileProperty(xf86OutputPtr output)
|
||||||
|
{
|
||||||
|
Atom tile_atom = MakeAtom(TILE_ATOM_NAME, sizeof(TILE_ATOM_NAME) - 1, TRUE);
|
||||||
|
|
||||||
|
/* This may get called before the RandR resources have been created */
|
||||||
|
if (output->randr_output == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (output->tile_info.group_id != 0) {
|
||||||
|
RRChangeOutputProperty(output->randr_output, tile_atom, XA_INTEGER, 32,
|
||||||
|
PropModeReplace, TILE_PROP_NUM_ITEMS, (uint32_t *)&output->tile_info, FALSE, TRUE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RRDeleteOutputProperty(output->randr_output, tile_atom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Pull out a phyiscal size from a detailed timing if available. */
|
/* Pull out a phyiscal size from a detailed timing if available. */
|
||||||
|
@ -3071,6 +3092,38 @@ handle_detailed_physical_size(struct detailed_monitor_section
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bool
|
||||||
|
xf86OutputParseKMSTile(const char *tile_data, int tile_length,
|
||||||
|
struct xf86CrtcTileInfo *tile_info)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = sscanf(tile_data, "%d:%d:%d:%d:%d:%d:%d:%d",
|
||||||
|
&tile_info->group_id,
|
||||||
|
&tile_info->flags,
|
||||||
|
&tile_info->num_h_tile,
|
||||||
|
&tile_info->num_v_tile,
|
||||||
|
&tile_info->tile_h_loc,
|
||||||
|
&tile_info->tile_v_loc,
|
||||||
|
&tile_info->tile_h_size,
|
||||||
|
&tile_info->tile_v_size);
|
||||||
|
if (ret != 8)
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xf86OutputSetTile(xf86OutputPtr output, struct xf86CrtcTileInfo *tile_info)
|
||||||
|
{
|
||||||
|
if (tile_info)
|
||||||
|
output->tile_info = *tile_info;
|
||||||
|
else
|
||||||
|
memset(&output->tile_info, 0, sizeof(output->tile_info));
|
||||||
|
#ifdef RANDR_12_INTERFACE
|
||||||
|
xf86OutputSetTileProperty(output);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the EDID information for the specified output
|
* Set the EDID information for the specified output
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -70,6 +70,17 @@ typedef enum _xf86OutputStatus {
|
||||||
XF86OutputStatusUnknown
|
XF86OutputStatusUnknown
|
||||||
} xf86OutputStatus;
|
} xf86OutputStatus;
|
||||||
|
|
||||||
|
struct xf86CrtcTileInfo {
|
||||||
|
uint32_t group_id;
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t num_h_tile;
|
||||||
|
uint32_t num_v_tile;
|
||||||
|
uint32_t tile_h_loc;
|
||||||
|
uint32_t tile_v_loc;
|
||||||
|
uint32_t tile_h_size;
|
||||||
|
uint32_t tile_v_size;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct _xf86CrtcFuncs {
|
typedef struct _xf86CrtcFuncs {
|
||||||
/**
|
/**
|
||||||
* Turns the crtc on/off, or sets intermediate power levels if available.
|
* Turns the crtc on/off, or sets intermediate power levels if available.
|
||||||
|
@ -226,7 +237,7 @@ typedef struct _xf86CrtcFuncs {
|
||||||
|
|
||||||
} xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
|
} xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
|
||||||
|
|
||||||
#define XF86_CRTC_VERSION 5
|
#define XF86_CRTC_VERSION 6
|
||||||
|
|
||||||
struct _xf86Crtc {
|
struct _xf86Crtc {
|
||||||
/**
|
/**
|
||||||
|
@ -500,7 +511,7 @@ typedef struct _xf86OutputFuncs {
|
||||||
(*destroy) (xf86OutputPtr output);
|
(*destroy) (xf86OutputPtr output);
|
||||||
} xf86OutputFuncsRec, *xf86OutputFuncsPtr;
|
} xf86OutputFuncsRec, *xf86OutputFuncsPtr;
|
||||||
|
|
||||||
#define XF86_OUTPUT_VERSION 2
|
#define XF86_OUTPUT_VERSION 3
|
||||||
|
|
||||||
struct _xf86Output {
|
struct _xf86Output {
|
||||||
/**
|
/**
|
||||||
|
@ -615,6 +626,8 @@ struct _xf86Output {
|
||||||
BoxRec initialTotalArea;
|
BoxRec initialTotalArea;
|
||||||
BoxRec initialTrackingArea;
|
BoxRec initialTrackingArea;
|
||||||
INT16 initialBorder[4];
|
INT16 initialBorder[4];
|
||||||
|
|
||||||
|
struct xf86CrtcTileInfo tile_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _xf86ProviderFuncs {
|
typedef struct _xf86ProviderFuncs {
|
||||||
|
@ -880,6 +893,15 @@ xf86SetSingleMode(ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation);
|
||||||
extern _X_EXPORT void
|
extern _X_EXPORT void
|
||||||
xf86OutputSetEDID(xf86OutputPtr output, xf86MonPtr edid_mon);
|
xf86OutputSetEDID(xf86OutputPtr output, xf86MonPtr edid_mon);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the TILE information for the specified output
|
||||||
|
*/
|
||||||
|
extern _X_EXPORT void
|
||||||
|
xf86OutputSetTile(xf86OutputPtr output, struct xf86CrtcTileInfo *tile_info);
|
||||||
|
|
||||||
|
extern _X_EXPORT Bool
|
||||||
|
xf86OutputParseKMSTile(const char *tile_data, int tile_length, struct xf86CrtcTileInfo *tile_info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the list of modes supported by the EDID information
|
* Return the list of modes supported by the EDID information
|
||||||
* stored in 'output'
|
* stored in 'output'
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
|
|
||||||
/* RandR */
|
/* RandR */
|
||||||
#define SERVER_RANDR_MAJOR_VERSION 1
|
#define SERVER_RANDR_MAJOR_VERSION 1
|
||||||
#define SERVER_RANDR_MINOR_VERSION 4
|
#define SERVER_RANDR_MINOR_VERSION 5
|
||||||
|
|
||||||
/* Record */
|
/* Record */
|
||||||
#define SERVER_RECORD_MAJOR_VERSION 1
|
#define SERVER_RECORD_MAJOR_VERSION 1
|
||||||
|
|
|
@ -15,6 +15,7 @@ librandr_la_SOURCES = \
|
||||||
rrdispatch.c \
|
rrdispatch.c \
|
||||||
rrinfo.c \
|
rrinfo.c \
|
||||||
rrmode.c \
|
rrmode.c \
|
||||||
|
rrmonitor.c \
|
||||||
rroutput.c \
|
rroutput.c \
|
||||||
rrpointer.c \
|
rrpointer.c \
|
||||||
rrproperty.c \
|
rrproperty.c \
|
||||||
|
|
|
@ -98,6 +98,8 @@ RRCloseScreen(ScreenPtr pScreen)
|
||||||
if (pScrPriv->provider)
|
if (pScrPriv->provider)
|
||||||
RRProviderDestroy(pScrPriv->provider);
|
RRProviderDestroy(pScrPriv->provider);
|
||||||
|
|
||||||
|
RRMonitorClose(pScreen);
|
||||||
|
|
||||||
free(pScrPriv->crtcs);
|
free(pScrPriv->crtcs);
|
||||||
free(pScrPriv->outputs);
|
free(pScrPriv->outputs);
|
||||||
free(pScrPriv);
|
free(pScrPriv);
|
||||||
|
@ -333,6 +335,8 @@ RRScreenInit(ScreenPtr pScreen)
|
||||||
pScrPriv->numCrtcs = 0;
|
pScrPriv->numCrtcs = 0;
|
||||||
pScrPriv->crtcs = NULL;
|
pScrPriv->crtcs = NULL;
|
||||||
|
|
||||||
|
RRMonitorInit(pScreen);
|
||||||
|
|
||||||
RRNScreens += 1; /* keep count of screens that implement randr */
|
RRNScreens += 1; /* keep count of screens that implement randr */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,7 @@ typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr;
|
||||||
typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr;
|
typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr;
|
||||||
typedef struct _rrOutput RROutputRec, *RROutputPtr;
|
typedef struct _rrOutput RROutputRec, *RROutputPtr;
|
||||||
typedef struct _rrProvider RRProviderRec, *RRProviderPtr;
|
typedef struct _rrProvider RRProviderRec, *RRProviderPtr;
|
||||||
|
typedef struct _rrMonitor RRMonitorRec, *RRMonitorPtr;
|
||||||
|
|
||||||
struct _rrMode {
|
struct _rrMode {
|
||||||
int refcnt;
|
int refcnt;
|
||||||
|
@ -169,6 +170,22 @@ struct _rrProvider {
|
||||||
struct _rrProvider *output_source;
|
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
|
#if RANDR_12_INTERFACE
|
||||||
typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen,
|
typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen,
|
||||||
CARD16 width,
|
CARD16 width,
|
||||||
|
@ -338,6 +355,9 @@ typedef struct _rrScrPriv {
|
||||||
|
|
||||||
RRProviderDestroyProcPtr rrProviderDestroy;
|
RRProviderDestroyProcPtr rrProviderDestroy;
|
||||||
|
|
||||||
|
int numMonitors;
|
||||||
|
RRMonitorPtr *monitors;
|
||||||
|
|
||||||
} rrScrPrivRec, *rrScrPrivPtr;
|
} rrScrPrivRec, *rrScrPrivPtr;
|
||||||
|
|
||||||
extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
|
extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
|
||||||
|
@ -981,6 +1001,30 @@ extern _X_EXPORT void
|
||||||
RRXineramaExtensionInit(void);
|
RRXineramaExtensionInit(void);
|
||||||
#endif
|
#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);
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcRRGetMonitors(ClientPtr client);
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcRRSetMonitor(ClientPtr client);
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcRRDeleteMonitor(ClientPtr client);
|
||||||
|
|
||||||
#endif /* _RANDRSTR_H_ */
|
#endif /* _RANDRSTR_H_ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -254,4 +254,7 @@ int (*ProcRandrVector[RRNumberRequests]) (ClientPtr) = {
|
||||||
ProcRRChangeProviderProperty, /* 39 */
|
ProcRRChangeProviderProperty, /* 39 */
|
||||||
ProcRRDeleteProviderProperty, /* 40 */
|
ProcRRDeleteProviderProperty, /* 40 */
|
||||||
ProcRRGetProviderProperty, /* 41 */
|
ProcRRGetProviderProperty, /* 41 */
|
||||||
|
ProcRRGetMonitors, /* 42 */
|
||||||
|
ProcRRSetMonitor, /* 43 */
|
||||||
|
ProcRRDeleteMonitor, /* 44 */
|
||||||
};
|
};
|
||||||
|
|
748
randr/rrmonitor.c
Normal file
748
randr/rrmonitor.c
Normal file
|
@ -0,0 +1,748 @@
|
||||||
|
/*
|
||||||
|
* 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-%08x", 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(pScrPriv->crtcs[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 < pScrPriv->numCrtcs; c++) {
|
||||||
|
RRCrtcPtr crtc = pScrPriv->crtcs[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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
RRMonitorFree(RRMonitorPtr monitor)
|
||||||
|
{
|
||||||
|
free(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static 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 = realloc(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)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RRMonitorDelete(client, screen, stuff->name);
|
||||||
|
}
|
|
@ -565,6 +565,41 @@ static int SProcRRGetProviderProperty(ClientPtr client)
|
||||||
return ProcRandrVector[stuff->randrReqType] (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) = {
|
int (*SProcRandrVector[RRNumberRequests]) (ClientPtr) = {
|
||||||
SProcRRQueryVersion, /* 0 */
|
SProcRRQueryVersion, /* 0 */
|
||||||
/* we skip 1 to make old clients fail pretty immediately */
|
/* we skip 1 to make old clients fail pretty immediately */
|
||||||
|
@ -614,4 +649,7 @@ int (*SProcRandrVector[RRNumberRequests]) (ClientPtr) = {
|
||||||
SProcRRChangeProviderProperty, /* 39 */
|
SProcRRChangeProviderProperty, /* 39 */
|
||||||
SProcRRDeleteProviderProperty, /* 40 */
|
SProcRRDeleteProviderProperty, /* 40 */
|
||||||
SProcRRGetProviderProperty, /* 41 */
|
SProcRRGetProviderProperty, /* 41 */
|
||||||
|
SProcRRGetMonitors, /* 42 */
|
||||||
|
SProcRRSetMonitor, /* 43 */
|
||||||
|
SProcRRDeleteMonitor, /* 44 */
|
||||||
};
|
};
|
||||||
|
|
|
@ -149,35 +149,10 @@ ProcRRXineramaGetState(ClientPtr client)
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool
|
|
||||||
RRXineramaCrtcActive(RRCrtcPtr crtc)
|
|
||||||
{
|
|
||||||
return crtc->mode != NULL && crtc->numOutputs > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
RRXineramaScreenCount(ScreenPtr pScreen)
|
RRXineramaScreenCount(ScreenPtr pScreen)
|
||||||
{
|
{
|
||||||
int i, n;
|
return RRMonitorCountList(pScreen);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool
|
static Bool
|
||||||
|
@ -276,42 +251,16 @@ ProcRRXineramaIsActive(ClientPtr client)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
RRXineramaWriteCrtc(ClientPtr client, RRCrtcPtr crtc)
|
RRXineramaWriteMonitor(ClientPtr client, RRMonitorPtr monitor)
|
||||||
{
|
{
|
||||||
xXineramaScreenInfo scratch;
|
xXineramaScreenInfo scratch;
|
||||||
|
|
||||||
if (RRXineramaCrtcActive(crtc)) {
|
scratch.x_org = monitor->geometry.box.x1;
|
||||||
ScreenPtr pScreen = crtc->pScreen;
|
scratch.y_org = monitor->geometry.box.y1;
|
||||||
rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
|
scratch.width = monitor->geometry.box.x2 - monitor->geometry.box.x1;
|
||||||
BoxRec panned_area;
|
scratch.height = monitor->geometry.box.y2 - monitor->geometry.box.y1;
|
||||||
|
|
||||||
/* Check to see if crtc is panned and return the full area when applicable. */
|
WriteToClient(client, sz_XineramaScreenInfo, &scratch);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -319,21 +268,23 @@ ProcRRXineramaQueryScreens(ClientPtr client)
|
||||||
{
|
{
|
||||||
xXineramaQueryScreensReply rep;
|
xXineramaQueryScreensReply rep;
|
||||||
ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN];
|
ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN];
|
||||||
int n = 0;
|
int m;
|
||||||
int i;
|
RRMonitorPtr monitors = NULL;
|
||||||
|
int nmonitors = 0;
|
||||||
|
|
||||||
REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
|
REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
|
||||||
|
|
||||||
if (RRXineramaScreenActive(pScreen)) {
|
if (RRXineramaScreenActive(pScreen)) {
|
||||||
RRGetInfo(pScreen, FALSE);
|
RRGetInfo(pScreen, FALSE);
|
||||||
n = RRXineramaScreenCount(pScreen);
|
if (!RRMonitorMakeList(pScreen, TRUE, &monitors, &nmonitors))
|
||||||
|
return BadAlloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rep = (xXineramaQueryScreensReply) {
|
rep = (xXineramaQueryScreensReply) {
|
||||||
.type = X_Reply,
|
.type = X_Reply,
|
||||||
.sequenceNumber = client->sequence,
|
.sequenceNumber = client->sequence,
|
||||||
.length = bytes_to_int32(n * sz_XineramaScreenInfo),
|
.length = bytes_to_int32(nmonitors * sz_XineramaScreenInfo),
|
||||||
.number = n
|
.number = nmonitors
|
||||||
};
|
};
|
||||||
if (client->swapped) {
|
if (client->swapped) {
|
||||||
swaps(&rep.sequenceNumber);
|
swaps(&rep.sequenceNumber);
|
||||||
|
@ -342,40 +293,11 @@ ProcRRXineramaQueryScreens(ClientPtr client)
|
||||||
}
|
}
|
||||||
WriteToClient(client, sizeof(xXineramaQueryScreensReply), &rep);
|
WriteToClient(client, sizeof(xXineramaQueryScreensReply), &rep);
|
||||||
|
|
||||||
if (n) {
|
for (m = 0; m < nmonitors; m++)
|
||||||
ScreenPtr slave;
|
RRXineramaWriteMonitor(client, &monitors[m]);
|
||||||
rrScrPriv(pScreen);
|
|
||||||
int has_primary = 0;
|
|
||||||
RRCrtcPtr primary_crtc = NULL;
|
|
||||||
|
|
||||||
if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) {
|
if (monitors)
|
||||||
has_primary = 1;
|
RRMonitorFreeList(monitors, nmonitors);
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user