Hi,

[...]

> > It's a little more than that because the driver is using 4:2:2
> > internally.  Copying the way it is doing you can't get much more than
> > 160 MB/sec and uses the CPU the whole time.
>
>   Hrm, I hope it doesn't just double each chroma scanline.  I'm in fear
> now.  Wish that was documented somewhere, I would have written a better
> chroma upsampler sooner.

A few months ago, I tried to add support for planar modes to the mga xvideo 
extension. It had some problems (noise) with downscaled DVD movies, but it 
works and is indeed faster than the "copy munged data" method.

I have attached the patch. You might need to make some changed to use it with 
the current CVS version though (only tried it with XFree86-4.1.0).

bye,

ewald
--- xc/programs/Xserver/hw/xfree86/drivers/mga/mga_video.c.mga-xv-planar-data	Fri Apr 27 20:59:53 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/mga/mga_video.c	Fri Apr 27 21:16:41 2001
@@ -622,6 +622,42 @@
    }
 }
 
+static void
+MGACopyPlanarData(
+   unsigned char *src1,
+   unsigned char *src2,
+   unsigned char *src3,
+   unsigned char *dst1,
+   unsigned char *dst2,
+   unsigned char *dst3,
+   int srcPitch,
+   int srcPitch2,
+   int dstPitch,
+   int h,
+   int w
+){
+    int w2, dstPitch2;
+
+    w2 = w >> 1;
+    dstPitch2 = dstPitch >> 1;
+    h >>= 1;
+
+    while(h--) {
+	memcpy(dst1, src1, w);
+	src1 += srcPitch;
+	dst1 += dstPitch;
+	memcpy(dst1, src1, w);
+	src1 += srcPitch;
+	dst1 += dstPitch;
+	memcpy(dst2, src2, w2);
+	src2 += srcPitch2;
+	dst2 += dstPitch2;
+	memcpy(dst3, src3, w2);
+	src3 += srcPitch2;
+	dst3 += dstPitch2;
+    }
+}
+
 
 static FBLinearPtr
 MGAAllocateMemory(
@@ -690,21 +726,44 @@
     hzoom = (pScrn->currentMode->Clock > 135000) ? 1 : 0;
 
     switch(id) {
+    case FOURCC_YV12:
+    case FOURCC_I420:
+	if(pMga->Chipset == PCI_CHIP_MGAG400)
+	    OUTREG(MGAREG_BESGLOBCTL, 0x00a0 | (3 * hzoom) | (tmp << 16));
+	else
+	    OUTREG(MGAREG_BESGLOBCTL, 0x0080 | (3 * hzoom) | (tmp << 16));
+	break;
     case FOURCC_UYVY:
 	OUTREG(MGAREG_BESGLOBCTL, 0x000000c0 | (3 * hzoom) | (tmp << 16));
 	break;
     case FOURCC_YUY2:
-    default:
 	OUTREG(MGAREG_BESGLOBCTL, 0x00000080 | (3 * hzoom) | (tmp << 16));
 	break;
     }
 
     OUTREG(MGAREG_BESA1ORG, offset);
 
-    if(y1 & 0x00010000)
-	OUTREG(MGAREG_BESCTL, 0x00040c41);
-    else 
-	OUTREG(MGAREG_BESCTL, 0x00040c01);
+    if((id == FOURCC_UYVY) || (id == FOURCC_YUY2) ||
+       (pMga->Chipset != PCI_CHIP_MGAG400))
+    {
+	if(y1 & 0x00010000)
+	    OUTREG(MGAREG_BESCTL, 0x00050c41);
+	else
+	    OUTREG(MGAREG_BESCTL, 0x00050c01);
+    } else {
+	int n = (pitch * height);
+	int corg = offset + n - (3 * (pitch >> 1) * (y1 >> 17));
+
+	if(y1 & 0x00010000)
+	    OUTREG(MGAREG_BESCTL, 0x00070c41);
+	else
+	    OUTREG(MGAREG_BESCTL, 0x00070c01);
+
+	OUTREG(MGAREG_BESA1CORG, corg);
+	OUTREG(MGAREG_BESA1C3ORG, corg + (n >> 2));
+
+	pitch <<= 1;
+    }
  
     OUTREG(MGAREG_BESHCOORD, (dstBox->x1 << 16) | (dstBox->x2 - 1));
     OUTREG(MGAREG_BESVCOORD, (dstBox->y1 << 16) | (dstBox->y2 - 1));
@@ -712,7 +771,7 @@
     OUTREG(MGAREG_BESHSRCST, x1 & 0x03fffffc);
     OUTREG(MGAREG_BESHSRCEND, (x2 - 0x00010000) & 0x03fffffc);
     OUTREG(MGAREG_BESHSRCLST, (width - 1) << 16);
-   
+
     OUTREG(MGAREG_BESPITCH, pitch >> 1);
 
     OUTREG(MGAREG_BESV1WGHT, y1 & 0x0000fffc);
@@ -871,6 +930,10 @@
    switch(id) {
    case FOURCC_YV12:
    case FOURCC_I420:
+	if(pMga->Chipset == PCI_CHIP_MGAG400) {
+	    dstPitch = (width + 31) & ~31;
+	    new_size = (((3 * dstPitch * height) >> 1) + bpp - 1) / bpp;
+	}
 	srcPitch = (width + 3) & ~3;
 	offset2 = srcPitch * height;
 	srcPitch2 = ((width >> 1) + 3) & ~3;
@@ -914,9 +977,23 @@
 	   offset3 = tmp;
 	}
 	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
-	MGACopyMungedData(buf + (top * srcPitch) + (left >> 1), 
-			  buf + offset2, buf + offset3, dst_start,
-			  srcPitch, srcPitch2, dstPitch, nlines, npixels);
+	if(pMga->TexturedVideo || (pMga->Chipset != PCI_CHIP_MGAG400))
+	    MGACopyMungedData(buf + (top * srcPitch) + (left >> 1),
+			      buf + offset2, buf + offset3, dst_start,
+			      srcPitch, srcPitch2, dstPitch, nlines,
+			      npixels);
+	else {
+	    int corg, n;
+	    left >>= 1;
+	    n = (dstPitch * height);
+	    corg = n - ((3 * top * dstPitch) >> 2) - (left >> 1);
+	    dst_start -= left;
+	    MGACopyPlanarData(buf + (top * srcPitch) + left,
+			      buf + offset2, buf + offset3,
+			      dst_start, dst_start + corg + (n >> 2),
+			      dst_start + corg, srcPitch, srcPitch2,
+			      dstPitch, nlines, npixels);
+	}
 	break;
     case FOURCC_UYVY:
     case FOURCC_YUY2:

Reply via email to