[Intel-gfx] [PATCH 04/13] Xv overlay: Cut 400 line function i830_display_video into smaller chunks

Daniel Vetter daniel.vetter at ffwll.ch
Tue Jun 30 13:12:46 CEST 2009


And rename it to i830_overlay_display, because it _only_ concerns itself
with the overlay. This changeset should contain zero functional changes.

Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 src/i830_video.c |  528 +++++++++++++++++++++++++++++------------------------
 1 files changed, 289 insertions(+), 239 deletions(-)

diff --git a/src/i830_video.c b/src/i830_video.c
index e142fb5..5085bdd 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1781,54 +1781,56 @@ i830_swidth (I830Ptr pI830, unsigned int offset,
 }
 
 static void
-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)
+i830_calc_src_regs(I830Ptr pI830, int planar, short width, short height,
+	uint32_t *swidth_out, uint32_t *swidthsw_out, uint32_t *sheigth_out)
 {
-    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;
-    int			tmp;
-    uint32_t		OCMD;
-    Bool		scaleChanged = FALSE;
+    unsigned int	swidth, swidthy, swidthuv;
+    I830PortPrivPtr	pPriv = pI830->adaptor->pPortPrivates[0].ptr;
 
-    OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
-		  dstPitch);
+    if (IS_I9XX(pI830)) {
+	shift = 6;
+	mask = 0x3f;
+    } else {
+	shift = 5;
+	mask = 0x1f;
+    }
 
