savage_video.c revision 8697ee19
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
11808697ee19Smrg                                                + dstPitch * 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 */
11928697ee19Smrg    memcpy(dstCopy, srcY, srcPitch * h);
1193ab47cfaaSmrg
1194ab47cfaaSmrg    /* copy V planar */
1195ab47cfaaSmrg    dstCopy = dstCopy + srcPitch * h;
11968697ee19Smrg    memcpy(dstCopy, srcV, srcPitch2 * (h>>1));
1197ab47cfaaSmrg
1198ab47cfaaSmrg    /* copy U planar */
1199ab47cfaaSmrg    dstCopy = dstCopy + srcPitch2 * (h>>1);
12008697ee19Smrg    memcpy(dstCopy, srcU, srcPitch2 * (h>>1));
1201ab47cfaaSmrg
1202ab47cfaaSmrg    /*
1203ab47cfaaSmrg     * Transfer pixel data from one memory location to another location
1204ab47cfaaSmrg     * and reformat the data during the transfer
1205ab47cfaaSmrg     * a. program BCI51 to specify the source information
1206ab47cfaaSmrg     * b. program BCI52 to specify the destination information
1207ab47cfaaSmrg     * c. program BCI53 to specify the source dimensions
1208ab47cfaaSmrg     * d. program BCI54 to specify the destination dimensions
1209ab47cfaaSmrg     * e. (if the data is in YCbCr420 format)program BCI55,BCI56,BCI57 to
1210ab47cfaaSmrg     *    locations of the Y,Cb,and Cr data
1211ab47cfaaSmrg     * f. program BCI50(command=011) to specify the formatting options and
1212ab47cfaaSmrg     *    kick off the transfer
1213ab47cfaaSmrg     * this command can be used for color space conversion(YCbCr to RGB)
1214ab47cfaaSmrg     * or for oversampling, but not for both simultaneously. it can also be
1215ab47cfaaSmrg     * used to do mastered image transfer when the source is tiled
1216ab47cfaaSmrg     */
1217ab47cfaaSmrg
1218ab47cfaaSmrg    w = (w+0xf)&0xff0;
1219ab47cfaaSmrg    psav->WaitQueue(psav,11);
1220ab47cfaaSmrg    BCI_SEND(0x96070051);
1221ab47cfaaSmrg    BCI_SEND(offsetY);
1222ab47cfaaSmrg
1223ab47cfaaSmrg    BCI_SEND(dstOffset);
1224ab47cfaaSmrg
1225ab47cfaaSmrg    BCI_SEND(((h-1)<<16)|((w-1)>>3));
1226ab47cfaaSmrg
1227ab47cfaaSmrg    BCI_SEND(dstPitch >> 3);
1228ab47cfaaSmrg
1229ab47cfaaSmrg
1230ab47cfaaSmrg    BCI_SEND(offsetU);
1231ab47cfaaSmrg    BCI_SEND(offsetV);
1232ab47cfaaSmrg
1233ab47cfaaSmrg    BCI_SEND((srcPitch2 << 16)| srcPitch2);
1234ab47cfaaSmrg
1235ab47cfaaSmrg    BCI_SEND(0x96010050);
1236ab47cfaaSmrg    BCI_SEND(0x00200003 | srcPitch);
1237ab47cfaaSmrg    BCI_SEND(0xC0170000);
1238ab47cfaaSmrg}
1239ab47cfaaSmrg
1240ab47cfaaSmrgstatic void
1241ab47cfaaSmrgSavageCopyData(
1242ab47cfaaSmrg  unsigned char *src,
1243ab47cfaaSmrg  unsigned char *dst,
1244ab47cfaaSmrg  int srcPitch,
1245ab47cfaaSmrg  int dstPitch,
1246ab47cfaaSmrg  int h,
1247ab47cfaaSmrg  int w
1248ab47cfaaSmrg){
1249ab47cfaaSmrg    w <<= 1;
12508697ee19Smrg    if (w == srcPitch && w == dstPitch) {
12518697ee19Smrg        memcpy(dst, src, w * h);
12528697ee19Smrg    } else
1253ab47cfaaSmrg    while(h--) {
1254ab47cfaaSmrg	memcpy(dst, src, w);
1255ab47cfaaSmrg	src += srcPitch;
1256ab47cfaaSmrg	dst += dstPitch;
1257ab47cfaaSmrg    }
1258ab47cfaaSmrg}
1259ab47cfaaSmrg
1260ab47cfaaSmrgstatic void
1261ab47cfaaSmrgSavageCopyPlanarData(
1262ab47cfaaSmrg   unsigned char *src1, /* Y */
1263ab47cfaaSmrg   unsigned char *src2, /* V */
1264ab47cfaaSmrg   unsigned char *src3, /* U */
1265ab47cfaaSmrg   unsigned char *dst1,
1266ab47cfaaSmrg   int srcPitch,
1267ab47cfaaSmrg   int srcPitch2,
1268ab47cfaaSmrg   int dstPitch,
1269ab47cfaaSmrg   int h,
1270ab47cfaaSmrg   int w
1271ab47cfaaSmrg){
1272ab47cfaaSmrg   CARD32 *dst = (CARD32*)dst1;
1273ab47cfaaSmrg   int i, j;
1274ab47cfaaSmrg
1275ab47cfaaSmrg   dstPitch >>= 2;
1276ab47cfaaSmrg   w >>= 1;
1277ab47cfaaSmrg
1278ab47cfaaSmrg   for(j = 0; j < h; j++) {
1279ab47cfaaSmrg	for(i = 0; i < w; i++) {
1280ab47cfaaSmrg/* Shouldn't this be 'if LITTLEENDIAN'? */
1281ab47cfaaSmrg#if 1
1282ab47cfaaSmrg	    dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
1283ab47cfaaSmrg		     (src3[i] << 8) | (src2[i] << 24);
1284ab47cfaaSmrg#else
1285ab47cfaaSmrg	    dst[i] = (src1[i << 1] << 24) | (src1[(i << 1) + 1] << 8) |
1286ab47cfaaSmrg		     (src3[i] << 0) | (src2[i] << 16);
1287ab47cfaaSmrg#endif
1288ab47cfaaSmrg	}
1289ab47cfaaSmrg	dst += dstPitch;
1290ab47cfaaSmrg	src1 += srcPitch;
1291ab47cfaaSmrg	if(j & 1) {
1292ab47cfaaSmrg	    src2 += srcPitch2;
1293ab47cfaaSmrg	    src3 += srcPitch2;
1294ab47cfaaSmrg	}
1295ab47cfaaSmrg   }
1296ab47cfaaSmrg}
1297ab47cfaaSmrg
1298ab47cfaaSmrgstatic void
1299ab47cfaaSmrgSavageVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
1300ab47cfaaSmrg{
1301ab47cfaaSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1302ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1303ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1304ab47cfaaSmrg
1305ab47cfaaSmrg    if (pPriv->video_memory == area)
1306ab47cfaaSmrg        pPriv->video_memory = NULL;
1307ab47cfaaSmrg}
1308ab47cfaaSmrg
1309ab47cfaaSmrgstatic CARD32
1310ab47cfaaSmrgSavageAllocateMemory(
1311ab47cfaaSmrg    ScrnInfoPtr pScrn,
1312ab47cfaaSmrg    void **mem_struct,
1313ab47cfaaSmrg    int size
1314ab47cfaaSmrg){
1315ab47cfaaSmrg    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
1316ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1317ab47cfaaSmrg    int offset = 0;
1318ab47cfaaSmrg
1319ab47cfaaSmrg    if (psav->useEXA) {
1320ab47cfaaSmrg	ExaOffscreenArea *area = *mem_struct;
1321ab47cfaaSmrg
1322ab47cfaaSmrg	if (area != NULL) {
1323ab47cfaaSmrg	    if (area->size >= size)
1324ab47cfaaSmrg		return area->offset;
1325ab47cfaaSmrg
1326ab47cfaaSmrg	    exaOffscreenFree(pScrn->pScreen, area);
1327ab47cfaaSmrg	}
1328ab47cfaaSmrg
1329ab47cfaaSmrg	area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, SavageVideoSave,
1330ab47cfaaSmrg				 NULL);
1331ab47cfaaSmrg	*mem_struct = area;
1332ab47cfaaSmrg	if (area == NULL)
1333ab47cfaaSmrg	    return 0;
1334ab47cfaaSmrg	offset = area->offset;
1335ab47cfaaSmrg    }
1336ab47cfaaSmrg
1337ab47cfaaSmrg    if (!psav->useEXA) {
1338ab47cfaaSmrg	FBLinearPtr linear = *mem_struct;
1339ab47cfaaSmrg	int cpp = pScrn->bitsPerPixel / 8;
1340ab47cfaaSmrg
1341ab47cfaaSmrg	/* XAA allocates in units of pixels at the screen bpp, so adjust size
1342ab47cfaaSmrg	 * appropriately.
1343ab47cfaaSmrg	 */
1344ab47cfaaSmrg	size = (size + cpp - 1) / cpp;
1345ab47cfaaSmrg
1346ab47cfaaSmrg	if (linear) {
1347ab47cfaaSmrg	    if(linear->size >= size)
1348ab47cfaaSmrg		return linear->offset * cpp;
1349ab47cfaaSmrg
1350ab47cfaaSmrg	    if(xf86ResizeOffscreenLinear(linear, size))
1351ab47cfaaSmrg		return linear->offset * cpp;
1352ab47cfaaSmrg
1353ab47cfaaSmrg	    xf86FreeOffscreenLinear(linear);
1354ab47cfaaSmrg	}
1355ab47cfaaSmrg
1356ab47cfaaSmrg	linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
1357ab47cfaaSmrg						NULL, NULL, NULL);
1358ab47cfaaSmrg	*mem_struct = linear;
1359ab47cfaaSmrg
1360ab47cfaaSmrg	if (!linear) {
1361ab47cfaaSmrg	    int max_size;
1362ab47cfaaSmrg
1363ab47cfaaSmrg	    xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
1364ab47cfaaSmrg					    PRIORITY_EXTREME);
1365ab47cfaaSmrg
1366ab47cfaaSmrg	    if(max_size < size)
1367ab47cfaaSmrg		return 0;
1368ab47cfaaSmrg
1369ab47cfaaSmrg	    xf86PurgeUnlockedOffscreenAreas(pScreen);
1370ab47cfaaSmrg	    linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
1371ab47cfaaSmrg						     NULL, NULL, NULL);
1372ab47cfaaSmrg	    *mem_struct = linear;
1373ab47cfaaSmrg	    if (!linear)
1374ab47cfaaSmrg		return 0;
1375ab47cfaaSmrg	}
1376ab47cfaaSmrg	offset = linear->offset * cpp;
1377ab47cfaaSmrg    }
1378ab47cfaaSmrg
1379ab47cfaaSmrg    return offset;
1380ab47cfaaSmrg}
1381ab47cfaaSmrg
1382ab47cfaaSmrgstatic void
1383ab47cfaaSmrgSavageFreeMemory(
1384ab47cfaaSmrg   ScrnInfoPtr pScrn,
1385ab47cfaaSmrg   void *mem_struct
1386ab47cfaaSmrg){
1387ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1388ab47cfaaSmrg
1389ab47cfaaSmrg    if (psav->useEXA) {
1390ab47cfaaSmrg	ExaOffscreenArea *area = mem_struct;
1391ab47cfaaSmrg
1392ab47cfaaSmrg	if (area != NULL)
1393ab47cfaaSmrg	    exaOffscreenFree(pScrn->pScreen, area);
1394ab47cfaaSmrg    }
1395ab47cfaaSmrg    if (!psav->useEXA) {
1396ab47cfaaSmrg	FBLinearPtr linear = mem_struct;
1397ab47cfaaSmrg
1398ab47cfaaSmrg	if (linear != NULL)
1399ab47cfaaSmrg	    xf86FreeOffscreenLinear(linear);
1400ab47cfaaSmrg    }
1401ab47cfaaSmrg}
1402ab47cfaaSmrg
1403ab47cfaaSmrgstatic void
1404ab47cfaaSmrgSavageSetBlend(ScrnInfoPtr pScrn, int id)
1405ab47cfaaSmrg{
1406ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1407ab47cfaaSmrg
1408ab47cfaaSmrg    if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) )
1409ab47cfaaSmrg    {
1410ab47cfaaSmrg	psav->blendBase = GetBlendForFourCC( id );
1411ab47cfaaSmrg	xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase );
1412ab47cfaaSmrg	if (psav->IsSecondary) {
1413ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
1414ab47cfaaSmrg	} else if (psav->IsPrimary) {
1415ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
1416ab47cfaaSmrg	} else {
1417ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
1418ab47cfaaSmrg#if 0
1419ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
1420ab47cfaaSmrg#endif
1421ab47cfaaSmrg	}
1422ab47cfaaSmrg    } else if (psav->Chipset == S3_SAVAGE2000) {
1423ab47cfaaSmrg      psav->blendBase = GetBlendForFourCC2000( id );
1424ab47cfaaSmrg      xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase );
1425ab47cfaaSmrg      if (id != FOURCC_YV12)
1426ab47cfaaSmrg	OUTREG( BLEND_CONTROL,
1427ab47cfaaSmrg		((psav->blendBase << 24) | (8 << 2) /*| 0x20000000*/));
1428ab47cfaaSmrg      else
1429ab47cfaaSmrg	OUTREG( BLEND_CONTROL,
1430ab47cfaaSmrg		((psav->blendBase << 24) | (8 << 2) /*| 0x10000000*/));
1431ab47cfaaSmrg    }
1432ab47cfaaSmrg
1433ab47cfaaSmrg    psav->videoFourCC = id;
1434ab47cfaaSmrg}
1435ab47cfaaSmrg
1436ab47cfaaSmrgstatic void
1437ab47cfaaSmrgSavageDisplayVideoOld(
1438ab47cfaaSmrg    ScrnInfoPtr pScrn,
1439ab47cfaaSmrg    int id,
1440ab47cfaaSmrg    int offset,
1441ab47cfaaSmrg    short width, short height,
1442ab47cfaaSmrg    int pitch,
1443ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1444ab47cfaaSmrg    BoxPtr dstBox,
1445ab47cfaaSmrg    short src_w, short src_h,
1446ab47cfaaSmrg    short drw_w, short drw_h
1447ab47cfaaSmrg){
1448ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1449ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1450ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1451ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1452ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
1453ab47cfaaSmrg    CARD32 ssControl;
1454ab47cfaaSmrg    int scalratio;
1455ab47cfaaSmrg
1456ab47cfaaSmrg
1457ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1458ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1459ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
1460ab47cfaaSmrg#if 0
1461ab47cfaaSmrg    if ( psav->videoFourCC != id ) {
1462ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1463ab47cfaaSmrg	SavageResetVideo(pScrn);
1464ab47cfaaSmrg    }
1465ab47cfaaSmrg#endif
1466ab47cfaaSmrg    if( psav->videoFourCC != id )
1467ab47cfaaSmrg      SavageStreamsOff(pScrn);
1468ab47cfaaSmrg
14698697ee19Smrg    if( !(psav->videoFlags & VF_STREAMS_ON) )
1470ab47cfaaSmrg      {
1471ab47cfaaSmrg        SavageSetBlend(pScrn,id);
1472ab47cfaaSmrg	SavageStreamsOn(pScrn);
1473ab47cfaaSmrg	SavageResetVideo(pScrn);
14748697ee19Smrg	pPriv->lastKnownPitch = 0;
1475ab47cfaaSmrg      }
1476ab47cfaaSmrg
1477ab47cfaaSmrg    if (S3_MOBILE_TWISTER_SERIES(psav->Chipset)
1478ab47cfaaSmrg        && psav->FPExpansion) {
1479ab47cfaaSmrg        drw_w = (((float)(drw_w * psav->XExp1)/(float)psav->XExp2)+1);
1480ab47cfaaSmrg        drw_h = (float)(drw_h * psav->YExp1)/(float)psav->YExp2+1;
1481ab47cfaaSmrg        dstBox->x1 = (float)(dstBox->x1 * psav->XExp1)/(float)psav->XExp2;
1482ab47cfaaSmrg        dstBox->y1 = (float)(dstBox->y1 * psav->YExp1)/(float)psav->YExp2;
1483ab47cfaaSmrg
1484ab47cfaaSmrg        dstBox->x1 += psav->displayXoffset;
1485ab47cfaaSmrg        dstBox->y1 += psav->displayYoffset;
1486ab47cfaaSmrg    }
1487ab47cfaaSmrg
1488ab47cfaaSmrg    /*
1489ab47cfaaSmrg     * Process horizontal scaling
1490ab47cfaaSmrg     *  upscaling and downscaling smaller than 2:1 controled by MM8198
1491ab47cfaaSmrg     *  MM8190 controls downscaling mode larger than 2:1
14928697ee19Smrg     *  Together MM8190 and MM8198 can set arbitrary downscale up to 64:1
1493ab47cfaaSmrg     */
1494ab47cfaaSmrg    scalratio = 0;
1495ab47cfaaSmrg    ssControl = 0;
1496ab47cfaaSmrg
1497ab47cfaaSmrg    if (src_w >= (drw_w * 2)) {
1498ab47cfaaSmrg        if (src_w < (drw_w * 4)) {
1499ab47cfaaSmrg            ssControl |= HDSCALE_4;
15008697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*4));
15018697ee19Smrg        } else if (src_w < (drw_w * 8)) {
1502ab47cfaaSmrg            ssControl |= HDSCALE_8;
15038697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*8));
15048697ee19Smrg        } else if (src_w < (drw_w * 16)) {
1505ab47cfaaSmrg            ssControl |= HDSCALE_16;
15068697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*16));
15078697ee19Smrg        } else if (src_w < (drw_w * 32)) {
1508ab47cfaaSmrg            ssControl |= HDSCALE_32;
15098697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*32));
15108697ee19Smrg        } else if (src_w < (drw_w * 64)) {
15118697ee19Smrg            ssControl |= HDSCALE_64;
15128697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*64));
15138697ee19Smrg        } else {
15148697ee19Smrg            /* Request beyond maximum downscale! */
1515ab47cfaaSmrg            ssControl |= HDSCALE_64;
15168697ee19Smrg            scalratio = HSCALING(2,1);
15178697ee19Smrg        }
1518ab47cfaaSmrg    } else
1519ab47cfaaSmrg        scalratio = HSCALING(src_w,drw_w);
1520ab47cfaaSmrg
1521ab47cfaaSmrg    ssControl |= src_w;
1522ab47cfaaSmrg    /*ssControl |= (1 << 24);*/
1523ab47cfaaSmrg    ssControl |= (GetBlendForFourCC(psav->videoFourCC) << 24);
15248697ee19Smrg#if 0
1525ab47cfaaSmrg    /* Wait for VBLANK. */
1526ab47cfaaSmrg    VerticalRetraceWait();
15278697ee19Smrg#endif
1528ab47cfaaSmrg    OUTREG(SSTREAM_CONTROL_REG, ssControl);
1529ab47cfaaSmrg    if (scalratio)
1530ab47cfaaSmrg        OUTREG(SSTREAM_STRETCH_REG,scalratio);
1531ab47cfaaSmrg
1532ab47cfaaSmrg    /* Calculate vertical scale factor. */
1533ab47cfaaSmrg    OUTREG(SSTREAM_VINITIAL_REG, 0 );
1534ab47cfaaSmrg    /*OUTREG(SSTREAM_VSCALE_REG, (src_h << 15) / drw_h );*/
1535ab47cfaaSmrg    OUTREG(SSTREAM_VSCALE_REG, VSCALING(src_h,drw_h));
1536ab47cfaaSmrg
1537ab47cfaaSmrg    /* Set surface location and stride. */
1538ab47cfaaSmrg    OUTREG(SSTREAM_FBADDR0_REG, (offset + (x1>>15)) & (0x1ffffff & ~BASE_PAD) );
1539ab47cfaaSmrg    OUTREG(SSTREAM_FBADDR1_REG, 0);
1540ab47cfaaSmrg    OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff );
1541ab47cfaaSmrg
1542ab47cfaaSmrg    OUTREG(SSTREAM_WINDOW_START_REG, OS_XY(dstBox->x1, dstBox->y1) );
1543ab47cfaaSmrg    OUTREG(SSTREAM_WINDOW_SIZE_REG, OS_WH(dstBox->x2-dstBox->x1,
1544ab47cfaaSmrg                                          dstBox->y2-dstBox->y1));
1545ab47cfaaSmrg
1546ab47cfaaSmrg    /*
1547ab47cfaaSmrg     * MM81E8:Secondary Stream Source Line Count
1548ab47cfaaSmrg     *   bit_0~10: # of lines in the source image (before scaling)
1549ab47cfaaSmrg     *   bit_15 = 1: Enable vertical interpolation
1550ab47cfaaSmrg     *            0: Line duplicaion
1551ab47cfaaSmrg     */
1552ab47cfaaSmrg    /*
1553ab47cfaaSmrg     * Vertical Interpolation is very bandwidth intensive.  Some savages can't
1554ab47cfaaSmrg     * seem to handle it.  Default is line doubling.  --AGD
1555ab47cfaaSmrg     */
1556ab47cfaaSmrg    if (pPriv->interpolation) {
1557ab47cfaaSmrg        if (src_w * 16 <= 0x3300) {
1558ab47cfaaSmrg            OUTREG(SSTREAM_LINES_REG, 0x8000 | src_h );
1559ab47cfaaSmrg	    OUTREG(FIFO_CONTROL, (INREG(FIFO_CONTROL) + 1));
1560ab47cfaaSmrg        } else {
1561ab47cfaaSmrg            OUTREG(SSTREAM_LINES_REG, src_h );
1562ab47cfaaSmrg        }
1563ab47cfaaSmrg    } else {
1564ab47cfaaSmrg        OUTREG(SSTREAM_LINES_REG, src_h );
1565ab47cfaaSmrg    }
1566ab47cfaaSmrg
1567ab47cfaaSmrg#if 0
1568ab47cfaaSmrg    /* Set color key on primary. */
1569ab47cfaaSmrg
1570ab47cfaaSmrg    SavageSetColorKey( pScrn );
1571ab47cfaaSmrg#endif
1572ab47cfaaSmrg
1573ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1574ab47cfaaSmrg
1575ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1576ab47cfaaSmrg    {
1577ab47cfaaSmrg	unsigned char cr92;
1578ab47cfaaSmrg
1579ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1580ab47cfaaSmrg
1581ab47cfaaSmrg	pitch = (pitch + 7) / 8;
1582ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1583ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1584ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1585ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1586ab47cfaaSmrg	if (psav->bTiled && (( drw_h > src_h) || (drw_w > src_w)))
1587ab47cfaaSmrg	    VGAOUT8(vgaCRReg, pitch | 0xf);
1588ab47cfaaSmrg	else
1589ab47cfaaSmrg	    VGAOUT8(vgaCRReg, pitch);
1590ab47cfaaSmrg    }
1591ab47cfaaSmrg}
1592ab47cfaaSmrg
1593ab47cfaaSmrgstatic void
1594ab47cfaaSmrgSavageDisplayVideoNew(
1595ab47cfaaSmrg    ScrnInfoPtr pScrn,
1596ab47cfaaSmrg    int id,
1597ab47cfaaSmrg    int offset,
1598ab47cfaaSmrg    short width, short height,
1599ab47cfaaSmrg    int pitch,
1600ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1601ab47cfaaSmrg    BoxPtr dstBox,
1602ab47cfaaSmrg    short src_w, short src_h,
1603ab47cfaaSmrg    short drw_w, short drw_h
1604ab47cfaaSmrg){
1605ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1606ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1607ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1608ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1609ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
1610ab47cfaaSmrg
1611ab47cfaaSmrg
1612ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1613ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1614ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
1615ab47cfaaSmrg#if 0
1616ab47cfaaSmrg    if ( psav->videoFourCC != id ) {
1617ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1618ab47cfaaSmrg	SavageResetVideo(pScrn);
1619ab47cfaaSmrg    }
1620ab47cfaaSmrg#endif
1621ab47cfaaSmrg    if( psav->videoFourCC != id )
1622ab47cfaaSmrg      SavageStreamsOff(pScrn);
1623ab47cfaaSmrg
16248697ee19Smrg    if( !(psav->videoFlags & VF_STREAMS_ON) )
1625ab47cfaaSmrg      {
1626ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1627ab47cfaaSmrg	SavageStreamsOn(pScrn);
1628ab47cfaaSmrg	SavageResetVideo(pScrn);
16298697ee19Smrg	pPriv->lastKnownPitch = 0;
1630ab47cfaaSmrg      }
1631ab47cfaaSmrg
1632ab47cfaaSmrg    /* Calculate horizontal and vertical scale factors. */
1633ab47cfaaSmrg
1634ab47cfaaSmrg    if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) &&
1635ab47cfaaSmrg	    (psav->DisplayType == MT_LCD) &&
1636ab47cfaaSmrg	    !psav->CrtOnly &&
1637ab47cfaaSmrg	    !psav->TvOn)
1638ab47cfaaSmrg    {
1639ab47cfaaSmrg	drw_w = (drw_w * psav->XExp1)/psav->XExp2 + 1;
1640ab47cfaaSmrg	drw_h = (drw_h * psav->YExp1)/psav->YExp2 + 1;
1641ab47cfaaSmrg	dstBox->x1 = (dstBox->x1 * psav->XExp1)/psav->XExp2;
1642ab47cfaaSmrg	dstBox->y1 = (dstBox->y1 * psav->YExp1)/psav->YExp2;
1643ab47cfaaSmrg	dstBox->x1 += psav->displayXoffset;
1644ab47cfaaSmrg	dstBox->y1 += psav->displayYoffset;
1645ab47cfaaSmrg    }
1646ab47cfaaSmrg
1647ab47cfaaSmrg	if (psav->IsSecondary) {
1648ab47cfaaSmrg	    OUTREG(SEC_STREAM2_HSCALING,
1649ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1650ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1651ab47cfaaSmrg	    OUTREG(SEC_STREAM2_VSCALING,
1652ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1653ab47cfaaSmrg	} else if (psav->IsPrimary) {
1654ab47cfaaSmrg	    OUTREG(SEC_STREAM_HSCALING,
1655ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1656ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1657ab47cfaaSmrg	    OUTREG(SEC_STREAM_VSCALING,
1658ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1659ab47cfaaSmrg	} else {
1660ab47cfaaSmrg	    OUTREG(SEC_STREAM_HSCALING,
1661ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1662ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1663ab47cfaaSmrg	    OUTREG(SEC_STREAM_VSCALING,
1664ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1665ab47cfaaSmrg#if 0
1666ab47cfaaSmrg	    OUTREG(SEC_STREAM2_HSCALING,
1667ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1668ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1669ab47cfaaSmrg	    OUTREG(SEC_STREAM2_VSCALING,
1670ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1671ab47cfaaSmrg#endif
1672ab47cfaaSmrg	}
1673ab47cfaaSmrg
1674ab47cfaaSmrg    /*
1675ab47cfaaSmrg     * Set surface location and stride.  We use x1>>15 because all surfaces
1676ab47cfaaSmrg     * are 2 bytes/pixel.
1677ab47cfaaSmrg     */
1678ab47cfaaSmrg
1679ab47cfaaSmrg    if (psav->IsSecondary) {
1680ab47cfaaSmrg        OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15))
1681ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1682ab47cfaaSmrg        OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff );
1683ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1684ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1685ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1686ab47cfaaSmrg    } else if (psav->IsPrimary) {
1687ab47cfaaSmrg        OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15))
1688ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1689ab47cfaaSmrg        OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff );
1690ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1691ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1692ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1693ab47cfaaSmrg    } else {
1694ab47cfaaSmrg        OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15))
1695ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1696ab47cfaaSmrg        OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff );
1697ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1698ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1699ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1700ab47cfaaSmrg#if 0
1701ab47cfaaSmrg        OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15))
1702ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1703ab47cfaaSmrg        OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff );
1704ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1705ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1706ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1707ab47cfaaSmrg#endif
1708ab47cfaaSmrg    }
1709ab47cfaaSmrg
1710ab47cfaaSmrg#if 0
1711ab47cfaaSmrg    /* Set color key on primary. */
1712ab47cfaaSmrg
1713ab47cfaaSmrg    SavageSetColorKey( pScrn );
1714ab47cfaaSmrg#endif
1715ab47cfaaSmrg
1716ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1717ab47cfaaSmrg    /* Is CR92 shadowed for crtc2? -- AGD */
1718ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1719ab47cfaaSmrg    {
1720ab47cfaaSmrg	unsigned char cr92;
1721ab47cfaaSmrg
1722ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1723ab47cfaaSmrg	pitch = (pitch + 7) / 8 - 4;
1724ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1725ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1726ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1727ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1728ab47cfaaSmrg	VGAOUT8(vgaCRReg, pitch);
1729ab47cfaaSmrg    }
1730ab47cfaaSmrg}
1731ab47cfaaSmrg
1732ab47cfaaSmrgstatic void
1733ab47cfaaSmrgSavageDisplayVideo2000(
1734ab47cfaaSmrg    ScrnInfoPtr pScrn,
1735ab47cfaaSmrg    int id,
1736ab47cfaaSmrg    int offset,
1737ab47cfaaSmrg    short width, short height,
1738ab47cfaaSmrg    int pitch,
1739ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1740ab47cfaaSmrg    BoxPtr dstBox,
1741ab47cfaaSmrg    short src_w, short src_h,
1742ab47cfaaSmrg    short drw_w, short drw_h
1743ab47cfaaSmrg){
1744ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1745ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1746ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1747ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1748ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
1749ab47cfaaSmrg    CARD32 addr0, addr1, addr2;
1750ab47cfaaSmrg
1751ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1752ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1753ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
1754ab47cfaaSmrg
1755ab47cfaaSmrg
1756ab47cfaaSmrg    if( psav->videoFourCC != id )
1757ab47cfaaSmrg        SavageStreamsOff(pScrn);
1758ab47cfaaSmrg
17598697ee19Smrg    if( !(psav->videoFlags & VF_STREAMS_ON) )
1760ab47cfaaSmrg    {
1761ab47cfaaSmrg        SavageSetBlend(pScrn,id);
1762ab47cfaaSmrg        SavageStreamsOn(pScrn);
1763ab47cfaaSmrg        SavageResetVideo(pScrn);
17648697ee19Smrg        pPriv->lastKnownPitch = 0;
1765ab47cfaaSmrg    }
1766ab47cfaaSmrg
1767ab47cfaaSmrg    if (src_w > drw_w)
1768ab47cfaaSmrg        OUTREG(SEC_STREAM_SRC_START_2000, 0);
1769ab47cfaaSmrg    else
1770ab47cfaaSmrg        OUTREG(SEC_STREAM_SRC_START_2000, SRCSTART(x1, y1));
1771ab47cfaaSmrg
1772ab47cfaaSmrg    /*OUTREG(SEC_STREAM_SRC_SIZE_2000, SRCSIZE(src_w, src_h));*/
1773ab47cfaaSmrg    OUTREG(SEC_STREAM_SRC_SIZE_2000,
1774ab47cfaaSmrg	   SRCSIZE((dstBox->x2-dstBox->x1), (dstBox->y2-dstBox->y1)));
1775ab47cfaaSmrg    /*
1776ab47cfaaSmrg        buffersize = (src_w * src_h * 2) / 4096;
1777ab47cfaaSmrg	  OUTREG(SEC_STREAM_BUFFERSIZE_2000, (buffersize & 0xffffff) << 12);
1778ab47cfaaSmrg    */
1779ab47cfaaSmrg
1780ab47cfaaSmrg    /*SavageResetVideo(pScrn);*/
1781ab47cfaaSmrg
1782ab47cfaaSmrg    if( src_w > drw_w )
1783ab47cfaaSmrg	OUTREG(SEC_STREAM_HSCALE_NORMALIZE, HSCALING_NORMALIZE(drw_w,src_w));
1784ab47cfaaSmrg    else
1785ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALE_NORMALIZE, (2048 << 16));
1786ab47cfaaSmrg
1787ab47cfaaSmrg    /* Calculate horizontal and vertical scale factors. */
1788ab47cfaaSmrg    if ((src_w > drw_w) || (src_h > drw_h))
1789ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALING, (HSCALING_2000(src_w,drw_w)) | 0x01000000);
1790ab47cfaaSmrg    else
1791ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALING, HSCALING_2000(src_w,drw_w));
1792ab47cfaaSmrg
1793ab47cfaaSmrg    OUTREG(SEC_STREAM_VSCALING, VSCALING_2000(src_h,drw_h));
1794ab47cfaaSmrg
1795ab47cfaaSmrg    /*
1796ab47cfaaSmrg     * Set surface location and stride.  We use x1>>15 because all surfaces
1797ab47cfaaSmrg     * are 2 bytes/pixel.
1798ab47cfaaSmrg     */
1799ab47cfaaSmrg
1800ab47cfaaSmrg    addr0 = offset + (x1>>15); /* Y in YCbCr420 */
1801ab47cfaaSmrg    addr1 = addr0 + (width * height); /* Cb in in YCbCr420 */
1802ab47cfaaSmrg    addr2 = addr1 + ((width * height) / 4); /* Cr in in YCbCr420 */
1803ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR0, (addr0) & (0x3fffff & ~BASE_PAD));
1804ab47cfaaSmrg#if 0
1805ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR1, (addr1) & (0x3fffff & ~BASE_PAD));
1806ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR2, (addr2) & (0x3fffff & ~BASE_PAD));
1807ab47cfaaSmrg#endif
1808ab47cfaaSmrg
1809ab47cfaaSmrg    OUTREG(SEC_STREAM_WINDOW_START, XY_2000(dstBox->x1,dstBox->y1));
1810ab47cfaaSmrg    OUTREG(SEC_STREAM_WINDOW_SZ,
1811ab47cfaaSmrg	   WH_2000((dstBox->x2-dstBox->x1),(dstBox->y2-dstBox->y1)));
1812ab47cfaaSmrg
1813ab47cfaaSmrg    /*pitch = width * 2;*/
1814ab47cfaaSmrg    OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff);
1815ab47cfaaSmrg#if 0
1816ab47cfaaSmrg    /* Y stride + CbCr stride in YCbCr420 */
1817ab47cfaaSmrg    OUTREG(SEC_STREAM_STRIDE, (pitch & 0xfff) + ((pitch & 0xfff) << 15));
1818ab47cfaaSmrg#endif
1819ab47cfaaSmrg
1820ab47cfaaSmrg#if 0
1821ab47cfaaSmrg    /* Set color key on primary. */
1822ab47cfaaSmrg
1823ab47cfaaSmrg    SavageSetColorKey2000( pScrn );
1824ab47cfaaSmrg#endif
1825ab47cfaaSmrg
1826ab47cfaaSmrg#if 0
1827ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1828ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1829ab47cfaaSmrg    {
1830ab47cfaaSmrg	unsigned char cr92;
1831ab47cfaaSmrg
1832ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1833ab47cfaaSmrg	pitch = (pitch + 7) / 8 - 4;
1834ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1835ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1836ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1837ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1838ab47cfaaSmrg	VGAOUT8(vgaCRReg, pitch);
1839ab47cfaaSmrg    }
1840ab47cfaaSmrg#endif
1841ab47cfaaSmrg}
1842ab47cfaaSmrg
1843ab47cfaaSmrgstatic int
1844ab47cfaaSmrgSavagePutImage(
1845ab47cfaaSmrg    ScrnInfoPtr pScrn,
1846ab47cfaaSmrg    short src_x, short src_y,
1847ab47cfaaSmrg    short drw_x, short drw_y,
1848ab47cfaaSmrg    short src_w, short src_h,
1849ab47cfaaSmrg    short drw_w, short drw_h,
1850ab47cfaaSmrg    int id, unsigned char* buf,
1851ab47cfaaSmrg    short width, short height,
1852ab47cfaaSmrg    Bool sync,
1853ab47cfaaSmrg    RegionPtr clipBoxes, pointer data,
1854ab47cfaaSmrg    DrawablePtr pDraw
1855ab47cfaaSmrg){
1856ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1857ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1858ab47cfaaSmrg    ScreenPtr pScreen = pScrn->pScreen;
1859ab47cfaaSmrg    INT32 x1, x2, y1, y2;
1860ab47cfaaSmrg    unsigned char *dst_start;
1861ab47cfaaSmrg    int pitch, new_size, offset, offsetV=0, offsetU=0;
1862ab47cfaaSmrg    int srcPitch, srcPitch2=0, dstPitch;
1863ab47cfaaSmrg    int top, left, npixels, nlines;
1864ab47cfaaSmrg    BoxRec dstBox;
1865ab47cfaaSmrg    CARD32 tmp;
1866ab47cfaaSmrg/*    xf86ErrorFVerb(XVTRACE,"SavagePutImage\n"); */
1867ab47cfaaSmrg    if(drw_w > 16384) drw_w = 16384;
1868ab47cfaaSmrg
1869ab47cfaaSmrg    /* Clip */
1870ab47cfaaSmrg    x1 = src_x;
1871ab47cfaaSmrg    x2 = src_x + src_w;
1872ab47cfaaSmrg    y1 = src_y;
1873ab47cfaaSmrg    y2 = src_y + src_h;
1874ab47cfaaSmrg
1875ab47cfaaSmrg    dstBox.x1 = drw_x;
1876ab47cfaaSmrg    dstBox.x2 = drw_x + drw_w;
1877ab47cfaaSmrg    dstBox.y1 = drw_y;
1878ab47cfaaSmrg    dstBox.y2 = drw_y + drw_h;
1879ab47cfaaSmrg
1880ab47cfaaSmrg    SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
1881ab47cfaaSmrg		REGION_EXTENTS(pScreen, clipBoxes), width, height);
1882ab47cfaaSmrg
1883ab47cfaaSmrg    drw_w = dstBox.x2 - dstBox.x1;
1884ab47cfaaSmrg    drw_h = dstBox.y2 - dstBox.y1;
1885ab47cfaaSmrg    src_w = ( x2 - x1 ) >> 16;
1886ab47cfaaSmrg    src_h = ( y2 - y1 ) >> 16;
1887ab47cfaaSmrg
1888ab47cfaaSmrg    if((x1 >= x2) || (y1 >= y2))
1889ab47cfaaSmrg	return Success;
1890ab47cfaaSmrg
1891ab47cfaaSmrg    dstBox.x1 -= pScrn->frameX0;
1892ab47cfaaSmrg    dstBox.x2 -= pScrn->frameX0;
1893ab47cfaaSmrg    dstBox.y1 -= pScrn->frameY0;
1894ab47cfaaSmrg    dstBox.y2 -= pScrn->frameY0;
1895ab47cfaaSmrg
1896ab47cfaaSmrg    pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
1897ab47cfaaSmrg
1898ab47cfaaSmrg    dstPitch = ((width << 1) + 15) & ~15;
1899ab47cfaaSmrg    /*new_h = ((dstPitch * height) + pitch - 1) / pitch;*/
1900ab47cfaaSmrg    new_size = dstPitch * height;
1901ab47cfaaSmrg
1902ab47cfaaSmrg    switch(id) {
1903ab47cfaaSmrg    case FOURCC_Y211:		/* Y211 */
1904ab47cfaaSmrg        srcPitch = width;
1905ab47cfaaSmrg	break;
1906ab47cfaaSmrg    case FOURCC_YV12:		/* YV12 */
1907ab47cfaaSmrg	srcPitch = (width + 3) & ~3;
1908ab47cfaaSmrg	offsetV = srcPitch * height;
1909ab47cfaaSmrg	srcPitch2 = ((width >> 1) + 3) & ~3;
1910ab47cfaaSmrg	offsetU = (srcPitch2 * (height >> 1)) + offsetV;
1911ab47cfaaSmrg	break;
1912ab47cfaaSmrg    case FOURCC_I420:
1913ab47cfaaSmrg	srcPitch = (width + 3) & ~3;
1914ab47cfaaSmrg	offsetU = srcPitch * height;
1915ab47cfaaSmrg	srcPitch2 = ((width >> 1) + 3) & ~3;
1916ab47cfaaSmrg	offsetV = (srcPitch2 * (height >> 1)) + offsetU;
1917ab47cfaaSmrg	break;
1918ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
1919ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
1920ab47cfaaSmrg    case FOURCC_YUY2:		/* YUY2 */
1921ab47cfaaSmrg    default:
1922ab47cfaaSmrg	srcPitch = (width << 1);
1923ab47cfaaSmrg	break;
1924ab47cfaaSmrg    }
1925ab47cfaaSmrg
19268697ee19Smrg    if (srcPitch2 != 0 && S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv) {
19278697ee19Smrg        new_size = ((new_size + 0xF) & ~0xF) + srcPitch * height + srcPitch2 * height;
19288697ee19Smrg    }
19298697ee19Smrg
1930ab47cfaaSmrg/*    if(!(pPriv->area = SavageAllocateMemory(pScrn, pPriv->area, new_h)))
1931ab47cfaaSmrg	return BadAlloc;*/
1932ab47cfaaSmrg    pPriv->video_offset = SavageAllocateMemory(pScrn, &pPriv->video_memory,
1933ab47cfaaSmrg					      new_size);
1934ab47cfaaSmrg    if (pPriv->video_offset == 0)
1935ab47cfaaSmrg        return BadAlloc;
1936ab47cfaaSmrg
1937ab47cfaaSmrg    /* copy data */
1938ab47cfaaSmrg    top = y1 >> 16;
1939ab47cfaaSmrg    left = (x1 >> 16) & ~1;
1940ab47cfaaSmrg    npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
1941ab47cfaaSmrg    left <<= 1;
1942ab47cfaaSmrg
1943ab47cfaaSmrg    offset = (pPriv->video_offset) + (top * dstPitch);
1944ab47cfaaSmrg    /*offset = pPriv->area->box.y1 * psav->lDelta;*/
1945ab47cfaaSmrg    dst_start = (psav->FBBase + ((offset + left) & ~BASE_PAD));
1946ab47cfaaSmrg
1947ab47cfaaSmrg    switch(id) {
1948ab47cfaaSmrg    case FOURCC_YV12:		/* YV12 */
1949ab47cfaaSmrg    case FOURCC_I420:
1950ab47cfaaSmrg	top &= ~1;
1951ab47cfaaSmrg	tmp = ((top >> 1) * srcPitch2) + (left >> 2);
1952ab47cfaaSmrg	offsetU += tmp;
1953ab47cfaaSmrg	offsetV += tmp;
1954ab47cfaaSmrg	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
19558697ee19Smrg        if (S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv && (npixels & 0xF) == 0) {
1956ab47cfaaSmrg            SavageCopyPlanarDataBCI(
1957ab47cfaaSmrg                pScrn,
1958ab47cfaaSmrg	    	buf + (top * srcPitch) + (left >> 1),
1959ab47cfaaSmrg	    	buf + offsetV,
1960ab47cfaaSmrg	    	buf + offsetU,
1961ab47cfaaSmrg	    	dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels);
1962ab47cfaaSmrg        } else {
1963ab47cfaaSmrg	    SavageCopyPlanarData(
1964ab47cfaaSmrg	    	buf + (top * srcPitch) + (left >> 1),
1965ab47cfaaSmrg	    	buf + offsetV,
1966ab47cfaaSmrg	    	buf + offsetU,
1967ab47cfaaSmrg	    	dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels);
1968ab47cfaaSmrg        }
1969ab47cfaaSmrg	break;
1970ab47cfaaSmrg    case FOURCC_Y211:		/* Y211 */
1971ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
1972ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
1973ab47cfaaSmrg    case FOURCC_YUY2:		/* YUY2 */
1974ab47cfaaSmrg    default:
1975ab47cfaaSmrg	buf += (top * srcPitch) + left;
1976ab47cfaaSmrg	nlines = ((y2 + 0xffff) >> 16) - top;
1977ab47cfaaSmrg	SavageCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
1978ab47cfaaSmrg	break;
1979ab47cfaaSmrg    }
1980ab47cfaaSmrg
1981ab47cfaaSmrg    /* We need to enable the video before we draw the chroma color.
1982ab47cfaaSmrg       Otherwise, we get blue flashes. */
1983ab47cfaaSmrg
1984ab47cfaaSmrg    SavageDisplayVideo(pScrn, id, offset, width, height, dstPitch,
1985ab47cfaaSmrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
1986ab47cfaaSmrg
1987ab47cfaaSmrg    /* update cliplist */
1988ab47cfaaSmrg    if(!REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes)) {
1989ab47cfaaSmrg	REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
1990ab47cfaaSmrg	/* draw these */
1991ab47cfaaSmrg	xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
1992ab47cfaaSmrg
1993ab47cfaaSmrg    }
1994ab47cfaaSmrg
1995ab47cfaaSmrg    pPriv->videoStatus = CLIENT_VIDEO_ON;
1996ab47cfaaSmrg
1997ab47cfaaSmrg    return Success;
1998ab47cfaaSmrg}
1999ab47cfaaSmrg
2000ab47cfaaSmrgstatic int
2001ab47cfaaSmrgSavageQueryImageAttributes(
2002ab47cfaaSmrg  ScrnInfoPtr pScrn,
2003ab47cfaaSmrg  int id,
2004ab47cfaaSmrg  unsigned short *w, unsigned short *h,
2005ab47cfaaSmrg  int *pitches, int *offsets
2006ab47cfaaSmrg){
2007ab47cfaaSmrg    int size, tmp;
2008ab47cfaaSmrg
2009ab47cfaaSmrg    if(*w > 1024) *w = 1024;
2010ab47cfaaSmrg    if(*h > 1024) *h = 1024;
2011ab47cfaaSmrg
2012ab47cfaaSmrg    *w = (*w + 1) & ~1;
2013ab47cfaaSmrg    if(offsets) offsets[0] = 0;
2014ab47cfaaSmrg
2015ab47cfaaSmrg    switch(id) {
2016ab47cfaaSmrg    case FOURCC_IA44:
2017ab47cfaaSmrg        if (pitches) pitches[0]=*w;
2018ab47cfaaSmrg        size=(*w)*(*h);
2019ab47cfaaSmrg        break;
2020ab47cfaaSmrg    case FOURCC_Y211:
2021ab47cfaaSmrg	size = *w << 2;
2022ab47cfaaSmrg	if(pitches) pitches[0] = size;
2023ab47cfaaSmrg	size *= *h;
2024ab47cfaaSmrg	break;
2025ab47cfaaSmrg    case FOURCC_YV12:
2026ab47cfaaSmrg    case FOURCC_I420:
2027ab47cfaaSmrg	*h = (*h + 1) & ~1;
2028ab47cfaaSmrg	size = (*w + 3) & ~3;
2029ab47cfaaSmrg	if(pitches) pitches[0] = size;
2030ab47cfaaSmrg	size *= *h;
2031ab47cfaaSmrg	if(offsets) offsets[1] = size;
2032ab47cfaaSmrg	tmp = ((*w >> 1) + 3) & ~3;
2033ab47cfaaSmrg	if(pitches) pitches[1] = pitches[2] = tmp;
2034ab47cfaaSmrg	tmp *= (*h >> 1);
2035ab47cfaaSmrg	size += tmp;
2036ab47cfaaSmrg	if(offsets) offsets[2] = size;
2037ab47cfaaSmrg	size += tmp;
2038ab47cfaaSmrg	break;
2039ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
2040ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
2041ab47cfaaSmrg    case FOURCC_YUY2:
2042ab47cfaaSmrg    default:
2043ab47cfaaSmrg	size = *w << 1;
2044ab47cfaaSmrg	if(pitches) pitches[0] = size;
2045ab47cfaaSmrg	size *= *h;
2046ab47cfaaSmrg	break;
2047ab47cfaaSmrg    }
2048ab47cfaaSmrg
2049ab47cfaaSmrg    return size;
2050ab47cfaaSmrg}
2051ab47cfaaSmrg
2052ab47cfaaSmrg/****************** Offscreen stuff ***************/
2053ab47cfaaSmrg
2054ab47cfaaSmrgtypedef struct {
2055ab47cfaaSmrg  void *surface_memory;
2056ab47cfaaSmrg  Bool isOn;
2057ab47cfaaSmrg} OffscreenPrivRec, * OffscreenPrivPtr;
2058ab47cfaaSmrg
2059ab47cfaaSmrgstatic int
2060ab47cfaaSmrgSavageAllocateSurface(
2061ab47cfaaSmrg    ScrnInfoPtr pScrn,
2062ab47cfaaSmrg    int id,
2063ab47cfaaSmrg    unsigned short w,
2064ab47cfaaSmrg    unsigned short h,
2065ab47cfaaSmrg    XF86SurfacePtr surface
2066ab47cfaaSmrg){
2067ab47cfaaSmrg    int offset, size;
2068ab47cfaaSmrg    int pitch, fbpitch, numlines;
2069ab47cfaaSmrg    void *surface_memory = NULL;
2070ab47cfaaSmrg    OffscreenPrivPtr pPriv;
2071ab47cfaaSmrg
2072ab47cfaaSmrg    if((w > 1024) || (h > 1024))
2073ab47cfaaSmrg	return BadAlloc;
2074ab47cfaaSmrg
2075ab47cfaaSmrg    w = (w + 1) & ~1;
2076ab47cfaaSmrg    pitch = ((w << 1) + 15) & ~15;
2077ab47cfaaSmrg    fbpitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
2078ab47cfaaSmrg    numlines = ((pitch * h) + fbpitch - 1) / fbpitch;
2079ab47cfaaSmrg    size = pitch * h;
2080ab47cfaaSmrg
2081ab47cfaaSmrg    offset = SavageAllocateMemory(pScrn, &surface_memory, size);
2082ab47cfaaSmrg    if (offset == 0)
2083ab47cfaaSmrg	return BadAlloc;
2084ab47cfaaSmrg
2085ab47cfaaSmrg    surface->width = w;
2086ab47cfaaSmrg    surface->height = h;
2087ab47cfaaSmrg
2088ab47cfaaSmrg    if(!(surface->pitches = xalloc(sizeof(int)))) {
2089ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2090ab47cfaaSmrg	return BadAlloc;
2091ab47cfaaSmrg    }
2092ab47cfaaSmrg    if(!(surface->offsets = xalloc(sizeof(int)))) {
2093ab47cfaaSmrg	xfree(surface->pitches);
2094ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2095ab47cfaaSmrg	return BadAlloc;
2096ab47cfaaSmrg    }
2097ab47cfaaSmrg    if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
2098ab47cfaaSmrg	xfree(surface->pitches);
2099ab47cfaaSmrg	xfree(surface->offsets);
2100ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2101ab47cfaaSmrg	return BadAlloc;
2102ab47cfaaSmrg    }
2103ab47cfaaSmrg
2104ab47cfaaSmrg    pPriv->surface_memory = surface_memory;
2105ab47cfaaSmrg    pPriv->isOn = FALSE;
2106ab47cfaaSmrg
2107ab47cfaaSmrg    surface->pScrn = pScrn;
2108ab47cfaaSmrg    surface->id = id;
2109ab47cfaaSmrg    surface->pitches[0] = pitch;
2110ab47cfaaSmrg    surface->offsets[0] = offset; /*area->box.y1 * fbpitch;*/
2111ab47cfaaSmrg    surface->devPrivate.ptr = (pointer)pPriv;
2112ab47cfaaSmrg
2113ab47cfaaSmrg    return Success;
2114ab47cfaaSmrg}
2115ab47cfaaSmrg
2116ab47cfaaSmrgstatic int
2117ab47cfaaSmrgSavageStopSurface(
2118ab47cfaaSmrg    XF86SurfacePtr surface
2119ab47cfaaSmrg){
2120ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2121ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageStopSurface\n");
2122ab47cfaaSmrg
2123ab47cfaaSmrg    if(pPriv->isOn) {
2124ab47cfaaSmrg	/*SavagePtr psav = SAVPTR(surface->pScrn);*/
2125ab47cfaaSmrg	/*SavageClipVWindow(surface->pScrn);*/
2126ab47cfaaSmrg	SavageStreamsOff( surface->pScrn );
2127ab47cfaaSmrg	pPriv->isOn = FALSE;
2128ab47cfaaSmrg    }
2129ab47cfaaSmrg
2130ab47cfaaSmrg    return Success;
2131ab47cfaaSmrg}
2132ab47cfaaSmrg
2133ab47cfaaSmrg
2134ab47cfaaSmrgstatic int
2135ab47cfaaSmrgSavageFreeSurface(
2136ab47cfaaSmrg    XF86SurfacePtr surface
2137ab47cfaaSmrg){
2138ab47cfaaSmrg    ScrnInfoPtr pScrn = surface->pScrn;
2139ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2140ab47cfaaSmrg
2141ab47cfaaSmrg    if(pPriv->isOn)
2142ab47cfaaSmrg	SavageStopSurface(surface);
2143ab47cfaaSmrg    SavageFreeMemory(pScrn, pPriv->surface_memory);
2144ab47cfaaSmrg    xfree(surface->pitches);
2145ab47cfaaSmrg    xfree(surface->offsets);
2146ab47cfaaSmrg    xfree(surface->devPrivate.ptr);
2147ab47cfaaSmrg
2148ab47cfaaSmrg    return Success;
2149ab47cfaaSmrg}
2150ab47cfaaSmrg
2151ab47cfaaSmrgstatic int
2152ab47cfaaSmrgSavageGetSurfaceAttribute(
2153ab47cfaaSmrg    ScrnInfoPtr pScrn,
2154ab47cfaaSmrg    Atom attribute,
2155ab47cfaaSmrg    INT32 *value
2156ab47cfaaSmrg){
2157ab47cfaaSmrg    return SavageGetPortAttribute(pScrn, attribute, value,
2158ab47cfaaSmrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
2159ab47cfaaSmrg}
2160ab47cfaaSmrg
2161ab47cfaaSmrgstatic int
2162ab47cfaaSmrgSavageSetSurfaceAttribute(
2163ab47cfaaSmrg    ScrnInfoPtr pScrn,
2164ab47cfaaSmrg    Atom attribute,
2165ab47cfaaSmrg    INT32 value
2166ab47cfaaSmrg){
2167ab47cfaaSmrg    return SavageSetPortAttribute(pScrn, attribute, value,
2168ab47cfaaSmrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
2169ab47cfaaSmrg}
2170ab47cfaaSmrg
2171ab47cfaaSmrg
2172ab47cfaaSmrgstatic int
2173ab47cfaaSmrgSavageDisplaySurface(
2174ab47cfaaSmrg    XF86SurfacePtr surface,
2175ab47cfaaSmrg    short src_x, short src_y,
2176ab47cfaaSmrg    short drw_x, short drw_y,
2177ab47cfaaSmrg    short src_w, short src_h,
2178ab47cfaaSmrg    short drw_w, short drw_h,
2179ab47cfaaSmrg    RegionPtr clipBoxes
2180ab47cfaaSmrg){
2181ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2182ab47cfaaSmrg    ScrnInfoPtr pScrn = surface->pScrn;
2183ab47cfaaSmrg    ScreenPtr pScreen = pScrn->pScreen;
2184ab47cfaaSmrg    SavagePortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn);
2185ab47cfaaSmrg    INT32 x1, y1, x2, y2;
2186ab47cfaaSmrg    BoxRec dstBox;
2187ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageDisplaySurface\n");
2188ab47cfaaSmrg
2189ab47cfaaSmrg    x1 = src_x;
2190ab47cfaaSmrg    x2 = src_x + src_w;
2191ab47cfaaSmrg    y1 = src_y;
2192ab47cfaaSmrg    y2 = src_y + src_h;
2193ab47cfaaSmrg
2194ab47cfaaSmrg    dstBox.x1 = drw_x;
2195ab47cfaaSmrg    dstBox.x2 = drw_x + drw_w;
2196ab47cfaaSmrg    dstBox.y1 = drw_y;
2197ab47cfaaSmrg    dstBox.y2 = drw_y + drw_h;
2198ab47cfaaSmrg
2199ab47cfaaSmrg    SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
2200ab47cfaaSmrg                	REGION_EXTENTS(pScreen, clipBoxes),
2201ab47cfaaSmrg			surface->width, surface->height);
2202ab47cfaaSmrg
2203ab47cfaaSmrg    if((x1 >= x2) || (y1 >= y2))
2204ab47cfaaSmrg	return Success;
2205ab47cfaaSmrg
2206ab47cfaaSmrg    dstBox.x1 -= pScrn->frameX0;
2207ab47cfaaSmrg    dstBox.x2 -= pScrn->frameX0;
2208ab47cfaaSmrg    dstBox.y1 -= pScrn->frameY0;
2209ab47cfaaSmrg    dstBox.y2 -= pScrn->frameY0;
2210ab47cfaaSmrg
2211ab47cfaaSmrg    SavageDisplayVideo(pScrn, surface->id, surface->offsets[0],
2212ab47cfaaSmrg	     surface->width, surface->height, surface->pitches[0],
2213ab47cfaaSmrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
2214ab47cfaaSmrg
2215ab47cfaaSmrg    xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
2216ab47cfaaSmrg
2217ab47cfaaSmrg    pPriv->isOn = TRUE;
2218ab47cfaaSmrg#if 0
2219ab47cfaaSmrg    if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
2220ab47cfaaSmrg	REGION_EMPTY(pScreen, &portPriv->clip);
2221ab47cfaaSmrg	UpdateCurrentTime();
2222ab47cfaaSmrg	portPriv->videoStatus = FREE_TIMER;
2223ab47cfaaSmrg	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
2224ab47cfaaSmrg    }
2225ab47cfaaSmrg#endif
2226ab47cfaaSmrg
2227ab47cfaaSmrg    return Success;
2228ab47cfaaSmrg}
2229ab47cfaaSmrg
2230ab47cfaaSmrg
2231ab47cfaaSmrgstatic void
2232ab47cfaaSmrgSavageInitOffscreenImages(ScreenPtr pScreen)
2233ab47cfaaSmrg{
2234ab47cfaaSmrg    XF86OffscreenImagePtr offscreenImages;
2235ab47cfaaSmrg    SavagePtr psav = SAVPTR(xf86Screens[pScreen->myNum]);
2236ab47cfaaSmrg
2237ab47cfaaSmrg    /* need to free this someplace */
2238ab47cfaaSmrg    if (!psav->offscreenImages) {
2239ab47cfaaSmrg	if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
2240ab47cfaaSmrg	    return;
2241ab47cfaaSmrg	psav->offscreenImages = offscreenImages;
2242ab47cfaaSmrg    } else {
2243ab47cfaaSmrg	offscreenImages = psav->offscreenImages;
2244ab47cfaaSmrg    }
2245ab47cfaaSmrg
2246ab47cfaaSmrg    offscreenImages[0].image = &Images[0];
2247ab47cfaaSmrg    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
2248ab47cfaaSmrg			       VIDEO_CLIP_TO_VIEWPORT;
2249ab47cfaaSmrg    offscreenImages[0].alloc_surface = SavageAllocateSurface;
2250ab47cfaaSmrg    offscreenImages[0].free_surface = SavageFreeSurface;
2251ab47cfaaSmrg    offscreenImages[0].display = SavageDisplaySurface;
2252ab47cfaaSmrg    offscreenImages[0].stop = SavageStopSurface;
2253ab47cfaaSmrg    offscreenImages[0].setAttribute = SavageSetSurfaceAttribute;
2254ab47cfaaSmrg    offscreenImages[0].getAttribute = SavageGetSurfaceAttribute;
2255ab47cfaaSmrg    offscreenImages[0].max_width = 1024;
2256ab47cfaaSmrg    offscreenImages[0].max_height = 1024;
2257ab47cfaaSmrg    offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
2258ab47cfaaSmrg    offscreenImages[0].attributes = Attributes;
2259ab47cfaaSmrg
2260ab47cfaaSmrg    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
2261ab47cfaaSmrg}
2262ab47cfaaSmrg
2263