[Intel-gfx] [PATCH] Enable overlay in KMS for chips not requiring phys address

Zhenyu Wang zhenyuw at linux.intel.com
Tue Jul 21 08:22:36 CEST 2009


This one trys to re-enable overlay Xv in KMS on chips like
G33 class and 965G/GM, which uses graphics address to pass in
overlay register buffer.

One drawback in KMS is that we can't get current overlay buffer
index through DOVSTA, so just stick to single buffer instead.
As overlay hw will do vblank sync anyway, this shouldn't affect
much.

This is tested on my T61 (965GM) with/without KMS.

Signed-off-by: Zhenyu Wang <zhenyuw at linux.intel.com>
---
 src/drmmode_display.c |    5 +-
 src/i830.h            |    1 +
 src/i830_driver.c     |    2 +
 src/i830_memory.c     |    3 +-
 src/i830_video.c      |  159 +++++++++++++++++++++++++++++++++++--------------
 src/i830_video.h      |    1 +
 6 files changed, 124 insertions(+), 47 deletions(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index df10fb5..e137511 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1130,7 +1130,10 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp)
 int
 drmmode_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crtc)
 {
-	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_crtc_private_ptr drmmode_crtc;
 
+	if (!crtc)
+	    return 0;
+	drmmode_crtc = crtc->driver_private;
 	return drm_intel_get_pipe_from_crtc_id (bufmgr, drmmode_crtc->mode_crtc->crtc_id);
 }
diff --git a/src/i830.h b/src/i830.h
index 21c98f5..6f81e31 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -451,6 +451,7 @@ typedef struct _I830Rec {
    XF86VideoAdaptorPtr adaptor;
    ScreenBlockHandlerProcPtr BlockHandler;
    Bool overlayOn;
+   void *overlay_ptr;
 
    struct {
       drm_intel_bo *gen4_vs_bo;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 33079fe..66b001b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3129,6 +3129,8 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen)
 
    xf86_cursors_fini (pScreen);
 
+   i830_free_video(pScrn);
+
    i830_allocator_fini(pScrn);
 
    i965_free_video(pScrn);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index cc9d376..534480f 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1291,8 +1291,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
 	i830_init_bufmgr(pScrn);
     }
 
-    if (!pI830->use_drm_mode)
-	i830_allocate_overlay(pScrn);
+    i830_allocate_overlay(pScrn);
 
     pI830->front_buffer = i830_allocate_framebuffer(pScrn);
     if (pI830->front_buffer == NULL)
diff --git a/src/i830_video.c b/src/i830_video.c
index 92b6324..5f75146 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -333,9 +333,26 @@ typedef struct {
     uint16_t RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
 } I830OverlayRegRec, *I830OverlayRegPtr;
 
-#define I830OVERLAYREG(pI830) ((I830OverlayRegPtr)\
-			       ((pI830)->FbBase + \
-				(pI830)->overlay_regs->offset))
+static void
+i830_overlay_start_access(I830Ptr pI830)
+{
+    if (pI830->use_drm_mode) {
+	drm_intel_bo_map(pI830->overlay_regs->bo, 1);
+	pI830->overlay_ptr = pI830->overlay_regs->bo->virtual;
+    } else {
+	pI830->overlay_ptr = pI830->FbBase + pI830->overlay_regs->offset;
+    }
+}
+
+static void
+i830_overlay_end_access(I830Ptr pI830)
+{
+    if (pI830->use_drm_mode) {
+	drm_intel_bo_unmap(pI830->overlay_regs->bo);
+	pI830->overlay_ptr = NULL;
+    }
+}
+
 #if VIDEO_DEBUG
 static void
 CompareOverlay(I830Ptr pI830, uint32_t * overlay, int size)
