1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/nsc_gx1_video.c,v 1.7tsi Exp $ */
2/*
3 * $Workfile: nsc_gx1_video.c $
4 * $Revision: 1.1.1.1 $
5 * $Author: mrg $
6 *
7 * File Contents: This file consists of main Xfree video supported routines.
8 *
9 * Project:       Geode Xfree Frame buffer device driver.
10 *
11 */
12
13/*
14 * NSC_LIC_ALTERNATIVE_PREAMBLE
15 *
16 * Revision 1.0
17 *
18 * National Semiconductor Alternative GPL-BSD License
19 *
20 * National Semiconductor Corporation licenses this software
21 * ("Software"):
22 *
23 * National Xfree frame buffer driver
24 *
25 * under one of the two following licenses, depending on how the
26 * Software is received by the Licensee.
27 *
28 * If this Software is received as part of the Linux Framebuffer or
29 * other GPL licensed software, then the GPL license designated
30 * NSC_LIC_GPL applies to this Software; in all other circumstances
31 * then the BSD-style license designated NSC_LIC_BSD shall apply.
32 *
33 * END_NSC_LIC_ALTERNATIVE_PREAMBLE */
34
35/* NSC_LIC_BSD
36 *
37 * National Semiconductor Corporation Open Source License for
38 *
39 * National Xfree frame buffer driver
40 *
41 * (BSD License with Export Notice)
42 *
43 * Copyright (c) 1999-2001
44 * National Semiconductor Corporation.
45 * All rights reserved.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 *
51 *   * Redistributions of source code must retain the above copyright
52 *     notice, this list of conditions and the following disclaimer.
53 *
54 *   * Redistributions in binary form must reproduce the above
55 *     copyright notice, this list of conditions and the following
56 *     disclaimer in the documentation and/or other materials provided
57 *     with the distribution.
58 *
59 *   * Neither the name of the National Semiconductor Corporation nor
60 *     the names of its contributors may be used to endorse or promote
61 *     products derived from this software without specific prior
62 *     written permission.
63 *
64 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
65 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
66 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
67 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
68 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
69 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
70 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
71 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
72 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
73 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
74 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
75 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
76 * OF SUCH DAMAGE.
77 *
78 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
79 * YOUR JURISDICTION. It is licensee's responsibility to comply with
80 * any export regulations applicable in licensee's jurisdiction. Under
81 * CURRENT (2001) U.S. export regulations this software
82 * is eligible for export from the U.S. and can be downloaded by or
83 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
84 * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
85 * Syria, Sudan, Afghanistan and any other country to which the U.S.
86 * has embargoed goods and services.
87 *
88 * END_NSC_LIC_BSD */
89
90/* NSC_LIC_GPL
91 *
92 * National Semiconductor Corporation Gnu General Public License for
93 *
94 * National Xfree frame buffer driver
95 *
96 * (GPL License with Export Notice)
97 *
98 * Copyright (c) 1999-2001
99 * National Semiconductor Corporation.
100 * All rights reserved.
101 *
102 * Redistribution and use in source and binary forms, with or without
103 * modification, are permitted under the terms of the GNU General
104 * Public License as published by the Free Software Foundation; either
105 * version 2 of the License, or (at your option) any later version
106 *
107 * In addition to the terms of the GNU General Public License, neither
108 * the name of the National Semiconductor Corporation nor the names of
109 * its contributors may be used to endorse or promote products derived
110 * from this software without specific prior written permission.
111 *
112 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
113 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
114 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
115 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
116 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
117 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
118 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
119 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
120 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
121 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
122 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
123 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
124 * OF SUCH DAMAGE. See the GNU General Public License for more details.
125 *
126 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
127 * YOUR JURISDICTION. It is licensee's responsibility to comply with
128 * any export regulations applicable in licensee's jurisdiction. Under
129 * CURRENT (2001) U.S. export regulations this software
130 * is eligible for export from the U.S. and can be downloaded by or
131 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
132 * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
133 * Syria, Sudan, Afghanistan and any other country to which the U.S.
134 * has embargoed goods and services.
135 *
136 * You should have received a copy of the GNU General Public License
137 * along with this file; if not, write to the Free Software Foundation,
138 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
139 *
140 * END_NSC_LIC_GPL */
141
142/*
143 * Fixes & Extensions to support Y800 greyscale modes
144 * Alan Hourihane <alanh@fairlite.demon.co.uk>
145 */
146
147#ifdef HAVE_CONFIG_H
148#include "config.h"
149#endif
150
151#include "xf86.h"
152#include "xf86_OSproc.h"
153#include "xf86Resources.h"
154#include "compiler.h"
155#include "xf86PciInfo.h"
156#include "xf86Pci.h"
157#include "xf86fbman.h"
158#include "regionstr.h"
159
160#include "nsc.h"
161#include <X11/extensions/Xv.h>
162#include "xaa.h"
163#include "xaalocal.h"
164#include "dixstruct.h"
165#include "fourcc.h"
166#include "nsc_fourcc.h"
167
168#define OFF_DELAY 	200		/* milliseconds */
169#define FREE_DELAY 	60000
170
171#define OFF_TIMER 	0x01
172#define FREE_TIMER	0x02
173#define CLIENT_VIDEO_ON	0x04
174
175#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
176#define XV_PROFILE 0
177#define REINIT  1
178
179void GX1InitVideo(ScreenPtr pScreen);
180void GX1ResetVideo(ScrnInfoPtr pScrn);
181
182#define DBUF 0
183
184static XF86VideoAdaptorPtr GX1SetupImageVideo(ScreenPtr);
185static void GX1InitOffscreenImages(ScreenPtr);
186static void GX1StopVideo(ScrnInfoPtr, pointer, Bool);
187static int GX1SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
188static int GX1GetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
189static void GX1QueryBestSize(ScrnInfoPtr, Bool,
190			     short, short, short, short, unsigned int *,
191			     unsigned int *, pointer);
192static int GX1PutImage(ScrnInfoPtr,
193		       short, short, short, short, short, short,
194		       short, short, int, unsigned char *, short, short,
195		       Bool, RegionPtr, pointer, DrawablePtr);
196static int GX1QueryImageAttributes(ScrnInfoPtr,
197				   int, unsigned short *, unsigned short *,
198				   int *, int *);
199
200static void GX1BlockHandler(int, pointer, pointer, pointer);
201
202void GX1SetVideoPosition(int, int, int, int,
203			 short, short, short, short, int, int, ScrnInfoPtr);
204
205extern void GX1AccelSync(ScrnInfoPtr pScreenInfo);
206
207#if !defined(STB_X)
208extern int DeltaX, DeltaY;
209#else
210int DeltaX, DeltaY;
211#endif
212
213#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
214
215static Atom xvColorKey, xvColorKeyMode, xvFilter
216#if DBUF
217  , xvDoubleBuffer
218#endif
219  ;
220
221/*----------------------------------------------------------------------------
222 * GX1InitVideo
223 *
224 * Description	:This is the initialization routine.It creates a new video adapter
225 *				 and calls GX1SetupImageVideo to initialize the adaptor by filling
226 *				 XF86VideoAdaptorREc.Then it lists the existing adaptors and adds the
227 *				 new one to it. Finally the list of XF86VideoAdaptorPtr pointers are
228 *				 passed to the xf86XVScreenInit().
229 *
230 * Parameters.
231 * ScreenPtr
232 *		pScreen	:Screen handler pointer having screen information.
233 *
234 * Returns		:none
235 *
236 * Comments		:none
237 *
238*----------------------------------------------------------------------------
239*/
240void
241GX1InitVideo(ScreenPtr pScreen)
242{
243   GeodePtr pGeode;
244
245   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
246    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
247   XF86VideoAdaptorPtr newAdaptor = NULL;
248
249   int num_adaptors;
250
251   pGeode = GEODEPTR(pScreenInfo);
252
253
254   DEBUGMSG(0, (0, X_NONE, "InitVideo\n"));
255   newAdaptor = GX1SetupImageVideo(pScreen);
256   GX1InitOffscreenImages(pScreen);
257
258   num_adaptors = xf86XVListGenericAdaptors(pScreenInfo, &adaptors);
259
260   if (newAdaptor) {
261       if (!num_adaptors) {
262	   num_adaptors = 1;
263	   adaptors = &newAdaptor;
264       } else {
265	   newAdaptors =		/* need to free this someplace */
266	       xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *));
267	   if (newAdaptors) {
268	       memcpy(newAdaptors, adaptors, num_adaptors *
269		      sizeof(XF86VideoAdaptorPtr));
270	       newAdaptors[num_adaptors] = newAdaptor;
271	       adaptors = newAdaptors;
272	       num_adaptors++;
273	   }
274       }
275   }
276
277   if (num_adaptors)
278       xf86XVScreenInit(pScreen, adaptors, num_adaptors);
279
280   if (newAdaptors)
281       xfree(newAdaptors);
282}
283
284/* client libraries expect an encoding */
285static XF86VideoEncodingRec DummyEncoding[1] = {
286   {
287    0,
288    "XV_IMAGE",
289    1024, 1024,
290    {1, 1}
291    }
292};
293
294#define NUM_FORMATS 4
295
296static XF86VideoFormatRec Formats[NUM_FORMATS] = {
297   {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
298};
299
300#if DBUF
301#define NUM_ATTRIBUTES 4
302#else
303#define NUM_ATTRIBUTES 3
304#endif
305
306static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {
307#if DBUF
308   {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
309#endif
310   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
311   {XvSettable | XvGettable, 0, 1, "XV_FILTER"},
312   {XvSettable | XvGettable, 0, 1, "XV_COLORKEYMODE"}
313};
314
315#define NUM_IMAGES 7
316
317static XF86ImageRec Images[NUM_IMAGES] = {
318   XVIMAGE_UYVY,
319   XVIMAGE_YUY2,
320   XVIMAGE_Y2YU,
321   XVIMAGE_YVYU,
322   XVIMAGE_Y800,
323   XVIMAGE_I420,
324   XVIMAGE_YV12
325};
326
327typedef struct
328{
329   FBAreaPtr area;
330   FBLinearPtr linear;
331   RegionRec clip;
332   CARD32 colorKey;
333   CARD32 colorKeyMode;
334   CARD32 filter;
335   CARD32 videoStatus;
336   Time offTime;
337   Time freeTime;
338#if DBUF
339   Bool doubleBuffer;
340   int currentBuffer;
341#endif
342}
343GeodePortPrivRec, *GeodePortPrivPtr;
344
345#define GET_PORT_PRIVATE(pScrn) \
346	(GeodePortPrivPtr)((GEODEPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
347
348/*----------------------------------------------------------------------------
349 * GX1SetColorKey
350 *
351 * Description	:This function reads the color key for the pallete and
352 *				  sets the video color key register.
353 *
354 * Parameters.
355 * ScreenInfoPtr
356 *		pScrn	:Screen  pointer having screen information.
357 *		pPriv	:Video port private data
358 *
359 * Returns		:none
360 *
361 * Comments		:none
362 *
363*----------------------------------------------------------------------------
364*/
365static INT32
366GX1SetColorkey(ScrnInfoPtr pScrn, GeodePortPrivPtr pPriv)
367{
368   int red, green, blue;
369   unsigned long key;
370
371   DEBUGMSG(0, (0, X_NONE, "ColorKey\n"));
372   switch (pScrn->depth) {
373   case 8:
374      GFX(get_display_palette_entry(pPriv->colorKey & 0xFF, &key));
375      red = ((key >> 16) & 0xFF);
376      green = ((key >> 8) & 0xFF);
377      blue = (key & 0xFF);
378      break;
379   default:
380      red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red << (8 -
381									 pScrn->
382									 weight.
383									 red);
384      green =
385	    (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.
386	    green << (8 - pScrn->weight.green);
387      blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.
388	    blue << (8 - pScrn->weight.blue);
389      break;
390   }
391   GFX(set_video_color_key((blue | (green << 8) | (red << 16)), 0xFCFCFC,
392			   (pPriv->colorKeyMode == 0)));
393   REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
394   return 0;
395}
396
397/*----------------------------------------------------------------------------
398 * GX1ResetVideo
399 *
400 * Description	: This function resets the video
401 *
402 * Parameters.
403 * ScreenInfoPtr
404 *		pScrn	:Screen  pointer having screen information.
405 *
406 * Returns		:None
407 *
408 * Comments		:none
409 *
410*----------------------------------------------------------------------------
411*/
412
413void
414GX1ResetVideo(ScrnInfoPtr pScrn)
415{
416    GeodePtr pGeode = GEODEPTR(pScrn);
417
418    GeodePortPrivPtr pPriv = pGeode->adaptor->pPortPrivates[0].ptr;
419
420    DEBUGMSG(0, (0, X_NONE, "ResetVideo\n"));
421    if (!pGeode->NoAccel) GX1AccelSync(pScrn);
422    GFX(set_video_palette(NULL));
423    GX1SetColorkey(pScrn, pPriv);
424    GFX(set_video_filter(pPriv->filter, pPriv->filter));
425}
426
427/*----------------------------------------------------------------------------
428 * GX1SetupImageVideo
429 *
430 * Description	: This function allocates space for a Videoadaptor and initializes
431 *				  the XF86VideoAdaptorPtr record.
432 *
433 * Parameters.
434 * ScreenPtr
435 *		pScreen	:Screen handler pointer having screen information.
436 *
437 * Returns		:XF86VideoAdaptorPtr :- pointer to the initialized video adaptor record.
438 *
439 * Comments		:none
440 *
441*----------------------------------------------------------------------------
442*/
443
444static XF86VideoAdaptorPtr
445GX1SetupImageVideo(ScreenPtr pScreen)
446{
447   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
448   GeodePtr pGeode = GEODEPTR(pScrn);
449   XF86VideoAdaptorPtr adapt;
450   GeodePortPrivPtr pPriv;
451
452   DEBUGMSG(0, (0, X_NONE, "SetupImageVideo\n"));
453   if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
454			 sizeof(GeodePortPrivRec) + sizeof(DevUnion))))
455      return NULL;
456
457   adapt->type = XvWindowMask | XvInputMask | XvImageMask;
458   adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
459   adapt->name = "National Semiconductor Corporation";
460   adapt->nEncodings = 1;
461   adapt->pEncodings = DummyEncoding;
462   adapt->nFormats = NUM_FORMATS;
463   adapt->pFormats = Formats;
464   adapt->nPorts = 1;
465   adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
466   pPriv = (GeodePortPrivPtr) (&adapt->pPortPrivates[1]);
467   adapt->pPortPrivates[0].ptr = (pointer) (pPriv);
468   adapt->pAttributes = Attributes;
469   adapt->nImages = NUM_IMAGES;
470   adapt->nAttributes = NUM_ATTRIBUTES;
471   adapt->pImages = Images;
472   adapt->PutVideo = NULL;
473   adapt->PutStill = NULL;
474   adapt->GetVideo = NULL;
475   adapt->GetStill = NULL;
476   adapt->StopVideo = GX1StopVideo;
477   adapt->SetPortAttribute = GX1SetPortAttribute;
478   adapt->GetPortAttribute = GX1GetPortAttribute;
479   adapt->QueryBestSize = GX1QueryBestSize;
480   adapt->PutImage = GX1PutImage;
481   adapt->QueryImageAttributes = GX1QueryImageAttributes;
482
483   pPriv->colorKey = pGeode->videoKey;
484   pPriv->colorKeyMode = 0;
485   pPriv->filter = 0;
486   pPriv->videoStatus = 0;
487#if DBUF
488   pPriv->doubleBuffer = TRUE;
489   pPriv->currentBuffer = 0;		/* init to first buffer */
490#endif
491
492   /* gotta uninit this someplace */
493   REGION_NULL(pScreen, &pPriv->clip);
494
495   pGeode->adaptor = adapt;
496
497   pGeode->BlockHandler = pScreen->BlockHandler;
498   pScreen->BlockHandler = GX1BlockHandler;
499
500   xvColorKey = MAKE_ATOM("XV_COLORKEY");
501   xvColorKeyMode = MAKE_ATOM("XV_COLORKEYMODE");
502   xvFilter = MAKE_ATOM("XV_FILTER");
503#if DBUF
504   xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
505#endif
506
507   GX1ResetVideo(pScrn);
508
509   return adapt;
510}
511
512/*----------------------------------------------------------------------------
513 * GX1StopVideo
514 *
515 * Description	:This function is used to stop input and output video
516 *
517 * Parameters.
518 * pScreenInfo
519 *		pScrn		:Screen handler pointer having screen information.
520 *		data		:Pointer to the video port's private data
521 *		exit		:Flag indicating whether the offscreen areas used for video
522 *					 to be deallocated or not.
523 * Returns		:none
524 *
525 * Comments		:none
526 *
527*----------------------------------------------------------------------------
528*/
529static void
530GX1StopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit)
531{
532   GeodePortPrivPtr pPriv = (GeodePortPrivPtr) data;
533   GeodePtr pGeode = GEODEPTR(pScrn);
534
535   DEBUGMSG(0, (0, X_NONE, "StopVideo\n"));
536   REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
537
538   if (!pGeode->NoAccel) GX1AccelSync(pScrn);
539   if (exit) {
540      if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
541	 GFX(set_video_enable(0));
542      }
543      if (pPriv->area) {
544	 xf86FreeOffscreenArea(pPriv->area);
545	 pPriv->area = NULL;
546      }
547      pPriv->videoStatus = 0;
548      pGeode->OverlayON = FALSE;
549   } else {
550      if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
551	 pPriv->videoStatus |= OFF_TIMER;
552	 pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
553      }
554   }
555}
556
557/*----------------------------------------------------------------------------
558 * GX1SetPortAttribute
559 *
560 * Description	:This function is used to set the attributes of a port like colorkeymode,
561 *				  double buffer support and filter.
562 *
563 * Parameters.
564 * pScreenInfo
565 *		Ptr			:Screen handler pointer having screen information.
566 *		data		:Pointer to the video port's private data
567 *		attribute	:The port attribute to be set
568 *		value		:Value of the attribute to be set.
569 *
570 * Returns		:Sucess if the attribute is supported, else BadMatch
571 *
572 * Comments		:none
573 *
574*----------------------------------------------------------------------------
575*/
576static int
577GX1SetPortAttribute(ScrnInfoPtr pScrn,
578		    Atom attribute, INT32 value, pointer data)
579{
580   GeodePortPrivPtr pPriv = (GeodePortPrivPtr) data;
581   GeodePtr pGeode = GEODEPTR(pScrn);
582
583   if (!pGeode->NoAccel) GX1AccelSync(pScrn);
584   if (attribute == xvColorKey) {
585      pPriv->colorKey = value;
586      GX1SetColorkey(pScrn, pPriv);
587   }
588#if DBUF
589   else if (attribute == xvDoubleBuffer) {
590      if ((value < 0) || (value > 1))
591	 return BadValue;
592      pPriv->doubleBuffer = value;
593   }
594#endif
595   else if (attribute == xvColorKeyMode) {
596      pPriv->colorKeyMode = value;
597      GX1SetColorkey(pScrn, pPriv);
598   } else if (attribute == xvFilter) {
599      pPriv->filter = value;
600      GFX(set_video_filter(pPriv->filter, pPriv->filter));
601   } else
602      return BadMatch;
603
604   return Success;
605}
606
607/*----------------------------------------------------------------------------
608 * GX1GetPortAttribute
609 *
610 * Description	:This function is used to get the attributes of a port like hue,
611 *				 saturation,brightness or contrast.
612 *
613 * Parameters.
614 * pScreenInfo
615 *		Ptr			:Screen handler pointer having screen information.
616 *		data		:Pointer to the video port's private data
617 *		attribute	:The port attribute to be read
618 *		value		:Pointer to the value of the attribute to be read.
619 *
620 * Returns		:Sucess if the attribute is supported, else BadMatch
621 *
622 * Comments		:none
623 *
624*----------------------------------------------------------------------------
625*/
626static int
627GX1GetPortAttribute(ScrnInfoPtr pScrn,
628		    Atom attribute, INT32 * value, pointer data)
629{
630   GeodePortPrivPtr pPriv = (GeodePortPrivPtr) data;
631
632   if (attribute == xvColorKey) {
633      *value = pPriv->colorKey;
634   }
635#if DBUF
636   else if (attribute == xvDoubleBuffer) {
637      *value = (pPriv->doubleBuffer) ? 1 : 0;
638   }
639#endif
640   else if (attribute == xvColorKeyMode) {
641      *value = pPriv->colorKeyMode;
642   } else if (attribute == xvFilter) {
643      *value = pPriv->filter;
644   } else
645      return BadMatch;
646
647   return Success;
648}
649
650/*----------------------------------------------------------------------------
651 * GX1QueryBestSize
652 *
653 * Description	:This function provides a way to query what the destination dimensions
654 *				 would end up being if they were to request that an area vid_w by vid_h
655 *               from the video stream be scaled to rectangle of drw_w by drw_h on
656 *				 the screen.
657 *
658 * Parameters.
659 * ScreenInfoPtr
660 *		pScrn		:Screen handler pointer having screen information.
661 *		data		:Pointer to the video port's private data
662 *      vid_w,vid_h	:Width and height of the video data.
663 *		drw_w,drw_h :Width and height of the scaled rectangle.
664 *		p_w,p_h		:Width and height of the destination rectangle.
665 *
666 * Returns		:None
667 *
668 * Comments		:None
669 *
670*----------------------------------------------------------------------------
671*/
672static void
673GX1QueryBestSize(ScrnInfoPtr pScrn,
674		 Bool motion,
675		 short vid_w, short vid_h,
676		 short drw_w, short drw_h,
677		 unsigned int *p_w, unsigned int *p_h, pointer data)
678{
679   DEBUGMSG(0, (0, X_NONE, "QueryBestSize\n"));
680   *p_w = drw_w;
681   *p_h = drw_h;
682
683   if (*p_w > 16384)
684      *p_w = 16384;
685}
686static void
687GX1CopyGreyscale(unsigned char *src,
688		 unsigned char *dst, int srcPitch, int dstPitch, int h, int w)
689{
690   int i;
691   unsigned char *src2 = src;
692   unsigned char *dst2 = dst;
693   unsigned char *dst3;
694   unsigned char *src3;
695
696   dstPitch <<= 1;
697
698   while (h--) {
699      dst3 = dst2;
700      src3 = src2;
701      for (i = 0; i < w; i++) {
702	 *dst3++ = *src3++;		/* Copy Y data */
703	 *dst3++ = 0x80;		/* Fill UV with 0x80 - greyscale */
704      }
705      src3 = src2;
706      for (i = 0; i < w; i++) {
707	 *dst3++ = *src3++;		/* Copy Y data */
708	 *dst3++ = 0x80;		/* Fill UV with 0x80 - greyscale */
709      }
710      dst2 += dstPitch;
711      src2 += srcPitch;
712   }
713}
714
715/*----------------------------------------------------------------------------
716 * GX1CopyData
717 *
718 * Description	: Copies data from src to destination
719 *
720 * Parameters.
721 *		src			: pointer to the source data
722 *		dst			: pointer to destination data
723 *		srcPitch	: pitch of the srcdata
724 *		dstPitch	: pitch of the destination data
725 *		h & w		: height and width of source data
726 *
727 * Returns		:None
728 *
729 * Comments		:None
730 *
731*----------------------------------------------------------------------------
732*/
733
734static void
735GX1CopyData(unsigned char *src, unsigned char *dst,
736	    int srcPitch, int dstPitch, int h, int w)
737{
738   w <<= 1;
739   while (h--) {
740      memcpy(dst, src, w);
741      src += srcPitch;
742      dst += dstPitch;
743   }
744}
745
746static void
747GX1CopyMungedData(unsigned char *src1,
748		  unsigned char *src2,
749		  unsigned char *src3,
750		  unsigned char *dst1,
751		  int srcPitch, int srcPitch2, int dstPitch, int h, int w)
752{
753   CARD32 *dstCur = (CARD32 *) dst1;
754   CARD32 *dstNext = (CARD32 *) dst1;
755   int i, j, k, m, n;
756   CARD32 crcb;
757
758#if XV_PROFILE
759   long oldtime, newtime;
760#endif
761
762   DEBUGMSG(0, (0, X_NONE, "CopyMungedData\n"));
763   /* dstPitch is in byte count, but we write longs.
764    * so divide dstpitch by 4
765    */
766   dstPitch >>= 2;
767   /* Width is in byte but video data is 16bit
768    */
769   w >>= 1;
770   /* We render 2 scanlines at one shot, handle the odd count */
771   m = h & 1;
772   /* decrement the height since we write 2 scans */
773   h -= 1;
774   /* we traverse by 2 bytes in src Y */
775   srcPitch <<= 1;
776#if XV_PROFILE
777   UpdateCurrentTime();
778   oldtime = currentTime.milliseconds;
779#endif
780
781   for (j = 0; j < h; j += 2) {
782      /* calc the next dest scan start */
783      dstNext = dstCur + dstPitch;
784      for (i = 0; i < w; i++) {
785	 /* crcb is same for the x pixel for 2 scans */
786	 crcb = (src3[i] << 8) | (src2[i] << 24);
787
788	 n = i << 1;
789
790	 /* write the first scan pixel DWORD */
791	 dstCur[i] = src1[n] | (src1[n + 1] << 16) | crcb;
792
793	 /* calc the offset of next pixel */
794	 k = n + srcPitch;
795
796	 /* write the 2nd scan pixel DWORD */
797	 dstNext[i] = src1[k] | (src1[k + 1] << 16) | crcb;
798      }
799      /* increment the offsets */
800
801      /* Y */
802      src1 += srcPitch;
803      /* crcb */
804      src2 += srcPitch2;
805      src3 += srcPitch2;
806      /* processed dest */
807      dstCur += (dstPitch << 1);
808   }
809
810   /* if any scans remaining */
811   if (m) {
812      for (i = 0, k = 0; i < w; i++, k += 2) {
813	 dstCur[i] = src1[k] | (src1[k + 1] << 16) |
814	       (src3[i] << 8) | (src2[i] << 24);
815      }
816   }
817#if XV_PROFILE
818   UpdateCurrentTime();
819   newtime = currentTime.milliseconds;
820   DEBUGMSG(1, (0, X_NONE, "CMD %d\n", newtime - oldtime));
821#endif
822}
823
824static FBAreaPtr
825GX1AllocateMemory(ScrnInfoPtr pScrn, FBAreaPtr area, int numlines)
826{
827   ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
828   FBAreaPtr new_area;
829
830   if (area) {
831      if ((area->box.y2 - area->box.y1) >= numlines)
832	 return area;
833
834      if (xf86ResizeOffscreenArea(area, pScrn->displayWidth, numlines))
835	 return area;
836
837      xf86FreeOffscreenArea(area);
838   }
839
840   new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
841					numlines, 0, NULL, NULL, NULL);
842
843   if (!new_area) {
844      int max_w, max_h;
845
846      xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0,
847				    FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME);
848
849      if ((max_w < pScrn->displayWidth) || (max_h < numlines))
850	 return NULL;
851
852      xf86PurgeUnlockedOffscreenAreas(pScreen);
853      new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
854					   numlines, 0, NULL, NULL, NULL);
855   }
856   return new_area;
857}
858
859static BoxRec dstBox;
860static int srcPitch = 0, srcPitch2 = 0, dstPitch = 0;
861static INT32 Bx1, Bx2, By1, By2;
862static int top, left, npixels, nlines;
863static int offset, s1offset = 0, s2offset = 0, s3offset = 0;
864static unsigned char *dst_start;
865static int TVOverScanX;
866
867static Bool
868RegionsIntersect(BoxPtr pRcl1, BoxPtr pRcl2, BoxPtr pRclResult)
869{
870   pRclResult->x1 = max(pRcl1->x1, pRcl2->x1);
871   pRclResult->x2 = min(pRcl1->x2, pRcl2->x2);
872
873   if (pRclResult->x1 <= pRclResult->x2) {
874      pRclResult->y1 = max(pRcl1->y1, pRcl2->y1);
875      pRclResult->y2 = min(pRcl1->y2, pRcl2->y2);
876
877      if (pRclResult->y1 <= pRclResult->y2) {
878	 return (TRUE);
879      }
880   }
881
882   return (FALSE);
883}
884
885void
886GX1SetVideoPosition(int x, int y, int width, int height,
887		    short src_w, short src_h, short drw_w, short drw_h,
888		    int id, int offset, ScrnInfoPtr pScrn)
889{
890   GeodePtr pGeode = GEODEPTR(pScrn);
891   long xstart, ystart, xend, yend;
892   unsigned long lines = 0;
893   unsigned long y_extra = 0;
894   unsigned short crop = 0;
895   BoxRec ovly, display, result;
896
897#if defined(STB_X)
898   unsigned long startAddress = 0;
899#endif
900   xend = x + drw_w;
901   yend = y + drw_h;
902
903   /* Take care of panning when panel is present */
904
905#if defined(STB_X)
906   Gal_get_display_offset(&startAddress);
907   DeltaY = startAddress / pGeode->Pitch;
908   DeltaX = startAddress & (pGeode->Pitch - 1);
909   DeltaX /= (pScrn->bitsPerPixel >> 3);
910#endif
911
912   if (pGeode->Panel) {
913      ovly.x1 = x;
914      ovly.x2 = x + pGeode->video_dstw;
915      ovly.y1 = y;
916      ovly.y2 = y + pGeode->video_dsth;
917
918      display.x1 = DeltaX;
919      display.x2 = DeltaX + pGeode->FPBX;
920      display.y1 = DeltaY;
921      display.y2 = DeltaY + pGeode->FPBY;
922
923      x = xend = 0;
924
925      if (RegionsIntersect(&display, &ovly, &result)) {
926	 x = ovly.x1 - DeltaX;
927	 xend = ovly.x2 - DeltaX;
928	 y = ovly.y1 - DeltaY;
929	 yend = ovly.y2 - DeltaY;
930      }
931   }
932
933   /*  LEFT CLIPPING */
934
935   if (x < 0) {
936      if (TVOverScanX)
937	 xstart = TVOverScanX;
938      else
939	 xstart = 0;
940   } else {
941      if (TVOverScanX)
942	 xstart = TVOverScanX;
943      else
944	 xstart = (unsigned long)x;
945   }
946   drw_w -= (xstart - x);
947
948   /*  TOP CLIPPING */
949
950   if (y < 0) {
951      lines = (-y) * src_h / drw_h;
952      ystart = 0;
953      drw_h += y;
954      y_extra = lines * dstPitch;
955   } else {
956      ystart = y;
957      lines = 0;
958      y_extra = 0;
959   }
960
961   /* CLIP RIGHT AND BOTTOM FOR TV OVER SCAN */
962   if (pGeode->TV_Overscan_On) {
963      crop = (pGeode->TVOw + pGeode->TVOx);
964      if ((xstart + drw_w) > crop)
965	 xend = crop;
966      crop = (pGeode->TVOh + pGeode->TVOy);
967      if ((ystart + drw_h) > crop)
968	 yend = crop;
969   }
970   GFX(set_video_window(xstart, ystart, xend - xstart, yend - ystart));
971   GFX(set_video_offset(offset + y_extra));
972   GFX(set_video_left_crop(xstart - x));
973
974}
975
976/*----------------------------------------------------------------------------
977 * GX1DisplayVideo
978 *
979 * Description		: This function sets up the video registers for playing video
980 *					  It sets up the video format,width, height & position of the
981 *					  video window ,video offsets( y,u,v) and video pitches(y,u,v)
982 * Parameters.
983 *
984 * Returns		:None
985 *
986 * Comments		:None
987 *
988*----------------------------------------------------------------------------
989*/
990
991static void
992GX1DisplayVideo(ScrnInfoPtr pScrn,
993		int id,
994		int offset,
995		short width, short height,
996		int pitch,
997		int x1, int y1, int x2, int y2,
998		BoxPtr dstBox,
999		short src_w, short src_h, short drw_w, short drw_h)
1000{
1001   GeodePtr pGeode = GEODEPTR(pScrn);
1002
1003   /*    DisplayModePtr mode = pScrn->currentMode; */
1004   if (!pGeode->NoAccel) GX1AccelSync(pScrn);
1005
1006   GFX(set_video_enable(1));
1007
1008   switch (id) {
1009   case FOURCC_UYVY:			/* UYVY */
1010      GFX(set_video_format(VIDEO_FORMAT_UYVY));
1011      break;
1012   case FOURCC_Y800:			/* Y800 - greyscale - we munge it! */
1013   case FOURCC_YV12:
1014   case FOURCC_I420:
1015   case FOURCC_YUY2:			/* YUY2 */
1016      GFX(set_video_format(VIDEO_FORMAT_YUYV));
1017      break;
1018   case FOURCC_Y2YU:			/* Y2YU */
1019      GFX(set_video_format(VIDEO_FORMAT_Y2YU));
1020      break;
1021   case FOURCC_YVYU:			/* YVYU */
1022      GFX(set_video_format(VIDEO_FORMAT_YVYU));
1023      break;
1024   }
1025
1026   if (pGeode->TV_Overscan_On) {
1027      if (dstBox->x1 < 0)
1028	 TVOverScanX = pGeode->TVOx;
1029      else
1030	 TVOverScanX = 0;
1031      dstBox->x1 += pGeode->TVOx;
1032      dstBox->y1 += pGeode->TVOy;
1033   }
1034   if (pGeode->Panel) {
1035      pGeode->video_x = dstBox->x1;
1036      pGeode->video_y = dstBox->y1;
1037      pGeode->video_w = width;
1038      pGeode->video_h = height;
1039      pGeode->video_srcw = src_w;
1040      pGeode->video_srch = src_h;
1041      pGeode->video_dstw = drw_w;
1042      pGeode->video_dsth = drw_h;
1043      pGeode->video_offset = offset;
1044      pGeode->video_id = id;
1045      pGeode->video_scrnptr = pScrn;
1046   }
1047
1048   GFX(set_video_size(width, height));
1049   GFX(set_video_scale(width, height, drw_w, drw_h));
1050   GX1SetVideoPosition(dstBox->x1, dstBox->y1, width, height, src_w, src_h,
1051		       drw_w, drw_h, id, offset, pScrn);
1052   GFX(set_color_space_YUV(0));
1053}
1054
1055/*----------------------------------------------------------------------------
1056 * GX1PutImage	: This function writes a single frame of video into a drawable.
1057 *		The position and size of the source rectangle is specified by src_x,src_y,
1058 *		src_w and src_h. This data is stored in a system memory buffer at buf.
1059 *		The position and size of the destination rectangle is specified by drw_x,
1060 *      drw_y,drw_w,drw_h.The data is in the format indicated by the image descriptor
1061 *		and represents a source of size width by height.  If sync is TRUE the driver
1062 *		should not return from this function until it is through reading the data from
1063 *		buf.  Returning when sync is TRUE indicates that it is safe for the data at buf
1064 *		to be replaced,freed, or modified.
1065 *
1066 *
1067 * Description		:
1068 * Parameters.
1069 *
1070 * Returns		:None
1071 *
1072 * Comments		:None
1073 *
1074*----------------------------------------------------------------------------
1075*/
1076
1077static int
1078GX1PutImage(ScrnInfoPtr pScrn,
1079	    short src_x, short src_y,
1080	    short drw_x, short drw_y,
1081	    short src_w, short src_h,
1082	    short drw_w, short drw_h,
1083	    int id, unsigned char *buf,
1084	    short width, short height,
1085	    Bool sync, RegionPtr clipBoxes, pointer data,
1086	    DrawablePtr pDraw)
1087{
1088   GeodePortPrivPtr pPriv = (GeodePortPrivPtr) data;
1089   GeodePtr pGeode = GEODEPTR(pScrn);
1090   int pitch, new_h;
1091
1092#if REINIT
1093   BOOL ReInitVideo = FALSE;
1094#endif
1095
1096#if XV_PROFILE
1097   long oldtime, newtime;
1098
1099   UpdateCurrentTime();
1100   oldtime = currentTime.milliseconds;
1101#endif
1102
1103#if REINIT
1104/* update cliplist */
1105   if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
1106      ReInitVideo = TRUE;
1107   }
1108   if (ReInitVideo) {
1109      DEBUGMSG(1, (0, X_NONE, "Regional Not Equal - Init\n"));
1110#endif
1111
1112      if (drw_w > 16384)
1113	 drw_w = 16384;
1114
1115      /* Clip */
1116      Bx1 = src_x;
1117      Bx2 = src_x + src_w;
1118      By1 = src_y;
1119      By2 = src_y + src_h;
1120
1121      if ((Bx1 >= Bx2) || (By1 >= By2))
1122	 return Success;
1123
1124      dstBox.x1 = drw_x;
1125      dstBox.x2 = drw_x + drw_w;
1126      dstBox.y1 = drw_y;
1127      dstBox.y2 = drw_y + drw_h;
1128
1129      dstBox.x1 -= pScrn->frameX0;
1130      dstBox.x2 -= pScrn->frameX0;
1131      dstBox.y1 -= pScrn->frameY0;
1132      dstBox.y2 -= pScrn->frameY0;
1133
1134      pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
1135
1136      dstPitch = ((width << 1) + 3) & ~3;
1137
1138      switch (id) {
1139      case FOURCC_YV12:
1140      case FOURCC_I420:
1141	 srcPitch = (width + 3) & ~3;	/* of luma */
1142	 s2offset = srcPitch * height;
1143	 srcPitch2 = ((width >> 1) + 3) & ~3;
1144	 s3offset = (srcPitch2 * (height >> 1)) + s2offset;
1145	 break;
1146      case FOURCC_UYVY:
1147      case FOURCC_YUY2:
1148      case FOURCC_Y800:
1149      default:
1150	 srcPitch = (width << 1);
1151	 break;
1152      }
1153
1154      /* Find how many pitch scanlines required to store the data */
1155      new_h = ((dstPitch * height) + pitch - 1) / pitch;
1156
1157#if DBUF
1158      if (pPriv->doubleBuffer)
1159	 new_h <<= 1;
1160#endif
1161
1162      if (!(pPriv->area = GX1AllocateMemory(pScrn, pPriv->area, new_h)))
1163	 return BadAlloc;
1164
1165      /* copy data */
1166      top = By1;
1167      left = Bx1 & ~1;
1168      npixels = ((Bx2 + 1) & ~1) - left;
1169
1170      switch (id) {
1171      case FOURCC_YV12:
1172      case FOURCC_I420:
1173	 {
1174	    int tmp;
1175
1176	    top &= ~1;
1177	    offset = (pPriv->area->box.y1 * pitch) + (top * dstPitch);
1178
1179#if DBUF
1180	    if (pPriv->doubleBuffer && pPriv->currentBuffer)
1181	       offset += (new_h >> 1) * pitch;
1182#endif
1183
1184	    dst_start = pGeode->FBBase + offset + left;
1185	    tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1186	    s2offset += tmp;
1187	    s3offset += tmp;
1188	    if (id == FOURCC_I420) {
1189	       tmp = s2offset;
1190	       s2offset = s3offset;
1191	       s3offset = tmp;
1192	    }
1193	    nlines = ((By2 + 1) & ~1) - top;
1194	 }
1195	 break;
1196
1197      case FOURCC_UYVY:
1198      case FOURCC_YUY2:
1199      case FOURCC_Y800:
1200      default:
1201	 left <<= 1;
1202	 buf += (top * srcPitch) + left;
1203	 nlines = By2 - top;
1204	 offset = (pPriv->area->box.y1 * pitch) + (top * dstPitch);
1205
1206#if DBUF
1207	 if (pPriv->doubleBuffer && pPriv->currentBuffer)
1208	    offset += (new_h >> 1) * pitch;
1209#endif
1210
1211	 dst_start = pGeode->FBBase + offset + left;
1212	 break;
1213      }
1214      s1offset = (top * srcPitch) + left;
1215
1216#if REINIT
1217      /* update cliplist */
1218      REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
1219      if (pPriv->colorKeyMode == 0) {
1220	 /* draw these */
1221	 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
1222      }
1223      GX1DisplayVideo(pScrn, id, offset, width, height, dstPitch,
1224		      Bx1, By1, Bx2, By2, &dstBox, src_w, src_h, drw_w,
1225		      drw_h);
1226   }
1227#endif
1228
1229   switch (id) {
1230
1231   case FOURCC_Y800:
1232      GX1CopyGreyscale(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
1233      break;
1234   case FOURCC_YV12:
1235   case FOURCC_I420:
1236      GX1CopyMungedData(buf + s1offset, buf + s2offset,
1237			buf + s3offset, dst_start, srcPitch, srcPitch2,
1238			dstPitch, nlines, npixels);
1239      break;
1240   case FOURCC_UYVY:
1241   case FOURCC_YUY2:
1242   default:
1243      GX1CopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
1244      break;
1245   }
1246#if !REINIT
1247   /* update cliplist */
1248   REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
1249   if (pPriv->colorKeyMode == 0) {
1250      /* draw these */
1251      xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
1252   }
1253   GX1DisplayVideo(pScrn, id, offset, width, height, dstPitch,
1254		   Bx1, By1, Bx2, By2, &dstBox, src_w, src_h, drw_w, drw_h);
1255#endif
1256
1257#if XV_PROFILE
1258   UpdateCurrentTime();
1259   newtime = currentTime.milliseconds;
1260   DEBUGMSG(1, (0, X_NONE, "PI %d\n", newtime - oldtime));
1261#endif
1262
1263#if DBUF
1264   pPriv->currentBuffer ^= 1;
1265#endif
1266
1267   pPriv->videoStatus = CLIENT_VIDEO_ON;
1268   pGeode->OverlayON = TRUE;
1269   return Success;
1270}
1271
1272/*----------------------------------------------------------------------------
1273 * GX1QueryImageAttributes
1274 *
1275 * Description	:This function is called to let the driver specify how data
1276 *				 for a particular image of size width by height should be
1277 *				 stored.
1278 *
1279 * Parameters.
1280 * pScreenInfo
1281 *		Ptr			:Screen handler pointer having screen information.
1282 *		id			:Id for the video format
1283 *		width		:width  of the image (can be modified by the driver)
1284 *		height		:height of the image (can be modified by the driver)
1285 * Returns		: Size of the memory required for storing this image
1286 *
1287 * Comments		:None
1288 *
1289*----------------------------------------------------------------------------
1290*/
1291static int
1292GX1QueryImageAttributes(ScrnInfoPtr pScrn,
1293			int id,
1294			unsigned short *w, unsigned short *h,
1295			int *pitches, int *offsets)
1296{
1297   int size;
1298   int tmp;
1299
1300   DEBUGMSG(0, (0, X_NONE, "QueryImageAttributes %X\n", id));
1301
1302   if (*w > 1024)
1303      *w = 1024;
1304   if (*h > 1024)
1305      *h = 1024;
1306
1307   *w = (*w + 1) & ~1;
1308   if (offsets)
1309      offsets[0] = 0;
1310
1311   switch (id) {
1312   case FOURCC_YV12:
1313   case FOURCC_I420:
1314      *h = (*h + 1) & ~1;
1315      size = (*w + 3) & ~3;
1316      if (pitches)
1317	 pitches[0] = size;
1318      size *= *h;
1319      if (offsets)
1320	 offsets[1] = size;
1321      tmp = ((*w >> 1) + 3) & ~3;
1322      if (pitches)
1323	 pitches[1] = pitches[2] = tmp;
1324      tmp *= (*h >> 1);
1325      size += tmp;
1326      if (offsets)
1327	 offsets[2] = size;
1328      size += tmp;
1329      break;
1330   case FOURCC_UYVY:
1331   case FOURCC_YUY2:
1332   case FOURCC_Y800:
1333   default:
1334      size = *w << 1;
1335      if (pitches)
1336	 pitches[0] = size;
1337      size *= *h;
1338      break;
1339   }
1340   return size;
1341}
1342
1343static void
1344GX1BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
1345{
1346   ScreenPtr pScreen = screenInfo.screens[i];
1347   ScrnInfoPtr pScrn = xf86Screens[i];
1348   GeodePtr pGeode = GEODEPTR(pScrn);
1349   GeodePortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
1350
1351   DEBUGMSG(0, (0, X_NONE, "BlockHandler\n"));
1352   pScreen->BlockHandler = pGeode->BlockHandler;
1353   (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
1354   pScreen->BlockHandler = GX1BlockHandler;
1355
1356   if (!pGeode->NoAccel) GX1AccelSync(pScrn);
1357   if (pPriv->videoStatus & TIMER_MASK) {
1358      UpdateCurrentTime();
1359      if (pPriv->videoStatus & OFF_TIMER) {
1360	 if (pPriv->offTime < currentTime.milliseconds) {
1361	    GFX(set_video_enable(0));
1362	    pPriv->videoStatus = FREE_TIMER;
1363	    pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
1364	 }
1365      } else {				/* FREE_TIMER */
1366	 if (pPriv->freeTime < currentTime.milliseconds) {
1367	    if (pPriv->area) {
1368	       xf86FreeOffscreenArea(pPriv->area);
1369	       pPriv->area = NULL;
1370	    }
1371	    pPriv->videoStatus = 0;
1372	 }
1373      }
1374   }
1375}
1376
1377/****************** Offscreen stuff ***************/
1378
1379typedef struct
1380{
1381   FBAreaPtr area;
1382   FBLinearPtr linear;
1383   Bool isOn;
1384}
1385OffscreenPrivRec, *OffscreenPrivPtr;
1386
1387/*----------------------------------------------------------------------------
1388 * GX1AllocateSurface
1389 *
1390 * Description	:This function allocates an area of w by h in the offscreen
1391 * Parameters.
1392 * ScreenPtr
1393 *		pScreen	:Screen handler pointer having screen information.
1394 *
1395 * Returns		:None
1396 *
1397 * Comments		:None
1398 *
1399*----------------------------------------------------------------------------
1400*/
1401
1402static int
1403GX1AllocateSurface(ScrnInfoPtr pScrn,
1404		   int id,
1405		   unsigned short w, unsigned short h, XF86SurfacePtr surface)
1406{
1407   FBAreaPtr area;
1408   int pitch, fbpitch, numlines;
1409   OffscreenPrivPtr pPriv;
1410
1411   DEBUGMSG(0, (0, X_NONE, "AllocateSurface %x\n", id));
1412   if ((w > 1024) || (h > 1024))
1413      return BadAlloc;
1414
1415   w = (w + 1) & ~1;
1416   pitch = ((w << 1) + 15) & ~15;
1417   fbpitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
1418   numlines = ((pitch * h) + fbpitch - 1) / fbpitch;
1419
1420   if (!(area = GX1AllocateMemory(pScrn, NULL, numlines)))
1421      return BadAlloc;
1422
1423   surface->width = w;
1424   surface->height = h;
1425
1426   if (!(surface->pitches = xalloc(sizeof(int))))
1427      return BadAlloc;
1428   if (!(surface->offsets = xalloc(sizeof(int)))) {
1429      xfree(surface->pitches);
1430      return BadAlloc;
1431   }
1432   if (!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
1433      xfree(surface->pitches);
1434      xfree(surface->offsets);
1435      return BadAlloc;
1436   }
1437
1438   pPriv->area = area;
1439   pPriv->isOn = FALSE;
1440
1441   surface->pScrn = pScrn;
1442   surface->id = id;
1443   surface->pitches[0] = pitch;
1444   surface->offsets[0] = area->box.y1 * fbpitch;
1445   surface->devPrivate.ptr = (pointer) pPriv;
1446
1447   return Success;
1448}
1449
1450static int
1451GX1StopSurface(XF86SurfacePtr surface)
1452{
1453   OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
1454
1455   if (pPriv->isOn) {
1456      pPriv->isOn = FALSE;
1457   }
1458
1459   return Success;
1460}
1461
1462static int
1463GX1FreeSurface(XF86SurfacePtr surface)
1464{
1465   OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
1466
1467   DEBUGMSG(0, (0, X_NONE, "FreeSurface\n"));
1468
1469   if (pPriv->isOn)
1470      GX1StopSurface(surface);
1471   xf86FreeOffscreenArea(pPriv->area);
1472   xfree(surface->pitches);
1473   xfree(surface->offsets);
1474   xfree(surface->devPrivate.ptr);
1475
1476   return Success;
1477}
1478
1479static int
1480GX1GetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 * value)
1481{
1482   return GX1GetPortAttribute(pScrn, attribute, value,
1483			      (pointer) (GET_PORT_PRIVATE(pScrn)));
1484}
1485
1486static int
1487GX1SetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
1488{
1489   return GX1SetPortAttribute(pScrn, attribute, value,
1490			      (pointer) (GET_PORT_PRIVATE(pScrn)));
1491}
1492
1493static int
1494GX1DisplaySurface(XF86SurfacePtr surface,
1495		  short src_x, short src_y,
1496		  short drw_x, short drw_y,
1497		  short src_w, short src_h,
1498		  short drw_w, short drw_h, RegionPtr clipBoxes)
1499{
1500   OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
1501   ScrnInfoPtr pScrn = surface->pScrn;
1502   GeodePortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn);
1503   INT32 x1, y1, x2, y2;
1504   BoxRec dstBox;
1505
1506   DEBUGMSG(0, (0, X_NONE, "DisplaySuface\n"));
1507   x1 = src_x;
1508   x2 = src_x + src_w;
1509   y1 = src_y;
1510   y2 = src_y + src_h;
1511
1512   dstBox.x1 = drw_x;
1513   dstBox.x2 = drw_x + drw_w;
1514   dstBox.y1 = drw_y;
1515   dstBox.y2 = drw_y + drw_h;
1516
1517   if ((x1 >= x2) || (y1 >= y2))
1518      return Success;
1519
1520   dstBox.x1 -= pScrn->frameX0;
1521   dstBox.x2 -= pScrn->frameX0;
1522   dstBox.y1 -= pScrn->frameY0;
1523   dstBox.y2 -= pScrn->frameY0;
1524
1525   xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
1526
1527   GX1DisplayVideo(pScrn, surface->id, surface->offsets[0],
1528		   surface->width, surface->height, surface->pitches[0],
1529		   x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
1530
1531   pPriv->isOn = TRUE;
1532   if (portPriv->videoStatus & CLIENT_VIDEO_ON) {
1533      REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
1534      UpdateCurrentTime();
1535      portPriv->videoStatus = FREE_TIMER;
1536      portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
1537   }
1538
1539   return Success;
1540}
1541
1542/*----------------------------------------------------------------------------
1543 * GX1InitOffscreenImages
1544 *
1545 * Description	:This function sets up the offscreen memory management.It fills
1546 *				 in the XF86OffscreenImagePtr structure with functions to handle
1547 *				 offscreen memory operations.
1548 *
1549 * Parameters.
1550 * ScreenPtr
1551 *		pScreen	:Screen handler pointer having screen information.
1552 *
1553 * Returns		: None
1554 *
1555 * Comments		:None
1556 *
1557*----------------------------------------------------------------------------
1558*/
1559static void
1560GX1InitOffscreenImages(ScreenPtr pScreen)
1561{
1562   XF86OffscreenImagePtr offscreenImages;
1563
1564   DEBUGMSG(0, (0, X_NONE, "InitOffscreenImages\n"));
1565   /* need to free this someplace */
1566   if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
1567      return;
1568
1569   offscreenImages[0].image = &Images[0];
1570   offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
1571   offscreenImages[0].alloc_surface = GX1AllocateSurface;
1572   offscreenImages[0].free_surface = GX1FreeSurface;
1573   offscreenImages[0].display = GX1DisplaySurface;
1574   offscreenImages[0].stop = GX1StopSurface;
1575   offscreenImages[0].setAttribute = GX1SetSurfaceAttribute;
1576   offscreenImages[0].getAttribute = GX1GetSurfaceAttribute;
1577   offscreenImages[0].max_width = 1024;
1578   offscreenImages[0].max_height = 1024;
1579   offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
1580   offscreenImages[0].attributes = Attributes;
1581
1582   xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
1583}
1584