-#if VIDEO_DEBUG
-    CompareOverlay(pI830, (uint32_t *) overlay, 0x100);
-#endif
-    
-    /*
-     * If the video isn't visible on any CRTC, turn it off
-     */
-    if (!crtc)
-    {
-	pPriv->current_crtc = NULL;
-	i830_overlay_off (pScrn);
-	return;
+    if (pPriv->currentBuf == 0) {
+	offsety = pPriv->YBuf0offset;
+	offsetu = pPriv->UBuf0offset;
+    } else {
+	offsety = pPriv->YBuf1offset;
+	offsetu = pPriv->UBuf1offset;
     }
-    
-    if (crtc != pPriv->current_crtc)
-    {
-	i830_overlay_switch_to_crtc (pScrn, crtc);
-	if (pPriv->overlayOK) {
-	    pPriv->current_crtc = crtc;
-	    I830ResetVideo (pScrn);
-	}
+
+    if (planar) {
+	*swidth_out = width | ((width/2 & 0x7ff) << 16);
+	swidthy  = i830_swidth (pI830, offsety, width, mask, shift);
+	swidthuv = i830_swidth (pI830, offsetu, width/2, mask, shift);
+	*swidthsw_out = (swidthy) | (swidthuv << 16);
+	*sheigth_out = height | ((height / 2) << 16);
+    } else {
+	*swidth_out = width;
+	swidth = i830_swidth (pI830, offsety, width << 1, mask, shift);
+	*swidthsw_out = swidth;
+	*sheigth_out = height;
     }
 
-    if (!pPriv->overlayOK)
-	return;
+    return;
+}
+
+static void
+i830_update_dst_box_to_crtc_coords(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
+		BoxPtr dstBox)
+{
+    int tmp;
 
+    /* for overlay, we should take it from crtc's screen
+     * coordinate to current crtc's display mode.
+     * yeah, a bit confusing.
+     */
     switch (crtc->rotation & 0xf) {
-	/* for overlay, we should take it from crtc's screen
-	 * coordinate to current crtc's display mode.
-	 * yeah, a bit confusing.
-	 */
     case RR_Rotate_0:
 	dstBox->x1 -= crtc->x;
 	dstBox->x2 -= crtc->x;
@@ -1867,6 +1869,240 @@ i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
 	break;
     }
 
+    return;
+}
+
+static void
+i830_store_coeffs_in_overlay_regs(uint16_t *reg_coeffs, coeffPtr new_coeffs,
+	int max_taps)
+{
+    int i, j, pos;
+
+    for (i = 0; i < N_PHASES; i++) {
+	for (j = 0; j < max_taps; j++) {
+	    pos = i * max_taps + j;
+	    reg_coeffs[pos] = (new_coeffs[pos].sign << 15 |
+				      new_coeffs[pos].exponent << 12 |
+				      new_coeffs[pos].mantissa);
+	}
+    }
+}
+
+static uint32_t
+i830_overlay_cmd(int id, int planar, unsigned char currentBuf)
+{
+    uint32_t OCMD = OVERLAY_ENABLE;
+    
+    if (planar) {
+	OVERLAY_DEBUG("YUV420\n");
+	OCMD &= ~SOURCE_FORMAT;
+	OCMD &= ~OV_BYTE_ORDER;
+	OCMD |= YUV_420;
+    } else {
+	OVERLAY_DEBUG("YUV422\n");
+	OCMD &= ~SOURCE_FORMAT;
+	OCMD |= YUV_422;
+	OCMD &= ~OV_BYTE_ORDER;
+	if (id == FOURCC_UYVY)
+	    OCMD |= Y_SWAP;
+    }
+
+    OCMD &= ~(BUFFER_SELECT | FIELD_SELECT);
+    if (currentBuf == 0)
+	OCMD |= BUFFER0;
+    else
+	OCMD |= BUFFER1;
+
+    OVERLAY_DEBUG("OCMD is 0x%x\n", OCMD);
+
+    return OCMD;
+}
+
+static double
+i830_limit_coeff(double coeff)
+{
+    /* Limit to between 1.0 and 3.0. */
+    if (coeff < MIN_CUTOFF_FREQ)
+	coeff = MIN_CUTOFF_FREQ;
+    if (coeff > MAX_CUTOFF_FREQ)
+	coeff = MAX_CUTOFF_FREQ;
+
+    return coeff;
+}
+
+static void
+i830_update_polyphase_coeffs(I830OverlayRegPtr	overlay,
+	int xscaleFract, int xscaleFractUV)
+{
+    /*
+     * Only Horizontal coefficients so far.
+     */
+    double fCutoffY;
+    double fCutoffUV;
+    coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
+    coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
+
+    fCutoffY = xscaleFract / 4096.0;
+    fCutoffUV = xscaleFractUV / 4096.0;
+
+    fCutoffUV = i830_limit_coeff(fCutoffUV);
+    fCutoffY = i830_limit_coeff(fCutoffY);
+
+    UpdateCoeff(N_HORIZ_Y_TAPS, fCutoffY, TRUE, TRUE, xcoeffY);
+    UpdateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, TRUE, FALSE, xcoeffUV);
+
+    i830_store_coeffs_in_overlay_regs(overlay->Y_HCOEFS, xcoeffY,
+		    N_HORIZ_Y_TAPS);
+    i830_store_coeffs_in_overlay_regs(overlay->UV_HCOEFS, xcoeffUV,
+		    N_HORIZ_UV_TAPS);
+}
+
+/* 
+ * Calculate horizontal and vertical scaling factors and polyphase
+ * coefficients.
+ */
+
+static Bool
+i830_update_scaling_factors(I830OverlayRegPtr overlay,
+	short src_w, short src_h, short drw_w, short drw_h)
+{
+    int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
+    int xscaleIntUV, xscaleFractUV;
+    int yscaleIntUV, yscaleFractUV;
+    uint32_t newval;
+    Bool scaleChanged = FALSE;
+
+    /*
+     * Y down-scale factor as a multiple of 4096.
+     */
+    xscaleFract = ((src_w - 1) << 12) / drw_w;
+    yscaleFract = ((src_h - 1) << 12) / drw_h;
+
+    /* Calculate the UV scaling factor.
+     * UV is half the size of Y -- YUV420 */
+    xscaleFractUV = xscaleFract / 2;
+    yscaleFractUV = yscaleFract / 2;
+
+    /*
+     * To keep the relative Y and UV ratios exact, round the Y scales
+     * to a multiple of the Y/UV ratio.
+     */
+    xscaleFract = xscaleFractUV * 2;
+    yscaleFract = yscaleFractUV * 2;
+
+    /* Integer (un-multiplied) values. */
+    xscaleInt = xscaleFract >> 12;
+    yscaleInt = yscaleFract >> 12;
+
+    xscaleIntUV = xscaleFractUV >> 12;
+    yscaleIntUV = yscaleFractUV >> 12;
+
+    OVERLAY_DEBUG("xscale: %x.%03x, yscale: %x.%03x\n", xscaleInt,
+		  xscaleFract & 0xFFF, yscaleInt, yscaleFract & 0xFFF);
+    OVERLAY_DEBUG("UV xscale: %x.%03x, UV yscale: %x.%03x\n", xscaleIntUV,
+		  xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF);
+
+    /* shouldn't get here */
+    if (xscaleInt > 7) {
+	OVERLAY_DEBUG("xscale: bad scale\n");
+	return FALSE;
+    }
+
+    /* shouldn't get here */
+    if (xscaleIntUV > 7) {
+	OVERLAY_DEBUG("xscaleUV: bad scale\n");
+	return FALSE;
+    }
+
+    newval = (xscaleInt << 16) |
+    ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
+    if (newval != overlay->YRGBSCALE) {
+	scaleChanged = TRUE;
+	overlay->YRGBSCALE = newval;
+    }
+
+    newval = (xscaleIntUV << 16) | ((xscaleFractUV & 0xFFF) << 3) |
+    ((yscaleFractUV & 0xFFF) << 20);
+    if (newval != overlay->UVSCALE) {
+	scaleChanged = TRUE;
+	overlay->UVSCALE = newval;
+    }
+
+    newval = yscaleInt << 16 | yscaleIntUV;
+    if (newval != overlay->UVSCALEV) {
+	scaleChanged = TRUE;
+	overlay->UVSCALEV = newval;
+    }
+
+    if (scaleChanged) {
+	i830_update_polyphase_coeffs(overlay, xscaleFract, xscaleFractUV);
+    }
+
+    return scaleChanged;
+}
+
+static int
+is_planar_fourcc(int id)
+{
+    switch (id) {
+    case FOURCC_YV12:
+    case FOURCC_I420:
+#ifdef INTEL_XVMC
+    case FOURCC_XVMC:
+#endif
+	return 1;
+    case FOURCC_UYVY:
+    case FOURCC_YUY2:
+    default:
+	return 0;
+    }
+}
+
+static void
+i830_display_overlay(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;
+    I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
+    int			planar;
+    uint32_t		swidth, swidthsw, sheigth;
+    int			tmp;
+    Bool		scaleChanged;
+
+    OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
+		  dstPitch);
+
+#if VIDEO_DEBUG
+    CompareOverlay(pI830, (uint32_t *) overlay, 0x100);
+#endif
+    
+    /*
+     * 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)
+    {
+	i830_overlay_switch_to_crtc (pScrn, crtc);
+	if (pPriv->overlayOK) {
+	    pPriv->current_crtc = crtc;
+	    I830ResetVideo (pScrn);
+	}
+    }
+
+    if (!pPriv->overlayOK)
+	return;
+
+    i830_update_dst_box_to_crtc_coords(pScrn, crtc, dstBox);
+
     if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
 	tmp = width;
 	width = height;
@@ -1888,54 +2124,14 @@ i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
 	drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1;
     }
 
-    if (IS_I9XX(pI830)) {
-	shift = 6;
-	mask = 0x3f;
-    } else {
-	shift = 5;
-	mask = 0x1f;
-    }
-
-    if (pPriv->currentBuf == 0) {
-	offsety = pPriv->YBuf0offset;
-	offsetu = pPriv->UBuf0offset;
-    } else {
-	offsety = pPriv->YBuf1offset;
-	offsetu = pPriv->UBuf1offset;
-    }
-
-    switch (id) {
-    case FOURCC_YV12:
-    case FOURCC_I420:
-	overlay->SWIDTH = width | ((width/2 & 0x7ff) << 16);
-	swidthy  = i830_swidth (pI830, offsety, width, mask, shift);
-	swidthuv = i830_swidth (pI830, offsetu, width/2, mask, shift);
-	overlay->SWIDTHSW = (swidthy) | (swidthuv << 16);
-	overlay->SHEIGHT = height | ((height / 2) << 16);
-	break;
-    case FOURCC_UYVY:
-    case FOURCC_YUY2:
-    default:
-	overlay->SWIDTH = width;
-	swidth = ((offsety + (width << 1) + mask) >> shift) -
-	(offsety >> shift);
+    planar = is_planar_fourcc(id);
 
-	if (IS_I9XX(pI830))
-	    swidth <<= 1;
+    i830_calc_src_regs(pI830, planar, width, height,
+	    &swidth, &swidthsw, &sheigth);
 
-	swidth -= 1;
-
-	swidth <<= 2;
-	
-	OVERLAY_DEBUG("swidthsw is old %d new %d\n",
-		      swidth,
-		      i830_swidth (pI830, offsety, width << 1,
-				   mask, shift));
-
-	overlay->SWIDTHSW = swidth;
-	overlay->SHEIGHT = height;
-	break;
-    }
+    overlay->SWIDTH = swidth;
+    overlay->SWIDTHSW = swidthsw;
+    overlay->SHEIGHT = sheigth;
 
     overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1;
 
@@ -1959,167 +2155,21 @@ i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
 		  overlay->DWINPOS, overlay->DWINSZ);
     OVERLAY_DEBUG("dst: %d x %d, src: %d x %d\n", drw_w, drw_h, src_w, src_h);
 
-    /* 
-     * Calculate horizontal and vertical scaling factors and polyphase
-     * coefficients.
-     */
-
-    {
-	int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
-	int xscaleIntUV, xscaleFractUV;
-	int yscaleIntUV, yscaleFractUV;
-	/* UV is half the size of Y -- YUV420 */
-	int uvratio = 2;
-	uint32_t newval;
-	coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
-	coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
-	int i, j, pos;
-
-	/*
-	 * Y down-scale factor as a multiple of 4096.
-	 */
-	xscaleFract = ((src_w - 1) << 12) / drw_w;
-	yscaleFract = ((src_h - 1) << 12) / drw_h;
-
-	/* Calculate the UV scaling factor. */
-	xscaleFractUV = xscaleFract / uvratio;
-	yscaleFractUV = yscaleFract / uvratio;
-
-	/*
-	 * To keep the relative Y and UV ratios exact, round the Y scales
-	 * to a multiple of the Y/UV ratio.
-	 */
-	xscaleFract = xscaleFractUV * uvratio;
-	yscaleFract = yscaleFractUV * uvratio;
-
-	/* Integer (un-multiplied) values. */
-	xscaleInt = xscaleFract >> 12;
-	yscaleInt = yscaleFract >> 12;
-
-	xscaleIntUV = xscaleFractUV >> 12;
-	yscaleIntUV = yscaleFractUV >> 12;
+    scaleChanged = i830_update_scaling_factors(overlay,
+	    src_w, src_h, drw_w, drw_h);
 
-	OVERLAY_DEBUG("xscale: %x.%03x, yscale: %x.%03x\n", xscaleInt,
-		      xscaleFract & 0xFFF, yscaleInt, yscaleFract & 0xFFF);
-	OVERLAY_DEBUG("UV xscale: %x.%03x, UV yscale: %x.%03x\n", xscaleIntUV,
-		      xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF);
-
-	/* shouldn't get here */
-	if (xscaleInt > 7) {
-	    OVERLAY_DEBUG("xscale: bad scale\n");
-	    return;
-	}
-
-	/* shouldn't get here */
-	if (xscaleIntUV > 7) {
-	    OVERLAY_DEBUG("xscaleUV: bad scale\n");
-	    return;
-	}
-
-	newval = (xscaleInt << 16) |
-	((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
-	if (newval != overlay->YRGBSCALE) {
-	    scaleChanged = TRUE;
-	    overlay->YRGBSCALE = newval;
-	}
-
-	newval = (xscaleIntUV << 16) | ((xscaleFractUV & 0xFFF) << 3) |
-	((yscaleFractUV & 0xFFF) << 20);
-	if (newval != overlay->UVSCALE) {
-	    scaleChanged = TRUE;
-	    overlay->UVSCALE = newval;
-	}
-
-	newval = yscaleInt << 16 | yscaleIntUV;
-	if (newval != overlay->UVSCALEV) {
-	    scaleChanged = TRUE;
-	    overlay->UVSCALEV = newval;
-	}
-
-	/* Recalculate coefficients if the scaling changed. */
-
-	/*
-	 * Only Horizontal coefficients so far.
-	 */
-	if (scaleChanged) {
-	    double fCutoffY;
-	    double fCutoffUV;
-
-	    fCutoffY = xscaleFract / 4096.0;
-	    fCutoffUV = xscaleFractUV / 4096.0;
-
-	    /* Limit to between 1.0 and 3.0. */
-	    if (fCutoffY < MIN_CUTOFF_FREQ)
-		fCutoffY = MIN_CUTOFF_FREQ;
-	    if (fCutoffY > MAX_CUTOFF_FREQ)
-		fCutoffY = MAX_CUTOFF_FREQ;
-	    if (fCutoffUV < MIN_CUTOFF_FREQ)
-		fCutoffUV = MIN_CUTOFF_FREQ;
-	    if (fCutoffUV > MAX_CUTOFF_FREQ)
-		fCutoffUV = MAX_CUTOFF_FREQ;
-
-	    UpdateCoeff(N_HORIZ_Y_TAPS, fCutoffY, TRUE, TRUE, xcoeffY);
-	    UpdateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, TRUE, FALSE, xcoeffUV);
-
-	    for (i = 0; i < N_PHASES; i++) {
-		for (j = 0; j < N_HORIZ_Y_TAPS; j++) {
-		    pos = i * N_HORIZ_Y_TAPS + j;
-		    overlay->Y_HCOEFS[pos] = (xcoeffY[pos].sign << 15 |
-					      xcoeffY[pos].exponent << 12 |
-					      xcoeffY[pos].mantissa);
-		}
-	    }
-	    for (i = 0; i < N_PHASES; i++) {
-		for (j = 0; j < N_HORIZ_UV_TAPS; j++) {
-		    pos = i * N_HORIZ_UV_TAPS + j;
-		    overlay->UV_HCOEFS[pos] = (xcoeffUV[pos].sign << 15 |
-					       xcoeffUV[pos].exponent << 12 |
-					       xcoeffUV[pos].mantissa);
-		}
-	    }
-	}
-    }
-
-    OCMD = OVERLAY_ENABLE;
-    
-    switch (id) {
-    case FOURCC_YV12:
-    case FOURCC_I420:
-#ifdef INTEL_XVMC
-    case FOURCC_XVMC:
-#endif
-	OVERLAY_DEBUG("YUV420\n");
+    if (planar) {
 #if 0
 	/* set UV vertical phase to -0.25 */
 	overlay->UV_VPH = 0x30003000;
 #endif
+	overlay->OSTRIDE = (dstPitch * 2) | (dstPitch << 16);
 	OVERLAY_DEBUG("UV stride is %d, Y stride is %d\n",
 		      dstPitch, dstPitch * 2);
-	overlay->OSTRIDE = (dstPitch * 2) | (dstPitch << 16);
-	OCMD &= ~SOURCE_FORMAT;
-	OCMD &= ~OV_BYTE_ORDER;
-	OCMD |= YUV_420;
-	break;
-    case FOURCC_UYVY:
-    case FOURCC_YUY2:
-	OVERLAY_DEBUG("YUV422\n");
+    } else
 	overlay->OSTRIDE = dstPitch;
-	OCMD &= ~SOURCE_FORMAT;
-	OCMD |= YUV_422;
-	OCMD &= ~OV_BYTE_ORDER;
-	if (id == FOURCC_UYVY)
-	    OCMD |= Y_SWAP;
-	break;
-    }
-
-    OCMD &= ~(BUFFER_SELECT | FIELD_SELECT);
-    if (pPriv->currentBuf == 0)
-	OCMD |= BUFFER0;
-    else
-	OCMD |= BUFFER1;
 
-    overlay->OCMD = OCMD;
-    OVERLAY_DEBUG("OCMD is 0x%x\n", OCMD);
+    overlay->OCMD = i830_overlay_cmd(id, planar, pPriv->currentBuf);
 
     /* make sure the overlay is on */
     i830_overlay_on (pScrn);
@@ -2485,7 +2535,7 @@ I830PutImage(ScrnInfoPtr pScrn,
     }
 
     if (!pPriv->textured) {
-	i830_display_video(pScrn, crtc, destId, width, height, dstPitch,
+	i830_display_overlay(pScrn, crtc, destId, width, height, dstPitch,
 			   x1, y1, x2, y2, &dstBox, src_w, src_h,
 			   drw_w, drw_h);
 	
@@ -2833,7 +2883,7 @@ I830DisplaySurface(XF86SurfacePtr surface,
     if (!pI830Priv->textured && pI830->overlayOn && pI830Priv->doubleBuffer)
 	pI830Priv->currentBuf = !((INREG(DOVSTA) & OC_BUF) >> 20);
 
-    i830_display_video(pScrn, crtc, surface->id, surface->width, surface->height,
+    i830_display_overlay(pScrn, crtc, surface->id, surface->width, surface->height,
 		     surface->pitches[0], x1, y1, x2, y2, &dstBox,
 		     src_w, src_h, drw_w, drw_h);
 
-- 
1.6.3.3




More information about the Intel-gfx mailing list