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