diff options
-rw-r--r-- | README.md | 20 | ||||
-rw-r--r-- | drm-lease-manager/drm-lease.h | 1 | ||||
-rw-r--r-- | drm-lease-manager/lease-manager.c | 22 | ||||
-rw-r--r-- | drm-lease-manager/lease-manager.h | 1 | ||||
-rw-r--r-- | drm-lease-manager/main.c | 22 |
5 files changed, 64 insertions, 2 deletions
@@ -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: |