gx_video.c revision 04007eba
1f29dbc25Smrg/* Copyright (c) 2003-2005 Advanced Micro Devices, Inc.
2f29dbc25Smrg *
3f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy
4f29dbc25Smrg * of this software and associated documentation files (the "Software"), to
5f29dbc25Smrg * deal in the Software without restriction, including without limitation the
6f29dbc25Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7f29dbc25Smrg * sell copies of the Software, and to permit persons to whom the Software is
8f29dbc25Smrg * furnished to do so, subject to the following conditions:
9f29dbc25Smrg *
10f29dbc25Smrg * The above copyright notice and this permission notice shall be included in
11f29dbc25Smrg * all copies or substantial portions of the Software.
12f29dbc25Smrg *
13f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14f29dbc25Smrg * IMPDIs2IED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19f29dbc25Smrg * IN THE SOFTWARE.
20f29dbc25Smrg *
21f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
22f29dbc25Smrg * contributors may be used to endorse or promote products derived from this
23f29dbc25Smrg * software without specific prior written permission.
24f29dbc25Smrg * */
25f29dbc25Smrg
26f29dbc25Smrg/*
27f29dbc25Smrg * File Contents:   This file consists of main Xfree video supported routines.
28f29dbc25Smrg *
29f29dbc25Smrg * Project:         Geode Xfree Frame buffer device driver.
30f29dbc25Smrg * */
31f29dbc25Smrg
32f29dbc25Smrg/*
33f29dbc25Smrg * Fixes & Extensions to support Y800 greyscale modes
34f29dbc25Smrg * Alan Hourihane <alanh@fairlite.demon.co.uk>
35f29dbc25Smrg
36f29dbc25Smrg * code to allocate offscreen memory from EXA - is borrowed from Radeon
37f29dbc25Smrg */
38f29dbc25Smrg
39f29dbc25Smrg#ifdef HAVE_CONFIG_H
40f29dbc25Smrg#include "config.h"
41f29dbc25Smrg#endif
42f29dbc25Smrg
43f29dbc25Smrg#include <stdlib.h>
44f29dbc25Smrg#include <string.h>
45f29dbc25Smrg
46f29dbc25Smrg#include "xf86.h"
47f29dbc25Smrg#include "xf86_OSproc.h"
48f29dbc25Smrg#include "compiler.h"
49f29dbc25Smrg#include "xf86PciInfo.h"
50f29dbc25Smrg#include "xf86Pci.h"
51f29dbc25Smrg#include "xf86fbman.h"
52f29dbc25Smrg#include "regionstr.h"
53f29dbc25Smrg
54f29dbc25Smrg#include "geode.h"
55f29dbc25Smrg#include "xf86xv.h"
56f29dbc25Smrg#include <X11/extensions/Xv.h>
5704007ebaSmrg#ifdef HAVE_XAA_H
58f29dbc25Smrg#include "xaa.h"
59f29dbc25Smrg#include "xaalocal.h"
6004007ebaSmrg#endif
61f29dbc25Smrg#include "dixstruct.h"
62f29dbc25Smrg#include "fourcc.h"
63f29dbc25Smrg#include "geode_fourcc.h"
64f29dbc25Smrg
6504007ebaSmrg#define OFF_DELAY 		200     /* milliseconds */
66f29dbc25Smrg#define FREE_DELAY 		60000
67f29dbc25Smrg
68f29dbc25Smrg#define OFF_TIMER 		0x01
69f29dbc25Smrg#define FREE_TIMER		0x02
70f29dbc25Smrg#define CLIENT_VIDEO_ON	0x04
71f29dbc25Smrg
72f29dbc25Smrg#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
73f29dbc25Smrg#define XV_PROFILE 		0
74f29dbc25Smrg#define REINIT  		1
75f29dbc25Smrg
76f29dbc25Smrg#ifndef XvExtension
77f29dbc25Smrg#error "It didn't work!"
78f29dbc25Smrgvoid
79f29dbc25SmrgGXInitVideo(ScreenPtr pScrn)
80f29dbc25Smrg{
81f29dbc25Smrg}
82f29dbc25Smrg
83f29dbc25Smrgvoid
84f29dbc25SmrgGXResetVideo(ScrnInfoPtr pScrni)
85f29dbc25Smrg{
86f29dbc25Smrg}
87f29dbc25Smrg
88f29dbc25Smrgvoid
89f29dbc25SmrgGXSetVideoPosition()
90f29dbc25Smrg{
91f29dbc25Smrg}
92f29dbc25Smrg#else
93f29dbc25Smrg
94f29dbc25Smrg#define DBUF 1
95f29dbc25Smrgvoid GXResetVideo(ScrnInfoPtr pScrni);
96f29dbc25Smrgstatic XF86VideoAdaptorPtr GXSetupImageVideo(ScreenPtr);
97f29dbc25Smrgstatic void GXInitOffscreenImages(ScreenPtr);
98f29dbc25Smrgstatic void GXStopVideo(ScrnInfoPtr, pointer, Bool);
99f29dbc25Smrgstatic int GXSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
100f29dbc25Smrgstatic int GXGetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
101f29dbc25Smrgstatic void GXQueryBestSize(ScrnInfoPtr, Bool,
10204007ebaSmrg                            short, short, short, short, unsigned int *,
10304007ebaSmrg                            unsigned int *, pointer);
104f29dbc25Smrgstatic int GXPutImage(ScrnInfoPtr, short, short, short, short, short, short,
10504007ebaSmrg                      short, short, int, unsigned char *, short, short, Bool,
10604007ebaSmrg                      RegionPtr, pointer, DrawablePtr pDraw);
107f29dbc25Smrg
10804007ebaSmrgstatic void GXBlockHandler(BLOCKHANDLER_ARGS_DECL);
109f29dbc25Smrgvoid GXSetVideoPosition(int x, int y, int width, int height,
11004007ebaSmrg                        short src_w, short src_h, short drw_w,
11104007ebaSmrg                        short drw_h, int id, int offset, ScrnInfoPtr pScrni);
112f29dbc25Smrg
113f29dbc25Smrgextern void GXAccelSync(ScrnInfoPtr pScrni);
114f29dbc25Smrg
115f29dbc25Smrgint DeltaX, DeltaY;
116f29dbc25Smrg
117f29dbc25Smrgunsigned long graphics_lut[256];
118f29dbc25Smrgstatic int lutflag = 0;
119f29dbc25Smrg
120f29dbc25Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
121f29dbc25Smrg
122f29dbc25Smrgstatic Atom xvColorKey, xvColorKeyMode, xvFilter
123f29dbc25Smrg#if DBUF
12404007ebaSmrg, xvDoubleBuffer
125f29dbc25Smrg#endif
12604007ebaSmrg;
127f29dbc25Smrg
128f29dbc25Smrg#define PALETTE_ADDRESS   0x038
129f29dbc25Smrg#define PALETTE_DATA      0x040
130f29dbc25Smrg#define DISPLAY_CONFIG    0x008
131f29dbc25Smrg#define MISC              0x050
132f29dbc25Smrg
133f29dbc25Smrgstatic void
134f29dbc25Smrgget_gamma_ram(unsigned long *lut)
135f29dbc25Smrg{
136f29dbc25Smrg
137f29dbc25Smrg    int i;
138f29dbc25Smrg
139f29dbc25Smrg    gfx_write_vid32(PALETTE_ADDRESS, 0);
140f29dbc25Smrg
141f29dbc25Smrg    for (i = 0; i < 256; i++)
14204007ebaSmrg        lut[i] = gfx_read_vid32(PALETTE_DATA);
143f29dbc25Smrg}
144f29dbc25Smrg
145f29dbc25Smrg/*----------------------------------------------------------------------------
146f29dbc25Smrg * GXInitVideo
147f29dbc25Smrg *
148f29dbc25Smrg * Description	:This is the initialization routine.It creates a new video
149f29dbc25Smrg * 				adapter and calls GXSetupImageVideo to initialize the adaptor
150f29dbc25Smrg * 				by filling XF86VideoAdaptorREc.Then it lists the existing
151f29dbc25Smrg * 				adaptors and adds the new one to it. Finally the list of
152f29dbc25Smrg * 				XF86VideoAdaptorPtr pointers are passed to the
153f29dbc25Smrg * 				xf86XVScreenInit().
154f29dbc25Smrg *
155f29dbc25Smrg * Parameters.
156f29dbc25Smrg *		pScrn	:Screen handler pointer having screen information.
157f29dbc25Smrg *
158f29dbc25Smrg * Returns		:none
159f29dbc25Smrg *
160f29dbc25Smrg * Comments		:none
161f29dbc25Smrg *----------------------------------------------------------------------------
162f29dbc25Smrg */
163f29dbc25Smrgvoid
164f29dbc25SmrgGXInitVideo(ScreenPtr pScrn)
165f29dbc25Smrg{
166f29dbc25Smrg    GeodeRec *pGeode;
16704007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
168f29dbc25Smrg
169f29dbc25Smrg    pGeode = GEODEPTR(pScrni);
170f29dbc25Smrg
171f29dbc25Smrg    if (!pGeode->NoAccel) {
17204007ebaSmrg        XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
17304007ebaSmrg        XF86VideoAdaptorPtr newAdaptor = NULL;
17404007ebaSmrg
17504007ebaSmrg        int num_adaptors;
17604007ebaSmrg
17704007ebaSmrg        newAdaptor = GXSetupImageVideo(pScrn);
17804007ebaSmrg        GXInitOffscreenImages(pScrn);
17904007ebaSmrg
18004007ebaSmrg        num_adaptors = xf86XVListGenericAdaptors(pScrni, &adaptors);
18104007ebaSmrg
18204007ebaSmrg        if (newAdaptor) {
18304007ebaSmrg            if (!num_adaptors) {
18404007ebaSmrg                num_adaptors = 1;
18504007ebaSmrg                adaptors = &newAdaptor;
18604007ebaSmrg            }
18704007ebaSmrg            else {
18804007ebaSmrg                newAdaptors =   /* need to free this someplace */
18904007ebaSmrg                    malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *));
19004007ebaSmrg                if (newAdaptors) {
19104007ebaSmrg                    memcpy(newAdaptors, adaptors, num_adaptors *
19204007ebaSmrg                           sizeof(XF86VideoAdaptorPtr));
19304007ebaSmrg                    newAdaptors[num_adaptors] = newAdaptor;
19404007ebaSmrg                    adaptors = newAdaptors;
19504007ebaSmrg                    num_adaptors++;
19604007ebaSmrg                }
19704007ebaSmrg            }
19804007ebaSmrg        }
19904007ebaSmrg
20004007ebaSmrg        if (num_adaptors)
20104007ebaSmrg            xf86XVScreenInit(pScrn, adaptors, num_adaptors);
20204007ebaSmrg
20304007ebaSmrg        if (newAdaptors)
20404007ebaSmrg            free(newAdaptors);
205f29dbc25Smrg    }
206f29dbc25Smrg}
207f29dbc25Smrg
208f29dbc25Smrg/* client libraries expect an encoding */
209f29dbc25Smrgstatic XF86VideoEncodingRec DummyEncoding[1] = {
210f29dbc25Smrg    {
21104007ebaSmrg     0,
21204007ebaSmrg     "XV_IMAGE",
21304007ebaSmrg     1024, 1024,
21404007ebaSmrg     {1, 1}
21504007ebaSmrg     }
216f29dbc25Smrg};
217f29dbc25Smrg
218f29dbc25Smrg#define NUM_FORMATS 4
219f29dbc25Smrg
220f29dbc25Smrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] = {
221f29dbc25Smrg    {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
222f29dbc25Smrg};
223f29dbc25Smrg
224f29dbc25Smrg#if DBUF
225f29dbc25Smrg#define NUM_ATTRIBUTES 4
226f29dbc25Smrg#else
227f29dbc25Smrg#define NUM_ATTRIBUTES 3
228f29dbc25Smrg#endif
229f29dbc25Smrg
230f29dbc25Smrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {
231f29dbc25Smrg#if DBUF
232f29dbc25Smrg    {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
233f29dbc25Smrg#endif
234f29dbc25Smrg    {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
235f29dbc25Smrg    {XvSettable | XvGettable, 0, 1, "XV_FILTER"},
236f29dbc25Smrg    {XvSettable | XvGettable, 0, 1, "XV_COLORKEYMODE"}
237f29dbc25Smrg};
238f29dbc25Smrg
239f29dbc25Smrg#define NUM_IMAGES 8
240f29dbc25Smrg
241f29dbc25Smrgstatic XF86ImageRec Images[NUM_IMAGES] = {
242f29dbc25Smrg    XVIMAGE_UYVY,
243f29dbc25Smrg    XVIMAGE_YUY2,
244f29dbc25Smrg    XVIMAGE_Y2YU,
245f29dbc25Smrg    XVIMAGE_YVYU,
246f29dbc25Smrg    XVIMAGE_Y800,
247f29dbc25Smrg    XVIMAGE_I420,
248f29dbc25Smrg    XVIMAGE_YV12,
249f29dbc25Smrg    XVIMAGE_RGB565
250f29dbc25Smrg};
251f29dbc25Smrg
25204007ebaSmrgtypedef struct {
253f29dbc25Smrg    void *area;
254f29dbc25Smrg    int offset;
255f29dbc25Smrg    RegionRec clip;
256f29dbc25Smrg    CARD32 filter;
257f29dbc25Smrg    CARD32 colorKey;
258f29dbc25Smrg    CARD32 colorKeyMode;
259f29dbc25Smrg    CARD32 videoStatus;
260f29dbc25Smrg    Time offTime;
261f29dbc25Smrg    Time freeTime;
262f29dbc25Smrg#if DBUF
263f29dbc25Smrg    Bool doubleBuffer;
264f29dbc25Smrg    int currentBuffer;
265f29dbc25Smrg#endif
266f29dbc25Smrg} GeodePortPrivRec, *GeodePortPrivPtr;
267f29dbc25Smrg
268f29dbc25Smrg#define GET_PORT_PRIVATE(pScrni) \
269f29dbc25Smrg   (GeodePortPrivRec *)((GEODEPTR(pScrni))->adaptor->pPortPrivates[0].ptr)
270f29dbc25Smrg
271f29dbc25Smrg/*----------------------------------------------------------------------------
272f29dbc25Smrg * GXSetColorKey
273f29dbc25Smrg *
274f29dbc25Smrg * Description	:This function reads the color key for the pallete and
275f29dbc25Smrg *				  sets the video color key register.
276f29dbc25Smrg *
277f29dbc25Smrg * Parameters.
278f29dbc25Smrg * ScreenInfoPtr
279f29dbc25Smrg *		pScrni	:Screen  pointer having screen information.
280f29dbc25Smrg *		pPriv	:Video port private data
281f29dbc25Smrg *
282f29dbc25Smrg * Returns		:none
283f29dbc25Smrg *
284f29dbc25Smrg * Comments		:none
285f29dbc25Smrg *
286f29dbc25Smrg *----------------------------------------------------------------------------
287f29dbc25Smrg */
288f29dbc25Smrgstatic INT32
289f29dbc25SmrgGXSetColorkey(ScrnInfoPtr pScrni, GeodePortPrivRec * pPriv)
290f29dbc25Smrg{
291f29dbc25Smrg    int red, green, blue;
292f29dbc25Smrg    unsigned long key;
293f29dbc25Smrg
294f29dbc25Smrg    switch (pScrni->depth) {
295f29dbc25Smrg    case 8:
29604007ebaSmrg        GFX(get_display_palette_entry(pPriv->colorKey & 0xFF, &key));
29704007ebaSmrg        red = ((key >> 16) & 0xFF);
29804007ebaSmrg        green = ((key >> 8) & 0xFF);
29904007ebaSmrg        blue = (key & 0xFF);
30004007ebaSmrg        break;
301f29dbc25Smrg    case 16:
30204007ebaSmrg        red = (pPriv->colorKey & pScrni->mask.red) >>
30304007ebaSmrg            pScrni->offset.red << (8 - pScrni->weight.red);
30404007ebaSmrg        green = (pPriv->colorKey & pScrni->mask.green) >>
30504007ebaSmrg            pScrni->offset.green << (8 - pScrni->weight.green);
30604007ebaSmrg        blue = (pPriv->colorKey & pScrni->mask.blue) >>
30704007ebaSmrg            pScrni->offset.blue << (8 - pScrni->weight.blue);
30804007ebaSmrg        break;
309f29dbc25Smrg    default:
31004007ebaSmrg        /* for > 16 bpp we send in the mask in xf86SetWeight. This
31104007ebaSmrg         * function is providing the offset by 1 more. So we take
31204007ebaSmrg         * this as a special case and subtract 1 for > 16
31304007ebaSmrg         */
31404007ebaSmrg        red = (pPriv->colorKey & pScrni->mask.red) >>
31504007ebaSmrg            (pScrni->offset.red - 1) << (8 - pScrni->weight.red);
31604007ebaSmrg        green = (pPriv->colorKey & pScrni->mask.green) >>
31704007ebaSmrg            (pScrni->offset.green - 1) << (8 - pScrni->weight.green);
31804007ebaSmrg        blue = (pPriv->colorKey & pScrni->mask.blue) >>
31904007ebaSmrg            (pScrni->offset.blue - 1) << (8 - pScrni->weight.blue);
32004007ebaSmrg        break;
321f29dbc25Smrg    }
322f29dbc25Smrg
323f29dbc25Smrg    GFX(set_video_color_key((blue | (green << 8) | (red << 16)), 0xFFFFFF,
32404007ebaSmrg                            (pPriv->colorKeyMode == 0)));
325f29dbc25Smrg    REGION_EMPTY(pScrni->pScreen, &pPriv->clip);
326f29dbc25Smrg    return 0;
327f29dbc25Smrg}
328f29dbc25Smrg
329f29dbc25Smrg/*----------------------------------------------------------------------------
330f29dbc25Smrg * GXResetVideo
331f29dbc25Smrg *
332f29dbc25Smrg * Description	: This function resets the video
333f29dbc25Smrg *
334f29dbc25Smrg * Parameters.
335f29dbc25Smrg *		pScrni	:Screen  pointer having screen information.
336f29dbc25Smrg *
337f29dbc25Smrg * Returns		:None
338f29dbc25Smrg *
339f29dbc25Smrg * Comments		:none
340f29dbc25Smrg *
341f29dbc25Smrg *----------------------------------------------------------------------------
342f29dbc25Smrg */
343f29dbc25Smrgvoid
344f29dbc25SmrgGXResetVideo(ScrnInfoPtr pScrni)
345f29dbc25Smrg{
346f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
347f29dbc25Smrg
348f29dbc25Smrg    if (!pGeode->NoAccel) {
34904007ebaSmrg        GeodePortPrivRec *pPriv = pGeode->adaptor->pPortPrivates[0].ptr;
350f29dbc25Smrg
35104007ebaSmrg        GXAccelSync(pScrni);
35204007ebaSmrg        GXSetColorkey(pScrni, pPriv);
35304007ebaSmrg        GFX(set_video_filter(pPriv->filter, pPriv->filter));
354f29dbc25Smrg    }
355f29dbc25Smrg}
356f29dbc25Smrg
357f29dbc25Smrg/*----------------------------------------------------------------------------
358f29dbc25Smrg * GXSetupImageVideo
359f29dbc25Smrg *
360f29dbc25Smrg * Description	: This function allocates space for a Videoadaptor and
361f29dbc25Smrg * 				initializes the XF86VideoAdaptorPtr record.
362f29dbc25Smrg *
363f29dbc25Smrg * Parameters.
364f29dbc25Smrg *		pScrn	:Screen handler pointer having screen information.
365f29dbc25Smrg *
366f29dbc25Smrg * Returns		:pointer to the initialized video adaptor record.
367f29dbc25Smrg *
368f29dbc25Smrg * Comments		:none
369f29dbc25Smrg *----------------------------------------------------------------------------
370f29dbc25Smrg */
371f29dbc25Smrgstatic XF86VideoAdaptorPtr
372f29dbc25SmrgGXSetupImageVideo(ScreenPtr pScrn)
373f29dbc25Smrg{
37404007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
375f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
376f29dbc25Smrg    XF86VideoAdaptorPtr adapt;
377f29dbc25Smrg    GeodePortPrivRec *pPriv;
378f29dbc25Smrg
379170d5fdcSmrg    if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
38004007ebaSmrg                         sizeof(GeodePortPrivRec) + sizeof(DevUnion))))
38104007ebaSmrg        return NULL;
382f29dbc25Smrg
383f29dbc25Smrg    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
384f29dbc25Smrg    adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
385f29dbc25Smrg    adapt->name = "Advanced Micro Devices";
386f29dbc25Smrg    adapt->nEncodings = 1;
387f29dbc25Smrg    adapt->pEncodings = DummyEncoding;
388f29dbc25Smrg    adapt->nFormats = NUM_FORMATS;
389f29dbc25Smrg    adapt->pFormats = Formats;
390f29dbc25Smrg    adapt->nPorts = 1;
391f29dbc25Smrg    adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
392f29dbc25Smrg    pPriv = (GeodePortPrivRec *) (&adapt->pPortPrivates[1]);
393f29dbc25Smrg    adapt->pPortPrivates[0].ptr = (pointer) (pPriv);
394f29dbc25Smrg    adapt->pAttributes = Attributes;
395f29dbc25Smrg    adapt->nImages = NUM_IMAGES;
396f29dbc25Smrg    adapt->nAttributes = NUM_ATTRIBUTES;
397f29dbc25Smrg    adapt->pImages = Images;
398f29dbc25Smrg    adapt->PutVideo = NULL;
399f29dbc25Smrg    adapt->PutStill = NULL;
400f29dbc25Smrg    adapt->GetVideo = NULL;
401f29dbc25Smrg    adapt->GetStill = NULL;
402f29dbc25Smrg    adapt->StopVideo = GXStopVideo;
403f29dbc25Smrg    adapt->SetPortAttribute = GXSetPortAttribute;
404f29dbc25Smrg    adapt->GetPortAttribute = GXGetPortAttribute;
405f29dbc25Smrg    adapt->QueryBestSize = GXQueryBestSize;
406f29dbc25Smrg    adapt->PutImage = GXPutImage;
407f29dbc25Smrg    adapt->QueryImageAttributes = GeodeQueryImageAttributes;
408f29dbc25Smrg
409f29dbc25Smrg    pPriv->filter = 0;
410f29dbc25Smrg    pPriv->colorKey = 0;
411f29dbc25Smrg    pPriv->colorKeyMode = 0;
412f29dbc25Smrg    pPriv->videoStatus = 0;
413f29dbc25Smrg#if DBUF
414f29dbc25Smrg    pPriv->doubleBuffer = TRUE;
41504007ebaSmrg    pPriv->currentBuffer = 0;   /* init to first buffer */
416f29dbc25Smrg#endif
417f29dbc25Smrg
418f29dbc25Smrg    /* gotta uninit this someplace */
419f29dbc25Smrg#if defined(REGION_NULL)
420f29dbc25Smrg    REGION_NULL(pScrn, &pPriv->clip);
421f29dbc25Smrg#else
422f29dbc25Smrg    REGION_INIT(pScrn, &pPriv->clip, NullBox, 0);
423f29dbc25Smrg#endif
424f29dbc25Smrg
425f29dbc25Smrg    pGeode->adaptor = adapt;
426f29dbc25Smrg
427f29dbc25Smrg    pGeode->BlockHandler = pScrn->BlockHandler;
428f29dbc25Smrg    pScrn->BlockHandler = GXBlockHandler;
429f29dbc25Smrg
430f29dbc25Smrg    xvColorKey = MAKE_ATOM("XV_COLORKEY");
431f29dbc25Smrg    xvColorKeyMode = MAKE_ATOM("XV_COLORKEYMODE");
432f29dbc25Smrg    xvFilter = MAKE_ATOM("XV_FILTER");
433f29dbc25Smrg#if DBUF
434f29dbc25Smrg    xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
435f29dbc25Smrg#endif
436f29dbc25Smrg
437f29dbc25Smrg    GXResetVideo(pScrni);
438f29dbc25Smrg
439f29dbc25Smrg    return adapt;
440f29dbc25Smrg}
441f29dbc25Smrg
442f29dbc25Smrg/*----------------------------------------------------------------------------
443f29dbc25Smrg * GXStopVideo
444f29dbc25Smrg *
445f29dbc25Smrg * Description	:This function is used to stop input and output video
446f29dbc25Smrg *
447f29dbc25Smrg * Parameters.
448f29dbc25Smrg *		pScrni	:Screen handler pointer having screen information.
449f29dbc25Smrg *		data	:Pointer to the video port's private data
450f29dbc25Smrg *		exit	:Flag indicating whether the offscreen areas used for
451f29dbc25Smrg *				video to be deallocated or not.
452f29dbc25Smrg *
453f29dbc25Smrg * Returns		:none
454f29dbc25Smrg *
455f29dbc25Smrg * Comments		:none
456f29dbc25Smrg *----------------------------------------------------------------------------
457f29dbc25Smrg */
458f29dbc25Smrgstatic void
459f29dbc25SmrgGXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit)
460f29dbc25Smrg{
461f29dbc25Smrg    GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
462f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
463f29dbc25Smrg
464f29dbc25Smrg    REGION_EMPTY(pScrni->pScreen, &pPriv->clip);
465f29dbc25Smrg
466f29dbc25Smrg    GXAccelSync(pScrni);
467f29dbc25Smrg    if (exit) {
46804007ebaSmrg        if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
46904007ebaSmrg            GFX(set_video_enable(0));
470f29dbc25Smrg
47104007ebaSmrg            /* If we have saved graphics LUT data - restore it */
47204007ebaSmrg            /* Otherwise, turn bypass on */
473f29dbc25Smrg
47404007ebaSmrg            if (lutflag)
47504007ebaSmrg                GFX(set_graphics_palette(graphics_lut));
47604007ebaSmrg            else
47704007ebaSmrg                GFX(set_video_palette_bypass(1));
478f29dbc25Smrg
47904007ebaSmrg            lutflag = 0;
48004007ebaSmrg        }
481f29dbc25Smrg
48204007ebaSmrg        if (pPriv->area) {
483f29dbc25Smrg#ifdef XF86EXA
48404007ebaSmrg            if (pGeode->useEXA)
48504007ebaSmrg                exaOffscreenFree(pScrni->pScreen, pPriv->area);
486f29dbc25Smrg#endif
487f29dbc25Smrg
48804007ebaSmrg            if (!pGeode->useEXA)
48904007ebaSmrg                xf86FreeOffscreenArea(pPriv->area);
490f29dbc25Smrg
49104007ebaSmrg            pPriv->area = NULL;
49204007ebaSmrg        }
493f29dbc25Smrg
49404007ebaSmrg        pPriv->videoStatus = 0;
49504007ebaSmrg        pGeode->OverlayON = FALSE;
49604007ebaSmrg    }
49704007ebaSmrg    else {
49804007ebaSmrg        if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
49904007ebaSmrg            pPriv->videoStatus |= OFF_TIMER;
50004007ebaSmrg            pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
50104007ebaSmrg        }
502f29dbc25Smrg    }
503f29dbc25Smrg}
504f29dbc25Smrg
505f29dbc25Smrg/*----------------------------------------------------------------------------
506f29dbc25Smrg * GXSetPortAttribute
507f29dbc25Smrg *
508f29dbc25Smrg * Description		:This function is used to set the attributes of a port
509f29dbc25Smrg * 					like colorkeymode, double buffer support and filter.
510f29dbc25Smrg *
511f29dbc25Smrg * Parameters.
512f29dbc25Smrg *		pScrni		:Screen handler pointer having screen information.
513f29dbc25Smrg *		data		:Pointer to the video port's private data
514f29dbc25Smrg *		attribute	:The port attribute to be set
515f29dbc25Smrg *		value		:Value of the attribute to be set.
516f29dbc25Smrg *
517f29dbc25Smrg * Returns			:Sucess if the attribute is supported, else BadMatch
518f29dbc25Smrg *
519f29dbc25Smrg * Comments			:none
520f29dbc25Smrg *----------------------------------------------------------------------------
521f29dbc25Smrg */
522f29dbc25Smrgstatic int
523f29dbc25SmrgGXSetPortAttribute(ScrnInfoPtr pScrni,
52404007ebaSmrg                   Atom attribute, INT32 value, pointer data)
525f29dbc25Smrg{
526f29dbc25Smrg    GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
527f29dbc25Smrg
528f29dbc25Smrg    GXAccelSync(pScrni);
529f29dbc25Smrg    if (attribute == xvColorKey) {
53004007ebaSmrg        pPriv->colorKey = value;
53104007ebaSmrg        GXSetColorkey(pScrni, pPriv);
532f29dbc25Smrg    }
533f29dbc25Smrg#if DBUF
534f29dbc25Smrg    else if (attribute == xvDoubleBuffer) {
53504007ebaSmrg        if ((value < 0) || (value > 1))
53604007ebaSmrg            return BadValue;
53704007ebaSmrg        pPriv->doubleBuffer = value;
538f29dbc25Smrg    }
539f29dbc25Smrg#endif
540f29dbc25Smrg    else if (attribute == xvColorKeyMode) {
54104007ebaSmrg        pPriv->colorKeyMode = value;
54204007ebaSmrg        GXSetColorkey(pScrni, pPriv);
54304007ebaSmrg    }
54404007ebaSmrg    else if (attribute == xvFilter) {
54504007ebaSmrg        if ((value < 0) || (value > 1))
54604007ebaSmrg            return BadValue;
54704007ebaSmrg        pPriv->filter = value;
54804007ebaSmrg    }
54904007ebaSmrg    else
55004007ebaSmrg        return BadMatch;
551f29dbc25Smrg
552f29dbc25Smrg    return Success;
553f29dbc25Smrg}
554f29dbc25Smrg
555f29dbc25Smrg/*----------------------------------------------------------------------------
556f29dbc25Smrg * GXGetPortAttribute
557f29dbc25Smrg *
558f29dbc25Smrg * Description		:This function is used to get the attributes of a port
559f29dbc25Smrg * 					like hue, saturation,brightness or contrast.
560f29dbc25Smrg *
561f29dbc25Smrg * Parameters.
562f29dbc25Smrg *		pScrni		:Screen handler pointer having screen information.
563f29dbc25Smrg *		data		:Pointer to the video port's private data
564f29dbc25Smrg *		attribute	:The port attribute to be read
565f29dbc25Smrg *		value		:Pointer to the value of the attribute to be read.
566f29dbc25Smrg *
567f29dbc25Smrg * Returns			:Sucess if the attribute is supported, else BadMatch
568f29dbc25Smrg *
569f29dbc25Smrg * Comments			:none
570f29dbc25Smrg *----------------------------------------------------------------------------
571f29dbc25Smrg */
572f29dbc25Smrgstatic int
573f29dbc25SmrgGXGetPortAttribute(ScrnInfoPtr pScrni,
57404007ebaSmrg                   Atom attribute, INT32 *value, pointer data)
575f29dbc25Smrg{
576f29dbc25Smrg    GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
577f29dbc25Smrg
578f29dbc25Smrg    if (attribute == xvColorKey) {
57904007ebaSmrg        *value = pPriv->colorKey;
580f29dbc25Smrg    }
581f29dbc25Smrg#if DBUF
582f29dbc25Smrg    else if (attribute == xvDoubleBuffer) {
58304007ebaSmrg        *value = (pPriv->doubleBuffer) ? 1 : 0;
584f29dbc25Smrg    }
585f29dbc25Smrg#endif
586f29dbc25Smrg    else if (attribute == xvColorKeyMode) {
58704007ebaSmrg        *value = pPriv->colorKeyMode;
58804007ebaSmrg    }
58904007ebaSmrg    else if (attribute == xvFilter) {
59004007ebaSmrg        *value = pPriv->filter;
59104007ebaSmrg    }
59204007ebaSmrg    else
59304007ebaSmrg        return BadMatch;
594f29dbc25Smrg
595f29dbc25Smrg    return Success;
596f29dbc25Smrg}
597f29dbc25Smrg
598f29dbc25Smrg/*----------------------------------------------------------------------------
599f29dbc25Smrg * GXQueryBestSize
600f29dbc25Smrg *
601f29dbc25Smrg * Description		:This function provides a way to query what the
602f29dbc25Smrg * 					destination dimensions would end up being if they were to
603f29dbc25Smrg * 					request that an area vid_w by vid_h from the video stream
604f29dbc25Smrg * 					be scaled to rectangle of drw_w by drw_h on the screen.
605f29dbc25Smrg *
606f29dbc25Smrg * Parameters.
607f29dbc25Smrg *		pScrni		:Screen handler pointer having screen information.
608f29dbc25Smrg *		data		:Pointer to the video port's private data
609f29dbc25Smrg *      vid_w,vid_h	:Width and height of the video data.
610f29dbc25Smrg *		drw_w,drw_h :Width and height of the scaled rectangle.
611f29dbc25Smrg *		p_w,p_h		:Width and height of the destination rectangle.
612f29dbc25Smrg *
613f29dbc25Smrg * Returns			:None
614f29dbc25Smrg *
615f29dbc25Smrg * Comments			:None
616f29dbc25Smrg *----------------------------------------------------------------------------
617f29dbc25Smrg */
618f29dbc25Smrgstatic void
619f29dbc25SmrgGXQueryBestSize(ScrnInfoPtr pScrni,
62004007ebaSmrg                Bool motion,
62104007ebaSmrg                short vid_w, short vid_h,
62204007ebaSmrg                short drw_w, short drw_h,
62304007ebaSmrg                unsigned int *p_w, unsigned int *p_h, pointer data)
624f29dbc25Smrg{
625f29dbc25Smrg    *p_w = drw_w;
626f29dbc25Smrg    *p_h = drw_h;
627f29dbc25Smrg
628f29dbc25Smrg    if (*p_w > 16384)
62904007ebaSmrg        *p_w = 16384;
630f29dbc25Smrg}
631f29dbc25Smrg
632f29dbc25Smrg/*----------------------------------------------------------------------------
633f29dbc25Smrg * GXCopyData420
634f29dbc25Smrg *
635f29dbc25Smrg * Description		: Copies data from src to destination
636f29dbc25Smrg *
637f29dbc25Smrg * Parameters.
638f29dbc25Smrg *		src			: pointer to the source data
639f29dbc25Smrg *		dst			: pointer to destination data
640f29dbc25Smrg *		srcPitch	: pitch of the srcdata
641f29dbc25Smrg *		dstPitch	: pitch of the destination data
642f29dbc25Smrg *		h & w		: height and width of source data
643f29dbc25Smrg *
644f29dbc25Smrg * Returns			:None
645f29dbc25Smrg *
646f29dbc25Smrg * Comments			:None
647f29dbc25Smrg *----------------------------------------------------------------------------
648f29dbc25Smrg */
649f29dbc25Smrgstatic void
650f29dbc25SmrgGXCopyData420(unsigned char *src, unsigned char *dst,
65104007ebaSmrg              int srcPitch, int dstPitch, int h, int w)
652f29dbc25Smrg{
653f29dbc25Smrg    while (h--) {
65404007ebaSmrg        memcpy(dst, src, w);
65504007ebaSmrg        src += srcPitch;
65604007ebaSmrg        dst += dstPitch;
657f29dbc25Smrg    }
658f29dbc25Smrg}
659f29dbc25Smrg
660f29dbc25Smrg/*----------------------------------------------------------------------------
661f29dbc25Smrg * GXCopyData422
662f29dbc25Smrg *
663f29dbc25Smrg * Description		: Copies data from src to destination
664f29dbc25Smrg *
665f29dbc25Smrg * Parameters.
666f29dbc25Smrg *		src			: pointer to the source data
667f29dbc25Smrg *		dst			: pointer to destination data
668f29dbc25Smrg *		srcPitch	: pitch of the srcdata
669f29dbc25Smrg *		dstPitch	: pitch of the destination data
670f29dbc25Smrg *		h & w		: height and width of source data
671f29dbc25Smrg *
672f29dbc25Smrg * Returns			:None
673f29dbc25Smrg *
674f29dbc25Smrg * Comments			:None
675f29dbc25Smrg *----------------------------------------------------------------------------
676f29dbc25Smrg */
677f29dbc25Smrgstatic void
678f29dbc25SmrgGXCopyData422(unsigned char *src, unsigned char *dst,
67904007ebaSmrg              int srcPitch, int dstPitch, int h, int w)
680f29dbc25Smrg{
681f29dbc25Smrg    w <<= 1;
682f29dbc25Smrg    while (h--) {
68304007ebaSmrg        memcpy(dst, src, w);
68404007ebaSmrg        src += srcPitch;
68504007ebaSmrg        dst += dstPitch;
686f29dbc25Smrg    }
687f29dbc25Smrg}
688f29dbc25Smrg
689f29dbc25Smrg#ifdef XF86EXA
690f29dbc25Smrgstatic void
691f29dbc25SmrgGXVideoSave(ScreenPtr pScreen, ExaOffscreenArea * area)
692f29dbc25Smrg{
69304007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen);
694f29dbc25Smrg    GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni);
695f29dbc25Smrg
696f29dbc25Smrg    if (area == pPriv->area)
69704007ebaSmrg        pPriv->area = NULL;
698f29dbc25Smrg}
699f29dbc25Smrg#endif
700f29dbc25Smrg
701f29dbc25Smrgstatic int
702f29dbc25SmrgGXAllocateMemory(ScrnInfoPtr pScrni, void **memp, int numlines)
703f29dbc25Smrg{
70404007ebaSmrg    ScreenPtr pScrn = xf86ScrnToScreen(pScrni);
705f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
706f29dbc25Smrg
707f29dbc25Smrg    //long displayWidth = pGeode->Pitch / ((pScrni->bitsPerPixel + 7) / 8);
708f29dbc25Smrg    int size = numlines * pGeode->displayWidth;
709f29dbc25Smrg
710f29dbc25Smrg#if XF86EXA
711f29dbc25Smrg    if (pGeode->useEXA) {
71204007ebaSmrg        ExaOffscreenArea *area = *memp;
713f29dbc25Smrg
71404007ebaSmrg        if (area != NULL) {
71504007ebaSmrg            if (area->size >= size)
71604007ebaSmrg                return area->offset;
717f29dbc25Smrg
71804007ebaSmrg            exaOffscreenFree(pScrni->pScreen, area);
71904007ebaSmrg        }
720f29dbc25Smrg
72104007ebaSmrg        area = exaOffscreenAlloc(pScrni->pScreen, size, 16,
72204007ebaSmrg                                 TRUE, GXVideoSave, NULL);
72304007ebaSmrg        *memp = area;
724f29dbc25Smrg
72504007ebaSmrg        return area == NULL ? 0 : area->offset;
726f29dbc25Smrg    }
727f29dbc25Smrg#endif
728f29dbc25Smrg
729f29dbc25Smrg    if (!pGeode->useEXA) {
73004007ebaSmrg        FBAreaPtr area = *memp;
73104007ebaSmrg        FBAreaPtr new_area;
732f29dbc25Smrg
73304007ebaSmrg        if (area) {
73404007ebaSmrg            if ((area->box.y2 - area->box.y1) >= numlines)
73504007ebaSmrg                return (area->box.y1 * pGeode->Pitch);
736f29dbc25Smrg
73704007ebaSmrg            if (xf86ResizeOffscreenArea(area, pGeode->displayWidth, numlines))
73804007ebaSmrg                return (area->box.y1 * pGeode->Pitch);
739f29dbc25Smrg
74004007ebaSmrg            xf86FreeOffscreenArea(area);
74104007ebaSmrg        }
742f29dbc25Smrg
74304007ebaSmrg        new_area = xf86AllocateOffscreenArea(pScrn, pGeode->displayWidth,
74404007ebaSmrg                                             numlines, 0, NULL, NULL, NULL);
745f29dbc25Smrg
74604007ebaSmrg        if (!new_area) {
74704007ebaSmrg            int max_w, max_h;
748f29dbc25Smrg
74904007ebaSmrg            xf86QueryLargestOffscreenArea(pScrn, &max_w, &max_h, 0,
75004007ebaSmrg                                          FAVOR_WIDTH_THEN_AREA,
75104007ebaSmrg                                          PRIORITY_EXTREME);
752f29dbc25Smrg
75304007ebaSmrg            if ((max_w < pGeode->displayWidth) || (max_h < numlines)) {
75404007ebaSmrg                xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
75504007ebaSmrg                           "No room - how sad %x, %x, %x, %x\n", max_w,
75604007ebaSmrg                           pGeode->displayWidth, max_h, numlines);
75704007ebaSmrg                return 0;
75804007ebaSmrg            }
759f29dbc25Smrg
76004007ebaSmrg            xf86PurgeUnlockedOffscreenAreas(pScrn);
76104007ebaSmrg            new_area = xf86AllocateOffscreenArea(pScrn, pGeode->displayWidth,
76204007ebaSmrg                                                 numlines, 0, NULL, NULL, NULL);
76304007ebaSmrg        }
764f29dbc25Smrg
76504007ebaSmrg        return (new_area->box.y1 * pGeode->Pitch);
766f29dbc25Smrg    }
767f29dbc25Smrg
768f29dbc25Smrg    return 0;
769f29dbc25Smrg}
770f29dbc25Smrg
771f29dbc25Smrgstatic BoxRec dstBox;
772f29dbc25Smrgstatic int srcPitch = 0, srcPitch2 = 0, dstPitch = 0, dstPitch2 = 0;
773f29dbc25Smrgstatic INT32 Bx1, Bx2, By1, By2;
774f29dbc25Smrgstatic int top, left, npixels, nlines;
775f29dbc25Smrgstatic int offset, s1offset = 0, s2offset = 0, s3offset = 0;
776f29dbc25Smrgstatic unsigned char *dst_start;
777f29dbc25Smrgstatic int d2offset = 0, d3offset = 0;
778f29dbc25Smrg
779f29dbc25Smrg#if 0
780f29dbc25Smrgstatic Bool
781f29dbc25SmrgRegionsIntersect(BoxPtr pRcl1, BoxPtr pRcl2, BoxPtr pRclResult)
782f29dbc25Smrg{
783f29dbc25Smrg    pRclResult->x1 = max(pRcl1->x1, pRcl2->x1);
784f29dbc25Smrg    pRclResult->x2 = min(pRcl1->x2, pRcl2->x2);
785f29dbc25Smrg
786f29dbc25Smrg    if (pRclResult->x1 <= pRclResult->x2) {
78704007ebaSmrg        pRclResult->y1 = max(pRcl1->y1, pRcl2->y1);
78804007ebaSmrg        pRclResult->y2 = min(pRcl1->y2, pRcl2->y2);
789f29dbc25Smrg
79004007ebaSmrg        if (pRclResult->y1 <= pRclResult->y2) {
79104007ebaSmrg            return (TRUE);
79204007ebaSmrg        }
793f29dbc25Smrg    }
794f29dbc25Smrg
795f29dbc25Smrg    return (FALSE);
796f29dbc25Smrg}
797f29dbc25Smrg#endif
798f29dbc25Smrg
799f29dbc25Smrgvoid
800f29dbc25SmrgGXSetVideoPosition(int x, int y, int width, int height,
80104007ebaSmrg                   short src_w, short src_h, short drw_w, short drw_h,
80204007ebaSmrg                   int id, int offset, ScrnInfoPtr pScrni)
803f29dbc25Smrg{
804f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
805f29dbc25Smrg    long ystart, xend, yend;
806f29dbc25Smrg    unsigned long lines = 0;
807f29dbc25Smrg    unsigned long y_extra, uv_extra = 0;
808f29dbc25Smrg    unsigned long startAddress;
809f29dbc25Smrg
810f29dbc25Smrg#if 0
811f29dbc25Smrg    BoxRec ovly, display, result;
812f29dbc25Smrg#endif
813f29dbc25Smrg
814f29dbc25Smrg    xend = x + drw_w;
815f29dbc25Smrg    yend = y + drw_h;
816f29dbc25Smrg
817f29dbc25Smrg    /* Take care of panning when panel is present */
818f29dbc25Smrg
819f29dbc25Smrg    startAddress = gfx_get_display_offset();
820f29dbc25Smrg    DeltaY = startAddress / pGeode->Pitch;
821f29dbc25Smrg    DeltaX = startAddress & (pGeode->Pitch - 1);
822f29dbc25Smrg    DeltaX /= (pScrni->bitsPerPixel >> 3);
823f29dbc25Smrg
824f29dbc25Smrg#if 0
825f29dbc25Smrg    /* Thhis code is pretty dang broken - comment it out for now */
826f29dbc25Smrg
827f29dbc25Smrg    if (pGeode->Panel) {
82804007ebaSmrg        ovly.x1 = x;
82904007ebaSmrg        ovly.x2 = x + pGeode->video_dstw;
83004007ebaSmrg        ovly.y1 = y;
83104007ebaSmrg        ovly.y2 = y + pGeode->video_dsth;
83204007ebaSmrg
83304007ebaSmrg        display.x1 = DeltaX;
83404007ebaSmrg        display.x2 = DeltaX + pGeode->FPBX;
83504007ebaSmrg        display.y1 = DeltaY;
83604007ebaSmrg        display.y2 = DeltaY + pGeode->FPBY;
83704007ebaSmrg        x = xend = 0;
83804007ebaSmrg        if (RegionsIntersect(&display, &ovly, &result)) {
83904007ebaSmrg            x = ovly.x1 - DeltaX;
84004007ebaSmrg            xend = ovly.x2 - DeltaX;
84104007ebaSmrg            y = ovly.y1 - DeltaY;
84204007ebaSmrg            yend = ovly.y2 - DeltaY;
84304007ebaSmrg        }
844f29dbc25Smrg    }
845f29dbc25Smrg#endif
846f29dbc25Smrg
847f29dbc25Smrg    /*  TOP CLIPPING */
848f29dbc25Smrg
849f29dbc25Smrg    if (y < 0) {
85004007ebaSmrg        if (src_h < drw_h)
85104007ebaSmrg            lines = (-y) * src_h / drw_h;
85204007ebaSmrg        else
85304007ebaSmrg            lines = (-y);
85404007ebaSmrg        ystart = 0;
85504007ebaSmrg        drw_h += y;
85604007ebaSmrg        y_extra = lines * dstPitch;
85704007ebaSmrg        uv_extra = (lines >> 1) * (dstPitch2);
85804007ebaSmrg    }
85904007ebaSmrg    else {
86004007ebaSmrg        ystart = y;
86104007ebaSmrg        lines = 0;
86204007ebaSmrg        y_extra = 0;
863f29dbc25Smrg    }
864f29dbc25Smrg
865f29dbc25Smrg    GFX(set_video_window(x, ystart, xend - x, yend - ystart));
866f29dbc25Smrg
867f29dbc25Smrg    if ((id == FOURCC_Y800) || (id == FOURCC_I420) || (id == FOURCC_YV12)) {
86804007ebaSmrg        GFX(set_video_yuv_offsets(offset + y_extra,
86904007ebaSmrg                                  offset + d3offset + uv_extra,
87004007ebaSmrg                                  offset + d2offset + uv_extra));
87104007ebaSmrg    }
87204007ebaSmrg    else {
87304007ebaSmrg        GFX(set_video_offset(offset + y_extra));
874f29dbc25Smrg    }
875f29dbc25Smrg}
876f29dbc25Smrg
877f29dbc25Smrg/*----------------------------------------------------------------------------
878f29dbc25Smrg * GXDisplayVideo
879f29dbc25Smrg *
880f29dbc25Smrg * Description	:This function sets up the video registers for playing video
881f29dbc25Smrg * 				It sets up the video format,width, height & position of the
882f29dbc25Smrg *		  		video window ,video offsets( y,u,v) and video pitches(y,u,v)
883f29dbc25Smrg *
884f29dbc25Smrg * Parameters
885f29dbc25Smrg *
886f29dbc25Smrg * Returns		:None
887f29dbc25Smrg *
888f29dbc25Smrg * Comments		:None
889f29dbc25Smrg *----------------------------------------------------------------------------
890f29dbc25Smrg */
891f29dbc25Smrg
892f29dbc25Smrgstatic void
893f29dbc25SmrgGXDisplayVideo(ScrnInfoPtr pScrni,
89404007ebaSmrg               int id,
89504007ebaSmrg               int offset,
89604007ebaSmrg               short width, short height,
89704007ebaSmrg               int pitch,
89804007ebaSmrg               int x1, int y1, int x2, int y2,
89904007ebaSmrg               BoxPtr dstBox, short src_w, short src_h, short drw_w,
90004007ebaSmrg               short drw_h)
901f29dbc25Smrg{
902f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
903f29dbc25Smrg    unsigned long dcfg, misc;
904f29dbc25Smrg
905f29dbc25Smrg    GXAccelSync(pScrni);
906f29dbc25Smrg
907f29dbc25Smrg    /* If the gamma LUT is already loaded with graphics data, then save it
908f29dbc25Smrg     * off
909f29dbc25Smrg     */
910f29dbc25Smrg
911f29dbc25Smrg    if (id != FOURCC_RGB565) {
91204007ebaSmrg        dcfg = gfx_read_vid32(DISPLAY_CONFIG);
91304007ebaSmrg        misc = gfx_read_vid32(MISC);
914f29dbc25Smrg
91504007ebaSmrg        lutflag = (!(misc & 1) && (dcfg & (1 << 21)));
916f29dbc25Smrg
91704007ebaSmrg        if (lutflag)
91804007ebaSmrg            get_gamma_ram(graphics_lut);
919f29dbc25Smrg
92004007ebaSmrg        /* Set the video gamma ram */
92104007ebaSmrg        GFX(set_video_palette(NULL));
922f29dbc25Smrg    }
923f29dbc25Smrg
924f29dbc25Smrg    GFX(set_video_enable(1));
925f29dbc25Smrg
926f29dbc25Smrg    switch (id) {
92704007ebaSmrg    case FOURCC_UYVY:          /* UYVY */
92804007ebaSmrg        GFX(set_video_format(VIDEO_FORMAT_UYVY));
92904007ebaSmrg        GFX(set_video_size(width, height));
93004007ebaSmrg        break;
93104007ebaSmrg    case FOURCC_Y800:          /* Y800 - greyscale - we munge it! */
93204007ebaSmrg    case FOURCC_YV12:          /* YV12 */
93304007ebaSmrg    case FOURCC_I420:          /* I420 */
93404007ebaSmrg        GFX(set_video_format(VIDEO_FORMAT_Y0Y1Y2Y3));
93504007ebaSmrg        GFX(set_video_size(width, height));
93604007ebaSmrg        GFX(set_video_yuv_pitch(dstPitch, dstPitch2));
93704007ebaSmrg        break;
93804007ebaSmrg    case FOURCC_YUY2:          /* YUY2 */
93904007ebaSmrg        GFX(set_video_format(VIDEO_FORMAT_YUYV));
94004007ebaSmrg        GFX(set_video_size(width, height));
94104007ebaSmrg        break;
94204007ebaSmrg    case FOURCC_Y2YU:          /* Y2YU */
94304007ebaSmrg        GFX(set_video_format(VIDEO_FORMAT_Y2YU));
94404007ebaSmrg        GFX(set_video_size(width, height));
94504007ebaSmrg        break;
94604007ebaSmrg    case FOURCC_YVYU:          /* YVYU */
94704007ebaSmrg        GFX(set_video_format(VIDEO_FORMAT_YVYU));
94804007ebaSmrg        GFX(set_video_size(width, height));
94904007ebaSmrg        break;
950f29dbc25Smrg    case FOURCC_RGB565:
95104007ebaSmrg        GFX(set_video_format(VIDEO_FORMAT_RGB));
95204007ebaSmrg        GFX(set_video_size(width, height));
95304007ebaSmrg        break;
954f29dbc25Smrg
955f29dbc25Smrg    }
956f29dbc25Smrg
957f29dbc25Smrg    if (pGeode->Panel) {
95804007ebaSmrg        pGeode->video_x = dstBox->x1;
95904007ebaSmrg        pGeode->video_y = dstBox->y1;
96004007ebaSmrg        pGeode->video_w = width;
96104007ebaSmrg        pGeode->video_h = height;
96204007ebaSmrg        pGeode->video_srcw = src_w;
96304007ebaSmrg        pGeode->video_srch = src_h;
96404007ebaSmrg        pGeode->video_dstw = drw_w;
96504007ebaSmrg        pGeode->video_dsth = drw_h;
96604007ebaSmrg        pGeode->video_offset = offset;
96704007ebaSmrg        pGeode->video_id = id;
96804007ebaSmrg        pGeode->video_scrnptr = pScrni;
969f29dbc25Smrg    }
970f29dbc25Smrg
971f29dbc25Smrg    if ((drw_w >= src_w) && (drw_h >= src_h))
97204007ebaSmrg        GFX(set_video_scale(width, height, drw_w, drw_h));
973f29dbc25Smrg    else if (drw_w < src_w)
97404007ebaSmrg        GFX(set_video_scale(drw_w, height, drw_w, drw_h));
975f29dbc25Smrg    else if (drw_h < src_h)
97604007ebaSmrg        GFX(set_video_scale(width, drw_h, drw_w, drw_h));
977f29dbc25Smrg
978f29dbc25Smrg    GXSetVideoPosition(dstBox->x1, dstBox->y1, width, height, src_w,
97904007ebaSmrg                       src_h, drw_w, drw_h, id, offset, pScrni);
980f29dbc25Smrg}
981f29dbc25Smrg
982f29dbc25Smrg/* Used by LX as well */
983f29dbc25Smrg
984f29dbc25SmrgBool
985f29dbc25SmrgRegionsEqual(RegionPtr A, RegionPtr B)
986f29dbc25Smrg{
987f29dbc25Smrg    int *dataA, *dataB;
988f29dbc25Smrg    int num;
989f29dbc25Smrg
990f29dbc25Smrg    num = REGION_NUM_RECTS(A);
991f29dbc25Smrg    if (num != REGION_NUM_RECTS(B)) {
99204007ebaSmrg        return FALSE;
993f29dbc25Smrg    }
994f29dbc25Smrg
995f29dbc25Smrg    if ((A->extents.x1 != B->extents.x1) ||
99604007ebaSmrg        (A->extents.x2 != B->extents.x2) ||
99704007ebaSmrg        (A->extents.y1 != B->extents.y1) || (A->extents.y2 != B->extents.y2))
99804007ebaSmrg        return FALSE;
999f29dbc25Smrg
100004007ebaSmrg    dataA = (int *) REGION_RECTS(A);
100104007ebaSmrg    dataB = (int *) REGION_RECTS(B);
1002f29dbc25Smrg
1003f29dbc25Smrg    while (num--) {
100404007ebaSmrg        if ((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
100504007ebaSmrg            return FALSE;
1006f29dbc25Smrg
100704007ebaSmrg        dataA += 2;
100804007ebaSmrg        dataB += 2;
1009f29dbc25Smrg    }
1010f29dbc25Smrg
1011f29dbc25Smrg    return TRUE;
1012f29dbc25Smrg}
1013f29dbc25Smrg
1014f29dbc25Smrg/*----------------------------------------------------------------------------
1015f29dbc25Smrg * GXPutImage	:This function writes a single frame of video into a
1016f29dbc25Smrg * 				drawable. The position and size of the source rectangle is
1017f29dbc25Smrg * 				specified by src_x,src_y, src_w and src_h. This data is
1018f29dbc25Smrg * 				stored in a system memory buffer at buf. The position and
1019f29dbc25Smrg * 				size of the destination rectangle is specified by drw_x,
1020f29dbc25Smrg * 				drw_y,drw_w,drw_h.The data is in the format indicated by the
1021f29dbc25Smrg * 				image descriptor and represents a source of size width by
1022f29dbc25Smrg * 				height.  If sync is TRUE the driver should not return from
1023f29dbc25Smrg * 				this function until it is through reading the data from buf.
1024f29dbc25Smrg * 				Returning when sync is TRUE indicates that it is safe for the
1025f29dbc25Smrg * 				data at buf to be replaced,freed, or modified.
1026f29dbc25Smrg *
1027f29dbc25Smrg * Parameters.
1028f29dbc25Smrg *
1029f29dbc25Smrg * Returns		:None
1030f29dbc25Smrg *
1031f29dbc25Smrg * Comments		:None
1032f29dbc25Smrg *----------------------------------------------------------------------------
1033f29dbc25Smrg */
1034f29dbc25Smrg
1035f29dbc25Smrgstatic int
1036f29dbc25SmrgGXPutImage(ScrnInfoPtr pScrni,
103704007ebaSmrg           short src_x, short src_y,
103804007ebaSmrg           short drw_x, short drw_y,
103904007ebaSmrg           short src_w, short src_h,
104004007ebaSmrg           short drw_w, short drw_h,
104104007ebaSmrg           int id, unsigned char *buf,
104204007ebaSmrg           short width, short height, Bool sync, RegionPtr clipBoxes,
104304007ebaSmrg           pointer data, DrawablePtr pDraw)
1044f29dbc25Smrg{
1045f29dbc25Smrg    GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
1046f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1047f29dbc25Smrg    int new_h;
1048f29dbc25Smrg
1049f29dbc25Smrg#if REINIT
1050f29dbc25Smrg    BOOL ReInitVideo = FALSE;
1051f29dbc25Smrg    static BOOL DoReinitAgain = 0;
1052f29dbc25Smrg#endif
1053f29dbc25Smrg
1054f29dbc25Smrg#if XV_PROFILE
1055f29dbc25Smrg    long oldtime, newtime;
1056f29dbc25Smrg
1057f29dbc25Smrg    UpdateCurrentTime();
1058f29dbc25Smrg    oldtime = currentTime.milliseconds;
1059f29dbc25Smrg#endif
1060f29dbc25Smrg
1061f29dbc25Smrg#if REINIT
1062f29dbc25Smrg/* update cliplist */
1063f29dbc25Smrg    if (!RegionsEqual(&pPriv->clip, clipBoxes)) {
106404007ebaSmrg        ReInitVideo = TRUE;
1065f29dbc25Smrg    }
1066f29dbc25Smrg
1067f29dbc25Smrg    if (DoReinitAgain)
106804007ebaSmrg        ReInitVideo = TRUE;
1069f29dbc25Smrg
1070f29dbc25Smrg    if (ReInitVideo) {
107104007ebaSmrg        DEBUGMSG(1, (0, X_NONE, "Regional Not Equal - Init\n"));
1072f29dbc25Smrg#endif
107304007ebaSmrg        DoReinitAgain = ~DoReinitAgain;
107404007ebaSmrg        if (drw_w > 16384)
107504007ebaSmrg            drw_w = 16384;
107604007ebaSmrg
107704007ebaSmrg        /* Clip */
107804007ebaSmrg        Bx1 = src_x;
107904007ebaSmrg        Bx2 = src_x + src_w;
108004007ebaSmrg        By1 = src_y;
108104007ebaSmrg        By2 = src_y + src_h;
108204007ebaSmrg
108304007ebaSmrg        if ((Bx1 >= Bx2) || (By1 >= By2))
108404007ebaSmrg            return Success;
108504007ebaSmrg
108604007ebaSmrg        dstBox.x1 = drw_x;
108704007ebaSmrg        dstBox.x2 = drw_x + drw_w;
108804007ebaSmrg        dstBox.y1 = drw_y;
108904007ebaSmrg        dstBox.y2 = drw_y + drw_h;
109004007ebaSmrg
109104007ebaSmrg        dstBox.x1 -= pScrni->frameX0;
109204007ebaSmrg        dstBox.x2 -= pScrni->frameX0;
109304007ebaSmrg        dstBox.y1 -= pScrni->frameY0;
109404007ebaSmrg        dstBox.y2 -= pScrni->frameY0;
109504007ebaSmrg
109604007ebaSmrg        switch (id) {
109704007ebaSmrg        case FOURCC_YV12:
109804007ebaSmrg        case FOURCC_I420:
109904007ebaSmrg            srcPitch = (width + 3) & ~3;        /* of luma */
110004007ebaSmrg            dstPitch = (width + 31) & ~31;
110104007ebaSmrg
110204007ebaSmrg            s2offset = srcPitch * height;
110304007ebaSmrg            d2offset = dstPitch * height;
110404007ebaSmrg
110504007ebaSmrg            srcPitch2 = ((width >> 1) + 3) & ~3;
110604007ebaSmrg            dstPitch2 = ((width >> 1) + 15) & ~15;
110704007ebaSmrg
110804007ebaSmrg            s3offset = (srcPitch2 * (height >> 1)) + s2offset;
110904007ebaSmrg            d3offset = (dstPitch2 * (height >> 1)) + d2offset;
111004007ebaSmrg
111104007ebaSmrg            new_h = dstPitch * height;  /* Y */
111204007ebaSmrg            new_h += (dstPitch2 * height);      /* U+V */
111304007ebaSmrg            new_h += pGeode->Pitch - 1;
111404007ebaSmrg            new_h /= pGeode->Pitch;
111504007ebaSmrg            break;
111604007ebaSmrg        case FOURCC_UYVY:
111704007ebaSmrg        case FOURCC_YUY2:
111804007ebaSmrg        case FOURCC_Y800:
111904007ebaSmrg        case FOURCC_RGB565:
112004007ebaSmrg        default:
112104007ebaSmrg            dstPitch = ((width << 1) + 3) & ~3;
112204007ebaSmrg            srcPitch = (width << 1);
112304007ebaSmrg            new_h = ((dstPitch * height) + pGeode->Pitch - 1) / pGeode->Pitch;
112404007ebaSmrg            break;
112504007ebaSmrg        }
1126f29dbc25Smrg#if DBUF
112704007ebaSmrg        if (pPriv->doubleBuffer)
112804007ebaSmrg            new_h <<= 1;
1129f29dbc25Smrg#endif
1130f29dbc25Smrg
113104007ebaSmrg        if (!(pPriv->offset = GXAllocateMemory(pScrni, &pPriv->area, new_h))) {
113204007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
113304007ebaSmrg                       "Could not allocate area of size %d\n", new_h);
113404007ebaSmrg            return BadAlloc;
113504007ebaSmrg        }
1136f29dbc25Smrg
113704007ebaSmrg        /* copy data */
113804007ebaSmrg        top = By1;
113904007ebaSmrg        left = Bx1 & ~1;
114004007ebaSmrg        npixels = ((Bx2 + 1) & ~1) - left;
1141f29dbc25Smrg
114204007ebaSmrg        switch (id) {
114304007ebaSmrg        case FOURCC_YV12:
114404007ebaSmrg        case FOURCC_I420:
114504007ebaSmrg        {
114604007ebaSmrg            int tmp;
1147f29dbc25Smrg
114804007ebaSmrg            top &= ~1;
1149f29dbc25Smrg
115004007ebaSmrg            offset = pPriv->offset + (top * dstPitch);
1151f29dbc25Smrg
1152f29dbc25Smrg#if DBUF
115304007ebaSmrg            if (pPriv->doubleBuffer && pPriv->currentBuffer)
115404007ebaSmrg                offset += (new_h >> 1) * pGeode->Pitch;
1155f29dbc25Smrg#endif
115604007ebaSmrg            dst_start = pGeode->FBBase + offset + left;
115704007ebaSmrg            tmp = ((top >> 1) * srcPitch2) + (left >> 1);
115804007ebaSmrg            s2offset += tmp;
115904007ebaSmrg            s3offset += tmp;
116004007ebaSmrg            if (id == FOURCC_I420) {
116104007ebaSmrg                tmp = s2offset;
116204007ebaSmrg                s2offset = s3offset;
116304007ebaSmrg                s3offset = tmp;
116404007ebaSmrg            }
116504007ebaSmrg            nlines = ((By2 + 1) & ~1) - top;
116604007ebaSmrg        }
116704007ebaSmrg            break;
116804007ebaSmrg        case FOURCC_UYVY:
116904007ebaSmrg        case FOURCC_YUY2:
117004007ebaSmrg        case FOURCC_Y800:
117104007ebaSmrg        case FOURCC_RGB565:
117204007ebaSmrg        default:
117304007ebaSmrg            left <<= 1;
117404007ebaSmrg            buf += (top * srcPitch) + left;
117504007ebaSmrg            nlines = By2 - top;
117604007ebaSmrg            offset = (pPriv->offset) + (top * dstPitch);
1177f29dbc25Smrg
1178f29dbc25Smrg#if DBUF
117904007ebaSmrg            if (pPriv->doubleBuffer && pPriv->currentBuffer)
118004007ebaSmrg                offset += (new_h >> 1) * pGeode->Pitch;
1181f29dbc25Smrg#endif
118204007ebaSmrg            dst_start = pGeode->FBBase + offset + left;
118304007ebaSmrg            break;
118404007ebaSmrg        }
118504007ebaSmrg        s1offset = (top * srcPitch) + left;
1186f29dbc25Smrg#if REINIT
118704007ebaSmrg        /* update cliplist */
118804007ebaSmrg        REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes);
1189f29dbc25Smrg
119004007ebaSmrg        if (pPriv->colorKeyMode == 0) {
119104007ebaSmrg            xf86XVFillKeyHelper(pScrni->pScreen, pPriv->colorKey, clipBoxes);
119204007ebaSmrg        }
1193f29dbc25Smrg
119404007ebaSmrg        GXDisplayVideo(pScrni, id, offset, width, height, dstPitch,
119504007ebaSmrg                       Bx1, By1, Bx2, By2, &dstBox, src_w, src_h, drw_w, drw_h);
1196f29dbc25Smrg    }
1197f29dbc25Smrg#endif
1198f29dbc25Smrg    switch (id) {
1199f29dbc25Smrg    case FOURCC_Y800:
120004007ebaSmrg        /* This is shared between LX and GX, so it lives in amd_common.c */
120104007ebaSmrg        GeodeCopyGreyscale(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
120204007ebaSmrg        break;
1203f29dbc25Smrg    case FOURCC_YV12:
1204f29dbc25Smrg    case FOURCC_I420:
120504007ebaSmrg        GXCopyData420(buf + s1offset, dst_start, srcPitch, dstPitch, nlines,
120604007ebaSmrg                      npixels);
120704007ebaSmrg        GXCopyData420(buf + s2offset, dst_start + d2offset, srcPitch2,
120804007ebaSmrg                      dstPitch2, nlines >> 1, npixels >> 1);
120904007ebaSmrg        GXCopyData420(buf + s3offset, dst_start + d3offset, srcPitch2,
121004007ebaSmrg                      dstPitch2, nlines >> 1, npixels >> 1);
121104007ebaSmrg        break;
1212f29dbc25Smrg    case FOURCC_UYVY:
1213f29dbc25Smrg    case FOURCC_YUY2:
1214f29dbc25Smrg    case FOURCC_RGB565:
1215f29dbc25Smrg    default:
121604007ebaSmrg        GXCopyData422(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
121704007ebaSmrg        break;
1218f29dbc25Smrg    }
1219f29dbc25Smrg#if !REINIT
1220f29dbc25Smrg    /* update cliplist */
1221f29dbc25Smrg    REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes);
1222f29dbc25Smrg    if (pPriv->colorKeyMode == 0) {
122304007ebaSmrg        /* draw these */
122404007ebaSmrg        XAAFillSolidRects(pScrni, pPriv->colorKey, GXcopy, ~0,
122504007ebaSmrg                          REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes));
1226f29dbc25Smrg    }
1227f29dbc25Smrg
1228f29dbc25Smrg    GXDisplayVideo(pScrni, id, offset, width, height, dstPitch,
122904007ebaSmrg                   Bx1, By1, Bx2, By2, &dstBox, src_w, src_h, drw_w, drw_h);
1230f29dbc25Smrg#endif
1231f29dbc25Smrg
1232f29dbc25Smrg#if XV_PROFILE
1233f29dbc25Smrg    UpdateCurrentTime();
1234f29dbc25Smrg    newtime = currentTime.milliseconds;
1235f29dbc25Smrg    DEBUGMSG(1, (0, X_NONE, "PI %d\n", newtime - oldtime));
1236f29dbc25Smrg#endif
1237f29dbc25Smrg
1238f29dbc25Smrg#if DBUF
1239f29dbc25Smrg    pPriv->currentBuffer ^= 1;
1240f29dbc25Smrg#endif
1241f29dbc25Smrg
1242f29dbc25Smrg    pPriv->videoStatus = CLIENT_VIDEO_ON;
1243f29dbc25Smrg    pGeode->OverlayON = TRUE;
1244f29dbc25Smrg    return Success;
1245f29dbc25Smrg}
1246f29dbc25Smrg
1247f29dbc25Smrg/*----------------------------------------------------------------------------
1248f29dbc25Smrg * GXQueryImageAttributes
1249f29dbc25Smrg *
1250f29dbc25Smrg * Description	:This function is called to let the driver specify how data
1251f29dbc25Smrg *				 for a particular image of size width by height should be
1252f29dbc25Smrg *				 stored.
1253f29dbc25Smrg *
1254f29dbc25Smrg * Parameters.
1255f29dbc25Smrg *		pScrni	:Screen handler pointer having screen information.
1256f29dbc25Smrg *		id		:Id for the video format
1257f29dbc25Smrg *		width	:width  of the image (can be modified by the driver)
1258f29dbc25Smrg *		height	:height of the image (can be modified by the driver)
1259f29dbc25Smrg * Returns		: Size of the memory required for storing this image
1260f29dbc25Smrg *
1261f29dbc25Smrg * Comments		:None
1262f29dbc25Smrg *
1263f29dbc25Smrg *----------------------------------------------------------------------------
1264f29dbc25Smrg */
1265f29dbc25Smrg
1266f29dbc25Smrgint
1267f29dbc25SmrgGeodeQueryImageAttributes(ScrnInfoPtr pScrni,
126804007ebaSmrg                          int id, unsigned short *w, unsigned short *h,
126904007ebaSmrg                          int *pitches, int *offsets)
1270f29dbc25Smrg{
1271f29dbc25Smrg    int size;
1272f29dbc25Smrg    int tmp;
1273f29dbc25Smrg
1274f29dbc25Smrg    DEBUGMSG(0, (0, X_NONE, "QueryImageAttributes %X\n", id));
1275f29dbc25Smrg
1276f29dbc25Smrg    if (*w > 1024)
127704007ebaSmrg        *w = 1024;
1278f29dbc25Smrg    if (*h > 1024)
127904007ebaSmrg        *h = 1024;
1280f29dbc25Smrg
1281f29dbc25Smrg    *w = (*w + 1) & ~1;
1282f29dbc25Smrg    if (offsets)
128304007ebaSmrg        offsets[0] = 0;
1284f29dbc25Smrg
1285f29dbc25Smrg    switch (id) {
1286f29dbc25Smrg    case FOURCC_YV12:
1287f29dbc25Smrg    case FOURCC_I420:
128804007ebaSmrg        *h = (*h + 1) & ~1;
128904007ebaSmrg        size = (*w + 3) & ~3;
129004007ebaSmrg        if (pitches)
129104007ebaSmrg            pitches[0] = size;
129204007ebaSmrg
129304007ebaSmrg        size *= *h;
129404007ebaSmrg        if (offsets)
129504007ebaSmrg            offsets[1] = size;
129604007ebaSmrg
129704007ebaSmrg        tmp = ((*w >> 1) + 3) & ~3;
129804007ebaSmrg        if (pitches)
129904007ebaSmrg            pitches[1] = pitches[2] = tmp;
130004007ebaSmrg
130104007ebaSmrg        tmp *= (*h >> 1);
130204007ebaSmrg        size += tmp;
130304007ebaSmrg        if (offsets)
130404007ebaSmrg            offsets[2] = size;
130504007ebaSmrg
130604007ebaSmrg        size += tmp;
130704007ebaSmrg        break;
1308f29dbc25Smrg    case FOURCC_UYVY:
1309f29dbc25Smrg    case FOURCC_YUY2:
1310f29dbc25Smrg    case FOURCC_Y800:
1311f29dbc25Smrg    default:
131204007ebaSmrg        size = *w << 1;
131304007ebaSmrg        if (pitches)
131404007ebaSmrg            pitches[0] = size;
1315f29dbc25Smrg
131604007ebaSmrg        size *= *h;
131704007ebaSmrg        break;
1318f29dbc25Smrg    }
1319f29dbc25Smrg    return size;
1320f29dbc25Smrg}
1321f29dbc25Smrg
1322f29dbc25Smrgstatic void
132304007ebaSmrgGXBlockHandler(BLOCKHANDLER_ARGS_DECL)
1324f29dbc25Smrg{
132504007ebaSmrg    SCREEN_PTR(arg);
132604007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
1327f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1328f29dbc25Smrg    GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni);
1329f29dbc25Smrg
1330f29dbc25Smrg    pScrn->BlockHandler = pGeode->BlockHandler;
133104007ebaSmrg    (*pScrn->BlockHandler) (BLOCKHANDLER_ARGS);
1332f29dbc25Smrg    pScrn->BlockHandler = GXBlockHandler;
1333f29dbc25Smrg
1334f29dbc25Smrg    if (pPriv->videoStatus & TIMER_MASK) {
133504007ebaSmrg        GXAccelSync(pScrni);
133604007ebaSmrg        UpdateCurrentTime();
133704007ebaSmrg        if (pPriv->videoStatus & OFF_TIMER) {
133804007ebaSmrg            if (pPriv->offTime < currentTime.milliseconds) {
133904007ebaSmrg                GFX(set_video_enable(0));
134004007ebaSmrg
134104007ebaSmrg                /* If we have saved graphics LUT data - restore it */
134204007ebaSmrg                /* Otherwise, turn bypass on */
134304007ebaSmrg
134404007ebaSmrg                if (lutflag)
134504007ebaSmrg                    GFX(set_graphics_palette(graphics_lut));
134604007ebaSmrg                else
134704007ebaSmrg                    GFX(set_video_palette_bypass(1));
134804007ebaSmrg
134904007ebaSmrg                lutflag = 0;
135004007ebaSmrg
135104007ebaSmrg                pPriv->videoStatus = FREE_TIMER;
135204007ebaSmrg                pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
135304007ebaSmrg            }
135404007ebaSmrg        }
135504007ebaSmrg        else {                  /* FREE_TIMER */
135604007ebaSmrg            if (pPriv->freeTime < currentTime.milliseconds) {
135704007ebaSmrg
135804007ebaSmrg                if (pPriv->area) {
1359f29dbc25Smrg#ifdef XF86EXA
136004007ebaSmrg                    if (pGeode->useEXA)
136104007ebaSmrg                        exaOffscreenFree(pScrn, pPriv->area);
1362f29dbc25Smrg#endif
136304007ebaSmrg                    if (!pGeode->useEXA)
136404007ebaSmrg                        xf86FreeOffscreenArea(pPriv->area);
1365f29dbc25Smrg
136604007ebaSmrg                    pPriv->area = NULL;
136704007ebaSmrg                }
1368f29dbc25Smrg
136904007ebaSmrg                pPriv->videoStatus = 0;
137004007ebaSmrg            }
137104007ebaSmrg        }
1372f29dbc25Smrg    }
1373f29dbc25Smrg}
1374f29dbc25Smrg
1375f29dbc25Smrg/****************** Offscreen stuff ***************/
1376f29dbc25Smrg
137704007ebaSmrgtypedef struct {
1378f29dbc25Smrg    void *area;
1379f29dbc25Smrg    int offset;
1380f29dbc25Smrg    Bool isOn;
1381f29dbc25Smrg} OffscreenPrivRec, *OffscreenPrivPtr;
1382f29dbc25Smrg
1383f29dbc25Smrg/*----------------------------------------------------------------------------
1384f29dbc25Smrg * GXAllocateSurface
1385f29dbc25Smrg *
1386f29dbc25Smrg * Description	:This function allocates an area of w by h in the offscreen
1387f29dbc25Smrg *
1388f29dbc25Smrg * Parameters.
1389f29dbc25Smrg *		pScrni	:Screen handler pointer having screen information.
1390f29dbc25Smrg *
1391f29dbc25Smrg * Returns		:None
1392f29dbc25Smrg *
1393f29dbc25Smrg * Comments		:None
1394f29dbc25Smrg *----------------------------------------------------------------------------
1395f29dbc25Smrg */
1396f29dbc25Smrgstatic int
1397f29dbc25SmrgGXAllocateSurface(ScrnInfoPtr pScrni,
139804007ebaSmrg                  int id, unsigned short w, unsigned short h,
139904007ebaSmrg                  XF86SurfacePtr surface)
1400f29dbc25Smrg{
1401f29dbc25Smrg    void *area = NULL;
1402f29dbc25Smrg    int pitch, fbpitch, numlines;
1403f29dbc25Smrg    OffscreenPrivRec *pPriv;
1404f29dbc25Smrg
1405f29dbc25Smrg    if ((w > 1024) || (h > 1024))
140604007ebaSmrg        return BadAlloc;
1407f29dbc25Smrg
1408f29dbc25Smrg    w = (w + 1) & ~1;
1409f29dbc25Smrg    pitch = ((w << 1) + 15) & ~15;
1410f29dbc25Smrg    fbpitch = pScrni->bitsPerPixel * pScrni->displayWidth >> 3;
1411f29dbc25Smrg    numlines = ((pitch * h) + fbpitch - 1) / fbpitch;
1412f29dbc25Smrg
1413f29dbc25Smrg    if (!(offset = GXAllocateMemory(pScrni, &area, numlines)))
141404007ebaSmrg        return BadAlloc;
1415f29dbc25Smrg
1416f29dbc25Smrg    surface->width = w;
1417f29dbc25Smrg    surface->height = h;
1418f29dbc25Smrg
1419170d5fdcSmrg    if (!(surface->pitches = malloc(sizeof(int))))
142004007ebaSmrg        return BadAlloc;
1421f29dbc25Smrg
1422170d5fdcSmrg    if (!(surface->offsets = malloc(sizeof(int)))) {
142304007ebaSmrg        free(surface->pitches);
142404007ebaSmrg        return BadAlloc;
1425f29dbc25Smrg    }
1426f29dbc25Smrg
1427170d5fdcSmrg    if (!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
142804007ebaSmrg        free(surface->pitches);
142904007ebaSmrg        free(surface->offsets);
143004007ebaSmrg        return BadAlloc;
1431f29dbc25Smrg    }
1432f29dbc25Smrg
1433f29dbc25Smrg    pPriv->area = area;
1434f29dbc25Smrg    pPriv->offset = offset;
1435f29dbc25Smrg
1436f29dbc25Smrg    pPriv->isOn = FALSE;
1437f29dbc25Smrg
1438f29dbc25Smrg    surface->pScrn = pScrni;
1439f29dbc25Smrg    surface->id = id;
1440f29dbc25Smrg    surface->pitches[0] = pitch;
1441f29dbc25Smrg    surface->offsets[0] = offset;
1442f29dbc25Smrg    surface->devPrivate.ptr = (pointer) pPriv;
1443f29dbc25Smrg
1444f29dbc25Smrg    return Success;
1445f29dbc25Smrg}
1446f29dbc25Smrg
1447f29dbc25Smrgstatic int
1448f29dbc25SmrgGXStopSurface(XF86SurfacePtr surface)
1449f29dbc25Smrg{
1450f29dbc25Smrg    OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr;
1451f29dbc25Smrg
1452f29dbc25Smrg    if (pPriv->isOn) {
145304007ebaSmrg        pPriv->isOn = FALSE;
1454f29dbc25Smrg    }
1455f29dbc25Smrg
1456f29dbc25Smrg    return Success;
1457f29dbc25Smrg}
1458f29dbc25Smrg
1459f29dbc25Smrgstatic int
1460f29dbc25SmrgGXFreeSurface(XF86SurfacePtr surface)
1461f29dbc25Smrg{
1462f29dbc25Smrg    OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr;
1463f29dbc25Smrg
1464f29dbc25Smrg    if (pPriv->isOn)
146504007ebaSmrg        GXStopSurface(surface);
1466f29dbc25Smrg
1467f29dbc25Smrg    xf86FreeOffscreenArea(pPriv->area);
1468170d5fdcSmrg    free(surface->pitches);
1469170d5fdcSmrg    free(surface->offsets);
1470170d5fdcSmrg    free(surface->devPrivate.ptr);
1471f29dbc25Smrg
1472f29dbc25Smrg    return Success;
1473f29dbc25Smrg}
1474f29dbc25Smrg
1475f29dbc25Smrgstatic int
147604007ebaSmrgGXGetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 *value)
1477f29dbc25Smrg{
1478f29dbc25Smrg    return GXGetPortAttribute(pScrni, attribute, value,
147904007ebaSmrg                              (pointer) (GET_PORT_PRIVATE(pScrni)));
1480f29dbc25Smrg}
1481f29dbc25Smrg
1482f29dbc25Smrgstatic int
1483f29dbc25SmrgGXSetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 value)
1484f29dbc25Smrg{
1485f29dbc25Smrg    return GXSetPortAttribute(pScrni, attribute, value,
148604007ebaSmrg                              (pointer) (GET_PORT_PRIVATE(pScrni)));
1487f29dbc25Smrg}
1488f29dbc25Smrg
1489f29dbc25Smrgstatic int
1490f29dbc25SmrgGXDisplaySurface(XF86SurfacePtr surface,
149104007ebaSmrg                 short src_x, short src_y,
149204007ebaSmrg                 short drw_x, short drw_y,
149304007ebaSmrg                 short src_w, short src_h, short drw_w, short drw_h,
149404007ebaSmrg                 RegionPtr clipBoxes)
1495f29dbc25Smrg{
1496f29dbc25Smrg    OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr;
1497f29dbc25Smrg    ScrnInfoPtr pScrni = surface->pScrn;
1498f29dbc25Smrg    GeodePortPrivRec *portPriv = GET_PORT_PRIVATE(pScrni);
1499f29dbc25Smrg    INT32 x1, y1, x2, y2;
1500f29dbc25Smrg    BoxRec dstBox;
1501f29dbc25Smrg
1502f29dbc25Smrg    DEBUGMSG(0, (0, X_NONE, "DisplaySuface\n"));
1503f29dbc25Smrg    x1 = src_x;
1504f29dbc25Smrg    x2 = src_x + src_w;
1505f29dbc25Smrg    y1 = src_y;
1506f29dbc25Smrg    y2 = src_y + src_h;
1507f29dbc25Smrg
1508f29dbc25Smrg    dstBox.x1 = drw_x;
1509f29dbc25Smrg    dstBox.x2 = drw_x + drw_w;
1510f29dbc25Smrg    dstBox.y1 = drw_y;
1511f29dbc25Smrg    dstBox.y2 = drw_y + drw_h;
1512f29dbc25Smrg
1513f29dbc25Smrg    if ((x1 >= x2) || (y1 >= y2))
151404007ebaSmrg        return Success;
1515f29dbc25Smrg
1516f29dbc25Smrg    dstBox.x1 -= pScrni->frameX0;
1517f29dbc25Smrg    dstBox.x2 -= pScrni->frameX0;
1518f29dbc25Smrg    dstBox.y1 -= pScrni->frameY0;
1519f29dbc25Smrg    dstBox.y2 -= pScrni->frameY0;
1520f29dbc25Smrg
1521f29dbc25Smrg    xf86XVFillKeyHelper(pScrni->pScreen, portPriv->colorKey, clipBoxes);
1522f29dbc25Smrg
1523f29dbc25Smrg    GXDisplayVideo(pScrni, surface->id, surface->offsets[0],
152404007ebaSmrg                   surface->width, surface->height, surface->pitches[0],
152504007ebaSmrg                   x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
1526f29dbc25Smrg
1527f29dbc25Smrg    pPriv->isOn = TRUE;
1528f29dbc25Smrg    if (portPriv->videoStatus & CLIENT_VIDEO_ON) {
152904007ebaSmrg        REGION_EMPTY(pScrni->pScreen, &portPriv->clip);
153004007ebaSmrg        UpdateCurrentTime();
153104007ebaSmrg        portPriv->videoStatus = FREE_TIMER;
153204007ebaSmrg        portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
1533f29dbc25Smrg    }
1534f29dbc25Smrg
1535f29dbc25Smrg    return Success;
1536f29dbc25Smrg}
1537f29dbc25Smrg
1538f29dbc25Smrg/*----------------------------------------------------------------------------
1539f29dbc25Smrg * GXInitOffscreenImages
1540f29dbc25Smrg *
1541f29dbc25Smrg * Description	:This function sets up the offscreen memory management. It
1542f29dbc25Smrg * 				fills in the XF86OffscreenImagePtr structure with functions to
1543f29dbc25Smrg * 				handle offscreen memory operations.
1544f29dbc25Smrg *
1545f29dbc25Smrg * Parameters.
1546f29dbc25Smrg *		pScrn	:Screen handler pointer having screen information.
1547f29dbc25Smrg *
1548f29dbc25Smrg * Returns		: None
1549f29dbc25Smrg *
1550f29dbc25Smrg * Comments		:None
1551f29dbc25Smrg *----------------------------------------------------------------------------
1552f29dbc25Smrg */
1553f29dbc25Smrgstatic void
1554f29dbc25SmrgGXInitOffscreenImages(ScreenPtr pScrn)
1555f29dbc25Smrg{
1556f29dbc25Smrg    XF86OffscreenImagePtr offscreenImages;
1557f29dbc25Smrg
1558f29dbc25Smrg    /* need to free this someplace */
1559170d5fdcSmrg    if (!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec))))
156004007ebaSmrg        return;
1561f29dbc25Smrg
1562f29dbc25Smrg    offscreenImages[0].image = &Images[0];
1563f29dbc25Smrg    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
1564f29dbc25Smrg    offscreenImages[0].alloc_surface = GXAllocateSurface;
1565f29dbc25Smrg    offscreenImages[0].free_surface = GXFreeSurface;
1566f29dbc25Smrg    offscreenImages[0].display = GXDisplaySurface;
1567f29dbc25Smrg    offscreenImages[0].stop = GXStopSurface;
1568f29dbc25Smrg    offscreenImages[0].setAttribute = GXSetSurfaceAttribute;
1569f29dbc25Smrg    offscreenImages[0].getAttribute = GXGetSurfaceAttribute;
1570f29dbc25Smrg    offscreenImages[0].max_width = 1024;
1571f29dbc25Smrg    offscreenImages[0].max_height = 1024;
1572f29dbc25Smrg    offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
1573f29dbc25Smrg    offscreenImages[0].attributes = Attributes;
1574f29dbc25Smrg
1575f29dbc25Smrg    xf86XVRegisterOffscreenImages(pScrn, offscreenImages, 1);
1576f29dbc25Smrg}
1577f29dbc25Smrg
157804007ebaSmrg#endif                          /* !XvExtension */
1579