diff options
-rw-r--r-- | man/armada.man | 12 | ||||
-rw-r--r-- | src/armada_drm.c | 1 | ||||
-rw-r--r-- | src/armada_drm.h | 1 | ||||
-rw-r--r-- | src/armada_drm_xv.c | 80 |
4 files changed, 93 insertions, 1 deletions
diff --git a/man/armada.man b/man/armada.man index 94acc3f..8e2acab 100644 --- a/man/armada.man +++ b/man/armada.man @@ -120,6 +120,18 @@ Enable or disable the X Video backend. .IP Default: enabled. .TP +.BI "Option \*qXvDisablePrimary\*q \*q" boolean \*q +Allow the X Video backend to disable the primary plane when X Video +image is displayed at full screen. +.IP +.B Note: +Some kernel drivers may not fully support this (eg, the kernel driver +does a full modeset when restoring the primary plane, causing the +screen to momentarily blank.) This option should be disabled for such +kernel drivers, or the kernel driver updated to avoid such behaviour. +.IP +Default: enabled. +.TP .BI "Option \*qXvPreferOverlay\*q \*q" boolean \*q Make the hardware overlay the first XV adapter. Disabling this option makes any GPU provided textured overlay the first XV adapter. diff --git a/src/armada_drm.c b/src/armada_drm.c index 0f21493..567350d 100644 --- a/src/armada_drm.c +++ b/src/armada_drm.c @@ -36,6 +36,7 @@ const OptionInfoRec armada_drm_options[] = { { OPTION_XV_ACCEL, "XvAccel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_XV_PREFEROVL, "XvPreferOverlay", OPTV_BOOLEAN, {0}, TRUE }, + { OPTION_XV_DISPRIMARY, "XvDisablePrimary",OPTV_BOOLEAN, {0}, FALSE }, { OPTION_USE_GPU, "UseGPU", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_USE_KMS_BO, "UseKMSBo", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_ACCEL_MODULE, "AccelModule", OPTV_STRING, {0}, FALSE }, diff --git a/src/armada_drm.h b/src/armada_drm.h index ec60e73..f9a3fae 100644 --- a/src/armada_drm.h +++ b/src/armada_drm.h @@ -38,6 +38,7 @@ struct all_drm_info { enum { OPTION_XV_ACCEL, OPTION_XV_PREFEROVL, + OPTION_XV_DISPRIMARY, OPTION_USE_GPU, OPTION_USE_KMS_BO, OPTION_ACCEL_MODULE, diff --git a/src/armada_drm_xv.c b/src/armada_drm_xv.c index 5302ac6..52c9c05 100644 --- a/src/armada_drm_xv.c +++ b/src/armada_drm_xv.c @@ -65,6 +65,8 @@ struct drm_xv { Bool has_xvbo; Bool is_xvbo; Bool autopaint_colorkey; + Bool has_primary; + Bool primary_obscured; /* Cached image information */ RegionRec clipBoxes; @@ -91,9 +93,10 @@ struct drm_xv { /* Plane information */ const struct xv_image_format *plane_format; uint32_t plane_fb_id; + xf86CrtcPtr primary_crtc; drmModePlanePtr overlay_plane; unsigned int num_planes; - drmModePlanePtr mode_planes[2]; + drmModePlanePtr mode_planes[4]; struct drm_xv_prop props[NR_DRM_PROPS]; }; @@ -780,6 +783,41 @@ armada_drm_plane_fbid(ScrnInfoPtr pScrn, struct drm_xv *drmxv, int image, return Success; } +static void armada_drm_primary_plane_restore(xf86CrtcPtr crtc) +{ + struct common_drm_info *drm = GET_DRM_INFO(crtc->scrn); + struct common_crtc_info *drmc = common_crtc(crtc); + int ret; + + ret = drmModeSetPlane(drm->fd, drmc->primary_plane_id, + drmc->mode_crtc->crtc_id, drm->fb_id, 0, + crtc->x, crtc->y, + crtc->mode.HDisplay, crtc->mode.VDisplay, + 0, 0, + crtc->mode.HDisplay << 16, + crtc->mode.VDisplay << 16); + if (ret) + xf86DrvMsg(crtc->scrn->scrnIndex, X_WARNING, + "[drm] unable to restore plane %u: %s\n", + drmc->primary_plane_id, strerror(errno)); +} + +static Bool armada_drm_primary_plane_disable(xf86CrtcPtr crtc) +{ + struct common_drm_info *drm = GET_DRM_INFO(crtc->scrn); + struct common_crtc_info *drmc = common_crtc(crtc); + int ret; + + ret = drmModeSetPlane(drm->fd, drmc->primary_plane_id, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + if (ret) + xf86DrvMsg(crtc->scrn->scrnIndex, X_WARNING, + "[drm] unable to disable plane %u: %s\n", + drmc->primary_plane_id, strerror(errno)); + + return ret == 0; +} + static void armada_drm_plane_disable(ScrnInfoPtr pScrn, struct drm_xv *drmxv, drmModePlanePtr mode_plane) { @@ -798,6 +836,11 @@ armada_drm_plane_StopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup) { struct drm_xv *drmxv = data; + if (drmxv->primary_crtc) { + armada_drm_primary_plane_restore(drmxv->primary_crtc); + drmxv->primary_crtc = NULL; + } + if (drmxv->overlay_plane) { RegionEmpty(&drmxv->clipBoxes); armada_drm_plane_disable(pScrn, drmxv, drmxv->overlay_plane); @@ -824,6 +867,13 @@ static Bool armada_drm_check_plane(ScrnInfoPtr pScrn, struct drm_xv *drmxv, crtc_mask = 1 << common_crtc(crtc)->num; + if (drmxv->primary_crtc && drmxv->primary_crtc != crtc) { + /* Moved to a different CRTC */ + armada_drm_primary_plane_restore(drmxv->primary_crtc); + drmxv->primary_crtc = NULL; + drmxv->primary_obscured = FALSE; + } + if (drmxv->overlay_plane && !(drmxv->overlay_plane->possible_crtcs & crtc_mask)) { /* Moved on to a different CRTC */ @@ -888,6 +938,29 @@ armada_drm_plane_Put(ScrnInfoPtr pScrn, struct drm_xv *drmxv, uint32_t fb_id, crtc_x, crtc_y, dst->x2 - dst->x1, dst->y2 - dst->y1, x1, y1, x2 - x1, y2 - y1); + if (drmxv->has_primary) { + BoxRec crtcbox; + Bool obscured; + + crtcbox.x1 = crtc->x; + crtcbox.y1 = crtc->y; + crtcbox.x2 = crtc->x + crtc->mode.HDisplay; + crtcbox.y2 = crtc->y + crtc->mode.VDisplay; + + obscured = RegionContainsRect(clipBoxes, &crtcbox) == rgnIN; + + if (obscured && !drmxv->primary_obscured) { + if (common_crtc(crtc)->primary_plane_id && + armada_drm_primary_plane_disable(crtc)) + drmxv->primary_crtc = crtc; + } else if (!obscured && drmxv->primary_crtc) { + armada_drm_primary_plane_restore(drmxv->primary_crtc); + drmxv->primary_crtc = NULL; + } + + drmxv->primary_obscured = obscured; + } + return Success; } @@ -1129,6 +1202,8 @@ static Bool armada_drm_gather_planes(ScrnInfoPtr pScrn, struct drm_xv *drmxv) if (!common_drm_init_plane_resources(pScrn)) return FALSE; + drmxv->has_primary = drm->has_universal_planes; + for (i = 0; i < drm->num_overlay_planes && i < ARRAY_SIZE(drmxv->mode_planes); i++) { drmxv->mode_planes[drmxv->num_planes++] = @@ -1181,6 +1256,9 @@ Bool armada_drm_XvInit(ScrnInfoPtr pScrn) if (!armada_drm_gather_planes(pScrn, drmxv)) goto err_free; + if (!xf86ReturnOptValBool(arm->Options, OPTION_XV_DISPRIMARY, TRUE)) + drmxv->has_primary = FALSE; + prefer_overlay = xf86ReturnOptValBool(arm->Options, OPTION_XV_PREFEROVL, TRUE); |