Home | History | Annotate | Line # | Download | only in src
      1 
      2 #ifdef HAVE_CONFIG_H
      3 #include "config.h"
      4 #endif
      5 
      6 #include "xf86.h"
      7 #include "tdfx.h"
      8 #include "dixstruct.h"
      9 
     10 #include <X11/extensions/Xv.h>
     11 #include "fourcc.h"
     12 
     13 static Atom xvColorKey, xvFilterQuality;
     14 
     15 /* These should move into tdfxdefs.h with better names */
     16 #define YUV_Y_BASE              0xC00000
     17 #define YUV_U_BASE              0xD00000
     18 #define YUV_V_BASE              0xE00000
     19 
     20 #define SST_2D_FORMAT_YUYV      0x8
     21 #define SST_2D_FORMAT_UYVY      0x9
     22 
     23 #define YUVBASEADDR             0x80100
     24 #define YUVSTRIDE               0x80104
     25 #define VIDPROCCFGMASK          0xa2e3eb6c
     26 
     27 #define OFF_DELAY               250  /* milliseconds */
     28 #define FREE_DELAY              15000
     29 
     30 #define OFF_TIMER               0x01
     31 #define FREE_TIMER              0x02
     32 #define CLIENT_VIDEO_ON         0x04
     33 #define TIMER_MASK              (OFF_TIMER | FREE_TIMER)
     34 
     35 #define TDFX_MAX_OVERLAY_PORTS  1
     36 #define TDFX_MAX_TEXTURE_PORTS  32
     37 
     38 #define GET_PORT_PRIVATE(pScrn) \
     39    (TDFXPortPrivPtr)((TDFXPTR(pScrn))->overlayAdaptor->pPortPrivates[0].ptr)
     40 
     41 /* Needed for attribute atoms */
     42 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
     43 
     44 /*
     45  * PROTOTYPES
     46  */
     47 
     48 static FBAreaPtr TDFXAllocateMemoryArea (ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height);
     49 static FBLinearPtr TDFXAllocateMemoryLinear (ScrnInfoPtr pScrn, FBLinearPtr linear, int size);
     50 static void TDFXVideoTimerCallback(ScrnInfoPtr pScrn, Time time);
     51 
     52 static XF86VideoAdaptorPtr TDFXSetupImageVideoTexture(ScreenPtr);
     53 static int  TDFXSetPortAttributeTexture(ScrnInfoPtr, Atom, INT32, pointer);
     54 static int  TDFXGetPortAttributeTexture(ScrnInfoPtr, Atom ,INT32 *, pointer);
     55 static int  TDFXPutImageTexture(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr);
     56 static void TDFXStopVideoTexture(ScrnInfoPtr, pointer, Bool);
     57 
     58 static XF86VideoAdaptorPtr TDFXSetupImageVideoOverlay(ScreenPtr);
     59 static int  TDFXSetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer);
     60 static int  TDFXGetPortAttributeOverlay(ScrnInfoPtr, Atom ,INT32 *, pointer);
     61 static int  TDFXPutImageOverlay(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr);
     62 static void TDFXStopVideoOverlay(ScrnInfoPtr, pointer, Bool);
     63 static void TDFXResetVideoOverlay(ScrnInfoPtr);
     64 
     65 static void TDFXQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer);
     66 static int  TDFXQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *,  int *, int *);
     67 
     68 static void TDFXInitOffscreenImages(ScreenPtr);
     69 
     70 /*
     71  * ADAPTOR INFORMATION
     72  */
     73 
     74 static XF86VideoEncodingRec OverlayEncoding[] =
     75 {
     76    { 0, "XV_IMAGE", 2048, 2048, {1, 1} }
     77 };
     78 
     79 static XF86VideoEncodingRec TextureEncoding[] =
     80 {
     81    { 0, "XV_IMAGE", 1024, 1024, {1, 1} }
     82 };
     83 
     84 static XF86VideoFormatRec OverlayFormats[] =
     85 {
     86    {8, TrueColor}, {8, DirectColor}, {8, PseudoColor},
     87    {8, GrayScale}, {8, StaticGray}, {8, StaticColor},
     88    {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
     89    {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
     90 };
     91 
     92 static XF86VideoFormatRec TextureFormats[] =
     93 {
     94    {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
     95 };
     96 
     97 static XF86AttributeRec OverlayAttributes[] =
     98 {
     99    {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
    100    {XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"}
    101 };
    102 
    103 static XF86AttributeRec TextureAttributes[] =
    104 {
    105    {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
    106    {XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"}
    107 };
    108 
    109 static XF86ImageRec OverlayImages[] =
    110 {
    111   XVIMAGE_YUY2, XVIMAGE_UYVY, XVIMAGE_YV12, XVIMAGE_I420
    112 };
    113 
    114 static XF86ImageRec TextureImages[] =
    115 {
    116   XVIMAGE_YV12, XVIMAGE_I420
    117 };
    118 
    119 /*
    120  * COMMON SETUP FUNCTIONS
    121  */
    122 
    123 void TDFXInitVideo(ScreenPtr pScreen)
    124 {
    125     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    126     XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
    127     XF86VideoAdaptorPtr newAdaptor = NULL;
    128     TDFXPtr pTDFX = TDFXPTR(pScrn);
    129     int num_adaptors;
    130 
    131     /* The hardware can't convert YUV->8 bit color */
    132     if(pTDFX->cpp == 1)
    133       return;
    134 
    135     if (!pTDFX->TextureXvideo) {
    136 	/* Offscreen support for Overlay only */
    137     	TDFXInitOffscreenImages(pScreen);
    138 
    139     	/* Overlay adaptor */
    140         newAdaptor = TDFXSetupImageVideoOverlay(pScreen);
    141     } else {
    142     	/* Texture adaptor */
    143         newAdaptor = TDFXSetupImageVideoTexture(pScreen);
    144     }
    145 
    146     num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
    147 
    148     if(newAdaptor) {
    149 	if (!num_adaptors) {
    150 	    num_adaptors = 1;
    151 	    adaptors = &newAdaptor;
    152 	} else {
    153             newAdaptors =
    154 		malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
    155             if(newAdaptors) {
    156                 memcpy(newAdaptors, adaptors, num_adaptors *
    157 						sizeof(XF86VideoAdaptorPtr));
    158                 newAdaptors[num_adaptors] = newAdaptor;
    159                 adaptors = newAdaptors;
    160                 num_adaptors++;
    161             }
    162 	}
    163     }
    164 
    165     if(num_adaptors)
    166         xf86XVScreenInit(pScreen, adaptors, num_adaptors);
    167 
    168     if(newAdaptors)
    169         free(newAdaptors);
    170 }
    171 
    172 
    173 void TDFXCloseVideo (ScreenPtr pScreen)
    174 {
    175 }
    176 
    177 
    178 static XF86VideoAdaptorPtr
    179 TDFXAllocAdaptor(ScrnInfoPtr pScrn, int numberPorts)
    180 {
    181     XF86VideoAdaptorPtr adapt;
    182     TDFXPtr pTDFX = TDFXPTR(pScrn);
    183     TDFXPortPrivPtr pPriv;
    184 
    185     if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
    186         return NULL;
    187 
    188     if(!(pPriv = calloc(1, sizeof(TDFXPortPrivRec) + (numberPorts * sizeof(DevUnion)))))
    189     {
    190         free(adapt);
    191         return NULL;
    192     }
    193 
    194     adapt->pPortPrivates = (DevUnion*)(&pPriv[1]);
    195     adapt->pPortPrivates[0].ptr = (pointer)pPriv;
    196 
    197     xvColorKey = MAKE_ATOM("XV_COLORKEY");
    198     xvFilterQuality = MAKE_ATOM("XV_FILTER_QUALITY");
    199 
    200     pPriv->colorKey = pTDFX->videoKey;
    201     pPriv->videoStatus = 0;
    202     pPriv->filterQuality = 1;
    203 
    204     return adapt;
    205 }
    206 
    207 
    208 static XF86VideoAdaptorPtr
    209 TDFXSetupImageVideoOverlay(ScreenPtr pScreen)
    210 {
    211     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    212     TDFXPtr pTDFX = TDFXPTR(pScrn);
    213     TDFXPortPrivPtr pPriv;
    214     XF86VideoAdaptorPtr adapt;
    215 
    216     if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_OVERLAY_PORTS)))
    217         return NULL;
    218 
    219     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
    220     adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
    221     adapt->name = "3dfx Video Overlay";
    222     adapt->nPorts = TDFX_MAX_OVERLAY_PORTS;
    223     adapt->nEncodings = sizeof(OverlayEncoding) / sizeof(XF86VideoEncodingRec);
    224     adapt->pEncodings = OverlayEncoding;
    225     adapt->nFormats = sizeof(OverlayFormats) / sizeof(XF86VideoFormatRec);
    226     adapt->pFormats = OverlayFormats;
    227     adapt->nAttributes = sizeof(OverlayAttributes) / sizeof(XF86AttributeRec);
    228     adapt->pAttributes = OverlayAttributes;
    229     adapt->nImages = sizeof(OverlayImages) / sizeof(XF86ImageRec);
    230     adapt->pImages = OverlayImages;
    231     adapt->PutVideo = NULL;
    232     adapt->PutStill = NULL;
    233     adapt->GetVideo = NULL;
    234     adapt->GetStill = NULL;
    235     adapt->StopVideo = TDFXStopVideoOverlay;
    236     adapt->SetPortAttribute = TDFXSetPortAttributeOverlay;
    237     adapt->GetPortAttribute = TDFXGetPortAttributeOverlay;
    238     adapt->QueryBestSize = TDFXQueryBestSize;
    239     adapt->PutImage = TDFXPutImageOverlay;
    240     adapt->QueryImageAttributes = TDFXQueryImageAttributes;
    241 
    242     pTDFX->overlayAdaptor = adapt;
    243 
    244     pPriv = (TDFXPortPrivPtr)(adapt->pPortPrivates[0].ptr);
    245     REGION_NULL(pScreen, &(pPriv->clip));
    246 
    247     TDFXResetVideoOverlay(pScrn);
    248 
    249     return adapt;
    250 }
    251 
    252 static XF86VideoAdaptorPtr
    253 TDFXSetupImageVideoTexture(ScreenPtr pScreen)
    254 {
    255     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    256     TDFXPtr pTDFX = TDFXPTR(pScrn);
    257     XF86VideoAdaptorPtr adapt;
    258     int i;
    259 
    260     if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_TEXTURE_PORTS)))
    261         return NULL;
    262 
    263     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
    264     adapt->flags = VIDEO_OVERLAID_IMAGES;
    265     adapt->name = "3dfx Video Texture";
    266     adapt->nPorts = TDFX_MAX_TEXTURE_PORTS;
    267     adapt->nEncodings = sizeof(TextureEncoding) / sizeof(XF86VideoEncodingRec);
    268     adapt->pEncodings = TextureEncoding;
    269     adapt->nFormats = sizeof(TextureFormats) / sizeof(XF86VideoFormatRec);
    270     adapt->pFormats = TextureFormats;
    271     adapt->nAttributes = sizeof(TextureAttributes) / sizeof(XF86AttributeRec);
    272     adapt->pAttributes = TextureAttributes;
    273     adapt->nImages = sizeof(TextureImages) / sizeof(XF86ImageRec);
    274     adapt->pImages = TextureImages;
    275     adapt->PutVideo = NULL;
    276     adapt->PutStill = NULL;
    277     adapt->GetVideo = NULL;
    278     adapt->GetStill = NULL;
    279     adapt->StopVideo = TDFXStopVideoTexture;
    280     adapt->SetPortAttribute = TDFXSetPortAttributeTexture;
    281     adapt->GetPortAttribute = TDFXGetPortAttributeTexture;
    282     adapt->QueryBestSize = TDFXQueryBestSize;
    283     adapt->PutImage = TDFXPutImageTexture;
    284     adapt->QueryImageAttributes = TDFXQueryImageAttributes;
    285 
    286     for(i = 0; i < TDFX_MAX_TEXTURE_PORTS; i++)
    287         adapt->pPortPrivates[i].val = i;
    288 
    289     pTDFX->textureAdaptor = adapt;
    290 
    291     return adapt;
    292 }
    293 
    294 
    295 /*
    296  * MISCELLANEOUS ROUTINES
    297  */
    298 
    299 static int
    300 TDFXQueryImageAttributes(
    301     ScrnInfoPtr pScrn,
    302     int id,
    303     unsigned short *w, unsigned short *h,
    304     int *pitches, int *offsets
    305 ){
    306     int size, tmp;
    307 
    308     if(*w > 1024) *w = 1024;
    309     if(*h > 1024) *h = 1024;
    310 
    311     *w = (*w + 1) & ~1;
    312     if(offsets) offsets[0] = 0;
    313 
    314     switch(id) {
    315     case FOURCC_YV12:
    316     case FOURCC_I420:
    317         *h = (*h + 1) & ~1;
    318         size = (*w + 3) & ~3;
    319         if(pitches) pitches[0] = size;
    320         size *= *h;
    321         if(offsets) offsets[1] = size;
    322         tmp = ((*w >> 1) + 3) & ~3;
    323         if(pitches) pitches[1] = pitches[2] = tmp;
    324         tmp *= (*h >> 1);
    325         size += tmp;
    326         if(offsets) offsets[2] = size;
    327         size += tmp;
    328         break;
    329     case FOURCC_UYVY:
    330     case FOURCC_YUY2:
    331     default:
    332         size = *w << 1;
    333         if(pitches) pitches[0] = size;
    334         size *= *h;
    335         break;
    336     }
    337 
    338     return size;
    339 }
    340 
    341 
    342 static int
    343 TDFXSetPortAttributeOverlay(
    344   ScrnInfoPtr pScrn,
    345   Atom attribute,
    346   INT32 value,
    347   pointer data
    348 ){
    349 
    350   TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
    351   TDFXPtr pTDFX = TDFXPTR(pScrn);
    352 
    353   if(attribute == xvColorKey) {
    354         pPriv->colorKey = value;
    355         pTDFX->writeLong(pTDFX, VIDCHROMAMIN, pPriv->colorKey);
    356         pTDFX->writeLong(pTDFX, VIDCHROMAMAX, pPriv->colorKey);
    357         REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
    358   } else if(attribute == xvFilterQuality) {
    359         if((value < 0) || (value > 1))
    360            return BadValue;
    361         pPriv->filterQuality = value;
    362   } else return BadMatch;
    363 
    364   return Success;
    365 }
    366 
    367 static int
    368 TDFXGetPortAttributeOverlay(
    369   ScrnInfoPtr pScrn,
    370   Atom attribute,
    371   INT32 *value,
    372   pointer data
    373 ){
    374   TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
    375 
    376   if(attribute == xvColorKey) {
    377         *value = pPriv->colorKey;
    378   } else if(attribute == xvFilterQuality) {
    379         *value = pPriv->filterQuality;
    380   } else return BadMatch;
    381 
    382   return Success;
    383 }
    384 
    385 
    386 static int
    387 TDFXSetPortAttributeTexture(
    388   ScrnInfoPtr pScrn,
    389   Atom attribute,
    390   INT32 value,
    391   pointer data
    392 ) {
    393   return Success;
    394 }
    395 
    396 
    397 static int
    398 TDFXGetPortAttributeTexture(
    399   ScrnInfoPtr pScrn,
    400   Atom attribute,
    401   INT32 *value,
    402   pointer data
    403 ){
    404   return Success;
    405 }
    406 
    407 
    408 static void
    409 TDFXQueryBestSize(
    410   ScrnInfoPtr pScrn,
    411   Bool motion,
    412   short vid_w, short vid_h,
    413   short drw_w, short drw_h,
    414   unsigned int *p_w, unsigned int *p_h,
    415   pointer data
    416 ){
    417    if(vid_w > drw_w) drw_w = vid_w;
    418    if(vid_h > drw_h) drw_h = vid_h;
    419 
    420   *p_w = drw_w;
    421   *p_h = drw_h;
    422 }
    423 
    424 
    425 static void
    426 TDFXCopyData(
    427   unsigned char *src,
    428   unsigned char *dst,
    429   int srcPitch,
    430   int dstPitch,
    431   int h,
    432   int w
    433 ){
    434 #if X_BYTE_ORDER == X_BIG_ENDIAN
    435     w >>= 1;
    436     while(h--) {
    437       int i;
    438       for (i=0; i<w; i++)
    439        ((unsigned long *)dst)[i]=BE_WSWAP32(((unsigned long *)src)[i]);
    440        src += srcPitch;
    441        dst += dstPitch;
    442     }
    443 #else
    444      w <<= 1;
    445      while(h--) {
    446  	memcpy(dst, src, w);
    447  	src += srcPitch;
    448  	dst += dstPitch;
    449      }
    450 #endif
    451 }
    452 
    453 static void
    454 TDFXCopyMungedData(
    455    unsigned char *src1,
    456    unsigned char *src2,
    457    unsigned char *src3,
    458    unsigned char *dst1,
    459    int srcPitch,
    460    int srcPitch2,
    461    int dstPitch,
    462    int h,
    463    int w
    464 ){
    465    CARD32 *dst;
    466    CARD8 *s1, *s2, *s3;
    467    int i, j;
    468 
    469    w >>= 1;
    470 
    471    for(j = 0; j < h; j++) {
    472         dst = (CARD32*)dst1;
    473         s1 = src1;  s2 = src2;  s3 = src3;
    474         i = w;
    475         while(i > 4) {
    476            dst[0] = BE_WSWAP32(s1[0] | (s1[1] << 16) | (s3[0] << 8) |
    477 			(s2[0] << 24));
    478            dst[1] = BE_WSWAP32(s1[2] | (s1[3] << 16) | (s3[1] << 8) |
    479 			(s2[1] << 24));
    480            dst[2] = BE_WSWAP32(s1[4] | (s1[5] << 16) | (s3[2] << 8) |
    481 			(s2[2] << 24));
    482            dst[3] = BE_WSWAP32(s1[6] | (s1[7] << 16) | (s3[3] << 8) |
    483 			(s2[3] << 24));
    484  	   dst += 4; s2 += 4; s3 += 4; s1 += 8;
    485  	   i -= 4;
    486  	}
    487  	while(i--) {
    488 	   dst[0] = BE_WSWAP32(s1[0] | (s1[1] << 16) | (s3[0] << 8) |
    489 				(s2[0] << 24));
    490  	   dst++; s2++; s3++;
    491  	   s1 += 2;
    492  	}
    493 
    494         dst1 += dstPitch;
    495         src1 += srcPitch;
    496         if(j & 1) {
    497             src2 += srcPitch2;
    498             src3 += srcPitch2;
    499         }
    500    }
    501 }
    502 
    503 
    504 /*
    505  * TEXTURE DRAWING FUNCTIONS
    506  */
    507 
    508 
    509 static void
    510 TDFXStopVideoTexture(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
    511 {
    512   TDFXPtr pTDFX = TDFXPTR(pScrn);
    513 
    514   if (cleanup) {
    515      if(pTDFX->textureBuffer) {
    516         xf86FreeOffscreenArea(pTDFX->textureBuffer);
    517         pTDFX->textureBuffer = NULL;
    518      }
    519   }
    520 }
    521 
    522 
    523 static void
    524 TDFXScreenToScreenYUVStretchBlit (ScrnInfoPtr pScrn,
    525                                   short src_x1, short src_y1,
    526                                   short src_x2, short src_y2,
    527                                   short dst_x1, short dst_y1,
    528                                   short dst_x2, short dst_y2)
    529 {
    530    TDFXPtr pTDFX = TDFXPTR(pScrn);
    531    /* reformulate the paramaters the way the hardware wants them */
    532    INT32 src_x = src_x1 & 0x1FFF;
    533    INT32 src_y = src_y1 & 0x1FFF;
    534    INT32 dst_x = dst_x1 & 0x1FFF;
    535    INT32 dst_y = dst_y1 & 0x1FFF;
    536    INT32 src_w = (src_x2 - src_x1) & 0x1FFF;
    537    INT32 src_h = (src_y2 - src_y1) & 0x1FFF;
    538    INT32 dst_w = (dst_x2 - dst_x1) & 0x1FFF;
    539    INT32 dst_h = (dst_y2 - dst_y1) & 0x1FFF;
    540 
    541    /* Setup for blit src and dest */
    542    TDFXMakeRoom(pTDFX, 4);
    543    DECLARE(SSTCP_DSTSIZE|SSTCP_SRCSIZE|SSTCP_DSTXY|SSTCP_COMMAND/*|SSTCP_COMMANDEXTRA*/);
    544    /* TDFXWriteLong(pTDFX, SST_2D_COMMANDEXTRA, SST_COMMANDEXTRA_VSYNC);*/
    545    TDFXWriteLong(pTDFX, SST_2D_SRCSIZE, src_w | (src_h<<16));
    546    TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, dst_w | (dst_h<<16));
    547    TDFXWriteLong(pTDFX, SST_2D_DSTXY,   dst_x | (dst_y<<16));
    548    TDFXWriteLong(pTDFX, SST_2D_COMMAND, SST_2D_SCRNTOSCRNSTRETCH | 0xCC000000);
    549    /* Write to the launch area to start the blit */
    550    TDFXMakeRoom(pTDFX, 1);
    551    DECLARE_LAUNCH(1, 0);
    552    TDFXWriteLong(pTDFX, SST_2D_LAUNCH, (src_x<<1) | (src_y<<16));
    553    /* Wait for it to happen */
    554    TDFXSendNOPFifo2D(pScrn);
    555 }
    556 
    557 
    558 static void
    559 YUVPlanarToPacked (ScrnInfoPtr pScrn,
    560                    short src_x, short src_y,
    561                    short src_h, short src_w,
    562                    int id, unsigned char *buf,
    563                    short width, short height,
    564                    FBAreaPtr fbarea)
    565 {
    566    TDFXPtr pTDFX = TDFXPTR(pScrn);
    567    unsigned char *psrc, *pdst;
    568    int count;
    569    int baseaddr;
    570    INT32 yuvBaseAddr, yuvStride;
    571 
    572    /* Save these registers so I can restore them when we are done. */
    573    yuvBaseAddr = TDFXReadLongMMIO(pTDFX, YUVBASEADDR);
    574    yuvStride =   TDFXReadLongMMIO(pTDFX, YUVSTRIDE);
    575 
    576    /* Set yuvBaseAddress and yuvStride. */
    577    baseaddr = pTDFX->fbOffset + pTDFX->cpp * fbarea->box.x1 + pTDFX->stride * fbarea->box.y1;
    578    TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, pTDFX->stride);
    579    TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, baseaddr);
    580 
    581    /* Copy Y plane (twice as much Y as U or V) */
    582    psrc = buf;
    583    psrc += (src_x & ~0x1) + src_y * width;
    584    pdst = pTDFX->MMIOBase[0] + YUV_Y_BASE;
    585    TDFXCopyData(psrc, pdst, width, 1024, src_h, src_w + (src_x & 0x1));
    586 
    587    /* Copy V plane */
    588    psrc = buf + width * height;
    589    psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1);
    590    pdst = pTDFX->MMIOBase[0] + YUV_V_BASE;
    591    TDFXCopyData(psrc, pdst, width >> 1, 1024, src_h >> 1, src_w >> 1);
    592 
    593    /* Copy U plane */
    594    psrc = buf + width * height + (width >> 1) * (height >> 1);
    595    psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1);
    596    pdst = pTDFX->MMIOBase[0] + YUV_U_BASE;
    597    TDFXCopyData(psrc, pdst, width >> 1, 1024, src_h >> 1, src_w >> 1);
    598 
    599    /* IDLE until the copy finished, timeout for safety */
    600    for (count = 0; count < 1000; count++)
    601      if (!((TDFXReadLongMMIO(pTDFX, STATUS) & SST_BUSY)))
    602        break;
    603 
    604    /* Restore trashed registers */
    605    TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, yuvBaseAddr);
    606    TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, yuvStride);
    607 
    608    /* Wait for it to happen */
    609    TDFXSendNOPFifo2D(pScrn);
    610 }
    611 
    612 
    613 static int
    614 TDFXPutImageTexture(
    615              ScrnInfoPtr pScrn,
    616              short src_x, short src_y,
    617              short drw_x, short drw_y,
    618              short src_w, short src_h,
    619              short drw_w, short drw_h,
    620              int id, unsigned char* buf,
    621              short width, short height,
    622              Bool sync,
    623              RegionPtr clipBoxes, pointer data,
    624              DrawablePtr pDraw
    625              )
    626 {
    627    TDFXPtr pTDFX = TDFXPTR(pScrn);
    628    BoxPtr pbox;
    629    int nbox;
    630    int format;
    631 
    632    TDFXTRACE("TDFXPutImageTexture(src_x=%d, src_y=%d, drw_x=%d, drw_y=%d, .. sync=%d\n",
    633 		   src_x, src_y, drw_x, drw_y, sync);
    634 
    635    /* Check the source format */
    636    if (id == FOURCC_YV12)      format = SST_2D_FORMAT_YUYV;
    637    else if (id == FOURCC_UYVY) format = SST_2D_FORMAT_UYVY;
    638    else                        return BadAlloc;
    639 
    640    /* Get a buffer to store the packed YUV data */
    641    if (!(pTDFX->textureBuffer = TDFXAllocateMemoryArea(pScrn, pTDFX->textureBuffer, src_w, src_h)))
    642         return BadAlloc;
    643 
    644    /* Pack the YUV data in offscreen memory using YUV framebuffer (0x[CDE]0000) */
    645    YUVPlanarToPacked (pScrn, src_x, src_y, src_h, src_w,
    646                       id, buf, width, height,
    647                       pTDFX->textureBuffer);
    648 
    649    /* Setup source and destination pixel formats (yuv -> rgb) */
    650    TDFXMakeRoom(pTDFX, 2);
    651    DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
    652    TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->stride|((pTDFX->cpp+1)<<16));
    653    TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->stride|((format)<<16));
    654 
    655    /* Blit packed YUV data from offscreen memory, respecting clips */
    656 #define SRC_X1 (pTDFX->textureBuffer->box.x1)
    657 #define SRC_Y1 (pTDFX->textureBuffer->box.y1)
    658 #define SCALEX(dx) ((int)(((dx) * src_w) / drw_w))
    659 #define SCALEY(dy) ((int)(((dy) * src_h) / drw_h))
    660    for (nbox = REGION_NUM_RECTS(clipBoxes),
    661         pbox = REGION_RECTS(clipBoxes); nbox > 0; nbox--, pbox++)
    662    {
    663      TDFXScreenToScreenYUVStretchBlit (pScrn,
    664         SRC_X1 + SCALEX(pbox->x1 - drw_x),
    665         SRC_Y1 + SCALEY(pbox->y1 - drw_y),
    666         SRC_X1 + SCALEX(pbox->x2 - drw_x),
    667         SRC_Y1 + SCALEY(pbox->y2 - drw_y),
    668         pbox->x1, pbox->y1,
    669         pbox->x2, pbox->y2);
    670    }
    671 
    672    /* Restore the WAX registers we trashed */
    673    TDFXMakeRoom(pTDFX, 2);
    674    DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
    675    TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->sst2DDstFmtShadow);
    676    TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->sst2DSrcFmtShadow);
    677 
    678    /* Wait for it to happen */
    679    TDFXSendNOPFifo2D(pScrn);
    680 
    681    return Success;
    682 }
    683 
    684 
    685 /*
    686  * OVERLAY DRAWING FUNCTIONS
    687  */
    688 
    689 
    690 static void
    691 TDFXResetVideoOverlay(ScrnInfoPtr pScrn)
    692 {
    693     TDFXPtr pTDFX = TDFXPTR(pScrn);
    694     TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
    695 
    696     /* reset the video */
    697     pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
    698     pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
    699     pTDFX->writeLong(pTDFX, RGBMAXDELTA, 0x0080808);
    700     pTDFX->writeLong(pTDFX, VIDCHROMAMIN, pPriv->colorKey);
    701     pTDFX->writeLong(pTDFX, VIDCHROMAMAX, pPriv->colorKey);
    702 }
    703 
    704 
    705 static void
    706 TDFXStopVideoOverlay(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
    707 {
    708   TDFXPtr pTDFX = TDFXPTR(pScrn);
    709   TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
    710 
    711   REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
    712 
    713   if(cleanup) {
    714      if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
    715         pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
    716         pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
    717      }
    718      if(pTDFX->overlayBuffer) {
    719         xf86FreeOffscreenLinear(pTDFX->overlayBuffer);
    720         pTDFX->overlayBuffer = NULL;
    721      }
    722      if(pTDFX->overlayBuffer2) {
    723         xf86FreeOffscreenLinear(pTDFX->overlayBuffer2);
    724         pTDFX->overlayBuffer2 = NULL;
    725      }
    726      pPriv->videoStatus = 0;
    727   } else {
    728      if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
    729         pPriv->videoStatus |= OFF_TIMER;
    730         pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
    731      }
    732   }
    733 }
    734 
    735 
    736 /* * * * * *
    737 
    738 Decoder...
    739 
    740 VIDPROCCFG:  0x5c:  Video Processor Configuration register
    741 
    742 #define VIDPROCCFGMASK          0xa2e3eb6c
    743   3 2         1         0
    744   10987654321098765432109876543210
    745   10100010111000111110101101101100
    746 
    747 The "1" bits are the bits cleared to 0 in pTDFX->ModeReg.vidcfg
    748 
    749 
    750 Then we or in 0x320:
    751 
    752       11
    753       109876543210
    754 320 = 001100100000
    755 
    756 bit 11=0: Do not bypass clut (colour lookup) for overlay
    757 bit 10=0: Do not bypass clut for desktop
    758 bit  9=1: use video-in buffer address as overlay start
    759           address (auto-flipping)
    760 bit  8=1: fetch overlay surface
    761 bit  7=0: do not fetch the desktop surface (?)
    762 bit  6=0: chromakey not inverted
    763 bit  5=1: chromakey enabled
    764 bit  4=0: half-mode disabled
    765 bit  3=0: not interlaced (interlace doesn't work on Avenger)
    766 bit  2=0: overlay stereo disabled
    767 bit  1=0: Windows cursor mode
    768 bit  0=0: Video processor off, VGA mode on
    769 
    770 SST_VIDEO_2X_MODE_EN: bit26: means 2 pixels per screen clock mode is on
    771 
    772 VIDOVERLAYSTARTCOORDS: x&y coords of overlay on the screen
    773 VIDOVERLAYENDSCREENCOORDS: x&y coorder of bot-right of overlay on the screen
    774 VIDOVERLAYDUDX: step size in source per hoz step in screen space (x-mag)
    775 VIDOVERLAYDUDXOFFSETSRCWIDTH:
    776 VIDOVERLAYDVDY: step size in sourcxe per vertical step in screen (y-mag)
    777 VIDOVERLAYDVDYOFFSET: initial offset of DVDY
    778 VIDDESKTOPOVERLAYSTRIDE: desktop surface stride
    779 
    780 SST_3D_LEFTOVERLAYBUF: starting physical address of the overlay surface buffer
    781 VIDINADDR0: starting address of video-in buffer-0
    782  [this is set, but this is for video _input_ as I understand docs...?]
    783 
    784 * * * * * */
    785 
    786 static void
    787 TDFXDisplayVideoOverlay(
    788     ScrnInfoPtr pScrn,
    789     int id,
    790     int offset,
    791     short width, short height,
    792     int pitch,
    793     int left, int right, int top,
    794     BoxPtr dstBox,
    795     short src_w, short src_h,
    796     short drw_w, short drw_h
    797 ){
    798     TDFXPtr pTDFX = TDFXPTR(pScrn);
    799     TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
    800     int dudx, dvdy;
    801 
    802     dudx = (src_w << 20) / drw_w;
    803     /* subtract 1 to eliminate garbage on last line */
    804     dvdy = (( src_h - 1 )<< 20) / drw_h;
    805 
    806     offset += ((left >> 16) & ~1) << 1;
    807     left = (left & 0x0001ffff) << 3;
    808 
    809     pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
    810     pTDFX->ModeReg.vidcfg |= 0x00000320;
    811 
    812     if(drw_w != src_w)       pTDFX->ModeReg.vidcfg |= (1 << 14);
    813     if(drw_h != src_h)       pTDFX->ModeReg.vidcfg |= (1 << 15);
    814     if(id == FOURCC_UYVY)    pTDFX->ModeReg.vidcfg |= (6 << 21);
    815     else                     pTDFX->ModeReg.vidcfg |= (5 << 21);
    816     if(pScrn->depth == 8)    pTDFX->ModeReg.vidcfg |= (1 << 11);
    817     /* can't do bilinear filtering when in 2X mode */
    818     if(pPriv->filterQuality && !(pTDFX->ModeReg.vidcfg & SST_VIDEO_2X_MODE_EN))
    819 	pTDFX->ModeReg.vidcfg |= (3 << 16);
    820     pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
    821 
    822     pTDFX->writeLong(pTDFX, VIDOVERLAYSTARTCOORDS, dstBox->x1 | (dstBox->y1 << 12));
    823     pTDFX->writeLong(pTDFX, VIDOVERLAYENDSCREENCOORDS, (dstBox->x2 - 1) | ((dstBox->y2 - 1) << 12));
    824     pTDFX->writeLong(pTDFX, VIDOVERLAYDUDX, dudx);
    825     pTDFX->writeLong(pTDFX, VIDOVERLAYDUDXOFFSETSRCWIDTH, left | (src_w << 20));
    826     pTDFX->writeLong(pTDFX, VIDOVERLAYDVDY, dvdy);
    827     pTDFX->writeLong(pTDFX, VIDOVERLAYDVDYOFFSET, (top & 0x0000ffff) << 3);
    828 
    829     pTDFX->ModeReg.stride &= 0x0000ffff;
    830     pTDFX->ModeReg.stride |= pitch << 16;
    831     pTDFX->writeLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE, pTDFX->ModeReg.stride);
    832     pTDFX->writeLong(pTDFX, SST_3D_LEFTOVERLAYBUF, offset & ~3);
    833     pTDFX->writeLong(pTDFX, VIDINADDR0, offset & ~3);
    834     TDFXTRACE("TDFXDisplayVideoOverlay: done, offset=0x%x\n", offset);
    835 }
    836 
    837 
    838 #if 0
    839 
    840 /* * * * *
    841 
    842 TDFXSwapVideoOverlayBuffer tries to use the Avenger SWAPBUFFER
    843 capability to change frames without tearing.
    844 
    845 Use this in preference to TDFXDisplayVideoOverlay where all image
    846 parameters are the same as the previous frame - ie where only the
    847 SST_3D_LEFTOVERLAYBUF register would have been changed.
    848 
    849 NOTE: Work in progress - doesn't seem to sync to VSYNC, and only every
    850 other frame gets displayed...
    851 
    852 Seeing that the buffer swap initiated by DisplayVideoOverlay gets
    853 synced to VSYNC anyway, just adding double-buffering to PutImageOverlay
    854 appears to do the job.  Still - I leave this code in in case we can
    855 get it working later
    856 
    857   -- Steve Davies 2002-10-04
    858   -- <steve (at) daviesfam.org>
    859 
    860 * * * * * */
    861 
    862 static void
    863 TDFXSwapVideoOverlayBuffer(
    864     ScrnInfoPtr pScrn,
    865     int offset,
    866     int left
    867 ){
    868     TDFXPtr pTDFX = TDFXPTR(pScrn);
    869     offset += ((left >> 16) & ~1) << 1;
    870     /* Write mew buffer address */
    871     pTDFX->writeLong(pTDFX, SST_3D_LEFTOVERLAYBUF, offset & ~3);
    872     /* Incremement the swap-pending counter */
    873     pTDFX->writeLong(pTDFX, SST_3D_SWAPPENDING, 0);
    874     /* write the swapbuffer command - triggered by (next) VSYNC */
    875     pTDFX->writeLong(pTDFX, SST_3D_SWAPBUFFERCMD, 1);
    876 }
    877 
    878 #endif
    879 
    880 static int
    881 TDFXPutImageOverlay(
    882   ScrnInfoPtr pScrn,
    883   short src_x, short src_y,
    884   short drw_x, short drw_y,
    885   short src_w, short src_h,
    886   short drw_w, short drw_h,
    887   int id, unsigned char* buf,
    888   short width, short height,
    889   Bool Sync,
    890   RegionPtr clipBoxes, pointer data,
    891   DrawablePtr pDraw
    892 ){
    893    TDFXPtr pTDFX = TDFXPTR(pScrn);
    894    TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
    895    INT32 xa, xb, ya, yb;
    896    unsigned char *dst_start;
    897    int new_size, offset;
    898    int s2offset = 0, s3offset = 0;
    899    int srcPitch = 0, srcPitch2 = 0;
    900    int dstPitch;
    901    int top, left, npixels, nlines, bpp;
    902    BoxRec dstBox;
    903    CARD32 tmp;
    904 
    905    TDFXTRACE("TDFXPutImageOverlay: src_x=%d, src_y=%d, drw_x=%d, drw_y=%d, src_w=%d, src_h=%d, drw_w=%d, drw_h=%d, id=%d, width=%d, height=%d, sync=%d\n",
    906 		   src_x, src_y, drw_x, drw_y, src_w, src_h, drw_w, drw_h, id, width, height, Sync);
    907 
    908    /*
    909     * s2offset, s3offset - byte offsets into U and V plane of the
    910     *                      source where copying starts.  Y plane is
    911     *                      done by editing "buf".
    912     *
    913     * offset - byte offset to the first line of the destination.
    914     *
    915     * dst_start - byte address to the first displayed pel.
    916     *
    917     */
    918 
    919    if(src_w > drw_w) drw_w = src_w;
    920    if(src_h > drw_h) drw_h = src_h;
    921 
    922    /* Clip */
    923    xa = src_x;
    924    xb = src_x + src_w;
    925    ya = src_y;
    926    yb = src_y + src_h;
    927 
    928    dstBox.x1 = drw_x;
    929    dstBox.x2 = drw_x + drw_w;
    930    dstBox.y1 = drw_y;
    931    dstBox.y2 = drw_y + drw_h;
    932 
    933    if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb,
    934 			     clipBoxes, width, height))
    935         return Success;
    936 
    937    dstBox.x1 -= pScrn->frameX0;
    938    dstBox.x2 -= pScrn->frameX0;
    939    dstBox.y1 -= pScrn->frameY0;
    940    dstBox.y2 -= pScrn->frameY0;
    941 
    942    bpp = pScrn->bitsPerPixel >> 3;
    943 
    944    switch(id) {
    945    case FOURCC_YV12:
    946    case FOURCC_I420:
    947         dstPitch = ((width << 1) + 3) & ~3;
    948         new_size = ((dstPitch * height) + bpp - 1) / bpp;
    949         srcPitch = (width + 3) & ~3;
    950         s2offset = srcPitch * height;
    951         srcPitch2 = ((width >> 1) + 3) & ~3;
    952         s3offset = (srcPitch2 * (height >> 1)) + s2offset;
    953         break;
    954    case FOURCC_UYVY:
    955    case FOURCC_YUY2:
    956    default:
    957         dstPitch = ((width << 1) + 3) & ~3;
    958         new_size = ((dstPitch * height) + bpp - 1) / bpp;
    959         srcPitch = (width << 1);
    960         break;
    961    }
    962 
    963    if(!(pTDFX->overlayBuffer = TDFXAllocateMemoryLinear(pScrn, pTDFX->overlayBuffer, new_size)))
    964         return BadAlloc;
    965    /* Second buffer for double-buffering (If we can't get the memory then we just don't double-buffer) */
    966    if (!(pTDFX->overlayBuffer2 = TDFXAllocateMemoryLinear(pScrn, pTDFX->overlayBuffer2, new_size)))
    967      pTDFX->whichOverlayBuffer = 0;
    968    TDFXTRACE("TDFXPutImageOverlay: %s have a second overlay buffer for double-buffering\n",
    969 	     pTDFX->overlayBuffer2 ? "Do" : "Do not");
    970 
    971    /* copy data */
    972    top = ya >> 16;
    973    left = (xa >> 16) & ~1;
    974    npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left;
    975 
    976    /* Get buffer offset */
    977    if (pTDFX->whichOverlayBuffer == 0)
    978      offset = (pTDFX->overlayBuffer->offset * bpp) + (top * dstPitch) + pTDFX->fbOffset;
    979    else
    980      offset = (pTDFX->overlayBuffer2->offset * bpp) + (top * dstPitch) + pTDFX->fbOffset;
    981 
    982    /* Flip to other buffer for next time */
    983    pTDFX->whichOverlayBuffer ^= 1;
    984 
    985    dst_start = pTDFX->FbBase + offset;
    986 
    987    switch(id) {
    988     case FOURCC_YV12:
    989     case FOURCC_I420:
    990         top &= ~1;
    991         dst_start += left << 1;
    992         tmp = ((top >> 1) * srcPitch2) + (left >> 1);
    993         s2offset += tmp;
    994         s3offset += tmp;
    995         if(id == FOURCC_I420) {
    996            tmp = s2offset;
    997            s2offset = s3offset;
    998            s3offset = tmp;
    999         }
   1000         nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top;
   1001 	TDFXTRACE("TDFXPutImageOverlay: using copymungeddata\n");
   1002         TDFXCopyMungedData(buf + (top * srcPitch) + left, buf + s2offset,
   1003                            buf + s3offset, dst_start, srcPitch, srcPitch2,
   1004                            dstPitch, nlines, npixels);
   1005         break;
   1006     case FOURCC_UYVY:
   1007     case FOURCC_YUY2:
   1008     default:
   1009         left <<= 1;
   1010         buf += (top * srcPitch) + left;
   1011         nlines = ((yb + 0xffff) >> 16) - top;
   1012         dst_start += left;
   1013 	TDFXTRACE("TDFXPutImageOverlay: using copydata\n");
   1014         TDFXCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
   1015         break;
   1016     }
   1017 
   1018     if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
   1019         REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
   1020 	xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
   1021     }
   1022 
   1023     TDFXDisplayVideoOverlay(pScrn, id, offset, width, height, dstPitch, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h);
   1024 
   1025     pPriv->videoStatus = CLIENT_VIDEO_ON;
   1026 
   1027     pTDFX->VideoTimerCallback = TDFXVideoTimerCallback;
   1028 
   1029     /* Display some swap-buffer related info...: vidCurrOverlayStartAddr, fbiSwapHistory */
   1030     /* To give us some insight into workings or otherwise of swapbuffer stuff */
   1031     TDFXTRACE("TDFXPutImageOverlay: vidCurrOverlayStrtAdr=%x, fbiSwpHist=%x, whchBuf=%d, 3Dstus=%x\n",
   1032 	      pTDFX->readLong(pTDFX, VIDCUROVERLAYSTARTADDR),
   1033 	      pTDFX->readLong(pTDFX, SST_3D_FBISWAPHISTORY),
   1034 	      pTDFX->whichOverlayBuffer,
   1035 	      pTDFX->readLong(pTDFX, SST_3D_STATUS)
   1036     );
   1037 
   1038     return Success;
   1039 }
   1040 
   1041 
   1042 static void
   1043 TDFXVideoTimerCallback(ScrnInfoPtr pScrn, Time time)
   1044 {
   1045     TDFXPtr pTDFX = TDFXPTR(pScrn);
   1046     TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
   1047 
   1048     if(pPriv->videoStatus & TIMER_MASK) {
   1049         if(pPriv->videoStatus & OFF_TIMER) {
   1050             if(pPriv->offTime < time) {
   1051                 pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
   1052                 pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
   1053                 pPriv->videoStatus = FREE_TIMER;
   1054                 pPriv->freeTime = time + FREE_DELAY;
   1055             }
   1056         } else
   1057         if(pPriv->videoStatus & FREE_TIMER) {
   1058             if(pPriv->freeTime < time) {
   1059                 if(pTDFX->overlayBuffer) {
   1060                    xf86FreeOffscreenLinear(pTDFX->overlayBuffer);
   1061                    pTDFX->overlayBuffer = NULL;
   1062                 }
   1063                 if(pTDFX->overlayBuffer2) {
   1064                    xf86FreeOffscreenLinear(pTDFX->overlayBuffer2);
   1065                    pTDFX->overlayBuffer2 = NULL;
   1066                 }
   1067                 pPriv->videoStatus = 0;
   1068                 pTDFX->VideoTimerCallback = NULL;
   1069             }
   1070         }
   1071     } else  /* shouldn't get here */
   1072         pTDFX->VideoTimerCallback = NULL;
   1073 }
   1074 
   1075 
   1076 /*
   1077  * MEMORY MANAGEMENT
   1078  */
   1079 
   1080 
   1081 static FBAreaPtr
   1082 TDFXAllocateMemoryArea (ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height)
   1083 {
   1084   TDFXPtr pTDFX = TDFXPTR(pScrn);
   1085   ScreenPtr pScreen;
   1086   FBAreaPtr new_area;
   1087 
   1088   if (area) {
   1089     if ((area->box.x2 - area->box.x1 >= width) &&
   1090         (area->box.y2 - area->box.y1 >= height))
   1091       return area;
   1092 
   1093     if (xf86ResizeOffscreenArea(area, width, height))
   1094       return area;
   1095 
   1096     xf86FreeOffscreenArea(area);
   1097   }
   1098 
   1099   pScreen = xf86ScrnToScreen(pScrn);
   1100 
   1101   new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL);
   1102 
   1103   if (!new_area) {
   1104     int max_width, max_height;
   1105 
   1106     xf86QueryLargestOffscreenArea(pScreen, &max_width, &max_height, pTDFX->cpp, 0, PRIORITY_EXTREME);
   1107 
   1108     if (max_width < width || max_height < height)
   1109       return NULL;
   1110 
   1111     xf86PurgeUnlockedOffscreenAreas(pScreen);
   1112     new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL);
   1113   }
   1114 
   1115   return new_area;
   1116 }
   1117 
   1118 
   1119 static FBLinearPtr
   1120 TDFXAllocateMemoryLinear (ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
   1121 {
   1122    ScreenPtr pScreen;
   1123    FBLinearPtr new_linear;
   1124 
   1125    if(linear) {
   1126         if(linear->size >= size)
   1127            return linear;
   1128 
   1129         if(xf86ResizeOffscreenLinear(linear, size))
   1130            return linear;
   1131 
   1132         xf86FreeOffscreenLinear(linear);
   1133    }
   1134 
   1135    pScreen = xf86ScrnToScreen(pScrn);
   1136 
   1137    new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL);
   1138 
   1139    if(!new_linear) {
   1140         int max_size;
   1141 
   1142         xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, PRIORITY_EXTREME);
   1143 
   1144         if(max_size < size)
   1145            return NULL;
   1146 
   1147         xf86PurgeUnlockedOffscreenAreas(pScreen);
   1148         new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL);
   1149    }
   1150 
   1151    return new_linear;
   1152 }
   1153 
   1154 /****************** Offscreen stuff ***************/
   1155 
   1156 typedef struct {
   1157   FBLinearPtr linear;
   1158   Bool isOn;
   1159 } OffscreenPrivRec, * OffscreenPrivPtr;
   1160 
   1161 static int
   1162 TDFXAllocateSurface(
   1163     ScrnInfoPtr pScrn,
   1164     int id,
   1165     unsigned short w,
   1166     unsigned short h,
   1167     XF86SurfacePtr surface
   1168 ){
   1169     TDFXPtr pTDFX = TDFXPTR(pScrn);
   1170     FBLinearPtr linear;
   1171     int pitch, size, bpp;
   1172     OffscreenPrivPtr pPriv;
   1173 
   1174     if((w > 2048) || (h > 2048))
   1175 	return BadAlloc;
   1176 
   1177     w = (w + 1) & ~1;
   1178     pitch = ((w << 1) + 15) & ~15;
   1179     bpp = pScrn->bitsPerPixel >> 3;
   1180     size = ((pitch * h) + bpp - 1) / bpp;
   1181 
   1182     if(!(linear = TDFXAllocateMemoryLinear(pScrn, NULL, size)))
   1183 	return BadAlloc;
   1184 
   1185     surface->width = w;
   1186     surface->height = h;
   1187 
   1188     if(!(surface->pitches = malloc(sizeof(int)))) {
   1189 	xf86FreeOffscreenLinear(linear);
   1190 	return BadAlloc;
   1191     }
   1192     if(!(surface->offsets = malloc(sizeof(int)))) {
   1193 	free(surface->pitches);
   1194 	xf86FreeOffscreenLinear(linear);
   1195 	return BadAlloc;
   1196     }
   1197     if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
   1198 	free(surface->pitches);
   1199 	free(surface->offsets);
   1200 	xf86FreeOffscreenLinear(linear);
   1201 	return BadAlloc;
   1202     }
   1203 
   1204     pPriv->linear = linear;
   1205     pPriv->isOn = FALSE;
   1206 
   1207     surface->pScrn = pScrn;
   1208     surface->id = id;
   1209     surface->pitches[0] = pitch;
   1210     surface->offsets[0] = pTDFX->fbOffset + (linear->offset * bpp);
   1211     surface->devPrivate.ptr = (pointer)pPriv;
   1212 
   1213     return Success;
   1214 }
   1215 
   1216 static int
   1217 TDFXStopSurface(
   1218     XF86SurfacePtr surface
   1219 ){
   1220     OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
   1221 
   1222     if(pPriv->isOn) {
   1223 	TDFXPtr pTDFX = TDFXPTR(surface->pScrn);
   1224         pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
   1225         pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
   1226 	pPriv->isOn = FALSE;
   1227     }
   1228 
   1229     return Success;
   1230 }
   1231 
   1232 
   1233 static int
   1234 TDFXFreeSurface(
   1235     XF86SurfacePtr surface
   1236 ){
   1237     OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
   1238 
   1239     if(pPriv->isOn)
   1240 	TDFXStopSurface(surface);
   1241     xf86FreeOffscreenLinear(pPriv->linear);
   1242     free(surface->pitches);
   1243     free(surface->offsets);
   1244     free(surface->devPrivate.ptr);
   1245 
   1246     return Success;
   1247 }
   1248 
   1249 static int
   1250 TDFXGetSurfaceAttribute(
   1251     ScrnInfoPtr pScrn,
   1252     Atom attribute,
   1253     INT32 *value
   1254 ){
   1255     return TDFXGetPortAttributeOverlay(pScrn, attribute, value,
   1256 			(pointer)(GET_PORT_PRIVATE(pScrn)));
   1257 }
   1258 
   1259 static int
   1260 TDFXSetSurfaceAttribute(
   1261     ScrnInfoPtr pScrn,
   1262     Atom attribute,
   1263     INT32 value
   1264 ){
   1265     return TDFXSetPortAttributeOverlay(pScrn, attribute, value,
   1266 			(pointer)(GET_PORT_PRIVATE(pScrn)));
   1267 }
   1268 
   1269 static int
   1270 TDFXDisplaySurface(
   1271     XF86SurfacePtr surface,
   1272     short src_x, short src_y,
   1273     short drw_x, short drw_y,
   1274     short src_w, short src_h,
   1275     short drw_w, short drw_h,
   1276     RegionPtr clipBoxes
   1277 ){
   1278     OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
   1279     ScrnInfoPtr pScrn = surface->pScrn;
   1280     TDFXPtr pTDFX = TDFXPTR(pScrn);
   1281     TDFXPortPrivPtr portPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
   1282     INT32 x1, y1, x2, y2;
   1283     BoxRec dstBox;
   1284 
   1285     x1 = src_x;
   1286     x2 = src_x + src_w;
   1287     y1 = src_y;
   1288     y2 = src_y + src_h;
   1289 
   1290     dstBox.x1 = drw_x;
   1291     dstBox.x2 = drw_x + drw_w;
   1292     dstBox.y1 = drw_y;
   1293     dstBox.y2 = drw_y + drw_h;
   1294 
   1295     if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
   1296 			      surface->width, surface->height))
   1297     {
   1298 	return Success;
   1299     }
   1300 
   1301     dstBox.x1 -= pScrn->frameX0;
   1302     dstBox.x2 -= pScrn->frameX0;
   1303     dstBox.y1 -= pScrn->frameY0;
   1304     dstBox.y2 -= pScrn->frameY0;
   1305 
   1306 #if 0
   1307     TDFXResetVideoOverlay(pScrn);
   1308 #endif
   1309 
   1310     TDFXDisplayVideoOverlay(pScrn, surface->id, surface->offsets[0],
   1311 	     surface->width, surface->height, surface->pitches[0],
   1312 	     x1, y1, x2, &dstBox, src_w, src_h, drw_w, drw_h);
   1313 
   1314     xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
   1315 
   1316     pPriv->isOn = TRUE;
   1317     /* we've prempted the XvImage stream so set its free timer */
   1318     if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
   1319 	REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
   1320 	UpdateCurrentTime();
   1321 	portPriv->videoStatus = FREE_TIMER;
   1322 	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
   1323 	pTDFX->VideoTimerCallback = TDFXVideoTimerCallback;
   1324     }
   1325 
   1326     return Success;
   1327 }
   1328 
   1329 static void
   1330 TDFXInitOffscreenImages(ScreenPtr pScreen)
   1331 {
   1332     XF86OffscreenImagePtr offscreenImages;
   1333 
   1334     /* need to free this someplace */
   1335     if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec))))
   1336 	return;
   1337 
   1338     offscreenImages[0].image = &OverlayImages[0];
   1339     offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
   1340 			       VIDEO_CLIP_TO_VIEWPORT;
   1341     offscreenImages[0].alloc_surface = TDFXAllocateSurface;
   1342     offscreenImages[0].free_surface = TDFXFreeSurface;
   1343     offscreenImages[0].display = TDFXDisplaySurface;
   1344     offscreenImages[0].stop = TDFXStopSurface;
   1345     offscreenImages[0].setAttribute = TDFXSetSurfaceAttribute;
   1346     offscreenImages[0].getAttribute = TDFXGetSurfaceAttribute;
   1347     offscreenImages[0].max_width = 2048;
   1348     offscreenImages[0].max_height = 2048;
   1349     offscreenImages[0].num_attributes = 2;
   1350     offscreenImages[0].attributes = OverlayAttributes;
   1351 
   1352     xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
   1353 }
   1354