@@ -422,7 +439,7 @@ static void
 i830_overlay_on(ScrnInfoPtr pScrn)
 {
     I830Ptr		pI830 = I830PTR(pScrn);
-    I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
+    I830OverlayRegPtr	overlay = (I830OverlayRegPtr)(pI830->overlay_ptr);
     I830PortPrivPtr	pPriv = pI830->adaptor->pPortPrivates[0].ptr;
     Bool		deactivate = FALSE;
     
@@ -434,16 +451,20 @@ i830_overlay_on(ScrnInfoPtr pScrn)
      * turn on and blank the entire screen or lock up the ring. Light up pipe
      * A in this case to provide a clock for the overlay hardware
      */
-    if (pPriv->current_crtc && i830_crtc_pipe (pPriv->current_crtc) != 0)
+    if (!pI830->use_drm_mode && pPriv->current_crtc &&
+	    i830_crtc_pipe (pPriv->current_crtc) != 0)
 	deactivate = i830_pipe_a_require_activate (pScrn);
 
     overlay->OCMD &= ~OVERLAY_ENABLE;
+
+    i830_overlay_end_access(pI830);
+
     BEGIN_BATCH(6);
     OUT_BATCH(MI_FLUSH | MI_WRITE_DIRTY_STATE);
     OUT_BATCH(MI_NOOP);
     OUT_BATCH(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON);
     if (OVERLAY_NOPHYSICAL(pI830))
-	OUT_BATCH(pI830->overlay_regs->offset | OFC_UPDATE);
+	OUT_BATCH(pI830->overlay_regs->bo->offset | OFC_UPDATE);
     else
 	OUT_BATCH(pI830->overlay_regs->bus_addr | OFC_UPDATE);
     /* Wait for the overlay to light up before attempting to use it */
@@ -462,6 +483,8 @@ i830_overlay_on(ScrnInfoPtr pScrn)
     OVERLAY_DEBUG("overlay_on\n");
     pI830->overlayOn = TRUE;
 
+    i830_overlay_start_access(pI830);
+    overlay = (I830OverlayRegPtr)(pI830->overlay_ptr);
     overlay->OCMD |= OVERLAY_ENABLE;
 }
 
@@ -470,19 +493,19 @@ i830_overlay_continue(ScrnInfoPtr pScrn, Bool update_filter)
 {
     I830Ptr		pI830 = I830PTR(pScrn);
     uint32_t		flip_addr;
-    I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
 
     if (!pI830->overlayOn)
 	return;
 
     if (OVERLAY_NOPHYSICAL(pI830))
-	flip_addr = pI830->overlay_regs->offset;
+	flip_addr = pI830->overlay_regs->bo->offset;
     else
 	flip_addr = pI830->overlay_regs->bus_addr;
     if (update_filter)
 	flip_addr |= OFC_UPDATE;
-    OVERLAY_DEBUG ("overlay_continue cmd 0x%08x  -> 0x%08x sta 0x%08x\n",
-		   overlay->OCMD, INREG(OCMD_REGISTER), INREG(DOVSTA));
+
+    i830_overlay_end_access(pI830);
+
     BEGIN_BATCH(4);
     OUT_BATCH(MI_FLUSH | MI_WRITE_DIRTY_STATE);
     OUT_BATCH(MI_NOOP);
@@ -490,13 +513,15 @@ i830_overlay_continue(ScrnInfoPtr pScrn, Bool update_filter)
     OUT_BATCH(flip_addr);
     ADVANCE_BATCH();
     OVERLAY_DEBUG("overlay_continue\n");
+
+    i830_overlay_start_access(pI830);
 }
 
 static void
 i830_overlay_off(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
+    I830OverlayRegPtr overlay = (I830OverlayRegPtr)(pI830->overlay_ptr);
 
     if (!pI830->overlayOn)
 	return;
@@ -521,6 +546,8 @@ i830_overlay_off(ScrnInfoPtr pScrn)
      */
     {
 	overlay->OCMD &= ~OVERLAY_ENABLE;
+	i830_overlay_end_access(pI830);
+
 	OVERLAY_DEBUG ("overlay_off cmd 0x%08x -> 0x%08x sta 0x%08x\n",
 		       overlay->OCMD, INREG(OCMD_REGISTER), INREG(DOVSTA));
 	BEGIN_BATCH(6);
@@ -528,7 +555,7 @@ i830_overlay_off(ScrnInfoPtr pScrn)
 	OUT_BATCH(MI_NOOP);
 	OUT_BATCH(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
 	if (OVERLAY_NOPHYSICAL(pI830))
-	    OUT_BATCH(pI830->overlay_regs->offset);
+	    OUT_BATCH(pI830->overlay_regs->bo->offset);
 	else
 	    OUT_BATCH(pI830->overlay_regs->bus_addr);
 	OUT_BATCH(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
@@ -537,6 +564,7 @@ i830_overlay_off(ScrnInfoPtr pScrn)
 	I830Sync(pScrn);
     }
     pI830->overlayOn = FALSE;
+    i830_overlay_start_access(pI830);
     OVERLAY_DEBUG("overlay_off\n");
 }
 
@@ -600,7 +628,8 @@ 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)
+	(!pI830->use_drm_mode || OVERLAY_NOPHYSICAL(pI830)) &&
+	pI830->overlay_regs != NULL)
     {
 	overlayAdaptor = I830SetupImageVideoOverlay(pScreen);
 	if (overlayAdaptor != NULL) {
@@ -648,7 +677,8 @@ I830ResetVideo(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
-    I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
+    I830OverlayRegPtr overlay = (I830OverlayRegPtr)(pI830->overlay_ptr);
+    int pipe;
 
     OVERLAY_DEBUG("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n",
 		  pI830->FbBase, pI830->overlay_regs->offset, overlay);
@@ -707,7 +737,11 @@ I830ResetVideo(ScrnInfoPtr pScrn)
      * Select which pipe the overlay is enabled on.
      */
     overlay->OCONFIG &= ~OVERLAY_PIPE_MASK;
-    if (i830_crtc_pipe (pPriv->current_crtc) == 0)
+    if (!pI830->use_drm_mode)
+	pipe = i830_crtc_pipe(pPriv->current_crtc);
+    else
+	pipe = drmmode_get_pipe_from_crtc_id(pI830->bufmgr, pPriv->current_crtc);
+    if (pipe == 0)
 	overlay->OCONFIG |= OVERLAY_PIPE_A;
     else 
 	overlay->OCONFIG |= OVERLAY_PIPE_B;
@@ -906,7 +940,13 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen)
     pPriv->gamma2 = 0x202020;
     pPriv->gamma1 = 0x101010;
     pPriv->gamma0 = 0x080808;
-    pPriv->doubleBuffer = 1;
+
+    /* in KMS we can't get current buffer index, so
+       just fall back to single buffer */
+    if (pI830->use_drm_mode)
+	pPriv->doubleBuffer = 0;
+    else
+	pPriv->doubleBuffer = 1;
 
     pPriv->rotation = RR_Rotate_0;
 
@@ -946,9 +986,21 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen)
 	xvGamma5 = MAKE_ATOM("XV_GAMMA5");
     }
 
