1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 
5 #include "xf86.h"
6 #include "xf86_OSproc.h"
7 #include "compiler.h"
8 #include "xf86Pci.h"
9 #include "xf86fbman.h"
10 #include "regionstr.h"
11 
12 #include "mga_reg.h"
13 #include "mga.h"
14 #include "mga_macros.h"
15 #include "xf86xv.h"
16 #include <X11/extensions/Xv.h>
17 
18 #ifdef USE_XAA
19 #include "xaa.h"
20 #include "xaalocal.h"
21 #endif
22 
23 #include "dixstruct.h"
24 #include "fourcc.h"
25 
26 #define OFF_DELAY 	250  /* milliseconds */
27 #define FREE_DELAY 	15000
28 
29 #define OFF_TIMER 	0x01
30 #define FREE_TIMER	0x02
31 #define CLIENT_VIDEO_ON	0x04
32 
33 #define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
34 
35 #define MGA_MAX_PORTS	32
36 
37 static void MGAInitOffscreenImages(ScreenPtr);
38 
39 static XF86VideoAdaptorPtr MGASetupImageVideoOverlay(ScreenPtr);
40 static int  MGASetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer);
41 static int  MGAGetPortAttributeOverlay(ScrnInfoPtr, Atom ,INT32 *, pointer);
42 
43 static XF86VideoAdaptorPtr MGASetupImageVideoTexture(ScreenPtr);
44 static int  MGASetPortAttributeTexture(ScrnInfoPtr, Atom, INT32, pointer);
45 static int  MGAGetPortAttributeTexture(ScrnInfoPtr, Atom ,INT32 *, pointer);
46 
47 static void MGAStopVideo(ScrnInfoPtr, pointer, Bool);
48 static void MGAQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short,
49 			unsigned int *, unsigned int *, pointer);
50 static int  MGAPutImage(ScrnInfoPtr, short, short, short, short, short,
51 			short, short, short, int, unsigned char*, short,
52 			short, Bool, RegionPtr, pointer, DrawablePtr);
53 static int  MGAQueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
54 			unsigned short *,  int *, int *);
55 static void MGAFreeMemory(ScrnInfoPtr pScrn, void *mem_struct);
56 
57 static void MGAResetVideoOverlay(ScrnInfoPtr);
58 
59 static void MGAVideoTimerCallback(ScrnInfoPtr pScrn, Time time);
60 
61 static XF86VideoAdaptorPtr MGASetupImageVideoILOAD(ScreenPtr);
62 static int MGAPutImageILOAD(ScrnInfoPtr, short, short, short, short, short,
63 			    short, short, short, int, unsigned char*, short,
64 			    short, Bool, RegionPtr, pointer, DrawablePtr);
65 
66 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
67 
68 static Atom xvBrightness, xvContrast, xvColorKey, xvDoubleBuffer;
69 
70 #ifdef USE_EXA
71 static void
MGAVideoSave(ScreenPtr pScreen,ExaOffscreenArea * area)72 MGAVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
73 {
74     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
75     MGAPtr pMga = MGAPTR(pScrn);
76     MGAPortPrivPtr pPriv = pMga->portPrivate;
77 
78     if (pPriv->video_memory == area)
79         pPriv->video_memory = NULL;
80 }
81 #endif /* USE_EXA */
82 
MGAInitVideo(ScreenPtr pScreen)83 void MGAInitVideo(ScreenPtr pScreen)
84 {
85     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
86     XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
87     XF86VideoAdaptorPtr newAdaptor = NULL;
88     MGAPtr pMga = MGAPTR(pScrn);
89     int num_adaptors;
90 
91     if ((pScrn->bitsPerPixel != 8) && !pMga->NoAccel &&
92 	(pMga->SecondCrtc == FALSE) &&
93 	((pMga->Chipset == PCI_CHIP_MGA2164) ||
94 	 (pMga->Chipset == PCI_CHIP_MGA2164_AGP) ||
95 /*	 (pMga->Chipset == PCI_CHIP_MGA2064) ||     */
96 	 (pMga->Chipset == PCI_CHIP_MGAG200) ||
97 	 (pMga->Chipset == PCI_CHIP_MGAG200_PCI) ||
98 	 (pMga->Chipset == PCI_CHIP_MGAG400) ||
99 	 (pMga->Chipset == PCI_CHIP_MGAG550))) {
100 	if ((pMga->Chipset == PCI_CHIP_MGA2164) ||
101 /*	    (pMga->Chipset == PCI_CHIP_MGA2064) ||   */
102 	    (pMga->Chipset == PCI_CHIP_MGA2164_AGP)) {
103 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using MGA 2164W ILOAD video\n");
104 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
105 		       "This is an experimental driver and may not work on your machine.\n");
106 
107 	    newAdaptor = MGASetupImageVideoILOAD(pScreen);
108 	    pMga->TexturedVideo = TRUE;
109 	    /* ^^^ this is not really true but the ILOAD scaler shares
110 	     * much more code with the textured video than the overlay
111 	     */
112 	} else if (pMga->TexturedVideo && (pScrn->bitsPerPixel != 24)) {
113 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using texture video\n");
114 	    newAdaptor = MGASetupImageVideoTexture(pScreen);
115 	    pMga->TexturedVideo = TRUE;
116 	} else {
117 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using overlay video\n");
118 	    newAdaptor = MGASetupImageVideoOverlay(pScreen);
119 	    pMga->TexturedVideo = FALSE;
120 	}
121 
122 	MGAInitOffscreenImages(pScreen);
123     }
124 
125     num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
126 
127     if(newAdaptor) {
128 	if(!num_adaptors) {
129 	    num_adaptors = 1;
130 	    adaptors = &newAdaptor;
131 	} else {
132 	    /* need to free this someplace */
133 	    newAdaptors = malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *));
134 	    if(newAdaptors) {
135 		memcpy(newAdaptors, adaptors, num_adaptors *
136 					sizeof(XF86VideoAdaptorPtr));
137 		newAdaptors[num_adaptors] = newAdaptor;
138 		adaptors = newAdaptors;
139 		num_adaptors++;
140 	    }
141 	}
142     }
143 
144     if(num_adaptors)
145         xf86XVScreenInit(pScreen, adaptors, num_adaptors);
146 
147     free(newAdaptors);
148 }
149 
150 /* client libraries expect an encoding */
151 static XF86VideoEncodingRec DummyEncoding[2] =
152 {
153  {   /* overlay limit */
154    0,
155    "XV_IMAGE",
156    1024, 1024,
157    {1, 1}
158  },
159  {  /* texture limit */
160    0,
161    "XV_IMAGE",
162    2046, 2046,
163    {1, 1}
164  }
165 };
166 
167 #define NUM_FORMATS 6
168 
169 static XF86VideoFormatRec Formats[NUM_FORMATS] =
170 {
171    {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
172    {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
173 };
174 
175 #define NUM_ATTRIBUTES_OVERLAY 4
176 
177 static XF86AttributeRec Attributes[NUM_ATTRIBUTES_OVERLAY] =
178 {
179    {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
180    {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
181    {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
182    {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}
183 };
184 
185 #define NUM_IMAGES 4
186 
187 static XF86ImageRec Images[NUM_IMAGES] =
188 {
189 	XVIMAGE_YUY2,
190 	XVIMAGE_YV12,
191 	XVIMAGE_I420,
192 	XVIMAGE_UYVY
193 };
194 
195 static void
MGAResetVideoOverlay(ScrnInfoPtr pScrn)196 MGAResetVideoOverlay(ScrnInfoPtr pScrn)
197 {
198     MGAPtr pMga = MGAPTR(pScrn);
199     MGAPortPrivPtr pPriv = pMga->portPrivate;
200 
201     CHECK_DMA_QUIESCENT(pMga, pScrn);
202 
203     outMGAdac(0x51, 0x01); /* keying on */
204     outMGAdac(0x52, 0xff); /* full mask */
205     outMGAdac(0x53, 0xff);
206     outMGAdac(0x54, 0xff);
207 
208     outMGAdac(0x55, (pPriv->colorKey & pScrn->mask.red) >>
209 		    pScrn->offset.red);
210     outMGAdac(0x56, (pPriv->colorKey & pScrn->mask.green) >>
211 		    pScrn->offset.green);
212     outMGAdac(0x57, (pPriv->colorKey & pScrn->mask.blue) >>
213 		    pScrn->offset.blue);
214 
215     OUTREG(MGAREG_BESLUMACTL, ((pPriv->brightness & 0xff) << 16) |
216 			       (pPriv->contrast & 0xff));
217 }
218 
219 
220 static XF86VideoAdaptorPtr
MGAAllocAdaptor(ScrnInfoPtr pScrn,Bool doublebuffer)221 MGAAllocAdaptor(ScrnInfoPtr pScrn, Bool doublebuffer)
222 {
223     XF86VideoAdaptorPtr adapt;
224     MGAPtr pMga = MGAPTR(pScrn);
225     MGAPortPrivPtr pPriv;
226     int i;
227 
228     if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
229 	return NULL;
230 
231     if(!(pPriv = calloc(1, sizeof(MGAPortPrivRec) +
232 			(sizeof(DevUnion) * MGA_MAX_PORTS))))
233     {
234 	free(adapt);
235 	return NULL;
236     }
237 
238     adapt->pPortPrivates = (DevUnion*)(&pPriv[1]);
239 
240     for(i = 0; i < MGA_MAX_PORTS; i++)
241 	adapt->pPortPrivates[i].val = i;
242 
243     xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
244     xvContrast   = MAKE_ATOM("XV_CONTRAST");
245     xvColorKey   = MAKE_ATOM("XV_COLORKEY");
246     xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
247 
248     pPriv->colorKey = pMga->videoKey;
249     pPriv->videoStatus = 0;
250     pPriv->brightness = 0;
251     pPriv->contrast = 128;
252     pPriv->lastPort = -1;
253     pPriv->doubleBuffer = doublebuffer;
254     pPriv->currentBuffer = 0;
255 
256     pMga->adaptor = adapt;
257     pMga->portPrivate = pPriv;
258 
259     return adapt;
260 }
261 
262 static XF86VideoAdaptorPtr
MGASetupImageVideoOverlay(ScreenPtr pScreen)263 MGASetupImageVideoOverlay(ScreenPtr pScreen)
264 {
265     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
266     MGAPtr pMga = MGAPTR(pScrn);
267     XF86VideoAdaptorPtr adapt;
268 
269     adapt = MGAAllocAdaptor(pScrn, TRUE);
270     if (adapt == NULL)
271 	return NULL;
272 
273     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
274     adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
275     adapt->name = "Matrox G-Series Backend Scaler";
276     adapt->nEncodings = 1;
277     adapt->pEncodings = &DummyEncoding[0];
278     adapt->nFormats = NUM_FORMATS;
279     adapt->pFormats = Formats;
280     adapt->nPorts = 1;
281     adapt->pAttributes = Attributes;
282     if (pMga->Chipset == PCI_CHIP_MGAG400 ||
283 	pMga->Chipset == PCI_CHIP_MGAG550) {
284 	adapt->nImages = 4;
285 	adapt->nAttributes = 4;
286     } else {
287 	adapt->nImages = 3;
288 	adapt->nAttributes = 1;
289     }
290     adapt->pImages = Images;
291     adapt->PutVideo = NULL;
292     adapt->PutStill = NULL;
293     adapt->GetVideo = NULL;
294     adapt->GetStill = NULL;
295     adapt->StopVideo = MGAStopVideo;
296     adapt->SetPortAttribute = MGASetPortAttributeOverlay;
297     adapt->GetPortAttribute = MGAGetPortAttributeOverlay;
298     adapt->QueryBestSize = MGAQueryBestSize;
299     adapt->PutImage = MGAPutImage;
300     adapt->QueryImageAttributes = MGAQueryImageAttributes;
301 
302     /* gotta uninit this someplace */
303     REGION_NULL(pScreen, &(pMga->portPrivate->clip));
304 
305     MGAResetVideoOverlay(pScrn);
306 
307     return adapt;
308 }
309 
310 
311 static XF86VideoAdaptorPtr
MGASetupImageVideoTexture(ScreenPtr pScreen)312 MGASetupImageVideoTexture(ScreenPtr pScreen)
313 {
314     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
315     XF86VideoAdaptorPtr adapt;
316     MGAPtr pMga = MGAPTR(pScrn);
317 
318     adapt = MGAAllocAdaptor(pScrn, FALSE);
319     if (adapt == NULL)
320 	return NULL;
321 
322     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
323     adapt->flags = 0;
324     adapt->name = "Matrox G-Series Texture Engine";
325     adapt->nEncodings = 1;
326     adapt->pEncodings = &DummyEncoding[1];
327     adapt->nFormats = NUM_FORMATS;
328     adapt->pFormats = Formats;
329     adapt->nPorts = MGA_MAX_PORTS;
330     adapt->pAttributes = NULL;
331     adapt->nAttributes = 0;
332     adapt->pImages = Images;
333     if (pMga->Chipset == PCI_CHIP_MGAG400 ||
334 	pMga->Chipset == PCI_CHIP_MGAG550)
335 	adapt->nImages = 4;
336     else
337 	adapt->nImages = 3;
338     adapt->PutVideo = NULL;
339     adapt->PutStill = NULL;
340     adapt->GetVideo = NULL;
341     adapt->GetStill = NULL;
342     adapt->StopVideo = MGAStopVideo;
343     adapt->SetPortAttribute = MGASetPortAttributeTexture;
344     adapt->GetPortAttribute = MGAGetPortAttributeTexture;
345     adapt->QueryBestSize = MGAQueryBestSize;
346     adapt->PutImage = MGAPutImage;
347     adapt->QueryImageAttributes = MGAQueryImageAttributes;
348 
349     return adapt;
350 }
351 
352 
353 static void
MGAStopVideo(ScrnInfoPtr pScrn,pointer data,Bool shutdown)354 MGAStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
355 {
356   MGAPtr pMga = MGAPTR(pScrn);
357   MGAPortPrivPtr pPriv = pMga->portPrivate;
358 
359   if(pMga->TexturedVideo) return;
360 
361   REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
362 
363   if(shutdown) {
364      if(pPriv->videoStatus & CLIENT_VIDEO_ON)
365 	OUTREG(MGAREG_BESCTL, 0);
366      if (pPriv->video_memory) {
367          MGAFreeMemory(pScrn, pPriv->video_memory);
368          pPriv->video_memory = NULL;
369      }
370      pPriv->videoStatus = 0;
371   } else {
372      if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
373 	pPriv->videoStatus |= OFF_TIMER;
374 	pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
375      }
376   }
377 }
378 
379 static int
MGASetPortAttributeOverlay(ScrnInfoPtr pScrn,Atom attribute,INT32 value,pointer data)380 MGASetPortAttributeOverlay(
381   ScrnInfoPtr pScrn,
382   Atom attribute,
383   INT32 value,
384   pointer data
385 ){
386   MGAPtr pMga = MGAPTR(pScrn);
387   MGAPortPrivPtr pPriv = pMga->portPrivate;
388 
389   CHECK_DMA_QUIESCENT(pMga, pScrn);
390 
391   if(attribute == xvBrightness) {
392 	if((value < -128) || (value > 127))
393 	   return BadValue;
394 	pPriv->brightness = value;
395 	OUTREG(MGAREG_BESLUMACTL, ((pPriv->brightness & 0xff) << 16) |
396 			           (pPriv->contrast & 0xff));
397   } else
398   if(attribute == xvContrast) {
399 	if((value < 0) || (value > 255))
400 	   return BadValue;
401 	pPriv->contrast = value;
402 	OUTREG(MGAREG_BESLUMACTL, ((pPriv->brightness & 0xff) << 16) |
403 			           (pPriv->contrast & 0xff));
404   } else
405   if(attribute == xvColorKey) {
406 	pPriv->colorKey = value;
407 	outMGAdac(0x55, (pPriv->colorKey & pScrn->mask.red) >>
408 		    pScrn->offset.red);
409 	outMGAdac(0x56, (pPriv->colorKey & pScrn->mask.green) >>
410 		    pScrn->offset.green);
411 	outMGAdac(0x57, (pPriv->colorKey & pScrn->mask.blue) >>
412 		    pScrn->offset.blue);
413 	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
414   } else
415   if(attribute == xvDoubleBuffer) {
416 	if((value < 0) || (value > 1))
417           return BadValue;
418 	pPriv->doubleBuffer = value;
419   } else return BadMatch;
420 
421   return Success;
422 }
423 
424 static int
MGAGetPortAttributeOverlay(ScrnInfoPtr pScrn,Atom attribute,INT32 * value,pointer data)425 MGAGetPortAttributeOverlay(
426   ScrnInfoPtr pScrn,
427   Atom attribute,
428   INT32 *value,
429   pointer data
430 ){
431   MGAPtr pMga = MGAPTR(pScrn);
432   MGAPortPrivPtr pPriv = pMga->portPrivate;
433 
434   if(attribute == xvBrightness) {
435 	*value = pPriv->brightness;
436   } else
437   if(attribute == xvContrast) {
438 	*value = pPriv->contrast;
439   } else
440   if(attribute == xvDoubleBuffer) {
441         *value = pPriv->doubleBuffer ? 1 : 0;
442   } else
443   if(attribute == xvColorKey) {
444 	*value = pPriv->colorKey;
445   } else return BadMatch;
446 
447   return Success;
448 }
449 
450 
451 static int
MGASetPortAttributeTexture(ScrnInfoPtr pScrn,Atom attribute,INT32 value,pointer data)452 MGASetPortAttributeTexture(
453   ScrnInfoPtr pScrn,
454   Atom attribute,
455   INT32 value,
456   pointer data
457 ) {
458   return BadMatch;
459 }
460 
461 
462 static int
MGAGetPortAttributeTexture(ScrnInfoPtr pScrn,Atom attribute,INT32 * value,pointer data)463 MGAGetPortAttributeTexture(
464   ScrnInfoPtr pScrn,
465   Atom attribute,
466   INT32 *value,
467   pointer data
468 ){
469   return BadMatch;
470 }
471 
472 static void
MGAQueryBestSize(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)473 MGAQueryBestSize(
474   ScrnInfoPtr pScrn,
475   Bool motion,
476   short vid_w, short vid_h,
477   short drw_w, short drw_h,
478   unsigned int *p_w, unsigned int *p_h,
479   pointer data
480 ){
481   *p_w = drw_w;
482   *p_h = drw_h;
483 }
484 
485 
486 static void
MGACopyData(unsigned char * src,unsigned char * dst,int srcPitch,int dstPitch,int h,int w)487 MGACopyData(
488   unsigned char *src,
489   unsigned char *dst,
490   int srcPitch,
491   int dstPitch,
492   int h,
493   int w
494 ){
495     w <<= 1;
496     while(h--) {
497 	/* XXX Maybe this one needs big-endian fixes, too? -ReneR */
498 	memcpy(dst, src, w);
499 	src += srcPitch;
500 	dst += dstPitch;
501     }
502 }
503 
504 static void
MGACopyMungedData(unsigned char * src1,unsigned char * src2,unsigned char * src3,unsigned char * dst1,int srcPitch,int srcPitch2,int dstPitch,int h,int w)505 MGACopyMungedData(
506    unsigned char *src1,
507    unsigned char *src2,
508    unsigned char *src3,
509    unsigned char *dst1,
510    int srcPitch,
511    int srcPitch2,
512    int dstPitch,
513    int h,
514    int w
515 ){
516    CARD32 *dst;
517    CARD8 *s1, *s2, *s3;
518    int i, j;
519 
520    w >>= 1;
521 
522    for(j = 0; j < h; j++) {
523         dst = (CARD32*)dst1;
524         s1 = src1;  s2 = src2;  s3 = src3;
525         i = w;
526         while(i > 4) {
527 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
528            dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
529            dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
530            dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
531            dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
532 #else
533            dst[0] = (s1[0] << 16) | s1[1] | (s3[0] << 24) | (s2[0] << 8);
534            dst[1] = (s1[2] << 16) | s1[3] | (s3[1] << 24) | (s2[1] << 8);
535            dst[2] = (s1[4] << 16) | s1[5] | (s3[2] << 24) | (s2[2] << 8);
536            dst[3] = (s1[6] << 16) | s1[7] | (s3[3] << 24) | (s2[3] << 8);
537 #endif
538            dst += 4; s2 += 4; s3 += 4; s1 += 8;
539            i -= 4;
540         }
541 
542         while(i--) {
543 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
544            dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
545 #else
546            dst[0] = (s1[0] << 16) | s1[1] | (s3[0] << 24) | (s2[0] << 8);
547 #endif
548            dst++; s2++; s3++;
549            s1 += 2;
550         }
551 
552         dst1 += dstPitch;
553         src1 += srcPitch;
554         if(j & 1) {
555             src2 += srcPitch2;
556             src3 += srcPitch2;
557         }
558    }
559 }
560 
561 
562 static CARD32
MGAAllocateMemory(ScrnInfoPtr pScrn,void ** mem_struct,int size)563 MGAAllocateMemory(
564    ScrnInfoPtr pScrn,
565    void **mem_struct,
566    int size
567 ){
568 #if defined(USE_XAA) || defined(USE_EXA)
569    MGAPtr pMga = MGAPTR(pScrn);
570 #endif /* defined(USE_XAA) || defined(USE_EXA) */
571 #ifdef USE_XAA
572    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
573 #endif /* USE_XAA */
574    int offset = 0;
575 
576 #ifdef USE_EXA
577    if (pMga->Exa) {
578        ExaOffscreenArea *area = *mem_struct;
579 
580 	if (area) {
581 	    if (area->size >= size)
582 		return area->offset;
583 
584 	    exaOffscreenFree(pScrn->pScreen, area);
585 	}
586 
587 	area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, MGAVideoSave,
588 				 NULL);
589 	*mem_struct = area;
590 
591 	if (!area)
592 	    return 0;
593 
594 	offset = area->offset;
595    }
596 #endif /* USE_EXA */
597 #ifdef USE_XAA
598    FBLinearPtr linear = *mem_struct;
599    int cpp = pMga->CurrentLayout.bitsPerPixel / 8;
600 
601    /* XAA allocates in units of pixels at the screen bpp, so adjust size
602     * appropriately.
603     */
604    size = (size + cpp - 1) / cpp;
605 
606    if (!pMga->Exa) {
607        if (linear) {
608            if (linear->size >= size)
609                return linear->offset * cpp;
610 
611            if (xf86ResizeOffscreenLinear(linear, size))
612                return linear->offset * cpp;
613 
614            xf86FreeOffscreenLinear(linear);
615        }
616 
617 
618        linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
619                                             NULL, NULL, NULL);
620        *mem_struct = linear;
621 
622        if (!linear) {
623            int max_size;
624 
625            xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
626                                            PRIORITY_EXTREME);
627 
628            if (max_size < size)
629                return 0;
630 
631            xf86PurgeUnlockedOffscreenAreas(pScreen);
632 
633            linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
634                                                 NULL, NULL, NULL);
635            *mem_struct = linear;
636 
637            if (!linear)
638                return 0;
639        }
640 
641        offset = linear->offset * cpp;
642    }
643 #endif /* USE_XAA */
644 
645    return offset;
646 }
647 
648 static void
MGAFreeMemory(ScrnInfoPtr pScrn,void * mem_struct)649 MGAFreeMemory(ScrnInfoPtr pScrn, void *mem_struct)
650 {
651 #if defined(USE_XAA) || defined(USE_EXA)
652     MGAPtr pMga = MGAPTR(pScrn);
653 #endif /* defined(USE_XAA) || defined(USE_EXA) */
654 
655 #ifdef USE_EXA
656     if (pMga->Exa) {
657 	ExaOffscreenArea *area = mem_struct;
658 
659 	if (area)
660 	    exaOffscreenFree(pScrn->pScreen, area);
661     }
662 #endif /* USE_EXA */
663 #ifdef USE_XAA
664     if (!pMga->Exa) {
665 	FBLinearPtr linear = mem_struct;
666 
667 	if (linear)
668 	    xf86FreeOffscreenLinear(linear);
669     }
670 #endif /* USE_XAA */
671 }
672 
673 static void
MGADisplayVideoOverlay(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)674 MGADisplayVideoOverlay(
675     ScrnInfoPtr pScrn,
676     int id,
677     int offset,
678     short width, short height,
679     int pitch,
680     int x1, int y1, int x2, int y2,
681     BoxPtr dstBox,
682     short src_w, short src_h,
683     short drw_w, short drw_h
684 ){
685     MGAPtr pMga = MGAPTR(pScrn);
686     int tmp, hzoom, intrep;
687     int maxOverlayClock;
688 
689     CHECK_DMA_QUIESCENT(pMga, pScrn);
690 
691     /* got 48 scanlines to do it in */
692     tmp = INREG(MGAREG_VCOUNT) + 48;
693     /* FIXME always change it in vertical retrace use CrtcV ?*/
694     if(tmp > pScrn->currentMode->CrtcVTotal)
695 	tmp -= 49; /* too bad */
696     else
697         tmp = pScrn->currentMode->CrtcVTotal -1;
698 
699     tmp = pScrn->currentMode->VDisplay +1;
700     /* enable accelerated 2x horizontal zoom when pixelclock >135MHz */
701 
702     if ((pMga->ChipRev >= 0x80) || (pMga->Chipset == PCI_CHIP_MGAG550)) {
703 	/* G450, G550 */
704 	maxOverlayClock = 234000;
705     } else {
706 	maxOverlayClock = 135000;
707     }
708 
709     hzoom = (pScrn->currentMode->Clock > maxOverlayClock) ? 1 : 0;
710 
711     switch(id) {
712     case FOURCC_UYVY:
713 	OUTREG(MGAREG_BESGLOBCTL, 0x000000c0 | (3 * hzoom) | (tmp << 16));
714 	break;
715     case FOURCC_YUY2:
716     default:
717 	OUTREG(MGAREG_BESGLOBCTL, 0x00000080 | (3 * hzoom) | (tmp << 16));
718 	break;
719     }
720 
721     OUTREG(MGAREG_BESA1ORG, offset);
722 
723     if(y1 & 0x00010000)
724 	OUTREG(MGAREG_BESCTL, 0x00040c41);
725     else
726 	OUTREG(MGAREG_BESCTL, 0x00040c01);
727 
728     OUTREG(MGAREG_BESHCOORD, (dstBox->x1 << 16) | (dstBox->x2 - 1));
729     OUTREG(MGAREG_BESVCOORD, (dstBox->y1 << 16) | (dstBox->y2 - 1));
730 
731     OUTREG(MGAREG_BESHSRCST, x1 & 0x03fffffc);
732     OUTREG(MGAREG_BESHSRCEND, (x2 - 0x00010000) & 0x03fffffc);
733     OUTREG(MGAREG_BESHSRCLST, (width - 1) << 16);
734 
735     OUTREG(MGAREG_BESPITCH, pitch >> 1);
736 
737     OUTREG(MGAREG_BESV1WGHT, y1 & 0x0000fffc);
738     OUTREG(MGAREG_BESV1SRCLST, height - 1 - (y1 >> 16));
739 
740     intrep = ((drw_h == src_h) || (drw_h < 2)) ? 0 : 1;
741     tmp = ((src_h - intrep) << 16)/(drw_h - intrep);
742     if(tmp >= (32 << 16))
743 	tmp = (32 << 16) - 1;
744     OUTREG(MGAREG_BESVISCAL, tmp & 0x001ffffc);
745 
746     intrep = ((drw_w == src_w) || (drw_w < 2)) ? 0 : 1;
747     tmp = (((src_w - intrep) << 16)/(drw_w - intrep)) << hzoom;
748     if(tmp >= (32 << 16))
749 	tmp = (32 << 16) - 1;
750     OUTREG(MGAREG_BESHISCAL, tmp & 0x001ffffc);
751 
752 }
753 
754 
755 /**
756  * \todo
757  * Starting with at least the G200, the chip can handle non-mipmapped
758  * non-power-of-two textures.  However, the code in this routine forces the
759  * texture dimensions to be powers of two.  That should simplify the code and
760  * may improve performance slightly.
761  */
762 static void
MGADisplayVideoTexture(ScrnInfoPtr pScrn,int id,int offset,int nbox,BoxPtr pbox,int width,int height,int pitch,short src_x,short src_y,short src_w,short src_h,short drw_x,short drw_y,short drw_w,short drw_h)763 MGADisplayVideoTexture(
764     ScrnInfoPtr pScrn,
765     int id, int offset,
766     int nbox, BoxPtr pbox,
767     int width, int height, int pitch,
768     short src_x, short src_y,
769     short src_w, short src_h,
770     short drw_x, short drw_y,
771     short drw_w, short drw_h
772 ){
773     MGAPtr pMga = MGAPTR(pScrn);
774     int log2w = 0, log2h = 0, i, incx, incy, padw, padh;
775 
776     pitch >>= 1;
777 
778     i = 12;
779     while(--i) {
780 	if(width & (1 << i)) {
781 	    log2w = i;
782 	    if(width & ((1 << i) - 1))
783 		log2w++;
784 	    break;
785 	}
786     }
787 
788     i = 12;
789     while(--i) {
790 	if(height & (1 << i)) {
791 	    log2h = i;
792 	    if(height & ((1 << i) - 1))
793 		log2h++;
794 	    break;
795 	}
796     }
797 
798     padw = 1 << log2w;
799     padh = 1 << log2h;
800     incx = (src_w << 20)/(drw_w * padw);
801     incy = (src_h << 20)/(drw_h * padh);
802 
803     CHECK_DMA_QUIESCENT(pMga, pScrn);
804 
805     WAITFIFO(15);
806     OUTREG(MGAREG_TMR0, incx);  /* sx inc */
807     OUTREG(MGAREG_TMR1, 0);  /* sy inc */
808     OUTREG(MGAREG_TMR2, 0);  /* tx inc */
809     OUTREG(MGAREG_TMR3, incy);  /* ty inc */
810     OUTREG(MGAREG_TMR4, 0x00000000);
811     OUTREG(MGAREG_TMR5, 0x00000000);
812     OUTREG(MGAREG_TMR8, 0x00010000);
813     OUTREG(MGAREG_TEXORG, offset);
814     OUTREG(MGAREG_TEXWIDTH,  log2w | (((8 - log2w) & 63) << 9) |
815 				((width - 1) << 18));
816     OUTREG(MGAREG_TEXHEIGHT, log2h | (((8 - log2h) & 63) << 9) |
817 				((height - 1) << 18));
818     if(id == FOURCC_UYVY)
819 	OUTREG(MGAREG_TEXCTL, 0x1A00010b | ((pitch & 0x07FF) << 9));
820     else
821 	OUTREG(MGAREG_TEXCTL, 0x1A00010a | ((pitch & 0x07FF) << 9));
822     OUTREG(MGAREG_TEXCTL2, 0x00000014);
823     OUTREG(MGAREG_DWGCTL, 0x000c7076);
824     OUTREG(MGAREG_TEXFILTER, 0x01e00020);
825     OUTREG(MGAREG_ALPHACTRL, 0x00000001);
826 
827     padw = (src_x << 20)/padw;
828     padh = (src_y << 20)/padh;
829 
830     while(nbox--) {
831 	WAITFIFO(4);
832 	OUTREG(MGAREG_TMR6, (incx * (pbox->x1 - drw_x)) + padw);
833 	OUTREG(MGAREG_TMR7, (incy * (pbox->y1 - drw_y)) + padh);
834 	OUTREG(MGAREG_FXBNDRY, (pbox->x2 << 16) | (pbox->x1 & 0xffff));
835 	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC,
836 				(pbox->y1 << 16) | (pbox->y2 - pbox->y1));
837 	pbox++;
838     }
839 
840     MGA_MARK_SYNC(pMga, pScrn);
841 }
842 
843 static int
MGAPutImage(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)844 MGAPutImage(
845   ScrnInfoPtr pScrn,
846   short src_x, short src_y,
847   short drw_x, short drw_y,
848   short src_w, short src_h,
849   short drw_w, short drw_h,
850   int id, unsigned char* buf,
851   short width, short height,
852   Bool Sync,
853   RegionPtr clipBoxes, pointer data,
854   DrawablePtr pDraw
855 ){
856    MGAPtr pMga = MGAPTR(pScrn);
857    MGAPortPrivPtr pPriv = pMga->portPrivate;
858    INT32 x1, x2, y1, y2;
859    unsigned char *dst_start;
860    int new_size, offset, offset2 = 0, offset3 = 0;
861    int srcPitch, srcPitch2 = 0, dstPitch;
862    int top, left, npixels, nlines;
863    BoxRec dstBox;
864    CARD32 tmp;
865 
866    /* Clip */
867    x1 = src_x;
868    x2 = src_x + src_w;
869    y1 = src_y;
870    y2 = src_y + src_h;
871 
872    dstBox.x1 = drw_x;
873    dstBox.x2 = drw_x + drw_w;
874    dstBox.y1 = drw_y;
875    dstBox.y2 = drw_y + drw_h;
876 
877    if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2,
878 			     clipBoxes, width, height))
879 	return Success;
880 
881    if(!pMga->TexturedVideo) {
882 	dstBox.x1 -= pScrn->frameX0;
883 	dstBox.x2 -= pScrn->frameX0;
884 	dstBox.y1 -= pScrn->frameY0;
885 	dstBox.y2 -= pScrn->frameY0;
886    }
887 
888    dstPitch = ((width << 1) + 15) & ~15;
889    new_size = dstPitch * height;
890 
891    switch(id) {
892    case FOURCC_YV12:
893    case FOURCC_I420:
894 	srcPitch = (width + 3) & ~3;
895 	offset2 = srcPitch * height;
896 	srcPitch2 = ((width >> 1) + 3) & ~3;
897 	offset3 = (srcPitch2 * (height >> 1)) + offset2;
898 	break;
899    case FOURCC_UYVY:
900    case FOURCC_YUY2:
901    default:
902 	srcPitch = (width << 1);
903 	break;
904    }
905 
906    pPriv->video_offset = MGAAllocateMemory(pScrn, &pPriv->video_memory,
907 					   pPriv->doubleBuffer ?
908                                            (new_size << 1) : new_size);
909    if (!pPriv->video_offset)
910 	return BadAlloc;
911 
912    pPriv->currentBuffer ^= 1;
913 
914     /* copy data */
915    top = y1 >> 16;
916    left = (x1 >> 16) & ~1;
917    npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
918    left <<= 1;
919 
920    offset = pPriv->video_offset;
921    if(pPriv->doubleBuffer)
922         offset += pPriv->currentBuffer * new_size;
923    dst_start = pMga->FbStart + offset + left + (top * dstPitch);
924 
925    if (pMga->TexturedVideo && ((long)data != pPriv->lastPort))
926        MGA_SYNC(pMga, pScrn);
927 
928    switch(id) {
929     case FOURCC_YV12:
930     case FOURCC_I420:
931 	top &= ~1;
932 	tmp = ((top >> 1) * srcPitch2) + (left >> 2);
933 	offset2 += tmp;
934 	offset3 += tmp;
935 	if(id == FOURCC_I420) {
936 	   tmp = offset2;
937 	   offset2 = offset3;
938 	   offset3 = tmp;
939 	}
940 	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
941 	MGACopyMungedData(buf + (top * srcPitch) + (left >> 1),
942 			  buf + offset2, buf + offset3, dst_start,
943 			  srcPitch, srcPitch2, dstPitch, nlines, npixels);
944 	break;
945     case FOURCC_UYVY:
946     case FOURCC_YUY2:
947     default:
948 	buf += (top * srcPitch) + left;
949 	nlines = ((y2 + 0xffff) >> 16) - top;
950 	MGACopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
951         break;
952     }
953 
954     if(pMga->TexturedVideo) {
955 	pPriv->lastPort = (long)data;
956 	MGADisplayVideoTexture(pScrn, id, offset,
957 		REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes),
958 		width, height, dstPitch, src_x, src_y, src_w, src_h,
959 		drw_x, drw_y, drw_w, drw_h);
960 	pPriv->videoStatus = FREE_TIMER;
961 	pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
962     } else {
963     /* update cliplist */
964 	if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
965 	    REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
966 	    /* draw these */
967 	    xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
968 	}
969 
970 	offset += top * dstPitch;
971 	MGADisplayVideoOverlay(pScrn, id, offset, width, height, dstPitch,
972 	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
973 
974 	pPriv->videoStatus = CLIENT_VIDEO_ON;
975     }
976     pMga->VideoTimerCallback = MGAVideoTimerCallback;
977 
978     return Success;
979 }
980 
981 
982 static int
MGAQueryImageAttributes(ScrnInfoPtr pScrn,int id,unsigned short * w,unsigned short * h,int * pitches,int * offsets)983 MGAQueryImageAttributes(
984     ScrnInfoPtr pScrn,
985     int id,
986     unsigned short *w, unsigned short *h,
987     int *pitches, int *offsets
988 ){
989     MGAPtr pMga = MGAPTR(pScrn);
990     int size, tmp;
991 
992     if(pMga->TexturedVideo) {
993 	if(*w > 2046) *w = 2046;
994 	if(*h > 2046) *h = 2046;
995     } else {
996 	if(*w > 1024) *w = 1024;
997 	if(*h > 1024) *h = 1024;
998     }
999 
1000     *w = (*w + 1) & ~1;
1001     if(offsets) offsets[0] = 0;
1002 
1003     switch(id) {
1004     case FOURCC_YV12:
1005     case FOURCC_I420:
1006 	*h = (*h + 1) & ~1;
1007 	size = (*w + 3) & ~3;
1008 	if(pitches) pitches[0] = size;
1009 	size *= *h;
1010 	if(offsets) offsets[1] = size;
1011 	tmp = ((*w >> 1) + 3) & ~3;
1012 	if(pitches) pitches[1] = pitches[2] = tmp;
1013 	tmp *= (*h >> 1);
1014 	size += tmp;
1015 	if(offsets) offsets[2] = size;
1016 	size += tmp;
1017 	break;
1018     case FOURCC_UYVY:
1019     case FOURCC_YUY2:
1020     default:
1021 	size = *w << 1;
1022 	if(pitches) pitches[0] = size;
1023 	size *= *h;
1024 	break;
1025     }
1026 
1027     return size;
1028 }
1029 
1030 static void
MGAVideoTimerCallback(ScrnInfoPtr pScrn,Time time)1031 MGAVideoTimerCallback(ScrnInfoPtr pScrn, Time time)
1032 {
1033     MGAPtr pMga = MGAPTR(pScrn);
1034     MGAPortPrivPtr pPriv = pMga->portPrivate;
1035 
1036     if(pPriv->videoStatus & TIMER_MASK) {
1037 	if(pPriv->videoStatus & OFF_TIMER) {
1038 	    if(pPriv->offTime < time) {
1039 		OUTREG(MGAREG_BESCTL, 0);
1040 		pPriv->videoStatus = FREE_TIMER;
1041 		pPriv->freeTime = time + FREE_DELAY;
1042 	    }
1043 	} else {  /* FREE_TIMER */
1044 	    if(pPriv->freeTime < time) {
1045 		if (pPriv->video_memory) {
1046                    MGAFreeMemory(pScrn, pPriv->video_memory);
1047 		   pPriv->video_memory = NULL;
1048 		}
1049 		pPriv->videoStatus = 0;
1050 	        pMga->VideoTimerCallback = NULL;
1051 	    }
1052         }
1053     } else  /* shouldn't get here */
1054 	pMga->VideoTimerCallback = NULL;
1055 }
1056 
1057 
1058 /****************** Offscreen stuff ***************/
1059 
1060 typedef struct {
1061   void *surface_memory;
1062   Bool isOn;
1063 } OffscreenPrivRec, * OffscreenPrivPtr;
1064 
1065 static int
MGAAllocateSurface(ScrnInfoPtr pScrn,int id,unsigned short w,unsigned short h,XF86SurfacePtr surface)1066 MGAAllocateSurface(
1067     ScrnInfoPtr pScrn,
1068     int id,
1069     unsigned short w,
1070     unsigned short h,
1071     XF86SurfacePtr surface
1072 ){
1073     void *surface_memory = NULL;
1074     int pitch, size, bpp, offset;
1075     OffscreenPrivPtr pPriv;
1076 
1077     if((w > 1024) || (h > 1024))
1078 	return BadAlloc;
1079 
1080     w = (w + 1) & ~1;
1081     pitch = ((w << 1) + 15) & ~15;
1082     bpp = pScrn->bitsPerPixel >> 3;
1083     size = ((pitch * h) + bpp - 1) / bpp;
1084 
1085     offset = MGAAllocateMemory(pScrn, &surface_memory, size);
1086     if (!offset)
1087 	return BadAlloc;
1088 
1089     surface->width = w;
1090     surface->height = h;
1091 
1092     if(!(surface->pitches = malloc(sizeof(int)))) {
1093         MGAFreeMemory(pScrn, surface_memory);
1094 	return BadAlloc;
1095     }
1096     if(!(surface->offsets = malloc(sizeof(int)))) {
1097 	free(surface->pitches);
1098         MGAFreeMemory(pScrn, surface_memory);
1099 	return BadAlloc;
1100     }
1101     if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
1102 	free(surface->pitches);
1103 	free(surface->offsets);
1104         MGAFreeMemory(pScrn, surface_memory);
1105 	return BadAlloc;
1106     }
1107 
1108     pPriv->surface_memory = surface_memory;
1109     pPriv->isOn = FALSE;
1110 
1111     surface->pScrn = pScrn;
1112     surface->id = id;
1113     surface->pitches[0] = pitch;
1114     surface->offsets[0] = offset;
1115     surface->devPrivate.ptr = (pointer)pPriv;
1116 
1117     return Success;
1118 }
1119 
1120 static int
MGAStopSurface(XF86SurfacePtr surface)1121 MGAStopSurface(
1122     XF86SurfacePtr surface
1123 ){
1124     OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1125 
1126     if(pPriv->isOn) {
1127 	ScrnInfoPtr pScrn = surface->pScrn;
1128 	MGAPtr pMga = MGAPTR(pScrn);
1129 	OUTREG(MGAREG_BESCTL, 0);
1130 	pPriv->isOn = FALSE;
1131     }
1132 
1133     return Success;
1134 }
1135 
1136 
1137 static int
MGAFreeSurface(XF86SurfacePtr surface)1138 MGAFreeSurface(
1139     XF86SurfacePtr surface
1140 ){
1141     ScrnInfoPtr pScrn = surface->pScrn;
1142     OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1143 
1144     if(pPriv->isOn)
1145 	MGAStopSurface(surface);
1146     MGAFreeMemory(pScrn, pPriv->surface_memory);
1147     free(surface->pitches);
1148     free(surface->offsets);
1149     free(surface->devPrivate.ptr);
1150 
1151     return Success;
1152 }
1153 
1154 static int
MGAGetSurfaceAttribute(ScrnInfoPtr pScrn,Atom attribute,INT32 * value)1155 MGAGetSurfaceAttribute(
1156     ScrnInfoPtr pScrn,
1157     Atom attribute,
1158     INT32 *value
1159 ){
1160     return MGAGetPortAttributeOverlay(pScrn, attribute, value, 0);
1161 }
1162 
1163 static int
MGASetSurfaceAttribute(ScrnInfoPtr pScrn,Atom attribute,INT32 value)1164 MGASetSurfaceAttribute(
1165     ScrnInfoPtr pScrn,
1166     Atom attribute,
1167     INT32 value
1168 ){
1169     return MGASetPortAttributeOverlay(pScrn, attribute, value, 0);
1170 }
1171 
1172 
1173 static int
MGADisplaySurface(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)1174 MGADisplaySurface(
1175     XF86SurfacePtr surface,
1176     short src_x, short src_y,
1177     short drw_x, short drw_y,
1178     short src_w, short src_h,
1179     short drw_w, short drw_h,
1180     RegionPtr clipBoxes
1181 ){
1182     OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1183     ScrnInfoPtr pScrn = surface->pScrn;
1184     MGAPtr pMga = MGAPTR(pScrn);
1185     MGAPortPrivPtr portPriv = pMga->portPrivate;
1186     INT32 x1, y1, x2, y2;
1187     BoxRec dstBox;
1188 
1189     x1 = src_x;
1190     x2 = src_x + src_w;
1191     y1 = src_y;
1192     y2 = src_y + src_h;
1193 
1194     dstBox.x1 = drw_x;
1195     dstBox.x2 = drw_x + drw_w;
1196     dstBox.y1 = drw_y;
1197     dstBox.y2 = drw_y + drw_h;
1198 
1199     if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
1200 			      surface->width, surface->height))
1201     {
1202 	return Success;
1203     }
1204 
1205     dstBox.x1 -= pScrn->frameX0;
1206     dstBox.x2 -= pScrn->frameX0;
1207     dstBox.y1 -= pScrn->frameY0;
1208     dstBox.y2 -= pScrn->frameY0;
1209 
1210     MGAResetVideoOverlay(pScrn);
1211 
1212     MGADisplayVideoOverlay(pScrn, surface->id, surface->offsets[0],
1213 	     surface->width, surface->height, surface->pitches[0],
1214 	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
1215 
1216     xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
1217 
1218     pPriv->isOn = TRUE;
1219     /* we've prempted the XvImage stream so set its free timer */
1220     if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
1221 	REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
1222 	UpdateCurrentTime();
1223 	portPriv->videoStatus = FREE_TIMER;
1224 	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
1225 	pMga->VideoTimerCallback = MGAVideoTimerCallback;
1226     }
1227 
1228     return Success;
1229 }
1230 
1231 
1232 static void
MGAInitOffscreenImages(ScreenPtr pScreen)1233 MGAInitOffscreenImages(ScreenPtr pScreen)
1234 {
1235     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1236     MGAPtr pMga = MGAPTR(pScrn);
1237     int num = (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550) ? 2 : 1;
1238     XF86OffscreenImagePtr offscreenImages;
1239 
1240     /* need to free this someplace */
1241     if(!(offscreenImages = malloc(num * sizeof(XF86OffscreenImageRec))))
1242 	return;
1243 
1244     offscreenImages[0].image = &Images[0];
1245     offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
1246 			       VIDEO_CLIP_TO_VIEWPORT;
1247     offscreenImages[0].alloc_surface = MGAAllocateSurface;
1248     offscreenImages[0].free_surface = MGAFreeSurface;
1249     offscreenImages[0].display = MGADisplaySurface;
1250     offscreenImages[0].stop = MGAStopSurface;
1251     offscreenImages[0].setAttribute = MGASetSurfaceAttribute;
1252     offscreenImages[0].getAttribute = MGAGetSurfaceAttribute;
1253     offscreenImages[0].max_width = 1024;
1254     offscreenImages[0].max_height = 1024;
1255     offscreenImages[0].num_attributes = (num == 1) ? 1 : 4;
1256     offscreenImages[0].attributes = Attributes;
1257 
1258     if(num == 2) {
1259 	offscreenImages[1].image = &Images[3];
1260 	offscreenImages[1].flags = VIDEO_OVERLAID_IMAGES |
1261 				   VIDEO_CLIP_TO_VIEWPORT;
1262 	offscreenImages[1].alloc_surface = MGAAllocateSurface;
1263 	offscreenImages[1].free_surface = MGAFreeSurface;
1264 	offscreenImages[1].display = MGADisplaySurface;
1265 	offscreenImages[1].stop = MGAStopSurface;
1266 	offscreenImages[1].setAttribute = MGASetSurfaceAttribute;
1267 	offscreenImages[1].getAttribute = MGAGetSurfaceAttribute;
1268 	offscreenImages[1].max_width = 1024;
1269 	offscreenImages[1].max_height = 1024;
1270 	offscreenImages[1].num_attributes = 4;
1271 	offscreenImages[1].attributes = Attributes;
1272     }
1273 
1274     xf86XVRegisterOffscreenImages(pScreen, offscreenImages, num);
1275 }
1276 
1277 
1278 /* Matrox MGA 2164W Xv extension support.
1279 *  The extension is implemented as a HOST->FB image load in YUV format.
1280 *  I decided not to use real hardware overlay since on the Millennium II
1281 *  it would limit the size of the frame buffer to 4Mb (even on a 16Mb
1282 *  card) due to an hardware limitation.
1283 *  Author: Gabriele Gorla (gorlik@yahoo.com)
1284 *  Based on the MGA-Gxxx Xv extension by: Mark Vojkovich
1285    */
1286 
1287 /* This code is still in alpha stage. Only YUV->RGB conversion
1288    and horizontal scaling are hardware accelerated.
1289    All 4 FOURCC formats supported by X should be supported.
1290    It has been tested only on my DEC XP1000 at 1024x768x32 under
1291    linux 2.6.18 with X.org 7.1.1 (debian alpha)
1292 
1293    Bug reports and success/failure stories are greatly appreciated.
1294 */
1295 
1296 /* #define DEBUG_MGA2164 */
1297 /* #define CUSTOM_MEMCOPY */
1298 #define MGA2164_SWFILTER
1299 
1300 
1301 static XF86VideoAdaptorPtr
MGASetupImageVideoILOAD(ScreenPtr pScreen)1302 MGASetupImageVideoILOAD(ScreenPtr pScreen)
1303 {
1304     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1305     XF86VideoAdaptorPtr adapt;
1306     MGAPtr pMga = MGAPTR(pScrn);
1307 
1308     adapt = MGAAllocAdaptor(pScrn, FALSE);
1309     if (adapt == NULL)
1310 	return NULL;
1311 
1312     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1313     adapt->flags = 0;
1314     adapt->name = "Matrox Millennium II ILOAD Video Engine";
1315     adapt->nEncodings = 1;
1316     adapt->pEncodings = &DummyEncoding[1];
1317     adapt->nFormats = NUM_FORMATS;
1318     adapt->pFormats = Formats;
1319     adapt->nPorts = MGA_MAX_PORTS;
1320     adapt->pAttributes = NULL;
1321     adapt->nAttributes = 0;
1322 
1323     /* number of supported color formats */
1324     adapt->pImages = Images;
1325     adapt->nImages = 4;
1326 
1327     adapt->PutVideo = NULL;
1328     adapt->PutStill = NULL;
1329     adapt->GetVideo = NULL;
1330     adapt->GetStill = NULL;
1331     adapt->StopVideo = MGAStopVideo;
1332 
1333     adapt->SetPortAttribute = MGASetPortAttributeTexture;
1334     adapt->GetPortAttribute = MGAGetPortAttributeTexture;
1335     adapt->QueryBestSize = MGAQueryBestSize;
1336     adapt->PutImage = MGAPutImageILOAD;
1337     adapt->QueryImageAttributes = MGAQueryImageAttributes;
1338 
1339     REGION_INIT(pScreen, &(pMga->portPrivate->clip), NullBox, 0);
1340 
1341     return adapt;
1342 }
1343 
1344 /* this function is optimized for alpha. It might be better also for
1345 other load/store risc architectures but I never tested on anything else
1346 than my ev56 */
CopyMungedScanline_AXP(CARD32 * fb_ptr,short src_w,CARD32 * tsp,CARD32 * tpu,CARD32 * tpv)1347 static void CopyMungedScanline_AXP(CARD32 *fb_ptr, short src_w,
1348 				   CARD32 *tsp, CARD32 *tpu, CARD32 *tpv)
1349 {
1350     CARD32 k,y0,y1,u,v;
1351 
1352     for(k=src_w/8;k;k--) {
1353 	y0=*tsp;
1354 	y1=*(tsp+1);
1355 	u=*tpu;
1356 	v=*tpv;
1357 
1358 	*(fb_ptr)=(y1&0x000000ff)|((y1&0x0000ff00)<<8) |
1359 	    (v&0x00ff0000)<<8 | (u&0x00ff0000)>>8;
1360 	*(fb_ptr+1)=(y1&0x000000ff)|((y1&0x0000ff00)<<8) |
1361 	    (v&0x00ff0000)<<8 | (u&0x00ff0000)>>8;
1362 
1363 	*(fb_ptr+2)=(y0&0x000000ff)|((y0&0x0000ff00)<<8) |
1364 	    (v&0x000000ff)<<24 | (u&0x000000ff)<<8;
1365 	*(fb_ptr+3)=(y0&0x000000ff)|((y0&0x0000ff00)<<8) |
1366 	    (v&0x000000ff)<<24 | (u&0x000000ff)<<8;
1367 
1368 	/*correct below*/
1369 	/*    *(fb_ptr)=(y0&0x000000ff)|((y0&0x0000ff00)<<8) |
1370 	      (v&0x000000ff)<<24 | (u&0x000000ff)<<8;
1371 	      *(fb_ptr+1)=((y0&0x00ff0000)>>16)|((y0&0xff000000)>>8) |
1372 	      (v&0x0000ff00)<<16 | (u&0x0000ff00);
1373 	      *(fb_ptr+2)=(y1&0x000000ff)|((y1&0x0000ff00)<<8) |
1374 	      (v&0x00ff0000)<<8 | (u&0x00ff0000)>>8;
1375 	      *(fb_ptr+3)=((y1&0x00ff0000)>>16)|((y1&0xff000000)>>8) |
1376 	      (v&0xff000000) | (u&0xff000000)>>16; */
1377 
1378 	tsp+=2; tpu++; tpv++;
1379 	fb_ptr+=4;
1380     }
1381 }
1382 
1383 #if 0
1384 static void CopyMungedScanline_AXP2(CARD32 *fb_ptr, short src_w,
1385 				    CARD32 *tsp, CARD32 *tpu, CARD32 *tpv)
1386 {
1387     CARD8 *y, *u, *v;
1388     int k;
1389     y=(CARD8 *)tsp;
1390     u=(CARD8 *)tpu;
1391     v=(CARD8 *)tpv;
1392 
1393     for(k=src_w/8;k;k--) {
1394 	fb_ptr[0]=y[0] | y[1]<<16 | v[0]<<24 | u[0]<<8;
1395 	fb_ptr[1]=y[2] | y[3]<<16 | v[1]<<24 | u[1]<<8;
1396 	fb_ptr[2]=y[4] | y[5]<<16 | v[2]<<24 | u[2]<<8;
1397 	fb_ptr[3]=y[6] | y[7]<<16 | v[3]<<24 | u[3]<<8;
1398 
1399 	y+=8; u+=4; v+=4;
1400 	fb_ptr+=4;
1401     }
1402 }
1403 #endif
1404 
1405 
CopyMungedScanlineFilter_AXP(CARD32 * fb_ptr,short src_w,CARD32 * tsp1,CARD32 * tpu1,CARD32 * tpv1,CARD32 * tsp2,CARD32 * tpu2,CARD32 * tpv2,int beta,int xds)1406 static void CopyMungedScanlineFilter_AXP(CARD32 *fb_ptr, short src_w,
1407 					 CARD32 *tsp1, CARD32 *tpu1, CARD32 *tpv1,
1408 					 CARD32 *tsp2, CARD32 *tpu2, CARD32 *tpv2,
1409 					 int beta, int xds )
1410 {
1411     unsigned int k,y0_1,y1_1,y0_2,y1_2,u,v;
1412     int yf[8], uf[4], vf[4];
1413     int oneminbeta = 0xff - beta;
1414 
1415     for(k=xds*src_w/8;k;k--) {
1416 	y0_1=*tsp1;
1417 	y1_1=*(tsp1+1);
1418 	y0_2=*tsp2;
1419 	y1_2=*(tsp2+1);
1420 	u=*tpu1;
1421 	v=*tpv1;
1422 
1423 	tsp1+=2; tsp2+=2; tpu1++; tpv1++;
1424 	yf[0] = ((y0_1&0x000000ff)*oneminbeta + (y0_2&0x000000ff)*beta )>>8;
1425 	yf[1] = (((y0_1&0x0000ff00)>>8)*oneminbeta + ((y0_2&0x0000ff00)>>8)*beta )>>8;
1426 	yf[2] = (((y0_1&0x00ff0000)>>16)*oneminbeta + ((y0_2&0x00ff0000)>>16)*beta )>>8;
1427 	yf[3] = (((y0_1&0xff000000)>>24)*oneminbeta + ((y0_2&0xff000000)>>24)*beta )>>8;
1428 	yf[4] = ((y1_1&0x000000ff)*oneminbeta + (y1_2&0x000000ff)*beta )>>8;
1429 	yf[5] = (((y1_1&0x0000ff00)>>8)*oneminbeta + ((y1_2&0x0000ff00)>>8)*beta )>>8;
1430 	yf[6] = (((y1_1&0x00ff0000)>>16)*oneminbeta + ((y1_2&0x00ff0000)>>16)*beta )>>8;
1431 	yf[7] = (((y1_1&0xff000000)>>24)*oneminbeta + ((y1_2&0xff000000)>>24)*beta )>>8;
1432 
1433 	/* FIXME: there is still no filtering on u and v */
1434 	uf[0]=(u&0x000000ff);
1435 	uf[1]=(u&0x0000ff00)>>8;
1436 	uf[2]=(u&0x00ff0000)>>16;
1437 	uf[3]=(u&0xff000000)>>24;
1438 
1439 	vf[0]=(v&0x000000ff);
1440 	vf[1]=(v&0x0000ff00)>>8;
1441 	vf[2]=(v&0x00ff0000)>>16;
1442 	vf[3]=(v&0xff000000)>>24;
1443 
1444 	switch(xds) {
1445 	case 1:
1446 	    *(fb_ptr)=(yf[0]) | (yf[1]<<16) |
1447 		vf[0]<<24 | uf[0]<<8;
1448 	    *(fb_ptr+1)=(yf[2]) | (yf[3]<<16) |
1449 		vf[1]<<24 | uf[1]<<8;
1450 	    *(fb_ptr+2)=(yf[4]) | (yf[5]<<16) |
1451 		vf[2]<<24 | uf[2]<<8;
1452 	    *(fb_ptr+3)=(yf[6]) | (yf[7]<<16) |
1453 		vf[3]<<24 | uf[3]<<8;
1454 	    fb_ptr+=4;
1455 	    break;
1456 
1457 	case 2:
1458 	    *(fb_ptr)=(yf[0]+yf[1])/2 | (((yf[2]+yf[3])/2)<<16) |
1459 		((vf[0]+vf[1])/2 )<<24 | ((uf[0]+uf[1])/2)<<8;
1460 	    *(fb_ptr+1)=(yf[4]+yf[5])/2 | ( ((yf[6]+yf[7])/2) <<16) |
1461 		((vf[2]+vf[3])/2 )<<24 | ((uf[2]+uf[3])/2)<<8;
1462 	    fb_ptr+=2;
1463 	    break;
1464 
1465 	case 4:
1466 	    *(fb_ptr)=(yf[0]+yf[1]+yf[2]+yf[3])/4 | (((yf[4]+yf[5]+yf[6]+yf[7])/4)<<16) |
1467 		((vf[0]+vf[1]+vf[2]+vf[3])/4 )<<24 | ((uf[0]+uf[1]+uf[2]+uf[3])/4)<<8;
1468 	    fb_ptr+=1;
1469 	    break;
1470 
1471 	default:
1472 	    break;
1473 	}
1474     }
1475 }
1476 
1477 #if 0
1478 static void CopyMungedScanlineFilterDown_AXP(CARD32 *fb_ptr, short src_w,
1479 					     CARD32 *tsp1, CARD32 *tpu1, CARD32 *tpv1,
1480 					     CARD32 *tsp2, CARD32 *tpu2, CARD32 *tpv2,
1481 					     int beta , int xds)
1482 {
1483     unsigned int k,y0_1,y1_1,y0_2,y1_2,u,v;
1484     int yf[8], uf[4], vf[4];
1485 
1486     for(k=src_w/8;k;k--) {
1487 	y0_1=*tsp1;
1488 	y1_1=*(tsp1+1);
1489 	y0_2=*tsp2;
1490 	y1_2=*(tsp2+1);
1491 	u=*tpu1;
1492 	v=*tpv1;
1493 
1494 	tsp1+=2; tsp2+=2; tpu1++; tpv1++;
1495 	yf[0] = ((y0_1&0x000000ff) + (y0_2&0x000000ff))>>8;
1496 	yf[1] = (((y0_1&0x0000ff00)>>8) + ((y0_2&0x0000ff00)>>8))>>8;
1497 	yf[2] = (((y0_1&0x00ff0000)>>16) + ((y0_2&0x00ff0000)>>16))>>8;
1498 	yf[3] = (((y0_1&0x000000ff)>>24) + ((y0_2&0x000000ff)>>24))>>8;
1499 	yf[4] = ((y1_1&0x000000ff) + (y1_2&0x000000ff))>>8;
1500 	yf[5] = (((y1_1&0x0000ff00)>>8) + ((y1_2&0x0000ff00)>>8))>>8;
1501 	yf[6] = (((y1_1&0x00ff0000)>>16) + ((y1_2&0x00ff0000)>>16))>>8;
1502 	yf[7] = (((y1_1&0x000000ff)>>24) + ((y1_2&0x000000ff)>>24))>>8;
1503 
1504 	*(fb_ptr)=(yf[0]) | (yf[1]<<16) |
1505 	    (v&0x000000ff)<<24 | (u&0x000000ff)<<8;
1506 	*(fb_ptr+1)=(yf[2]) | (yf[3]<<16) |
1507 	    (v&0x0000ff00)<<16 | (u&0x0000ff00);
1508 	*(fb_ptr+2)=(yf[4]) | (yf[5]<<16) |
1509 	    (v&0x00ff0000)<<8 | (u&0x00ff0000)>>8;
1510 	*(fb_ptr+3)=(yf[6]) | (yf[7]<<16) |
1511 	    (v&0xff000000) | (u&0xff000000)>>16;
1512 
1513 	fb_ptr+=4;
1514     }
1515 }
1516 #endif
1517 
MGACopyScaledILOAD(ScrnInfoPtr pScrn,int id,unsigned char * buf,BoxPtr pbox,int width,int height,int pitch,short src_x,short src_y,short src_w,short src_h,short drw_x,short drw_y,short drw_w,short drw_h)1518 static void MGACopyScaledILOAD(
1519 			       ScrnInfoPtr pScrn,
1520 			       int id, unsigned char *buf,
1521 			       BoxPtr pbox,
1522 			       int width, int height, int pitch,
1523 			       short src_x, short src_y,
1524 			       short src_w, short src_h,
1525 			       short drw_x, short drw_y,
1526 			       short drw_w, short drw_h
1527 			       )
1528 {
1529     MGAPtr pMga = MGAPTR(pScrn);
1530     CARD32 *fb_ptr;
1531     unsigned char *ubuf, *vbuf, *tbuf;
1532     CARD32 *pu, *pv;
1533     int k,l;
1534 #ifdef MGA2164_BLIT_DUP
1535     int pl;
1536 #endif /* MGA2164_BLIT_DUP */
1537     int dl;
1538     int xds, yds;
1539     short box_h;
1540     short scr_pitch = ( pScrn->virtualX + 15) & ~15;
1541 
1542 #ifdef DEBUG_MGA2164
1543     char sbuf[255];
1544 
1545     sprintf(sbuf,"---- PBOX: x1=%d y1=%d w=%d h=%d (x2=%d y2=%d)\n",
1546 	    pbox->x1,pbox->y1,pbox->x2-pbox->x1,pbox->y2-pbox->y1,
1547 	    pbox->x2,pbox->y2);
1548     xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1549 
1550     sprintf(sbuf,"in src: src_x=%d src_y=%d src_w=%d src_h=%d\n",
1551 	    src_x,src_y,src_w,src_h);
1552     xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1553     sprintf(sbuf,"in drw: drw_x=%d drw_y=%d drw_w=%d drw_h=%d\n",
1554 	    drw_x,drw_y,drw_w,drw_h);
1555     xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1556 #endif
1557 
1558     /* scaling yuv->rgb */
1559 
1560     /* hack to force width and src image to be 8 pixel aligned */
1561     src_x&=~0x7;
1562     src_w&=~0x7;
1563 
1564     box_h=pbox->y2-pbox->y1;
1565 
1566     /* compute X down scaling factor */
1567     if(src_w>drw_w) {
1568 	if(src_w/2<drw_w) {
1569 	    xds=2;
1570 	} else if(src_w/4<drw_w) {
1571 	    xds=4;
1572 	} else { xds=8; }
1573     } else xds = 1;
1574 
1575     /* prevent crashing when dragging window outside left boundary of screen */
1576     /* FIXME: need to implement per pixel left start to avoid undesired
1577        effects when dragging window outside left screen boundary */
1578 
1579     if(drw_x<0) {
1580 	src_x=( -(drw_x*src_w)/drw_w + 0x7)&~0x7;
1581 	src_w-=src_x;
1582 	drw_w+=drw_x;
1583 	drw_x=0;
1584     }
1585 
1586     src_w/=xds;
1587 
1588     /* compute X down scaling factor */
1589     if(src_h>drw_h) {
1590 	if(src_h/2<drw_h) {
1591 	    yds=2;
1592 	} else if(src_h/4<drw_h) {
1593 	    yds=4;
1594 	} else { yds=8; }
1595     } else yds = 1;
1596 
1597 
1598 #ifdef DEBUG_MGA2164
1599     char sbuf[255];
1600 
1601     sprintf(sbuf,"---- xds = %d\n",
1602 	    xds);
1603     xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1604 #endif
1605 
1606 
1607 #ifdef DEBUG_MGA2164
1608     sprintf(sbuf,"out src: src_x=%d src_y=%d src_w=%d src_h=%d\n",
1609 	    src_x,src_y,src_w,src_h);
1610     xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1611     sprintf(sbuf,"out drw: drw_x=%d drw_y=%d drw_w=%d drw_h=%d\n",
1612 	    drw_x,drw_y,drw_w,drw_h);
1613     xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1614 #endif
1615 
1616     CHECK_DMA_QUIESCENT(pMga, pScrn);
1617 
1618     /* scaling ILOAD */
1619 
1620     vbuf=buf+width*height;
1621     ubuf=vbuf+width*height/4;
1622     pu = (CARD32 *)(ubuf+(src_y/2)*(width/2));
1623     pv = (CARD32 *)(vbuf+(src_y/2)*(width/2));
1624 #ifdef MGA2164_BLIT_DUP
1625     pl = -1;
1626 #endif /* MGA2164_BLIT_DUP */
1627     for(dl=0;dl<box_h;dl++) {
1628 	int beta;
1629 	l=(dl+(pbox->y1-drw_y))*src_h/drw_h;
1630 	/* FIXME: check the math */
1631 	beta = ((dl+(pbox->y1-drw_y))*src_h*0xff/drw_h) - ((dl+(pbox->y1-drw_y))*src_h/drw_h*0xff);
1632 
1633 #ifdef MGA2164_BLIT_DUP
1634 	if(l!=pl)
1635 #else
1636 	    if(1)
1637 #endif
1638 		{
1639 
1640 		    /*
1641 		      #ifdef DEBUG_MGA2164
1642 		      sprintf(sbuf,"new line: scr_dst %d   img_src %d   prev %d\n",
1643 		      dl,l,pl);
1644 		      xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1645 		      #endif
1646 		    */
1647 
1648 		    OUTREG(MGAREG_DWGCTL, MGADWG_ILOAD_HIQH | MGADWG_BUYUV | MGADWG_SHIFTZERO
1649 			   | MGADWG_SGNZERO | 0xc0000);
1650 
1651 		    OUTREG(MGAREG_AR0, pbox->x1 + drw_w -1);    /* SRC LINE END   why -1 ? */
1652 		    OUTREG(MGAREG_AR2, ( ( (src_w-1)<<16) / (drw_w-1)) + 1 ); /* ((SRC_X_DIM -1)<<16) / (DST_X_DIM-1) +1 */
1653 		    OUTREG(MGAREG_AR3, pbox->x1 );                            /* SRC LINE START*/
1654 		    OUTREG(MGAREG_AR5, scr_pitch);                            /* DST_Y_INCR = PITCH? */
1655 		    OUTREG(MGAREG_AR6, ((src_w-drw_w)<<16) / (drw_w-1) );     /* */
1656 		    OUTREG(MGAREG_FXBNDRY, drw_x|((drw_x+drw_w-1)<<16) );     /* why -1 ? */
1657 		    OUTREG(MGAREG_CXBNDRY, pbox->x1 | ((pbox->x2-1)<<16 ) );
1658 		    OUTREG(MGAREG_YDST , pbox->y1+dl );                       /* Y_START_POS */
1659 		    OUTREG(MGAREG_LEN + MGAREG_EXEC , 1);                     /* # of LINES */
1660 
1661 		    /* xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Data finished\n"); */
1662 
1663 		    fb_ptr=(CARD32 *)pMga->ILOADBase;
1664 
1665 		    switch(id) {
1666 		    case FOURCC_YV12:
1667 		    case FOURCC_I420:
1668 			tbuf=buf+(l+src_y)*width;
1669 			{
1670 			    CARD32 *tpu=pu+src_x/8+l/2*width/8;
1671 			    CARD32 *tpv=pv+src_x/8+l/2*width/8;
1672 			    CARD32 *tsp=(CARD32 *)(tbuf+src_x), *tsp2;
1673 
1674 			    if((l+src_y)<(src_h-1))
1675 				tsp2=(CARD32 *)(tbuf+src_x+width);
1676 			    else
1677 				tsp2=(CARD32 *)(tbuf+src_x);
1678 
1679 			    /* it is not clear if waiting is actually good for performance */
1680 			    /*	 WAITFIFO(pMga->FifoSize);*/
1681 			    /* should try to get MGACopyMunged data to work here */
1682 			    /*		CopyMungedScanline_AXP(fb_ptr,src_w,tsp,tpu,tpv); */
1683 
1684 			    /* Filter does not work yet */
1685 			    CopyMungedScanlineFilter_AXP(fb_ptr,src_w,tsp,tpu,tpv,tsp2,tpu,tpv, beta, xds);
1686 			    /*	if(l&1) {
1687 				pu+=width/8;
1688 				pv+=width/8;
1689 				} */
1690 			}
1691 			break;
1692 		    case FOURCC_UYVY:
1693 		    case FOURCC_YUY2:
1694 			tbuf=buf+(l+src_y)*width*2;
1695 
1696 #ifndef MGA2164_SWFILTER
1697 			WAITFIFO(pMga->FifoSize/2);
1698 			memcpy(fb_ptr, tbuf+src_x*2, src_w*2);
1699 			fb_ptr+=src_w*2;   /* pointer in the pseudo dma window */
1700 #else
1701 			{
1702 			    CARD32 *tsp=(CARD32 *)(tbuf+src_x*2), *tsp2;
1703 
1704 			    if((l+src_y)<(src_h-1))
1705 				tsp2=(CARD32 *)(tbuf+src_x*2+width*2);
1706 			    else
1707 				tsp2=(CARD32 *)(tbuf+src_x*2);
1708 			    /*	  {
1709 				  char sbuf [256];
1710 				  sprintf(sbuf,"dst line: %d   src_line: %d    beta: %x\n",
1711 				  dl, l, beta );
1712 				  xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1713 				  }  */
1714 
1715 			    WAITFIFO(pMga->FifoSize/4);
1716 			    for(k=xds*src_w/8;k;k--) {
1717 				int oneminbeta = 0xff-beta;
1718 				int y[8], u[4], v[4], ya[4], ua[2], va[2], p;
1719 
1720 				switch(yds) {
1721 				case 1:
1722 				    /* upscale y filter */
1723 				    for(p=0;p<4;p++) {
1724 					y[2*p]=(((*(tsp+p)&0x000000ff))*oneminbeta+((*(tsp2+p)&0x000000ff))*beta)>>8;
1725 					y[2*p+1]=(((*(tsp+p)&0x00ff0000)>>16)*oneminbeta+((*(tsp2+p)&0x00ff0000)>>16)*beta)>>8;
1726 					u[p]=(((*(tsp+p)&0x0000ff00)>>8)*oneminbeta+((*(tsp2+p)&0x0000ff00)>>8)*beta)>>8;
1727 					v[p]=(((*(tsp+p)&0xff000000)>>24)*oneminbeta+((*(tsp2+p)&0xff000000)>>24)*beta)>>8;
1728 				    }
1729 				    break;
1730 				    /* downscale y filter */
1731 				case 2:
1732 				case 3:
1733 				case 4:
1734 				default:
1735 				    for(p=0;p<4;p++) {
1736 					y[2*p]=(((*(tsp+p)&0x000000ff)));
1737 					y[2*p+1]=(((*(tsp+p)&0x00ff0000)>>16));
1738 					u[p]=(((*(tsp+p)&0x0000ff00)>>8));
1739 					v[p]=(((*(tsp+p)&0xff000000)>>24));
1740 				    }
1741 				    break;
1742 				}
1743 
1744 				switch (xds) {
1745 				case 1: /* simple copy */
1746 				    *(fb_ptr++)=y[0]|y[1]<<16|u[0]<<8|v[0]<<24;
1747 				    *(fb_ptr++)=y[2]|y[3]<<16|u[1]<<8|v[1]<<24;
1748 				    *(fb_ptr++)=y[4]|y[5]<<16|u[2]<<8|v[2]<<24;
1749 				    *(fb_ptr++)=y[6]|y[7]<<16|u[3]<<8|v[3]<<24;
1750 				    break;
1751 				case 2: /* dowscale by 2 */
1752 				    ya[0]=(y[0]+y[1])>>1;
1753 				    ya[1]=(y[2]+y[3])>>1;
1754 				    ya[2]=(y[4]+y[5])>>1;
1755 				    ya[3]=(y[6]+y[7])>>1;
1756 				    ua[0]=(u[0]+u[1])>>1;
1757 				    ua[1]=(u[2]+u[3])>>1;
1758 				    va[0]=(v[0]+v[1])>>1;
1759 				    va[1]=(v[2]+v[3])>>1;
1760 				    *(fb_ptr++)=ya[0]|ya[1]<<16|ua[0]<<8|va[0]<<24;
1761 				    *(fb_ptr++)=ya[2]|ya[3]<<16|ua[1]<<8|va[1]<<24;
1762 				    break;
1763 				case 4: /* downscale by 4 */
1764 				    ya[0]=(y[0]+y[1]+y[2]+y[3])>>2;
1765 				    ya[1]=(y[4]+y[5]+y[6]+y[7])>>2;
1766 				    ua[0]=(u[0]+u[1]+u[2]+u[3])>>2;
1767 				    va[0]=(v[0]+v[1]+v[2]+v[3])>>2;
1768 				    *(fb_ptr++)=ya[0]|ya[1]<<16|ua[0]<<8|va[0]<<24;
1769 				    break;
1770 				case 8:
1771 				default:
1772 				    break;
1773 				}
1774 
1775 				/* fb_ptr+=4; */
1776 				tsp+=4; tsp2+=4;
1777 			    }
1778 			}
1779 #endif /* MGA2164_SWFILTER */
1780 			break;
1781 		    default:
1782 			break;
1783 		    }
1784 #ifdef MGA2164_BLIT_DUP
1785 		    pl=l;
1786 #endif /* MGA2164_BLIT_DUP */
1787 		} else {
1788 		    /* dup lines */
1789 
1790 #ifdef DEBUG_MGA2164
1791 		    sprintf(sbuf,"dup line: scr_src %d   scr_dst %d\n",
1792 			    dl-1,dl);
1793 		    xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1794 #endif
1795 
1796 		    OUTREG(MGAREG_DWGCTL, 0x040C6008);
1797 		    OUTREG(MGAREG_FXBNDRY, pbox->x1|((pbox->x2-1)<<16) );      /* why -1 ? */
1798 		    OUTREG(MGAREG_AR3, (pbox->y1+dl-1)*scr_pitch+pbox->x1 );   /* SRC LINE START*/
1799 		    OUTREG(MGAREG_AR0, (pbox->y1+dl-1)*scr_pitch+pbox->x2 -1); /* SRC LINE END   why -1 ? */
1800 		    OUTREG(MGAREG_AR5, scr_pitch);                             /* DST_Y_INCR = PITCH? */
1801 		    OUTREG(MGAREG_YDST , pbox->y1+dl);                         /* Y_START_POS */
1802 		    OUTREG(MGAREG_LEN + MGAREG_EXEC , 1);                      /* # of LINES */
1803 		}
1804     }
1805     OUTREG(MGAREG_CXBNDRY, 0xFFFF0000);
1806 }
1807 
MGACopyILOAD(ScrnInfoPtr pScrn,int id,unsigned char * buf,BoxPtr pbox,int width,int height,int pitch,short src_x,short src_y,short src_w,short src_h,short drw_x,short drw_y,short drw_w,short drw_h)1808 static void MGACopyILOAD(
1809 			 ScrnInfoPtr pScrn,
1810 			 int id, unsigned char *buf,
1811 			 BoxPtr pbox,
1812 			 int width, int height, int pitch,
1813 			 short src_x, short src_y,
1814 			 short src_w, short src_h,
1815 			 short drw_x, short drw_y,
1816 			 short drw_w, short drw_h
1817 			 )
1818 {
1819     MGAPtr pMga = MGAPTR(pScrn);
1820     CARD32 *fb_ptr;
1821     CARD8  *ubuf, *vbuf;
1822     CARD32 *pu, *pv;
1823 #ifdef CUSTOM_MEMCOPY
1824     int k;
1825 #endif /* CUSTOM_MEMCOPY */
1826     int l;
1827     short clip_x1, clip_x2, tmp_w;
1828 
1829 #ifdef DEBUG_MGA2164
1830     char sbuf[255];
1831 
1832     sprintf(sbuf,"---- PBOX: x1=%d y1=%d w=%d h=%d (x2=%d y2=%d)\n",
1833 	    pbox->x1,pbox->y1,pbox->x2-pbox->x1,pbox->y2-pbox->y1,
1834 	    pbox->x2,pbox->y2);
1835     xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1836 
1837     sprintf(sbuf,"in src: src_x=%d src_y=%d src_w=%d src_h=%d\n",
1838 	    src_x,src_y,src_w,src_h);
1839     xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1840     sprintf(sbuf,"in drw: drw_x=%d drw_y=%d drw_w=%d drw_h=%d\n",
1841 	    drw_x,drw_y,drw_w,drw_h);
1842     xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1843 #endif
1844 
1845     /* non-scaling yuv->rgb */
1846 
1847     /* hack to force width and src image to be 8 pixel aligned */
1848     src_x&=~0x7;
1849     src_w&=~0x7;
1850     drw_w&=~0x7;
1851     tmp_w=drw_w;
1852     clip_x1=drw_x;
1853     clip_x2=drw_x+drw_w;
1854 
1855     /* hack for clipping in non scaling version */
1856     /* this works only if no scaling */
1857     if(pbox->x1 > drw_x) {              /* left side X clipping*/
1858 	src_x+=((pbox->x1-drw_x)&~0x7);
1859 	src_w-=((pbox->x1-drw_x)&~0x7);
1860 	clip_x1=pbox->x1;
1861 	drw_x+=src_x;
1862 	drw_w=src_w;
1863     }
1864 
1865     if( (pbox->x2) < (drw_x+drw_w) ) {     /* right side X clipping */
1866 	tmp_w=( (pbox->x2) - drw_x );
1867 	drw_w= tmp_w & (~0x7);
1868 	if(drw_w!=tmp_w) drw_w+=8;
1869 	clip_x2=drw_x+tmp_w-1; /* not sure why needs -1 */
1870 	src_w=drw_w;
1871     }
1872 
1873     if(pbox->y1 > drw_y) {             /* top side Y clipping */
1874 	src_y+=(pbox->y1-drw_y);
1875 	src_h-=(pbox->y1-drw_y);
1876 	drw_y+=src_y;
1877 	drw_h=src_h;
1878     }
1879     if((pbox->y2)<(drw_y+drw_h)) {     /* bottom side Y clipping */
1880 	drw_h=(pbox->y2)-drw_y;
1881 	src_h=drw_h;
1882     }
1883 
1884     if(drw_x<0) drw_x=0;
1885 
1886 #ifdef DEBUG_MGA2164
1887     sprintf(sbuf,"out src: src_x=%d src_y=%d src_w=%d src_h=%d\n",
1888 	    src_x,src_y,src_w,src_h);
1889     xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1890     sprintf(sbuf,"out drw: drw_x=%d drw_y=%d drw_w=%d drw_h=%d\n",
1891 	    drw_x,drw_y,drw_w,drw_h);
1892     xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf);
1893 #endif
1894 
1895     /* ready to draw */
1896     if(drw_w==0||drw_h==0) return;
1897 
1898     if(drw_w<0||drw_h<0) {
1899 	/* actually until scaling is working this might happen
1900 	   during normal operation */
1901 	/*  sprintf(sbuf,"drw_w or drw_h are negative (this should never
1902 	    happen)\n");
1903 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); */
1904 	return;
1905     }
1906 
1907     CHECK_DMA_QUIESCENT(pMga, pScrn);
1908 
1909     /* non scaling ILOAD */
1910     WAITFIFO(6);
1911     OUTREG(MGAREG_AR5, 0);
1912     OUTREG(MGAREG_DWGCTL, MGADWG_ILOAD | MGADWG_BUYUV | MGADWG_SHIFTZERO
1913 	   | MGADWG_SGNZERO | 0xc0000);
1914     OUTREG(MGAREG_AR0, (drw_w)-1 );
1915     OUTREG(MGAREG_AR3, 0);
1916     OUTREG(MGAREG_CXBNDRY, clip_x1|(clip_x2<<16));
1917     OUTREG(MGAREG_FXBNDRY, drw_x|((drw_x+drw_w-1)<<16));
1918     OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC , (drw_y<<16)|drw_h);
1919 
1920     fb_ptr=(CARD32 *)pMga->ILOADBase;
1921     vbuf=buf+width*height;
1922     ubuf=vbuf+width*height/4;
1923 
1924     switch(id) {
1925     case FOURCC_YV12:
1926     case FOURCC_I420:
1927 	pu = (CARD32 *)(ubuf+(src_y/2)*(width/2));
1928 	pv = (CARD32 *)(vbuf+(src_y/2)*(width/2));
1929 	buf+=src_y*width;
1930 
1931 	for(l=0;l<drw_h;l++) {
1932 	    CARD32 *tpu=pu+src_x/8;
1933 	    CARD32 *tpv=pv+src_x/8;
1934 	    CARD32 *tsp=(CARD32 *)(buf+src_x);
1935 
1936 	    /* it is not clear if waiting is actually good for performance */
1937 	    /*	WAITFIFO(pMga->FifoSize);*/
1938 	    /* should try to get MGACopyMunged data to work here */
1939 	    CopyMungedScanline_AXP(fb_ptr,src_w,tsp,tpu,tpv);
1940 	    buf+=width;
1941 	    if(l&1) {
1942 		pu+=width/8;
1943 		pv+=width/8;
1944 	    }
1945 	}
1946 	break;
1947     case FOURCC_UYVY:
1948     case FOURCC_YUY2:
1949 	buf+=src_y*width*2;
1950 	for(l=0;l<drw_h;l++) {
1951 
1952 #ifndef CUSTOM_MEMCOPY
1953 	    WAITFIFO(pMga->FifoSize/2); /* not sure what's the value for best performance */
1954 	    memcpy(fb_ptr, buf+src_x*2, src_w*2);
1955 	    fb_ptr+=src_w*2;
1956 #else
1957 	    CARD32 *tsp=(CARD32 *)(buf+src_x*2);
1958 	    WAITFIFO(pMga->FifoSize/4);
1959 	    for(k=src_w/8;k;k--) {
1960 		*(fb_ptr)=*(tsp);
1961 		*(fb_ptr+1)=*(tsp+1);
1962 		*(fb_ptr+2)=*(tsp+2);
1963 		*(fb_ptr+3)=*(tsp+3);
1964 		fb_ptr+=4; tsp+=4;
1965 	    }
1966 #endif /* CUSTOM_MEMCOPY */
1967 	    buf+=width*2;
1968 	}
1969 	break;
1970     default:
1971 	break;
1972     }
1973     OUTREG(MGAREG_CXBNDRY, 0xFFFF0000);    /* put clipping back to normal */
1974 }
1975 
1976 static int
MGAPutImageILOAD(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)1977 MGAPutImageILOAD(
1978 		 ScrnInfoPtr pScrn,
1979 		 short src_x, short src_y,
1980 		 short drw_x, short drw_y,
1981 		 short src_w, short src_h,
1982 		 short drw_w, short drw_h,
1983 		 int id, unsigned char* buf,
1984 		 short width, short height,
1985 		 Bool Sync,
1986 		 RegionPtr clipBoxes, pointer data,
1987 		 DrawablePtr pDraw
1988 		 ){
1989     MGAPtr pMga = MGAPTR(pScrn);
1990     MGAPortPrivPtr pPriv = pMga->portPrivate;
1991     INT32 x1, x2, y1, y2;
1992     int dstPitch = 0;
1993     BoxRec dstBox;
1994     int nbox;
1995     BoxPtr pbox;
1996 
1997     /* Clip */
1998     x1 = src_x; x2 = src_x + src_w;
1999     y1 = src_y; y2 = src_y + src_h;
2000 
2001     dstBox.x1 = drw_x; dstBox.x2 = drw_x + drw_w;
2002     dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h;
2003 
2004     if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2,
2005 			      clipBoxes, width, height))
2006 	return Success;
2007 
2008 #ifdef USE_XAA
2009     if( pMga->AccelInfoRec->NeedToSync && ((long)data != pPriv->lastPort) ) {
2010 	MGAStormSync(pScrn);
2011     }
2012 #endif
2013 
2014     pPriv->lastPort = (long)data;
2015     nbox=REGION_NUM_RECTS(clipBoxes);
2016     pbox=REGION_RECTS(clipBoxes);
2017 
2018     while(nbox--) {
2019 
2020 	if ( (drw_w==src_w) && (drw_h==src_h) && (drw_x >= 0 ) ) {
2021 	    /* special case 1: non scaling optimization */
2022 	    MGACopyILOAD(pScrn,id,buf,pbox,
2023 			 width, height, dstPitch, src_x, src_y, src_w, src_h,
2024 			 drw_x, drw_y, drw_w, drw_h);
2025 #if 0
2026 	    } else if ( (drw_w>src_w) && (drw_h>src_h) && (drw_x >= 0 ) ) {
2027 		/* special case 2: upscaling for full screen apps */
2028 		/* FIXME: to do */
2029 		MGACopyScaledILOAD(pScrn,id,buf,pbox,
2030 				   width, height, dstPitch, src_x, src_y, src_w, src_h,
2031 				   drw_x, drw_y, drw_w, drw_h);
2032 
2033 #endif
2034 	    } else /* generic fallback case */
2035 		MGACopyScaledILOAD(pScrn,id,buf,pbox,
2036 				   width, height, dstPitch, src_x, src_y, src_w, src_h,
2037 				   drw_x, drw_y, drw_w, drw_h);
2038 	/* FIXME: when the generic is perfect I will enable the optimizations */
2039 	pbox++;
2040     }
2041 
2042 #ifdef USE_XAA
2043     pMga->AccelInfoRec->NeedToSync = TRUE;
2044 #endif
2045     pPriv->videoStatus = FREE_TIMER;
2046     pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
2047     pMga->VideoTimerCallback = MGAVideoTimerCallback;
2048 
2049     return Success;
2050 }
2051