xf86-video-intel: src/i830_video.c

Keith Packard keithp at kemper.freedesktop.org
Fri May 25 20:30:20 PDT 2007


 src/i830_video.c |  293 +++++++++++++++++++++++++++----------------------------
 1 files changed, 148 insertions(+), 145 deletions(-)

New commits:
diff-tree ff8c8cb869a3c780dbd826f7c94f06e4f3fda6af (from 33f635d79fe891079558fd909d564f3cf424c482)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Fri May 25 20:29:59 2007 -0700

    Compute and clip to crtc before call to xf86XVClipVideoHelper.
    
    By clipping to the crtc ahead of time, xf86XVClipVideoHelper will
    correctly clip to the bounds of the crtc, eliminating the need for any
    custom crtc clipping.
    
    Also, replace the broken xf86XVFillKeyHelper with a private version that
    doesn't end up stuck with the wrong clip list when the root window changes
    size.

diff --git a/src/i830_video.c b/src/i830_video.c
index c2d3b4b..d57519b 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1636,38 +1636,35 @@ UpdateCoeff(int taps, double fCutoff, Bo
     }
 }
 
-/*
- * Return the number of pixels from 'box' covered by 'crtc'.
- * That is, the area of the intersection of 'box' and 'crtc'
- */
-static int
-I830CrtcBoxCoverage (xf86CrtcPtr crtc, BoxPtr box)
+static void
+i830_box_intersect (BoxPtr dest, BoxPtr a, BoxPtr b)
 {
-    BoxRec   dest;
-    BoxRec   pipe;
+    dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
+    dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
+    dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
+    dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
+    if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
+	dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
+}
 
+static void
+i830_crtc_box (xf86CrtcPtr crtc, BoxPtr crtc_box)
+{
     if (crtc->enabled)
     {
-	pipe.x1 = crtc->x;
-	pipe.x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
-	pipe.y1 = crtc->y;
-	pipe.y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
+	crtc_box->x1 = crtc->x;
+	crtc_box->x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
+	crtc_box->y1 = crtc->y;
+	crtc_box->y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
     }
     else
-    {
-	pipe.x1 = pipe.x2 = 0;
-	pipe.y1 = pipe.y2 = 0;
-    }
-    dest.x1 = pipe.x1 > box->x1 ? pipe.x1 : box->x1;
-    dest.x2 = pipe.x2 < box->x2 ? pipe.x2 : box->x2;
-    dest.y1 = pipe.y1 > box->y1 ? pipe.y1 : box->y1;
-    dest.y2 = pipe.y2 < box->y2 ? pipe.y2 : box->y2;
-    if (dest.x1 >= dest.x2 || dest.y1 >= dest.y2)
-    {
-	dest.x1 = dest.x2 = 0;
-	dest.y1 = dest.y2 = 0;
-    }
-    return (int) (dest.x2 - dest.x1) * (int) (dest.y2 - dest.y1);
+	crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
+}
+
+static int
+i830_box_area (BoxPtr box)
+{
+    return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
 }
 
 /*
@@ -1677,21 +1674,28 @@ I830CrtcBoxCoverage (xf86CrtcPtr crtc, B
  */
 
 static xf86CrtcPtr