+    if (pI830->use_drm_mode &&
+	(drm_intel_bo_pin(pI830->overlay_regs->bo, 4096) != 0)) {
+	xfree(adapt->pAttributes);
+	xfree(adapt);
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		"Failed to bind overlay register bo!\n");
+	return NULL;
+    }
+
+    i830_overlay_start_access(pI830);
+
     I830ResetVideo(pScrn);
 
-    I830UpdateGamma(pScrn);
+    if (!pI830->use_drm_mode)
+	I830UpdateGamma(pScrn);
 
     return adapt;
 }
@@ -1094,9 +1146,7 @@ I830SetPortAttributeOverlay(ScrnInfoPtr pScrn,
 {
     I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
     I830Ptr pI830 = I830PTR(pScrn);
-    I830OverlayRegPtr overlay;
-
-    overlay = I830OVERLAYREG(pI830);
+    I830OverlayRegPtr overlay = (I830OverlayRegPtr)(pI830->overlay_ptr);
 
     if (attribute == xvBrightness) {
 	if ((value < -128) || (value > 127))
@@ -1174,7 +1224,8 @@ I830SetPortAttributeOverlay(ScrnInfoPtr pScrn,
 	 attribute == xvGamma4 ||
 	 attribute == xvGamma5) && (IS_I9XX(pI830))) {
 	OVERLAY_DEBUG("GAMMA\n");
-	I830UpdateGamma(pScrn);
+	if (!pI830->use_drm_mode)
+	    I830UpdateGamma(pScrn);
     }
 
     return Success;
@@ -1261,7 +1312,7 @@ I830CopyPackedData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv,
 
     src = buf + (top * srcPitch) + (left << 1);
 
-    if (pPriv->textured) {
+    if (pPriv->textured || pI830->use_drm_mode) {
 	drm_intel_bo_map(pPriv->buf, TRUE);
 	dst_base = pPriv->buf->virtual;
     } else {
@@ -1346,7 +1397,7 @@ I830CopyPackedData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv,
 	break;
     }
 
-    if (pPriv->textured)
+    if (pPriv->textured || pI830->use_drm_mode)
 	drm_intel_bo_unmap(pPriv->buf);
 }
 
@@ -1376,7 +1427,7 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv,
 	   (unsigned long)src1 - (unsigned long)buf);
 #endif
 
-    if (pPriv->textured) {
+    if (pPriv->textured || pI830->use_drm_mode) {
 	drm_intel_bo_map(pPriv->buf, TRUE);
 	dst_base = pPriv->buf->virtual;
     } else {
@@ -1556,7 +1607,7 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv,
 	break;
     }
 
-    if (pPriv->textured)
+    if (pPriv->textured || pI830->use_drm_mode)
 	drm_intel_bo_unmap(pPriv->buf);
 }
 
@@ -1981,12 +2032,13 @@ i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
 {
     I830Ptr		pI830 = I830PTR(pScrn);
     I830PortPrivPtr	pPriv = pI830->adaptor->pPortPrivates[0].ptr;
-    I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
+    I830OverlayRegPtr	overlay = (I830OverlayRegPtr)(pI830->overlay_ptr);
     unsigned int	swidth, swidthy, swidthuv;
     unsigned int	mask, shift, offsety, offsetu;
     int			tmp;
     uint32_t		OCMD;
     Bool		scaleChanged = FALSE;
+    int			buf_offset;
 
     OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
 		  dstPitch);
@@ -2007,7 +2059,11 @@ i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
     
     if (crtc != pPriv->current_crtc)
     {
-	i830_overlay_switch_to_crtc (pScrn, crtc);
+	if (!pI830->use_drm_mode)
+	    i830_overlay_switch_to_crtc (pScrn, crtc);
+	else
+	    pPriv->overlayOK = TRUE;
+
 	if (pPriv->overlayOK) {
 	    pPriv->current_crtc = crtc;
 	    I830ResetVideo (pScrn);
@@ -2048,12 +2104,20 @@ i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
 	mask = 0x1f;
     }
 
+    /* Add on pinned xv buffer offset, as we didn't
+       account it in PutImage, so xv data copy can just
+       map xv buffer. */
+    if (pI830->use_drm_mode)
+	buf_offset = pPriv->buf->offset;
+    else
+	buf_offset = 0;
+
     if (pPriv->currentBuf == 0) {
-	offsety = pPriv->YBuf0offset;
-	offsetu = pPriv->UBuf0offset;
+	offsety = pPriv->YBuf0offset + buf_offset;
+	offsetu = pPriv->UBuf0offset + buf_offset;
     } else {
-	offsety = pPriv->YBuf1offset;
-	offsetu = pPriv->UBuf1offset;
+	offsety = pPriv->YBuf1offset + buf_offset;
+	offsetu = pPriv->UBuf1offset + buf_offset;
     }
 
     switch (id) {
@@ -2098,13 +2162,13 @@ i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
 		  dstBox->x1, dstBox->y1, dstBox->x2, dstBox->y2);
 
     /* buffer locations */
-    overlay->OBUF_0Y = pPriv->YBuf0offset;
-    overlay->OBUF_0U = pPriv->UBuf0offset;
-    overlay->OBUF_0V = pPriv->VBuf0offset;
+    overlay->OBUF_0Y = pPriv->YBuf0offset + buf_offset;
+    overlay->OBUF_0U = pPriv->UBuf0offset + buf_offset;
+    overlay->OBUF_0V = pPriv->VBuf0offset + buf_offset;
     if(pPriv->doubleBuffer) {
-	overlay->OBUF_1Y = pPriv->YBuf1offset;
-	overlay->OBUF_1U = pPriv->UBuf1offset;
-	overlay->OBUF_1V = pPriv->VBuf1offset;
+	overlay->OBUF_1Y = pPriv->YBuf1offset + buf_offset;
+	overlay->OBUF_1U = pPriv->UBuf1offset + buf_offset;
+	overlay->OBUF_1V = pPriv->VBuf1offset + buf_offset;
     }
 
     OVERLAY_DEBUG("pos: 0x%x, size: 0x%x\n",
@@ -2266,7 +2330,6 @@ I830PutImage(ScrnInfoPtr pScrn,
     I830Ptr pI830 = I830PTR(pScrn);
     I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
     ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-    I830OverlayRegPtr overlay;
     PixmapPtr pPixmap = get_drawable_pixmap(pDraw);;
     INT32 x1, x2, y1, y2;
     int srcPitch = 0, srcPitch2 = 0, dstPitch, destId;
@@ -2277,11 +2340,6 @@ I830PutImage(ScrnInfoPtr pScrn,
     int alloc_size;
     xf86CrtcPtr	crtc;
 
-    if (pPriv->textured)
-	overlay = NULL;
-    else
-	overlay = I830OVERLAYREG(pI830);
-
 #if 0
     ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n"
 	   "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x, drw_y,
@@ -2454,7 +2512,7 @@ I830PutImage(ScrnInfoPtr pScrn,
 	destId = FOURCC_YV12;
     } else {
 #endif
-	if (pPriv->textured)
+	if (pPriv->textured || pI830->use_drm_mode)
 	    pPriv->YBuf0offset = 0;
 	else
 	    pPriv->YBuf0offset = pPriv->buf->offset;
@@ -2948,3 +3006,16 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on)
 	pPriv->oneLineMode = FALSE;
     }
 }
+
+void
+i830_free_video(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    /* no overlay */
+    if (pI830->adaptor == NULL)
+	return;
+
+    i830_overlay_end_access(pI830);
+    drm_intel_bo_unpin(pI830->overlay_regs->bo);
+}
diff --git a/src/i830_video.h b/src/i830_video.h
index 03e2ba9..d6b8e99 100644
--- a/src/i830_video.h
+++ b/src/i830_video.h
@@ -91,3 +91,4 @@ void I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv,
 void I830VideoBlockHandler(int i, pointer blockData, pointer pTimeout,
 			   pointer pReadmask);
 void i965_free_video(ScrnInfoPtr scrn);
+void i830_free_video(ScrnInfoPtr scrn);
-- 
1.5.3.8




More information about the Intel-gfx mailing list