[PATCH xserver 3/3] Add RandR leases with modesetting driver support [v2]
Keith Packard
keithp at keithp.com
Wed Aug 2 10:42:13 UTC 2017
This adds support for RandR CRTC/Output leases through the modesetting
driver, creating a lease using new kernel infrastructure and returning
that to a client through an fd which will have access to only those
resources.
v2:
When a lease terminates for a crtc we have saved data for, go
ahead and restore the saved mode.
Signed-off-by: Keith Packard <keithp at keithp.com>
---
configure.ac | 2 +-
hw/xfree86/drivers/modesetting/drmmode_display.c | 138 ++++++++++++++++++++-
hw/xfree86/drivers/modesetting/drmmode_display.h | 4 +
hw/xfree86/modes/xf86Crtc.c | 11 +-
hw/xfree86/modes/xf86Crtc.h | 67 +++++++++++
hw/xfree86/modes/xf86RandR12.c | 54 +++++++++
include/protocol-versions.h | 2 +-
randr/Makefile.am | 1 +
randr/randr.c | 29 +++++
randr/randrstr.h | 65 +++++++++-
randr/rrcrtc.c | 147 ++++++++++++++---------
randr/rrdispatch.c | 4 +
randr/rrmode.c | 6 +
randr/rroutput.c | 137 +++++++++++++--------
randr/rrproperty.c | 6 +
randr/rrsdispatch.c | 27 +++++
16 files changed, 589 insertions(+), 111 deletions(-)
diff --git a/configure.ac b/configure.ac
index 8d3c3b55b..ac9fbc87f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -744,7 +744,7 @@ LIBXSHMFENCE="xshmfence >= 1.1"
dnl Required modules
XPROTO="xproto >= 7.0.31"
-RANDRPROTO="randrproto >= 1.5.0"
+RANDRPROTO="randrproto >= 1.6.0"
RENDERPROTO="renderproto >= 0.11"
XEXTPROTO="xextproto >= 7.2.99.901"
INPUTPROTO="inputproto >= 2.3"
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 837421efe..70bc68354 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -54,7 +54,6 @@ static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height);
static PixmapPtr drmmode_create_pixmap_header(ScreenPtr pScreen, int width, int height,
int depth, int bitsPerPixel, int devKind,
void *pPixData);
-
static Bool drmmode_set_cursor(xf86CrtcPtr crtc);
static void drmmode_hide_cursor(xf86CrtcPtr crtc);
@@ -2057,8 +2056,140 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
return FALSE;
}
+static void
+drmmode_validate_leases(ScrnInfoPtr scrn)
+{
+ ScreenPtr screen = scrn->pScreen;
+ rrScrPrivPtr scr_priv = rrGetScrPriv(screen);
+ modesettingPtr ms = modesettingPTR(scrn);
+ drmmode_ptr drmmode = &ms->drmmode;
+ drmModeLesseeListPtr lessees;
+ RRLeasePtr lease, next;
+ int l;
+
+ lessees = drmModeListLessees(drmmode->fd);
+ if (!lessees)
+ return;
+
+ xorg_list_for_each_entry_safe(lease, next, &scr_priv->leases, list) {
+ drmmode_lease_private_ptr lease_private = lease->devPrivate;
+
+ for (l = 0; l < lessees->count; l++) {
+ if (lessees->lessees[l] == lease_private->lessee_id)
+ break;
+ }
+
+ /* check to see if the lease has gone away */
+ if (l == lessees->count) {
+ free(lease_private);
+ lease->devPrivate = NULL;
+ xf86CrtcLeaseTerminated(lease);
+ }
+ }
+
+ free(lessees);
+}
+
+static int
+drmmode_create_lease(RRLeasePtr lease, int *fd)
+{
+ ScreenPtr screen = lease->screen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ modesettingPtr ms = modesettingPTR(scrn);
+ drmmode_ptr drmmode = &ms->drmmode;
+ int ncrtc = lease->numCrtcs;
+ int noutput = lease->numOutputs;
+ int nencoder = 0;
+ int nobjects;
+ int c, o, e;
+ int i;
+ int lease_fd;
+ uint32_t *objects;
+ drmmode_lease_private_ptr lease_private;
+
+ /* Find encoders for each output */
+ for (o = 0; o < noutput; o++) {
+ xf86OutputPtr output = lease->outputs[o]->devPrivate;
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+
+ nencoder += drmmode_output->mode_output->count_encoders;
+ }
+
+ nobjects = ncrtc + noutput + nencoder;
+
+ if (nobjects == 0)
+ return BadValue;
+
+ lease_private = calloc(1, sizeof (drmmode_lease_private_rec));
+ if (!lease_private)
+ return BadAlloc;
+
+ objects = xallocarray(nobjects, sizeof (uint32_t));
+
+ if (!objects) {
+ free(lease_private);
+ return BadAlloc;
+ }
+
+ i = 0;
+
+ /* Add CRTC ids */
+ for (c = 0; c < ncrtc; c++) {
+ xf86CrtcPtr crtc = lease->crtcs[c]->devPrivate;
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ objects[i++] = drmmode_crtc->mode_crtc->crtc_id;
+ }
+
+ /* Add connector and encoder ids */
+
+ for (o = 0; o < noutput; o++) {
+ xf86OutputPtr output = lease->outputs[o]->devPrivate;
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+
+ objects[i++] = drmmode_output->mode_output->connector_id;
+ for (e = 0; e < drmmode_output->mode_output->count_encoders; e++)
+ objects[i++] = drmmode_output->mode_encoders[e]->encoder_id;
+ }
+
+ /* call kernel to create lease */
+ assert (i == nobjects);
+
+ lease_fd = drmModeCreateLease(drmmode->fd, objects, nobjects, 0, &lease_private->lessee_id);
+
+ free(objects);
+
+ if (lease_fd < 0) {
+ free(lease_private);
+ return BadMatch;
+ }
+
+ lease->devPrivate = lease_private;
+
+ *fd = lease_fd;
+ return Success;
+}
+
+static void
+drmmode_terminate_lease(RRLeasePtr lease)
+{
+ ScreenPtr screen = lease->screen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ modesettingPtr ms = modesettingPTR(scrn);
+ drmmode_ptr drmmode = &ms->drmmode;
+ drmmode_lease_private_ptr lease_private = lease->devPrivate;
+
+ if (drmModeRevokeLease(drmmode->fd, lease_private->lessee_id) == 0) {
+ free(lease_private);
+ lease->devPrivate = NULL;
+ xf86CrtcLeaseTerminated(lease);
+ }
+}
+
static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
- drmmode_xf86crtc_resize
+ .resize = drmmode_xf86crtc_resize,
+ .create_lease = drmmode_create_lease,
+ .terminate_lease = drmmode_terminate_lease
};
Bool
@@ -2399,6 +2530,9 @@ drmmode_handle_uevents(int fd, void *closure)
drmmode_output_init(scrn, drmmode, mode_res, i, TRUE, 0);
}
+ /* Check to see if a lessee has disappeared */
+ drmmode_validate_leases(scrn);
+
if (changed) {
RRSetChanged(xf86ScrnToScreen(scrn));
RRTellChanged(xf86ScrnToScreen(scrn));
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index f774250ef..e99d32a86 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -140,6 +140,10 @@ typedef struct {
int enc_clone_mask;
} drmmode_output_private_rec, *drmmode_output_private_ptr;
+typedef struct {
+ uint32_t lessee_id;
+} drmmode_lease_private_rec, *drmmode_lease_private_ptr;
+
typedef struct _msPixmapPriv {
uint32_t fb_id;
struct dumb_bo *backing_bo; /* if this pixmap is backed by a dumb bo */
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index fa404d9d4..7cfbd6bc7 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -2665,6 +2665,9 @@ xf86PrepareOutputs(ScrnInfoPtr scrn)
for (o = 0; o < config->num_output; o++) {
xf86OutputPtr output = config->output[o];
+ if (RROutputIsLeased(output->randr_output))
+ continue;
+
#if RANDR_GET_CRTC_INTERFACE
/* Disable outputs that are unused or will be re-routed */
if (!output->funcs->get_crtc ||
@@ -2682,12 +2685,15 @@ xf86PrepareCrtcs(ScrnInfoPtr scrn)
int c;
for (c = 0; c < config->num_crtc; c++) {
-#if RANDR_GET_CRTC_INTERFACE
xf86CrtcPtr crtc = config->crtc[c];
+#if RANDR_GET_CRTC_INTERFACE
xf86OutputPtr output = NULL;
uint32_t desired_outputs = 0, current_outputs = 0;
int o;
+ if (RRCrtcIsLeased(crtc->randr_crtc))
+ continue;
+
for (o = 0; o < config->num_output; o++) {
output = config->output[o];
if (output->crtc == crtc)
@@ -2708,6 +2714,9 @@ xf86PrepareCrtcs(ScrnInfoPtr scrn)
if (desired_outputs != current_outputs || !desired_outputs)
(*crtc->funcs->dpms) (crtc, DPMSModeOff);
#else
+ if (RRCrtcIsLeased(crtc->randr_crtc))
+ continue;
+
(*crtc->funcs->dpms) (crtc, DPMSModeOff);
#endif
}
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 215eb2a04..840bf99b5 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -47,6 +47,7 @@
typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
+typedef struct _xf86Lease xf86LeaseRec, *xf86LeasePtr;
/* define a standard for connector types */
typedef enum _xf86ConnectorType {
@@ -672,6 +673,54 @@ typedef struct _xf86ProviderFuncs {
} xf86ProviderFuncsRec, *xf86ProviderFuncsPtr;
+#define XF86_LEASE_VERSION 1
+
+struct _xf86Lease {
+ /**
+ * ABI versioning
+ */
+ int version;
+
+ /**
+ * Associated ScrnInfo
+ */
+ ScrnInfoPtr scrn;
+
+ /**
+ * Driver private
+ */
+ void *driver_private;
+
+ /**
+ * RandR lease
+ */
+ RRLeasePtr randr_lease;
+
+ /*
+ * Contents of the lease
+ */
+
+ /**
+ * Number of leased CRTCs
+ */
+ int num_crtc;
+
+ /**
+ * Number of leased outputs
+ */
+ int num_output;
+
+ /**
+ * Array of pointers to leased CRTCs
+ */
+ RRCrtcPtr *crtcs;
+
+ /**
+ * Array of pointers to leased outputs
+ */
+ RROutputPtr *outputs;
+};
+
typedef struct _xf86CrtcConfigFuncs {
/**
* Requests that the driver resize the screen.
@@ -687,8 +736,26 @@ typedef struct _xf86CrtcConfigFuncs {
*/
Bool
(*resize) (ScrnInfoPtr scrn, int width, int height);
+
+ /**
+ * Requests that the driver create a lease
+ */
+ int (*create_lease)(RRLeasePtr lease, int *fd);
+
+ /**
+ * Ask the driver to terminate a lease, freeing all
+ * driver resources
+ */
+ void (*terminate_lease)(RRLeasePtr lease);
} xf86CrtcConfigFuncsRec, *xf86CrtcConfigFuncsPtr;
+/*
+ * The driver calls this when it detects that a lease
+ * has been terminated
+ */
+extern _X_EXPORT void
+xf86CrtcLeaseTerminated(RRLeasePtr lease);
+
typedef void (*xf86_crtc_notify_proc_ptr) (ScreenPtr pScreen);
typedef struct _xf86CrtcConfig {
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index fe8770d61..c55ab7c90 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -2163,6 +2163,57 @@ xf86RandR14ProviderDestroy(ScreenPtr screen, RRProviderPtr provider)
config->randr_provider = NULL;
}
+void
+xf86CrtcLeaseTerminated(RRLeasePtr lease)
+{
+ int c;
+
+ /*
+ * Force a full mode set on any crtc in the expiring lease which
+ * was running before the lease started
+ */
+ for (c = 0; c < lease->numCrtcs; c++) {
+ RRCrtcPtr randr_crtc = lease->crtcs[c];
+ xf86CrtcPtr crtc = randr_crtc->devPrivate;
+
+ if (crtc->enabled) {
+ RRTransformPtr transform;
+
+ if (crtc->desiredTransformPresent)
+ transform = &crtc->desiredTransform;
+ else
+ transform = NULL;
+ xf86CrtcSetModeTransform(crtc, &crtc->desiredMode,
+ crtc->desiredRotation, transform,
+ crtc->desiredX, crtc->desiredY);
+ }
+ }
+ RRLeaseTerminated(lease);
+}
+
+static int
+xf86RandR16CreateLease(ScreenPtr screen, RRLeasePtr randr_lease, int *fd)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ if (config->funcs->create_lease)
+ return config->funcs->create_lease(randr_lease, fd);
+ else
+ return BadMatch;
+}
+
+
+static void
+xf86RandR16TerminateLease(ScreenPtr screen, RRLeasePtr randr_lease)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ if (config->funcs->terminate_lease)
+ config->funcs->terminate_lease(randr_lease);
+}
+
static Bool
xf86RandR12Init12(ScreenPtr pScreen)
{
@@ -2192,6 +2243,9 @@ xf86RandR12Init12(ScreenPtr pScreen)
rp->rrCrtcSetScanoutPixmap = xf86CrtcSetScanoutPixmap;
rp->rrProviderDestroy = xf86RandR14ProviderDestroy;
+ rp->rrCreateLease = xf86RandR16CreateLease;
+ rp->rrTerminateLease = xf86RandR16TerminateLease;
+
pScrn->PointerMoved = xf86RandR12PointerMoved;
pScrn->ChangeGamma = xf86RandR12ChangeGamma;
diff --git a/include/protocol-versions.h b/include/protocol-versions.h
index b4498927b..938b9caa4 100644
--- a/include/protocol-versions.h
+++ b/include/protocol-versions.h
@@ -73,7 +73,7 @@
/* RandR */
#define SERVER_RANDR_MAJOR_VERSION 1
-#define SERVER_RANDR_MINOR_VERSION 5
+#define SERVER_RANDR_MINOR_VERSION 6
/* Record */
#define SERVER_RECORD_MAJOR_VERSION 1
diff --git a/randr/Makefile.am b/randr/Makefile.am
index 90dc9ec9a..f9cefd18a 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -14,6 +14,7 @@ librandr_la_SOURCES = \
rrcrtc.c \
rrdispatch.c \
rrinfo.c \
+ rrlease.c \
rrmode.c \
rrmonitor.c \
rroutput.c \
diff --git a/randr/randr.c b/randr/randr.c
index 507158eb6..339ad3ece 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -2,6 +2,7 @@
* Copyright © 2000 Compaq Computer Corporation
* Copyright © 2002 Hewlett-Packard Company
* Copyright © 2006 Intel Corporation
+ * Copyright © 2017 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
@@ -223,6 +224,19 @@ SRRResourceChangeNotifyEvent(xRRResourceChangeNotifyEvent * from,
}
static void _X_COLD
+SRRLeaseNotifyEvent(xRRLeaseNotifyEvent * from,
+ xRRLeaseNotifyEvent * to)
+{
+ to->type = from->type;
+ to->subCode = from->subCode;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->timestamp, to->timestamp);
+ cpswapl(from->window, to->window);
+ cpswapl(from->lease, to->lease);
+ to->created = from->created;
+}
+
+static void _X_COLD
SRRNotifyEvent(xEvent *from, xEvent *to)
{
switch (from->u.u.detail) {
@@ -249,6 +263,11 @@ SRRNotifyEvent(xEvent *from, xEvent *to)
case RRNotify_ResourceChange:
SRRResourceChangeNotifyEvent((xRRResourceChangeNotifyEvent *) from,
(xRRResourceChangeNotifyEvent *) to);
+ break;
+ case RRNotify_Lease:
+ SRRLeaseNotifyEvent((xRRLeaseNotifyEvent *) from,
+ (xRRLeaseNotifyEvent *) to);
+ break;
default:
break;
}
@@ -268,6 +287,8 @@ RRInit(void)
return FALSE;
if (!RRProviderInit())
return FALSE;
+ if (!RRLeaseInit())
+ return FALSE;
RRGeneration = serverGeneration;
}
if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0))
@@ -335,6 +356,8 @@ RRScreenInit(ScreenPtr pScreen)
pScrPriv->numCrtcs = 0;
pScrPriv->crtcs = NULL;
+ xorg_list_init(&pScrPriv->leases);
+
RRMonitorInit(pScreen);
RRNScreens += 1; /* keep count of screens that implement randr */
@@ -532,6 +555,12 @@ TellChanged(WindowPtr pWin, void *value)
RRDeliverResourceEvent(client, pWin);
}
}
+
+ if (pRREvent->mask & RRLeaseNotifyMask) {
+ if (pScrPriv->leasesChanged) {
+ RRDeliverLeaseEvent(client, pWin);
+ }
+ }
}
return WT_WALKCHILDREN;
}
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 706e9a7b0..924c0e837 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -63,6 +63,7 @@ typedef XID RRMode;
typedef XID RROutput;
typedef XID RRCrtc;
typedef XID RRProvider;
+typedef XID RRLease;
extern int RREventBase, RRErrorBase;
@@ -81,6 +82,7 @@ typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr;
typedef struct _rrOutput RROutputRec, *RROutputPtr;
typedef struct _rrProvider RRProviderRec, *RRProviderPtr;
typedef struct _rrMonitor RRMonitorRec, *RRMonitorPtr;
+typedef struct _rrLease RRLeaseRec, *RRLeasePtr;
struct _rrMode {
int refcnt;
@@ -187,6 +189,20 @@ struct _rrMonitor {
RRMonitorGeometryRec geometry;
};
+typedef enum _rrLeaseState { RRLeaseCreating, RRLeaseRunning, RRLeaseTerminating } RRLeaseState;
+
+struct _rrLease {
+ struct xorg_list list;
+ ScreenPtr screen;
+ RRLease id;
+ RRLeaseState state;
+ void *devPrivate;
+ int numCrtcs;
+ RRCrtcPtr *crtcs;
+ int numOutputs;
+ RROutputPtr *outputs;
+};
+
#if RANDR_12_INTERFACE
typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen,
CARD16 width,
@@ -254,6 +270,15 @@ typedef Bool (*RRProviderSetOffloadSinkProcPtr)(ScreenPtr pScreen,
typedef void (*RRProviderDestroyProcPtr)(ScreenPtr pScreen,
RRProviderPtr provider);
+/* Additions for 1.6 */
+
+typedef int (*RRCreateLeaseProcPtr)(ScreenPtr screen,
+ RRLeasePtr lease,
+ int *fd);
+
+typedef void (*RRTerminateLeaseProcPtr)(ScreenPtr screen,
+ RRLeasePtr lease);
+
/* These are for 1.0 compatibility */
typedef struct _rrRefresh {
@@ -326,6 +351,10 @@ typedef struct _rrScrPriv {
RRProviderSetOffloadSinkProcPtr rrProviderSetOffloadSink;
RRProviderGetPropertyProcPtr rrProviderGetProperty;
RRProviderSetPropertyProcPtr rrProviderSetProperty;
+
+ RRCreateLeaseProcPtr rrCreateLease;
+ RRTerminateLeaseProcPtr rrTerminateLease;
+
/*
* Private part of the structure; not considered part of the ABI
*/
@@ -337,6 +366,7 @@ typedef struct _rrScrPriv {
Bool configChanged; /* configuration changed */
Bool layoutChanged; /* screen layout changed */
Bool resourcesChanged; /* screen resources change */
+ Bool leasesChanged; /* leases change */
CARD16 minWidth, minHeight;
CARD16 maxWidth, maxHeight;
@@ -376,6 +406,7 @@ typedef struct _rrScrPriv {
int numMonitors;
RRMonitorPtr *monitors;
+ struct xorg_list leases;
} rrScrPrivRec, *rrScrPrivPtr;
extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
@@ -419,7 +450,7 @@ extern RESTYPE RRClientType, RREventType; /* resource types for event masks
extern DevPrivateKeyRec RRClientPrivateKeyRec;
#define RRClientPrivateKey (&RRClientPrivateKeyRec)
-extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType, RRProviderType;
+extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType, RRProviderType, RRLeaseType;
#define VERIFY_RR_OUTPUT(id, ptr, a)\
{\
@@ -461,6 +492,16 @@ extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType, RRProviderType;
}\
}
+#define VERIFY_RR_LEASE(id, ptr, a)\
+ {\
+ int rc = dixLookupResourceByType((void **)&(ptr), id,\
+ RRLeaseType, client, a);\
+ if (rc != Success) {\
+ client->errorValue = id;\
+ return rc;\
+ }\
+ }
+
#define GetRRClient(pClient) ((RRClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RRClientPrivateKey))
#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
@@ -769,6 +810,22 @@ void
extern _X_EXPORT Bool
RRClientKnowsRates(ClientPtr pClient);
+/* rrlease.c */
+void
+RRDeliverLeaseEvent(ClientPtr client, WindowPtr window);
+
+void
+RRLeaseTerminated(RRLeasePtr lease);
+
+extern _X_EXPORT Bool
+RRCrtcIsLeased(RRCrtcPtr crtc);
+
+extern _X_EXPORT Bool
+RROutputIsLeased(RROutputPtr output);
+
+Bool
+RRLeaseInit(void);
+
/* rrmode.c */
/*
* Find, and if necessary, create a mode
@@ -1059,6 +1116,12 @@ ProcRRSetMonitor(ClientPtr client);
int
ProcRRDeleteMonitor(ClientPtr client);
+int
+ProcRRCreateLease(ClientPtr client);
+
+int
+ProcRRFreeLease(ClientPtr client);
+
#endif /* _RANDRSTR_H_ */
/*
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 401a1c178..f310cd00f 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -1079,7 +1079,7 @@ ProcRRGetCrtcInfo(ClientPtr client)
REQUEST(xRRGetCrtcInfoReq);
xRRGetCrtcInfoReply rep;
RRCrtcPtr crtc;
- CARD8 *extra;
+ CARD8 *extra = NULL;
unsigned long extraLen;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
@@ -1089,10 +1089,13 @@ ProcRRGetCrtcInfo(ClientPtr client)
int i, j, k;
int width, height;
BoxRec panned_area;
+ Bool leased;
REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq);
VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+ leased = RRCrtcIsLeased(crtc);
+
/* All crtcs must be associated with screens before client
* requests are processed
*/
@@ -1108,61 +1111,77 @@ ProcRRGetCrtcInfo(ClientPtr client)
.length = 0,
.timestamp = pScrPriv->lastSetTime.milliseconds
};
- if (pScrPriv->rrGetPanning &&
- pScrPriv->rrGetPanning(pScreen, crtc, &panned_area, NULL, NULL) &&
- (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1))
- {
- rep.x = panned_area.x1;
- rep.y = panned_area.y1;
- rep.width = panned_area.x2 - panned_area.x1;
- rep.height = panned_area.y2 - panned_area.y1;
- }
- else {
- RRCrtcGetScanoutSize(crtc, &width, &height);
- rep.x = crtc->x;
- rep.y = crtc->y;
- rep.width = width;
- rep.height = height;
- }
- rep.mode = mode ? mode->mode.id : 0;
- rep.rotation = crtc->rotation;
- rep.rotations = crtc->rotations;
- rep.nOutput = crtc->numOutputs;
- k = 0;
- for (i = 0; i < pScrPriv->numOutputs; i++)
- for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
- if (pScrPriv->outputs[i]->crtcs[j] == crtc)
- k++;
- rep.nPossibleOutput = k;
-
- rep.length = rep.nOutput + rep.nPossibleOutput;
-
- extraLen = rep.length << 2;
- if (extraLen) {
- extra = malloc(extraLen);
- if (!extra)
- return BadAlloc;
- }
- else
- extra = NULL;
-
- outputs = (RROutput *) extra;
- possible = (RROutput *) (outputs + rep.nOutput);
-
- for (i = 0; i < crtc->numOutputs; i++) {
- outputs[i] = crtc->outputs[i]->id;
- if (client->swapped)
- swapl(&outputs[i]);
- }
- k = 0;
- for (i = 0; i < pScrPriv->numOutputs; i++)
- for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
- if (pScrPriv->outputs[i]->crtcs[j] == crtc) {
- possible[k] = pScrPriv->outputs[i]->id;
- if (client->swapped)
- swapl(&possible[k]);
- k++;
+ if (leased) {
+ rep.x = rep.y = rep.width = rep.height = 0;
+ rep.mode = 0;
+ rep.rotation = 0;
+ rep.rotations = 0;
+ rep.nOutput = 0;
+ rep.nPossibleOutput = 0;
+ rep.length = 0;
+ extraLen = 0;
+ } else {
+ if (pScrPriv->rrGetPanning &&
+ pScrPriv->rrGetPanning(pScreen, crtc, &panned_area, NULL, NULL) &&
+ (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1))
+ {
+ rep.x = panned_area.x1;
+ rep.y = panned_area.y1;
+ rep.width = panned_area.x2 - panned_area.x1;
+ rep.height = panned_area.y2 - panned_area.y1;
+ }
+ else {
+ RRCrtcGetScanoutSize(crtc, &width, &height);
+ rep.x = crtc->x;
+ rep.y = crtc->y;
+ rep.width = width;
+ rep.height = height;
+ }
+ rep.mode = mode ? mode->mode.id : 0;
+ rep.rotation = crtc->rotation;
+ rep.rotations = crtc->rotations;
+ rep.nOutput = crtc->numOutputs;
+ k = 0;
+ for (i = 0; i < pScrPriv->numOutputs; i++) {
+ if (!RROutputIsLeased(pScrPriv->outputs[i])) {
+ for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
+ if (pScrPriv->outputs[i]->crtcs[j] == crtc)
+ k++;
+ }
+ }
+
+ rep.nPossibleOutput = k;
+
+ rep.length = rep.nOutput + rep.nPossibleOutput;
+
+ extraLen = rep.length << 2;
+ if (extraLen) {
+ extra = malloc(extraLen);
+ if (!extra)
+ return BadAlloc;
+ }
+
+ outputs = (RROutput *) extra;
+ possible = (RROutput *) (outputs + rep.nOutput);
+
+ for (i = 0; i < crtc->numOutputs; i++) {
+ outputs[i] = crtc->outputs[i]->id;
+ if (client->swapped)
+ swapl(&outputs[i]);
+ }
+ k = 0;
+ for (i = 0; i < pScrPriv->numOutputs; i++) {
+ if (!RROutputIsLeased(pScrPriv->outputs[i])) {
+ for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
+ if (pScrPriv->outputs[i]->crtcs[j] == crtc) {
+ possible[k] = pScrPriv->outputs[i]->id;
+ if (client->swapped)
+ swapl(&possible[k]);
+ k++;
+ }
}
+ }
+ }
if (client->swapped) {
swaps(&rep.sequenceNumber);
@@ -1209,6 +1228,9 @@ ProcRRSetCrtcConfig(ClientPtr client)
VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess);
+ if (RRCrtcIsLeased(crtc))
+ return BadAccess;
+
if (stuff->mode == None) {
mode = NULL;
if (numOutputs > 0)
@@ -1235,6 +1257,12 @@ ProcRRSetCrtcConfig(ClientPtr client)
free(outputs);
return ret;
}
+
+ if (RROutputIsLeased(outputs[i])) {
+ free(outputs);
+ return BadAccess;
+ }
+
/* validate crtc for this output */
for (j = 0; j < outputs[i]->numCrtcs; j++)
if (outputs[i]->crtcs[j] == crtc)
@@ -1478,6 +1506,9 @@ ProcRRSetPanning(ClientPtr client)
REQUEST_SIZE_MATCH(xRRSetPanningReq);
VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+ if (RRCrtcIsLeased(crtc))
+ return BadAccess;
+
/* All crtcs must be associated with screens before client
* requests are processed
*/
@@ -1618,6 +1649,9 @@ ProcRRSetCrtcGamma(ClientPtr client)
REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq);
VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+ if (RRCrtcIsLeased(crtc))
+ return BadAccess;
+
len = client->req_len - bytes_to_int32(sizeof(xRRSetCrtcGammaReq));
if (len < (stuff->size * 3 + 1) >> 1)
return BadLength;
@@ -1651,6 +1685,9 @@ ProcRRSetCrtcTransform(ClientPtr client)
REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq);
VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+ if (RRCrtcIsLeased(crtc))
+ return BadAccess;
+
PictTransform_from_xRenderTransform(&transform, &stuff->transform);
pixman_f_transform_from_pixman_transform(&f_transform, &transform);
if (!pixman_f_transform_invert(&f_inverse, &f_transform))
diff --git a/randr/rrdispatch.c b/randr/rrdispatch.c
index 314e4ea52..a5b390914 100644
--- a/randr/rrdispatch.c
+++ b/randr/rrdispatch.c
@@ -256,7 +256,11 @@ int (*ProcRandrVector[RRNumberRequests]) (ClientPtr) = {
ProcRRChangeProviderProperty, /* 39 */
ProcRRDeleteProviderProperty, /* 40 */
ProcRRGetProviderProperty, /* 41 */
+/* V1.5 additions */
ProcRRGetMonitors, /* 42 */
ProcRRSetMonitor, /* 43 */
ProcRRDeleteMonitor, /* 44 */
+/* V1.6 additions */
+ ProcRRCreateLease, /* 45 */
+ ProcRRFreeLease, /* 46 */
};
diff --git a/randr/rrmode.c b/randr/rrmode.c
index a7aa43320..d34025bd0 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -357,6 +357,9 @@ ProcRRAddOutputMode(ClientPtr client)
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess);
+ if (RROutputIsLeased(output))
+ return BadAccess;
+
return RROutputAddUserMode(output, mode);
}
@@ -371,5 +374,8 @@ ProcRRDeleteOutputMode(ClientPtr client)
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess);
+ if (RROutputIsLeased(output))
+ return BadAccess;
+
return RROutputDeleteUserMode(output, mode);
}
diff --git a/randr/rroutput.c b/randr/rroutput.c
index a8efec409..ce2e6216b 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -429,65 +429,99 @@ ProcRRGetOutputInfo(ClientPtr client)
RROutput *clones;
char *name;
int i;
+ Bool leased;
REQUEST_SIZE_MATCH(xRRGetOutputInfoReq);
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
+ leased = RROutputIsLeased(output);
+
pScreen = output->pScreen;
pScrPriv = rrGetScrPriv(pScreen);
- rep = (xRRGetOutputInfoReply) {
- .type = X_Reply,
- .status = RRSetConfigSuccess,
- .sequenceNumber = client->sequence,
- .length = bytes_to_int32(OutputInfoExtra),
- .timestamp = pScrPriv->lastSetTime.milliseconds,
- .crtc = output->crtc ? output->crtc->id : None,
- .mmWidth = output->mmWidth,
- .mmHeight = output->mmHeight,
- .connection = output->connection,
- .subpixelOrder = output->subpixelOrder,
- .nCrtcs = output->numCrtcs,
- .nModes = output->numModes + output->numUserModes,
- .nPreferred = output->numPreferred,
- .nClones = output->numClones,
- .nameLength = output->nameLength
- };
- extraLen = ((output->numCrtcs +
- output->numModes + output->numUserModes +
- output->numClones + bytes_to_int32(rep.nameLength)) << 2);
-
- if (extraLen) {
- rep.length += bytes_to_int32(extraLen);
- extra = malloc(extraLen);
- if (!extra)
- return BadAlloc;
- }
- else
- extra = NULL;
+ if (leased) {
+ rep = (xRRGetOutputInfoReply) {
+ .type = X_Reply,
+ .status = RRSetConfigSuccess,
+ .sequenceNumber = client->sequence,
+ .length = bytes_to_int32(OutputInfoExtra),
+ .timestamp = pScrPriv->lastSetTime.milliseconds,
+ .crtc = None,
+ .mmWidth = 0,
+ .mmHeight = 0,
+ .connection = 0,
+ .subpixelOrder = SubPixelUnknown,
+ .nCrtcs = 0,
+ .nModes = 0,
+ .nPreferred = 0,
+ .nClones = 0,
+ .nameLength = output->nameLength
+ };
+ extraLen = bytes_to_int32(rep.nameLength) << 2;
+ if (extraLen) {
+ rep.length += bytes_to_int32(extraLen);
+ extra = malloc(extraLen);
+ if (!extra)
+ return BadAlloc;
+ }
+ else
+ extra = NULL;
+
+ name = (char *) extra;
+ } else {
+ rep = (xRRGetOutputInfoReply) {
+ .type = X_Reply,
+ .status = RRSetConfigSuccess,
+ .sequenceNumber = client->sequence,
+ .length = bytes_to_int32(OutputInfoExtra),
+ .timestamp = pScrPriv->lastSetTime.milliseconds,
+ .crtc = output->crtc ? output->crtc->id : None,
+ .mmWidth = output->mmWidth,
+ .mmHeight = output->mmHeight,
+ .connection = output->connection,
+ .subpixelOrder = output->subpixelOrder,
+ .nCrtcs = output->numCrtcs,
+ .nModes = output->numModes + output->numUserModes,
+ .nPreferred = output->numPreferred,
+ .nClones = output->numClones,
+ .nameLength = output->nameLength
+ };
+ extraLen = ((output->numCrtcs +
+ output->numModes + output->numUserModes +
+ output->numClones + bytes_to_int32(rep.nameLength)) << 2);
+
+ if (extraLen) {
+ rep.length += bytes_to_int32(extraLen);
+ extra = malloc(extraLen);
+ if (!extra)
+ return BadAlloc;
+ }
+ else
+ extra = NULL;
- crtcs = (RRCrtc *) extra;
- modes = (RRMode *) (crtcs + output->numCrtcs);
- clones = (RROutput *) (modes + output->numModes + output->numUserModes);
- name = (char *) (clones + output->numClones);
+ crtcs = (RRCrtc *) extra;
+ modes = (RRMode *) (crtcs + output->numCrtcs);
+ clones = (RROutput *) (modes + output->numModes + output->numUserModes);
+ name = (char *) (clones + output->numClones);
- for (i = 0; i < output->numCrtcs; i++) {
- crtcs[i] = output->crtcs[i]->id;
- if (client->swapped)
- swapl(&crtcs[i]);
- }
- for (i = 0; i < output->numModes + output->numUserModes; i++) {
- if (i < output->numModes)
- modes[i] = output->modes[i]->mode.id;
- else
- modes[i] = output->userModes[i - output->numModes]->mode.id;
- if (client->swapped)
- swapl(&modes[i]);
- }
- for (i = 0; i < output->numClones; i++) {
- clones[i] = output->clones[i]->id;
- if (client->swapped)
- swapl(&clones[i]);
+ for (i = 0; i < output->numCrtcs; i++) {
+ crtcs[i] = output->crtcs[i]->id;
+ if (client->swapped)
+ swapl(&crtcs[i]);
+ }
+ for (i = 0; i < output->numModes + output->numUserModes; i++) {
+ if (i < output->numModes)
+ modes[i] = output->modes[i]->mode.id;
+ else
+ modes[i] = output->userModes[i - output->numModes]->mode.id;
+ if (client->swapped)
+ swapl(&modes[i]);
+ }
+ for (i = 0; i < output->numClones; i++) {
+ clones[i] = output->clones[i]->id;
+ if (client->swapped)
+ swapl(&clones[i]);
+ }
}
memcpy(name, output->name, output->nameLength);
if (client->swapped) {
@@ -554,6 +588,9 @@ ProcRRSetOutputPrimary(ClientPtr client)
if (stuff->output) {
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
+ if (RROutputIsLeased(output))
+ return BadAccess;
+
if (!output->pScreen->isGPU && output->pScreen != pWin->drawable.pScreen) {
client->errorValue = stuff->window;
return BadMatch;
diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index e56626cd2..b5a591de5 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -485,6 +485,9 @@ ProcRRConfigureOutputProperty(ClientPtr client)
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
+ if (RROutputIsLeased(output))
+ return BadAccess;
+
num_valid =
stuff->length - bytes_to_int32(sizeof(xRRConfigureOutputPropertyReq));
return RRConfigureOutputProperty(output, stuff->property, stuff->pending,
@@ -555,6 +558,9 @@ ProcRRDeleteOutputProperty(ClientPtr client)
UpdateCurrentTime();
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
+ if (RROutputIsLeased(output))
+ return BadAccess;
+
if (!ValidAtom(stuff->property)) {
client->errorValue = stuff->property;
return BadAtom;
diff --git a/randr/rrsdispatch.c b/randr/rrsdispatch.c
index e0ffaa4d5..7d7b5a884 100644
--- a/randr/rrsdispatch.c
+++ b/randr/rrsdispatch.c
@@ -613,6 +613,29 @@ SProcRRDeleteMonitor(ClientPtr client) {
return ProcRandrVector[stuff->randrReqType] (client);
}
+static int _X_COLD
+SProcRRCreateLease(ClientPtr client) {
+ REQUEST(xRRCreateLeaseReq);
+
+ REQUEST_AT_LEAST_SIZE(xRRCreateLeaseReq);
+ swaps(&stuff->length);
+ swapl(&stuff->window);
+ swaps(&stuff->nCrtcs);
+ swaps(&stuff->nOutputs);
+ SwapRestL(stuff);
+ return ProcRandrVector[stuff->randrReqType] (client);
+}
+
+static int _X_COLD
+SProcRRFreeLease(ClientPtr client) {
+ REQUEST(xRRFreeLeaseReq);
+
+ REQUEST_SIZE_MATCH(xRRFreeLeaseReq);
+ swaps(&stuff->length);
+ swapl(&stuff->lid);
+ return ProcRandrVector[stuff->randrReqType] (client);
+}
+
int (*SProcRandrVector[RRNumberRequests]) (ClientPtr) = {
SProcRRQueryVersion, /* 0 */
/* we skip 1 to make old clients fail pretty immediately */
@@ -662,7 +685,11 @@ int (*SProcRandrVector[RRNumberRequests]) (ClientPtr) = {
SProcRRChangeProviderProperty, /* 39 */
SProcRRDeleteProviderProperty, /* 40 */
SProcRRGetProviderProperty, /* 41 */
+/* V1.5 additions */
SProcRRGetMonitors, /* 42 */
SProcRRSetMonitor, /* 43 */
SProcRRDeleteMonitor, /* 44 */
+/* V1.6 additions */
+ SProcRRCreateLease, /* 45 */
+ SProcRRFreeLease, /* 46 */
};
--
2.11.0
More information about the xorg-devel
mailing list