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
4600be8644Schristos#include "xorg-server.h"
4700be8644Schristos
48f29dbc25Smrg#include "xf86.h"
49f29dbc25Smrg#include "xf86_OSproc.h"
50f29dbc25Smrg#include "compiler.h"
5100be8644Schristos// #include "xf86PciInfo.h"
52f29dbc25Smrg#include "xf86Pci.h"
53f29dbc25Smrg#include "xf86fbman.h"
54f29dbc25Smrg#include "regionstr.h"
55f29dbc25Smrg
56f29dbc25Smrg#include "geode.h"
57f29dbc25Smrg#include "xf86xv.h"
58f29dbc25Smrg#include <X11/extensions/Xv.h>
5904007ebaSmrg#ifdef HAVE_XAA_H
60f29dbc25Smrg#include "xaa.h"
61f29dbc25Smrg#include "xaalocal.h"
6204007ebaSmrg#endif
63f29dbc25Smrg#include "dixstruct.h"
64f29dbc25Smrg#include "fourcc.h"
65f29dbc25Smrg#include "geode_fourcc.h"
66f29dbc25Smrg
6704007ebaSmrg#define OFF_DELAY 		200     /* milliseconds */
68f29dbc25Smrg#define FREE_DELAY 		60000
69f29dbc25Smrg
70f29dbc25Smrg#define OFF_TIMER 		0x01
71f29dbc25Smrg#define FREE_TIMER		0x02
72f29dbc25Smrg#define CLIENT_VIDEO_ON	0x04
73f29dbc25Smrg
74f29dbc25Smrg#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
75f29dbc25Smrg#define XV_PROFILE 		0
76f29dbc25Smrg#define REINIT  		1
77f29dbc25Smrg
78f29dbc25Smrg#ifndef XvExtension
79f29dbc25Smrg#error "It didn't work!"
80f29dbc25Smrgvoid
81f29dbc25SmrgGXInitVideo(ScreenPtr pScrn)
82f29dbc25Smrg{
83f29dbc25Smrg}
84f29dbc25Smrg
85f29dbc25Smrgvoid
86f29dbc25SmrgGXResetVideo(ScrnInfoPtr pScrni)
87f29dbc25Smrg{
88f29dbc25Smrg}
89f29dbc25Smrg
90f29dbc25Smrgvoid
91f29dbc25SmrgGXSetVideoPosition()
92f29dbc25Smrg{
93f29dbc25Smrg}
94f29dbc25Smrg#else
95f29dbc25Smrg
96f29dbc25Smrg#define DBUF 1
97f29dbc25Smrgvoid GXResetVideo(ScrnInfoPtr pScrni);
98f29dbc25Smrgstatic XF86VideoAdaptorPtr GXSetupImageVideo(ScreenPtr);
99f29dbc25Smrgstatic void GXInitOffscreenImages(ScreenPtr);
100f29dbc25Smrgstatic void GXStopVideo(ScrnInfoPtr, pointer, Bool);
101f29dbc25Smrgstatic int GXSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
102f29dbc25Smrgstatic int GXGetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
103f29dbc25Smrgstatic void GXQueryBestSize(ScrnInfoPtr, Bool,
10404007ebaSmrg                            short, short, short, short, unsigned int *,
10504007ebaSmrg                            unsigned int *, pointer);
106f29dbc25Smrgstatic int GXPutImage(ScrnInfoPtr, short, short, short, short, short, short,
10704007ebaSmrg                      short, short, int, unsigned char *, short, short, Bool,
10804007ebaSmrg                      RegionPtr, pointer, DrawablePtr pDraw);
109f29dbc25Smrg
11004007ebaSmrgstatic void GXBlockHandler(BLOCKHANDLER_ARGS_DECL);
111f29dbc25Smrgvoid GXSetVideoPosition(int x, int y, int width, int height,
11204007ebaSmrg                        short src_w, short src_h, short drw_w,
11304007ebaSmrg                        short drw_h, int id, int offset, ScrnInfoPtr pScrni);
114f29dbc25Smrg
115f29dbc25Smrgextern void GXAccelSync(ScrnInfoPtr pScrni);
116f29dbc25Smrg
117ad01e365Sjoergextern int DeltaX, DeltaY;
118f29dbc25Smrg
119f29dbc25Smrgunsigned long graphics_lut[256];
120f29dbc25Smrgstatic int lutflag = 0;
121f29dbc25Smrg
122f29dbc25Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
123f29dbc25Smrg
124f29dbc25Smrgstatic Atom xvColorKey, xvColorKeyMode, xvFilter
125f29dbc25Smrg#if DBUF
12604007ebaSmrg, xvDoubleBuffer
127f29dbc25Smrg#endif
12804007ebaSmrg;
129f29dbc25Smrg
130f29dbc25Smrg#define PALETTE_ADDRESS   0x038
131f29dbc25Smrg#define PALETTE_DATA      0x040
132f29dbc25Smrg#define DISPLAY_CONFIG    0x008
133f29dbc25Smrg#define MISC              0x050
134f29dbc25Smrg
135f29dbc25Smrgstatic void
136f29dbc25Smrgget_gamma_ram(unsigned long *lut)
137f29dbc25Smrg{
138f29dbc25Smrg
139f29dbc25Smrg    int i;
140f29dbc25Smrg
141f29dbc25Smrg    gfx_write_vid32(PALETTE_ADDRESS, 0);
142f29dbc25Smrg
143f29dbc25Smrg    for (i = 0; i < 256; i++)
14404007ebaSmrg        lut[i] = gfx_read_vid32(PALETTE_DATA);
145f29dbc25Smrg}
146f29dbc25Smrg
147f29dbc25Smrg/*----------------------------------------------------------------------------
148f29dbc25Smrg * GXInitVideo
149f29dbc25Smrg *
150f29dbc25Smrg * Description	:This is the initialization routine.It creates a new video
151f29dbc25Smrg * 				adapter and calls GXSetupImageVideo to initialize the adaptor
152f29dbc25Smrg * 				by filling XF86VideoAdaptorREc.Then it lists the existing
153f29dbc25Smrg * 				adaptors and adds the new one to it. Finally the list of
154f29dbc25Smrg * 				XF86VideoAdaptorPtr pointers are passed to the
155f29dbc25Smrg * 				xf86XVScreenInit().
156f29dbc25Smrg *
157f29dbc25Smrg * Parameters.
158f29dbc25Smrg *		pScrn	:Screen handler pointer having screen information.
159f29dbc25Smrg *
160f29dbc25Smrg * Returns		:none
161f29dbc25Smrg *
162f29dbc25Smrg * Comments		:none
163f29dbc25Smrg *----------------------------------------------------------------------------
164f29dbc25Smrg */
165f29dbc25Smrgvoid
166f29dbc25SmrgGXInitVideo(ScreenPtr pScrn)
167f29dbc25Smrg{
168f29dbc25Smrg    GeodeRec *pGeode;
16904007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
170f29dbc25Smrg
171f29dbc25Smrg    pGeode = GEODEPTR(pScrni);
172f29dbc25Smrg
173f29dbc25Smrg    if (!pGeode->NoAccel) {
17404007ebaSmrg        XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
17504007ebaSmrg        XF86VideoAdaptorPtr newAdaptor = NULL;
17604007ebaSmrg
17704007ebaSmrg        int num_adaptors;
17804007ebaSmrg
17904007ebaSmrg        newAdaptor = GXSetupImageVideo(pScrn);
18004007ebaSmrg        GXInitOffscreenImages(pScrn);
18104007ebaSmrg
18204007ebaSmrg        num_adaptors = xf86XVListGenericAdaptors(pScrni, &adaptors);
18304007ebaSmrg
18404007ebaSmrg        if (newAdaptor) {
18504007ebaSmrg            if (!num_adaptors) {
18604007ebaSmrg                num_adaptors = 1;
18704007ebaSmrg                adaptors = &newAdaptor;
18804007ebaSmrg            }
18904007ebaSmrg            else {
19004007ebaSmrg                newAdaptors =   /* need to free this someplace */
19104007ebaSmrg                    malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *));
19204007ebaSmrg                if (newAdaptors) {
19304007ebaSmrg                    memcpy(newAdaptors, adaptors, num_adaptors *
19404007ebaSmrg                           sizeof(XF86VideoAdaptorPtr));
19504007ebaSmrg                    newAdaptors[num_adaptors] = newAdaptor;
19604007ebaSmrg                    adaptors = newAdaptors;
19704007ebaSmrg                    num_adaptors++;
19804007ebaSmrg                }
19904007ebaSmrg            }
20004007ebaSmrg        }
20104007ebaSmrg
20204007ebaSmrg        if (num_adaptors)
20304007ebaSmrg            xf86XVScreenInit(pScrn, adaptors, num_adaptors);
20404007ebaSmrg
20504007ebaSmrg        if (newAdaptors)
20604007ebaSmrg            free(newAdaptors);
207f29dbc25Smrg    }
208f29dbc25Smrg}
209f29dbc25Smrg
210f29dbc25Smrg/* client libraries expect an encoding */
211f29dbc25Smrgstatic XF86VideoEncodingRec DummyEncoding[1] = {
212f29dbc25Smrg    {
21304007ebaSmrg     0,
21404007ebaSmrg     "XV_IMAGE",
21504007ebaSmrg     1024, 1024,
21604007ebaSmrg     {1, 1}
21704007ebaSmrg     }
218f29dbc25Smrg};
219f29dbc25Smrg
220f29dbc25Smrg#define NUM_FORMATS 4
221f29dbc25Smrg
222f29dbc25Smrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] = {
223f29dbc25Smrg    {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
224f29dbc25Smrg};
225f29dbc25Smrg
226f29dbc25Smrg#if DBUF
227f29dbc25Smrg#define NUM_ATTRIBUTES 4
228f29dbc25Smrg#else
229f29dbc25Smrg#define NUM_ATTRIBUTES 3
230f29dbc25Smrg#endif
231f29dbc25Smrg
232f29dbc25Smrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {
233f29dbc25Smrg#if DBUF
234f29dbc25Smrg    {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
235f29dbc25Smrg#endif
236f29dbc25Smrg    {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
237f29dbc25Smrg    {XvSettable | XvGettable, 0, 1, "XV_FILTER"},
238f29dbc25Smrg    {XvSettable | XvGettable, 0, 1, "XV_COLORKEYMODE"}
239f29dbc25Smrg};
240f29dbc25Smrg
241f29dbc25Smrg#define NUM_IMAGES 8
242f29dbc25Smrg
243f29dbc25Smrgstatic XF86ImageRec Images[NUM_IMAGES] = {
244f29dbc25Smrg    XVIMAGE_UYVY,
245f29dbc25Smrg    XVIMAGE_YUY2,
246f29dbc25Smrg    XVIMAGE_Y2YU,
247f29dbc25Smrg    XVIMAGE_YVYU,
248f29dbc25Smrg    XVIMAGE_Y800,
249f29dbc25Smrg    XVIMAGE_I420,
250f29dbc25Smrg    XVIMAGE_YV12,
251f29dbc25Smrg    XVIMAGE_RGB565
252f29dbc25Smrg};
253f29dbc25Smrg
25404007ebaSmrgtypedef struct {
255f29dbc25Smrg    void *area;
256f29dbc25Smrg    int offset;
257f29dbc25Smrg    RegionRec clip;
258f29dbc25Smrg    CARD32 filter;
259f29dbc25Smrg    CARD32 colorKey;
260f29dbc25Smrg    CARD32 colorKeyMode;
261f29dbc25Smrg    CARD32 videoStatus;
262f29dbc25Smrg    Time offTime;
263f29dbc25Smrg    Time freeTime;
264f29dbc25Smrg#if DBUF
265f29dbc25Smrg    Bool doubleBuffer;
266f29dbc25Smrg    int currentBuffer;
267f29dbc25Smrg#endif
268f29dbc25Smrg} GeodePortPrivRec, *GeodePortPrivPtr;
269f29dbc25Smrg
270f29dbc25Smrg#define GET_PORT_PRIVATE(pScrni) \
271f29dbc25Smrg   (GeodePortPrivRec *)((GEODEPTR(pScrni))->adaptor->pPortPrivates[0].ptr)
272f29dbc25Smrg
273f29dbc25Smrg/*----------------------------------------------------------------------------
274f29dbc25Smrg * GXSetColorKey
275f29dbc25Smrg *
276c744f008Smrg * Description	:This function reads the color key for the palette and
277f29dbc25Smrg *				  sets the video color key register.
278f29dbc25Smrg *
279f29dbc25Smrg * Parameters.
280f29dbc25Smrg * ScreenInfoPtr
281f29dbc25Smrg *		pScrni	:Screen  pointer having screen information.
282f29dbc25Smrg *		pPriv	:Video port private data
283f29dbc25Smrg *
284f29dbc25Smrg * Returns		:none
285f29dbc25Smrg *
286f29dbc25Smrg * Comments		:none
287f29dbc25Smrg *
288f29dbc25Smrg *----------------------------------------------------------------------------
289f29dbc25Smrg */
290f29dbc25Smrgstatic INT32
291f29dbc25SmrgGXSetColorkey(ScrnInfoPtr pScrni, GeodePortPrivRec * pPriv)
292f29dbc25Smrg{
293f29dbc25Smrg    int red, green, blue;
294f29dbc25Smrg    unsigned long key;
295f29dbc25Smrg
296f29dbc25Smrg    switch (pScrni->depth) {
297f29dbc25Smrg    case 8:
29804007ebaSmrg        GFX(get_display_palette_entry(pPriv->colorKey & 0xFF, &key));
29904007ebaSmrg        red = ((key >> 16) & 0xFF);
30004007ebaSmrg        green = ((key >> 8) & 0xFF);
30104007ebaSmrg        blue = (key & 0xFF);
30204007ebaSmrg        break;
303f29dbc25Smrg    case 16:
30404007ebaSmrg        red = (pPriv->colorKey & pScrni->mask.red) >>
30504007ebaSmrg            pScrni->offset.red << (8 - pScrni->weight.red);
30604007ebaSmrg        green = (pPriv->colorKey & pScrni->mask.green) >>
30704007ebaSmrg            pScrni->offset.green << (8 - pScrni->weight.green);
30804007ebaSmrg        blue = (pPriv->colorKey & pScrni->mask.blue) >>
30904007ebaSmrg            pScrni->offset.blue << (8 - pScrni->weight.blue);
31004007ebaSmrg        break;
311f29dbc25Smrg    default:
31204007ebaSmrg        /* for > 16 bpp we send in the mask in xf86SetWeight. This
31304007ebaSmrg         * function is providing the offset by 1 more. So we take
31404007ebaSmrg         * this as a special case and subtract 1 for > 16
31504007ebaSmrg         */
31604007ebaSmrg        red = (pPriv->colorKey & pScrni->mask.red) >>
31704007ebaSmrg            (pScrni->offset.red - 1) << (8 - pScrni->weight.red);
31804007ebaSmrg        green = (pPriv->colorKey & pScrni->mask.green) >>
31904007ebaSmrg            (pScrni->offset.green - 1) << (8 - pScrni->weight.green);
32004007ebaSmrg        blue = (pPriv->colorKey & pScrni->mask.blue) >>
32104007ebaSmrg            (pScrni->offset.blue - 1) << (8 - pScrni->weight.blue);
32204007ebaSmrg        break;
323f29dbc25Smrg    }
324f29dbc25Smrg
325f29dbc25Smrg    GFX(set_video_color_key((blue | (green << 8) | (red << 16)), 0xFFFFFF,
32604007ebaSmrg                            (pPriv->colorKeyMode == 0)));
327f29dbc25Smrg    REGION_EMPTY(pScrni->pScreen, &pPriv->clip);
328f29dbc25Smrg    return 0;
329f29dbc25Smrg}
330f29dbc25Smrg
331f29dbc25Smrg/*----------------------------------------------------------------------------
332f29dbc25Smrg * GXResetVideo
333f29dbc25Smrg *
334f29dbc25Smrg * Description	: This function resets the video
335f29dbc25Smrg *
336f29dbc25Smrg * Parameters.
337f29dbc25Smrg *		pScrni	:Screen  pointer having screen information.
338f29dbc25Smrg *
339f29dbc25Smrg * Returns		:None
340f29dbc25Smrg *
341f29dbc25Smrg * Comments		:none
342f29dbc25Smrg *
343f29dbc25Smrg *----------------------------------------------------------------------------
344f29dbc25Smrg */
345f29dbc25Smrgvoid
346f29dbc25SmrgGXResetVideo(ScrnInfoPtr pScrni)
347f29dbc25Smrg{
348f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
349f29dbc25Smrg
350f29dbc25Smrg    if (!pGeode->NoAccel) {
35104007ebaSmrg        GeodePortPrivRec *pPriv = pGeode->adaptor->pPortPrivates[0].ptr;
352f29dbc25Smrg
35304007ebaSmrg        GXAccelSync(pScrni);
35404007ebaSmrg        GXSetColorkey(pScrni, pPriv);
35504007ebaSmrg        GFX(set_video_filter(pPriv->filter, pPriv->filter));
356f29dbc25Smrg    }
357f29dbc25Smrg}
358f29dbc25Smrg
359f29dbc25Smrg/*----------------------------------------------------------------------------
360f29dbc25Smrg * GXSetupImageVideo
361f29dbc25Smrg *
362f29dbc25Smrg * Description	: This function allocates space for a Videoadaptor and
363f29dbc25Smrg * 				initializes the XF86VideoAdaptorPtr record.
364f29dbc25Smrg *
365f29dbc25Smrg * Parameters.
366f29dbc25Smrg *		pScrn	:Screen handler pointer having screen information.
367f29dbc25Smrg *
368f29dbc25Smrg * Returns		:pointer to the initialized video adaptor record.
369f29dbc25Smrg *
370f29dbc25Smrg * Comments		:none
371f29dbc25Smrg *----------------------------------------------------------------------------
372f29dbc25Smrg */
373f29dbc25Smrgstatic XF86VideoAdaptorPtr
374f29dbc25SmrgGXSetupImageVideo(ScreenPtr pScrn)
375f29dbc25Smrg{
37604007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
377f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
378f29dbc25Smrg    XF86VideoAdaptorPtr adapt;
379f29dbc25Smrg    GeodePortPrivRec *pPriv;
380f29dbc25Smrg
381170d5fdcSmrg    if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
38204007ebaSmrg                         sizeof(GeodePortPrivRec) + sizeof(DevUnion))))
38304007ebaSmrg        return NULL;
384f29dbc25Smrg
385f29dbc25Smrg    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
386f29dbc25Smrg    adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
387f29dbc25Smrg    adapt->name = "Advanced Micro Devices";
388f29dbc25Smrg    adapt->nEncodings = 1;
389f29dbc25Smrg    adapt->pEncodings = DummyEncoding;
390f29dbc25Smrg    adapt->nFormats = NUM_FORMATS;
391f29dbc25Smrg    adapt->pFormats = Formats;
392f29dbc25Smrg    adapt->nPorts = 1;
393f29dbc25Smrg    adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
394f29dbc25Smrg    pPriv = (GeodePortPrivRec *) (&adapt->pPortPrivates[1]);
395f29dbc25Smrg    adapt->pPortPrivates[0].ptr = (pointer) (pPriv);
396f29dbc25Smrg    adapt->pAttributes = Attributes;
397f29dbc25Smrg    adapt->nImages = NUM_IMAGES;
398f29dbc25Smrg    adapt->nAttributes = NUM_ATTRIBUTES;
399f29dbc25Smrg    adapt->pImages = Images;
400f29dbc25Smrg    adapt->PutVideo = NULL;
401f29dbc25Smrg    adapt->PutStill = NULL;
402f29dbc25Smrg    adapt->GetVideo = NULL;
403f29dbc25Smrg    adapt->GetStill = NULL;
404f29dbc25Smrg    adapt->StopVideo = GXStopVideo;
405f29dbc25Smrg    adapt->SetPortAttribute = GXSetPortAttribute;
406f29dbc25Smrg    adapt->GetPortAttribute = GXGetPortAttribute;
407f29dbc25Smrg    adapt->QueryBestSize = GXQueryBestSize;
408f29dbc25Smrg    adapt->PutImage = GXPutImage;
409f29dbc25Smrg    adapt->QueryImageAttributes = GeodeQueryImageAttributes;
410f29dbc25Smrg
411f29dbc25Smrg    pPriv->filter = 0;
412f29dbc25Smrg    pPriv->colorKey = 0;
413f29dbc25Smrg    pPriv->colorKeyMode = 0;
414f29dbc25Smrg    pPriv->videoStatus = 0;
415f29dbc25Smrg#if DBUF
416f29dbc25Smrg    pPriv->doubleBuffer = TRUE;
41704007ebaSmrg    pPriv->currentBuffer = 0;   /* init to first buffer */
418f29dbc25Smrg#endif
419f29dbc25Smrg
420f29dbc25Smrg    /* gotta uninit this someplace */
421f29dbc25Smrg#if defined(REGION_NULL)
422f29dbc25Smrg    REGION_NULL(pScrn, &pPriv->clip);
423f29dbc25Smrg#else
424f29dbc25Smrg    REGION_INIT(pScrn, &pPriv->clip, NullBox, 0);
425f29dbc25Smrg#endif
426f29dbc25Smrg
427f29dbc25Smrg    pGeode->adaptor = adapt;
428f29dbc25Smrg
429f29dbc25Smrg    pGeode->BlockHandler = pScrn->BlockHandler;
430f29dbc25Smrg    pScrn->BlockHandler = GXBlockHandler;
431f29dbc25Smrg
432f29dbc25Smrg    xvColorKey = MAKE_ATOM("XV_COLORKEY");
433f29dbc25Smrg    xvColorKeyMode = MAKE_ATOM("XV_COLORKEYMODE");
434f29dbc25Smrg    xvFilter = MAKE_ATOM("XV_FILTER");
435f29dbc25Smrg#if DBUF
436f29dbc25Smrg    xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
437f29dbc25Smrg#endif
438f29dbc25Smrg
439f29dbc25Smrg    GXResetVideo(pScrni);
440f29dbc25Smrg
441f29dbc25Smrg    return adapt;
442f29dbc25Smrg}
443f29dbc25Smrg
444f29dbc25Smrg/*----------------------------------------------------------------------------
445f29dbc25Smrg * GXStopVideo
446f29dbc25Smrg *
447f29dbc25Smrg * Description	:This function is used to stop input and output video
448f29dbc25Smrg *
449f29dbc25Smrg * Parameters.
450f29dbc25Smrg *		pScrni	:Screen handler pointer having screen information.
451f29dbc25Smrg *		data	:Pointer to the video port's private data
452f29dbc25Smrg *		exit	:Flag indicating whether the offscreen areas used for
453f29dbc25Smrg *				video to be deallocated or not.
454f29dbc25Smrg *
455f29dbc25Smrg * Returns		:none
456f29dbc25Smrg *
457f29dbc25Smrg * Comments		:none
458f29dbc25Smrg *----------------------------------------------------------------------------
459f29dbc25Smrg */
460f29dbc25Smrgstatic void
461f29dbc25SmrgGXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit)
462f29dbc25Smrg{
463f29dbc25Smrg    GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
464f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
465f29dbc25Smrg
466f29dbc25Smrg    REGION_EMPTY(pScrni->pScreen, &pPriv->clip);
467f29dbc25Smrg
468f29dbc25Smrg    GXAccelSync(pScrni);
469f29dbc25Smrg    if (exit) {
47004007ebaSmrg        if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
47104007ebaSmrg            GFX(set_video_enable(0));
472f29dbc25Smrg
47304007ebaSmrg            /* If we have saved graphics LUT data - restore it */
47404007ebaSmrg            /* Otherwise, turn bypass on */
475f29dbc25Smrg
47604007ebaSmrg            if (lutflag)
47704007ebaSmrg                GFX(set_graphics_palette(graphics_lut));
47804007ebaSmrg            else
47904007ebaSmrg                GFX(set_video_palette_bypass(1));
480f29dbc25Smrg
48104007ebaSmrg            lutflag = 0;
48204007ebaSmrg        }
483f29dbc25Smrg
48404007ebaSmrg        if (pPriv->area) {
485f29dbc25Smrg#ifdef XF86EXA
48604007ebaSmrg            if (pGeode->useEXA)
48704007ebaSmrg                exaOffscreenFree(pScrni->pScreen, pPriv->area);
488f29dbc25Smrg#endif
489f29dbc25Smrg
49004007ebaSmrg            if (!pGeode->useEXA)
49104007ebaSmrg                xf86FreeOffscreenArea(pPriv->area);
492f29dbc25Smrg
49304007ebaSmrg            pPriv->area = NULL;
49404007ebaSmrg        }
495f29dbc25Smrg
49604007ebaSmrg        pPriv->videoStatus = 0;
49704007ebaSmrg        pGeode->OverlayON = FALSE;
49804007ebaSmrg    }
49904007ebaSmrg    else {
50004007ebaSmrg        if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
50104007ebaSmrg            pPriv->videoStatus |= OFF_TIMER;
50204007ebaSmrg            pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
50304007ebaSmrg        }
504f29dbc25Smrg    }
505f29dbc25Smrg}
506f29dbc25Smrg
507f29dbc25Smrg/*----------------------------------------------------------------------------
508f29dbc25Smrg * GXSetPortAttribute
509f29dbc25Smrg *
510f29dbc25Smrg * Description		:This function is used to set the attributes of a port
511f29dbc25Smrg * 					like colorkeymode, double buffer support and filter.
512f29dbc25Smrg *
513f29dbc25Smrg * Parameters.
514f29dbc25Smrg *		pScrni		:Screen handler pointer having screen information.
515f29dbc25Smrg *		data		:Pointer to the video port's private data
516f29dbc25Smrg *		attribute	:The port attribute to be set
517f29dbc25Smrg *		value		:Value of the attribute to be set.
518f29dbc25Smrg *
519c744f008Smrg * Returns			:Success if the attribute is supported, else BadMatch
520f29dbc25Smrg *
521f29dbc25Smrg * Comments			:none
522f29dbc25Smrg *----------------------------------------------------------------------------
523f29dbc25Smrg */
524f29dbc25Smrgstatic int
525f29dbc25SmrgGXSetPortAttribute(ScrnInfoPtr pScrni,
52604007ebaSmrg                   Atom attribute, INT32 value, pointer data)
527f29dbc25Smrg{
528f29dbc25Smrg    GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
529f29dbc25Smrg
530f29dbc25Smrg    GXAccelSync(pScrni);
531f29dbc25Smrg    if (attribute == xvColorKey) {
53204007ebaSmrg        pPriv->colorKey = value;
53304007ebaSmrg        GXSetColorkey(pScrni, pPriv);
534f29dbc25Smrg    }
535f29dbc25Smrg#if DBUF
536f29dbc25Smrg    else if (attribute == xvDoubleBuffer) {
53704007ebaSmrg        if ((value < 0) || (value > 1))
53804007ebaSmrg            return BadValue;
53904007ebaSmrg        pPriv->doubleBuffer = value;
540f29dbc25Smrg    }
541f29dbc25Smrg#endif
542f29dbc25Smrg    else if (attribute == xvColorKeyMode) {
54304007ebaSmrg        pPriv->colorKeyMode = value;
54404007ebaSmrg        GXSetColorkey(pScrni, pPriv);
54504007ebaSmrg    }
54604007ebaSmrg    else if (attribute == xvFilter) {
54704007ebaSmrg        if ((value < 0) || (value > 1))
54804007ebaSmrg            return BadValue;
54904007ebaSmrg        pPriv->filter = value;
55004007ebaSmrg    }
55104007ebaSmrg    else
55204007ebaSmrg        return BadMatch;
553f29dbc25Smrg
554f29dbc25Smrg    return Success;
555f29dbc25Smrg}
556f29dbc25Smrg
557f29dbc25Smrg/*----------------------------------------------------------------------------
558f29dbc25Smrg * GXGetPortAttribute
559f29dbc25Smrg *
560f29dbc25Smrg * Description		:This function is used to get the attributes of a port
561f29dbc25Smrg * 					like hue, saturation,brightness or contrast.
562f29dbc25Smrg *
563f29dbc25Smrg * Parameters.
564f29dbc25Smrg *		pScrni		:Screen handler pointer having screen information.
565f29dbc25Smrg *		data		:Pointer to the video port's private data
566f29dbc25Smrg *		attribute	:The port attribute to be read
567f29dbc25Smrg *		value		:Pointer to the value of the attribute to be read.
568f29dbc25Smrg *
569c744f008Smrg * Returns			:Success if the attribute is supported, else BadMatch
570f29dbc25Smrg *
571f29dbc25Smrg * Comments			:none
572f29dbc25Smrg *----------------------------------------------------------------------------
573f29dbc25Smrg */
574f29dbc25Smrgstatic int
575f29dbc25SmrgGXGetPortAttribute(ScrnInfoPtr pScrni,
57604007ebaSmrg                   Atom attribute, INT32 *value, pointer data)
577f29dbc25Smrg{
578f29dbc25Smrg    GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
579f29dbc25Smrg
580f29dbc25Smrg    if (attribute == xvColorKey) {
58104007ebaSmrg        *value = pPriv->colorKey;
582f29dbc25Smrg    }
583f29dbc25Smrg#if DBUF
584f29dbc25Smrg    else if (attribute == xvDoubleBuffer) {
58504007ebaSmrg        *value = (pPriv->doubleBuffer) ? 1 : 0;
586f29dbc25Smrg    }
587f29dbc25Smrg#endif
588f29dbc25Smrg    else if (attribute == xvColorKeyMode) {
58904007ebaSmrg        *value = pPriv->colorKeyMode;
59004007ebaSmrg    }
59104007ebaSmrg    else if (attribute == xvFilter) {
59204007ebaSmrg        *value = pPriv->filter;
59304007ebaSmrg    }
59404007ebaSmrg    else
59504007ebaSmrg        return BadMatch;
596f29dbc25Smrg
597f29dbc25Smrg    return Success;
598f29dbc25Smrg}
599f29dbc25Smrg
600f29dbc25Smrg/*----------------------------------------------------------------------------
601f29dbc25Smrg * GXQueryBestSize
602f29dbc25Smrg *
603f29dbc25Smrg * Description		:This function provides a way to query what the
604f29dbc25Smrg * 					destination dimensions would end up being if they were to
605f29dbc25Smrg * 					request that an area vid_w by vid_h from the video stream
606f29dbc25Smrg * 					be scaled to rectangle of drw_w by drw_h on the screen.
607f29dbc25Smrg *
608f29dbc25Smrg * Parameters.
609f29dbc25Smrg *		pScrni		:Screen handler pointer having screen information.
610f29dbc25Smrg *		data		:Pointer to the video port's private data
611f29dbc25Smrg *      vid_w,vid_h	:Width and height of the video data.
612f29dbc25Smrg *		drw_w,drw_h :Width and height of the scaled rectangle.
613f29dbc25Smrg *		p_w,p_h		:Width and height of the destination rectangle.
614f29dbc25Smrg *
615f29dbc25Smrg * Returns			:None
616f29dbc25Smrg *
617f29dbc25Smrg * Comments			:None
618f29dbc25Smrg *----------------------------------------------------------------------------
619f29dbc25Smrg */
620f29dbc25Smrgstatic void
621f29dbc25SmrgGXQueryBestSize(ScrnInfoPtr pScrni,
62204007ebaSmrg                Bool motion,
62304007ebaSmrg                short vid_w, short vid_h,
62404007ebaSmrg                short drw_w, short drw_h,
62504007ebaSmrg                unsigned int *p_w, unsigned int *p_h, pointer data)
626f29dbc25Smrg{
627f29dbc25Smrg    *p_w = drw_w;
628f29dbc25Smrg    *p_h = drw_h;
629f29dbc25Smrg
630f29dbc25Smrg    if (*p_w > 16384)
63104007ebaSmrg        *p_w = 16384;
632f29dbc25Smrg}
633f29dbc25Smrg
634f29dbc25Smrg/*----------------------------------------------------------------------------
635f29dbc25Smrg * GXCopyData420
636f29dbc25Smrg *
637f29dbc25Smrg * Description		: Copies data from src to destination
638f29dbc25Smrg *
639f29dbc25Smrg * Parameters.
640f29dbc25Smrg *		src			: pointer to the source data
641f29dbc25Smrg *		dst			: pointer to destination data
642f29dbc25Smrg *		srcPitch	: pitch of the srcdata
643f29dbc25Smrg *		dstPitch	: pitch of the destination data
644f29dbc25Smrg *		h & w		: height and width of source data
645f29dbc25Smrg *
646f29dbc25Smrg * Returns			:None
647f29dbc25Smrg *
648f29dbc25Smrg * Comments			:None
649f29dbc25Smrg *----------------------------------------------------------------------------
650f29dbc25Smrg */
651f29dbc25Smrgstatic void
652f29dbc25SmrgGXCopyData420(unsigned char *src, unsigned char *dst,
65304007ebaSmrg              int srcPitch, int dstPitch, int h, int w)
654f29dbc25Smrg{
655f29dbc25Smrg    while (h--) {
65604007ebaSmrg        memcpy(dst, src, w);
65704007ebaSmrg        src += srcPitch;
65804007ebaSmrg        dst += dstPitch;
659f29dbc25Smrg    }
660f29dbc25Smrg}
661f29dbc25Smrg
662f29dbc25Smrg/*----------------------------------------------------------------------------
663f29dbc25Smrg * GXCopyData422
664f29dbc25Smrg *
665f29dbc25Smrg * Description		: Copies data from src to destination
666f29dbc25Smrg *
667f29dbc25Smrg * Parameters.
668f29dbc25Smrg *		src			: pointer to the source data
669f29dbc25Smrg *		dst			: pointer to destination data
670f29dbc25Smrg *		srcPitch	: pitch of the srcdata
671f29dbc25Smrg *		dstPitch	: pitch of the destination data
672f29dbc25Smrg *		h & w		: height and width of source data
673f29dbc25Smrg *
674f29dbc25Smrg * Returns			:None
675f29dbc25Smrg *
676f29dbc25Smrg * Comments			:None
677f29dbc25Smrg *----------------------------------------------------------------------------
678f29dbc25Smrg */
679f29dbc25Smrgstatic void
680f29dbc25SmrgGXCopyData422(unsigned char *src, unsigned char *dst,
68104007ebaSmrg              int srcPitch, int dstPitch, int h, int w)
682f29dbc25Smrg{
683f29dbc25Smrg    w <<= 1;
684f29dbc25Smrg    while (h--) {
68504007ebaSmrg        memcpy(dst, src, w);
68604007ebaSmrg        src += srcPitch;
68704007ebaSmrg        dst += dstPitch;
688f29dbc25Smrg    }
689f29dbc25Smrg}
690f29dbc25Smrg
691f29dbc25Smrg#ifdef XF86EXA
692f29dbc25Smrgstatic void
693f29dbc25SmrgGXVideoSave(ScreenPtr pScreen, ExaOffscreenArea * area)
694f29dbc25Smrg{
69504007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen);
696f29dbc25Smrg    GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni);
697f29dbc25Smrg
698f29dbc25Smrg    if (area == pPriv->area)
69904007ebaSmrg        pPriv->area = NULL;
700f29dbc25Smrg}
701f29dbc25Smrg#endif
702f29dbc25Smrg
703f29dbc25Smrgstatic int
704f29dbc25SmrgGXAllocateMemory(ScrnInfoPtr pScrni, void **memp, int numlines)
705f29dbc25Smrg{
70604007ebaSmrg    ScreenPtr pScrn = xf86ScrnToScreen(pScrni);
707f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
708f29dbc25Smrg
709f29dbc25Smrg    //long displayWidth = pGeode->Pitch / ((pScrni->bitsPerPixel + 7) / 8);
710f29dbc25Smrg    int size = numlines * pGeode->displayWidth;
711f29dbc25Smrg
712f29dbc25Smrg#if XF86EXA
713f29dbc25Smrg    if (pGeode->useEXA) {
71404007ebaSmrg        ExaOffscreenArea *area = *memp;
715f29dbc25Smrg
71604007ebaSmrg        if (area != NULL) {
71704007ebaSmrg            if (area->size >= size)
71804007ebaSmrg                return area->offset;
719f29dbc25Smrg
72004007ebaSmrg            exaOffscreenFree(pScrni->pScreen, area);
72104007ebaSmrg        }
722f29dbc25Smrg
72304007ebaSmrg        area = exaOffscreenAlloc(pScrni->pScreen, size, 16,
72404007ebaSmrg                                 TRUE, GXVideoSave, NULL);
72504007ebaSmrg        *memp = area;
726f29dbc25Smrg
72704007ebaSmrg        return area == NULL ? 0 : area->offset;
728f29dbc25Smrg    }
729f29dbc25Smrg#endif
730f29dbc25Smrg
731f29dbc25Smrg    if (!pGeode->useEXA) {
73204007ebaSmrg        FBAreaPtr area = *memp;
73304007ebaSmrg        FBAreaPtr new_area;
734f29dbc25Smrg
73504007ebaSmrg        if (area) {
73604007ebaSmrg            if ((area->box.y2 - area->box.y1) >= numlines)
73704007ebaSmrg                return (area->box.y1 * pGeode->Pitch);
738f29dbc25Smrg
73904007ebaSmrg            if (xf86ResizeOffscreenArea(area, pGeode->displayWidth, numlines))
74004007ebaSmrg                return (area->box.y1 * pGeode->Pitch);
741f29dbc25Smrg
74204007ebaSmrg            xf86FreeOffscreenArea(area);
74304007ebaSmrg        }
744f29dbc25Smrg
74504007ebaSmrg        new_area = xf86AllocateOffscreenArea(pScrn, pGeode->displayWidth,
74604007ebaSmrg                                             numlines, 0, NULL, NULL, NULL);
747f29dbc25Smrg
74804007ebaSmrg        if (!new_area) {
74904007ebaSmrg            int max_w, max_h;
750f29dbc25Smrg
75104007ebaSmrg            xf86QueryLargestOffscreenArea(pScrn, &max_w, &max_h, 0,
75204007ebaSmrg                                          FAVOR_WIDTH_THEN_AREA,
75304007ebaSmrg                                          PRIORITY_EXTREME);
754f29dbc25Smrg
75504007ebaSmrg            if ((max_w < pGeode->displayWidth) || (max_h < numlines)) {
75604007ebaSmrg                xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
75704007ebaSmrg                           "No room - how sad %x, %x, %x, %x\n", max_w,
75804007ebaSmrg                           pGeode->displayWidth, max_h, numlines);
75904007ebaSmrg                return 0;
76004007ebaSmrg            }
761f29dbc25Smrg
76204007ebaSmrg            xf86PurgeUnlockedOffscreenAreas(pScrn);
76304007ebaSmrg            new_area = xf86AllocateOffscreenArea(pScrn, pGeode->displayWidth,
76404007ebaSmrg                                                 numlines, 0, NULL, NULL, NULL);
76504007ebaSmrg        }
766f29dbc25Smrg
76704007ebaSmrg        return (new_area->box.y1 * pGeode->Pitch);
768f29dbc25Smrg    }
769f29dbc25Smrg
770f29dbc25Smrg    return 0;
771f29dbc25Smrg}
772f29dbc25Smrg
773f29dbc25Smrgstatic BoxRec dstBox;
774f29dbc25Smrgstatic int srcPitch = 0, srcPitch2 = 0, dstPitch = 0, dstPitch2 = 0;
775f29dbc25Smrgstatic INT32 Bx1, Bx2, By1, By2;
776f29dbc25Smrgstatic int top, left, npixels, nlines;
777f29dbc25Smrgstatic int offset, s1offset = 0, s2offset = 0, s3offset = 0;
778f29dbc25Smrgstatic unsigned char *dst_start;
779f29dbc25Smrgstatic int d2offset = 0, d3offset = 0;
780f29dbc25Smrg
781f29dbc25Smrg#if 0
782f29dbc25Smrgstatic Bool
783f29dbc25SmrgRegionsIntersect(BoxPtr pRcl1, BoxPtr pRcl2, BoxPtr pRclResult)
784f29dbc25Smrg{
785f29dbc25Smrg    pRclResult->x1 = max(pRcl1->x1, pRcl2->x1);
786f29dbc25Smrg    pRclResult->x2 = min(pRcl1->x2, pRcl2->x2);
787f29dbc25Smrg
788f29dbc25Smrg    if (pRclResult->x1 <= pRclResult->x2) {
78904007ebaSmrg        pRclResult->y1 = max(pRcl1->y1, pRcl2->y1);
79004007ebaSmrg        pRclResult->y2 = min(pRcl1->y2, pRcl2->y2);
791f29dbc25Smrg
79204007ebaSmrg        if (pRclResult->y1 <= pRclResult->y2) {
79304007ebaSmrg            return (TRUE);
79404007ebaSmrg        }
795f29dbc25Smrg    }
796f29dbc25Smrg
797f29dbc25Smrg    return (FALSE);
798f29dbc25Smrg}
799f29dbc25Smrg#endif
800f29dbc25Smrg
801f29dbc25Smrgvoid
802f29dbc25SmrgGXSetVideoPosition(int x, int y, int width, int height,
80304007ebaSmrg                   short src_w, short src_h, short drw_w, short drw_h,
80404007ebaSmrg                   int id, int offset, ScrnInfoPtr pScrni)
805f29dbc25Smrg{
806f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
807f29dbc25Smrg    long ystart, xend, yend;
808f29dbc25Smrg    unsigned long lines = 0;
809f29dbc25Smrg    unsigned long y_extra, uv_extra = 0;
810f29dbc25Smrg    unsigned long startAddress;
811f29dbc25Smrg
812f29dbc25Smrg#if 0
813f29dbc25Smrg    BoxRec ovly, display, result;
814f29dbc25Smrg#endif
815f29dbc25Smrg
816f29dbc25Smrg    xend = x + drw_w;
817f29dbc25Smrg    yend = y + drw_h;
818f29dbc25Smrg
819f29dbc25Smrg    /* Take care of panning when panel is present */
820f29dbc25Smrg
821f29dbc25Smrg    startAddress = gfx_get_display_offset();
822f29dbc25Smrg    DeltaY = startAddress / pGeode->Pitch;
823f29dbc25Smrg    DeltaX = startAddress & (pGeode->Pitch - 1);
824f29dbc25Smrg    DeltaX /= (pScrni->bitsPerPixel >> 3);
825f29dbc25Smrg
826f29dbc25Smrg#if 0
827f29dbc25Smrg    /* Thhis code is pretty dang broken - comment it out for now */
828f29dbc25Smrg
829f29dbc25Smrg    if (pGeode->Panel) {
83004007ebaSmrg        ovly.x1 = x;
83104007ebaSmrg        ovly.x2 = x + pGeode->video_dstw;
83204007ebaSmrg        ovly.y1 = y;
83304007ebaSmrg        ovly.y2 = y + pGeode->video_dsth;
83404007ebaSmrg
83504007ebaSmrg        display.x1 = DeltaX;
83604007ebaSmrg        display.x2 = DeltaX + pGeode->FPBX;
83704007ebaSmrg        display.y1 = DeltaY;
83804007ebaSmrg        display.y2 = DeltaY + pGeode->FPBY;
83904007ebaSmrg        x = xend = 0;
84004007ebaSmrg        if (RegionsIntersect(&display, &ovly, &result)) {
84104007ebaSmrg            x = ovly.x1 - DeltaX;
84204007ebaSmrg            xend = ovly.x2 - DeltaX;
84304007ebaSmrg            y = ovly.y1 - DeltaY;
84404007ebaSmrg            yend = ovly.y2 - DeltaY;
84504007ebaSmrg        }
846f29dbc25Smrg    }
847f29dbc25Smrg#endif
848f29dbc25Smrg
849f29dbc25Smrg    /*  TOP CLIPPING */
850f29dbc25Smrg
851f29dbc25Smrg    if (y < 0) {
85204007ebaSmrg        if (src_h < drw_h)
85304007ebaSmrg            lines = (-y) * src_h / drw_h;
85404007ebaSmrg        else
85504007ebaSmrg            lines = (-y);
85604007ebaSmrg        ystart = 0;
85704007ebaSmrg        drw_h += y;
85804007ebaSmrg        y_extra = lines * dstPitch;
85904007ebaSmrg        uv_extra = (lines >> 1) * (dstPitch2);
86004007ebaSmrg    }
86104007ebaSmrg    else {
86204007ebaSmrg        ystart = y;
86304007ebaSmrg        lines = 0;
86404007ebaSmrg        y_extra = 0;
865f29dbc25Smrg    }
866f29dbc25Smrg
867f29dbc25Smrg    GFX(set_video_window(x, ystart, xend - x, yend - ystart));
868f29dbc25Smrg
869f29dbc25Smrg    if ((id == FOURCC_Y800) || (id == FOURCC_I420) || (id == FOURCC_YV12)) {
87004007ebaSmrg        GFX(set_video_yuv_offsets(offset + y_extra,
87104007ebaSmrg                                  offset + d3offset + uv_extra,
87204007ebaSmrg                                  offset + d2offset + uv_extra));
87304007ebaSmrg    }
87404007ebaSmrg    else {
87504007ebaSmrg        GFX(set_video_offset(offset + y_extra));
876f29dbc25Smrg    }
877f29dbc25Smrg}
878f29dbc25Smrg
879f29dbc25Smrg/*----------------------------------------------------------------------------
880f29dbc25Smrg * GXDisplayVideo
881f29dbc25Smrg *
882f29dbc25Smrg * Description	:This function sets up the video registers for playing video
883f29dbc25Smrg * 				It sets up the video format,width, height & position of the
884f29dbc25Smrg *		  		video window ,video offsets( y,u,v) and video pitches(y,u,v)
885f29dbc25Smrg *
886f29dbc25Smrg * Parameters
887f29dbc25Smrg *
888f29dbc25Smrg * Returns		:None
889f29dbc25Smrg *
890f29dbc25Smrg * Comments		:None
891f29dbc25Smrg *----------------------------------------------------------------------------
892f29dbc25Smrg */
893f29dbc25Smrg
894f29dbc25Smrgstatic void
895f29dbc25SmrgGXDisplayVideo(ScrnInfoPtr pScrni,
89604007ebaSmrg               int id,
89704007ebaSmrg               int offset,
89804007ebaSmrg               short width, short height,
89904007ebaSmrg               int pitch,
90004007ebaSmrg               int x1, int y1, int x2, int y2,
90104007ebaSmrg               BoxPtr dstBox, short src_w, short src_h, short drw_w,
90204007ebaSmrg               short drw_h)
903f29dbc25Smrg{
904f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
905f29dbc25Smrg    unsigned long dcfg, misc;
906f29dbc25Smrg
907f29dbc25Smrg    GXAccelSync(pScrni);
908f29dbc25Smrg
909f29dbc25Smrg    /* If the gamma LUT is already loaded with graphics data, then save it
910f29dbc25Smrg     * off
911f29dbc25Smrg     */
912f29dbc25Smrg
913f29dbc25Smrg    if (id != FOURCC_RGB565) {
91404007ebaSmrg        dcfg = gfx_read_vid32(DISPLAY_CONFIG);
91504007ebaSmrg        misc = gfx_read_vid32(MISC);
916f29dbc25Smrg
91704007ebaSmrg        lutflag = (!(misc & 1) && (dcfg & (1 << 21)));
918f29dbc25Smrg
91904007ebaSmrg        if (lutflag)
92004007ebaSmrg            get_gamma_ram(graphics_lut);
921f29dbc25Smrg
92204007ebaSmrg        /* Set the video gamma ram */
92304007ebaSmrg        GFX(set_video_palette(NULL));
924f29dbc25Smrg    }
925f29dbc25Smrg
926f29dbc25Smrg    GFX(set_video_enable(1));
927f29dbc25Smrg
928f29dbc25Smrg    switch (id) {
92904007ebaSmrg    case FOURCC_UYVY:          /* UYVY */
93004007ebaSmrg        GFX(set_video_format(VIDEO_FORMAT_UYVY));
93104007ebaSmrg        GFX(set_video_size(width, height));
93204007ebaSmrg        break;
93304007ebaSmrg    case FOURCC_Y800:          /* Y800 - greyscale - we munge it! */
93404007ebaSmrg    case FOURCC_YV12:          /* YV12 */
93504007ebaSmrg    case FOURCC_I420:          /* I420 */
93604007ebaSmrg        GFX(set_video_format(VIDEO_FORMAT_Y0Y1Y2Y3));
93704007ebaSmrg        GFX(set_video_size(width, height));
93804007ebaSmrg        GFX(set_video_yuv_pitch(dstPitch, dstPitch2));
93904007ebaSmrg        break;
94004007ebaSmrg    case FOURCC_YUY2:          /* YUY2 */
94104007ebaSmrg        GFX(set_video_format(VIDEO_FORMAT_YUYV));
94204007ebaSmrg        GFX(set_video_size(width, height));
94304007ebaSmrg        break;
94404007ebaSmrg    case FOURCC_Y2YU:          /* Y2YU */
94504007ebaSmrg        GFX(set_video_format(VIDEO_FORMAT_Y2YU));
94604007ebaSmrg        GFX(set_video_size(width, height));
94704007ebaSmrg        break;
94804007ebaSmrg    case FOURCC_YVYU:          /* YVYU */
94904007ebaSmrg        GFX(set_video_format(VIDEO_FORMAT_YVYU));
95004007ebaSmrg        GFX(set_video_size(width, height));
95104007ebaSmrg        break;
952f29dbc25Smrg    case FOURCC_RGB565:
95304007ebaSmrg        GFX(set_video_format(VIDEO_FORMAT_RGB));
95404007ebaSmrg        GFX(set_video_size(width, height));
95504007ebaSmrg        break;
956f29dbc25Smrg
957f29dbc25Smrg    }
958f29dbc25Smrg
959f29dbc25Smrg    if (pGeode->Panel) {
96004007ebaSmrg        pGeode->video_x = dstBox->x1;
96104007ebaSmrg        pGeode->video_y = dstBox->y1;
96204007ebaSmrg        pGeode->video_w = width;
96304007ebaSmrg        pGeode->video_h = height;
96404007ebaSmrg        pGeode->video_srcw = src_w;
96504007ebaSmrg        pGeode->video_srch = src_h;
96604007ebaSmrg        pGeode->video_dstw = drw_w;
96704007ebaSmrg        pGeode->video_dsth = drw_h;
96804007ebaSmrg        pGeode->video_offset = offset;
96904007ebaSmrg        pGeode->video_id = id;
97004007ebaSmrg        pGeode->video_scrnptr = pScrni;
971f29dbc25Smrg    }
972f29dbc25Smrg
973f29dbc25Smrg    if ((drw_w >= src_w) && (drw_h >= src_h))
97404007ebaSmrg        GFX(set_video_scale(width, height, drw_w, drw_h));
975f29dbc25Smrg    else if (drw_w < src_w)
97604007ebaSmrg        GFX(set_video_scale(drw_w, height, drw_w, drw_h));
977f29dbc25Smrg    else if (drw_h < src_h)
97804007ebaSmrg        GFX(set_video_scale(width, drw_h, drw_w, drw_h));
979f29dbc25Smrg
980f29dbc25Smrg    GXSetVideoPosition(dstBox->x1, dstBox->y1, width, height, src_w,
98104007ebaSmrg                       src_h, drw_w, drw_h, id, offset, pScrni);
982f29dbc25Smrg}
983f29dbc25Smrg
984f29dbc25Smrg/* Used by LX as well */
985f29dbc25Smrg
986f29dbc25SmrgBool
987f29dbc25SmrgRegionsEqual(RegionPtr A, RegionPtr B)
988f29dbc25Smrg{
989f29dbc25Smrg    int *dataA, *dataB;
990f29dbc25Smrg    int num;
991f29dbc25Smrg
992f29dbc25Smrg    num = REGION_NUM_RECTS(A);
993f29dbc25Smrg    if (num != REGION_NUM_RECTS(B)) {
99404007ebaSmrg        return FALSE;
995f29dbc25Smrg    }
996f29dbc25Smrg
997f29dbc25Smrg    if ((A->extents.x1 != B->extents.x1) ||
99804007ebaSmrg        (A->extents.x2 != B->extents.x2) ||
99904007ebaSmrg        (A->extents.y1 != B->extents.y1) || (A->extents.y2 != B->extents.y2))
100004007ebaSmrg        return FALSE;
1001f29dbc25Smrg
100204007ebaSmrg    dataA = (int *) REGION_RECTS(A);
100304007ebaSmrg    dataB = (int *) REGION_RECTS(B);
1004f29dbc25Smrg
1005f29dbc25Smrg    while (num--) {
100604007ebaSmrg        if ((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
100704007ebaSmrg            return FALSE;
1008f29dbc25Smrg
100904007ebaSmrg        dataA += 2;
101004007ebaSmrg        dataB += 2;
1011f29dbc25Smrg    }
1012f29dbc25Smrg
1013f29dbc25Smrg    return TRUE;
1014f29dbc25Smrg}
1015f29dbc25Smrg
1016f29dbc25Smrg/*----------------------------------------------------------------------------
1017f29dbc25Smrg * GXPutImage	:This function writes a single frame of video into a
1018f29dbc25Smrg * 				drawable. The position and size of the source rectangle is
1019f29dbc25Smrg * 				specified by src_x,src_y, src_w and src_h. This data is
1020f29dbc25Smrg * 				stored in a system memory buffer at buf. The position and
1021f29dbc25Smrg * 				size of the destination rectangle is specified by drw_x,
1022f29dbc25Smrg * 				drw_y,drw_w,drw_h.The data is in the format indicated by the
1023f29dbc25Smrg * 				image descriptor and represents a source of size width by
1024f29dbc25Smrg * 				height.  If sync is TRUE the driver should not return from
1025f29dbc25Smrg * 				this function until it is through reading the data from buf.
1026f29dbc25Smrg * 				Returning when sync is TRUE indicates that it is safe for the
1027f29dbc25Smrg * 				data at buf to be replaced,freed, or modified.
1028f29dbc25Smrg *
1029f29dbc25Smrg * Parameters.
1030f29dbc25Smrg *
1031f29dbc25Smrg * Returns		:None
1032f29dbc25Smrg *
1033f29dbc25Smrg * Comments		:None
1034f29dbc25Smrg *----------------------------------------------------------------------------
1035f29dbc25Smrg */
1036f29dbc25Smrg
1037f29dbc25Smrgstatic int
1038f29dbc25SmrgGXPutImage(ScrnInfoPtr pScrni,
103904007ebaSmrg           short src_x, short src_y,
104004007ebaSmrg           short drw_x, short drw_y,
104104007ebaSmrg           short src_w, short src_h,
104204007ebaSmrg           short drw_w, short drw_h,
104304007ebaSmrg           int id, unsigned char *buf,
104404007ebaSmrg           short width, short height, Bool sync, RegionPtr clipBoxes,
104504007ebaSmrg           pointer data, DrawablePtr pDraw)
1046f29dbc25Smrg{
1047f29dbc25Smrg    GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
1048f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1049f29dbc25Smrg    int new_h;
1050f29dbc25Smrg
1051f29dbc25Smrg#if REINIT
1052f29dbc25Smrg    BOOL ReInitVideo = FALSE;
1053f29dbc25Smrg    static BOOL DoReinitAgain = 0;
1054f29dbc25Smrg#endif
1055f29dbc25Smrg
1056f29dbc25Smrg#if XV_PROFILE
1057f29dbc25Smrg    long oldtime, newtime;
1058f29dbc25Smrg
1059f29dbc25Smrg    UpdateCurrentTime();
1060f29dbc25Smrg    oldtime = currentTime.milliseconds;
1061f29dbc25Smrg#endif
1062f29dbc25Smrg
1063f29dbc25Smrg#if REINIT
1064f29dbc25Smrg/* update cliplist */
1065f29dbc25Smrg    if (!RegionsEqual(&pPriv->clip, clipBoxes)) {
106604007ebaSmrg        ReInitVideo = TRUE;
1067f29dbc25Smrg    }
1068f29dbc25Smrg
1069f29dbc25Smrg    if (DoReinitAgain)
107004007ebaSmrg        ReInitVideo = TRUE;
1071f29dbc25Smrg
1072f29dbc25Smrg    if (ReInitVideo) {
107304007ebaSmrg        DEBUGMSG(1, (0, X_NONE, "Regional Not Equal - Init\n"));
1074f29dbc25Smrg#endif
107504007ebaSmrg        DoReinitAgain = ~DoReinitAgain;
107604007ebaSmrg        if (drw_w > 16384)
107704007ebaSmrg            drw_w = 16384;
107804007ebaSmrg
107904007ebaSmrg        /* Clip */
108004007ebaSmrg        Bx1 = src_x;
108104007ebaSmrg        Bx2 = src_x + src_w;
108204007ebaSmrg        By1 = src_y;
108304007ebaSmrg        By2 = src_y + src_h;
108404007ebaSmrg
108504007ebaSmrg        if ((Bx1 >= Bx2) || (By1 >= By2))
108604007ebaSmrg            return Success;
108704007ebaSmrg
108804007ebaSmrg        dstBox.x1 = drw_x;
108904007ebaSmrg        dstBox.x2 = drw_x + drw_w;
109004007ebaSmrg        dstBox.y1 = drw_y;
109104007ebaSmrg        dstBox.y2 = drw_y + drw_h;
109204007ebaSmrg
109304007ebaSmrg        dstBox.x1 -= pScrni->frameX0;
109404007ebaSmrg        dstBox.x2 -= pScrni->frameX0;
109504007ebaSmrg        dstBox.y1 -= pScrni->frameY0;
109604007ebaSmrg        dstBox.y2 -= pScrni->frameY0;
109704007ebaSmrg
109804007ebaSmrg        switch (id) {
109904007ebaSmrg        case FOURCC_YV12:
110004007ebaSmrg        case FOURCC_I420:
110104007ebaSmrg            srcPitch = (width + 3) & ~3;        /* of luma */
110204007ebaSmrg            dstPitch = (width + 31) & ~31;
110304007ebaSmrg
110404007ebaSmrg            s2offset = srcPitch * height;
110504007ebaSmrg            d2offset = dstPitch * height;
110604007ebaSmrg
110704007ebaSmrg            srcPitch2 = ((width >> 1) + 3) & ~3;
110804007ebaSmrg            dstPitch2 = ((width >> 1) + 15) & ~15;
110904007ebaSmrg
111004007ebaSmrg            s3offset = (srcPitch2 * (height >> 1)) + s2offset;
111104007ebaSmrg            d3offset = (dstPitch2 * (height >> 1)) + d2offset;
111204007ebaSmrg
111304007ebaSmrg            new_h = dstPitch * height;  /* Y */
111404007ebaSmrg            new_h += (dstPitch2 * height);      /* U+V */
111504007ebaSmrg            new_h += pGeode->Pitch - 1;
111604007ebaSmrg            new_h /= pGeode->Pitch;
111704007ebaSmrg            break;
111804007ebaSmrg        case FOURCC_UYVY:
111904007ebaSmrg        case FOURCC_YUY2:
112004007ebaSmrg        case FOURCC_Y800:
112104007ebaSmrg        case FOURCC_RGB565:
112204007ebaSmrg        default:
112304007ebaSmrg            dstPitch = ((width << 1) + 3) & ~3;
112404007ebaSmrg            srcPitch = (width << 1);
112504007ebaSmrg            new_h = ((dstPitch * height) + pGeode->Pitch - 1) / pGeode->Pitch;
112604007ebaSmrg            break;
112704007ebaSmrg        }
1128f29dbc25Smrg#if DBUF
112904007ebaSmrg        if (pPriv->doubleBuffer)
113004007ebaSmrg            new_h <<= 1;
1131f29dbc25Smrg#endif
1132f29dbc25Smrg
113304007ebaSmrg        if (!(pPriv->offset = GXAllocateMemory(pScrni, &pPriv->area, new_h))) {
113404007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
113504007ebaSmrg                       "Could not allocate area of size %d\n", new_h);
113604007ebaSmrg            return BadAlloc;
113704007ebaSmrg        }
1138f29dbc25Smrg
113904007ebaSmrg        /* copy data */
114004007ebaSmrg        top = By1;
114104007ebaSmrg        left = Bx1 & ~1;
114204007ebaSmrg        npixels = ((Bx2 + 1) & ~1) - left;
1143f29dbc25Smrg
114404007ebaSmrg        switch (id) {
114504007ebaSmrg        case FOURCC_YV12:
114604007ebaSmrg        case FOURCC_I420:
114704007ebaSmrg        {
114804007ebaSmrg            int tmp;
1149f29dbc25Smrg
115004007ebaSmrg            top &= ~1;
1151f29dbc25Smrg
115204007ebaSmrg            offset = pPriv->offset + (top * dstPitch);
1153f29dbc25Smrg
1154f29dbc25Smrg#if DBUF
115504007ebaSmrg            if (pPriv->doubleBuffer && pPriv->currentBuffer)
115604007ebaSmrg                offset += (new_h >> 1) * pGeode->Pitch;
1157f29dbc25Smrg#endif
115804007ebaSmrg            dst_start = pGeode->FBBase + offset + left;
115904007ebaSmrg            tmp = ((top >> 1) * srcPitch2) + (left >> 1);
116004007ebaSmrg            s2offset += tmp;
116104007ebaSmrg            s3offset += tmp;
116204007ebaSmrg            if (id == FOURCC_I420) {
116304007ebaSmrg                tmp = s2offset;
116404007ebaSmrg                s2offset = s3offset;
116504007ebaSmrg                s3offset = tmp;
116604007ebaSmrg            }
116704007ebaSmrg            nlines = ((By2 + 1) & ~1) - top;
116804007ebaSmrg        }
116904007ebaSmrg            break;
117004007ebaSmrg        case FOURCC_UYVY:
117104007ebaSmrg        case FOURCC_YUY2:
117204007ebaSmrg        case FOURCC_Y800:
117304007ebaSmrg        case FOURCC_RGB565:
117404007ebaSmrg        default:
117504007ebaSmrg            left <<= 1;
117604007ebaSmrg            buf += (top * srcPitch) + left;
117704007ebaSmrg            nlines = By2 - top;
117804007ebaSmrg            offset = (pPriv->offset) + (top * dstPitch);
1179f29dbc25Smrg
1180f29dbc25Smrg#if DBUF
118104007ebaSmrg            if (pPriv->doubleBuffer && pPriv->currentBuffer)
118204007ebaSmrg                offset += (new_h >> 1) * pGeode->Pitch;
1183f29dbc25Smrg#endif
118404007ebaSmrg            dst_start = pGeode->FBBase + offset + left;
118504007ebaSmrg            break;
118604007ebaSmrg        }
118704007ebaSmrg        s1offset = (top * srcPitch) + left;
1188f29dbc25Smrg#if REINIT
118904007ebaSmrg        /* update cliplist */
119004007ebaSmrg        REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes);
1191f29dbc25Smrg
119204007ebaSmrg        if (pPriv->colorKeyMode == 0) {
119304007ebaSmrg            xf86XVFillKeyHelper(pScrni->pScreen, pPriv->colorKey, clipBoxes);
119404007ebaSmrg        }
1195f29dbc25Smrg
119604007ebaSmrg        GXDisplayVideo(pScrni, id, offset, width, height, dstPitch,
119704007ebaSmrg                       Bx1, By1, Bx2, By2, &dstBox, src_w, src_h, drw_w, drw_h);
1198f29dbc25Smrg    }
1199f29dbc25Smrg#endif
1200f29dbc25Smrg    switch (id) {
1201f29dbc25Smrg    case FOURCC_Y800:
120204007ebaSmrg        /* This is shared between LX and GX, so it lives in amd_common.c */
120304007ebaSmrg        GeodeCopyGreyscale(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
120404007ebaSmrg        break;
1205f29dbc25Smrg    case FOURCC_YV12:
1206f29dbc25Smrg    case FOURCC_I420:
120704007ebaSmrg        GXCopyData420(buf + s1offset, dst_start, srcPitch, dstPitch, nlines,
120804007ebaSmrg                      npixels);
120904007ebaSmrg        GXCopyData420(buf + s2offset, dst_start + d2offset, srcPitch2,
121004007ebaSmrg                      dstPitch2, nlines >> 1, npixels >> 1);
121104007ebaSmrg        GXCopyData420(buf + s3offset, dst_start + d3offset, srcPitch2,
121204007ebaSmrg                      dstPitch2, nlines >> 1, npixels >> 1);
121304007ebaSmrg        break;
1214f29dbc25Smrg    case FOURCC_UYVY:
1215f29dbc25Smrg    case FOURCC_YUY2:
1216f29dbc25Smrg    case FOURCC_RGB565:
1217f29dbc25Smrg    default:
121804007ebaSmrg        GXCopyData422(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
121904007ebaSmrg        break;
1220f29dbc25Smrg    }
1221f29dbc25Smrg#if !REINIT
1222f29dbc25Smrg    /* update cliplist */
1223f29dbc25Smrg    REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes);
1224f29dbc25Smrg    if (pPriv->colorKeyMode == 0) {
122504007ebaSmrg        /* draw these */
122604007ebaSmrg        XAAFillSolidRects(pScrni, pPriv->colorKey, GXcopy, ~0,
122704007ebaSmrg                          REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes));
1228f29dbc25Smrg    }
1229f29dbc25Smrg
1230f29dbc25Smrg    GXDisplayVideo(pScrni, id, offset, width, height, dstPitch,
123104007ebaSmrg                   Bx1, By1, Bx2, By2, &dstBox, src_w, src_h, drw_w, drw_h);
1232f29dbc25Smrg#endif
1233f29dbc25Smrg
1234f29dbc25Smrg#if XV_PROFILE
1235f29dbc25Smrg    UpdateCurrentTime();
1236f29dbc25Smrg    newtime = currentTime.milliseconds;
1237f29dbc25Smrg    DEBUGMSG(1, (0, X_NONE, "PI %d\n", newtime - oldtime));
1238f29dbc25Smrg#endif
1239f29dbc25Smrg
1240f29dbc25Smrg#if DBUF
1241f29dbc25Smrg    pPriv->currentBuffer ^= 1;
1242f29dbc25Smrg#endif
1243f29dbc25Smrg
1244f29dbc25Smrg    pPriv->videoStatus = CLIENT_VIDEO_ON;
1245f29dbc25Smrg    pGeode->OverlayON = TRUE;
1246f29dbc25Smrg    return Success;
1247f29dbc25Smrg}
1248f29dbc25Smrg
1249f29dbc25Smrg/*----------------------------------------------------------------------------
1250f29dbc25Smrg * GXQueryImageAttributes
1251f29dbc25Smrg *
1252f29dbc25Smrg * Description	:This function is called to let the driver specify how data
1253f29dbc25Smrg *				 for a particular image of size width by height should be
1254f29dbc25Smrg *				 stored.
1255f29dbc25Smrg *
1256f29dbc25Smrg * Parameters.
1257f29dbc25Smrg *		pScrni	:Screen handler pointer having screen information.
1258f29dbc25Smrg *		id		:Id for the video format
1259f29dbc25Smrg *		width	:width  of the image (can be modified by the driver)
1260f29dbc25Smrg *		height	:height of the image (can be modified by the driver)
1261f29dbc25Smrg * Returns		: Size of the memory required for storing this image
1262f29dbc25Smrg *
1263f29dbc25Smrg * Comments		:None
1264f29dbc25Smrg *
1265f29dbc25Smrg *----------------------------------------------------------------------------
1266f29dbc25Smrg */
1267f29dbc25Smrg
1268f29dbc25Smrgint
1269f29dbc25SmrgGeodeQueryImageAttributes(ScrnInfoPtr pScrni,
127004007ebaSmrg                          int id, unsigned short *w, unsigned short *h,
127104007ebaSmrg                          int *pitches, int *offsets)
1272f29dbc25Smrg{
1273f29dbc25Smrg    int size;
1274f29dbc25Smrg    int tmp;
1275f29dbc25Smrg
1276f29dbc25Smrg    DEBUGMSG(0, (0, X_NONE, "QueryImageAttributes %X\n", id));
1277f29dbc25Smrg
1278f29dbc25Smrg    if (*w > 1024)
127904007ebaSmrg        *w = 1024;
1280f29dbc25Smrg    if (*h > 1024)
128104007ebaSmrg        *h = 1024;
1282f29dbc25Smrg
1283f29dbc25Smrg    *w = (*w + 1) & ~1;
1284f29dbc25Smrg    if (offsets)
128504007ebaSmrg        offsets[0] = 0;
1286f29dbc25Smrg
1287f29dbc25Smrg    switch (id) {
1288f29dbc25Smrg    case FOURCC_YV12:
1289f29dbc25Smrg    case FOURCC_I420:
129004007ebaSmrg        *h = (*h + 1) & ~1;
129104007ebaSmrg        size = (*w + 3) & ~3;
129204007ebaSmrg        if (pitches)
129304007ebaSmrg            pitches[0] = size;
129404007ebaSmrg
129504007ebaSmrg        size *= *h;
129604007ebaSmrg        if (offsets)
129704007ebaSmrg            offsets[1] = size;
129804007ebaSmrg
129904007ebaSmrg        tmp = ((*w >> 1) + 3) & ~3;
130004007ebaSmrg        if (pitches)
130104007ebaSmrg            pitches[1] = pitches[2] = tmp;
130204007ebaSmrg
130304007ebaSmrg        tmp *= (*h >> 1);
130404007ebaSmrg        size += tmp;
130504007ebaSmrg        if (offsets)
130604007ebaSmrg            offsets[2] = size;
130704007ebaSmrg
130804007ebaSmrg        size += tmp;
130904007ebaSmrg        break;
1310f29dbc25Smrg    case FOURCC_UYVY:
1311f29dbc25Smrg    case FOURCC_YUY2:
1312f29dbc25Smrg    case FOURCC_Y800:
1313f29dbc25Smrg    default:
131404007ebaSmrg        size = *w << 1;
131504007ebaSmrg        if (pitches)
131604007ebaSmrg            pitches[0] = size;
1317f29dbc25Smrg
131804007ebaSmrg        size *= *h;
131904007ebaSmrg        break;
1320f29dbc25Smrg    }
1321f29dbc25Smrg    return size;
1322f29dbc25Smrg}
1323f29dbc25Smrg
1324f29dbc25Smrgstatic void
132504007ebaSmrgGXBlockHandler(BLOCKHANDLER_ARGS_DECL)
1326f29dbc25Smrg{
132704007ebaSmrg    SCREEN_PTR(arg);
132804007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
1329f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1330f29dbc25Smrg    GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni);
1331f29dbc25Smrg
1332f29dbc25Smrg    pScrn->BlockHandler = pGeode->BlockHandler;
133304007ebaSmrg    (*pScrn->BlockHandler) (BLOCKHANDLER_ARGS);
1334f29dbc25Smrg    pScrn->BlockHandler = GXBlockHandler;
1335f29dbc25Smrg
1336f29dbc25Smrg    if (pPriv->videoStatus & TIMER_MASK) {
133704007ebaSmrg        GXAccelSync(pScrni);
133804007ebaSmrg        UpdateCurrentTime();
133904007ebaSmrg        if (pPriv->videoStatus & OFF_TIMER) {
134004007ebaSmrg            if (pPriv->offTime < currentTime.milliseconds) {
134104007ebaSmrg                GFX(set_video_enable(0));
134204007ebaSmrg
134304007ebaSmrg                /* If we have saved graphics LUT data - restore it */
134404007ebaSmrg                /* Otherwise, turn bypass on */
134504007ebaSmrg
134604007ebaSmrg                if (lutflag)
134704007ebaSmrg                    GFX(set_graphics_palette(graphics_lut));
134804007ebaSmrg                else
134904007ebaSmrg                    GFX(set_video_palette_bypass(1));
135004007ebaSmrg
135104007ebaSmrg                lutflag = 0;
135204007ebaSmrg
135304007ebaSmrg                pPriv->videoStatus = FREE_TIMER;
135404007ebaSmrg                pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
135504007ebaSmrg            }
135604007ebaSmrg        }
135704007ebaSmrg        else {                  /* FREE_TIMER */
135804007ebaSmrg            if (pPriv->freeTime < currentTime.milliseconds) {
135904007ebaSmrg
136004007ebaSmrg                if (pPriv->area) {
1361f29dbc25Smrg#ifdef XF86EXA
136204007ebaSmrg                    if (pGeode->useEXA)
136304007ebaSmrg                        exaOffscreenFree(pScrn, pPriv->area);
1364f29dbc25Smrg#endif
136504007ebaSmrg                    if (!pGeode->useEXA)
136604007ebaSmrg                        xf86FreeOffscreenArea(pPriv->area);
1367f29dbc25Smrg
136804007ebaSmrg                    pPriv->area = NULL;
136904007ebaSmrg                }
1370f29dbc25Smrg
137104007ebaSmrg                pPriv->videoStatus = 0;
137204007ebaSmrg            }
137304007ebaSmrg        }
1374f29dbc25Smrg    }
1375f29dbc25Smrg}
1376f29dbc25Smrg
1377f29dbc25Smrg/****************** Offscreen stuff ***************/
1378f29dbc25Smrg
137904007ebaSmrgtypedef struct {
1380f29dbc25Smrg    void *area;
1381f29dbc25Smrg    int offset;
1382f29dbc25Smrg    Bool isOn;
1383f29dbc25Smrg} OffscreenPrivRec, *OffscreenPrivPtr;
1384f29dbc25Smrg
1385f29dbc25Smrg/*----------------------------------------------------------------------------
1386f29dbc25Smrg * GXAllocateSurface
1387f29dbc25Smrg *
1388f29dbc25Smrg * Description	:This function allocates an area of w by h in the offscreen
1389f29dbc25Smrg *
1390f29dbc25Smrg * Parameters.
1391f29dbc25Smrg *		pScrni	:Screen handler pointer having screen information.
1392f29dbc25Smrg *
1393f29dbc25Smrg * Returns		:None
1394f29dbc25Smrg *
1395f29dbc25Smrg * Comments		:None
1396f29dbc25Smrg *----------------------------------------------------------------------------
1397f29dbc25Smrg */
1398f29dbc25Smrgstatic int
1399f29dbc25SmrgGXAllocateSurface(ScrnInfoPtr pScrni,
140004007ebaSmrg                  int id, unsigned short w, unsigned short h,
140104007ebaSmrg                  XF86SurfacePtr surface)
1402f29dbc25Smrg{
1403f29dbc25Smrg    void *area = NULL;
1404f29dbc25Smrg    int pitch, fbpitch, numlines;
1405f29dbc25Smrg    OffscreenPrivRec *pPriv;
1406f29dbc25Smrg
1407f29dbc25Smrg    if ((w > 1024) || (h > 1024))
140804007ebaSmrg        return BadAlloc;
1409f29dbc25Smrg
1410f29dbc25Smrg    w = (w + 1) & ~1;
1411f29dbc25Smrg    pitch = ((w << 1) + 15) & ~15;
1412f29dbc25Smrg    fbpitch = pScrni->bitsPerPixel * pScrni->displayWidth >> 3;
1413f29dbc25Smrg    numlines = ((pitch * h) + fbpitch - 1) / fbpitch;
1414f29dbc25Smrg
1415f29dbc25Smrg    if (!(offset = GXAllocateMemory(pScrni, &area, numlines)))
141604007ebaSmrg        return BadAlloc;
1417f29dbc25Smrg
1418f29dbc25Smrg    surface->width = w;
1419f29dbc25Smrg    surface->height = h;
1420f29dbc25Smrg
1421170d5fdcSmrg    if (!(surface->pitches = malloc(sizeof(int))))
142204007ebaSmrg        return BadAlloc;
1423f29dbc25Smrg
1424170d5fdcSmrg    if (!(surface->offsets = malloc(sizeof(int)))) {
142504007ebaSmrg        free(surface->pitches);
142604007ebaSmrg        return BadAlloc;
1427f29dbc25Smrg    }
1428f29dbc25Smrg
1429170d5fdcSmrg    if (!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
143004007ebaSmrg        free(surface->pitches);
143104007ebaSmrg        free(surface->offsets);
143204007ebaSmrg        return BadAlloc;
1433f29dbc25Smrg    }
1434f29dbc25Smrg
1435f29dbc25Smrg    pPriv->area = area;
1436f29dbc25Smrg    pPriv->offset = offset;
1437f29dbc25Smrg
1438f29dbc25Smrg    pPriv->isOn = FALSE;
1439f29dbc25Smrg
1440f29dbc25Smrg    surface->pScrn = pScrni;
1441f29dbc25Smrg    surface->id = id;
1442f29dbc25Smrg    surface->pitches[0] = pitch;
1443f29dbc25Smrg    surface->offsets[0] = offset;
1444f29dbc25Smrg    surface->devPrivate.ptr = (pointer) pPriv;
1445f29dbc25Smrg
1446f29dbc25Smrg    return Success;
1447f29dbc25Smrg}
1448f29dbc25Smrg
1449f29dbc25Smrgstatic int
1450f29dbc25SmrgGXStopSurface(XF86SurfacePtr surface)
1451f29dbc25Smrg{
1452f29dbc25Smrg    OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr;
1453f29dbc25Smrg
1454f29dbc25Smrg    if (pPriv->isOn) {
145504007ebaSmrg        pPriv->isOn = FALSE;
1456f29dbc25Smrg    }
1457f29dbc25Smrg
1458f29dbc25Smrg    return Success;
1459f29dbc25Smrg}
1460f29dbc25Smrg
1461f29dbc25Smrgstatic int
1462f29dbc25SmrgGXFreeSurface(XF86SurfacePtr surface)
1463f29dbc25Smrg{
1464f29dbc25Smrg    OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr;
1465f29dbc25Smrg
1466f29dbc25Smrg    if (pPriv->isOn)
146704007ebaSmrg        GXStopSurface(surface);
1468f29dbc25Smrg
1469f29dbc25Smrg    xf86FreeOffscreenArea(pPriv->area);
1470170d5fdcSmrg    free(surface->pitches);
1471170d5fdcSmrg    free(surface->offsets);
1472170d5fdcSmrg    free(surface->devPrivate.ptr);
1473f29dbc25Smrg
1474f29dbc25Smrg    return Success;
1475f29dbc25Smrg}
1476f29dbc25Smrg
1477f29dbc25Smrgstatic int
147804007ebaSmrgGXGetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 *value)
1479f29dbc25Smrg{
1480f29dbc25Smrg    return GXGetPortAttribute(pScrni, attribute, value,
148104007ebaSmrg                              (pointer) (GET_PORT_PRIVATE(pScrni)));
1482f29dbc25Smrg}
1483f29dbc25Smrg
1484f29dbc25Smrgstatic int
1485f29dbc25SmrgGXSetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 value)
1486f29dbc25Smrg{
1487f29dbc25Smrg    return GXSetPortAttribute(pScrni, attribute, value,
148804007ebaSmrg                              (pointer) (GET_PORT_PRIVATE(pScrni)));
1489f29dbc25Smrg}
1490f29dbc25Smrg
1491f29dbc25Smrgstatic int
1492f29dbc25SmrgGXDisplaySurface(XF86SurfacePtr surface,
149304007ebaSmrg                 short src_x, short src_y,
149404007ebaSmrg                 short drw_x, short drw_y,
149504007ebaSmrg                 short src_w, short src_h, short drw_w, short drw_h,
149604007ebaSmrg                 RegionPtr clipBoxes)
1497f29dbc25Smrg{
1498f29dbc25Smrg    OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr;
1499f29dbc25Smrg    ScrnInfoPtr pScrni = surface->pScrn;
1500f29dbc25Smrg    GeodePortPrivRec *portPriv = GET_PORT_PRIVATE(pScrni);
1501f29dbc25Smrg    INT32 x1, y1, x2, y2;
1502f29dbc25Smrg    BoxRec dstBox;
1503f29dbc25Smrg
1504f29dbc25Smrg    DEBUGMSG(0, (0, X_NONE, "DisplaySuface\n"));
1505f29dbc25Smrg    x1 = src_x;
1506f29dbc25Smrg    x2 = src_x + src_w;
1507f29dbc25Smrg    y1 = src_y;
1508f29dbc25Smrg    y2 = src_y + src_h;
1509f29dbc25Smrg
1510f29dbc25Smrg    dstBox.x1 = drw_x;
1511f29dbc25Smrg    dstBox.x2 = drw_x + drw_w;
1512f29dbc25Smrg    dstBox.y1 = drw_y;
1513f29dbc25Smrg    dstBox.y2 = drw_y + drw_h;
1514f29dbc25Smrg
1515f29dbc25Smrg    if ((x1 >= x2) || (y1 >= y2))
151604007ebaSmrg        return Success;
1517f29dbc25Smrg
1518f29dbc25Smrg    dstBox.x1 -= pScrni->frameX0;
1519f29dbc25Smrg    dstBox.x2 -= pScrni->frameX0;
1520f29dbc25Smrg    dstBox.y1 -= pScrni->frameY0;
1521f29dbc25Smrg    dstBox.y2 -= pScrni->frameY0;
1522f29dbc25Smrg
1523f29dbc25Smrg    xf86XVFillKeyHelper(pScrni->pScreen, portPriv->colorKey, clipBoxes);
1524f29dbc25Smrg
1525f29dbc25Smrg    GXDisplayVideo(pScrni, surface->id, surface->offsets[0],
152604007ebaSmrg                   surface->width, surface->height, surface->pitches[0],
152704007ebaSmrg                   x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
1528f29dbc25Smrg
1529f29dbc25Smrg    pPriv->isOn = TRUE;
1530f29dbc25Smrg    if (portPriv->videoStatus & CLIENT_VIDEO_ON) {
153104007ebaSmrg        REGION_EMPTY(pScrni->pScreen, &portPriv->clip);
153204007ebaSmrg        UpdateCurrentTime();
153304007ebaSmrg        portPriv->videoStatus = FREE_TIMER;
153404007ebaSmrg        portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
1535f29dbc25Smrg    }
1536f29dbc25Smrg
1537f29dbc25Smrg    return Success;
1538f29dbc25Smrg}
1539f29dbc25Smrg
1540f29dbc25Smrg/*----------------------------------------------------------------------------
1541f29dbc25Smrg * GXInitOffscreenImages
1542f29dbc25Smrg *
1543f29dbc25Smrg * Description	:This function sets up the offscreen memory management. It
1544f29dbc25Smrg * 				fills in the XF86OffscreenImagePtr structure with functions to
1545f29dbc25Smrg * 				handle offscreen memory operations.
1546f29dbc25Smrg *
1547f29dbc25Smrg * Parameters.
1548f29dbc25Smrg *		pScrn	:Screen handler pointer having screen information.
1549f29dbc25Smrg *
1550f29dbc25Smrg * Returns		: None
1551f29dbc25Smrg *
1552f29dbc25Smrg * Comments		:None
1553f29dbc25Smrg *----------------------------------------------------------------------------
1554f29dbc25Smrg */
1555f29dbc25Smrgstatic void
1556f29dbc25SmrgGXInitOffscreenImages(ScreenPtr pScrn)
1557f29dbc25Smrg{
1558f29dbc25Smrg    XF86OffscreenImagePtr offscreenImages;
1559f29dbc25Smrg
1560f29dbc25Smrg    /* need to free this someplace */
1561170d5fdcSmrg    if (!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec))))
156204007ebaSmrg        return;
1563f29dbc25Smrg
1564f29dbc25Smrg    offscreenImages[0].image = &Images[0];
1565f29dbc25Smrg    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
1566f29dbc25Smrg    offscreenImages[0].alloc_surface = GXAllocateSurface;
1567f29dbc25Smrg    offscreenImages[0].free_surface = GXFreeSurface;
1568f29dbc25Smrg    offscreenImages[0].display = GXDisplaySurface;
1569f29dbc25Smrg    offscreenImages[0].stop = GXStopSurface;
1570f29dbc25Smrg    offscreenImages[0].setAttribute = GXSetSurfaceAttribute;
1571f29dbc25Smrg    offscreenImages[0].getAttribute = GXGetSurfaceAttribute;
1572f29dbc25Smrg    offscreenImages[0].max_width = 1024;
1573f29dbc25Smrg    offscreenImages[0].max_height = 1024;
1574f29dbc25Smrg    offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
1575f29dbc25Smrg    offscreenImages[0].attributes = Attributes;
1576f29dbc25Smrg
1577f29dbc25Smrg    xf86XVRegisterOffscreenImages(pScrn, offscreenImages, 1);
1578f29dbc25Smrg}
1579f29dbc25Smrg
158004007ebaSmrg#endif                          /* !XvExtension */
1581