Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright 2003 through 2004 by Marc Aurele La France (TSI @ UQV), tsi (at) xfree86.org
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that copyright
      7  * notice and this permission notice appear in supporting documentation, and
      8  * that the name of Marc Aurele La France not be used in advertising or
      9  * publicity pertaining to distribution of the software without specific,
     10  * written prior permission.  Marc Aurele La France makes no representations
     11  * about the suitability of this software for any purpose.  It is provided
     12  * "as-is" without express or implied warranty.
     13  *
     14  * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
     16  * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     20  * PERFORMANCE OF THIS SOFTWARE.
     21  */
     22 
     23 #ifdef HAVE_CONFIG_H
     24 #include "config.h"
     25 #endif
     26 
     27 #include <string.h>
     28 
     29 #include "ati.h"
     30 #include "atichip.h"
     31 #include "atimach64accel.h"
     32 #include "atimach64io.h"
     33 #include "atixv.h"
     34 #include "atimach64version.h"
     35 
     36 #include <X11/extensions/Xv.h>
     37 #include "fourcc.h"
     38 #include "xf86xv.h"
     39 
     40 #define MAKE_ATOM(string) MakeAtom(string, strlen(string), TRUE)
     41 #define MaxScale          (CARD32)(CARD16)(-1)
     42 
     43 static unsigned long ATIMach64XVAtomGeneration = (unsigned long)(-1);
     44 
     45 static XF86VideoEncodingRec ATIMach64VideoEncoding[] =
     46 {
     47     { 0, "XV_IMAGE", 720, 2048, {1, 1} }
     48 };
     49 #define nATIMach64VideoEncoding NumberOf(ATIMach64VideoEncoding)
     50 
     51 static XF86VideoFormatRec ATIMach64VideoFormat[] =
     52 {
     53     { 8, TrueColor},
     54     { 8, DirectColor},
     55     { 8, PseudoColor},
     56     { 8, GrayScale},
     57     { 8, StaticGray},
     58     { 8, StaticColor},
     59     {15, TrueColor},
     60     {16, TrueColor},
     61     {24, TrueColor},
     62     {15, DirectColor},
     63     {16, DirectColor},
     64     {24, DirectColor}
     65 };
     66 #define nATIMach64VideoFormat NumberOf(ATIMach64VideoFormat)
     67 
     68 static XF86AttributeRec ATIMach64Attribute[] =
     69 {
     70     /* These are only supported on the Rage Pro and later ... */
     71     {
     72         XvSettable | XvGettable,
     73         -1000, 1000,
     74         "XV_SATURATION"
     75     },
     76     {
     77         XvSettable | XvGettable,
     78         -1000, 1000,
     79         "XV_BRIGHTNESS"
     80     },
     81     {
     82         XvSettable | XvGettable,
     83         -1000, 1000,
     84         "XV_COLOUR"
     85     },
     86     {
     87         XvSettable | XvGettable,
     88         -1000, 1000,
     89         "XV_COLOR"
     90     },
     91 
     92     /* Local attributes, odds and ends for compatibility, etc... */
     93     {
     94         XvSettable | XvGettable,
     95         0, 1,
     96         "XV_AUTOPAINT_COLOURKEY"
     97     },
     98     {
     99         XvSettable | XvGettable,
    100         0, 1,
    101         "XV_AUTOPAINT_COLORKEY"
    102     },
    103     {
    104         XvSettable | XvGettable,
    105         0, (1 << 24) - 1,
    106         "XV_COLOURKEY"
    107     },
    108     {
    109         XvSettable | XvGettable,
    110         0, (1 << 24) - 1,
    111         "XV_COLORKEY"
    112     },
    113     {
    114         XvSettable | XvGettable,
    115         0, (1 << 24) - 1,
    116         "XV_COLOURKEY_MASK"
    117     },
    118     {
    119         XvSettable | XvGettable,
    120         0, (1 << 24) - 1,
    121         "XV_COLORKEY_MASK"
    122     },
    123     {
    124         XvSettable,
    125         0, 0,
    126         "XV_SET_DEFAULTS"
    127     },
    128     {   /* Keep last */
    129         XvSettable | XvGettable,
    130         0, 1,
    131         "XV_DOUBLE_BUFFER"
    132     }
    133 };
    134 #define nATIMach64Attribute NumberOf(ATIMach64Attribute)
    135 
    136 static XF86ImageRec ATIMach64Image[] =
    137 {
    138     XVIMAGE_YUY2,
    139     XVIMAGE_UYVY,
    140     XVIMAGE_YV12,
    141     XVIMAGE_I420
    142 };
    143 #define nATIMach64Image NumberOf(ATIMach64Image)
    144 
    145 /* A local XVideo adaptor attribute record */
    146 typedef struct _ATIMach64Attribute
    147 {
    148     Atom  AttributeID;
    149     INT32 MaxValue;             /* ... for the hardware */
    150     void  (*SetAttribute) (ATIPtr, INT32);
    151     INT32 (*GetAttribute) (ATIPtr);
    152 } ATIMach64AttributeRec, *ATIMach64AttributePtr;
    153 
    154 /* Functions to get/set XVideo adaptor attributes */
    155 
    156 static void
    157 ATIMach64SetSaturationAttribute
    158 (
    159     ATIPtr pATI,
    160     INT32  Value
    161 )
    162 {
    163     /* Set the register */
    164     pATI->NewHW.scaler_colour_cntl &=
    165         ~(SCALE_SATURATION_U | SCALE_SATURATION_V);
    166     pATI->NewHW.scaler_colour_cntl |= SetBits(Value, SCALE_SATURATION_U) |
    167         SetBits(Value, SCALE_SATURATION_V);
    168     outf(SCALER_COLOUR_CNTL, pATI->NewHW.scaler_colour_cntl);
    169 }
    170 
    171 static INT32
    172 ATIMach64GetSaturationAttribute
    173 (
    174     ATIPtr pATI
    175 )
    176 {
    177     return (INT32)GetBits(pATI->NewHW.scaler_colour_cntl, SCALE_SATURATION_U);
    178 }
    179 
    180 static void
    181 ATIMach64SetBrightnessAttribute
    182 (
    183     ATIPtr pATI,
    184     INT32  Value
    185 )
    186 {
    187     /* Set the register */
    188     pATI->NewHW.scaler_colour_cntl &= ~SCALE_BRIGHTNESS;
    189     pATI->NewHW.scaler_colour_cntl |= SetBits(Value, SCALE_BRIGHTNESS);
    190     outf(SCALER_COLOUR_CNTL, pATI->NewHW.scaler_colour_cntl);
    191 }
    192 
    193 static INT32
    194 ATIMach64GetBrightnessAttribute
    195 (
    196     ATIPtr pATI
    197 )
    198 {
    199     return (INT32)GetBits(pATI->NewHW.scaler_colour_cntl, SCALE_BRIGHTNESS);
    200 }
    201 
    202 static void
    203 ATIMach64SetDoubleBufferAttribute
    204 (
    205     ATIPtr pATI,
    206     INT32  Value
    207 )
    208 {
    209     pATI->DoubleBuffer = Value;
    210 }
    211 
    212 static INT32
    213 ATIMach64GetDoubleBufferAttribute
    214 (
    215     ATIPtr pATI
    216 )
    217 {
    218     return (int)pATI->DoubleBuffer;
    219 }
    220 
    221 static void
    222 ATIMach64SetAutoPaintAttribute
    223 (
    224     ATIPtr pATI,
    225     INT32  Value
    226 )
    227 {
    228     pATI->AutoPaint = Value;
    229 }
    230 
    231 static INT32
    232 ATIMach64GetAutoPaintAttribute
    233 (
    234     ATIPtr pATI
    235 )
    236 {
    237     return (int)pATI->AutoPaint;
    238 }
    239 
    240 static void
    241 ATIMach64SetColourKeyAttribute
    242 (
    243     ATIPtr pATI,
    244     INT32  Value
    245 )
    246 {
    247     pATI->NewHW.overlay_graphics_key_clr =
    248         (CARD32)(Value & ((1 << pATI->depth) - 1));
    249     outf(OVERLAY_GRAPHICS_KEY_CLR, pATI->NewHW.overlay_graphics_key_clr);
    250 }
    251 
    252 static INT32
    253 ATIMach64GetColourKeyAttribute
    254 (
    255     ATIPtr pATI
    256 )
    257 {
    258     return (INT32)pATI->NewHW.overlay_graphics_key_clr;
    259 }
    260 
    261 static void
    262 ATIMach64SetColourKeyMaskAttribute
    263 (
    264     ATIPtr pATI,
    265     INT32  Value
    266 )
    267 {
    268     pATI->NewHW.overlay_graphics_key_msk =
    269         (CARD32)(Value & ((1 << pATI->depth) - 1));
    270     outf(OVERLAY_GRAPHICS_KEY_MSK, pATI->NewHW.overlay_graphics_key_msk);
    271 }
    272 
    273 static INT32
    274 ATIMach64GetColourKeyMaskAttribute
    275 (
    276     ATIPtr pATI
    277 )
    278 {
    279     return (INT32)pATI->NewHW.overlay_graphics_key_msk;
    280 }
    281 
    282 /*
    283  * ATIMach64SetDefaultAttributes --
    284  *
    285  * This function calls other functions to set default values for the various
    286  * attributes of an XVideo port.
    287  */
    288 static void
    289 ATIMach64SetDefaultAttributes
    290 (
    291     ATIPtr pATI,
    292     INT32  Value
    293 )
    294 {
    295     ATIMach64SetAutoPaintAttribute(pATI, TRUE);
    296     ATIMach64SetDoubleBufferAttribute(pATI, FALSE);
    297     ATIMach64SetColourKeyMaskAttribute(pATI, (1 << pATI->depth) - 1);
    298     ATIMach64SetColourKeyAttribute(pATI, (3 << ((2 * pATI->depth) / 3)) |
    299                                          (2 << ((1 * pATI->depth) / 3)) |
    300                                          (1 << ((0 * pATI->depth) / 3)));
    301 
    302     if (pATI->Chip < ATI_CHIP_264GTPRO)
    303         return;
    304 
    305     ATIMach64SetBrightnessAttribute(pATI, 32);
    306     ATIMach64SetSaturationAttribute(pATI, 16);
    307 }
    308 
    309 /*
    310  * There is a one-to-one correspondence between elements of the following array
    311  * and those of ATIMach64Attribute.
    312  */
    313 static ATIMach64AttributeRec ATIMach64AttributeInfo[nATIMach64Attribute] =
    314 {
    315     {   /* SATURATION */
    316         0, 23,
    317         ATIMach64SetSaturationAttribute,
    318         ATIMach64GetSaturationAttribute
    319     },
    320     {   /* BRIGHTNESS */
    321         0, 63,
    322         ATIMach64SetBrightnessAttribute,
    323         ATIMach64GetBrightnessAttribute
    324     },
    325     {   /* COLOUR */
    326         0, 23,
    327         ATIMach64SetSaturationAttribute,
    328         ATIMach64GetSaturationAttribute
    329     },
    330     {   /* COLOR */
    331         0, 23,
    332         ATIMach64SetSaturationAttribute,
    333         ATIMach64GetSaturationAttribute
    334     },
    335     {   /* AUTOPAINT_COLOURKEY */
    336         0, 1,
    337         ATIMach64SetAutoPaintAttribute,
    338         ATIMach64GetAutoPaintAttribute
    339     },
    340     {   /* AUTOPAINT_COLORKEY */
    341         0, 1,
    342         ATIMach64SetAutoPaintAttribute,
    343         ATIMach64GetAutoPaintAttribute
    344     },
    345     {   /* COLOURKEY */
    346         0, (1 << 24) - 1,
    347         ATIMach64SetColourKeyAttribute,
    348         ATIMach64GetColourKeyAttribute
    349     },
    350     {   /* COLORKEY */
    351         0, (1 << 24) - 1,
    352         ATIMach64SetColourKeyAttribute,
    353         ATIMach64GetColourKeyAttribute
    354     },
    355     {   /* COLOURKEY_MASK */
    356         0, (1 << 24) - 1,
    357         ATIMach64SetColourKeyMaskAttribute,
    358         ATIMach64GetColourKeyMaskAttribute
    359     },
    360     {   /* COLORKEY_MASK */
    361         0, (1 << 24) - 1,
    362         ATIMach64SetColourKeyMaskAttribute,
    363         ATIMach64GetColourKeyMaskAttribute
    364     },
    365     {   /* SET_DEFAULTS */
    366         0, 0,
    367         ATIMach64SetDefaultAttributes,
    368         NULL
    369     },
    370     {   /* DOUBLE_BUFFER */
    371         0, 1,
    372         ATIMach64SetDoubleBufferAttribute,
    373         ATIMach64GetDoubleBufferAttribute
    374     }
    375 };
    376 
    377 /*
    378  * ATIMach64FindAttribute --
    379  *
    380  * This function is called to locate an Xv attribute's table entry.
    381  */
    382 static int
    383 ATIMach64FindPortAttribute
    384 (
    385     ATIPtr pATI,
    386     Atom   AttributeID
    387 )
    388 {
    389     int iAttribute;
    390 
    391     if (pATI->Chip < ATI_CHIP_264GTPRO)
    392         iAttribute = 4;
    393     else
    394         iAttribute = 0;
    395 
    396     for (;  iAttribute < nATIMach64Attribute;  iAttribute++)
    397         if (AttributeID == ATIMach64AttributeInfo[iAttribute].AttributeID)
    398             return iAttribute;
    399 
    400     return -1;
    401 }
    402 
    403 /*
    404  * ATIMach64SetPortAttribute --
    405  *
    406  * This function sets the value of a particular port's attribute.
    407  */
    408 static int
    409 ATIMach64SetPortAttribute
    410 (
    411     ScrnInfoPtr pScreenInfo,
    412     Atom        AttributeID,
    413     INT32       Value,
    414     pointer     pATI
    415 )
    416 {
    417     INT32 Range;
    418     int   iAttribute;
    419 
    420     if (((iAttribute = ATIMach64FindPortAttribute(pATI, AttributeID)) < 0) ||
    421         !ATIMach64AttributeInfo[iAttribute].SetAttribute)
    422         return BadMatch;
    423 
    424     Range = ATIMach64Attribute[iAttribute].max_value -
    425         ATIMach64Attribute[iAttribute].min_value;
    426 
    427     if (Range >= 0)
    428     {
    429         /* Limit and scale the value */
    430         Value -= ATIMach64Attribute[iAttribute].min_value;
    431 
    432         if (Value < 0)
    433             Value = 0;
    434         else if (Value > Range)
    435             Value = Range;
    436 
    437         if (Range != ATIMach64AttributeInfo[iAttribute].MaxValue)
    438         {
    439             if (ATIMach64AttributeInfo[iAttribute].MaxValue > 0)
    440                 Value *= ATIMach64AttributeInfo[iAttribute].MaxValue;
    441             if (Range > 0)
    442                 Value /= Range;
    443         }
    444     }
    445 
    446     (*ATIMach64AttributeInfo[iAttribute].SetAttribute)(pATI, Value);
    447 
    448     return Success;
    449 }
    450 
    451 /*
    452  * ATIMach64SetPortAttribute --
    453  *
    454  * This function retrieves the value of a particular port's attribute.
    455  */
    456 static int
    457 ATIMach64GetPortAttribute
    458 (
    459     ScrnInfoPtr pScreenInfo,
    460     Atom        AttributeID,
    461     INT32       *Value,
    462     pointer     pATI
    463 )
    464 {
    465     INT32 Range;
    466     int   iAttribute;
    467 
    468     if (!Value ||
    469         ((iAttribute = ATIMach64FindPortAttribute(pATI, AttributeID)) < 0) ||
    470         !ATIMach64AttributeInfo[iAttribute].GetAttribute)
    471         return BadMatch;
    472 
    473     *Value = (*ATIMach64AttributeInfo[iAttribute].GetAttribute)(pATI);
    474 
    475     Range = ATIMach64Attribute[iAttribute].max_value -
    476         ATIMach64Attribute[iAttribute].min_value;
    477 
    478     if (Range >= 0)
    479     {
    480         if (Range != ATIMach64AttributeInfo[iAttribute].MaxValue)
    481         {
    482             /* (Un-)scale the value */
    483             if (Range > 0)
    484                 *Value *= Range;
    485             if (ATIMach64AttributeInfo[iAttribute].MaxValue > 0)
    486                 *Value /= ATIMach64AttributeInfo[iAttribute].MaxValue;
    487         }
    488 
    489         *Value += ATIMach64Attribute[iAttribute].min_value;
    490     }
    491 
    492     return Success;
    493 }
    494 
    495 static pointer
    496 ATIMach64XVMemAlloc
    497 (
    498     ScreenPtr pScreen,
    499     pointer   pVideo,
    500     int       size,
    501     int       *offset,
    502     ATIPtr    pATI
    503 );
    504 
    505 static void
    506 ATIMach64XVMemFree
    507 (
    508     ScreenPtr pScreen,
    509     pointer   pVideo,
    510     ATIPtr    pATI
    511 );
    512 
    513 
    514 /*
    515  * ATIMach64StopVideo --
    516  *
    517  * This is called to stop displaying a video.  Note that, to prevent jittering
    518  * this doesn't actually turn off the overlay unless 'Cleanup' is TRUE, i.e.
    519  * when the video is to be actually stopped rather than temporarily disabled.
    520  */
    521 static void
    522 ATIMach64StopVideo
    523 (
    524     ScrnInfoPtr pScreenInfo,
    525     pointer     Data,
    526     Bool        Cleanup
    527 )
    528 {
    529     ScreenPtr pScreen = pScreenInfo->pScreen;
    530     ATIPtr    pATI    = Data;
    531 
    532     if (pATI->ActiveSurface)
    533         return;
    534 
    535     REGION_EMPTY(pScreen, &pATI->VideoClip);
    536 
    537 
    538     ATIMach64XVMemFree(pScreen, pATI->pXVBuffer, pATI);
    539     pATI->pXVBuffer = NULL;
    540     outf(OVERLAY_SCALE_CNTL, SCALE_EN);
    541 }
    542 
    543 /*
    544  * ATIMach64QueryBestSize --
    545  *
    546  * Quoting XVideo docs:
    547  *
    548  * This function provides the client with a way to query what the destination
    549  * dimensions would end up being if they were to request that an area
    550  * VideoWidth by VideoHeight from the video stream be scaled to rectangle of
    551  * DrawableWidth by DrawableHeight on the screen.  Since it is not expected
    552  * that all hardware will be able to get the target dimensions exactly, it is
    553  * important that the driver provide this function.
    554  */
    555 static void
    556 ATIMach64QueryBestSize
    557 (
    558     ScrnInfoPtr  pScreenInfo,
    559     Bool         Motion,
    560     short        VideoWidth,
    561     short        VideoHeight,
    562     short        DrawableWidth,
    563     short        DrawableHeight,
    564     unsigned int *Width,
    565     unsigned int *Height,
    566     pointer      pATI
    567 )
    568 {
    569     *Width  = DrawableWidth;
    570     *Height = DrawableHeight;
    571 }
    572 
    573 /*
    574  * ATIMach64QueryImageAttributes --
    575  *
    576  * Quoting XVideo docs:
    577  *
    578  * This function is called to let the driver specify how data for a particular
    579  * image of size Width by Height should be stored.  Sometimes only the size and
    580  * corrected width and height are needed.  In that case pitches and offsets are
    581  * NULL.  The size of the memory required for the image is returned by this
    582  * function.  The width and height of the requested image can be altered by the
    583  * driver to reflect format limitations (such as component sampling periods
    584  * that are larger than one).  If pPitch and pOffset are not NULL, these will
    585  * be arrays with as many elements in them as there are planes in the image
    586  * format.  The driver should specify the pitch (in bytes) of each scanline in
    587  * the particular plane as well as the offset to that plane (in bytes) from the
    588  * beginning of the image.
    589  */
    590 static int
    591 ATIMach64QueryImageAttributes
    592 (
    593     ScrnInfoPtr    pScreenInfo,
    594     int            ImageID,
    595     unsigned short *Width,
    596     unsigned short *Height,
    597     int            *pPitch,
    598     int            *pOffset
    599 )
    600 {
    601     int Size, tmp;
    602 
    603     if (!Width || !Height)
    604         return 0;
    605 
    606     if (*Width > 2048)
    607         *Width = 2048;
    608     else
    609         *Width = (*Width + 1) & ~1;
    610 
    611     if (*Height > 2048)
    612         *Height = 2048;
    613 
    614     if (pOffset)
    615         pOffset[0] = 0;
    616 
    617     switch (ImageID)
    618     {
    619         case FOURCC_YV12:
    620         case FOURCC_I420:
    621             *Height = (*Height + 1) & ~1;
    622             Size = (*Width + 3) & ~3;
    623             if (pPitch)
    624                 pPitch[0] = Size;
    625             Size *= *Height;
    626             if (pOffset)
    627                 pOffset[1] = Size;
    628             tmp = ((*Width >> 1) + 3) & ~3;
    629             if (pPitch)
    630                 pPitch[1] = pPitch[2] = tmp;
    631             tmp *= (*Height >> 1);
    632             Size += tmp;
    633             if (pOffset)
    634                 pOffset[2] = Size;
    635             Size += tmp;
    636             break;
    637 
    638         case FOURCC_UYVY:
    639         case FOURCC_YUY2:
    640             Size = *Width << 1;
    641             if (pPitch)
    642                 pPitch[0] = Size;
    643             Size *= *Height;
    644             break;
    645 
    646         default:
    647             Size = 0;
    648             break;
    649     }
    650 
    651     return Size;
    652 }
    653 
    654 /*
    655  * ATIMach64ScaleVideo --
    656  *
    657  * This function is called to calculate overlay scaling factors.
    658  */
    659 static void
    660 ATIMach64ScaleVideo
    661 (
    662     ATIPtr         pATI,
    663     DisplayModePtr pMode,
    664     int            SrcW,
    665     int            SrcH,
    666     int            DstW,
    667     int            DstH,
    668     CARD32         *pHScale,
    669     CARD32         *pVScale
    670 )
    671 {
    672     int Shift;
    673 
    674     *pHScale = ATIDivide(SrcW, DstW,
    675         GetBits(pATI->NewHW.pll_vclk_cntl, PLL_ECP_DIV) + 12, 0);
    676 
    677     Shift = 12;
    678     if (pMode->Flags & V_INTERLACE)
    679         Shift++;
    680 
    681     if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
    682     {
    683         if (pMode->VDisplay < pATI->LCDVertical)
    684         {
    685             SrcH *= pMode->VDisplay;
    686             DstH *= pATI->LCDVertical;
    687         }
    688     }
    689     else
    690     {
    691         if (pMode->Flags & V_DBLSCAN)
    692             Shift--;
    693         if (pMode->VScan > 1)
    694             DstH *= pMode->VScan;
    695     }
    696 
    697     *pVScale = ATIDivide(SrcH, DstH, Shift, 0);
    698 }
    699 
    700 /*
    701  * ATIMach64ClipVideo --
    702  *
    703  * Clip the video (both source and destination) and make various other
    704  * adjustments.
    705  */
    706 static Bool
    707 ATIMach64ClipVideo
    708 (
    709     ScrnInfoPtr pScreenInfo,
    710     ATIPtr      pATI,
    711     int         ImageID,
    712     short       SrcX,
    713     short       SrcY,
    714     short       SrcW,
    715     short       SrcH,
    716     short       DstX,
    717     short       DstY,
    718     short       *DstW,
    719     short       *DstH,
    720     short       Width,
    721     short       Height,
    722     RegionPtr   pClip,
    723     BoxPtr      pDstBox,
    724     INT32       *SrcX1,
    725     INT32       *SrcX2,
    726     INT32       *SrcY1,
    727     INT32       *SrcY2,
    728     int         *SrcLeft,
    729     int         *SrcTop
    730 )
    731 {
    732     CARD32 HScale, VScale;
    733 
    734     /* Check hardware limits */
    735     if ((Height <= 0) || (Height > 2048) || (Width <= 0) || (Width > 768) ||
    736         ((Width > 384) && (pATI->Chip < ATI_CHIP_264VTB)) ||
    737         ((Width > 720) && (pATI->Chip < ATI_CHIP_264GTPRO ||
    738                            pATI->Chip > ATI_CHIP_264LTPRO)))
    739         return FALSE;
    740 
    741     ATIMach64ScaleVideo(pATI, pScreenInfo->currentMode,
    742         SrcW, SrcH, *DstW, *DstH, &HScale, &VScale);
    743     if (!HScale || !VScale)
    744         return FALSE;
    745     if (HScale > MaxScale)
    746         *DstW = (*DstW * HScale) / MaxScale;
    747     if (VScale > MaxScale)
    748         *DstH = (*DstH * HScale) / MaxScale;
    749 
    750     /* Clip both the source and the destination */
    751     *SrcX1 = SrcX;
    752     *SrcX2 = SrcX + SrcW;
    753     *SrcY1 = SrcY;
    754     *SrcY2 = SrcY + SrcH;
    755 
    756     pDstBox->x1 = DstX;
    757     pDstBox->x2 = DstX + *DstW;
    758     pDstBox->y1 = DstY;
    759     pDstBox->y2 = DstY + *DstH;
    760 
    761     if (!xf86XVClipVideoHelper(pDstBox, SrcX1, SrcX2, SrcY1, SrcY2,
    762                                pClip, Width, Height))
    763         return FALSE;
    764 
    765     /*
    766      * Reset overlay scaler origin.  This prevents jittering during
    767      * viewport panning or while the video is being moved or gradually
    768      * obscured/unobscured.
    769      */
    770     pDstBox->x1 = DstX;
    771     pDstBox->y1 = DstY;
    772 
    773     /* Translate to the current viewport */
    774     pDstBox->x1 -= pScreenInfo->frameX0;
    775     pDstBox->x2 -= pScreenInfo->frameX0;
    776     pDstBox->y1 -= pScreenInfo->frameY0;
    777     pDstBox->y2 -= pScreenInfo->frameY0;
    778 
    779     *SrcLeft = *SrcTop = 0;
    780 
    781     /*
    782      * If the overlay scaler origin ends up outside the current viewport, move
    783      * it to the viewport's top left corner.  This unavoidably causes a slight
    784      * jittering in the image (even with double-buffering).
    785      */
    786     if (pDstBox->x1 < 0)
    787     {
    788         *SrcLeft = ((-pDstBox->x1 * SrcW) / *DstW) & ~1;
    789         pDstBox->x1 = 0;
    790     }
    791 
    792     if (pDstBox->y1 < 0)
    793     {
    794         *SrcTop = (-pDstBox->y1 * SrcH) / *DstH;
    795         pDstBox->y1 = 0;
    796 
    797         switch (ImageID)
    798         {
    799             case FOURCC_YV12:
    800             case FOURCC_I420:
    801                 *SrcTop = (*SrcTop + 1) & ~1;
    802                 break;
    803 
    804             default:
    805                 break;
    806         }
    807     }
    808 
    809     return TRUE;
    810 }
    811 
    812 #ifdef ATIMove32
    813 
    814 /* A faster intercept */
    815 #undef  xf86XVCopyPacked
    816 #define xf86XVCopyPacked ATIMach64XVCopyPacked
    817 
    818 static void
    819 ATIMach64XVCopyPacked
    820 (
    821     const CARD8 *pSrc,
    822     CARD8       *pDst,
    823     int         SrcPitch,
    824     int         DstPitch,
    825     int         Height,
    826     int         Width
    827 )
    828 {
    829     Width >>= 1;
    830     while (--Height >= 0)
    831     {
    832         ATIMove32(pDst, pSrc, Width);
    833         pSrc += SrcPitch;
    834         pDst += DstPitch;
    835     }
    836 }
    837 
    838 #endif
    839 
    840 /*
    841  * ATIMach64DisplayVideo --
    842  *
    843  * This function programmes Mach64 registers needed to display a video.
    844  */
    845 static void
    846 ATIMach64DisplayVideo
    847 (
    848     ScrnInfoPtr pScreenInfo,
    849     ATIPtr      pATI,
    850     BoxPtr      pDstBox,
    851     int         ImageID,
    852     int         Offset,
    853     int         Pitch,
    854     short       SrcW,
    855     short       SrcH,
    856     short       DstW,
    857     short       DstH,
    858     short       Width,
    859     short       Height
    860 )
    861 {
    862     DisplayModePtr pMode = pScreenInfo->currentMode;
    863     CARD32         HScale, VScale;
    864 
    865     if (pMode->VScan > 1)
    866     {
    867         pDstBox->y1 *= pMode->VScan;
    868         pDstBox->y2 *= pMode->VScan;
    869     }
    870     if (pMode->Flags & V_DBLSCAN)
    871     {
    872         pDstBox->y1 <<= 1;
    873         pDstBox->y2 <<= 1;
    874     }
    875 
    876     /* Recalculate overlay scale factors */
    877     ATIMach64ScaleVideo(pATI, pMode, SrcW, SrcH, DstW, DstH, &HScale, &VScale);
    878 
    879     pATI->NewHW.video_format &= ~SCALER_IN;
    880     if (ImageID == FOURCC_UYVY)
    881         pATI->NewHW.video_format |= SCALER_IN_YVYU422;
    882     else
    883         pATI->NewHW.video_format |= SCALER_IN_VYUY422;
    884 
    885     ATIMach64WaitForFIFO(pATI, 8);
    886     outq(OVERLAY_Y_X_START, OVERLAY_Y_X_END, OVERLAY_LOCK_START |
    887         SetWord(pDstBox->x1, 1) | SetWord(pDstBox->y1, 0),
    888         SetWord(pDstBox->x2 - 1, 1) | SetWord(pDstBox->y2 - 1, 0));
    889     outf(OVERLAY_SCALE_INC, SetWord(HScale, 1) | SetWord(VScale, 0));
    890     outf(SCALER_HEIGHT_WIDTH, SetWord(Width, 1) | SetWord(Height, 0));
    891     outf(VIDEO_FORMAT, pATI->NewHW.video_format);
    892 
    893     if (pATI->Chip < ATI_CHIP_264VTB)
    894     {
    895         outf(BUF0_OFFSET, Offset);
    896         outf(BUF0_PITCH, Pitch);
    897     }
    898     else
    899     {
    900         outf(SCALER_BUF0_OFFSET, Offset);
    901         outf(SCALER_BUF_PITCH, Pitch);
    902     }
    903 
    904     outf(OVERLAY_SCALE_CNTL, SCALE_PIX_EXPAND | OVERLAY_EN | SCALE_EN);
    905 }
    906 
    907 /*
    908  * ATIMach64PutImage --
    909  *
    910  * This function is called to put a video image on the screen.
    911  */
    912 static int
    913 ATIMach64PutImage
    914 (
    915     ScrnInfoPtr   pScreenInfo,
    916     short         SrcX,
    917     short         SrcY,
    918     short         DstX,
    919     short         DstY,
    920     short         SrcW,
    921     short         SrcH,
    922     short         DstW,
    923     short         DstH,
    924     int           ImageID,
    925     unsigned char *Buffer,
    926     short         Width,
    927     short         Height,
    928     Bool          Synchronise,
    929     RegionPtr     pClip,
    930     pointer       Data,
    931     DrawablePtr   pDraw
    932 )
    933 {
    934     ATIPtr    pATI    = Data;
    935     ScreenPtr pScreen;
    936     INT32     SrcX1, SrcX2, SrcY1, SrcY2;
    937     BoxRec    DstBox;
    938     int       SrcPitch, SrcPitchUV, DstPitch, DstSize;
    939     int       SrcTop, SrcLeft, DstWidth, DstHeight;
    940     int       Top, Bottom, Left, Right, nLine, nPixel, Offset;
    941     int       OffsetV, OffsetU;
    942     int       XVOffset;
    943     int       tmp;
    944     CARD8     *pDst;
    945 
    946     if (pATI->ActiveSurface)
    947         return Success;
    948 
    949     if (DstH < 16)
    950 	return Success;
    951 
    952     if (!ATIMach64ClipVideo(pScreenInfo, pATI, ImageID,
    953                             SrcX, SrcY, SrcW, SrcH,
    954                             DstX, DstY, &DstW, &DstH,
    955                             Width, Height, pClip, &DstBox,
    956                             &SrcX1, &SrcX2, &SrcY1, &SrcY2,
    957                             &SrcLeft, &SrcTop))
    958         return Success;
    959 
    960     pScreen = pScreenInfo->pScreen;
    961 
    962     DstWidth = Width - SrcLeft;
    963     DstHeight = Height - SrcTop;
    964 
    965     /*
    966      * Allocate an offscreen buffer for the entire source, even though only a
    967      * subset of the source will be copied into it.
    968      */
    969     DstPitch = /* bytes */
    970         (DstWidth + DstWidth + 15) & ~15;
    971     DstSize =  /* bytes */
    972         (DstPitch * DstHeight);
    973 
    974     pATI->pXVBuffer = ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer,
    975         (pATI->DoubleBuffer + 1) * DstSize, &XVOffset, pATI);
    976 
    977     if (!pATI->pXVBuffer)
    978     {
    979         if (!pATI->DoubleBuffer)
    980             return BadAlloc;
    981 
    982         pATI->pXVBuffer =
    983             ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer, DstSize, &XVOffset, pATI);
    984 
    985         if (!pATI->pXVBuffer)
    986             return BadAlloc;
    987 
    988         xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
    989             "Video image double-buffering downgraded to single-buffering\n due"
    990             " to insufficient video memory.\n");
    991         pATI->DoubleBuffer = pATI->CurrentBuffer = 0;
    992     }
    993     else
    994     {
    995         /* Possibly switch buffers */
    996         pATI->CurrentBuffer = pATI->DoubleBuffer - pATI->CurrentBuffer;
    997     }
    998 
    999     /* Synchronise video memory accesses */
   1000     ATIMach64Sync(pScreenInfo);
   1001 
   1002     Offset = XVOffset + pATI->CurrentBuffer * DstSize;
   1003     pDst = pATI->pMemoryLE;
   1004     pDst += Offset;
   1005 
   1006     switch (ImageID)
   1007     {
   1008         case FOURCC_YV12:
   1009         case FOURCC_I420:
   1010             Left = (SrcX1 >> 16) & ~1;
   1011             Right = ((SrcX2 + 0x1FFFF) >> 16) & ~1;
   1012             Top = (SrcY1 >> 16) & ~1;
   1013             Bottom = ((SrcY2 + 0x1FFFF) >> 16) & ~1;
   1014 
   1015             if ((Right < Width) && ((SrcX1 & 0x1FFFF) <= (SrcX2 & 0x1FFFF)))
   1016                 Right += 2;
   1017             if ((Bottom < Height) && ((SrcY1 & 0x1FFFF) <= (SrcY2 & 0x1FFFF)))
   1018                 Bottom += 2;
   1019 
   1020             nPixel = Right - Left;
   1021             nLine = Bottom - Top;
   1022 
   1023             SrcPitch = (Width + 3) & ~3;
   1024             OffsetV = SrcPitch * Height;
   1025             SrcPitchUV = ((Width >> 1) + 3) & ~3;
   1026             OffsetU = ((Height >> 1) * SrcPitchUV) + OffsetV;
   1027 
   1028             tmp = ((Top >> 1) * SrcPitchUV) + (Left >> 1);
   1029             OffsetV += tmp;
   1030             OffsetU += tmp;
   1031 
   1032             if (ImageID == FOURCC_I420)
   1033             {
   1034                 tmp = OffsetV;
   1035                 OffsetV = OffsetU;
   1036                 OffsetU = tmp;
   1037             }
   1038 
   1039             pDst += ((Top - SrcTop) * DstPitch) + ((Left - SrcLeft) << 1);
   1040 
   1041             xf86XVCopyYUV12ToPacked(Buffer + (Top * SrcPitch) + Left,
   1042                 Buffer + OffsetV, Buffer + OffsetU, pDst, SrcPitch, SrcPitchUV,
   1043                 DstPitch, nLine, nPixel);
   1044             break;
   1045 
   1046         case FOURCC_UYVY:
   1047         case FOURCC_YUY2:
   1048         default:
   1049             Left = (SrcX1 >> 16) & ~1;
   1050             Right = ((SrcX2 + 0x1FFFF) >> 16) & ~1;
   1051             Top = SrcY1 >> 16;
   1052             Bottom = (SrcY2 + 0x0FFFF) >> 16;
   1053 
   1054             if ((Right < Width) && ((SrcX1 & 0x1FFFF) <= (SrcX2 & 0x1FFFF)))
   1055                 Right += 2;
   1056             if ((Bottom < Height) && ((SrcY1 & 0x0FFFF) <= (SrcY2 & 0x0FFFF)))
   1057                 Bottom++;
   1058 
   1059             nPixel = Right - Left;
   1060             nLine = Bottom - Top;
   1061 
   1062             SrcPitch = Width << 1;
   1063             Buffer += (Top * SrcPitch) + (Left << 1);
   1064             pDst += ((Top - SrcTop) * DstPitch) + ((Left - SrcLeft) << 1);
   1065 
   1066             xf86XVCopyPacked(Buffer, pDst, SrcPitch, DstPitch, nLine, nPixel);
   1067             break;
   1068     }
   1069 
   1070     if (!REGION_EQUAL(pScreen, &pATI->VideoClip, pClip))
   1071     {
   1072         REGION_COPY(pScreen, &pATI->VideoClip, pClip);
   1073         if (pATI->AutoPaint)
   1074             xf86XVFillKeyHelper(pScreen, pATI->NewHW.overlay_graphics_key_clr,
   1075                 pClip);
   1076     }
   1077 
   1078     ATIMach64DisplayVideo(pScreenInfo, pATI, &DstBox, ImageID,
   1079         Offset, DstPitch / 2, SrcW, SrcH, DstW, DstH, DstWidth, DstHeight);
   1080 
   1081     return Success;
   1082 }
   1083 
   1084 /*
   1085  * ATIMach64AllocateSurface --
   1086  *
   1087  * This function allocates an offscreen buffer (called a "surface") for use by
   1088  * an external driver such as 'v4l'.
   1089  */
   1090 static int
   1091 ATIMach64AllocateSurface
   1092 (
   1093     ScrnInfoPtr    pScreenInfo,
   1094     int            ImageID,
   1095     unsigned short Width,
   1096     unsigned short Height,
   1097     XF86SurfacePtr pSurface
   1098 )
   1099 {
   1100     ScreenPtr pScreen;
   1101     ATIPtr    pATI = ATIPTR(pScreenInfo);
   1102     int       XVOffset;
   1103 
   1104     if (pATI->ActiveSurface)
   1105         return BadAlloc;
   1106 
   1107     if ((Height <= 0) || (Height > 2048) || (Width <= 0) || (Width > 768) ||
   1108         ((Width > 384) && (pATI->Chip < ATI_CHIP_264VTB)) ||
   1109         ((Width > 720) && (pATI->Chip < ATI_CHIP_264GTPRO ||
   1110                            pATI->Chip > ATI_CHIP_264LTPRO)))
   1111         return BadValue;
   1112 
   1113     Width = (Width + 1) & ~1;
   1114     pATI->SurfacePitch = ((Width << 1) + 15) & ~15;
   1115 
   1116     pScreen = pScreenInfo->pScreen;
   1117 
   1118     pATI->pXVBuffer = ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer,
   1119         Height * pATI->SurfacePitch, &XVOffset, pATI);
   1120     if (!pATI->pXVBuffer)
   1121         return BadAlloc;
   1122 
   1123     pATI->SurfaceOffset = XVOffset;
   1124 
   1125     pSurface->pScrn = pScreenInfo;
   1126     pSurface->id = ImageID;
   1127     pSurface->width = Width;
   1128     pSurface->height = Height;
   1129     pSurface->pitches = &pATI->SurfacePitch;
   1130     pSurface->offsets = &pATI->SurfaceOffset;
   1131     pSurface->devPrivate.ptr = pATI;
   1132 
   1133     /* Stop the video */
   1134     outf(OVERLAY_SCALE_CNTL, SCALE_EN);
   1135     REGION_EMPTY(pScreen, &pATI->VideoClip);
   1136     pATI->ActiveSurface = TRUE;
   1137 
   1138     return Success;
   1139 }
   1140 
   1141 /*
   1142  * ATIMach64FreeSurface --
   1143  *
   1144  * This function called to free a surface's offscreen buffer.
   1145  */
   1146 static int
   1147 ATIMach64FreeSurface
   1148 (
   1149     XF86SurfacePtr pSurface
   1150 )
   1151 {
   1152     ATIPtr pATI = pSurface->devPrivate.ptr;
   1153 
   1154     if (!pATI->ActiveSurface)
   1155         return Success;
   1156 
   1157     outf(OVERLAY_SCALE_CNTL, SCALE_EN);
   1158     ATIMach64XVMemFree(pSurface->pScrn->pScreen, pATI->pXVBuffer, pATI);
   1159     pATI->pXVBuffer = NULL;
   1160     pATI->ActiveSurface = FALSE;
   1161 
   1162     return Success;
   1163 }
   1164 
   1165 /*
   1166  * ATIMach64DisplaySurface --
   1167  *
   1168  * This function is called to display a video surface.
   1169  */
   1170 static int
   1171 ATIMach64DisplaySurface
   1172 (
   1173     XF86SurfacePtr pSurface,
   1174     short          SrcX,
   1175     short          SrcY,
   1176     short          DstX,
   1177     short          DstY,
   1178     short          SrcW,
   1179     short          SrcH,
   1180     short          DstW,
   1181     short          DstH,
   1182     RegionPtr      pClip
   1183 )
   1184 {
   1185     ATIPtr      pATI = pSurface->devPrivate.ptr;
   1186     ScrnInfoPtr pScreenInfo;
   1187     int         ImageID;
   1188     short       Width, Height;
   1189     BoxRec      DstBox;
   1190     INT32       SrcX1, SrcX2, SrcY1, SrcY2;
   1191     int         SrcLeft, SrcTop, SrcPitch, Offset;
   1192 
   1193     if (!pATI->ActiveSurface)
   1194         return Success;
   1195 
   1196     pScreenInfo = pSurface->pScrn;
   1197     ImageID = pSurface->id;
   1198     Width = pSurface->width;
   1199     Height = pSurface->height;
   1200 
   1201     if (!ATIMach64ClipVideo(pScreenInfo, pATI, ImageID,
   1202                             SrcX, SrcY, SrcW, SrcH,
   1203                             DstX, DstY, &DstW, &DstH,
   1204                             Width, Height, pClip, &DstBox,
   1205                             &SrcX1, &SrcX2, &SrcY1, &SrcY2,
   1206                             &SrcLeft, &SrcTop))
   1207         return Success;
   1208 
   1209     xf86XVFillKeyHelper(pScreenInfo->pScreen,
   1210         pATI->NewHW.overlay_graphics_key_clr, pClip);
   1211 
   1212     SrcPitch = pSurface->pitches[0];
   1213     Offset = pSurface->offsets[0] + (SrcTop * SrcPitch) + (SrcLeft << 1);
   1214     ATIMach64DisplayVideo(pScreenInfo, pATI, &DstBox, ImageID,
   1215         Offset, SrcPitch, SrcW, SrcH, DstW, DstH, Width, Height);
   1216 
   1217     return Success;
   1218 }
   1219 
   1220 /*
   1221  * ATIMach64StopSurface --
   1222  *
   1223  * This function is called to stop the overlaid display of a video surface.
   1224  */
   1225 static int
   1226 ATIMach64StopSurface
   1227 (
   1228     XF86SurfacePtr pSurface
   1229 )
   1230 {
   1231     ATIPtr pATI = pSurface->devPrivate.ptr;
   1232 
   1233     if (pATI->ActiveSurface)
   1234         outf(OVERLAY_SCALE_CNTL, SCALE_EN);
   1235 
   1236     return Success;
   1237 }
   1238 
   1239 /*
   1240  * ATIMach64GetSurfaceAttribute --
   1241  *
   1242  * Retrieve the value of an XVideo attribute.
   1243  */
   1244 static int
   1245 ATIMach64GetSurfaceAttribute
   1246 (
   1247     ScrnInfoPtr pScreenInfo,
   1248     Atom        AttributeID,
   1249     INT32       *Value
   1250 )
   1251 {
   1252     return ATIMach64GetPortAttribute(pScreenInfo, AttributeID, Value,
   1253                                      ATIPTR(pScreenInfo));
   1254 }
   1255 
   1256 /*
   1257  * ATIMach64SetSurfaceAttribute
   1258  *
   1259  * Set the value of an XVideo attribute.
   1260  */
   1261 static int
   1262 ATIMach64SetSurfaceAttribute
   1263 (
   1264     ScrnInfoPtr pScreenInfo,
   1265     Atom        AttributeID,
   1266     INT32       Value
   1267 )
   1268 {
   1269     return ATIMach64SetPortAttribute(pScreenInfo, AttributeID, Value,
   1270                                      ATIPTR(pScreenInfo));
   1271 }
   1272 
   1273 /* XVideo surface registration data */
   1274 static XF86OffscreenImageRec ATIMach64Surface[] =
   1275 {
   1276     {
   1277         &ATIMach64Image[0],             /* YUY2 */
   1278         VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
   1279         ATIMach64AllocateSurface,
   1280         ATIMach64FreeSurface,
   1281         ATIMach64DisplaySurface,
   1282         ATIMach64StopSurface,
   1283         ATIMach64GetSurfaceAttribute,
   1284         ATIMach64SetSurfaceAttribute,
   1285         720, 2048,
   1286         nATIMach64Attribute - 1,        /* No double-buffering */
   1287         ATIMach64Attribute
   1288     },
   1289     {
   1290         &ATIMach64Image[1],             /* UYVY */
   1291         VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
   1292         ATIMach64AllocateSurface,
   1293         ATIMach64FreeSurface,
   1294         ATIMach64DisplaySurface,
   1295         ATIMach64StopSurface,
   1296         ATIMach64GetSurfaceAttribute,
   1297         ATIMach64SetSurfaceAttribute,
   1298         720, 2048,
   1299         nATIMach64Attribute - 1,        /* No double-buffering */
   1300         ATIMach64Attribute
   1301     }
   1302 };
   1303 #define nATIMach64Surface NumberOf(ATIMach64Surface)
   1304 
   1305 /*
   1306  * ATIMach64XVInitialiseAdaptor --
   1307  *
   1308  * This function is called to make a Mach64's hardware overlay support
   1309  * available as an XVideo adaptor.
   1310  */
   1311 static int
   1312 ATIMach64XVInitialiseAdaptor
   1313 (
   1314     ScrnInfoPtr         pScreenInfo,
   1315     XF86VideoAdaptorPtr **pppAdaptor
   1316 )
   1317 {
   1318     ScreenPtr           pScreen    = xf86ScrnToScreen(pScreenInfo);
   1319     ATIPtr              pATI       = ATIPTR(pScreenInfo);
   1320     XF86VideoAdaptorPtr *ppAdaptor = NULL;
   1321     XF86VideoAdaptorPtr pAdaptor;
   1322 
   1323     XF86VideoEncodingPtr  enc = &(ATIMach64VideoEncoding[0]);
   1324     XF86OffscreenImagePtr surf0 = &(ATIMach64Surface[0]);
   1325     XF86OffscreenImagePtr surf1 = &(ATIMach64Surface[1]);
   1326 
   1327     if (xf86NameCmp(pScreenInfo->driverName, MACH64_DRIVER_NAME) != 0)
   1328 	return 0;
   1329 
   1330     if (pppAdaptor)
   1331         *pppAdaptor = NULL;
   1332 
   1333     if (!pATI->Block1Base)
   1334         return 0;
   1335 
   1336     if (!(pAdaptor = xf86XVAllocateVideoAdaptorRec(pScreenInfo)))
   1337         return 0;
   1338 
   1339     ppAdaptor = XNFalloc(sizeof(pAdaptor));
   1340     ppAdaptor[0] = pAdaptor;
   1341 
   1342     pAdaptor->nPorts = 1;
   1343     pAdaptor->pPortPrivates = pATI->XVPortPrivate;
   1344     pATI->XVPortPrivate[0].ptr = pATI;
   1345 
   1346     pAdaptor->type = XvInputMask | XvImageMask | XvWindowMask;
   1347     pAdaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
   1348     pAdaptor->name = "ATI Mach64 Back-end Overlay Scaler";
   1349 
   1350     if (pATI->Chip < ATI_CHIP_264VTB)
   1351     {
   1352         enc->width = 384;
   1353     }
   1354     else if (pATI->Chip < ATI_CHIP_264GTPRO ||
   1355              pATI->Chip > ATI_CHIP_264LTPRO)
   1356     {
   1357         enc->width = 720; /* default */
   1358     }
   1359     else
   1360     {
   1361         enc->width = 768;
   1362     }
   1363     pAdaptor->nEncodings = nATIMach64VideoEncoding;
   1364     pAdaptor->pEncodings = ATIMach64VideoEncoding;
   1365 
   1366     pAdaptor->nFormats = nATIMach64VideoFormat;
   1367     pAdaptor->pFormats = ATIMach64VideoFormat;
   1368 
   1369     pAdaptor->nAttributes = nATIMach64Attribute;
   1370     pAdaptor->pAttributes = ATIMach64Attribute;
   1371 
   1372     if (pATI->Chip < ATI_CHIP_264GTPRO)
   1373     {
   1374         /* Older controllers don't have brightness or saturation controls */
   1375         pAdaptor->nAttributes -= 4;
   1376         pAdaptor->pAttributes += 4;
   1377     }
   1378 
   1379     pAdaptor->nImages = nATIMach64Image;
   1380     pAdaptor->pImages = ATIMach64Image;
   1381 
   1382     pAdaptor->StopVideo            = ATIMach64StopVideo;
   1383     pAdaptor->SetPortAttribute     = ATIMach64SetPortAttribute;
   1384     pAdaptor->GetPortAttribute     = ATIMach64GetPortAttribute;
   1385     pAdaptor->QueryBestSize        = ATIMach64QueryBestSize;
   1386     pAdaptor->PutImage             = ATIMach64PutImage;
   1387     pAdaptor->QueryImageAttributes = ATIMach64QueryImageAttributes;
   1388 
   1389     REGION_NULL(pScreen, &pATI->VideoClip);
   1390     pATI->ActiveSurface = FALSE;
   1391 
   1392     if (ATIMach64XVAtomGeneration != serverGeneration)
   1393     {
   1394         int                 Index;
   1395 
   1396         /* Refresh static data */
   1397         ATIMach64XVAtomGeneration = serverGeneration;
   1398 
   1399         Index = nATIMach64Attribute - pAdaptor->nAttributes;
   1400         for (;  Index < nATIMach64Attribute;  Index++)
   1401             ATIMach64AttributeInfo[Index].AttributeID =
   1402                 MAKE_ATOM(ATIMach64Attribute[Index].name);
   1403     }
   1404 
   1405     ATIMach64SetDefaultAttributes(pATI, 0);
   1406 
   1407     if (pATI->Chip < ATI_CHIP_264VTB)
   1408     {
   1409         surf0->max_width = 384;
   1410         surf1->max_width = 384;
   1411     }
   1412     else if (pATI->Chip < ATI_CHIP_264GTPRO ||
   1413              pATI->Chip > ATI_CHIP_264LTPRO)
   1414     {
   1415         surf0->max_width = 720; /* default */
   1416         surf1->max_width = 720;
   1417     }
   1418     else
   1419     {
   1420         surf0->max_width = 768;
   1421         surf1->max_width = 768;
   1422     }
   1423 
   1424     if (pATI->Chip < ATI_CHIP_264GTPRO)
   1425     {
   1426         /* No saturation nor brightness */
   1427         surf0->num_attributes -= 4;
   1428         surf1->num_attributes -= 4;
   1429         surf0->attributes += 4;
   1430         surf1->attributes += 4;
   1431     }
   1432     xf86XVRegisterOffscreenImages(pScreen, ATIMach64Surface, nATIMach64Surface);
   1433 
   1434     if (pppAdaptor)
   1435         *pppAdaptor = ppAdaptor;
   1436     else {
   1437         free(ppAdaptor[0]);
   1438         free(ppAdaptor);
   1439     }
   1440 
   1441     return 1;
   1442 }
   1443 
   1444 /*
   1445  * ATIXVPreInit --
   1446  *
   1447  * This function is called by ATIPreInit() to set up the environment required
   1448  * to support the XVideo extension.
   1449  */
   1450 void
   1451 ATIXVPreInit
   1452 (
   1453     ATIPtr      pATI
   1454 )
   1455 {
   1456     (void)xf86XVRegisterGenericAdaptorDriver(ATIMach64XVInitialiseAdaptor);
   1457 }
   1458 
   1459 /*
   1460  * ATIXVFreeAdaptorInfo --
   1461  *
   1462  * Free XVideo adaptor information.
   1463  */
   1464 static void
   1465 ATIXVFreeAdaptorInfo
   1466 (
   1467     XF86VideoAdaptorPtr *ppAdaptor,
   1468     int                 nAdaptor
   1469 )
   1470 {
   1471     if (!ppAdaptor)
   1472         return;
   1473 
   1474     while (nAdaptor > 0)
   1475         free(ppAdaptor[--nAdaptor]);
   1476 
   1477     free(ppAdaptor);
   1478 }
   1479 
   1480 /*
   1481  * ATIInitializeXVideo --
   1482  *
   1483  * This function is called to initialise XVideo extension support on a screen.
   1484  */
   1485 Bool
   1486 ATIInitializeXVideo
   1487 (
   1488     ScreenPtr   pScreen,
   1489     ScrnInfoPtr pScreenInfo,
   1490     ATIPtr      pATI
   1491 )
   1492 {
   1493     XF86VideoAdaptorPtr *ppAdaptor;
   1494     int                 nAdaptor;
   1495     Bool                result;
   1496 
   1497     pScreenInfo->memPhysBase = pATI->LinearBase;
   1498     pScreenInfo->fbOffset = 0;
   1499 
   1500     nAdaptor = xf86XVListGenericAdaptors(pScreenInfo, &ppAdaptor);
   1501     result = xf86XVScreenInit(pScreen, ppAdaptor, nAdaptor);
   1502 
   1503     ATIXVFreeAdaptorInfo(ppAdaptor, nAdaptor);
   1504 
   1505     return result;
   1506 }
   1507 
   1508 /*
   1509  * ATIMach64CloseXVideo --
   1510  *
   1511  * This function is called during screen termination to clean up after
   1512  * initialisation of Mach64 XVideo support.
   1513  */
   1514 void
   1515 ATICloseXVideo
   1516 (
   1517     ScreenPtr   pScreen,
   1518     ScrnInfoPtr pScreenInfo,
   1519     ATIPtr      pATI
   1520 )
   1521 {
   1522     if (!pATI->Block1Base)
   1523         return;
   1524 
   1525     ATIMach64StopVideo(pScreenInfo, pATI, TRUE);
   1526 
   1527     REGION_UNINIT(pScreen, &pATI->VideoClip);
   1528 }
   1529 
   1530 /* Functions for offscreen memory management */
   1531 
   1532 
   1533 static pointer
   1534 ATIMach64XVMemAlloc
   1535 (
   1536     ScreenPtr pScreen,
   1537     pointer   pVideo,
   1538     int       size,
   1539     int       *offset,
   1540     ATIPtr    pATI
   1541 )
   1542 {
   1543 #ifdef USE_EXA
   1544     if (pATI->useEXA) {
   1545         ExaOffscreenArea *area = (ExaOffscreenArea *)pVideo;
   1546 
   1547         if (area != NULL) {
   1548             if (area->size >= size) {
   1549                 *offset = area->offset;
   1550                 return area;
   1551             }
   1552 
   1553             exaOffscreenFree(pScreen, area);
   1554         }
   1555 
   1556         area = exaOffscreenAlloc(pScreen, size, 64, TRUE, NULL, NULL);
   1557         if (area != NULL) {
   1558             *offset = area->offset;
   1559             return area;
   1560         }
   1561     }
   1562 #endif /* USE_EXA */
   1563 
   1564 
   1565     *offset = 0;
   1566     return NULL;
   1567 }
   1568 
   1569 static void
   1570 ATIMach64XVMemFree
   1571 (
   1572     ScreenPtr pScreen,
   1573     pointer   pVideo,
   1574     ATIPtr    pATI
   1575 )
   1576 {
   1577 #ifdef USE_EXA
   1578     if (pATI->useEXA) {
   1579         ExaOffscreenArea *area = (ExaOffscreenArea *)pVideo;
   1580 
   1581         if (area != NULL)
   1582             exaOffscreenFree(pScreen, area);
   1583     }
   1584 #endif /* USE_EXA */
   1585 
   1586 }
   1587 
   1588