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