-I830CoveringCrtc (ScrnInfoPtr pScrn, BoxPtr pBox, xf86CrtcPtr desired)
+i830_covering_crtc (ScrnInfoPtr pScrn,
+		    BoxPtr	box,
+		    xf86CrtcPtr desired,
+		    BoxPtr	crtc_box_ret)
 {
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     xf86CrtcPtr		crtc, best_crtc;
     int			coverage, best_coverage;
     int			c;
+    BoxRec		crtc_box, cover_box;
 
     best_crtc = NULL;
     best_coverage = 0;
     for (c = 0; c < xf86_config->num_crtc; c++)
     {
 	crtc = xf86_config->crtc[c];
-	coverage = I830CrtcBoxCoverage (crtc, pBox);
+	i830_crtc_box (crtc, &crtc_box);
+	i830_box_intersect (&cover_box, &crtc_box, box);
+	coverage = i830_box_area (&cover_box);
 	if (coverage > best_coverage)
 	{
+	    *crtc_box_ret = crtc_box;
 	    if (crtc == desired)
 		return crtc;
 	    best_crtc = crtc;
@@ -1713,19 +1717,19 @@ i830_swidth (I830Ptr pI830, unsigned int
 }
 
 static void
-I830DisplayVideo(ScrnInfoPtr pScrn, 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)
+i830_display_video(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)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+    I830Ptr		pI830 = I830PTR(pScrn);
+    I830PortPrivPtr	pPriv = pI830->adaptor->pPortPrivates[0].ptr;
     I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
-    unsigned int swidth, swidthy, swidthuv;
-    unsigned int mask, shift, offsety, offsetu;
-    xf86CrtcPtr crtc;
-    int		tmp;
-    CARD32	OCMD;
-    Bool	scaleChanged = FALSE;
+    unsigned int	swidth, swidthy, swidthuv;
+    unsigned int	mask, shift, offsety, offsetu;
+    int			tmp;
+    CARD32		OCMD;
+    Bool		scaleChanged = FALSE;
 
     OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
 		  dstPitch);
@@ -1736,23 +1740,23 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 #if VIDEO_DEBUG
     CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
 #endif
-
-    crtc = I830CoveringCrtc (pScrn, dstBox, pPriv->desired_crtc);
-    if (crtc != pPriv->current_crtc)
-    {
-        pPriv->current_crtc = crtc;
-        I830ResetVideo (pScrn);
-    }
-
+    
     /*
      * If the video isn't visible on any CRTC, turn it off
      */
     if (!crtc)
     {
+	pPriv->current_crtc = NULL;
 	i830_overlay_off (pScrn);
 	return;
     }
     
+    if (crtc != pPriv->current_crtc)
+    {
+        pPriv->current_crtc = crtc;
+        I830ResetVideo (pScrn);
+    }
+
     switch (crtc->rotation & 0xf) {
     case RR_Rotate_0:
 	dstBox->x1 -= crtc->x;
@@ -1792,44 +1796,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 	break;
     }
 
-    /* Fix up the dstBox if outside the visible screen */
-    {
-	int offset_x = (dstBox->x1 < 0) ? -dstBox->x1 : 0;
-	int offset_y = (dstBox->y1 < 0) ? -dstBox->y1 : 0;
-	int offset, offset2;
-
-	/* align */
-	offset_x = (offset_x + 3) & ~3;
-	offset_y = (offset_y + 3) & ~3;
-
-	if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
-	    height -= offset_x;
-	    width -= offset_y;
-	} else {
-	    height -= offset_y;
-	    width -= offset_x;
-	}
-
-	if (id == FOURCC_I420 || id == FOURCC_YV12) {
-	    offset = ((offset_x/2) + (dstPitch * offset_y)) * 2;
-	    offset2 = ((offset_x/2) + ((dstPitch/2) * offset_y));
-	} else {
-	    offset = ((offset_x*2) + (dstPitch * offset_y));
-	    offset2 = ((offset_x*2) + ((dstPitch/2) * offset_y));
-	}
-
-	/* buffer locations */
-	pPriv->YBuf0offset += offset;
-	pPriv->UBuf0offset += offset2;
-	pPriv->VBuf0offset += offset2;
-
-	if(pPriv->doubleBuffer) {
-	    pPriv->YBuf1offset += offset;
-	    pPriv->UBuf1offset += offset2;
-	    pPriv->VBuf1offset += offset2;
-	}
-    }
-
     if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
 	tmp = width;
 	width = height;
@@ -1851,32 +1817,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 	drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1;
     }
 
