savage_video.c revision aa9e3350
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,",
307ab47cfaaSmrg	offset, (CARD32)MMIO_IN32( psav->MapBase, offset ), value );
308ab47cfaaSmrg    MMIO_OUT32( psav->MapBase, offset, value );
309ab47cfaaSmrg    ErrorF( " now %08lx\n", (CARD32)MMIO_IN32( psav->MapBase, offset ) );
310ab47cfaaSmrg}
311ab47cfaaSmrg
312ab47cfaaSmrg#if 0
313ab47cfaaSmrgstatic void
314ab47cfaaSmrgSavageClipVWindow(ScrnInfoPtr pScrn)
315ab47cfaaSmrg{
316ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
317ab47cfaaSmrg
318ab47cfaaSmrg    if( (psav->Chipset == S3_SAVAGE_MX)  ||
319ab47cfaaSmrg	(psav->Chipset == S3_SUPERSAVAGE) ) {
320ab47cfaaSmrg	if (psav->IsSecondary) {
321ab47cfaaSmrg	    OUTREG(SEC_STREAM2_WINDOW_SZ, 0);
322ab47cfaaSmrg	} else if (psav->IsPrimary) {
323ab47cfaaSmrg	    OUTREG(SEC_STREAM_WINDOW_SZ, 0);
324ab47cfaaSmrg	} else {
325ab47cfaaSmrg	    OUTREG(SEC_STREAM_WINDOW_SZ, 0);
326ab47cfaaSmrg#if 0
327ab47cfaaSmrg	    OUTREG(SEC_STREAM2_WINDOW_SZ, 0);
328ab47cfaaSmrg#endif
329ab47cfaaSmrg  	}
330ab47cfaaSmrg    } else if (psav->Chipset == S3_SAVAGE2000) {
331ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_SZ, 0);
332ab47cfaaSmrg    } else {
333ab47cfaaSmrg	OUTREG( SSTREAM_WINDOW_SIZE_REG, 1);
334ab47cfaaSmrg	OUTREG( SSTREAM_WINDOW_START_REG, 0x03ff03ff);
335ab47cfaaSmrg    }
336ab47cfaaSmrg}
337ab47cfaaSmrg#endif
338ab47cfaaSmrg
339ab47cfaaSmrgvoid SavageInitVideo(ScreenPtr pScreen)
340ab47cfaaSmrg{
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;
10401473d951Smrg    SavagePtr psav = SAVPTR(pScrn);
1041ab47cfaaSmrg
1042ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageStopVideo\n");
1043ab47cfaaSmrg
1044ab47cfaaSmrg    REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1045ab47cfaaSmrg
1046ab47cfaaSmrg    if(shutdown) {
1047ab47cfaaSmrg      /*SavageClipVWindow(pScrn);*/
1048ab47cfaaSmrg 	SavageStreamsOff( pScrn );
10491473d951Smrg
1050aa9e3350Smrg#ifdef SAVAGEDRI
10511473d951Smrg	if (pPriv->agpBufferMap != NULL) {
10521473d951Smrg	    SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
10531473d951Smrg
10541473d951Smrg            /* agpXVideo is reused to implement UploadToScreen in EXA */
10551473d951Smrg            if (!psav->useEXA) {
10561473d951Smrg	        drmUnmap(pPriv->agpBufferMap, pSAVAGEDRIServer->agpXVideo.size);
10571473d951Smrg	        pSAVAGEDRIServer->agpXVideo.map = NULL;
10581473d951Smrg            }
10591473d951Smrg	    pPriv->agpBufferMap = NULL;
10601473d951Smrg	    pPriv->agpBufferOffset = 0;
10611473d951Smrg	}
10626aec45a7Smrg	pPriv->tried_agp = FALSE;
10636aec45a7Smrg#endif
10641473d951Smrg
1065ab47cfaaSmrg        if (pPriv->video_memory != NULL) {
1066ab47cfaaSmrg	    SavageFreeMemory(pScrn, pPriv->video_memory);
1067ab47cfaaSmrg	    pPriv->video_memory = NULL;
1068ab47cfaaSmrg        }
10691473d951Smrg        if (pPriv->video_planarmem != NULL) {
10701473d951Smrg	    SavageFreeMemory(pScrn, pPriv->video_planarmem);
10711473d951Smrg	    pPriv->video_planarmem = NULL;
10721473d951Smrg        }
1073ab47cfaaSmrg	pPriv->videoStatus = 0;
1074ab47cfaaSmrg    } else {
1075ab47cfaaSmrg	if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
1076ab47cfaaSmrg	    pPriv->videoStatus |= OFF_TIMER;
1077ab47cfaaSmrg	    pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
1078ab47cfaaSmrg	}
1079ab47cfaaSmrg    }
1080ab47cfaaSmrg}
1081ab47cfaaSmrg
1082ab47cfaaSmrg
1083ab47cfaaSmrgstatic int
1084ab47cfaaSmrgSavageSetPortAttribute(
1085ab47cfaaSmrg    ScrnInfoPtr pScrn,
1086ab47cfaaSmrg    Atom attribute,
1087ab47cfaaSmrg    INT32 value,
1088ab47cfaaSmrg    pointer data
1089ab47cfaaSmrg){
1090ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1091ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1092ab47cfaaSmrg
1093ab47cfaaSmrg    if(attribute == xvColorKey) {
1094ab47cfaaSmrg	pPriv->colorKey = value;
1095ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1096ab47cfaaSmrg	    SavageSetColorKey( pScrn );
1097ab47cfaaSmrg	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1098ab47cfaaSmrg    }
1099ab47cfaaSmrg    else if( attribute == xvBrightness) {
1100ab47cfaaSmrg	if((value < -128) || (value > 127))
1101ab47cfaaSmrg	    return BadValue;
1102ab47cfaaSmrg	pPriv->brightness = value;
1103ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1104ab47cfaaSmrg	    SavageSetColor( pScrn );
1105ab47cfaaSmrg    }
1106ab47cfaaSmrg    else if( attribute == xvContrast) {
1107ab47cfaaSmrg	if((value < 0) || (value > 255))
1108ab47cfaaSmrg	    return BadValue;
1109ab47cfaaSmrg	pPriv->contrast = value;
1110ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1111ab47cfaaSmrg	    SavageSetColor( pScrn );
1112ab47cfaaSmrg    }
1113ab47cfaaSmrg    else if( attribute == xvSaturation) {
1114ab47cfaaSmrg	if((value < 0) || (value > 255))
1115ab47cfaaSmrg	    return BadValue;
1116ab47cfaaSmrg	pPriv->saturation = value;
1117ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1118ab47cfaaSmrg	    SavageSetColor( pScrn );
1119ab47cfaaSmrg    }
1120ab47cfaaSmrg    else if( attribute == xvHue) {
1121ab47cfaaSmrg	if((value < -180) || (value > 180))
1122ab47cfaaSmrg	    return BadValue;
1123ab47cfaaSmrg	pPriv->hue = value;
1124ab47cfaaSmrg	if( psav->videoFlags & VF_STREAMS_ON)
1125ab47cfaaSmrg	    SavageSetColor( pScrn );
1126ab47cfaaSmrg    }
1127ab47cfaaSmrg    else if( attribute == xvInterpolation) {
1128ab47cfaaSmrg        if((value < 0) || (value > 1))
1129ab47cfaaSmrg            return BadValue;
1130ab47cfaaSmrg        if (value == 1)
1131ab47cfaaSmrg            pPriv->interpolation = TRUE;
1132ab47cfaaSmrg	else
1133ab47cfaaSmrg	    pPriv->interpolation = FALSE;
1134ab47cfaaSmrg    }
1135ab47cfaaSmrg    else
1136ab47cfaaSmrg	return BadMatch;
1137ab47cfaaSmrg
1138ab47cfaaSmrg    return Success;
1139ab47cfaaSmrg}
1140ab47cfaaSmrg
1141ab47cfaaSmrg
1142ab47cfaaSmrgstatic int
1143ab47cfaaSmrgSavageGetPortAttribute(
1144ab47cfaaSmrg  ScrnInfoPtr pScrn,
1145ab47cfaaSmrg  Atom attribute,
1146ab47cfaaSmrg  INT32 *value,
1147ab47cfaaSmrg  pointer data
1148ab47cfaaSmrg){
1149ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1150ab47cfaaSmrg
1151ab47cfaaSmrg    if(attribute == xvColorKey) {
1152ab47cfaaSmrg	*value = pPriv->colorKey;
1153ab47cfaaSmrg    }
1154ab47cfaaSmrg    else if( attribute == xvBrightness ) {
1155ab47cfaaSmrg	*value = pPriv->brightness;
1156ab47cfaaSmrg    }
1157ab47cfaaSmrg    else if( attribute == xvContrast ) {
1158ab47cfaaSmrg	*value = pPriv->contrast;
1159ab47cfaaSmrg    }
1160ab47cfaaSmrg    else if( attribute == xvHue ) {
1161ab47cfaaSmrg	*value = pPriv->hue;
1162ab47cfaaSmrg    }
1163ab47cfaaSmrg    else if( attribute == xvSaturation ) {
1164ab47cfaaSmrg	*value = pPriv->saturation;
1165ab47cfaaSmrg    }
1166ab47cfaaSmrg    else if( attribute == xvInterpolation ) {
1167ab47cfaaSmrg        *value = pPriv->interpolation;
1168ab47cfaaSmrg    }
1169ab47cfaaSmrg    else return BadMatch;
1170ab47cfaaSmrg
1171ab47cfaaSmrg    return Success;
1172ab47cfaaSmrg}
1173ab47cfaaSmrg
1174ab47cfaaSmrgstatic void
1175ab47cfaaSmrgSavageQueryBestSize(
1176ab47cfaaSmrg  ScrnInfoPtr pScrn,
1177ab47cfaaSmrg  Bool motion,
1178ab47cfaaSmrg  short vid_w, short vid_h,
1179ab47cfaaSmrg  short drw_w, short drw_h,
1180ab47cfaaSmrg  unsigned int *p_w, unsigned int *p_h,
1181ab47cfaaSmrg  pointer data
1182ab47cfaaSmrg){
1183ab47cfaaSmrg    /* What are the real limits for the Savage? */
1184ab47cfaaSmrg
1185ab47cfaaSmrg    *p_w = drw_w;
1186ab47cfaaSmrg    *p_h = drw_h;
1187ab47cfaaSmrg
1188ab47cfaaSmrg    if(*p_w > 16384) *p_w = 16384;
1189ab47cfaaSmrg}
1190ab47cfaaSmrg
1191ab47cfaaSmrg/* SavageCopyPlanarDataBCI() causes artifacts on the screen when used on savage4.
1192ab47cfaaSmrg * It's probably something with the BCI.  Maybe we need a waitforidle() or
1193ab47cfaaSmrg * something...
1194ab47cfaaSmrg */
1195ab47cfaaSmrgstatic void
1196ab47cfaaSmrgSavageCopyPlanarDataBCI(
1197ab47cfaaSmrg    ScrnInfoPtr pScrn,
1198ab47cfaaSmrg    unsigned char *srcY, /* Y */
1199ab47cfaaSmrg    unsigned char *srcV, /* V */
1200ab47cfaaSmrg    unsigned char *srcU, /* U */
1201ab47cfaaSmrg    unsigned char *dst,
12021473d951Smrg    unsigned char * planarPtr,
12031473d951Smrg    unsigned long planarOffset,
1204ab47cfaaSmrg    int srcPitch, int srcPitch2,
1205ab47cfaaSmrg    int dstPitch,
12061473d951Smrg    int h,int w,
12071473d951Smrg    Bool isAGP)
1208ab47cfaaSmrg{
1209ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
12101473d951Smrg
1211ab47cfaaSmrg    /* for pixel transfer */
12121473d951Smrg    unsigned long offsetY = planarOffset;
1213ab47cfaaSmrg    unsigned long offsetV = offsetY +  srcPitch * h;
1214ab47cfaaSmrg    unsigned long offsetU = offsetV +  srcPitch2 * (h>>1);
1215ab47cfaaSmrg    unsigned long dstOffset  = (unsigned long)dst - (unsigned long)psav->FBBase;
12161473d951Smrg    unsigned char memType;
1217ab47cfaaSmrg
1218ab47cfaaSmrg    BCI_GET_PTR;
1219ab47cfaaSmrg
1220ab47cfaaSmrg    /* copy Y planar */
12211473d951Smrg    memcpy(planarPtr, srcY, srcPitch * h);
1222ab47cfaaSmrg
1223ab47cfaaSmrg    /* copy V planar */
12241473d951Smrg    planarPtr = planarPtr + srcPitch * h;
12251473d951Smrg    memcpy(planarPtr, srcV, srcPitch2 * (h>>1));
1226ab47cfaaSmrg
1227ab47cfaaSmrg    /* copy U planar */
12281473d951Smrg    planarPtr = planarPtr + srcPitch2 * (h>>1);
12291473d951Smrg    memcpy(planarPtr, srcU, srcPitch2 * (h>>1));
12301473d951Smrg
12311473d951Smrg    memType = isAGP ? 3 : 0;
1232ab47cfaaSmrg
1233ab47cfaaSmrg    /*
1234ab47cfaaSmrg     * Transfer pixel data from one memory location to another location
1235ab47cfaaSmrg     * and reformat the data during the transfer
1236ab47cfaaSmrg     * a. program BCI51 to specify the source information
1237ab47cfaaSmrg     * b. program BCI52 to specify the destination information
1238ab47cfaaSmrg     * c. program BCI53 to specify the source dimensions
1239ab47cfaaSmrg     * d. program BCI54 to specify the destination dimensions
1240ab47cfaaSmrg     * e. (if the data is in YCbCr420 format)program BCI55,BCI56,BCI57 to
1241ab47cfaaSmrg     *    locations of the Y,Cb,and Cr data
1242ab47cfaaSmrg     * f. program BCI50(command=011) to specify the formatting options and
1243ab47cfaaSmrg     *    kick off the transfer
1244ab47cfaaSmrg     * this command can be used for color space conversion(YCbCr to RGB)
1245ab47cfaaSmrg     * or for oversampling, but not for both simultaneously. it can also be
1246ab47cfaaSmrg     * used to do mastered image transfer when the source is tiled
1247ab47cfaaSmrg     */
1248ab47cfaaSmrg
1249ab47cfaaSmrg    w = (w+0xf)&0xff0;
1250ab47cfaaSmrg    psav->WaitQueue(psav,11);
12511473d951Smrg    BCI_SEND(BCI_SET_REGISTER | BCI_SET_REGISTER_COUNT(7) | 0x51);
12521473d951Smrg    BCI_SEND(offsetY | memType);
1253ab47cfaaSmrg    BCI_SEND(dstOffset);
1254ab47cfaaSmrg    BCI_SEND(((h-1)<<16)|((w-1)>>3));
1255ab47cfaaSmrg    BCI_SEND(dstPitch >> 3);
12561473d951Smrg    BCI_SEND(offsetU | memType);
12571473d951Smrg    BCI_SEND(offsetV | memType);
1258ab47cfaaSmrg    BCI_SEND((srcPitch2 << 16)| srcPitch2);
1259ab47cfaaSmrg
12601473d951Smrg    BCI_SEND(BCI_SET_REGISTER | BCI_SET_REGISTER_COUNT(1) | 0x50);
1261ab47cfaaSmrg    BCI_SEND(0x00200003 | srcPitch);
12621473d951Smrg
1263ab47cfaaSmrg    BCI_SEND(0xC0170000);
1264ab47cfaaSmrg}
1265ab47cfaaSmrg
1266ab47cfaaSmrgstatic void
1267ab47cfaaSmrgSavageCopyData(
1268ab47cfaaSmrg  unsigned char *src,
1269ab47cfaaSmrg  unsigned char *dst,
1270ab47cfaaSmrg  int srcPitch,
1271ab47cfaaSmrg  int dstPitch,
1272ab47cfaaSmrg  int h,
1273ab47cfaaSmrg  int w
1274ab47cfaaSmrg){
1275ab47cfaaSmrg    w <<= 1;
12768697ee19Smrg    if (w == srcPitch && w == dstPitch) {
12778697ee19Smrg        memcpy(dst, src, w * h);
12788697ee19Smrg    } else
1279ab47cfaaSmrg    while(h--) {
1280ab47cfaaSmrg	memcpy(dst, src, w);
1281ab47cfaaSmrg	src += srcPitch;
1282ab47cfaaSmrg	dst += dstPitch;
1283ab47cfaaSmrg    }
1284ab47cfaaSmrg}
1285ab47cfaaSmrg
1286ab47cfaaSmrgstatic void
1287ab47cfaaSmrgSavageCopyPlanarData(
1288ab47cfaaSmrg   unsigned char *src1, /* Y */
1289ab47cfaaSmrg   unsigned char *src2, /* V */
1290ab47cfaaSmrg   unsigned char *src3, /* U */
1291ab47cfaaSmrg   unsigned char *dst1,
1292ab47cfaaSmrg   int srcPitch,
1293ab47cfaaSmrg   int srcPitch2,
1294ab47cfaaSmrg   int dstPitch,
1295ab47cfaaSmrg   int h,
1296ab47cfaaSmrg   int w
1297ab47cfaaSmrg){
1298ab47cfaaSmrg   CARD32 *dst = (CARD32*)dst1;
1299ab47cfaaSmrg   int i, j;
1300ab47cfaaSmrg
1301ab47cfaaSmrg   dstPitch >>= 2;
1302ab47cfaaSmrg   w >>= 1;
1303ab47cfaaSmrg
1304ab47cfaaSmrg   for(j = 0; j < h; j++) {
1305ab47cfaaSmrg	for(i = 0; i < w; i++) {
1306ab47cfaaSmrg/* Shouldn't this be 'if LITTLEENDIAN'? */
1307ab47cfaaSmrg#if 1
1308ab47cfaaSmrg	    dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
1309ab47cfaaSmrg		     (src3[i] << 8) | (src2[i] << 24);
1310ab47cfaaSmrg#else
1311ab47cfaaSmrg	    dst[i] = (src1[i << 1] << 24) | (src1[(i << 1) + 1] << 8) |
1312ab47cfaaSmrg		     (src3[i] << 0) | (src2[i] << 16);
1313ab47cfaaSmrg#endif
1314ab47cfaaSmrg	}
1315ab47cfaaSmrg	dst += dstPitch;
1316ab47cfaaSmrg	src1 += srcPitch;
1317ab47cfaaSmrg	if(j & 1) {
1318ab47cfaaSmrg	    src2 += srcPitch2;
1319ab47cfaaSmrg	    src3 += srcPitch2;
1320ab47cfaaSmrg	}
1321ab47cfaaSmrg   }
1322ab47cfaaSmrg}
1323ab47cfaaSmrg
1324ab47cfaaSmrgstatic void
1325ab47cfaaSmrgSavageVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
1326ab47cfaaSmrg{
1327aa9e3350Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1328ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1329ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1330ab47cfaaSmrg
1331ab47cfaaSmrg    if (pPriv->video_memory == area)
1332ab47cfaaSmrg        pPriv->video_memory = NULL;
13331473d951Smrg    if (pPriv->video_planarmem == area)
13341473d951Smrg        pPriv->video_planarmem = NULL;
1335ab47cfaaSmrg}
1336ab47cfaaSmrg
1337ab47cfaaSmrgstatic CARD32
1338ab47cfaaSmrgSavageAllocateMemory(
1339ab47cfaaSmrg    ScrnInfoPtr pScrn,
1340ab47cfaaSmrg    void **mem_struct,
1341ab47cfaaSmrg    int size
1342ab47cfaaSmrg){
1343aa9e3350Smrg    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
1344ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1345ab47cfaaSmrg    int offset = 0;
1346ab47cfaaSmrg
1347ab47cfaaSmrg    if (psav->useEXA) {
1348ab47cfaaSmrg	ExaOffscreenArea *area = *mem_struct;
1349ab47cfaaSmrg
1350ab47cfaaSmrg	if (area != NULL) {
1351ab47cfaaSmrg	    if (area->size >= size)
1352ab47cfaaSmrg		return area->offset;
1353ab47cfaaSmrg
1354ab47cfaaSmrg	    exaOffscreenFree(pScrn->pScreen, area);
1355ab47cfaaSmrg	}
1356ab47cfaaSmrg
1357ab47cfaaSmrg	area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, SavageVideoSave,
1358ab47cfaaSmrg				 NULL);
1359ab47cfaaSmrg	*mem_struct = area;
1360ab47cfaaSmrg	if (area == NULL)
1361ab47cfaaSmrg	    return 0;
1362ab47cfaaSmrg	offset = area->offset;
1363ab47cfaaSmrg    }
1364ab47cfaaSmrg
1365ab47cfaaSmrg    if (!psav->useEXA) {
1366ab47cfaaSmrg	FBLinearPtr linear = *mem_struct;
1367ab47cfaaSmrg	int cpp = pScrn->bitsPerPixel / 8;
1368ab47cfaaSmrg
1369ab47cfaaSmrg	/* XAA allocates in units of pixels at the screen bpp, so adjust size
1370ab47cfaaSmrg	 * appropriately.
1371ab47cfaaSmrg	 */
1372ab47cfaaSmrg	size = (size + cpp - 1) / cpp;
1373ab47cfaaSmrg
1374ab47cfaaSmrg	if (linear) {
1375ab47cfaaSmrg	    if(linear->size >= size)
1376ab47cfaaSmrg		return linear->offset * cpp;
1377ab47cfaaSmrg
1378ab47cfaaSmrg	    if(xf86ResizeOffscreenLinear(linear, size))
1379ab47cfaaSmrg		return linear->offset * cpp;
1380ab47cfaaSmrg
1381ab47cfaaSmrg	    xf86FreeOffscreenLinear(linear);
1382ab47cfaaSmrg	}
1383ab47cfaaSmrg
1384ab47cfaaSmrg	linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
1385ab47cfaaSmrg						NULL, NULL, NULL);
1386ab47cfaaSmrg	*mem_struct = linear;
1387ab47cfaaSmrg
1388ab47cfaaSmrg	if (!linear) {
1389ab47cfaaSmrg	    int max_size;
1390ab47cfaaSmrg
1391ab47cfaaSmrg	    xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
1392ab47cfaaSmrg					    PRIORITY_EXTREME);
1393ab47cfaaSmrg
1394ab47cfaaSmrg	    if(max_size < size)
1395ab47cfaaSmrg		return 0;
1396ab47cfaaSmrg
1397ab47cfaaSmrg	    xf86PurgeUnlockedOffscreenAreas(pScreen);
1398ab47cfaaSmrg	    linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
1399ab47cfaaSmrg						     NULL, NULL, NULL);
1400ab47cfaaSmrg	    *mem_struct = linear;
1401ab47cfaaSmrg	    if (!linear)
1402ab47cfaaSmrg		return 0;
1403ab47cfaaSmrg	}
1404ab47cfaaSmrg	offset = linear->offset * cpp;
1405ab47cfaaSmrg    }
1406ab47cfaaSmrg
1407ab47cfaaSmrg    return offset;
1408ab47cfaaSmrg}
1409ab47cfaaSmrg
1410ab47cfaaSmrgstatic void
1411ab47cfaaSmrgSavageFreeMemory(
1412ab47cfaaSmrg   ScrnInfoPtr pScrn,
1413ab47cfaaSmrg   void *mem_struct
1414ab47cfaaSmrg){
1415ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1416ab47cfaaSmrg
1417ab47cfaaSmrg    if (psav->useEXA) {
1418ab47cfaaSmrg	ExaOffscreenArea *area = mem_struct;
1419ab47cfaaSmrg
1420ab47cfaaSmrg	if (area != NULL)
1421ab47cfaaSmrg	    exaOffscreenFree(pScrn->pScreen, area);
1422ab47cfaaSmrg    }
1423ab47cfaaSmrg    if (!psav->useEXA) {
1424ab47cfaaSmrg	FBLinearPtr linear = mem_struct;
1425ab47cfaaSmrg
1426ab47cfaaSmrg	if (linear != NULL)
1427ab47cfaaSmrg	    xf86FreeOffscreenLinear(linear);
1428ab47cfaaSmrg    }
1429ab47cfaaSmrg}
1430ab47cfaaSmrg
1431ab47cfaaSmrgstatic void
1432ab47cfaaSmrgSavageSetBlend(ScrnInfoPtr pScrn, int id)
1433ab47cfaaSmrg{
1434ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1435ab47cfaaSmrg
1436ab47cfaaSmrg    if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) )
1437ab47cfaaSmrg    {
1438ab47cfaaSmrg	psav->blendBase = GetBlendForFourCC( id );
1439ab47cfaaSmrg	xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase );
1440ab47cfaaSmrg	if (psav->IsSecondary) {
1441ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
1442ab47cfaaSmrg	} else if (psav->IsPrimary) {
1443ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
1444ab47cfaaSmrg	} else {
1445ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
1446ab47cfaaSmrg#if 0
1447ab47cfaaSmrg	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
1448ab47cfaaSmrg#endif
1449ab47cfaaSmrg	}
1450ab47cfaaSmrg    } else if (psav->Chipset == S3_SAVAGE2000) {
1451ab47cfaaSmrg      psav->blendBase = GetBlendForFourCC2000( id );
1452ab47cfaaSmrg      xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase );
1453ab47cfaaSmrg      if (id != FOURCC_YV12)
1454ab47cfaaSmrg	OUTREG( BLEND_CONTROL,
1455ab47cfaaSmrg		((psav->blendBase << 24) | (8 << 2) /*| 0x20000000*/));
1456ab47cfaaSmrg      else
1457ab47cfaaSmrg	OUTREG( BLEND_CONTROL,
1458ab47cfaaSmrg		((psav->blendBase << 24) | (8 << 2) /*| 0x10000000*/));
1459ab47cfaaSmrg    }
1460ab47cfaaSmrg
1461ab47cfaaSmrg    psav->videoFourCC = id;
1462ab47cfaaSmrg}
1463ab47cfaaSmrg
1464ab47cfaaSmrgstatic void
1465ab47cfaaSmrgSavageDisplayVideoOld(
1466ab47cfaaSmrg    ScrnInfoPtr pScrn,
1467ab47cfaaSmrg    int id,
1468ab47cfaaSmrg    int offset,
1469ab47cfaaSmrg    short width, short height,
1470ab47cfaaSmrg    int pitch,
1471ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1472ab47cfaaSmrg    BoxPtr dstBox,
1473ab47cfaaSmrg    short src_w, short src_h,
1474ab47cfaaSmrg    short drw_w, short drw_h
1475ab47cfaaSmrg){
1476ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1477ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1478ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1479ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1480ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
1481ab47cfaaSmrg    CARD32 ssControl;
1482ab47cfaaSmrg    int scalratio;
1483ab47cfaaSmrg
1484ab47cfaaSmrg
1485ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1486ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1487ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
1488ab47cfaaSmrg#if 0
1489ab47cfaaSmrg    if ( psav->videoFourCC != id ) {
1490ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1491ab47cfaaSmrg	SavageResetVideo(pScrn);
1492ab47cfaaSmrg    }
1493ab47cfaaSmrg#endif
1494ab47cfaaSmrg    if( psav->videoFourCC != id )
1495ab47cfaaSmrg      SavageStreamsOff(pScrn);
1496ab47cfaaSmrg
14978697ee19Smrg    if( !(psav->videoFlags & VF_STREAMS_ON) )
1498ab47cfaaSmrg      {
1499ab47cfaaSmrg        SavageSetBlend(pScrn,id);
1500ab47cfaaSmrg	SavageStreamsOn(pScrn);
1501ab47cfaaSmrg	SavageResetVideo(pScrn);
15028697ee19Smrg	pPriv->lastKnownPitch = 0;
1503ab47cfaaSmrg      }
1504ab47cfaaSmrg
1505ab47cfaaSmrg    if (S3_MOBILE_TWISTER_SERIES(psav->Chipset)
1506aa9e3350Smrg	&& psav->FPExpansion) {
1507aa9e3350Smrg	drw_w = (drw_w * psav->XExp1) / psav->XExp2 + 1;
1508aa9e3350Smrg	drw_h = (drw_h * psav->YExp1) / psav->YExp2 + 1;
1509aa9e3350Smrg	dstBox->x1 = (dstBox->x1 * psav->XExp1) / psav->XExp2;
1510aa9e3350Smrg	dstBox->y1 = (dstBox->y1 * psav->YExp1) / psav->YExp2;
1511aa9e3350Smrg	dstBox->x2 = (dstBox->x2 * psav->XExp1) / psav->XExp2;
1512aa9e3350Smrg	dstBox->y2 = (dstBox->y2 * psav->YExp1) / psav->YExp2;
1513aa9e3350Smrg	dstBox->x1 += psav->displayXoffset;
1514aa9e3350Smrg	dstBox->y1 += psav->displayYoffset;
1515aa9e3350Smrg	dstBox->x2 += psav->displayXoffset;
1516aa9e3350Smrg	dstBox->y2 += psav->displayYoffset;
1517ab47cfaaSmrg    }
1518ab47cfaaSmrg
1519ab47cfaaSmrg    /*
1520ab47cfaaSmrg     * Process horizontal scaling
1521ab47cfaaSmrg     *  upscaling and downscaling smaller than 2:1 controled by MM8198
1522ab47cfaaSmrg     *  MM8190 controls downscaling mode larger than 2:1
15238697ee19Smrg     *  Together MM8190 and MM8198 can set arbitrary downscale up to 64:1
1524ab47cfaaSmrg     */
1525ab47cfaaSmrg    scalratio = 0;
1526ab47cfaaSmrg    ssControl = 0;
1527ab47cfaaSmrg
1528ab47cfaaSmrg    if (src_w >= (drw_w * 2)) {
1529ab47cfaaSmrg        if (src_w < (drw_w * 4)) {
1530ab47cfaaSmrg            ssControl |= HDSCALE_4;
15318697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*4));
15328697ee19Smrg        } else if (src_w < (drw_w * 8)) {
1533ab47cfaaSmrg            ssControl |= HDSCALE_8;
15348697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*8));
15358697ee19Smrg        } else if (src_w < (drw_w * 16)) {
1536ab47cfaaSmrg            ssControl |= HDSCALE_16;
15378697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*16));
15388697ee19Smrg        } else if (src_w < (drw_w * 32)) {
1539ab47cfaaSmrg            ssControl |= HDSCALE_32;
15408697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*32));
15418697ee19Smrg        } else if (src_w < (drw_w * 64)) {
15428697ee19Smrg            ssControl |= HDSCALE_64;
15438697ee19Smrg            scalratio = HSCALING(src_w,(drw_w*64));
15448697ee19Smrg        } else {
15458697ee19Smrg            /* Request beyond maximum downscale! */
1546ab47cfaaSmrg            ssControl |= HDSCALE_64;
15478697ee19Smrg            scalratio = HSCALING(2,1);
15488697ee19Smrg        }
1549ab47cfaaSmrg    } else
1550ab47cfaaSmrg        scalratio = HSCALING(src_w,drw_w);
1551ab47cfaaSmrg
1552ab47cfaaSmrg    ssControl |= src_w;
1553ab47cfaaSmrg    /*ssControl |= (1 << 24);*/
1554ab47cfaaSmrg    ssControl |= (GetBlendForFourCC(psav->videoFourCC) << 24);
15558697ee19Smrg#if 0
1556ab47cfaaSmrg    /* Wait for VBLANK. */
1557ab47cfaaSmrg    VerticalRetraceWait();
15588697ee19Smrg#endif
1559ab47cfaaSmrg    OUTREG(SSTREAM_CONTROL_REG, ssControl);
1560ab47cfaaSmrg    if (scalratio)
1561ab47cfaaSmrg        OUTREG(SSTREAM_STRETCH_REG,scalratio);
1562ab47cfaaSmrg
1563ab47cfaaSmrg    /* Calculate vertical scale factor. */
1564ab47cfaaSmrg    OUTREG(SSTREAM_VINITIAL_REG, 0 );
1565ab47cfaaSmrg    /*OUTREG(SSTREAM_VSCALE_REG, (src_h << 15) / drw_h );*/
1566ab47cfaaSmrg    OUTREG(SSTREAM_VSCALE_REG, VSCALING(src_h,drw_h));
1567ab47cfaaSmrg
1568ab47cfaaSmrg    /* Set surface location and stride. */
1569ab47cfaaSmrg    OUTREG(SSTREAM_FBADDR0_REG, (offset + (x1>>15)) & (0x1ffffff & ~BASE_PAD) );
1570ab47cfaaSmrg    OUTREG(SSTREAM_FBADDR1_REG, 0);
1571ab47cfaaSmrg    OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff );
1572ab47cfaaSmrg
1573ab47cfaaSmrg    OUTREG(SSTREAM_WINDOW_START_REG, OS_XY(dstBox->x1, dstBox->y1) );
1574ab47cfaaSmrg    OUTREG(SSTREAM_WINDOW_SIZE_REG, OS_WH(dstBox->x2-dstBox->x1,
1575ab47cfaaSmrg                                          dstBox->y2-dstBox->y1));
1576ab47cfaaSmrg
1577ab47cfaaSmrg    /*
1578ab47cfaaSmrg     * MM81E8:Secondary Stream Source Line Count
1579ab47cfaaSmrg     *   bit_0~10: # of lines in the source image (before scaling)
1580ab47cfaaSmrg     *   bit_15 = 1: Enable vertical interpolation
1581ab47cfaaSmrg     *            0: Line duplicaion
1582ab47cfaaSmrg     */
1583ab47cfaaSmrg    /*
1584ab47cfaaSmrg     * Vertical Interpolation is very bandwidth intensive.  Some savages can't
1585ab47cfaaSmrg     * seem to handle it.  Default is line doubling.  --AGD
1586ab47cfaaSmrg     */
1587ab47cfaaSmrg    if (pPriv->interpolation) {
1588ab47cfaaSmrg        if (src_w * 16 <= 0x3300) {
1589ab47cfaaSmrg            OUTREG(SSTREAM_LINES_REG, 0x8000 | src_h );
1590ab47cfaaSmrg	    OUTREG(FIFO_CONTROL, (INREG(FIFO_CONTROL) + 1));
1591ab47cfaaSmrg        } else {
1592ab47cfaaSmrg            OUTREG(SSTREAM_LINES_REG, src_h );
1593ab47cfaaSmrg        }
1594ab47cfaaSmrg    } else {
1595ab47cfaaSmrg        OUTREG(SSTREAM_LINES_REG, src_h );
1596ab47cfaaSmrg    }
1597ab47cfaaSmrg
1598ab47cfaaSmrg#if 0
1599ab47cfaaSmrg    /* Set color key on primary. */
1600ab47cfaaSmrg
1601ab47cfaaSmrg    SavageSetColorKey( pScrn );
1602ab47cfaaSmrg#endif
1603ab47cfaaSmrg
1604ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1605ab47cfaaSmrg
1606ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1607ab47cfaaSmrg    {
1608ab47cfaaSmrg	unsigned char cr92;
1609ab47cfaaSmrg
1610ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1611ab47cfaaSmrg
1612ab47cfaaSmrg	pitch = (pitch + 7) / 8;
1613ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1614ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1615ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1616ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1617ab47cfaaSmrg	if (psav->bTiled && (( drw_h > src_h) || (drw_w > src_w)))
1618ab47cfaaSmrg	    VGAOUT8(vgaCRReg, pitch | 0xf);
1619ab47cfaaSmrg	else
1620ab47cfaaSmrg	    VGAOUT8(vgaCRReg, pitch);
1621ab47cfaaSmrg    }
1622ab47cfaaSmrg}
1623ab47cfaaSmrg
1624ab47cfaaSmrgstatic void
1625ab47cfaaSmrgSavageDisplayVideoNew(
1626ab47cfaaSmrg    ScrnInfoPtr pScrn,
1627ab47cfaaSmrg    int id,
1628ab47cfaaSmrg    int offset,
1629ab47cfaaSmrg    short width, short height,
1630ab47cfaaSmrg    int pitch,
1631ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1632ab47cfaaSmrg    BoxPtr dstBox,
1633ab47cfaaSmrg    short src_w, short src_h,
1634ab47cfaaSmrg    short drw_w, short drw_h
1635ab47cfaaSmrg){
1636ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1637ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1638ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1639ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1640ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
1641ab47cfaaSmrg
1642ab47cfaaSmrg
1643ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1644ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1645ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
1646ab47cfaaSmrg#if 0
1647ab47cfaaSmrg    if ( psav->videoFourCC != id ) {
1648ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1649ab47cfaaSmrg	SavageResetVideo(pScrn);
1650ab47cfaaSmrg    }
1651ab47cfaaSmrg#endif
1652ab47cfaaSmrg    if( psav->videoFourCC != id )
1653ab47cfaaSmrg      SavageStreamsOff(pScrn);
1654ab47cfaaSmrg
16558697ee19Smrg    if( !(psav->videoFlags & VF_STREAMS_ON) )
1656ab47cfaaSmrg      {
1657ab47cfaaSmrg	SavageSetBlend(pScrn,id);
1658ab47cfaaSmrg	SavageStreamsOn(pScrn);
1659ab47cfaaSmrg	SavageResetVideo(pScrn);
16608697ee19Smrg	pPriv->lastKnownPitch = 0;
1661ab47cfaaSmrg      }
1662ab47cfaaSmrg
1663ab47cfaaSmrg    /* Calculate horizontal and vertical scale factors. */
1664ab47cfaaSmrg
1665ab47cfaaSmrg    if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) &&
1666ab47cfaaSmrg	    (psav->DisplayType == MT_LCD) &&
1667ab47cfaaSmrg	    !psav->CrtOnly &&
1668ab47cfaaSmrg	    !psav->TvOn)
1669ab47cfaaSmrg    {
1670aa9e3350Smrg	drw_w = (drw_w * psav->XExp1) / psav->XExp2 + 1;
1671aa9e3350Smrg	drw_h = (drw_h * psav->YExp1) / psav->YExp2 + 1;
1672aa9e3350Smrg	dstBox->x1 = (dstBox->x1 * psav->XExp1) / psav->XExp2;
1673aa9e3350Smrg	dstBox->y1 = (dstBox->y1 * psav->YExp1) / psav->YExp2;
1674aa9e3350Smrg	dstBox->x2 = (dstBox->x2 * psav->XExp1) / psav->XExp2;
1675aa9e3350Smrg	dstBox->y2 = (dstBox->y2 * psav->YExp1) / psav->YExp2;
1676ab47cfaaSmrg	dstBox->x1 += psav->displayXoffset;
1677ab47cfaaSmrg	dstBox->y1 += psav->displayYoffset;
1678aa9e3350Smrg	dstBox->x2 += psav->displayXoffset;
1679aa9e3350Smrg	dstBox->y2 += psav->displayYoffset;
1680ab47cfaaSmrg    }
1681ab47cfaaSmrg
1682ab47cfaaSmrg	if (psav->IsSecondary) {
1683ab47cfaaSmrg	    OUTREG(SEC_STREAM2_HSCALING,
1684ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1685ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1686ab47cfaaSmrg	    OUTREG(SEC_STREAM2_VSCALING,
1687ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1688ab47cfaaSmrg	} else if (psav->IsPrimary) {
1689ab47cfaaSmrg	    OUTREG(SEC_STREAM_HSCALING,
1690ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1691ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1692ab47cfaaSmrg	    OUTREG(SEC_STREAM_VSCALING,
1693ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1694ab47cfaaSmrg	} else {
1695ab47cfaaSmrg	    OUTREG(SEC_STREAM_HSCALING,
1696ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1697ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1698ab47cfaaSmrg	    OUTREG(SEC_STREAM_VSCALING,
1699ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1700ab47cfaaSmrg#if 0
1701ab47cfaaSmrg	    OUTREG(SEC_STREAM2_HSCALING,
1702ab47cfaaSmrg	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1703ab47cfaaSmrg	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1704ab47cfaaSmrg	    OUTREG(SEC_STREAM2_VSCALING,
1705ab47cfaaSmrg	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1706ab47cfaaSmrg#endif
1707ab47cfaaSmrg	}
1708ab47cfaaSmrg
1709ab47cfaaSmrg    /*
1710ab47cfaaSmrg     * Set surface location and stride.  We use x1>>15 because all surfaces
1711ab47cfaaSmrg     * are 2 bytes/pixel.
1712ab47cfaaSmrg     */
1713ab47cfaaSmrg
1714ab47cfaaSmrg    if (psav->IsSecondary) {
1715ab47cfaaSmrg        OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15))
1716ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1717ab47cfaaSmrg        OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff );
1718ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1719ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1720ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1721ab47cfaaSmrg    } else if (psav->IsPrimary) {
1722ab47cfaaSmrg        OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15))
1723ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1724ab47cfaaSmrg        OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff );
1725ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1726ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1727ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1728ab47cfaaSmrg    } else {
1729ab47cfaaSmrg        OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15))
1730ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1731ab47cfaaSmrg        OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff );
1732ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1733ab47cfaaSmrg        OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1734ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1735ab47cfaaSmrg#if 0
1736ab47cfaaSmrg        OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15))
1737ab47cfaaSmrg	   & (0x7ffffff & ~BASE_PAD));
1738ab47cfaaSmrg        OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff );
1739ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1740ab47cfaaSmrg        OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1741ab47cfaaSmrg	   | (dstBox->x2-dstBox->x1) );
1742ab47cfaaSmrg#endif
1743ab47cfaaSmrg    }
1744ab47cfaaSmrg
1745ab47cfaaSmrg#if 0
1746ab47cfaaSmrg    /* Set color key on primary. */
1747ab47cfaaSmrg
1748ab47cfaaSmrg    SavageSetColorKey( pScrn );
1749ab47cfaaSmrg#endif
1750ab47cfaaSmrg
1751ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1752ab47cfaaSmrg    /* Is CR92 shadowed for crtc2? -- AGD */
1753ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1754ab47cfaaSmrg    {
1755ab47cfaaSmrg	unsigned char cr92;
1756ab47cfaaSmrg
1757ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1758ab47cfaaSmrg	pitch = (pitch + 7) / 8 - 4;
1759ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1760ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1761ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1762ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1763ab47cfaaSmrg	VGAOUT8(vgaCRReg, pitch);
1764ab47cfaaSmrg    }
1765ab47cfaaSmrg}
1766ab47cfaaSmrg
1767ab47cfaaSmrgstatic void
1768ab47cfaaSmrgSavageDisplayVideo2000(
1769ab47cfaaSmrg    ScrnInfoPtr pScrn,
1770ab47cfaaSmrg    int id,
1771ab47cfaaSmrg    int offset,
1772ab47cfaaSmrg    short width, short height,
1773ab47cfaaSmrg    int pitch,
1774ab47cfaaSmrg    int x1, int y1, int x2, int y2,
1775ab47cfaaSmrg    BoxPtr dstBox,
1776ab47cfaaSmrg    short src_w, short src_h,
1777ab47cfaaSmrg    short drw_w, short drw_h
1778ab47cfaaSmrg){
1779ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1780ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1781ab47cfaaSmrg    /*DisplayModePtr mode = pScrn->currentMode;*/
1782ab47cfaaSmrg    SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1783ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
1784ab47cfaaSmrg    CARD32 addr0, addr1, addr2;
1785ab47cfaaSmrg
1786ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
1787ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
1788ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
1789ab47cfaaSmrg
1790ab47cfaaSmrg
1791ab47cfaaSmrg    if( psav->videoFourCC != id )
1792ab47cfaaSmrg        SavageStreamsOff(pScrn);
1793ab47cfaaSmrg
17948697ee19Smrg    if( !(psav->videoFlags & VF_STREAMS_ON) )
1795ab47cfaaSmrg    {
1796ab47cfaaSmrg        SavageSetBlend(pScrn,id);
1797ab47cfaaSmrg        SavageStreamsOn(pScrn);
1798ab47cfaaSmrg        SavageResetVideo(pScrn);
17998697ee19Smrg        pPriv->lastKnownPitch = 0;
1800ab47cfaaSmrg    }
1801ab47cfaaSmrg
1802ab47cfaaSmrg    if (src_w > drw_w)
1803ab47cfaaSmrg        OUTREG(SEC_STREAM_SRC_START_2000, 0);
1804ab47cfaaSmrg    else
1805ab47cfaaSmrg        OUTREG(SEC_STREAM_SRC_START_2000, SRCSTART(x1, y1));
1806ab47cfaaSmrg
1807ab47cfaaSmrg    /*OUTREG(SEC_STREAM_SRC_SIZE_2000, SRCSIZE(src_w, src_h));*/
1808ab47cfaaSmrg    OUTREG(SEC_STREAM_SRC_SIZE_2000,
1809ab47cfaaSmrg	   SRCSIZE((dstBox->x2-dstBox->x1), (dstBox->y2-dstBox->y1)));
1810ab47cfaaSmrg    /*
1811ab47cfaaSmrg        buffersize = (src_w * src_h * 2) / 4096;
1812ab47cfaaSmrg	  OUTREG(SEC_STREAM_BUFFERSIZE_2000, (buffersize & 0xffffff) << 12);
1813ab47cfaaSmrg    */
1814ab47cfaaSmrg
1815ab47cfaaSmrg    /*SavageResetVideo(pScrn);*/
1816ab47cfaaSmrg
1817ab47cfaaSmrg    if( src_w > drw_w )
1818ab47cfaaSmrg	OUTREG(SEC_STREAM_HSCALE_NORMALIZE, HSCALING_NORMALIZE(drw_w,src_w));
1819ab47cfaaSmrg    else
1820ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALE_NORMALIZE, (2048 << 16));
1821ab47cfaaSmrg
1822ab47cfaaSmrg    /* Calculate horizontal and vertical scale factors. */
1823ab47cfaaSmrg    if ((src_w > drw_w) || (src_h > drw_h))
1824ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALING, (HSCALING_2000(src_w,drw_w)) | 0x01000000);
1825ab47cfaaSmrg    else
1826ab47cfaaSmrg        OUTREG(SEC_STREAM_HSCALING, HSCALING_2000(src_w,drw_w));
1827ab47cfaaSmrg
1828ab47cfaaSmrg    OUTREG(SEC_STREAM_VSCALING, VSCALING_2000(src_h,drw_h));
1829ab47cfaaSmrg
1830ab47cfaaSmrg    /*
1831ab47cfaaSmrg     * Set surface location and stride.  We use x1>>15 because all surfaces
1832ab47cfaaSmrg     * are 2 bytes/pixel.
1833ab47cfaaSmrg     */
1834ab47cfaaSmrg
1835ab47cfaaSmrg    addr0 = offset + (x1>>15); /* Y in YCbCr420 */
1836ab47cfaaSmrg    addr1 = addr0 + (width * height); /* Cb in in YCbCr420 */
1837ab47cfaaSmrg    addr2 = addr1 + ((width * height) / 4); /* Cr in in YCbCr420 */
1838ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR0, (addr0) & (0x3fffff & ~BASE_PAD));
1839ab47cfaaSmrg#if 0
1840ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR1, (addr1) & (0x3fffff & ~BASE_PAD));
1841ab47cfaaSmrg    OUTREG(SEC_STREAM_FBUF_ADDR2, (addr2) & (0x3fffff & ~BASE_PAD));
1842ab47cfaaSmrg#endif
1843ab47cfaaSmrg
1844ab47cfaaSmrg    OUTREG(SEC_STREAM_WINDOW_START, XY_2000(dstBox->x1,dstBox->y1));
1845ab47cfaaSmrg    OUTREG(SEC_STREAM_WINDOW_SZ,
1846ab47cfaaSmrg	   WH_2000((dstBox->x2-dstBox->x1),(dstBox->y2-dstBox->y1)));
1847ab47cfaaSmrg
1848ab47cfaaSmrg    /*pitch = width * 2;*/
1849ab47cfaaSmrg    OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff);
1850ab47cfaaSmrg#if 0
1851ab47cfaaSmrg    /* Y stride + CbCr stride in YCbCr420 */
1852ab47cfaaSmrg    OUTREG(SEC_STREAM_STRIDE, (pitch & 0xfff) + ((pitch & 0xfff) << 15));
1853ab47cfaaSmrg#endif
1854ab47cfaaSmrg
1855ab47cfaaSmrg#if 0
1856ab47cfaaSmrg    /* Set color key on primary. */
1857ab47cfaaSmrg
1858ab47cfaaSmrg    SavageSetColorKey2000( pScrn );
1859ab47cfaaSmrg#endif
1860ab47cfaaSmrg
1861ab47cfaaSmrg#if 0
1862ab47cfaaSmrg    /* Set FIFO L2 on second stream. */
1863ab47cfaaSmrg    if( pPriv->lastKnownPitch != pitch )
1864ab47cfaaSmrg    {
1865ab47cfaaSmrg	unsigned char cr92;
1866ab47cfaaSmrg
1867ab47cfaaSmrg	pPriv->lastKnownPitch = pitch;
1868ab47cfaaSmrg	pitch = (pitch + 7) / 8 - 4;
1869ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x92);
1870ab47cfaaSmrg	cr92 = VGAIN8(vgaCRReg);
1871ab47cfaaSmrg	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1872ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x93);
1873ab47cfaaSmrg	VGAOUT8(vgaCRReg, pitch);
1874ab47cfaaSmrg    }
1875ab47cfaaSmrg#endif
1876ab47cfaaSmrg}
1877ab47cfaaSmrg
18781473d951Smrgstatic void
18791473d951SmrgSavageFillKeyHelper(DrawablePtr pDraw, uint32_t colorKey, RegionPtr clipBoxes)
18801473d951Smrg{
18811473d951Smrg#if HAVE_XV_DRAWABLE_HELPER
18821473d951Smrg    xf86XVFillKeyHelperDrawable(pDraw, colorKey, clipBoxes);
18831473d951Smrg#else
18841473d951Smrg    xf86XVFillKeyHelper(pDraw->pScreen, colorKey, clipBoxes);
18851473d951Smrg#endif
18861473d951Smrg}
18871473d951Smrg
1888ab47cfaaSmrgstatic int
1889ab47cfaaSmrgSavagePutImage(
1890ab47cfaaSmrg    ScrnInfoPtr pScrn,
1891ab47cfaaSmrg    short src_x, short src_y,
1892ab47cfaaSmrg    short drw_x, short drw_y,
1893ab47cfaaSmrg    short src_w, short src_h,
1894ab47cfaaSmrg    short drw_w, short drw_h,
1895ab47cfaaSmrg    int id, unsigned char* buf,
1896ab47cfaaSmrg    short width, short height,
1897ab47cfaaSmrg    Bool sync,
1898ab47cfaaSmrg    RegionPtr clipBoxes, pointer data,
1899ab47cfaaSmrg    DrawablePtr pDraw
1900ab47cfaaSmrg){
1901ab47cfaaSmrg    SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1902ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1903ab47cfaaSmrg    ScreenPtr pScreen = pScrn->pScreen;
1904ab47cfaaSmrg    INT32 x1, x2, y1, y2;
1905ab47cfaaSmrg    unsigned char *dst_start;
1906ab47cfaaSmrg    int pitch, new_size, offset, offsetV=0, offsetU=0;
1907ab47cfaaSmrg    int srcPitch, srcPitch2=0, dstPitch;
19081473d951Smrg    int planarFrameSize;
1909ab47cfaaSmrg    int top, left, npixels, nlines;
1910ab47cfaaSmrg    BoxRec dstBox;
1911ab47cfaaSmrg    CARD32 tmp;
1912ab47cfaaSmrg/*    xf86ErrorFVerb(XVTRACE,"SavagePutImage\n"); */
1913ab47cfaaSmrg    if(drw_w > 16384) drw_w = 16384;
1914ab47cfaaSmrg
1915ab47cfaaSmrg    /* Clip */
1916ab47cfaaSmrg    x1 = src_x;
1917ab47cfaaSmrg    x2 = src_x + src_w;
1918ab47cfaaSmrg    y1 = src_y;
1919ab47cfaaSmrg    y2 = src_y + src_h;
1920ab47cfaaSmrg
1921ab47cfaaSmrg    dstBox.x1 = drw_x;
1922ab47cfaaSmrg    dstBox.x2 = drw_x + drw_w;
1923ab47cfaaSmrg    dstBox.y1 = drw_y;
1924ab47cfaaSmrg    dstBox.y2 = drw_y + drw_h;
1925ab47cfaaSmrg
1926ab47cfaaSmrg    SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
1927ab47cfaaSmrg		REGION_EXTENTS(pScreen, clipBoxes), width, height);
1928ab47cfaaSmrg
1929ab47cfaaSmrg    drw_w = dstBox.x2 - dstBox.x1;
1930ab47cfaaSmrg    drw_h = dstBox.y2 - dstBox.y1;
1931ab47cfaaSmrg    src_w = ( x2 - x1 ) >> 16;
1932ab47cfaaSmrg    src_h = ( y2 - y1 ) >> 16;
1933ab47cfaaSmrg
1934ab47cfaaSmrg    if((x1 >= x2) || (y1 >= y2))
1935ab47cfaaSmrg	return Success;
1936ab47cfaaSmrg
1937ab47cfaaSmrg    dstBox.x1 -= pScrn->frameX0;
1938ab47cfaaSmrg    dstBox.x2 -= pScrn->frameX0;
1939ab47cfaaSmrg    dstBox.y1 -= pScrn->frameY0;
1940ab47cfaaSmrg    dstBox.y2 -= pScrn->frameY0;
1941ab47cfaaSmrg
1942ab47cfaaSmrg    pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
1943ab47cfaaSmrg
19441473d951Smrg    /* All formats directly displayable by Savage are packed and 2 bytes per pixel */
1945ab47cfaaSmrg    dstPitch = ((width << 1) + 15) & ~15;
1946ab47cfaaSmrg    new_size = dstPitch * height;
1947ab47cfaaSmrg
1948ab47cfaaSmrg    switch(id) {
1949ab47cfaaSmrg    case FOURCC_Y211:		/* Y211 */
1950ab47cfaaSmrg        srcPitch = width;
1951ab47cfaaSmrg	break;
1952ab47cfaaSmrg    case FOURCC_YV12:		/* YV12 */
1953ab47cfaaSmrg	srcPitch = (width + 3) & ~3;
1954ab47cfaaSmrg	offsetV = srcPitch * height;
1955ab47cfaaSmrg	srcPitch2 = ((width >> 1) + 3) & ~3;
1956ab47cfaaSmrg	offsetU = (srcPitch2 * (height >> 1)) + offsetV;
1957ab47cfaaSmrg	break;
1958ab47cfaaSmrg    case FOURCC_I420:
1959ab47cfaaSmrg	srcPitch = (width + 3) & ~3;
1960ab47cfaaSmrg	offsetU = srcPitch * height;
1961ab47cfaaSmrg	srcPitch2 = ((width >> 1) + 3) & ~3;
1962ab47cfaaSmrg	offsetV = (srcPitch2 * (height >> 1)) + offsetU;
1963ab47cfaaSmrg	break;
1964ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
1965ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
1966ab47cfaaSmrg    case FOURCC_YUY2:		/* YUY2 */
1967ab47cfaaSmrg    default:
1968ab47cfaaSmrg	srcPitch = (width << 1);
1969ab47cfaaSmrg	break;
1970ab47cfaaSmrg    }
1971ab47cfaaSmrg
19721473d951Smrg    /* Calculate required memory for all planar frames */
19731473d951Smrg    planarFrameSize = 0;
19748697ee19Smrg    if (srcPitch2 != 0 && S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv) {
19751473d951Smrg        new_size = ((new_size + 0xF) & ~0xF);
19761473d951Smrg        planarFrameSize = srcPitch * height + srcPitch2 * height;
19771473d951Smrg    }
19781473d951Smrg
19791473d951Smrg    /* Check whether AGP buffers can be allocated. If not, fall back to ordinary
19801473d951Smrg       upload to framebuffer (slower) */
1981aa9e3350Smrg#ifdef SAVAGEDRI
19821473d951Smrg    if (!pPriv->tried_agp && !psav->IsPCI && psav->drmFD > 0 && psav->DRIServerInfo != NULL) {
19831473d951Smrg	SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
19841473d951Smrg
19851473d951Smrg	pPriv->tried_agp = TRUE;
19861473d951Smrg	if (pSAVAGEDRIServer->agpXVideo.size >= max(new_size, planarFrameSize)) {
19871473d951Smrg	    if (pSAVAGEDRIServer->agpXVideo.map == NULL &&
19881473d951Smrg	        drmMap( psav->drmFD,
19891473d951Smrg		pSAVAGEDRIServer->agpXVideo.handle,
19901473d951Smrg		pSAVAGEDRIServer->agpXVideo.size,
19911473d951Smrg		&pSAVAGEDRIServer->agpXVideo.map ) < 0 ) {
19921473d951Smrg
19931473d951Smrg		xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] XVideo: Could not map agpXVideo \n" );
19941473d951Smrg		pPriv->agpBufferOffset = 0;
19951473d951Smrg		pPriv->agpBufferMap = NULL;
19961473d951Smrg	    } else {
19971473d951Smrg		pPriv->agpBufferMap = pSAVAGEDRIServer->agpXVideo.map;
19981473d951Smrg		pPriv->agpBufferOffset = pSAVAGEDRIServer->agpXVideo.offset;
19991473d951Smrg		pPriv->agpBase = drmAgpBase(psav->drmFD);
20001473d951Smrg#if 0
20011473d951Smrg		xf86DrvMsg( pScreen->myNum, X_INFO,
20021473d951Smrg		       "[agp] agpXVideo mapped at 0x%08lx aperture=0x%08x offset=0x%08lx\n",
20031473d951Smrg		       (unsigned long)pPriv->agpBufferMap, pPriv->agpBase, pPriv->agpBufferOffset);
20041473d951Smrg#endif
20051473d951Smrg	    }
20061473d951Smrg	} else {
20071473d951Smrg	    /* This situation is expected if AGPforXv is disabled, otherwise report. */
20081473d951Smrg	    if (pSAVAGEDRIServer->agpXVideo.size > 0) {
20091473d951Smrg		xf86DrvMsg( pScreen->myNum, X_ERROR,
2010aa9e3350Smrg		    "[agp] XVideo: not enough space in buffer (got %ld bytes, required %d bytes).\n",
2011aa9e3350Smrg	    	    (long int)pSAVAGEDRIServer->agpXVideo.size, max(new_size, planarFrameSize));
20121473d951Smrg	    }
20131473d951Smrg	    pPriv->agpBufferMap = NULL;
20141473d951Smrg	    pPriv->agpBufferOffset = 0;
20151473d951Smrg	}
20168697ee19Smrg    }
2017aa9e3350Smrg#endif /* SAVAGEDRI */
20188697ee19Smrg
20191473d951Smrg
20201473d951Smrg    /* Buffer for final packed frame */
20211473d951Smrg    pPriv->video_offset = SavageAllocateMemory(
20221473d951Smrg	pScrn, &pPriv->video_memory,
20231473d951Smrg	new_size);
2024ab47cfaaSmrg    if (pPriv->video_offset == 0)
2025ab47cfaaSmrg        return BadAlloc;
2026ab47cfaaSmrg
20271473d951Smrg    /* Packed format cases */
20281473d951Smrg    if (planarFrameSize == 0) {
20291473d951Smrg	pPriv->video_planarbuf = 0;
20301473d951Smrg
20311473d951Smrg    /* Planar format cases */
20321473d951Smrg    } else {
20331473d951Smrg	/* Hardware-assisted planar conversion only works on 16-byte aligned addresses */
20341473d951Smrg	pPriv->video_planarbuf = SavageAllocateMemory(
20351473d951Smrg	    pScrn, &pPriv->video_planarmem,
20361473d951Smrg	    ((planarFrameSize + 0xF) & ~0xF));
20371473d951Smrg	if (pPriv->video_planarbuf != 0) {
20381473d951Smrg	    /* TODO: stop any pending conversions when buffers change... */
20391473d951Smrg	    pPriv->video_planarbuf = ((pPriv->video_planarbuf + 0xF) & ~0xF);
20401473d951Smrg	} else {
20411473d951Smrg	    /* Fallback using software conversion */
20421473d951Smrg	}
20431473d951Smrg    }
20441473d951Smrg
2045ab47cfaaSmrg    /* copy data */
2046ab47cfaaSmrg    top = y1 >> 16;
2047ab47cfaaSmrg    left = (x1 >> 16) & ~1;
2048ab47cfaaSmrg    npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
2049ab47cfaaSmrg    left <<= 1;
2050ab47cfaaSmrg
2051ab47cfaaSmrg    offset = (pPriv->video_offset) + (top * dstPitch);
2052ab47cfaaSmrg    dst_start = (psav->FBBase + ((offset + left) & ~BASE_PAD));
2053ab47cfaaSmrg
2054ab47cfaaSmrg    switch(id) {
2055ab47cfaaSmrg    case FOURCC_YV12:		/* YV12 */
2056ab47cfaaSmrg    case FOURCC_I420:
2057ab47cfaaSmrg	top &= ~1;
2058ab47cfaaSmrg	tmp = ((top >> 1) * srcPitch2) + (left >> 2);
2059ab47cfaaSmrg	offsetU += tmp;
2060ab47cfaaSmrg	offsetV += tmp;
2061ab47cfaaSmrg	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
20621473d951Smrg        if (S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv && (npixels & 0xF) == 0 && pPriv->video_planarbuf != 0) {
2063aa9e3350Smrg#ifdef SAVAGEDRI
20641473d951Smrg            if (pPriv->agpBufferMap != NULL) {
20651473d951Smrg		/* Using copy to AGP memory */
20661473d951Smrg		SavageCopyPlanarDataBCI(
20671473d951Smrg		    pScrn,
20681473d951Smrg		    buf + (top * srcPitch) + (left >> 1),
20691473d951Smrg		    buf + offsetV,
20701473d951Smrg		    buf + offsetU,
20711473d951Smrg		    dst_start,
20721473d951Smrg		    pPriv->agpBufferMap,
20731473d951Smrg		    pPriv->agpBase + pPriv->agpBufferOffset,
20741473d951Smrg		    srcPitch, srcPitch2, dstPitch, nlines, npixels, TRUE);
20756aec45a7Smrg            } else
2076aa9e3350Smrg#endif /* SAVAGEDRI */
20776aec45a7Smrg            {
20781473d951Smrg		/* Using ordinary copy to framebuffer */
20791473d951Smrg		SavageCopyPlanarDataBCI(
20801473d951Smrg		    pScrn,
20811473d951Smrg		    buf + (top * srcPitch) + (left >> 1),
20821473d951Smrg		    buf + offsetV,
20831473d951Smrg		    buf + offsetU,
20841473d951Smrg		    dst_start,
20851473d951Smrg		    (unsigned char *)psav->FBBase + pPriv->video_planarbuf,
20861473d951Smrg		    pPriv->video_planarbuf,
20871473d951Smrg		    srcPitch, srcPitch2, dstPitch, nlines, npixels, FALSE);
20881473d951Smrg	    }
2089ab47cfaaSmrg        } else {
2090ab47cfaaSmrg	    SavageCopyPlanarData(
2091ab47cfaaSmrg	    	buf + (top * srcPitch) + (left >> 1),
2092ab47cfaaSmrg	    	buf + offsetV,
2093ab47cfaaSmrg	    	buf + offsetU,
2094ab47cfaaSmrg	    	dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels);
2095ab47cfaaSmrg        }
2096ab47cfaaSmrg	break;
2097ab47cfaaSmrg    case FOURCC_Y211:		/* Y211 */
2098ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
2099ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
2100ab47cfaaSmrg    case FOURCC_YUY2:		/* YUY2 */
2101ab47cfaaSmrg    default:
2102ab47cfaaSmrg	buf += (top * srcPitch) + left;
2103ab47cfaaSmrg	nlines = ((y2 + 0xffff) >> 16) - top;
2104ab47cfaaSmrg	SavageCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
2105ab47cfaaSmrg	break;
2106ab47cfaaSmrg    }
2107ab47cfaaSmrg
2108ab47cfaaSmrg    /* We need to enable the video before we draw the chroma color.
2109ab47cfaaSmrg       Otherwise, we get blue flashes. */
2110ab47cfaaSmrg
2111ab47cfaaSmrg    SavageDisplayVideo(pScrn, id, offset, width, height, dstPitch,
2112ab47cfaaSmrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
2113ab47cfaaSmrg
2114ab47cfaaSmrg    /* update cliplist */
2115ab47cfaaSmrg    if(!REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes)) {
2116ab47cfaaSmrg	REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
2117ab47cfaaSmrg	/* draw these */
21181473d951Smrg	SavageFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes);
2119ab47cfaaSmrg
2120ab47cfaaSmrg    }
2121ab47cfaaSmrg
2122ab47cfaaSmrg    pPriv->videoStatus = CLIENT_VIDEO_ON;
2123ab47cfaaSmrg
2124ab47cfaaSmrg    return Success;
2125ab47cfaaSmrg}
2126ab47cfaaSmrg
2127ab47cfaaSmrgstatic int
2128ab47cfaaSmrgSavageQueryImageAttributes(
2129ab47cfaaSmrg  ScrnInfoPtr pScrn,
2130ab47cfaaSmrg  int id,
2131ab47cfaaSmrg  unsigned short *w, unsigned short *h,
2132ab47cfaaSmrg  int *pitches, int *offsets
2133ab47cfaaSmrg){
2134ab47cfaaSmrg    int size, tmp;
2135ab47cfaaSmrg
2136ab47cfaaSmrg    if(*w > 1024) *w = 1024;
2137ab47cfaaSmrg    if(*h > 1024) *h = 1024;
2138ab47cfaaSmrg
2139ab47cfaaSmrg    *w = (*w + 1) & ~1;
2140ab47cfaaSmrg    if(offsets) offsets[0] = 0;
2141ab47cfaaSmrg
2142ab47cfaaSmrg    switch(id) {
2143ab47cfaaSmrg    case FOURCC_IA44:
2144ab47cfaaSmrg        if (pitches) pitches[0]=*w;
2145ab47cfaaSmrg        size=(*w)*(*h);
2146ab47cfaaSmrg        break;
2147ab47cfaaSmrg    case FOURCC_Y211:
2148ab47cfaaSmrg	size = *w << 2;
2149ab47cfaaSmrg	if(pitches) pitches[0] = size;
2150ab47cfaaSmrg	size *= *h;
2151ab47cfaaSmrg	break;
2152ab47cfaaSmrg    case FOURCC_YV12:
2153ab47cfaaSmrg    case FOURCC_I420:
2154ab47cfaaSmrg	*h = (*h + 1) & ~1;
2155ab47cfaaSmrg	size = (*w + 3) & ~3;
2156ab47cfaaSmrg	if(pitches) pitches[0] = size;
2157ab47cfaaSmrg	size *= *h;
2158ab47cfaaSmrg	if(offsets) offsets[1] = size;
2159ab47cfaaSmrg	tmp = ((*w >> 1) + 3) & ~3;
2160ab47cfaaSmrg	if(pitches) pitches[1] = pitches[2] = tmp;
2161ab47cfaaSmrg	tmp *= (*h >> 1);
2162ab47cfaaSmrg	size += tmp;
2163ab47cfaaSmrg	if(offsets) offsets[2] = size;
2164ab47cfaaSmrg	size += tmp;
2165ab47cfaaSmrg	break;
2166ab47cfaaSmrg    case FOURCC_RV15:		/* RGB15 */
2167ab47cfaaSmrg    case FOURCC_RV16:		/* RGB16 */
2168ab47cfaaSmrg    case FOURCC_YUY2:
2169ab47cfaaSmrg    default:
2170ab47cfaaSmrg	size = *w << 1;
2171ab47cfaaSmrg	if(pitches) pitches[0] = size;
2172ab47cfaaSmrg	size *= *h;
2173ab47cfaaSmrg	break;
2174ab47cfaaSmrg    }
2175ab47cfaaSmrg
2176ab47cfaaSmrg    return size;
2177ab47cfaaSmrg}
2178ab47cfaaSmrg
2179ab47cfaaSmrg/****************** Offscreen stuff ***************/
2180ab47cfaaSmrg
2181ab47cfaaSmrgtypedef struct {
2182ab47cfaaSmrg  void *surface_memory;
2183ab47cfaaSmrg  Bool isOn;
2184ab47cfaaSmrg} OffscreenPrivRec, * OffscreenPrivPtr;
2185ab47cfaaSmrg
2186ab47cfaaSmrgstatic int
2187ab47cfaaSmrgSavageAllocateSurface(
2188ab47cfaaSmrg    ScrnInfoPtr pScrn,
2189ab47cfaaSmrg    int id,
2190ab47cfaaSmrg    unsigned short w,
2191ab47cfaaSmrg    unsigned short h,
2192ab47cfaaSmrg    XF86SurfacePtr surface
2193ab47cfaaSmrg){
2194ab47cfaaSmrg    int offset, size;
2195ab47cfaaSmrg    int pitch, fbpitch, numlines;
2196ab47cfaaSmrg    void *surface_memory = NULL;
2197ab47cfaaSmrg    OffscreenPrivPtr pPriv;
2198ab47cfaaSmrg
2199ab47cfaaSmrg    if((w > 1024) || (h > 1024))
2200ab47cfaaSmrg	return BadAlloc;
2201ab47cfaaSmrg
2202ab47cfaaSmrg    w = (w + 1) & ~1;
2203ab47cfaaSmrg    pitch = ((w << 1) + 15) & ~15;
2204ab47cfaaSmrg    fbpitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
2205ab47cfaaSmrg    numlines = ((pitch * h) + fbpitch - 1) / fbpitch;
2206ab47cfaaSmrg    size = pitch * h;
2207ab47cfaaSmrg
2208ab47cfaaSmrg    offset = SavageAllocateMemory(pScrn, &surface_memory, size);
2209ab47cfaaSmrg    if (offset == 0)
2210ab47cfaaSmrg	return BadAlloc;
2211ab47cfaaSmrg
2212ab47cfaaSmrg    surface->width = w;
2213ab47cfaaSmrg    surface->height = h;
2214ab47cfaaSmrg
2215aa9e3350Smrg    if(!(surface->pitches = malloc(sizeof(int)))) {
2216ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2217ab47cfaaSmrg	return BadAlloc;
2218ab47cfaaSmrg    }
2219aa9e3350Smrg    if(!(surface->offsets = malloc(sizeof(int)))) {
2220aa9e3350Smrg	free(surface->pitches);
2221ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2222ab47cfaaSmrg	return BadAlloc;
2223ab47cfaaSmrg    }
2224aa9e3350Smrg    if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
2225aa9e3350Smrg	free(surface->pitches);
2226aa9e3350Smrg	free(surface->offsets);
2227ab47cfaaSmrg	SavageFreeMemory(pScrn, surface_memory);
2228ab47cfaaSmrg	return BadAlloc;
2229ab47cfaaSmrg    }
2230ab47cfaaSmrg
2231ab47cfaaSmrg    pPriv->surface_memory = surface_memory;
2232ab47cfaaSmrg    pPriv->isOn = FALSE;
2233ab47cfaaSmrg
2234ab47cfaaSmrg    surface->pScrn = pScrn;
2235ab47cfaaSmrg    surface->id = id;
2236ab47cfaaSmrg    surface->pitches[0] = pitch;
2237ab47cfaaSmrg    surface->offsets[0] = offset; /*area->box.y1 * fbpitch;*/
2238ab47cfaaSmrg    surface->devPrivate.ptr = (pointer)pPriv;
2239ab47cfaaSmrg
2240ab47cfaaSmrg    return Success;
2241ab47cfaaSmrg}
2242ab47cfaaSmrg
2243ab47cfaaSmrgstatic int
2244ab47cfaaSmrgSavageStopSurface(
2245ab47cfaaSmrg    XF86SurfacePtr surface
2246ab47cfaaSmrg){
2247ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2248ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageStopSurface\n");
2249ab47cfaaSmrg
2250ab47cfaaSmrg    if(pPriv->isOn) {
2251ab47cfaaSmrg	/*SavagePtr psav = SAVPTR(surface->pScrn);*/
2252ab47cfaaSmrg	/*SavageClipVWindow(surface->pScrn);*/
2253ab47cfaaSmrg	SavageStreamsOff( surface->pScrn );
2254ab47cfaaSmrg	pPriv->isOn = FALSE;
2255ab47cfaaSmrg    }
2256ab47cfaaSmrg
2257ab47cfaaSmrg    return Success;
2258ab47cfaaSmrg}
2259ab47cfaaSmrg
2260ab47cfaaSmrg
2261ab47cfaaSmrgstatic int
2262ab47cfaaSmrgSavageFreeSurface(
2263ab47cfaaSmrg    XF86SurfacePtr surface
2264ab47cfaaSmrg){
2265ab47cfaaSmrg    ScrnInfoPtr pScrn = surface->pScrn;
2266ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2267ab47cfaaSmrg
2268ab47cfaaSmrg    if(pPriv->isOn)
2269ab47cfaaSmrg	SavageStopSurface(surface);
2270ab47cfaaSmrg    SavageFreeMemory(pScrn, pPriv->surface_memory);
2271aa9e3350Smrg    free(surface->pitches);
2272aa9e3350Smrg    free(surface->offsets);
2273aa9e3350Smrg    free(surface->devPrivate.ptr);
2274ab47cfaaSmrg
2275ab47cfaaSmrg    return Success;
2276ab47cfaaSmrg}
2277ab47cfaaSmrg
2278ab47cfaaSmrgstatic int
2279ab47cfaaSmrgSavageGetSurfaceAttribute(
2280ab47cfaaSmrg    ScrnInfoPtr pScrn,
2281ab47cfaaSmrg    Atom attribute,
2282ab47cfaaSmrg    INT32 *value
2283ab47cfaaSmrg){
2284ab47cfaaSmrg    return SavageGetPortAttribute(pScrn, attribute, value,
2285ab47cfaaSmrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
2286ab47cfaaSmrg}
2287ab47cfaaSmrg
2288ab47cfaaSmrgstatic int
2289ab47cfaaSmrgSavageSetSurfaceAttribute(
2290ab47cfaaSmrg    ScrnInfoPtr pScrn,
2291ab47cfaaSmrg    Atom attribute,
2292ab47cfaaSmrg    INT32 value
2293ab47cfaaSmrg){
2294ab47cfaaSmrg    return SavageSetPortAttribute(pScrn, attribute, value,
2295ab47cfaaSmrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
2296ab47cfaaSmrg}
2297ab47cfaaSmrg
2298ab47cfaaSmrg
2299ab47cfaaSmrgstatic int
2300ab47cfaaSmrgSavageDisplaySurface(
2301ab47cfaaSmrg    XF86SurfacePtr surface,
2302ab47cfaaSmrg    short src_x, short src_y,
2303ab47cfaaSmrg    short drw_x, short drw_y,
2304ab47cfaaSmrg    short src_w, short src_h,
2305ab47cfaaSmrg    short drw_w, short drw_h,
2306ab47cfaaSmrg    RegionPtr clipBoxes
2307ab47cfaaSmrg){
2308ab47cfaaSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2309ab47cfaaSmrg    ScrnInfoPtr pScrn = surface->pScrn;
2310ab47cfaaSmrg    ScreenPtr pScreen = pScrn->pScreen;
2311ab47cfaaSmrg    SavagePortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn);
2312ab47cfaaSmrg    INT32 x1, y1, x2, y2;
2313ab47cfaaSmrg    BoxRec dstBox;
2314ab47cfaaSmrg    xf86ErrorFVerb(XVTRACE,"SavageDisplaySurface\n");
2315ab47cfaaSmrg
2316ab47cfaaSmrg    x1 = src_x;
2317ab47cfaaSmrg    x2 = src_x + src_w;
2318ab47cfaaSmrg    y1 = src_y;
2319ab47cfaaSmrg    y2 = src_y + src_h;
2320ab47cfaaSmrg
2321ab47cfaaSmrg    dstBox.x1 = drw_x;
2322ab47cfaaSmrg    dstBox.x2 = drw_x + drw_w;
2323ab47cfaaSmrg    dstBox.y1 = drw_y;
2324ab47cfaaSmrg    dstBox.y2 = drw_y + drw_h;
2325ab47cfaaSmrg
2326ab47cfaaSmrg    SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
2327ab47cfaaSmrg                	REGION_EXTENTS(pScreen, clipBoxes),
2328ab47cfaaSmrg			surface->width, surface->height);
2329ab47cfaaSmrg
2330ab47cfaaSmrg    if((x1 >= x2) || (y1 >= y2))
2331ab47cfaaSmrg	return Success;
2332ab47cfaaSmrg
2333ab47cfaaSmrg    dstBox.x1 -= pScrn->frameX0;
2334ab47cfaaSmrg    dstBox.x2 -= pScrn->frameX0;
2335ab47cfaaSmrg    dstBox.y1 -= pScrn->frameY0;
2336ab47cfaaSmrg    dstBox.y2 -= pScrn->frameY0;
2337ab47cfaaSmrg
2338ab47cfaaSmrg    SavageDisplayVideo(pScrn, surface->id, surface->offsets[0],
2339ab47cfaaSmrg	     surface->width, surface->height, surface->pitches[0],
2340ab47cfaaSmrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
2341ab47cfaaSmrg
2342aa9e3350Smrg    xf86XVFillKeyHelper(pScreen, portPriv->colorKey, clipBoxes);
2343ab47cfaaSmrg
2344ab47cfaaSmrg    pPriv->isOn = TRUE;
2345ab47cfaaSmrg#if 0
2346ab47cfaaSmrg    if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
2347ab47cfaaSmrg	REGION_EMPTY(pScreen, &portPriv->clip);
2348ab47cfaaSmrg	UpdateCurrentTime();
2349ab47cfaaSmrg	portPriv->videoStatus = FREE_TIMER;
2350ab47cfaaSmrg	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
2351ab47cfaaSmrg    }
2352ab47cfaaSmrg#endif
2353ab47cfaaSmrg
2354ab47cfaaSmrg    return Success;
2355ab47cfaaSmrg}
2356ab47cfaaSmrg
2357ab47cfaaSmrg
2358ab47cfaaSmrgstatic void
2359ab47cfaaSmrgSavageInitOffscreenImages(ScreenPtr pScreen)
2360ab47cfaaSmrg{
2361ab47cfaaSmrg    XF86OffscreenImagePtr offscreenImages;
2362aa9e3350Smrg    SavagePtr psav = SAVPTR(xf86ScreenToScrn(pScreen));
2363ab47cfaaSmrg
2364ab47cfaaSmrg    /* need to free this someplace */
2365ab47cfaaSmrg    if (!psav->offscreenImages) {
2366aa9e3350Smrg	if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec))))
2367ab47cfaaSmrg	    return;
2368ab47cfaaSmrg	psav->offscreenImages = offscreenImages;
2369ab47cfaaSmrg    } else {
2370ab47cfaaSmrg	offscreenImages = psav->offscreenImages;
2371ab47cfaaSmrg    }
2372ab47cfaaSmrg
2373ab47cfaaSmrg    offscreenImages[0].image = &Images[0];
2374ab47cfaaSmrg    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
2375ab47cfaaSmrg			       VIDEO_CLIP_TO_VIEWPORT;
2376ab47cfaaSmrg    offscreenImages[0].alloc_surface = SavageAllocateSurface;
2377ab47cfaaSmrg    offscreenImages[0].free_surface = SavageFreeSurface;
2378ab47cfaaSmrg    offscreenImages[0].display = SavageDisplaySurface;
2379ab47cfaaSmrg    offscreenImages[0].stop = SavageStopSurface;
2380ab47cfaaSmrg    offscreenImages[0].setAttribute = SavageSetSurfaceAttribute;
2381ab47cfaaSmrg    offscreenImages[0].getAttribute = SavageGetSurfaceAttribute;
2382ab47cfaaSmrg    offscreenImages[0].max_width = 1024;
2383ab47cfaaSmrg    offscreenImages[0].max_height = 1024;
2384ab47cfaaSmrg    offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
2385ab47cfaaSmrg    offscreenImages[0].attributes = Attributes;
2386ab47cfaaSmrg
2387ab47cfaaSmrg    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
2388ab47cfaaSmrg}
2389ab47cfaaSmrg
2390