summaryrefslogtreecommitdiff
path: root/src/savage_video.c
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
commitbe3817e94d5c31cd15aa4785cb5b0bdefc45141c (patch)
tree1c89ec3834e348b290ffa7a7c5ddb11958ed5360 /src/savage_video.c
Initial revisionXORG-STABLE
Diffstat (limited to 'src/savage_video.c')
-rw-r--r--src/savage_video.c1982
1 files changed, 1982 insertions, 0 deletions
diff --git a/src/savage_video.c b/src/savage_video.c
new file mode 100644
index 0000000..38c2cc3
--- /dev/null
+++ b/src/savage_video.c
@@ -0,0 +1,1982 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/savage/savage_video.c,v 1.11 2003/01/12 03:55:49 tsi Exp $ */
+
+#include "Xv.h"
+#include "dix.h"
+#include "dixstruct.h"
+#include "fourcc.h"
+#include "xaalocal.h"
+
+#include "savage_driver.h"
+
+#define OFF_DELAY 200 /* milliseconds */
+#define FREE_DELAY 60000
+
+#define OFF_TIMER 0x01
+#define FREE_TIMER 0x02
+#define CLIENT_VIDEO_ON 0x04
+
+#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
+
+#ifndef XvExtension
+void SavageInitVideo(ScreenPtr pScreen) {}
+void SavageResetVideo(ScrnInfoPtr pScrn) {}
+#else
+
+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(SavagePtr psav);
+
+/*static void SavageBlockHandler(int, pointer, pointer, pointer);*/
+
+#define XVTRACE 4
+
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+static Atom xvColorKey, xvBrightness, xvContrast, xvSaturation, xvHue;
+
+/* client libraries expect an encoding */
+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
+
+/*
+ * For completeness sake, here is a cracking of the fourcc's I support.
+ *
+ * YUY2, packed 4:2:2, byte order: Y0 U0 Y1 V0 Y2 U2 Y3 V2
+ * Y211, packed 2:1:1, byte order: Y0 U0 Y2 V0 Y4 U2 Y6 V2
+ * YV12, planar 4:1:1, Y plane HxW, V plane H/2xW/2, U plane H/2xW/2
+ * I420, planar 4:1:1, Y plane HxW, U plane H/2xW/2, V plane H/2xW/2
+ * (I420 is also known as IYUV)
+ */
+
+
+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; /* -128 .. 127 */
+ CARD32 contrast; /* 0 .. 255 */
+ CARD32 saturation; /* 0 .. 255 */
+ int hue; /* -128 .. 127 */
+
+ 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)
+
+/**************************************
+ S3 streams processor
+**************************************/
+
+#define EXT_MISC_CTRL2 0x67
+
+/* New streams */
+
+/* CR67[2] = 1 : enable stream 1 */
+#define ENABLE_STREAM1 0x04
+/* CR67[1] = 1 : enable stream 2 */
+#define ENABLE_STREAM2 0x02
+/* mask to clear CR67[2,1] */
+#define NO_STREAMS 0xF9
+/* CR67[3] = 1 : Mem-mapped regs */
+#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)
+
+/* Old Streams */
+
+#define ENABLE_STREAMS_OLD 0x0c
+#define NO_STREAMS_OLD 0xf3
+/* CR69[0] = 1 : Mem-mapped regs */
+#define USE_MM_FOR_PRI_STREAM_OLD 0x01
+
+
+/*
+ * There are two different streams engines used in the Savage line.
+ * The old engine is in the 3D, 4, Pro, and Twister.
+ * The new engine is in the 2000, MX, IX, and Super.
+ */
+
+
+/* streams registers for old engine */
+#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 %04x, was %08x, want %08x,",
+ offset, MMIO_IN32( psav->MapBase, offset ), value );
+ MMIO_OUT32( psav->MapBase, offset, value );
+ ErrorF( " now %08x\n", MMIO_IN32( psav->MapBase, offset ) );
+}
+
+void SavageInitStreamsOld(ScrnInfoPtr pScrn)
+{
+ SavagePtr psav = SAVPTR(pScrn);
+ unsigned long jDelta;
+ unsigned long format = 0;
+
+ /*
+ * For the OLD streams engine, several of these registers
+ * cannot be touched unless streams are on. Seems backwards to me;
+ * I'd want to set 'em up, then cut 'em loose.
+ */
+
+ xf86ErrorFVerb(XVTRACE, "SavageInitStreams\n" );
+
+ /* Primary stream reflects the frame buffer. */
+
+ 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_FBSIZE_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 );
+ }
+
+ /* Primary stream reflects the frame buffer. */
+
+ 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_BUFFERSIZE, 0 ); */
+ OUTREG( SEC_STREAM_TILE_OFF, 0 );
+ OUTREG( SEC_STREAM_OPAQUE_OVERLAY, 0 );
+ OUTREG( SEC_STREAM_STRIDE, 0 );
+
+ /* These values specify brightness, contrast, saturation and hue. */
+ 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" );
+
+ /* Sequence stolen from streams.c in M7 NT driver */
+
+
+ xf86EnableIO();
+
+ /* Unlock extended registers. */
+
+ 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 ) | ENABLE_STREAM1;
+
+ /* Wait for VBLANK. */
+
+ VerticalRetraceWait(psav);
+
+ /* Fire up streams! */
+
+ VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 );
+
+ psav->blendBase = GetBlendForFourCC( id ) << 9;
+ xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", &id, psav->blendBase );
+ OUTREG( BLEND_CONTROL, psav->blendBase | 0x08 );
+
+ /* These values specify brightness, contrast, saturation and hue. */
+ 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;
+
+ /* Wait for VBLANK. */
+
+ VerticalRetraceWait(psav);
+
+ /* Fire up streams! */
+
+ VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 );
+
+ SavageInitStreamsOld( pScrn );
+ }
+
+ /* Wait for VBLANK. */
+
+ VerticalRetraceWait(psav);
+
+ /* Turn on secondary stream TV flicker filter, once we support TV. */
+
+ /* SR70 |= 0x10 */
+
+ 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();
+
+ /* Unlock extended registers. */
+
+ 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;
+
+ /* Wait for VBLANK. */
+
+ VerticalRetraceWait(psav);
+
+ /* Kill streams. */
+
+ 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);
+ /*DELETENEXTLINE*/
+ /* Since newAdaptor is still NULL, these are still disabled for now. */
+ 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 = /* need to free this someplace */
+ 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;
+
+ /* Here, we reset the colorkey and all the controls. */
+
+ 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;
+ }
+
+ /* We use destination colorkey */
+ OUTREG( BLEND_CONTROL_REG, 0x05000000 );
+ }
+}
+
+void SavageSetColorKeyNew(ScrnInfoPtr pScrn)
+{
+ SavagePtr psav = SAVPTR(pScrn);
+ SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
+ int red, green, blue;
+
+ /* Here, we reset the colorkey and all the controls. */
+
+ 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;
+ }
+
+ /* We assume destination colorkey */
+ 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, pPriv->contrast, pPriv->saturation, pPriv->hue );
+
+ if(
+ (psav->videoFourCC == FOURCC_RV15) ||
+ (psav->videoFourCC == FOURCC_RV16)
+ )
+ {
+ OUTREG( COLOR_ADJUSTMENT_REG, 0 );
+ }
+ else
+ {
+ /* Change 0..255 into 0..15 */
+ 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;
+
+ /* Brightness/contrast/saturation/hue computations. */
+
+ 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, pPriv->contrast, pPriv->saturation, pPriv->hue );
+
+ if( psav->videoFourCC == FOURCC_Y211 )
+ k = 1.0; /* YUV */
+ else
+ k = 1.14; /* YCrCb */
+
+ /*
+ * The S3 documentation must be wrong for k4 and k5. Their default
+ * values, which they hardcode in their Windows driver, have the
+ * opposite sign from the results in the register spec.
+ */
+
+ 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); /* == k3 / 1.26331, right? */
+ dk7 = 64.0 * 1.732 * k * s * cos(h); /* == k2 / -1.26331, right? */
+ 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 = %08x ", 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 = %08x ", 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 = %08x\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
+ /*
+ * The S3 driver has these values for some of the chips. I have yet
+ * to find any Savage where these make sense.
+ */
+ pPriv->brightness = 64;
+ pPriv->contrast = 16;
+ pPriv->saturation = 128;
+#endif
+ pPriv->hue = 0;
+ pPriv->lastKnownPitch = 0;
+
+ /* gotta uninit this someplace */
+ REGION_INIT(pScreen, &pPriv->clip, NullBox, 0);
+
+ psav->adaptor = adapt;
+
+#if 0
+ psav->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = SavageBlockHandler;
+#endif
+
+ return adapt;
+}
+
+
+static Bool
+RegionsEqual(RegionPtr A, RegionPtr B)
+{
+ int *dataA, *dataB;
+ int num;
+
+ num = REGION_NUM_RECTS(A);
+ if(num != REGION_NUM_RECTS(B))
+ return FALSE;
+
+ if((A->extents.x1 != B->extents.x1) ||
+ (A->extents.x2 != B->extents.x2) ||
+ (A->extents.y1 != B->extents.y1) ||
+ (A->extents.y2 != B->extents.y2))
+ return FALSE;
+
+ dataA = (int*)REGION_RECTS(A);
+ dataB = (int*)REGION_RECTS(B);
+
+ while(num--) {
+ if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
+ return FALSE;
+ dataA += 2;
+ dataB += 2;
+ }
+
+ return TRUE;
+}
+
+
+/* SavageClipVideo -
+
+ Takes the dst box in standard X BoxRec form (top and left
+ edges inclusive, bottom and right exclusive). The new dst
+ box is returned. The source boundaries are given (x1, y1
+ inclusive, x2, y2 exclusive) and returned are the new source
+ boundaries in 16.16 fixed point.
+*/
+
+static void
+SavageClipVideo(
+ BoxPtr dst,
+ INT32 *x1,
+ INT32 *x2,
+ INT32 *y1,
+ INT32 *y2,
+ BoxPtr extents, /* extents of the clip region */
+ 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;
+ /*SavagePtr psav = SAVPTR(pScrn); */
+
+ xf86ErrorFVerb(XVTRACE,"SavageStopVideo\n");
+
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+
+ SavageStreamsOff( pScrn );
+
+ if(shutdown) {
+ 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
+){
+ /* What are the real limits for the Savage? */
+
+ *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, /* Y */
+ unsigned char *src2, /* V */
+ unsigned char *src3, /* U */
+ 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++) {
+/* Shouldn't this be 'if LITTLEENDIAN'? */
+#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;
+ /*DisplayModePtr mode = pScrn->currentMode;*/
+ 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);
+ }
+
+ /* Set surface format. */
+
+ OUTREG(SSTREAM_CONTROL_REG,
+ (GetBlendForFourCC(psav->videoFourCC) << 24) + src_w );
+
+ /* Calculate horizontal scale factor. */
+
+ OUTREG(SSTREAM_STRETCH_REG, (src_w << 15) / drw_w );
+
+ /* Calculate vertical scale factor. */
+
+ OUTREG(SSTREAM_LINES_REG, src_h );
+ OUTREG(SSTREAM_VINITIAL_REG, 0 );
+ OUTREG(SSTREAM_VSCALE_REG, (src_h << 15) / drw_h );
+
+ /* Set surface location and stride. */
+
+ 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) )
+ {
+ /* BUGBUG shouldn't this be >=? */
+ 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);
+
+ /* Set color key on primary. */
+
+ SavageSetColorKey( pScrn );
+
+ /* Set FIFO L2 on second stream. */
+
+ 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);
+ /*DisplayModePtr mode = pScrn->currentMode;*/
+ 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);
+ }
+
+ /* Calculate horizontal and vertical scale factors. */
+
+ 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 = (float)(drw_w * psav->XExp1)/(float)psav->XExp2 + 1;
+ drw_h = (float)(drw_h * psav->YExp1)/(float)psav->YExp2 + 1;
+ dstBox->x1 = (float)(dstBox->x1 * psav->XExp1)/(float)psav->XExp2;
+ dstBox->y1 = (float)(dstBox->y1 * psav->YExp1)/(float)psav->YExp2;
+ dstBox->x1 += psav->displayXoffset;
+ dstBox->y1 += psav->displayYoffset;
+ }
+
+ OUTREG(SEC_STREAM_HSCALING,
+ ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
+ /* BUGBUG need to add 00040000 if src stride > 2048 */
+ OUTREG(SEC_STREAM_VSCALING,
+ ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
+ }
+
+ /*
+ * Set surface location and stride. We use x1>>15 because all surfaces
+ * are 2 bytes/pixel.
+ */
+
+ OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15)) & 0x3ffff0 );
+ 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 );
+
+ /* Set color key on primary. */
+
+ SavageSetColorKey( pScrn );
+
+ /* Set FIFO L2 on second stream. */
+
+ 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);
+ 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(drw_w > 16384) drw_w = 16384;
+
+ /* Clip */
+ 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: /* Y211 */
+ srcPitch = width;
+ break;
+ case FOURCC_YV12: /* 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: /* RGB15 */
+ case FOURCC_RV16: /* RGB16 */
+ case FOURCC_YUY2: /* YUY2 */
+ default:
+ srcPitch = (width << 1);
+ break;
+ }
+
+ if(!(pPriv->area = SavageAllocateMemory(pScrn, pPriv->area, new_h)))
+ return BadAlloc;
+
+ /* copy data */
+ 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: /* 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: /* Y211 */
+ case FOURCC_RV15: /* RGB15 */
+ case FOURCC_RV16: /* RGB16 */
+ case FOURCC_YUY2: /* YUY2 */
+ default:
+ buf += (top * srcPitch) + left;
+ nlines = ((y2 + 0xffff) >> 16) - top;
+ SavageCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
+ break;
+ }
+
+ /* update cliplist */
+ if(!RegionsEqual(&pPriv->clip, clipBoxes)) {
+ REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
+ /* draw these */
+ XAAFillSolidRects(pScrn, pPriv->colorKey, GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes));
+ }
+
+ SavageDisplayVideo(pScrn, id, offset, width, height, dstPitch,
+ x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
+
+ 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: /* RGB15 */
+ case FOURCC_RV16: /* RGB16 */
+ 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 { /* FREE_TIMER */
+ if(pPriv->freeTime < currentTime.milliseconds) {
+ if(pPriv->area) {
+ xf86FreeOffscreenArea(pPriv->area);
+ pPriv->area = NULL;
+ }
+ pPriv->videoStatus = 0;
+ }
+ }
+ }
+}
+
+#endif
+
+/****************** Offscreen stuff ***************/
+
+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;
+
+ if(pPriv->isOn) {
+ /*SavagePtr psav = SAVPTR(surface->pScrn);*/
+ 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;
+ SavagePortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn);
+ INT32 x1, y1, x2, y2;
+ BoxRec dstBox;
+
+ 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;
+
+ XAAFillSolidRects(pScrn, portPriv->colorKey, GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes));
+
+ 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);
+
+ pPriv->isOn = TRUE;
+#if 0
+ if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
+ REGION_EMPTY(pScrn->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]);
+
+ /* need to free this someplace */
+ 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);
+}
+
+/* Function to get lcd factor, display offset for overlay use
+ * Input: pScrn; Output: x,yfactor, displayoffset in pScrn
+ */
+static void OverlayParamInit(ScrnInfoPtr pScrn)
+{
+ SavagePtr psav = SAVPTR(pScrn);
+
+ psav = SAVPTR(pScrn);
+ psav->cxScreen = psav->iResX;
+ InitStreamsForExpansion(psav);
+}
+
+/* Function to calculate lcd expansion x,yfactor and offset for overlay
+ */
+static void InitStreamsForExpansion(SavagePtr psav)
+{
+ int PanelSizeX,PanelSizeY;
+ int ViewPortWidth,ViewPortHeight;
+ int XFactor, YFactor;
+
+ PanelSizeX = psav->PanelX;
+ PanelSizeY = psav->PanelY;
+ ViewPortWidth = psav->iResX;
+ ViewPortHeight = psav->iResY;
+ if( PanelSizeX == 1408 )
+ PanelSizeX = 1400;
+ psav->XExpansion = 0x00010001;
+ psav->YExpansion = 0x00010001;
+ psav->displayXoffset = 0;
+ psav->displayYoffset = 0;
+
+ VGAOUT8(0x3C4, HZEXP_FACTOR_IGA1);
+ XFactor = VGAIN8(0x3C5) >> 4;
+ VGAOUT8(0x3C4, VTEXP_FACTOR_IGA1);
+ YFactor = VGAIN8(0x3C5) >> 4;
+
+ switch( XFactor )
+ {
+ case 1:
+ psav->XExpansion = 0x00010001;
+ psav->displayXoffset =
+ (((PanelSizeX - ViewPortWidth) / 2) + 0x7) & 0xFFF8;
+ break;
+
+ case 3:
+ psav->XExpansion = 0x00090008;
+ psav->displayXoffset =
+ (((PanelSizeX - ((9 * ViewPortWidth)/8)) / 2) + 0x7) & 0xFFF8;
+ break;
+
+ case 4:
+ psav->XExpansion = 0x00050004;
+
+ if ((psav->cxScreen == 800) && (PanelSizeX !=1400))
+ {
+ psav->displayXoffset =
+ (((PanelSizeX - ((5 * ViewPortWidth)/4)) / 2) ) & 0xFFF8;
+ }
+ else
+ {
+ psav->displayXoffset =
+ (((PanelSizeX - ((5 * ViewPortWidth)/4)) / 2) +0x7) & 0xFFF8;
+ }
+ break;
+
+ case 6:
+ psav->XExpansion = 0x00030002;
+ psav->displayXoffset =
+ (((PanelSizeX - ((3 * ViewPortWidth)/2)) / 2) + 0x7) & 0xFFF8;
+ break;
+
+ case 7:
+ psav->XExpansion = 0x00020001;
+ psav->displayXoffset =
+ (((PanelSizeX - (2 * ViewPortWidth)) / 2) + 0x7) & 0xFFF8;
+ break;
+ }
+
+ switch( YFactor )
+ {
+ case 0:
+ psav->YExpansion = 0x00010001;
+ psav->displayYoffset = (PanelSizeY - ViewPortHeight) / 2;
+ break;
+ case 1:
+ psav->YExpansion = 0x00010001;
+ psav->displayYoffset = (PanelSizeY - ViewPortHeight) / 2;
+ break;
+ case 2:
+ psav->YExpansion = 0x00040003;
+ psav->displayYoffset = (PanelSizeY - ((4 * ViewPortHeight)/3)) / 2;
+ break;
+ case 4:
+ psav->YExpansion = 0x00050004;
+ psav->displayYoffset = (PanelSizeY - ((5 * ViewPortHeight)/4)) / 2;
+ break;
+ case 5:
+ psav->YExpansion = 0x00040003;
+
+ if((psav->cxScreen == 1024)&&(PanelSizeX ==1400))
+ {
+ psav->displayYoffset =
+ ((PanelSizeY - ((4 * ViewPortHeight)/3)) / 2) - 0x1 ;
+ }
+ else
+ {
+ psav->displayYoffset = (PanelSizeY - ((4 * ViewPortHeight)/3)) / 2;
+ }
+ break;
+ case 6:
+ psav->YExpansion = 0x00050004;
+ psav->displayYoffset = (PanelSizeY - ((5 * ViewPortHeight)/4)) / 2;
+ break;
+ case 7:
+ psav->YExpansion = 0x00030002;
+ psav->displayYoffset = (PanelSizeY - ((3 * ViewPortHeight)/2)) / 2;
+ break;
+ case 8:
+ psav->YExpansion = 0x00020001;
+ psav->displayYoffset = (PanelSizeY - (2 * ViewPortHeight)) /2;
+ break;
+ case 9:
+ psav->YExpansion = 0x00090004;
+ psav->displayYoffset = (PanelSizeY - ((9 * ViewPortHeight)/4)) /2;
+ break;
+ case 11:
+ psav->YExpansion = 0x00110005;
+ psav->displayYoffset = (PanelSizeY - ((11 * ViewPortHeight)/5)) /2;
+ break;
+ case 12:
+ psav->YExpansion = 0x00070003;
+ psav->displayYoffset = (PanelSizeY - ((7 * ViewPortHeight)/3)) /2;
+ break;
+ case 14:
+ psav->YExpansion = 0x00050002;
+ psav->displayYoffset = (PanelSizeY - ((5 * ViewPortHeight)/2)) /2;
+ break;
+ case 15:
+ psav->YExpansion = 0x00040001;
+ psav->displayYoffset = (PanelSizeY - (4 * ViewPortHeight)) /2;
+ break;
+ }
+ psav->XExp1 = psav->XExpansion >> 16;
+ psav->XExp2 = psav->XExpansion & 0xFFFF;
+ psav->YExp1 = psav->YExpansion >> 16;
+ psav->YExp2 = psav->YExpansion & 0xFFFF;
+} /* InitStreamsForExpansionPM */
+
+#endif /* XvExtension */