-    {
-	/* Keep the engine happy and clip to the real vertical size just
-	 * in case an LFP is in use and it's not at it's native resolution.
-	 */
-	int vactive = I830CrtcPipe (pPriv->current_crtc) ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF);
-	int hactive = pPriv->current_crtc->mode.HDisplay;
-
-	vactive += 1;
-
-	if (dstBox->y1 < 0) dstBox->y1 = 0;
-	if (dstBox->y2 < 0) dstBox->y2 = 0;
-	if (dstBox->x1 < 0) dstBox->x1 = 0;
-	if (dstBox->x2 < 0) dstBox->x2 = 0;
-	if (dstBox->y1 > vactive) dstBox->y1 = vactive;
-	if (dstBox->y2 > vactive) dstBox->y2 = vactive;
-	if (dstBox->x1 > hactive) dstBox->x1 = hactive;
-	if (dstBox->x2 > hactive) dstBox->x2 = hactive;
-
-	/* nothing do to */
-	if (dstBox->x2 - dstBox->x1 <= 2 || dstBox->y2 - dstBox->y1 < N_VERT_Y_TAPS)
-	{
-	    OVERLAY_DEBUG("NOTHING TO DO\n");
-	    return;
-	}
-    }
-
     if (IS_I9XX(pI830)) {
 	shift = 6;
 	mask = 0x3f;
@@ -2220,6 +2160,84 @@ I830FreeMemory(ScrnInfoPtr pScrn, struct
     linear->offset = 0;
 }
 
+static Bool
+i830_clip_video_helper (ScrnInfoPtr pScrn,
+			xf86CrtcPtr *crtc_ret,
+			BoxPtr	    dst,
+			INT32	    *xa,
+			INT32	    *xb,
+			INT32	    *ya,
+			INT32	    *yb,
+			RegionPtr   reg,
+			INT32	    width,
+			INT32	    height)
+{
+    Bool	ret;
+    RegionRec	crtc_region_local;
+    RegionPtr	crtc_region = reg;
+    
+    /*
+     * For overlay video, compute the relevant CRTC and
+     * clip video to that
+     */
+    if (crtc_ret)
+    {
+	I830Ptr		pI830 = I830PTR(pScrn);
+	I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+	BoxRec		crtc_box;
+	xf86CrtcPtr	crtc = i830_covering_crtc (pScrn, dst,
+						   pPriv->desired_crtc,
+						   &crtc_box);
+	
+	if (crtc)
+	{
+	    REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1);
+	    crtc_region = &crtc_region_local;
+	    REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg);
+	}
+	*crtc_ret = crtc;
+    }
+    ret = xf86XVClipVideoHelper (dst, xa, xb, ya, yb, 
+				 crtc_region, width, height);
+    if (crtc_region != reg)
+	REGION_UNINIT (pScreen, &crtc_region_local);
+    return ret;
+}
+
+static void
+i830_fill_colorkey (ScreenPtr pScreen, CARD32 key, RegionPtr clipboxes)
+{
+   DrawablePtr root = &WindowTable[pScreen->myNum]->drawable;
+   XID	       pval[2];
+   BoxPtr      pbox = REGION_RECTS(clipboxes);
+   int	       i, nbox = REGION_NUM_RECTS(clipboxes);
+   xRectangle  *rects;
+   GCPtr       gc;
+
+   if(!xf86Screens[pScreen->myNum]->vtSema) return;
+
+   gc = GetScratchGC(root->depth, pScreen);
+   pval[0] = key;
+   pval[1] = IncludeInferiors;
+   (void) ChangeGC(gc, GCForeground|GCSubwindowMode, pval);
+   ValidateGC(root, gc);
+
+   rects = xalloc (nbox * sizeof(xRectangle));
+
+   for(i = 0; i < nbox; i++, pbox++) 
+   {
+      rects[i].x = pbox->x1;
+      rects[i].y = pbox->y1;
+      rects[i].width = pbox->x2 - pbox->x1;
+      rects[i].height = pbox->y2 - pbox->y1;
+   }
+   
+   (*gc->ops->PolyFillRect)(root, gc, nbox, rects);
+   
+   xfree (rects);
+   FreeScratchGC (gc);
+}
+
 /*
  * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h).
  * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h).
@@ -2255,6 +2273,7 @@ I830PutImage(ScrnInfoPtr pScrn,
     BoxRec dstBox;
     int pitchAlignMask;
     int extraLinear;
+    xf86CrtcPtr	crtc;
 
     if (pPriv->textured)
 	overlay = NULL;
@@ -2301,8 +2320,10 @@ I830PutImage(ScrnInfoPtr pScrn,
     dstBox.y1 = drw_y;
     dstBox.y2 = drw_y + drw_h;
 
-    if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
-			       width, height))
+    if (!i830_clip_video_helper(pScrn, 
+				pPriv->textured ? NULL : &crtc,
+				&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
+				width, height))
 	return Success;
 
     destId = id;
@@ -2455,14 +2476,15 @@ I830PutImage(ScrnInfoPtr pScrn,
     }
 
     if (!pPriv->textured) {
+	i830_display_video(pScrn, crtc, destId, width, height, dstPitch,
+			   x1, y1, x2, y2, &dstBox, src_w, src_h,
+			   drw_w, drw_h);
+	
 	/* update cliplist */
 	if (!RegionsEqual(&pPriv->clip, clipBoxes)) {
 	    REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
-	    xf86XVFillKeyHelper(pScreen, pPriv->colorKey, clipBoxes);
+	    i830_fill_colorkey (pScreen, pPriv->colorKey, clipBoxes);
 	}
