--- /dev/null
+--- XFree86-4.2.0/xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/Imakefile Wed Jan 24 01:06:21 2001
++++ XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/neomagic/Imakefile Thu Apr 4 16:05:44 2002
+@@ -2,12 +2,12 @@
+ #define IHaveModules
+ #include <Server.tmpl>
+
+
+ SRCS = neo_driver.c neo_bank.c neo_cursor.c neo_2097.c neo_2070.c \
+- neo_2090.c neo_2200.c neo_i2c.c neo_shadow.c neo_dga.c
++ neo_2090.c neo_2200.c neo_i2c.c neo_shadow.c neo_dga.c neo_video.c
+
+ OBJS = neo_driver.o neo_bank.o neo_cursor.o neo_2097.o neo_2070.o \
+- neo_2090.o neo_2200.o neo_i2c.o neo_shadow.o neo_dga.o
++ neo_2090.o neo_2200.o neo_i2c.o neo_shadow.o neo_dga.o neo_video.o
+
+ DEFINES = -DPSZ=8
+
+--- XFree86-4.2.0/xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/NM-reg.txt Thu Jan 1 01:00:00 1970
++++ XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/neomagic/NM-reg.txt Thu Apr 4 16:05:44 2002
+@@ -0,0 +1,69 @@
++NM2160 Register GUESS
++ --- Overlay and ZV capture ---
++
++2002,2.3.
++
++1. Overlay
++ GRB0 bit5 Format; 0:YUY2/1:RGB
++ bit1 1
++ bit0 Enable overlay ; 1:enable/0:disable
++ GRB1 bit7:4 X2[11:8]
++ bit3:0 X1[11:8]
++ GRB2 X1[7:0]
++ GRB3 X2[7:0]
++ GRB4 bit7:4 Y2[11:8]
++ bit3:0 Y1[11:8]
++ GRB5 Y1[7:0]
++ GRB6 Y2[7:0]
++ GRB7 VRAM offset[24:17]
++ GRB8 VRAM offset[16:9]
++ GRB9 VRAM offset[8:1]
++ GRBA Width in byte[15:8]
++ GRBB Width in byte[7:0]
++ GRBC 0x4f
++ GRBD -
++ GRBE -
++ GRBF bit2 0:normal/1:mirror
++ bit1:0 b'10'
++ GRC0 X scale[15:8] ; x1.0 == 0x1000
++ GRC1 X scale[7:0]
++ GRC2 Y scale[15:8] ; x1.0 == 0x1000
++ GRC3 Y scale[7:0]
++ GRC4 brightness ; -128 to +127
++ GRC5 Color key(R)
++ GRC6 Color key(G) / Color key(8bpp)
++ GRC7 Color key(B)
++
++2. ZV capture
++ GR0A bit5 Enable extended SR reg. ; 1:enable/0:disable
++ bit0 1
++
++ SR08 bit7:1 b'1010000'
++ bit0 Enable capture ; 1:enable/0:disable
++ SR09 0x11
++ SR0A 0x00
++ SR0B -
++ SR0C VRAM offset[8:1]
++ SR0D VRAM offset[16:9]
++ SR0E VRAM offset[24:17]
++ SR0F -
++ SR10 -
++ SR11 -
++ SR12 -
++ SR13 -
++ SR14 Y1[7:0]
++ SR15 Y2[7:0]
++ SR16 bit7:4 Y2[11:4]
++ bit3:0 Y1[11:4]
++ SR17 X1[7:0]
++ SR18 X2[7:0]
++ SR19 bit7:4 X2[11:8]
++ bit3:0 X1[11:8]
++ SR1A Width in byte[7:0]
++ SR1B Width in byte[15:8]
++ SR1C 0xfb
++ SR1D 0x00
++ SR1E 0xe2
++ SR1F 0x02
++
++s.nomura@mba.nifty.ne.jp
+--- XFree86-4.2.0/xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo.h Mon Oct 1 15:44:07 2001
++++ XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo.h Thu Apr 4 16:05:44 2002
+@@ -60,6 +60,11 @@
+
+ #include "xf86i2c.h"
+
++#ifdef XvExtension
++# include "xf86xv.h"
++# include "Xv.h"
++#endif /* XvExtension */
++
+ /*
+ * Driver data structures.
+ */
+@@ -121,6 +126,10 @@
+ /* in neo_dga.c */
+ Bool NEODGAInit(ScreenPtr pScreen);
+
++/* in neo_video.c */
++extern void NEOInitVideo(ScreenPtr pScreen);
++extern void NEOResetVideo(ScrnInfoPtr pScrn);
++
+ /* shadow regs */
+
+ #define NEO_EXT_CR_MAX 0x85
+@@ -199,6 +208,8 @@
+ unsigned long NeoMMIOAddr;
+ unsigned long NeoLinearAddr;
+ unsigned char* NeoMMIOBase;
++ unsigned long NeoMMIOAddr2;
++ unsigned char* NeoMMIOBase2;
+ unsigned char* NeoFbBase;
+ long NeoFbMapSize;
+ unsigned long vgaIOBase;
+@@ -249,6 +260,17 @@
+ RefreshAreaFuncPtr refreshArea;
+ void (*PointerMoved)(int index, int x, int y);
+ int rotate;
++ Bool showcache;
++#ifdef XvExtension
++ Bool video;
++ double videoHZoom;
++ double videoVZoom;
++ XF86VideoAdaptorPtr overlayAdaptor;
++ int overlay;
++ int overlay_offset;
++ int videoKey;
++ int interlace;
++#endif /* XvExtension */
+ } NEORec, *NEOPtr;
+
+ typedef struct {
+@@ -264,18 +286,20 @@
+ #define GRAX 0x3CE
+
+ /* vga IO functions */
+-#define VGArCR(index) hwp->readCrtc(hwp,index)
+-#define VGAwCR(index,val) hwp->writeCrtc(hwp,index,val)
+-#define VGArGR(index) hwp->readGr(hwp,index)
+-#define VGAwGR(index,val) hwp->writeGr(hwp,index,val)
++#define VGArCR(index) (*hwp->readCrtc)(hwp, index)
++#define VGAwCR(index, val) (*hwp->writeCrtc)(hwp, index, val)
++#define VGArGR(index) (*hwp->readGr)(hwp, index)
++#define VGAwGR(index, val) (*hwp->writeGr)(hwp, index, val)
++#define VGArSR(index) (*hwp->readSeq)(hwp, index)
++#define VGAwSR(index, val) (*hwp->writeSeq)(hwp, index, val)
+
+ /* memory mapped register access macros */
+-#define INREG8(addr) MMIO_IN8(nPtr->NeoMMIOBase, (addr))
+-#define INREG16(addr) MMIO_IN16(nPtr->NeoMMIOBase, (addr))
+-#define INREG(addr) MMIO_IN32(nPtr->NeoMMIOBase, (addr))
+-#define OUTREG8(addr, val) MMIO_OUT8(nPtr->NeoMMIOBase, (addr), (val))
+-#define OUTREG16(addr, val) MMIO_OUT16(nPtr->NeoMMIOBase, (addr), (val))
+-#define OUTREG(addr, val) MMIO_OUT32(nPtr->NeoMMIOBase, (addr), (val))
++#define INREG8(addr) MMIO_IN8(nPtr->NeoMMIOBase, addr)
++#define INREG16(addr) MMIO_IN16(nPtr->NeoMMIOBase, addr)
++#define INREG(addr) MMIO_IN32(nPtr->NeoMMIOBase, addr)
++#define OUTREG8(addr, val) MMIO_OUT8(nPtr->NeoMMIOBase, addr, val)
++#define OUTREG16(addr, val) MMIO_OUT16(nPtr->NeoMMIOBase, addr, val)
++#define OUTREG(addr, val) MMIO_OUT32(nPtr->NeoMMIOBase, addr, val)
+
+ /* This swizzle macro is to support the manipulation of cursor masks when
+ * the sprite moves off the left edge of the display. This code is
+--- XFree86-4.2.0/xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2070.c Tue Sep 26 01:57:08 2000
++++ XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2070.c Thu Apr 4 16:05:44 2002
+@@ -104,8 +104,6 @@
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ NEOPtr nPtr = NEOPTR(pScrn);
+ NEOACLPtr nAcl = NEOACLPTR(pScrn);
+- BoxRec AvailFBArea;
+- int lines;
+
+ nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
+ if(!infoPtr) return FALSE;
+@@ -158,23 +156,7 @@
+ default:
+ return FALSE;
+ }
+-
+- /* Initialize for widths */
+- nAcl->Pitch = pScrn->displayWidth * nAcl->PixelWidth;
+- lines = nAcl->cacheEnd /
+- (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
+- if(lines > 1024) lines = 1024;
+-
+- AvailFBArea.x1 = 0;
+- AvailFBArea.y1 = 0;
+- AvailFBArea.x2 = pScrn->displayWidth;
+- AvailFBArea.y2 = lines;
+- xf86InitFBManager(pScreen, &AvailFBArea);
+-
+- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+- "Using %i scanlines of offscreen memory for pixmap caching\n",
+- lines - pScrn->virtualY);
+-
++
+ return(XAAInit(pScreen, infoPtr));
+
+ }
+--- XFree86-4.2.0/xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2090.c Mon Oct 1 15:44:07 2001
++++ XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2090.c Thu Apr 4 16:05:44 2002
+@@ -101,8 +101,6 @@
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ NEOPtr nPtr = NEOPTR(pScrn);
+ NEOACLPtr nAcl = NEOACLPTR(pScrn);
+- BoxRec AvailFBArea;
+- int lines;
+
+ nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
+ if(!infoPtr) return FALSE;
+@@ -197,20 +195,6 @@
+
+ nAcl->BltCntlFlags |= NEO_BC3_FIFO_EN;
+
+- lines = nAcl->cacheEnd /
+- (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
+- if(lines > 1024) lines = 1024;
+-
+- AvailFBArea.x1 = 0;
+- AvailFBArea.y1 = 0;
+- AvailFBArea.x2 = pScrn->displayWidth;
+- AvailFBArea.y2 = lines;
+- xf86InitFBManager(pScreen, &AvailFBArea);
+-
+- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+- "Using %i scanlines of offscreen memory for pixmap caching\n",
+- lines - pScrn->virtualY);
+-
+ return(XAAInit(pScreen, infoPtr));
+ }
+
+--- XFree86-4.2.0/xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2097.c Mon Oct 1 15:44:07 2001
++++ XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2097.c Thu Apr 4 16:05:44 2002
+@@ -123,8 +123,6 @@
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ NEOPtr nPtr = NEOPTR(pScrn);
+ NEOACLPtr nAcl = NEOACLPTR(pScrn);
+- int lines;
+- BoxRec AvailFBArea;
+
+ nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
+ if(!infoPtr) return FALSE;
+@@ -245,21 +243,7 @@
+ default:
+ return FALSE;
+ }
+-
+- lines = nAcl->cacheEnd /
+- (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
+- if(lines > 1024) lines = 1024;
+-
+- AvailFBArea.x1 = 0;
+- AvailFBArea.y1 = 0;
+- AvailFBArea.x2 = pScrn->displayWidth;
+- AvailFBArea.y2 = lines;
+- xf86InitFBManager(pScreen, &AvailFBArea);
+-
+- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+- "Using %i scanlines of offscreen memory for pixmap caching\n",
+- lines - pScrn->virtualY);
+-
++
+ return(XAAInit(pScreen, infoPtr));
+ }
+
+--- XFree86-4.2.0/xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2200.c Sun Oct 28 04:33:42 2001
++++ XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2200.c Thu Apr 4 16:05:44 2002
+@@ -120,8 +120,6 @@
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ NEOPtr nPtr = NEOPTR(pScrn);
+ NEOACLPtr nAcl = NEOACLPTR(pScrn);
+- BoxRec AvailFBArea;
+- int lines;
+
+ nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
+ if(!infoPtr) return FALSE;
+@@ -251,19 +249,6 @@
+ return FALSE;
+ }
+
+- lines = nAcl->cacheEnd /
+- (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
+- if(lines > 1024) lines = 1024;
+-
+- AvailFBArea.x1 = 0;
+- AvailFBArea.y1 = 0;
+- AvailFBArea.x2 = pScrn->displayWidth;
+- AvailFBArea.y2 = lines;
+- xf86InitFBManager(pScreen, &AvailFBArea);
+-
+- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+- "Using %i scanlines of offscreen memory for pixmap caching\n",
+- lines - pScrn->virtualY);
+
+ return(XAAInit(pScreen, infoPtr));
+ }
+@@ -482,7 +467,7 @@
+ NEOPtr nPtr = NEOPTR(pScrn);
+
+ WAIT_ENGINE_IDLE();
+- OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
++ OUTREG(NEOREG_DSTSTARTOFF, (y <<16) | (x & 0xffff));
+ OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
+ }
+
+--- XFree86-4.2.0/xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_dga.c Mon Oct 1 15:44:07 2001
++++ XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_dga.c Thu Apr 4 16:05:44 2002
+@@ -43,8 +43,10 @@
+ static void NEO_SetViewport(ScrnInfoPtr, int, int, int);
+ static void NEO_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
+ static void NEO_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
++#if 0
+ static void NEO_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
+ unsigned long);
++#endif
+
+ static
+ DGAFunctionRec NEODGAFuncs = {
+@@ -76,7 +78,7 @@
+ imlines = (pScrn->videoRam * 1024) /
+ (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
+
+- pixlines = (imlines > 1024 && !pNEO->noAccel) ? 1024 : imlines;
++ pixlines = (imlines > 1024 && !pNEO->noAccel) ? 1024 : imlines;
+
+ pMode = firstMode = pScrn->modes;
+
+@@ -184,7 +186,7 @@
+ ){
+ NEOPtr pNEO = NEOPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+-
++
+ NEOAdjustFrame(pScrn->pScreen->myNum, x, y, flags);
+ /* wait for retrace */
+ while((hwp->readST01(hwp) & 0x08));
+@@ -240,7 +242,7 @@
+ }
+ }
+
+-
++#if 0
+ static void
+ NEO_BlitTransRect(
+ ScrnInfoPtr pScrn,
+@@ -252,7 +254,7 @@
+ /* this one should be separate since the XAA function would
+ prohibit usage of ~0 as the key */
+ }
+-
++#endif
+
+ static Bool
+ NEO_OpenFramebuffer(
+--- XFree86-4.2.0/xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_driver.c Fri Nov 30 13:11:57 2001
++++ XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_driver.c Sat Apr 6 19:49:40 2002
+@@ -299,7 +307,11 @@
+ OPTION_PROG_LCD_MODE_REGS,
+ OPTION_PROG_LCD_MODE_STRETCH,
+ OPTION_OVERRIDE_VALIDATE_MODE,
++ OPTION_SHOWCACHE,
+ OPTION_ROTATE,
++ OPTION_VIDEO_KEY,
++ OPTION_OVERLAYMEM,
++ OPTION_VIDEO_INTERLACE,
+ OPTION_DISPLAY_HEIGHT_480,
+ OPTION_STRANGE_LOCKUPS
+ } NEOOpts;
+@@ -314,6 +326,7 @@
+ { OPTION_LCD_STRETCH, "NoStretch", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_PCI_BURST, "pciBurst", OPTV_BOOLEAN, {0}, FALSE },
++ { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE },
+ { OPTION_PROG_LCD_MODE_REGS, "progLcdModeRegs",
+ OPTV_BOOLEAN, {0}, FALSE },
+@@ -321,6 +334,10 @@
+ OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_OVERRIDE_VALIDATE_MODE, "overrideValidateMode",
+ OPTV_BOOLEAN, {0}, FALSE },
++ { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE },
++ { OPTION_OVERLAYMEM, "OverlayMem", OPTV_INTEGER, {0}, FALSE },
++ { OPTION_VIDEO_INTERLACE, "Interlace",
++ OPTV_INTEGER, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+ };
+
+@@ -335,6 +352,7 @@
+ { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_LCD_STRETCH,"NoStretch", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_PCI_BURST, "pciBurst", OPTV_BOOLEAN, {0}, FALSE },
++ { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE },
+ { OPTION_STRANGE_LOCKUPS, "StrangeLockups", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DISPLAY_HEIGHT_480, "DisplayHeight480",
+@@ -345,6 +363,10 @@
+ OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_OVERRIDE_VALIDATE_MODE, "overrideValidateMode",
+ OPTV_BOOLEAN, {0}, FALSE },
++ { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE },
++ { OPTION_OVERLAYMEM, "OverlayMem", OPTV_INTEGER, {0}, FALSE },
++ { OPTION_VIDEO_INTERLACE, "Interlace",
++ OPTV_INTEGER, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+ };
+
+@@ -979,6 +1001,7 @@
+ xf86GetOptValBool(nPtr->Options, OPTION_LCD_CENTER,&nPtr->lcdCenter);
+ xf86GetOptValBool(nPtr->Options, OPTION_LCD_STRETCH,&nPtr->noLcdStretch);
+ xf86GetOptValBool(nPtr->Options, OPTION_SHADOW_FB,&nPtr->shadowFB);
++ xf86GetOptValBool(nPtr->Options, OPTION_SHOWCACHE,&nPtr->showcache);
+ nPtr->onPciBurst = TRUE;
+ xf86GetOptValBool(nPtr->Options, OPTION_PCI_BURST,&nPtr->onPciBurst);
+ xf86GetOptValBool(nPtr->Options,
+@@ -1014,6 +1037,39 @@
+ "Valid options are \"CW\" or \"CCW\"\n");
+ }
+ }
++#ifdef XvExtension
++ if(xf86GetOptValInteger(nPtr->Options,
++ OPTION_VIDEO_KEY, &(nPtr->videoKey))) {
++ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
++ nPtr->videoKey);
++ } else {
++ nPtr->videoKey = (1 << pScrn->offset.red) |
++ (1 << pScrn->offset.green) |
++ (((pScrn->mask.blue >> pScrn->offset.blue) - 1)
++ << pScrn->offset.blue);
++ }
++ if(xf86GetOptValInteger(nPtr->Options, OPTION_OVERLAYMEM,
++ &(nPtr->overlay))) {
++ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
++ "reserve %d bytes for overlay.\n", nPtr->overlay);
++ } else {
++ nPtr->overlay = 0;
++ }
++ nPtr->interlace = 0;
++ if(xf86GetOptValInteger(nPtr->Options, OPTION_VIDEO_INTERLACE,
++ &(nPtr->interlace))) {
++ if (nPtr->interlace >= 0 && nPtr->interlace <= 2){
++ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "interlace flag = %d\n",
++ nPtr->interlace);
++ } else {
++ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
++ "\"%s\" is not a valid value for "
++ "Option \"Interlaced\"\n", s);
++ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid options are 0..2\n");
++ }
++ }
++#endif /* XvExtension */
++
+
+ if (height_480 && nPtr->NeoPanelWidth == 800) {
+ xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
+@@ -1069,6 +1125,9 @@
+ if (nPtr->strangeLockups)
+ xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
+ "Option StrangeLockups set: disabling some acceleration\n");
++ if (nPtr->showcache)
++ xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
++ "Show chache for debugging\n");
+ if (nPtr->shadowFB) {
+ if (nPtr->noLinear) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+@@ -1096,6 +1155,8 @@
+ nPtr->NeoLinearAddr = 0;
+ }
+
++ nPtr->NeoMMIOAddr2 = 0;
++ nPtr->NeoMMIOBase2 = NULL;
+ if (nPtr->pEnt->device->IOBase && !nPtr->noMMIO) {
+ /* XXX Check this matches a PCI base address */
+ nPtr->NeoMMIOAddr = nPtr->pEnt->device->IOBase;
+@@ -1113,7 +1174,7 @@
+ "FB base address is set at 0x%X.\n",
+ nPtr->NeoLinearAddr);
+ }
+- if (!nPtr->NeoMMIOAddr) {
++ if (!nPtr->NeoMMIOAddr && !nPtr->noMMIO) {
+ switch (nPtr->NeoChipset) {
+ case NM2070 :
+ nPtr->NeoMMIOAddr = nPtr->NeoLinearAddr + 0x100000;
+@@ -1129,11 +1190,17 @@
+ case NM2360:
+ case NM2380:
+ nPtr->NeoMMIOAddr = nPtr->PciInfo->memBase[1];
++ nPtr->NeoMMIOAddr2 = nPtr->PciInfo->memBase[2];
+ break;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "MMIO base address is set at 0x%X.\n",
+ nPtr->NeoMMIOAddr);
++ if (nPtr->NeoMMIOAddr2 != 0){
++ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
++ "MMIO base address2 is set at 0x%X.\n",
++ nPtr->NeoMMIOAddr2);
++ }
+ }
+ /* XXX What about VGA resources in OPERATING mode? */
+ if (xf86RegisterResources(nPtr->pEnt->index, NULL, ResExclusive))
+@@ -1152,7 +1219,7 @@
+ "FB base address is set at 0x%X.\n",
+ nPtr->NeoLinearAddr);
+ }
+- if (!nPtr->NeoMMIOAddr) {
++ if (!nPtr->NeoMMIOAddr && !nPtr->noMMIO) {
+ nPtr->NeoMMIOAddr = nPtr->NeoLinearAddr + 0x100000;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "MMIO base address is set at 0x%X.\n",
+@@ -1293,6 +1360,10 @@
+ /* Should we re-save the text mode on each VT enter? */
+ if(!neoModeInit(pScrn, pScrn->currentMode))
+ return FALSE;
++#ifdef XvExtension
++ if (nPtr->video)
++ NEOResetVideo(pScrn);
++#endif
+ if (nPtr->NeoHWCursorShown)
+ NeoShowCursor(pScrn);
+ NEOAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+@@ -1384,12 +1455,12 @@
+ /* Map the Neo memory and possible MMIO areas */
+ if (!neoMapMem(pScrn))
+ return FALSE;
+-
++
+ /*
+ * next we save the current state and setup the first mode
+ */
+ neoSave(pScrn);
+-
++
+ if (!neoModeInit(pScrn,pScrn->currentMode))
+ return FALSE;
+ vgaHWSaveScreen(pScreen,SCREEN_SAVER_ON);
+@@ -1431,7 +1502,7 @@
+ nPtr->ShadowPtr = NULL;
+ FBStart = nPtr->NeoFbBase;
+ }
+-
++
+ ret = fbScreenInit(pScreen, FBStart,
+ width, height,
+ pScrn->xDpi, pScrn->yDpi,
+@@ -1509,13 +1580,13 @@
+ nPtr->NeoLinearAddr);
+ /* Setup pointers to free space in video ram */
+ allocatebase = (pScrn->videoRam << 10);
+- freespace = allocatebase - pScrn->displayWidth *
++ freespace = allocatebase - pScrn->displayWidth *
+ pScrn->virtualY * (pScrn->bitsPerPixel >> 3);
+ currentaddr = allocatebase;
+ xf86DrvMsg(scrnIndex, X_PROBED,
+ "%d bytes off-screen memory available\n", freespace);
+
+- if (nPtr->swCursor || nPtr->noMMIO) {
++ if (nPtr->swCursor || !nPtr->NeoMMIOBase) {
+ xf86DrvMsg(scrnIndex, X_CONFIG,
+ "Using Software Cursor.\n");
+ } else if (nPtr->NeoCursorMem <= freespace) {
+@@ -1530,19 +1601,52 @@
+ } else xf86DrvMsg(scrnIndex, X_ERROR,
+ "Too little space for H/W cursor.\n");
+
+- if (!nPtr->noAccel && nPtr->noMMIO)
++ if (!nPtr->noAccel && !nPtr->NeoMMIOBase)
+ xf86DrvMsg(pScrn->scrnIndex,X_INFO,
+ "Acceleration disabled when not using MMIO\n");
+-
+- /* Setup the acceleration primitives */
+- if (!nPtr->noAccel && !nPtr->noMMIO) {
++ {
++#ifdef XvExtension
++ if (nPtr->overlay > 0){
++ if (nPtr->overlay > freespace){
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,
++ "Can not reserve %d bytes for overlay. "
++ "Resize to %d bytes.\n",
++ nPtr->overlay, freespace);
++ nPtr->overlay = freespace;
++ }
++ currentaddr -= nPtr->overlay;
++ freespace -= nPtr->overlay;
++ nPtr->overlay_offset = currentaddr;
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Overlay at 0x%x\n",
++ nPtr->overlay_offset);
++ }
++#endif /* XvExtension */
+ nAcl->cacheStart = currentaddr - freespace;
+ nAcl->cacheEnd = currentaddr;
+ freespace = 0;
++ if (nAcl->cacheStart < nAcl->cacheEnd) {
++ BoxRec AvailFBArea;
++ int lines = nAcl->cacheEnd /
++ (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
++ if (!nPtr->noAccel && nPtr->NeoMMIOBase && lines > 1024)
++ lines = 1024;
++ AvailFBArea.x1 = 0;
++ AvailFBArea.y1 = 0;
++ AvailFBArea.x2 = pScrn->displayWidth;
++ AvailFBArea.y2 = lines;
++ xf86InitFBManager(pScreen, &AvailFBArea);
++
++ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
++ "Using %i scanlines of offscreen memory \n"
++ , lines - pScrn->virtualY);
++ }
++ }
++ /* Setup the acceleration primitives */
++ if (!nPtr->noAccel && nPtr->NeoMMIOBase) {
+ if (nAcl->cacheStart >= nAcl->cacheEnd) {
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Too little space for pixmap cache.\n");
+- }
++ }
+ switch(nPtr->NeoChipset) {
+ case NM2070 :
+ Neo2070AccelInit(pScreen);
+@@ -1624,6 +1728,8 @@
+
+ pScrn->racIoFlags = pScrn->racMemFlags = racflag;
+
++ NEOInitVideo(pScreen);
++
+ pScreen->SaveScreen = vgaHWSaveScreen;
+
+ /* Setup DPMS mode */
+@@ -1635,18 +1741,7 @@
+ pScrn->memPhysBase = (unsigned long)nPtr->NeoFbBase;
+ pScrn->fbOffset = 0;
+ }
+-
+-#ifdef XvExtension
+- {
+- XF86VideoAdaptorPtr *ptr;
+- int n;
+-
+- n = xf86XVListGenericAdaptors(pScrn,&ptr);
+- if (n)
+- xf86XVScreenInit(pScreen, ptr, n);
+- }
+-#endif
+-
++
+ /* Wrap the current CloseScreen function */
+ nPtr->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = NEOCloseScreen;
+@@ -1677,11 +1772,21 @@
+ int Base;
+
+ pScrn = xf86Screens[scrnIndex];
+- Base = (y * pScrn->displayWidth + x) >> 2;
+ hwp = VGAHWPTR(pScrn);
+ nPtr = NEOPTR(pScrn);
+- /* Scale Base by the number of bytes per pixel. */
+
++ if (nPtr->showcache && y) {
++ int lastline = nPtr->NeoFbMapSize /
++ ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8);
++
++ lastline -= pScrn->currentMode->VDisplay;
++ y += pScrn->virtualY - 1;
++ if (y > lastline) y = lastline;
++ }
++
++ Base = (y * pScrn->displayWidth + x) >> 2;
++
++ /* Scale Base by the number of bytes per pixel. */
+ switch (pScrn->depth) {
+ case 8 :
+ break;
+@@ -1730,6 +1835,7 @@
+ if (nPtr->NeoHWCursorShown)
+ NeoHideCursor(pScrn);
+ neoRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &nPtr->NeoSavedReg, TRUE);
++
+ neoLock(pScrn);
+ neoUnmapMem(pScrn);
+ }
+@@ -1845,12 +1951,18 @@
+
+ if (!nPtr->noLinear) {
+ if (!nPtr->noMMIO) {
+- if (nPtr->pEnt->location.type == BUS_PCI)
++ if (nPtr->pEnt->location.type == BUS_PCI){
+ nPtr->NeoMMIOBase =
+ xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
+ nPtr->PciTag, nPtr->NeoMMIOAddr,
+ 0x200000L);
+- else
++ if (nPtr->NeoMMIOAddr2 != 0){
++ nPtr->NeoMMIOBase2 =
++ xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
++ nPtr->PciTag, nPtr->NeoMMIOAddr2,
++ 0x100000L);
++ }
++ } else
+ nPtr->NeoMMIOBase =
+ xf86MapVidMem(pScrn->scrnIndex,
+ VIDMEM_MMIO, nPtr->NeoMMIOAddr,
+@@ -1889,8 +2001,14 @@
+ NEOPtr nPtr = NEOPTR(pScrn);
+
+ if (!nPtr->noLinear) {
+- xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoMMIOBase, 0x200000L);
++ if (nPtr->NeoMMIOBase)
++ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoMMIOBase,
++ 0x200000L);
+ nPtr->NeoMMIOBase = NULL;
++ if (nPtr->NeoMMIOBase2)
++ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoMMIOBase2,
++ 0x100000L);
++ nPtr->NeoMMIOBase2 = NULL;
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoFbBase,
+ nPtr->NeoFbMapSize);
+ }
+@@ -2200,7 +2318,7 @@
+ unsigned char temp;
+ int i;
+ Bool clock_hi = FALSE;
+-
++
+ vgaHWProtect(pScrn,TRUE); /* Blank the screen */
+
+ VGAwGR(0x09,0x26);
+@@ -2220,6 +2338,7 @@
+ * any reserved bits.
+ */
+ temp = VGArGR(0x90);
++
+ switch (nPtr->NeoChipset) {
+ case NM2070 :
+ temp &= 0xF0; /* Save bits 7:4 */
+@@ -2238,6 +2357,7 @@
+ break;
+ }
+ VGAwGR(0x90,temp);
++
+ /*
+ * In some rare cases a lockup might occur if we don't delay
+ * here. (Reported by Miles Lane)
+@@ -2256,7 +2376,6 @@
+ * had time to take effect.
+ */
+ xf86UDelay(200000);
+-
+ /*
+ * This function handles restoring the generic VGA registers. */
+ vgaHWRestore(pScrn, VgaReg,
+@@ -2273,6 +2392,7 @@
+ VGAwGR(0x11, restore->SysIfaceCntl2);
+ VGAwGR(0x15, restore->SingleAddrPage);
+ VGAwGR(0x16, restore->DualAddrPage);
++
+ temp = VGArGR(0x20);
+ switch (nPtr->NeoChipset) {
+ case NM2070 :
+@@ -2349,7 +2469,7 @@
+ }
+ if (restore->biosMode)
+ VGAwCR(0x23,restore->biosMode);
+-
++
+ if (restore->reg) {
+ VGAwCR(0x23,restore->reg->CR[0x23]);
+ VGAwCR(0x25,restore->reg->CR[0x25]);
+@@ -2371,13 +2491,13 @@
+ VGAwGR(i, restore->reg->GR[i]);
+ }
+ }
++
+ /* Program vertical extension register */
+ if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230
+ || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) {
+ VGAwCR(0x70, restore->VerticalExt);
+ }
+-
+-
++
+ vgaHWProtect(pScrn, FALSE); /* Turn on screen */
+
+ }
+@@ -2574,7 +2694,7 @@
+ NeoNew->PanelHorizCenterReg3 = 0x00;
+ NeoNew->PanelHorizCenterReg4 = 0x00;
+ NeoNew->PanelHorizCenterReg5 = 0x00;
+-
++
+ if (nPtr->lcdCenter &&
+ (NeoNew->PanelDispCntlReg1 & 0x02)) {
+ if (mode->HDisplay == nPtr->NeoPanelWidth) {
+@@ -2632,6 +2752,18 @@
+ }
+ }
+ }
++#ifdef XvExtension
++ if (!noLcdStretch) {
++ if (mode->HDisplay != nPtr->NeoPanelWidth)
++ nPtr->videoHZoom = (double)nPtr->NeoPanelWidth/mode->HDisplay;
++ if (mode->VDisplay != nPtr->NeoPanelHeight)
++ nPtr->videoVZoom = (double)nPtr->NeoPanelHeight/mode->VDisplay;
++ } else {
++ nPtr->videoHZoom = 1.0;
++ nPtr->videoVZoom = 1.0;
++ }
++#endif
++
+ NeoNew->biosMode = neoFindMode(mode->HDisplay,mode->VDisplay,pScrn->depth);
+
+ /*
+@@ -2764,9 +2896,8 @@
+ }
+
+ /* Turn the screen on/off */
+- outb(0x3C4, 0x01);
+- SEQ01 |= inb(0x3C5) & ~0x20;
+- outb(0x3C5, SEQ01);
++ SEQ01 |= VGArSR(0x01) & ~0x20;
++ VGAwSR(0x01, SEQ01);
+
+ /* Turn the LCD on/off */
+ LCD_on |= VGArGR(0x20) & ~0x02;
+--- XFree86-4.2.0/xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_video.c Thu Jan 1 01:00:00 1970
++++ XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_video.c Thu Apr 4 16:05:44 2002
+@@ -0,0 +1,1232 @@
++/**********************************************************************
++Copyright 2002 by Shigehiro Nomura.
++
++ All Rights Reserved
++
++Permission to use, copy, modify, distribute, and sell this software and
++its documentation for any purpose is hereby granted without fee,
++provided that the above copyright notice appear in all copies and that
++both that copyright notice and this permission notice appear in
++supporting documentation, and that the name of Shigehiro Nomura not be
++used in advertising or publicity pertaining to distribution of the
++software without specific, written prior permission. Shigehiro Nomura
++and its suppliers make no representations about the suitability of this
++software for any purpose. It is provided "as is" without express or
++implied warranty.
++
++SHIGEHIRO NOMURA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++EVENT SHALL SHIGEHIRO NOMURA AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
++CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++**********************************************************************/
++
++/*
++ * Copyright 2002 SuSE Linux AG, Author: Egbert Eich
++ */
++
++#include "neo.h"
++#include "neo_video.h"
++
++#define nElems(x) (sizeof(x) / sizeof(x[0]))
++#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
++
++#if defined(XvExtension)
++
++#include "dixstruct.h"
++#include "xaa.h"
++#include "xaalocal.h"
++
++static XF86VideoAdaptorPtr NEOSetupVideo(ScreenPtr);
++
++static int NEOPutVideo(ScrnInfoPtr, short, short, short, short,
++ short, short, short, short, RegionPtr, pointer);
++
++static void NEOStopVideo(ScrnInfoPtr, pointer, Bool);
++static int NEOSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
++static int NEOGetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
++static void NEOQueryBestSize(ScrnInfoPtr, Bool, short, short, short,
++ short, unsigned int *, unsigned int *, pointer);
++static int NEOPutImage(ScrnInfoPtr, short, short, short, short, short, short,
++ short, short, int, unsigned char *, short, short, Bool,
++ RegionPtr, pointer);
++static int NEOQueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
++ unsigned short *, int *, int *);
++
++static Bool RegionsEqual(RegionPtr, RegionPtr);
++static void NEODisplayVideo(ScrnInfoPtr, int, int, short, short, int, int,
++ int, int, int, BoxPtr, short, short, short, short);
++
++static void NEOInitOffscreenImages(ScreenPtr);
++static FBLinearPtr NEOAllocateMemory(ScrnInfoPtr, FBLinearPtr, int);
++static void NEOCopyData(unsigned char *, unsigned char *, int, int, int, int);
++static void NEOCopyYV12Data(unsigned char *, unsigned char *, unsigned char *,
++ unsigned char *, int, int, int, int, int);
++
++static int NEOAllocSurface(ScrnInfoPtr, int, unsigned short, unsigned short,
++ XF86SurfacePtr);
++static int NEOFreeSurface(XF86SurfacePtr);
++static int NEODisplaySurface(XF86SurfacePtr, short, short, short, short,
++ short, short, short, short, RegionPtr clipBoxes);
++static int NEOStopSurface(XF86SurfacePtr);
++static int NEOGetSurfaceAttribute(ScrnInfoPtr, Atom, INT32 *);
++static int NEOSetSurfaceAttribute(ScrnInfoPtr, Atom, INT32);
++
++static Atom xvColorKey, xvBrightness, xvInterlace;
++
++void
++NEOInitVideo(ScreenPtr pScreen)
++{
++ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
++ NEOPtr nPtr = NEOPTR(pScrn);
++ XF86VideoAdaptorPtr *overlayAdaptors, *newAdaptors = NULL;
++ XF86VideoAdaptorPtr newAdaptor = NULL;
++ int numAdaptors;
++
++ numAdaptors = xf86XVListGenericAdaptors(pScrn, &overlayAdaptors);
++
++ if (nPtr->NeoChipset >= NM2160
++ && !nPtr->noLinear
++ && nPtr->NeoMMIOBase2 != NULL){
++ nPtr->video = TRUE;
++ newAdaptor = NEOSetupVideo(pScreen);
++ NEOInitOffscreenImages(pScreen);
++ } else
++ nPtr->video = FALSE;
++
++ if (newAdaptor){
++ if (!numAdaptors){
++ numAdaptors = 1;
++ overlayAdaptors = &newAdaptor;
++ } else {
++ newAdaptors = xalloc((numAdaptors + 1)
++ * sizeof(XF86VideoAdaptorPtr*));
++ if (newAdaptors){
++ memcpy(newAdaptors, overlayAdaptors,
++ numAdaptors * sizeof(XF86VideoAdaptorPtr));
++ newAdaptors[numAdaptors++] = newAdaptor;
++ overlayAdaptors = newAdaptors;
++ }
++ }
++ }
++
++ if (numAdaptors)
++ xf86XVScreenInit(pScreen, overlayAdaptors, numAdaptors);
++
++ if (newAdaptors)
++ xfree(newAdaptors);
++}
++
++static XF86VideoEncodingRec NEOVideoEncodings[] =
++{
++ {
++ NEO_VIDEO_VIDEO,
++ "XV_VIDEO",
++ 1024, 1024,
++ {1, 1}
++ },
++ {
++ NEO_VIDEO_IMAGE,
++ "XV_IMAGE",
++ 1024, 1024,
++ {1, 1}
++ }
++};
++
++static XF86VideoFormatRec NEOVideoFormats[] =
++{
++ { 8, PseudoColor },
++ { 15, TrueColor },
++ { 16, TrueColor },
++ { 24, TrueColor },
++};
++
++static XF86AttributeRec NEOVideoAttributes[] =
++{
++ {
++ XvSettable | XvGettable,
++ 0x000000, 0xFFFFFF,
++ "XV_COLORKEY"
++ },
++ {
++ XvSettable | XvGettable,
++ -128, 127,
++ "XV_BRIGHTNESS"
++ },
++ {
++ XvSettable | XvGettable,
++ 0,2,
++ "XV_INTERLACE"
++ },
++};
++
++static XF86ImageRec NEOVideoImages[] =
++{
++ XVIMAGE_YUY2,
++ XVIMAGE_YV12,
++ XVIMAGE_I420,
++ {
++ FOURCC_RV15,
++ XvRGB,
++ LSBFirst,
++ { 'R', 'V' ,'1', '5',
++ 0x00,'5',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
++ 16,
++ XvPacked,
++ 1,
++ 15, 0x001F, 0x03E0, 0x7C00,
++ 0, 0, 0,
++ 0, 0, 0,
++ 0, 0, 0,
++ { 'R', 'V', 'B' },
++ XvTopToBottom
++ },
++ {
++ FOURCC_RV16,
++ XvRGB,
++ LSBFirst,
++ { 'R', 'V' ,'1', '6',
++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
++ 16,
++ XvPacked,
++ 1,
++ 16, 0x001F, 0x07E0, 0xF800,
++ 0, 0, 0,
++ 0, 0, 0,
++ 0, 0, 0,
++ { 'R', 'V', 'B' },
++ XvTopToBottom
++ }
++};
++
++static XF86VideoAdaptorPtr
++NEOSetupVideo(ScreenPtr pScreen)
++{
++ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
++ NEOPtr nPtr = NEOPTR(pScrn);
++ NEOPortPtr pPriv;
++ XF86VideoAdaptorPtr overlayAdaptor;
++ int i;
++
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetupVideo\n");
++#endif
++ if ((overlayAdaptor = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
++ sizeof(DevUnion) +
++ sizeof(NEOPortRec))) == NULL){
++ return (NULL);
++ }
++
++ overlayAdaptor->type = XvInputMask | XvImageMask | XvWindowMask
++ | XvOutputMask | XvVideoMask;
++ overlayAdaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
++ overlayAdaptor->name = "NeoMagic Video Engine";
++ overlayAdaptor->nEncodings = nElems(NEOVideoEncodings);
++ overlayAdaptor->pEncodings = NEOVideoEncodings;
++ for (i = 0; i < nElems(NEOVideoEncodings); i++){
++ NEOVideoEncodings[i].width = 1024;
++ NEOVideoEncodings[i].height = 1024;
++ }
++ overlayAdaptor->nFormats = nElems(NEOVideoFormats);
++ overlayAdaptor->pFormats = NEOVideoFormats;
++ overlayAdaptor->nPorts = 1;
++ overlayAdaptor->pPortPrivates = (DevUnion*) &overlayAdaptor[1];
++ overlayAdaptor->pPortPrivates[0].ptr =
++ (pointer) &overlayAdaptor->pPortPrivates[1];
++ overlayAdaptor->nAttributes = nElems(NEOVideoAttributes);
++ overlayAdaptor->pAttributes = NEOVideoAttributes;
++ overlayAdaptor->nImages = nElems(NEOVideoImages);
++ overlayAdaptor->pImages = NEOVideoImages;
++
++ overlayAdaptor->PutVideo = NEOPutVideo;
++ overlayAdaptor->PutStill = NULL;
++ overlayAdaptor->GetVideo = NULL;
++ overlayAdaptor->GetStill = NULL;
++
++ overlayAdaptor->StopVideo = NEOStopVideo;
++ overlayAdaptor->SetPortAttribute = NEOSetPortAttribute;
++ overlayAdaptor->GetPortAttribute = NEOGetPortAttribute;
++ overlayAdaptor->QueryBestSize = NEOQueryBestSize;
++ overlayAdaptor->PutImage = NEOPutImage;
++ overlayAdaptor->QueryImageAttributes = NEOQueryImageAttributes;
++
++ pPriv = (NEOPortPtr)overlayAdaptor->pPortPrivates[0].ptr;
++ pPriv->colorKey = nPtr->videoKey;
++ pPriv->interlace = nPtr->interlace;
++ pPriv->videoStatus = 0;
++ pPriv->brightness = 0;
++ REGION_INIT(pScreen, &pPriv->clip, NullBox, 0);
++ nPtr->overlayAdaptor = overlayAdaptor;
++
++ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
++ xvColorKey = MAKE_ATOM("XV_COLORKEY");
++ xvInterlace = MAKE_ATOM("XV_INTERLACE");
++
++ NEOResetVideo(pScrn);
++
++ return (overlayAdaptor);
++}
++
++void
++NEOResetVideo(ScrnInfoPtr pScrn)
++{
++ NEOPtr nPtr = NEOPTR(pScrn);
++ NEOPortPtr pPriv = (NEOPortPtr)nPtr->overlayAdaptor->pPortPrivates[0].ptr;
++ int r, g, b;
++ VGA_HWP(pScrn);
++
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOResetVideo\n");
++#endif
++ switch (pScrn->depth){
++ case 8:
++ OUTGR(0xc6, pPriv->colorKey & 0);
++ OUTGR(0xc5, pPriv->colorKey & 0xff);
++ OUTGR(0xc7, pPriv->colorKey & 0);
++ break;
++ default:
++ r = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
++ g = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
++ b = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
++ OUTGR(0xc5, r);
++ OUTGR(0xc6, g);
++ OUTGR(0xc7, b);
++ break;
++ }
++ OUTGR(0xc4, pPriv->brightness);
++}
++
++static int
++NEOPutVideo(ScrnInfoPtr pScrn,
++ short src_x, short src_y, short drw_x, short drw_y,
++ short src_w, short src_h, short drw_w, short drw_h,
++ RegionPtr clipBoxes, pointer data)
++{
++ NEOPortPtr pPriv = (NEOPortPtr)data;
++ NEOPtr nPtr = NEOPTR(pScrn);
++ CARD32 src_pitch, offset;
++ int xscale, yscale;
++ BoxRec dstBox;
++ INT32 x1, y1, x2, y2;
++ int size, bpp;
++ unsigned char capctrl;
++ VGA_HWP(pScrn);
++
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: src: %d %d %d %d\n",
++ src_x, src_y, src_w, src_h);
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: drw: %d %d %d %d\n",
++ drw_x, drw_y, drw_w, drw_h);
++#endif
++ if (src_w > 720)
++ src_w = 720;
++ if (src_h > 576)
++ src_h = 576;
++ if (pPriv->interlace != 2)
++ src_h /= 2;
++ x1 = src_x;
++ y1 = src_y;
++ x2 = src_x + src_w;
++ y2 = src_y + src_h;
++
++ dstBox.x1 = drw_x;
++ dstBox.y1 = drw_y;
++ dstBox.x2 = drw_x + drw_w;
++ dstBox.y2 = drw_y + drw_h;
++
++ if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2,
++ clipBoxes, src_w, src_h)){
++ return(Success);
++ }
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: %d %d %d %d\n",
++ x1, y1, x2, y2);
++#endif
++
++ dstBox.x1 -= pScrn->frameX0;
++ dstBox.y1 -= pScrn->frameY0;
++ dstBox.x2 -= pScrn->frameX0;
++ dstBox.y2 -= pScrn->frameY0;
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: dstBox %d %d %d %d\n",
++ dstBox.x1, dstBox.y1, dstBox.x2, dstBox.y2);
++#endif
++
++ bpp = (pScrn->bitsPerPixel + 1) >> 3;
++ src_pitch = (src_w + 7) & ~7;
++
++ xscale = 0x1000;
++ if (src_w <= drw_w){
++ xscale = (src_w * 0x1000 / drw_w) & 0xffff;
++ }
++
++ yscale = 0x1000;
++ if (src_h <= drw_h){
++ yscale = (src_h * 0x1000 / drw_h) & 0xffff;
++ }
++
++ size = src_h * src_pitch * 2;
++
++ if (size > nPtr->overlay){
++ if ((pPriv->linear = NEOAllocateMemory(pScrn, pPriv->linear, size))
++ == NULL){
++ return (BadAlloc);
++ }
++ } else {
++ pPriv->linear = NULL;
++ }
++
++ if (pPriv->linear == NULL){
++ offset = nPtr->overlay_offset;
++ } else {
++ offset = pPriv->linear->offset * bpp;
++ }
++
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: offset=0x%x\n", offset);
++#endif
++ WAIT_ENGINE_IDLE();
++ memset(nPtr->NeoFbBase + offset, 0, size);
++
++ if (!RegionsEqual(&pPriv->clip, clipBoxes)){
++ REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
++ xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey,
++ clipBoxes);
++ }
++
++ x1 >>= 16;
++ y1 >>= 16;
++ x2 >>= 16;
++ y2 >>= 16;
++
++ switch (nPtr->NeoChipset) {
++ default:
++ case NM2160:
++ offset/=2;
++ OUTGR(0xbc, 0x4f);
++ break;
++ case NM2200:
++ case NM2230:
++ case NM2360:
++ case NM2380:
++ OUTGR(0xbc, 0x2e);
++ break;
++ }
++
++
++ OUTGR(0xb1, (((dstBox.x2-1) >> 4) & 0xf0) | ((dstBox.x1 >> 8) & 0x0f));
++ OUTGR(0xb2, dstBox.x1);
++ OUTGR(0xb3, dstBox.x2 - 1);
++ OUTGR(0xb4, (((dstBox.y2 - 1) >> 4) & 0xf0) | ((dstBox.y1 >> 8) & 0x0f));
++ OUTGR(0xb5, dstBox.y1);
++ OUTGR(0xb6, dstBox.y2 - 1);
++ OUTGR(0xb7, offset >> 16);
++ OUTGR(0xb8, offset >> 8);
++ OUTGR(0xb9, offset );
++ OUTGR(0xba, src_pitch >> 8);
++ OUTGR(0xbb, src_pitch);
++
++ OUTGR(0xc0, xscale >> 8);
++ OUTGR(0xc1, xscale);
++ OUTGR(0xc2, yscale >> 8);
++ OUTGR(0xc3, yscale);
++ OUTGR(0xbf, 0x02);
++
++ OUTGR(0x0a, 0x21);
++
++ OUTSR(0x0c, offset );
++ OUTSR(0x0d, offset >> 8);
++ OUTSR(0x0e, offset >> 16);
++ OUTSR(0x1a, src_pitch);
++ OUTSR(0x1b, src_pitch>>8);
++
++ OUTSR(0x17, 0 + x1);
++ OUTSR(0x18, 0 + x2 -1);
++ OUTSR(0x19, (((0 + x2 - 1) >> 4) & 0xf0) | (((0 + x1) >> 8) & 0x0f));
++
++ OUTSR(0x14, 14 + y1);
++ OUTSR(0x15, 14 + y2 - 2);
++ OUTSR(0x16, (((14 + y2 - 1) >> 4) & 0xf0) | (((14 + y1) >> 8) & 0x0f));
++
++ OUTSR(0x1c, 0xfb);
++ OUTSR(0x1d, 0x00);
++ OUTSR(0x1e, 0xe2);
++ OUTSR(0x1f, 0x02);
++
++ OUTSR(0x09, 0x11);
++ OUTSR(0x0a, 0x00);
++
++ capctrl = 0x21;
++ switch (pPriv->interlace){
++ case 0: /* Combine 2 fields */
++ break;
++ case 1: /* one field only */
++ capctrl |= 0x80;
++ break;
++ case 2: /* Interlaced fields */
++ capctrl |= 0x40;
++ break;
++ }
++ OUTSR(0x08, capctrl);
++
++#if 0
++ OUTGR(0x0a, 0x01);
++#endif
++ OUTGR(0xb0, 0x03);
++
++ pPriv->videoStatus = CLIENT_VIDEO_ON;
++ return (Success);
++}
++
++static void
++NEOStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit)
++{
++ NEOPortPtr pPriv = (NEOPortPtr)data;
++ NEOPtr nPtr = NEOPTR(pScrn);
++ VGA_HWP(pScrn);
++
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOStopVideo\n");
++#endif
++ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
++
++ if (exit){
++ if (pPriv->videoStatus & CLIENT_VIDEO_ON){
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOStopVideo: stop capture\n");
++#endif
++ OUTGR(0xb0, 0x02);
++ OUTGR(0x0a, 0x21);
++ OUTSR(0x08, 0xa0);
++#if 0
++ OUTGR(0x0a, 0x01);
++#endif
++ }
++ if (pPriv->linear != NULL){
++ xf86FreeOffscreenLinear(pPriv->linear);
++ pPriv->linear = NULL;
++ }
++ pPriv->videoStatus = 0;
++ } else {
++ if (pPriv->videoStatus & CLIENT_VIDEO_ON){
++ OUTGR(0xb0, 0x02);
++ OUTGR(0x0a, 0x21);
++ OUTSR(0x08, 0xa0);
++#if 0
++ OUTGR(0x0a, 0x01);
++#endif
++ pPriv->videoStatus |= OFF_TIMER;
++ pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
++ }
++ }
++}
++
++static int
++NEOSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value,
++ pointer data)
++{
++ NEOPortPtr pPriv = (NEOPortPtr)data;
++ NEOPtr nPtr = NEOPTR(pScrn);
++ VGA_HWP(pScrn);
++
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetPortAttribute\n");
++#endif
++ if (attribute == xvColorKey){
++ int r, g, b;
++
++ pPriv->colorKey = value;
++ switch (pScrn->depth){
++ case 8:
++ OUTGR(0xc6, pPriv->colorKey & 0xff);
++ OUTGR(0xc5, 0x00);
++ OUTGR(0xc7, 0x00);
++ break;
++ default:
++ r = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
++ g = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
++ b = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
++ OUTGR(0xc5, r);
++ OUTGR(0xc6, g);
++ OUTGR(0xc7, b);
++ }
++ } else if (attribute == xvBrightness){
++ if ((value < -128) || (value > 127)){
++ return (BadValue);
++ }
++ pPriv->brightness = value;
++ OUTGR(0xc4, value);
++ } else if (attribute == xvInterlace){
++ if (value < 0 || value > 2){
++ return (BadValue);
++ }
++ pPriv->interlace = value;
++ } else {
++ return (BadMatch);
++ }
++ return (Success);
++}
++
++static int
++NEOGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value,
++ pointer data)
++{
++ NEOPortPtr pPriv = (NEOPortPtr)data;
++
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOGetPortAttribute\n");
++#endif
++ if (attribute == xvColorKey){
++ *value = pPriv->colorKey;
++ } else if (attribute == xvBrightness){
++ *value = pPriv->brightness;
++ } else if (attribute == xvInterlace){
++ *value = pPriv->interlace;
++ } else {
++ return (BadMatch);
++ }
++ return (Success);
++}
++
++static void
++NEOQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
++ short vid_w, short vid_h, short drw_w, short drw_h,
++ unsigned int *p_w, unsigned int *p_h,
++ pointer data)
++{
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOQueryBestSize\n");
++#endif
++ *p_w = min(drw_w, 1024);
++ *p_h = min(drw_h, 1024);
++}
++
++static int
++NEOPutImage(ScrnInfoPtr pScrn,
++ short src_x, short src_y, short drw_x, short drw_y,
++ short src_w, short src_h, short drw_w, short drw_h,
++ int id, unsigned char *buf, short width, short height,
++ Bool sync, RegionPtr clipBoxes, pointer data)
++{
++ NEOPtr nPtr = NEOPTR(pScrn);
++ NEOPortPtr pPriv = (NEOPortPtr)nPtr->overlayAdaptor->pPortPrivates[0].ptr;
++ INT32 x1, y1, x2, y2;
++ int bpp;
++ int srcPitch, srcPitch2 = 0, dstPitch, size;
++ BoxRec dstBox;
++ CARD32 offset, offset2 = 0, offset3 = 0, tmp;
++ int left, top, nPixels, nLines;
++ unsigned char *dstStart;
++
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutImage\n");
++#endif
++
++ x1 = src_x;
++ y1 = src_y;
++ x2 = src_x + src_w;
++ y2 = src_y + src_h;
++
++ dstBox.x1 = drw_x;
++ dstBox.y1 = drw_y;
++ dstBox.x2 = drw_x + drw_w;
++ dstBox.y2 = drw_y + drw_h;
++
++ if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2,
++ clipBoxes, width, height)){
++ return (Success);
++ }
++
++ dstBox.x1 -= pScrn->frameX0;
++ dstBox.y1 -= pScrn->frameY0;
++ dstBox.x2 -= pScrn->frameX0;
++ dstBox.y2 -= pScrn->frameY0;
++
++ bpp = ((pScrn->bitsPerPixel + 1) >> 3);
++
++ switch (id){
++ case FOURCC_YV12:
++ srcPitch = (width + 3) & ~3;
++ offset2 = srcPitch * height;
++ srcPitch2 = ((width >> 1) + 3) & ~3;
++ offset3 = offset2 + (srcPitch2 * (height >> 1));
++ dstPitch = ((width << 1) + 15) & ~15;
++ break;
++ case FOURCC_I420:
++ srcPitch = (width + 3) & ~3;
++ offset3 = srcPitch * height;
++ srcPitch2 = ((width >> 1) + 3) & ~3;
++ offset2 = offset3 + (srcPitch2 * (height >> 1));
++ dstPitch = ((width << 1) + 15) & ~15;
++ break;
++ case FOURCC_YUY2:
++ case FOURCC_RV15:
++ case FOURCC_RV16:
++ default:
++ srcPitch = width << 1;
++ dstPitch = (srcPitch + 15) & ~15;
++ break;
++ }
++
++ size = dstPitch * height;
++ if (size > nPtr->overlay){
++ if ((pPriv->linear = NEOAllocateMemory(pScrn, pPriv->linear, size))
++ == NULL){
++ return (BadAlloc);
++ }
++ } else {
++ pPriv->linear = NULL;
++ }
++
++ top = y1 >> 16;
++ left = (x1 >> 16) & ~1;
++ nPixels = ((((x2 + 0xFFFF) >> 16) + 1) & ~1) - left;
++ left <<= 1;
++
++ if (pPriv->linear == NULL){
++ offset = nPtr->overlay_offset;
++ } else {
++ offset = pPriv->linear->offset * bpp;
++ }
++
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"offset=%x\n", offset);
++#endif
++
++ dstStart = (unsigned char *)(nPtr->NeoFbBase + offset + left);
++
++ switch (id){
++ case FOURCC_YV12:
++ case FOURCC_I420:
++ top &= ~1;
++ tmp = ((top >> 1) * srcPitch2) + (left >> 2);
++ offset2 += tmp;
++ offset3 += tmp;
++ nLines = ((((y2 + 0xFFFF) >> 16) + 1) & ~1) - top;
++ NEOCopyYV12Data(buf + (top * srcPitch) + (left >> 1), buf + offset2,
++ buf + offset3, dstStart, srcPitch, srcPitch2,
++ dstPitch, nLines, nPixels);
++ break;
++ default:
++ buf += (top * srcPitch) + left;
++ nLines = ((y2 + 0xFFFF) >> 16) - top;
++ NEOCopyData(buf, dstStart, srcPitch, dstPitch, nLines, nPixels << 1);
++ }
++
++ if (!RegionsEqual(&pPriv->clip, clipBoxes)){
++ REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
++ xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
++ }
++ NEODisplayVideo(pScrn, id, offset, width, height, dstPitch, x1, y1,
++ x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
++
++ pPriv->videoStatus = CLIENT_VIDEO_ON;
++ return (Success);
++
++}
++
++static int
++NEOQueryImageAttributes(ScrnInfoPtr pScrn, int id,
++ unsigned short *width, unsigned short *height,
++ int *pitches, int *offsets)
++{
++ int size, tmp;
++
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOQueryImageAttributes\n");
++#endif
++ if (*width > 1024){
++ *width = 1024;
++ }
++ if (*height > 1024){
++ *height = 1024;
++ }
++
++ *width = (*width + 1) & ~1;
++ if (offsets != NULL){
++ offsets[0] = 0;
++ }
++
++ switch (id){
++ case FOURCC_YV12:
++ case FOURCC_I420:
++ *height = (*height + 1) & ~1;
++ size = (*width + 3) & ~3;
++ if (pitches != NULL){
++ pitches[0] = size;
++ }
++ size *= *height;
++ if (offsets != NULL){
++ offsets[1] = size;
++ }
++ tmp = ((*width >> 1) + 3) & ~3;
++ if (pitches != NULL){
++ pitches[1] = pitches[2] = tmp;
++ }
++ tmp *= (*height >> 1);
++ size += tmp;
++ if (offsets != NULL){
++ offsets[2] = size;
++ }
++ size += tmp;
++ break;
++ case FOURCC_YUY2:
++ case FOURCC_RV15:
++ case FOURCC_RV16:
++ default:
++ size = *width * 2;
++ if (pitches != NULL){
++ pitches[0] = size;
++ }
++ size *= *height;
++ break;
++ }
++ return (size);
++}
++
++static Bool
++RegionsEqual(RegionPtr A, RegionPtr B)
++{
++ int *dataA, *dataB;
++ int num;
++
++ num = REGION_NUM_RECTS(A);
++ if (num != REGION_NUM_RECTS(B)){
++ return (FALSE);
++ }
++
++ if ((A->extents.x1 != B->extents.x1)
++ || (A->extents.y1 != B->extents.y1)
++ || (A->extents.x2 != B->extents.x2)
++ || (A->extents.y2 != B->extents.y2)){
++ return (FALSE);
++ }
++
++ dataA = (int*) REGION_RECTS(A);
++ dataB = (int*) REGION_RECTS(B);
++
++ while (num--){
++ if ((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])){
++ return (FALSE);
++ }
++ dataA += 2;
++ dataB += 2;
++ }
++ return (TRUE);
++}
++
++static void
++NEODisplayVideo(ScrnInfoPtr pScrn, int id, int offset,
++ short width, short height, int pitch,
++ int x1, int y1, int x2, int y2, BoxPtr dstBox,
++ short src_w, short src_h, short drw_w, short drw_h)
++{
++ NEOPtr nPtr = NEOPTR(pScrn);
++ int hstretch, vstretch, fmt;
++ VGA_HWP(pScrn);
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEODisplayVideo\n");
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEODisplayVideo src_w=%d, src_h=%d, pitch=%d, drw_w=%d, drw_h=%d\n", src_w, src_h, pitch, drw_w, drw_h);
++#endif
++#define WIDTH_THRESHOLD 160
++ if (dstBox->x2 >= pScrn->virtualX) {
++ /*
++ * This is a hack to work around a problem when video is moved
++ * accross the right border.
++ */
++ int diff_s = (width - ((x2 - x1) >> 16)) & ~1;
++ int diff_d = (drw_w - dstBox->x2 + dstBox->x1) & ~1;
++
++ offset -= 2 * ((diff_s > diff_d) ? diff_d : diff_s);
++ dstBox->x1 -= diff_d;
++ } else if (dstBox->x2 - dstBox->x1 < WIDTH_THRESHOLD) {
++ /*
++ * When the video window is less than about 160 pixel wide
++ * it will be distoreted. We attempt to fix it by actually
++ * making it wider and relying on the color key to prevent
++ * it from appearanig outside of the video.
++ */
++ int pre, post;
++ int scale = 1;
++
++ if (dstBox->x1 < WIDTH_THRESHOLD) {
++ pre = dstBox->x1;
++ post = 160 - pre;
++ } else {
++ pre = 160;
++ post = 0;
++ }
++ offset -= 2 * scale * pre;
++ dstBox->x1 -= pre;
++ dstBox->x2 += post;
++ }
++ if (nPtr->videoHZoom != 1.0) {
++ if ((dstBox->x2 += 5) > pScrn->virtualX)
++ dstBox->x2 = pScrn->virtualX;
++ if (dstBox->x1 > 0) dstBox->x1 += 2;
++ }
++
++ fmt = 0x00;
++ switch (id){
++ case FOURCC_YV12:
++ case FOURCC_I420:
++ case FOURCC_YUY2:
++ fmt = 0x00;
++ break;
++ case FOURCC_RV15:
++ case FOURCC_RV16:
++ fmt = 0x20;
++ break;
++ }
++
++ offset += (x1 >> 15) & ~0x03;
++
++ switch (nPtr->NeoChipset) {
++ default:
++ case NM2160:
++ offset/=2;
++ pitch/=2;
++ OUTGR(0xbc, 0x4f);
++ break;
++ case NM2200:
++ case NM2230:
++ case NM2360:
++ case NM2380:
++ OUTGR(0xbc, 0x2e);
++ break;
++ }
++
++ /* factor 4 for granularity */
++ hstretch = (double)0x1000 * 4 / (int)(nPtr->videoHZoom * 4);
++ if (drw_w > src_w)
++ hstretch = (((int)src_w) * hstretch) / (int) drw_w;
++
++ vstretch = (double)0x1000 / nPtr->videoVZoom;
++ if (drw_h > src_h)
++ vstretch = (((int)src_h) * vstretch )/ (int) drw_h;
++
++ OUTGR(0xb1, (((dstBox->x2 - 1) >> 4) & 0xf0) | ((dstBox->x1 >> 8) & 0x0f));
++ OUTGR(0xb2, dstBox->x1);
++ OUTGR(0xb3, dstBox->x2 - 1);
++ OUTGR(0xb4, (((dstBox->y2 - 1) >> 4) & 0xf0) | ((dstBox->y1 >> 8) & 0x0f));
++ OUTGR(0xb5, dstBox->y1);
++ OUTGR(0xb6, dstBox->y2 - 1);
++ OUTGR(0xb7, offset >> 16);
++ OUTGR(0xb8, offset >> 8);
++ OUTGR(0xb9, offset );
++ OUTGR(0xba, pitch >> 8);
++ OUTGR(0xbb, pitch);
++
++ OUTGR(0xbd, 0x02);
++ OUTGR(0xbe, 0x00);
++ OUTGR(0xbf, 0x02);
++
++ OUTGR(0xc0, hstretch >> 8);
++ OUTGR(0xc1, hstretch);
++ OUTGR(0xc2, vstretch >> 8);
++ OUTGR(0xc3, vstretch);
++
++ OUTGR(0xb0, fmt | 0x03);
++
++ OUTGR(0x0a, 0x21);
++ OUTSR(0x08, 0xa0);
++ OUTGR(0x0a, 0x01);
++}
++
++static void
++NEOInitOffscreenImages(ScreenPtr pScreen)
++{
++ XF86OffscreenImagePtr offscreenImages;
++
++#ifdef DEBUG
++ xf86DrvMsg(xf86Screens[pScreen->myNum]->scrnIndex,X_INFO,"NEOInitOffscreenImages\n");
++#endif
++ if ((offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))) == NULL){
++ return;
++ }
++
++ offscreenImages->image = NEOVideoImages;
++ offscreenImages->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
++ offscreenImages->alloc_surface = NEOAllocSurface;
++ offscreenImages->free_surface = NEOFreeSurface;
++ offscreenImages->display = NEODisplaySurface;
++ offscreenImages->stop = NEOStopSurface;
++ offscreenImages->getAttribute = NEOGetSurfaceAttribute;
++ offscreenImages->setAttribute = NEOSetSurfaceAttribute;
++ offscreenImages->max_width = 1024;
++ offscreenImages->max_height = 1024;
++ offscreenImages->num_attributes = nElems(NEOVideoAttributes);
++ offscreenImages->attributes = NEOVideoAttributes;
++
++ xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
++}
++
++static FBLinearPtr
++NEOAllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
++{
++ ScreenPtr pScreen;
++ FBLinearPtr new_linear;
++ int bytespp = pScrn->bitsPerPixel >> 3;
++
++ /* convert size in bytes into number of pixels */
++ size = (size + bytespp - 1) / bytespp;
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,
++ "NEOAllocateMemory: linear=%x, size=%d\n", linear, size);
++#endif
++ if (linear){
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,
++ "NEOAllocateMemory: linear->size=%d\n", linear->size);
++#endif
++ if (linear->size >= size){
++ return (linear);
++ }
++
++ if (xf86ResizeOffscreenLinear(linear, size)){
++ return (linear);
++ }
++
++ xf86FreeOffscreenLinear(linear);
++ }
++
++
++ pScreen = screenInfo.screens[pScrn->scrnIndex];
++ if ((new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, NULL,
++ NULL, NULL)) == NULL){
++ int max_size;
++
++ xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
++ PRIORITY_EXTREME);
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,
++ "NEOAllocateMemory: max_size=%d\n", max_size);
++#endif
++ if (max_size < size){
++ return (NULL);
++ }
++
++ xf86PurgeUnlockedOffscreenAreas(pScreen);
++ new_linear = xf86AllocateOffscreenLinear(pScreen,
++ size, 16, NULL, NULL, NULL);
++ }
++
++ return (new_linear);
++}
++
++static void
++NEOCopyData(unsigned char *src, unsigned char *dst,
++ int srcPitch, int dstPitch,
++ int height, int width)
++{
++ while (height-- > 0){
++ memcpy(dst, src, width);
++ src += srcPitch;
++ dst += dstPitch;
++ }
++}
++
++static void
++NEOCopyYV12Data(unsigned char *src1, unsigned char *src2,
++ unsigned char *src3, unsigned char *dst,
++ int srcPitch1, int srcPitch2, int dstPitch,
++ int height, int width)
++{
++ CARD32 *pDst = (CARD32 *) dst;
++ int i;
++
++ width >>= 1;
++ height >>= 1;
++ dstPitch >>= 2;
++ while (--height >= 0){
++ for (i =0; i < width; i++){
++ pDst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
++ (src3[i] << 8) | (src2[i] << 24);
++ }
++ pDst += dstPitch;
++ src1 += srcPitch1;
++
++ for (i =0; i < width; i++){
++ pDst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
++ (src3[i] << 8) | (src2[i] << 24);
++ }
++ pDst += dstPitch;
++ src1 += srcPitch1;
++ src2 += srcPitch2;
++ src3 += srcPitch2;
++ }
++}
++
++static int
++NEOAllocSurface(ScrnInfoPtr pScrn, int id,
++ unsigned short width, unsigned short height,
++ XF86SurfacePtr surface)
++{
++ int pitch, bpp, size;
++ NEOOffscreenPtr pPriv;
++ FBLinearPtr linear;
++
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOAllocSurface\n");
++#endif
++ if (width > 1024 || height > 1024){
++ return (BadAlloc);
++ }
++
++ width = (width + 1) & ~1;
++ bpp = ((pScrn->bitsPerPixel + 1) >> 3);
++ pitch = ((width << 1) + 15) & ~15;
++ size = pitch * height;
++
++ if ((linear = NEOAllocateMemory(pScrn, NULL, size)) == NULL){
++ return (BadAlloc);
++ }
++
++ surface->width = width;
++ surface->height = height;
++ if ((surface->pitches = xalloc(sizeof(int))) == NULL){
++ xf86FreeOffscreenLinear(linear);
++ return (BadAlloc);
++ }
++ if ((surface->offsets = xalloc(sizeof(int))) == NULL){
++ xfree(surface->pitches);
++ xf86FreeOffscreenLinear(linear);
++ return (BadAlloc);
++ }
++
++ if ((pPriv = xalloc(sizeof(NEOOffscreenRec))) == NULL){
++ xfree(surface->pitches);
++ xfree(surface->offsets);
++ xf86FreeOffscreenLinear(linear);
++ return (BadAlloc);
++ }
++
++ pPriv->linear = linear;
++ pPriv->isOn = FALSE;
++
++ surface->pScrn = pScrn;
++ surface->id = id;
++ surface->pitches[0] = pitch;
++ surface->offsets[0] = linear->offset << 1;
++ surface->devPrivate.ptr = (pointer)pPriv;
++ return (Success);
++}
++
++static int
++NEOFreeSurface(XF86SurfacePtr surface)
++{
++ NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr;
++
++#ifdef DEBUG
++ xf86DrvMsg(0,X_INFO,"NEOFreeSurface\n");
++#endif
++ if (pPriv->isOn)
++ NEOStopSurface(surface);
++
++ xf86FreeOffscreenLinear(pPriv->linear);
++ xfree(surface->pitches);
++ xfree(surface->offsets);
++ xfree(surface->devPrivate.ptr);
++ return (Success);
++}
++
++static int
++NEODisplaySurface(XF86SurfacePtr surface,
++ short src_x, short src_y, short drw_x, short drw_y,
++ short src_w, short src_h, short drw_w, short drw_h,
++ RegionPtr clipBoxes)
++{
++ NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr;
++ NEOPtr nPtr = NEOPTR(surface->pScrn);
++ NEOPortPtr portPriv = nPtr->overlayAdaptor->pPortPrivates[0].ptr;
++ INT32 x1, y1, x2, y2;
++ BoxRec dstBox;
++
++#ifdef DEBUG
++ xf86DrvMsg(surface->pScrn->scrnIndex,X_INFO,"NEODisplaySurface\n");
++#endif
++ x1 = src_x;
++ x2 = src_x + src_w;
++ y1 = src_y;
++ y2 = src_y + src_h;
++
++ dstBox.x1 = drw_x;
++ dstBox.x2 = drw_x + drw_w;
++ dstBox.y1 = drw_y;
++ dstBox.y2 = drw_y + drw_h;
++ if (!xf86XVClipVideoHelper( &dstBox, &x1, &x2, &y1, &y2,
++ clipBoxes, surface->width, surface->height)){
++ return (Success);
++ }
++
++ dstBox.x1 -= surface->pScrn->frameX0;
++ dstBox.y1 -= surface->pScrn->frameY0;
++ dstBox.x2 -= surface->pScrn->frameX0;
++ dstBox.y2 -= surface->pScrn->frameY0;
++
++ xf86XVFillKeyHelper(surface->pScrn->pScreen, portPriv->colorKey,
++ clipBoxes);
++ NEOResetVideo(surface->pScrn);
++ NEODisplayVideo(surface->pScrn, surface->id, surface->offsets[0],
++ surface->width, surface->height, surface->pitches[0],
++ x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
++
++ pPriv->isOn = TRUE;
++ if (portPriv->videoStatus & CLIENT_VIDEO_ON){
++ REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
++ UpdateCurrentTime();
++ portPriv->videoStatus = FREE_TIMER;
++ portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
++ }
++ return (Success);
++}
++
++static int
++NEOStopSurface(XF86SurfacePtr surface)
++{
++ NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr;
++
++#ifdef DEBUG
++ xf86DrvMsg(surface->pScrn->scrnIndex,X_INFO,"NEOStopSurface\n");
++#endif
++ if (pPriv->isOn){
++ NEOPtr nPtr = NEOPTR(surface->pScrn);
++ VGA_HWP(surface->pScrn);
++ OUTGR(0xb0, 0x02);
++ pPriv->isOn = FALSE;
++ }
++ return (Success);
++}
++
++static int
++NEOGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 *value)
++{
++ NEOPtr nPtr = NEOPTR(pScrn);
++
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOGetSurfaceAttribute\n");
++#endif
++ return (NEOGetPortAttribute(pScrn,
++ attr, value, (pointer)nPtr->overlayAdaptor->pPortPrivates[0].ptr));
++}
++
++static int
++NEOSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 value)
++{
++ NEOPtr nPtr = NEOPTR(pScrn);
++
++#ifdef DEBUG
++ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetSurfaceAttribute\n");
++#endif
++ return (NEOSetPortAttribute(pScrn,
++ attr, value, (pointer)nPtr->overlayAdaptor->pPortPrivates[0].ptr));
++}
++
++#else /* XvExtension */
++
++void NEOInitVideo(ScreenPtr pScreen) {}
++void NEOResetVideo(ScreenPtr pScreen) {}
++
++#endif
+--- XFree86-4.2.0/xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_video.h Thu Jan 1 01:00:00 1970
++++ XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_video.h Thu Apr 4 16:05:44 2002
+@@ -0,0 +1,83 @@
++/**********************************************************************
++Copyright 2002 by Shigehiro Nomura.
++
++ All Rights Reserved
++
++Permission to use, copy, modify, distribute, and sell this software and
++its documentation for any purpose is hereby granted without fee,
++provided that the above copyright notice appear in all copies and that
++both that copyright notice and this permission notice appear in
++supporting documentation, and that the name of Shigehiro Nomura not be
++used in advertising or publicity pertaining to distribution of the
++software without specific, written prior permission. Shigehiro Nomura
++and its suppliers make no representations about the suitability of this
++software for any purpose. It is provided "as is" without express or
++implied warranty.
++
++SHIGEHIRO NOMURA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++EVENT SHALL SHIGEHIRO NOMURA AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
++SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
++RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
++CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
++CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++**********************************************************************/
++
++#ifndef _NEO_VIDEO_H
++#define _NEO_VIDEO_H
++
++#define ACC_MMIO
++
++#include "vgaHW.h"
++#include "fourcc.h"
++#include "Xv.h"
++
++#define NEO_VIDEO_VIDEO 0
++#define NEO_VIDEO_IMAGE 1
++
++#define FOURCC_RV15 0x35315652
++#define FOURCC_RV16 0x36315652
++
++#define OFF_DELAY 200 /* milliseconds */
++#define FREE_DELAY 60000 /* milliseconds */
++
++#define OFF_TIMER 0x01
++#define FREE_TIMER 0x02
++#define CLIENT_VIDEO_ON 0x04
++#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
++
++typedef struct
++{
++ FBLinearPtr linear;
++ RegionRec clip;
++ CARD32 colorKey;
++ CARD32 interlace;
++ CARD32 brightness;
++ CARD32 videoStatus;
++ Time offTime;
++ Time freeTime;
++} NEOPortRec, *NEOPortPtr;
++
++typedef struct
++{
++ FBLinearPtr linear;
++ Bool isOn;
++} NEOOffscreenRec, *NEOOffscreenPtr;
++
++/* I/O Functions */
++# define OUTGR(idx,dat) \
++ if (nPtr->NeoMMIOBase2) \
++ (*(unsigned short *)(nPtr->NeoMMIOBase2+VGA_GRAPH_INDEX)\
++ =(idx)|((dat)<<8));\
++ else \
++ VGAwGR((idx),(dat));
++
++# define OUTSR(idx,dat) \
++if (nPtr->NeoMMIOBase2) \
++ (*(unsigned short *)(nPtr->NeoMMIOBase2+VGA_SEQ_INDEX)=(idx)|((dat)<<8));\
++else \
++ VGAwSR((idx),(dat));
++
++# define VGA_HWP(x) vgaHWPtr hwp = VGAHWPTR(x)
++
++#endif /* _NEO_VIDEO_H */