aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamian Hobson-Garcia <dhobsong@igel.co.jp>2021-03-09 14:58:22 +0900
committerDamian Hobson-Garcia <dhobsong@igel.co.jp>2021-04-06 10:33:11 +0900
commitbdf7c337439ff0b70b67462c1f00f5b61942e76a (patch)
tree81110462b242a62db0d09d1ef6bfdb22ad9b0802
parentecaaf9e2ad40181d916049510823ce8557ecd91e (diff)
Add support for lease transition
When enabled allow the ownership of a lease to transition from one client to another. If a request is made for a lease that is already allocated to a client, revoke the lease from the old client and issue a new lease for the same resources to the new client. This allows the ownership of the leased resources to be transferred without the display being closed and the screen blanking. During the tranistion, hold a reference to the old clients lease fd so that the last frame presented by the old client will remain on screen until the new client presents its first frame. Currenly there is no notification or authentication mechanism implemeted for the transition. Any client can request a transition from any other. The only notification that a transfer has happened is that the previous client's DRM API calls will suddenly fail with -ENOENT, since all resources will have been removed. It is up to the client to sensibly handle this condition. Bug-AGL: SPEC-3816 Change-Id: Iaff87e275f909f3b6ef448df39364d6fe62007b1 Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-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: