[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