summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk@armlinux.org.uk>2017-02-25 11:36:16 +0000
committerRussell King <rmk@armlinux.org.uk>2017-02-25 17:16:16 +0000
commite88e6b76947d0720395a19e316c7013e9b61d439 (patch)
treef2e780b93ea6e7ef5678f96467c04401acae38b1
parentba91654fb427f8dd86e9a53f42a93e2c5dc39bf6 (diff)
src: Xv: add support for disabling the primary plane
When Xv video is being displayed at full screen, and the video is completely unobscured, there is no point having the primary plane enabled; this wastes system bus bandwidth as the display hardware has to read the primary plane to check the colorkey. Disable the primary plane in this case, restoring it when the primary plane becomes visible once again. This results in a gain of CPU performance of about 20% when video is displayed at full screen on the Dove Cubox. Signed-off-by: Russell King <rmk@armlinux.org.uk>
-rw-r--r--man/armada.man12
-rw-r--r--src/armada_drm.c1
-rw-r--r--src/armada_drm.h1
-rw-r--r--src/armada_drm_xv.c80
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);