summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2009-08-11 16:06:47 +0200
committerEric Anholt <eric@anholt.net>2009-10-05 13:17:47 -0700
commit2370af32fe31bed8e5715639023635bdb3b83b1b (patch)
tree625a04265ee42a8db35516ca3e4dfabe854f8524 /src
parent99230864050ea2f26c2412c4c87c50947fc3cbe1 (diff)
Implement drmmode overlay
This does not restore the overlay on EnterVT/disable it on LeaveVT. Does not look like this is necessary. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> [anholt: Hacked in avoiding the actual kernel calls with Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'src')
-rw-r--r--src/drmmode_display.c9
-rw-r--r--src/i830.h3
-rw-r--r--src/i830_driver.c2
-rw-r--r--src/i830_video.c202
4 files changed, 196 insertions, 20 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index e8a6c018..00b17dcb 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1415,3 +1415,12 @@ drmmode_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crtc)
return drm_intel_get_pipe_from_crtc_id (bufmgr, drmmode_crtc->mode_crtc->crtc_id);
}
+
+/* for the drmmode overlay */
+int
+drmmode_crtc_id(xf86CrtcPtr crtc)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ return drmmode_crtc->mode_crtc->crtc_id;
+}
diff --git a/src/i830.h b/src/i830.h
index 009641ad..c84fd0c5 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -388,7 +388,7 @@ typedef struct _I830Rec {
/* For Xvideo */
i830_memory *overlay_regs;
- void *offscreenImages; /**< remembered memory block for release */
+ Bool use_drmmode_overlay;
#ifdef INTEL_XVMC
/* For XvMC */
Bool XvMCEnabled;
@@ -693,6 +693,7 @@ void I830DRI2CloseScreen(ScreenPtr pScreen);
extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp);
extern int drmmode_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crtc);
extern int drmmode_output_dpms_status(xf86OutputPtr output);
+extern int drmmode_crtc_id(xf86CrtcPtr crtc);
void
drmmode_crtc_set_cursor_bo(xf86CrtcPtr crtc, dri_bo *cursor);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 316a1fa1..585eb811 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3088,8 +3088,6 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen)
i830_allocator_fini(pScrn);
i965_free_video(pScrn);
- free(pI830->offscreenImages);
- pI830->offscreenImages = NULL;
pScreen->CloseScreen = pI830->CloseScreen;
(*pScreen->CloseScreen) (scrnIndex, pScreen);
diff --git a/src/i830_video.c b/src/i830_video.c
index 80f73034..5e98f27f 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -356,6 +356,150 @@ CompareOverlay(I830Ptr pI830, uint32_t * overlay, int size)
static void
I830SetOneLineModeRatio(ScrnInfoPtr pScrn);
+/* kernel modesetting overlay functions */
+static Bool
+drmmode_has_overlay(ScrnInfoPtr pScrn)
+{
+#ifdef DRM_MODE_OVERLAY_LANDED
+ I830Ptr p830 = I830PTR(pScrn);
+ struct drm_i915_getparam gp;
+ int has_overlay = 0;
+
+ gp.param = I915_PARAM_HAS_OVERLAY;
+ gp.value = &has_overlay;
+ drmCommandWriteRead(p830->drmSubFD, DRM_I915_GETPARAM,
+ &gp, sizeof(gp));
+
+ return has_overlay ? TRUE : FALSE;
+#else
+ return FALSE;
+#endif
+}
+
+static void
+drmmode_overlay_update_attrs(ScrnInfoPtr pScrn)
+{
+#ifdef DRM_MODE_OVERLAY_LANDED
+ I830Ptr p830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
+ struct drm_intel_overlay_attrs attrs;
+ int ret;
+
+ attrs.flags = I915_OVERLAY_UPDATE_ATTRS;
+ attrs.brightness = pPriv->brightness;
+ attrs.contrast = pPriv->contrast;
+ attrs.saturation = pPriv->saturation;
+ attrs.color_key = pPriv->colorKey;
+ attrs.gamma0 = pPriv->gamma0;
+ attrs.gamma1 = pPriv->gamma1;
+ attrs.gamma2 = pPriv->gamma2;
+ attrs.gamma3 = pPriv->gamma3;
+ attrs.gamma4 = pPriv->gamma4;
+ attrs.gamma5 = pPriv->gamma5;
+
+ ret = drmCommandWriteRead(p830->drmSubFD, DRM_I915_OVERLAY_ATTRS,
+ &attrs, sizeof(attrs));
+
+ if (ret != 0)
+ OVERLAY_DEBUG("overlay attrs ioctl failed: %i\n", ret);
+#endif
+}
+
+static void
+drmmode_overlay_off(ScrnInfoPtr pScrn)
+{
+#ifdef DRM_MODE_OVERLAY_LANDED
+ I830Ptr p830 = I830PTR(pScrn);
+ struct drm_intel_overlay_put_image request;
+ int ret;
+
+ request.flags = 0;
+
+ ret = drmCommandWrite(p830->drmSubFD, DRM_I915_OVERLAY_PUT_IMAGE,
+ &request, sizeof(request));
+
+ if (ret != 0)
+ OVERLAY_DEBUG("overlay switch-off ioctl failed: %i\n", ret);
+#endif
+}
+
+static Bool
+drmmode_overlay_put_image(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
+ int id, short width, short height,
+ int dstPitch, int x1, int y1, int x2, int y2, BoxPtr dstBox,
+ short src_w, short src_h, short drw_w, short drw_h)
+{
+#ifdef DRM_MODE_OVERLAY_LANDED
+ I830Ptr p830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
+ struct drm_intel_overlay_put_image request;
+ int ret;
+ int planar = is_planar_fourcc(id);
+ float scale;
+
+ request.flags = I915_OVERLAY_ENABLE;
+
+ request.bo_handle = pPriv->buf->handle;
+ if (planar) {
+ request.stride_Y = dstPitch*2;
+ request.stride_UV = dstPitch;
+ } else {
+ request.stride_Y = dstPitch;
+ request.stride_UV = 0;
+ }
+ request.offset_Y = pPriv->YBufOffset;
+ request.offset_U = pPriv->UBufOffset;
+ request.offset_V = pPriv->VBufOffset;
+ OVERLAY_DEBUG("off_Y: %i, off_U: %i, off_V: %i\n", request.offset_Y,
+ request.offset_U, request.offset_V);
+
+ request.crtc_id = drmmode_crtc_id(crtc);
+ request.dst_x = dstBox->x1;
+ request.dst_y = dstBox->y1;
+ request.dst_width = dstBox->x2 - dstBox->x1;
+ request.dst_height = dstBox->y2 - dstBox->y1;
+
+ request.src_width = width;
+ request.src_height = height;
+ /* adjust src dimensions */
+ if (request.dst_height > 1) {
+ scale = ((float) request.dst_height - 1) / ((float) drw_h - 1);
+ request.src_scan_height = src_h * scale;
+ } else
+ request.src_scan_height = 1;
+
+ if (request.dst_width > 1) {
+ scale = ((float) request.dst_width - 1) / ((float) drw_w - 1);
+ request.src_scan_width = src_w * scale;
+ } else
+ request.src_scan_width = 1;
+
+ if (planar) {
+ request.flags |= I915_OVERLAY_YUV_PLANAR | I915_OVERLAY_YUV420;
+ } else {
+ request.flags |= I915_OVERLAY_YUV_PACKED | I915_OVERLAY_YUV422;
+ if (id == FOURCC_UYVY)
+ request.flags |= I915_OVERLAY_Y_SWAP;
+ }
+
+ ret = drmCommandWrite(p830->drmSubFD, DRM_I915_OVERLAY_PUT_IMAGE,
+ &request, sizeof(request));
+
+ /* drop the newly displaying buffer right away */
+ drm_intel_bo_disable_reuse(pPriv->buf);
+ drm_intel_bo_unreference(pPriv->buf);
+ pPriv->buf = NULL;
+
+ if (ret != 0) {
+ OVERLAY_DEBUG("overlay put-image ioctl failed: %i\n", ret);
+ return FALSE;
+ } else
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
static void
i830_overlay_switch_to_crtc (ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
{
@@ -597,15 +741,18 @@ I830InitVideo(ScreenPtr pScreen)
}
/* Set up overlay video if we can do it at this depth. */
- if (!OVERLAY_NOEXIST(pI830) && pScrn->bitsPerPixel != 8 &&
- !pI830->use_drm_mode && pI830->overlay_regs != NULL)
+ if (!OVERLAY_NOEXIST(pI830) && pScrn->bitsPerPixel != 8)
{
- overlayAdaptor = I830SetupImageVideoOverlay(pScreen);
- if (overlayAdaptor != NULL) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n");
- } else {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Failed to set up overlay video\n");
+ pI830->use_drmmode_overlay = drmmode_has_overlay(pScrn);
+ if ((!pI830->use_drm_mode && pI830->overlay_regs != NULL)
+ || pI830->use_drmmode_overlay) {
+ overlayAdaptor = I830SetupImageVideoOverlay(pScreen);
+ if (overlayAdaptor != NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to set up overlay video\n");
+ }
}
}
@@ -942,9 +1089,12 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen)
xvGamma5 = MAKE_ATOM("XV_GAMMA5");
}
- /* XXX These two access the overlay regs, dont call with drmmode */
- I830ResetVideo(pScrn);
- I830UpdateGamma(pScrn);
+ if (pI830->use_drmmode_overlay)
+ drmmode_overlay_update_attrs(pScrn);
+ else {
+ I830ResetVideo(pScrn);
+ I830UpdateGamma(pScrn);
+ }
return adapt;
}
@@ -1052,6 +1202,7 @@ static void
I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
{
I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
+ I830Ptr pI830 = I830PTR(pScrn);
if (pPriv->textured)
return;
@@ -1062,7 +1213,10 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
if (shutdown) {
if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
- ums_overlay_off(pScrn);
+ if (pI830->use_drmmode_overlay)
+ drmmode_overlay_off(pScrn);
+ else
+ ums_overlay_off(pScrn);
}
i830_free_video_buffers(pPriv);
@@ -1191,7 +1345,10 @@ I830SetPortAttributeOverlay(ScrnInfoPtr pScrn,
OVERLAY_DEBUG("GAMMA\n");
}
- ums_overlay_update_attrs(pScrn, pPriv);
+ if (pI830->use_drmmode_overlay)
+ drmmode_overlay_update_attrs(pScrn);
+ else
+ ums_overlay_update_attrs(pScrn, pPriv);
if (attribute == xvColorKey)
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
@@ -2108,7 +2265,11 @@ i830_display_overlay(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
if (!crtc)
{
pPriv->current_crtc = NULL;
- ums_overlay_off(pScrn);
+ if (pI830->use_drmmode_overlay)
+ drmmode_overlay_off(pScrn);
+ else
+ ums_overlay_off(pScrn);
+
return TRUE;
}
@@ -2126,8 +2287,12 @@ i830_display_overlay(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
src_h = tmp;
}
- return ums_overlay_put_image(pScrn, crtc, id, width, height, dstPitch,
- x1, y1, x2, y2, dstBox, src_w, src_h, drw_w, drw_h);
+ if (pI830->use_drmmode_overlay)
+ return drmmode_overlay_put_image(pScrn, crtc, id, width, height, dstPitch,
+ x1, y1, x2, y2, dstBox, src_w, src_h, drw_w, drw_h);
+ else
+ return ums_overlay_put_image(pScrn, crtc, id, width, height, dstPitch,
+ x1, y1, x2, y2, dstBox, src_w, src_h, drw_w, drw_h);
}
static Bool
@@ -2636,7 +2801,10 @@ I830VideoBlockHandler(int i, pointer blockData, pointer pTimeout,
/* Turn off the overlay */
OVERLAY_DEBUG("BLOCKHANDLER\n");
- ums_overlay_off (pScrn);
+ if (pI830->use_drmmode_overlay)
+ drmmode_overlay_off(pScrn);
+ else
+ ums_overlay_off (pScrn);
pPriv->videoStatus = FREE_TIMER;
pPriv->freeTime = now + FREE_DELAY;