-
-	I830DisplayVideo(pScrn, destId, width, height, dstPitch,
-			 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
     } else if (IS_I965G(pI830)) {
 	I965DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height,
 				 dstPitch, x1, y1, x2, y2,
@@ -2754,8 +2776,8 @@ I830DisplaySurface(XF86SurfacePtr surfac
     I830Ptr pI830 = I830PTR(pScrn);
     I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn);
     INT32 x1, y1, x2, y2;
-    INT32 loops = 0;
     BoxRec dstBox;
+    xf86CrtcPtr crtc;
 
     OVERLAY_DEBUG("I830DisplaySurface\n");
 
@@ -2785,43 +2807,24 @@ I830DisplaySurface(XF86SurfacePtr surfac
     dstBox.y1 = drw_y;
     dstBox.y2 = drw_y + drw_h;
 
-    if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
-			       surface->width, surface->height))
+    if (!i830_clip_video_helper (pScrn, &crtc, &dstBox,
+				 &x1, &x2, &y1, &y2, clipBoxes,
+				 surface->width, surface->height))
 	return Success;
 
     /* fixup pointers */
     pI830Priv->YBuf0offset = surface->offsets[0];
     pI830Priv->YBuf1offset = pI830Priv->YBuf0offset;
 
-    /* Make sure this buffer isn't in use */
-    loops = 0;
-    if (*pI830->overlayOn && pI830Priv->doubleBuffer) 
-    {
-	while (loops < 1000000) {
-#if USE_USLEEP_FOR_VIDEO
-	    usleep(10);
-#endif
-	    if (((INREG(DOVSTA) & OC_BUF) >> 20) == pI830Priv->currentBuf) {
-		break;
-	    }
-	    loops++;
-	}
-	if (loops >= 1000000) {
-	    ErrorF("loops (1) maxed out for buffer %d\n", pI830Priv->currentBuf);
-#if 0
-	    pI830Priv->currentBuf = !pI830Priv->currentBuf;
-#endif
-	}
-
-	/* buffer swap */
-	pI830Priv->currentBuf = !pI830Priv->currentBuf;
-    }
+    /* Pick the idle buffer */
+    if (!pI830Priv->textured && *pI830->overlayOn && pI830Priv->doubleBuffer) 
+	pI830Priv->currentBuf = !((INREG(DOVSTA) & OC_BUF) >> 20);
 
-    I830DisplayVideo(pScrn, surface->id, surface->width, surface->height,
+    i830_display_video(pScrn, crtc, surface->id, surface->width, surface->height,
 		     surface->pitches[0], x1, y1, x2, y2, &dstBox,
 		     src_w, src_h, drw_w, drw_h);
 
-    xf86XVFillKeyHelper(pScreen, pI830Priv->colorKey, clipBoxes);
+    i830_fill_colorkey (pScreen, pI830Priv->colorKey, clipBoxes);
 
     pPriv->isOn = TRUE;
     /* we've prempted the XvImage stream so set its free timer */


More information about the xorg-commit mailing list