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 
52 void savageOUTREG( SavagePtr psav, unsigned long offset, unsigned long value );
53 
54 static XF86VideoAdaptorPtr SavageSetupImageVideo(ScreenPtr);
55 static void SavageInitOffscreenImages(ScreenPtr);
56 static void SavageStopVideo(ScrnInfoPtr, pointer, Bool);
57 static int SavageSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
58 static int SavageGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
59 static void SavageQueryBestSize(ScrnInfoPtr, Bool,
60 	short, short, short, short, unsigned int *, unsigned int *, pointer);
61 static int SavagePutImage( ScrnInfoPtr,
62 	short, short, short, short, short, short, short, short,
63 	int, unsigned char*, short, short, Bool, RegionPtr, pointer,
64 	DrawablePtr);
65 static int SavageQueryImageAttributes(ScrnInfoPtr,
66 	int, unsigned short *, unsigned short *,  int *, int *);
67 static void SavageFreeMemory(ScrnInfoPtr pScrn, void *mem_struct);
68 
69 void SavageResetVideo(ScrnInfoPtr pScrn);
70 
71 static void SavageSetColorKeyOld(ScrnInfoPtr pScrn);
72 static void SavageSetColorKeyNew(ScrnInfoPtr pScrn);
73 static void SavageSetColorKey2000(ScrnInfoPtr pScrn);
74 static void (*SavageSetColorKey)(ScrnInfoPtr pScrn) = NULL;
75 
76 static void SavageSetColorOld(ScrnInfoPtr pScrn );
77 static void SavageSetColorNew(ScrnInfoPtr pScrn );
78 static void SavageSetColor2000(ScrnInfoPtr pScrn );
79 static void (*SavageSetColor)(ScrnInfoPtr pScrn ) = NULL;
80 
81 static void (*SavageInitStreams)(ScrnInfoPtr pScrn) = NULL;
82 
83 static 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 );
91 static 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 );
99 static 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 );
107 static 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 
122 static Atom xvColorKey, xvBrightness, xvContrast, xvSaturation, xvHue, xvInterpolation;
123 
124 /* client libraries expect an encoding */
125 static 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 
137 static XF86VideoFormatRec Formats[NUM_FORMATS] =
138 {
139   {8, PseudoColor},  {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
140 };
141 
142 #define NUM_ATTRIBUTES 6
143 
144 static 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 
169 static 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 
229 typedef 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 SAVAGEDRI
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 
263 static
GetBlendForFourCC(int id)264 unsigned 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 
282 static
GetBlendForFourCC2000(int id)283 unsigned 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 
savageOUTREG(SavagePtr psav,unsigned long offset,unsigned long value)304 void savageOUTREG( SavagePtr psav, unsigned long offset, unsigned long value )
305 {
306     ErrorF( "MMIO %08lx, was %08x, want %08lx,",
307 	offset, (CARD32)MMIO_IN32( psav->MapBase, offset ), value );
308     MMIO_OUT32( psav->MapBase, offset, value );
309     ErrorF( " now %08x\n", (CARD32)MMIO_IN32( psav->MapBase, offset ) );
310 }
311 
312 #if 0
313 static void
314 SavageClipVWindow(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 
SavageInitVideo(ScreenPtr pScreen)339 void SavageInitVideo(ScreenPtr pScreen)
340 {
341     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
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         	malloc((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 	free(newAdaptors);
403 
404     if( newAdaptor )
405     {
406 	psav->videoFourCC = 0;
407     }
408 }
409 
410 
SavageSetColorKeyOld(ScrnInfoPtr pScrn)411 void 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 
SavageSetColorKeyNew(ScrnInfoPtr pScrn)461 void 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 
SavageSetColorKey2000(ScrnInfoPtr pScrn)608 void 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 
SavageSetColorOld(ScrnInfoPtr pScrn)658 void 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 
SavageSetColorNew(ScrnInfoPtr pScrn)692 void 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 
SavageSetColor2000(ScrnInfoPtr pScrn)768 void 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 
SavageResetVideo(ScrnInfoPtr pScrn)869 void SavageResetVideo(ScrnInfoPtr pScrn)
870 {
871     xf86ErrorFVerb(XVTRACE,"SavageResetVideo\n");
872     SavageSetColor( pScrn );
873     SavageSetColorKey( pScrn );
874 }
875 
876 
877 static XF86VideoAdaptorPtr
SavageSetupImageVideo(ScreenPtr pScreen)878 SavageSetupImageVideo(ScreenPtr pScreen)
879 {
880     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
881     SavagePtr psav = SAVPTR(pScrn);
882     XF86VideoAdaptorPtr adapt;
883     SavagePortPrivPtr pPriv;
884 
885     xf86ErrorFVerb(XVTRACE,"SavageSetupImageVideo\n");
886 
887     if(!(adapt = calloc(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 
971 static void
SavageClipVideo(BoxPtr dst,INT32 * x1,INT32 * x2,INT32 * y1,INT32 * y2,BoxPtr extents,INT32 width,INT32 height)972 SavageClipVideo(
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 
1036 static void
SavageStopVideo(ScrnInfoPtr pScrn,pointer data,Bool shutdown)1037 SavageStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
1038 {
1039     SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1040     SavagePtr psav = SAVPTR(pScrn);
1041 
1042     xf86ErrorFVerb(XVTRACE,"SavageStopVideo\n");
1043 
1044     REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1045 
1046     if(shutdown) {
1047       /*SavageClipVWindow(pScrn);*/
1048  	SavageStreamsOff( pScrn );
1049 
1050 #ifdef SAVAGEDRI
1051 	if (pPriv->agpBufferMap != NULL) {
1052 	    SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
1053 
1054             /* agpXVideo is reused to implement UploadToScreen in EXA */
1055             if (!psav->useEXA) {
1056 	        drmUnmap(pPriv->agpBufferMap, pSAVAGEDRIServer->agpXVideo.size);
1057 	        pSAVAGEDRIServer->agpXVideo.map = NULL;
1058             }
1059 	    pPriv->agpBufferMap = NULL;
1060 	    pPriv->agpBufferOffset = 0;
1061 	}
1062 	pPriv->tried_agp = FALSE;
1063 #endif
1064 
1065         if (pPriv->video_memory != NULL) {
1066 	    SavageFreeMemory(pScrn, pPriv->video_memory);
1067 	    pPriv->video_memory = NULL;
1068         }
1069         if (pPriv->video_planarmem != NULL) {
1070 	    SavageFreeMemory(pScrn, pPriv->video_planarmem);
1071 	    pPriv->video_planarmem = NULL;
1072         }
1073 	pPriv->videoStatus = 0;
1074     } else {
1075 	if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
1076 	    pPriv->videoStatus |= OFF_TIMER;
1077 	    pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
1078 	}
1079     }
1080 }
1081 
1082 
1083 static int
SavageSetPortAttribute(ScrnInfoPtr pScrn,Atom attribute,INT32 value,pointer data)1084 SavageSetPortAttribute(
1085     ScrnInfoPtr pScrn,
1086     Atom attribute,
1087     INT32 value,
1088     pointer data
1089 ){
1090     SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1091     SavagePtr psav = SAVPTR(pScrn);
1092 
1093     if(attribute == xvColorKey) {
1094 	pPriv->colorKey = value;
1095 	if( psav->videoFlags & VF_STREAMS_ON)
1096 	    SavageSetColorKey( pScrn );
1097 	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1098     }
1099     else if( attribute == xvBrightness) {
1100 	if((value < -128) || (value > 127))
1101 	    return BadValue;
1102 	pPriv->brightness = value;
1103 	if( psav->videoFlags & VF_STREAMS_ON)
1104 	    SavageSetColor( pScrn );
1105     }
1106     else if( attribute == xvContrast) {
1107 	if((value < 0) || (value > 255))
1108 	    return BadValue;
1109 	pPriv->contrast = value;
1110 	if( psav->videoFlags & VF_STREAMS_ON)
1111 	    SavageSetColor( pScrn );
1112     }
1113     else if( attribute == xvSaturation) {
1114 	if((value < 0) || (value > 255))
1115 	    return BadValue;
1116 	pPriv->saturation = value;
1117 	if( psav->videoFlags & VF_STREAMS_ON)
1118 	    SavageSetColor( pScrn );
1119     }
1120     else if( attribute == xvHue) {
1121 	if((value < -180) || (value > 180))
1122 	    return BadValue;
1123 	pPriv->hue = value;
1124 	if( psav->videoFlags & VF_STREAMS_ON)
1125 	    SavageSetColor( pScrn );
1126     }
1127     else if( attribute == xvInterpolation) {
1128         if((value < 0) || (value > 1))
1129             return BadValue;
1130         if (value == 1)
1131             pPriv->interpolation = TRUE;
1132 	else
1133 	    pPriv->interpolation = FALSE;
1134     }
1135     else
1136 	return BadMatch;
1137 
1138     return Success;
1139 }
1140 
1141 
1142 static int
SavageGetPortAttribute(ScrnInfoPtr pScrn,Atom attribute,INT32 * value,pointer data)1143 SavageGetPortAttribute(
1144   ScrnInfoPtr pScrn,
1145   Atom attribute,
1146   INT32 *value,
1147   pointer data
1148 ){
1149     SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1150 
1151     if(attribute == xvColorKey) {
1152 	*value = pPriv->colorKey;
1153     }
1154     else if( attribute == xvBrightness ) {
1155 	*value = pPriv->brightness;
1156     }
1157     else if( attribute == xvContrast ) {
1158 	*value = pPriv->contrast;
1159     }
1160     else if( attribute == xvHue ) {
1161 	*value = pPriv->hue;
1162     }
1163     else if( attribute == xvSaturation ) {
1164 	*value = pPriv->saturation;
1165     }
1166     else if( attribute == xvInterpolation ) {
1167         *value = pPriv->interpolation;
1168     }
1169     else return BadMatch;
1170 
1171     return Success;
1172 }
1173 
1174 static void
SavageQueryBestSize(ScrnInfoPtr pScrn,Bool motion,short vid_w,short vid_h,short drw_w,short drw_h,unsigned int * p_w,unsigned int * p_h,pointer data)1175 SavageQueryBestSize(
1176   ScrnInfoPtr pScrn,
1177   Bool motion,
1178   short vid_w, short vid_h,
1179   short drw_w, short drw_h,
1180   unsigned int *p_w, unsigned int *p_h,
1181   pointer data
1182 ){
1183     /* What are the real limits for the Savage? */
1184 
1185     *p_w = drw_w;
1186     *p_h = drw_h;
1187 
1188     if(*p_w > 16384) *p_w = 16384;
1189 }
1190 
1191 /* SavageCopyPlanarDataBCI() causes artifacts on the screen when used on savage4.
1192  * It's probably something with the BCI.  Maybe we need a waitforidle() or
1193  * something...
1194  */
1195 static void
SavageCopyPlanarDataBCI(ScrnInfoPtr pScrn,unsigned char * srcY,unsigned char * srcV,unsigned char * srcU,unsigned char * dst,unsigned char * planarPtr,unsigned long planarOffset,int srcPitch,int srcPitch2,int dstPitch,int h,int w,Bool isAGP)1196 SavageCopyPlanarDataBCI(
1197     ScrnInfoPtr pScrn,
1198     unsigned char *srcY, /* Y */
1199     unsigned char *srcV, /* V */
1200     unsigned char *srcU, /* U */
1201     unsigned char *dst,
1202     unsigned char * planarPtr,
1203     unsigned long planarOffset,
1204     int srcPitch, int srcPitch2,
1205     int dstPitch,
1206     int h,int w,
1207     Bool isAGP)
1208 {
1209     SavagePtr psav = SAVPTR(pScrn);
1210 
1211     /* for pixel transfer */
1212     unsigned long offsetY = planarOffset;
1213     unsigned long offsetV = offsetY +  srcPitch * h;
1214     unsigned long offsetU = offsetV +  srcPitch2 * (h>>1);
1215     unsigned long dstOffset  = (unsigned long)dst - (unsigned long)psav->FBBase;
1216     unsigned char memType;
1217 
1218     BCI_GET_PTR;
1219 
1220     /* copy Y planar */
1221     memcpy(planarPtr, srcY, srcPitch * h);
1222 
1223     /* copy V planar */
1224     planarPtr = planarPtr + srcPitch * h;
1225     memcpy(planarPtr, srcV, srcPitch2 * (h>>1));
1226 
1227     /* copy U planar */
1228     planarPtr = planarPtr + srcPitch2 * (h>>1);
1229     memcpy(planarPtr, srcU, srcPitch2 * (h>>1));
1230 
1231     memType = isAGP ? 3 : 0;
1232 
1233     /*
1234      * Transfer pixel data from one memory location to another location
1235      * and reformat the data during the transfer
1236      * a. program BCI51 to specify the source information
1237      * b. program BCI52 to specify the destination information
1238      * c. program BCI53 to specify the source dimensions
1239      * d. program BCI54 to specify the destination dimensions
1240      * e. (if the data is in YCbCr420 format)program BCI55,BCI56,BCI57 to
1241      *    locations of the Y,Cb,and Cr data
1242      * f. program BCI50(command=011) to specify the formatting options and
1243      *    kick off the transfer
1244      * this command can be used for color space conversion(YCbCr to RGB)
1245      * or for oversampling, but not for both simultaneously. it can also be
1246      * used to do mastered image transfer when the source is tiled
1247      */
1248 
1249     w = (w+0xf)&0xff0;
1250     psav->WaitQueue(psav,11);
1251     BCI_SEND(BCI_SET_REGISTER | BCI_SET_REGISTER_COUNT(7) | 0x51);
1252     BCI_SEND(offsetY | memType);
1253     BCI_SEND(dstOffset);
1254     BCI_SEND(((h-1)<<16)|((w-1)>>3));
1255     BCI_SEND(dstPitch >> 3);
1256     BCI_SEND(offsetU | memType);
1257     BCI_SEND(offsetV | memType);
1258     BCI_SEND((srcPitch2 << 16)| srcPitch2);
1259 
1260     BCI_SEND(BCI_SET_REGISTER | BCI_SET_REGISTER_COUNT(1) | 0x50);
1261     BCI_SEND(0x00200003 | srcPitch);
1262 
1263     BCI_SEND(0xC0170000);
1264 }
1265 
1266 static void
SavageCopyData(unsigned char * src,unsigned char * dst,int srcPitch,int dstPitch,int h,int w)1267 SavageCopyData(
1268   unsigned char *src,
1269   unsigned char *dst,
1270   int srcPitch,
1271   int dstPitch,
1272   int h,
1273   int w
1274 ){
1275     w <<= 1;
1276     if (w == srcPitch && w == dstPitch) {
1277         memcpy(dst, src, w * h);
1278     } else
1279     while(h--) {
1280 	memcpy(dst, src, w);
1281 	src += srcPitch;
1282 	dst += dstPitch;
1283     }
1284 }
1285 
1286 static void
SavageCopyPlanarData(unsigned char * src1,unsigned char * src2,unsigned char * src3,unsigned char * dst1,int srcPitch,int srcPitch2,int dstPitch,int h,int w)1287 SavageCopyPlanarData(
1288    unsigned char *src1, /* Y */
1289    unsigned char *src2, /* V */
1290    unsigned char *src3, /* U */
1291    unsigned char *dst1,
1292    int srcPitch,
1293    int srcPitch2,
1294    int dstPitch,
1295    int h,
1296    int w
1297 ){
1298    CARD32 *dst = (CARD32*)dst1;
1299    int i, j;
1300 
1301    dstPitch >>= 2;
1302    w >>= 1;
1303 
1304    for(j = 0; j < h; j++) {
1305 	for(i = 0; i < w; i++) {
1306 /* Shouldn't this be 'if LITTLEENDIAN'? */
1307 #if 1
1308 	    dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
1309 		     (src3[i] << 8) | (src2[i] << 24);
1310 #else
1311 	    dst[i] = (src1[i << 1] << 24) | (src1[(i << 1) + 1] << 8) |
1312 		     (src3[i] << 0) | (src2[i] << 16);
1313 #endif
1314 	}
1315 	dst += dstPitch;
1316 	src1 += srcPitch;
1317 	if(j & 1) {
1318 	    src2 += srcPitch2;
1319 	    src3 += srcPitch2;
1320 	}
1321    }
1322 }
1323 
1324 static void
SavageVideoSave(ScreenPtr pScreen,ExaOffscreenArea * area)1325 SavageVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
1326 {
1327     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1328     SavagePtr psav = SAVPTR(pScrn);
1329     SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1330 
1331     if (pPriv->video_memory == area)
1332         pPriv->video_memory = NULL;
1333     if (pPriv->video_planarmem == area)
1334         pPriv->video_planarmem = NULL;
1335 }
1336 
1337 static CARD32
SavageAllocateMemory(ScrnInfoPtr pScrn,void ** mem_struct,int size)1338 SavageAllocateMemory(
1339     ScrnInfoPtr pScrn,
1340     void **mem_struct,
1341     int size
1342 ){
1343     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
1344     SavagePtr psav = SAVPTR(pScrn);
1345     int offset = 0;
1346 
1347     if (psav->useEXA) {
1348 	ExaOffscreenArea *area = *mem_struct;
1349 
1350 	if (area != NULL) {
1351 	    if (area->size >= size)
1352 		return area->offset;
1353 
1354 	    exaOffscreenFree(pScrn->pScreen, area);
1355 	}
1356 
1357 	area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, SavageVideoSave,
1358 				 NULL);
1359 	*mem_struct = area;
1360 	if (area == NULL)
1361 	    return 0;
1362 	offset = area->offset;
1363     }
1364 
1365     if (!psav->useEXA) {
1366 	FBLinearPtr linear = *mem_struct;
1367 	int cpp = pScrn->bitsPerPixel / 8;
1368 
1369 	/* XAA allocates in units of pixels at the screen bpp, so adjust size
1370 	 * appropriately.
1371 	 */
1372 	size = (size + cpp - 1) / cpp;
1373 
1374 	if (linear) {
1375 	    if(linear->size >= size)
1376 		return linear->offset * cpp;
1377 
1378 	    if(xf86ResizeOffscreenLinear(linear, size))
1379 		return linear->offset * cpp;
1380 
1381 	    xf86FreeOffscreenLinear(linear);
1382 	}
1383 
1384 	linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
1385 						NULL, NULL, NULL);
1386 	*mem_struct = linear;
1387 
1388 	if (!linear) {
1389 	    int max_size;
1390 
1391 	    xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
1392 					    PRIORITY_EXTREME);
1393 
1394 	    if(max_size < size)
1395 		return 0;
1396 
1397 	    xf86PurgeUnlockedOffscreenAreas(pScreen);
1398 	    linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
1399 						     NULL, NULL, NULL);
1400 	    *mem_struct = linear;
1401 	    if (!linear)
1402 		return 0;
1403 	}
1404 	offset = linear->offset * cpp;
1405     }
1406 
1407     return offset;
1408 }
1409 
1410 static void
SavageFreeMemory(ScrnInfoPtr pScrn,void * mem_struct)1411 SavageFreeMemory(
1412    ScrnInfoPtr pScrn,
1413    void *mem_struct
1414 ){
1415     SavagePtr psav = SAVPTR(pScrn);
1416 
1417     if (psav->useEXA) {
1418 	ExaOffscreenArea *area = mem_struct;
1419 
1420 	if (area != NULL)
1421 	    exaOffscreenFree(pScrn->pScreen, area);
1422     }
1423     if (!psav->useEXA) {
1424 	FBLinearPtr linear = mem_struct;
1425 
1426 	if (linear != NULL)
1427 	    xf86FreeOffscreenLinear(linear);
1428     }
1429 }
1430 
1431 static void
SavageSetBlend(ScrnInfoPtr pScrn,int id)1432 SavageSetBlend(ScrnInfoPtr pScrn, int id)
1433 {
1434     SavagePtr psav = SAVPTR(pScrn);
1435 
1436     if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) )
1437     {
1438 	psav->blendBase = GetBlendForFourCC( id );
1439 	xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase );
1440 	if (psav->IsSecondary) {
1441 	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
1442 	} else if (psav->IsPrimary) {
1443 	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
1444 	} else {
1445 	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 ));
1446 #if 0
1447 	    OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) ));
1448 #endif
1449 	}
1450     } else if (psav->Chipset == S3_SAVAGE2000) {
1451       psav->blendBase = GetBlendForFourCC2000( id );
1452       xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase );
1453       if (id != FOURCC_YV12)
1454 	OUTREG( BLEND_CONTROL,
1455 		((psav->blendBase << 24) | (8 << 2) /*| 0x20000000*/));
1456       else
1457 	OUTREG( BLEND_CONTROL,
1458 		((psav->blendBase << 24) | (8 << 2) /*| 0x10000000*/));
1459     }
1460 
1461     psav->videoFourCC = id;
1462 }
1463 
1464 static void
SavageDisplayVideoOld(ScrnInfoPtr pScrn,int id,int offset,short width,short height,int pitch,int x1,int y1,int x2,int y2,BoxPtr dstBox,short src_w,short src_h,short drw_w,short drw_h)1465 SavageDisplayVideoOld(
1466     ScrnInfoPtr pScrn,
1467     int id,
1468     int offset,
1469     short width, short height,
1470     int pitch,
1471     int x1, int y1, int x2, int y2,
1472     BoxPtr dstBox,
1473     short src_w, short src_h,
1474     short drw_w, short drw_h
1475 ){
1476     SavagePtr psav = SAVPTR(pScrn);
1477     vgaHWPtr hwp = VGAHWPTR(pScrn);
1478     SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1479     /*DisplayModePtr mode = pScrn->currentMode;*/
1480     int vgaCRIndex, vgaCRReg, vgaIOBase;
1481     CARD32 ssControl;
1482     int scalratio;
1483 
1484 
1485     vgaIOBase = hwp->IOBase;
1486     vgaCRIndex = vgaIOBase + 4;
1487     vgaCRReg = vgaIOBase + 5;
1488 #if 0
1489     if ( psav->videoFourCC != id ) {
1490 	SavageSetBlend(pScrn,id);
1491 	SavageResetVideo(pScrn);
1492     }
1493 #endif
1494     if( psav->videoFourCC != id )
1495       SavageStreamsOff(pScrn);
1496 
1497     if( !(psav->videoFlags & VF_STREAMS_ON) )
1498       {
1499         SavageSetBlend(pScrn,id);
1500 	SavageStreamsOn(pScrn);
1501 	SavageResetVideo(pScrn);
1502 	pPriv->lastKnownPitch = 0;
1503       }
1504 
1505     if (S3_MOBILE_TWISTER_SERIES(psav->Chipset)
1506 	&& psav->FPExpansion) {
1507 	drw_w = (drw_w * psav->XExp1) / psav->XExp2 + 1;
1508 	drw_h = (drw_h * psav->YExp1) / psav->YExp2 + 1;
1509 	dstBox->x1 = (dstBox->x1 * psav->XExp1) / psav->XExp2;
1510 	dstBox->y1 = (dstBox->y1 * psav->YExp1) / psav->YExp2;
1511 	dstBox->x2 = (dstBox->x2 * psav->XExp1) / psav->XExp2;
1512 	dstBox->y2 = (dstBox->y2 * psav->YExp1) / psav->YExp2;
1513 	dstBox->x1 += psav->displayXoffset;
1514 	dstBox->y1 += psav->displayYoffset;
1515 	dstBox->x2 += psav->displayXoffset;
1516 	dstBox->y2 += psav->displayYoffset;
1517     }
1518 
1519     /*
1520      * Process horizontal scaling
1521      *  upscaling and downscaling smaller than 2:1 controled by MM8198
1522      *  MM8190 controls downscaling mode larger than 2:1
1523      *  Together MM8190 and MM8198 can set arbitrary downscale up to 64:1
1524      */
1525     scalratio = 0;
1526     ssControl = 0;
1527 
1528     if (src_w >= (drw_w * 2)) {
1529         if (src_w < (drw_w * 4)) {
1530             ssControl |= HDSCALE_4;
1531             scalratio = HSCALING(src_w,(drw_w*4));
1532         } else if (src_w < (drw_w * 8)) {
1533             ssControl |= HDSCALE_8;
1534             scalratio = HSCALING(src_w,(drw_w*8));
1535         } else if (src_w < (drw_w * 16)) {
1536             ssControl |= HDSCALE_16;
1537             scalratio = HSCALING(src_w,(drw_w*16));
1538         } else if (src_w < (drw_w * 32)) {
1539             ssControl |= HDSCALE_32;
1540             scalratio = HSCALING(src_w,(drw_w*32));
1541         } else if (src_w < (drw_w * 64)) {
1542             ssControl |= HDSCALE_64;
1543             scalratio = HSCALING(src_w,(drw_w*64));
1544         } else {
1545             /* Request beyond maximum downscale! */
1546             ssControl |= HDSCALE_64;
1547             scalratio = HSCALING(2,1);
1548         }
1549     } else
1550         scalratio = HSCALING(src_w,drw_w);
1551 
1552     ssControl |= src_w;
1553     /*ssControl |= (1 << 24);*/
1554     ssControl |= (GetBlendForFourCC(psav->videoFourCC) << 24);
1555 #if 0
1556     /* Wait for VBLANK. */
1557     VerticalRetraceWait();
1558 #endif
1559     OUTREG(SSTREAM_CONTROL_REG, ssControl);
1560     if (scalratio)
1561         OUTREG(SSTREAM_STRETCH_REG,scalratio);
1562 
1563     /* Calculate vertical scale factor. */
1564     OUTREG(SSTREAM_VINITIAL_REG, 0 );
1565     /*OUTREG(SSTREAM_VSCALE_REG, (src_h << 15) / drw_h );*/
1566     OUTREG(SSTREAM_VSCALE_REG, VSCALING(src_h,drw_h));
1567 
1568     /* Set surface location and stride. */
1569     OUTREG(SSTREAM_FBADDR0_REG, (offset + (x1>>15)) & (0x1ffffff & ~BASE_PAD) );
1570     OUTREG(SSTREAM_FBADDR1_REG, 0);
1571     OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff );
1572 
1573     OUTREG(SSTREAM_WINDOW_START_REG, OS_XY(dstBox->x1, dstBox->y1) );
1574     OUTREG(SSTREAM_WINDOW_SIZE_REG, OS_WH(dstBox->x2-dstBox->x1,
1575                                           dstBox->y2-dstBox->y1));
1576 
1577     /*
1578      * MM81E8:Secondary Stream Source Line Count
1579      *   bit_0~10: # of lines in the source image (before scaling)
1580      *   bit_15 = 1: Enable vertical interpolation
1581      *            0: Line duplicaion
1582      */
1583     /*
1584      * Vertical Interpolation is very bandwidth intensive.  Some savages can't
1585      * seem to handle it.  Default is line doubling.  --AGD
1586      */
1587     if (pPriv->interpolation) {
1588         if (src_w * 16 <= 0x3300) {
1589             OUTREG(SSTREAM_LINES_REG, 0x8000 | src_h );
1590 	    OUTREG(FIFO_CONTROL, (INREG(FIFO_CONTROL) + 1));
1591         } else {
1592             OUTREG(SSTREAM_LINES_REG, src_h );
1593         }
1594     } else {
1595         OUTREG(SSTREAM_LINES_REG, src_h );
1596     }
1597 
1598 #if 0
1599     /* Set color key on primary. */
1600 
1601     SavageSetColorKey( pScrn );
1602 #endif
1603 
1604     /* Set FIFO L2 on second stream. */
1605 
1606     if( pPriv->lastKnownPitch != pitch )
1607     {
1608 	unsigned char cr92;
1609 
1610 	pPriv->lastKnownPitch = pitch;
1611 
1612 	pitch = (pitch + 7) / 8;
1613 	VGAOUT8(vgaCRIndex, 0x92);
1614 	cr92 = VGAIN8(vgaCRReg);
1615 	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1616 	VGAOUT8(vgaCRIndex, 0x93);
1617 	if (psav->bTiled && (( drw_h > src_h) || (drw_w > src_w)))
1618 	    VGAOUT8(vgaCRReg, pitch | 0xf);
1619 	else
1620 	    VGAOUT8(vgaCRReg, pitch);
1621     }
1622 }
1623 
1624 static void
SavageDisplayVideoNew(ScrnInfoPtr pScrn,int id,int offset,short width,short height,int pitch,int x1,int y1,int x2,int y2,BoxPtr dstBox,short src_w,short src_h,short drw_w,short drw_h)1625 SavageDisplayVideoNew(
1626     ScrnInfoPtr pScrn,
1627     int id,
1628     int offset,
1629     short width, short height,
1630     int pitch,
1631     int x1, int y1, int x2, int y2,
1632     BoxPtr dstBox,
1633     short src_w, short src_h,
1634     short drw_w, short drw_h
1635 ){
1636     SavagePtr psav = SAVPTR(pScrn);
1637     vgaHWPtr hwp = VGAHWPTR(pScrn);
1638     /*DisplayModePtr mode = pScrn->currentMode;*/
1639     SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1640     int vgaCRIndex, vgaCRReg, vgaIOBase;
1641 
1642 
1643     vgaIOBase = hwp->IOBase;
1644     vgaCRIndex = vgaIOBase + 4;
1645     vgaCRReg = vgaIOBase + 5;
1646 #if 0
1647     if ( psav->videoFourCC != id ) {
1648 	SavageSetBlend(pScrn,id);
1649 	SavageResetVideo(pScrn);
1650     }
1651 #endif
1652     if( psav->videoFourCC != id )
1653       SavageStreamsOff(pScrn);
1654 
1655     if( !(psav->videoFlags & VF_STREAMS_ON) )
1656       {
1657 	SavageSetBlend(pScrn,id);
1658 	SavageStreamsOn(pScrn);
1659 	SavageResetVideo(pScrn);
1660 	pPriv->lastKnownPitch = 0;
1661       }
1662 
1663     /* Calculate horizontal and vertical scale factors. */
1664 
1665     if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) &&
1666 	    (psav->DisplayType == MT_LCD) &&
1667 	    !psav->CrtOnly &&
1668 	    !psav->TvOn)
1669     {
1670 	drw_w = (drw_w * psav->XExp1) / psav->XExp2 + 1;
1671 	drw_h = (drw_h * psav->YExp1) / psav->YExp2 + 1;
1672 	dstBox->x1 = (dstBox->x1 * psav->XExp1) / psav->XExp2;
1673 	dstBox->y1 = (dstBox->y1 * psav->YExp1) / psav->YExp2;
1674 	dstBox->x2 = (dstBox->x2 * psav->XExp1) / psav->XExp2;
1675 	dstBox->y2 = (dstBox->y2 * psav->YExp1) / psav->YExp2;
1676 	dstBox->x1 += psav->displayXoffset;
1677 	dstBox->y1 += psav->displayYoffset;
1678 	dstBox->x2 += psav->displayXoffset;
1679 	dstBox->y2 += psav->displayYoffset;
1680     }
1681 
1682 	if (psav->IsSecondary) {
1683 	    OUTREG(SEC_STREAM2_HSCALING,
1684 	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1685 	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1686 	    OUTREG(SEC_STREAM2_VSCALING,
1687 	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1688 	} else if (psav->IsPrimary) {
1689 	    OUTREG(SEC_STREAM_HSCALING,
1690 	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1691 	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1692 	    OUTREG(SEC_STREAM_VSCALING,
1693 	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1694 	} else {
1695 	    OUTREG(SEC_STREAM_HSCALING,
1696 	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1697 	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1698 	    OUTREG(SEC_STREAM_VSCALING,
1699 	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1700 #if 0
1701 	    OUTREG(SEC_STREAM2_HSCALING,
1702 	        ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
1703 	    /* BUGBUG need to add 00040000 if src stride > 2048 */
1704 	    OUTREG(SEC_STREAM2_VSCALING,
1705 	        ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF ));
1706 #endif
1707 	}
1708 
1709     /*
1710      * Set surface location and stride.  We use x1>>15 because all surfaces
1711      * are 2 bytes/pixel.
1712      */
1713 
1714     if (psav->IsSecondary) {
1715         OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15))
1716 	   & (0x7ffffff & ~BASE_PAD));
1717         OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff );
1718         OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1719         OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1720 	   | (dstBox->y2 - dstBox->y1) );
1721     } else if (psav->IsPrimary) {
1722         OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15))
1723 	   & (0x7ffffff & ~BASE_PAD));
1724         OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff );
1725         OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1726         OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1727 	   | (dstBox->y2 - dstBox->y1) );
1728     } else {
1729         OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15))
1730 	   & (0x7ffffff & ~BASE_PAD));
1731         OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff );
1732         OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1733         OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1734 	   | (dstBox->y2 - dstBox->y1) );
1735 #if 0
1736         OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15))
1737 	   & (0x7ffffff & ~BASE_PAD));
1738         OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff );
1739         OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) );
1740         OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16)
1741 	   | (dstBox->y2 - dstBox->y1) );
1742 #endif
1743     }
1744 
1745 #if 0
1746     /* Set color key on primary. */
1747 
1748     SavageSetColorKey( pScrn );
1749 #endif
1750 
1751     /* Set FIFO L2 on second stream. */
1752     /* Is CR92 shadowed for crtc2? -- AGD */
1753     if( pPriv->lastKnownPitch != pitch )
1754     {
1755 	unsigned char cr92;
1756 
1757 	pPriv->lastKnownPitch = pitch;
1758 	pitch = (pitch + 7) / 8 - 4;
1759 	VGAOUT8(vgaCRIndex, 0x92);
1760 	cr92 = VGAIN8(vgaCRReg);
1761 	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1762 	VGAOUT8(vgaCRIndex, 0x93);
1763 	VGAOUT8(vgaCRReg, pitch);
1764     }
1765 }
1766 
1767 static void
SavageDisplayVideo2000(ScrnInfoPtr pScrn,int id,int offset,short width,short height,int pitch,int x1,int y1,int x2,int y2,BoxPtr dstBox,short src_w,short src_h,short drw_w,short drw_h)1768 SavageDisplayVideo2000(
1769     ScrnInfoPtr pScrn,
1770     int id,
1771     int offset,
1772     short width, short height,
1773     int pitch,
1774     int x1, int y1, int x2, int y2,
1775     BoxPtr dstBox,
1776     short src_w, short src_h,
1777     short drw_w, short drw_h
1778 ){
1779     SavagePtr psav = SAVPTR(pScrn);
1780     vgaHWPtr hwp = VGAHWPTR(pScrn);
1781     /*DisplayModePtr mode = pScrn->currentMode;*/
1782     SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
1783     int vgaCRIndex, vgaCRReg, vgaIOBase;
1784     CARD32 addr0, addr1, addr2;
1785 
1786     vgaIOBase = hwp->IOBase;
1787     vgaCRIndex = vgaIOBase + 4;
1788     vgaCRReg = vgaIOBase + 5;
1789 
1790 
1791     if( psav->videoFourCC != id )
1792         SavageStreamsOff(pScrn);
1793 
1794     if( !(psav->videoFlags & VF_STREAMS_ON) )
1795     {
1796         SavageSetBlend(pScrn,id);
1797         SavageStreamsOn(pScrn);
1798         SavageResetVideo(pScrn);
1799         pPriv->lastKnownPitch = 0;
1800     }
1801 
1802     if (src_w > drw_w)
1803         OUTREG(SEC_STREAM_SRC_START_2000, 0);
1804     else
1805         OUTREG(SEC_STREAM_SRC_START_2000, SRCSTART(x1, y1));
1806 
1807     /*OUTREG(SEC_STREAM_SRC_SIZE_2000, SRCSIZE(src_w, src_h));*/
1808     OUTREG(SEC_STREAM_SRC_SIZE_2000,
1809 	   SRCSIZE((dstBox->x2-dstBox->x1), (dstBox->y2-dstBox->y1)));
1810     /*
1811         buffersize = (src_w * src_h * 2) / 4096;
1812 	  OUTREG(SEC_STREAM_BUFFERSIZE_2000, (buffersize & 0xffffff) << 12);
1813     */
1814 
1815     /*SavageResetVideo(pScrn);*/
1816 
1817     if( src_w > drw_w )
1818 	OUTREG(SEC_STREAM_HSCALE_NORMALIZE, HSCALING_NORMALIZE(drw_w,src_w));
1819     else
1820         OUTREG(SEC_STREAM_HSCALE_NORMALIZE, (2048 << 16));
1821 
1822     /* Calculate horizontal and vertical scale factors. */
1823     if ((src_w > drw_w) || (src_h > drw_h))
1824         OUTREG(SEC_STREAM_HSCALING, (HSCALING_2000(src_w,drw_w)) | 0x01000000);
1825     else
1826         OUTREG(SEC_STREAM_HSCALING, HSCALING_2000(src_w,drw_w));
1827 
1828     OUTREG(SEC_STREAM_VSCALING, VSCALING_2000(src_h,drw_h));
1829 
1830     /*
1831      * Set surface location and stride.  We use x1>>15 because all surfaces
1832      * are 2 bytes/pixel.
1833      */
1834 
1835     addr0 = offset + (x1>>15); /* Y in YCbCr420 */
1836     addr1 = addr0 + (width * height); /* Cb in in YCbCr420 */
1837     addr2 = addr1 + ((width * height) / 4); /* Cr in in YCbCr420 */
1838     OUTREG(SEC_STREAM_FBUF_ADDR0, (addr0) & (0x3fffff & ~BASE_PAD));
1839 #if 0
1840     OUTREG(SEC_STREAM_FBUF_ADDR1, (addr1) & (0x3fffff & ~BASE_PAD));
1841     OUTREG(SEC_STREAM_FBUF_ADDR2, (addr2) & (0x3fffff & ~BASE_PAD));
1842 #endif
1843 
1844     OUTREG(SEC_STREAM_WINDOW_START, XY_2000(dstBox->x1,dstBox->y1));
1845     OUTREG(SEC_STREAM_WINDOW_SZ,
1846 	   WH_2000((dstBox->x2-dstBox->x1),(dstBox->y2-dstBox->y1)));
1847 
1848     /*pitch = width * 2;*/
1849     OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff);
1850 #if 0
1851     /* Y stride + CbCr stride in YCbCr420 */
1852     OUTREG(SEC_STREAM_STRIDE, (pitch & 0xfff) + ((pitch & 0xfff) << 15));
1853 #endif
1854 
1855 #if 0
1856     /* Set color key on primary. */
1857 
1858     SavageSetColorKey2000( pScrn );
1859 #endif
1860 
1861 #if 0
1862     /* Set FIFO L2 on second stream. */
1863     if( pPriv->lastKnownPitch != pitch )
1864     {
1865 	unsigned char cr92;
1866 
1867 	pPriv->lastKnownPitch = pitch;
1868 	pitch = (pitch + 7) / 8 - 4;
1869 	VGAOUT8(vgaCRIndex, 0x92);
1870 	cr92 = VGAIN8(vgaCRReg);
1871 	VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80);
1872 	VGAOUT8(vgaCRIndex, 0x93);
1873 	VGAOUT8(vgaCRReg, pitch);
1874     }
1875 #endif
1876 }
1877 
1878 static void
SavageFillKeyHelper(DrawablePtr pDraw,uint32_t colorKey,RegionPtr clipBoxes)1879 SavageFillKeyHelper(DrawablePtr pDraw, uint32_t colorKey, RegionPtr clipBoxes)
1880 {
1881 #if HAVE_XV_DRAWABLE_HELPER
1882     xf86XVFillKeyHelperDrawable(pDraw, colorKey, clipBoxes);
1883 #else
1884     xf86XVFillKeyHelper(pDraw->pScreen, colorKey, clipBoxes);
1885 #endif
1886 }
1887 
1888 static int
SavagePutImage(ScrnInfoPtr pScrn,short src_x,short src_y,short drw_x,short drw_y,short src_w,short src_h,short drw_w,short drw_h,int id,unsigned char * buf,short width,short height,Bool sync,RegionPtr clipBoxes,pointer data,DrawablePtr pDraw)1889 SavagePutImage(
1890     ScrnInfoPtr pScrn,
1891     short src_x, short src_y,
1892     short drw_x, short drw_y,
1893     short src_w, short src_h,
1894     short drw_w, short drw_h,
1895     int id, unsigned char* buf,
1896     short width, short height,
1897     Bool sync,
1898     RegionPtr clipBoxes, pointer data,
1899     DrawablePtr pDraw
1900 ){
1901     SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
1902     SavagePtr psav = SAVPTR(pScrn);
1903     ScreenPtr pScreen = pScrn->pScreen;
1904     INT32 x1, x2, y1, y2;
1905     unsigned char *dst_start;
1906     int pitch, new_size, offset, offsetV=0, offsetU=0;
1907     int srcPitch, srcPitch2=0, dstPitch;
1908     int planarFrameSize;
1909     int top, left, npixels, nlines;
1910     BoxRec dstBox;
1911     CARD32 tmp;
1912 /*    xf86ErrorFVerb(XVTRACE,"SavagePutImage\n"); */
1913     if(drw_w > 16384) drw_w = 16384;
1914 
1915     /* Clip */
1916     x1 = src_x;
1917     x2 = src_x + src_w;
1918     y1 = src_y;
1919     y2 = src_y + src_h;
1920 
1921     dstBox.x1 = drw_x;
1922     dstBox.x2 = drw_x + drw_w;
1923     dstBox.y1 = drw_y;
1924     dstBox.y2 = drw_y + drw_h;
1925 
1926     SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
1927 		REGION_EXTENTS(pScreen, clipBoxes), width, height);
1928 
1929     drw_w = dstBox.x2 - dstBox.x1;
1930     drw_h = dstBox.y2 - dstBox.y1;
1931     src_w = ( x2 - x1 ) >> 16;
1932     src_h = ( y2 - y1 ) >> 16;
1933 
1934     if((x1 >= x2) || (y1 >= y2))
1935 	return Success;
1936 
1937     dstBox.x1 -= pScrn->frameX0;
1938     dstBox.x2 -= pScrn->frameX0;
1939     dstBox.y1 -= pScrn->frameY0;
1940     dstBox.y2 -= pScrn->frameY0;
1941 
1942     pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
1943 
1944     /* All formats directly displayable by Savage are packed and 2 bytes per pixel */
1945     dstPitch = ((width << 1) + 15) & ~15;
1946     new_size = dstPitch * height;
1947 
1948     switch(id) {
1949     case FOURCC_Y211:		/* Y211 */
1950         srcPitch = width;
1951 	break;
1952     case FOURCC_YV12:		/* YV12 */
1953 	srcPitch = (width + 3) & ~3;
1954 	offsetV = srcPitch * height;
1955 	srcPitch2 = ((width >> 1) + 3) & ~3;
1956 	offsetU = (srcPitch2 * (height >> 1)) + offsetV;
1957 	break;
1958     case FOURCC_I420:
1959 	srcPitch = (width + 3) & ~3;
1960 	offsetU = srcPitch * height;
1961 	srcPitch2 = ((width >> 1) + 3) & ~3;
1962 	offsetV = (srcPitch2 * (height >> 1)) + offsetU;
1963 	break;
1964     case FOURCC_RV15:		/* RGB15 */
1965     case FOURCC_RV16:		/* RGB16 */
1966     case FOURCC_YUY2:		/* YUY2 */
1967     default:
1968 	srcPitch = (width << 1);
1969 	break;
1970     }
1971 
1972     /* Calculate required memory for all planar frames */
1973     planarFrameSize = 0;
1974     if (srcPitch2 != 0 && S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv) {
1975         new_size = ((new_size + 0xF) & ~0xF);
1976         planarFrameSize = srcPitch * height + srcPitch2 * height;
1977     }
1978 
1979     /* Check whether AGP buffers can be allocated. If not, fall back to ordinary
1980        upload to framebuffer (slower) */
1981 #ifdef SAVAGEDRI
1982     if (!pPriv->tried_agp && !psav->IsPCI && psav->drmFD > 0 && psav->DRIServerInfo != NULL) {
1983 	SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
1984 
1985 	pPriv->tried_agp = TRUE;
1986 	if (pSAVAGEDRIServer->agpXVideo.size >= max(new_size, planarFrameSize)) {
1987 	    if (pSAVAGEDRIServer->agpXVideo.map == NULL &&
1988 	        drmMap( psav->drmFD,
1989 		pSAVAGEDRIServer->agpXVideo.handle,
1990 		pSAVAGEDRIServer->agpXVideo.size,
1991 		&pSAVAGEDRIServer->agpXVideo.map ) < 0 ) {
1992 
1993 		xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] XVideo: Could not map agpXVideo \n" );
1994 		pPriv->agpBufferOffset = 0;
1995 		pPriv->agpBufferMap = NULL;
1996 	    } else {
1997 		pPriv->agpBufferMap = pSAVAGEDRIServer->agpXVideo.map;
1998 		pPriv->agpBufferOffset = pSAVAGEDRIServer->agpXVideo.offset;
1999 		pPriv->agpBase = drmAgpBase(psav->drmFD);
2000 #if 0
2001 		xf86DrvMsg( pScreen->myNum, X_INFO,
2002 		       "[agp] agpXVideo mapped at 0x%08lx aperture=0x%08x offset=0x%08lx\n",
2003 		       (unsigned long)pPriv->agpBufferMap, pPriv->agpBase, pPriv->agpBufferOffset);
2004 #endif
2005 	    }
2006 	} else {
2007 	    /* This situation is expected if AGPforXv is disabled, otherwise report. */
2008 	    if (pSAVAGEDRIServer->agpXVideo.size > 0) {
2009 		xf86DrvMsg( pScreen->myNum, X_ERROR,
2010 		    "[agp] XVideo: not enough space in buffer (got %ld bytes, required %d bytes).\n",
2011 	    	    (long int)pSAVAGEDRIServer->agpXVideo.size, max(new_size, planarFrameSize));
2012 	    }
2013 	    pPriv->agpBufferMap = NULL;
2014 	    pPriv->agpBufferOffset = 0;
2015 	}
2016     }
2017 #endif /* SAVAGEDRI */
2018 
2019 
2020     /* Buffer for final packed frame */
2021     pPriv->video_offset = SavageAllocateMemory(
2022 	pScrn, &pPriv->video_memory,
2023 	new_size);
2024     if (pPriv->video_offset == 0)
2025         return BadAlloc;
2026 
2027     /* Packed format cases */
2028     if (planarFrameSize == 0) {
2029 	pPriv->video_planarbuf = 0;
2030 
2031     /* Planar format cases */
2032     } else {
2033 	/* Hardware-assisted planar conversion only works on 16-byte aligned addresses */
2034 	pPriv->video_planarbuf = SavageAllocateMemory(
2035 	    pScrn, &pPriv->video_planarmem,
2036 	    ((planarFrameSize + 0xF) & ~0xF));
2037 	if (pPriv->video_planarbuf != 0) {
2038 	    /* TODO: stop any pending conversions when buffers change... */
2039 	    pPriv->video_planarbuf = ((pPriv->video_planarbuf + 0xF) & ~0xF);
2040 	} else {
2041 	    /* Fallback using software conversion */
2042 	}
2043     }
2044 
2045     /* copy data */
2046     top = y1 >> 16;
2047     left = (x1 >> 16) & ~1;
2048     npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
2049     left <<= 1;
2050 
2051     offset = (pPriv->video_offset) + (top * dstPitch);
2052     dst_start = (psav->FBBase + ((offset + left) & ~BASE_PAD));
2053 
2054     switch(id) {
2055     case FOURCC_YV12:		/* YV12 */
2056     case FOURCC_I420:
2057 	top &= ~1;
2058 	tmp = ((top >> 1) * srcPitch2) + (left >> 2);
2059 	offsetU += tmp;
2060 	offsetV += tmp;
2061 	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
2062         if (S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv && (npixels & 0xF) == 0 && pPriv->video_planarbuf != 0) {
2063 #ifdef SAVAGEDRI
2064             if (pPriv->agpBufferMap != NULL) {
2065 		/* Using copy to AGP memory */
2066 		SavageCopyPlanarDataBCI(
2067 		    pScrn,
2068 		    buf + (top * srcPitch) + (left >> 1),
2069 		    buf + offsetV,
2070 		    buf + offsetU,
2071 		    dst_start,
2072 		    pPriv->agpBufferMap,
2073 		    pPriv->agpBase + pPriv->agpBufferOffset,
2074 		    srcPitch, srcPitch2, dstPitch, nlines, npixels, TRUE);
2075             } else
2076 #endif /* SAVAGEDRI */
2077             {
2078 		/* Using ordinary copy to framebuffer */
2079 		SavageCopyPlanarDataBCI(
2080 		    pScrn,
2081 		    buf + (top * srcPitch) + (left >> 1),
2082 		    buf + offsetV,
2083 		    buf + offsetU,
2084 		    dst_start,
2085 		    (unsigned char *)psav->FBBase + pPriv->video_planarbuf,
2086 		    pPriv->video_planarbuf,
2087 		    srcPitch, srcPitch2, dstPitch, nlines, npixels, FALSE);
2088 	    }
2089         } else {
2090 	    SavageCopyPlanarData(
2091 	    	buf + (top * srcPitch) + (left >> 1),
2092 	    	buf + offsetV,
2093 	    	buf + offsetU,
2094 	    	dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels);
2095         }
2096 	break;
2097     case FOURCC_Y211:		/* Y211 */
2098     case FOURCC_RV15:		/* RGB15 */
2099     case FOURCC_RV16:		/* RGB16 */
2100     case FOURCC_YUY2:		/* YUY2 */
2101     default:
2102 	buf += (top * srcPitch) + left;
2103 	nlines = ((y2 + 0xffff) >> 16) - top;
2104 	SavageCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
2105 	break;
2106     }
2107 
2108     /* We need to enable the video before we draw the chroma color.
2109        Otherwise, we get blue flashes. */
2110 
2111     SavageDisplayVideo(pScrn, id, offset, width, height, dstPitch,
2112 	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
2113 
2114     /* update cliplist */
2115     if(!REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes)) {
2116 	REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
2117 	/* draw these */
2118 	SavageFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes);
2119 
2120     }
2121 
2122     pPriv->videoStatus = CLIENT_VIDEO_ON;
2123 
2124     return Success;
2125 }
2126 
2127 static int
SavageQueryImageAttributes(ScrnInfoPtr pScrn,int id,unsigned short * w,unsigned short * h,int * pitches,int * offsets)2128 SavageQueryImageAttributes(
2129   ScrnInfoPtr pScrn,
2130   int id,
2131   unsigned short *w, unsigned short *h,
2132   int *pitches, int *offsets
2133 ){
2134     int size, tmp;
2135 
2136     if(*w > 1024) *w = 1024;
2137     if(*h > 1024) *h = 1024;
2138 
2139     *w = (*w + 1) & ~1;
2140     if(offsets) offsets[0] = 0;
2141 
2142     switch(id) {
2143     case FOURCC_IA44:
2144         if (pitches) pitches[0]=*w;
2145         size=(*w)*(*h);
2146         break;
2147     case FOURCC_Y211:
2148 	size = *w << 2;
2149 	if(pitches) pitches[0] = size;
2150 	size *= *h;
2151 	break;
2152     case FOURCC_YV12:
2153     case FOURCC_I420:
2154 	*h = (*h + 1) & ~1;
2155 	size = (*w + 3) & ~3;
2156 	if(pitches) pitches[0] = size;
2157 	size *= *h;
2158 	if(offsets) offsets[1] = size;
2159 	tmp = ((*w >> 1) + 3) & ~3;
2160 	if(pitches) pitches[1] = pitches[2] = tmp;
2161 	tmp *= (*h >> 1);
2162 	size += tmp;
2163 	if(offsets) offsets[2] = size;
2164 	size += tmp;
2165 	break;
2166     case FOURCC_RV15:		/* RGB15 */
2167     case FOURCC_RV16:		/* RGB16 */
2168     case FOURCC_YUY2:
2169     default:
2170 	size = *w << 1;
2171 	if(pitches) pitches[0] = size;
2172 	size *= *h;
2173 	break;
2174     }
2175 
2176     return size;
2177 }
2178 
2179 /****************** Offscreen stuff ***************/
2180 
2181 typedef struct {
2182   void *surface_memory;
2183   Bool isOn;
2184 } OffscreenPrivRec, * OffscreenPrivPtr;
2185 
2186 static int
SavageAllocateSurface(ScrnInfoPtr pScrn,int id,unsigned short w,unsigned short h,XF86SurfacePtr surface)2187 SavageAllocateSurface(
2188     ScrnInfoPtr pScrn,
2189     int id,
2190     unsigned short w,
2191     unsigned short h,
2192     XF86SurfacePtr surface
2193 ){
2194     int offset, size;
2195     int pitch, fbpitch, numlines;
2196     void *surface_memory = NULL;
2197     OffscreenPrivPtr pPriv;
2198 
2199     if((w > 1024) || (h > 1024))
2200 	return BadAlloc;
2201 
2202     w = (w + 1) & ~1;
2203     pitch = ((w << 1) + 15) & ~15;
2204     fbpitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
2205     numlines = ((pitch * h) + fbpitch - 1) / fbpitch;
2206     size = pitch * h;
2207 
2208     offset = SavageAllocateMemory(pScrn, &surface_memory, size);
2209     if (offset == 0)
2210 	return BadAlloc;
2211 
2212     surface->width = w;
2213     surface->height = h;
2214 
2215     if(!(surface->pitches = malloc(sizeof(int)))) {
2216 	SavageFreeMemory(pScrn, surface_memory);
2217 	return BadAlloc;
2218     }
2219     if(!(surface->offsets = malloc(sizeof(int)))) {
2220 	free(surface->pitches);
2221 	SavageFreeMemory(pScrn, surface_memory);
2222 	return BadAlloc;
2223     }
2224     if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
2225 	free(surface->pitches);
2226 	free(surface->offsets);
2227 	SavageFreeMemory(pScrn, surface_memory);
2228 	return BadAlloc;
2229     }
2230 
2231     pPriv->surface_memory = surface_memory;
2232     pPriv->isOn = FALSE;
2233 
2234     surface->pScrn = pScrn;
2235     surface->id = id;
2236     surface->pitches[0] = pitch;
2237     surface->offsets[0] = offset; /*area->box.y1 * fbpitch;*/
2238     surface->devPrivate.ptr = (pointer)pPriv;
2239 
2240     return Success;
2241 }
2242 
2243 static int
SavageStopSurface(XF86SurfacePtr surface)2244 SavageStopSurface(
2245     XF86SurfacePtr surface
2246 ){
2247     OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2248     xf86ErrorFVerb(XVTRACE,"SavageStopSurface\n");
2249 
2250     if(pPriv->isOn) {
2251 	/*SavagePtr psav = SAVPTR(surface->pScrn);*/
2252 	/*SavageClipVWindow(surface->pScrn);*/
2253 	SavageStreamsOff( surface->pScrn );
2254 	pPriv->isOn = FALSE;
2255     }
2256 
2257     return Success;
2258 }
2259 
2260 
2261 static int
SavageFreeSurface(XF86SurfacePtr surface)2262 SavageFreeSurface(
2263     XF86SurfacePtr surface
2264 ){
2265     ScrnInfoPtr pScrn = surface->pScrn;
2266     OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2267 
2268     if(pPriv->isOn)
2269 	SavageStopSurface(surface);
2270     SavageFreeMemory(pScrn, pPriv->surface_memory);
2271     free(surface->pitches);
2272     free(surface->offsets);
2273     free(surface->devPrivate.ptr);
2274 
2275     return Success;
2276 }
2277 
2278 static int
SavageGetSurfaceAttribute(ScrnInfoPtr pScrn,Atom attribute,INT32 * value)2279 SavageGetSurfaceAttribute(
2280     ScrnInfoPtr pScrn,
2281     Atom attribute,
2282     INT32 *value
2283 ){
2284     return SavageGetPortAttribute(pScrn, attribute, value,
2285 			(pointer)(GET_PORT_PRIVATE(pScrn)));
2286 }
2287 
2288 static int
SavageSetSurfaceAttribute(ScrnInfoPtr pScrn,Atom attribute,INT32 value)2289 SavageSetSurfaceAttribute(
2290     ScrnInfoPtr pScrn,
2291     Atom attribute,
2292     INT32 value
2293 ){
2294     return SavageSetPortAttribute(pScrn, attribute, value,
2295 			(pointer)(GET_PORT_PRIVATE(pScrn)));
2296 }
2297 
2298 
2299 static int
SavageDisplaySurface(XF86SurfacePtr surface,short src_x,short src_y,short drw_x,short drw_y,short src_w,short src_h,short drw_w,short drw_h,RegionPtr clipBoxes)2300 SavageDisplaySurface(
2301     XF86SurfacePtr surface,
2302     short src_x, short src_y,
2303     short drw_x, short drw_y,
2304     short src_w, short src_h,
2305     short drw_w, short drw_h,
2306     RegionPtr clipBoxes
2307 ){
2308     OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
2309     ScrnInfoPtr pScrn = surface->pScrn;
2310     ScreenPtr pScreen = pScrn->pScreen;
2311     SavagePortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn);
2312     INT32 x1, y1, x2, y2;
2313     BoxRec dstBox;
2314     xf86ErrorFVerb(XVTRACE,"SavageDisplaySurface\n");
2315 
2316     x1 = src_x;
2317     x2 = src_x + src_w;
2318     y1 = src_y;
2319     y2 = src_y + src_h;
2320 
2321     dstBox.x1 = drw_x;
2322     dstBox.x2 = drw_x + drw_w;
2323     dstBox.y1 = drw_y;
2324     dstBox.y2 = drw_y + drw_h;
2325 
2326     SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2,
2327                 	REGION_EXTENTS(pScreen, clipBoxes),
2328 			surface->width, surface->height);
2329 
2330     if((x1 >= x2) || (y1 >= y2))
2331 	return Success;
2332 
2333     dstBox.x1 -= pScrn->frameX0;
2334     dstBox.x2 -= pScrn->frameX0;
2335     dstBox.y1 -= pScrn->frameY0;
2336     dstBox.y2 -= pScrn->frameY0;
2337 
2338     SavageDisplayVideo(pScrn, surface->id, surface->offsets[0],
2339 	     surface->width, surface->height, surface->pitches[0],
2340 	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
2341 
2342     xf86XVFillKeyHelper(pScreen, portPriv->colorKey, clipBoxes);
2343 
2344     pPriv->isOn = TRUE;
2345 #if 0
2346     if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
2347 	REGION_EMPTY(pScreen, &portPriv->clip);
2348 	UpdateCurrentTime();
2349 	portPriv->videoStatus = FREE_TIMER;
2350 	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
2351     }
2352 #endif
2353 
2354     return Success;
2355 }
2356 
2357 
2358 static void
SavageInitOffscreenImages(ScreenPtr pScreen)2359 SavageInitOffscreenImages(ScreenPtr pScreen)
2360 {
2361     XF86OffscreenImagePtr offscreenImages;
2362     SavagePtr psav = SAVPTR(xf86ScreenToScrn(pScreen));
2363 
2364     /* need to free this someplace */
2365     if (!psav->offscreenImages) {
2366 	if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec))))
2367 	    return;
2368 	psav->offscreenImages = offscreenImages;
2369     } else {
2370 	offscreenImages = psav->offscreenImages;
2371     }
2372 
2373     offscreenImages[0].image = &Images[0];
2374     offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
2375 			       VIDEO_CLIP_TO_VIEWPORT;
2376     offscreenImages[0].alloc_surface = SavageAllocateSurface;
2377     offscreenImages[0].free_surface = SavageFreeSurface;
2378     offscreenImages[0].display = SavageDisplaySurface;
2379     offscreenImages[0].stop = SavageStopSurface;
2380     offscreenImages[0].setAttribute = SavageSetSurfaceAttribute;
2381     offscreenImages[0].getAttribute = SavageGetSurfaceAttribute;
2382     offscreenImages[0].max_width = 1024;
2383     offscreenImages[0].max_height = 1024;
2384     offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
2385     offscreenImages[0].attributes = Attributes;
2386 
2387     xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
2388 }
2389 
2390