diff options
author | Keith Packard <keithp@keithp.com> | 2018-07-11 19:13:28 +0200 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2018-07-12 18:13:34 +0200 |
commit | f533b1f654952cee794de49d28d01947a6571daf (patch) | |
tree | 1708cf691e13e00e66fc278df40935aa45d7acb9 | |
parent | b4f0f44a9f67f2eafd4a2b5ab919e6ea7fa2acf7 (diff) |
Add RandR leases support
Signed-off-by: Keith Packard <keithp@keithp.com>
(Ported from xserver commit e4e3447603b5fd3a38a92c3f972396d1f81168ad)
Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
(Ported from amdgpu commit 61040bdfa360975614fb47aa7ea1b3a1abac3427)
Acked-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/drmmode_display.c | 159 | ||||
-rw-r--r-- | src/drmmode_display.h | 6 | ||||
-rw-r--r-- | src/radeon_kms.c | 1 |
4 files changed, 166 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac index 65206e7f..15c7b212 100644 --- a/configure.ac +++ b/configure.ac @@ -70,7 +70,7 @@ XORG_DRIVER_CHECK_EXT(XV, videoproto) XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto) # Checks for libraries. -PKG_CHECK_MODULES(LIBDRM, [libdrm >= 2.4.78]) +PKG_CHECK_MODULES(LIBDRM, [libdrm >= 2.4.89]) PKG_CHECK_MODULES(LIBDRM_RADEON, [libdrm_radeon]) # Obtain compiler/linker options for the driver dependencies diff --git a/src/drmmode_display.c b/src/drmmode_display.c index d4bd76e1..2af64e3f 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -2400,8 +2400,159 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) return FALSE; } +static void +drmmode_validate_leases(ScrnInfoPtr scrn) +{ +#ifdef XF86_LEASE_VERSION + ScreenPtr screen = scrn->pScreen; + rrScrPrivPtr scr_priv = rrGetScrPriv(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + drmModeLesseeListPtr lessees; + RRLeasePtr lease, next; + int l; + + /* We can't talk to the kernel about leases when VT switched */ + if (!scrn->vtSema) + return; + + lessees = drmModeListLessees(pRADEONEnt->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); +#endif +} + +#ifdef XF86_LEASE_VERSION + +static int +drmmode_create_lease(RRLeasePtr lease, int *fd) +{ + ScreenPtr screen = lease->screen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + drmmode_lease_private_ptr lease_private; + int noutput = lease->numOutputs; + int ncrtc = lease->numCrtcs; + uint32_t *objects; + size_t nobjects; + int lease_fd; + int c, o; + int i; + + nobjects = ncrtc + noutput; + if (nobjects == 0 || nobjects > (SIZE_MAX / 4) || + ncrtc > (SIZE_MAX - noutput)) + return BadValue; + + lease_private = calloc(1, sizeof (drmmode_lease_private_rec)); + if (!lease_private) + return BadAlloc; + + objects = malloc(nobjects * 4); + 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 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; + } + + /* call kernel to create lease */ + assert (i == nobjects); + + lease_fd = drmModeCreateLease(pRADEONEnt->fd, objects, nobjects, 0, + &lease_private->lessee_id); + + free(objects); + + if (lease_fd < 0) { + free(lease_private); + return BadMatch; + } + + lease->devPrivate = lease_private; + + xf86CrtcLeaseStarted(lease); + + *fd = lease_fd; + return Success; +} + +static void +drmmode_terminate_lease(RRLeasePtr lease) +{ + drmmode_lease_private_ptr lease_private = lease->devPrivate; + ScreenPtr screen = lease->screen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + + if (drmModeRevokeLease(pRADEONEnt->fd, lease_private->lessee_id) == 0) { + free(lease_private); + lease->devPrivate = NULL; + xf86CrtcLeaseTerminated(lease); + } +} + +#endif // XF86_LEASE_VERSION + +void +drmmode_terminate_leases(ScrnInfoPtr pScrn) +{ +#ifdef XF86_LEASE_VERSION + ScreenPtr screen = xf86ScrnToScreen(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + rrScrPrivPtr scr_priv = rrGetScrPriv(screen); + RRLeasePtr lease, next; + + xorg_list_for_each_entry_safe(lease, next, &scr_priv->leases, list) { + drmmode_lease_private_ptr lease_private = lease->devPrivate; + drmModeRevokeLease(pRADEONEnt->fd, lease_private->lessee_id); + free(lease_private); + lease->devPrivate = NULL; + RRLeaseTerminated(lease); + RRLeaseFree(lease); + } +#endif +} + static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { - drmmode_xf86crtc_resize + .resize = drmmode_xf86crtc_resize, +#ifdef XF86_LEASE_VERSION + .create_lease = drmmode_create_lease, + .terminate_lease = drmmode_terminate_lease +#endif }; static void @@ -2888,6 +3039,9 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, return FALSE; } + /* Validate leases on VT re-entry */ + drmmode_validate_leases(pScrn); + return TRUE; } @@ -3055,6 +3209,9 @@ restart_destroy: changed = TRUE; } + /* Check to see if a lessee has disappeared */ + drmmode_validate_leases(scrn); + if (changed && dixPrivateKeyRegistered(rrPrivKey)) { #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0) RRSetChanged(xf86ScrnToScreen(scrn)); diff --git a/src/drmmode_display.h b/src/drmmode_display.h index 27c23c1a..4551e0c7 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -139,6 +139,10 @@ typedef struct { int tear_free; } drmmode_output_private_rec, *drmmode_output_private_ptr; +typedef struct { + uint32_t lessee_id; +} drmmode_lease_private_rec, *drmmode_lease_private_ptr; + enum drmmode_flip_sync { FLIP_VSYNC, @@ -223,6 +227,8 @@ PixmapPtr drmmode_crtc_scanout_create(xf86CrtcPtr crtc, extern void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode); extern void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode); +extern void drmmode_terminate_leases(ScrnInfoPtr scrn); + Bool drmmode_set_mode(xf86CrtcPtr crtc, struct drmmode_fb *fb, DisplayModePtr mode, int x, int y); diff --git a/src/radeon_kms.c b/src/radeon_kms.c index 36840ad3..c8a5726a 100644 --- a/src/radeon_kms.c +++ b/src/radeon_kms.c @@ -2154,6 +2154,7 @@ static Bool RADEONCloseScreen_KMS(ScreenPtr pScreen) /* Clear mask of assigned crtc's in this generation */ pRADEONEnt->assigned_crtcs = 0; + drmmode_terminate_leases(pScrn); drmmode_uevent_fini(pScrn, &info->drmmode); radeon_drm_queue_close(pScrn); radeon_cs_flush_indirect(pScrn); |