#include "radeon.h"
#include "radeon_macros.h"
#include "radeon_probe.h"
#include "radeon_reg.h"
#include "xf86.h"
#include "dixstruct.h"
#include "Xv.h"
#include "fourcc.h"
#define OFF_DELAY 250
#define FREE_DELAY 15000
#define OFF_TIMER 0x01
#define FREE_TIMER 0x02
#define CLIENT_VIDEO_ON 0x04
#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
extern int gRADEONEntityIndex;
static void RADEONInitOffscreenImages(ScreenPtr);
static XF86VideoAdaptorPtr RADEONSetupImageVideo(ScreenPtr);
static int RADEONSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
static int RADEONGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
static void RADEONStopVideo(ScrnInfoPtr, pointer, Bool);
static void RADEONQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short,
unsigned int *, unsigned int *, pointer);
static int RADEONPutImage(ScrnInfoPtr, short, short, short, short, short,
short, short, short, int, unsigned char*, short,
short, Bool, RegionPtr, pointer);
static int RADEONQueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
unsigned short *, int *, int *);
static void RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now);
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer;
static Atom xvRedIntensity, xvGreenIntensity, xvBlueIntensity;
static Atom xvContrast, xvHue, xvColor, xvAutopaintColorkey, xvSetDefaults;
typedef struct {
CARD32 transform_index;
int brightness;
int saturation;
int hue;
int contrast;
int red_intensity;
int green_intensity;
int blue_intensity;
int ecp_div;
Bool doubleBuffer;
unsigned char currentBuffer;
RegionRec clip;
CARD32 colorKey;
CARD32 videoStatus;
Time offTime;
Time freeTime;
Bool autopaint_colorkey;
} RADEONPortPrivRec, *RADEONPortPrivPtr;
#define GET_PORT_PRIVATE(pScrn) \
(RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
void RADEONInitVideo(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
XF86VideoAdaptorPtr newAdaptor = NULL;
int num_adaptors;
newAdaptor = RADEONSetupImageVideo(pScreen);
RADEONInitOffscreenImages(pScreen);
num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
if(newAdaptor) {
if(!num_adaptors) {
num_adaptors = 1;
adaptors = &newAdaptor;
} else {
newAdaptors =
xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
if(newAdaptors) {
memcpy(newAdaptors, adaptors, num_adaptors *
sizeof(XF86VideoAdaptorPtr));
newAdaptors[num_adaptors] = newAdaptor;
adaptors = newAdaptors;
num_adaptors++;
}
}
}
if(num_adaptors)
xf86XVScreenInit(pScreen, adaptors, num_adaptors);
if(newAdaptors)
xfree(newAdaptors);
}
static XF86VideoEncodingRec DummyEncoding =
{
0,
"XV_IMAGE",
2048, 2048,
{1, 1}
};
#define NUM_FORMATS 12
static XF86VideoFormatRec Formats[NUM_FORMATS] =
{
{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 NUM_ATTRIBUTES 9+3
static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
{
{XvSettable , 0, 1, "XV_SET_DEFAULTS"},
{XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
{XvSettable | XvGettable, 0, ~0, "XV_COLORKEY"},
{XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
{XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
{XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
{XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
{XvSettable | XvGettable, -1000, 1000, "XV_COLOR"},
{XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
{XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"},
{XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"},
{XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"},
};
#define NUM_IMAGES 4
static XF86ImageRec Images[NUM_IMAGES] =
{
XVIMAGE_YUY2,
XVIMAGE_UYVY,
XVIMAGE_YV12,
XVIMAGE_I420
};
typedef struct tagREF_TRANSFORM
{
float RefLuma;
float RefRCb;
float RefRCr;
float RefGCb;
float RefGCr;
float RefBCb;
float RefBCr;
} REF_TRANSFORM;
REF_TRANSFORM trans[2] =
{
{1.1678, 0.0, 1.6007, -0.3929, -0.8154, 2.0232, 0.0},
{1.1678, 0.0, 1.7980, -0.2139, -0.5345, 2.1186, 0.0}
};
typedef struct
{
unsigned int gammaReg;
unsigned int gammaSlope;
unsigned int gammaOffset;
} GAMMA_SETTINGS;
GAMMA_SETTINGS def_gamma[18] =
{
{RADEON_OV0_GAMMA_000_00F, 0x100, 0x0000},
{RADEON_OV0_GAMMA_010_01F, 0x100, 0x0020},
{RADEON_OV0_GAMMA_020_03F, 0x100, 0x0040},
{RADEON_OV0_GAMMA_040_07F, 0x100, 0x0080},
{RADEON_OV0_GAMMA_080_0BF, 0x100, 0x0100},
{RADEON_OV0_GAMMA_0C0_0FF, 0x100, 0x0100},
{RADEON_OV0_GAMMA_100_13F, 0x100, 0x0200},
{RADEON_OV0_GAMMA_140_17F, 0x100, 0x0200},
{RADEON_OV0_GAMMA_180_1BF, 0x100, 0x0300},
{RADEON_OV0_GAMMA_1C0_1FF, 0x100, 0x0300},
{RADEON_OV0_GAMMA_200_23F, 0x100, 0x0400},
{RADEON_OV0_GAMMA_240_27F, 0x100, 0x0400},
{RADEON_OV0_GAMMA_280_2BF, 0x100, 0x0500},
{RADEON_OV0_GAMMA_2C0_2FF, 0x100, 0x0500},
{RADEON_OV0_GAMMA_300_33F, 0x100, 0x0600},
{RADEON_OV0_GAMMA_340_37F, 0x100, 0x0600},
{RADEON_OV0_GAMMA_380_3BF, 0x100, 0x0700},
{RADEON_OV0_GAMMA_3C0_3FF, 0x100, 0x0700}
};
static void RADEONSetTransform (ScrnInfoPtr pScrn,
float bright,
float cont,
float sat,
float hue,
float red_intensity,
float green_intensity,
float blue_intensity,
CARD32 ref)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
float OvHueSin, OvHueCos;
float CAdjLuma, CAdjOff;
float CAdjRCb, CAdjRCr;
float CAdjGCb, CAdjGCr;
float CAdjBCb, CAdjBCr;
float RedAdj,GreenAdj,BlueAdj;
float OvLuma, OvROff, OvGOff, OvBOff;
float OvRCb, OvRCr;
float OvGCb, OvGCr;
float OvBCb, OvBCr;
float Loff = 64.0;
float Coff = 512.0f;
CARD32 dwOvLuma, dwOvROff, dwOvGOff, dwOvBOff;
CARD32 dwOvRCb, dwOvRCr;
CARD32 dwOvGCb, dwOvGCr;
CARD32 dwOvBCb, dwOvBCr;
if (ref >= 2)
return;
OvHueSin = sin(hue);
OvHueCos = cos(hue);
CAdjLuma = cont * trans[ref].RefLuma;
CAdjOff = cont * trans[ref].RefLuma * bright * 1023.0;
RedAdj = cont * trans[ref].RefLuma * red_intensity * 1023.0;
GreenAdj = cont * trans[ref].RefLuma * green_intensity * 1023.0;
BlueAdj = cont * trans[ref].RefLuma * blue_intensity * 1023.0;
CAdjRCb = sat * -OvHueSin * trans[ref].RefRCr;
CAdjRCr = sat * OvHueCos * trans[ref].RefRCr;
CAdjGCb = sat * (OvHueCos * trans[ref].RefGCb - OvHueSin * trans[ref].RefGCr);
CAdjGCr = sat * (OvHueSin * trans[ref].RefGCb + OvHueCos * trans[ref].RefGCr);
CAdjBCb = sat * OvHueCos * trans[ref].RefBCb;
CAdjBCr = sat * OvHueSin * trans[ref].RefBCb;
#if 0
CAdjLuma = 1.16455078125;
CAdjRCb = 0.0;
CAdjRCr = 1.59619140625;
CAdjGCb = -0.39111328125;
CAdjGCr = -0.8125;
CAdjBCb = 2.01708984375;
CAdjBCr = 0;
#endif
OvLuma = CAdjLuma;
OvRCb = CAdjRCb;
OvRCr = CAdjRCr;
OvGCb = CAdjGCb;
OvGCr = CAdjGCr;
OvBCb = CAdjBCb;
OvBCr = CAdjBCr;
OvROff = RedAdj + CAdjOff -
OvLuma * Loff - (OvRCb + OvRCr) * Coff;
OvGOff = GreenAdj + CAdjOff -
OvLuma * Loff - (OvGCb + OvGCr) * Coff;
OvBOff = BlueAdj + CAdjOff -
OvLuma * Loff - (OvBCb + OvBCr) * Coff;
#if 0
OvROff = -888.5;
OvGOff = 545;
OvBOff = -1104;
#endif
dwOvROff = ((INT32)(OvROff * 2.0)) & 0x1fff;
dwOvGOff = ((INT32)(OvGOff * 2.0)) & 0x1fff;
dwOvBOff = ((INT32)(OvBOff * 2.0)) & 0x1fff;
if(1 || info->ChipFamily < CHIP_FAMILY_R200)
{
dwOvLuma =(((INT32)(OvLuma * 2048.0))&0x7fff)<<17;
dwOvRCb = (((INT32)(OvRCb * 2048.0))&0x7fff)<<1;
dwOvRCr = (((INT32)(OvRCr * 2048.0))&0x7fff)<<17;
dwOvGCb = (((INT32)(OvGCb * 2048.0))&0x7fff)<<1;
dwOvGCr = (((INT32)(OvGCr * 2048.0))&0x7fff)<<17;
dwOvBCb = (((INT32)(OvBCb * 2048.0))&0x7fff)<<1;
dwOvBCr = (((INT32)(OvBCr * 2048.0))&0x7fff)<<17;
}
else
{
dwOvLuma = (((INT32)(OvLuma * 256.0))&0x7ff)<<20;
dwOvRCb = (((INT32)(OvRCb * 256.0))&0x7ff)<<4;
dwOvRCr = (((INT32)(OvRCr * 256.0))&0x7ff)<<20;
dwOvGCb = (((INT32)(OvGCb * 256.0))&0x7ff)<<4;
dwOvGCr = (((INT32)(OvGCr * 256.0))&0x7ff)<<20;
dwOvBCb = (((INT32)(OvBCb * 256.0))&0x7ff)<<4;
dwOvBCr = (((INT32)(OvBCr * 256.0))&0x7ff)<<20;
}
OUTREG(RADEON_OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma);
OUTREG(RADEON_OV0_LIN_TRANS_B, dwOvROff | dwOvRCr);
OUTREG(RADEON_OV0_LIN_TRANS_C, dwOvGCb | dwOvLuma);
OUTREG(RADEON_OV0_LIN_TRANS_D, dwOvGOff | dwOvGCr);
OUTREG(RADEON_OV0_LIN_TRANS_E, dwOvBCb | dwOvLuma);
OUTREG(RADEON_OV0_LIN_TRANS_F, dwOvBOff | dwOvBCr);
}
static void RADEONSetColorKey(ScrnInfoPtr pScrn, CARD32 colorKey)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
CARD32 min, max;
CARD8 r, g, b;
if (info->CurrentLayout.depth > 8)
{
CARD32 rbits, gbits, bbits;
rbits = (colorKey & pScrn->mask.red) >> pScrn->offset.red;
gbits = (colorKey & pScrn->mask.green) >> pScrn->offset.green;
bbits = (colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
r = rbits << (8 - pScrn->weight.red);
g = gbits << (8 - pScrn->weight.green);
b = bbits << (8 - pScrn->weight.blue);
}
else
{
CARD32 bits;
bits = colorKey & ((1 << info->CurrentLayout.depth) - 1);
r = bits;
g = bits;
b = bits;
}
min = (r << 16) | (g << 8) | (b);
max = (0xff << 24) | (r << 16) | (g << 8) | (b);
RADEONWaitForFifo(pScrn, 2);
OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_HIGH, max);
OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_LOW, min);
}
void
RADEONResetVideo(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
RADEONPortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr;
if (info->accelOn) info->accel->Sync(pScrn);
RADEONWaitForIdleMMIO(pScrn);
OUTREG(RADEON_OV0_SCALE_CNTL, 0x80000000);
OUTREG(RADEON_OV0_AUTO_FLIP_CNTL, 0);
OUTREG(RADEON_OV0_EXCLUSIVE_HORZ, 0);
OUTREG(RADEON_OV0_FILTER_CNTL, 0x0000000f);
OUTREG(RADEON_OV0_KEY_CNTL, RADEON_GRAPHIC_KEY_FN_EQ |
RADEON_VIDEO_KEY_FN_FALSE |
RADEON_CMP_MIX_OR);
OUTREG(RADEON_OV0_TEST, 0);
OUTREG(RADEON_FCP_CNTL, RADEON_FCP0_SRC_GND);
OUTREG(RADEON_CAP0_TRIG_CNTL, 0);
RADEONSetColorKey(pScrn, pPriv->colorKey);
if ((info->ChipFamily == CHIP_FAMILY_R300) ||
(info->ChipFamily == CHIP_FAMILY_R350) ||
(info->ChipFamily == CHIP_FAMILY_RV350) ||
(info->ChipFamily == CHIP_FAMILY_R200) ||
(info->ChipFamily == CHIP_FAMILY_RADEON)) {
int i;
OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a20000);
OUTREG(RADEON_OV0_LIN_TRANS_B, 0x198a190e);
OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a2f9da);
OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf2fe0442);
OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a22046);
OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f);
for (i = 0; i < 18; i++) {
OUTREG(def_gamma[i].gammaReg,
(def_gamma[i].gammaSlope<<16) | def_gamma[i].gammaOffset);
}
} else {
OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a00000);
OUTREG(RADEON_OV0_LIN_TRANS_B, 0x1990190e);
OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a0f9c0);
OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf3000442);
OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a02040);
OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f);
}
}
static XF86VideoAdaptorPtr
RADEONAllocAdaptor(ScrnInfoPtr pScrn)
{
XF86VideoAdaptorPtr adapt;
RADEONInfoPtr info = RADEONPTR(pScrn);
RADEONPortPrivPtr pPriv;
unsigned char *RADEONMMIO = info->MMIO;
if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
return NULL;
if(!(pPriv = xcalloc(1, sizeof(RADEONPortPrivRec) + sizeof(DevUnion))))
{
xfree(adapt);
return NULL;
}
adapt->pPortPrivates = (DevUnion*)(&pPriv[1]);
adapt->pPortPrivates[0].ptr = (pointer)pPriv;
pPriv->colorKey = info->videoKey;
pPriv->doubleBuffer = TRUE;
pPriv->videoStatus = 0;
pPriv->brightness = 0;
pPriv->transform_index = 0;
pPriv->saturation = 0;
pPriv->contrast = 0;
pPriv->red_intensity = 0;
pPriv->green_intensity = 0;
pPriv->blue_intensity = 0;
pPriv->hue = 0;
pPriv->currentBuffer = 0;
pPriv->autopaint_colorkey = TRUE;
if(info->ModeReg.dot_clock_freq < 17500)
pPriv->ecp_div = 0;
else
pPriv->ecp_div = 1;
#if 0
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dotclock is %g Mhz, setting ecp_div to %d\n", info->ModeReg.dot_clock_freq/100.0, pPriv->ecp_div);
#endif
OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) &
0xfffffCff) | (pPriv->ecp_div << 8));
if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
(info->ChipFamily == CHIP_FAMILY_RS200) ||
(info->ChipFamily == CHIP_FAMILY_RS300)) {
OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) | (1<<18)));
}
info->adaptor = adapt;
return adapt;
}
static XF86VideoAdaptorPtr
RADEONSetupImageVideo(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONPortPrivPtr pPriv;
XF86VideoAdaptorPtr adapt;
if(!(adapt = RADEONAllocAdaptor(pScrn)))
return NULL;
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
adapt->name = "ATI Radeon Video Overlay";
adapt->nEncodings = 1;
adapt->pEncodings = &DummyEncoding;
adapt->nFormats = NUM_FORMATS;
adapt->pFormats = Formats;
adapt->nPorts = 1;
adapt->nAttributes = NUM_ATTRIBUTES;
adapt->pAttributes = Attributes;
adapt->nImages = NUM_IMAGES;
adapt->pImages = Images;
adapt->PutVideo = NULL;
adapt->PutStill = NULL;
adapt->GetVideo = NULL;
adapt->GetStill = NULL;
adapt->StopVideo = RADEONStopVideo;
adapt->SetPortAttribute = RADEONSetPortAttribute;
adapt->GetPortAttribute = RADEONGetPortAttribute;
adapt->QueryBestSize = RADEONQueryBestSize;
adapt->PutImage = RADEONPutImage;
adapt->QueryImageAttributes = RADEONQueryImageAttributes;
pPriv = (RADEONPortPrivPtr)(adapt->pPortPrivates[0].ptr);
REGION_NULL(pScreen, &(pPriv->clip));
xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
xvSaturation = MAKE_ATOM("XV_SATURATION");
xvColor = MAKE_ATOM("XV_COLOR");
xvContrast = MAKE_ATOM("XV_CONTRAST");
xvColorKey = MAKE_ATOM("XV_COLORKEY");
xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
xvHue = MAKE_ATOM("XV_HUE");
xvRedIntensity = MAKE_ATOM("XV_RED_INTENSITY");
xvGreenIntensity = MAKE_ATOM("XV_GREEN_INTENSITY");
xvBlueIntensity = MAKE_ATOM("XV_BLUE_INTENSITY");
xvAutopaintColorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
RADEONResetVideo(pScrn);
return adapt;
}
static void
RADEONStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
if(cleanup) {
if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
RADEONWaitForFifo(pScrn, 2);
OUTREG(RADEON_OV0_SCALE_CNTL, 0);
}
if(info->videoLinear) {
xf86FreeOffscreenLinear(info->videoLinear);
info->videoLinear = NULL;
}
pPriv->videoStatus = 0;
} else {
if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
pPriv->videoStatus |= OFF_TIMER;
pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
}
}
}
static int
RADEONSetPortAttribute(ScrnInfoPtr pScrn,
Atom attribute,
INT32 value,
pointer data)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
Bool setTransform = FALSE;
info->accel->Sync(pScrn);
#define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0)
#define RTFBrightness(a) (((a)*1.0)/2000.0)
#define RTFIntensity(a) (((a)*1.0)/2000.0)
#define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
#define RTFHue(a) (((a)*3.1416)/1000.0)
#define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
if(attribute == xvAutopaintColorkey)
{
pPriv->autopaint_colorkey = ClipValue (value, 0, 1);
}
else if(attribute == xvSetDefaults)
{
pPriv->autopaint_colorkey = TRUE;
pPriv->brightness = 0;
pPriv->saturation = 0;
pPriv->contrast = 0;
pPriv->hue = 0;
pPriv->red_intensity = 0;
pPriv->green_intensity = 0;
pPriv->blue_intensity = 0;
pPriv->doubleBuffer = FALSE;
setTransform = TRUE;
}
else if(attribute == xvBrightness)
{
pPriv->brightness = ClipValue (value, -1000, 1000);
setTransform = TRUE;
}
else if((attribute == xvSaturation) || (attribute == xvColor))
{
pPriv->saturation = ClipValue (value, -1000, 1000);
setTransform = TRUE;
}
else if(attribute == xvContrast)
{
pPriv->contrast = ClipValue (value, -1000, 1000);
setTransform = TRUE;
}
else if(attribute == xvHue)
{
pPriv->hue = ClipValue (value, -1000, 1000);
setTransform = TRUE;
}
else if(attribute == xvRedIntensity)
{
pPriv->red_intensity = ClipValue (value, -1000, 1000);
setTransform = TRUE;
}
else if(attribute == xvGreenIntensity)
{
pPriv->green_intensity = ClipValue (value, -1000, 1000);
setTransform = TRUE;
}
else if(attribute == xvBlueIntensity)
{
pPriv->blue_intensity = ClipValue (value, -1000, 1000);
setTransform = TRUE;
}
else if(attribute == xvDoubleBuffer)
{
pPriv->doubleBuffer = ClipValue (value, 0, 1);
pPriv->doubleBuffer = value;
}
else if(attribute == xvColorKey)
{
pPriv->colorKey = value;
RADEONSetColorKey (pScrn, pPriv->colorKey);
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
}
else
return BadMatch;
if (setTransform)
{
RADEONSetTransform(pScrn,
RTFBrightness(pPriv->brightness),
RTFContrast(pPriv->contrast),
RTFSaturation(pPriv->saturation),
RTFHue(pPriv->hue),
RTFIntensity(pPriv->red_intensity),
RTFIntensity(pPriv->green_intensity),
RTFIntensity(pPriv->blue_intensity),
pPriv->transform_index);
}
return Success;
}
static int
RADEONGetPortAttribute(ScrnInfoPtr pScrn,
Atom attribute,
INT32 *value,
pointer data)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
if (info->accelOn) info->accel->Sync(pScrn);
if(attribute == xvAutopaintColorkey)
*value = pPriv->autopaint_colorkey;
else if(attribute == xvBrightness)
*value = pPriv->brightness;
else if((attribute == xvSaturation) || (attribute == xvColor))
*value = pPriv->saturation;
else if(attribute == xvContrast)
*value = pPriv->contrast;
else if(attribute == xvHue)
*value = pPriv->hue;
else if(attribute == xvRedIntensity)
*value = pPriv->red_intensity;
else if(attribute == xvGreenIntensity)
*value = pPriv->green_intensity;
else if(attribute == xvBlueIntensity)
*value = pPriv->blue_intensity;
else if(attribute == xvDoubleBuffer)
*value = pPriv->doubleBuffer ? 1 : 0;
else if(attribute == xvColorKey)
*value = pPriv->colorKey;
else
return BadMatch;
return Success;
}
static void
RADEONQueryBestSize(
ScrnInfoPtr pScrn,
Bool motion,
short vid_w, short vid_h,
short drw_w, short drw_h,
unsigned int *p_w, unsigned int *p_h,
pointer data
){
if(vid_w > (drw_w << 4))
drw_w = vid_w >> 4;
if(vid_h > (drw_h << 4))
drw_h = vid_h >> 4;
*p_w = drw_w;
*p_h = drw_h;
}
static void
RADEONCopyData(
unsigned char *src,
unsigned char *dst,
int srcPitch,
int dstPitch,
int h,
int w
){
w <<= 1;
while(h--) {
memcpy(dst, src, w);
src += srcPitch;
dst += dstPitch;
}
}
static void
RADEONCopyMungedData(
unsigned char *src1,
unsigned char *src2,
unsigned char *src3,
unsigned char *dst1,
int srcPitch,
int srcPitch2,
int dstPitch,
int h,
int w
){
CARD32 *dst;
CARD8 *s1, *s2, *s3;
int i, j;
w >>= 1;
for(j = 0; j < h; j++) {
dst = (pointer)dst1;
s1 = src1; s2 = src2; s3 = src3;
i = w;
while(i > 4) {
dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
dst += 4; s2 += 4; s3 += 4; s1 += 8;
i -= 4;
}
while(i--) {
dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
dst++; s2++; s3++;
s1 += 2;
}
dst1 += dstPitch;
src1 += srcPitch;
if(j & 1) {
src2 += srcPitch2;
src3 += srcPitch2;
}
}
}
static FBLinearPtr
RADEONAllocateMemory(
ScrnInfoPtr pScrn,
FBLinearPtr linear,
int size
){
ScreenPtr pScreen;
FBLinearPtr new_linear;
if(linear) {
if(linear->size >= size)
return linear;
if(xf86ResizeOffscreenLinear(linear, size))
return linear;
xf86FreeOffscreenLinear(linear);
}
pScreen = screenInfo.screens[pScrn->scrnIndex];
new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
NULL, NULL, NULL);
if(!new_linear) {
int max_size;
xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
PRIORITY_EXTREME);
if(max_size < size)
return NULL;
xf86PurgeUnlockedOffscreenAreas(pScreen);
new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
NULL, NULL, NULL);
}
return new_linear;
}
static void
RADEONDisplayVideo(
ScrnInfoPtr pScrn,
int id,
int offset1, int offset2,
short width, short height,
int pitch,
int left, int right, int top,
BoxPtr dstBox,
short src_w, short src_h,
short drw_w, short drw_h
){
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
int v_inc, h_inc, step_by, tmp;
int p1_h_accum_init, p23_h_accum_init;
int p1_v_accum_init;
int ecp_div;
int v_inc_shift;
int y_mult;
int x_off;
CARD32 scaler_src;
if(info->ModeReg.dot_clock_freq < 17500)
ecp_div = 0;
else
ecp_div = 1;
OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (ecp_div << 8));
v_inc_shift = 20;
if (pScrn->currentMode->Flags & V_INTERLACE)
v_inc_shift++;
if (pScrn->currentMode->Flags & V_DBLSCAN)
v_inc_shift--;
if (pScrn->currentMode->Flags & RADEON_USE_RMX) {
v_inc = ((src_h * pScrn->currentMode->CrtcVDisplay / info->PanelYRes) << v_inc_shift) / drw_h;
} else {
v_inc = (src_h << v_inc_shift) / drw_h;
}
h_inc = ((src_w << (12 + ecp_div)) / drw_w);
step_by = 1;
while(h_inc >= (2 << 12)) {
step_by++;
h_inc >>= 1;
}
offset1 += ((left >> 16) & ~7) << 1;
offset2 += ((left >> 16) & ~7) << 1;
if (info->IsSecondary) {
offset1 += info->FbMapSize;
offset2 += info->FbMapSize;
}
tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3);
p1_h_accum_init = ((tmp << 4) & 0x000f8000) |
((tmp << 12) & 0xf0000000);
tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2);
p23_h_accum_init = ((tmp << 4) & 0x000f8000) |
((tmp << 12) & 0x70000000);
tmp = (top & 0x0000ffff) + 0x00018000;
p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001;
left = (left >> 16) & 7;
RADEONWaitForFifo(pScrn, 2);
OUTREG(RADEON_OV0_REG_LOAD_CNTL, 1);
if (info->accelOn) info->accel->Sync(pScrn);
while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & (1 << 3)));
RADEONWaitForFifo(pScrn, 14);
OUTREG(RADEON_OV0_H_INC, h_inc | ((h_inc >> 1) << 16));
OUTREG(RADEON_OV0_STEP_BY, step_by | (step_by << 8));
y_mult = 1;
if (pScrn->currentMode->Flags & V_DBLSCAN)
y_mult = 2;
x_off = 8;
if ((info->ChipFamily == CHIP_FAMILY_R300) ||
(info->ChipFamily == CHIP_FAMILY_R350) ||
(info->ChipFamily == CHIP_FAMILY_RV350) ||
(info->ChipFamily == CHIP_FAMILY_R200))
x_off = 0;
if ((info->Clone && info->OverlayOnCRTC2) || info->IsSecondary) {
x_off = 0;
OUTREG(RADEON_OV1_Y_X_START, ((dstBox->x1
+ x_off
- info->CloneFrameX0
+ pScrn->frameX0) |
((dstBox->y1*y_mult -
info->CloneFrameY0
+ pScrn->frameY0) << 16)));
OUTREG(RADEON_OV1_Y_X_END, ((dstBox->x2
+ x_off
- info->CloneFrameX0
+ pScrn->frameX0) |
((dstBox->y2*y_mult
- info->CloneFrameY0
+ pScrn->frameY0) << 16)));
scaler_src = (1 << 14);
} else {
OUTREG(RADEON_OV0_Y_X_START, ((dstBox->x1 + x_off) |
((dstBox->y1*y_mult) << 16)));
OUTREG(RADEON_OV0_Y_X_END, ((dstBox->x2 + x_off) |
((dstBox->y2*y_mult) << 16)));
scaler_src = 0;
}
OUTREG(RADEON_OV0_V_INC, v_inc);
OUTREG(RADEON_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16));
OUTREG(RADEON_OV0_VID_BUF_PITCH0_VALUE, pitch);
OUTREG(RADEON_OV0_VID_BUF_PITCH1_VALUE, pitch);
OUTREG(RADEON_OV0_P1_X_START_END, (src_w + left - 1) | (left << 16));
left >>= 1; src_w >>= 1;
OUTREG(RADEON_OV0_P2_X_START_END, (src_w + left - 1) | (left << 16));
OUTREG(RADEON_OV0_P3_X_START_END, (src_w + left - 1) | (left << 16));
OUTREG(RADEON_OV0_VID_BUF0_BASE_ADRS, offset1 & 0xfffffff0);
OUTREG(RADEON_OV0_VID_BUF1_BASE_ADRS, offset2 & 0xfffffff0);
OUTREG(RADEON_OV0_VID_BUF2_BASE_ADRS, offset1 & 0xfffffff0);
RADEONWaitForFifo(pScrn, 9);
OUTREG(RADEON_OV0_VID_BUF3_BASE_ADRS, offset2 & 0xfffffff0);
OUTREG(RADEON_OV0_VID_BUF4_BASE_ADRS, offset1 & 0xfffffff0);
OUTREG(RADEON_OV0_VID_BUF5_BASE_ADRS, offset2 & 0xfffffff0);
OUTREG(RADEON_OV0_P1_V_ACCUM_INIT, p1_v_accum_init);
OUTREG(RADEON_OV0_P1_H_ACCUM_INIT, p1_h_accum_init);
OUTREG(RADEON_OV0_P23_H_ACCUM_INIT, p23_h_accum_init);
#if 0
if(id == FOURCC_UYVY)
OUTREG(RADEON_OV0_SCALE_CNTL, 0x41008C03);
else
OUTREG(RADEON_OV0_SCALE_CNTL, 0x41008B03);
#endif
if (id == FOURCC_UYVY)
OUTREG(RADEON_OV0_SCALE_CNTL, (RADEON_SCALER_SOURCE_YVYU422
| RADEON_SCALER_ADAPTIVE_DEINT
| RADEON_SCALER_SMART_SWITCH
| RADEON_SCALER_DOUBLE_BUFFER
| RADEON_SCALER_ENABLE
| scaler_src));
else
OUTREG(RADEON_OV0_SCALE_CNTL, (RADEON_SCALER_SOURCE_VYUY422
| RADEON_SCALER_ADAPTIVE_DEINT
| RADEON_SCALER_SMART_SWITCH
| RADEON_SCALER_DOUBLE_BUFFER
| RADEON_SCALER_ENABLE
| scaler_src));
OUTREG(RADEON_OV0_REG_LOAD_CNTL, 0);
}
static int
RADEONPutImage(
ScrnInfoPtr pScrn,
short src_x, short src_y,
short drw_x, short drw_y,
short src_w, short src_h,
short drw_w, short drw_h,
int id, unsigned char* buf,
short width, short height,
Bool Sync,
RegionPtr clipBoxes, pointer data
){
RADEONInfoPtr info = RADEONPTR(pScrn);
RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
INT32 xa, xb, ya, yb;
unsigned char *dst_start;
int new_size, offset, s2offset, s3offset;
int srcPitch, srcPitch2, dstPitch;
int top, left, npixels, nlines, bpp;
BoxRec dstBox;
CARD32 tmp;
#if X_BYTE_ORDER == X_BIG_ENDIAN
unsigned char *RADEONMMIO = info->MMIO;
CARD32 surface_cntl = INREG(RADEON_SURFACE_CNTL);
OUTREG(RADEON_SURFACE_CNTL, (surface_cntl |
RADEON_NONSURF_AP0_SWP_32BPP) & ~RADEON_NONSURF_AP0_SWP_16BPP);
#endif
s2offset = s3offset = srcPitch2 = 0;
if(src_w > (drw_w << 4))
drw_w = src_w >> 4;
if(src_h > (drw_h << 4))
drw_h = src_h >> 4;
xa = src_x;
xb = src_x + src_w;
ya = src_y;
yb = src_y + src_h;
dstBox.x1 = drw_x;
dstBox.x2 = drw_x + drw_w;
dstBox.y1 = drw_y;
dstBox.y2 = drw_y + drw_h;
if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb,
clipBoxes, width, height))
return Success;
dstBox.x1 -= pScrn->frameX0;
dstBox.x2 -= pScrn->frameX0;
dstBox.y1 -= pScrn->frameY0;
dstBox.y2 -= pScrn->frameY0;
bpp = pScrn->bitsPerPixel >> 3;
switch(id) {
case FOURCC_YV12:
case FOURCC_I420:
dstPitch = ((width << 1) + 15) & ~15;
new_size = ((dstPitch * height) + bpp - 1) / bpp;
srcPitch = (width + 3) & ~3;
s2offset = srcPitch * height;
srcPitch2 = ((width >> 1) + 3) & ~3;
s3offset = (srcPitch2 * (height >> 1)) + s2offset;
break;
case FOURCC_UYVY:
case FOURCC_YUY2:
default:
dstPitch = ((width << 1) + 15) & ~15;
new_size = ((dstPitch * height) + bpp - 1) / bpp;
srcPitch = (width << 1);
break;
}
if(!(info->videoLinear = RADEONAllocateMemory(pScrn, info->videoLinear,
pPriv->doubleBuffer ? (new_size << 1) : new_size)))
{
return BadAlloc;
}
pPriv->currentBuffer ^= 1;
top = ya >> 16;
left = (xa >> 16) & ~1;
npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left;
offset = (info->videoLinear->offset * bpp) + (top * dstPitch);
if(pPriv->doubleBuffer)
offset += pPriv->currentBuffer * new_size * bpp;
dst_start = info->FB + offset;
switch(id) {
case FOURCC_YV12:
case FOURCC_I420:
top &= ~1;
dst_start += left << 1;
tmp = ((top >> 1) * srcPitch2) + (left >> 1);
s2offset += tmp;
s3offset += tmp;
if(id == FOURCC_I420) {
tmp = s2offset;
s2offset = s3offset;
s3offset = tmp;
}
nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top;
#if X_BYTE_ORDER == X_BIG_ENDIAN
OUTREG(RADEON_SURFACE_CNTL, (surface_cntl | RADEON_NONSURF_AP0_SWP_32BPP)
& ~RADEON_NONSURF_AP0_SWP_16BPP);
#endif
RADEONCopyMungedData(buf + (top * srcPitch) + left, buf + s2offset,
buf + s3offset, dst_start, srcPitch, srcPitch2,
dstPitch, nlines, npixels);
break;
case FOURCC_UYVY:
case FOURCC_YUY2:
default:
left <<= 1;
buf += (top * srcPitch) + left;
nlines = ((yb + 0xffff) >> 16) - top;
dst_start += left;
#if X_BYTE_ORDER == X_BIG_ENDIAN
OUTREG(RADEON_SURFACE_CNTL, surface_cntl & ~(RADEON_NONSURF_AP0_SWP_32BPP
| RADEON_NONSURF_AP0_SWP_16BPP));
#endif
RADEONCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
break;
}
#if X_BYTE_ORDER == X_BIG_ENDIAN
OUTREG(RADEON_SURFACE_CNTL, surface_cntl);
#endif
if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))
{
REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
if(pPriv->autopaint_colorkey)
xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
}
RADEONDisplayVideo(pScrn, id, offset, offset, width, height, dstPitch,
xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h);
pPriv->videoStatus = CLIENT_VIDEO_ON;
info->VideoTimerCallback = RADEONVideoTimerCallback;
return Success;
}
static int
RADEONQueryImageAttributes(
ScrnInfoPtr pScrn,
int id,
unsigned short *w, unsigned short *h,
int *pitches, int *offsets
){
int size, tmp;
if(*w > 2048) *w = 2048;
if(*h > 2048) *h = 2048;
*w = (*w + 1) & ~1;
if(offsets) offsets[0] = 0;
switch(id) {
case FOURCC_YV12:
case FOURCC_I420:
*h = (*h + 1) & ~1;
size = (*w + 3) & ~3;
if(pitches) pitches[0] = size;
size *= *h;
if(offsets) offsets[1] = size;
tmp = ((*w >> 1) + 3) & ~3;
if(pitches) pitches[1] = pitches[2] = tmp;
tmp *= (*h >> 1);
size += tmp;
if(offsets) offsets[2] = size;
size += tmp;
break;
case FOURCC_UYVY:
case FOURCC_YUY2:
default:
size = *w << 1;
if(pitches) pitches[0] = size;
size *= *h;
break;
}
return size;
}
static void
RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
RADEONPortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr;
if(pPriv->videoStatus & TIMER_MASK) {
if(pPriv->videoStatus & OFF_TIMER) {
if(pPriv->offTime < now) {
unsigned char *RADEONMMIO = info->MMIO;
OUTREG(RADEON_OV0_SCALE_CNTL, 0);
pPriv->videoStatus = FREE_TIMER;
pPriv->freeTime = now + FREE_DELAY;
}
} else {
if(pPriv->freeTime < now) {
if(info->videoLinear) {
xf86FreeOffscreenLinear(info->videoLinear);
info->videoLinear = NULL;
}
pPriv->videoStatus = 0;
info->VideoTimerCallback = NULL;
}
}
} else
info->VideoTimerCallback = NULL;
}
typedef struct {
FBLinearPtr linear;
Bool isOn;
} OffscreenPrivRec, * OffscreenPrivPtr;
static int
RADEONAllocateSurface(
ScrnInfoPtr pScrn,
int id,
unsigned short w,
unsigned short h,
XF86SurfacePtr surface
){
FBLinearPtr linear;
int pitch, size, bpp;
OffscreenPrivPtr pPriv;
if((w > 1024) || (h > 1024))
return BadAlloc;
w = (w + 1) & ~1;
pitch = ((w << 1) + 15) & ~15;
bpp = pScrn->bitsPerPixel >> 3;
size = ((pitch * h) + bpp - 1) / bpp;
if(!(linear = RADEONAllocateMemory(pScrn, NULL, size)))
return BadAlloc;
surface->width = w;
surface->height = h;
if(!(surface->pitches = xalloc(sizeof(int)))) {
xf86FreeOffscreenLinear(linear);
return BadAlloc;
}
if(!(surface->offsets = xalloc(sizeof(int)))) {
xfree(surface->pitches);
xf86FreeOffscreenLinear(linear);
return BadAlloc;
}
if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
xfree(surface->pitches);
xfree(surface->offsets);
xf86FreeOffscreenLinear(linear);
return BadAlloc;
}
pPriv->linear = linear;
pPriv->isOn = FALSE;
surface->pScrn = pScrn;
surface->id = id;
surface->pitches[0] = pitch;
surface->offsets[0] = linear->offset * bpp;
surface->devPrivate.ptr = (pointer)pPriv;
return Success;
}
static int
RADEONStopSurface(
XF86SurfacePtr surface
){
OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
RADEONInfoPtr info = RADEONPTR(surface->pScrn);
unsigned char *RADEONMMIO = info->MMIO;
if(pPriv->isOn) {
OUTREG(RADEON_OV0_SCALE_CNTL, 0);
pPriv->isOn = FALSE;
}
return Success;
}
static int
RADEONFreeSurface(
XF86SurfacePtr surface
){
OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
if(pPriv->isOn)
RADEONStopSurface(surface);
xf86FreeOffscreenLinear(pPriv->linear);
xfree(surface->pitches);
xfree(surface->offsets);
xfree(surface->devPrivate.ptr);
return Success;
}
static int
RADEONGetSurfaceAttribute(
ScrnInfoPtr pScrn,
Atom attribute,
INT32 *value
){
return RADEONGetPortAttribute(pScrn, attribute, value,
(pointer)(GET_PORT_PRIVATE(pScrn)));
}
static int
RADEONSetSurfaceAttribute(
ScrnInfoPtr pScrn,
Atom attribute,
INT32 value
){
return RADEONSetPortAttribute(pScrn, attribute, value,
(pointer)(GET_PORT_PRIVATE(pScrn)));
}
static int
RADEONDisplaySurface(
XF86SurfacePtr surface,
short src_x, short src_y,
short drw_x, short drw_y,
short src_w, short src_h,
short drw_w, short drw_h,
RegionPtr clipBoxes
){
OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
ScrnInfoPtr pScrn = surface->pScrn;
RADEONInfoPtr info = RADEONPTR(pScrn);
RADEONPortPrivPtr portPriv = info->adaptor->pPortPrivates[0].ptr;
INT32 xa, ya, xb, yb;
BoxRec dstBox;
if (src_w > (drw_w << 4))
drw_w = src_w >> 4;
if (src_h > (drw_h << 4))
drw_h = src_h >> 4;
xa = src_x;
xb = src_x + src_w;
ya = src_y;
yb = src_y + src_h;
dstBox.x1 = drw_x;
dstBox.x2 = drw_x + drw_w;
dstBox.y1 = drw_y;
dstBox.y2 = drw_y + drw_h;
if (!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
surface->width, surface->height))
return Success;
dstBox.x1 -= pScrn->frameX0;
dstBox.x2 -= pScrn->frameX0;
dstBox.y1 -= pScrn->frameY0;
dstBox.y2 -= pScrn->frameY0;
RADEONResetVideo(pScrn);
RADEONDisplayVideo(pScrn, surface->id,
surface->offsets[0], surface->offsets[0],
surface->width, surface->height, surface->pitches[0],
xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h);
if (portPriv->autopaint_colorkey)
xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
pPriv->isOn = TRUE;
if (portPriv->videoStatus & CLIENT_VIDEO_ON) {
REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
UpdateCurrentTime();
portPriv->videoStatus = FREE_TIMER;
portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
info->VideoTimerCallback = RADEONVideoTimerCallback;
}
return Success;
}
static void
RADEONInitOffscreenImages(ScreenPtr pScreen)
{
XF86OffscreenImagePtr offscreenImages;
if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
return;
offscreenImages[0].image = &Images[0];
offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
VIDEO_CLIP_TO_VIEWPORT;
offscreenImages[0].alloc_surface = RADEONAllocateSurface;
offscreenImages[0].free_surface = RADEONFreeSurface;
offscreenImages[0].display = RADEONDisplaySurface;
offscreenImages[0].stop = RADEONStopSurface;
offscreenImages[0].setAttribute = RADEONSetSurfaceAttribute;
offscreenImages[0].getAttribute = RADEONGetSurfaceAttribute;
offscreenImages[0].max_width = 1024;
offscreenImages[0].max_height = 1024;
offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
offscreenImages[0].attributes = Attributes;
xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
}