1606 lines
40 KiB
C
1606 lines
40 KiB
C
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64xv.c,v 1.7 2003/11/10 18:22:18 tsi Exp $ */
|
|
/*
|
|
* Copyright 2003 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice appear in all copies and that both that copyright
|
|
* notice and this permission notice appear in supporting documentation, and
|
|
* that the name of Marc Aurele La France not be used in advertising or
|
|
* publicity pertaining to distribution of the software without specific,
|
|
* written prior permission. Marc Aurele La France makes no representations
|
|
* about the suitability of this software for any purpose. It is provided
|
|
* "as-is" without express or implied warranty.
|
|
*
|
|
* MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
|
* EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
#include "ati.h"
|
|
#include "atiaccel.h"
|
|
#include "atichip.h"
|
|
#include "atimach64accel.h"
|
|
#include "atimach64io.h"
|
|
#include "atimach64xv.h"
|
|
|
|
#include <X11/extensions/Xv.h>
|
|
#include "fourcc.h"
|
|
|
|
#define MAKE_ATOM(string) MakeAtom(string, strlen(string), TRUE)
|
|
#define MaxScale (CARD32)(CARD16)(-1)
|
|
|
|
static unsigned long ATIMach64XVAtomGeneration = (unsigned long)(-1);
|
|
|
|
static XF86VideoEncodingRec ATIMach64VideoEncoding_A[] =
|
|
{
|
|
{ 0, "XV_IMAGE", 384, 2048, {1, 1} }
|
|
};
|
|
#define nATIMach64VideoEncoding_A NumberOf(ATIMach64VideoEncoding_A)
|
|
|
|
static XF86VideoEncodingRec ATIMach64VideoEncoding_B[] =
|
|
{
|
|
{ 0, "XV_IMAGE", 720, 2048, {1, 1} }
|
|
};
|
|
#define nATIMach64VideoEncoding_B NumberOf(ATIMach64VideoEncoding_B)
|
|
|
|
/* nATIMach64VideoEncoding_[AB] should be equal */
|
|
#define nATIMach64VideoEncoding nATIMach64VideoEncoding_A
|
|
|
|
static XF86VideoFormatRec ATIMach64VideoFormat[] =
|
|
{
|
|
{ 8, TrueColor},
|
|
{ 8, DirectColor},
|
|
{ 8, PseudoColor},
|
|
{ 8, GrayScale},
|
|
{ 8, StaticGray},
|
|
{ 8, StaticColor},
|
|
{15, TrueColor},
|
|
{16, TrueColor},
|
|
{24, TrueColor},
|
|
{15, DirectColor},
|
|
{16, DirectColor},
|
|
{24, DirectColor}
|
|
};
|
|
#define nATIMach64VideoFormat NumberOf(ATIMach64VideoFormat)
|
|
|
|
static XF86AttributeRec ATIMach64Attribute[] =
|
|
{
|
|
/* These are only supported on the Rage Pro and later ... */
|
|
{
|
|
XvSettable | XvGettable,
|
|
-1000, 1000,
|
|
"XV_SATURATION"
|
|
},
|
|
{
|
|
XvSettable | XvGettable,
|
|
-1000, 1000,
|
|
"XV_BRIGHTNESS"
|
|
},
|
|
{
|
|
XvSettable | XvGettable,
|
|
-1000, 1000,
|
|
"XV_COLOUR"
|
|
},
|
|
{
|
|
XvSettable | XvGettable,
|
|
-1000, 1000,
|
|
"XV_COLOR"
|
|
},
|
|
|
|
/* Local attributes, odds and ends for compatibility, etc... */
|
|
{
|
|
XvSettable | XvGettable,
|
|
0, 1,
|
|
"XV_AUTOPAINT_COLOURKEY"
|
|
},
|
|
{
|
|
XvSettable | XvGettable,
|
|
0, 1,
|
|
"XV_AUTOPAINT_COLORKEY"
|
|
},
|
|
{
|
|
XvSettable | XvGettable,
|
|
0, (1 << 24) - 1,
|
|
"XV_COLOURKEY"
|
|
},
|
|
{
|
|
XvSettable | XvGettable,
|
|
0, (1 << 24) - 1,
|
|
"XV_COLORKEY"
|
|
},
|
|
{
|
|
XvSettable | XvGettable,
|
|
0, (1 << 24) - 1,
|
|
"XV_COLOURKEY_MASK"
|
|
},
|
|
{
|
|
XvSettable | XvGettable,
|
|
0, (1 << 24) - 1,
|
|
"XV_COLORKEY_MASK"
|
|
},
|
|
{
|
|
XvSettable,
|
|
0, 0,
|
|
"XV_SET_DEFAULTS"
|
|
},
|
|
{ /* Keep last */
|
|
XvSettable | XvGettable,
|
|
0, 1,
|
|
"XV_DOUBLE_BUFFER"
|
|
}
|
|
};
|
|
#define nATIMach64Attribute NumberOf(ATIMach64Attribute)
|
|
|
|
static XF86ImageRec ATIMach64Image[] =
|
|
{
|
|
XVIMAGE_YUY2,
|
|
XVIMAGE_UYVY,
|
|
XVIMAGE_YV12,
|
|
XVIMAGE_I420
|
|
};
|
|
#define nATIMach64Image NumberOf(ATIMach64Image)
|
|
|
|
/* A local XVideo adaptor attribute record */
|
|
typedef struct _ATIMach64Attribute
|
|
{
|
|
Atom AttributeID;
|
|
INT32 MaxValue; /* ... for the hardware */
|
|
void (*SetAttribute) (ATIPtr, INT32);
|
|
INT32 (*GetAttribute) (ATIPtr);
|
|
} ATIMach64AttributeRec, *ATIMach64AttributePtr;
|
|
|
|
/* Functions to get/set XVideo adaptor attributes */
|
|
|
|
static void
|
|
ATIMach64SetSaturationAttribute
|
|
(
|
|
ATIPtr pATI,
|
|
INT32 Value
|
|
)
|
|
{
|
|
/* Set the register */
|
|
pATI->NewHW.scaler_colour_cntl &=
|
|
~(SCALE_SATURATION_U | SCALE_SATURATION_V);
|
|
pATI->NewHW.scaler_colour_cntl |= SetBits(Value, SCALE_SATURATION_U) |
|
|
SetBits(Value, SCALE_SATURATION_V);
|
|
outf(SCALER_COLOUR_CNTL, pATI->NewHW.scaler_colour_cntl);
|
|
}
|
|
|
|
static INT32
|
|
ATIMach64GetSaturationAttribute
|
|
(
|
|
ATIPtr pATI
|
|
)
|
|
{
|
|
return (INT32)GetBits(pATI->NewHW.scaler_colour_cntl, SCALE_SATURATION_U);
|
|
}
|
|
|
|
static void
|
|
ATIMach64SetBrightnessAttribute
|
|
(
|
|
ATIPtr pATI,
|
|
INT32 Value
|
|
)
|
|
{
|
|
/* Set the register */
|
|
pATI->NewHW.scaler_colour_cntl &= ~SCALE_BRIGHTNESS;
|
|
pATI->NewHW.scaler_colour_cntl |= SetBits(Value, SCALE_BRIGHTNESS);
|
|
outf(SCALER_COLOUR_CNTL, pATI->NewHW.scaler_colour_cntl);
|
|
}
|
|
|
|
static INT32
|
|
ATIMach64GetBrightnessAttribute
|
|
(
|
|
ATIPtr pATI
|
|
)
|
|
{
|
|
return (INT32)GetBits(pATI->NewHW.scaler_colour_cntl, SCALE_BRIGHTNESS);
|
|
}
|
|
|
|
static void
|
|
ATIMach64SetDoubleBufferAttribute
|
|
(
|
|
ATIPtr pATI,
|
|
INT32 Value
|
|
)
|
|
{
|
|
pATI->DoubleBuffer = Value;
|
|
}
|
|
|
|
static INT32
|
|
ATIMach64GetDoubleBufferAttribute
|
|
(
|
|
ATIPtr pATI
|
|
)
|
|
{
|
|
return (int)pATI->DoubleBuffer;
|
|
}
|
|
|
|
static void
|
|
ATIMach64SetAutoPaintAttribute
|
|
(
|
|
ATIPtr pATI,
|
|
INT32 Value
|
|
)
|
|
{
|
|
pATI->AutoPaint = Value;
|
|
}
|
|
|
|
static INT32
|
|
ATIMach64GetAutoPaintAttribute
|
|
(
|
|
ATIPtr pATI
|
|
)
|
|
{
|
|
return (int)pATI->AutoPaint;
|
|
}
|
|
|
|
static void
|
|
ATIMach64SetColourKeyAttribute
|
|
(
|
|
ATIPtr pATI,
|
|
INT32 Value
|
|
)
|
|
{
|
|
pATI->NewHW.overlay_graphics_key_clr =
|
|
(CARD32)(Value & ((1 << pATI->depth) - 1));
|
|
outf(OVERLAY_GRAPHICS_KEY_CLR, pATI->NewHW.overlay_graphics_key_clr);
|
|
}
|
|
|
|
static INT32
|
|
ATIMach64GetColourKeyAttribute
|
|
(
|
|
ATIPtr pATI
|
|
)
|
|
{
|
|
return (INT32)pATI->NewHW.overlay_graphics_key_clr;
|
|
}
|
|
|
|
static void
|
|
ATIMach64SetColourKeyMaskAttribute
|
|
(
|
|
ATIPtr pATI,
|
|
INT32 Value
|
|
)
|
|
{
|
|
pATI->NewHW.overlay_graphics_key_msk =
|
|
(CARD32)(Value & ((1 << pATI->depth) - 1));
|
|
outf(OVERLAY_GRAPHICS_KEY_MSK, pATI->NewHW.overlay_graphics_key_msk);
|
|
}
|
|
|
|
static INT32
|
|
ATIMach64GetColourKeyMaskAttribute
|
|
(
|
|
ATIPtr pATI
|
|
)
|
|
{
|
|
return (INT32)pATI->NewHW.overlay_graphics_key_msk;
|
|
}
|
|
|
|
/*
|
|
* ATIMach64SetDefaultAttributes --
|
|
*
|
|
* This function calls other functions to set default values for the various
|
|
* attributes of an XVideo port.
|
|
*/
|
|
static void
|
|
ATIMach64SetDefaultAttributes
|
|
(
|
|
ATIPtr pATI,
|
|
INT32 Value
|
|
)
|
|
{
|
|
ATIMach64SetAutoPaintAttribute(pATI, TRUE);
|
|
ATIMach64SetDoubleBufferAttribute(pATI, FALSE);
|
|
ATIMach64SetColourKeyMaskAttribute(pATI, (1 << pATI->depth) - 1);
|
|
ATIMach64SetColourKeyAttribute(pATI, (3 << ((2 * pATI->depth) / 3)) |
|
|
(2 << ((1 * pATI->depth) / 3)) |
|
|
(1 << ((0 * pATI->depth) / 3)));
|
|
|
|
if (pATI->Chip < ATI_CHIP_264GTPRO)
|
|
return;
|
|
|
|
ATIMach64SetBrightnessAttribute(pATI, 32);
|
|
ATIMach64SetSaturationAttribute(pATI, 16);
|
|
}
|
|
|
|
/*
|
|
* There is a one-to-one correspondance between elements of the following array
|
|
* and those of ATIMach64Attribute.
|
|
*/
|
|
static ATIMach64AttributeRec ATIMach64AttributeInfo[nATIMach64Attribute] =
|
|
{
|
|
{ /* SATURATION */
|
|
0, 23,
|
|
ATIMach64SetSaturationAttribute,
|
|
ATIMach64GetSaturationAttribute
|
|
},
|
|
{ /* BRIGHTNESS */
|
|
0, 63,
|
|
ATIMach64SetBrightnessAttribute,
|
|
ATIMach64GetBrightnessAttribute
|
|
},
|
|
{ /* COLOUR */
|
|
0, 23,
|
|
ATIMach64SetSaturationAttribute,
|
|
ATIMach64GetSaturationAttribute
|
|
},
|
|
{ /* COLOR */
|
|
0, 23,
|
|
ATIMach64SetSaturationAttribute,
|
|
ATIMach64GetSaturationAttribute
|
|
},
|
|
{ /* AUTOPAINT_COLOURKEY */
|
|
0, 1,
|
|
ATIMach64SetAutoPaintAttribute,
|
|
ATIMach64GetAutoPaintAttribute
|
|
},
|
|
{ /* AUTOPAINT_COLORKEY */
|
|
0, 1,
|
|
ATIMach64SetAutoPaintAttribute,
|
|
ATIMach64GetAutoPaintAttribute
|
|
},
|
|
{ /* COLOURKEY */
|
|
0, (1 << 24) - 1,
|
|
ATIMach64SetColourKeyAttribute,
|
|
ATIMach64GetColourKeyAttribute
|
|
},
|
|
{ /* COLORKEY */
|
|
0, (1 << 24) - 1,
|
|
ATIMach64SetColourKeyAttribute,
|
|
ATIMach64GetColourKeyAttribute
|
|
},
|
|
{ /* COLOURKEY_MASK */
|
|
0, (1 << 24) - 1,
|
|
ATIMach64SetColourKeyMaskAttribute,
|
|
ATIMach64GetColourKeyMaskAttribute
|
|
},
|
|
{ /* COLORKEY_MASK */
|
|
0, (1 << 24) - 1,
|
|
ATIMach64SetColourKeyMaskAttribute,
|
|
ATIMach64GetColourKeyMaskAttribute
|
|
},
|
|
{ /* SET_DEFAULTS */
|
|
0, 0,
|
|
ATIMach64SetDefaultAttributes,
|
|
NULL
|
|
},
|
|
{ /* DOUBLE_BUFFER */
|
|
0, 1,
|
|
ATIMach64SetDoubleBufferAttribute,
|
|
ATIMach64GetDoubleBufferAttribute
|
|
}
|
|
};
|
|
|
|
/*
|
|
* ATIMach64FindAttribute --
|
|
*
|
|
* This function is called to locate an Xv attribute's table entry.
|
|
*/
|
|
static int
|
|
ATIMach64FindPortAttribute
|
|
(
|
|
ATIPtr pATI,
|
|
Atom AttributeID
|
|
)
|
|
{
|
|
int iAttribute;
|
|
|
|
if (pATI->Chip < ATI_CHIP_264GTPRO)
|
|
iAttribute = 4;
|
|
else
|
|
iAttribute = 0;
|
|
|
|
for (; iAttribute < nATIMach64Attribute; iAttribute++)
|
|
if (AttributeID == ATIMach64AttributeInfo[iAttribute].AttributeID)
|
|
return iAttribute;
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* ATIMach64SetPortAttribute --
|
|
*
|
|
* This function sets the value of a particular port's attribute.
|
|
*/
|
|
static int
|
|
ATIMach64SetPortAttribute
|
|
(
|
|
ScrnInfoPtr pScreenInfo,
|
|
Atom AttributeID,
|
|
INT32 Value,
|
|
pointer pATI
|
|
)
|
|
{
|
|
INT32 Range;
|
|
int iAttribute;
|
|
|
|
if (((iAttribute = ATIMach64FindPortAttribute(pATI, AttributeID)) < 0) ||
|
|
!ATIMach64AttributeInfo[iAttribute].SetAttribute)
|
|
return BadMatch;
|
|
|
|
Range = ATIMach64Attribute[iAttribute].max_value -
|
|
ATIMach64Attribute[iAttribute].min_value;
|
|
|
|
if (Range >= 0)
|
|
{
|
|
/* Limit and scale the value */
|
|
Value -= ATIMach64Attribute[iAttribute].min_value;
|
|
|
|
if (Value < 0)
|
|
Value = 0;
|
|
else if (Value > Range)
|
|
Value = Range;
|
|
|
|
if (Range != ATIMach64AttributeInfo[iAttribute].MaxValue)
|
|
{
|
|
if (ATIMach64AttributeInfo[iAttribute].MaxValue > 0)
|
|
Value *= ATIMach64AttributeInfo[iAttribute].MaxValue;
|
|
if (Range > 0)
|
|
Value /= Range;
|
|
}
|
|
}
|
|
|
|
(*ATIMach64AttributeInfo[iAttribute].SetAttribute)(pATI, Value);
|
|
|
|
return Success;
|
|
}
|
|
|
|
/*
|
|
* ATIMach64SetPortAttribute --
|
|
*
|
|
* This function retrieves the value of a particular port's attribute.
|
|
*/
|
|
static int
|
|
ATIMach64GetPortAttribute
|
|
(
|
|
ScrnInfoPtr pScreenInfo,
|
|
Atom AttributeID,
|
|
INT32 *Value,
|
|
pointer pATI
|
|
)
|
|
{
|
|
INT32 Range;
|
|
int iAttribute;
|
|
|
|
if (!Value ||
|
|
((iAttribute = ATIMach64FindPortAttribute(pATI, AttributeID)) < 0) ||
|
|
!ATIMach64AttributeInfo[iAttribute].GetAttribute)
|
|
return BadMatch;
|
|
|
|
*Value = (*ATIMach64AttributeInfo[iAttribute].GetAttribute)(pATI);
|
|
|
|
Range = ATIMach64Attribute[iAttribute].max_value -
|
|
ATIMach64Attribute[iAttribute].min_value;
|
|
|
|
if (Range >= 0)
|
|
{
|
|
if (Range != ATIMach64AttributeInfo[iAttribute].MaxValue)
|
|
{
|
|
/* (Un-)scale the value */
|
|
if (Range > 0)
|
|
*Value *= Range;
|
|
if (ATIMach64AttributeInfo[iAttribute].MaxValue > 0)
|
|
*Value /= ATIMach64AttributeInfo[iAttribute].MaxValue;
|
|
}
|
|
|
|
*Value += ATIMach64Attribute[iAttribute].min_value;
|
|
}
|
|
|
|
return Success;
|
|
}
|
|
|
|
static pointer
|
|
ATIMach64XVMemAlloc
|
|
(
|
|
ScreenPtr pScreen,
|
|
pointer pVideo,
|
|
int size,
|
|
int *offset,
|
|
ATIPtr pATI
|
|
);
|
|
|
|
static void
|
|
ATIMach64XVMemFree
|
|
(
|
|
ScreenPtr pScreen,
|
|
pointer pVideo,
|
|
ATIPtr pATI
|
|
);
|
|
|
|
#ifdef USE_XAA
|
|
/*
|
|
* ATIMach64RemoveLinearCallback --
|
|
*
|
|
* This is called by the framebuffer manager to release the offscreen XVideo
|
|
* buffer after the video has been temporarily disabled due to its window being
|
|
* iconified or completely occluded.
|
|
*/
|
|
static void
|
|
ATIMach64RemoveLinearCallback
|
|
(
|
|
FBLinearPtr pLinear
|
|
)
|
|
{
|
|
ATIPtr pATI = ATIPTR(xf86Screens[pLinear->pScreen->myNum]);
|
|
|
|
pATI->pXVBuffer = NULL;
|
|
outf(OVERLAY_SCALE_CNTL, SCALE_EN);
|
|
}
|
|
#endif /* USE_XAA */
|
|
|
|
/*
|
|
* ATIMach64StopVideo --
|
|
*
|
|
* This is called to stop displaying a video. Note that, to prevent jittering
|
|
* this doesn't actually turn off the overlay unless 'Cleanup' is TRUE, i.e.
|
|
* when the video is to be actually stopped rather than temporarily disabled.
|
|
*/
|
|
static void
|
|
ATIMach64StopVideo
|
|
(
|
|
ScrnInfoPtr pScreenInfo,
|
|
pointer Data,
|
|
Bool Cleanup
|
|
)
|
|
{
|
|
ScreenPtr pScreen = pScreenInfo->pScreen;
|
|
ATIPtr pATI = Data;
|
|
|
|
if (pATI->ActiveSurface)
|
|
return;
|
|
|
|
REGION_EMPTY(pScreen, &pATI->VideoClip);
|
|
|
|
#ifdef USE_XAA
|
|
if (!pATI->useEXA && !Cleanup)
|
|
{
|
|
/*
|
|
* Free offscreen buffer if/when its allocation is needed by XAA's
|
|
* pixmap cache.
|
|
*/
|
|
FBLinearPtr linear = (FBLinearPtr)pATI->pXVBuffer;
|
|
if (linear)
|
|
linear->RemoveLinearCallback =
|
|
ATIMach64RemoveLinearCallback;
|
|
return;
|
|
}
|
|
#endif /* USE_XAA */
|
|
|
|
ATIMach64XVMemFree(pScreen, pATI->pXVBuffer, pATI);
|
|
pATI->pXVBuffer = NULL;
|
|
outf(OVERLAY_SCALE_CNTL, SCALE_EN);
|
|
}
|
|
|
|
/*
|
|
* ATIMach64QueryBestSize --
|
|
*
|
|
* Quoting XVideo docs:
|
|
*
|
|
* This function provides the client with a way to query what the destination
|
|
* dimensions would end up being if they were to request that an area
|
|
* VideoWidth by VideoHeight from the video stream be scaled to rectangle of
|
|
* DrawableWidth by DrawableHeight on the screen. Since it is not expected
|
|
* that all hardware will be able to get the target dimensions exactly, it is
|
|
* important that the driver provide this function.
|
|
*/
|
|
static void
|
|
ATIMach64QueryBestSize
|
|
(
|
|
ScrnInfoPtr pScreenInfo,
|
|
Bool Motion,
|
|
short VideoWidth,
|
|
short VideoHeight,
|
|
short DrawableWidth,
|
|
short DrawableHeight,
|
|
unsigned int *Width,
|
|
unsigned int *Height,
|
|
pointer pATI
|
|
)
|
|
{
|
|
*Width = DrawableWidth;
|
|
*Height = DrawableHeight;
|
|
}
|
|
|
|
/*
|
|
* ATIMach64QueryImageAttributes --
|
|
*
|
|
* Quoting XVideo docs:
|
|
*
|
|
* This function is called to let the driver specify how data for a particular
|
|
* image of size Width by Height should be stored. Sometimes only the size and
|
|
* corrected width and height are needed. In that case pitches and offsets are
|
|
* NULL. The size of the memory required for the image is returned by this
|
|
* function. The width and height of the requested image can be altered by the
|
|
* driver to reflect format limitations (such as component sampling periods
|
|
* that are larger than one). If pPitch and pOffset are not NULL, these will
|
|
* be arrays with as many elements in them as there are planes in the image
|
|
* format. The driver should specify the pitch (in bytes) of each scanline in
|
|
* the particular plane as well as the offset to that plane (in bytes) from the
|
|
* beginning of the image.
|
|
*/
|
|
static int
|
|
ATIMach64QueryImageAttributes
|
|
(
|
|
ScrnInfoPtr pScreenInfo,
|
|
int ImageID,
|
|
unsigned short *Width,
|
|
unsigned short *Height,
|
|
int *pPitch,
|
|
int *pOffset
|
|
)
|
|
{
|
|
int Size, tmp;
|
|
|
|
if (!Width || !Height)
|
|
return 0;
|
|
|
|
if (*Width > 2048)
|
|
*Width = 2048;
|
|
else
|
|
*Width = (*Width + 1) & ~1;
|
|
|
|
if (*Height > 2048)
|
|
*Height = 2048;
|
|
|
|
if (pOffset)
|
|
pOffset[0] = 0;
|
|
|
|
switch (ImageID)
|
|
{
|
|
case FOURCC_YV12:
|
|
case FOURCC_I420:
|
|
*Height = (*Height + 1) & ~1;
|
|
Size = (*Width + 3) & ~3;
|
|
if (pPitch)
|
|
pPitch[0] = Size;
|
|
Size *= *Height;
|
|
if (pOffset)
|
|
pOffset[1] = Size;
|
|
tmp = ((*Width >> 1) + 3) & ~3;
|
|
if (pPitch)
|
|
pPitch[1] = pPitch[2] = tmp;
|
|
tmp *= (*Height >> 1);
|
|
Size += tmp;
|
|
if (pOffset)
|
|
pOffset[2] = Size;
|
|
Size += tmp;
|
|
break;
|
|
|
|
case FOURCC_UYVY:
|
|
case FOURCC_YUY2:
|
|
Size = *Width << 1;
|
|
if (pPitch)
|
|
pPitch[0] = Size;
|
|
Size *= *Height;
|
|
break;
|
|
|
|
default:
|
|
Size = 0;
|
|
break;
|
|
}
|
|
|
|
return Size;
|
|
}
|
|
|
|
/*
|
|
* ATIMach64ScaleVideo --
|
|
*
|
|
* This function is called to calculate overlay scaling factors.
|
|
*/
|
|
static void
|
|
ATIMach64ScaleVideo
|
|
(
|
|
ATIPtr pATI,
|
|
DisplayModePtr pMode,
|
|
int SrcW,
|
|
int SrcH,
|
|
int DstW,
|
|
int DstH,
|
|
CARD32 *pHScale,
|
|
CARD32 *pVScale
|
|
)
|
|
{
|
|
int Shift;
|
|
|
|
*pHScale = ATIDivide(SrcW, DstW,
|
|
GetBits(pATI->NewHW.pll_vclk_cntl, PLL_ECP_DIV) + 12, 0);
|
|
|
|
Shift = 12;
|
|
if (pMode->Flags & V_INTERLACE)
|
|
Shift++;
|
|
|
|
if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
|
|
{
|
|
if (pMode->VDisplay < pATI->LCDVertical)
|
|
{
|
|
SrcH *= pMode->VDisplay;
|
|
DstH *= pATI->LCDVertical;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pMode->Flags & V_DBLSCAN)
|
|
Shift--;
|
|
if (pMode->VScan > 1)
|
|
DstH *= pMode->VScan;
|
|
}
|
|
|
|
*pVScale = ATIDivide(SrcH, DstH, Shift, 0);
|
|
}
|
|
|
|
/*
|
|
* ATIMach64ClipVideo --
|
|
*
|
|
* Clip the video (both source and destination) and make various other
|
|
* adjustments.
|
|
*/
|
|
static Bool
|
|
ATIMach64ClipVideo
|
|
(
|
|
ScrnInfoPtr pScreenInfo,
|
|
ATIPtr pATI,
|
|
int ImageID,
|
|
short SrcX,
|
|
short SrcY,
|
|
short SrcW,
|
|
short SrcH,
|
|
short DstX,
|
|
short DstY,
|
|
short *DstW,
|
|
short *DstH,
|
|
short Width,
|
|
short Height,
|
|
RegionPtr pClip,
|
|
BoxPtr pDstBox,
|
|
INT32 *SrcX1,
|
|
INT32 *SrcX2,
|
|
INT32 *SrcY1,
|
|
INT32 *SrcY2,
|
|
int *SrcLeft,
|
|
int *SrcTop
|
|
)
|
|
{
|
|
CARD32 HScale, VScale;
|
|
|
|
/* Check hardware limits */
|
|
if ((Height <= 0) || (Height > 2048) || (Width <= 0) || (Width > 720) ||
|
|
((Width > 384) && (pATI->Chip < ATI_CHIP_264VTB)))
|
|
return FALSE;
|
|
|
|
ATIMach64ScaleVideo(pATI, pScreenInfo->currentMode,
|
|
SrcW, SrcH, *DstW, *DstH, &HScale, &VScale);
|
|
if (!HScale || !VScale)
|
|
return FALSE;
|
|
if (HScale > MaxScale)
|
|
*DstW = (*DstW * HScale) / MaxScale;
|
|
if (VScale > MaxScale)
|
|
*DstH = (*DstH * HScale) / MaxScale;
|
|
|
|
/* Clip both the source and the destination */
|
|
*SrcX1 = SrcX;
|
|
*SrcX2 = SrcX + SrcW;
|
|
*SrcY1 = SrcY;
|
|
*SrcY2 = SrcY + SrcH;
|
|
|
|
pDstBox->x1 = DstX;
|
|
pDstBox->x2 = DstX + *DstW;
|
|
pDstBox->y1 = DstY;
|
|
pDstBox->y2 = DstY + *DstH;
|
|
|
|
if (!xf86XVClipVideoHelper(pDstBox, SrcX1, SrcX2, SrcY1, SrcY2,
|
|
pClip, Width, Height))
|
|
return FALSE;
|
|
|
|
/*
|
|
* Reset overlay scaler origin. This prevents jittering during
|
|
* viewport panning or while the video is being moved or gradually
|
|
* obscured/unobscured.
|
|
*/
|
|
pDstBox->x1 = DstX;
|
|
pDstBox->y1 = DstY;
|
|
|
|
/* Translate to the current viewport */
|
|
pDstBox->x1 -= pScreenInfo->frameX0;
|
|
pDstBox->x2 -= pScreenInfo->frameX0;
|
|
pDstBox->y1 -= pScreenInfo->frameY0;
|
|
pDstBox->y2 -= pScreenInfo->frameY0;
|
|
|
|
*SrcLeft = *SrcTop = 0;
|
|
|
|
/*
|
|
* If the overlay scaler origin ends up outside the current viewport, move
|
|
* it to the viewport's top left corner. This unavoidably causes a slight
|
|
* jittering in the image (even with double-buffering).
|
|
*/
|
|
if (pDstBox->x1 < 0)
|
|
{
|
|
*SrcLeft = ((-pDstBox->x1 * SrcW) / *DstW) & ~1;
|
|
pDstBox->x1 = 0;
|
|
}
|
|
|
|
if (pDstBox->y1 < 0)
|
|
{
|
|
*SrcTop = (-pDstBox->y1 * SrcH) / *DstH;
|
|
pDstBox->y1 = 0;
|
|
|
|
switch (ImageID)
|
|
{
|
|
case FOURCC_YV12:
|
|
case FOURCC_I420:
|
|
*SrcTop = (*SrcTop + 1) & ~1;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef ATIMove32
|
|
|
|
/* A faster intercept */
|
|
#undef xf86XVCopyPacked
|
|
#define xf86XVCopyPacked ATIMach64XVCopyPacked
|
|
|
|
static void
|
|
ATIMach64XVCopyPacked
|
|
(
|
|
const CARD8 *pSrc,
|
|
CARD8 *pDst,
|
|
int SrcPitch,
|
|
int DstPitch,
|
|
int Height,
|
|
int Width
|
|
)
|
|
{
|
|
Width >>= 1;
|
|
while (--Height >= 0)
|
|
{
|
|
ATIMove32(pDst, pSrc, Width);
|
|
pSrc += SrcPitch;
|
|
pDst += DstPitch;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
* ATIMach64DisplayVideo --
|
|
*
|
|
* This function programmes Mach64 registers needed to display a video.
|
|
*/
|
|
static void
|
|
ATIMach64DisplayVideo
|
|
(
|
|
ScrnInfoPtr pScreenInfo,
|
|
ATIPtr pATI,
|
|
BoxPtr pDstBox,
|
|
int ImageID,
|
|
int Offset,
|
|
int Pitch,
|
|
short SrcW,
|
|
short SrcH,
|
|
short DstW,
|
|
short DstH,
|
|
short Width,
|
|
short Height
|
|
)
|
|
{
|
|
DisplayModePtr pMode = pScreenInfo->currentMode;
|
|
CARD32 HScale, VScale;
|
|
|
|
if (pMode->VScan > 1)
|
|
{
|
|
pDstBox->y1 *= pMode->VScan;
|
|
pDstBox->y2 *= pMode->VScan;
|
|
}
|
|
if (pMode->Flags & V_DBLSCAN)
|
|
{
|
|
pDstBox->y1 <<= 1;
|
|
pDstBox->y2 <<= 1;
|
|
}
|
|
|
|
/* Recalculate overlay scale factors */
|
|
ATIMach64ScaleVideo(pATI, pMode, SrcW, SrcH, DstW, DstH, &HScale, &VScale);
|
|
|
|
pATI->NewHW.video_format &= ~SCALER_IN;
|
|
if (ImageID == FOURCC_UYVY)
|
|
pATI->NewHW.video_format |= SCALER_IN_YVYU422;
|
|
else
|
|
pATI->NewHW.video_format |= SCALER_IN_VYUY422;
|
|
|
|
ATIMach64WaitForFIFO(pATI, 8);
|
|
outq(OVERLAY_Y_X_START, OVERLAY_Y_X_END, OVERLAY_LOCK_START |
|
|
SetWord(pDstBox->x1, 1) | SetWord(pDstBox->y1, 0),
|
|
SetWord(pDstBox->x2 - 1, 1) | SetWord(pDstBox->y2 - 1, 0));
|
|
outf(OVERLAY_SCALE_INC, SetWord(HScale, 1) | SetWord(VScale, 0));
|
|
outf(SCALER_HEIGHT_WIDTH, SetWord(Width, 1) | SetWord(Height, 0));
|
|
outf(VIDEO_FORMAT, pATI->NewHW.video_format);
|
|
|
|
if (pATI->Chip < ATI_CHIP_264VTB)
|
|
{
|
|
outf(BUF0_OFFSET, Offset);
|
|
outf(BUF0_PITCH, Pitch);
|
|
}
|
|
else
|
|
{
|
|
outf(SCALER_BUF0_OFFSET, Offset);
|
|
outf(SCALER_BUF_PITCH, Pitch);
|
|
}
|
|
|
|
outf(OVERLAY_SCALE_CNTL, SCALE_PIX_EXPAND | OVERLAY_EN | SCALE_EN);
|
|
}
|
|
|
|
/*
|
|
* ATIMach64PutImage --
|
|
*
|
|
* This function is called to put a video image on the screen.
|
|
*/
|
|
static int
|
|
ATIMach64PutImage
|
|
(
|
|
ScrnInfoPtr pScreenInfo,
|
|
short SrcX,
|
|
short SrcY,
|
|
short DstX,
|
|
short DstY,
|
|
short SrcW,
|
|
short SrcH,
|
|
short DstW,
|
|
short DstH,
|
|
int ImageID,
|
|
unsigned char *Buffer,
|
|
short Width,
|
|
short Height,
|
|
Bool Synchronise,
|
|
RegionPtr pClip,
|
|
pointer Data,
|
|
DrawablePtr pDraw
|
|
)
|
|
{
|
|
ATIPtr pATI = Data;
|
|
ScreenPtr pScreen;
|
|
INT32 SrcX1, SrcX2, SrcY1, SrcY2;
|
|
BoxRec DstBox;
|
|
int SrcPitch, SrcPitchUV, DstPitch, DstSize;
|
|
int SrcTop, SrcLeft, DstWidth, DstHeight;
|
|
int Top, Bottom, Left, Right, nLine, nPixel, Offset;
|
|
int OffsetV, OffsetU;
|
|
int XVOffset;
|
|
int tmp;
|
|
CARD8 *pDst;
|
|
|
|
if (pATI->ActiveSurface)
|
|
return Success;
|
|
|
|
if (!ATIMach64ClipVideo(pScreenInfo, pATI, ImageID,
|
|
SrcX, SrcY, SrcW, SrcH,
|
|
DstX, DstY, &DstW, &DstH,
|
|
Width, Height, pClip, &DstBox,
|
|
&SrcX1, &SrcX2, &SrcY1, &SrcY2,
|
|
&SrcLeft, &SrcTop))
|
|
return Success;
|
|
|
|
pScreen = pScreenInfo->pScreen;
|
|
|
|
DstWidth = Width - SrcLeft;
|
|
DstHeight = Height - SrcTop;
|
|
|
|
/*
|
|
* Allocate an offscreen buffer for the entire source, even though only a
|
|
* subset of the source will be copied into it.
|
|
*/
|
|
DstPitch = /* bytes */
|
|
(DstWidth + DstWidth + 15) & ~15;
|
|
DstSize = /* bytes */
|
|
(DstPitch * DstHeight);
|
|
|
|
pATI->pXVBuffer = ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer,
|
|
(pATI->DoubleBuffer + 1) * DstSize, &XVOffset, pATI);
|
|
|
|
if (!pATI->pXVBuffer)
|
|
{
|
|
if (!pATI->DoubleBuffer)
|
|
return BadAlloc;
|
|
|
|
pATI->pXVBuffer =
|
|
ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer, DstSize, &XVOffset, pATI);
|
|
|
|
if (!pATI->pXVBuffer)
|
|
return BadAlloc;
|
|
|
|
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
|
|
"Video image double-buffering downgraded to single-buffering\n due"
|
|
" to insufficient video memory.\n");
|
|
pATI->DoubleBuffer = pATI->CurrentBuffer = 0;
|
|
}
|
|
else
|
|
{
|
|
/* Possibly switch buffers */
|
|
pATI->CurrentBuffer = pATI->DoubleBuffer - pATI->CurrentBuffer;
|
|
}
|
|
|
|
/* Synchronise video memory accesses */
|
|
ATIMach64Sync(pScreenInfo);
|
|
|
|
Offset = XVOffset + pATI->CurrentBuffer * DstSize;
|
|
pDst = pATI->pMemoryLE;
|
|
pDst += Offset;
|
|
|
|
switch (ImageID)
|
|
{
|
|
case FOURCC_YV12:
|
|
case FOURCC_I420:
|
|
Left = (SrcX1 >> 16) & ~1;
|
|
Right = ((SrcX2 + 0x1FFFF) >> 16) & ~1;
|
|
Top = (SrcY1 >> 16) & ~1;
|
|
Bottom = ((SrcY2 + 0x1FFFF) >> 16) & ~1;
|
|
|
|
if ((Right < Width) && ((SrcX1 & 0x1FFFF) <= (SrcX2 & 0x1FFFF)))
|
|
Right += 2;
|
|
if ((Bottom < Height) && ((SrcY1 & 0x1FFFF) <= (SrcY2 & 0x1FFFF)))
|
|
Bottom += 2;
|
|
|
|
nPixel = Right - Left;
|
|
nLine = Bottom - Top;
|
|
|
|
SrcPitch = (Width + 3) & ~3;
|
|
OffsetV = SrcPitch * Height;
|
|
SrcPitchUV = ((Width >> 1) + 3) & ~3;
|
|
OffsetU = ((Height >> 1) * SrcPitchUV) + OffsetV;
|
|
|
|
tmp = ((Top >> 1) * SrcPitchUV) + (Left >> 1);
|
|
OffsetV += tmp;
|
|
OffsetU += tmp;
|
|
|
|
if (ImageID == FOURCC_I420)
|
|
{
|
|
tmp = OffsetV;
|
|
OffsetV = OffsetU;
|
|
OffsetU = tmp;
|
|
}
|
|
|
|
pDst += ((Top - SrcTop) * DstPitch) + ((Left - SrcLeft) << 1);
|
|
|
|
xf86XVCopyYUV12ToPacked(Buffer + (Top * SrcPitch) + Left,
|
|
Buffer + OffsetV, Buffer + OffsetU, pDst, SrcPitch, SrcPitchUV,
|
|
DstPitch, nLine, nPixel);
|
|
break;
|
|
|
|
case FOURCC_UYVY:
|
|
case FOURCC_YUY2:
|
|
default:
|
|
Left = (SrcX1 >> 16) & ~1;
|
|
Right = ((SrcX2 + 0x1FFFF) >> 16) & ~1;
|
|
Top = SrcY1 >> 16;
|
|
Bottom = (SrcY2 + 0x0FFFF) >> 16;
|
|
|
|
if ((Right < Width) && ((SrcX1 & 0x1FFFF) <= (SrcX2 & 0x1FFFF)))
|
|
Right += 2;
|
|
if ((Bottom < Height) && ((SrcY1 & 0x0FFFF) <= (SrcY2 & 0x0FFFF)))
|
|
Bottom++;
|
|
|
|
nPixel = Right - Left;
|
|
nLine = Bottom - Top;
|
|
|
|
SrcPitch = Width << 1;
|
|
Buffer += (Top * SrcPitch) + (Left << 1);
|
|
pDst += ((Top - SrcTop) * DstPitch) + ((Left - SrcLeft) << 1);
|
|
|
|
xf86XVCopyPacked(Buffer, pDst, SrcPitch, DstPitch, nLine, nPixel);
|
|
break;
|
|
}
|
|
|
|
if (!REGION_EQUAL(pScreen, &pATI->VideoClip, pClip))
|
|
{
|
|
REGION_COPY(pScreen, &pATI->VideoClip, pClip);
|
|
if (pATI->AutoPaint)
|
|
xf86XVFillKeyHelper(pScreen, pATI->NewHW.overlay_graphics_key_clr,
|
|
pClip);
|
|
}
|
|
|
|
ATIMach64DisplayVideo(pScreenInfo, pATI, &DstBox, ImageID,
|
|
Offset, DstPitch / 2, SrcW, SrcH, DstW, DstH, DstWidth, DstHeight);
|
|
|
|
return Success;
|
|
}
|
|
|
|
/*
|
|
* ATIMach64AllocateSurface --
|
|
*
|
|
* This function allocates an offscreen buffer (called a "surface") for use by
|
|
* an external driver such as 'v4l'.
|
|
*/
|
|
static int
|
|
ATIMach64AllocateSurface
|
|
(
|
|
ScrnInfoPtr pScreenInfo,
|
|
int ImageID,
|
|
unsigned short Width,
|
|
unsigned short Height,
|
|
XF86SurfacePtr pSurface
|
|
)
|
|
{
|
|
ScreenPtr pScreen;
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
int XVOffset;
|
|
|
|
if (pATI->ActiveSurface)
|
|
return BadAlloc;
|
|
|
|
if ((Height <= 0) || (Height > 2048) || (Width <= 0) || (Width > 720) ||
|
|
((Width > 384) && (pATI->Chip < ATI_CHIP_264VTB)))
|
|
return BadValue;
|
|
|
|
Width = (Width + 1) & ~1;
|
|
pATI->SurfacePitch = ((Width << 1) + 15) & ~15;
|
|
|
|
pScreen = pScreenInfo->pScreen;
|
|
|
|
pATI->pXVBuffer = ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer,
|
|
Height * pATI->SurfacePitch, &XVOffset, pATI);
|
|
if (!pATI->pXVBuffer)
|
|
return BadAlloc;
|
|
|
|
pATI->SurfaceOffset = XVOffset;
|
|
|
|
pSurface->pScrn = pScreenInfo;
|
|
pSurface->id = ImageID;
|
|
pSurface->width = Width;
|
|
pSurface->height = Height;
|
|
pSurface->pitches = &pATI->SurfacePitch;
|
|
pSurface->offsets = &pATI->SurfaceOffset;
|
|
pSurface->devPrivate.ptr = pATI;
|
|
|
|
/* Stop the video */
|
|
outf(OVERLAY_SCALE_CNTL, SCALE_EN);
|
|
REGION_EMPTY(pScreen, &pATI->VideoClip);
|
|
pATI->ActiveSurface = TRUE;
|
|
|
|
return Success;
|
|
}
|
|
|
|
/*
|
|
* ATIMach64FreeSurface --
|
|
*
|
|
* This function called to free a surface's offscreen buffer.
|
|
*/
|
|
static int
|
|
ATIMach64FreeSurface
|
|
(
|
|
XF86SurfacePtr pSurface
|
|
)
|
|
{
|
|
ATIPtr pATI = pSurface->devPrivate.ptr;
|
|
|
|
if (!pATI->ActiveSurface)
|
|
return Success;
|
|
|
|
outf(OVERLAY_SCALE_CNTL, SCALE_EN);
|
|
ATIMach64XVMemFree(pSurface->pScrn->pScreen, pATI->pXVBuffer, pATI);
|
|
pATI->pXVBuffer = NULL;
|
|
pATI->ActiveSurface = FALSE;
|
|
|
|
return Success;
|
|
}
|
|
|
|
/*
|
|
* ATIMach64DisplaySurface --
|
|
*
|
|
* This function is called to display a video surface.
|
|
*/
|
|
static int
|
|
ATIMach64DisplaySurface
|
|
(
|
|
XF86SurfacePtr pSurface,
|
|
short SrcX,
|
|
short SrcY,
|
|
short DstX,
|
|
short DstY,
|
|
short SrcW,
|
|
short SrcH,
|
|
short DstW,
|
|
short DstH,
|
|
RegionPtr pClip
|
|
)
|
|
{
|
|
ATIPtr pATI = pSurface->devPrivate.ptr;
|
|
ScrnInfoPtr pScreenInfo;
|
|
int ImageID;
|
|
short Width, Height;
|
|
BoxRec DstBox;
|
|
INT32 SrcX1, SrcX2, SrcY1, SrcY2;
|
|
int SrcLeft, SrcTop, SrcPitch, Offset;
|
|
|
|
if (!pATI->ActiveSurface)
|
|
return Success;
|
|
|
|
pScreenInfo = pSurface->pScrn;
|
|
ImageID = pSurface->id;
|
|
Width = pSurface->width;
|
|
Height = pSurface->height;
|
|
|
|
if (!ATIMach64ClipVideo(pScreenInfo, pATI, ImageID,
|
|
SrcX, SrcY, SrcW, SrcH,
|
|
DstX, DstY, &DstW, &DstH,
|
|
Width, Height, pClip, &DstBox,
|
|
&SrcX1, &SrcX2, &SrcY1, &SrcY2,
|
|
&SrcLeft, &SrcTop))
|
|
return Success;
|
|
|
|
xf86XVFillKeyHelper(pScreenInfo->pScreen,
|
|
pATI->NewHW.overlay_graphics_key_clr, pClip);
|
|
|
|
SrcPitch = pSurface->pitches[0];
|
|
Offset = pSurface->offsets[0] + (SrcTop * SrcPitch) + (SrcLeft << 1);
|
|
ATIMach64DisplayVideo(pScreenInfo, pATI, &DstBox, ImageID,
|
|
Offset, SrcPitch, SrcW, SrcH, DstW, DstH, Width, Height);
|
|
|
|
return Success;
|
|
}
|
|
|
|
/*
|
|
* ATIMach64StopSurface --
|
|
*
|
|
* This function is called to stop the overlaid display of a video surface.
|
|
*/
|
|
static int
|
|
ATIMach64StopSurface
|
|
(
|
|
XF86SurfacePtr pSurface
|
|
)
|
|
{
|
|
ATIPtr pATI = pSurface->devPrivate.ptr;
|
|
|
|
if (pATI->ActiveSurface)
|
|
outf(OVERLAY_SCALE_CNTL, SCALE_EN);
|
|
|
|
return Success;
|
|
}
|
|
|
|
/*
|
|
* ATIMach64GetSurfaceAttribute --
|
|
*
|
|
* Retrieve the value of an XVideo attribute.
|
|
*/
|
|
static int
|
|
ATIMach64GetSurfaceAttribute
|
|
(
|
|
ScrnInfoPtr pScreenInfo,
|
|
Atom AttributeID,
|
|
INT32 *Value
|
|
)
|
|
{
|
|
return ATIMach64GetPortAttribute(pScreenInfo, AttributeID, Value,
|
|
ATIPTR(pScreenInfo));
|
|
}
|
|
|
|
/*
|
|
* ATIMach64SetSurfaceAttribute
|
|
*
|
|
* Set the value of an XVideo attribute.
|
|
*/
|
|
static int
|
|
ATIMach64SetSurfaceAttribute
|
|
(
|
|
ScrnInfoPtr pScreenInfo,
|
|
Atom AttributeID,
|
|
INT32 Value
|
|
)
|
|
{
|
|
return ATIMach64SetPortAttribute(pScreenInfo, AttributeID, Value,
|
|
ATIPTR(pScreenInfo));
|
|
}
|
|
|
|
/* XVideo surface registration data */
|
|
static XF86OffscreenImageRec ATIMach64Surface_A[] =
|
|
{
|
|
{
|
|
&ATIMach64Image[0], /* YUY2 */
|
|
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
|
|
ATIMach64AllocateSurface,
|
|
ATIMach64FreeSurface,
|
|
ATIMach64DisplaySurface,
|
|
ATIMach64StopSurface,
|
|
ATIMach64GetSurfaceAttribute,
|
|
ATIMach64SetSurfaceAttribute,
|
|
384, 2048,
|
|
nATIMach64Attribute - 5, /* No double-buffering */
|
|
ATIMach64Attribute + 4 /* No saturation nor brightness */
|
|
},
|
|
{
|
|
&ATIMach64Image[1], /* UYVY */
|
|
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
|
|
ATIMach64AllocateSurface,
|
|
ATIMach64FreeSurface,
|
|
ATIMach64DisplaySurface,
|
|
ATIMach64StopSurface,
|
|
ATIMach64GetSurfaceAttribute,
|
|
ATIMach64SetSurfaceAttribute,
|
|
384, 2048,
|
|
nATIMach64Attribute - 5, /* No double-buffering */
|
|
ATIMach64Attribute + 4 /* No saturation nor brightness */
|
|
}
|
|
};
|
|
#define nATIMach64Surface_A NumberOf(ATIMach64Surface_A)
|
|
|
|
static XF86OffscreenImageRec ATIMach64Surface_B[] =
|
|
{
|
|
{
|
|
&ATIMach64Image[0], /* YUY2 */
|
|
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
|
|
ATIMach64AllocateSurface,
|
|
ATIMach64FreeSurface,
|
|
ATIMach64DisplaySurface,
|
|
ATIMach64StopSurface,
|
|
ATIMach64GetSurfaceAttribute,
|
|
ATIMach64SetSurfaceAttribute,
|
|
720, 2048,
|
|
nATIMach64Attribute - 5, /* No double-buffering */
|
|
ATIMach64Attribute + 4 /* No saturation nor brightness */
|
|
},
|
|
{
|
|
&ATIMach64Image[1], /* UYVY */
|
|
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
|
|
ATIMach64AllocateSurface,
|
|
ATIMach64FreeSurface,
|
|
ATIMach64DisplaySurface,
|
|
ATIMach64StopSurface,
|
|
ATIMach64GetSurfaceAttribute,
|
|
ATIMach64SetSurfaceAttribute,
|
|
720, 2048,
|
|
nATIMach64Attribute - 5, /* No double-buffering */
|
|
ATIMach64Attribute + 4 /* No saturation nor brightness */
|
|
}
|
|
};
|
|
#define nATIMach64Surface_B NumberOf(ATIMach64Surface_B)
|
|
|
|
static XF86OffscreenImageRec ATIMach64Surface_C[] =
|
|
{
|
|
{
|
|
&ATIMach64Image[0], /* YUY2 */
|
|
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
|
|
ATIMach64AllocateSurface,
|
|
ATIMach64FreeSurface,
|
|
ATIMach64DisplaySurface,
|
|
ATIMach64StopSurface,
|
|
ATIMach64GetSurfaceAttribute,
|
|
ATIMach64SetSurfaceAttribute,
|
|
720, 2048,
|
|
nATIMach64Attribute - 1, /* No double-buffering */
|
|
ATIMach64Attribute
|
|
},
|
|
{
|
|
&ATIMach64Image[1], /* UYVY */
|
|
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
|
|
ATIMach64AllocateSurface,
|
|
ATIMach64FreeSurface,
|
|
ATIMach64DisplaySurface,
|
|
ATIMach64StopSurface,
|
|
ATIMach64GetSurfaceAttribute,
|
|
ATIMach64SetSurfaceAttribute,
|
|
720, 2048,
|
|
nATIMach64Attribute - 1, /* No double-buffering */
|
|
ATIMach64Attribute
|
|
}
|
|
};
|
|
#define nATIMach64Surface_C NumberOf(ATIMach64Surface_C)
|
|
|
|
/*
|
|
* ATIMach64XVInitialiseAdaptor --
|
|
*
|
|
* This function is called to make a Mach64's hardware overlay support
|
|
* available as an XVideo adaptor.
|
|
*/
|
|
int
|
|
ATIMach64XVInitialiseAdaptor
|
|
(
|
|
ScreenPtr pScreen,
|
|
ScrnInfoPtr pScreenInfo,
|
|
ATIPtr pATI,
|
|
XF86VideoAdaptorPtr **pppAdaptor
|
|
)
|
|
{
|
|
XF86VideoAdaptorPtr pAdaptor;
|
|
int Index;
|
|
|
|
if (!pATI->Block1Base)
|
|
return 0;
|
|
|
|
if (!(pAdaptor = xf86XVAllocateVideoAdaptorRec(pScreenInfo)))
|
|
return 0;
|
|
|
|
*pppAdaptor = xnfalloc(sizeof(pAdaptor));
|
|
**pppAdaptor = pAdaptor;
|
|
|
|
pAdaptor->nPorts = 1;
|
|
pAdaptor->pPortPrivates = pATI->XVPortPrivate;
|
|
pATI->XVPortPrivate[0].ptr = pATI;
|
|
|
|
pAdaptor->type = XvInputMask | XvImageMask | XvWindowMask;
|
|
pAdaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
|
|
pAdaptor->name = "ATI Mach64 Back-end Overlay Scaler";
|
|
|
|
if (pATI->Chip < ATI_CHIP_264VTB)
|
|
{
|
|
pAdaptor->nEncodings = nATIMach64VideoEncoding_A;
|
|
pAdaptor->pEncodings = ATIMach64VideoEncoding_A;
|
|
}
|
|
else
|
|
{
|
|
pAdaptor->nEncodings = nATIMach64VideoEncoding_B;
|
|
pAdaptor->pEncodings = ATIMach64VideoEncoding_B;
|
|
}
|
|
|
|
pAdaptor->nFormats = nATIMach64VideoFormat;
|
|
pAdaptor->pFormats = ATIMach64VideoFormat;
|
|
|
|
pAdaptor->nAttributes = nATIMach64Attribute;
|
|
pAdaptor->pAttributes = ATIMach64Attribute;
|
|
|
|
if (pATI->Chip < ATI_CHIP_264GTPRO)
|
|
{
|
|
/* Older controllers don't have brightness or saturation controls */
|
|
pAdaptor->nAttributes -= 4;
|
|
pAdaptor->pAttributes += 4;
|
|
}
|
|
|
|
pAdaptor->nImages = nATIMach64Image;
|
|
pAdaptor->pImages = ATIMach64Image;
|
|
|
|
pAdaptor->StopVideo = ATIMach64StopVideo;
|
|
pAdaptor->SetPortAttribute = ATIMach64SetPortAttribute;
|
|
pAdaptor->GetPortAttribute = ATIMach64GetPortAttribute;
|
|
pAdaptor->QueryBestSize = ATIMach64QueryBestSize;
|
|
pAdaptor->PutImage = ATIMach64PutImage;
|
|
pAdaptor->QueryImageAttributes = ATIMach64QueryImageAttributes;
|
|
|
|
REGION_NULL(pScreen, &pATI->VideoClip);
|
|
pATI->ActiveSurface = FALSE;
|
|
|
|
if (ATIMach64XVAtomGeneration != serverGeneration)
|
|
{
|
|
/* Refresh static data */
|
|
ATIMach64XVAtomGeneration = serverGeneration;
|
|
|
|
Index = nATIMach64Attribute - pAdaptor->nAttributes;
|
|
for (; Index < nATIMach64Attribute; Index++)
|
|
ATIMach64AttributeInfo[Index].AttributeID =
|
|
MAKE_ATOM(ATIMach64Attribute[Index].name);
|
|
}
|
|
|
|
ATIMach64SetDefaultAttributes(pATI, 0);
|
|
|
|
if (pATI->Chip < ATI_CHIP_264VTB)
|
|
{
|
|
xf86XVRegisterOffscreenImages(pScreen,
|
|
ATIMach64Surface_A, nATIMach64Surface_A);
|
|
}
|
|
else if (pATI->Chip < ATI_CHIP_264GTPRO)
|
|
{
|
|
xf86XVRegisterOffscreenImages(pScreen,
|
|
ATIMach64Surface_B, nATIMach64Surface_B);
|
|
}
|
|
else
|
|
{
|
|
xf86XVRegisterOffscreenImages(pScreen,
|
|
ATIMach64Surface_C, nATIMach64Surface_C);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* ATIMach64CloseXVideo --
|
|
*
|
|
* This function is called during screen termination to clean up after
|
|
* initialisation of Mach64 XVideo support.
|
|
*/
|
|
void
|
|
ATIMach64CloseXVideo
|
|
(
|
|
ScreenPtr pScreen,
|
|
ScrnInfoPtr pScreenInfo,
|
|
ATIPtr pATI
|
|
)
|
|
{
|
|
ATIMach64StopVideo(pScreenInfo, pATI, TRUE);
|
|
|
|
REGION_UNINIT(pScreen, &pATI->VideoClip);
|
|
}
|
|
|
|
static pointer
|
|
ATIMach64XVMemAlloc
|
|
(
|
|
ScreenPtr pScreen,
|
|
pointer pVideo,
|
|
int size,
|
|
int *offset,
|
|
ATIPtr pATI
|
|
)
|
|
{
|
|
#ifdef USE_EXA
|
|
if (pATI->useEXA) {
|
|
ExaOffscreenArea *area = (ExaOffscreenArea *)pVideo;
|
|
|
|
if (area != NULL) {
|
|
if (area->size >= size) {
|
|
*offset = area->offset;
|
|
return area;
|
|
}
|
|
|
|
exaOffscreenFree(pScreen, area);
|
|
}
|
|
|
|
area = exaOffscreenAlloc(pScreen, size, 64, TRUE, NULL, NULL);
|
|
if (area != NULL) {
|
|
*offset = area->offset;
|
|
return area;
|
|
}
|
|
}
|
|
#endif /* USE_EXA */
|
|
|
|
#ifdef USE_XAA
|
|
if (!pATI->useEXA) {
|
|
FBLinearPtr linear = (FBLinearPtr)pVideo;
|
|
int cpp = pATI->AdjustDepth;
|
|
|
|
/* XAA allocates in units of pixels at the screen bpp, so adjust size
|
|
* appropriately.
|
|
*/
|
|
size = (size + cpp - 1) / cpp;
|
|
|
|
linear = ATIResizeOffscreenLinear(pScreen, linear, size);
|
|
if (linear != NULL) {
|
|
*offset = linear->offset * cpp;
|
|
return linear;
|
|
}
|
|
}
|
|
#endif /* USE_XAA */
|
|
|
|
*offset = 0;
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
ATIMach64XVMemFree
|
|
(
|
|
ScreenPtr pScreen,
|
|
pointer pVideo,
|
|
ATIPtr pATI
|
|
)
|
|
{
|
|
#ifdef USE_EXA
|
|
if (pATI->useEXA) {
|
|
ExaOffscreenArea *area = (ExaOffscreenArea *)pVideo;
|
|
|
|
if (area != NULL)
|
|
exaOffscreenFree(pScreen, area);
|
|
}
|
|
#endif /* USE_EXA */
|
|
|
|
#ifdef USE_XAA
|
|
if (!pATI->useEXA) {
|
|
FBLinearPtr linear = (FBLinearPtr)pVideo;
|
|
|
|
if (linear != NULL)
|
|
ATIResizeOffscreenLinear(pScreen, linear, 0);
|
|
}
|
|
#endif /* USE_XAA */
|
|
}
|
|
|