savage_video.c revision 6aec45a7
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
2441473d951Smrg   void         *video_memory;			/* opaque memory management information structure */
2451473d951Smrg   CARD32       video_offset;			/* offset in video memory of packed YUV buffer */
2461473d951Smrg
2471473d951Smrg   void         *video_planarmem;		/* opaque memory management information structure */
2481473d951Smrg   CARD32       video_planarbuf; 		/* offset in video memory of planar YV12 buffer */
2491473d951Smrg
2506aec45a7Smrg#ifdef XF86DRI
2511473d951Smrg   Bool         tried_agp;			/* TRUE if AGP allocation has been tried */
2521473d951Smrg   CARD32	agpBase;			/* Physical address of aperture base */
2531473d951Smrg   CARD32	agpBufferOffset;		/* Offset of buffer in AGP memory, or 0 if unavailable */
2541473d951Smrg   drmAddress   agpBufferMap;			/* Mapping of AGP buffer in process memory, or NULL */
2556aec45a7Smrg#endif
256ab47cfaaSmrg
257ab47cfaaSmrg} SavagePortPrivRec, *SavagePortPrivPtr;
258ab47cfaaSmrg
259ab47cfaaSmrg
260ab47cfaaSmrg#define GET_PORT_PRIVATE(pScrn) \
261ab47cfaaSmrg   (SavagePortPrivPtr)((SAVPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
262ab47cfaaSmrg
263ab47cfaaSmrgstatic
264ab47cfaaSmrgunsigned int GetBlendForFourCC( int id )
265ab47cfaaSmrg{
266ab47cfaaSmrg    switch( id ) {
267ab47cfaaSmrg	case FOURCC_YUY2:
268ab47cfaaSmrg        case FOURCC_YV12: /* shouldn't this be 4? */
269ab47cfaaSmrg        case FOURCC_I420: /* shouldn't this be 4? */
270ab47cfaaSmrg	    return 1;
271ab47cfaaSmrg	case FOURCC_Y211:
272ab47cfaaSmrg	    return 4;
273ab47cfaaSmrg	case FOURCC_RV15:
274ab47cfaaSmrg	    return 3;
275ab47cfaaSmrg	case FOURCC_RV16:
276ab47cfaaSmrg	    return 5;
277ab47cfaaSmrg        default:
278ab47cfaaSmrg	    return 0;
279ab47cfaaSmrg    }
280ab47cfaaSmrg}
281ab47cfaaSmrg
282ab47cfaaSmrgstatic
283ab47cfaaSmrgunsigned int GetBlendForFourCC2000( int id )
284ab47cfaaSmrg{
285ab47cfaaSmrg  switch( id ) {
286ab47cfaaSmrg  case FOURCC_YUY2:
287ab47cfaaSmrg    return 1;
288ab47cfaaSmrg  case FOURCC_I420:
289ab47cfaaSmrg    return 1; /* was 4 */
290ab47cfaaSmrg  case FOURCC_YV12:
291ab47cfaaSmrg    return 1; /* was 4 */
292ab47cfaaSmrg  case FOURCC_Y211:
293ab47cfaaSmrg    return 4;
294ab47cfaaSmrg  case FOURCC_RV15:
295ab47cfaaSmrg    return 3;
296ab47cfaaSmrg  case FOURCC_RV16:
297ab47cfaaSmrg    return 5;
298ab47cfaaSmrg  default:
299ab47cfaaSmrg    return 0;
300ab47cfaaSmrg  }
301ab47cfaaSmrg}
302ab47cfaaSmrg
303ab47cfaaSmrg
304ab47cfaaSmrgvoid savageOUTREG( SavagePtr psav, unsigned long offset, unsigned long value )
305ab47cfaaSmrg{
306ab47cfaaSmrg    ErrorF( "MMIO %08lx, was %08lx, want %08lx,",
307ab47cfaaSmrg	offset, (CARD32)MMIO_IN32( psav->MapBase, offset ), value );
308ab47cfaaSmrg    MMIO_OUT32( psav->MapBase, offset, value );
309ab47cfaaSmrg    ErrorF( " now %08lx\n", (CARD32)MMIO_IN32( psav->MapBase, offset ) );
310ab47cfaaSmrg}
311ab47cfaaSmrg
312ab47cfaaSmrg#if 0
313ab47cfaaSmrgstatic void
314ab47cfaaSmrgSavageClipVWindow(ScrnInfoPtr pScrn)
315ab47cfaaSmrg{
316ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
317ab47cfaaSmrg
318ab47cfaaSmrg    if( (psav->Chipset == S3_SAVAGE_MX)  ||
319ab47cfaaSmrg	(psav->Chipset == S3_SUPERSAVAGE) ) {
320ab47cfaaSmrg	if (psav->IsSecondary) {
321ab47cfaaSmrg	    OUTREG(SEC_STREAM2_WINDOW_SZ, 0);
322ab47cfaaSmrg	} else if (psav->IsPrimary) {
323ab47cfaaSmrg	    OUTREG(SEC_STREAM_WINDOW_SZ, 0);
324ab47cfaaSmrg	} else {
325ab47cfaaSmrg	    OUTREG(SEC_STREAM_WINDOW_SZ, 0);
326ab47cfaaSmrg#if 0
327ab47cfaaSmrg	    OUTREG(SEC_STREAM2_WINDOW_SZ, 0);
328ab47cfaaSmrg#endif
329ab47cfaaSmrg  	}
330ab47cfaaSmrg    } else if (psav->Chipset == S3_SAVAGE2000) {
331ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_SZ, 0);
332ab47cfaaSmrg    } else {
333ab47cfaaSmrg	OUTREG( SSTREAM_WINDOW_SIZE_REG, 1);
334ab47cfaaSmrg	OUTREG( SSTREAM_WINDOW_START_REG, 0x03ff03ff);
335ab47cfaaSmrg    }
336ab47cfaaSmrg}
337ab47cfaaSmrg#endif
338ab47cfaaSmrg
339ab47cfaaSmrgvoid SavageInitVideo(ScreenPtr pScreen)
340ab47cfaaSmrg{
341ab47cfaaSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
342ab47cfaaSmrg    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
343ab47cfaaSmrg    XF86VideoAdaptorPtr newAdaptor = NULL;
344ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
345ab47cfaaSmrg    int num_adaptors;
346ab47cfaaSmrg
347ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageInitVideo\n");
348ab47cfaaSmrg    if (S3_SAVAGE_MOBILE_SERIES(psav->Chipset))
349ab47cfaaSmrg    {
350ab47cfaaSmrg	newAdaptor = SavageSetupImageVideo(pScreen);
351ab47cfaaSmrg	SavageInitOffscreenImages(pScreen);
352ab47cfaaSmrg
353ab47cfaaSmrg	SavageInitStreams = SavageInitStreamsNew;
354ab47cfaaSmrg	SavageSetColor = SavageSetColorNew;
355ab47cfaaSmrg	SavageSetColorKey = SavageSetColorKeyNew;
356ab47cfaaSmrg	SavageDisplayVideo = SavageDisplayVideoNew;
357ab47cfaaSmrg    }
358ab47cfaaSmrg    else if (psav->Chipset == S3_SAVAGE2000)
359ab47cfaaSmrg    {
360ab47cfaaSmrg        newAdaptor = SavageSetupImageVideo(pScreen);
361ab47cfaaSmrg        SavageInitOffscreenImages(pScreen);
362ab47cfaaSmrg
363ab47cfaaSmrg	SavageInitStreams = SavageInitStreams2000;
364ab47cfaaSmrg        SavageSetColor = SavageSetColor2000;
365ab47cfaaSmrg        SavageSetColorKey = SavageSetColorKey2000;
366ab47cfaaSmrg        SavageDisplayVideo = SavageDisplayVideo2000;
367ab47cfaaSmrg    }
368ab47cfaaSmrg    else
369ab47cfaaSmrg    {
370ab47cfaaSmrg	newAdaptor = SavageSetupImageVideo(pScreen);
371ab47cfaaSmrg	SavageInitOffscreenImages(pScreen);
372ab47cfaaSmrg
373ab47cfaaSmrg	SavageInitStreams = SavageInitStreamsOld;
374ab47cfaaSmrg	SavageSetColor = SavageSetColorOld;
375ab47cfaaSmrg	SavageSetColorKey = SavageSetColorKeyOld;
376ab47cfaaSmrg	SavageDisplayVideo = SavageDisplayVideoOld;
377ab47cfaaSmrg    }
378ab47cfaaSmrg
379ab47cfaaSmrg    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
380ab47cfaaSmrg
381ab47cfaaSmrg    if(newAdaptor) {
382ab47cfaaSmrg        if(!num_adaptors) {
383ab47cfaaSmrg            num_adaptors = 1;
384ab47cfaaSmrg            adaptors = &newAdaptor;
385ab47cfaaSmrg        } else {
386ab47cfaaSmrg            newAdaptors =  /* need to free this someplace */
387ab47cfaaSmrg        	xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
388ab47cfaaSmrg            if(newAdaptors) {
389ab47cfaaSmrg        	memcpy(newAdaptors, adaptors, num_adaptors *
390ab47cfaaSmrg        				sizeof(XF86VideoAdaptorPtr));
391ab47cfaaSmrg        	newAdaptors[num_adaptors] = newAdaptor;
392ab47cfaaSmrg        	adaptors = newAdaptors;
393ab47cfaaSmrg        	num_adaptors++;
394ab47cfaaSmrg            }
395ab47cfaaSmrg        }
396ab47cfaaSmrg    }
397ab47cfaaSmrg
398ab47cfaaSmrg    if(num_adaptors)
399ab47cfaaSmrg        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
400ab47cfaaSmrg
401ab47cfaaSmrg    if(newAdaptors)
402ab47cfaaSmrg	xfree(newAdaptors);
403ab47cfaaSmrg
404ab47cfaaSmrg    if( newAdaptor )
405ab47cfaaSmrg    {
406ab47cfaaSmrg	psav->videoFourCC = 0;
407ab47cfaaSmrg    }
408ab47cfaaSmrg}
409ab47cfaaSmrg
410ab47cfaaSmrg
411ab47cfaaSmrgvoid SavageSetColorKeyOld(ScrnInfoPtr pScrn)
412ab47cfaaSmrg{
413ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
414ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
415ab47cfaaSmrg    int red, green, blue;
416ab47cfaaSmrg
417ab47cfaaSmrg    /* Here, we reset the colorkey and all the controls. */
418ab47cfaaSmrg
419ab47cfaaSmrg    red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
420ab47cfaaSmrg    green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
421ab47cfaaSmrg    blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
422ab47cfaaSmrg
423ab47cfaaSmrg    if( !pPriv->colorKey ) {
424ab47cfaaSmrg	OUTREG( COL_CHROMA_KEY_CONTROL_REG, 0 );
425ab47cfaaSmrg	OUTREG( CHROMA_KEY_UPPER_BOUND_REG, 0 );
426ab47cfaaSmrg	OUTREG( BLEND_CONTROL_REG, 0 );
427ab47cfaaSmrg    }
428ab47cfaaSmrg    else {
429ab47cfaaSmrg	switch (pScrn->depth) {
430ab47cfaaSmrg	case 8:
431ab47cfaaSmrg	    OUTREG( COL_CHROMA_KEY_CONTROL_REG,
432ab47cfaaSmrg		0x37000000 | (pPriv->colorKey & 0xFF) );
433ab47cfaaSmrg	    OUTREG( CHROMA_KEY_UPPER_BOUND_REG,
434ab47cfaaSmrg		0x00000000 | (pPriv->colorKey & 0xFF) );
435ab47cfaaSmrg	    break;
436ab47cfaaSmrg	case 15:
437ab47cfaaSmrg	    OUTREG( COL_CHROMA_KEY_CONTROL_REG,
438ab47cfaaSmrg		0x05000000 | (red<<19) | (green<<11) | (blue<<3) );
439ab47cfaaSmrg	    OUTREG( CHROMA_KEY_UPPER_BOUND_REG,
440ab47cfaaSmrg		0x00000000 | (red<<19) | (green<<11) | (blue<<3) );
441ab47cfaaSmrg	    break;
442ab47cfaaSmrg	case 16:
443ab47cfaaSmrg	    OUTREG( COL_CHROMA_KEY_CONTROL_REG,
444ab47cfaaSmrg		0x16000000 | (red<<19) | (green<<10) | (blue<<3) );
445ab47cfaaSmrg	    OUTREG( CHROMA_KEY_UPPER_BOUND_REG,
446ab47cfaaSmrg		0x00020002 | (red<<19) | (green<<10) | (blue<<3) );
447ab47cfaaSmrg	    break;
448ab47cfaaSmrg	case 24:
449ab47cfaaSmrg	    OUTREG( COL_CHROMA_KEY_CONTROL_REG,
450ab47cfaaSmrg		0x17000000 | (red<<16) | (green<<8) | (blue) );
451ab47cfaaSmrg	    OUTREG( CHROMA_KEY_UPPER_BOUND_REG,
452ab47cfaaSmrg		0x00000000 | (red<<16) | (green<<8) | (blue) );
453ab47cfaaSmrg	    break;
454ab47cfaaSmrg	}
455ab47cfaaSmrg
456ab47cfaaSmrg	/* We use destination colorkey */
457ab47cfaaSmrg	OUTREG( BLEND_CONTROL_REG, 0x05000000 );
458ab47cfaaSmrg    }
459ab47cfaaSmrg}
460ab47cfaaSmrg
461ab47cfaaSmrgvoid SavageSetColorKeyNew(ScrnInfoPtr pScrn)
462ab47cfaaSmrg{
463ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
464ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
465ab47cfaaSmrg    int red, green, blue;
466ab47cfaaSmrg
467ab47cfaaSmrg    /* Here, we reset the colorkey and all the controls. */
468ab47cfaaSmrg
469ab47cfaaSmrg    red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
470ab47cfaaSmrg    green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
471ab47cfaaSmrg    blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
472ab47cfaaSmrg
473ab47cfaaSmrg    if( !pPriv->colorKey ) {
474ab47cfaaSmrg	if (psav->IsSecondary) {
475ab47cfaaSmrg	    OUTREG( SEC_STREAM2_CKEY_LOW, 0 );
476ab47cfaaSmrg	    OUTREG( SEC_STREAM2_CKEY_UPPER, 0 );
477ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
478ab47cfaaSmrg	} else if (psav->IsPrimary) {
479ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_LOW, 0 );
480ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_UPPER, 0 );
481ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
482ab47cfaaSmrg	} else {
483ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_LOW, 0 );
484ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_UPPER, 0 );
485ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
486ab47cfaaSmrg#if 0
487ab47cfaaSmrg	    sleep(1);
488ab47cfaaSmrg	    OUTREG( SEC_STREAM2_CKEY_LOW, 0 );
489ab47cfaaSmrg	    OUTREG( SEC_STREAM2_CKEY_UPPER, 0 );
490ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
491ab47cfaaSmrg#endif
492ab47cfaaSmrg	}
493ab47cfaaSmrg    }
494ab47cfaaSmrg    else {
495ab47cfaaSmrg	switch (pScrn->depth) {
496ab47cfaaSmrg	case 8:
497ab47cfaaSmrg	    if (psav->IsSecondary) {
498ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_LOW,
499ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
500ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_UPPER,
501ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
502ab47cfaaSmrg	    } else if (psav->IsPrimary) {
503ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_LOW,
504ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
505ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_UPPER,
506ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
507ab47cfaaSmrg	    } else {
508ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_LOW,
509ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
510ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_UPPER,
511ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
512ab47cfaaSmrg#if 0
513ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_LOW,
514ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
515ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_UPPER,
516ab47cfaaSmrg		    0x47000000 | (pPriv->colorKey & 0xFF) );
517ab47cfaaSmrg#endif
518ab47cfaaSmrg	    }
519ab47cfaaSmrg	    break;
520ab47cfaaSmrg	case 15:
521ab47cfaaSmrg	    if (psav->IsSecondary) {
522ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_LOW,
523ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
524ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_UPPER,
525ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
526ab47cfaaSmrg	    } else if (psav->IsPrimary) {
527ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_LOW,
528ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
529ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_UPPER,
530ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
531ab47cfaaSmrg	    } else {
532ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_LOW,
533ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
534ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_UPPER,
535ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
536ab47cfaaSmrg#if 0
537ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_LOW,
538ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
539ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_UPPER,
540ab47cfaaSmrg		    0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
541ab47cfaaSmrg#endif
542ab47cfaaSmrg	    }
543ab47cfaaSmrg	    break;
544ab47cfaaSmrg	case 16:
545ab47cfaaSmrg	    if (psav->IsSecondary) {
546ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_LOW,
547ab47cfaaSmrg		    0x46000000 | (red<<19) | (green<<10) | (blue<<3) );
548ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_UPPER,
549ab47cfaaSmrg		    0x46020002 | (red<<19) | (green<<10) | (blue<<3) );
550ab47cfaaSmrg	    } else if (psav->IsPrimary) {
551ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_LOW,
552ab47cfaaSmrg		    0x46000000 | (red<<19) | (green<<10) | (blue<<3) );
553ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_UPPER,
554ab47cfaaSmrg		    0x46020002 | (red<<19) | (green<<10) | (blue<<3) );
555ab47cfaaSmrg	    } else {
556ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_LOW,
557ab47cfaaSmrg		    0x46000000 | (red<<19) | (green<<10) | (blue<<3) );
558ab47cfaaSmrg	    	OUTREG( SEC_STREAM_CKEY_UPPER,
559ab47cfaaSmrg		    0x46020002 | (red<<19) | (green<<10) | (blue<<3) );
560ab47cfaaSmrg#if 0
561ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_LOW,
562ab47cfaaSmrg		    0x46000000 | (red<<19) | (green<<10) | (blue<<3) );
563ab47cfaaSmrg	    	OUTREG( SEC_STREAM2_CKEY_UPPER,
564ab47cfaaSmrg		    0x46020002 | (red<<19) | (green<<10) | (blue<<3) );
565ab47cfaaSmrg#endif
566ab47cfaaSmrg	    }
567ab47cfaaSmrg	    break;
568ab47cfaaSmrg	case 24:
569ab47cfaaSmrg	    if (psav->IsSecondary) {
570ab47cfaaSmrg	        OUTREG( SEC_STREAM2_CKEY_LOW,
571ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
572ab47cfaaSmrg	        OUTREG( SEC_STREAM2_CKEY_UPPER,
573ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
574ab47cfaaSmrg	    } else if (psav->IsPrimary) {
575ab47cfaaSmrg	        OUTREG( SEC_STREAM_CKEY_LOW,
576ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
577ab47cfaaSmrg	        OUTREG( SEC_STREAM_CKEY_UPPER,
578ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
579ab47cfaaSmrg	    } else {
580ab47cfaaSmrg	        OUTREG( SEC_STREAM_CKEY_LOW,
581ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
582ab47cfaaSmrg	        OUTREG( SEC_STREAM_CKEY_UPPER,
583ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
584ab47cfaaSmrg#if 0
585ab47cfaaSmrg	        OUTREG( SEC_STREAM2_CKEY_LOW,
586ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
587ab47cfaaSmrg	        OUTREG( SEC_STREAM2_CKEY_UPPER,
588ab47cfaaSmrg		    0x47000000 | (red<<16) | (green<<8) | (blue) );
589ab47cfaaSmrg#endif
590ab47cfaaSmrg	    }
591ab47cfaaSmrg	    break;
592ab47cfaaSmrg	}
593ab47cfaaSmrg
594ab47cfaaSmrg	/* We assume destination colorkey */
595ab47cfaaSmrg	if (psav->IsSecondary) {
596ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
597ab47cfaaSmrg	} else if (psav->IsPrimary) {
598ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
599ab47cfaaSmrg	} else {
600ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
601ab47cfaaSmrg#if 0
602ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
603ab47cfaaSmrg#endif
604ab47cfaaSmrg	}
605ab47cfaaSmrg    }
606ab47cfaaSmrg}
607ab47cfaaSmrg
608ab47cfaaSmrgvoid SavageSetColorKey2000(ScrnInfoPtr pScrn)
609ab47cfaaSmrg{
610ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
611ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
612ab47cfaaSmrg    int red, green, blue;
613ab47cfaaSmrg
614ab47cfaaSmrg    /* Here, we reset the colorkey and all the controls. */
615ab47cfaaSmrg
616ab47cfaaSmrg    red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
617ab47cfaaSmrg    green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
618ab47cfaaSmrg    blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
619ab47cfaaSmrg
620ab47cfaaSmrg    if( !pPriv->colorKey ) {
621ab47cfaaSmrg        OUTREG( SEC_STREAM_CKEY_LOW, 0);
622ab47cfaaSmrg	OUTREG( SEC_STREAM_CKEY_UPPER, 0);
623ab47cfaaSmrg        OUTREG( BLEND_CONTROL, (8 << 2));
624ab47cfaaSmrg    }
625ab47cfaaSmrg    else {
626ab47cfaaSmrg	switch (pScrn->depth) {
627ab47cfaaSmrg	case 8:
628ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_LOW,
629ab47cfaaSmrg		0x47000000 | (pPriv->colorKey & 0xFF) );
630ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_UPPER,
631ab47cfaaSmrg		  (pPriv->colorKey & 0xFF) );
632ab47cfaaSmrg	    break;
633ab47cfaaSmrg	case 15:
634ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_LOW,
635ab47cfaaSmrg		0x45000000 | (red<<19) | (green<<11) | (blue<<3) );
636ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_UPPER,
637ab47cfaaSmrg		  (red<<19) | (green<<11) | (blue<<3) );
638ab47cfaaSmrg	    break;
639ab47cfaaSmrg	case 16:
640ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_LOW,
641ab47cfaaSmrg		0x46000000 | (red<<19) | (green<<10) | (blue<<3) );
642ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_UPPER,
643ab47cfaaSmrg		  (red<<19) | (green<<10) | (blue<<3) );
644ab47cfaaSmrg	    break;
645ab47cfaaSmrg	case 24:
646ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_LOW,
647ab47cfaaSmrg		0x47000000 | (red<<16) | (green<<8) | (blue) );
648ab47cfaaSmrg	    OUTREG( SEC_STREAM_CKEY_UPPER,
649ab47cfaaSmrg		  (red<<16) | (green<<8) | (blue) );
650ab47cfaaSmrg	    break;
651ab47cfaaSmrg	}
652ab47cfaaSmrg
653ab47cfaaSmrg	/* We assume destination colorkey */
654ab47cfaaSmrg	OUTREG( BLEND_CONTROL, INREG(BLEND_CONTROL) | (8 << 2));
655ab47cfaaSmrg    }
656ab47cfaaSmrg}
657ab47cfaaSmrg
658ab47cfaaSmrgvoid SavageSetColorOld( ScrnInfoPtr pScrn )
659ab47cfaaSmrg{
660ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
661ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
662ab47cfaaSmrg
663ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE, "bright %d, contrast %d, saturation %d, hue %d\n",
664ab47cfaaSmrg	pPriv->brightness, (int)pPriv->contrast, (int)pPriv->saturation, pPriv->hue );
665ab47cfaaSmrg
666ab47cfaaSmrg    if(
667ab47cfaaSmrg	(psav->videoFourCC == FOURCC_RV15) ||
668ab47cfaaSmrg	(psav->videoFourCC == FOURCC_RV16)
669ab47cfaaSmrg    )
670ab47cfaaSmrg    {
671ab47cfaaSmrg	OUTREG( COLOR_ADJUSTMENT_REG, 0 );
672ab47cfaaSmrg    }
673ab47cfaaSmrg    else
674ab47cfaaSmrg    {
675ab47cfaaSmrg        /* Change 0..255 into 0..15 */
676ab47cfaaSmrg	long sat = pPriv->saturation * 16 / 256;
677ab47cfaaSmrg	double hue = pPriv->hue * 0.017453292;
678ab47cfaaSmrg	unsigned long hs1 = ((long)(sat * cos(hue))) & 0x1f;
679ab47cfaaSmrg	unsigned long hs2 = ((long)(sat * sin(hue))) & 0x1f;
680ab47cfaaSmrg
681ab47cfaaSmrg	OUTREG( COLOR_ADJUSTMENT_REG,
682ab47cfaaSmrg	    0x80008000 |
683ab47cfaaSmrg	    (pPriv->brightness + 128) |
684ab47cfaaSmrg	    ((pPriv->contrast & 0xf8) << (12-7)) |
685ab47cfaaSmrg	    (hs1 << 16) |
686ab47cfaaSmrg	    (hs2 << 24)
687ab47cfaaSmrg	);
688ab47cfaaSmrg
689ab47cfaaSmrg    }
690ab47cfaaSmrg}
691ab47cfaaSmrg
692ab47cfaaSmrgvoid SavageSetColorNew( ScrnInfoPtr pScrn )
693ab47cfaaSmrg{
694ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
695ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
696ab47cfaaSmrg
697ab47cfaaSmrg    /* Brightness/contrast/saturation/hue computations. */
698ab47cfaaSmrg
699ab47cfaaSmrg    double k, dk1, dk2, dk3, dk4, dk5, dk6, dk7, dkb;
700ab47cfaaSmrg    int k1, k2, k3, k4, k5, k6, k7, kb;
701ab47cfaaSmrg    double s = pPriv->saturation / 128.0;
702ab47cfaaSmrg    double h = pPriv->hue * 0.017453292;
703ab47cfaaSmrg    unsigned long assembly1, assembly2, assembly3;
704ab47cfaaSmrg
705ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE, "bright %d, contrast %d, saturation %d, hue %d\n",
706ab47cfaaSmrg	pPriv->brightness, (int)pPriv->contrast, (int)pPriv->saturation, pPriv->hue );
707ab47cfaaSmrg
708ab47cfaaSmrg    if( psav->videoFourCC == FOURCC_Y211 )
709ab47cfaaSmrg	k = 1.0;	/* YUV */
710ab47cfaaSmrg    else
711ab47cfaaSmrg	k = 1.14;	/* YCrCb */
712ab47cfaaSmrg
713ab47cfaaSmrg    /*
714ab47cfaaSmrg     * The S3 documentation must be wrong for k4 and k5.  Their default
715ab47cfaaSmrg     * values, which they hardcode in their Windows driver, have the
716ab47cfaaSmrg     * opposite sign from the results in the register spec.
717ab47cfaaSmrg     */
718ab47cfaaSmrg
719ab47cfaaSmrg    dk1 = k * pPriv->contrast;
720ab47cfaaSmrg    dk2 = 64.0 * 1.371 * k * s * cos(h);
721ab47cfaaSmrg    dk3 = -64.0 * 1.371 * k * s * sin(h);
722ab47cfaaSmrg    dk4 = -128.0 * k * s * (0.698 * cos(h) - 0.336 * sin(h));
723ab47cfaaSmrg    dk5 = -128.0 * k * s * (0.698 * sin(h) + 0.336 * cos(h));
724ab47cfaaSmrg    dk6 = 64.0 * 1.732 * k * s * sin(h);	/* == k3 / 1.26331, right? */
725ab47cfaaSmrg    dk7 = 64.0 * 1.732 * k * s * cos(h);	/* == k2 / -1.26331, right? */
726ab47cfaaSmrg    dkb = 128.0 * pPriv->brightness + 64.0;
727ab47cfaaSmrg    if( psav->videoFourCC != FOURCC_Y211 )
728ab47cfaaSmrg	dkb -= dk1 * 14.0;
729ab47cfaaSmrg
730ab47cfaaSmrg    k1 = (int)(dk1+0.5) & 0x1ff;
731ab47cfaaSmrg    k2 = (int)(dk2+0.5) & 0x1ff;
732ab47cfaaSmrg    k3 = (int)(dk3+0.5) & 0x1ff;
733ab47cfaaSmrg    assembly1 = (k3<<18) | (k2<<9) | k1;
734ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE+1, "CC1 = %08lx  ", assembly1 );
735ab47cfaaSmrg
736ab47cfaaSmrg    k4 = (int)(dk4+0.5) & 0x1ff;
737ab47cfaaSmrg    k5 = (int)(dk5+0.5) & 0x1ff;
738ab47cfaaSmrg    k6 = (int)(dk6+0.5) & 0x1ff;
739ab47cfaaSmrg    assembly2 = (k6<<18) | (k5<<9) | k4;
740ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE+1, "CC2 = %08lx  ", assembly2 );
741ab47cfaaSmrg
742ab47cfaaSmrg    k7 = (int)(dk7+0.5) & 0x1ff;
743ab47cfaaSmrg    kb = (int)(dkb+0.5) & 0xffff;
744ab47cfaaSmrg    assembly3 = (kb<<9) | k7;
745ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE+1, "CC3 = %08lx\n", assembly3 );
746ab47cfaaSmrg
747ab47cfaaSmrg    if (psav->IsSecondary) {
748ab47cfaaSmrg	OUTREG( SEC_STREAM2_COLOR_CONVERT1, assembly1 );
749ab47cfaaSmrg	OUTREG( SEC_STREAM2_COLOR_CONVERT2, assembly2 );
750ab47cfaaSmrg	OUTREG( SEC_STREAM2_COLOR_CONVERT3, assembly3 );
751ab47cfaaSmrg    } else if (psav->IsPrimary) {
752ab47cfaaSmrg	OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly1 );
753ab47cfaaSmrg	OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly2 );
754ab47cfaaSmrg	OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly3 );
755ab47cfaaSmrg    } else {
756ab47cfaaSmrg	OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly1 );
757ab47cfaaSmrg	OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly2 );
758ab47cfaaSmrg	OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly3 );
759ab47cfaaSmrg#if 0
760ab47cfaaSmrg	sleep(1);
761ab47cfaaSmrg	OUTREG( SEC_STREAM2_COLOR_CONVERT1, assembly1 );
762ab47cfaaSmrg	OUTREG( SEC_STREAM2_COLOR_CONVERT2, assembly2 );
763ab47cfaaSmrg	OUTREG( SEC_STREAM2_COLOR_CONVERT3, assembly3 );
764ab47cfaaSmrg#endif
765ab47cfaaSmrg    }
766ab47cfaaSmrg}
767ab47cfaaSmrg
768ab47cfaaSmrgvoid SavageSetColor2000( ScrnInfoPtr pScrn )
769ab47cfaaSmrg{
770ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
771ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
772ab47cfaaSmrg
773ab47cfaaSmrg    /* Brightness/contrast/saturation/hue computations. */
774ab47cfaaSmrg
775ab47cfaaSmrg    double k, yb, dk1, dk2, dk3, dk4, dk5, dk6, dk7, dkb;
776ab47cfaaSmrg    int k1, k2, k3, k4, k5, k6, k7, kb;
777ab47cfaaSmrg    double s = pPriv->saturation / 10000.0;
778ab47cfaaSmrg    double h = pPriv->hue * 0.017453292;
779ab47cfaaSmrg    unsigned long assembly1, assembly2, assembly3, assembly4;
780ab47cfaaSmrg    unsigned long brightness = pPriv->brightness;
781ab47cfaaSmrg
782ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE, "bright %d, contrast %d, saturation %d, hue %d\n",
783ab47cfaaSmrg		 pPriv->brightness, (int)pPriv->contrast, (int)pPriv->saturation, pPriv->hue );
784ab47cfaaSmrg
785ab47cfaaSmrg    if( psav->videoFourCC == FOURCC_Y211 ) {
786ab47cfaaSmrg      k = 1.0;/* YUV */
787ab47cfaaSmrg      yb = 0.0;
788ab47cfaaSmrg    } else {
789ab47cfaaSmrg      k = 1.1;/* YCrCb */
790ab47cfaaSmrg      yb = 14.0;
791ab47cfaaSmrg    }
792ab47cfaaSmrg
793ab47cfaaSmrg    dk1 = 128 * k * (pPriv->contrast / 10000.0);
794ab47cfaaSmrg    if (dk1 < 0)
795ab47cfaaSmrg      dk1 -= 0.5;
796ab47cfaaSmrg    else
797ab47cfaaSmrg      dk1 += 0.5;
798ab47cfaaSmrg    dk2 = 64.0 * 1.371 * k * s * cos(h);
799ab47cfaaSmrg    if (dk2 < 0)
800ab47cfaaSmrg      dk2 -= 0.5;
801ab47cfaaSmrg    else
802ab47cfaaSmrg      dk2 += 0.5;
803ab47cfaaSmrg    dk3 = -64.0 * 1.371 * k * s * sin(h);
804ab47cfaaSmrg    if (dk3 < 0)
805ab47cfaaSmrg      dk3 -= 0.5;
806ab47cfaaSmrg    else
807ab47cfaaSmrg      dk3 += 0.5;
808ab47cfaaSmrg    dk4 = -128.0 * k * s * (0.698 * cos(h) + 0.336 * sin(h));
809ab47cfaaSmrg    if (dk4 < 0)
810ab47cfaaSmrg      dk4 -= 0.5;
811ab47cfaaSmrg    else
812ab47cfaaSmrg      dk4 += 0.5;
813ab47cfaaSmrg    dk5 = 128.0 * k * s * (0.698 * sin(h) - 0.336 * cos(h));
814ab47cfaaSmrg    if (dk5 < 0)
815ab47cfaaSmrg      dk5 -= 0.5;
816ab47cfaaSmrg    else
817ab47cfaaSmrg      dk5 += 0.5;
818ab47cfaaSmrg    dk6 = 64.0 * 1.732 * k * s * sin(h);
819ab47cfaaSmrg    if (dk6 < 0)
820ab47cfaaSmrg      dk6 -= 0.5;
821ab47cfaaSmrg    else
822ab47cfaaSmrg      dk6 += 0.5;
823ab47cfaaSmrg    dk7 = 64.0 * 1.732 * k * s * cos(h);
824ab47cfaaSmrg    if (dk7 < 0)
825ab47cfaaSmrg      dk7 -= 0.5;
826ab47cfaaSmrg    else
827ab47cfaaSmrg      dk7 += 0.5;
828ab47cfaaSmrg
829ab47cfaaSmrg    if (pPriv->brightness <= 0)
830ab47cfaaSmrg        brightness = pPriv->brightness * 200 / 750 - 200;
831ab47cfaaSmrg    else
832ab47cfaaSmrg        brightness = (pPriv->brightness - 750) * 200 / (10000 - 750);
833ab47cfaaSmrg    dkb = 128 * (brightness - (k * pPriv->contrast * yb / 10000.0) + 0.5);
834ab47cfaaSmrg    if (dkb < 0)
835ab47cfaaSmrg      dkb -= 0.5;
836ab47cfaaSmrg    else
837ab47cfaaSmrg      dkb += 0.5;
838ab47cfaaSmrg
839ab47cfaaSmrg    k1 = (int)(dk1 /*+0.5*/) & 0x1ff;
840ab47cfaaSmrg    k2 = (int)(dk2 /*+0.5*/) & 0x1ff;
841ab47cfaaSmrg    assembly1 = (k2<<16) | k1;
842ab47cfaaSmrg
843ab47cfaaSmrg    k3 = (int)(dk3 /*+0.5*/) & 0x1ff;
844ab47cfaaSmrg    k4 = (int)(dk4 /*+0.5*/) & 0x1ff;
845ab47cfaaSmrg    assembly2 = (k4<<16) | k3;
846ab47cfaaSmrg
847ab47cfaaSmrg    k5 = (int)(dk5 /*+0.5*/) & 0x1ff;
848ab47cfaaSmrg    k6 = (int)(dk6 /*+0.5*/) & 0x1ff;
849ab47cfaaSmrg    assembly3 = (k6<<16) | k5;
850ab47cfaaSmrg
851ab47cfaaSmrg    k7 = (int)(dk7 /*+0.5*/) & 0x1ff;
852ab47cfaaSmrg    kb = (int)(dkb /*+0.5*/) & 0xffff;
853ab47cfaaSmrg    assembly4 = (kb<<16) | k7;
854ab47cfaaSmrg
855ab47cfaaSmrg#if 0
856ab47cfaaSmrg    assembly1 = 0x640092;
857ab47cfaaSmrg    assembly2 = 0x19a0000;
858ab47cfaaSmrg    assembly3 = 0x001cf;
859ab47cfaaSmrg    assembly4 = 0xf8ca007e;
860ab47cfaaSmrg#endif
861ab47cfaaSmrg
862ab47cfaaSmrg    OUTREG( SEC_STREAM_COLOR_CONVERT0_2000, assembly1 );
863ab47cfaaSmrg    OUTREG( SEC_STREAM_COLOR_CONVERT1_2000, assembly2 );
864ab47cfaaSmrg    OUTREG( SEC_STREAM_COLOR_CONVERT2_2000, assembly3 );
865ab47cfaaSmrg    OUTREG( SEC_STREAM_COLOR_CONVERT3_2000, assembly4 );
866ab47cfaaSmrg
867ab47cfaaSmrg}
868ab47cfaaSmrg
869ab47cfaaSmrgvoid SavageResetVideo(ScrnInfoPtr pScrn)
870ab47cfaaSmrg{
871ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageResetVideo\n");
872ab47cfaaSmrg    SavageSetColor( pScrn );
873ab47cfaaSmrg    SavageSetColorKey( pScrn );
874ab47cfaaSmrg}
875ab47cfaaSmrg
876ab47cfaaSmrg
877ab47cfaaSmrgstatic XF86VideoAdaptorPtr
878ab47cfaaSmrgSavageSetupImageVideo(ScreenPtr pScreen)
879ab47cfaaSmrg{
880ab47cfaaSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
881ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
882ab47cfaaSmrg    XF86VideoAdaptorPtr adapt;
883ab47cfaaSmrg    SavagePortPrivPtr pPriv;
884ab47cfaaSmrg
885ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageSetupImageVideo\n");
886ab47cfaaSmrg
887ab47cfaaSmrg    if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
888ab47cfaaSmrg			    sizeof(SavagePortPrivRec) +
889ab47cfaaSmrg			    sizeof(DevUnion))))
890ab47cfaaSmrg	return NULL;
891ab47cfaaSmrg
892ab47cfaaSmrg    adapt->type		= XvWindowMask | XvInputMask | XvImageMask;
893ab47cfaaSmrg    adapt->flags	= VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
894ab47cfaaSmrg    adapt->name			= "Savage Streams Engine";
895ab47cfaaSmrg    adapt->nEncodings 		= 1;
896ab47cfaaSmrg    adapt->pEncodings 		= DummyEncoding;
897ab47cfaaSmrg    adapt->nFormats 		= NUM_FORMATS;
898ab47cfaaSmrg    adapt->pFormats 		= Formats;
899ab47cfaaSmrg    adapt->nPorts 		= 1;
900ab47cfaaSmrg    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
901ab47cfaaSmrg    pPriv = (SavagePortPrivPtr)(&adapt->pPortPrivates[1]);
902ab47cfaaSmrg    adapt->pPortPrivates[0].ptr	= (pointer)(pPriv);
903ab47cfaaSmrg    adapt->pAttributes		= Attributes;
904ab47cfaaSmrg    adapt->nImages		= NUM_IMAGES;
905ab47cfaaSmrg    adapt->nAttributes		= NUM_ATTRIBUTES;
906ab47cfaaSmrg    adapt->pImages		= Images;
907ab47cfaaSmrg    adapt->PutVideo		= NULL;
908ab47cfaaSmrg    adapt->PutStill		= NULL;
909ab47cfaaSmrg    adapt->GetVideo		= NULL;
910ab47cfaaSmrg    adapt->GetStill		= NULL;
911ab47cfaaSmrg    adapt->StopVideo		= SavageStopVideo;
912ab47cfaaSmrg    adapt->SetPortAttribute	= SavageSetPortAttribute;
913ab47cfaaSmrg    adapt->GetPortAttribute	= SavageGetPortAttribute;
914ab47cfaaSmrg    adapt->QueryBestSize	= SavageQueryBestSize;
915ab47cfaaSmrg    adapt->PutImage		= SavagePutImage;
916ab47cfaaSmrg    adapt->QueryImageAttributes	= SavageQueryImageAttributes;
917ab47cfaaSmrg
918ab47cfaaSmrg    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
919ab47cfaaSmrg    xvContrast   = MAKE_ATOM("XV_CONTRAST");
920ab47cfaaSmrg    xvColorKey   = MAKE_ATOM("XV_COLORKEY");
921ab47cfaaSmrg    xvHue        = MAKE_ATOM("XV_HUE");
922ab47cfaaSmrg    xvSaturation = MAKE_ATOM("XV_SATURATION");
923ab47cfaaSmrg    /* interpolation option only available on "old" streams */
924ab47cfaaSmrg    xvInterpolation = MAKE_ATOM("XV_VERTICAL_INTERPOLATION");
925ab47cfaaSmrg
926ab47cfaaSmrg    pPriv->colorKey =
927ab47cfaaSmrg      (1 << pScrn->offset.red) |
928ab47cfaaSmrg      (1 << pScrn->offset.green) |
929ab47cfaaSmrg      (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
930ab47cfaaSmrg    pPriv->videoStatus = 0;
931ab47cfaaSmrg    pPriv->brightness = 0;
932ab47cfaaSmrg    pPriv->contrast = 128;
933ab47cfaaSmrg    pPriv->saturation = 128;
934ab47cfaaSmrg#if 0
935ab47cfaaSmrg    /*
936ab47cfaaSmrg     * The S3 driver has these values for some of the chips.  I have yet
937ab47cfaaSmrg     * to find any Savage where these make sense.
938ab47cfaaSmrg     */
939ab47cfaaSmrg    pPriv->brightness = 64;
940ab47cfaaSmrg    pPriv->contrast = 16;
941ab47cfaaSmrg    pPriv->saturation = 128;
942ab47cfaaSmrg#endif
943ab47cfaaSmrg    pPriv->hue = 0;
944ab47cfaaSmrg    pPriv->lastKnownPitch = 0;
945ab47cfaaSmrg
946ab47cfaaSmrg    pPriv->interpolation = FALSE;
947ab47cfaaSmrg
948ab47cfaaSmrg    /* gotta uninit this someplace */
949ab47cfaaSmrg    REGION_NULL(pScreen, &pPriv->clip);
950ab47cfaaSmrg
951ab47cfaaSmrg    psav->adaptor = adapt;
952ab47cfaaSmrg
953ab47cfaaSmrg    #if 0
954ab47cfaaSmrg    psav->BlockHandler = pScreen->BlockHandler;
955ab47cfaaSmrg    pScreen->BlockHandler = SavageBlockHandler;
956ab47cfaaSmrg    #endif
957ab47cfaaSmrg
958ab47cfaaSmrg    return adapt;
959ab47cfaaSmrg}
960ab47cfaaSmrg
961ab47cfaaSmrg
962ab47cfaaSmrg/* SavageClipVideo -
963ab47cfaaSmrg
964ab47cfaaSmrg   Takes the dst box in standard X BoxRec form (top and left
965ab47cfaaSmrg   edges inclusive, bottom and right exclusive).  The new dst
966ab47cfaaSmrg   box is returned.  The source boundaries are given (x1, y1
967ab47cfaaSmrg   inclusive, x2, y2 exclusive) and returned are the new source
968ab47cfaaSmrg   boundaries in 16.16 fixed point.
969ab47cfaaSmrg*/
970ab47cfaaSmrg
971ab47cfaaSmrgstatic void
972ab47cfaaSmrgSavageClipVideo(
973ab47cfaaSmrg  BoxPtr dst,
974ab47cfaaSmrg  INT32 *x1,
975ab47cfaaSmrg  INT32 *x2,
976ab47cfaaSmrg  INT32 *y1,
977ab47cfaaSmrg  INT32 *y2,
978ab47cfaaSmrg  BoxPtr extents,            /* extents of the clip region */
979ab47cfaaSmrg  INT32 width,
980ab47cfaaSmrg  INT32 height
981ab47cfaaSmrg){
982ab47cfaaSmrg    INT32 vscale, hscale, delta;
983ab47cfaaSmrg    int diff;
984ab47cfaaSmrg
985ab47cfaaSmrg    hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
986ab47cfaaSmrg    vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
987ab47cfaaSmrg
988ab47cfaaSmrg    *x1 <<= 16; *x2 <<= 16;
989ab47cfaaSmrg    *y1 <<= 16; *y2 <<= 16;
990ab47cfaaSmrg
991ab47cfaaSmrg    diff = extents->x1 - dst->x1;
992ab47cfaaSmrg    if(diff > 0) {
993ab47cfaaSmrg	dst->x1 = extents->x1;
994ab47cfaaSmrg	*x1 += diff * hscale;
995ab47cfaaSmrg    }
996ab47cfaaSmrg    diff = dst->x2 - extents->x2;
997ab47cfaaSmrg    if(diff > 0) {
998ab47cfaaSmrg	dst->x2 = extents->x2;
999ab47cfaaSmrg	*x2 -= diff * hscale;
1000ab47cfaaSmrg    }
1001ab47cfaaSmrg    diff = extents->y1 - dst->y1;
1002ab47cfaaSmrg    if(diff > 0) {
1003ab47cfaaSmrg	dst->y1 = extents->y1;
1004ab47cfaaSmrg	*y1 += diff * vscale;
1005ab47cfaaSmrg    }
1006ab47cfaaSmrg    diff = dst->y2 - extents->y2;
1007ab47cfaaSmrg    if(diff > 0) {
1008ab47cfaaSmrg	dst->y2 = extents->y2;
1009ab47cfaaSmrg	*y2 -= diff * vscale;
1010ab47cfaaSmrg    }
1011ab47cfaaSmrg
1012ab47cfaaSmrg    if(*x1 < 0) {
1013ab47cfaaSmrg	diff =  (- *x1 + hscale - 1)/ hscale;
1014ab47cfaaSmrg	dst->x1 += diff;
1015ab47cfaaSmrg	*x1 += diff * hscale;
1016ab47cfaaSmrg    }
1017ab47cfaaSmrg    delta = *x2 - (width << 16);
1018ab47cfaaSmrg    if(delta > 0) {
1019ab47cfaaSmrg	diff = (delta + hscale - 1)/ hscale;
1020ab47cfaaSmrg	dst->x2 -= diff;
1021ab47cfaaSmrg	*x2 -= diff * hscale;
1022ab47cfaaSmrg    }
1023ab47cfaaSmrg    if(*y1 < 0) {
1024ab47cfaaSmrg	diff =  (- *y1 + vscale - 1)/ vscale;
1025ab47cfaaSmrg	dst->y1 += diff;
1026ab47cfaaSmrg	*y1 += diff * vscale;
1027ab47cfaaSmrg    }
1028ab47cfaaSmrg    delta = *y2 - (height << 16);
1029ab47cfaaSmrg    if(delta > 0) {
1030ab47cfaaSmrg	diff = (delta + vscale - 1)/ vscale;
1031ab47cfaaSmrg	dst->y2 -= diff;
1032ab47cfaaSmrg	*y2 -= diff * vscale;
1033ab47cfaaSmrg    }
1034ab47cfaaSmrg}
1035ab47cfaaSmrg
1036ab47cfaaSmrgstatic void
1037ab47cfaaSmrgSavageStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
1038ab47cfaaSmrg{
1039ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
10401473d951Smrg    SavagePtr psav = SAVPTR(pScrn);
10411473d951Smrg    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
1042ab47cfaaSmrg
1043ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageStopVideo\n");
1044ab47cfaaSmrg
1045ab47cfaaSmrg    REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1046ab47cfaaSmrg
1047ab47cfaaSmrg    if(shutdown) {
1048ab47cfaaSmrg      /*SavageClipVWindow(pScrn);*/
1049ab47cfaaSmrg 	SavageStreamsOff( pScrn );
10501473d951Smrg
10516aec45a7Smrg#ifdef XF86DRI
10521473d951Smrg	if (pPriv->agpBufferMap != NULL) {
10531473d951Smrg	    SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
10541473d951Smrg
10551473d951Smrg            /* agpXVideo is reused to implement UploadToScreen in EXA */
10561473d951Smrg            if (!psav->useEXA) {
10571473d951Smrg	        drmUnmap(pPriv->agpBufferMap, pSAVAGEDRIServer->agpXVideo.size);
10581473d951Smrg	        pSAVAGEDRIServer->agpXVideo.map = NULL;
10591473d951Smrg            }
10601473d951Smrg	    pPriv->agpBufferMap = NULL;
10611473d951Smrg	    pPriv->agpBufferOffset = 0;
10621473d951Smrg	}
10636aec45a7Smrg	pPriv->tried_agp = FALSE;
10646aec45a7Smrg#endif
10651473d951Smrg
1066ab47cfaaSmrg        if (pPriv->video_memory != NULL) {
1067ab47cfaaSmrg	    SavageFreeMemory(pScrn, pPriv->video_memory);
1068ab47cfaaSmrg	    pPriv->video_memory = NULL;
1069ab47cfaaSmrg        }
10701473d951Smrg        if (pPriv->video_planarmem != NULL) {
10711473d951Smrg	    SavageFreeMemory(pScrn, pPriv->video_planarmem);
10721473d951Smrg	    pPriv->video_planarmem = NULL;
10731473d951Smrg        }
1074ab47cfaaSmrg	pPriv->videoStatus = 0;
1075ab47cfaaSmrg    } else {
1076ab47cfaaSmrg	if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
1077ab47cfaaSmrg	    pPriv->videoStatus |= OFF_TIMER;
1078ab47cfaaSmrg	    pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
1079ab47cfaaSmrg	}
1080ab47cfaaSmrg    }
1081ab47cfaaSmrg}
1082ab47cfaaSmrg
1083ab47cfaaSmrg
1084ab47cfaaSmrgstatic int
1085ab47cfaaSmrgSavageSetPortAttribute(
1086ab47cfaaSmrg    ScrnInfoPtr pScrn,
1087ab47cfaaSmrg    Atom attribute,
1088ab47cfaaSmrg    INT32 value,
1089ab47cfaaSmrg    pointer data
1090ab47cfaaSmrg){
1091ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1092ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1093ab47cfaaSmrg
1094ab47cfaaSmrg    if(attribute == xvColorKey) {
1095ab47cfaaSmrg	pPriv->colorKey = value;
1096ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1097ab47cfaaSmrg	    SavageSetColorKey( pScrn );
1098ab47cfaaSmrg	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1099ab47cfaaSmrg    }
1100ab47cfaaSmrg    else if( attribute == xvBrightness) {
1101ab47cfaaSmrg	if((value < -128) || (value > 127))
1102ab47cfaaSmrg	    return BadValue;
1103ab47cfaaSmrg	pPriv->brightness = value;
1104ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1105ab47cfaaSmrg	    SavageSetColor( pScrn );
1106ab47cfaaSmrg    }
1107ab47cfaaSmrg    else if( attribute == xvContrast) {
1108ab47cfaaSmrg	if((value < 0) || (value > 255))
1109ab47cfaaSmrg	    return BadValue;
1110ab47cfaaSmrg	pPriv->contrast = value;
1111ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1112ab47cfaaSmrg	    SavageSetColor( pScrn );
1113ab47cfaaSmrg    }
1114ab47cfaaSmrg    else if( attribute == xvSaturation) {
1115ab47cfaaSmrg	if((value < 0) || (value > 255))
1116ab47cfaaSmrg	    return BadValue;
1117ab47cfaaSmrg	pPriv->saturation = value;
1118ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1119ab47cfaaSmrg	    SavageSetColor( pScrn );
1120ab47cfaaSmrg    }
1121ab47cfaaSmrg    else if( attribute == xvHue) {
1122ab47cfaaSmrg	if((value < -180) || (value > 180))
1123ab47cfaaSmrg	    return BadValue;
1124ab47cfaaSmrg	pPriv->hue = value;
1125ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1126ab47cfaaSmrg	    SavageSetColor( pScrn );
1127ab47cfaaSmrg    }
1128ab47cfaaSmrg    else if( attribute == xvInterpolation) {
1129ab47cfaaSmrg        if((value < 0) || (value > 1))
1130ab47cfaaSmrg            return BadValue;
1131ab47cfaaSmrg        if (value == 1)
1132ab47cfaaSmrg            pPriv->interpolation = TRUE;
1133ab47cfaaSmrg	else
1134ab47cfaaSmrg	    pPriv->interpolation = FALSE;
1135ab47cfaaSmrg    }
1136ab47cfaaSmrg    else
1137ab47cfaaSmrg	return BadMatch;
1138ab47cfaaSmrg
1139ab47cfaaSmrg    return Success;
1140ab47cfaaSmrg}
1141ab47cfaaSmrg
1142ab47cfaaSmrg
1143ab47cfaaSmrgstatic int
1144ab47cfaaSmrgSavageGetPortAttribute(
1145ab47cfaaSmrg  ScrnInfoPtr pScrn,
1146ab47cfaaSmrg  Atom attribute,
1147ab47cfaaSmrg  INT32 *value,
1148ab47cfaaSmrg  pointer data
1149ab47cfaaSmrg){
1150ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1151ab47cfaaSmrg
1152ab47cfaaSmrg    if(attribute == xvColorKey) {
1153ab47cfaaSmrg	*value = pPriv->colorKey;
1154ab47cfaaSmrg    }
1155ab47cfaaSmrg    else if( attribute == xvBrightness ) {
1156ab47cfaaSmrg	*value = pPriv->brightness;
1157ab47cfaaSmrg    }
1158ab47cfaaSmrg    else if( attribute == xvContrast ) {
1159ab47cfaaSmrg	*value = pPriv->contrast;
1160ab47cfaaSmrg    }
1161ab47cfaaSmrg    else if( attribute == xvHue ) {
1162ab47cfaaSmrg	*value = pPriv->hue;
1163ab47cfaaSmrg    }
1164ab47cfaaSmrg    else if( attribute == xvSaturation ) {
1165ab47cfaaSmrg	*value = pPriv->saturation;
1166ab47cfaaSmrg    }
1167ab47cfaaSmrg    else if( attribute == xvInterpolation ) {
1168ab47cfaaSmrg        *value = pPriv->interpolation;
1169ab47cfaaSmrg    }
1170ab47cfaaSmrg    else return BadMatch;
1171ab47cfaaSmrg
1172ab47cfaaSmrg    return Success;
1173ab47cfaaSmrg}
1174ab47cfaaSmrg
1175ab47cfaaSmrgstatic void
1176ab47cfaaSmrgSavageQueryBestSize(
1177ab47cfaaSmrg  ScrnInfoPtr pScrn,
1178ab47cfaaSmrg  Bool motion,
1179ab47cfaaSmrg  short vid_w, short vid_h,
1180ab47cfaaSmrg  short drw_w, short drw_h,
1181ab47cfaaSmrg  unsigned int *p_w, unsigned int *p_h,
1182ab47cfaaSmrg  pointer data
1183ab47cfaaSmrg){
1184ab47cfaaSmrg    /* What are the real limits for the Savage? */
1185ab47cfaaSmrg
1186ab47cfaaSmrg    *p_w = drw_w;
1187ab47cfaaSmrg    *p_h = drw_h;
1188ab47cfaaSmrg
1189ab47cfaaSmrg    if(*p_w > 16384) *p_w = 16384;
1190ab47cfaaSmrg}
1191ab47cfaaSmrg
1192ab47cfaaSmrg/* SavageCopyPlanarDataBCI() causes artifacts on the screen when used on savage4.
1193ab47cfaaSmrg * It's probably something with the BCI.  Maybe we need a waitforidle() or
1194ab47cfaaSmrg * something...
1195ab47cfaaSmrg */
1196ab47cfaaSmrgstatic void
1197ab47cfaaSmrgSavageCopyPlanarDataBCI(
1198ab47cfaaSmrg    ScrnInfoPtr pScrn,
1199ab47cfaaSmrg    unsigned char *srcY, /* Y */
1200ab47cfaaSmrg    unsigned char *srcV, /* V */
1201ab47cfaaSmrg    unsigned char *srcU, /* U */
1202ab47cfaaSmrg    unsigned char *dst,
12031473d951Smrg    unsigned char * planarPtr,
12041473d951Smrg    unsigned long planarOffset,
1205ab47cfaaSmrg    int srcPitch, int srcPitch2,
1206ab47cfaaSmrg    int dstPitch,
12071473d951Smrg    int h,int w,
12081473d951Smrg    Bool isAGP)
1209ab47cfaaSmrg{
1210ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
12111473d951Smrg
1212ab47cfaaSmrg    /* for pixel transfer */
12131473d951Smrg    unsigned long offsetY = planarOffset;
1214ab47cfaaSmrg    unsigned long offsetV = offsetY +  srcPitch * h;
1215ab47cfaaSmrg    unsigned long offsetU = offsetV +  srcPitch2 * (h>>1);
1216ab47cfaaSmrg    unsigned long dstOffset  = (unsigned long)dst - (unsigned long)psav->FBBase;
1217ab47cfaaSmrg    int i;
12181473d951Smrg    unsigned char memType;
1219ab47cfaaSmrg
1220ab47cfaaSmrg    BCI_GET_PTR;
1221ab47cfaaSmrg
1222ab47cfaaSmrg    /* copy Y planar */
12231473d951Smrg    memcpy(planarPtr, srcY, srcPitch * h);
1224ab47cfaaSmrg
1225ab47cfaaSmrg    /* copy V planar */
12261473d951Smrg    planarPtr = planarPtr + srcPitch * h;
12271473d951Smrg    memcpy(planarPtr, srcV, srcPitch2 * (h>>1));
1228ab47cfaaSmrg
1229ab47cfaaSmrg    /* copy U planar */
12301473d951Smrg    planarPtr = planarPtr + srcPitch2 * (h>>1);
12311473d951Smrg    memcpy(planarPtr, srcU, srcPitch2 * (h>>1));
12321473d951Smrg
12331473d951Smrg    memType = isAGP ? 3 : 0;
1234ab47cfaaSmrg
1235ab47cfaaSmrg    /*
1236ab47cfaaSmrg     * Transfer pixel data from one memory location to another location
1237ab47cfaaSmrg     * and reformat the data during the transfer
1238ab47cfaaSmrg     * a. program BCI51 to specify the source information
1239ab47cfaaSmrg     * b. program BCI52 to specify the destination information
1240ab47cfaaSmrg     * c. program BCI53 to specify the source dimensions
1241ab47cfaaSmrg     * d. program BCI54 to specify the destination dimensions
1242ab47cfaaSmrg     * e. (if the data is in YCbCr420 format)program BCI55,BCI56,BCI57 to
1243ab47cfaaSmrg     *    locations of the Y,Cb,and Cr data
1244ab47cfaaSmrg     * f. program BCI50(command=011) to specify the formatting options and
1245ab47cfaaSmrg     *    kick off the transfer
1246ab47cfaaSmrg     * this command can be used for color space conversion(YCbCr to RGB)
1247ab47cfaaSmrg     * or for oversampling, but not for both simultaneously. it can also be
1248ab47cfaaSmrg     * used to do mastered image transfer when the source is tiled
1249ab47cfaaSmrg     */
1250ab47cfaaSmrg
1251ab47cfaaSmrg    w = (w+0xf)&0xff0;
1252ab47cfaaSmrg    psav->WaitQueue(psav,11);
12531473d951Smrg    BCI_SEND(BCI_SET_REGISTER | BCI_SET_REGISTER_COUNT(7) | 0x51);
12541473d951Smrg    BCI_SEND(offsetY | memType);
1255ab47cfaaSmrg    BCI_SEND(dstOffset);
1256ab47cfaaSmrg    BCI_SEND(((h-1)<<16)|((w-1)>>3));
1257ab47cfaaSmrg    BCI_SEND(dstPitch >> 3);
12581473d951Smrg    BCI_SEND(offsetU | memType);
12591473d951Smrg    BCI_SEND(offsetV | memType);
1260ab47cfaaSmrg    BCI_SEND((srcPitch2 << 16)| srcPitch2);
1261ab47cfaaSmrg
12621473d951Smrg    BCI_SEND(BCI_SET_REGISTER | BCI_SET_REGISTER_COUNT(1) | 0x50);
1263ab47cfaaSmrg    BCI_SEND(0x00200003 | srcPitch);
12641473d951Smrg
1265ab47cfaaSmrg    BCI_SEND(0xC0170000);
1266ab47cfaaSmrg}
1267ab47cfaaSmrg
1268ab47cfaaSmrgstatic void
1269ab47cfaaSmrgSavageCopyData(
1270ab47cfaaSmrg  unsigned char *src,
1271ab47cfaaSmrg  unsigned char *dst,
1272ab47cfaaSmrg  int srcPitch,
1273ab47cfaaSmrg  int dstPitch,
1274ab47cfaaSmrg  int h,
1275ab47cfaaSmrg  int w
1276ab47cfaaSmrg){
1277ab47cfaaSmrg    w <<= 1;
12788697ee19Smrg    if (w == srcPitch && w == dstPitch) {
12798697ee19Smrg        memcpy(dst, src, w * h);
12808697ee19Smrg    } else
1281ab47cfaaSmrg    while(h--) {
1282ab47cfaaSmrg	memcpy(dst, src, w);
1283ab47cfaaSmrg	src += srcPitch;
1284ab47cfaaSmrg	dst += dstPitch;
1285ab47cfaaSmrg    }
1286ab47cfaaSmrg}
1287ab47cfaaSmrg
1288ab47cfaaSmrgstatic void
1289ab47cfaaSmrgSavageCopyPlanarData(
1290ab47cfaaSmrg   unsigned char *src1, /* Y */
1291ab47cfaaSmrg   unsigned char *src2, /* V */
1292ab47cfaaSmrg   unsigned char *src3, /* U */
1293ab47cfaaSmrg   unsigned char *dst1,
1294ab47cfaaSmrg   int srcPitch,
1295ab47cfaaSmrg   int srcPitch2,
1296ab47cfaaSmrg   int dstPitch,
1297ab47cfaaSmrg   int h,
1298ab47cfaaSmrg   int w
1299ab47cfaaSmrg){
1300ab47cfaaSmrg   CARD32 *dst = (CARD32*)dst1;
1301ab47cfaaSmrg   int i, j;
1302ab47cfaaSmrg
1303ab47cfaaSmrg   dstPitch >>= 2;
1304ab47cfaaSmrg   w >>= 1;
1305ab47cfaaSmrg
1306ab47cfaaSmrg   for(j = 0; j < h; j++) {
1307ab47cfaaSmrg	for(i = 0; i < w; i++) {
1308ab47cfaaSmrg/* Shouldn't this be 'if LITTLEENDIAN'? */
1309ab47cfaaSmrg#if 1
1310ab47cfaaSmrg	    dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
1311ab47cfaaSmrg		     (src3[i] << 8) | (src2[i] << 24);
1312ab47cfaaSmrg#else
1313ab47cfaaSmrg	    dst[i] = (src1[i << 1] << 24) | (src1[(i << 1) + 1] << 8) |
1314ab47cfaaSmrg		     (src3[i] << 0) | (src2[i] << 16);
1315ab47cfaaSmrg#endif
1316ab47cfaaSmrg	}
1317ab47cfaaSmrg	dst += dstPitch;
1318ab47cfaaSmrg	src1 += srcPitch;
1319ab47cfaaSmrg	if(j & 1) {
1320ab47cfaaSmrg	    src2 += srcPitch2;
1321ab47cfaaSmrg	    src3 += srcPitch2;
1322ab47cfaaSmrg	}
1323ab47cfaaSmrg   }
1324ab47cfaaSmrg}
1325ab47cfaaSmrg
1326ab47cfaaSmrgstatic void
1327ab47cfaaSmrgSavageVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
1328ab47cfaaSmrg{
1329ab47cfaaSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1330ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1331ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1332ab47cfaaSmrg
1333ab47cfaaSmrg    if (pPriv->video_memory == area)
1334ab47cfaaSmrg        pPriv->video_memory = NULL;
13351473d951Smrg    if (pPriv->video_planarmem == area)
13361473d951Smrg        pPriv->video_planarmem = NULL;
1337ab47cfaaSmrg}
1338ab47cfaaSmrg
1339ab47cfaaSmrgstatic CARD32
1340ab47cfaaSmrgSavageAllocateMemory(
1341ab47cfaaSmrg    ScrnInfoPtr pScrn,
1342ab47cfaaSmrg    void **mem_struct,
1343ab47cfaaSmrg    int size
1344ab47cfaaSmrg){
1345ab47cfaaSmrg    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
1346ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1347ab47cfaaSmrg    int offset = 0;
1348ab47cfaaSmrg
1349ab47cfaaSmrg    if (psav->useEXA) {
1350ab47cfaaSmrg	ExaOffscreenArea *area = *mem_struct;
1351ab47cfaaSmrg
1352ab47cfaaSmrg	if (area != NULL) {
1353ab47cfaaSmrg	    if (area->size >= size)
1354ab47cfaaSmrg		return area->offset;
1355ab47cfaaSmrg
1356ab47cfaaSmrg	    exaOffscreenFree(pScrn->pScreen, area);
1357ab47cfaaSmrg	}
1358ab47cfaaSmrg
1359ab47cfaaSmrg	area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, SavageVideoSave,
1360ab47cfaaSmrg				 NULL);
1361ab47cfaaSmrg	*mem_struct = area;
1362ab47cfaaSmrg	if (area == NULL)
1363ab47cfaaSmrg	    return 0;
1364ab47cfaaSmrg	offset = area->offset;
1365ab47cfaaSmrg    }
1366ab47cfaaSmrg
1367ab47cfaaSmrg    if (!psav->useEXA) {
1368ab47cfaaSmrg	FBLinearPtr linear = *mem_struct;
1369ab47cfaaSmrg	int cpp = pScrn->bitsPerPixel / 8;
1370ab47cfaaSmrg
1371ab47cfaaSmrg	/* XAA allocates in units of pixels at the screen bpp, so adjust size
1372ab47cfaaSmrg	 * appropriately.
1373ab47cfaaSmrg	 */
1374ab47cfaaSmrg	size = (size + cpp - 1) / cpp;
1375ab47cfaaSmrg
1376ab47cfaaSmrg	if (linear) {
1377ab47cfaaSmrg	    if(linear->size >= size)
1378ab47cfaaSmrg		return linear->offset * cpp;
1379ab47cfaaSmrg
1380ab47cfaaSmrg	    if(xf86ResizeOffscreenLinear(linear, size))
1381ab47cfaaSmrg		return linear->offset * cpp;
1382ab47cfaaSmrg
1383ab47cfaaSmrg	    xf86FreeOffscreenLinear(linear);
1384ab47cfaaSmrg	}
1385ab47cfaaSmrg
1386ab47cfaaSmrg	linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
1387ab47cfaaSmrg						NULL, NULL, NULL);
1388ab47cfaaSmrg	*mem_struct = linear;
1389ab47cfaaSmrg
1390ab47cfaaSmrg	if (!linear) {
1391ab47cfaaSmrg	    int max_size;
1392ab47cfaaSmrg
1393ab47cfaaSmrg	    xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
1394ab47cfaaSmrg					    PRIORITY_EXTREME);
1395ab47cfaaSmrg
1396ab47cfaaSmrg	    if(max_size < size)
1397ab47cfaaSmrg		return 0;
1398ab47cfaaSmrg
1399ab47cfaaSmrg	    xf86PurgeUnlockedOffscreenAreas(pScreen);
1400ab47cfaaSmrg	    linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
1401ab47cfaaSmrg						     NULL, NULL, NULL);
1402ab47cfaaSmrg	    *mem_struct = linear;
1403ab47cfaaSmrg	    if (!linear)
1404ab47cfaaSmrg		return 0;
1405ab47cfaaSmrg	}
1406ab47cfaaSmrg	offset = linear->offset * cpp;
1407ab47cfaaSmrg    }
1408ab47cfaaSmrg
1409ab47cfaaSmrg    return offset;
1410ab47cfaaSmrg}
1411ab47cfaaSmrg
1412ab47cfaaSmrgstatic void
1413ab47cfaaSmrgSavageFreeMemory(
1414ab47cfaaSmrg   ScrnInfoPtr pScrn,
1415ab47cfaaSmrg   void *mem_struct
1416ab47cfaaSmrg){
1417ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1418ab47cfaaSmrg
1419ab47cfaaSmrg    if (psav->useEXA) {
1420ab47cfaaSmrg	ExaOffscreenArea *area = mem_struct;
1421ab47cfaaSmrg
1422ab47cfaaSmrg	if (area != NULL)
1423ab47cfaaSmrg	    exaOffscreenFree(pScrn->pScreen, area);
1424ab47cfaaSmrg    }
1425ab47cfaaSmrg    if (!psav->useEXA) {
1426ab47cfaaSmrg	FBLinearPtr linear = mem_struct;
1427ab47cfaaSmrg
1428ab47cfaaSmrg	if (linear != NULL)
1429ab47cfaaSmrg	    xf86FreeOffscreenLinear(linear);
1430ab47cfaaSmrg    }
1431ab47cfaaSmrg}
1432ab47cfaaSmrg
1433ab47cfaaSmrgstatic void
1434ab47cfaaSmrgSavageSetBlend(ScrnInfoPtr pScrn, int id)
1435ab47cfaaSmrg{
1436ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1437ab47cfaaSmrg
1438ab47cfaaSmrg    if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) )
1439ab47cfaaSmrg    {
1440ab47cfaaSmrg	psav->blendBase = GetBlendForFourCC( id );
1441ab47cfaaSmrg	xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase );
1442ab47cfaaSmrg	if (psav->IsSecondary) {
1443ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
1444ab47cfaaSmrg	} else if (psav->IsPrimary) {
1445ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
1446ab47cfaaSmrg	} else {
1447ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
1448ab47cfaaSmrg#if 0
1449ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
1450ab47cfaaSmrg#endif
1451ab47cfaaSmrg	}
1452ab47cfaaSmrg    } else if (psav->Chipset == S3_SAVAGE2000) {
1453ab47cfaaSmrg      psav->blendBase = GetBlendForFourCC2000( id );
1454ab47cfaaSmrg      xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase );
1455ab47cfaaSmrg      if (id != FOURCC_YV12)
1456ab47cfaaSmrg	OUTREG( BLEND_CONTROL,
1457ab47cfaaSmrg		((psav->blendBase << 24) | (8 << 2) /*| 0x20000000*/));
1458ab47cfaaSmrg      else
1459ab47cfaaSmrg	OUTREG( BLEND_CONTROL,
1460ab47cfaaSmrg		((psav->blendBase << 24) | (8 << 2) /*| 0x10000000*/));
1461ab47cfaaSmrg    }
1462ab47cfaaSmrg
1463ab47cfaaSmrg    psav->videoFourCC = id;
1464ab47cfaaSmrg}
1465ab47cfaaSmrg
1466ab47cfaaSmrgstatic void
1467ab47cfaaSmrgSavageDisplayVideoOld(
1468ab47cfaaSmrg    ScrnInfoPtr pScrn,
1469ab47cfaaSmrg    int id,
1470ab47cfaaSmrg    int offset,
1471ab47cfaaSmrg    short width, short height,
1472ab47cfaaSmrg    int pitch,
1473ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1474ab47cfaaSmrg    BoxPtr dstBox,
1475ab47cfaaSmrg    short src_w, short src_h,
1476ab47cfaaSmrg    short drw_w, short drw_h
1477ab47cfaaSmrg){
1478ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1479ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1480ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1481ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1482ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
1483ab47cfaaSmrg    CARD32 ssControl;
1484ab47cfaaSmrg    int scalratio;
1485ab47cfaaSmrg
1486ab47cfaaSmrg
1487ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1488ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1489ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
1490ab47cfaaSmrg#if 0
1491ab47cfaaSmrg    if ( psav->videoFourCC != id ) {
1492ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1493ab47cfaaSmrg	SavageResetVideo(pScrn);
1494ab47cfaaSmrg    }
1495ab47cfaaSmrg#endif
1496ab47cfaaSmrg    if( psav->videoFourCC != id )
1497ab47cfaaSmrg      SavageStreamsOff(pScrn);
1498ab47cfaaSmrg
14998697ee19Smrg    if( !(psav->videoFlags & VF_STREAMS_ON) )
1500ab47cfaaSmrg      {
1501ab47cfaaSmrg        SavageSetBlend(pScrn,id);
1502ab47cfaaSmrg	SavageStreamsOn(pScrn);
1503ab47cfaaSmrg	SavageResetVideo(pScrn);
15048697ee19Smrg	pPriv->lastKnownPitch = 0;
1505ab47cfaaSmrg      }
1506ab47cfaaSmrg
1507ab47cfaaSmrg    if (S3_MOBILE_TWISTER_SERIES(psav->Chipset)
1508ab47cfaaSmrg        && psav->FPExpansion) {
1509ab47cfaaSmrg        drw_w = (((float)(drw_w * psav->XExp1)/(float)psav->XExp2)+1);
1510ab47cfaaSmrg        drw_h = (float)(drw_h * psav->YExp1)/(float)psav->YExp2+1;
1511ab47cfaaSmrg        dstBox->x1 = (float)(dstBox->x1 * psav->XExp1)/(float)psav->XExp2;
1512ab47cfaaSmrg        dstBox->y1 = (float)(dstBox->y1 * psav->YExp1)/(float)psav->YExp2;
1513ab47cfaaSmrg
1514ab47cfaaSmrg        dstBox->x1 += psav->displayXoffset;
1515ab47cfaaSmrg        dstBox->y1 += psav->displayYoffset;
1516ab47cfaaSmrg    }
1517ab47cfaaSmrg
1518ab47cfaaSmrg    /*
1519ab47cfaaSmrg     * Process horizontal scaling
1520ab47cfaaSmrg     *  upscaling and downscaling smaller than 2:1 controled by MM8198
1521ab47cfaaSmrg     *  MM8190 controls downscaling mode larger than 2:1
15228697ee19Smrg     *  Together MM8190 and MM8198 can set arbitrary downscale up to 64:1
1523ab47cfaaSmrg     */
1524ab47cfaaSmrg    scalratio = 0;
1525ab47cfaaSmrg    ssControl = 0;
1526ab47cfaaSmrg
1527ab47cfaaSmrg    if (src_w >= (drw_w * 2)) {
1528ab47cfaaSmrg        if (src_w < (drw_w * 4)) {
1529ab47cfaaSmrg            ssControl |= HDSCALE_4;
15308697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*4));
15318697ee19Smrg        } else if (src_w < (drw_w * 8)) {
1532ab47cfaaSmrg            ssControl |= HDSCALE_8;
15338697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*8));
15348697ee19Smrg        } else if (src_w < (drw_w * 16)) {
1535ab47cfaaSmrg            ssControl |= HDSCALE_16;
15368697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*16));
15378697ee19Smrg        } else if (src_w < (drw_w * 32)) {
1538ab47cfaaSmrg            ssControl |= HDSCALE_32;
15398697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*32));
15408697ee19Smrg        } else if (src_w < (drw_w * 64)) {
15418697ee19Smrg            ssControl |= HDSCALE_64;
15428697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*64));
15438697ee19Smrg        } else {
15448697ee19Smrg            /* Request beyond maximum downscale! */
1545ab47cfaaSmrg            ssControl |= HDSCALE_64;
15468697ee19Smrg            scalratio = HSCALING(2,1);
15478697ee19Smrg        }
1548ab47cfaaSmrg    } else
1549ab47cfaaSmrg        scalratio = HSCALING(src_w,drw_w);
1550ab47cfaaSmrg
1551ab47cfaaSmrg    ssControl |= src_w;
1552ab47cfaaSmrg    /*ssControl |= (1 << 24);*/
1553ab47cfaaSmrg    ssControl |= (GetBlendForFourCC(psav->videoFourCC) << 24);
15548697ee19Smrg#if 0
1555ab47cfaaSmrg    /* Wait for VBLANK. */
1556ab47cfaaSmrg    VerticalRetraceWait();
15578697ee19Smrg#endif
1558ab47cfaaSmrg    OUTREG(SSTREAM_CONTROL_REG, ssControl);
1559ab47cfaaSmrg    if (scalratio)
1560ab47cfaaSmrg        OUTREG(SSTREAM_STRETCH_REG,scalratio);
1561ab47cfaaSmrg
1562ab47cfaaSmrg    /* Calculate vertical scale factor. */
1563ab47cfaaSmrg    OUTREG(SSTREAM_VINITIAL_REG, 0 );
1564ab47cfaaSmrg    /*OUTREG(SSTREAM_VSCALE_REG, (src_h << 15) / drw_h );*/
1565ab47cfaaSmrg    OUTREG(SSTREAM_VSCALE_REG, VSCALING(src_h,drw_h));
1566ab47cfaaSmrg
1567ab47cfaaSmrg    /* Set surface location and stride. */
1568ab47cfaaSmrg    OUTREG(SSTREAM_FBADDR0_REG, (offset + (x1>>15)) & (0x1ffffff & ~BASE_PAD) );
1569ab47cfaaSmrg    OUTREG(SSTREAM_FBADDR1_REG, 0);
1570ab47cfaaSmrg    OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff );
1571ab47cfaaSmrg
1572ab47cfaaSmrg    OUTREG(SSTREAM_WINDOW_START_REG, OS_XY(dstBox->x1, dstBox->y1) );
1573ab47cfaaSmrg    OUTREG(SSTREAM_WINDOW_SIZE_REG, OS_WH(dstBox->x2-dstBox->x1,
1574ab47cfaaSmrg                                          dstBox->y2-dstBox->y1));
1575ab47cfaaSmrg
1576ab47cfaaSmrg    /*
1577ab47cfaaSmrg     * MM81E8:Secondary Stream Source Line Count
1578ab47cfaaSmrg     *   bit_0~10: # of lines in the source image (before scaling)
1579ab47cfaaSmrg     *   bit_15 = 1: Enable vertical interpolation
1580ab47cfaaSmrg     *            0: Line duplicaion
1581ab47cfaaSmrg     */
1582ab47cfaaSmrg    /*
1583ab47cfaaSmrg     * Vertical Interpolation is very bandwidth intensive.  Some savages can't
1584ab47cfaaSmrg     * seem to handle it.  Default is line doubling.  --AGD
1585ab47cfaaSmrg     */
1586ab47cfaaSmrg    if (pPriv->interpolation) {
1587ab47cfaaSmrg        if (src_w * 16 <= 0x3300) {
1588ab47cfaaSmrg            OUTREG(SSTREAM_LINES_REG, 0x8000 | src_h );
1589ab47cfaaSmrg	    OUTREG(FIFO_CONTROL, (INREG(FIFO_CONTROL) + 1));
1590ab47cfaaSmrg        } else {
1591ab47cfaaSmrg            OUTREG(SSTREAM_LINES_REG, src_h );
1592ab47cfaaSmrg        }
1593ab47cfaaSmrg    } else {
1594ab47cfaaSmrg        OUTREG(SSTREAM_LINES_REG, src_h );
1595ab47cfaaSmrg    }
1596ab47cfaaSmrg
1597ab47cfaaSmrg#if 0
1598ab47cfaaSmrg    /* Set color key on primary. */
1599ab47cfaaSmrg
1600ab47cfaaSmrg    SavageSetColorKey( pScrn );
1601ab47cfaaSmrg#endif
1602ab47cfaaSmrg
1603ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1604ab47cfaaSmrg
1605ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1606ab47cfaaSmrg    {
1607ab47cfaaSmrg	unsigned char cr92;
1608ab47cfaaSmrg
1609ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1610ab47cfaaSmrg
1611ab47cfaaSmrg	pitch = (pitch + 7) / 8;
1612ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1613ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1614ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1615ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1616ab47cfaaSmrg	if (psav->bTiled && (( drw_h > src_h) || (drw_w > src_w)))
1617ab47cfaaSmrg	    VGAOUT8(vgaCRReg, pitch | 0xf);
1618ab47cfaaSmrg	else
1619ab47cfaaSmrg	    VGAOUT8(vgaCRReg, pitch);
1620ab47cfaaSmrg    }
1621ab47cfaaSmrg}
1622ab47cfaaSmrg
1623ab47cfaaSmrgstatic void
1624ab47cfaaSmrgSavageDisplayVideoNew(
1625ab47cfaaSmrg    ScrnInfoPtr pScrn,
1626ab47cfaaSmrg    int id,
1627ab47cfaaSmrg    int offset,
1628ab47cfaaSmrg    short width, short height,
1629ab47cfaaSmrg    int pitch,
1630ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1631ab47cfaaSmrg    BoxPtr dstBox,
1632ab47cfaaSmrg    short src_w, short src_h,
1633ab47cfaaSmrg    short drw_w, short drw_h
1634ab47cfaaSmrg){
1635ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1636ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1637ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1638ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1639ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
1640ab47cfaaSmrg
1641ab47cfaaSmrg
1642ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1643ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1644ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
1645ab47cfaaSmrg#if 0
1646ab47cfaaSmrg    if ( psav->videoFourCC != id ) {
1647ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1648ab47cfaaSmrg	SavageResetVideo(pScrn);
1649ab47cfaaSmrg    }
1650ab47cfaaSmrg#endif
1651ab47cfaaSmrg    if( psav->videoFourCC != id )
1652ab47cfaaSmrg      SavageStreamsOff(pScrn);
1653ab47cfaaSmrg
16548697ee19Smrg    if( !(psav->videoFlags & VF_STREAMS_ON) )
1655ab47cfaaSmrg      {
1656ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1657ab47cfaaSmrg	SavageStreamsOn(pScrn);
1658ab47cfaaSmrg	SavageResetVideo(pScrn);
16598697ee19Smrg	pPriv->lastKnownPitch = 0;
1660ab47cfaaSmrg      }
1661ab47cfaaSmrg
1662ab47cfaaSmrg    /* Calculate horizontal and vertical scale factors. */
1663ab47cfaaSmrg
1664ab47cfaaSmrg    if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) &&
1665ab47cfaaSmrg	    (psav->DisplayType == MT_LCD) &&
1666ab47cfaaSmrg	    !psav->CrtOnly &&
1667ab47cfaaSmrg	    !psav->TvOn)
1668ab47cfaaSmrg    {
1669ab47cfaaSmrg	drw_w = (drw_w * psav->XExp1)/psav->XExp2 + 1;
1670ab47cfaaSmrg	drw_h = (drw_h * psav->YExp1)/psav->YExp2 + 1;
1671ab47cfaaSmrg	dstBox->x1 = (dstBox->x1 * psav->XExp1)/psav->XExp2;
1672ab47cfaaSmrg	dstBox->y1 = (dstBox->y1 * psav->YExp1)/psav->YExp2;
1673ab47cfaaSmrg	dstBox->x1 += psav->displayXoffset;
1674ab47cfaaSmrg	dstBox->y1 += psav->displayYoffset;
1675ab47cfaaSmrg    }
1676ab47cfaaSmrg
1677ab47cfaaSmrg	if (psav->IsSecondary) {
1678ab47cfaaSmrg	    OUTREG(SEC_STREAM2_HSCALING,
1679ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1680ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1681ab47cfaaSmrg	    OUTREG(SEC_STREAM2_VSCALING,
1682ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1683ab47cfaaSmrg	} else if (psav->IsPrimary) {
1684ab47cfaaSmrg	    OUTREG(SEC_STREAM_HSCALING,
1685ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1686ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1687ab47cfaaSmrg	    OUTREG(SEC_STREAM_VSCALING,
1688ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1689ab47cfaaSmrg	} else {
1690ab47cfaaSmrg	    OUTREG(SEC_STREAM_HSCALING,
1691ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1692ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1693ab47cfaaSmrg	    OUTREG(SEC_STREAM_VSCALING,
1694ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1695ab47cfaaSmrg#if 0
1696ab47cfaaSmrg	    OUTREG(SEC_STREAM2_HSCALING,
1697ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1698ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1699ab47cfaaSmrg	    OUTREG(SEC_STREAM2_VSCALING,
1700ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1701ab47cfaaSmrg#endif
1702ab47cfaaSmrg	}
1703ab47cfaaSmrg
1704ab47cfaaSmrg    /*
1705ab47cfaaSmrg     * Set surface location and stride.  We use x1>>15 because all surfaces
1706ab47cfaaSmrg     * are 2 bytes/pixel.
1707ab47cfaaSmrg     */
1708ab47cfaaSmrg
1709ab47cfaaSmrg    if (psav->IsSecondary) {
1710ab47cfaaSmrg        OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15))
1711ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1712ab47cfaaSmrg        OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff );
1713ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1714ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1715ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1716ab47cfaaSmrg    } else if (psav->IsPrimary) {
1717ab47cfaaSmrg        OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15))
1718ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1719ab47cfaaSmrg        OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff );
1720ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1721ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1722ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1723ab47cfaaSmrg    } else {
1724ab47cfaaSmrg        OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15))
1725ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1726ab47cfaaSmrg        OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff );
1727ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1728ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1729ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1730ab47cfaaSmrg#if 0
1731ab47cfaaSmrg        OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15))
1732ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1733ab47cfaaSmrg        OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff );
1734ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1735ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1736ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1737ab47cfaaSmrg#endif
1738ab47cfaaSmrg    }
1739ab47cfaaSmrg
1740ab47cfaaSmrg#if 0
1741ab47cfaaSmrg    /* Set color key on primary. */
1742ab47cfaaSmrg
1743ab47cfaaSmrg    SavageSetColorKey( pScrn );
1744ab47cfaaSmrg#endif
1745ab47cfaaSmrg
1746ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1747ab47cfaaSmrg    /* Is CR92 shadowed for crtc2? -- AGD */
1748ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1749ab47cfaaSmrg    {
1750ab47cfaaSmrg	unsigned char cr92;
1751ab47cfaaSmrg
1752ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1753ab47cfaaSmrg	pitch = (pitch + 7) / 8 - 4;
1754ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1755ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1756ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1757ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1758ab47cfaaSmrg	VGAOUT8(vgaCRReg, pitch);
1759ab47cfaaSmrg    }
1760ab47cfaaSmrg}
1761ab47cfaaSmrg
1762ab47cfaaSmrgstatic void
1763ab47cfaaSmrgSavageDisplayVideo2000(
1764ab47cfaaSmrg    ScrnInfoPtr pScrn,
1765ab47cfaaSmrg    int id,
1766ab47cfaaSmrg    int offset,
1767ab47cfaaSmrg    short width, short height,
1768ab47cfaaSmrg    int pitch,
1769ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1770ab47cfaaSmrg    BoxPtr dstBox,
1771ab47cfaaSmrg    short src_w, short src_h,
1772ab47cfaaSmrg    short drw_w, short drw_h
1773ab47cfaaSmrg){
1774ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1775ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1776ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1777ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1778ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
1779ab47cfaaSmrg    CARD32 addr0, addr1, addr2;
1780ab47cfaaSmrg
1781ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1782ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1783ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
1784ab47cfaaSmrg
1785ab47cfaaSmrg
1786ab47cfaaSmrg    if( psav->videoFourCC != id )
1787ab47cfaaSmrg        SavageStreamsOff(pScrn);
1788ab47cfaaSmrg
17898697ee19Smrg    if( !(psav->videoFlags & VF_STREAMS_ON) )
1790ab47cfaaSmrg    {
1791ab47cfaaSmrg        SavageSetBlend(pScrn,id);
1792ab47cfaaSmrg        SavageStreamsOn(pScrn);
1793ab47cfaaSmrg        SavageResetVideo(pScrn);
17948697ee19Smrg        pPriv->lastKnownPitch = 0;
1795ab47cfaaSmrg    }
1796ab47cfaaSmrg
1797ab47cfaaSmrg    if (src_w > drw_w)
1798ab47cfaaSmrg        OUTREG(SEC_STREAM_SRC_START_2000, 0);
1799ab47cfaaSmrg    else
1800ab47cfaaSmrg        OUTREG(SEC_STREAM_SRC_START_2000, SRCSTART(x1, y1));
1801ab47cfaaSmrg
1802ab47cfaaSmrg    /*OUTREG(SEC_STREAM_SRC_SIZE_2000, SRCSIZE(src_w, src_h));*/
1803ab47cfaaSmrg    OUTREG(SEC_STREAM_SRC_SIZE_2000,
1804ab47cfaaSmrg	   SRCSIZE((dstBox->x2-dstBox->x1), (dstBox->y2-dstBox->y1)));
1805ab47cfaaSmrg    /*
1806ab47cfaaSmrg        buffersize = (src_w * src_h * 2) / 4096;
1807ab47cfaaSmrg	  OUTREG(SEC_STREAM_BUFFERSIZE_2000, (buffersize & 0xffffff) << 12);
1808ab47cfaaSmrg    */
1809ab47cfaaSmrg
1810ab47cfaaSmrg    /*SavageResetVideo(pScrn);*/
1811ab47cfaaSmrg
1812ab47cfaaSmrg    if( src_w > drw_w )
1813ab47cfaaSmrg	OUTREG(SEC_STREAM_HSCALE_NORMALIZE, HSCALING_NORMALIZE(drw_w,src_w));
1814ab47cfaaSmrg    else
1815ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALE_NORMALIZE, (2048 << 16));
1816ab47cfaaSmrg
1817ab47cfaaSmrg    /* Calculate horizontal and vertical scale factors. */
1818ab47cfaaSmrg    if ((src_w > drw_w) || (src_h > drw_h))
1819ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALING, (HSCALING_2000(src_w,drw_w)) | 0x01000000);
1820ab47cfaaSmrg    else
1821ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALING, HSCALING_2000(src_w,drw_w));
1822ab47cfaaSmrg
1823ab47cfaaSmrg    OUTREG(SEC_STREAM_VSCALING, VSCALING_2000(src_h,drw_h));
1824ab47cfaaSmrg
1825ab47cfaaSmrg    /*
1826ab47cfaaSmrg     * Set surface location and stride.  We use x1>>15 because all surfaces
1827ab47cfaaSmrg     * are 2 bytes/pixel.
1828ab47cfaaSmrg     */
1829ab47cfaaSmrg
1830ab47cfaaSmrg    addr0 = offset + (x1>>15); /* Y in YCbCr420 */
1831ab47cfaaSmrg    addr1 = addr0 + (width * height); /* Cb in in YCbCr420 */
1832ab47cfaaSmrg    addr2 = addr1 + ((width * height) / 4); /* Cr in in YCbCr420 */
1833ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR0, (addr0) & (0x3fffff & ~BASE_PAD));
1834ab47cfaaSmrg#if 0
1835ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR1, (addr1) & (0x3fffff & ~BASE_PAD));
1836ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR2, (addr2) & (0x3fffff & ~BASE_PAD));
1837ab47cfaaSmrg#endif
1838ab47cfaaSmrg
1839ab47cfaaSmrg    OUTREG(SEC_STREAM_WINDOW_START, XY_2000(dstBox->x1,dstBox->y1));
1840ab47cfaaSmrg    OUTREG(SEC_STREAM_WINDOW_SZ,
1841ab47cfaaSmrg	   WH_2000((dstBox->x2-dstBox->x1),(dstBox->y2-dstBox->y1)));
1842ab47cfaaSmrg
1843ab47cfaaSmrg    /*pitch = width * 2;*/
1844ab47cfaaSmrg    OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff);
1845ab47cfaaSmrg#if 0
1846ab47cfaaSmrg    /* Y stride + CbCr stride in YCbCr420 */
1847ab47cfaaSmrg    OUTREG(SEC_STREAM_STRIDE, (pitch & 0xfff) + ((pitch & 0xfff) << 15));
1848ab47cfaaSmrg#endif
1849ab47cfaaSmrg
1850ab47cfaaSmrg#if 0
1851ab47cfaaSmrg    /* Set color key on primary. */
1852ab47cfaaSmrg
1853ab47cfaaSmrg    SavageSetColorKey2000( pScrn );
1854ab47cfaaSmrg#endif
1855ab47cfaaSmrg
1856ab47cfaaSmrg#if 0
1857ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1858ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1859ab47cfaaSmrg    {
1860ab47cfaaSmrg	unsigned char cr92;
1861ab47cfaaSmrg
1862ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1863ab47cfaaSmrg	pitch = (pitch + 7) / 8 - 4;
1864ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1865ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1866ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1867ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1868ab47cfaaSmrg	VGAOUT8(vgaCRReg, pitch);
1869ab47cfaaSmrg    }
1870ab47cfaaSmrg#endif
1871ab47cfaaSmrg}
1872ab47cfaaSmrg
18731473d951Smrgstatic void
18741473d951SmrgSavageFillKeyHelper(DrawablePtr pDraw, uint32_t colorKey, RegionPtr clipBoxes)
18751473d951Smrg{
18761473d951Smrg#if HAVE_XV_DRAWABLE_HELPER
18771473d951Smrg    xf86XVFillKeyHelperDrawable(pDraw, colorKey, clipBoxes);
18781473d951Smrg#else
18791473d951Smrg    xf86XVFillKeyHelper(pDraw->pScreen, colorKey, clipBoxes);
18801473d951Smrg#endif
18811473d951Smrg}
18821473d951Smrg
1883ab47cfaaSmrgstatic int
1884ab47cfaaSmrgSavagePutImage(
1885ab47cfaaSmrg    ScrnInfoPtr pScrn,
1886ab47cfaaSmrg    short src_x, short src_y,
1887ab47cfaaSmrg    short drw_x, short drw_y,
1888ab47cfaaSmrg    short src_w, short src_h,
1889ab47cfaaSmrg    short drw_w, short drw_h,
1890ab47cfaaSmrg    int id, unsigned char* buf,
1891ab47cfaaSmrg    short width, short height,
1892ab47cfaaSmrg    Bool sync,
1893ab47cfaaSmrg    RegionPtr clipBoxes, pointer data,
1894ab47cfaaSmrg    DrawablePtr pDraw
1895ab47cfaaSmrg){
1896ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1897ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1898ab47cfaaSmrg    ScreenPtr pScreen = pScrn->pScreen;
1899ab47cfaaSmrg    INT32 x1, x2, y1, y2;
1900ab47cfaaSmrg    unsigned char *dst_start;
1901ab47cfaaSmrg    int pitch, new_size, offset, offsetV=0, offsetU=0;
1902ab47cfaaSmrg    int srcPitch, srcPitch2=0, dstPitch;
19031473d951Smrg    int planarFrameSize;
1904ab47cfaaSmrg    int top, left, npixels, nlines;
1905ab47cfaaSmrg    BoxRec dstBox;
1906ab47cfaaSmrg    CARD32 tmp;
1907ab47cfaaSmrg/*    xf86ErrorFVerb(XVTRACE,"SavagePutImage\n"); */
1908ab47cfaaSmrg    if(drw_w > 16384) drw_w = 16384;
1909ab47cfaaSmrg
1910ab47cfaaSmrg    /* Clip */
1911ab47cfaaSmrg    x1 = src_x;
1912ab47cfaaSmrg    x2 = src_x + src_w;
1913ab47cfaaSmrg    y1 = src_y;
1914ab47cfaaSmrg    y2 = src_y + src_h;
1915ab47cfaaSmrg
1916ab47cfaaSmrg    dstBox.x1 = drw_x;
1917ab47cfaaSmrg    dstBox.x2 = drw_x + drw_w;
1918ab47cfaaSmrg    dstBox.y1 = drw_y;
1919ab47cfaaSmrg    dstBox.y2 = drw_y + drw_h;
1920ab47cfaaSmrg
1921ab47cfaaSmrg    SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
1922ab47cfaaSmrg		REGION_EXTENTS(pScreen, clipBoxes), width, height);
1923ab47cfaaSmrg
1924ab47cfaaSmrg    drw_w = dstBox.x2 - dstBox.x1;
1925ab47cfaaSmrg    drw_h = dstBox.y2 - dstBox.y1;
1926ab47cfaaSmrg    src_w = ( x2 - x1 ) >> 16;
1927ab47cfaaSmrg    src_h = ( y2 - y1 ) >> 16;
1928ab47cfaaSmrg
1929ab47cfaaSmrg    if((x1 >= x2) || (y1 >= y2))
1930ab47cfaaSmrg	return Success;
1931ab47cfaaSmrg
1932ab47cfaaSmrg    dstBox.x1 -= pScrn->frameX0;
1933ab47cfaaSmrg    dstBox.x2 -= pScrn->frameX0;
1934ab47cfaaSmrg    dstBox.y1 -= pScrn->frameY0;
1935ab47cfaaSmrg    dstBox.y2 -= pScrn->frameY0;
1936ab47cfaaSmrg
1937ab47cfaaSmrg    pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
1938ab47cfaaSmrg
19391473d951Smrg    /* All formats directly displayable by Savage are packed and 2 bytes per pixel */
1940ab47cfaaSmrg    dstPitch = ((width << 1) + 15) & ~15;
1941ab47cfaaSmrg    new_size = dstPitch * height;
1942ab47cfaaSmrg
1943ab47cfaaSmrg    switch(id) {
1944ab47cfaaSmrg    case FOURCC_Y211:		/* Y211 */
1945ab47cfaaSmrg        srcPitch = width;
1946ab47cfaaSmrg	break;
1947ab47cfaaSmrg    case FOURCC_YV12:		/* YV12 */
1948ab47cfaaSmrg	srcPitch = (width + 3) & ~3;
1949ab47cfaaSmrg	offsetV = srcPitch * height;
1950ab47cfaaSmrg	srcPitch2 = ((width >> 1) + 3) & ~3;
1951ab47cfaaSmrg	offsetU = (srcPitch2 * (height >> 1)) + offsetV;
1952ab47cfaaSmrg	break;
1953ab47cfaaSmrg    case FOURCC_I420:
1954ab47cfaaSmrg	srcPitch = (width + 3) & ~3;
1955ab47cfaaSmrg	offsetU = srcPitch * height;
1956ab47cfaaSmrg	srcPitch2 = ((width >> 1) + 3) & ~3;
1957ab47cfaaSmrg	offsetV = (srcPitch2 * (height >> 1)) + offsetU;
1958ab47cfaaSmrg	break;
1959ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
1960ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
1961ab47cfaaSmrg    case FOURCC_YUY2:		/* YUY2 */
1962ab47cfaaSmrg    default:
1963ab47cfaaSmrg	srcPitch = (width << 1);
1964ab47cfaaSmrg	break;
1965ab47cfaaSmrg    }
1966ab47cfaaSmrg
19671473d951Smrg    /* Calculate required memory for all planar frames */
19681473d951Smrg    planarFrameSize = 0;
19698697ee19Smrg    if (srcPitch2 != 0 && S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv) {
19701473d951Smrg        new_size = ((new_size + 0xF) & ~0xF);
19711473d951Smrg        planarFrameSize = srcPitch * height + srcPitch2 * height;
19721473d951Smrg    }
19731473d951Smrg
19741473d951Smrg    /* Check whether AGP buffers can be allocated. If not, fall back to ordinary
19751473d951Smrg       upload to framebuffer (slower) */
19766aec45a7Smrg#ifdef XF86DRI
19771473d951Smrg    if (!pPriv->tried_agp && !psav->IsPCI && psav->drmFD > 0 && psav->DRIServerInfo != NULL) {
19781473d951Smrg        int ret;
19791473d951Smrg	SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
19801473d951Smrg
19811473d951Smrg	pPriv->tried_agp = TRUE;
19821473d951Smrg	if (pSAVAGEDRIServer->agpXVideo.size >= max(new_size, planarFrameSize)) {
19831473d951Smrg	    if (pSAVAGEDRIServer->agpXVideo.map == NULL &&
19841473d951Smrg	        drmMap( psav->drmFD,
19851473d951Smrg		pSAVAGEDRIServer->agpXVideo.handle,
19861473d951Smrg		pSAVAGEDRIServer->agpXVideo.size,
19871473d951Smrg		&pSAVAGEDRIServer->agpXVideo.map ) < 0 ) {
19881473d951Smrg
19891473d951Smrg		xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] XVideo: Could not map agpXVideo \n" );
19901473d951Smrg		pPriv->agpBufferOffset = 0;
19911473d951Smrg		pPriv->agpBufferMap = NULL;
19921473d951Smrg	    } else {
19931473d951Smrg		pPriv->agpBufferMap = pSAVAGEDRIServer->agpXVideo.map;
19941473d951Smrg		pPriv->agpBufferOffset = pSAVAGEDRIServer->agpXVideo.offset;
19951473d951Smrg		pPriv->agpBase = drmAgpBase(psav->drmFD);
19961473d951Smrg#if 0
19971473d951Smrg		xf86DrvMsg( pScreen->myNum, X_INFO,
19981473d951Smrg		       "[agp] agpXVideo mapped at 0x%08lx aperture=0x%08x offset=0x%08lx\n",
19991473d951Smrg		       (unsigned long)pPriv->agpBufferMap, pPriv->agpBase, pPriv->agpBufferOffset);
20001473d951Smrg#endif
20011473d951Smrg	    }
20021473d951Smrg	} else {
20031473d951Smrg	    /* This situation is expected if AGPforXv is disabled, otherwise report. */
20041473d951Smrg	    if (pSAVAGEDRIServer->agpXVideo.size > 0) {
20051473d951Smrg		xf86DrvMsg( pScreen->myNum, X_ERROR,
20061473d951Smrg		    "[agp] XVideo: not enough space in buffer (got %ld bytes, required %ld bytes).\n",
20071473d951Smrg	    	    pSAVAGEDRIServer->agpXVideo.size, max(new_size, planarFrameSize));
20081473d951Smrg	    }
20091473d951Smrg	    pPriv->agpBufferMap = NULL;
20101473d951Smrg	    pPriv->agpBufferOffset = 0;
20111473d951Smrg	}
20128697ee19Smrg    }
20136aec45a7Smrg#endif /* XF86DRI */
20148697ee19Smrg
20151473d951Smrg
20161473d951Smrg    /* Buffer for final packed frame */
20171473d951Smrg    pPriv->video_offset = SavageAllocateMemory(
20181473d951Smrg	pScrn, &pPriv->video_memory,
20191473d951Smrg	new_size);
2020ab47cfaaSmrg    if (pPriv->video_offset == 0)
2021ab47cfaaSmrg        return BadAlloc;
2022ab47cfaaSmrg
20231473d951Smrg    /* Packed format cases */
20241473d951Smrg    if (planarFrameSize == 0) {
20251473d951Smrg	pPriv->video_planarbuf = 0;
20261473d951Smrg
20271473d951Smrg    /* Planar format cases */
20281473d951Smrg    } else {
20291473d951Smrg	/* Hardware-assisted planar conversion only works on 16-byte aligned addresses */
20301473d951Smrg	pPriv->video_planarbuf = SavageAllocateMemory(
20311473d951Smrg	    pScrn, &pPriv->video_planarmem,
20321473d951Smrg	    ((planarFrameSize + 0xF) & ~0xF));
20331473d951Smrg	if (pPriv->video_planarbuf != 0) {
20341473d951Smrg	    /* TODO: stop any pending conversions when buffers change... */
20351473d951Smrg	    pPriv->video_planarbuf = ((pPriv->video_planarbuf + 0xF) & ~0xF);
20361473d951Smrg	} else {
20371473d951Smrg	    /* Fallback using software conversion */
20381473d951Smrg	}
20391473d951Smrg    }
20401473d951Smrg
2041ab47cfaaSmrg    /* copy data */
2042ab47cfaaSmrg    top = y1 >> 16;
2043ab47cfaaSmrg    left = (x1 >> 16) & ~1;
2044ab47cfaaSmrg    npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
2045ab47cfaaSmrg    left <<= 1;
2046ab47cfaaSmrg
2047ab47cfaaSmrg    offset = (pPriv->video_offset) + (top * dstPitch);
2048ab47cfaaSmrg    dst_start = (psav->FBBase + ((offset + left) & ~BASE_PAD));
2049ab47cfaaSmrg
2050ab47cfaaSmrg    switch(id) {
2051ab47cfaaSmrg    case FOURCC_YV12:		/* YV12 */
2052ab47cfaaSmrg    case FOURCC_I420:
2053ab47cfaaSmrg	top &= ~1;
2054ab47cfaaSmrg	tmp = ((top >> 1) * srcPitch2) + (left >> 2);
2055ab47cfaaSmrg	offsetU += tmp;
2056ab47cfaaSmrg	offsetV += tmp;
2057ab47cfaaSmrg	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
20581473d951Smrg        if (S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv && (npixels & 0xF) == 0 && pPriv->video_planarbuf != 0) {
20596aec45a7Smrg#ifdef XF86DRI
20601473d951Smrg            if (pPriv->agpBufferMap != NULL) {
20611473d951Smrg		/* Using copy to AGP memory */
20621473d951Smrg		SavageCopyPlanarDataBCI(
20631473d951Smrg		    pScrn,
20641473d951Smrg		    buf + (top * srcPitch) + (left >> 1),
20651473d951Smrg		    buf + offsetV,
20661473d951Smrg		    buf + offsetU,
20671473d951Smrg		    dst_start,
20681473d951Smrg		    pPriv->agpBufferMap,
20691473d951Smrg		    pPriv->agpBase + pPriv->agpBufferOffset,
20701473d951Smrg		    srcPitch, srcPitch2, dstPitch, nlines, npixels, TRUE);
20716aec45a7Smrg            } else
20726aec45a7Smrg#endif /* XF86DRI */
20736aec45a7Smrg            {
20741473d951Smrg		/* Using ordinary copy to framebuffer */
20751473d951Smrg		SavageCopyPlanarDataBCI(
20761473d951Smrg		    pScrn,
20771473d951Smrg		    buf + (top * srcPitch) + (left >> 1),
20781473d951Smrg		    buf + offsetV,
20791473d951Smrg		    buf + offsetU,
20801473d951Smrg		    dst_start,
20811473d951Smrg		    (unsigned char *)psav->FBBase + pPriv->video_planarbuf,
20821473d951Smrg		    pPriv->video_planarbuf,
20831473d951Smrg		    srcPitch, srcPitch2, dstPitch, nlines, npixels, FALSE);
20841473d951Smrg	    }
2085ab47cfaaSmrg        } else {
2086ab47cfaaSmrg	    SavageCopyPlanarData(
2087ab47cfaaSmrg	    	buf + (top * srcPitch) + (left >> 1),
2088ab47cfaaSmrg	    	buf + offsetV,
2089ab47cfaaSmrg	    	buf + offsetU,
2090ab47cfaaSmrg	    	dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels);
2091ab47cfaaSmrg        }
2092ab47cfaaSmrg	break;
2093ab47cfaaSmrg    case FOURCC_Y211:		/* Y211 */
2094ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
2095ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
2096ab47cfaaSmrg    case FOURCC_YUY2:		/* YUY2 */
2097ab47cfaaSmrg    default:
2098ab47cfaaSmrg	buf += (top * srcPitch) + left;
2099ab47cfaaSmrg	nlines = ((y2 + 0xffff) >> 16) - top;
2100ab47cfaaSmrg	SavageCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
2101ab47cfaaSmrg	break;
2102ab47cfaaSmrg    }
2103ab47cfaaSmrg
2104ab47cfaaSmrg    /* We need to enable the video before we draw the chroma color.
2105ab47cfaaSmrg       Otherwise, we get blue flashes. */
2106ab47cfaaSmrg
2107ab47cfaaSmrg    SavageDisplayVideo(pScrn, id, offset, width, height, dstPitch,
2108ab47cfaaSmrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
2109ab47cfaaSmrg
2110ab47cfaaSmrg    /* update cliplist */
2111ab47cfaaSmrg    if(!REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes)) {
2112ab47cfaaSmrg	REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
2113ab47cfaaSmrg	/* draw these */
21141473d951Smrg	SavageFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes);
2115ab47cfaaSmrg
2116ab47cfaaSmrg    }
2117ab47cfaaSmrg
2118ab47cfaaSmrg    pPriv->videoStatus = CLIENT_VIDEO_ON;
2119ab47cfaaSmrg
2120ab47cfaaSmrg    return Success;
2121ab47cfaaSmrg}
2122ab47cfaaSmrg
2123ab47cfaaSmrgstatic int
2124ab47cfaaSmrgSavageQueryImageAttributes(
2125ab47cfaaSmrg  ScrnInfoPtr pScrn,
2126ab47cfaaSmrg  int id,
2127ab47cfaaSmrg  unsigned short *w, unsigned short *h,
2128ab47cfaaSmrg  int *pitches, int *offsets
2129ab47cfaaSmrg){
2130ab47cfaaSmrg    int size, tmp;
2131ab47cfaaSmrg
2132ab47cfaaSmrg    if(*w > 1024) *w = 1024;
2133ab47cfaaSmrg    if(*h > 1024) *h = 1024;
2134ab47cfaaSmrg
2135ab47cfaaSmrg    *w = (*w + 1) & ~1;
2136ab47cfaaSmrg    if(offsets) offsets[0] = 0;
2137ab47cfaaSmrg
2138ab47cfaaSmrg    switch(id) {
2139ab47cfaaSmrg    case FOURCC_IA44:
2140ab47cfaaSmrg        if (pitches) pitches[0]=*w;
2141ab47cfaaSmrg        size=(*w)*(*h);
2142ab47cfaaSmrg        break;
2143ab47cfaaSmrg    case FOURCC_Y211:
2144ab47cfaaSmrg	size = *w << 2;
2145ab47cfaaSmrg	if(pitches) pitches[0] = size;
2146ab47cfaaSmrg	size *= *h;
2147ab47cfaaSmrg	break;
2148ab47cfaaSmrg    case FOURCC_YV12:
2149ab47cfaaSmrg    case FOURCC_I420:
2150ab47cfaaSmrg	*h = (*h + 1) & ~1;
2151ab47cfaaSmrg	size = (*w + 3) & ~3;
2152ab47cfaaSmrg	if(pitches) pitches[0] = size;
2153ab47cfaaSmrg	size *= *h;
2154ab47cfaaSmrg	if(offsets) offsets[1] = size;
2155ab47cfaaSmrg	tmp = ((*w >> 1) + 3) & ~3;
2156ab47cfaaSmrg	if(pitches) pitches[1] = pitches[2] = tmp;
2157ab47cfaaSmrg	tmp *= (*h >> 1);
2158ab47cfaaSmrg	size += tmp;
2159ab47cfaaSmrg	if(offsets) offsets[2] = size;
2160ab47cfaaSmrg	size += tmp;
2161ab47cfaaSmrg	break;
2162ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
2163ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
2164ab47cfaaSmrg    case FOURCC_YUY2:
2165ab47cfaaSmrg    default:
2166ab47cfaaSmrg	size = *w << 1;
2167ab47cfaaSmrg	if(pitches) pitches[0] = size;
2168ab47cfaaSmrg	size *= *h;
2169ab47cfaaSmrg	break;
2170ab47cfaaSmrg    }
2171ab47cfaaSmrg
2172ab47cfaaSmrg    return size;
2173ab47cfaaSmrg}
2174ab47cfaaSmrg
2175ab47cfaaSmrg/****************** Offscreen stuff ***************/
2176ab47cfaaSmrg
2177ab47cfaaSmrgtypedef struct {
2178ab47cfaaSmrg  void *surface_memory;
2179ab47cfaaSmrg  Bool isOn;
2180ab47cfaaSmrg} OffscreenPrivRec, * OffscreenPrivPtr;
2181ab47cfaaSmrg
2182ab47cfaaSmrgstatic int
2183ab47cfaaSmrgSavageAllocateSurface(
2184ab47cfaaSmrg    ScrnInfoPtr pScrn,
2185ab47cfaaSmrg    int id,
2186ab47cfaaSmrg    unsigned short w,
2187ab47cfaaSmrg    unsigned short h,
2188ab47cfaaSmrg    XF86SurfacePtr surface
2189ab47cfaaSmrg){
2190ab47cfaaSmrg    int offset, size;
2191ab47cfaaSmrg    int pitch, fbpitch, numlines;
2192ab47cfaaSmrg    void *surface_memory = NULL;
2193ab47cfaaSmrg    OffscreenPrivPtr pPriv;
2194ab47cfaaSmrg
2195ab47cfaaSmrg    if((w > 1024) || (h > 1024))
2196ab47cfaaSmrg	return BadAlloc;
2197ab47cfaaSmrg
2198ab47cfaaSmrg    w = (w + 1) & ~1;
2199ab47cfaaSmrg    pitch = ((w << 1) + 15) & ~15;
2200ab47cfaaSmrg    fbpitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
2201ab47cfaaSmrg    numlines = ((pitch * h) + fbpitch - 1) / fbpitch;
2202ab47cfaaSmrg    size = pitch * h;
2203ab47cfaaSmrg
2204ab47cfaaSmrg    offset = SavageAllocateMemory(pScrn, &surface_memory, size);
2205ab47cfaaSmrg    if (offset == 0)
2206ab47cfaaSmrg	return BadAlloc;
2207ab47cfaaSmrg
2208ab47cfaaSmrg    surface->width = w;
2209ab47cfaaSmrg    surface->height = h;
2210ab47cfaaSmrg
2211ab47cfaaSmrg    if(!(surface->pitches = xalloc(sizeof(int)))) {
2212ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2213ab47cfaaSmrg	return BadAlloc;
2214ab47cfaaSmrg    }
2215ab47cfaaSmrg    if(!(surface->offsets = xalloc(sizeof(int)))) {
2216ab47cfaaSmrg	xfree(surface->pitches);
2217ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2218ab47cfaaSmrg	return BadAlloc;
2219ab47cfaaSmrg    }
2220ab47cfaaSmrg    if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
2221ab47cfaaSmrg	xfree(surface->pitches);
2222ab47cfaaSmrg	xfree(surface->offsets);
2223ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2224ab47cfaaSmrg	return BadAlloc;
2225ab47cfaaSmrg    }
2226ab47cfaaSmrg
2227ab47cfaaSmrg    pPriv->surface_memory = surface_memory;
2228ab47cfaaSmrg    pPriv->isOn = FALSE;
2229ab47cfaaSmrg
2230ab47cfaaSmrg    surface->pScrn = pScrn;
2231ab47cfaaSmrg    surface->id = id;
2232ab47cfaaSmrg    surface->pitches[0] = pitch;
2233ab47cfaaSmrg    surface->offsets[0] = offset; /*area->box.y1 * fbpitch;*/
2234ab47cfaaSmrg    surface->devPrivate.ptr = (pointer)pPriv;
2235ab47cfaaSmrg
2236ab47cfaaSmrg    return Success;
2237ab47cfaaSmrg}
2238ab47cfaaSmrg
2239ab47cfaaSmrgstatic int
2240ab47cfaaSmrgSavageStopSurface(
2241ab47cfaaSmrg    XF86SurfacePtr surface
2242ab47cfaaSmrg){
2243ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2244ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageStopSurface\n");
2245ab47cfaaSmrg
2246ab47cfaaSmrg    if(pPriv->isOn) {
2247ab47cfaaSmrg	/*SavagePtr psav = SAVPTR(surface->pScrn);*/
2248ab47cfaaSmrg	/*SavageClipVWindow(surface->pScrn);*/
2249ab47cfaaSmrg	SavageStreamsOff( surface->pScrn );
2250ab47cfaaSmrg	pPriv->isOn = FALSE;
2251ab47cfaaSmrg    }
2252ab47cfaaSmrg
2253ab47cfaaSmrg    return Success;
2254ab47cfaaSmrg}
2255ab47cfaaSmrg
2256ab47cfaaSmrg
2257ab47cfaaSmrgstatic int
2258ab47cfaaSmrgSavageFreeSurface(
2259ab47cfaaSmrg    XF86SurfacePtr surface
2260ab47cfaaSmrg){
2261ab47cfaaSmrg    ScrnInfoPtr pScrn = surface->pScrn;
2262ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2263ab47cfaaSmrg
2264ab47cfaaSmrg    if(pPriv->isOn)
2265ab47cfaaSmrg	SavageStopSurface(surface);
2266ab47cfaaSmrg    SavageFreeMemory(pScrn, pPriv->surface_memory);
2267ab47cfaaSmrg    xfree(surface->pitches);
2268ab47cfaaSmrg    xfree(surface->offsets);
2269ab47cfaaSmrg    xfree(surface->devPrivate.ptr);
2270ab47cfaaSmrg
2271ab47cfaaSmrg    return Success;
2272ab47cfaaSmrg}
2273ab47cfaaSmrg
2274ab47cfaaSmrgstatic int
2275ab47cfaaSmrgSavageGetSurfaceAttribute(
2276ab47cfaaSmrg    ScrnInfoPtr pScrn,
2277ab47cfaaSmrg    Atom attribute,
2278ab47cfaaSmrg    INT32 *value
2279ab47cfaaSmrg){
2280ab47cfaaSmrg    return SavageGetPortAttribute(pScrn, attribute, value,
2281ab47cfaaSmrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
2282ab47cfaaSmrg}
2283ab47cfaaSmrg
2284ab47cfaaSmrgstatic int
2285ab47cfaaSmrgSavageSetSurfaceAttribute(
2286ab47cfaaSmrg    ScrnInfoPtr pScrn,
2287ab47cfaaSmrg    Atom attribute,
2288ab47cfaaSmrg    INT32 value
2289ab47cfaaSmrg){
2290ab47cfaaSmrg    return SavageSetPortAttribute(pScrn, attribute, value,
2291ab47cfaaSmrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
2292ab47cfaaSmrg}
2293ab47cfaaSmrg
2294ab47cfaaSmrg
2295ab47cfaaSmrgstatic int
2296ab47cfaaSmrgSavageDisplaySurface(
2297ab47cfaaSmrg    XF86SurfacePtr surface,
2298ab47cfaaSmrg    short src_x, short src_y,
2299ab47cfaaSmrg    short drw_x, short drw_y,
2300ab47cfaaSmrg    short src_w, short src_h,
2301ab47cfaaSmrg    short drw_w, short drw_h,
2302ab47cfaaSmrg    RegionPtr clipBoxes
2303ab47cfaaSmrg){
2304ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2305ab47cfaaSmrg    ScrnInfoPtr pScrn = surface->pScrn;
2306ab47cfaaSmrg    ScreenPtr pScreen = pScrn->pScreen;
2307ab47cfaaSmrg    SavagePortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn);
2308ab47cfaaSmrg    INT32 x1, y1, x2, y2;
2309ab47cfaaSmrg    BoxRec dstBox;
2310ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageDisplaySurface\n");
2311ab47cfaaSmrg
2312ab47cfaaSmrg    x1 = src_x;
2313ab47cfaaSmrg    x2 = src_x + src_w;
2314ab47cfaaSmrg    y1 = src_y;
2315ab47cfaaSmrg    y2 = src_y + src_h;
2316ab47cfaaSmrg
2317ab47cfaaSmrg    dstBox.x1 = drw_x;
2318ab47cfaaSmrg    dstBox.x2 = drw_x + drw_w;
2319ab47cfaaSmrg    dstBox.y1 = drw_y;
2320ab47cfaaSmrg    dstBox.y2 = drw_y + drw_h;
2321ab47cfaaSmrg
2322ab47cfaaSmrg    SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
2323ab47cfaaSmrg                	REGION_EXTENTS(pScreen, clipBoxes),
2324ab47cfaaSmrg			surface->width, surface->height);
2325ab47cfaaSmrg
2326ab47cfaaSmrg    if((x1 >= x2) || (y1 >= y2))
2327ab47cfaaSmrg	return Success;
2328ab47cfaaSmrg
2329ab47cfaaSmrg    dstBox.x1 -= pScrn->frameX0;
2330ab47cfaaSmrg    dstBox.x2 -= pScrn->frameX0;
2331ab47cfaaSmrg    dstBox.y1 -= pScrn->frameY0;
2332ab47cfaaSmrg    dstBox.y2 -= pScrn->frameY0;
2333ab47cfaaSmrg
2334ab47cfaaSmrg    SavageDisplayVideo(pScrn, surface->id, surface->offsets[0],
2335ab47cfaaSmrg	     surface->width, surface->height, surface->pitches[0],
2336ab47cfaaSmrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
2337ab47cfaaSmrg
2338ab47cfaaSmrg    xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
2339ab47cfaaSmrg
2340ab47cfaaSmrg    pPriv->isOn = TRUE;
2341ab47cfaaSmrg#if 0
2342ab47cfaaSmrg    if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
2343ab47cfaaSmrg	REGION_EMPTY(pScreen, &portPriv->clip);
2344ab47cfaaSmrg	UpdateCurrentTime();
2345ab47cfaaSmrg	portPriv->videoStatus = FREE_TIMER;
2346ab47cfaaSmrg	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
2347ab47cfaaSmrg    }
2348ab47cfaaSmrg#endif
2349ab47cfaaSmrg
2350ab47cfaaSmrg    return Success;
2351ab47cfaaSmrg}
2352ab47cfaaSmrg
2353ab47cfaaSmrg
2354ab47cfaaSmrgstatic void
2355ab47cfaaSmrgSavageInitOffscreenImages(ScreenPtr pScreen)
2356ab47cfaaSmrg{
2357ab47cfaaSmrg    XF86OffscreenImagePtr offscreenImages;
2358ab47cfaaSmrg    SavagePtr psav = SAVPTR(xf86Screens[pScreen->myNum]);
2359ab47cfaaSmrg
2360ab47cfaaSmrg    /* need to free this someplace */
2361ab47cfaaSmrg    if (!psav->offscreenImages) {
2362ab47cfaaSmrg	if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
2363ab47cfaaSmrg	    return;
2364ab47cfaaSmrg	psav->offscreenImages = offscreenImages;
2365ab47cfaaSmrg    } else {
2366ab47cfaaSmrg	offscreenImages = psav->offscreenImages;
2367ab47cfaaSmrg    }
2368ab47cfaaSmrg
2369ab47cfaaSmrg    offscreenImages[0].image = &Images[0];
2370ab47cfaaSmrg    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
2371ab47cfaaSmrg			       VIDEO_CLIP_TO_VIEWPORT;
2372ab47cfaaSmrg    offscreenImages[0].alloc_surface = SavageAllocateSurface;
2373ab47cfaaSmrg    offscreenImages[0].free_surface = SavageFreeSurface;
2374ab47cfaaSmrg    offscreenImages[0].display = SavageDisplaySurface;
2375ab47cfaaSmrg    offscreenImages[0].stop = SavageStopSurface;
2376ab47cfaaSmrg    offscreenImages[0].setAttribute = SavageSetSurfaceAttribute;
2377ab47cfaaSmrg    offscreenImages[0].getAttribute = SavageGetSurfaceAttribute;
2378ab47cfaaSmrg    offscreenImages[0].max_width = 1024;
2379ab47cfaaSmrg    offscreenImages[0].max_height = 1024;
2380ab47cfaaSmrg    offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
2381ab47cfaaSmrg    offscreenImages[0].attributes = Attributes;
2382ab47cfaaSmrg
2383ab47cfaaSmrg    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
2384ab47cfaaSmrg}
2385ab47cfaaSmrg
2386