1
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5
6 #if PSZ != 24
7 #include "dixstruct.h"
8 #include "fourcc.h"
9
10 /*
11 * Ported from mga_video.c by Loïc Grenié
12 */
13
14 #ifndef OFF_DELAY
15 #define OFF_DELAY 200
16 #endif
17
18 static XF86VideoAdaptorPtr A(SetupImageVideo)(ScreenPtr);
19
20 static void A(StopVideo)(ScrnInfoPtr, pointer, Bool);
21 static int A(SetPortAttribute)(ScrnInfoPtr, Atom, INT32, pointer);
22 static int ApmGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
23 static void ApmQueryBestSize(ScrnInfoPtr, Bool, short, short, short,
24 short, unsigned int *, unsigned int *,
25 pointer);
26 static int ApmQueryImageAttributes(ScrnInfoPtr, int,
27 unsigned short *, unsigned short *,
28 int *, int *);
29 #ifndef XV_NEW_REPUT
30 static int A(ReputImage)(ScrnInfoPtr, short, short, RegionPtr, pointer,
31 DrawablePtr);
32 #endif
33 static int A(PutImage)(ScrnInfoPtr, short, short, short, short, short,
34 short, short, short, int, unsigned char*,
35 short, short, Bool, RegionPtr, pointer,
36 DrawablePtr);
37
38 static void A(ResetVideo)(ScrnInfoPtr);
39 static void A(XvMoveCB)(FBAreaPtr, FBAreaPtr);
40 static void A(XvRemoveCB)(FBAreaPtr);
41
42 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
43
A(InitVideo)44 void A(InitVideo)(ScreenPtr pScreen)
45 {
46 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
47 XF86VideoAdaptorPtr *adaptors, *newAdaptors;
48 XF86VideoAdaptorPtr newAdaptor;
49 APMDECL(pScrn);
50 int num_adaptors;
51 Bool freeAdaptors = FALSE;
52
53 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
54
55 if (pApm->Chipset >= AT24) {
56 if ((newAdaptor = A(SetupImageVideo)(pScreen))) {
57
58 newAdaptors = malloc((num_adaptors + 1) *
59 sizeof(XF86VideoAdaptorPtr*));
60 if(newAdaptors) {
61 if(num_adaptors)
62 memcpy(newAdaptors, adaptors, num_adaptors *
63 sizeof(XF86VideoAdaptorPtr));
64 newAdaptors[num_adaptors] = newAdaptor;
65 adaptors = newAdaptors;
66 num_adaptors++;
67 freeAdaptors = TRUE;
68 }
69 }
70 }
71
72 if(num_adaptors)
73 xf86XVScreenInit(pScreen, adaptors, num_adaptors);
74
75 free(adaptors);
76 }
77
78 #ifndef APM_VIDEO_DEFINES
79 #define APM_VIDEO_DEFINES
80
81 static Atom xvBrightness, xvContrast;
82
83 /* client libraries expect an encoding */
84 static XF86VideoEncodingRec DummyEncoding[1] =
85 {
86 {
87 0,
88 "XV_IMAGE",
89 1024, 1024,
90 {1, 1}
91 }
92 };
93
94 #define NUM_FORMATS 24
95
96 static XF86VideoFormatRec Formats[NUM_FORMATS] =
97 {
98 { 8, PseudoColor},
99 {15, PseudoColor},
100 {16, PseudoColor},
101 {24, PseudoColor},
102 {32, PseudoColor},
103 { 8, DirectColor},
104 {15, DirectColor},
105 {16, DirectColor},
106 {24, DirectColor},
107 {32, DirectColor},
108 { 8, TrueColor},
109 {15, TrueColor},
110 {16, TrueColor},
111 {24, TrueColor},
112 {32, TrueColor}
113 };
114
115 #define NUM_ATTRIBUTES 2
116
117 static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
118 {
119 {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
120 {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
121 };
122
123 #define NUM_IMAGES 9
124 typedef char c8;
125
126 static XF86ImageRec Images[NUM_IMAGES] =
127 {
128 {
129 0x35315652,
130 XvRGB,
131 LSBFirst,
132 {'R','V','1','5',
133 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
134 16,
135 XvPacked,
136 1,
137 15, 0x001F, 0x03E0, 0x7C00,
138 0, 0, 0,
139 0, 0, 0,
140 0, 0, 0,
141 {'R','V','B',0,
142 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},
143 XvTopToBottom
144 },
145 {
146 0x36315652,
147 XvRGB,
148 LSBFirst,
149 {'R','V','1','6',
150 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
151 16,
152 XvPacked,
153 1,
154 16, 0x001F, 0x07E0, 0xF800,
155 0, 0, 0,
156 0, 0, 0,
157 0, 0, 0,
158 {'R','V','B',0,
159 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},
160 XvTopToBottom
161 },
162 {
163 0x32335652,
164 XvRGB,
165 LSBFirst,
166 {'R','V','3','2',
167 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
168 32,
169 XvPacked,
170 1,
171 24, 0x0000FF, 0x00FF00, 0xFF0000,
172 0, 0, 0,
173 0, 0, 0,
174 0, 0, 0,
175 {'R','V','B',0,
176 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},
177 XvTopToBottom
178 },
179 XVIMAGE_YUY2,
180 {
181 0x59595959,
182 XvYUV,
183 LSBFirst,
184 {0x00,0x00,0x00,0x00,
185 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
186 8,
187 XvPacked,
188 1,
189 0, 0, 0, 0,
190 8, 0, 0,
191 1, 1, 1,
192 1, 1, 1,
193 {'Y','Y','Y','Y',
194 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},
195 XvTopToBottom
196 },
197 {
198 0x32315659,
199 XvYUV,
200 LSBFirst,
201 {'Y','V','1','2',
202 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71},
203 12,
204 XvPlanar,
205 3,
206 0, 0, 0, 0 ,
207 8, 8, 8,
208 1, 2, 2,
209 1, 2, 2,
210 {'Y','V','U',
211 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,0},
212 XvTopToBottom
213 },
214 {
215 0x59565955,
216 XvYUV,
217 LSBFirst,
218 {'U','Y','V','Y',
219 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71},
220 16,
221 XvPlanar,
222 1,
223 0, 0, 0, 0,
224 8, 8, 8,
225 1, 2, 2,
226 1, 1, 1,
227 {'U','Y','V','Y',
228 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},
229 XvTopToBottom
230 },
231 {
232 0x55595659,
233 XvYUV,
234 LSBFirst,
235 {'Y','V','Y','U',
236 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71},
237 16,
238 XvPlanar,
239 1,
240 0, 0, 0, 0,
241 8, 8, 8,
242 1, 2, 2,
243 1, 1, 1,
244 {'Y','V','Y','U',
245 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},
246 XvTopToBottom
247 },
248 {
249 0x59555956,
250 XvYUV,
251 LSBFirst,
252 {'V','Y','U','Y',
253 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71},
254 16,
255 XvPlanar,
256 1,
257 0, 0, 0, 0,
258 8, 8, 8,
259 1, 2, 2,
260 1, 1, 1,
261 {'V','Y','U','Y',
262 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},
263 XvTopToBottom
264 }
265 };
266
267 typedef struct {
268 Bool on;
269 unsigned char brightness;
270 unsigned char contrast;
271 unsigned short reg, val;
272 ApmPtr pApm;
273 int x1, x10, y1, drw_x, drw_y, Bpp, Bps;
274 FBAreaPtr area;
275 RegionRec clip;
276 int xnum, xden, ynum, yden;
277 CARD32 scalex, scaley;
278 CARD32 data;
279 } ApmPortPrivRec, *ApmPortPrivPtr;
280 #endif
281
282
283 static void
A(ResetVideo)284 A(ResetVideo)(ScrnInfoPtr pScrn)
285 {
286 APMDECL(pScrn);
287
288 A(WaitForFifo)(pApm, 2);
289 ((ApmPortPrivPtr)pApm->adaptor->pPortPrivates[0].ptr)->on = 0;
290 ((ApmPortPrivPtr)pApm->adaptor->pPortPrivates[1].ptr)->on = 0;
291 WRXW(0x82, 0);
292 WRXW(0x92, 0);
293 }
294
295
296 static XF86VideoAdaptorPtr
A(SetupImageVideo)297 A(SetupImageVideo)(ScreenPtr pScreen)
298 {
299 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
300 APMDECL(pScrn);
301 XF86VideoAdaptorPtr adapt;
302 ApmPortPrivPtr pPriv;
303
304 if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
305 2 * sizeof(ApmPortPrivRec) +
306 2 * sizeof(DevUnion))))
307 return NULL;
308
309 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
310 adapt->flags = VIDEO_OVERLAID_IMAGES;
311 adapt->name = "Alliance Pro Motion video engine";
312 adapt->nEncodings = 1;
313 adapt->pEncodings = DummyEncoding;
314 adapt->nFormats = NUM_FORMATS;
315 adapt->pFormats = Formats;
316 adapt->nPorts = 2;
317 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
318 pPriv = (ApmPortPrivPtr)(&adapt->pPortPrivates[2]);
319 pPriv->pApm = pApm;
320 pPriv[1].pApm = pApm;
321 pPriv->reg = 0x82;
322 pPriv[1].reg = 0x92;
323 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
324 adapt->pPortPrivates[1].ptr = (pointer)(pPriv + 1);
325 adapt->nAttributes = NUM_ATTRIBUTES;
326 adapt->pAttributes = Attributes;
327 adapt->nImages = NUM_IMAGES;
328 adapt->pImages = Images;
329 adapt->PutVideo = NULL;
330 adapt->PutStill = NULL;
331 adapt->GetVideo = NULL;
332 adapt->GetStill = NULL;
333 adapt->StopVideo = A(StopVideo);
334 adapt->SetPortAttribute = A(SetPortAttribute);
335 adapt->GetPortAttribute = ApmGetPortAttribute;
336 adapt->QueryBestSize = ApmQueryBestSize;
337 adapt->PutImage = A(PutImage);
338 #ifndef XV_NEW_REPUT
339 adapt->ReputImage = A(ReputImage);
340 #endif
341 adapt->QueryImageAttributes = ApmQueryImageAttributes;
342
343 pPriv->brightness = 0;
344 pPriv->contrast = 128;
345 pPriv[1].brightness = 0;
346 pPriv[1].contrast = 128;
347
348 /* gotta uninit this someplace */
349 REGION_NULL(pScreen, &pPriv->clip);
350 REGION_NULL(pScreen, &(pPriv + 1)->clip);
351
352 pApm->adaptor = adapt;
353
354 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
355 xvContrast = MAKE_ATOM("XV_CONTRAST");
356
357 A(ResetVideo)(pScrn);
358
359 return adapt;
360 }
361
362 /* ApmClipVideo -
363
364 Takes the dst box in standard X BoxRec form (top and left
365 edges inclusive, bottom and right exclusive). The new dst
366 box is returned. The source boundaries are given (x1, y1
367 inclusive, x2, y2 exclusive) and returned are the new source
368 boundaries in 16.16 fixed point.
369
370 extents is the extents of the clip region
371 */
372
373 static void
ApmClipVideo(BoxPtr dst,INT32 * x1,INT32 * x2,INT32 * y1,INT32 * y2,BoxPtr extents,INT32 width,INT32 height,CARD32 * scalex,CARD32 * scaley,INT32 mask)374 ApmClipVideo(BoxPtr dst, INT32 *x1, INT32 *x2, INT32 *y1, INT32 *y2,
375 BoxPtr extents, INT32 width, INT32 height,
376 CARD32 *scalex, CARD32 *scaley, INT32 mask)
377 {
378 INT32 vscale, hscale;
379 int diff;
380
381 if (dst->x2 - dst->x1 < *x2 - *x1)
382 dst->x2 = dst->x1 + *x2 - *x1;
383
384 if (dst->y2 - dst->y1 < *y2 - *y1)
385 dst->y2 = dst->y1 + *y2 - *y1;
386
387 *x1 <<= 12; *x2 <<= 16;
388 *y1 <<= 12; *y2 <<= 16;
389
390 hscale = (*x2 - *x1) / (dst->x2 - dst->x1);
391 vscale = (*y2 - *y1) / (dst->y2 - dst->y1);
392
393 diff = extents->x1 - dst->x1;
394 if(diff > 0) {
395 dst->x1 = extents->x1;
396 *x1 += diff * hscale;
397 }
398 diff = dst->x2 - extents->x2;
399 if(diff > 0) {
400 dst->x2 = extents->x2;
401 *x2 -= diff * hscale;
402 }
403 diff = extents->y1 - dst->y1;
404 if(diff > 0) {
405 dst->y1 = extents->y1;
406 *y1 += diff * vscale;
407 }
408 diff = dst->y2 - extents->y2;
409 if(diff > 0) {
410 dst->y2 = extents->y2;
411 *y2 -= diff * vscale;
412 }
413
414 if (*x2 - *x1 == 0x10000 * (dst->x2 - dst->x1)) /* Shrinking */
415 *scalex = 0;
416 else
417 *scalex = ((*x2 - *x1) / (dst->x2 - dst->x1)) >> 4;
418 if (*y2 - *y1 == 0x10000 * (dst->y2 - dst->y1)) /* Shrinking */
419 *scaley = 0;
420 else
421 *scaley = ((*y2 - *y1) / (dst->y2 - dst->y1)) >> 4;
422 }
423
424 static void
A(StopVideo)425 A(StopVideo)(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
426 {
427 ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data;
428 APMDECL(pScrn);
429
430 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
431
432 pPriv->on = 0;
433 A(WaitForFifo)(pApm, 1);
434 WRXB(pPriv->reg, 0);
435 }
436
437 static int
A(SetPortAttribute)438 A(SetPortAttribute)(ScrnInfoPtr pScrn, Atom attribute, INT32 value,
439 pointer data)
440 {
441 ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data;
442 /*APMDECL(pScrn);*/
443
444 if(attribute == xvBrightness) {
445 if((value < -128) || (value > 127))
446 return BadValue;
447 pPriv->brightness = value;
448 /* TODO : enable */
449 } else if(attribute == xvContrast) {
450 if((value < 0) || (value > 255))
451 return BadValue;
452 pPriv->contrast = value;
453 /* TODO : enable */
454 }
455
456 return Success;
457 }
458
459 static int
ApmGetPortAttribute(ScrnInfoPtr pScrn,Atom attribute,INT32 * value,pointer data)460 ApmGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value,
461 pointer data)
462 {
463 ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data;
464
465 if(attribute == xvBrightness) {
466 *value = pPriv->brightness;
467 } else
468 if(attribute == xvContrast) {
469 *value = pPriv->contrast;
470 }
471
472 return Success;
473 }
474
475 static void
ApmQueryBestSize(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)476 ApmQueryBestSize(ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h,
477 short drw_w, short drw_h,
478 unsigned int *p_w, unsigned int *p_h, pointer data)
479 {
480 APMDECL(pScrn);
481 unsigned short round = ~pApm->CurrentLayout.mask32;
482
483 *p_w = drw_w & round;
484 *p_h = drw_h & round;
485 }
486
A(XvMoveCB)487 static void A(XvMoveCB)(FBAreaPtr area1, FBAreaPtr area2)
488 {
489 ApmPortPrivPtr pPriv = (ApmPortPrivPtr)area1->devPrivate.ptr;
490 ApmPtr pApm = pPriv->pApm;
491
492 pPriv->on = 0;
493 A(WaitForFifo)(pApm, 1);
494 WRXB(pPriv->reg, 0); /* Stop video for this port */
495 pPriv->area = area2;
496 }
497
A(XvRemoveCB)498 static void A(XvRemoveCB)(FBAreaPtr area)
499 {
500 ApmPortPrivPtr pPriv = (ApmPortPrivPtr)area->devPrivate.ptr;
501 ApmPtr pApm = pPriv->pApm;
502
503 pPriv->on = 0;
504 A(WaitForFifo)(pApm, 1);
505 WRXB(pPriv->reg, 0); /* Stop video for this port */
506 pPriv->area = NULL;
507 }
508
509 static int
A(ReputImage)510 A(ReputImage)(ScrnInfoPtr pScrn, short drw_x, short drw_y,
511 RegionPtr clipBoxes, pointer pdata, DrawablePtr pDraw)
512 {
513 ScreenPtr pScreen = pScrn->pScreen;
514 APMDECL(pScrn);
515 ApmPortPrivPtr pPriv = pdata, pPriv0, pPriv1;
516 register int fx, fy;
517 CARD32 mask;
518 RegionRec Union;
519 RegionPtr reg0;
520 int nrects, CurrY, tile;
521 int X1, X2, Y1, y2, xmax, ymax;
522 BoxPtr rects;
523 Bool didit = 0;
524
525 mask = pApm->CurrentLayout.mask32;
526 fx = pScrn->frameX0 & ~mask;
527 fy = pScrn->frameY0 + 1;
528 REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
529 pPriv->x1 += drw_x - pPriv->drw_x;
530 pPriv->x10 = ((pPriv->x1 + mask) & ~mask) - fx;
531 pPriv->y1 += drw_y - pPriv->drw_y;
532 pPriv->drw_x = drw_x;
533 pPriv->drw_y = drw_y;
534 A(WaitForFifo)(pApm, 2);
535 WRXW(pPriv->reg + 0x06, 0xFFF - ((pPriv->scalex * pPriv->x10) & 0xFFF));
536 WRXW(pPriv->reg + 0x0A, 0xFFF - ((pPriv->scaley * pPriv->y1) & 0xFFF));
537 pPriv0 = (ApmPortPrivPtr)pApm->adaptor->pPortPrivates[0].ptr;
538 pPriv1 = (ApmPortPrivPtr)pApm->adaptor->pPortPrivates[1].ptr;
539 reg0 = &pPriv0->clip;
540 bzero(&Union, sizeof Union);
541 REGION_EMPTY(pScreen, &Union);
542 REGION_NULL(pScreen, &Union);
543 REGION_UNION(pScreen, &Union, reg0, &pPriv1->clip);
544 nrects = REGION_NUM_RECTS(&Union);
545 rects = REGION_RECTS(&Union);
546 tile = 0x200;
547 xmax = pScrn->frameX1 - pScrn->frameX0 + 1;
548 ymax = pScrn->frameY1 - pScrn->frameY0;
549 CurrY = -1;
550 goto BEGIN_LOOP_1;
551 do {
552 rects++;
553 BEGIN_LOOP_1:
554 X1 = ((rects->x1 + mask) & ~mask) - fx;
555 if (X1 < 0)
556 X1 = 0;
557 X2 = (rects->x2 & ~mask) - fx;
558 if (X2 > xmax)
559 X2 = xmax;
560 y2 = rects->y2 - fy;
561 } while ((X2 <= X1 || y2 < -1) && --nrects > 0);
562 Y1 = rects->y1 - fy;
563
564 while (!(STATUS() & 0x800));
565 while (STATUS() & 0x800);
566 while (nrects-- > 0) {
567 CARD32 reg, data;
568 int x1, x2, y1;
569
570 x1 = X1;
571 x2 = X2;
572 y1 = Y1;
573 if (y1 < -1) y1 = -1;
574 if (y1 > ymax)
575 break;
576 didit = 1;
577 if (y1 > CurrY) {
578 A(WaitForFifo)(pApm, 3);
579 WRXL(tile + 0x00, 0xFFF0011);
580 WRXL(tile + 0x04, y1 << 16);
581 WRXL(tile + 0x08, 0);
582 tile += 16;
583 }
584 if (RECT_IN_REGION(pScreen, reg0, rects)) {
585 pPriv = pPriv0;
586 reg = (x1 << 16) | 1;
587 }
588 else {
589 pPriv = pPriv1;
590 reg = (x1 << 16) | 2;
591 }
592 CurrY = y2;
593 if (nrects <= 0)
594 goto BEGIN_LOOP_2;
595 do {
596 rects++;
597 BEGIN_LOOP_2:
598 X1 = ((rects->x1 + mask) & ~mask) - fx;
599 if (X1 < 0)
600 X1 = 0;
601 X2 = (rects->x2 & ~mask) - fx;
602 if (X2 > xmax)
603 X2 = xmax;
604 } while (X2 <= X1 && --nrects > 0);
605 Y1 = rects->y1 - fy;
606 y2 = rects->y2 - fy;
607 data = pPriv->data + (((x1 - pPriv->x10)
608 * pPriv->xden) / pPriv->xnum) * pPriv->Bpp +
609 (((y1 - pPriv->y1 + fy) * pPriv->yden) / pPriv->ynum) * pPriv->Bps;
610 A(WaitForFifo)(pApm, 4);
611 if (!nrects || tile == 0x2B0 || y1 < Y1) {
612 WRXL(tile , 0x10 | reg);
613 }
614 else {
615 WRXL(tile , reg);
616 }
617 WRXL(tile + 0x04, x2 | (CurrY << 16));
618 WRXL(tile + 0x08, (((x2-x1)*pPriv->xden+pPriv->xnum-1) / pPriv->xnum) |
619 (data << 16));
620 WRXB(tile + 0x0C, data >> 16);
621 tile += 16;
622 if (tile == 0x2C0) {
623 tile = 0x200;
624 break;
625 }
626 }
627 REGION_UNINIT(pScreen, &Union);
628
629 if (didit) {
630 A(WaitForFifo)(pApm, 1);
631 WRXW(0x8E, tile - 0x200);
632 }
633
634 if (didit ^ ((pPriv0->val | pPriv1->val) & 1)) {
635 if (didit) {
636 pPriv0->val |= 1;
637 pPriv1->val |= 1;
638 }
639 else {
640 pPriv0->val &= 0xFFFE;
641 pPriv1->val &= 0xFFFE;
642 }
643 if (pPriv0->on) {
644 A(WaitForFifo)(pApm, 1);
645 WRXW(0x82, pPriv0->val);
646 }
647 if (pPriv1->on) {
648 A(WaitForFifo)(pApm, 1);
649 WRXW(0x92, pPriv1->val);
650 }
651 }
652
653 return Success;
654 }
655
656 static int
A(PutImage)657 A(PutImage)(ScrnInfoPtr pScrn, short src_x, short src_y,
658 short drw_x, short drw_y, short src_w, short src_h,
659 short drw_w, short drw_h, int id, unsigned char* buf,
660 short width, short height, Bool sync, RegionPtr clipBoxes,
661 pointer data, DrawablePtr pDraw)
662 {
663 ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data;
664 ScreenPtr pScreen = pScrn->pScreen;
665 APMDECL(pScrn);
666 INT32 x1, x2, y1, y2;
667 unsigned char *dst_start;
668 int pitch, Bpp, new_h, offset = 0, offset2 = 0, offset3 = 0;
669 CARD32 mask;
670 FBAreaPtr area;
671 int srcPitch, dstPitch, srcPitch2 = 0;
672 int top, left, npixels, nlines;
673 BoxRec dstBox;
674 CARD32 scalex, scaley, scale;
675 CARD32 tmp;
676 Bool offscreen;
677
678 offscreen = (buf < (unsigned char *)pApm->FbBase ||
679 buf > (unsigned char *)pApm->FbBase + 0x400000);
680
681 if(drw_w > 16384) drw_w = 16384;
682
683 /* Clip */
684 x1 = src_x;
685 x2 = src_x + src_w;
686 y1 = src_y;
687 y2 = src_y + src_h;
688
689 dstBox.x1 = drw_x;
690 dstBox.x2 = drw_x + drw_w;
691 dstBox.y1 = drw_y;
692 dstBox.y2 = drw_y + drw_h;
693
694 mask = pApm->CurrentLayout.mask32;
695
696 ApmClipVideo(&dstBox, &x1, &x2, &y1, &y2,
697 REGION_EXTENTS(pScreen, clipBoxes), width, height,
698 &scalex, &scaley, mask);
699
700 pPriv->drw_x = drw_x;
701 pPriv->drw_y = drw_y;
702 pPriv->xnum = drw_w;
703 if (scalex)
704 pPriv->xden = src_w;
705 else
706 pPriv->xden = drw_w; /* If image is larger than window */
707 pPriv->ynum = drw_h;
708 if (scaley)
709 pPriv->yden = src_h;
710 else
711 pPriv->yden = drw_h;
712 if((x1 - x2 >= 0xFFFF) || (y1 - y2 >= 0xFFFF))
713 return Success;
714
715 Bpp = pScrn->bitsPerPixel >> 3;
716 pitch = Bpp * pScrn->displayWidth;
717
718 switch(id) {
719 case 0x32315659:
720 dstPitch = ((width << 1) + 3) & ~3;
721 srcPitch = (width + 3) & ~3;
722 offset2 = srcPitch * height;
723 srcPitch2 = ((width >> 1) + 3) & ~3;
724 offset = srcPitch2 * (height >> 1);
725 offset3 = offset + offset2;
726 new_h = (2 * offset2 + pitch - 1) / pitch;
727 break;
728 case 0x59595959:
729 srcPitch = width;
730 dstPitch = (srcPitch + 3) & ~3;
731 offset = dstPitch * height;
732 new_h = (offset + pitch - 1) / pitch;
733 break;
734 case 0x32335652:
735 srcPitch = (width << 2);
736 dstPitch = (srcPitch + 3) & ~3;
737 offset = dstPitch * height;
738 new_h = (offset + pitch - 1) / pitch;
739 break;
740 default:
741 if (pApm->PutImageStride)
742 srcPitch = pApm->PutImageStride;
743 else
744 srcPitch = (width << 1);
745 dstPitch = (srcPitch + 3) & ~3;
746 offset = dstPitch * height;
747 new_h = (offset + pitch - 1) / pitch;
748 break;
749 }
750
751 area = pPriv->area;
752
753 /* Allocate offscreen memory */
754 if (offscreen && (!area || ((area->box.y2 - area->box.y1) < new_h))) {
755 Bool nukeMem = FALSE;
756 int max_w, max_h;
757
758 xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0,
759 FAVOR_WIDTH_THEN_AREA, PRIORITY_LOW);
760 if (max_w == pScrn->displayWidth && max_h >= new_h) {
761 area = xf86AllocateOffscreenArea(pScreen,
762 pScrn->displayWidth, new_h,
763 4, A(XvMoveCB), A(XvRemoveCB), pPriv);
764 if (area) {
765 if (pPriv->area)
766 xf86FreeOffscreenArea(pPriv->area);
767 }
768 else
769 area = pPriv->area; /* Should not happen */
770 }
771 if(!area) {
772 if(!(area = xf86AllocateOffscreenArea(pScreen,
773 pScrn->displayWidth, new_h, 4,
774 A(XvMoveCB), A(XvRemoveCB), pPriv)))
775 {
776 nukeMem = TRUE;
777 }
778 } else {
779 if(!xf86ResizeOffscreenArea(area, pScrn->displayWidth, new_h)) {
780 xf86FreeOffscreenArea(area);
781 pPriv->area = area = NULL;
782 nukeMem = TRUE;
783 }
784 }
785 if(nukeMem) {
786 xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0,
787 FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME);
788
789 if((max_w < pScrn->displayWidth) || (max_h < new_h))
790 return BadAlloc;
791
792 xf86PurgeUnlockedOffscreenAreas(pScreen);
793
794 area = xf86AllocateOffscreenArea(pScreen,
795 pScrn->displayWidth, new_h, 4,
796 A(XvMoveCB), A(XvRemoveCB), pPriv);
797 }
798
799 pPriv->area = area;
800 }
801
802 /* copy data */
803 pPriv->x1 = dstBox.x1 /*drw_x*/;
804 pPriv->y1 = dstBox.y1 /*drw_y*/;
805 top = y1 >> 16;
806 left = (x1 >> 16) & ~1;
807 npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
808
809 switch(id) {
810 case 0x59595959:
811 pPriv->Bpp = 1;
812 break;
813 default:
814 pPriv->Bpp = 2;
815 left <<= 1;
816 break;
817 case 0x32335652:
818 pPriv->Bpp = 4;
819 left <<= 2;
820 break;
821 }
822 pPriv->Bps = pPriv->Bpp * pPriv->xden;
823 if (offscreen) {
824 offset = (area->box.y1 * pitch) + (top * dstPitch);
825 dst_start = ((unsigned char *)pApm->FbBase) +
826 (pPriv->data = offset + left);
827 switch(id) {
828 case 0x32315659:
829 top &= ~1;
830 tmp = ((top >> 1) * srcPitch2) + (left >> 2);
831 offset2 += tmp;
832 offset3 += tmp;
833 nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
834 xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1),
835 buf + offset2, buf + offset3, dst_start,
836 srcPitch, srcPitch2, dstPitch,
837 nlines, npixels);
838 break;
839 default:
840 if (id == 0x32335652)
841 npixels <<= 1;
842 else if (id == 0x59595959)
843 npixels >>= 1;
844 buf += (top * srcPitch) + left;
845 nlines = ((y2 + 0xffff) >> 16) - top;
846 if (offscreen)
847 xf86XVCopyPacked(buf, dst_start, srcPitch, dstPitch,
848 nlines, npixels);
849 break;
850 }
851 }
852 else
853 pPriv->data = buf - (unsigned char *)pApm->FbBase;
854 pPriv->on = 1;
855 A(WaitForFifo)(pApm, 3);
856 WRXW(pPriv->reg + 0x02, dstPitch >> 2);
857 WRXW(pPriv->reg + 0x04, scalex);
858 WRXW(pPriv->reg + 0x08, scaley);
859 pPriv->scalex = scalex;
860 pPriv->scaley = scaley;
861 if (scalex && scaley)
862 scale = 0x0E00;
863 else if (scalex)
864 scale = 0x0600;
865 else if (scaley)
866 scale = 0x0A00;
867 else
868 scale = 0;
869 switch(id) {
870 case 0x59595959:
871 pPriv->val = 0x017B | scale;
872 break;
873 case 0x32335652:
874 pPriv->val = 0x002F | (scale & 0xF7FF);/*Smoothing filter doesn't work*/
875 break;
876 case 0x36315652:
877 pPriv->val = 0x002B | (scale & 0xF7FF);
878 break;
879 case 0x35315652:
880 pPriv->val = 0x0029 | (scale & 0xF7FF);
881 break;
882 case 0x59555956:
883 pPriv->val = 0x013B | scale;
884 break;
885 case 0x55595659:
886 pPriv->val = 0x014B | scale;
887 break;
888 case 0x32315659:
889 case 0x59565955:
890 default:
891 pPriv->val = 0x016B | scale;
892 break;
893 }
894
895 (void) A(ReputImage)(pScrn, drw_x, drw_y, clipBoxes, data, pDraw);
896
897 A(WaitForFifo)(pApm, 1);
898 WRXW(pPriv->reg, pPriv->val);
899
900 return Success;
901 }
902
903 static int
ApmQueryImageAttributes(ScrnInfoPtr pScrn,int id,unsigned short * w,unsigned short * h,int * pitches,int * offsets)904 ApmQueryImageAttributes(ScrnInfoPtr pScrn, int id,
905 unsigned short *w, unsigned short *h,
906 int *pitches, int *offsets)
907 {
908 int size, tmp;
909
910 if(*w > 1024) *w = 1024;
911 if(*h > 1024) *h = 1024;
912
913 *w = (*w + 1) & ~1;
914 if(offsets) offsets[0] = 0;
915
916 switch(id) {
917 case 0x32315659:
918 *h = (*h + 1) & ~1;
919 size = (*w + 3) & ~3;
920 if(pitches) pitches[0] = size;
921 size *= *h;
922 if(offsets) offsets[1] = size;
923 tmp = ((*w >> 1) + 3) & ~3;
924 if(pitches) pitches[1] = pitches[2] = tmp;
925 tmp *= (*h >> 1);
926 size += tmp;
927 if(offsets) offsets[2] = size;
928 size += tmp;
929 break;
930 case 0x59565955:
931 case 0x55595659:
932 case 0x59555956:
933 case 0x32595559:
934 size = *w << 1;
935 goto common;
936 case 0x59595959:
937 default:
938 size = *w;
939 common:
940 if (pitches)
941 pitches[0] = size;
942 size *= *h;
943 break;
944 }
945
946 return size;
947 }
948
949 #endif
950