s3v_xv.c revision ba85709e
1/*
2Copyright (C) 2000 The XFree86 Project, Inc.  All Rights Reserved.
3
4Permission is hereby granted, free of charge, to any person obtaining a copy of
5this software and associated documentation files (the "Software"), to deal in
6the Software without restriction, including without limitation the rights to
7use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8of the Software, and to permit persons to whom the Software is furnished to do
9so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all
12copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
16NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of the XFree86 Project shall not
22be used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from the XFree86 Project.
24*/
25
26/*
27 * s3v_xv.c
28 * X Video Extension support
29 *
30 * S3 ViRGE driver
31 *
32 * 7/2000 Kevin Brosius
33 *
34 * Useful references:
35 * X Video extension support -> xc/programs/hw/xfree86/common/xf86xv.c
36 *
37 */
38
39#ifdef HAVE_CONFIG_H
40#include "config.h"
41#endif
42
43	/* Most xf86 commons are already in s3v.h */
44#include	"s3v.h"
45
46#if 0
47#define OFF_DELAY 	250  /* milliseconds */
48#define FREE_DELAY 	15000
49
50#define OFF_TIMER 	0x01
51#define FREE_TIMER	0x02
52#endif
53#define CLIENT_VIDEO_ON	0x04
54
55#define S3V_MAX_PORTS 1
56
57#if 0
58static void S3VInitOffscreenImages(ScreenPtr);
59#endif
60
61static XF86VideoAdaptorPtr S3VAllocAdaptor(ScrnInfoPtr pScrn);
62static XF86VideoAdaptorPtr S3VSetupImageVideoOverlay(ScreenPtr);
63static int  S3VSetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer);
64static int  S3VGetPortAttributeOverlay(ScrnInfoPtr, Atom ,INT32 *, pointer);
65
66
67static void S3VStopVideo(ScrnInfoPtr, pointer, Bool);
68static void S3VQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short,
69			unsigned int *, unsigned int *, pointer);
70static int  S3VPutImage(ScrnInfoPtr, short, short, short, short, short,
71			short, short, short, int, unsigned char*, short,
72			short, Bool, RegionPtr, pointer, DrawablePtr);
73static int  S3VQueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
74			unsigned short *,  int *, int *);
75
76
77static void S3VResetVideoOverlay(ScrnInfoPtr);
78
79#if 0
80#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
81
82static Atom xvBrightness, xvContrast, xvColorKey;
83
84#endif /* 0 */
85
86int S3VQueryXvCapable(ScrnInfoPtr pScrn)
87{
88  S3VPtr ps3v = S3VPTR(pScrn);
89
90  if(
91     ((pScrn->bitsPerPixel == 24) ||
92      (pScrn->bitsPerPixel == 16)
93      )
94     &&
95     ((ps3v->Chipset == S3_ViRGE_DXGX)  ||
96      S3_ViRGE_MX_SERIES(ps3v->Chipset) ||
97      S3_ViRGE_GX2_SERIES(ps3v->Chipset)
98      ))
99    return TRUE;
100  else
101    return FALSE;
102}
103
104
105void S3VInitVideo(ScreenPtr pScreen)
106{
107    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
108    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
109    XF86VideoAdaptorPtr newAdaptor = NULL;
110    S3VPtr ps3v = S3VPTR(pScrn);
111    int num_adaptors;
112
113    if(
114       ((pScrn->bitsPerPixel == 24) ||
115	(pScrn->bitsPerPixel == 16)
116	)
117       &&
118       ((ps3v->Chipset == S3_ViRGE_DXGX)  ||
119	S3_ViRGE_MX_SERIES(ps3v->Chipset) ||
120	S3_ViRGE_GX2_SERIES(ps3v->Chipset) /* || */
121	/* (ps3v->Chipset == S3_ViRGE) */
122	)
123       && !ps3v->NoAccel
124       && ps3v->XVideo
125       )
126    {
127	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using overlay video\n");
128	    newAdaptor = S3VSetupImageVideoOverlay(pScreen);
129    }
130
131
132    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
133
134    if(newAdaptor) {
135	if(!num_adaptors) {
136	    num_adaptors = 1;
137	    adaptors = &newAdaptor;
138	} else {
139	    newAdaptors =  /* need to free this someplace */
140		xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
141	    if(newAdaptors) {
142		memcpy(newAdaptors, adaptors, num_adaptors *
143					sizeof(XF86VideoAdaptorPtr));
144		newAdaptors[num_adaptors] = newAdaptor;
145		adaptors = newAdaptors;
146		num_adaptors++;
147	    }
148	}
149    }
150
151    if(num_adaptors)
152        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
153
154    if(newAdaptors)
155	xfree(newAdaptors);
156}
157
158/* client libraries expect an encoding */
159static XF86VideoEncodingRec DummyEncoding[2] =
160{
161 {   /* overlay limit */
162   0,
163   "XV_IMAGE",
164   1024, 1024,
165   {1, 1}
166 },
167 {  /* texture limit */
168   0,
169   "XV_IMAGE",
170   2046, 2046,
171   {1, 1}
172 }
173};
174
175#define NUM_FORMATS_OVERLAY 4
176#define NUM_FORMATS_TEXTURE 4
177
178static XF86VideoFormatRec Formats[NUM_FORMATS_TEXTURE] =
179{
180  /*{15, TrueColor},*/ {16, TrueColor}, {24, TrueColor} /* ,
181    {15, DirectColor}*/, {16, DirectColor}, {24, DirectColor}
182};
183
184#if 0
185#define NUM_ATTRIBUTES_OVERLAY 3
186
187static XF86AttributeRec Attributes[NUM_ATTRIBUTES_OVERLAY] =
188{
189   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
190   {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
191   {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
192};
193#endif
194
195#define NUM_IMAGES 3
196
197static XF86ImageRec Images[NUM_IMAGES] =
198{
199  XVIMAGE_YUY2,
200  /* As in mga, YV12 & I420 are converted to YUY2 on the fly by */
201  /* copy over conversion. */
202  XVIMAGE_YV12,
203  XVIMAGE_I420
204	/* XVIMAGE_UYVY */
205};
206
207
208
209static int
210S3VSetPortAttributeOverlay(
211  ScrnInfoPtr pScrn,
212  Atom attribute,
213  INT32 value,
214  pointer data
215){
216
217return BadMatch;
218
219}
220
221static int
222S3VGetPortAttributeOverlay(
223  ScrnInfoPtr pScrn,
224  Atom attribute,
225  INT32 *value,
226  pointer data
227){
228
229
230return BadMatch;
231
232}
233
234
235
236static void
237S3VQueryBestSize(
238  ScrnInfoPtr pScrn,
239  Bool motion,
240  short vid_w, short vid_h,
241  short drw_w, short drw_h,
242  unsigned int *p_w, unsigned int *p_h,
243  pointer data
244){
245  *p_w = drw_w;
246  *p_h = drw_h;
247
248#if 0
249  /* Only support scaling up, no down scaling. */
250  /* This doesn't seem to work (at least for XMovie) */
251  /* and the DESIGN doc says this is illegal anyway... */
252  if( drw_w < vid_w ) *p_w = vid_w;
253  if( drw_h < vid_h ) *p_h = vid_h;
254#endif
255}
256
257
258
259static void
260S3VResetVideoOverlay(ScrnInfoPtr pScrn)
261{
262  /* empty for ViRGE at the moment... */
263#if 0
264  S3VPtr ps3v = S3VPTR(pScrn);
265  S3VPortPrivPtr pPriv = ps3v->portPrivate;
266
267    MGAPtr pMga = MGAPTR(pScrn);
268    MGAPortPrivPtr pPriv = pMga->portPrivate;
269
270    CHECK_DMA_QUIESCENT(pMga, pScrn);
271
272    outMGAdac(0x51, 0x01); /* keying on */
273    outMGAdac(0x52, 0xff); /* full mask */
274    outMGAdac(0x53, 0xff);
275    outMGAdac(0x54, 0xff);
276
277    outMGAdac(0x55, (pPriv->colorKey & pScrn->mask.red) >>
278		    pScrn->offset.red);
279    outMGAdac(0x56, (pPriv->colorKey & pScrn->mask.green) >>
280		    pScrn->offset.green);
281    outMGAdac(0x57, (pPriv->colorKey & pScrn->mask.blue) >>
282		    pScrn->offset.blue);
283#endif
284
285#if 0
286    OUTREG(MGAREG_BESLUMACTL, ((pPriv->brightness & 0xff) << 16) |
287			       (pPriv->contrast & 0xff));
288#endif /*0*/
289}
290
291
292
293static XF86VideoAdaptorPtr
294S3VAllocAdaptor(ScrnInfoPtr pScrn)
295{
296    XF86VideoAdaptorPtr adapt;
297    S3VPtr ps3v = S3VPTR(pScrn);
298    S3VPortPrivPtr pPriv;
299    int i;
300
301    if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
302	return NULL;
303
304    if(!(pPriv = xcalloc(1, sizeof(S3VPortPrivRec)  +
305			(sizeof(DevUnion) * S3V_MAX_PORTS))))
306    {
307	xfree(adapt);
308	return NULL;
309    }
310
311    adapt->pPortPrivates = (DevUnion*)(&pPriv[1]);
312
313    for(i = 0; i < S3V_MAX_PORTS; i++)
314	adapt->pPortPrivates[i].val = i;
315
316#if 0
317    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
318    xvContrast   = MAKE_ATOM("XV_CONTRAST");
319    xvColorKey   = MAKE_ATOM("XV_COLORKEY");
320#endif
321
322    pPriv->colorKey =
323      (1 << pScrn->offset.red) |
324      (1 << pScrn->offset.green) |
325      (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
326
327#if 0
328    pPriv->brightness = 0;
329    pPriv->contrast = 128;
330#endif
331
332    pPriv->videoStatus = 0;
333    pPriv->lastPort = -1;
334
335    ps3v->adaptor = adapt;
336    ps3v->portPrivate = pPriv;
337
338    return adapt;
339}
340
341
342
343
344
345static XF86VideoAdaptorPtr
346S3VSetupImageVideoOverlay(ScreenPtr pScreen)
347{
348    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
349    S3VPtr ps3v = S3VPTR(pScrn);
350    XF86VideoAdaptorPtr adapt;
351
352    adapt = S3VAllocAdaptor(pScrn);
353
354    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
355    adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
356    adapt->name = "S3 ViRGE Backend Scaler";
357    adapt->nEncodings = 1;
358    adapt->pEncodings = &DummyEncoding[0];
359    adapt->nFormats = NUM_FORMATS_OVERLAY;
360    adapt->pFormats = Formats;
361    adapt->nPorts = 1;
362    adapt->pAttributes = NULL /*Attributes*/;
363    adapt->nImages = 3;
364    adapt->nAttributes = 0;
365    adapt->pImages = Images;
366    adapt->PutVideo = NULL;
367    adapt->PutStill = NULL;
368    adapt->GetVideo = NULL;
369    adapt->GetStill = NULL;
370    adapt->StopVideo = S3VStopVideo;
371    /* Empty Attrib functions - required anyway */
372    adapt->SetPortAttribute = S3VSetPortAttributeOverlay;
373    adapt->GetPortAttribute = S3VGetPortAttributeOverlay;
374    adapt->QueryBestSize = S3VQueryBestSize;
375    adapt->PutImage = S3VPutImage;
376    adapt->QueryImageAttributes = S3VQueryImageAttributes;
377
378    /* gotta uninit this someplace */
379    REGION_NULL(pScreen, &(ps3v->portPrivate->clip));
380
381    S3VResetVideoOverlay(pScrn);
382
383    return adapt;
384}
385
386
387static void
388S3VStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
389{
390  S3VPtr ps3v = S3VPTR(pScrn);
391  S3VPortPrivPtr pPriv = ps3v->portPrivate;
392
393  REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
394
395  if(shutdown) {
396     if(pPriv->videoStatus & CLIENT_VIDEO_ON)
397       {
398	 if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
399	      S3_ViRGE_MX_SERIES(ps3v->Chipset)
400	      )
401	   {
402	     /*  Aaarg... It .. won't.. go .. away!  */
403	     /* So let's be creative, make the overlay really */
404	     /* small and near an edge. */
405	     /* Size of 0 leaves a window sized vertical stripe */
406	     /* Size of 1 leaves a single pixel.. */
407	     OUTREG(SSTREAM_WINDOW_SIZE_REG, 1);
408	     /* And hide it at 0,0 */
409	     OUTREG(SSTREAM_START_REG, 0 );
410	   }
411	 else
412	   {
413	     /* Primary over secondary */
414	     OUTREG(BLEND_CONTROL_REG, 0x01000000);
415	   }
416       }
417
418     if(pPriv->area) {
419	xf86FreeOffscreenArea(pPriv->area);
420	pPriv->area = NULL;
421     }
422     pPriv->videoStatus = 0;
423#if 0
424  } else {
425     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
426	pPriv->videoStatus |= OFF_TIMER;
427	pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
428     }
429#endif
430  }
431}
432
433
434
435static FBAreaPtr
436S3VAllocateMemory(
437   ScrnInfoPtr pScrn,
438   FBAreaPtr area,
439   int numlines
440){
441   ScreenPtr pScreen;
442   FBAreaPtr new_area;
443
444   if(area) {
445	if((area->box.y2 - area->box.y1) >= numlines)
446	   return area;
447
448        if(xf86ResizeOffscreenArea(area, pScrn->displayWidth, numlines))
449	   return area;
450
451	xf86FreeOffscreenArea(area);
452   }
453
454   pScreen = screenInfo.screens[pScrn->scrnIndex];
455
456   new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
457				numlines, 0, NULL, NULL, NULL);
458
459   if(!new_area) {
460	int max_w, max_h;
461
462	xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0,
463			FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME);
464
465	if((max_w < pScrn->displayWidth) || (max_h < numlines))
466	   return NULL;
467
468	xf86PurgeUnlockedOffscreenAreas(pScreen);
469	new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
470				numlines, 0, NULL, NULL, NULL);
471   }
472
473   return new_area;
474}
475
476
477
478static void
479S3VDisplayVideoOverlay(
480    ScrnInfoPtr pScrn,
481    int id,
482    int offset,
483    short width, short height,
484    int pitch,
485    /* x,y src co-ordinates */
486    int x1, int y1, int x2, int y2,
487    /* dst in BoxPtr format */
488    BoxPtr dstBox,
489    /* src width and height */
490    short src_w, short src_h,
491    /* dst width and height */
492    short drw_w, short drw_h
493){
494    int tmp;
495
496#if 0
497    CHECK_DMA_QUIESCENT(pMga, pScrn);
498#endif
499    S3VPtr ps3v = S3VPTR(pScrn);
500    S3VPortPrivPtr pPriv = ps3v->portPrivate;
501
502  vgaHWPtr hwp = VGAHWPTR(pScrn);
503  /*  S3VPtr ps3v = S3VPTR(pScrn);*/
504  int vgaCRIndex, vgaCRReg, vgaIOBase;
505  vgaIOBase = hwp->IOBase;
506  vgaCRIndex = vgaIOBase + 4;
507  vgaCRReg = vgaIOBase + 5;
508
509   /* If streams aren't enabled, do nothing */
510   if(!ps3v->NeedSTREAMS)
511     return;
512
513
514    /* Reference at http://www.webartz.com/fourcc/ */
515      /* Looks like ViRGE only supports YUY2 and Y211?, */
516      /* listed as YUV-16 (4.2.2) and YUV (2.1.1) in manual. */
517
518#if 0
519      /* Only supporting modes we listed for the time being, */
520      /* No, switching required... #if 0'd this out */
521
522    switch(id) {
523    case FOURCC_UYVY:
524      /*
525	FOURCC=0x59565955
526	bpp=16
527	YUV 4:2:2 (Y sample at every
528	pixel, U and V sampled at
529	every second pixel
530	horizontally on each line). A
531	macropixel contains 2 pixels
532	in 1 u_int32.
533      */
534
535      /* OUTREG(MGAREG_BESGLOBCTL, 0x000000c3 | (tmp << 16));*/
536	 break;
537    case FOURCC_YUY2:
538      /*
539	FOURCC=0x32595559
540	bpp=16
541	YUV 4:2:2 as for UYVY but
542	with different component
543	ordering within the u_int32
544	macropixel.
545
546	Supports YV12 & I420 by copy over conversion of formats to YUY2,
547	copied from mga driver.  Thanks Mark!
548       */
549    default:
550      /*OUTREG(MGAREG_BESGLOBCTL, 0x00000083 | (tmp << 16));*/
551      /* YUV-16 (4.2.2) Secondary stream */
552      /* temp ... add DDA Horiz Accum. */
553      /*OUTREG(SSTREAM_CONTROL_REG, 0x02000000); / YUV-16 */
554      /* works for xvtest and suzi */
555      /* OUTREG(SSTREAM_CONTROL_REG, 0x01000000);  * YCbCr-16 * no scaling */
556
557      /* calc horizontal scale factor */
558      tmp = drw_w / src_w;
559      if (drw_w == src_w) tmp = 0;
560      else if (tmp>=4) tmp =3;
561      else if (tmp>=2) tmp =2;
562      else tmp =1;
563
564      /* YCbCr-16 */
565      OUTREG(SSTREAM_CONTROL_REG,
566	     tmp << 28 | 0x01000000 |
567	     ((((src_w-1)<<1)-(drw_w-1)) & 0xfff)
568	     );
569      break;
570    }
571#endif
572
573      /* calc horizontal scale factor */
574      if (drw_w == src_w)
575	tmp = 0;
576      else
577	tmp =2;
578      /* YCbCr-16 */
579    OUTREG(SSTREAM_CONTROL_REG,
580	   tmp << 28 | 0x01000000 |
581	   ((((src_w-1)<<1)-(drw_w-1)) & 0xfff)
582	   );
583
584    OUTREG(SSTREAM_STRETCH_REG,
585	   ((src_w - 1) & 0x7ff) | (((src_w-drw_w-1) & 0x7ff) << 16)
586	   );
587
588    /* Color key on primary */
589    if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
590	 S3_ViRGE_MX_SERIES(ps3v->Chipset)
591	 )
592      {
593	/* 100% of secondary, no primary */
594	/* gx2/mx can both blend while keying, need to */
595	/* select secondary here, otherwise all you'll get */
596	/* from the primary is the color key.  (And setting */
597	/* 0 here gives you black... no primary or secondary. */
598	/* Discovered that the hard way!) */
599	OUTREG(BLEND_CONTROL_REG, 0x20 );
600      }
601    else
602      {
603	OUTREG(BLEND_CONTROL_REG, 0x05000000);
604      }
605
606    OUTREG(SSTREAM_FBADDR0_REG, offset & 0x3fffff );
607    OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff );
608
609    OUTREG(K1_VSCALE_REG, src_h-1 );
610    OUTREG(K2_VSCALE_REG, (src_h - drw_h) & 0x7ff );
611
612    if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
613	 S3_ViRGE_MX_SERIES(ps3v->Chipset) )
614      {
615	/* enable vert interp. & bandwidth saving - gx2 */
616	OUTREG(DDA_VERT_REG, (((~drw_h)-1) & 0xfff ) |
617	       /* bw & vert interp */
618	       0xc000
619	       /* no bw save 0x8000*/
620	       );
621      }
622    else
623      {
624	OUTREG(DDA_VERT_REG, (((~drw_h)-1)) & 0xfff );
625      }
626
627    OUTREG(SSTREAM_START_REG, ((dstBox->x1 +1) << 16) | (dstBox->y1 +1));
628    OUTREG(SSTREAM_WINDOW_SIZE_REG,
629	   ( ((drw_w-1) << 16) | (drw_h ) ) & 0x7ff07ff
630	   );
631
632    if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
633	 S3_ViRGE_MX_SERIES(ps3v->Chipset)
634	 )
635      {
636	OUTREG(COL_CHROMA_KEY_CONTROL_REG,
637	       /* color key ON - keying on primary */
638	       0x40000000  |
639	       /* # bits to compare */
640	       ((pScrn->weight.red-1) << 24) |
641
642	       ((pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red) <<
643	       (16 + 8-pScrn->weight.red) |
644
645	       ((pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green) <<
646	       (8 + 8-pScrn->weight.green) |
647
648	       ((pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue) <<
649	       (8-pScrn->weight.blue)
650	       );
651      }
652    else
653      {
654	OUTREG(COL_CHROMA_KEY_CONTROL_REG,
655	       /* color key ON */
656	       0x10000000 |
657	       /* # bits to compare */
658	       ((pScrn->weight.red-1) << 24) |
659
660	       ((pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red) <<
661	       (16 + 8-pScrn->weight.red) |
662
663	       ((pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green) <<
664	       (8 + 8-pScrn->weight.green) |
665
666	       ((pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue) <<
667	       (8-pScrn->weight.blue)
668	       );
669      }
670
671    if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
672	 S3_ViRGE_MX_SERIES(ps3v->Chipset) )
673      {
674	VGAOUT8(vgaCRIndex, 0x92);
675	VGAOUT8(vgaCRReg, (((pitch + 7) / 8) >> 8) | 0x80);
676	VGAOUT8(vgaCRIndex, 0x93);
677	VGAOUT8(vgaCRReg, (pitch + 7) / 8);
678      }
679
680}
681
682
683static int
684S3VPutImage(
685  ScrnInfoPtr pScrn,
686  short src_x, short src_y,
687  short drw_x, short drw_y,
688  short src_w, short src_h,
689  short drw_w, short drw_h,
690  int id, unsigned char* buf,
691  short width, short height,
692  Bool sync,
693  RegionPtr clipBoxes, pointer data,
694  DrawablePtr pDraw
695){
696   S3VPtr ps3v = S3VPTR(pScrn);
697   S3VPortPrivPtr pPriv = ps3v->portPrivate;
698   INT32 x1, x2, y1, y2;
699   unsigned char *dst_start;
700   int pitch, new_h, offset, offset2=0, offset3=0;
701   int srcPitch, srcPitch2=0, dstPitch;
702   int top, left, npixels, nlines;
703   BoxRec dstBox;
704   CARD32 tmp;
705
706   /* If streams aren't enabled, do nothing */
707   if(!ps3v->NeedSTREAMS)
708     return Success;
709
710   /* Clip */
711   x1 = src_x;
712   x2 = src_x + src_w;
713   y1 = src_y;
714   y2 = src_y + src_h;
715
716   dstBox.x1 = drw_x;
717   dstBox.x2 = drw_x + drw_w;
718   dstBox.y1 = drw_y;
719   dstBox.y2 = drw_y + drw_h;
720
721   if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2,
722			     clipBoxes, width, height))
723	return Success;
724
725   /*if(!pMga->TexturedVideo) {*/
726	dstBox.x1 -= pScrn->frameX0;
727	dstBox.x2 -= pScrn->frameX0;
728	dstBox.y1 -= pScrn->frameY0;
729	dstBox.y2 -= pScrn->frameY0;
730	/*}*/
731
732   pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
733
734   dstPitch = ((width << 1) + 15) & ~15;
735   new_h = ((dstPitch * height) + pitch - 1) / pitch;
736
737   switch(id) {
738   case FOURCC_YV12:
739   case FOURCC_I420:
740	srcPitch = (width + 3) & ~3;
741	offset2 = srcPitch * height;
742	srcPitch2 = ((width >> 1) + 3) & ~3;
743	offset3 = (srcPitch2 * (height >> 1)) + offset2;
744	break;
745   case FOURCC_UYVY:
746   case FOURCC_YUY2:
747   default:
748	srcPitch = (width << 1);
749	break;
750   }
751
752   if(!(pPriv->area = S3VAllocateMemory(pScrn, pPriv->area, new_h)))
753	return BadAlloc;
754
755    /* copy data */
756    top = y1 >> 16;
757    left = (x1 >> 16) & ~1;
758    npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
759    left <<= 1;
760
761    offset = pPriv->area->box.y1 * pitch;
762    dst_start = ps3v->FBStart + offset + left + (top * dstPitch);
763    /*dst_start = pMga->FbStart + offset + left + (top * dstPitch);*/
764
765
766    switch(id) {
767    case FOURCC_YV12:
768    case FOURCC_I420:
769	top &= ~1;
770	tmp = ((top >> 1) * srcPitch2) + (left >> 2);
771	offset2 += tmp;
772	offset3 += tmp;
773	if(id == FOURCC_I420) {
774	   tmp = offset2;
775	   offset2 = offset3;
776	   offset3 = tmp;
777	}
778	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
779	xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1),
780				buf + offset2, buf + offset3, dst_start,
781				srcPitch, srcPitch2, dstPitch, nlines, npixels);
782	break;
783    case FOURCC_UYVY:
784    case FOURCC_YUY2:
785    default:
786	buf += (top * srcPitch) + left;
787	nlines = ((y2 + 0xffff) >> 16) - top;
788	xf86XVCopyPacked(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
789        break;
790    }
791
792
793    /* update cliplist */
794	if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
795	    REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
796	    /* draw these */
797	    xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
798	}
799
800	offset += left + (top * dstPitch);
801	S3VDisplayVideoOverlay(pScrn, id, offset, width, height, dstPitch,
802	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
803
804	pPriv->videoStatus = CLIENT_VIDEO_ON;
805
806
807    return Success;
808}
809
810
811static int
812S3VQueryImageAttributes(
813    ScrnInfoPtr pScrn,
814    int id,
815    unsigned short *w, unsigned short *h,
816    int *pitches, int *offsets
817){
818
819    int size, tmp;
820
821	if(*w > 1024) *w = 1024;
822	if(*h > 1024) *h = 1024;
823
824    *w = (*w + 1) & ~1;
825    if(offsets) offsets[0] = 0;
826
827    switch(id) {
828    case FOURCC_YV12:
829    case FOURCC_I420:
830	*h = (*h + 1) & ~1;
831	size = (*w + 3) & ~3;
832	if(pitches) pitches[0] = size;
833	size *= *h;
834	if(offsets) offsets[1] = size;
835	tmp = ((*w >> 1) + 3) & ~3;
836	if(pitches) pitches[1] = pitches[2] = tmp;
837	tmp *= (*h >> 1);
838	size += tmp;
839	if(offsets) offsets[2] = size;
840	size += tmp;
841	break;
842    case FOURCC_UYVY:
843    case FOURCC_YUY2:
844    default:
845	size = *w << 1;
846	if(pitches) pitches[0] = size;
847	size *= *h;
848	break;
849    }
850
851    return size;
852}
853