aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md20
-rw-r--r--drm-lease-manager/drm-lease.h1
-rw-r--r--drm-lease-manager/lease-manager.c22
-rw-r--r--drm-lease-manager/lease-manager.h1
-rw-r--r--drm-lease-manager/main.c22
5 files changed, 64 insertions, 2 deletions
diff --git a/README.md b/README.md
index 5368f6b..84af0a7 100644
--- a/README.md
+++ b/README.md
@@ -44,6 +44,26 @@ The names of the DRM leases will have the following pattern:
So, for example, a DRM lease for the first LVDS device on the device `/dev/dri/card0` would be named
`card0-LVDS-1`.
+### Dynamic lease transfer
+
+When `drm-lease-manager` is started with the `-t` option, the
+ownership of a leases resourses can be transfered from
+one client to another.
+
+This allows the ownership of the leased resources to be transferred
+without the display being closed and the screen blanking.
+`drm-lease-manager` handles the timing of the tranfser and manages the
+references to the DRM device, so that the last framebuffer of
+the old client stays on screen until the new client presents its first frame.
+
+The transition can be completed without direct communication between the old
+and new client applications, however, the client that the lease will be
+transitioned *from* must be able to handle unexpected lease revokation.
+Once the lease is revoked, all DRM API calls referring to the DRM
+resources managed by the lease will fail with -ENOENT. The client
+should be able to gracefully handle this condition by, for example,
+pausing or shutting down its rendering operations.
+
## Client API usage
The libdmclient handles all communication with the DRM Lease Manager and provides file descriptors that
diff --git a/drm-lease-manager/drm-lease.h b/drm-lease-manager/drm-lease.h
index 6c618a0..a855054 100644
--- a/drm-lease-manager/drm-lease.h
+++ b/drm-lease-manager/drm-lease.h
@@ -18,5 +18,6 @@
struct lease_handle {
char *name;
+ void *user_data;
};
#endif
diff --git a/drm-lease-manager/lease-manager.c b/drm-lease-manager/lease-manager.c
index 016f318..6fafb46 100644
--- a/drm-lease-manager/lease-manager.c
+++ b/drm-lease-manager/lease-manager.c
@@ -372,6 +372,28 @@ int lm_lease_grant(struct lm *lm, struct lease_handle *handle)
return lease->lease_fd;
}
+int lm_lease_transfer(struct lm *lm, struct lease_handle *handle)
+{
+ assert(lm);
+ assert(handle);
+
+ struct lease *lease = (struct lease *)handle;
+ if (!lease->is_granted)
+ return -1;
+
+ // TODO: close this fd once a frame is presented from the new
+ // client.
+ int old_lease_fd = dup(lease->lease_fd);
+
+ lm_lease_revoke(lm, handle);
+ if (lm_lease_grant(lm, handle) < 0) {
+ close(old_lease_fd);
+ return -1;
+ }
+
+ return lease->lease_fd;
+}
+
void lm_lease_revoke(struct lm *lm, struct lease_handle *handle)
{
assert(lm);
diff --git a/drm-lease-manager/lease-manager.h b/drm-lease-manager/lease-manager.h
index ed5bcdc..581e05c 100644
--- a/drm-lease-manager/lease-manager.h
+++ b/drm-lease-manager/lease-manager.h
@@ -25,5 +25,6 @@ void lm_destroy(struct lm *lm);
int lm_get_lease_handles(struct lm *lm, struct lease_handle ***lease_handles);
int lm_lease_grant(struct lm *lm, struct lease_handle *lease_handle);
+int lm_lease_transfer(struct lm *lm, struct lease_handle *lease_handle);
void lm_lease_revoke(struct lm *lm, struct lease_handle *lease_handle);
#endif
diff --git a/drm-lease-manager/main.c b/drm-lease-manager/main.c
index 491c80c..78ff0df 100644
--- a/drm-lease-manager/main.c
+++ b/drm-lease-manager/main.c
@@ -27,14 +27,16 @@ static void usage(const char *progname)
printf("Usage: %s [OPTIONS] [<DRM device>]\n\n"
"Options:\n"
"-h, --help \tPrint this help\n"
- "-v, --verbose \tEnable verbose debug messages\n",
+ "-v, --verbose \tEnable verbose debug messages\n"
+ "-t, --lease-transfer \tAllow lease transfter to new clients\n",
progname);
}
-const char *opts = "vh";
+const char *opts = "vth";
const struct option options[] = {
{"help", no_argument, NULL, 'h'},
{"verbose", no_argument, NULL, 'v'},
+ {"lease-transfer", no_argument, NULL, 't'},
{NULL, 0, NULL, 0},
};
@@ -43,6 +45,7 @@ int main(int argc, char **argv)
char *device = "/dev/dri/card0";
bool debug_log = false;
+ bool can_transfer_leases = false;
int c;
while ((c = getopt_long(argc, argv, opts, options, NULL)) != -1) {
@@ -51,6 +54,9 @@ int main(int argc, char **argv)
case 'v':
debug_log = true;
break;
+ case 't':
+ can_transfer_leases = true;
+ break;
case 'h':
ret = EXIT_SUCCESS;
/* fall through */
@@ -87,6 +93,10 @@ int main(int argc, char **argv)
switch (req.type) {
case LS_REQ_GET_LEASE: {
int fd = lm_lease_grant(lm, req.lease_handle);
+
+ if (fd < 0 && can_transfer_leases)
+ fd = lm_lease_transfer(lm, req.lease_handle);
+
if (fd < 0) {
ERROR_LOG(
"Can't fulfill lease request: lease=%s\n",
@@ -95,6 +105,13 @@ int main(int argc, char **argv)
break;
}
+ struct ls_client *active_client =
+ req.lease_handle->user_data;
+ if (active_client)
+ ls_disconnect_client(ls, active_client);
+
+ req.lease_handle->user_data = req.client;
+
if (!ls_send_fd(ls, req.client, fd)) {
ERROR_LOG(
"Client communication error: lease=%s\n",
@@ -106,6 +123,7 @@ int main(int argc, char **argv)
}
case LS_REQ_RELEASE_LEASE:
ls_disconnect_client(ls, req.client);
+ req.lease_handle->user_data = NULL;
lm_lease_revoke(lm, req.lease_handle);
break;
default: