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
250aa9e3350Smrg#ifdef SAVAGEDRI
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,",
3072b2b4fcbSmrg	offset, (unsigned long)MMIO_IN32( psav->MapBase, offset ), value );
308ab47cfaaSmrg    MMIO_OUT32( psav->MapBase, offset, value );
3092b2b4fcbSmrg    ErrorF( " now %08lx\n", (unsigned long)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{
341aa9e3350Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
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 */
387aa9e3350Smrg        	malloc((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)
402aa9e3350Smrg	free(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{
880aa9e3350Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
881ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
882ab47cfaaSmrg    XF86VideoAdaptorPtr adapt;
883ab47cfaaSmrg    SavagePortPrivPtr pPriv;
884ab47cfaaSmrg
885ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageSetupImageVideo\n");
886ab47cfaaSmrg
887aa9e3350Smrg    if(!(adapt = calloc(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;
10402b2b4fcbSmrg#ifdef SAVAGEDRI
10411473d951Smrg    SavagePtr psav = SAVPTR(pScrn);
10422b2b4fcbSmrg#endif
1043ab47cfaaSmrg
1044ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageStopVideo\n");
1045ab47cfaaSmrg
1046ab47cfaaSmrg    REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1047ab47cfaaSmrg
1048ab47cfaaSmrg    if(shutdown) {
1049ab47cfaaSmrg      /*SavageClipVWindow(pScrn);*/
1050ab47cfaaSmrg 	SavageStreamsOff( pScrn );
10511473d951Smrg
1052aa9e3350Smrg#ifdef SAVAGEDRI
10531473d951Smrg	if (pPriv->agpBufferMap != NULL) {
10541473d951Smrg	    SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
10551473d951Smrg
10561473d951Smrg            /* agpXVideo is reused to implement UploadToScreen in EXA */
10571473d951Smrg            if (!psav->useEXA) {
10581473d951Smrg	        drmUnmap(pPriv->agpBufferMap, pSAVAGEDRIServer->agpXVideo.size);
10591473d951Smrg	        pSAVAGEDRIServer->agpXVideo.map = NULL;
10601473d951Smrg            }
10611473d951Smrg	    pPriv->agpBufferMap = NULL;
10621473d951Smrg	    pPriv->agpBufferOffset = 0;
10631473d951Smrg	}
10646aec45a7Smrg	pPriv->tried_agp = FALSE;
10656aec45a7Smrg#endif
10661473d951Smrg
1067ab47cfaaSmrg        if (pPriv->video_memory != NULL) {
1068ab47cfaaSmrg	    SavageFreeMemory(pScrn, pPriv->video_memory);
1069ab47cfaaSmrg	    pPriv->video_memory = NULL;
1070ab47cfaaSmrg        }
10711473d951Smrg        if (pPriv->video_planarmem != NULL) {
10721473d951Smrg	    SavageFreeMemory(pScrn, pPriv->video_planarmem);
10731473d951Smrg	    pPriv->video_planarmem = NULL;
10741473d951Smrg        }
1075ab47cfaaSmrg	pPriv->videoStatus = 0;
1076ab47cfaaSmrg    } else {
1077ab47cfaaSmrg	if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
1078ab47cfaaSmrg	    pPriv->videoStatus |= OFF_TIMER;
1079ab47cfaaSmrg	    pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
1080ab47cfaaSmrg	}
1081ab47cfaaSmrg    }
1082ab47cfaaSmrg}
1083ab47cfaaSmrg
1084ab47cfaaSmrg
1085ab47cfaaSmrgstatic int
1086ab47cfaaSmrgSavageSetPortAttribute(
1087ab47cfaaSmrg    ScrnInfoPtr pScrn,
1088ab47cfaaSmrg    Atom attribute,
1089ab47cfaaSmrg    INT32 value,
1090ab47cfaaSmrg    pointer data
1091ab47cfaaSmrg){
1092ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1093ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1094ab47cfaaSmrg
1095ab47cfaaSmrg    if(attribute == xvColorKey) {
1096ab47cfaaSmrg	pPriv->colorKey = value;
1097ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1098ab47cfaaSmrg	    SavageSetColorKey( pScrn );
1099ab47cfaaSmrg	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1100ab47cfaaSmrg    }
1101ab47cfaaSmrg    else if( attribute == xvBrightness) {
1102ab47cfaaSmrg	if((value < -128) || (value > 127))
1103ab47cfaaSmrg	    return BadValue;
1104ab47cfaaSmrg	pPriv->brightness = value;
1105ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1106ab47cfaaSmrg	    SavageSetColor( pScrn );
1107ab47cfaaSmrg    }
1108ab47cfaaSmrg    else if( attribute == xvContrast) {
1109ab47cfaaSmrg	if((value < 0) || (value > 255))
1110ab47cfaaSmrg	    return BadValue;
1111ab47cfaaSmrg	pPriv->contrast = value;
1112ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1113ab47cfaaSmrg	    SavageSetColor( pScrn );
1114ab47cfaaSmrg    }
1115ab47cfaaSmrg    else if( attribute == xvSaturation) {
1116ab47cfaaSmrg	if((value < 0) || (value > 255))
1117ab47cfaaSmrg	    return BadValue;
1118ab47cfaaSmrg	pPriv->saturation = value;
1119ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1120ab47cfaaSmrg	    SavageSetColor( pScrn );
1121ab47cfaaSmrg    }
1122ab47cfaaSmrg    else if( attribute == xvHue) {
1123ab47cfaaSmrg	if((value < -180) || (value > 180))
1124ab47cfaaSmrg	    return BadValue;
1125ab47cfaaSmrg	pPriv->hue = value;
1126ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1127ab47cfaaSmrg	    SavageSetColor( pScrn );
1128ab47cfaaSmrg    }
1129ab47cfaaSmrg    else if( attribute == xvInterpolation) {
1130ab47cfaaSmrg        if((value < 0) || (value > 1))
1131ab47cfaaSmrg            return BadValue;
1132ab47cfaaSmrg        if (value == 1)
1133ab47cfaaSmrg            pPriv->interpolation = TRUE;
1134ab47cfaaSmrg	else
1135ab47cfaaSmrg	    pPriv->interpolation = FALSE;
1136ab47cfaaSmrg    }
1137ab47cfaaSmrg    else
1138ab47cfaaSmrg	return BadMatch;
1139ab47cfaaSmrg
1140ab47cfaaSmrg    return Success;
1141ab47cfaaSmrg}
1142ab47cfaaSmrg
1143ab47cfaaSmrg
1144ab47cfaaSmrgstatic int
1145ab47cfaaSmrgSavageGetPortAttribute(
1146ab47cfaaSmrg  ScrnInfoPtr pScrn,
1147ab47cfaaSmrg  Atom attribute,
1148ab47cfaaSmrg  INT32 *value,
1149ab47cfaaSmrg  pointer data
1150ab47cfaaSmrg){
1151ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1152ab47cfaaSmrg
1153ab47cfaaSmrg    if(attribute == xvColorKey) {
1154ab47cfaaSmrg	*value = pPriv->colorKey;
1155ab47cfaaSmrg    }
1156ab47cfaaSmrg    else if( attribute == xvBrightness ) {
1157ab47cfaaSmrg	*value = pPriv->brightness;
1158ab47cfaaSmrg    }
1159ab47cfaaSmrg    else if( attribute == xvContrast ) {
1160ab47cfaaSmrg	*value = pPriv->contrast;
1161ab47cfaaSmrg    }
1162ab47cfaaSmrg    else if( attribute == xvHue ) {
1163ab47cfaaSmrg	*value = pPriv->hue;
1164ab47cfaaSmrg    }
1165ab47cfaaSmrg    else if( attribute == xvSaturation ) {
1166ab47cfaaSmrg	*value = pPriv->saturation;
1167ab47cfaaSmrg    }
1168ab47cfaaSmrg    else if( attribute == xvInterpolation ) {
1169ab47cfaaSmrg        *value = pPriv->interpolation;
1170ab47cfaaSmrg    }
1171ab47cfaaSmrg    else return BadMatch;
1172ab47cfaaSmrg
1173ab47cfaaSmrg    return Success;
1174ab47cfaaSmrg}
1175ab47cfaaSmrg
1176ab47cfaaSmrgstatic void
1177ab47cfaaSmrgSavageQueryBestSize(
1178ab47cfaaSmrg  ScrnInfoPtr pScrn,
1179ab47cfaaSmrg  Bool motion,
1180ab47cfaaSmrg  short vid_w, short vid_h,
1181ab47cfaaSmrg  short drw_w, short drw_h,
1182ab47cfaaSmrg  unsigned int *p_w, unsigned int *p_h,
1183ab47cfaaSmrg  pointer data
1184ab47cfaaSmrg){
1185ab47cfaaSmrg    /* What are the real limits for the Savage? */
1186ab47cfaaSmrg
1187ab47cfaaSmrg    *p_w = drw_w;
1188ab47cfaaSmrg    *p_h = drw_h;
1189ab47cfaaSmrg
1190ab47cfaaSmrg    if(*p_w > 16384) *p_w = 16384;
1191ab47cfaaSmrg}
1192ab47cfaaSmrg
1193ab47cfaaSmrg/* SavageCopyPlanarDataBCI() causes artifacts on the screen when used on savage4.
1194ab47cfaaSmrg * It's probably something with the BCI.  Maybe we need a waitforidle() or
1195ab47cfaaSmrg * something...
1196ab47cfaaSmrg */
1197ab47cfaaSmrgstatic void
1198ab47cfaaSmrgSavageCopyPlanarDataBCI(
1199ab47cfaaSmrg    ScrnInfoPtr pScrn,
1200ab47cfaaSmrg    unsigned char *srcY, /* Y */
1201ab47cfaaSmrg    unsigned char *srcV, /* V */
1202ab47cfaaSmrg    unsigned char *srcU, /* U */
1203ab47cfaaSmrg    unsigned char *dst,
12041473d951Smrg    unsigned char * planarPtr,
12051473d951Smrg    unsigned long planarOffset,
1206ab47cfaaSmrg    int srcPitch, int srcPitch2,
1207ab47cfaaSmrg    int dstPitch,
12081473d951Smrg    int h,int w,
12091473d951Smrg    Bool isAGP)
1210ab47cfaaSmrg{
1211ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
12121473d951Smrg
1213ab47cfaaSmrg    /* for pixel transfer */
12141473d951Smrg    unsigned long offsetY = planarOffset;
1215ab47cfaaSmrg    unsigned long offsetV = offsetY +  srcPitch * h;
1216ab47cfaaSmrg    unsigned long offsetU = offsetV +  srcPitch2 * (h>>1);
1217ab47cfaaSmrg    unsigned long dstOffset  = (unsigned long)dst - (unsigned long)psav->FBBase;
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{
1329aa9e3350Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
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){
1345aa9e3350Smrg    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
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)
1508aa9e3350Smrg	&& psav->FPExpansion) {
1509aa9e3350Smrg	drw_w = (drw_w * psav->XExp1) / psav->XExp2 + 1;
1510aa9e3350Smrg	drw_h = (drw_h * psav->YExp1) / psav->YExp2 + 1;
1511aa9e3350Smrg	dstBox->x1 = (dstBox->x1 * psav->XExp1) / psav->XExp2;
1512aa9e3350Smrg	dstBox->y1 = (dstBox->y1 * psav->YExp1) / psav->YExp2;
1513aa9e3350Smrg	dstBox->x2 = (dstBox->x2 * psav->XExp1) / psav->XExp2;
1514aa9e3350Smrg	dstBox->y2 = (dstBox->y2 * psav->YExp1) / psav->YExp2;
1515aa9e3350Smrg	dstBox->x1 += psav->displayXoffset;
1516aa9e3350Smrg	dstBox->y1 += psav->displayYoffset;
1517aa9e3350Smrg	dstBox->x2 += psav->displayXoffset;
1518aa9e3350Smrg	dstBox->y2 += psav->displayYoffset;
1519ab47cfaaSmrg    }
1520ab47cfaaSmrg
1521ab47cfaaSmrg    /*
1522ab47cfaaSmrg     * Process horizontal scaling
15232b2b4fcbSmrg     *  upscaling and downscaling smaller than 2:1 controlled by MM8198
1524ab47cfaaSmrg     *  MM8190 controls downscaling mode larger than 2:1
15258697ee19Smrg     *  Together MM8190 and MM8198 can set arbitrary downscale up to 64:1
1526ab47cfaaSmrg     */
1527ab47cfaaSmrg    scalratio = 0;
1528ab47cfaaSmrg    ssControl = 0;
1529ab47cfaaSmrg
1530ab47cfaaSmrg    if (src_w >= (drw_w * 2)) {
1531ab47cfaaSmrg        if (src_w < (drw_w * 4)) {
1532ab47cfaaSmrg            ssControl |= HDSCALE_4;
15338697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*4));
15348697ee19Smrg        } else if (src_w < (drw_w * 8)) {
1535ab47cfaaSmrg            ssControl |= HDSCALE_8;
15368697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*8));
15378697ee19Smrg        } else if (src_w < (drw_w * 16)) {
1538ab47cfaaSmrg            ssControl |= HDSCALE_16;
15398697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*16));
15408697ee19Smrg        } else if (src_w < (drw_w * 32)) {
1541ab47cfaaSmrg            ssControl |= HDSCALE_32;
15428697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*32));
15438697ee19Smrg        } else if (src_w < (drw_w * 64)) {
15448697ee19Smrg            ssControl |= HDSCALE_64;
15458697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*64));
15468697ee19Smrg        } else {
15478697ee19Smrg            /* Request beyond maximum downscale! */
1548ab47cfaaSmrg            ssControl |= HDSCALE_64;
15498697ee19Smrg            scalratio = HSCALING(2,1);
15508697ee19Smrg        }
1551ab47cfaaSmrg    } else
1552ab47cfaaSmrg        scalratio = HSCALING(src_w,drw_w);
1553ab47cfaaSmrg
1554ab47cfaaSmrg    ssControl |= src_w;
1555ab47cfaaSmrg    /*ssControl |= (1 << 24);*/
1556ab47cfaaSmrg    ssControl |= (GetBlendForFourCC(psav->videoFourCC) << 24);
15578697ee19Smrg#if 0
1558ab47cfaaSmrg    /* Wait for VBLANK. */
1559ab47cfaaSmrg    VerticalRetraceWait();
15608697ee19Smrg#endif
1561ab47cfaaSmrg    OUTREG(SSTREAM_CONTROL_REG, ssControl);
1562ab47cfaaSmrg    if (scalratio)
1563ab47cfaaSmrg        OUTREG(SSTREAM_STRETCH_REG,scalratio);
1564ab47cfaaSmrg
1565ab47cfaaSmrg    /* Calculate vertical scale factor. */
1566ab47cfaaSmrg    OUTREG(SSTREAM_VINITIAL_REG, 0 );
1567ab47cfaaSmrg    /*OUTREG(SSTREAM_VSCALE_REG, (src_h << 15) / drw_h );*/
1568ab47cfaaSmrg    OUTREG(SSTREAM_VSCALE_REG, VSCALING(src_h,drw_h));
1569ab47cfaaSmrg
1570ab47cfaaSmrg    /* Set surface location and stride. */
1571ab47cfaaSmrg    OUTREG(SSTREAM_FBADDR0_REG, (offset + (x1>>15)) & (0x1ffffff & ~BASE_PAD) );
1572ab47cfaaSmrg    OUTREG(SSTREAM_FBADDR1_REG, 0);
1573ab47cfaaSmrg    OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff );
1574ab47cfaaSmrg
1575ab47cfaaSmrg    OUTREG(SSTREAM_WINDOW_START_REG, OS_XY(dstBox->x1, dstBox->y1) );
1576ab47cfaaSmrg    OUTREG(SSTREAM_WINDOW_SIZE_REG, OS_WH(dstBox->x2-dstBox->x1,
1577ab47cfaaSmrg                                          dstBox->y2-dstBox->y1));
1578ab47cfaaSmrg
1579ab47cfaaSmrg    /*
1580ab47cfaaSmrg     * MM81E8:Secondary Stream Source Line Count
1581ab47cfaaSmrg     *   bit_0~10: # of lines in the source image (before scaling)
1582ab47cfaaSmrg     *   bit_15 = 1: Enable vertical interpolation
1583ab47cfaaSmrg     *            0: Line duplicaion
1584ab47cfaaSmrg     */
1585ab47cfaaSmrg    /*
1586ab47cfaaSmrg     * Vertical Interpolation is very bandwidth intensive.  Some savages can't
1587ab47cfaaSmrg     * seem to handle it.  Default is line doubling.  --AGD
1588ab47cfaaSmrg     */
1589ab47cfaaSmrg    if (pPriv->interpolation) {
1590ab47cfaaSmrg        if (src_w * 16 <= 0x3300) {
1591ab47cfaaSmrg            OUTREG(SSTREAM_LINES_REG, 0x8000 | src_h );
1592ab47cfaaSmrg	    OUTREG(FIFO_CONTROL, (INREG(FIFO_CONTROL) + 1));
1593ab47cfaaSmrg        } else {
1594ab47cfaaSmrg            OUTREG(SSTREAM_LINES_REG, src_h );
1595ab47cfaaSmrg        }
1596ab47cfaaSmrg    } else {
1597ab47cfaaSmrg        OUTREG(SSTREAM_LINES_REG, src_h );
1598ab47cfaaSmrg    }
1599ab47cfaaSmrg
1600ab47cfaaSmrg#if 0
1601ab47cfaaSmrg    /* Set color key on primary. */
1602ab47cfaaSmrg
1603ab47cfaaSmrg    SavageSetColorKey( pScrn );
1604ab47cfaaSmrg#endif
1605ab47cfaaSmrg
1606ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1607ab47cfaaSmrg
1608ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1609ab47cfaaSmrg    {
1610ab47cfaaSmrg	unsigned char cr92;
1611ab47cfaaSmrg
1612ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1613ab47cfaaSmrg
1614ab47cfaaSmrg	pitch = (pitch + 7) / 8;
1615ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1616ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1617ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1618ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1619ab47cfaaSmrg	if (psav->bTiled && (( drw_h > src_h) || (drw_w > src_w)))
1620ab47cfaaSmrg	    VGAOUT8(vgaCRReg, pitch | 0xf);
1621ab47cfaaSmrg	else
1622ab47cfaaSmrg	    VGAOUT8(vgaCRReg, pitch);
1623ab47cfaaSmrg    }
1624ab47cfaaSmrg}
1625ab47cfaaSmrg
1626ab47cfaaSmrgstatic void
1627ab47cfaaSmrgSavageDisplayVideoNew(
1628ab47cfaaSmrg    ScrnInfoPtr pScrn,
1629ab47cfaaSmrg    int id,
1630ab47cfaaSmrg    int offset,
1631ab47cfaaSmrg    short width, short height,
1632ab47cfaaSmrg    int pitch,
1633ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1634ab47cfaaSmrg    BoxPtr dstBox,
1635ab47cfaaSmrg    short src_w, short src_h,
1636ab47cfaaSmrg    short drw_w, short drw_h
1637ab47cfaaSmrg){
1638ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1639ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1640ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1641ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1642ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
1643ab47cfaaSmrg
1644ab47cfaaSmrg
1645ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1646ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1647ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
1648ab47cfaaSmrg#if 0
1649ab47cfaaSmrg    if ( psav->videoFourCC != id ) {
1650ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1651ab47cfaaSmrg	SavageResetVideo(pScrn);
1652ab47cfaaSmrg    }
1653ab47cfaaSmrg#endif
1654ab47cfaaSmrg    if( psav->videoFourCC != id )
1655ab47cfaaSmrg      SavageStreamsOff(pScrn);
1656ab47cfaaSmrg
16578697ee19Smrg    if( !(psav->videoFlags & VF_STREAMS_ON) )
1658ab47cfaaSmrg      {
1659ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1660ab47cfaaSmrg	SavageStreamsOn(pScrn);
1661ab47cfaaSmrg	SavageResetVideo(pScrn);
16628697ee19Smrg	pPriv->lastKnownPitch = 0;
1663ab47cfaaSmrg      }
1664ab47cfaaSmrg
1665ab47cfaaSmrg    /* Calculate horizontal and vertical scale factors. */
1666ab47cfaaSmrg
1667ab47cfaaSmrg    if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) &&
1668ab47cfaaSmrg	    (psav->DisplayType == MT_LCD) &&
1669ab47cfaaSmrg	    !psav->CrtOnly &&
1670ab47cfaaSmrg	    !psav->TvOn)
1671ab47cfaaSmrg    {
1672aa9e3350Smrg	drw_w = (drw_w * psav->XExp1) / psav->XExp2 + 1;
1673aa9e3350Smrg	drw_h = (drw_h * psav->YExp1) / psav->YExp2 + 1;
1674aa9e3350Smrg	dstBox->x1 = (dstBox->x1 * psav->XExp1) / psav->XExp2;
1675aa9e3350Smrg	dstBox->y1 = (dstBox->y1 * psav->YExp1) / psav->YExp2;
1676aa9e3350Smrg	dstBox->x2 = (dstBox->x2 * psav->XExp1) / psav->XExp2;
1677aa9e3350Smrg	dstBox->y2 = (dstBox->y2 * psav->YExp1) / psav->YExp2;
1678ab47cfaaSmrg	dstBox->x1 += psav->displayXoffset;
1679ab47cfaaSmrg	dstBox->y1 += psav->displayYoffset;
1680aa9e3350Smrg	dstBox->x2 += psav->displayXoffset;
1681aa9e3350Smrg	dstBox->y2 += psav->displayYoffset;
1682ab47cfaaSmrg    }
1683ab47cfaaSmrg
1684ab47cfaaSmrg	if (psav->IsSecondary) {
1685ab47cfaaSmrg	    OUTREG(SEC_STREAM2_HSCALING,
1686ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1687ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1688ab47cfaaSmrg	    OUTREG(SEC_STREAM2_VSCALING,
1689ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1690ab47cfaaSmrg	} else if (psav->IsPrimary) {
1691ab47cfaaSmrg	    OUTREG(SEC_STREAM_HSCALING,
1692ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1693ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1694ab47cfaaSmrg	    OUTREG(SEC_STREAM_VSCALING,
1695ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1696ab47cfaaSmrg	} else {
1697ab47cfaaSmrg	    OUTREG(SEC_STREAM_HSCALING,
1698ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1699ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1700ab47cfaaSmrg	    OUTREG(SEC_STREAM_VSCALING,
1701ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1702ab47cfaaSmrg#if 0
1703ab47cfaaSmrg	    OUTREG(SEC_STREAM2_HSCALING,
1704ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1705ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1706ab47cfaaSmrg	    OUTREG(SEC_STREAM2_VSCALING,
1707ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1708ab47cfaaSmrg#endif
1709ab47cfaaSmrg	}
1710ab47cfaaSmrg
1711ab47cfaaSmrg    /*
1712ab47cfaaSmrg     * Set surface location and stride.  We use x1>>15 because all surfaces
1713ab47cfaaSmrg     * are 2 bytes/pixel.
1714ab47cfaaSmrg     */
1715ab47cfaaSmrg
1716ab47cfaaSmrg    if (psav->IsSecondary) {
1717ab47cfaaSmrg        OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15))
1718ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1719ab47cfaaSmrg        OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff );
1720ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1721ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
172238770048Smrg	   | (dstBox->y2 - dstBox->y1) );
1723ab47cfaaSmrg    } else if (psav->IsPrimary) {
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)
172938770048Smrg	   | (dstBox->y2 - dstBox->y1) );
1730ab47cfaaSmrg    } else {
1731ab47cfaaSmrg        OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15))
1732ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1733ab47cfaaSmrg        OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff );
1734ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1735ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
173638770048Smrg	   | (dstBox->y2 - dstBox->y1) );
1737ab47cfaaSmrg#if 0
1738ab47cfaaSmrg        OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15))
1739ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1740ab47cfaaSmrg        OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff );
1741ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1742ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
174338770048Smrg	   | (dstBox->y2 - dstBox->y1) );
1744ab47cfaaSmrg#endif
1745ab47cfaaSmrg    }
1746ab47cfaaSmrg
1747ab47cfaaSmrg#if 0
1748ab47cfaaSmrg    /* Set color key on primary. */
1749ab47cfaaSmrg
1750ab47cfaaSmrg    SavageSetColorKey( pScrn );
1751ab47cfaaSmrg#endif
1752ab47cfaaSmrg
1753ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1754ab47cfaaSmrg    /* Is CR92 shadowed for crtc2? -- AGD */
1755ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1756ab47cfaaSmrg    {
1757ab47cfaaSmrg	unsigned char cr92;
1758ab47cfaaSmrg
1759ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1760ab47cfaaSmrg	pitch = (pitch + 7) / 8 - 4;
1761ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1762ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1763ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1764ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1765ab47cfaaSmrg	VGAOUT8(vgaCRReg, pitch);
1766ab47cfaaSmrg    }
1767ab47cfaaSmrg}
1768ab47cfaaSmrg
1769ab47cfaaSmrgstatic void
1770ab47cfaaSmrgSavageDisplayVideo2000(
1771ab47cfaaSmrg    ScrnInfoPtr pScrn,
1772ab47cfaaSmrg    int id,
1773ab47cfaaSmrg    int offset,
1774ab47cfaaSmrg    short width, short height,
1775ab47cfaaSmrg    int pitch,
1776ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1777ab47cfaaSmrg    BoxPtr dstBox,
1778ab47cfaaSmrg    short src_w, short src_h,
1779ab47cfaaSmrg    short drw_w, short drw_h
1780ab47cfaaSmrg){
1781ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
17822b2b4fcbSmrg#if 0
1783ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
17842b2b4fcbSmrg#endif
1785ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1786ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
17872b2b4fcbSmrg#if 0
1788ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
17892b2b4fcbSmrg#endif
17902b2b4fcbSmrg    CARD32 addr0;
17912b2b4fcbSmrg#if 0
17922b2b4fcbSmrg    CARD32 addr1, addr2;
17932b2b4fcbSmrg#endif
1794ab47cfaaSmrg
17952b2b4fcbSmrg#if 0
1796ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1797ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1798ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
17992b2b4fcbSmrg#endif
1800ab47cfaaSmrg
1801ab47cfaaSmrg
1802ab47cfaaSmrg    if( psav->videoFourCC != id )
1803ab47cfaaSmrg        SavageStreamsOff(pScrn);
1804ab47cfaaSmrg
18058697ee19Smrg    if( !(psav->videoFlags & VF_STREAMS_ON) )
1806ab47cfaaSmrg    {
1807ab47cfaaSmrg        SavageSetBlend(pScrn,id);
1808ab47cfaaSmrg        SavageStreamsOn(pScrn);
1809ab47cfaaSmrg        SavageResetVideo(pScrn);
18108697ee19Smrg        pPriv->lastKnownPitch = 0;
1811ab47cfaaSmrg    }
1812ab47cfaaSmrg
1813ab47cfaaSmrg    if (src_w > drw_w)
1814ab47cfaaSmrg        OUTREG(SEC_STREAM_SRC_START_2000, 0);
1815ab47cfaaSmrg    else
1816ab47cfaaSmrg        OUTREG(SEC_STREAM_SRC_START_2000, SRCSTART(x1, y1));
1817ab47cfaaSmrg
1818ab47cfaaSmrg    /*OUTREG(SEC_STREAM_SRC_SIZE_2000, SRCSIZE(src_w, src_h));*/
1819ab47cfaaSmrg    OUTREG(SEC_STREAM_SRC_SIZE_2000,
1820ab47cfaaSmrg	   SRCSIZE((dstBox->x2-dstBox->x1), (dstBox->y2-dstBox->y1)));
1821ab47cfaaSmrg    /*
1822ab47cfaaSmrg        buffersize = (src_w * src_h * 2) / 4096;
1823ab47cfaaSmrg	  OUTREG(SEC_STREAM_BUFFERSIZE_2000, (buffersize & 0xffffff) << 12);
1824ab47cfaaSmrg    */
1825ab47cfaaSmrg
1826ab47cfaaSmrg    /*SavageResetVideo(pScrn);*/
1827ab47cfaaSmrg
1828ab47cfaaSmrg    if( src_w > drw_w )
1829ab47cfaaSmrg	OUTREG(SEC_STREAM_HSCALE_NORMALIZE, HSCALING_NORMALIZE(drw_w,src_w));
1830ab47cfaaSmrg    else
1831ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALE_NORMALIZE, (2048 << 16));
1832ab47cfaaSmrg
1833ab47cfaaSmrg    /* Calculate horizontal and vertical scale factors. */
1834ab47cfaaSmrg    if ((src_w > drw_w) || (src_h > drw_h))
1835ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALING, (HSCALING_2000(src_w,drw_w)) | 0x01000000);
1836ab47cfaaSmrg    else
1837ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALING, HSCALING_2000(src_w,drw_w));
1838ab47cfaaSmrg
1839ab47cfaaSmrg    OUTREG(SEC_STREAM_VSCALING, VSCALING_2000(src_h,drw_h));
1840ab47cfaaSmrg
1841ab47cfaaSmrg    /*
1842ab47cfaaSmrg     * Set surface location and stride.  We use x1>>15 because all surfaces
1843ab47cfaaSmrg     * are 2 bytes/pixel.
1844ab47cfaaSmrg     */
1845ab47cfaaSmrg
1846ab47cfaaSmrg    addr0 = offset + (x1>>15); /* Y in YCbCr420 */
18472b2b4fcbSmrg#if 0
1848ab47cfaaSmrg    addr1 = addr0 + (width * height); /* Cb in in YCbCr420 */
1849ab47cfaaSmrg    addr2 = addr1 + ((width * height) / 4); /* Cr in in YCbCr420 */
18502b2b4fcbSmrg#endif
1851ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR0, (addr0) & (0x3fffff & ~BASE_PAD));
1852ab47cfaaSmrg#if 0
1853ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR1, (addr1) & (0x3fffff & ~BASE_PAD));
1854ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR2, (addr2) & (0x3fffff & ~BASE_PAD));
1855ab47cfaaSmrg#endif
1856ab47cfaaSmrg
1857ab47cfaaSmrg    OUTREG(SEC_STREAM_WINDOW_START, XY_2000(dstBox->x1,dstBox->y1));
1858ab47cfaaSmrg    OUTREG(SEC_STREAM_WINDOW_SZ,
1859ab47cfaaSmrg	   WH_2000((dstBox->x2-dstBox->x1),(dstBox->y2-dstBox->y1)));
1860ab47cfaaSmrg
1861ab47cfaaSmrg    /*pitch = width * 2;*/
1862ab47cfaaSmrg    OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff);
1863ab47cfaaSmrg#if 0
1864ab47cfaaSmrg    /* Y stride + CbCr stride in YCbCr420 */
1865ab47cfaaSmrg    OUTREG(SEC_STREAM_STRIDE, (pitch & 0xfff) + ((pitch & 0xfff) << 15));
1866ab47cfaaSmrg#endif
1867ab47cfaaSmrg
1868ab47cfaaSmrg#if 0
1869ab47cfaaSmrg    /* Set color key on primary. */
1870ab47cfaaSmrg
1871ab47cfaaSmrg    SavageSetColorKey2000( pScrn );
1872ab47cfaaSmrg#endif
1873ab47cfaaSmrg
1874ab47cfaaSmrg#if 0
1875ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1876ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1877ab47cfaaSmrg    {
1878ab47cfaaSmrg	unsigned char cr92;
1879ab47cfaaSmrg
1880ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1881ab47cfaaSmrg	pitch = (pitch + 7) / 8 - 4;
1882ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1883ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1884ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1885ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1886ab47cfaaSmrg	VGAOUT8(vgaCRReg, pitch);
1887ab47cfaaSmrg    }
1888ab47cfaaSmrg#endif
1889ab47cfaaSmrg}
1890ab47cfaaSmrg
18911473d951Smrgstatic void
18921473d951SmrgSavageFillKeyHelper(DrawablePtr pDraw, uint32_t colorKey, RegionPtr clipBoxes)
18931473d951Smrg{
18941473d951Smrg#if HAVE_XV_DRAWABLE_HELPER
18951473d951Smrg    xf86XVFillKeyHelperDrawable(pDraw, colorKey, clipBoxes);
18961473d951Smrg#else
18971473d951Smrg    xf86XVFillKeyHelper(pDraw->pScreen, colorKey, clipBoxes);
18981473d951Smrg#endif
18991473d951Smrg}
19001473d951Smrg
1901ab47cfaaSmrgstatic int
1902ab47cfaaSmrgSavagePutImage(
1903ab47cfaaSmrg    ScrnInfoPtr pScrn,
1904ab47cfaaSmrg    short src_x, short src_y,
1905ab47cfaaSmrg    short drw_x, short drw_y,
1906ab47cfaaSmrg    short src_w, short src_h,
1907ab47cfaaSmrg    short drw_w, short drw_h,
1908ab47cfaaSmrg    int id, unsigned char* buf,
1909ab47cfaaSmrg    short width, short height,
1910ab47cfaaSmrg    Bool sync,
1911ab47cfaaSmrg    RegionPtr clipBoxes, pointer data,
1912ab47cfaaSmrg    DrawablePtr pDraw
1913ab47cfaaSmrg){
1914ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1915ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
19162b2b4fcbSmrg#ifdef SAVAGEDRI
1917ab47cfaaSmrg    ScreenPtr pScreen = pScrn->pScreen;
19182b2b4fcbSmrg#endif
1919ab47cfaaSmrg    INT32 x1, x2, y1, y2;
1920ab47cfaaSmrg    unsigned char *dst_start;
19212b2b4fcbSmrg    int new_size, offset, offsetV=0, offsetU=0;
1922ab47cfaaSmrg    int srcPitch, srcPitch2=0, dstPitch;
19231473d951Smrg    int planarFrameSize;
1924ab47cfaaSmrg    int top, left, npixels, nlines;
1925ab47cfaaSmrg    BoxRec dstBox;
1926ab47cfaaSmrg    CARD32 tmp;
1927ab47cfaaSmrg/*    xf86ErrorFVerb(XVTRACE,"SavagePutImage\n"); */
1928ab47cfaaSmrg    if(drw_w > 16384) drw_w = 16384;
1929ab47cfaaSmrg
1930ab47cfaaSmrg    /* Clip */
1931ab47cfaaSmrg    x1 = src_x;
1932ab47cfaaSmrg    x2 = src_x + src_w;
1933ab47cfaaSmrg    y1 = src_y;
1934ab47cfaaSmrg    y2 = src_y + src_h;
1935ab47cfaaSmrg
1936ab47cfaaSmrg    dstBox.x1 = drw_x;
1937ab47cfaaSmrg    dstBox.x2 = drw_x + drw_w;
1938ab47cfaaSmrg    dstBox.y1 = drw_y;
1939ab47cfaaSmrg    dstBox.y2 = drw_y + drw_h;
1940ab47cfaaSmrg
1941ab47cfaaSmrg    SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
1942ab47cfaaSmrg		REGION_EXTENTS(pScreen, clipBoxes), width, height);
1943ab47cfaaSmrg
1944ab47cfaaSmrg    drw_w = dstBox.x2 - dstBox.x1;
1945ab47cfaaSmrg    drw_h = dstBox.y2 - dstBox.y1;
1946ab47cfaaSmrg    src_w = ( x2 - x1 ) >> 16;
1947ab47cfaaSmrg    src_h = ( y2 - y1 ) >> 16;
1948ab47cfaaSmrg
1949ab47cfaaSmrg    if((x1 >= x2) || (y1 >= y2))
1950ab47cfaaSmrg	return Success;
1951ab47cfaaSmrg
1952ab47cfaaSmrg    dstBox.x1 -= pScrn->frameX0;
1953ab47cfaaSmrg    dstBox.x2 -= pScrn->frameX0;
1954ab47cfaaSmrg    dstBox.y1 -= pScrn->frameY0;
1955ab47cfaaSmrg    dstBox.y2 -= pScrn->frameY0;
1956ab47cfaaSmrg
19571473d951Smrg    /* All formats directly displayable by Savage are packed and 2 bytes per pixel */
1958ab47cfaaSmrg    dstPitch = ((width << 1) + 15) & ~15;
1959ab47cfaaSmrg    new_size = dstPitch * height;
1960ab47cfaaSmrg
1961ab47cfaaSmrg    switch(id) {
1962ab47cfaaSmrg    case FOURCC_Y211:		/* Y211 */
1963ab47cfaaSmrg        srcPitch = width;
1964ab47cfaaSmrg	break;
1965ab47cfaaSmrg    case FOURCC_YV12:		/* YV12 */
1966ab47cfaaSmrg	srcPitch = (width + 3) & ~3;
1967ab47cfaaSmrg	offsetV = srcPitch * height;
1968ab47cfaaSmrg	srcPitch2 = ((width >> 1) + 3) & ~3;
1969ab47cfaaSmrg	offsetU = (srcPitch2 * (height >> 1)) + offsetV;
1970ab47cfaaSmrg	break;
1971ab47cfaaSmrg    case FOURCC_I420:
1972ab47cfaaSmrg	srcPitch = (width + 3) & ~3;
1973ab47cfaaSmrg	offsetU = srcPitch * height;
1974ab47cfaaSmrg	srcPitch2 = ((width >> 1) + 3) & ~3;
1975ab47cfaaSmrg	offsetV = (srcPitch2 * (height >> 1)) + offsetU;
1976ab47cfaaSmrg	break;
1977ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
1978ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
1979ab47cfaaSmrg    case FOURCC_YUY2:		/* YUY2 */
1980ab47cfaaSmrg    default:
1981ab47cfaaSmrg	srcPitch = (width << 1);
1982ab47cfaaSmrg	break;
1983ab47cfaaSmrg    }
1984ab47cfaaSmrg
19851473d951Smrg    /* Calculate required memory for all planar frames */
19861473d951Smrg    planarFrameSize = 0;
19878697ee19Smrg    if (srcPitch2 != 0 && S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv) {
19881473d951Smrg        new_size = ((new_size + 0xF) & ~0xF);
19891473d951Smrg        planarFrameSize = srcPitch * height + srcPitch2 * height;
19901473d951Smrg    }
19911473d951Smrg
19921473d951Smrg    /* Check whether AGP buffers can be allocated. If not, fall back to ordinary
19931473d951Smrg       upload to framebuffer (slower) */
1994aa9e3350Smrg#ifdef SAVAGEDRI
19951473d951Smrg    if (!pPriv->tried_agp && !psav->IsPCI && psav->drmFD > 0 && psav->DRIServerInfo != NULL) {
19961473d951Smrg	SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
19971473d951Smrg
19981473d951Smrg	pPriv->tried_agp = TRUE;
19991473d951Smrg	if (pSAVAGEDRIServer->agpXVideo.size >= max(new_size, planarFrameSize)) {
20001473d951Smrg	    if (pSAVAGEDRIServer->agpXVideo.map == NULL &&
20011473d951Smrg	        drmMap( psav->drmFD,
20021473d951Smrg		pSAVAGEDRIServer->agpXVideo.handle,
20031473d951Smrg		pSAVAGEDRIServer->agpXVideo.size,
20041473d951Smrg		&pSAVAGEDRIServer->agpXVideo.map ) < 0 ) {
20051473d951Smrg
20061473d951Smrg		xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] XVideo: Could not map agpXVideo \n" );
20071473d951Smrg		pPriv->agpBufferOffset = 0;
20081473d951Smrg		pPriv->agpBufferMap = NULL;
20091473d951Smrg	    } else {
20101473d951Smrg		pPriv->agpBufferMap = pSAVAGEDRIServer->agpXVideo.map;
20111473d951Smrg		pPriv->agpBufferOffset = pSAVAGEDRIServer->agpXVideo.offset;
20121473d951Smrg		pPriv->agpBase = drmAgpBase(psav->drmFD);
20131473d951Smrg#if 0
20141473d951Smrg		xf86DrvMsg( pScreen->myNum, X_INFO,
20151473d951Smrg		       "[agp] agpXVideo mapped at 0x%08lx aperture=0x%08x offset=0x%08lx\n",
20161473d951Smrg		       (unsigned long)pPriv->agpBufferMap, pPriv->agpBase, pPriv->agpBufferOffset);
20171473d951Smrg#endif
20181473d951Smrg	    }
20191473d951Smrg	} else {
20201473d951Smrg	    /* This situation is expected if AGPforXv is disabled, otherwise report. */
20211473d951Smrg	    if (pSAVAGEDRIServer->agpXVideo.size > 0) {
20221473d951Smrg		xf86DrvMsg( pScreen->myNum, X_ERROR,
2023aa9e3350Smrg		    "[agp] XVideo: not enough space in buffer (got %ld bytes, required %d bytes).\n",
2024aa9e3350Smrg	    	    (long int)pSAVAGEDRIServer->agpXVideo.size, max(new_size, planarFrameSize));
20251473d951Smrg	    }
20261473d951Smrg	    pPriv->agpBufferMap = NULL;
20271473d951Smrg	    pPriv->agpBufferOffset = 0;
20281473d951Smrg	}
20298697ee19Smrg    }
2030aa9e3350Smrg#endif /* SAVAGEDRI */
20318697ee19Smrg
20321473d951Smrg
20331473d951Smrg    /* Buffer for final packed frame */
20341473d951Smrg    pPriv->video_offset = SavageAllocateMemory(
20351473d951Smrg	pScrn, &pPriv->video_memory,
20361473d951Smrg	new_size);
2037ab47cfaaSmrg    if (pPriv->video_offset == 0)
2038ab47cfaaSmrg        return BadAlloc;
2039ab47cfaaSmrg
20401473d951Smrg    /* Packed format cases */
20411473d951Smrg    if (planarFrameSize == 0) {
20421473d951Smrg	pPriv->video_planarbuf = 0;
20431473d951Smrg
20441473d951Smrg    /* Planar format cases */
20451473d951Smrg    } else {
20461473d951Smrg	/* Hardware-assisted planar conversion only works on 16-byte aligned addresses */
20471473d951Smrg	pPriv->video_planarbuf = SavageAllocateMemory(
20481473d951Smrg	    pScrn, &pPriv->video_planarmem,
20491473d951Smrg	    ((planarFrameSize + 0xF) & ~0xF));
20501473d951Smrg	if (pPriv->video_planarbuf != 0) {
20511473d951Smrg	    /* TODO: stop any pending conversions when buffers change... */
20521473d951Smrg	    pPriv->video_planarbuf = ((pPriv->video_planarbuf + 0xF) & ~0xF);
20531473d951Smrg	} else {
20541473d951Smrg	    /* Fallback using software conversion */
20551473d951Smrg	}
20561473d951Smrg    }
20571473d951Smrg
2058ab47cfaaSmrg    /* copy data */
2059ab47cfaaSmrg    top = y1 >> 16;
2060ab47cfaaSmrg    left = (x1 >> 16) & ~1;
2061ab47cfaaSmrg    npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
2062ab47cfaaSmrg    left <<= 1;
2063ab47cfaaSmrg
2064ab47cfaaSmrg    offset = (pPriv->video_offset) + (top * dstPitch);
2065ab47cfaaSmrg    dst_start = (psav->FBBase + ((offset + left) & ~BASE_PAD));
2066ab47cfaaSmrg
2067ab47cfaaSmrg    switch(id) {
2068ab47cfaaSmrg    case FOURCC_YV12:		/* YV12 */
2069ab47cfaaSmrg    case FOURCC_I420:
2070ab47cfaaSmrg	top &= ~1;
2071ab47cfaaSmrg	tmp = ((top >> 1) * srcPitch2) + (left >> 2);
2072ab47cfaaSmrg	offsetU += tmp;
2073ab47cfaaSmrg	offsetV += tmp;
2074ab47cfaaSmrg	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
20751473d951Smrg        if (S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv && (npixels & 0xF) == 0 && pPriv->video_planarbuf != 0) {
2076aa9e3350Smrg#ifdef SAVAGEDRI
20771473d951Smrg            if (pPriv->agpBufferMap != NULL) {
20781473d951Smrg		/* Using copy to AGP memory */
20791473d951Smrg		SavageCopyPlanarDataBCI(
20801473d951Smrg		    pScrn,
20811473d951Smrg		    buf + (top * srcPitch) + (left >> 1),
20821473d951Smrg		    buf + offsetV,
20831473d951Smrg		    buf + offsetU,
20841473d951Smrg		    dst_start,
20851473d951Smrg		    pPriv->agpBufferMap,
20861473d951Smrg		    pPriv->agpBase + pPriv->agpBufferOffset,
20871473d951Smrg		    srcPitch, srcPitch2, dstPitch, nlines, npixels, TRUE);
20886aec45a7Smrg            } else
2089aa9e3350Smrg#endif /* SAVAGEDRI */
20906aec45a7Smrg            {
20911473d951Smrg		/* Using ordinary copy to framebuffer */
20921473d951Smrg		SavageCopyPlanarDataBCI(
20931473d951Smrg		    pScrn,
20941473d951Smrg		    buf + (top * srcPitch) + (left >> 1),
20951473d951Smrg		    buf + offsetV,
20961473d951Smrg		    buf + offsetU,
20971473d951Smrg		    dst_start,
20981473d951Smrg		    (unsigned char *)psav->FBBase + pPriv->video_planarbuf,
20991473d951Smrg		    pPriv->video_planarbuf,
21001473d951Smrg		    srcPitch, srcPitch2, dstPitch, nlines, npixels, FALSE);
21011473d951Smrg	    }
2102ab47cfaaSmrg        } else {
2103ab47cfaaSmrg	    SavageCopyPlanarData(
2104ab47cfaaSmrg	    	buf + (top * srcPitch) + (left >> 1),
2105ab47cfaaSmrg	    	buf + offsetV,
2106ab47cfaaSmrg	    	buf + offsetU,
2107ab47cfaaSmrg	    	dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels);
2108ab47cfaaSmrg        }
2109ab47cfaaSmrg	break;
2110ab47cfaaSmrg    case FOURCC_Y211:		/* Y211 */
2111ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
2112ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
2113ab47cfaaSmrg    case FOURCC_YUY2:		/* YUY2 */
2114ab47cfaaSmrg    default:
2115ab47cfaaSmrg	buf += (top * srcPitch) + left;
2116ab47cfaaSmrg	nlines = ((y2 + 0xffff) >> 16) - top;
2117ab47cfaaSmrg	SavageCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
2118ab47cfaaSmrg	break;
2119ab47cfaaSmrg    }
2120ab47cfaaSmrg
2121ab47cfaaSmrg    /* We need to enable the video before we draw the chroma color.
2122ab47cfaaSmrg       Otherwise, we get blue flashes. */
2123ab47cfaaSmrg
2124ab47cfaaSmrg    SavageDisplayVideo(pScrn, id, offset, width, height, dstPitch,
2125ab47cfaaSmrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
2126ab47cfaaSmrg
2127ab47cfaaSmrg    /* update cliplist */
2128ab47cfaaSmrg    if(!REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes)) {
2129ab47cfaaSmrg	REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
2130ab47cfaaSmrg	/* draw these */
21311473d951Smrg	SavageFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes);
2132ab47cfaaSmrg
2133ab47cfaaSmrg    }
2134ab47cfaaSmrg
2135ab47cfaaSmrg    pPriv->videoStatus = CLIENT_VIDEO_ON;
2136ab47cfaaSmrg
2137ab47cfaaSmrg    return Success;
2138ab47cfaaSmrg}
2139ab47cfaaSmrg
2140ab47cfaaSmrgstatic int
2141ab47cfaaSmrgSavageQueryImageAttributes(
2142ab47cfaaSmrg  ScrnInfoPtr pScrn,
2143ab47cfaaSmrg  int id,
2144ab47cfaaSmrg  unsigned short *w, unsigned short *h,
2145ab47cfaaSmrg  int *pitches, int *offsets
2146ab47cfaaSmrg){
2147ab47cfaaSmrg    int size, tmp;
2148ab47cfaaSmrg
2149ab47cfaaSmrg    if(*w > 1024) *w = 1024;
2150ab47cfaaSmrg    if(*h > 1024) *h = 1024;
2151ab47cfaaSmrg
2152ab47cfaaSmrg    *w = (*w + 1) & ~1;
2153ab47cfaaSmrg    if(offsets) offsets[0] = 0;
2154ab47cfaaSmrg
2155ab47cfaaSmrg    switch(id) {
2156ab47cfaaSmrg    case FOURCC_IA44:
2157ab47cfaaSmrg        if (pitches) pitches[0]=*w;
2158ab47cfaaSmrg        size=(*w)*(*h);
2159ab47cfaaSmrg        break;
2160ab47cfaaSmrg    case FOURCC_Y211:
2161ab47cfaaSmrg	size = *w << 2;
2162ab47cfaaSmrg	if(pitches) pitches[0] = size;
2163ab47cfaaSmrg	size *= *h;
2164ab47cfaaSmrg	break;
2165ab47cfaaSmrg    case FOURCC_YV12:
2166ab47cfaaSmrg    case FOURCC_I420:
2167ab47cfaaSmrg	*h = (*h + 1) & ~1;
2168ab47cfaaSmrg	size = (*w + 3) & ~3;
2169ab47cfaaSmrg	if(pitches) pitches[0] = size;
2170ab47cfaaSmrg	size *= *h;
2171ab47cfaaSmrg	if(offsets) offsets[1] = size;
2172ab47cfaaSmrg	tmp = ((*w >> 1) + 3) & ~3;
2173ab47cfaaSmrg	if(pitches) pitches[1] = pitches[2] = tmp;
2174ab47cfaaSmrg	tmp *= (*h >> 1);
2175ab47cfaaSmrg	size += tmp;
2176ab47cfaaSmrg	if(offsets) offsets[2] = size;
2177ab47cfaaSmrg	size += tmp;
2178ab47cfaaSmrg	break;
2179ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
2180ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
2181ab47cfaaSmrg    case FOURCC_YUY2:
2182ab47cfaaSmrg    default:
2183ab47cfaaSmrg	size = *w << 1;
2184ab47cfaaSmrg	if(pitches) pitches[0] = size;
2185ab47cfaaSmrg	size *= *h;
2186ab47cfaaSmrg	break;
2187ab47cfaaSmrg    }
2188ab47cfaaSmrg
2189ab47cfaaSmrg    return size;
2190ab47cfaaSmrg}
2191ab47cfaaSmrg
2192ab47cfaaSmrg/****************** Offscreen stuff ***************/
2193ab47cfaaSmrg
2194ab47cfaaSmrgtypedef struct {
2195ab47cfaaSmrg  void *surface_memory;
2196ab47cfaaSmrg  Bool isOn;
2197ab47cfaaSmrg} OffscreenPrivRec, * OffscreenPrivPtr;
2198ab47cfaaSmrg
2199ab47cfaaSmrgstatic int
2200ab47cfaaSmrgSavageAllocateSurface(
2201ab47cfaaSmrg    ScrnInfoPtr pScrn,
2202ab47cfaaSmrg    int id,
2203ab47cfaaSmrg    unsigned short w,
2204ab47cfaaSmrg    unsigned short h,
2205ab47cfaaSmrg    XF86SurfacePtr surface
2206ab47cfaaSmrg){
2207ab47cfaaSmrg    int offset, size;
22082b2b4fcbSmrg    int pitch;
2209ab47cfaaSmrg    void *surface_memory = NULL;
2210ab47cfaaSmrg    OffscreenPrivPtr pPriv;
2211ab47cfaaSmrg
2212ab47cfaaSmrg    if((w > 1024) || (h > 1024))
2213ab47cfaaSmrg	return BadAlloc;
2214ab47cfaaSmrg
2215ab47cfaaSmrg    w = (w + 1) & ~1;
2216ab47cfaaSmrg    pitch = ((w << 1) + 15) & ~15;
2217ab47cfaaSmrg    size = pitch * h;
2218ab47cfaaSmrg
2219ab47cfaaSmrg    offset = SavageAllocateMemory(pScrn, &surface_memory, size);
2220ab47cfaaSmrg    if (offset == 0)
2221ab47cfaaSmrg	return BadAlloc;
2222ab47cfaaSmrg
2223ab47cfaaSmrg    surface->width = w;
2224ab47cfaaSmrg    surface->height = h;
2225ab47cfaaSmrg
2226aa9e3350Smrg    if(!(surface->pitches = malloc(sizeof(int)))) {
2227ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2228ab47cfaaSmrg	return BadAlloc;
2229ab47cfaaSmrg    }
2230aa9e3350Smrg    if(!(surface->offsets = malloc(sizeof(int)))) {
2231aa9e3350Smrg	free(surface->pitches);
2232ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2233ab47cfaaSmrg	return BadAlloc;
2234ab47cfaaSmrg    }
2235aa9e3350Smrg    if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
2236aa9e3350Smrg	free(surface->pitches);
2237aa9e3350Smrg	free(surface->offsets);
2238ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2239ab47cfaaSmrg	return BadAlloc;
2240ab47cfaaSmrg    }
2241ab47cfaaSmrg
2242ab47cfaaSmrg    pPriv->surface_memory = surface_memory;
2243ab47cfaaSmrg    pPriv->isOn = FALSE;
2244ab47cfaaSmrg
2245ab47cfaaSmrg    surface->pScrn = pScrn;
2246ab47cfaaSmrg    surface->id = id;
2247ab47cfaaSmrg    surface->pitches[0] = pitch;
2248ab47cfaaSmrg    surface->offsets[0] = offset; /*area->box.y1 * fbpitch;*/
2249ab47cfaaSmrg    surface->devPrivate.ptr = (pointer)pPriv;
2250ab47cfaaSmrg
2251ab47cfaaSmrg    return Success;
2252ab47cfaaSmrg}
2253ab47cfaaSmrg
2254ab47cfaaSmrgstatic int
2255ab47cfaaSmrgSavageStopSurface(
2256ab47cfaaSmrg    XF86SurfacePtr surface
2257ab47cfaaSmrg){
2258ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2259ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageStopSurface\n");
2260ab47cfaaSmrg
2261ab47cfaaSmrg    if(pPriv->isOn) {
2262ab47cfaaSmrg	/*SavagePtr psav = SAVPTR(surface->pScrn);*/
2263ab47cfaaSmrg	/*SavageClipVWindow(surface->pScrn);*/
2264ab47cfaaSmrg	SavageStreamsOff( surface->pScrn );
2265ab47cfaaSmrg	pPriv->isOn = FALSE;
2266ab47cfaaSmrg    }
2267ab47cfaaSmrg
2268ab47cfaaSmrg    return Success;
2269ab47cfaaSmrg}
2270ab47cfaaSmrg
2271ab47cfaaSmrg
2272ab47cfaaSmrgstatic int
2273ab47cfaaSmrgSavageFreeSurface(
2274ab47cfaaSmrg    XF86SurfacePtr surface
2275ab47cfaaSmrg){
2276ab47cfaaSmrg    ScrnInfoPtr pScrn = surface->pScrn;
2277ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2278ab47cfaaSmrg
2279ab47cfaaSmrg    if(pPriv->isOn)
2280ab47cfaaSmrg	SavageStopSurface(surface);
2281ab47cfaaSmrg    SavageFreeMemory(pScrn, pPriv->surface_memory);
2282aa9e3350Smrg    free(surface->pitches);
2283aa9e3350Smrg    free(surface->offsets);
2284aa9e3350Smrg    free(surface->devPrivate.ptr);
2285ab47cfaaSmrg
2286ab47cfaaSmrg    return Success;
2287ab47cfaaSmrg}
2288ab47cfaaSmrg
2289ab47cfaaSmrgstatic int
2290ab47cfaaSmrgSavageGetSurfaceAttribute(
2291ab47cfaaSmrg    ScrnInfoPtr pScrn,
2292ab47cfaaSmrg    Atom attribute,
2293ab47cfaaSmrg    INT32 *value
2294ab47cfaaSmrg){
2295ab47cfaaSmrg    return SavageGetPortAttribute(pScrn, attribute, value,
2296ab47cfaaSmrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
2297ab47cfaaSmrg}
2298ab47cfaaSmrg
2299ab47cfaaSmrgstatic int
2300ab47cfaaSmrgSavageSetSurfaceAttribute(
2301ab47cfaaSmrg    ScrnInfoPtr pScrn,
2302ab47cfaaSmrg    Atom attribute,
2303ab47cfaaSmrg    INT32 value
2304ab47cfaaSmrg){
2305ab47cfaaSmrg    return SavageSetPortAttribute(pScrn, attribute, value,
2306ab47cfaaSmrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
2307ab47cfaaSmrg}
2308ab47cfaaSmrg
2309ab47cfaaSmrg
2310ab47cfaaSmrgstatic int
2311ab47cfaaSmrgSavageDisplaySurface(
2312ab47cfaaSmrg    XF86SurfacePtr surface,
2313ab47cfaaSmrg    short src_x, short src_y,
2314ab47cfaaSmrg    short drw_x, short drw_y,
2315ab47cfaaSmrg    short src_w, short src_h,
2316ab47cfaaSmrg    short drw_w, short drw_h,
2317ab47cfaaSmrg    RegionPtr clipBoxes
2318ab47cfaaSmrg){
2319ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2320ab47cfaaSmrg    ScrnInfoPtr pScrn = surface->pScrn;
2321ab47cfaaSmrg    ScreenPtr pScreen = pScrn->pScreen;
2322ab47cfaaSmrg    SavagePortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn);
2323ab47cfaaSmrg    INT32 x1, y1, x2, y2;
2324ab47cfaaSmrg    BoxRec dstBox;
2325ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageDisplaySurface\n");
2326ab47cfaaSmrg
2327ab47cfaaSmrg    x1 = src_x;
2328ab47cfaaSmrg    x2 = src_x + src_w;
2329ab47cfaaSmrg    y1 = src_y;
2330ab47cfaaSmrg    y2 = src_y + src_h;
2331ab47cfaaSmrg
2332ab47cfaaSmrg    dstBox.x1 = drw_x;
2333ab47cfaaSmrg    dstBox.x2 = drw_x + drw_w;
2334ab47cfaaSmrg    dstBox.y1 = drw_y;
2335ab47cfaaSmrg    dstBox.y2 = drw_y + drw_h;
2336ab47cfaaSmrg
2337ab47cfaaSmrg    SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
2338ab47cfaaSmrg                	REGION_EXTENTS(pScreen, clipBoxes),
2339ab47cfaaSmrg			surface->width, surface->height);
2340ab47cfaaSmrg
2341ab47cfaaSmrg    if((x1 >= x2) || (y1 >= y2))
2342ab47cfaaSmrg	return Success;
2343ab47cfaaSmrg
2344ab47cfaaSmrg    dstBox.x1 -= pScrn->frameX0;
2345ab47cfaaSmrg    dstBox.x2 -= pScrn->frameX0;
2346ab47cfaaSmrg    dstBox.y1 -= pScrn->frameY0;
2347ab47cfaaSmrg    dstBox.y2 -= pScrn->frameY0;
2348ab47cfaaSmrg
2349ab47cfaaSmrg    SavageDisplayVideo(pScrn, surface->id, surface->offsets[0],
2350ab47cfaaSmrg	     surface->width, surface->height, surface->pitches[0],
2351ab47cfaaSmrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
2352ab47cfaaSmrg
2353aa9e3350Smrg    xf86XVFillKeyHelper(pScreen, portPriv->colorKey, clipBoxes);
2354ab47cfaaSmrg
2355ab47cfaaSmrg    pPriv->isOn = TRUE;
2356ab47cfaaSmrg#if 0
2357ab47cfaaSmrg    if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
2358ab47cfaaSmrg	REGION_EMPTY(pScreen, &portPriv->clip);
2359ab47cfaaSmrg	UpdateCurrentTime();
2360ab47cfaaSmrg	portPriv->videoStatus = FREE_TIMER;
2361ab47cfaaSmrg	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
2362ab47cfaaSmrg    }
2363ab47cfaaSmrg#endif
2364ab47cfaaSmrg
2365ab47cfaaSmrg    return Success;
2366ab47cfaaSmrg}
2367ab47cfaaSmrg
2368ab47cfaaSmrg
2369ab47cfaaSmrgstatic void
2370ab47cfaaSmrgSavageInitOffscreenImages(ScreenPtr pScreen)
2371ab47cfaaSmrg{
2372ab47cfaaSmrg    XF86OffscreenImagePtr offscreenImages;
2373aa9e3350Smrg    SavagePtr psav = SAVPTR(xf86ScreenToScrn(pScreen));
2374ab47cfaaSmrg
2375ab47cfaaSmrg    /* need to free this someplace */
2376ab47cfaaSmrg    if (!psav->offscreenImages) {
2377aa9e3350Smrg	if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec))))
2378ab47cfaaSmrg	    return;
2379ab47cfaaSmrg	psav->offscreenImages = offscreenImages;
2380ab47cfaaSmrg    } else {
2381ab47cfaaSmrg	offscreenImages = psav->offscreenImages;
2382ab47cfaaSmrg    }
2383ab47cfaaSmrg
2384ab47cfaaSmrg    offscreenImages[0].image = &Images[0];
2385ab47cfaaSmrg    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
2386ab47cfaaSmrg			       VIDEO_CLIP_TO_VIEWPORT;
2387ab47cfaaSmrg    offscreenImages[0].alloc_surface = SavageAllocateSurface;
2388ab47cfaaSmrg    offscreenImages[0].free_surface = SavageFreeSurface;
2389ab47cfaaSmrg    offscreenImages[0].display = SavageDisplaySurface;
2390ab47cfaaSmrg    offscreenImages[0].stop = SavageStopSurface;
2391ab47cfaaSmrg    offscreenImages[0].setAttribute = SavageSetSurfaceAttribute;
2392ab47cfaaSmrg    offscreenImages[0].getAttribute = SavageGetSurfaceAttribute;
2393ab47cfaaSmrg    offscreenImages[0].max_width = 1024;
2394ab47cfaaSmrg    offscreenImages[0].max_height = 1024;
2395ab47cfaaSmrg    offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
2396ab47cfaaSmrg    offscreenImages[0].attributes = Attributes;
2397ab47cfaaSmrg
2398ab47cfaaSmrg    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
2399ab47cfaaSmrg}
2400ab47cfaaSmrg
2401