#include "Xv.h"
#include "dix.h"
#include "dixstruct.h"
#include "fourcc.h"
#include "xaalocal.h"
#include "savage_driver.h"
#define OFF_DELAY 200
#define FREE_DELAY 60000
#define OFF_TIMER 0x01
#define FREE_TIMER 0x02
#define CLIENT_VIDEO_ON 0x04
#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
void myOUTREG( SavagePtr psav, unsigned long offset, unsigned long value );
static XF86VideoAdaptorPtr SavageSetupImageVideo(ScreenPtr);
static void SavageInitOffscreenImages(ScreenPtr);
static void SavageStopVideo(ScrnInfoPtr, pointer, Bool);
static int SavageSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
static int SavageGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
static void SavageQueryBestSize(ScrnInfoPtr, Bool,
short, short, short, short, unsigned int *, unsigned int *, pointer);
static int SavagePutImage( ScrnInfoPtr,
short, short, short, short, short, short, short, short,
int, unsigned char*, short, short, Bool, RegionPtr, pointer);
static int SavageQueryImageAttributes(ScrnInfoPtr,
int, unsigned short *, unsigned short *, int *, int *);
void SavageStreamsOn(ScrnInfoPtr pScrn, int id);
void SavageStreamsOff(ScrnInfoPtr pScrn);
void SavageResetVideo(ScrnInfoPtr pScrn);
static void SavageInitStreamsOld(ScrnInfoPtr pScrn);
static void SavageInitStreamsNew(ScrnInfoPtr pScrn);
static void (*SavageInitStreams)(ScrnInfoPtr pScrn) = NULL;
static void SavageSetColorKeyOld(ScrnInfoPtr pScrn);
static void SavageSetColorKeyNew(ScrnInfoPtr pScrn);
static void (*SavageSetColorKey)(ScrnInfoPtr pScrn) = NULL;
static void SavageSetColorOld(ScrnInfoPtr pScrn );
static void SavageSetColorNew(ScrnInfoPtr pScrn );
static void (*SavageSetColor)(ScrnInfoPtr pScrn ) = NULL;
static void SavageDisplayVideoOld(
ScrnInfoPtr pScrn, int id, int offset,
short width, short height, int pitch,
int x1, int y1, int x2, int y2,
BoxPtr dstBox,
short src_w, short src_h,
short drw_w, short drw_h
);
static void SavageDisplayVideoNew(
ScrnInfoPtr pScrn, int id, int offset,
short width, short height, int pitch,
int x1, int y1, int x2, int y2,
BoxPtr dstBox,
short src_w, short src_h,
short drw_w, short drw_h
);
static void (*SavageDisplayVideo)(
ScrnInfoPtr pScrn, int id, int offset,
short width, short height, int pitch,
int x1, int y1, int x2, int y2,
BoxPtr dstBox,
short src_w, short src_h,
short drw_w, short drw_h
) = NULL;
static void OverlayParamInit(ScrnInfoPtr pScrn);
static void InitStreamsForExpansion(ScrnInfoPtr pScrn);
#define XVTRACE 4
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
static Atom xvColorKey, xvBrightness, xvContrast, xvSaturation, xvHue;
static XF86VideoEncodingRec DummyEncoding[1] =
{
{
0,
"XV_IMAGE",
1024, 1024,
{1, 1}
}
};
#define NUM_FORMATS 4
static XF86VideoFormatRec Formats[NUM_FORMATS] =
{
{8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
};
#define NUM_ATTRIBUTES 5
static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
{
{XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
{XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
{XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
{XvSettable | XvGettable, 0, 255, "XV_SATURATION"},
{XvSettable | XvGettable, -180, 180, "XV_HUE"}
};
#define FOURCC_RV16 0x36315652
#define FOURCC_RV15 0x35315652
#define FOURCC_Y211 0x31313259
static XF86ImageRec Images[] =
{
XVIMAGE_YUY2,
XVIMAGE_YV12,
XVIMAGE_I420,
{
FOURCC_RV15,
XvRGB,
LSBFirst,
{'R','V','1','5',
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
16,
XvPacked,
1,
15, 0x001F, 0x03E0, 0x7C00,
0, 0, 0,
0, 0, 0,
0, 0, 0,
{'R','V','B',0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
XvTopToBottom
},
{
FOURCC_RV16,
XvRGB,
LSBFirst,
{'R','V','1','6',
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
16,
XvPacked,
1,
16, 0x001F, 0x07E0, 0xF800,
0, 0, 0,
0, 0, 0,
0, 0, 0,
{'R','V','B',0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
XvTopToBottom
},
{
FOURCC_Y211,
XvYUV,
LSBFirst,
{'Y','2','1','1',
0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71},
6,
XvPacked,
3,
0, 0, 0, 0 ,
8, 8, 8,
2, 4, 4,
1, 1, 1,
{'Y','U','Y','V',
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
XvTopToBottom
}
};
#define NUM_IMAGES (sizeof(Images)/sizeof(Images[0]))
typedef struct {
int brightness;
CARD32 contrast;
CARD32 saturation;
int hue;
FBAreaPtr area;
RegionRec clip;
CARD32 colorKey;
CARD32 videoStatus;
Time offTime;
Time freeTime;
int lastKnownPitch;
} SavagePortPrivRec, *SavagePortPrivPtr;
#define GET_PORT_PRIVATE(pScrn) \
(SavagePortPrivPtr)((SAVPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
#define EXT_MISC_CTRL2 0x67
#define ENABLE_STREAM1 0x04
#define ENABLE_STREAM2 0x02
#define NO_STREAMS 0xF9
#define USE_MM_FOR_PRI_STREAM 0x08
#define HDM_SHIFT 16
#define HDSCALE_4 (2 << HDM_SHIFT)
#define HDSCALE_8 (3 << HDM_SHIFT)
#define HDSCALE_16 (4 << HDM_SHIFT)
#define HDSCALE_32 (5 << HDM_SHIFT)
#define HDSCALE_64 (6 << HDM_SHIFT)
#define ENABLE_STREAMS_OLD 0x0c
#define NO_STREAMS_OLD 0xf3
#define USE_MM_FOR_PRI_STREAM_OLD 0x01
#define PSTREAM_CONTROL_REG 0x8180
#define COL_CHROMA_KEY_CONTROL_REG 0x8184
#define SSTREAM_CONTROL_REG 0x8190
#define CHROMA_KEY_UPPER_BOUND_REG 0x8194
#define SSTREAM_STRETCH_REG 0x8198
#define COLOR_ADJUSTMENT_REG 0x819C
#define BLEND_CONTROL_REG 0x81A0
#define PSTREAM_FBADDR0_REG 0x81C0
#define PSTREAM_FBADDR1_REG 0x81C4
#define PSTREAM_STRIDE_REG 0x81C8
#define DOUBLE_BUFFER_REG 0x81CC
#define SSTREAM_FBADDR0_REG 0x81D0
#define SSTREAM_FBADDR1_REG 0x81D4
#define SSTREAM_STRIDE_REG 0x81D8
#define SSTREAM_VSCALE_REG 0x81E0
#define SSTREAM_VINITIAL_REG 0x81E4
#define SSTREAM_LINES_REG 0x81E8
#define STREAMS_FIFO_REG 0x81EC
#define PSTREAM_WINDOW_START_REG 0x81F0
#define PSTREAM_WINDOW_SIZE_REG 0x81F4
#define SSTREAM_WINDOW_START_REG 0x81F8
#define SSTREAM_WINDOW_SIZE_REG 0x81FC
#define FIFO_CONTROL 0x8200
#define PSTREAM_FBSIZE_REG 0x8300
#define SSTREAM_FBSIZE_REG 0x8304
#define SSTREAM_FBADDR2_REG 0x8308
#define OS_XY(x,y) (((x+1)<<16)|(y+1))
#define OS_WH(x,y) (((x-1)<<16)|(y))
static
unsigned int GetBlendForFourCC( int id )
{
switch( id ) {
case FOURCC_YUY2:
case FOURCC_YV12:
case FOURCC_I420:
return 1;
case FOURCC_Y211:
return 4;
case FOURCC_RV15:
return 3;
case FOURCC_RV16:
return 5;
default:
return 0;
}
}
void myOUTREG( SavagePtr psav, unsigned long offset, unsigned long value )
{
ErrorF( "MMIO %04lx, was %08lx, want %08lx,",
offset, (unsigned long)MMIO_IN32( psav->MapBase, offset ), value );
MMIO_OUT32( psav->MapBase, offset, value );
ErrorF( " now %08lx\n", (unsigned long)MMIO_IN32( psav->MapBase, offset ) );
}
void SavageInitStreamsOld(ScrnInfoPtr pScrn)
{
SavagePtr psav = SAVPTR(pScrn);
unsigned long jDelta;
unsigned long format = 0;
xf86ErrorFVerb(XVTRACE, "SavageInitStreams\n" );
switch( pScrn->depth ) {
case 8: format = 0 << 24; break;
case 15: format = 3 << 24; break;
case 16: format = 5 << 24; break;
case 24: format = 7 << 24; break;
}
jDelta = pScrn->displayWidth * pScrn->bitsPerPixel / 8;
OUTREG( PSTREAM_WINDOW_START_REG, OS_XY(0,0) );
OUTREG( PSTREAM_WINDOW_SIZE_REG, OS_WH(pScrn->displayWidth, pScrn->virtualY) );
OUTREG( PSTREAM_FBADDR0_REG, pScrn->fbOffset );
OUTREG( PSTREAM_FBADDR1_REG, 0 );
OUTREG( PSTREAM_STRIDE_REG, jDelta );
OUTREG( PSTREAM_CONTROL_REG, format );
OUTREG( PSTREAM_FBSIZE_REG, jDelta * pScrn->virtualY >> 3 );
OUTREG( COL_CHROMA_KEY_CONTROL_REG, 0 );
OUTREG( SSTREAM_CONTROL_REG, 0 );
OUTREG( CHROMA_KEY_UPPER_BOUND_REG, 0 );
OUTREG( SSTREAM_STRETCH_REG, 0 );
OUTREG( COLOR_ADJUSTMENT_REG, 0 );
OUTREG( BLEND_CONTROL_REG, 1 << 24 );
OUTREG( DOUBLE_BUFFER_REG, 0 );
OUTREG( SSTREAM_FBADDR0_REG, 0 );
OUTREG( SSTREAM_FBADDR1_REG, 0 );
OUTREG( SSTREAM_FBADDR2_REG, 0 );
OUTREG( SSTREAM_STRIDE_REG, 0 );
OUTREG( SSTREAM_VSCALE_REG, 0 );
OUTREG( SSTREAM_LINES_REG, 0 );
OUTREG( SSTREAM_VINITIAL_REG, 0 );
OUTREG( SSTREAM_WINDOW_START_REG, OS_XY(0xfffe, 0xfffe) );
OUTREG( SSTREAM_WINDOW_SIZE_REG, OS_WH(10,2) );
}
#undef OUTREG
#if 0
#define OUTREG(a,v) myOUTREG(psav,a,v)
#else
#define OUTREG(addr,val) MMIO_OUT32(psav->MapBase, addr, val)
#endif
void SavageInitStreamsNew(ScrnInfoPtr pScrn)
{
SavagePtr psav = SAVPTR(pScrn);
unsigned long jDelta;
xf86ErrorFVerb(XVTRACE, "SavageInitStreams\n" );
if(
S3_SAVAGE_MOBILE_SERIES(psav->Chipset) &&
!psav->CrtOnly &&
!psav->TvOn
) {
OverlayParamInit( pScrn );
}
jDelta = pScrn->displayWidth * pScrn->bitsPerPixel / 8;
OUTREG( PRI_STREAM_BUFFERSIZE, jDelta * pScrn->virtualY >> 3 );
OUTREG( PRI_STREAM_FBUF_ADDR0, pScrn->fbOffset );
OUTREG( PRI_STREAM_STRIDE, jDelta );
OUTREG( SEC_STREAM_CKEY_LOW, 0 );
OUTREG( SEC_STREAM_CKEY_UPPER, 0 );
OUTREG( SEC_STREAM_HSCALING, 0 );
OUTREG( SEC_STREAM_VSCALING, 0 );
OUTREG( BLEND_CONTROL, 0 );
OUTREG( SEC_STREAM_FBUF_ADDR0, 0 );
OUTREG( SEC_STREAM_FBUF_ADDR1, 0 );
OUTREG( SEC_STREAM_FBUF_ADDR2, 0 );
OUTREG( SEC_STREAM_WINDOW_START, 0 );
OUTREG( SEC_STREAM_WINDOW_SZ, 0 );
OUTREG( SEC_STREAM_TILE_OFF, 0 );
OUTREG( SEC_STREAM_OPAQUE_OVERLAY, 0 );
OUTREG( SEC_STREAM_STRIDE, 0 );
OUTREG( SEC_STREAM_COLOR_CONVERT1, 0x0000C892 );
OUTREG( SEC_STREAM_COLOR_CONVERT2, 0x00039F9A );
OUTREG( SEC_STREAM_COLOR_CONVERT3, 0x01F1547E );
}
void SavageStreamsOn(ScrnInfoPtr pScrn, int id)
{
SavagePtr psav = SAVPTR(pScrn);
unsigned char jStreamsControl;
unsigned short vgaCRIndex = psav->vgaIOBase + 4;
unsigned short vgaCRReg = psav->vgaIOBase + 5;
xf86ErrorFVerb(XVTRACE, "SavageStreamsOn\n" );
xf86EnableIO();
VGAOUT16(vgaCRIndex, 0x4838);
VGAOUT16(vgaCRIndex, 0xa039);
VGAOUT16(0x3c4, 0x0608);
if(
S3_SAVAGE_MOBILE_SERIES(psav->Chipset) &&
!psav->CrtOnly &&
!psav->TvOn
) {
OverlayParamInit( pScrn );
}
VGAOUT8( vgaCRIndex, EXT_MISC_CTRL2 );
if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ||
#if 0
(psav->Chipset == S3_SUPERSAVAGE) ||
#endif
(psav->Chipset == S3_SAVAGE2000) )
{
jStreamsControl = VGAIN8( vgaCRReg ) | ENABLE_STREAM1;
VerticalRetraceWait(psav);
VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 );
psav->blendBase = GetBlendForFourCC( id ) << 9;
xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char *)&id, psav->blendBase );
OUTREG( BLEND_CONTROL, psav->blendBase | 0x08 );
OUTREG( SEC_STREAM_COLOR_CONVERT1, 0x0000C892 );
OUTREG( SEC_STREAM_COLOR_CONVERT2, 0x00039F9A );
OUTREG( SEC_STREAM_COLOR_CONVERT3, 0x01F1547E );
}
else
{
jStreamsControl = VGAIN8( vgaCRReg ) | ENABLE_STREAMS_OLD;
VerticalRetraceWait(psav);
VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 );
SavageInitStreamsOld( pScrn );
}
VerticalRetraceWait(psav);
psav->videoFlags |= VF_STREAMS_ON;
psav->videoFourCC = id;
}
void SavageStreamsOff(ScrnInfoPtr pScrn)
{
SavagePtr psav = SAVPTR(pScrn);
unsigned char jStreamsControl;
unsigned short vgaCRIndex = psav->vgaIOBase + 4;
unsigned short vgaCRReg = psav->vgaIOBase + 5;
xf86ErrorFVerb(XVTRACE, "SavageStreamsOff\n" );
xf86EnableIO();
VGAOUT16(vgaCRIndex, 0x4838);
VGAOUT16(vgaCRIndex, 0xa039);
VGAOUT16(0x3c4, 0x0608);
VGAOUT8( vgaCRIndex, EXT_MISC_CTRL2 );
if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ||
(psav->Chipset == S3_SUPERSAVAGE) ||
(psav->Chipset == S3_SAVAGE2000) )
jStreamsControl = VGAIN8( vgaCRReg ) & NO_STREAMS;
else
jStreamsControl = VGAIN8( vgaCRReg ) & NO_STREAMS_OLD;
VerticalRetraceWait(psav);
VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 );
VGAOUT16( vgaCRIndex, 0x0093 );
VGAOUT8( vgaCRIndex, 0x92 );
VGAOUT8( vgaCRReg, VGAIN8(vgaCRReg) & 0x40 );
psav->videoFlags &= ~VF_STREAMS_ON;
}
void SavageInitVideo(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
XF86VideoAdaptorPtr newAdaptor = NULL;
SavagePtr psav = SAVPTR(pScrn);
int num_adaptors;
xf86ErrorFVerb(XVTRACE,"SavageInitVideo\n");
if(
S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ||
(psav->Chipset == S3_SUPERSAVAGE) ||
(psav->Chipset == S3_SAVAGE2000)
)
{
newAdaptor = SavageSetupImageVideo(pScreen);
SavageInitOffscreenImages(pScreen);
SavageInitStreams = SavageInitStreamsNew;
SavageSetColor = SavageSetColorNew;
SavageSetColorKey = SavageSetColorKeyNew;
SavageDisplayVideo = SavageDisplayVideoNew;
}
else
{
newAdaptor = SavageSetupImageVideo(pScreen);
SavageInitOffscreenImages(pScreen);
SavageInitStreams = SavageInitStreamsOld;
SavageSetColor = SavageSetColorOld;
SavageSetColorKey = SavageSetColorKeyOld;
SavageDisplayVideo = SavageDisplayVideoOld;
}
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);
if( newAdaptor )
{
if( SavageInitStreams == SavageInitStreamsNew )
SavageInitStreams(pScrn);
psav->videoFlags = 0;
psav->videoFourCC = 0;
}
}
void SavageSetColorKeyOld(ScrnInfoPtr pScrn)
{
SavagePtr psav = SAVPTR(pScrn);
SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
int red, green, blue;
red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
if( !pPriv->colorKey ) {
OUTREG( COL_CHROMA_KEY_CONTROL_REG, 0 );
OUTREG( CHROMA_KEY_UPPER_BOUND_REG, 0 );
OUTREG( BLEND_CONTROL_REG, 0 );
}
else {
switch (pScrn->depth) {
case 8:
OUTREG( COL_CHROMA_KEY_CONTROL_REG,
0x37000000 | (pPriv->colorKey & 0xFF) );
OUTREG( CHROMA_KEY_UPPER_BOUND_REG,
0x00000000 | (pPriv->colorKey & 0xFF) );
break;
case 15:
OUTREG( COL_CHROMA_KEY_CONTROL_REG,
0x05000000 | (red<<19) | (green<<11) | (blue<<3) );
OUTREG( CHROMA_KEY_UPPER_BOUND_REG,
0x00000000 | (red<<19) | (green<<11) | (blue<<3) );
break;
case 16:
OUTREG( COL_CHROMA_KEY_CONTROL_REG,
0x16000000 | (red<<19) | (green<<10) | (blue<<3) );
OUTREG( CHROMA_KEY_UPPER_BOUND_REG,
0x00020002 | (red<<19) | (green<<10) | (blue<<3) );
break;
case 24:
OUTREG( COL_CHROMA_KEY_CONTROL_REG,
0x17000000 | (red<<16) | (green<<8) | (blue) );
OUTREG( CHROMA_KEY_UPPER_BOUND_REG,
0x00000000 | (red<<16) | (green<<8) | (blue) );
break;
}
OUTREG( BLEND_CONTROL_REG, 0x05000000 );
}
}
void SavageSetColorKeyNew(ScrnInfoPtr pScrn)
{
SavagePtr psav = SAVPTR(pScrn);
SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
int red, green, blue;
red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
if( !pPriv->colorKey ) {
OUTREG( SEC_STREAM_CKEY_LOW, 0 );
OUTREG( SEC_STREAM_CKEY_UPPER, 0 );
OUTREG( BLEND_CONTROL, psav->blendBase | 0x08 );
}
else {
switch (pScrn->depth) {
case 8:
OUTREG( SEC_STREAM_CKEY_LOW,
0x47000000 | (pPriv->colorKey & 0xFF) );
OUTREG( SEC_STREAM_CKEY_UPPER,
0x47000000 | (pPriv->colorKey & 0xFF) );
break;
case 15:
OUTREG( SEC_STREAM_CKEY_LOW,
0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
OUTREG( SEC_STREAM_CKEY_UPPER,
0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
break;
case 16:
OUTREG( SEC_STREAM_CKEY_LOW,
0x46000000 | (red<<19) | (green<<10) | (blue<<3) );
OUTREG( SEC_STREAM_CKEY_UPPER,
0x46020002 | (red<<19) | (green<<10) | (blue<<3) );
break;
case 24:
OUTREG( SEC_STREAM_CKEY_LOW,
0x47000000 | (red<<16) | (green<<8) | (blue) );
OUTREG( SEC_STREAM_CKEY_UPPER,
0x47000000 | (red<<16) | (green<<8) | (blue) );
break;
}
OUTREG( BLEND_CONTROL, psav->blendBase | 0x08 );
}
}
void SavageSetColorOld( ScrnInfoPtr pScrn )
{
SavagePtr psav = SAVPTR(pScrn);
SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
xf86ErrorFVerb(XVTRACE, "bright %d, contrast %d, saturation %d, hue %d\n",
pPriv->brightness, (int)pPriv->contrast, (int)pPriv->saturation, pPriv->hue );
if(
(psav->videoFourCC == FOURCC_RV15) ||
(psav->videoFourCC == FOURCC_RV16)
)
{
OUTREG( COLOR_ADJUSTMENT_REG, 0 );
}
else
{
long sat = pPriv->saturation * 16 / 256;
double hue = pPriv->hue * 0.017453292;
unsigned long hs1 = ((long)(sat * cos(hue))) & 0x1f;
unsigned long hs2 = ((long)(sat * sin(hue))) & 0x1f;
OUTREG( COLOR_ADJUSTMENT_REG,
0x80008000 |
(pPriv->brightness + 128) |
((pPriv->contrast & 0xf8) << (12-7)) |
(hs1 << 16) |
(hs2 << 24)
);
}
}
void SavageSetColorNew( ScrnInfoPtr pScrn )
{
SavagePtr psav = SAVPTR(pScrn);
SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
double k, dk1, dk2, dk3, dk4, dk5, dk6, dk7, dkb;
int k1, k2, k3, k4, k5, k6, k7, kb;
double s = pPriv->saturation / 128.0;
double h = pPriv->hue * 0.017453292;
unsigned long assembly;
xf86ErrorFVerb(XVTRACE, "bright %d, contrast %d, saturation %d, hue %d\n",
pPriv->brightness, (int)pPriv->contrast, (int)pPriv->saturation, pPriv->hue );
if( psav->videoFourCC == FOURCC_Y211 )
k = 1.0;
else
k = 1.14;
dk1 = k * pPriv->contrast;
dk2 = 64.0 * 1.371 * k * s * cos(h);
dk3 = -64.0 * 1.371 * k * s * sin(h);
dk4 = -128.0 * k * s * (0.698 * cos(h) - 0.336 * sin(h));
dk5 = -128.0 * k * s * (0.698 * sin(h) + 0.336 * cos(h));
dk6 = 64.0 * 1.732 * k * s * sin(h);
dk7 = 64.0 * 1.732 * k * s * cos(h);
dkb = 128.0 * pPriv->brightness + 64.0;
if( psav->videoFourCC != FOURCC_Y211 )
dkb -= dk1 * 14.0;
k1 = (int)(dk1+0.5) & 0x1ff;
k2 = (int)(dk2+0.5) & 0x1ff;
k3 = (int)(dk3+0.5) & 0x1ff;
assembly = (k3<<18) | (k2<<9) | k1;
xf86ErrorFVerb(XVTRACE+1, "CC1 = %08lx ", assembly );
OUTREG( SEC_STREAM_COLOR_CONVERT1, assembly );
k4 = (int)(dk4+0.5) & 0x1ff;
k5 = (int)(dk5+0.5) & 0x1ff;
k6 = (int)(dk6+0.5) & 0x1ff;
assembly = (k6<<18) | (k5<<9) | k4;
xf86ErrorFVerb(XVTRACE+1, "CC2 = %08lx ", assembly );
OUTREG( SEC_STREAM_COLOR_CONVERT2, assembly );
k7 = (int)(dk7+0.5) & 0x1ff;
kb = (int)(dkb+0.5) & 0xffff;
assembly = (kb<<9) | k7;
xf86ErrorFVerb(XVTRACE+1, "CC3 = %08lx\n", assembly );
OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly );
}
void SavageResetVideo(ScrnInfoPtr pScrn)
{
xf86ErrorFVerb(XVTRACE,"SavageResetVideo\n");
SavageSetColor( pScrn );
SavageSetColorKey( pScrn );
}
static XF86VideoAdaptorPtr
SavageSetupImageVideo(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
SavagePtr psav = SAVPTR(pScrn);
XF86VideoAdaptorPtr adapt;
SavagePortPrivPtr pPriv;
xf86ErrorFVerb(XVTRACE,"SavageSetupImageVideo\n");
if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
sizeof(SavagePortPrivRec) +
sizeof(DevUnion))))
return NULL;
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
adapt->name = "Savage Streams Engine";
adapt->nEncodings = 1;
adapt->pEncodings = DummyEncoding;
adapt->nFormats = NUM_FORMATS;
adapt->pFormats = Formats;
adapt->nPorts = 1;
adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
pPriv = (SavagePortPrivPtr)(&adapt->pPortPrivates[1]);
adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
adapt->pAttributes = Attributes;
adapt->nImages = NUM_IMAGES;
adapt->nAttributes = NUM_ATTRIBUTES;
adapt->pImages = Images;
adapt->PutVideo = NULL;
adapt->PutStill = NULL;
adapt->GetVideo = NULL;
adapt->GetStill = NULL;
adapt->StopVideo = SavageStopVideo;
adapt->SetPortAttribute = SavageSetPortAttribute;
adapt->GetPortAttribute = SavageGetPortAttribute;
adapt->QueryBestSize = SavageQueryBestSize;
adapt->PutImage = SavagePutImage;
adapt->QueryImageAttributes = SavageQueryImageAttributes;
xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
xvContrast = MAKE_ATOM("XV_CONTRAST");
xvColorKey = MAKE_ATOM("XV_COLORKEY");
xvHue = MAKE_ATOM("XV_HUE");
xvSaturation = MAKE_ATOM("XV_SATURATION");
pPriv->colorKey =
(1 << pScrn->offset.red) |
(1 << pScrn->offset.green) |
(((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
pPriv->videoStatus = 0;
pPriv->brightness = 0;
pPriv->contrast = 128;
pPriv->saturation = 128;
#if 0
pPriv->brightness = 64;
pPriv->contrast = 16;
pPriv->saturation = 128;
#endif
pPriv->hue = 0;
pPriv->lastKnownPitch = 0;
REGION_NULL(pScreen, &pPriv->clip);
psav->adaptor = adapt;
#if 0
psav->BlockHandler = pScreen->BlockHandler;
pScreen->BlockHandler = SavageBlockHandler;
#endif
return adapt;
}
static void
SavageClipVideo(
BoxPtr dst,
INT32 *x1,
INT32 *x2,
INT32 *y1,
INT32 *y2,
BoxPtr extents,
INT32 width,
INT32 height
){
INT32 vscale, hscale, delta;
int diff;
hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
*x1 <<= 16; *x2 <<= 16;
*y1 <<= 16; *y2 <<= 16;
diff = extents->x1 - dst->x1;
if(diff > 0) {
dst->x1 = extents->x1;
*x1 += diff * hscale;
}
diff = dst->x2 - extents->x2;
if(diff > 0) {
dst->x2 = extents->x2;
*x2 -= diff * hscale;
}
diff = extents->y1 - dst->y1;
if(diff > 0) {
dst->y1 = extents->y1;
*y1 += diff * vscale;
}
diff = dst->y2 - extents->y2;
if(diff > 0) {
dst->y2 = extents->y2;
*y2 -= diff * vscale;
}
if(*x1 < 0) {
diff = (- *x1 + hscale - 1)/ hscale;
dst->x1 += diff;
*x1 += diff * hscale;
}
delta = *x2 - (width << 16);
if(delta > 0) {
diff = (delta + hscale - 1)/ hscale;
dst->x2 -= diff;
*x2 -= diff * hscale;
}
if(*y1 < 0) {
diff = (- *y1 + vscale - 1)/ vscale;
dst->y1 += diff;
*y1 += diff * vscale;
}
delta = *y2 - (height << 16);
if(delta > 0) {
diff = (delta + vscale - 1)/ vscale;
dst->y2 -= diff;
*y2 -= diff * vscale;
}
}
static void
SavageStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
{
SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
xf86ErrorFVerb(XVTRACE,"SavageStopVideo\n");
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
if(shutdown) {
SavageStreamsOff( pScrn );
if(pPriv->area) {
xf86FreeOffscreenArea(pPriv->area);
pPriv->area = NULL;
}
pPriv->videoStatus = 0;
} else {
if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
pPriv->videoStatus |= OFF_TIMER;
pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
}
}
}
static int
SavageSetPortAttribute(
ScrnInfoPtr pScrn,
Atom attribute,
INT32 value,
pointer data
){
SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
SavagePtr psav = SAVPTR(pScrn);
if(attribute == xvColorKey) {
pPriv->colorKey = value;
if( psav->videoFlags & VF_STREAMS_ON)
SavageSetColorKey( pScrn );
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
}
else if( attribute == xvBrightness) {
if((value < -128) || (value > 127))
return BadValue;
pPriv->brightness = value;
if( psav->videoFlags & VF_STREAMS_ON)
SavageSetColor( pScrn );
}
else if( attribute == xvContrast) {
if((value < 0) || (value > 255))
return BadValue;
pPriv->contrast = value;
if( psav->videoFlags & VF_STREAMS_ON)
SavageSetColor( pScrn );
}
else if( attribute == xvSaturation) {
if((value < 0) || (value > 255))
return BadValue;
pPriv->saturation = value;
if( psav->videoFlags & VF_STREAMS_ON)
SavageSetColor( pScrn );
}
else if( attribute == xvHue) {
if((value < -180) || (value > 180))
return BadValue;
pPriv->hue = value;
if( psav->videoFlags & VF_STREAMS_ON)
SavageSetColor( pScrn );
}
else
return BadMatch;
return Success;
}
static int
SavageGetPortAttribute(
ScrnInfoPtr pScrn,
Atom attribute,
INT32 *value,
pointer data
){
SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
if(attribute == xvColorKey) {
*value = pPriv->colorKey;
}
else if( attribute == xvBrightness ) {
*value = pPriv->brightness;
}
else if( attribute == xvContrast ) {
*value = pPriv->contrast;
}
else if( attribute == xvHue ) {
*value = pPriv->hue;
}
else if( attribute == xvSaturation ) {
*value = pPriv->saturation;
}
else return BadMatch;
return Success;
}
static void
SavageQueryBestSize(
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
){
*p_w = drw_w;
*p_h = drw_h;
if(*p_w > 16384) *p_w = 16384;
}
static void
SavageCopyData(
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
SavageCopyPlanarData(
unsigned char *src1,
unsigned char *src2,
unsigned char *src3,
unsigned char *dst1,
int srcPitch,
int srcPitch2,
int dstPitch,
int h,
int w
){
CARD32 *dst = (CARD32*)dst1;
int i, j;
dstPitch >>= 2;
w >>= 1;
for(j = 0; j < h; j++) {
for(i = 0; i < w; i++) {
#if 1
dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
(src3[i] << 8) | (src2[i] << 24);
#else
dst[i] = (src1[i << 1] << 24) | (src1[(i << 1) + 1] << 8) |
(src3[i] << 0) | (src2[i] << 16);
#endif
}
dst += dstPitch;
src1 += srcPitch;
if(j & 1) {
src2 += srcPitch2;
src3 += srcPitch2;
}
}
}
static FBAreaPtr
SavageAllocateMemory(
ScrnInfoPtr pScrn,
FBAreaPtr area,
int numlines
){
ScreenPtr pScreen;
FBAreaPtr new_area;
if(area) {
if((area->box.y2 - area->box.y1) >= numlines)
return area;
if(xf86ResizeOffscreenArea(area, pScrn->displayWidth, numlines))
return area;
xf86FreeOffscreenArea(area);
}
pScreen = screenInfo.screens[pScrn->scrnIndex];
xf86PurgeUnlockedOffscreenAreas(pScreen);
new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
numlines, 0, NULL, NULL, NULL);
if(!new_area) {
int max_w, max_h;
xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0,
FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME);
if((max_w < pScrn->displayWidth) || (max_h < numlines))
return NULL;
xf86PurgeUnlockedOffscreenAreas(pScreen);
new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
numlines, 0, NULL, NULL, NULL);
}
return new_area;
}
static void
SavageDisplayVideoOld(
ScrnInfoPtr pScrn,
int id,
int offset,
short width, short height,
int pitch,
int x1, int y1, int x2, int y2,
BoxPtr dstBox,
short src_w, short src_h,
short drw_w, short drw_h
){
SavagePtr psav = SAVPTR(pScrn);
vgaHWPtr hwp = VGAHWPTR(pScrn);
SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
int vgaCRIndex, vgaCRReg, vgaIOBase;
unsigned int ssControl;
vgaIOBase = hwp->IOBase;
vgaCRIndex = vgaIOBase + 4;
vgaCRReg = vgaIOBase + 5;
if( psav->videoFourCC != id )
SavageStreamsOff(pScrn);
if( !psav->videoFlags & VF_STREAMS_ON )
{
SavageStreamsOn(pScrn, id);
SavageResetVideo(pScrn);
}
OUTREG(SSTREAM_CONTROL_REG,
(GetBlendForFourCC(psav->videoFourCC) << 24) + src_w );
OUTREG(SSTREAM_STRETCH_REG, (src_w << 15) / drw_w );
OUTREG(SSTREAM_LINES_REG, src_h );
OUTREG(SSTREAM_VINITIAL_REG, 0 );
OUTREG(SSTREAM_VSCALE_REG, (src_h << 15) / drw_h );
OUTREG(SSTREAM_FBADDR0_REG, (offset + (x1>>15)) & 0x3ffff0 );
OUTREG(SSTREAM_FBADDR1_REG, 0 );
OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff );
OUTREG(SSTREAM_WINDOW_START_REG, OS_XY(dstBox->x1, dstBox->y1) );
OUTREG(SSTREAM_WINDOW_SIZE_REG, OS_WH(drw_w, drw_h) );
ssControl = 0;
if( src_w > (drw_w << 1) )
{
if( src_w <= (drw_w << 2) )
ssControl |= HDSCALE_4;
else if( src_w <= (drw_w << 3) )
ssControl |= HDSCALE_8;
else if( src_w <= (drw_w << 4) )
ssControl |= HDSCALE_16;
else if( src_w <= (drw_w << 5) )
ssControl |= HDSCALE_32;
else if( src_w <= (drw_w << 6) )
ssControl |= HDSCALE_64;
}
ssControl |= src_w;
ssControl |= (1 << 24);
OUTREG(SSTREAM_CONTROL_REG, ssControl);
#if 0
SavageSetColorKey( pScrn );
#endif
if( pPriv->lastKnownPitch != pitch )
{
unsigned char cr92;
pPriv->lastKnownPitch = pitch;
pitch = (pitch + 7) / 8;
VGAOUT8(vgaCRIndex, 0x92);
cr92 = VGAIN8(vgaCRReg);
VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
VGAOUT8(vgaCRIndex, 0x93);
VGAOUT8(vgaCRReg, pitch);
}
}
static void
SavageDisplayVideoNew(
ScrnInfoPtr pScrn,
int id,
int offset,
short width, short height,
int pitch,
int x1, int y1, int x2, int y2,
BoxPtr dstBox,
short src_w, short src_h,
short drw_w, short drw_h
){
SavagePtr psav = SAVPTR(pScrn);
vgaHWPtr hwp = VGAHWPTR(pScrn);
SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
int vgaCRIndex, vgaCRReg, vgaIOBase;
vgaIOBase = hwp->IOBase;
vgaCRIndex = vgaIOBase + 4;
vgaCRReg = vgaIOBase + 5;
if( psav->videoFourCC != id )
SavageStreamsOff(pScrn);
if( !psav->videoFlags & VF_STREAMS_ON )
{
SavageStreamsOn(pScrn, id);
SavageResetVideo(pScrn);
}
if( psav->Chipset == S3_SAVAGE2000 )
{
OUTREG(SEC_STREAM_HSCALING,
(65536 * src_w / drw_w) & 0x1FFFFF );
if( src_w < drw_w )
OUTREG(SEC_STREAM_HSCALE_NORMALIZE,
((2048 * src_w / drw_w) & 0x7ff) << 16 );
else
OUTREG(SEC_STREAM_HSCALE_NORMALIZE, 2048 << 16 );
OUTREG(SEC_STREAM_VSCALING,
(65536 * src_h / drw_h) & 0x1FFFFF );
}
else
{
if(
S3_SAVAGE_MOBILE_SERIES(psav->Chipset) &&
!psav->CrtOnly &&
!psav->TvOn
) {
drw_w = (drw_w * psav->XExp1)/psav->XExp2 + 1;
drw_h = (drw_h * psav->YExp1)/psav->YExp2 + 1;
dstBox->x1 = (dstBox->x1 * psav->XExp1)/psav->XExp2;
dstBox->y1 = (dstBox->y1 * psav->YExp1)/psav->YExp2;
dstBox->x1 += psav->displayXoffset;
dstBox->y1 += psav->displayYoffset;
}
OUTREG(SEC_STREAM_HSCALING,
((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
OUTREG(SEC_STREAM_VSCALING,
((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
}
OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15)) & 0x7ffff0 );
OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff );
OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
OUTREG(SEC_STREAM_WINDOW_SZ, ((drw_w) << 16) | drw_h );
#if 0
SavageSetColorKey( pScrn );
#endif
if( pPriv->lastKnownPitch != pitch )
{
unsigned char cr92;
pPriv->lastKnownPitch = pitch;
pitch = (pitch + 7) / 8 - 4;
VGAOUT8(vgaCRIndex, 0x92);
cr92 = VGAIN8(vgaCRReg);
VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
VGAOUT8(vgaCRIndex, 0x93);
VGAOUT8(vgaCRReg, pitch);
}
}
static int
SavagePutImage(
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
){
SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
SavagePtr psav = SAVPTR(pScrn);
ScreenPtr pScreen = pScrn->pScreen;
INT32 x1, x2, y1, y2;
unsigned char *dst_start;
int pitch, new_h, offset, offsetV=0, offsetU=0;
int srcPitch, srcPitch2=0, dstPitch;
int top, left, npixels, nlines;
BoxRec dstBox;
CARD32 tmp;
if( psav->cxScreen != pScrn->currentMode->HDisplay )
{
if(
S3_SAVAGE_MOBILE_SERIES(psav->Chipset) &&
!psav->CrtOnly &&
!psav->TvOn
) {
OverlayParamInit( pScrn );
}
}
if(drw_w > 16384) drw_w = 16384;
x1 = src_x;
x2 = src_x + src_w;
y1 = src_y;
y2 = src_y + src_h;
dstBox.x1 = drw_x;
dstBox.x2 = drw_x + drw_w;
dstBox.y1 = drw_y;
dstBox.y2 = drw_y + drw_h;
SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
REGION_EXTENTS(pScreen, clipBoxes), width, height);
drw_w = dstBox.x2 - dstBox.x1;
drw_h = dstBox.y2 - dstBox.y1;
src_w = ( x2 - x1 ) >> 16;
src_h = ( y2 - y1 ) >> 16;
if((x1 >= x2) || (y1 >= y2))
return Success;
dstBox.x1 -= pScrn->frameX0;
dstBox.x2 -= pScrn->frameX0;
dstBox.y1 -= pScrn->frameY0;
dstBox.y2 -= pScrn->frameY0;
pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
dstPitch = ((width << 1) + 15) & ~15;
new_h = ((dstPitch * height) + pitch - 1) / pitch;
switch(id) {
case FOURCC_Y211:
srcPitch = width;
break;
case FOURCC_YV12:
srcPitch = (width + 3) & ~3;
offsetV = srcPitch * height;
srcPitch2 = ((width >> 1) + 3) & ~3;
offsetU = (srcPitch2 * (height >> 1)) + offsetV;
break;
case FOURCC_I420:
srcPitch = (width + 3) & ~3;
offsetU = srcPitch * height;
srcPitch2 = ((width >> 1) + 3) & ~3;
offsetV = (srcPitch2 * (height >> 1)) + offsetU;
break;
case FOURCC_RV15:
case FOURCC_RV16:
case FOURCC_YUY2:
default:
srcPitch = (width << 1);
break;
}
if(!(pPriv->area = SavageAllocateMemory(pScrn, pPriv->area, new_h)))
return BadAlloc;
top = y1 >> 16;
left = (x1 >> 16) & ~1;
npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
left <<= 1;
offset = (pPriv->area->box.y1 * pitch) + (top * dstPitch);
dst_start = psav->FBBase + offset + left;
switch(id) {
case FOURCC_YV12:
case FOURCC_I420:
top &= ~1;
tmp = ((top >> 1) * srcPitch2) + (left >> 2);
offsetU += tmp;
offsetV += tmp;
nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
SavageCopyPlanarData(
buf + (top * srcPitch) + (left >> 1),
buf + offsetV,
buf + offsetU,
dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels);
break;
case FOURCC_Y211:
case FOURCC_RV15:
case FOURCC_RV16:
case FOURCC_YUY2:
default:
buf += (top * srcPitch) + left;
nlines = ((y2 + 0xffff) >> 16) - top;
SavageCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
break;
}
SavageDisplayVideo(pScrn, id, offset, width, height, dstPitch,
x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
if(!REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes)) {
REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
}
pPriv->videoStatus = CLIENT_VIDEO_ON;
return Success;
}
static int
SavageQueryImageAttributes(
ScrnInfoPtr pScrn,
int id,
unsigned short *w, unsigned short *h,
int *pitches, int *offsets
){
int size, tmp;
if(*w > 1024) *w = 1024;
if(*h > 1024) *h = 1024;
*w = (*w + 1) & ~1;
if(offsets) offsets[0] = 0;
switch(id) {
case FOURCC_Y211:
size = *w << 2;
if(pitches) pitches[0] = size;
size *= *h;
break;
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_RV15:
case FOURCC_RV16:
case FOURCC_YUY2:
default:
size = *w << 1;
if(pitches) pitches[0] = size;
size *= *h;
break;
}
return size;
}
#if 0
static void
CHIPSBlockHandler (
int i,
pointer blockData,
pointer pTimeout,
pointer pReadmask
){
ScreenPtr pScreen = screenInfo.screens[i];
ScrnInfoPtr pScrn = xf86Screens[i];
CHIPSPtr cPtr = CHIPSPTR(pScrn);
CHIPSPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
unsigned char mr3c;
pScreen->BlockHandler = cPtr->BlockHandler;
(*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
pScreen->BlockHandler = CHIPSBlockHandler;
CHIPSHiQVSync(pScrn);
if(pPriv->videoStatus & TIMER_MASK) {
UpdateCurrentTime();
if(pPriv->videoStatus & OFF_TIMER) {
if(pPriv->offTime < currentTime.milliseconds) {
mr3c = cPtr->readMR(cPtr, 0x3C);
cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE));
pPriv->videoStatus = FREE_TIMER;
pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
}
} else {
if(pPriv->freeTime < currentTime.milliseconds) {
if(pPriv->area) {
xf86FreeOffscreenArea(pPriv->area);
pPriv->area = NULL;
}
pPriv->videoStatus = 0;
}
}
}
}
#endif
typedef struct {
FBAreaPtr area;
Bool isOn;
} OffscreenPrivRec, * OffscreenPrivPtr;
static int
SavageAllocateSurface(
ScrnInfoPtr pScrn,
int id,
unsigned short w,
unsigned short h,
XF86SurfacePtr surface
){
FBAreaPtr area;
int pitch, fbpitch, numlines;
OffscreenPrivPtr pPriv;
if((w > 1024) || (h > 1024))
return BadAlloc;
w = (w + 1) & ~1;
pitch = ((w << 1) + 15) & ~15;
fbpitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
numlines = ((pitch * h) + fbpitch - 1) / fbpitch;
if(!(area = SavageAllocateMemory(pScrn, NULL, numlines)))
return BadAlloc;
surface->width = w;
surface->height = h;
if(!(surface->pitches = xalloc(sizeof(int))))
return BadAlloc;
if(!(surface->offsets = xalloc(sizeof(int)))) {
xfree(surface->pitches);
return BadAlloc;
}
if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
xfree(surface->pitches);
xfree(surface->offsets);
return BadAlloc;
}
pPriv->area = area;
pPriv->isOn = FALSE;
surface->pScrn = pScrn;
surface->id = id;
surface->pitches[0] = pitch;
surface->offsets[0] = area->box.y1 * fbpitch;
surface->devPrivate.ptr = (pointer)pPriv;
return Success;
}
static int
SavageStopSurface(
XF86SurfacePtr surface
){
OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
xf86ErrorFVerb(XVTRACE,"SavageStopSurface\n");
if(pPriv->isOn) {
SavageStreamsOff( surface->pScrn );
pPriv->isOn = FALSE;
}
return Success;
}
static int
SavageFreeSurface(
XF86SurfacePtr surface
){
OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
if(pPriv->isOn)
SavageStopSurface(surface);
xf86FreeOffscreenArea(pPriv->area);
xfree(surface->pitches);
xfree(surface->offsets);
xfree(surface->devPrivate.ptr);
return Success;
}
static int
SavageGetSurfaceAttribute(
ScrnInfoPtr pScrn,
Atom attribute,
INT32 *value
){
return SavageGetPortAttribute(pScrn, attribute, value,
(pointer)(GET_PORT_PRIVATE(pScrn)));
}
static int
SavageSetSurfaceAttribute(
ScrnInfoPtr pScrn,
Atom attribute,
INT32 value
){
return SavageSetPortAttribute(pScrn, attribute, value,
(pointer)(GET_PORT_PRIVATE(pScrn)));
}
static int
SavageDisplaySurface(
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;
ScreenPtr pScreen = pScrn->pScreen;
SavagePortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn);
INT32 x1, y1, x2, y2;
BoxRec dstBox;
xf86ErrorFVerb(XVTRACE,"SavageDisplaySurface\n");
x1 = src_x;
x2 = src_x + src_w;
y1 = src_y;
y2 = src_y + src_h;
dstBox.x1 = drw_x;
dstBox.x2 = drw_x + drw_w;
dstBox.y1 = drw_y;
dstBox.y2 = drw_y + drw_h;
SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
REGION_EXTENTS(pScreen, clipBoxes),
surface->width, surface->height);
if((x1 >= x2) || (y1 >= y2))
return Success;
dstBox.x1 -= pScrn->frameX0;
dstBox.x2 -= pScrn->frameX0;
dstBox.y1 -= pScrn->frameY0;
dstBox.y2 -= pScrn->frameY0;
SavageDisplayVideo(pScrn, surface->id, surface->offsets[0],
surface->width, surface->height, surface->pitches[0],
x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
pPriv->isOn = TRUE;
#if 0
if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
REGION_EMPTY(pScreen, &portPriv->clip);
UpdateCurrentTime();
portPriv->videoStatus = FREE_TIMER;
portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
}
#endif
return Success;
}
static void
SavageInitOffscreenImages(ScreenPtr pScreen)
{
XF86OffscreenImagePtr offscreenImages;
SavagePtr psav = SAVPTR(xf86Screens[pScreen->myNum]);
if (!psav->offscreenImages) {
if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
return;
psav->offscreenImages = offscreenImages;
} else {
offscreenImages = psav->offscreenImages;
}
offscreenImages[0].image = &Images[0];
offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
VIDEO_CLIP_TO_VIEWPORT;
offscreenImages[0].alloc_surface = SavageAllocateSurface;
offscreenImages[0].free_surface = SavageFreeSurface;
offscreenImages[0].display = SavageDisplaySurface;
offscreenImages[0].stop = SavageStopSurface;
offscreenImages[0].setAttribute = SavageSetSurfaceAttribute;
offscreenImages[0].getAttribute = SavageGetSurfaceAttribute;
offscreenImages[0].max_width = 1024;
offscreenImages[0].max_height = 1024;
offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
offscreenImages[0].attributes = Attributes;
xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
}
static void OverlayParamInit(ScrnInfoPtr pScrn)
{
SavagePtr psav = SAVPTR(pScrn);
psav = SAVPTR(pScrn);
psav->cxScreen = pScrn->currentMode->HDisplay;
InitStreamsForExpansion(pScrn);
}
static void InitStreamsForExpansion(ScrnInfoPtr pScrn)
{
SavagePtr psav = SAVPTR(pScrn);
int PanelSizeX,PanelSizeY;
int ViewPortWidth,ViewPortHeight;
int XExpansion, YExpansion;
int XFactor, YFactor;
int Hstate, Vstate;
static CARD32 Xfactors[] = {
0x00010001,
0x00010001,
0,
0x00090008,
0x00050004,
0,
0x00030002,
0x00020001
};
static CARD32 Yfactors[] = {
0x00010001, 0x00010001,
0, 0x00060005,
0x00050004, 0x00040003,
0, 0x00030002,
0x00020001, 0x00050002,
0x000C0005, 0x00080003,
0x00090004, 0,
0x00030001, 0x00040001,
};
PanelSizeX = psav->PanelX;
PanelSizeY = psav->PanelY;
ViewPortWidth = pScrn->currentMode->HDisplay;
ViewPortHeight = pScrn->currentMode->VDisplay;
if( PanelSizeX == 1408 )
PanelSizeX = 1400;
XExpansion = 0x00010001;
YExpansion = 0x00010001;
psav->displayXoffset = 0;
psav->displayYoffset = 0;
VGAOUT8(0x3C4, HZEXP_COMP_1);
Hstate = VGAIN8(0x3C5);
VGAOUT8(0x3C4, VTEXP_COMP_1);
Vstate = VGAIN8(0x3C5);
VGAOUT8(0x3C4, HZEXP_FACTOR_IGA1);
XFactor = VGAIN8(0x3C5);
VGAOUT8(0x3C4, VTEXP_FACTOR_IGA1);
YFactor = VGAIN8(0x3C5);
if( Hstate & EC1_EXPAND_ON )
{
XExpansion = Xfactors[XFactor>>4];
}
if( Vstate & EC1_EXPAND_ON )
{
YExpansion = Yfactors[YFactor>>4];
}
psav->XExp1 = XExpansion >> 16;
psav->XExp2 = XExpansion & 0xFFFF;
psav->YExp1 = YExpansion >> 16;
psav->YExp2 = YExpansion & 0xFFFF;
psav->displayXoffset =
((PanelSizeX - (psav->XExp1 * ViewPortWidth) / psav->XExp2) / 2 + 7) & 0xfff8;
psav->displayYoffset =
((PanelSizeY - (psav->YExp1 * ViewPortHeight) / psav->YExp2) / 2);
}