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