savage_video.c revision ab47cfaa
1ab47cfaaSmrg/*
2ab47cfaaSmrg * Copyright (C) 1994-2000 The XFree86 Project, Inc.  All Rights Reserved.
3ab47cfaaSmrg * Copyright (c) 2003-2006, X.Org Foundation
4ab47cfaaSmrg *
5ab47cfaaSmrg * Permission is hereby granted, free of charge, to any person obtaining a
6ab47cfaaSmrg * copy of this software and associated documentation files (the "Software"),
7ab47cfaaSmrg * to deal in the Software without restriction, including without limitation
8ab47cfaaSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9ab47cfaaSmrg * and/or sell copies of the Software, and to permit persons to whom the
10ab47cfaaSmrg * Software is furnished to do so, subject to the following conditions:
11ab47cfaaSmrg *
12ab47cfaaSmrg * The above copyright notice and this permission notice shall be included in
13ab47cfaaSmrg * all copies or substantial portions of the Software.
14ab47cfaaSmrg *
15ab47cfaaSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16ab47cfaaSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17ab47cfaaSmrg * FITESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18ab47cfaaSmrg * COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19ab47cfaaSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20ab47cfaaSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21ab47cfaaSmrg * DEALINGS IN THE SOFTWARE.
22ab47cfaaSmrg *
23ab47cfaaSmrg * Except as contained in this notice, the name of the copyright holder(s)
24ab47cfaaSmrg * and author(s) shall not be used in advertising or otherwise to promote
25ab47cfaaSmrg * the sale, use or other dealings in this Software without prior written
26ab47cfaaSmrg * authorization from the copyright holder(s) and author(s).
27ab47cfaaSmrg */
28ab47cfaaSmrg
29ab47cfaaSmrg#ifdef HAVE_CONFIG_H
30ab47cfaaSmrg#include "config.h"
31ab47cfaaSmrg#endif
32ab47cfaaSmrg
33ab47cfaaSmrg#include <X11/extensions/Xv.h>
34ab47cfaaSmrg#include "dix.h"
35ab47cfaaSmrg#include "dixstruct.h"
36ab47cfaaSmrg#include "fourcc.h"
37ab47cfaaSmrg
38ab47cfaaSmrg#include "savage_driver.h"
39ab47cfaaSmrg#include "savage_streams.h"
40ab47cfaaSmrg#include "savage_regs.h"
41ab47cfaaSmrg#include "savage_bci.h"
42ab47cfaaSmrg
43ab47cfaaSmrg#define OFF_DELAY 	200  /* milliseconds */
44ab47cfaaSmrg#define FREE_DELAY 	60000
45ab47cfaaSmrg
46ab47cfaaSmrg#define OFF_TIMER 	0x01
47ab47cfaaSmrg#define FREE_TIMER	0x02
48ab47cfaaSmrg#define CLIENT_VIDEO_ON	0x04
49ab47cfaaSmrg
50ab47cfaaSmrg#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
51ab47cfaaSmrg
52ab47cfaaSmrgvoid savageOUTREG( SavagePtr psav, unsigned long offset, unsigned long value );
53ab47cfaaSmrg
54ab47cfaaSmrgstatic XF86VideoAdaptorPtr SavageSetupImageVideo(ScreenPtr);
55ab47cfaaSmrgstatic void SavageInitOffscreenImages(ScreenPtr);
56ab47cfaaSmrgstatic void SavageStopVideo(ScrnInfoPtr, pointer, Bool);
57ab47cfaaSmrgstatic int SavageSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
58ab47cfaaSmrgstatic int SavageGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
59ab47cfaaSmrgstatic void SavageQueryBestSize(ScrnInfoPtr, Bool,
60ab47cfaaSmrg	short, short, short, short, unsigned int *, unsigned int *, pointer);
61ab47cfaaSmrgstatic int SavagePutImage( ScrnInfoPtr,
62ab47cfaaSmrg	short, short, short, short, short, short, short, short,
63ab47cfaaSmrg	int, unsigned char*, short, short, Bool, RegionPtr, pointer,
64ab47cfaaSmrg	DrawablePtr);
65ab47cfaaSmrgstatic int SavageQueryImageAttributes(ScrnInfoPtr,
66ab47cfaaSmrg	int, unsigned short *, unsigned short *,  int *, int *);
67ab47cfaaSmrgstatic void SavageFreeMemory(ScrnInfoPtr pScrn, void *mem_struct);
68ab47cfaaSmrg
69ab47cfaaSmrgvoid SavageResetVideo(ScrnInfoPtr pScrn);
70ab47cfaaSmrg
71ab47cfaaSmrgstatic void SavageSetColorKeyOld(ScrnInfoPtr pScrn);
72ab47cfaaSmrgstatic void SavageSetColorKeyNew(ScrnInfoPtr pScrn);
73ab47cfaaSmrgstatic void SavageSetColorKey2000(ScrnInfoPtr pScrn);
74ab47cfaaSmrgstatic void (*SavageSetColorKey)(ScrnInfoPtr pScrn) = NULL;
75ab47cfaaSmrg
76ab47cfaaSmrgstatic void SavageSetColorOld(ScrnInfoPtr pScrn );
77ab47cfaaSmrgstatic void SavageSetColorNew(ScrnInfoPtr pScrn );
78ab47cfaaSmrgstatic void SavageSetColor2000(ScrnInfoPtr pScrn );
79ab47cfaaSmrgstatic void (*SavageSetColor)(ScrnInfoPtr pScrn ) = NULL;
80ab47cfaaSmrg
81ab47cfaaSmrgstatic void (*SavageInitStreams)(ScrnInfoPtr pScrn) = NULL;
82ab47cfaaSmrg
83ab47cfaaSmrgstatic void SavageDisplayVideoOld(
84ab47cfaaSmrg    ScrnInfoPtr pScrn, int id, int offset,
85ab47cfaaSmrg    short width, short height, int pitch,
86ab47cfaaSmrg    int x1, int y1, int x2, int y2,
87ab47cfaaSmrg    BoxPtr dstBox,
88ab47cfaaSmrg    short src_w, short src_h,
89ab47cfaaSmrg    short drw_w, short drw_h
90ab47cfaaSmrg);
91ab47cfaaSmrgstatic void SavageDisplayVideoNew(
92ab47cfaaSmrg    ScrnInfoPtr pScrn, int id, int offset,
93ab47cfaaSmrg    short width, short height, int pitch,
94ab47cfaaSmrg    int x1, int y1, int x2, int y2,
95ab47cfaaSmrg    BoxPtr dstBox,
96ab47cfaaSmrg    short src_w, short src_h,
97ab47cfaaSmrg    short drw_w, short drw_h
98ab47cfaaSmrg);
99ab47cfaaSmrgstatic void SavageDisplayVideo2000(
100ab47cfaaSmrg    ScrnInfoPtr pScrn, int id, int offset,
101ab47cfaaSmrg    short width, short height, int pitch,
102ab47cfaaSmrg    int x1, int y1, int x2, int y2,
103ab47cfaaSmrg    BoxPtr dstBox,
104ab47cfaaSmrg    short src_w, short src_h,
105ab47cfaaSmrg    short drw_w, short drw_h
106ab47cfaaSmrg);
107ab47cfaaSmrgstatic void (*SavageDisplayVideo)(
108ab47cfaaSmrg    ScrnInfoPtr pScrn, int id, int offset,
109ab47cfaaSmrg    short width, short height, int pitch,
110ab47cfaaSmrg    int x1, int y1, int x2, int y2,
111ab47cfaaSmrg    BoxPtr dstBox,
112ab47cfaaSmrg    short src_w, short src_h,
113ab47cfaaSmrg    short drw_w, short drw_h
114ab47cfaaSmrg) = NULL;
115ab47cfaaSmrg
116ab47cfaaSmrg/*static void SavageBlockHandler(int, pointer, pointer, pointer);*/
117ab47cfaaSmrg
118ab47cfaaSmrg#define XVTRACE	4
119ab47cfaaSmrg
120ab47cfaaSmrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
121ab47cfaaSmrg
122ab47cfaaSmrgstatic Atom xvColorKey, xvBrightness, xvContrast, xvSaturation, xvHue, xvInterpolation;
123ab47cfaaSmrg
124ab47cfaaSmrg/* client libraries expect an encoding */
125ab47cfaaSmrgstatic XF86VideoEncodingRec DummyEncoding[1] =
126ab47cfaaSmrg{
127ab47cfaaSmrg {
128ab47cfaaSmrg   0,
129ab47cfaaSmrg   "XV_IMAGE",
130ab47cfaaSmrg   1024, 1024,
131ab47cfaaSmrg   {1, 1}
132ab47cfaaSmrg }
133ab47cfaaSmrg};
134ab47cfaaSmrg
135ab47cfaaSmrg#define NUM_FORMATS 5
136ab47cfaaSmrg
137ab47cfaaSmrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] =
138ab47cfaaSmrg{
139ab47cfaaSmrg  {8, PseudoColor},  {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
140ab47cfaaSmrg};
141ab47cfaaSmrg
142ab47cfaaSmrg#define NUM_ATTRIBUTES 6
143ab47cfaaSmrg
144ab47cfaaSmrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
145ab47cfaaSmrg{
146ab47cfaaSmrg   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
147ab47cfaaSmrg   {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
148ab47cfaaSmrg   {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
149ab47cfaaSmrg   {XvSettable | XvGettable, 0, 255, "XV_SATURATION"},
150ab47cfaaSmrg   {XvSettable | XvGettable, -180, 180, "XV_HUE"},
151ab47cfaaSmrg   {XvSettable | XvGettable, 0, 1, "XV_VERTICAL_INTERPOLATION"}
152ab47cfaaSmrg};
153ab47cfaaSmrg
154ab47cfaaSmrg#define FOURCC_RV16	0x36315652
155ab47cfaaSmrg#define FOURCC_RV15	0x35315652
156ab47cfaaSmrg#define FOURCC_Y211	0x31313259
157ab47cfaaSmrg
158ab47cfaaSmrg/*
159ab47cfaaSmrg * For completeness sake, here is a cracking of the fourcc's I support.
160ab47cfaaSmrg *
161ab47cfaaSmrg * YUY2, packed 4:2:2, byte order: Y0 U0 Y1 V0  Y2 U2 Y3 V2
162ab47cfaaSmrg * Y211, packed 2:1:1, byte order: Y0 U0 Y2 V0  Y4 U2 Y6 V2
163ab47cfaaSmrg * YV12, planar 4:1:1, Y plane HxW, V plane H/2xW/2, U plane H/2xW/2
164ab47cfaaSmrg * I420, planar 4:1:1, Y plane HxW, U plane H/2xW/2, V plane H/2xW/2
165ab47cfaaSmrg * (I420 is also known as IYUV)
166ab47cfaaSmrg */
167ab47cfaaSmrg
168ab47cfaaSmrg
169ab47cfaaSmrgstatic XF86ImageRec Images[] =
170ab47cfaaSmrg{
171ab47cfaaSmrg   XVIMAGE_YUY2,
172ab47cfaaSmrg   XVIMAGE_YV12,
173ab47cfaaSmrg   XVIMAGE_I420,
174ab47cfaaSmrg   {
175ab47cfaaSmrg	FOURCC_RV15,
176ab47cfaaSmrg        XvRGB,
177ab47cfaaSmrg	LSBFirst,
178ab47cfaaSmrg	{'R','V','1','5',
179ab47cfaaSmrg	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
180ab47cfaaSmrg	16,
181ab47cfaaSmrg	XvPacked,
182ab47cfaaSmrg	1,
183ab47cfaaSmrg	15, 0x001F, 0x03E0, 0x7C00,
184ab47cfaaSmrg	0, 0, 0,
185ab47cfaaSmrg	0, 0, 0,
186ab47cfaaSmrg	0, 0, 0,
187ab47cfaaSmrg	{'R','V','B',0,
188ab47cfaaSmrg	  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},
189ab47cfaaSmrg	XvTopToBottom
190ab47cfaaSmrg   },
191ab47cfaaSmrg   {
192ab47cfaaSmrg	FOURCC_RV16,
193ab47cfaaSmrg        XvRGB,
194ab47cfaaSmrg	LSBFirst,
195ab47cfaaSmrg	{'R','V','1','6',
196ab47cfaaSmrg	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
197ab47cfaaSmrg	16,
198ab47cfaaSmrg	XvPacked,
199ab47cfaaSmrg	1,
200ab47cfaaSmrg	16, 0x001F, 0x07E0, 0xF800,
201ab47cfaaSmrg	0, 0, 0,
202ab47cfaaSmrg	0, 0, 0,
203ab47cfaaSmrg	0, 0, 0,
204ab47cfaaSmrg	{'R','V','B',0,
205ab47cfaaSmrg	  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},
206ab47cfaaSmrg	XvTopToBottom
207ab47cfaaSmrg   },
208ab47cfaaSmrg   {
209ab47cfaaSmrg	FOURCC_Y211,
210ab47cfaaSmrg	XvYUV,
211ab47cfaaSmrg	LSBFirst,
212ab47cfaaSmrg	{'Y','2','1','1',
213ab47cfaaSmrg	  0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71},
214ab47cfaaSmrg	6,
215ab47cfaaSmrg	XvPacked,
216ab47cfaaSmrg	3,
217ab47cfaaSmrg	0, 0, 0, 0 ,
218ab47cfaaSmrg	8, 8, 8,
219ab47cfaaSmrg	2, 4, 4,
220ab47cfaaSmrg	1, 1, 1,
221ab47cfaaSmrg	{'Y','U','Y','V',
222ab47cfaaSmrg	  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},
223ab47cfaaSmrg	XvTopToBottom
224ab47cfaaSmrg   }
225ab47cfaaSmrg};
226ab47cfaaSmrg
227ab47cfaaSmrg#define NUM_IMAGES (sizeof(Images)/sizeof(Images[0]))
228ab47cfaaSmrg
229ab47cfaaSmrgtypedef struct {
230ab47cfaaSmrg   int		brightness;	/* -128 .. 127 */
231ab47cfaaSmrg   CARD32	contrast;	/* 0 .. 255 */
232ab47cfaaSmrg   CARD32	saturation;	/* 0 .. 255 */
233ab47cfaaSmrg   int		hue;		/* -128 .. 127 */
234ab47cfaaSmrg   Bool		interpolation; /* on/off */
235ab47cfaaSmrg
236ab47cfaaSmrg   /*FBAreaPtr	area;*/
237ab47cfaaSmrg   RegionRec	clip;
238ab47cfaaSmrg   CARD32	colorKey;
239ab47cfaaSmrg   CARD32	videoStatus;
240ab47cfaaSmrg   Time		offTime;
241ab47cfaaSmrg   Time		freeTime;
242ab47cfaaSmrg   int		lastKnownPitch;
243ab47cfaaSmrg
244ab47cfaaSmrg   int          size;
245ab47cfaaSmrg   void         *video_memory;
246ab47cfaaSmrg   int          video_offset;
247ab47cfaaSmrg
248ab47cfaaSmrg} SavagePortPrivRec, *SavagePortPrivPtr;
249ab47cfaaSmrg
250ab47cfaaSmrg
251ab47cfaaSmrg#define GET_PORT_PRIVATE(pScrn) \
252ab47cfaaSmrg   (SavagePortPrivPtr)((SAVPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
253ab47cfaaSmrg
254ab47cfaaSmrgstatic
255ab47cfaaSmrgunsigned int GetBlendForFourCC( int id )
256ab47cfaaSmrg{
257ab47cfaaSmrg    switch( id ) {
258ab47cfaaSmrg	case FOURCC_YUY2:
259ab47cfaaSmrg        case FOURCC_YV12: /* shouldn't this be 4? */
260ab47cfaaSmrg        case FOURCC_I420: /* shouldn't this be 4? */
261ab47cfaaSmrg	    return 1;
262ab47cfaaSmrg	case FOURCC_Y211:
263ab47cfaaSmrg	    return 4;
264ab47cfaaSmrg	case FOURCC_RV15:
265ab47cfaaSmrg	    return 3;
266ab47cfaaSmrg	case FOURCC_RV16:
267ab47cfaaSmrg	    return 5;
268ab47cfaaSmrg        default:
269ab47cfaaSmrg	    return 0;
270ab47cfaaSmrg    }
271ab47cfaaSmrg}
272ab47cfaaSmrg
273ab47cfaaSmrgstatic
274ab47cfaaSmrgunsigned int GetBlendForFourCC2000( int id )
275ab47cfaaSmrg{
276ab47cfaaSmrg  switch( id ) {
277ab47cfaaSmrg  case FOURCC_YUY2:
278ab47cfaaSmrg    return 1;
279ab47cfaaSmrg  case FOURCC_I420:
280ab47cfaaSmrg    return 1; /* was 4 */
281ab47cfaaSmrg  case FOURCC_YV12:
282ab47cfaaSmrg    return 1; /* was 4 */
283ab47cfaaSmrg  case FOURCC_Y211:
284ab47cfaaSmrg    return 4;
285ab47cfaaSmrg  case FOURCC_RV15:
286ab47cfaaSmrg    return 3;
287ab47cfaaSmrg  case FOURCC_RV16:
288ab47cfaaSmrg    return 5;
289ab47cfaaSmrg  default:
290ab47cfaaSmrg    return 0;
291ab47cfaaSmrg  }
292ab47cfaaSmrg}
293ab47cfaaSmrg
294ab47cfaaSmrg
295ab47cfaaSmrgvoid savageOUTREG( SavagePtr psav, unsigned long offset, unsigned long value )
296ab47cfaaSmrg{
297ab47cfaaSmrg    ErrorF( "MMIO %08lx, was %08lx, want %08lx,",
298ab47cfaaSmrg	offset, (CARD32)MMIO_IN32( psav->MapBase, offset ), value );
299ab47cfaaSmrg    MMIO_OUT32( psav->MapBase, offset, value );
300ab47cfaaSmrg    ErrorF( " now %08lx\n", (CARD32)MMIO_IN32( psav->MapBase, offset ) );
301ab47cfaaSmrg}
302ab47cfaaSmrg
303ab47cfaaSmrg#if 0
304ab47cfaaSmrgstatic void
305ab47cfaaSmrgSavageClipVWindow(ScrnInfoPtr pScrn)
306ab47cfaaSmrg{
307ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
308ab47cfaaSmrg
309ab47cfaaSmrg    if( (psav->Chipset == S3_SAVAGE_MX)  ||
310ab47cfaaSmrg	(psav->Chipset == S3_SUPERSAVAGE) ) {
311ab47cfaaSmrg	if (psav->IsSecondary) {
312ab47cfaaSmrg	    OUTREG(SEC_STREAM2_WINDOW_SZ, 0);
313ab47cfaaSmrg	} else if (psav->IsPrimary) {
314ab47cfaaSmrg	    OUTREG(SEC_STREAM_WINDOW_SZ, 0);
315ab47cfaaSmrg	} else {
316ab47cfaaSmrg	    OUTREG(SEC_STREAM_WINDOW_SZ, 0);
317ab47cfaaSmrg#if 0
318ab47cfaaSmrg	    OUTREG(SEC_STREAM2_WINDOW_SZ, 0);
319ab47cfaaSmrg#endif
320ab47cfaaSmrg  	}
321ab47cfaaSmrg    } else if (psav->Chipset == S3_SAVAGE2000) {
322ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_SZ, 0);
323ab47cfaaSmrg    } else {
324ab47cfaaSmrg	OUTREG( SSTREAM_WINDOW_SIZE_REG, 1);
325ab47cfaaSmrg	OUTREG( SSTREAM_WINDOW_START_REG, 0x03ff03ff);
326ab47cfaaSmrg    }
327ab47cfaaSmrg}
328ab47cfaaSmrg#endif
329ab47cfaaSmrg
330ab47cfaaSmrgvoid SavageInitVideo(ScreenPtr pScreen)
331ab47cfaaSmrg{
332ab47cfaaSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
333ab47cfaaSmrg    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
334ab47cfaaSmrg    XF86VideoAdaptorPtr newAdaptor = NULL;
335ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
336ab47cfaaSmrg    int num_adaptors;
337ab47cfaaSmrg
338ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageInitVideo\n");
339ab47cfaaSmrg    if (S3_SAVAGE_MOBILE_SERIES(psav->Chipset))
340ab47cfaaSmrg    {
341ab47cfaaSmrg	newAdaptor = SavageSetupImageVideo(pScreen);
342ab47cfaaSmrg	SavageInitOffscreenImages(pScreen);
343ab47cfaaSmrg
344ab47cfaaSmrg	SavageInitStreams = SavageInitStreamsNew;
345ab47cfaaSmrg	SavageSetColor = SavageSetColorNew;
346ab47cfaaSmrg	SavageSetColorKey = SavageSetColorKeyNew;
347ab47cfaaSmrg	SavageDisplayVideo = SavageDisplayVideoNew;
348ab47cfaaSmrg    }
349ab47cfaaSmrg    else if (psav->Chipset == S3_SAVAGE2000)
350ab47cfaaSmrg    {
351ab47cfaaSmrg        newAdaptor = SavageSetupImageVideo(pScreen);
352ab47cfaaSmrg        SavageInitOffscreenImages(pScreen);
353ab47cfaaSmrg
354ab47cfaaSmrg	SavageInitStreams = SavageInitStreams2000;
355ab47cfaaSmrg        SavageSetColor = SavageSetColor2000;
356ab47cfaaSmrg        SavageSetColorKey = SavageSetColorKey2000;
357ab47cfaaSmrg        SavageDisplayVideo = SavageDisplayVideo2000;
358ab47cfaaSmrg    }
359ab47cfaaSmrg    else
360ab47cfaaSmrg    {
361ab47cfaaSmrg	newAdaptor = SavageSetupImageVideo(pScreen);
362ab47cfaaSmrg	SavageInitOffscreenImages(pScreen);
363ab47cfaaSmrg
364ab47cfaaSmrg	SavageInitStreams = SavageInitStreamsOld;
365ab47cfaaSmrg	SavageSetColor = SavageSetColorOld;
366ab47cfaaSmrg	SavageSetColorKey = SavageSetColorKeyOld;
367ab47cfaaSmrg	SavageDisplayVideo = SavageDisplayVideoOld;
368ab47cfaaSmrg    }
369ab47cfaaSmrg
370ab47cfaaSmrg    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
371ab47cfaaSmrg
372ab47cfaaSmrg    if(newAdaptor) {
373ab47cfaaSmrg        if(!num_adaptors) {
374ab47cfaaSmrg            num_adaptors = 1;
375ab47cfaaSmrg            adaptors = &newAdaptor;
376ab47cfaaSmrg        } else {
377ab47cfaaSmrg            newAdaptors =  /* need to free this someplace */
378ab47cfaaSmrg        	xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
379ab47cfaaSmrg            if(newAdaptors) {
380ab47cfaaSmrg        	memcpy(newAdaptors, adaptors, num_adaptors *
381ab47cfaaSmrg        				sizeof(XF86VideoAdaptorPtr));
382ab47cfaaSmrg        	newAdaptors[num_adaptors] = newAdaptor;
383ab47cfaaSmrg        	adaptors = newAdaptors;
384ab47cfaaSmrg        	num_adaptors++;
385ab47cfaaSmrg            }
386ab47cfaaSmrg        }
387ab47cfaaSmrg    }
388ab47cfaaSmrg
389ab47cfaaSmrg    if(num_adaptors)
390ab47cfaaSmrg        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
391ab47cfaaSmrg
392ab47cfaaSmrg    if(newAdaptors)
393ab47cfaaSmrg	xfree(newAdaptors);
394ab47cfaaSmrg
395ab47cfaaSmrg    if( newAdaptor )
396ab47cfaaSmrg    {
397ab47cfaaSmrg	psav->videoFourCC = 0;
398ab47cfaaSmrg    }
399ab47cfaaSmrg}
400ab47cfaaSmrg
401ab47cfaaSmrg
402ab47cfaaSmrgvoid SavageSetColorKeyOld(ScrnInfoPtr pScrn)
403ab47cfaaSmrg{
404ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
405ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
406ab47cfaaSmrg    int red, green, blue;
407ab47cfaaSmrg
408ab47cfaaSmrg    /* Here, we reset the colorkey and all the controls. */
409ab47cfaaSmrg
410ab47cfaaSmrg    red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
411ab47cfaaSmrg    green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
412ab47cfaaSmrg    blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
413ab47cfaaSmrg
414ab47cfaaSmrg    if( !pPriv->colorKey ) {
415ab47cfaaSmrg	OUTREG( COL_CHROMA_KEY_CONTROL_REG, 0 );
416ab47cfaaSmrg	OUTREG( CHROMA_KEY_UPPER_BOUND_REG, 0 );
417ab47cfaaSmrg	OUTREG( BLEND_CONTROL_REG, 0 );
418ab47cfaaSmrg    }
419ab47cfaaSmrg    else {
420ab47cfaaSmrg	switch (pScrn->depth) {
421ab47cfaaSmrg	case 8:
422ab47cfaaSmrg	    OUTREG( COL_CHROMA_KEY_CONTROL_REG,
423ab47cfaaSmrg		0x37000000 | (pPriv->colorKey & 0xFF) );
424ab47cfaaSmrg	    OUTREG( CHROMA_KEY_UPPER_BOUND_REG,
425ab47cfaaSmrg		0x00000000 | (pPriv->colorKey & 0xFF) );
426ab47cfaaSmrg	    break;
427ab47cfaaSmrg	case 15:
428ab47cfaaSmrg	    OUTREG( COL_CHROMA_KEY_CONTROL_REG,
429ab47cfaaSmrg		0x05000000 | (red<<19) | (green<<11) | (blue<<3) );
430ab47cfaaSmrg	    OUTREG( CHROMA_KEY_UPPER_BOUND_REG,
431ab47cfaaSmrg		0x00000000 | (red<<19) | (green<<11) | (blue<<3) );
432ab47cfaaSmrg	    break;
433ab47cfaaSmrg	case 16:
434ab47cfaaSmrg	    OUTREG( COL_CHROMA_KEY_CONTROL_REG,
435ab47cfaaSmrg		0x16000000 | (red<<19) | (green<<10) | (blue<<3) );
436ab47cfaaSmrg	    OUTREG( CHROMA_KEY_UPPER_BOUND_REG,
437ab47cfaaSmrg		0x00020002 | (red<<19) | (green<<10) | (blue<<3) );
438ab47cfaaSmrg	    break;
439ab47cfaaSmrg	case 24:
440ab47cfaaSmrg	    OUTREG( COL_CHROMA_KEY_CONTROL_REG,
441ab47cfaaSmrg		0x17000000 | (red<<16) | (green<<8) | (blue) );
442ab47cfaaSmrg	    OUTREG( CHROMA_KEY_UPPER_BOUND_REG,
443ab47cfaaSmrg		0x00000000 | (red<<16) | (green<<8) | (blue) );
444ab47cfaaSmrg	    break;
445ab47cfaaSmrg	}
446ab47cfaaSmrg
447ab47cfaaSmrg	/* We use destination colorkey */
448ab47cfaaSmrg	OUTREG( BLEND_CONTROL_REG, 0x05000000 );
449ab47cfaaSmrg    }
450ab47cfaaSmrg}
451ab47cfaaSmrg
452ab47cfaaSmrgvoid SavageSetColorKeyNew(ScrnInfoPtr pScrn)
453ab47cfaaSmrg{
454ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
455ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
456ab47cfaaSmrg    int red, green, blue;
457ab47cfaaSmrg
458ab47cfaaSmrg    /* Here, we reset the colorkey and all the controls. */
459ab47cfaaSmrg
460ab47cfaaSmrg    red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
461ab47cfaaSmrg    green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
462ab47cfaaSmrg    blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
463ab47cfaaSmrg
464ab47cfaaSmrg    if( !pPriv->colorKey ) {
465ab47cfaaSmrg	if (psav->IsSecondary) {
466ab47cfaaSmrg	    OUTREG( SEC_STREAM2_CKEY_LOW, 0 );
467ab47cfaaSmrg	    OUTREG( SEC_STREAM2_CKEY_UPPER, 0 );
468ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
469ab47cfaaSmrg	} else if (psav->IsPrimary) {
470ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_LOW, 0 );
471ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_UPPER, 0 );
472ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
473ab47cfaaSmrg	} else {
474ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_LOW, 0 );
475ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_UPPER, 0 );
476ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
477ab47cfaaSmrg#if 0
478ab47cfaaSmrg	    sleep(1);
479ab47cfaaSmrg	    OUTREG( SEC_STREAM2_CKEY_LOW, 0 );
480ab47cfaaSmrg	    OUTREG( SEC_STREAM2_CKEY_UPPER, 0 );
481ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
482ab47cfaaSmrg#endif
483ab47cfaaSmrg	}
484ab47cfaaSmrg    }
485ab47cfaaSmrg    else {
486ab47cfaaSmrg	switch (pScrn->depth) {
487ab47cfaaSmrg	case 8:
488ab47cfaaSmrg	    if (psav->IsSecondary) {
489ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_LOW,
490ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
491ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_UPPER,
492ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
493ab47cfaaSmrg	    } else if (psav->IsPrimary) {
494ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_LOW,
495ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
496ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_UPPER,
497ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
498ab47cfaaSmrg	    } else {
499ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_LOW,
500ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
501ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_UPPER,
502ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
503ab47cfaaSmrg#if 0
504ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_LOW,
505ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
506ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_UPPER,
507ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
508ab47cfaaSmrg#endif
509ab47cfaaSmrg	    }
510ab47cfaaSmrg	    break;
511ab47cfaaSmrg	case 15:
512ab47cfaaSmrg	    if (psav->IsSecondary) {
513ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_LOW,
514ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
515ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_UPPER,
516ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
517ab47cfaaSmrg	    } else if (psav->IsPrimary) {
518ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_LOW,
519ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
520ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_UPPER,
521ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
522ab47cfaaSmrg	    } else {
523ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_LOW,
524ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
525ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_UPPER,
526ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
527ab47cfaaSmrg#if 0
528ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_LOW,
529ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
530ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_UPPER,
531ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
532ab47cfaaSmrg#endif
533ab47cfaaSmrg	    }
534ab47cfaaSmrg	    break;
535ab47cfaaSmrg	case 16:
536ab47cfaaSmrg	    if (psav->IsSecondary) {
537ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_LOW,
538ab47cfaaSmrg		    0x46000000 | (red<<19) | (green<<10) | (blue<<3) );
539ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_UPPER,
540ab47cfaaSmrg		    0x46020002 | (red<<19) | (green<<10) | (blue<<3) );
541ab47cfaaSmrg	    } else if (psav->IsPrimary) {
542ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_LOW,
543ab47cfaaSmrg		    0x46000000 | (red<<19) | (green<<10) | (blue<<3) );
544ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_UPPER,
545ab47cfaaSmrg		    0x46020002 | (red<<19) | (green<<10) | (blue<<3) );
546ab47cfaaSmrg	    } else {
547ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_LOW,
548ab47cfaaSmrg		    0x46000000 | (red<<19) | (green<<10) | (blue<<3) );
549ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_UPPER,
550ab47cfaaSmrg		    0x46020002 | (red<<19) | (green<<10) | (blue<<3) );
551ab47cfaaSmrg#if 0
552ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_LOW,
553ab47cfaaSmrg		    0x46000000 | (red<<19) | (green<<10) | (blue<<3) );
554ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_UPPER,
555ab47cfaaSmrg		    0x46020002 | (red<<19) | (green<<10) | (blue<<3) );
556ab47cfaaSmrg#endif
557ab47cfaaSmrg	    }
558ab47cfaaSmrg	    break;
559ab47cfaaSmrg	case 24:
560ab47cfaaSmrg	    if (psav->IsSecondary) {
561ab47cfaaSmrg	        OUTREG( SEC_STREAM2_CKEY_LOW,
562ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
563ab47cfaaSmrg	        OUTREG( SEC_STREAM2_CKEY_UPPER,
564ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
565ab47cfaaSmrg	    } else if (psav->IsPrimary) {
566ab47cfaaSmrg	        OUTREG( SEC_STREAM_CKEY_LOW,
567ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
568ab47cfaaSmrg	        OUTREG( SEC_STREAM_CKEY_UPPER,
569ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
570ab47cfaaSmrg	    } else {
571ab47cfaaSmrg	        OUTREG( SEC_STREAM_CKEY_LOW,
572ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
573ab47cfaaSmrg	        OUTREG( SEC_STREAM_CKEY_UPPER,
574ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
575ab47cfaaSmrg#if 0
576ab47cfaaSmrg	        OUTREG( SEC_STREAM2_CKEY_LOW,
577ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
578ab47cfaaSmrg	        OUTREG( SEC_STREAM2_CKEY_UPPER,
579ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
580ab47cfaaSmrg#endif
581ab47cfaaSmrg	    }
582ab47cfaaSmrg	    break;
583ab47cfaaSmrg	}
584ab47cfaaSmrg
585ab47cfaaSmrg	/* We assume destination colorkey */
586ab47cfaaSmrg	if (psav->IsSecondary) {
587ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
588ab47cfaaSmrg	} else if (psav->IsPrimary) {
589ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
590ab47cfaaSmrg	} else {
591ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
592ab47cfaaSmrg#if 0
593ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
594ab47cfaaSmrg#endif
595ab47cfaaSmrg	}
596ab47cfaaSmrg    }
597ab47cfaaSmrg}
598ab47cfaaSmrg
599ab47cfaaSmrgvoid SavageSetColorKey2000(ScrnInfoPtr pScrn)
600ab47cfaaSmrg{
601ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
602ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
603ab47cfaaSmrg    int red, green, blue;
604ab47cfaaSmrg
605ab47cfaaSmrg    /* Here, we reset the colorkey and all the controls. */
606ab47cfaaSmrg
607ab47cfaaSmrg    red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
608ab47cfaaSmrg    green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
609ab47cfaaSmrg    blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
610ab47cfaaSmrg
611ab47cfaaSmrg    if( !pPriv->colorKey ) {
612ab47cfaaSmrg        OUTREG( SEC_STREAM_CKEY_LOW, 0);
613ab47cfaaSmrg	OUTREG( SEC_STREAM_CKEY_UPPER, 0);
614ab47cfaaSmrg        OUTREG( BLEND_CONTROL, (8 << 2));
615ab47cfaaSmrg    }
616ab47cfaaSmrg    else {
617ab47cfaaSmrg	switch (pScrn->depth) {
618ab47cfaaSmrg	case 8:
619ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_LOW,
620ab47cfaaSmrg		0x47000000 | (pPriv->colorKey & 0xFF) );
621ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_UPPER,
622ab47cfaaSmrg		  (pPriv->colorKey & 0xFF) );
623ab47cfaaSmrg	    break;
624ab47cfaaSmrg	case 15:
625ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_LOW,
626ab47cfaaSmrg		0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
627ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_UPPER,
628ab47cfaaSmrg		  (red<<19) | (green<<11) | (blue<<3) );
629ab47cfaaSmrg	    break;
630ab47cfaaSmrg	case 16:
631ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_LOW,
632ab47cfaaSmrg		0x46000000 | (red<<19) | (green<<10) | (blue<<3) );
633ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_UPPER,
634ab47cfaaSmrg		  (red<<19) | (green<<10) | (blue<<3) );
635ab47cfaaSmrg	    break;
636ab47cfaaSmrg	case 24:
637ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_LOW,
638ab47cfaaSmrg		0x47000000 | (red<<16) | (green<<8) | (blue) );
639ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_UPPER,
640ab47cfaaSmrg		  (red<<16) | (green<<8) | (blue) );
641ab47cfaaSmrg	    break;
642ab47cfaaSmrg	}
643ab47cfaaSmrg
644ab47cfaaSmrg	/* We assume destination colorkey */
645ab47cfaaSmrg	OUTREG( BLEND_CONTROL, INREG(BLEND_CONTROL) | (8 << 2));
646ab47cfaaSmrg    }
647ab47cfaaSmrg}
648ab47cfaaSmrg
649ab47cfaaSmrgvoid SavageSetColorOld( ScrnInfoPtr pScrn )
650ab47cfaaSmrg{
651ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
652ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
653ab47cfaaSmrg
654ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE, "bright %d, contrast %d, saturation %d, hue %d\n",
655ab47cfaaSmrg	pPriv->brightness, (int)pPriv->contrast, (int)pPriv->saturation, pPriv->hue );
656ab47cfaaSmrg
657ab47cfaaSmrg    if(
658ab47cfaaSmrg	(psav->videoFourCC == FOURCC_RV15) ||
659ab47cfaaSmrg	(psav->videoFourCC == FOURCC_RV16)
660ab47cfaaSmrg    )
661ab47cfaaSmrg    {
662ab47cfaaSmrg	OUTREG( COLOR_ADJUSTMENT_REG, 0 );
663ab47cfaaSmrg    }
664ab47cfaaSmrg    else
665ab47cfaaSmrg    {
666ab47cfaaSmrg        /* Change 0..255 into 0..15 */
667ab47cfaaSmrg	long sat = pPriv->saturation * 16 / 256;
668ab47cfaaSmrg	double hue = pPriv->hue * 0.017453292;
669ab47cfaaSmrg	unsigned long hs1 = ((long)(sat * cos(hue))) & 0x1f;
670ab47cfaaSmrg	unsigned long hs2 = ((long)(sat * sin(hue))) & 0x1f;
671ab47cfaaSmrg
672ab47cfaaSmrg	OUTREG( COLOR_ADJUSTMENT_REG,
673ab47cfaaSmrg	    0x80008000 |
674ab47cfaaSmrg	    (pPriv->brightness + 128) |
675ab47cfaaSmrg	    ((pPriv->contrast & 0xf8) << (12-7)) |
676ab47cfaaSmrg	    (hs1 << 16) |
677ab47cfaaSmrg	    (hs2 << 24)
678ab47cfaaSmrg	);
679ab47cfaaSmrg
680ab47cfaaSmrg    }
681ab47cfaaSmrg}
682ab47cfaaSmrg
683ab47cfaaSmrgvoid SavageSetColorNew( ScrnInfoPtr pScrn )
684ab47cfaaSmrg{
685ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
686ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
687ab47cfaaSmrg
688ab47cfaaSmrg    /* Brightness/contrast/saturation/hue computations. */
689ab47cfaaSmrg
690ab47cfaaSmrg    double k, dk1, dk2, dk3, dk4, dk5, dk6, dk7, dkb;
691ab47cfaaSmrg    int k1, k2, k3, k4, k5, k6, k7, kb;
692ab47cfaaSmrg    double s = pPriv->saturation / 128.0;
693ab47cfaaSmrg    double h = pPriv->hue * 0.017453292;
694ab47cfaaSmrg    unsigned long assembly1, assembly2, assembly3;
695ab47cfaaSmrg
696ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE, "bright %d, contrast %d, saturation %d, hue %d\n",
697ab47cfaaSmrg	pPriv->brightness, (int)pPriv->contrast, (int)pPriv->saturation, pPriv->hue );
698ab47cfaaSmrg
699ab47cfaaSmrg    if( psav->videoFourCC == FOURCC_Y211 )
700ab47cfaaSmrg	k = 1.0;	/* YUV */
701ab47cfaaSmrg    else
702ab47cfaaSmrg	k = 1.14;	/* YCrCb */
703ab47cfaaSmrg
704ab47cfaaSmrg    /*
705ab47cfaaSmrg     * The S3 documentation must be wrong for k4 and k5.  Their default
706ab47cfaaSmrg     * values, which they hardcode in their Windows driver, have the
707ab47cfaaSmrg     * opposite sign from the results in the register spec.
708ab47cfaaSmrg     */
709ab47cfaaSmrg
710ab47cfaaSmrg    dk1 = k * pPriv->contrast;
711ab47cfaaSmrg    dk2 = 64.0 * 1.371 * k * s * cos(h);
712ab47cfaaSmrg    dk3 = -64.0 * 1.371 * k * s * sin(h);
713ab47cfaaSmrg    dk4 = -128.0 * k * s * (0.698 * cos(h) - 0.336 * sin(h));
714ab47cfaaSmrg    dk5 = -128.0 * k * s * (0.698 * sin(h) + 0.336 * cos(h));
715ab47cfaaSmrg    dk6 = 64.0 * 1.732 * k * s * sin(h);	/* == k3 / 1.26331, right? */
716ab47cfaaSmrg    dk7 = 64.0 * 1.732 * k * s * cos(h);	/* == k2 / -1.26331, right? */
717ab47cfaaSmrg    dkb = 128.0 * pPriv->brightness + 64.0;
718ab47cfaaSmrg    if( psav->videoFourCC != FOURCC_Y211 )
719ab47cfaaSmrg	dkb -= dk1 * 14.0;
720ab47cfaaSmrg
721ab47cfaaSmrg    k1 = (int)(dk1+0.5) & 0x1ff;
722ab47cfaaSmrg    k2 = (int)(dk2+0.5) & 0x1ff;
723ab47cfaaSmrg    k3 = (int)(dk3+0.5) & 0x1ff;
724ab47cfaaSmrg    assembly1 = (k3<<18) | (k2<<9) | k1;
725ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE+1, "CC1 = %08lx  ", assembly1 );
726ab47cfaaSmrg
727ab47cfaaSmrg    k4 = (int)(dk4+0.5) & 0x1ff;
728ab47cfaaSmrg    k5 = (int)(dk5+0.5) & 0x1ff;
729ab47cfaaSmrg    k6 = (int)(dk6+0.5) & 0x1ff;
730ab47cfaaSmrg    assembly2 = (k6<<18) | (k5<<9) | k4;
731ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE+1, "CC2 = %08lx  ", assembly2 );
732ab47cfaaSmrg
733ab47cfaaSmrg    k7 = (int)(dk7+0.5) & 0x1ff;
734ab47cfaaSmrg    kb = (int)(dkb+0.5) & 0xffff;
735ab47cfaaSmrg    assembly3 = (kb<<9) | k7;
736ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE+1, "CC3 = %08lx\n", assembly3 );
737ab47cfaaSmrg
738ab47cfaaSmrg    if (psav->IsSecondary) {
739ab47cfaaSmrg	OUTREG( SEC_STREAM2_COLOR_CONVERT1, assembly1 );
740ab47cfaaSmrg	OUTREG( SEC_STREAM2_COLOR_CONVERT2, assembly2 );
741ab47cfaaSmrg	OUTREG( SEC_STREAM2_COLOR_CONVERT3, assembly3 );
742ab47cfaaSmrg    } else if (psav->IsPrimary) {
743ab47cfaaSmrg	OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly1 );
744ab47cfaaSmrg	OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly2 );
745ab47cfaaSmrg	OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly3 );
746ab47cfaaSmrg    } else {
747ab47cfaaSmrg	OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly1 );
748ab47cfaaSmrg	OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly2 );
749ab47cfaaSmrg	OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly3 );
750ab47cfaaSmrg#if 0
751ab47cfaaSmrg	sleep(1);
752ab47cfaaSmrg	OUTREG( SEC_STREAM2_COLOR_CONVERT1, assembly1 );
753ab47cfaaSmrg	OUTREG( SEC_STREAM2_COLOR_CONVERT2, assembly2 );
754ab47cfaaSmrg	OUTREG( SEC_STREAM2_COLOR_CONVERT3, assembly3 );
755ab47cfaaSmrg#endif
756ab47cfaaSmrg    }
757ab47cfaaSmrg}
758ab47cfaaSmrg
759ab47cfaaSmrgvoid SavageSetColor2000( ScrnInfoPtr pScrn )
760ab47cfaaSmrg{
761ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
762ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
763ab47cfaaSmrg
764ab47cfaaSmrg    /* Brightness/contrast/saturation/hue computations. */
765ab47cfaaSmrg
766ab47cfaaSmrg    double k, yb, dk1, dk2, dk3, dk4, dk5, dk6, dk7, dkb;
767ab47cfaaSmrg    int k1, k2, k3, k4, k5, k6, k7, kb;
768ab47cfaaSmrg    double s = pPriv->saturation / 10000.0;
769ab47cfaaSmrg    double h = pPriv->hue * 0.017453292;
770ab47cfaaSmrg    unsigned long assembly1, assembly2, assembly3, assembly4;
771ab47cfaaSmrg    unsigned long brightness = pPriv->brightness;
772ab47cfaaSmrg
773ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE, "bright %d, contrast %d, saturation %d, hue %d\n",
774ab47cfaaSmrg		 pPriv->brightness, (int)pPriv->contrast, (int)pPriv->saturation, pPriv->hue );
775ab47cfaaSmrg
776ab47cfaaSmrg    if( psav->videoFourCC == FOURCC_Y211 ) {
777ab47cfaaSmrg      k = 1.0;/* YUV */
778ab47cfaaSmrg      yb = 0.0;
779ab47cfaaSmrg    } else {
780ab47cfaaSmrg      k = 1.1;/* YCrCb */
781ab47cfaaSmrg      yb = 14.0;
782ab47cfaaSmrg    }
783ab47cfaaSmrg
784ab47cfaaSmrg    dk1 = 128 * k * (pPriv->contrast / 10000.0);
785ab47cfaaSmrg    if (dk1 < 0)
786ab47cfaaSmrg      dk1 -= 0.5;
787ab47cfaaSmrg    else
788ab47cfaaSmrg      dk1 += 0.5;
789ab47cfaaSmrg    dk2 = 64.0 * 1.371 * k * s * cos(h);
790ab47cfaaSmrg    if (dk2 < 0)
791ab47cfaaSmrg      dk2 -= 0.5;
792ab47cfaaSmrg    else
793ab47cfaaSmrg      dk2 += 0.5;
794ab47cfaaSmrg    dk3 = -64.0 * 1.371 * k * s * sin(h);
795ab47cfaaSmrg    if (dk3 < 0)
796ab47cfaaSmrg      dk3 -= 0.5;
797ab47cfaaSmrg    else
798ab47cfaaSmrg      dk3 += 0.5;
799ab47cfaaSmrg    dk4 = -128.0 * k * s * (0.698 * cos(h) + 0.336 * sin(h));
800ab47cfaaSmrg    if (dk4 < 0)
801ab47cfaaSmrg      dk4 -= 0.5;
802ab47cfaaSmrg    else
803ab47cfaaSmrg      dk4 += 0.5;
804ab47cfaaSmrg    dk5 = 128.0 * k * s * (0.698 * sin(h) - 0.336 * cos(h));
805ab47cfaaSmrg    if (dk5 < 0)
806ab47cfaaSmrg      dk5 -= 0.5;
807ab47cfaaSmrg    else
808ab47cfaaSmrg      dk5 += 0.5;
809ab47cfaaSmrg    dk6 = 64.0 * 1.732 * k * s * sin(h);
810ab47cfaaSmrg    if (dk6 < 0)
811ab47cfaaSmrg      dk6 -= 0.5;
812ab47cfaaSmrg    else
813ab47cfaaSmrg      dk6 += 0.5;
814ab47cfaaSmrg    dk7 = 64.0 * 1.732 * k * s * cos(h);
815ab47cfaaSmrg    if (dk7 < 0)
816ab47cfaaSmrg      dk7 -= 0.5;
817ab47cfaaSmrg    else
818ab47cfaaSmrg      dk7 += 0.5;
819ab47cfaaSmrg
820ab47cfaaSmrg    if (pPriv->brightness <= 0)
821ab47cfaaSmrg        brightness = pPriv->brightness * 200 / 750 - 200;
822ab47cfaaSmrg    else
823ab47cfaaSmrg        brightness = (pPriv->brightness - 750) * 200 / (10000 - 750);
824ab47cfaaSmrg    dkb = 128 * (brightness - (k * pPriv->contrast * yb / 10000.0) + 0.5);
825ab47cfaaSmrg    if (dkb < 0)
826ab47cfaaSmrg      dkb -= 0.5;
827ab47cfaaSmrg    else
828ab47cfaaSmrg      dkb += 0.5;
829ab47cfaaSmrg
830ab47cfaaSmrg    k1 = (int)(dk1 /*+0.5*/) & 0x1ff;
831ab47cfaaSmrg    k2 = (int)(dk2 /*+0.5*/) & 0x1ff;
832ab47cfaaSmrg    assembly1 = (k2<<16) | k1;
833ab47cfaaSmrg
834ab47cfaaSmrg    k3 = (int)(dk3 /*+0.5*/) & 0x1ff;
835ab47cfaaSmrg    k4 = (int)(dk4 /*+0.5*/) & 0x1ff;
836ab47cfaaSmrg    assembly2 = (k4<<16) | k3;
837ab47cfaaSmrg
838ab47cfaaSmrg    k5 = (int)(dk5 /*+0.5*/) & 0x1ff;
839ab47cfaaSmrg    k6 = (int)(dk6 /*+0.5*/) & 0x1ff;
840ab47cfaaSmrg    assembly3 = (k6<<16) | k5;
841ab47cfaaSmrg
842ab47cfaaSmrg    k7 = (int)(dk7 /*+0.5*/) & 0x1ff;
843ab47cfaaSmrg    kb = (int)(dkb /*+0.5*/) & 0xffff;
844ab47cfaaSmrg    assembly4 = (kb<<16) | k7;
845ab47cfaaSmrg
846ab47cfaaSmrg#if 0
847ab47cfaaSmrg    assembly1 = 0x640092;
848ab47cfaaSmrg    assembly2 = 0x19a0000;
849ab47cfaaSmrg    assembly3 = 0x001cf;
850ab47cfaaSmrg    assembly4 = 0xf8ca007e;
851ab47cfaaSmrg#endif
852ab47cfaaSmrg
853ab47cfaaSmrg    OUTREG( SEC_STREAM_COLOR_CONVERT0_2000, assembly1 );
854ab47cfaaSmrg    OUTREG( SEC_STREAM_COLOR_CONVERT1_2000, assembly2 );
855ab47cfaaSmrg    OUTREG( SEC_STREAM_COLOR_CONVERT2_2000, assembly3 );
856ab47cfaaSmrg    OUTREG( SEC_STREAM_COLOR_CONVERT3_2000, assembly4 );
857ab47cfaaSmrg
858ab47cfaaSmrg}
859ab47cfaaSmrg
860ab47cfaaSmrgvoid SavageResetVideo(ScrnInfoPtr pScrn)
861ab47cfaaSmrg{
862ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageResetVideo\n");
863ab47cfaaSmrg    SavageSetColor( pScrn );
864ab47cfaaSmrg    SavageSetColorKey( pScrn );
865ab47cfaaSmrg}
866ab47cfaaSmrg
867ab47cfaaSmrg
868ab47cfaaSmrgstatic XF86VideoAdaptorPtr
869ab47cfaaSmrgSavageSetupImageVideo(ScreenPtr pScreen)
870ab47cfaaSmrg{
871ab47cfaaSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
872ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
873ab47cfaaSmrg    XF86VideoAdaptorPtr adapt;
874ab47cfaaSmrg    SavagePortPrivPtr pPriv;
875ab47cfaaSmrg
876ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageSetupImageVideo\n");
877ab47cfaaSmrg
878ab47cfaaSmrg    if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
879ab47cfaaSmrg			    sizeof(SavagePortPrivRec) +
880ab47cfaaSmrg			    sizeof(DevUnion))))
881ab47cfaaSmrg	return NULL;
882ab47cfaaSmrg
883ab47cfaaSmrg    adapt->type		= XvWindowMask | XvInputMask | XvImageMask;
884ab47cfaaSmrg    adapt->flags	= VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
885ab47cfaaSmrg    adapt->name			= "Savage Streams Engine";
886ab47cfaaSmrg    adapt->nEncodings 		= 1;
887ab47cfaaSmrg    adapt->pEncodings 		= DummyEncoding;
888ab47cfaaSmrg    adapt->nFormats 		= NUM_FORMATS;
889ab47cfaaSmrg    adapt->pFormats 		= Formats;
890ab47cfaaSmrg    adapt->nPorts 		= 1;
891ab47cfaaSmrg    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
892ab47cfaaSmrg    pPriv = (SavagePortPrivPtr)(&adapt->pPortPrivates[1]);
893ab47cfaaSmrg    adapt->pPortPrivates[0].ptr	= (pointer)(pPriv);
894ab47cfaaSmrg    adapt->pAttributes		= Attributes;
895ab47cfaaSmrg    adapt->nImages		= NUM_IMAGES;
896ab47cfaaSmrg    adapt->nAttributes		= NUM_ATTRIBUTES;
897ab47cfaaSmrg    adapt->pImages		= Images;
898ab47cfaaSmrg    adapt->PutVideo		= NULL;
899ab47cfaaSmrg    adapt->PutStill		= NULL;
900ab47cfaaSmrg    adapt->GetVideo		= NULL;
901ab47cfaaSmrg    adapt->GetStill		= NULL;
902ab47cfaaSmrg    adapt->StopVideo		= SavageStopVideo;
903ab47cfaaSmrg    adapt->SetPortAttribute	= SavageSetPortAttribute;
904ab47cfaaSmrg    adapt->GetPortAttribute	= SavageGetPortAttribute;
905ab47cfaaSmrg    adapt->QueryBestSize	= SavageQueryBestSize;
906ab47cfaaSmrg    adapt->PutImage		= SavagePutImage;
907ab47cfaaSmrg    adapt->QueryImageAttributes	= SavageQueryImageAttributes;
908ab47cfaaSmrg
909ab47cfaaSmrg    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
910ab47cfaaSmrg    xvContrast   = MAKE_ATOM("XV_CONTRAST");
911ab47cfaaSmrg    xvColorKey   = MAKE_ATOM("XV_COLORKEY");
912ab47cfaaSmrg    xvHue        = MAKE_ATOM("XV_HUE");
913ab47cfaaSmrg    xvSaturation = MAKE_ATOM("XV_SATURATION");
914ab47cfaaSmrg    /* interpolation option only available on "old" streams */
915ab47cfaaSmrg    xvInterpolation = MAKE_ATOM("XV_VERTICAL_INTERPOLATION");
916ab47cfaaSmrg
917ab47cfaaSmrg    pPriv->colorKey =
918ab47cfaaSmrg      (1 << pScrn->offset.red) |
919ab47cfaaSmrg      (1 << pScrn->offset.green) |
920ab47cfaaSmrg      (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
921ab47cfaaSmrg    pPriv->videoStatus = 0;
922ab47cfaaSmrg    pPriv->brightness = 0;
923ab47cfaaSmrg    pPriv->contrast = 128;
924ab47cfaaSmrg    pPriv->saturation = 128;
925ab47cfaaSmrg#if 0
926ab47cfaaSmrg    /*
927ab47cfaaSmrg     * The S3 driver has these values for some of the chips.  I have yet
928ab47cfaaSmrg     * to find any Savage where these make sense.
929ab47cfaaSmrg     */
930ab47cfaaSmrg    pPriv->brightness = 64;
931ab47cfaaSmrg    pPriv->contrast = 16;
932ab47cfaaSmrg    pPriv->saturation = 128;
933ab47cfaaSmrg#endif
934ab47cfaaSmrg    pPriv->hue = 0;
935ab47cfaaSmrg    pPriv->lastKnownPitch = 0;
936ab47cfaaSmrg
937ab47cfaaSmrg    pPriv->interpolation = FALSE;
938ab47cfaaSmrg
939ab47cfaaSmrg    /* gotta uninit this someplace */
940ab47cfaaSmrg    REGION_NULL(pScreen, &pPriv->clip);
941ab47cfaaSmrg
942ab47cfaaSmrg    psav->adaptor = adapt;
943ab47cfaaSmrg
944ab47cfaaSmrg    #if 0
945ab47cfaaSmrg    psav->BlockHandler = pScreen->BlockHandler;
946ab47cfaaSmrg    pScreen->BlockHandler = SavageBlockHandler;
947ab47cfaaSmrg    #endif
948ab47cfaaSmrg
949ab47cfaaSmrg    return adapt;
950ab47cfaaSmrg}
951ab47cfaaSmrg
952ab47cfaaSmrg
953ab47cfaaSmrg/* SavageClipVideo -
954ab47cfaaSmrg
955ab47cfaaSmrg   Takes the dst box in standard X BoxRec form (top and left
956ab47cfaaSmrg   edges inclusive, bottom and right exclusive).  The new dst
957ab47cfaaSmrg   box is returned.  The source boundaries are given (x1, y1
958ab47cfaaSmrg   inclusive, x2, y2 exclusive) and returned are the new source
959ab47cfaaSmrg   boundaries in 16.16 fixed point.
960ab47cfaaSmrg*/
961ab47cfaaSmrg
962ab47cfaaSmrgstatic void
963ab47cfaaSmrgSavageClipVideo(
964ab47cfaaSmrg  BoxPtr dst,
965ab47cfaaSmrg  INT32 *x1,
966ab47cfaaSmrg  INT32 *x2,
967ab47cfaaSmrg  INT32 *y1,
968ab47cfaaSmrg  INT32 *y2,
969ab47cfaaSmrg  BoxPtr extents,            /* extents of the clip region */
970ab47cfaaSmrg  INT32 width,
971ab47cfaaSmrg  INT32 height
972ab47cfaaSmrg){
973ab47cfaaSmrg    INT32 vscale, hscale, delta;
974ab47cfaaSmrg    int diff;
975ab47cfaaSmrg
976ab47cfaaSmrg    hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
977ab47cfaaSmrg    vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
978ab47cfaaSmrg
979ab47cfaaSmrg    *x1 <<= 16; *x2 <<= 16;
980ab47cfaaSmrg    *y1 <<= 16; *y2 <<= 16;
981ab47cfaaSmrg
982ab47cfaaSmrg    diff = extents->x1 - dst->x1;
983ab47cfaaSmrg    if(diff > 0) {
984ab47cfaaSmrg	dst->x1 = extents->x1;
985ab47cfaaSmrg	*x1 += diff * hscale;
986ab47cfaaSmrg    }
987ab47cfaaSmrg    diff = dst->x2 - extents->x2;
988ab47cfaaSmrg    if(diff > 0) {
989ab47cfaaSmrg	dst->x2 = extents->x2;
990ab47cfaaSmrg	*x2 -= diff * hscale;
991ab47cfaaSmrg    }
992ab47cfaaSmrg    diff = extents->y1 - dst->y1;
993ab47cfaaSmrg    if(diff > 0) {
994ab47cfaaSmrg	dst->y1 = extents->y1;
995ab47cfaaSmrg	*y1 += diff * vscale;
996ab47cfaaSmrg    }
997ab47cfaaSmrg    diff = dst->y2 - extents->y2;
998ab47cfaaSmrg    if(diff > 0) {
999ab47cfaaSmrg	dst->y2 = extents->y2;
1000ab47cfaaSmrg	*y2 -= diff * vscale;
1001ab47cfaaSmrg    }
1002ab47cfaaSmrg
1003ab47cfaaSmrg    if(*x1 < 0) {
1004ab47cfaaSmrg	diff =  (- *x1 + hscale - 1)/ hscale;
1005ab47cfaaSmrg	dst->x1 += diff;
1006ab47cfaaSmrg	*x1 += diff * hscale;
1007ab47cfaaSmrg    }
1008ab47cfaaSmrg    delta = *x2 - (width << 16);
1009ab47cfaaSmrg    if(delta > 0) {
1010ab47cfaaSmrg	diff = (delta + hscale - 1)/ hscale;
1011ab47cfaaSmrg	dst->x2 -= diff;
1012ab47cfaaSmrg	*x2 -= diff * hscale;
1013ab47cfaaSmrg    }
1014ab47cfaaSmrg    if(*y1 < 0) {
1015ab47cfaaSmrg	diff =  (- *y1 + vscale - 1)/ vscale;
1016ab47cfaaSmrg	dst->y1 += diff;
1017ab47cfaaSmrg	*y1 += diff * vscale;
1018ab47cfaaSmrg    }
1019ab47cfaaSmrg    delta = *y2 - (height << 16);
1020ab47cfaaSmrg    if(delta > 0) {
1021ab47cfaaSmrg	diff = (delta + vscale - 1)/ vscale;
1022ab47cfaaSmrg	dst->y2 -= diff;
1023ab47cfaaSmrg	*y2 -= diff * vscale;
1024ab47cfaaSmrg    }
1025ab47cfaaSmrg}
1026ab47cfaaSmrg
1027ab47cfaaSmrgstatic void
1028ab47cfaaSmrgSavageStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
1029ab47cfaaSmrg{
1030ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1031ab47cfaaSmrg    /*SavagePtr psav = SAVPTR(pScrn); */
1032ab47cfaaSmrg
1033ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageStopVideo\n");
1034ab47cfaaSmrg
1035ab47cfaaSmrg    REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1036ab47cfaaSmrg
1037ab47cfaaSmrg    if(shutdown) {
1038ab47cfaaSmrg      /*SavageClipVWindow(pScrn);*/
1039ab47cfaaSmrg 	SavageStreamsOff( pScrn );
1040ab47cfaaSmrg        if (pPriv->video_memory != NULL) {
1041ab47cfaaSmrg	    SavageFreeMemory(pScrn, pPriv->video_memory);
1042ab47cfaaSmrg	    pPriv->video_memory = NULL;
1043ab47cfaaSmrg        }
1044ab47cfaaSmrg	pPriv->videoStatus = 0;
1045ab47cfaaSmrg    } else {
1046ab47cfaaSmrg	if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
1047ab47cfaaSmrg	    pPriv->videoStatus |= OFF_TIMER;
1048ab47cfaaSmrg	    pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
1049ab47cfaaSmrg	}
1050ab47cfaaSmrg    }
1051ab47cfaaSmrg}
1052ab47cfaaSmrg
1053ab47cfaaSmrg
1054ab47cfaaSmrgstatic int
1055ab47cfaaSmrgSavageSetPortAttribute(
1056ab47cfaaSmrg    ScrnInfoPtr pScrn,
1057ab47cfaaSmrg    Atom attribute,
1058ab47cfaaSmrg    INT32 value,
1059ab47cfaaSmrg    pointer data
1060ab47cfaaSmrg){
1061ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1062ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1063ab47cfaaSmrg
1064ab47cfaaSmrg    if(attribute == xvColorKey) {
1065ab47cfaaSmrg	pPriv->colorKey = value;
1066ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1067ab47cfaaSmrg	    SavageSetColorKey( pScrn );
1068ab47cfaaSmrg	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1069ab47cfaaSmrg    }
1070ab47cfaaSmrg    else if( attribute == xvBrightness) {
1071ab47cfaaSmrg	if((value < -128) || (value > 127))
1072ab47cfaaSmrg	    return BadValue;
1073ab47cfaaSmrg	pPriv->brightness = value;
1074ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1075ab47cfaaSmrg	    SavageSetColor( pScrn );
1076ab47cfaaSmrg    }
1077ab47cfaaSmrg    else if( attribute == xvContrast) {
1078ab47cfaaSmrg	if((value < 0) || (value > 255))
1079ab47cfaaSmrg	    return BadValue;
1080ab47cfaaSmrg	pPriv->contrast = value;
1081ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1082ab47cfaaSmrg	    SavageSetColor( pScrn );
1083ab47cfaaSmrg    }
1084ab47cfaaSmrg    else if( attribute == xvSaturation) {
1085ab47cfaaSmrg	if((value < 0) || (value > 255))
1086ab47cfaaSmrg	    return BadValue;
1087ab47cfaaSmrg	pPriv->saturation = value;
1088ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1089ab47cfaaSmrg	    SavageSetColor( pScrn );
1090ab47cfaaSmrg    }
1091ab47cfaaSmrg    else if( attribute == xvHue) {
1092ab47cfaaSmrg	if((value < -180) || (value > 180))
1093ab47cfaaSmrg	    return BadValue;
1094ab47cfaaSmrg	pPriv->hue = value;
1095ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1096ab47cfaaSmrg	    SavageSetColor( pScrn );
1097ab47cfaaSmrg    }
1098ab47cfaaSmrg    else if( attribute == xvInterpolation) {
1099ab47cfaaSmrg        if((value < 0) || (value > 1))
1100ab47cfaaSmrg            return BadValue;
1101ab47cfaaSmrg        if (value == 1)
1102ab47cfaaSmrg            pPriv->interpolation = TRUE;
1103ab47cfaaSmrg	else
1104ab47cfaaSmrg	    pPriv->interpolation = FALSE;
1105ab47cfaaSmrg    }
1106ab47cfaaSmrg    else
1107ab47cfaaSmrg	return BadMatch;
1108ab47cfaaSmrg
1109ab47cfaaSmrg    return Success;
1110ab47cfaaSmrg}
1111ab47cfaaSmrg
1112ab47cfaaSmrg
1113ab47cfaaSmrgstatic int
1114ab47cfaaSmrgSavageGetPortAttribute(
1115ab47cfaaSmrg  ScrnInfoPtr pScrn,
1116ab47cfaaSmrg  Atom attribute,
1117ab47cfaaSmrg  INT32 *value,
1118ab47cfaaSmrg  pointer data
1119ab47cfaaSmrg){
1120ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1121ab47cfaaSmrg
1122ab47cfaaSmrg    if(attribute == xvColorKey) {
1123ab47cfaaSmrg	*value = pPriv->colorKey;
1124ab47cfaaSmrg    }
1125ab47cfaaSmrg    else if( attribute == xvBrightness ) {
1126ab47cfaaSmrg	*value = pPriv->brightness;
1127ab47cfaaSmrg    }
1128ab47cfaaSmrg    else if( attribute == xvContrast ) {
1129ab47cfaaSmrg	*value = pPriv->contrast;
1130ab47cfaaSmrg    }
1131ab47cfaaSmrg    else if( attribute == xvHue ) {
1132ab47cfaaSmrg	*value = pPriv->hue;
1133ab47cfaaSmrg    }
1134ab47cfaaSmrg    else if( attribute == xvSaturation ) {
1135ab47cfaaSmrg	*value = pPriv->saturation;
1136ab47cfaaSmrg    }
1137ab47cfaaSmrg    else if( attribute == xvInterpolation ) {
1138ab47cfaaSmrg        *value = pPriv->interpolation;
1139ab47cfaaSmrg    }
1140ab47cfaaSmrg    else return BadMatch;
1141ab47cfaaSmrg
1142ab47cfaaSmrg    return Success;
1143ab47cfaaSmrg}
1144ab47cfaaSmrg
1145ab47cfaaSmrgstatic void
1146ab47cfaaSmrgSavageQueryBestSize(
1147ab47cfaaSmrg  ScrnInfoPtr pScrn,
1148ab47cfaaSmrg  Bool motion,
1149ab47cfaaSmrg  short vid_w, short vid_h,
1150ab47cfaaSmrg  short drw_w, short drw_h,
1151ab47cfaaSmrg  unsigned int *p_w, unsigned int *p_h,
1152ab47cfaaSmrg  pointer data
1153ab47cfaaSmrg){
1154ab47cfaaSmrg    /* What are the real limits for the Savage? */
1155ab47cfaaSmrg
1156ab47cfaaSmrg    *p_w = drw_w;
1157ab47cfaaSmrg    *p_h = drw_h;
1158ab47cfaaSmrg
1159ab47cfaaSmrg    if(*p_w > 16384) *p_w = 16384;
1160ab47cfaaSmrg}
1161ab47cfaaSmrg
1162ab47cfaaSmrg/* SavageCopyPlanarDataBCI() causes artifacts on the screen when used on savage4.
1163ab47cfaaSmrg * It's probably something with the BCI.  Maybe we need a waitforidle() or
1164ab47cfaaSmrg * something...
1165ab47cfaaSmrg */
1166ab47cfaaSmrgstatic void
1167ab47cfaaSmrgSavageCopyPlanarDataBCI(
1168ab47cfaaSmrg    ScrnInfoPtr pScrn,
1169ab47cfaaSmrg    unsigned char *srcY, /* Y */
1170ab47cfaaSmrg    unsigned char *srcV, /* V */
1171ab47cfaaSmrg    unsigned char *srcU, /* U */
1172ab47cfaaSmrg    unsigned char *dst,
1173ab47cfaaSmrg    int srcPitch, int srcPitch2,
1174ab47cfaaSmrg    int dstPitch,
1175ab47cfaaSmrg    int h,int w)
1176ab47cfaaSmrg{
1177ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1178ab47cfaaSmrg    /* half of the dest buffer for copying the YVU data to it ??? */
1179ab47cfaaSmrg    unsigned char *dstCopy = (unsigned char *)(((unsigned long)dst
1180ab47cfaaSmrg                                                + 2 * srcPitch * h
1181ab47cfaaSmrg                                                + 0x0f) & ~0x0f);
1182ab47cfaaSmrg    /* for pixel transfer */
1183ab47cfaaSmrg    unsigned long offsetY = (unsigned long)dstCopy - (unsigned long)psav->FBBase;
1184ab47cfaaSmrg    unsigned long offsetV = offsetY +  srcPitch * h;
1185ab47cfaaSmrg    unsigned long offsetU = offsetV +  srcPitch2 * (h>>1);
1186ab47cfaaSmrg    unsigned long dstOffset  = (unsigned long)dst - (unsigned long)psav->FBBase;
1187ab47cfaaSmrg    int i;
1188ab47cfaaSmrg
1189ab47cfaaSmrg    BCI_GET_PTR;
1190ab47cfaaSmrg
1191ab47cfaaSmrg    /* copy Y planar */
1192ab47cfaaSmrg    for (i=0;i<srcPitch * h;i++) {
1193ab47cfaaSmrg        dstCopy[i] = srcY[i];
1194ab47cfaaSmrg    }
1195ab47cfaaSmrg
1196ab47cfaaSmrg    /* copy V planar */
1197ab47cfaaSmrg    dstCopy = dstCopy + srcPitch * h;
1198ab47cfaaSmrg    for (i=0;i<srcPitch2 * (h>>1);i++) {
1199ab47cfaaSmrg        dstCopy[i] = srcV[i];
1200ab47cfaaSmrg    }
1201ab47cfaaSmrg
1202ab47cfaaSmrg    /* copy U planar */
1203ab47cfaaSmrg    dstCopy = dstCopy + srcPitch2 * (h>>1);
1204ab47cfaaSmrg    for (i=0;i<srcPitch2 * (h>>1);i++) {
1205ab47cfaaSmrg        dstCopy[i] = srcU[i];
1206ab47cfaaSmrg    }
1207ab47cfaaSmrg
1208ab47cfaaSmrg    /*
1209ab47cfaaSmrg     * Transfer pixel data from one memory location to another location
1210ab47cfaaSmrg     * and reformat the data during the transfer
1211ab47cfaaSmrg     * a. program BCI51 to specify the source information
1212ab47cfaaSmrg     * b. program BCI52 to specify the destination information
1213ab47cfaaSmrg     * c. program BCI53 to specify the source dimensions
1214ab47cfaaSmrg     * d. program BCI54 to specify the destination dimensions
1215ab47cfaaSmrg     * e. (if the data is in YCbCr420 format)program BCI55,BCI56,BCI57 to
1216ab47cfaaSmrg     *    locations of the Y,Cb,and Cr data
1217ab47cfaaSmrg     * f. program BCI50(command=011) to specify the formatting options and
1218ab47cfaaSmrg     *    kick off the transfer
1219ab47cfaaSmrg     * this command can be used for color space conversion(YCbCr to RGB)
1220ab47cfaaSmrg     * or for oversampling, but not for both simultaneously. it can also be
1221ab47cfaaSmrg     * used to do mastered image transfer when the source is tiled
1222ab47cfaaSmrg     */
1223ab47cfaaSmrg
1224ab47cfaaSmrg    w = (w+0xf)&0xff0;
1225ab47cfaaSmrg    psav->WaitQueue(psav,11);
1226ab47cfaaSmrg    BCI_SEND(0x96070051);
1227ab47cfaaSmrg    BCI_SEND(offsetY);
1228ab47cfaaSmrg
1229ab47cfaaSmrg    BCI_SEND(dstOffset);
1230ab47cfaaSmrg
1231ab47cfaaSmrg    BCI_SEND(((h-1)<<16)|((w-1)>>3));
1232ab47cfaaSmrg
1233ab47cfaaSmrg    BCI_SEND(dstPitch >> 3);
1234ab47cfaaSmrg
1235ab47cfaaSmrg
1236ab47cfaaSmrg    BCI_SEND(offsetU);
1237ab47cfaaSmrg    BCI_SEND(offsetV);
1238ab47cfaaSmrg
1239ab47cfaaSmrg    BCI_SEND((srcPitch2 << 16)| srcPitch2);
1240ab47cfaaSmrg
1241ab47cfaaSmrg    BCI_SEND(0x96010050);
1242ab47cfaaSmrg    BCI_SEND(0x00200003 | srcPitch);
1243ab47cfaaSmrg    BCI_SEND(0xC0170000);
1244ab47cfaaSmrg}
1245ab47cfaaSmrg
1246ab47cfaaSmrgstatic void
1247ab47cfaaSmrgSavageCopyData(
1248ab47cfaaSmrg  unsigned char *src,
1249ab47cfaaSmrg  unsigned char *dst,
1250ab47cfaaSmrg  int srcPitch,
1251ab47cfaaSmrg  int dstPitch,
1252ab47cfaaSmrg  int h,
1253ab47cfaaSmrg  int w
1254ab47cfaaSmrg){
1255ab47cfaaSmrg    w <<= 1;
1256ab47cfaaSmrg    while(h--) {
1257ab47cfaaSmrg	memcpy(dst, src, w);
1258ab47cfaaSmrg	src += srcPitch;
1259ab47cfaaSmrg	dst += dstPitch;
1260ab47cfaaSmrg    }
1261ab47cfaaSmrg}
1262ab47cfaaSmrg
1263ab47cfaaSmrgstatic void
1264ab47cfaaSmrgSavageCopyPlanarData(
1265ab47cfaaSmrg   unsigned char *src1, /* Y */
1266ab47cfaaSmrg   unsigned char *src2, /* V */
1267ab47cfaaSmrg   unsigned char *src3, /* U */
1268ab47cfaaSmrg   unsigned char *dst1,
1269ab47cfaaSmrg   int srcPitch,
1270ab47cfaaSmrg   int srcPitch2,
1271ab47cfaaSmrg   int dstPitch,
1272ab47cfaaSmrg   int h,
1273ab47cfaaSmrg   int w
1274ab47cfaaSmrg){
1275ab47cfaaSmrg   CARD32 *dst = (CARD32*)dst1;
1276ab47cfaaSmrg   int i, j;
1277ab47cfaaSmrg
1278ab47cfaaSmrg   dstPitch >>= 2;
1279ab47cfaaSmrg   w >>= 1;
1280ab47cfaaSmrg
1281ab47cfaaSmrg   for(j = 0; j < h; j++) {
1282ab47cfaaSmrg	for(i = 0; i < w; i++) {
1283ab47cfaaSmrg/* Shouldn't this be 'if LITTLEENDIAN'? */
1284ab47cfaaSmrg#if 1
1285ab47cfaaSmrg	    dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
1286ab47cfaaSmrg		     (src3[i] << 8) | (src2[i] << 24);
1287ab47cfaaSmrg#else
1288ab47cfaaSmrg	    dst[i] = (src1[i << 1] << 24) | (src1[(i << 1) + 1] << 8) |
1289ab47cfaaSmrg		     (src3[i] << 0) | (src2[i] << 16);
1290ab47cfaaSmrg#endif
1291ab47cfaaSmrg	}
1292ab47cfaaSmrg	dst += dstPitch;
1293ab47cfaaSmrg	src1 += srcPitch;
1294ab47cfaaSmrg	if(j & 1) {
1295ab47cfaaSmrg	    src2 += srcPitch2;
1296ab47cfaaSmrg	    src3 += srcPitch2;
1297ab47cfaaSmrg	}
1298ab47cfaaSmrg   }
1299ab47cfaaSmrg}
1300ab47cfaaSmrg
1301ab47cfaaSmrgstatic void
1302ab47cfaaSmrgSavageVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
1303ab47cfaaSmrg{
1304ab47cfaaSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1305ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1306ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1307ab47cfaaSmrg
1308ab47cfaaSmrg    if (pPriv->video_memory == area)
1309ab47cfaaSmrg        pPriv->video_memory = NULL;
1310ab47cfaaSmrg}
1311ab47cfaaSmrg
1312ab47cfaaSmrgstatic CARD32
1313ab47cfaaSmrgSavageAllocateMemory(
1314ab47cfaaSmrg    ScrnInfoPtr pScrn,
1315ab47cfaaSmrg    void **mem_struct,
1316ab47cfaaSmrg    int size
1317ab47cfaaSmrg){
1318ab47cfaaSmrg    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
1319ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1320ab47cfaaSmrg    int offset = 0;
1321ab47cfaaSmrg
1322ab47cfaaSmrg    if (psav->useEXA) {
1323ab47cfaaSmrg	ExaOffscreenArea *area = *mem_struct;
1324ab47cfaaSmrg
1325ab47cfaaSmrg	if (area != NULL) {
1326ab47cfaaSmrg	    if (area->size >= size)
1327ab47cfaaSmrg		return area->offset;
1328ab47cfaaSmrg
1329ab47cfaaSmrg	    exaOffscreenFree(pScrn->pScreen, area);
1330ab47cfaaSmrg	}
1331ab47cfaaSmrg
1332ab47cfaaSmrg	area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, SavageVideoSave,
1333ab47cfaaSmrg				 NULL);
1334ab47cfaaSmrg	*mem_struct = area;
1335ab47cfaaSmrg	if (area == NULL)
1336ab47cfaaSmrg	    return 0;
1337ab47cfaaSmrg	offset = area->offset;
1338ab47cfaaSmrg    }
1339ab47cfaaSmrg
1340ab47cfaaSmrg    if (!psav->useEXA) {
1341ab47cfaaSmrg	FBLinearPtr linear = *mem_struct;
1342ab47cfaaSmrg	int cpp = pScrn->bitsPerPixel / 8;
1343ab47cfaaSmrg
1344ab47cfaaSmrg	/* XAA allocates in units of pixels at the screen bpp, so adjust size
1345ab47cfaaSmrg	 * appropriately.
1346ab47cfaaSmrg	 */
1347ab47cfaaSmrg	size = (size + cpp - 1) / cpp;
1348ab47cfaaSmrg
1349ab47cfaaSmrg	if (linear) {
1350ab47cfaaSmrg	    if(linear->size >= size)
1351ab47cfaaSmrg		return linear->offset * cpp;
1352ab47cfaaSmrg
1353ab47cfaaSmrg	    if(xf86ResizeOffscreenLinear(linear, size))
1354ab47cfaaSmrg		return linear->offset * cpp;
1355ab47cfaaSmrg
1356ab47cfaaSmrg	    xf86FreeOffscreenLinear(linear);
1357ab47cfaaSmrg	}
1358ab47cfaaSmrg
1359ab47cfaaSmrg	linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
1360ab47cfaaSmrg						NULL, NULL, NULL);
1361ab47cfaaSmrg	*mem_struct = linear;
1362ab47cfaaSmrg
1363ab47cfaaSmrg	if (!linear) {
1364ab47cfaaSmrg	    int max_size;
1365ab47cfaaSmrg
1366ab47cfaaSmrg	    xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
1367ab47cfaaSmrg					    PRIORITY_EXTREME);
1368ab47cfaaSmrg
1369ab47cfaaSmrg	    if(max_size < size)
1370ab47cfaaSmrg		return 0;
1371ab47cfaaSmrg
1372ab47cfaaSmrg	    xf86PurgeUnlockedOffscreenAreas(pScreen);
1373ab47cfaaSmrg	    linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
1374ab47cfaaSmrg						     NULL, NULL, NULL);
1375ab47cfaaSmrg	    *mem_struct = linear;
1376ab47cfaaSmrg	    if (!linear)
1377ab47cfaaSmrg		return 0;
1378ab47cfaaSmrg	}
1379ab47cfaaSmrg	offset = linear->offset * cpp;
1380ab47cfaaSmrg    }
1381ab47cfaaSmrg
1382ab47cfaaSmrg    return offset;
1383ab47cfaaSmrg}
1384ab47cfaaSmrg
1385ab47cfaaSmrgstatic void
1386ab47cfaaSmrgSavageFreeMemory(
1387ab47cfaaSmrg   ScrnInfoPtr pScrn,
1388ab47cfaaSmrg   void *mem_struct
1389ab47cfaaSmrg){
1390ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1391ab47cfaaSmrg
1392ab47cfaaSmrg    if (psav->useEXA) {
1393ab47cfaaSmrg	ExaOffscreenArea *area = mem_struct;
1394ab47cfaaSmrg
1395ab47cfaaSmrg	if (area != NULL)
1396ab47cfaaSmrg	    exaOffscreenFree(pScrn->pScreen, area);
1397ab47cfaaSmrg    }
1398ab47cfaaSmrg    if (!psav->useEXA) {
1399ab47cfaaSmrg	FBLinearPtr linear = mem_struct;
1400ab47cfaaSmrg
1401ab47cfaaSmrg	if (linear != NULL)
1402ab47cfaaSmrg	    xf86FreeOffscreenLinear(linear);
1403ab47cfaaSmrg    }
1404ab47cfaaSmrg}
1405ab47cfaaSmrg
1406ab47cfaaSmrgstatic void
1407ab47cfaaSmrgSavageSetBlend(ScrnInfoPtr pScrn, int id)
1408ab47cfaaSmrg{
1409ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1410ab47cfaaSmrg
1411ab47cfaaSmrg    if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) )
1412ab47cfaaSmrg    {
1413ab47cfaaSmrg	psav->blendBase = GetBlendForFourCC( id );
1414ab47cfaaSmrg	xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase );
1415ab47cfaaSmrg	if (psav->IsSecondary) {
1416ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
1417ab47cfaaSmrg	} else if (psav->IsPrimary) {
1418ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
1419ab47cfaaSmrg	} else {
1420ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
1421ab47cfaaSmrg#if 0
1422ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
1423ab47cfaaSmrg#endif
1424ab47cfaaSmrg	}
1425ab47cfaaSmrg    } else if (psav->Chipset == S3_SAVAGE2000) {
1426ab47cfaaSmrg      psav->blendBase = GetBlendForFourCC2000( id );
1427ab47cfaaSmrg      xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase );
1428ab47cfaaSmrg      if (id != FOURCC_YV12)
1429ab47cfaaSmrg	OUTREG( BLEND_CONTROL,
1430ab47cfaaSmrg		((psav->blendBase << 24) | (8 << 2) /*| 0x20000000*/));
1431ab47cfaaSmrg      else
1432ab47cfaaSmrg	OUTREG( BLEND_CONTROL,
1433ab47cfaaSmrg		((psav->blendBase << 24) | (8 << 2) /*| 0x10000000*/));
1434ab47cfaaSmrg    }
1435ab47cfaaSmrg
1436ab47cfaaSmrg    psav->videoFourCC = id;
1437ab47cfaaSmrg}
1438ab47cfaaSmrg
1439ab47cfaaSmrgstatic void
1440ab47cfaaSmrgSavageDisplayVideoOld(
1441ab47cfaaSmrg    ScrnInfoPtr pScrn,
1442ab47cfaaSmrg    int id,
1443ab47cfaaSmrg    int offset,
1444ab47cfaaSmrg    short width, short height,
1445ab47cfaaSmrg    int pitch,
1446ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1447ab47cfaaSmrg    BoxPtr dstBox,
1448ab47cfaaSmrg    short src_w, short src_h,
1449ab47cfaaSmrg    short drw_w, short drw_h
1450ab47cfaaSmrg){
1451ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1452ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1453ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1454ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1455ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
1456ab47cfaaSmrg    CARD32 ssControl;
1457ab47cfaaSmrg    int scalratio;
1458ab47cfaaSmrg
1459ab47cfaaSmrg
1460ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1461ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1462ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
1463ab47cfaaSmrg#if 0
1464ab47cfaaSmrg    if ( psav->videoFourCC != id ) {
1465ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1466ab47cfaaSmrg	SavageResetVideo(pScrn);
1467ab47cfaaSmrg    }
1468ab47cfaaSmrg#endif
1469ab47cfaaSmrg    if( psav->videoFourCC != id )
1470ab47cfaaSmrg      SavageStreamsOff(pScrn);
1471ab47cfaaSmrg
1472ab47cfaaSmrg    if( !psav->videoFlags & VF_STREAMS_ON )
1473ab47cfaaSmrg      {
1474ab47cfaaSmrg        SavageSetBlend(pScrn,id);
1475ab47cfaaSmrg	SavageStreamsOn(pScrn);
1476ab47cfaaSmrg	SavageResetVideo(pScrn);
1477ab47cfaaSmrg      }
1478ab47cfaaSmrg
1479ab47cfaaSmrg    if (S3_MOBILE_TWISTER_SERIES(psav->Chipset)
1480ab47cfaaSmrg        && psav->FPExpansion) {
1481ab47cfaaSmrg        drw_w = (((float)(drw_w * psav->XExp1)/(float)psav->XExp2)+1);
1482ab47cfaaSmrg        drw_h = (float)(drw_h * psav->YExp1)/(float)psav->YExp2+1;
1483ab47cfaaSmrg        dstBox->x1 = (float)(dstBox->x1 * psav->XExp1)/(float)psav->XExp2;
1484ab47cfaaSmrg        dstBox->y1 = (float)(dstBox->y1 * psav->YExp1)/(float)psav->YExp2;
1485ab47cfaaSmrg
1486ab47cfaaSmrg        dstBox->x1 += psav->displayXoffset;
1487ab47cfaaSmrg        dstBox->y1 += psav->displayYoffset;
1488ab47cfaaSmrg    }
1489ab47cfaaSmrg
1490ab47cfaaSmrg    /*
1491ab47cfaaSmrg     * Process horizontal scaling
1492ab47cfaaSmrg     *  upscaling and downscaling smaller than 2:1 controled by MM8198
1493ab47cfaaSmrg     *  MM8190 controls downscaling mode larger than 2:1
1494ab47cfaaSmrg     */
1495ab47cfaaSmrg    scalratio = 0;
1496ab47cfaaSmrg    ssControl = 0;
1497ab47cfaaSmrg
1498ab47cfaaSmrg    if (src_w >= (drw_w * 2)) {
1499ab47cfaaSmrg        if (src_w < (drw_w * 4)) {
1500ab47cfaaSmrg            scalratio = HSCALING(2,1);
1501ab47cfaaSmrg        } else if (src_w < (drw_w * 8)) {
1502ab47cfaaSmrg            ssControl |= HDSCALE_4;
1503ab47cfaaSmrg        } else if (src_w < (drw_w * 16)) {
1504ab47cfaaSmrg            ssControl |= HDSCALE_8;
1505ab47cfaaSmrg        } else if (src_w < (drw_w * 32)) {
1506ab47cfaaSmrg            ssControl |= HDSCALE_16;
1507ab47cfaaSmrg        }  else if (src_w < (drw_w * 64)) {
1508ab47cfaaSmrg            ssControl |= HDSCALE_32;
1509ab47cfaaSmrg        } else
1510ab47cfaaSmrg            ssControl |= HDSCALE_64;
1511ab47cfaaSmrg    } else
1512ab47cfaaSmrg        scalratio = HSCALING(src_w,drw_w);
1513ab47cfaaSmrg
1514ab47cfaaSmrg    ssControl |= src_w;
1515ab47cfaaSmrg    /*ssControl |= (1 << 24);*/
1516ab47cfaaSmrg    ssControl |= (GetBlendForFourCC(psav->videoFourCC) << 24);
1517ab47cfaaSmrg    /* Wait for VBLANK. */
1518ab47cfaaSmrg    VerticalRetraceWait();
1519ab47cfaaSmrg    OUTREG(SSTREAM_CONTROL_REG, ssControl);
1520ab47cfaaSmrg    if (scalratio)
1521ab47cfaaSmrg        OUTREG(SSTREAM_STRETCH_REG,scalratio);
1522ab47cfaaSmrg
1523ab47cfaaSmrg    /* Calculate vertical scale factor. */
1524ab47cfaaSmrg    OUTREG(SSTREAM_VINITIAL_REG, 0 );
1525ab47cfaaSmrg    /*OUTREG(SSTREAM_VSCALE_REG, (src_h << 15) / drw_h );*/
1526ab47cfaaSmrg    OUTREG(SSTREAM_VSCALE_REG, VSCALING(src_h,drw_h));
1527ab47cfaaSmrg
1528ab47cfaaSmrg    /* Set surface location and stride. */
1529ab47cfaaSmrg    OUTREG(SSTREAM_FBADDR0_REG, (offset + (x1>>15)) & (0x1ffffff & ~BASE_PAD) );
1530ab47cfaaSmrg    OUTREG(SSTREAM_FBADDR1_REG, 0);
1531ab47cfaaSmrg    OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff );
1532ab47cfaaSmrg
1533ab47cfaaSmrg    OUTREG(SSTREAM_WINDOW_START_REG, OS_XY(dstBox->x1, dstBox->y1) );
1534ab47cfaaSmrg    OUTREG(SSTREAM_WINDOW_SIZE_REG, OS_WH(dstBox->x2-dstBox->x1,
1535ab47cfaaSmrg                                          dstBox->y2-dstBox->y1));
1536ab47cfaaSmrg
1537ab47cfaaSmrg    /*
1538ab47cfaaSmrg     * MM81E8:Secondary Stream Source Line Count
1539ab47cfaaSmrg     *   bit_0~10: # of lines in the source image (before scaling)
1540ab47cfaaSmrg     *   bit_15 = 1: Enable vertical interpolation
1541ab47cfaaSmrg     *            0: Line duplicaion
1542ab47cfaaSmrg     */
1543ab47cfaaSmrg    /*
1544ab47cfaaSmrg     * Vertical Interpolation is very bandwidth intensive.  Some savages can't
1545ab47cfaaSmrg     * seem to handle it.  Default is line doubling.  --AGD
1546ab47cfaaSmrg     */
1547ab47cfaaSmrg    if (pPriv->interpolation) {
1548ab47cfaaSmrg        if (src_w * 16 <= 0x3300) {
1549ab47cfaaSmrg            OUTREG(SSTREAM_LINES_REG, 0x8000 | src_h );
1550ab47cfaaSmrg	    OUTREG(FIFO_CONTROL, (INREG(FIFO_CONTROL) + 1));
1551ab47cfaaSmrg        } else {
1552ab47cfaaSmrg            OUTREG(SSTREAM_LINES_REG, src_h );
1553ab47cfaaSmrg        }
1554ab47cfaaSmrg    } else {
1555ab47cfaaSmrg        OUTREG(SSTREAM_LINES_REG, src_h );
1556ab47cfaaSmrg    }
1557ab47cfaaSmrg
1558ab47cfaaSmrg#if 0
1559ab47cfaaSmrg    /* Set color key on primary. */
1560ab47cfaaSmrg
1561ab47cfaaSmrg    SavageSetColorKey( pScrn );
1562ab47cfaaSmrg#endif
1563ab47cfaaSmrg
1564ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1565ab47cfaaSmrg
1566ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1567ab47cfaaSmrg    {
1568ab47cfaaSmrg	unsigned char cr92;
1569ab47cfaaSmrg
1570ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1571ab47cfaaSmrg
1572ab47cfaaSmrg	pitch = (pitch + 7) / 8;
1573ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1574ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1575ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1576ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1577ab47cfaaSmrg	if (psav->bTiled && (( drw_h > src_h) || (drw_w > src_w)))
1578ab47cfaaSmrg	    VGAOUT8(vgaCRReg, pitch | 0xf);
1579ab47cfaaSmrg	else
1580ab47cfaaSmrg	    VGAOUT8(vgaCRReg, pitch);
1581ab47cfaaSmrg    }
1582ab47cfaaSmrg}
1583ab47cfaaSmrg
1584ab47cfaaSmrgstatic void
1585ab47cfaaSmrgSavageDisplayVideoNew(
1586ab47cfaaSmrg    ScrnInfoPtr pScrn,
1587ab47cfaaSmrg    int id,
1588ab47cfaaSmrg    int offset,
1589ab47cfaaSmrg    short width, short height,
1590ab47cfaaSmrg    int pitch,
1591ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1592ab47cfaaSmrg    BoxPtr dstBox,
1593ab47cfaaSmrg    short src_w, short src_h,
1594ab47cfaaSmrg    short drw_w, short drw_h
1595ab47cfaaSmrg){
1596ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1597ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1598ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1599ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1600ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
1601ab47cfaaSmrg
1602ab47cfaaSmrg
1603ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1604ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1605ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
1606ab47cfaaSmrg#if 0
1607ab47cfaaSmrg    if ( psav->videoFourCC != id ) {
1608ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1609ab47cfaaSmrg	SavageResetVideo(pScrn);
1610ab47cfaaSmrg    }
1611ab47cfaaSmrg#endif
1612ab47cfaaSmrg    if( psav->videoFourCC != id )
1613ab47cfaaSmrg      SavageStreamsOff(pScrn);
1614ab47cfaaSmrg
1615ab47cfaaSmrg    if( !psav->videoFlags & VF_STREAMS_ON )
1616ab47cfaaSmrg      {
1617ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1618ab47cfaaSmrg	SavageStreamsOn(pScrn);
1619ab47cfaaSmrg	SavageResetVideo(pScrn);
1620ab47cfaaSmrg      }
1621ab47cfaaSmrg
1622ab47cfaaSmrg    /* Calculate horizontal and vertical scale factors. */
1623ab47cfaaSmrg
1624ab47cfaaSmrg    if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) &&
1625ab47cfaaSmrg	    (psav->DisplayType == MT_LCD) &&
1626ab47cfaaSmrg	    !psav->CrtOnly &&
1627ab47cfaaSmrg	    !psav->TvOn)
1628ab47cfaaSmrg    {
1629ab47cfaaSmrg	drw_w = (drw_w * psav->XExp1)/psav->XExp2 + 1;
1630ab47cfaaSmrg	drw_h = (drw_h * psav->YExp1)/psav->YExp2 + 1;
1631ab47cfaaSmrg	dstBox->x1 = (dstBox->x1 * psav->XExp1)/psav->XExp2;
1632ab47cfaaSmrg	dstBox->y1 = (dstBox->y1 * psav->YExp1)/psav->YExp2;
1633ab47cfaaSmrg	dstBox->x1 += psav->displayXoffset;
1634ab47cfaaSmrg	dstBox->y1 += psav->displayYoffset;
1635ab47cfaaSmrg    }
1636ab47cfaaSmrg
1637ab47cfaaSmrg	if (psav->IsSecondary) {
1638ab47cfaaSmrg	    OUTREG(SEC_STREAM2_HSCALING,
1639ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1640ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1641ab47cfaaSmrg	    OUTREG(SEC_STREAM2_VSCALING,
1642ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1643ab47cfaaSmrg	} else if (psav->IsPrimary) {
1644ab47cfaaSmrg	    OUTREG(SEC_STREAM_HSCALING,
1645ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1646ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1647ab47cfaaSmrg	    OUTREG(SEC_STREAM_VSCALING,
1648ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1649ab47cfaaSmrg	} else {
1650ab47cfaaSmrg	    OUTREG(SEC_STREAM_HSCALING,
1651ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1652ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1653ab47cfaaSmrg	    OUTREG(SEC_STREAM_VSCALING,
1654ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1655ab47cfaaSmrg#if 0
1656ab47cfaaSmrg	    OUTREG(SEC_STREAM2_HSCALING,
1657ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1658ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1659ab47cfaaSmrg	    OUTREG(SEC_STREAM2_VSCALING,
1660ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1661ab47cfaaSmrg#endif
1662ab47cfaaSmrg	}
1663ab47cfaaSmrg
1664ab47cfaaSmrg    /*
1665ab47cfaaSmrg     * Set surface location and stride.  We use x1>>15 because all surfaces
1666ab47cfaaSmrg     * are 2 bytes/pixel.
1667ab47cfaaSmrg     */
1668ab47cfaaSmrg
1669ab47cfaaSmrg    if (psav->IsSecondary) {
1670ab47cfaaSmrg        OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15))
1671ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1672ab47cfaaSmrg        OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff );
1673ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1674ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1675ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1676ab47cfaaSmrg    } else if (psav->IsPrimary) {
1677ab47cfaaSmrg        OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15))
1678ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1679ab47cfaaSmrg        OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff );
1680ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1681ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1682ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1683ab47cfaaSmrg    } else {
1684ab47cfaaSmrg        OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15))
1685ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1686ab47cfaaSmrg        OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff );
1687ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1688ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1689ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1690ab47cfaaSmrg#if 0
1691ab47cfaaSmrg        OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15))
1692ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1693ab47cfaaSmrg        OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff );
1694ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1695ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1696ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1697ab47cfaaSmrg#endif
1698ab47cfaaSmrg    }
1699ab47cfaaSmrg
1700ab47cfaaSmrg#if 0
1701ab47cfaaSmrg    /* Set color key on primary. */
1702ab47cfaaSmrg
1703ab47cfaaSmrg    SavageSetColorKey( pScrn );
1704ab47cfaaSmrg#endif
1705ab47cfaaSmrg
1706ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1707ab47cfaaSmrg    /* Is CR92 shadowed for crtc2? -- AGD */
1708ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1709ab47cfaaSmrg    {
1710ab47cfaaSmrg	unsigned char cr92;
1711ab47cfaaSmrg
1712ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1713ab47cfaaSmrg	pitch = (pitch + 7) / 8 - 4;
1714ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1715ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1716ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1717ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1718ab47cfaaSmrg	VGAOUT8(vgaCRReg, pitch);
1719ab47cfaaSmrg    }
1720ab47cfaaSmrg}
1721ab47cfaaSmrg
1722ab47cfaaSmrgstatic void
1723ab47cfaaSmrgSavageDisplayVideo2000(
1724ab47cfaaSmrg    ScrnInfoPtr pScrn,
1725ab47cfaaSmrg    int id,
1726ab47cfaaSmrg    int offset,
1727ab47cfaaSmrg    short width, short height,
1728ab47cfaaSmrg    int pitch,
1729ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1730ab47cfaaSmrg    BoxPtr dstBox,
1731ab47cfaaSmrg    short src_w, short src_h,
1732ab47cfaaSmrg    short drw_w, short drw_h
1733ab47cfaaSmrg){
1734ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1735ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1736ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1737ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1738ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
1739ab47cfaaSmrg    CARD32 addr0, addr1, addr2;
1740ab47cfaaSmrg
1741ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1742ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1743ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
1744ab47cfaaSmrg
1745ab47cfaaSmrg
1746ab47cfaaSmrg    if( psav->videoFourCC != id )
1747ab47cfaaSmrg        SavageStreamsOff(pScrn);
1748ab47cfaaSmrg
1749ab47cfaaSmrg    if( !psav->videoFlags & VF_STREAMS_ON )
1750ab47cfaaSmrg    {
1751ab47cfaaSmrg        SavageSetBlend(pScrn,id);
1752ab47cfaaSmrg        SavageStreamsOn(pScrn);
1753ab47cfaaSmrg        SavageResetVideo(pScrn);
1754ab47cfaaSmrg    }
1755ab47cfaaSmrg
1756ab47cfaaSmrg    if (src_w > drw_w)
1757ab47cfaaSmrg        OUTREG(SEC_STREAM_SRC_START_2000, 0);
1758ab47cfaaSmrg    else
1759ab47cfaaSmrg        OUTREG(SEC_STREAM_SRC_START_2000, SRCSTART(x1, y1));
1760ab47cfaaSmrg
1761ab47cfaaSmrg    /*OUTREG(SEC_STREAM_SRC_SIZE_2000, SRCSIZE(src_w, src_h));*/
1762ab47cfaaSmrg    OUTREG(SEC_STREAM_SRC_SIZE_2000,
1763ab47cfaaSmrg	   SRCSIZE((dstBox->x2-dstBox->x1), (dstBox->y2-dstBox->y1)));
1764ab47cfaaSmrg    /*
1765ab47cfaaSmrg        buffersize = (src_w * src_h * 2) / 4096;
1766ab47cfaaSmrg	  OUTREG(SEC_STREAM_BUFFERSIZE_2000, (buffersize & 0xffffff) << 12);
1767ab47cfaaSmrg    */
1768ab47cfaaSmrg
1769ab47cfaaSmrg    /*SavageResetVideo(pScrn);*/
1770ab47cfaaSmrg
1771ab47cfaaSmrg    if( src_w > drw_w )
1772ab47cfaaSmrg	OUTREG(SEC_STREAM_HSCALE_NORMALIZE, HSCALING_NORMALIZE(drw_w,src_w));
1773ab47cfaaSmrg    else
1774ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALE_NORMALIZE, (2048 << 16));
1775ab47cfaaSmrg
1776ab47cfaaSmrg    /* Calculate horizontal and vertical scale factors. */
1777ab47cfaaSmrg    if ((src_w > drw_w) || (src_h > drw_h))
1778ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALING, (HSCALING_2000(src_w,drw_w)) | 0x01000000);
1779ab47cfaaSmrg    else
1780ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALING, HSCALING_2000(src_w,drw_w));
1781ab47cfaaSmrg
1782ab47cfaaSmrg    OUTREG(SEC_STREAM_VSCALING, VSCALING_2000(src_h,drw_h));
1783ab47cfaaSmrg
1784ab47cfaaSmrg    /*
1785ab47cfaaSmrg     * Set surface location and stride.  We use x1>>15 because all surfaces
1786ab47cfaaSmrg     * are 2 bytes/pixel.
1787ab47cfaaSmrg     */
1788ab47cfaaSmrg
1789ab47cfaaSmrg    addr0 = offset + (x1>>15); /* Y in YCbCr420 */
1790ab47cfaaSmrg    addr1 = addr0 + (width * height); /* Cb in in YCbCr420 */
1791ab47cfaaSmrg    addr2 = addr1 + ((width * height) / 4); /* Cr in in YCbCr420 */
1792ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR0, (addr0) & (0x3fffff & ~BASE_PAD));
1793ab47cfaaSmrg#if 0
1794ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR1, (addr1) & (0x3fffff & ~BASE_PAD));
1795ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR2, (addr2) & (0x3fffff & ~BASE_PAD));
1796ab47cfaaSmrg#endif
1797ab47cfaaSmrg
1798ab47cfaaSmrg    OUTREG(SEC_STREAM_WINDOW_START, XY_2000(dstBox->x1,dstBox->y1));
1799ab47cfaaSmrg    OUTREG(SEC_STREAM_WINDOW_SZ,
1800ab47cfaaSmrg	   WH_2000((dstBox->x2-dstBox->x1),(dstBox->y2-dstBox->y1)));
1801ab47cfaaSmrg
1802ab47cfaaSmrg    /*pitch = width * 2;*/
1803ab47cfaaSmrg    OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff);
1804ab47cfaaSmrg#if 0
1805ab47cfaaSmrg    /* Y stride + CbCr stride in YCbCr420 */
1806ab47cfaaSmrg    OUTREG(SEC_STREAM_STRIDE, (pitch & 0xfff) + ((pitch & 0xfff) << 15));
1807ab47cfaaSmrg#endif
1808ab47cfaaSmrg
1809ab47cfaaSmrg#if 0
1810ab47cfaaSmrg    /* Set color key on primary. */
1811ab47cfaaSmrg
1812ab47cfaaSmrg    SavageSetColorKey2000( pScrn );
1813ab47cfaaSmrg#endif
1814ab47cfaaSmrg
1815ab47cfaaSmrg#if 0
1816ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1817ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1818ab47cfaaSmrg    {
1819ab47cfaaSmrg	unsigned char cr92;
1820ab47cfaaSmrg
1821ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1822ab47cfaaSmrg	pitch = (pitch + 7) / 8 - 4;
1823ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1824ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1825ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1826ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1827ab47cfaaSmrg	VGAOUT8(vgaCRReg, pitch);
1828ab47cfaaSmrg    }
1829ab47cfaaSmrg#endif
1830ab47cfaaSmrg}
1831ab47cfaaSmrg
1832ab47cfaaSmrgstatic int
1833ab47cfaaSmrgSavagePutImage(
1834ab47cfaaSmrg    ScrnInfoPtr pScrn,
1835ab47cfaaSmrg    short src_x, short src_y,
1836ab47cfaaSmrg    short drw_x, short drw_y,
1837ab47cfaaSmrg    short src_w, short src_h,
1838ab47cfaaSmrg    short drw_w, short drw_h,
1839ab47cfaaSmrg    int id, unsigned char* buf,
1840ab47cfaaSmrg    short width, short height,
1841ab47cfaaSmrg    Bool sync,
1842ab47cfaaSmrg    RegionPtr clipBoxes, pointer data,
1843ab47cfaaSmrg    DrawablePtr pDraw
1844ab47cfaaSmrg){
1845ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1846ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1847ab47cfaaSmrg    ScreenPtr pScreen = pScrn->pScreen;
1848ab47cfaaSmrg    INT32 x1, x2, y1, y2;
1849ab47cfaaSmrg    unsigned char *dst_start;
1850ab47cfaaSmrg    int pitch, new_size, offset, offsetV=0, offsetU=0;
1851ab47cfaaSmrg    int srcPitch, srcPitch2=0, dstPitch;
1852ab47cfaaSmrg    int top, left, npixels, nlines;
1853ab47cfaaSmrg    BoxRec dstBox;
1854ab47cfaaSmrg    CARD32 tmp;
1855ab47cfaaSmrg/*    xf86ErrorFVerb(XVTRACE,"SavagePutImage\n"); */
1856ab47cfaaSmrg    if(drw_w > 16384) drw_w = 16384;
1857ab47cfaaSmrg
1858ab47cfaaSmrg    /* Clip */
1859ab47cfaaSmrg    x1 = src_x;
1860ab47cfaaSmrg    x2 = src_x + src_w;
1861ab47cfaaSmrg    y1 = src_y;
1862ab47cfaaSmrg    y2 = src_y + src_h;
1863ab47cfaaSmrg
1864ab47cfaaSmrg    dstBox.x1 = drw_x;
1865ab47cfaaSmrg    dstBox.x2 = drw_x + drw_w;
1866ab47cfaaSmrg    dstBox.y1 = drw_y;
1867ab47cfaaSmrg    dstBox.y2 = drw_y + drw_h;
1868ab47cfaaSmrg
1869ab47cfaaSmrg    SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
1870ab47cfaaSmrg		REGION_EXTENTS(pScreen, clipBoxes), width, height);
1871ab47cfaaSmrg
1872ab47cfaaSmrg    drw_w = dstBox.x2 - dstBox.x1;
1873ab47cfaaSmrg    drw_h = dstBox.y2 - dstBox.y1;
1874ab47cfaaSmrg    src_w = ( x2 - x1 ) >> 16;
1875ab47cfaaSmrg    src_h = ( y2 - y1 ) >> 16;
1876ab47cfaaSmrg
1877ab47cfaaSmrg    if((x1 >= x2) || (y1 >= y2))
1878ab47cfaaSmrg	return Success;
1879ab47cfaaSmrg
1880ab47cfaaSmrg    dstBox.x1 -= pScrn->frameX0;
1881ab47cfaaSmrg    dstBox.x2 -= pScrn->frameX0;
1882ab47cfaaSmrg    dstBox.y1 -= pScrn->frameY0;
1883ab47cfaaSmrg    dstBox.y2 -= pScrn->frameY0;
1884ab47cfaaSmrg
1885ab47cfaaSmrg    pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
1886ab47cfaaSmrg
1887ab47cfaaSmrg    dstPitch = ((width << 1) + 15) & ~15;
1888ab47cfaaSmrg    /*new_h = ((dstPitch * height) + pitch - 1) / pitch;*/
1889ab47cfaaSmrg    new_size = dstPitch * height;
1890ab47cfaaSmrg
1891ab47cfaaSmrg    switch(id) {
1892ab47cfaaSmrg    case FOURCC_Y211:		/* Y211 */
1893ab47cfaaSmrg        srcPitch = width;
1894ab47cfaaSmrg	break;
1895ab47cfaaSmrg    case FOURCC_YV12:		/* YV12 */
1896ab47cfaaSmrg	srcPitch = (width + 3) & ~3;
1897ab47cfaaSmrg	offsetV = srcPitch * height;
1898ab47cfaaSmrg	srcPitch2 = ((width >> 1) + 3) & ~3;
1899ab47cfaaSmrg	offsetU = (srcPitch2 * (height >> 1)) + offsetV;
1900ab47cfaaSmrg	break;
1901ab47cfaaSmrg    case FOURCC_I420:
1902ab47cfaaSmrg	srcPitch = (width + 3) & ~3;
1903ab47cfaaSmrg	offsetU = srcPitch * height;
1904ab47cfaaSmrg	srcPitch2 = ((width >> 1) + 3) & ~3;
1905ab47cfaaSmrg	offsetV = (srcPitch2 * (height >> 1)) + offsetU;
1906ab47cfaaSmrg	break;
1907ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
1908ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
1909ab47cfaaSmrg    case FOURCC_YUY2:		/* YUY2 */
1910ab47cfaaSmrg    default:
1911ab47cfaaSmrg	srcPitch = (width << 1);
1912ab47cfaaSmrg	break;
1913ab47cfaaSmrg    }
1914ab47cfaaSmrg
1915ab47cfaaSmrg/*    if(!(pPriv->area = SavageAllocateMemory(pScrn, pPriv->area, new_h)))
1916ab47cfaaSmrg	return BadAlloc;*/
1917ab47cfaaSmrg    pPriv->video_offset = SavageAllocateMemory(pScrn, &pPriv->video_memory,
1918ab47cfaaSmrg					      new_size);
1919ab47cfaaSmrg    if (pPriv->video_offset == 0)
1920ab47cfaaSmrg        return BadAlloc;
1921ab47cfaaSmrg
1922ab47cfaaSmrg    /* copy data */
1923ab47cfaaSmrg    top = y1 >> 16;
1924ab47cfaaSmrg    left = (x1 >> 16) & ~1;
1925ab47cfaaSmrg    npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
1926ab47cfaaSmrg    left <<= 1;
1927ab47cfaaSmrg
1928ab47cfaaSmrg    offset = (pPriv->video_offset) + (top * dstPitch);
1929ab47cfaaSmrg    /*offset = pPriv->area->box.y1 * psav->lDelta;*/
1930ab47cfaaSmrg    dst_start = (psav->FBBase + ((offset + left) & ~BASE_PAD));
1931ab47cfaaSmrg
1932ab47cfaaSmrg    switch(id) {
1933ab47cfaaSmrg    case FOURCC_YV12:		/* YV12 */
1934ab47cfaaSmrg    case FOURCC_I420:
1935ab47cfaaSmrg	top &= ~1;
1936ab47cfaaSmrg	tmp = ((top >> 1) * srcPitch2) + (left >> 2);
1937ab47cfaaSmrg	offsetU += tmp;
1938ab47cfaaSmrg	offsetV += tmp;
1939ab47cfaaSmrg	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
1940ab47cfaaSmrg        if (S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv) {
1941ab47cfaaSmrg            SavageCopyPlanarDataBCI(
1942ab47cfaaSmrg                pScrn,
1943ab47cfaaSmrg	    	buf + (top * srcPitch) + (left >> 1),
1944ab47cfaaSmrg	    	buf + offsetV,
1945ab47cfaaSmrg	    	buf + offsetU,
1946ab47cfaaSmrg	    	dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels);
1947ab47cfaaSmrg        } else {
1948ab47cfaaSmrg	    SavageCopyPlanarData(
1949ab47cfaaSmrg	    	buf + (top * srcPitch) + (left >> 1),
1950ab47cfaaSmrg	    	buf + offsetV,
1951ab47cfaaSmrg	    	buf + offsetU,
1952ab47cfaaSmrg	    	dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels);
1953ab47cfaaSmrg        }
1954ab47cfaaSmrg	break;
1955ab47cfaaSmrg    case FOURCC_Y211:		/* Y211 */
1956ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
1957ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
1958ab47cfaaSmrg    case FOURCC_YUY2:		/* YUY2 */
1959ab47cfaaSmrg    default:
1960ab47cfaaSmrg	buf += (top * srcPitch) + left;
1961ab47cfaaSmrg	nlines = ((y2 + 0xffff) >> 16) - top;
1962ab47cfaaSmrg	SavageCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
1963ab47cfaaSmrg	break;
1964ab47cfaaSmrg    }
1965ab47cfaaSmrg
1966ab47cfaaSmrg    /* We need to enable the video before we draw the chroma color.
1967ab47cfaaSmrg       Otherwise, we get blue flashes. */
1968ab47cfaaSmrg
1969ab47cfaaSmrg    SavageDisplayVideo(pScrn, id, offset, width, height, dstPitch,
1970ab47cfaaSmrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
1971ab47cfaaSmrg
1972ab47cfaaSmrg    /* update cliplist */
1973ab47cfaaSmrg    if(!REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes)) {
1974ab47cfaaSmrg	REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
1975ab47cfaaSmrg	/* draw these */
1976ab47cfaaSmrg	xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
1977ab47cfaaSmrg
1978ab47cfaaSmrg    }
1979ab47cfaaSmrg
1980ab47cfaaSmrg    pPriv->videoStatus = CLIENT_VIDEO_ON;
1981ab47cfaaSmrg
1982ab47cfaaSmrg    return Success;
1983ab47cfaaSmrg}
1984ab47cfaaSmrg
1985ab47cfaaSmrgstatic int
1986ab47cfaaSmrgSavageQueryImageAttributes(
1987ab47cfaaSmrg  ScrnInfoPtr pScrn,
1988ab47cfaaSmrg  int id,
1989ab47cfaaSmrg  unsigned short *w, unsigned short *h,
1990ab47cfaaSmrg  int *pitches, int *offsets
1991ab47cfaaSmrg){
1992ab47cfaaSmrg    int size, tmp;
1993ab47cfaaSmrg
1994ab47cfaaSmrg    if(*w > 1024) *w = 1024;
1995ab47cfaaSmrg    if(*h > 1024) *h = 1024;
1996ab47cfaaSmrg
1997ab47cfaaSmrg    *w = (*w + 1) & ~1;
1998ab47cfaaSmrg    if(offsets) offsets[0] = 0;
1999ab47cfaaSmrg
2000ab47cfaaSmrg    switch(id) {
2001ab47cfaaSmrg    case FOURCC_IA44:
2002ab47cfaaSmrg        if (pitches) pitches[0]=*w;
2003ab47cfaaSmrg        size=(*w)*(*h);
2004ab47cfaaSmrg        break;
2005ab47cfaaSmrg    case FOURCC_Y211:
2006ab47cfaaSmrg	size = *w << 2;
2007ab47cfaaSmrg	if(pitches) pitches[0] = size;
2008ab47cfaaSmrg	size *= *h;
2009ab47cfaaSmrg	break;
2010ab47cfaaSmrg    case FOURCC_YV12:
2011ab47cfaaSmrg    case FOURCC_I420:
2012ab47cfaaSmrg	*h = (*h + 1) & ~1;
2013ab47cfaaSmrg	size = (*w + 3) & ~3;
2014ab47cfaaSmrg	if(pitches) pitches[0] = size;
2015ab47cfaaSmrg	size *= *h;
2016ab47cfaaSmrg	if(offsets) offsets[1] = size;
2017ab47cfaaSmrg	tmp = ((*w >> 1) + 3) & ~3;
2018ab47cfaaSmrg	if(pitches) pitches[1] = pitches[2] = tmp;
2019ab47cfaaSmrg	tmp *= (*h >> 1);
2020ab47cfaaSmrg	size += tmp;
2021ab47cfaaSmrg	if(offsets) offsets[2] = size;
2022ab47cfaaSmrg	size += tmp;
2023ab47cfaaSmrg	break;
2024ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
2025ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
2026ab47cfaaSmrg    case FOURCC_YUY2:
2027ab47cfaaSmrg    default:
2028ab47cfaaSmrg	size = *w << 1;
2029ab47cfaaSmrg	if(pitches) pitches[0] = size;
2030ab47cfaaSmrg	size *= *h;
2031ab47cfaaSmrg	break;
2032ab47cfaaSmrg    }
2033ab47cfaaSmrg
2034ab47cfaaSmrg    return size;
2035ab47cfaaSmrg}
2036ab47cfaaSmrg
2037ab47cfaaSmrg/****************** Offscreen stuff ***************/
2038ab47cfaaSmrg
2039ab47cfaaSmrgtypedef struct {
2040ab47cfaaSmrg  void *surface_memory;
2041ab47cfaaSmrg  Bool isOn;
2042ab47cfaaSmrg} OffscreenPrivRec, * OffscreenPrivPtr;
2043ab47cfaaSmrg
2044ab47cfaaSmrgstatic int
2045ab47cfaaSmrgSavageAllocateSurface(
2046ab47cfaaSmrg    ScrnInfoPtr pScrn,
2047ab47cfaaSmrg    int id,
2048ab47cfaaSmrg    unsigned short w,
2049ab47cfaaSmrg    unsigned short h,
2050ab47cfaaSmrg    XF86SurfacePtr surface
2051ab47cfaaSmrg){
2052ab47cfaaSmrg    int offset, size;
2053ab47cfaaSmrg    int pitch, fbpitch, numlines;
2054ab47cfaaSmrg    void *surface_memory = NULL;
2055ab47cfaaSmrg    OffscreenPrivPtr pPriv;
2056ab47cfaaSmrg
2057ab47cfaaSmrg    if((w > 1024) || (h > 1024))
2058ab47cfaaSmrg	return BadAlloc;
2059ab47cfaaSmrg
2060ab47cfaaSmrg    w = (w + 1) & ~1;
2061ab47cfaaSmrg    pitch = ((w << 1) + 15) & ~15;
2062ab47cfaaSmrg    fbpitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
2063ab47cfaaSmrg    numlines = ((pitch * h) + fbpitch - 1) / fbpitch;
2064ab47cfaaSmrg    size = pitch * h;
2065ab47cfaaSmrg
2066ab47cfaaSmrg    offset = SavageAllocateMemory(pScrn, &surface_memory, size);
2067ab47cfaaSmrg    if (offset == 0)
2068ab47cfaaSmrg	return BadAlloc;
2069ab47cfaaSmrg
2070ab47cfaaSmrg    surface->width = w;
2071ab47cfaaSmrg    surface->height = h;
2072ab47cfaaSmrg
2073ab47cfaaSmrg    if(!(surface->pitches = xalloc(sizeof(int)))) {
2074ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2075ab47cfaaSmrg	return BadAlloc;
2076ab47cfaaSmrg    }
2077ab47cfaaSmrg    if(!(surface->offsets = xalloc(sizeof(int)))) {
2078ab47cfaaSmrg	xfree(surface->pitches);
2079ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2080ab47cfaaSmrg	return BadAlloc;
2081ab47cfaaSmrg    }
2082ab47cfaaSmrg    if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
2083ab47cfaaSmrg	xfree(surface->pitches);
2084ab47cfaaSmrg	xfree(surface->offsets);
2085ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2086ab47cfaaSmrg	return BadAlloc;
2087ab47cfaaSmrg    }
2088ab47cfaaSmrg
2089ab47cfaaSmrg    pPriv->surface_memory = surface_memory;
2090ab47cfaaSmrg    pPriv->isOn = FALSE;
2091ab47cfaaSmrg
2092ab47cfaaSmrg    surface->pScrn = pScrn;
2093ab47cfaaSmrg    surface->id = id;
2094ab47cfaaSmrg    surface->pitches[0] = pitch;
2095ab47cfaaSmrg    surface->offsets[0] = offset; /*area->box.y1 * fbpitch;*/
2096ab47cfaaSmrg    surface->devPrivate.ptr = (pointer)pPriv;
2097ab47cfaaSmrg
2098ab47cfaaSmrg    return Success;
2099ab47cfaaSmrg}
2100ab47cfaaSmrg
2101ab47cfaaSmrgstatic int
2102ab47cfaaSmrgSavageStopSurface(
2103ab47cfaaSmrg    XF86SurfacePtr surface
2104ab47cfaaSmrg){
2105ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2106ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageStopSurface\n");
2107ab47cfaaSmrg
2108ab47cfaaSmrg    if(pPriv->isOn) {
2109ab47cfaaSmrg	/*SavagePtr psav = SAVPTR(surface->pScrn);*/
2110ab47cfaaSmrg	/*SavageClipVWindow(surface->pScrn);*/
2111ab47cfaaSmrg	SavageStreamsOff( surface->pScrn );
2112ab47cfaaSmrg	pPriv->isOn = FALSE;
2113ab47cfaaSmrg    }
2114ab47cfaaSmrg
2115ab47cfaaSmrg    return Success;
2116ab47cfaaSmrg}
2117ab47cfaaSmrg
2118ab47cfaaSmrg
2119ab47cfaaSmrgstatic int
2120ab47cfaaSmrgSavageFreeSurface(
2121ab47cfaaSmrg    XF86SurfacePtr surface
2122ab47cfaaSmrg){
2123ab47cfaaSmrg    ScrnInfoPtr pScrn = surface->pScrn;
2124ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2125ab47cfaaSmrg
2126ab47cfaaSmrg    if(pPriv->isOn)
2127ab47cfaaSmrg	SavageStopSurface(surface);
2128ab47cfaaSmrg    SavageFreeMemory(pScrn, pPriv->surface_memory);
2129ab47cfaaSmrg    xfree(surface->pitches);
2130ab47cfaaSmrg    xfree(surface->offsets);
2131ab47cfaaSmrg    xfree(surface->devPrivate.ptr);
2132ab47cfaaSmrg
2133ab47cfaaSmrg    return Success;
2134ab47cfaaSmrg}
2135ab47cfaaSmrg
2136ab47cfaaSmrgstatic int
2137ab47cfaaSmrgSavageGetSurfaceAttribute(
2138ab47cfaaSmrg    ScrnInfoPtr pScrn,
2139ab47cfaaSmrg    Atom attribute,
2140ab47cfaaSmrg    INT32 *value
2141ab47cfaaSmrg){
2142ab47cfaaSmrg    return SavageGetPortAttribute(pScrn, attribute, value,
2143ab47cfaaSmrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
2144ab47cfaaSmrg}
2145ab47cfaaSmrg
2146ab47cfaaSmrgstatic int
2147ab47cfaaSmrgSavageSetSurfaceAttribute(
2148ab47cfaaSmrg    ScrnInfoPtr pScrn,
2149ab47cfaaSmrg    Atom attribute,
2150ab47cfaaSmrg    INT32 value
2151ab47cfaaSmrg){
2152ab47cfaaSmrg    return SavageSetPortAttribute(pScrn, attribute, value,
2153ab47cfaaSmrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
2154ab47cfaaSmrg}
2155ab47cfaaSmrg
2156ab47cfaaSmrg
2157ab47cfaaSmrgstatic int
2158ab47cfaaSmrgSavageDisplaySurface(
2159ab47cfaaSmrg    XF86SurfacePtr surface,
2160ab47cfaaSmrg    short src_x, short src_y,
2161ab47cfaaSmrg    short drw_x, short drw_y,
2162ab47cfaaSmrg    short src_w, short src_h,
2163ab47cfaaSmrg    short drw_w, short drw_h,
2164ab47cfaaSmrg    RegionPtr clipBoxes
2165ab47cfaaSmrg){
2166ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2167ab47cfaaSmrg    ScrnInfoPtr pScrn = surface->pScrn;
2168ab47cfaaSmrg    ScreenPtr pScreen = pScrn->pScreen;
2169ab47cfaaSmrg    SavagePortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn);
2170ab47cfaaSmrg    INT32 x1, y1, x2, y2;
2171ab47cfaaSmrg    BoxRec dstBox;
2172ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageDisplaySurface\n");
2173ab47cfaaSmrg
2174ab47cfaaSmrg    x1 = src_x;
2175ab47cfaaSmrg    x2 = src_x + src_w;
2176ab47cfaaSmrg    y1 = src_y;
2177ab47cfaaSmrg    y2 = src_y + src_h;
2178ab47cfaaSmrg
2179ab47cfaaSmrg    dstBox.x1 = drw_x;
2180ab47cfaaSmrg    dstBox.x2 = drw_x + drw_w;
2181ab47cfaaSmrg    dstBox.y1 = drw_y;
2182ab47cfaaSmrg    dstBox.y2 = drw_y + drw_h;
2183ab47cfaaSmrg
2184ab47cfaaSmrg    SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
2185ab47cfaaSmrg                	REGION_EXTENTS(pScreen, clipBoxes),
2186ab47cfaaSmrg			surface->width, surface->height);
2187ab47cfaaSmrg
2188ab47cfaaSmrg    if((x1 >= x2) || (y1 >= y2))
2189ab47cfaaSmrg	return Success;
2190ab47cfaaSmrg
2191ab47cfaaSmrg    dstBox.x1 -= pScrn->frameX0;
2192ab47cfaaSmrg    dstBox.x2 -= pScrn->frameX0;
2193ab47cfaaSmrg    dstBox.y1 -= pScrn->frameY0;
2194ab47cfaaSmrg    dstBox.y2 -= pScrn->frameY0;
2195ab47cfaaSmrg
2196ab47cfaaSmrg    SavageDisplayVideo(pScrn, surface->id, surface->offsets[0],
2197ab47cfaaSmrg	     surface->width, surface->height, surface->pitches[0],
2198ab47cfaaSmrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
2199ab47cfaaSmrg
2200ab47cfaaSmrg    xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
2201ab47cfaaSmrg
2202ab47cfaaSmrg    pPriv->isOn = TRUE;
2203ab47cfaaSmrg#if 0
2204ab47cfaaSmrg    if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
2205ab47cfaaSmrg	REGION_EMPTY(pScreen, &portPriv->clip);
2206ab47cfaaSmrg	UpdateCurrentTime();
2207ab47cfaaSmrg	portPriv->videoStatus = FREE_TIMER;
2208ab47cfaaSmrg	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
2209ab47cfaaSmrg    }
2210ab47cfaaSmrg#endif
2211ab47cfaaSmrg
2212ab47cfaaSmrg    return Success;
2213ab47cfaaSmrg}
2214ab47cfaaSmrg
2215ab47cfaaSmrg
2216ab47cfaaSmrgstatic void
2217ab47cfaaSmrgSavageInitOffscreenImages(ScreenPtr pScreen)
2218ab47cfaaSmrg{
2219ab47cfaaSmrg    XF86OffscreenImagePtr offscreenImages;
2220ab47cfaaSmrg    SavagePtr psav = SAVPTR(xf86Screens[pScreen->myNum]);
2221ab47cfaaSmrg
2222ab47cfaaSmrg    /* need to free this someplace */
2223ab47cfaaSmrg    if (!psav->offscreenImages) {
2224ab47cfaaSmrg	if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
2225ab47cfaaSmrg	    return;
2226ab47cfaaSmrg	psav->offscreenImages = offscreenImages;
2227ab47cfaaSmrg    } else {
2228ab47cfaaSmrg	offscreenImages = psav->offscreenImages;
2229ab47cfaaSmrg    }
2230ab47cfaaSmrg
2231ab47cfaaSmrg    offscreenImages[0].image = &Images[0];
2232ab47cfaaSmrg    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
2233ab47cfaaSmrg			       VIDEO_CLIP_TO_VIEWPORT;
2234ab47cfaaSmrg    offscreenImages[0].alloc_surface = SavageAllocateSurface;
2235ab47cfaaSmrg    offscreenImages[0].free_surface = SavageFreeSurface;
2236ab47cfaaSmrg    offscreenImages[0].display = SavageDisplaySurface;
2237ab47cfaaSmrg    offscreenImages[0].stop = SavageStopSurface;
2238ab47cfaaSmrg    offscreenImages[0].setAttribute = SavageSetSurfaceAttribute;
2239ab47cfaaSmrg    offscreenImages[0].getAttribute = SavageGetSurfaceAttribute;
2240ab47cfaaSmrg    offscreenImages[0].max_width = 1024;
2241ab47cfaaSmrg    offscreenImages[0].max_height = 1024;
2242ab47cfaaSmrg    offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
2243ab47cfaaSmrg    offscreenImages[0].attributes = Attributes;
2244ab47cfaaSmrg
2245ab47cfaaSmrg    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
2246ab47cfaaSmrg}
2247ab47cfaaSmrg
2248