gx_video.c revision f29dbc25
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>
57f29dbc25Smrg#include "xaa.h"
58f29dbc25Smrg#include "xaalocal.h"
59f29dbc25Smrg#include "dixstruct.h"
60f29dbc25Smrg#include "fourcc.h"
61f29dbc25Smrg#include "geode_fourcc.h"
62f29dbc25Smrg
63f29dbc25Smrg#define OFF_DELAY 		200    /* milliseconds */
64f29dbc25Smrg#define FREE_DELAY 		60000
65f29dbc25Smrg
66f29dbc25Smrg#define OFF_TIMER 		0x01
67f29dbc25Smrg#define FREE_TIMER		0x02
68f29dbc25Smrg#define CLIENT_VIDEO_ON	0x04
69f29dbc25Smrg
70f29dbc25Smrg#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
71f29dbc25Smrg#define XV_PROFILE 		0
72f29dbc25Smrg#define REINIT  		1
73f29dbc25Smrg
74f29dbc25Smrg#ifndef XvExtension
75f29dbc25Smrg#error "It didn't work!"
76f29dbc25Smrgvoid
77f29dbc25SmrgGXInitVideo(ScreenPtr pScrn)
78f29dbc25Smrg{
79f29dbc25Smrg}
80f29dbc25Smrg
81f29dbc25Smrgvoid
82f29dbc25SmrgGXResetVideo(ScrnInfoPtr pScrni)
83f29dbc25Smrg{
84f29dbc25Smrg}
85f29dbc25Smrg
86f29dbc25Smrgvoid
87f29dbc25SmrgGXSetVideoPosition()
88f29dbc25Smrg{
89f29dbc25Smrg}
90f29dbc25Smrg#else
91f29dbc25Smrg
92f29dbc25Smrg#define DBUF 1
93f29dbc25Smrgvoid GXResetVideo(ScrnInfoPtr pScrni);
94f29dbc25Smrgstatic XF86VideoAdaptorPtr GXSetupImageVideo(ScreenPtr);
95f29dbc25Smrgstatic void GXInitOffscreenImages(ScreenPtr);
96f29dbc25Smrgstatic void GXStopVideo(ScrnInfoPtr, pointer, Bool);
97f29dbc25Smrgstatic int GXSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
98f29dbc25Smrgstatic int GXGetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
99f29dbc25Smrgstatic void GXQueryBestSize(ScrnInfoPtr, Bool,
100f29dbc25Smrg    short, short, short, short, unsigned int *, unsigned int *, pointer);
101f29dbc25Smrgstatic int GXPutImage(ScrnInfoPtr, short, short, short, short, short, short,
102f29dbc25Smrg    short, short, int, unsigned char *, short, short, Bool,
103f29dbc25Smrg    RegionPtr, pointer, DrawablePtr pDraw);
104f29dbc25Smrg
105f29dbc25Smrgstatic void GXBlockHandler(int, pointer, pointer, pointer);
106f29dbc25Smrgvoid GXSetVideoPosition(int x, int y, int width, int height,
107f29dbc25Smrg    short src_w, short src_h, short drw_w,
108f29dbc25Smrg    short drw_h, int id, int offset, ScrnInfoPtr pScrni);
109f29dbc25Smrg
110f29dbc25Smrgextern void GXAccelSync(ScrnInfoPtr pScrni);
111f29dbc25Smrg
112f29dbc25Smrgint DeltaX, DeltaY;
113f29dbc25Smrg
114f29dbc25Smrgunsigned long graphics_lut[256];
115f29dbc25Smrgstatic int lutflag = 0;
116f29dbc25Smrg
117f29dbc25Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
118f29dbc25Smrg
119f29dbc25Smrgstatic Atom xvColorKey, xvColorKeyMode, xvFilter
120f29dbc25Smrg#if DBUF
121f29dbc25Smrg   , xvDoubleBuffer
122f29dbc25Smrg#endif
123f29dbc25Smrg   ;
124f29dbc25Smrg
125f29dbc25Smrg#define PALETTE_ADDRESS   0x038
126f29dbc25Smrg#define PALETTE_DATA      0x040
127f29dbc25Smrg#define DISPLAY_CONFIG    0x008
128f29dbc25Smrg#define MISC              0x050
129f29dbc25Smrg
130f29dbc25Smrgstatic void
131f29dbc25Smrgget_gamma_ram(unsigned long *lut)
132f29dbc25Smrg{
133f29dbc25Smrg
134f29dbc25Smrg    int i;
135f29dbc25Smrg
136f29dbc25Smrg    gfx_write_vid32(PALETTE_ADDRESS, 0);
137f29dbc25Smrg
138f29dbc25Smrg    for (i = 0; i < 256; i++)
139f29dbc25Smrg	lut[i] = gfx_read_vid32(PALETTE_DATA);
140f29dbc25Smrg}
141f29dbc25Smrg
142f29dbc25Smrg/*----------------------------------------------------------------------------
143f29dbc25Smrg * GXInitVideo
144f29dbc25Smrg *
145f29dbc25Smrg * Description	:This is the initialization routine.It creates a new video
146f29dbc25Smrg * 				adapter and calls GXSetupImageVideo to initialize the adaptor
147f29dbc25Smrg * 				by filling XF86VideoAdaptorREc.Then it lists the existing
148f29dbc25Smrg * 				adaptors and adds the new one to it. Finally the list of
149f29dbc25Smrg * 				XF86VideoAdaptorPtr pointers are passed to the
150f29dbc25Smrg * 				xf86XVScreenInit().
151f29dbc25Smrg *
152f29dbc25Smrg * Parameters.
153f29dbc25Smrg *		pScrn	:Screen handler pointer having screen information.
154f29dbc25Smrg *
155f29dbc25Smrg * Returns		:none
156f29dbc25Smrg *
157f29dbc25Smrg * Comments		:none
158f29dbc25Smrg *----------------------------------------------------------------------------
159f29dbc25Smrg */
160f29dbc25Smrgvoid
161f29dbc25SmrgGXInitVideo(ScreenPtr pScrn)
162f29dbc25Smrg{
163f29dbc25Smrg    GeodeRec *pGeode;
164f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[pScrn->myNum];
165f29dbc25Smrg
166f29dbc25Smrg    pGeode = GEODEPTR(pScrni);
167f29dbc25Smrg
168f29dbc25Smrg    if (!pGeode->NoAccel) {
169f29dbc25Smrg	XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
170f29dbc25Smrg	XF86VideoAdaptorPtr newAdaptor = NULL;
171f29dbc25Smrg
172f29dbc25Smrg	int num_adaptors;
173f29dbc25Smrg
174f29dbc25Smrg	newAdaptor = GXSetupImageVideo(pScrn);
175f29dbc25Smrg	GXInitOffscreenImages(pScrn);
176f29dbc25Smrg
177f29dbc25Smrg	num_adaptors = xf86XVListGenericAdaptors(pScrni, &adaptors);
178f29dbc25Smrg
179f29dbc25Smrg	if (newAdaptor) {
180f29dbc25Smrg	    if (!num_adaptors) {
181f29dbc25Smrg		num_adaptors = 1;
182f29dbc25Smrg		adaptors = &newAdaptor;
183f29dbc25Smrg	    } else {
184f29dbc25Smrg		newAdaptors =	       /* need to free this someplace */
185f29dbc25Smrg		    xalloc((num_adaptors +
186f29dbc25Smrg			1) * sizeof(XF86VideoAdaptorPtr *));
187f29dbc25Smrg		if (newAdaptors) {
188f29dbc25Smrg		    memcpy(newAdaptors, adaptors, num_adaptors *
189f29dbc25Smrg			sizeof(XF86VideoAdaptorPtr));
190f29dbc25Smrg		    newAdaptors[num_adaptors] = newAdaptor;
191f29dbc25Smrg		    adaptors = newAdaptors;
192f29dbc25Smrg		    num_adaptors++;
193f29dbc25Smrg		}
194f29dbc25Smrg	    }
195f29dbc25Smrg	}
196f29dbc25Smrg
197f29dbc25Smrg	if (num_adaptors)
198f29dbc25Smrg	    xf86XVScreenInit(pScrn, adaptors, num_adaptors);
199f29dbc25Smrg
200f29dbc25Smrg	if (newAdaptors)
201f29dbc25Smrg	    xfree(newAdaptors);
202f29dbc25Smrg    }
203f29dbc25Smrg}
204f29dbc25Smrg
205f29dbc25Smrg/* client libraries expect an encoding */
206f29dbc25Smrgstatic XF86VideoEncodingRec DummyEncoding[1] = {
207f29dbc25Smrg    {
208f29dbc25Smrg	    0,
209f29dbc25Smrg	    "XV_IMAGE",
210f29dbc25Smrg	    1024, 1024,
211f29dbc25Smrg	    {1, 1}
212f29dbc25Smrg	}
213f29dbc25Smrg};
214f29dbc25Smrg
215f29dbc25Smrg#define NUM_FORMATS 4
216f29dbc25Smrg
217f29dbc25Smrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] = {
218f29dbc25Smrg    {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
219f29dbc25Smrg};
220f29dbc25Smrg
221f29dbc25Smrg#if DBUF
222f29dbc25Smrg#define NUM_ATTRIBUTES 4
223f29dbc25Smrg#else
224f29dbc25Smrg#define NUM_ATTRIBUTES 3
225f29dbc25Smrg#endif
226f29dbc25Smrg
227f29dbc25Smrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {
228f29dbc25Smrg#if DBUF
229f29dbc25Smrg    {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
230f29dbc25Smrg#endif
231f29dbc25Smrg    {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
232f29dbc25Smrg    {XvSettable | XvGettable, 0, 1, "XV_FILTER"},
233f29dbc25Smrg    {XvSettable | XvGettable, 0, 1, "XV_COLORKEYMODE"}
234f29dbc25Smrg};
235f29dbc25Smrg
236f29dbc25Smrg#define NUM_IMAGES 8
237f29dbc25Smrg
238f29dbc25Smrgstatic XF86ImageRec Images[NUM_IMAGES] = {
239f29dbc25Smrg    XVIMAGE_UYVY,
240f29dbc25Smrg    XVIMAGE_YUY2,
241f29dbc25Smrg    XVIMAGE_Y2YU,
242f29dbc25Smrg    XVIMAGE_YVYU,
243f29dbc25Smrg    XVIMAGE_Y800,
244f29dbc25Smrg    XVIMAGE_I420,
245f29dbc25Smrg    XVIMAGE_YV12,
246f29dbc25Smrg    XVIMAGE_RGB565
247f29dbc25Smrg};
248f29dbc25Smrg
249f29dbc25Smrgtypedef struct
250f29dbc25Smrg{
251f29dbc25Smrg    void *area;
252f29dbc25Smrg    int offset;
253f29dbc25Smrg    RegionRec clip;
254f29dbc25Smrg    CARD32 filter;
255f29dbc25Smrg    CARD32 colorKey;
256f29dbc25Smrg    CARD32 colorKeyMode;
257f29dbc25Smrg    CARD32 videoStatus;
258f29dbc25Smrg    Time offTime;
259f29dbc25Smrg    Time freeTime;
260f29dbc25Smrg#if DBUF
261f29dbc25Smrg    Bool doubleBuffer;
262f29dbc25Smrg    int currentBuffer;
263f29dbc25Smrg#endif
264f29dbc25Smrg} GeodePortPrivRec, *GeodePortPrivPtr;
265f29dbc25Smrg
266f29dbc25Smrg#define GET_PORT_PRIVATE(pScrni) \
267f29dbc25Smrg   (GeodePortPrivRec *)((GEODEPTR(pScrni))->adaptor->pPortPrivates[0].ptr)
268f29dbc25Smrg
269f29dbc25Smrg/*----------------------------------------------------------------------------
270f29dbc25Smrg * GXSetColorKey
271f29dbc25Smrg *
272f29dbc25Smrg * Description	:This function reads the color key for the pallete and
273f29dbc25Smrg *				  sets the video color key register.
274f29dbc25Smrg *
275f29dbc25Smrg * Parameters.
276f29dbc25Smrg * ScreenInfoPtr
277f29dbc25Smrg *		pScrni	:Screen  pointer having screen information.
278f29dbc25Smrg *		pPriv	:Video port private data
279f29dbc25Smrg *
280f29dbc25Smrg * Returns		:none
281f29dbc25Smrg *
282f29dbc25Smrg * Comments		:none
283f29dbc25Smrg *
284f29dbc25Smrg *----------------------------------------------------------------------------
285f29dbc25Smrg */
286f29dbc25Smrgstatic INT32
287f29dbc25SmrgGXSetColorkey(ScrnInfoPtr pScrni, GeodePortPrivRec * pPriv)
288f29dbc25Smrg{
289f29dbc25Smrg    int red, green, blue;
290f29dbc25Smrg    unsigned long key;
291f29dbc25Smrg
292f29dbc25Smrg    switch (pScrni->depth) {
293f29dbc25Smrg    case 8:
294f29dbc25Smrg	GFX(get_display_palette_entry(pPriv->colorKey & 0xFF, &key));
295f29dbc25Smrg	red = ((key >> 16) & 0xFF);
296f29dbc25Smrg	green = ((key >> 8) & 0xFF);
297f29dbc25Smrg	blue = (key & 0xFF);
298f29dbc25Smrg	break;
299f29dbc25Smrg    case 16:
300f29dbc25Smrg	red = (pPriv->colorKey & pScrni->mask.red) >>
301f29dbc25Smrg	    pScrni->offset.red << (8 - pScrni->weight.red);
302f29dbc25Smrg	green = (pPriv->colorKey & pScrni->mask.green) >>
303f29dbc25Smrg	    pScrni->offset.green << (8 - pScrni->weight.green);
304f29dbc25Smrg	blue = (pPriv->colorKey & pScrni->mask.blue) >>
305f29dbc25Smrg	    pScrni->offset.blue << (8 - pScrni->weight.blue);
306f29dbc25Smrg	break;
307f29dbc25Smrg    default:
308f29dbc25Smrg	/* for > 16 bpp we send in the mask in xf86SetWeight. This
309f29dbc25Smrg	 * function is providing the offset by 1 more. So we take
310f29dbc25Smrg	 * this as a special case and subtract 1 for > 16
311f29dbc25Smrg	 */
312f29dbc25Smrg	red = (pPriv->colorKey & pScrni->mask.red) >>
313f29dbc25Smrg	    (pScrni->offset.red - 1) << (8 - pScrni->weight.red);
314f29dbc25Smrg	green = (pPriv->colorKey & pScrni->mask.green) >>
315f29dbc25Smrg	    (pScrni->offset.green - 1) << (8 - pScrni->weight.green);
316f29dbc25Smrg	blue = (pPriv->colorKey & pScrni->mask.blue) >>
317f29dbc25Smrg	    (pScrni->offset.blue - 1) << (8 - pScrni->weight.blue);
318f29dbc25Smrg	break;
319f29dbc25Smrg    }
320f29dbc25Smrg
321f29dbc25Smrg    GFX(set_video_color_key((blue | (green << 8) | (red << 16)), 0xFFFFFF,
322f29dbc25Smrg	    (pPriv->colorKeyMode == 0)));
323f29dbc25Smrg    REGION_EMPTY(pScrni->pScreen, &pPriv->clip);
324f29dbc25Smrg    return 0;
325f29dbc25Smrg}
326f29dbc25Smrg
327f29dbc25Smrg/*----------------------------------------------------------------------------
328f29dbc25Smrg * GXResetVideo
329f29dbc25Smrg *
330f29dbc25Smrg * Description	: This function resets the video
331f29dbc25Smrg *
332f29dbc25Smrg * Parameters.
333f29dbc25Smrg *		pScrni	:Screen  pointer having screen information.
334f29dbc25Smrg *
335f29dbc25Smrg * Returns		:None
336f29dbc25Smrg *
337f29dbc25Smrg * Comments		:none
338f29dbc25Smrg *
339f29dbc25Smrg *----------------------------------------------------------------------------
340f29dbc25Smrg */
341f29dbc25Smrgvoid
342f29dbc25SmrgGXResetVideo(ScrnInfoPtr pScrni)
343f29dbc25Smrg{
344f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
345f29dbc25Smrg
346f29dbc25Smrg    if (!pGeode->NoAccel) {
347f29dbc25Smrg	GeodePortPrivRec *pPriv = pGeode->adaptor->pPortPrivates[0].ptr;
348f29dbc25Smrg
349f29dbc25Smrg	GXAccelSync(pScrni);
350f29dbc25Smrg	GXSetColorkey(pScrni, pPriv);
351f29dbc25Smrg	GFX(set_video_filter(pPriv->filter, pPriv->filter));
352f29dbc25Smrg    }
353f29dbc25Smrg}
354f29dbc25Smrg
355f29dbc25Smrg/*----------------------------------------------------------------------------
356f29dbc25Smrg * GXSetupImageVideo
357f29dbc25Smrg *
358f29dbc25Smrg * Description	: This function allocates space for a Videoadaptor and
359f29dbc25Smrg * 				initializes the XF86VideoAdaptorPtr record.
360f29dbc25Smrg *
361f29dbc25Smrg * Parameters.
362f29dbc25Smrg *		pScrn	:Screen handler pointer having screen information.
363f29dbc25Smrg *
364f29dbc25Smrg * Returns		:pointer to the initialized video adaptor record.
365f29dbc25Smrg *
366f29dbc25Smrg * Comments		:none
367f29dbc25Smrg *----------------------------------------------------------------------------
368f29dbc25Smrg */
369f29dbc25Smrgstatic XF86VideoAdaptorPtr
370f29dbc25SmrgGXSetupImageVideo(ScreenPtr pScrn)
371f29dbc25Smrg{
372f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[pScrn->myNum];
373f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
374f29dbc25Smrg    XF86VideoAdaptorPtr adapt;
375f29dbc25Smrg    GeodePortPrivRec *pPriv;
376f29dbc25Smrg
377f29dbc25Smrg    if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
378f29dbc25Smrg		sizeof(GeodePortPrivRec) + sizeof(DevUnion))))
379f29dbc25Smrg	return NULL;
380f29dbc25Smrg
381f29dbc25Smrg    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
382f29dbc25Smrg    adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
383f29dbc25Smrg    adapt->name = "Advanced Micro Devices";
384f29dbc25Smrg    adapt->nEncodings = 1;
385f29dbc25Smrg    adapt->pEncodings = DummyEncoding;
386f29dbc25Smrg    adapt->nFormats = NUM_FORMATS;
387f29dbc25Smrg    adapt->pFormats = Formats;
388f29dbc25Smrg    adapt->nPorts = 1;
389f29dbc25Smrg    adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
390f29dbc25Smrg    pPriv = (GeodePortPrivRec *) (&adapt->pPortPrivates[1]);
391f29dbc25Smrg    adapt->pPortPrivates[0].ptr = (pointer) (pPriv);
392f29dbc25Smrg    adapt->pAttributes = Attributes;
393f29dbc25Smrg    adapt->nImages = NUM_IMAGES;
394f29dbc25Smrg    adapt->nAttributes = NUM_ATTRIBUTES;
395f29dbc25Smrg    adapt->pImages = Images;
396f29dbc25Smrg    adapt->PutVideo = NULL;
397f29dbc25Smrg    adapt->PutStill = NULL;
398f29dbc25Smrg    adapt->GetVideo = NULL;
399f29dbc25Smrg    adapt->GetStill = NULL;
400f29dbc25Smrg    adapt->StopVideo = GXStopVideo;
401f29dbc25Smrg    adapt->SetPortAttribute = GXSetPortAttribute;
402f29dbc25Smrg    adapt->GetPortAttribute = GXGetPortAttribute;
403f29dbc25Smrg    adapt->QueryBestSize = GXQueryBestSize;
404f29dbc25Smrg    adapt->PutImage = GXPutImage;
405f29dbc25Smrg    adapt->QueryImageAttributes = GeodeQueryImageAttributes;
406f29dbc25Smrg
407f29dbc25Smrg    pPriv->filter = 0;
408f29dbc25Smrg    pPriv->colorKey = 0;
409f29dbc25Smrg    pPriv->colorKeyMode = 0;
410f29dbc25Smrg    pPriv->videoStatus = 0;
411f29dbc25Smrg#if DBUF
412f29dbc25Smrg    pPriv->doubleBuffer = TRUE;
413f29dbc25Smrg    pPriv->currentBuffer = 0;	       /* init to first buffer */
414f29dbc25Smrg#endif
415f29dbc25Smrg
416f29dbc25Smrg    /* gotta uninit this someplace */
417f29dbc25Smrg#if defined(REGION_NULL)
418f29dbc25Smrg    REGION_NULL(pScrn, &pPriv->clip);
419f29dbc25Smrg#else
420f29dbc25Smrg    REGION_INIT(pScrn, &pPriv->clip, NullBox, 0);
421f29dbc25Smrg#endif
422f29dbc25Smrg
423f29dbc25Smrg    pGeode->adaptor = adapt;
424f29dbc25Smrg
425f29dbc25Smrg    pGeode->BlockHandler = pScrn->BlockHandler;
426f29dbc25Smrg    pScrn->BlockHandler = GXBlockHandler;
427f29dbc25Smrg
428f29dbc25Smrg    xvColorKey = MAKE_ATOM("XV_COLORKEY");
429f29dbc25Smrg    xvColorKeyMode = MAKE_ATOM("XV_COLORKEYMODE");
430f29dbc25Smrg    xvFilter = MAKE_ATOM("XV_FILTER");
431f29dbc25Smrg#if DBUF
432f29dbc25Smrg    xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
433f29dbc25Smrg#endif
434f29dbc25Smrg
435f29dbc25Smrg    GXResetVideo(pScrni);
436f29dbc25Smrg
437f29dbc25Smrg    return adapt;
438f29dbc25Smrg}
439f29dbc25Smrg
440f29dbc25Smrg/*----------------------------------------------------------------------------
441f29dbc25Smrg * GXStopVideo
442f29dbc25Smrg *
443f29dbc25Smrg * Description	:This function is used to stop input and output video
444f29dbc25Smrg *
445f29dbc25Smrg * Parameters.
446f29dbc25Smrg *		pScrni	:Screen handler pointer having screen information.
447f29dbc25Smrg *		data	:Pointer to the video port's private data
448f29dbc25Smrg *		exit	:Flag indicating whether the offscreen areas used for
449f29dbc25Smrg *				video to be deallocated or not.
450f29dbc25Smrg *
451f29dbc25Smrg * Returns		:none
452f29dbc25Smrg *
453f29dbc25Smrg * Comments		:none
454f29dbc25Smrg *----------------------------------------------------------------------------
455f29dbc25Smrg */
456f29dbc25Smrgstatic void
457f29dbc25SmrgGXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit)
458f29dbc25Smrg{
459f29dbc25Smrg    GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
460f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
461f29dbc25Smrg
462f29dbc25Smrg    REGION_EMPTY(pScrni->pScreen, &pPriv->clip);
463f29dbc25Smrg
464f29dbc25Smrg    GXAccelSync(pScrni);
465f29dbc25Smrg    if (exit) {
466f29dbc25Smrg	if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
467f29dbc25Smrg	    GFX(set_video_enable(0));
468f29dbc25Smrg
469f29dbc25Smrg	    /* If we have saved graphics LUT data - restore it */
470f29dbc25Smrg	    /* Otherwise, turn bypass on */
471f29dbc25Smrg
472f29dbc25Smrg	    if (lutflag)
473f29dbc25Smrg		GFX(set_graphics_palette(graphics_lut));
474f29dbc25Smrg	    else
475f29dbc25Smrg		GFX(set_video_palette_bypass(1));
476f29dbc25Smrg
477f29dbc25Smrg	    lutflag = 0;
478f29dbc25Smrg	}
479f29dbc25Smrg
480f29dbc25Smrg	if (pPriv->area) {
481f29dbc25Smrg#ifdef XF86EXA
482f29dbc25Smrg	    if (pGeode->useEXA)
483f29dbc25Smrg		exaOffscreenFree(pScrni->pScreen, pPriv->area);
484f29dbc25Smrg#endif
485f29dbc25Smrg
486f29dbc25Smrg	    if (!pGeode->useEXA)
487f29dbc25Smrg		xf86FreeOffscreenArea(pPriv->area);
488f29dbc25Smrg
489f29dbc25Smrg	    pPriv->area = NULL;
490f29dbc25Smrg	}
491f29dbc25Smrg
492f29dbc25Smrg	pPriv->videoStatus = 0;
493f29dbc25Smrg	pGeode->OverlayON = FALSE;
494f29dbc25Smrg    } else {
495f29dbc25Smrg	if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
496f29dbc25Smrg	    pPriv->videoStatus |= OFF_TIMER;
497f29dbc25Smrg	    pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
498f29dbc25Smrg	}
499f29dbc25Smrg    }
500f29dbc25Smrg}
501f29dbc25Smrg
502f29dbc25Smrg/*----------------------------------------------------------------------------
503f29dbc25Smrg * GXSetPortAttribute
504f29dbc25Smrg *
505f29dbc25Smrg * Description		:This function is used to set the attributes of a port
506f29dbc25Smrg * 					like colorkeymode, double buffer support and filter.
507f29dbc25Smrg *
508f29dbc25Smrg * Parameters.
509f29dbc25Smrg *		pScrni		:Screen handler pointer having screen information.
510f29dbc25Smrg *		data		:Pointer to the video port's private data
511f29dbc25Smrg *		attribute	:The port attribute to be set
512f29dbc25Smrg *		value		:Value of the attribute to be set.
513f29dbc25Smrg *
514f29dbc25Smrg * Returns			:Sucess if the attribute is supported, else BadMatch
515f29dbc25Smrg *
516f29dbc25Smrg * Comments			:none
517f29dbc25Smrg *----------------------------------------------------------------------------
518f29dbc25Smrg */
519f29dbc25Smrgstatic int
520f29dbc25SmrgGXSetPortAttribute(ScrnInfoPtr pScrni,
521f29dbc25Smrg    Atom attribute, INT32 value, pointer data)
522f29dbc25Smrg{
523f29dbc25Smrg    GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
524f29dbc25Smrg
525f29dbc25Smrg    GXAccelSync(pScrni);
526f29dbc25Smrg    if (attribute == xvColorKey) {
527f29dbc25Smrg	pPriv->colorKey = value;
528f29dbc25Smrg	GXSetColorkey(pScrni, pPriv);
529f29dbc25Smrg    }
530f29dbc25Smrg#if DBUF
531f29dbc25Smrg    else if (attribute == xvDoubleBuffer) {
532f29dbc25Smrg	if ((value < 0) || (value > 1))
533f29dbc25Smrg	    return BadValue;
534f29dbc25Smrg	pPriv->doubleBuffer = value;
535f29dbc25Smrg    }
536f29dbc25Smrg#endif
537f29dbc25Smrg    else if (attribute == xvColorKeyMode) {
538f29dbc25Smrg	pPriv->colorKeyMode = value;
539f29dbc25Smrg	GXSetColorkey(pScrni, pPriv);
540f29dbc25Smrg    } else if (attribute == xvFilter) {
541f29dbc25Smrg	if ((value < 0) || (value > 1))
542f29dbc25Smrg	    return BadValue;
543f29dbc25Smrg	pPriv->filter = value;
544f29dbc25Smrg    } else
545f29dbc25Smrg	return BadMatch;
546f29dbc25Smrg
547f29dbc25Smrg    return Success;
548f29dbc25Smrg}
549f29dbc25Smrg
550f29dbc25Smrg/*----------------------------------------------------------------------------
551f29dbc25Smrg * GXGetPortAttribute
552f29dbc25Smrg *
553f29dbc25Smrg * Description		:This function is used to get the attributes of a port
554f29dbc25Smrg * 					like hue, saturation,brightness or contrast.
555f29dbc25Smrg *
556f29dbc25Smrg * Parameters.
557f29dbc25Smrg *		pScrni		:Screen handler pointer having screen information.
558f29dbc25Smrg *		data		:Pointer to the video port's private data
559f29dbc25Smrg *		attribute	:The port attribute to be read
560f29dbc25Smrg *		value		:Pointer to the value of the attribute to be read.
561f29dbc25Smrg *
562f29dbc25Smrg * Returns			:Sucess if the attribute is supported, else BadMatch
563f29dbc25Smrg *
564f29dbc25Smrg * Comments			:none
565f29dbc25Smrg *----------------------------------------------------------------------------
566f29dbc25Smrg */
567f29dbc25Smrgstatic int
568f29dbc25SmrgGXGetPortAttribute(ScrnInfoPtr pScrni,
569f29dbc25Smrg    Atom attribute, INT32 * value, pointer data)
570f29dbc25Smrg{
571f29dbc25Smrg    GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
572f29dbc25Smrg
573f29dbc25Smrg    if (attribute == xvColorKey) {
574f29dbc25Smrg	*value = pPriv->colorKey;
575f29dbc25Smrg    }
576f29dbc25Smrg#if DBUF
577f29dbc25Smrg    else if (attribute == xvDoubleBuffer) {
578f29dbc25Smrg	*value = (pPriv->doubleBuffer) ? 1 : 0;
579f29dbc25Smrg    }
580f29dbc25Smrg#endif
581f29dbc25Smrg    else if (attribute == xvColorKeyMode) {
582f29dbc25Smrg	*value = pPriv->colorKeyMode;
583f29dbc25Smrg    } else if (attribute == xvFilter) {
584f29dbc25Smrg	*value = pPriv->filter;
585f29dbc25Smrg    } else
586f29dbc25Smrg	return BadMatch;
587f29dbc25Smrg
588f29dbc25Smrg    return Success;
589f29dbc25Smrg}
590f29dbc25Smrg
591f29dbc25Smrg/*----------------------------------------------------------------------------
592f29dbc25Smrg * GXQueryBestSize
593f29dbc25Smrg *
594f29dbc25Smrg * Description		:This function provides a way to query what the
595f29dbc25Smrg * 					destination dimensions would end up being if they were to
596f29dbc25Smrg * 					request that an area vid_w by vid_h from the video stream
597f29dbc25Smrg * 					be scaled to rectangle of drw_w by drw_h on the screen.
598f29dbc25Smrg *
599f29dbc25Smrg * Parameters.
600f29dbc25Smrg *		pScrni		:Screen handler pointer having screen information.
601f29dbc25Smrg *		data		:Pointer to the video port's private data
602f29dbc25Smrg *      vid_w,vid_h	:Width and height of the video data.
603f29dbc25Smrg *		drw_w,drw_h :Width and height of the scaled rectangle.
604f29dbc25Smrg *		p_w,p_h		:Width and height of the destination rectangle.
605f29dbc25Smrg *
606f29dbc25Smrg * Returns			:None
607f29dbc25Smrg *
608f29dbc25Smrg * Comments			:None
609f29dbc25Smrg *----------------------------------------------------------------------------
610f29dbc25Smrg */
611f29dbc25Smrgstatic void
612f29dbc25SmrgGXQueryBestSize(ScrnInfoPtr pScrni,
613f29dbc25Smrg    Bool motion,
614f29dbc25Smrg    short vid_w, short vid_h,
615f29dbc25Smrg    short drw_w, short drw_h,
616f29dbc25Smrg    unsigned int *p_w, unsigned int *p_h, pointer data)
617f29dbc25Smrg{
618f29dbc25Smrg    *p_w = drw_w;
619f29dbc25Smrg    *p_h = drw_h;
620f29dbc25Smrg
621f29dbc25Smrg    if (*p_w > 16384)
622f29dbc25Smrg	*p_w = 16384;
623f29dbc25Smrg}
624f29dbc25Smrg
625f29dbc25Smrg/*----------------------------------------------------------------------------
626f29dbc25Smrg * GXCopyData420
627f29dbc25Smrg *
628f29dbc25Smrg * Description		: Copies data from src to destination
629f29dbc25Smrg *
630f29dbc25Smrg * Parameters.
631f29dbc25Smrg *		src			: pointer to the source data
632f29dbc25Smrg *		dst			: pointer to destination data
633f29dbc25Smrg *		srcPitch	: pitch of the srcdata
634f29dbc25Smrg *		dstPitch	: pitch of the destination data
635f29dbc25Smrg *		h & w		: height and width of source data
636f29dbc25Smrg *
637f29dbc25Smrg * Returns			:None
638f29dbc25Smrg *
639f29dbc25Smrg * Comments			:None
640f29dbc25Smrg *----------------------------------------------------------------------------
641f29dbc25Smrg */
642f29dbc25Smrgstatic void
643f29dbc25SmrgGXCopyData420(unsigned char *src, unsigned char *dst,
644f29dbc25Smrg    int srcPitch, int dstPitch, int h, int w)
645f29dbc25Smrg{
646f29dbc25Smrg    while (h--) {
647f29dbc25Smrg	memcpy(dst, src, w);
648f29dbc25Smrg	src += srcPitch;
649f29dbc25Smrg	dst += dstPitch;
650f29dbc25Smrg    }
651f29dbc25Smrg}
652f29dbc25Smrg
653f29dbc25Smrg/*----------------------------------------------------------------------------
654f29dbc25Smrg * GXCopyData422
655f29dbc25Smrg *
656f29dbc25Smrg * Description		: Copies data from src to destination
657f29dbc25Smrg *
658f29dbc25Smrg * Parameters.
659f29dbc25Smrg *		src			: pointer to the source data
660f29dbc25Smrg *		dst			: pointer to destination data
661f29dbc25Smrg *		srcPitch	: pitch of the srcdata
662f29dbc25Smrg *		dstPitch	: pitch of the destination data
663f29dbc25Smrg *		h & w		: height and width of source data
664f29dbc25Smrg *
665f29dbc25Smrg * Returns			:None
666f29dbc25Smrg *
667f29dbc25Smrg * Comments			:None
668f29dbc25Smrg *----------------------------------------------------------------------------
669f29dbc25Smrg */
670f29dbc25Smrgstatic void
671f29dbc25SmrgGXCopyData422(unsigned char *src, unsigned char *dst,
672f29dbc25Smrg    int srcPitch, int dstPitch, int h, int w)
673f29dbc25Smrg{
674f29dbc25Smrg    w <<= 1;
675f29dbc25Smrg    while (h--) {
676f29dbc25Smrg	memcpy(dst, src, w);
677f29dbc25Smrg	src += srcPitch;
678f29dbc25Smrg	dst += dstPitch;
679f29dbc25Smrg    }
680f29dbc25Smrg}
681f29dbc25Smrg
682f29dbc25Smrg#ifdef XF86EXA
683f29dbc25Smrgstatic void
684f29dbc25SmrgGXVideoSave(ScreenPtr pScreen, ExaOffscreenArea * area)
685f29dbc25Smrg{
686f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[pScreen->myNum];
687f29dbc25Smrg    GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni);
688f29dbc25Smrg
689f29dbc25Smrg    if (area == pPriv->area)
690f29dbc25Smrg	pPriv->area = NULL;
691f29dbc25Smrg}
692f29dbc25Smrg#endif
693f29dbc25Smrg
694f29dbc25Smrgstatic int
695f29dbc25SmrgGXAllocateMemory(ScrnInfoPtr pScrni, void **memp, int numlines)
696f29dbc25Smrg{
697f29dbc25Smrg    ScreenPtr pScrn = screenInfo.screens[pScrni->scrnIndex];
698f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
699f29dbc25Smrg
700f29dbc25Smrg    //long displayWidth = pGeode->Pitch / ((pScrni->bitsPerPixel + 7) / 8);
701f29dbc25Smrg    int size = numlines * pGeode->displayWidth;
702f29dbc25Smrg
703f29dbc25Smrg#if XF86EXA
704f29dbc25Smrg    if (pGeode->useEXA) {
705f29dbc25Smrg	ExaOffscreenArea *area = *memp;
706f29dbc25Smrg
707f29dbc25Smrg	if (area != NULL) {
708f29dbc25Smrg	    if (area->size >= size)
709f29dbc25Smrg		return area->offset;
710f29dbc25Smrg
711f29dbc25Smrg	    exaOffscreenFree(pScrni->pScreen, area);
712f29dbc25Smrg	}
713f29dbc25Smrg
714f29dbc25Smrg	area = exaOffscreenAlloc(pScrni->pScreen, size, 16,
715f29dbc25Smrg	    TRUE, GXVideoSave, NULL);
716f29dbc25Smrg	*memp = area;
717f29dbc25Smrg
718f29dbc25Smrg	return area == NULL ? 0 : area->offset;
719f29dbc25Smrg    }
720f29dbc25Smrg#endif
721f29dbc25Smrg
722f29dbc25Smrg    if (!pGeode->useEXA) {
723f29dbc25Smrg	FBAreaPtr area = *memp;
724f29dbc25Smrg	FBAreaPtr new_area;
725f29dbc25Smrg
726f29dbc25Smrg	if (area) {
727f29dbc25Smrg	    if ((area->box.y2 - area->box.y1) >= numlines)
728f29dbc25Smrg		return (area->box.y1 * pGeode->Pitch);
729f29dbc25Smrg
730f29dbc25Smrg	    if (xf86ResizeOffscreenArea(area, pGeode->displayWidth, numlines))
731f29dbc25Smrg		return (area->box.y1 * pGeode->Pitch);
732f29dbc25Smrg
733f29dbc25Smrg	    xf86FreeOffscreenArea(area);
734f29dbc25Smrg	}
735f29dbc25Smrg
736f29dbc25Smrg	new_area = xf86AllocateOffscreenArea(pScrn, pGeode->displayWidth,
737f29dbc25Smrg	    numlines, 0, NULL, NULL, NULL);
738f29dbc25Smrg
739f29dbc25Smrg	if (!new_area) {
740f29dbc25Smrg	    int max_w, max_h;
741f29dbc25Smrg
742f29dbc25Smrg	    xf86QueryLargestOffscreenArea(pScrn, &max_w, &max_h, 0,
743f29dbc25Smrg		FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME);
744f29dbc25Smrg
745f29dbc25Smrg	    if ((max_w < pGeode->displayWidth) || (max_h < numlines)) {
746f29dbc25Smrg		xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
747f29dbc25Smrg		    "No room - how sad %x, %x, %x, %x\n", max_w,
748f29dbc25Smrg		    pGeode->displayWidth, max_h, numlines);
749f29dbc25Smrg		return 0;
750f29dbc25Smrg	    }
751f29dbc25Smrg
752f29dbc25Smrg	    xf86PurgeUnlockedOffscreenAreas(pScrn);
753f29dbc25Smrg	    new_area = xf86AllocateOffscreenArea(pScrn, pGeode->displayWidth,
754f29dbc25Smrg		numlines, 0, NULL, NULL, NULL);
755f29dbc25Smrg	}
756f29dbc25Smrg
757f29dbc25Smrg	return (new_area->box.y1 * pGeode->Pitch);
758f29dbc25Smrg    }
759f29dbc25Smrg
760f29dbc25Smrg    return 0;
761f29dbc25Smrg}
762f29dbc25Smrg
763f29dbc25Smrgstatic BoxRec dstBox;
764f29dbc25Smrgstatic int srcPitch = 0, srcPitch2 = 0, dstPitch = 0, dstPitch2 = 0;
765f29dbc25Smrgstatic INT32 Bx1, Bx2, By1, By2;
766f29dbc25Smrgstatic int top, left, npixels, nlines;
767f29dbc25Smrgstatic int offset, s1offset = 0, s2offset = 0, s3offset = 0;
768f29dbc25Smrgstatic unsigned char *dst_start;
769f29dbc25Smrgstatic int d2offset = 0, d3offset = 0;
770f29dbc25Smrg
771f29dbc25Smrg#if 0
772f29dbc25Smrgstatic Bool
773f29dbc25SmrgRegionsIntersect(BoxPtr pRcl1, BoxPtr pRcl2, BoxPtr pRclResult)
774f29dbc25Smrg{
775f29dbc25Smrg    pRclResult->x1 = max(pRcl1->x1, pRcl2->x1);
776f29dbc25Smrg    pRclResult->x2 = min(pRcl1->x2, pRcl2->x2);
777f29dbc25Smrg
778f29dbc25Smrg    if (pRclResult->x1 <= pRclResult->x2) {
779f29dbc25Smrg	pRclResult->y1 = max(pRcl1->y1, pRcl2->y1);
780f29dbc25Smrg	pRclResult->y2 = min(pRcl1->y2, pRcl2->y2);
781f29dbc25Smrg
782f29dbc25Smrg	if (pRclResult->y1 <= pRclResult->y2) {
783f29dbc25Smrg	    return (TRUE);
784f29dbc25Smrg	}
785f29dbc25Smrg    }
786f29dbc25Smrg
787f29dbc25Smrg    return (FALSE);
788f29dbc25Smrg}
789f29dbc25Smrg#endif
790f29dbc25Smrg
791f29dbc25Smrgvoid
792f29dbc25SmrgGXSetVideoPosition(int x, int y, int width, int height,
793f29dbc25Smrg    short src_w, short src_h, short drw_w, short drw_h,
794f29dbc25Smrg    int id, int offset, ScrnInfoPtr pScrni)
795f29dbc25Smrg{
796f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
797f29dbc25Smrg    long ystart, xend, yend;
798f29dbc25Smrg    unsigned long lines = 0;
799f29dbc25Smrg    unsigned long y_extra, uv_extra = 0;
800f29dbc25Smrg    unsigned long startAddress;
801f29dbc25Smrg
802f29dbc25Smrg#if 0
803f29dbc25Smrg    BoxRec ovly, display, result;
804f29dbc25Smrg#endif
805f29dbc25Smrg
806f29dbc25Smrg    xend = x + drw_w;
807f29dbc25Smrg    yend = y + drw_h;
808f29dbc25Smrg
809f29dbc25Smrg    /* Take care of panning when panel is present */
810f29dbc25Smrg
811f29dbc25Smrg    startAddress = gfx_get_display_offset();
812f29dbc25Smrg    DeltaY = startAddress / pGeode->Pitch;
813f29dbc25Smrg    DeltaX = startAddress & (pGeode->Pitch - 1);
814f29dbc25Smrg    DeltaX /= (pScrni->bitsPerPixel >> 3);
815f29dbc25Smrg
816f29dbc25Smrg#if 0
817f29dbc25Smrg    /* Thhis code is pretty dang broken - comment it out for now */
818f29dbc25Smrg
819f29dbc25Smrg    if (pGeode->Panel) {
820f29dbc25Smrg	ovly.x1 = x;
821f29dbc25Smrg	ovly.x2 = x + pGeode->video_dstw;
822f29dbc25Smrg	ovly.y1 = y;
823f29dbc25Smrg	ovly.y2 = y + pGeode->video_dsth;
824f29dbc25Smrg
825f29dbc25Smrg	display.x1 = DeltaX;
826f29dbc25Smrg	display.x2 = DeltaX + pGeode->FPBX;
827f29dbc25Smrg	display.y1 = DeltaY;
828f29dbc25Smrg	display.y2 = DeltaY + pGeode->FPBY;
829f29dbc25Smrg	x = xend = 0;
830f29dbc25Smrg	if (RegionsIntersect(&display, &ovly, &result)) {
831f29dbc25Smrg	    x = ovly.x1 - DeltaX;
832f29dbc25Smrg	    xend = ovly.x2 - DeltaX;
833f29dbc25Smrg	    y = ovly.y1 - DeltaY;
834f29dbc25Smrg	    yend = ovly.y2 - DeltaY;
835f29dbc25Smrg	}
836f29dbc25Smrg    }
837f29dbc25Smrg#endif
838f29dbc25Smrg
839f29dbc25Smrg    /*  TOP CLIPPING */
840f29dbc25Smrg
841f29dbc25Smrg    if (y < 0) {
842f29dbc25Smrg	if (src_h < drw_h)
843f29dbc25Smrg	    lines = (-y) * src_h / drw_h;
844f29dbc25Smrg	else
845f29dbc25Smrg	    lines = (-y);
846f29dbc25Smrg	ystart = 0;
847f29dbc25Smrg	drw_h += y;
848f29dbc25Smrg	y_extra = lines * dstPitch;
849f29dbc25Smrg	uv_extra = (lines >> 1) * (dstPitch2);
850f29dbc25Smrg    } else {
851f29dbc25Smrg	ystart = y;
852f29dbc25Smrg	lines = 0;
853f29dbc25Smrg	y_extra = 0;
854f29dbc25Smrg    }
855f29dbc25Smrg
856f29dbc25Smrg    GFX(set_video_window(x, ystart, xend - x, yend - ystart));
857f29dbc25Smrg
858f29dbc25Smrg    if ((id == FOURCC_Y800) || (id == FOURCC_I420) || (id == FOURCC_YV12)) {
859f29dbc25Smrg	GFX(set_video_yuv_offsets(offset + y_extra,
860f29dbc25Smrg		offset + d3offset + uv_extra, offset + d2offset + uv_extra));
861f29dbc25Smrg    } else {
862f29dbc25Smrg	GFX(set_video_offset(offset + y_extra));
863f29dbc25Smrg    }
864f29dbc25Smrg}
865f29dbc25Smrg
866f29dbc25Smrg/*----------------------------------------------------------------------------
867f29dbc25Smrg * GXDisplayVideo
868f29dbc25Smrg *
869f29dbc25Smrg * Description	:This function sets up the video registers for playing video
870f29dbc25Smrg * 				It sets up the video format,width, height & position of the
871f29dbc25Smrg *		  		video window ,video offsets( y,u,v) and video pitches(y,u,v)
872f29dbc25Smrg *
873f29dbc25Smrg * Parameters
874f29dbc25Smrg *
875f29dbc25Smrg * Returns		:None
876f29dbc25Smrg *
877f29dbc25Smrg * Comments		:None
878f29dbc25Smrg *----------------------------------------------------------------------------
879f29dbc25Smrg */
880f29dbc25Smrg
881f29dbc25Smrgstatic void
882f29dbc25SmrgGXDisplayVideo(ScrnInfoPtr pScrni,
883f29dbc25Smrg    int id,
884f29dbc25Smrg    int offset,
885f29dbc25Smrg    short width, short height,
886f29dbc25Smrg    int pitch,
887f29dbc25Smrg    int x1, int y1, int x2, int y2,
888f29dbc25Smrg    BoxPtr dstBox, short src_w, short src_h, short drw_w, short drw_h)
889f29dbc25Smrg{
890f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
891f29dbc25Smrg    unsigned long dcfg, misc;
892f29dbc25Smrg
893f29dbc25Smrg    GXAccelSync(pScrni);
894f29dbc25Smrg
895f29dbc25Smrg    /* If the gamma LUT is already loaded with graphics data, then save it
896f29dbc25Smrg     * off
897f29dbc25Smrg     */
898f29dbc25Smrg
899f29dbc25Smrg    if (id != FOURCC_RGB565) {
900f29dbc25Smrg	dcfg = gfx_read_vid32(DISPLAY_CONFIG);
901f29dbc25Smrg	misc = gfx_read_vid32(MISC);
902f29dbc25Smrg
903f29dbc25Smrg	lutflag = (!(misc & 1) && (dcfg & (1 << 21)));
904f29dbc25Smrg
905f29dbc25Smrg	if (lutflag)
906f29dbc25Smrg	    get_gamma_ram(graphics_lut);
907f29dbc25Smrg
908f29dbc25Smrg	/* Set the video gamma ram */
909f29dbc25Smrg	GFX(set_video_palette(NULL));
910f29dbc25Smrg    }
911f29dbc25Smrg
912f29dbc25Smrg    GFX(set_video_enable(1));
913f29dbc25Smrg
914f29dbc25Smrg    switch (id) {
915f29dbc25Smrg    case FOURCC_UYVY:		       /* UYVY */
916f29dbc25Smrg	GFX(set_video_format(VIDEO_FORMAT_UYVY));
917f29dbc25Smrg	GFX(set_video_size(width, height));
918f29dbc25Smrg	break;
919f29dbc25Smrg    case FOURCC_Y800:		       /* Y800 - greyscale - we munge it! */
920f29dbc25Smrg    case FOURCC_YV12:		       /* YV12 */
921f29dbc25Smrg    case FOURCC_I420:		       /* I420 */
922f29dbc25Smrg	GFX(set_video_format(VIDEO_FORMAT_Y0Y1Y2Y3));
923f29dbc25Smrg	GFX(set_video_size(width, height));
924f29dbc25Smrg	GFX(set_video_yuv_pitch(dstPitch, dstPitch2));
925f29dbc25Smrg	break;
926f29dbc25Smrg    case FOURCC_YUY2:		       /* YUY2 */
927f29dbc25Smrg	GFX(set_video_format(VIDEO_FORMAT_YUYV));
928f29dbc25Smrg	GFX(set_video_size(width, height));
929f29dbc25Smrg	break;
930f29dbc25Smrg    case FOURCC_Y2YU:		       /* Y2YU */
931f29dbc25Smrg	GFX(set_video_format(VIDEO_FORMAT_Y2YU));
932f29dbc25Smrg	GFX(set_video_size(width, height));
933f29dbc25Smrg	break;
934f29dbc25Smrg    case FOURCC_YVYU:		       /* YVYU */
935f29dbc25Smrg	GFX(set_video_format(VIDEO_FORMAT_YVYU));
936f29dbc25Smrg	GFX(set_video_size(width, height));
937f29dbc25Smrg	break;
938f29dbc25Smrg    case FOURCC_RGB565:
939f29dbc25Smrg	GFX(set_video_format(VIDEO_FORMAT_RGB));
940f29dbc25Smrg	GFX(set_video_size(width, height));
941f29dbc25Smrg	break;
942f29dbc25Smrg
943f29dbc25Smrg    }
944f29dbc25Smrg
945f29dbc25Smrg    if (pGeode->Panel) {
946f29dbc25Smrg	pGeode->video_x = dstBox->x1;
947f29dbc25Smrg	pGeode->video_y = dstBox->y1;
948f29dbc25Smrg	pGeode->video_w = width;
949f29dbc25Smrg	pGeode->video_h = height;
950f29dbc25Smrg	pGeode->video_srcw = src_w;
951f29dbc25Smrg	pGeode->video_srch = src_h;
952f29dbc25Smrg	pGeode->video_dstw = drw_w;
953f29dbc25Smrg	pGeode->video_dsth = drw_h;
954f29dbc25Smrg	pGeode->video_offset = offset;
955f29dbc25Smrg	pGeode->video_id = id;
956f29dbc25Smrg	pGeode->video_scrnptr = pScrni;
957f29dbc25Smrg    }
958f29dbc25Smrg
959f29dbc25Smrg    if ((drw_w >= src_w) && (drw_h >= src_h))
960f29dbc25Smrg	GFX(set_video_scale(width, height, drw_w, drw_h));
961f29dbc25Smrg    else if (drw_w < src_w)
962f29dbc25Smrg	GFX(set_video_scale(drw_w, height, drw_w, drw_h));
963f29dbc25Smrg    else if (drw_h < src_h)
964f29dbc25Smrg	GFX(set_video_scale(width, drw_h, drw_w, drw_h));
965f29dbc25Smrg
966f29dbc25Smrg    GXSetVideoPosition(dstBox->x1, dstBox->y1, width, height, src_w,
967f29dbc25Smrg	src_h, drw_w, drw_h, id, offset, pScrni);
968f29dbc25Smrg}
969f29dbc25Smrg
970f29dbc25Smrg/* Used by LX as well */
971f29dbc25Smrg
972f29dbc25SmrgBool
973f29dbc25SmrgRegionsEqual(RegionPtr A, RegionPtr B)
974f29dbc25Smrg{
975f29dbc25Smrg    int *dataA, *dataB;
976f29dbc25Smrg    int num;
977f29dbc25Smrg
978f29dbc25Smrg    num = REGION_NUM_RECTS(A);
979f29dbc25Smrg    if (num != REGION_NUM_RECTS(B)) {
980f29dbc25Smrg	return FALSE;
981f29dbc25Smrg    }
982f29dbc25Smrg
983f29dbc25Smrg    if ((A->extents.x1 != B->extents.x1) ||
984f29dbc25Smrg	(A->extents.x2 != B->extents.x2) ||
985f29dbc25Smrg	(A->extents.y1 != B->extents.y1) || (A->extents.y2 != B->extents.y2))
986f29dbc25Smrg	return FALSE;
987f29dbc25Smrg
988f29dbc25Smrg    dataA = (int *)REGION_RECTS(A);
989f29dbc25Smrg    dataB = (int *)REGION_RECTS(B);
990f29dbc25Smrg
991f29dbc25Smrg    while (num--) {
992f29dbc25Smrg	if ((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
993f29dbc25Smrg	    return FALSE;
994f29dbc25Smrg
995f29dbc25Smrg	dataA += 2;
996f29dbc25Smrg	dataB += 2;
997f29dbc25Smrg    }
998f29dbc25Smrg
999f29dbc25Smrg    return TRUE;
1000f29dbc25Smrg}
1001f29dbc25Smrg
1002f29dbc25Smrg/*----------------------------------------------------------------------------
1003f29dbc25Smrg * GXPutImage	:This function writes a single frame of video into a
1004f29dbc25Smrg * 				drawable. The position and size of the source rectangle is
1005f29dbc25Smrg * 				specified by src_x,src_y, src_w and src_h. This data is
1006f29dbc25Smrg * 				stored in a system memory buffer at buf. The position and
1007f29dbc25Smrg * 				size of the destination rectangle is specified by drw_x,
1008f29dbc25Smrg * 				drw_y,drw_w,drw_h.The data is in the format indicated by the
1009f29dbc25Smrg * 				image descriptor and represents a source of size width by
1010f29dbc25Smrg * 				height.  If sync is TRUE the driver should not return from
1011f29dbc25Smrg * 				this function until it is through reading the data from buf.
1012f29dbc25Smrg * 				Returning when sync is TRUE indicates that it is safe for the
1013f29dbc25Smrg * 				data at buf to be replaced,freed, or modified.
1014f29dbc25Smrg *
1015f29dbc25Smrg * Parameters.
1016f29dbc25Smrg *
1017f29dbc25Smrg * Returns		:None
1018f29dbc25Smrg *
1019f29dbc25Smrg * Comments		:None
1020f29dbc25Smrg *----------------------------------------------------------------------------
1021f29dbc25Smrg */
1022f29dbc25Smrg
1023f29dbc25Smrgstatic int
1024f29dbc25SmrgGXPutImage(ScrnInfoPtr pScrni,
1025f29dbc25Smrg    short src_x, short src_y,
1026f29dbc25Smrg    short drw_x, short drw_y,
1027f29dbc25Smrg    short src_w, short src_h,
1028f29dbc25Smrg    short drw_w, short drw_h,
1029f29dbc25Smrg    int id, unsigned char *buf,
1030f29dbc25Smrg    short width, short height, Bool sync, RegionPtr clipBoxes, pointer data,
1031f29dbc25Smrg    DrawablePtr pDraw)
1032f29dbc25Smrg{
1033f29dbc25Smrg    GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
1034f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1035f29dbc25Smrg    int new_h;
1036f29dbc25Smrg
1037f29dbc25Smrg#if REINIT
1038f29dbc25Smrg    BOOL ReInitVideo = FALSE;
1039f29dbc25Smrg    static BOOL DoReinitAgain = 0;
1040f29dbc25Smrg#endif
1041f29dbc25Smrg
1042f29dbc25Smrg#if XV_PROFILE
1043f29dbc25Smrg    long oldtime, newtime;
1044f29dbc25Smrg
1045f29dbc25Smrg    UpdateCurrentTime();
1046f29dbc25Smrg    oldtime = currentTime.milliseconds;
1047f29dbc25Smrg#endif
1048f29dbc25Smrg
1049f29dbc25Smrg#if REINIT
1050f29dbc25Smrg/* update cliplist */
1051f29dbc25Smrg    if (!RegionsEqual(&pPriv->clip, clipBoxes)) {
1052f29dbc25Smrg	ReInitVideo = TRUE;
1053f29dbc25Smrg    }
1054f29dbc25Smrg
1055f29dbc25Smrg    if (DoReinitAgain)
1056f29dbc25Smrg	ReInitVideo = TRUE;
1057f29dbc25Smrg
1058f29dbc25Smrg    if (ReInitVideo) {
1059f29dbc25Smrg	DEBUGMSG(1, (0, X_NONE, "Regional Not Equal - Init\n"));
1060f29dbc25Smrg#endif
1061f29dbc25Smrg	DoReinitAgain = ~DoReinitAgain;
1062f29dbc25Smrg	if (drw_w > 16384)
1063f29dbc25Smrg	    drw_w = 16384;
1064f29dbc25Smrg
1065f29dbc25Smrg	/* Clip */
1066f29dbc25Smrg	Bx1 = src_x;
1067f29dbc25Smrg	Bx2 = src_x + src_w;
1068f29dbc25Smrg	By1 = src_y;
1069f29dbc25Smrg	By2 = src_y + src_h;
1070f29dbc25Smrg
1071f29dbc25Smrg	if ((Bx1 >= Bx2) || (By1 >= By2))
1072f29dbc25Smrg	    return Success;
1073f29dbc25Smrg
1074f29dbc25Smrg	dstBox.x1 = drw_x;
1075f29dbc25Smrg	dstBox.x2 = drw_x + drw_w;
1076f29dbc25Smrg	dstBox.y1 = drw_y;
1077f29dbc25Smrg	dstBox.y2 = drw_y + drw_h;
1078f29dbc25Smrg
1079f29dbc25Smrg	dstBox.x1 -= pScrni->frameX0;
1080f29dbc25Smrg	dstBox.x2 -= pScrni->frameX0;
1081f29dbc25Smrg	dstBox.y1 -= pScrni->frameY0;
1082f29dbc25Smrg	dstBox.y2 -= pScrni->frameY0;
1083f29dbc25Smrg
1084f29dbc25Smrg	switch (id) {
1085f29dbc25Smrg	case FOURCC_YV12:
1086f29dbc25Smrg	case FOURCC_I420:
1087f29dbc25Smrg	    srcPitch = (width + 3) & ~3;	/* of luma */
1088f29dbc25Smrg	    dstPitch = (width + 31) & ~31;
1089f29dbc25Smrg
1090f29dbc25Smrg	    s2offset = srcPitch * height;
1091f29dbc25Smrg	    d2offset = dstPitch * height;
1092f29dbc25Smrg
1093f29dbc25Smrg	    srcPitch2 = ((width >> 1) + 3) & ~3;
1094f29dbc25Smrg	    dstPitch2 = ((width >> 1) + 15) & ~15;
1095f29dbc25Smrg
1096f29dbc25Smrg	    s3offset = (srcPitch2 * (height >> 1)) + s2offset;
1097f29dbc25Smrg	    d3offset = (dstPitch2 * (height >> 1)) + d2offset;
1098f29dbc25Smrg
1099f29dbc25Smrg	    new_h = dstPitch * height; /* Y */
1100f29dbc25Smrg	    new_h += (dstPitch2 * height);	/* U+V */
1101f29dbc25Smrg	    new_h += pGeode->Pitch - 1;
1102f29dbc25Smrg	    new_h /= pGeode->Pitch;
1103f29dbc25Smrg	    break;
1104f29dbc25Smrg	case FOURCC_UYVY:
1105f29dbc25Smrg	case FOURCC_YUY2:
1106f29dbc25Smrg	case FOURCC_Y800:
1107f29dbc25Smrg	case FOURCC_RGB565:
1108f29dbc25Smrg	default:
1109f29dbc25Smrg	    dstPitch = ((width << 1) + 3) & ~3;
1110f29dbc25Smrg	    srcPitch = (width << 1);
1111f29dbc25Smrg	    new_h = ((dstPitch * height) + pGeode->Pitch - 1) / pGeode->Pitch;
1112f29dbc25Smrg	    break;
1113f29dbc25Smrg	}
1114f29dbc25Smrg#if DBUF
1115f29dbc25Smrg	if (pPriv->doubleBuffer)
1116f29dbc25Smrg	    new_h <<= 1;
1117f29dbc25Smrg#endif
1118f29dbc25Smrg
1119f29dbc25Smrg	if (!(pPriv->offset = GXAllocateMemory(pScrni, &pPriv->area, new_h))) {
1120f29dbc25Smrg	    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
1121f29dbc25Smrg		"Could not allocate area of size %d\n", new_h);
1122f29dbc25Smrg	    return BadAlloc;
1123f29dbc25Smrg	}
1124f29dbc25Smrg
1125f29dbc25Smrg	/* copy data */
1126f29dbc25Smrg	top = By1;
1127f29dbc25Smrg	left = Bx1 & ~1;
1128f29dbc25Smrg	npixels = ((Bx2 + 1) & ~1) - left;
1129f29dbc25Smrg
1130f29dbc25Smrg	switch (id) {
1131f29dbc25Smrg	case FOURCC_YV12:
1132f29dbc25Smrg	case FOURCC_I420:
1133f29dbc25Smrg	    {
1134f29dbc25Smrg		int tmp;
1135f29dbc25Smrg
1136f29dbc25Smrg		top &= ~1;
1137f29dbc25Smrg
1138f29dbc25Smrg		offset = pPriv->offset + (top * dstPitch);
1139f29dbc25Smrg
1140f29dbc25Smrg#if DBUF
1141f29dbc25Smrg		if (pPriv->doubleBuffer && pPriv->currentBuffer)
1142f29dbc25Smrg		    offset += (new_h >> 1) * pGeode->Pitch;
1143f29dbc25Smrg#endif
1144f29dbc25Smrg		dst_start = pGeode->FBBase + offset + left;
1145f29dbc25Smrg		tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1146f29dbc25Smrg		s2offset += tmp;
1147f29dbc25Smrg		s3offset += tmp;
1148f29dbc25Smrg		if (id == FOURCC_I420) {
1149f29dbc25Smrg		    tmp = s2offset;
1150f29dbc25Smrg		    s2offset = s3offset;
1151f29dbc25Smrg		    s3offset = tmp;
1152f29dbc25Smrg		}
1153f29dbc25Smrg		nlines = ((By2 + 1) & ~1) - top;
1154f29dbc25Smrg	    }
1155f29dbc25Smrg	    break;
1156f29dbc25Smrg	case FOURCC_UYVY:
1157f29dbc25Smrg	case FOURCC_YUY2:
1158f29dbc25Smrg	case FOURCC_Y800:
1159f29dbc25Smrg	case FOURCC_RGB565:
1160f29dbc25Smrg	default:
1161f29dbc25Smrg	    left <<= 1;
1162f29dbc25Smrg	    buf += (top * srcPitch) + left;
1163f29dbc25Smrg	    nlines = By2 - top;
1164f29dbc25Smrg	    offset = (pPriv->offset) + (top * dstPitch);
1165f29dbc25Smrg
1166f29dbc25Smrg#if DBUF
1167f29dbc25Smrg	    if (pPriv->doubleBuffer && pPriv->currentBuffer)
1168f29dbc25Smrg		offset += (new_h >> 1) * pGeode->Pitch;
1169f29dbc25Smrg#endif
1170f29dbc25Smrg	    dst_start = pGeode->FBBase + offset + left;
1171f29dbc25Smrg	    break;
1172f29dbc25Smrg	}
1173f29dbc25Smrg	s1offset = (top * srcPitch) + left;
1174f29dbc25Smrg#if REINIT
1175f29dbc25Smrg	/* update cliplist */
1176f29dbc25Smrg	REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes);
1177f29dbc25Smrg
1178f29dbc25Smrg	if (pPriv->colorKeyMode == 0) {
1179f29dbc25Smrg	    xf86XVFillKeyHelper(pScrni->pScreen, pPriv->colorKey, clipBoxes);
1180f29dbc25Smrg	}
1181f29dbc25Smrg
1182f29dbc25Smrg	GXDisplayVideo(pScrni, id, offset, width, height, dstPitch,
1183f29dbc25Smrg	    Bx1, By1, Bx2, By2, &dstBox, src_w, src_h, drw_w, drw_h);
1184f29dbc25Smrg    }
1185f29dbc25Smrg#endif
1186f29dbc25Smrg    switch (id) {
1187f29dbc25Smrg    case FOURCC_Y800:
1188f29dbc25Smrg	/* This is shared between LX and GX, so it lives in amd_common.c */
1189f29dbc25Smrg	GeodeCopyGreyscale(buf, dst_start, srcPitch, dstPitch, nlines,
1190f29dbc25Smrg	    npixels);
1191f29dbc25Smrg	break;
1192f29dbc25Smrg    case FOURCC_YV12:
1193f29dbc25Smrg    case FOURCC_I420:
1194f29dbc25Smrg	GXCopyData420(buf + s1offset, dst_start, srcPitch, dstPitch, nlines,
1195f29dbc25Smrg	    npixels);
1196f29dbc25Smrg	GXCopyData420(buf + s2offset, dst_start + d2offset, srcPitch2,
1197f29dbc25Smrg	    dstPitch2, nlines >> 1, npixels >> 1);
1198f29dbc25Smrg	GXCopyData420(buf + s3offset, dst_start + d3offset, srcPitch2,
1199f29dbc25Smrg	    dstPitch2, nlines >> 1, npixels >> 1);
1200f29dbc25Smrg	break;
1201f29dbc25Smrg    case FOURCC_UYVY:
1202f29dbc25Smrg    case FOURCC_YUY2:
1203f29dbc25Smrg    case FOURCC_RGB565:
1204f29dbc25Smrg    default:
1205f29dbc25Smrg	GXCopyData422(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
1206f29dbc25Smrg	break;
1207f29dbc25Smrg    }
1208f29dbc25Smrg#if !REINIT
1209f29dbc25Smrg    /* update cliplist */
1210f29dbc25Smrg    REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes);
1211f29dbc25Smrg    if (pPriv->colorKeyMode == 0) {
1212f29dbc25Smrg	/* draw these */
1213f29dbc25Smrg	XAAFillSolidRects(pScrni, pPriv->colorKey, GXcopy, ~0,
1214f29dbc25Smrg	    REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes));
1215f29dbc25Smrg    }
1216f29dbc25Smrg
1217f29dbc25Smrg    GXDisplayVideo(pScrni, id, offset, width, height, dstPitch,
1218f29dbc25Smrg	Bx1, By1, Bx2, By2, &dstBox, src_w, src_h, drw_w, drw_h);
1219f29dbc25Smrg#endif
1220f29dbc25Smrg
1221f29dbc25Smrg#if XV_PROFILE
1222f29dbc25Smrg    UpdateCurrentTime();
1223f29dbc25Smrg    newtime = currentTime.milliseconds;
1224f29dbc25Smrg    DEBUGMSG(1, (0, X_NONE, "PI %d\n", newtime - oldtime));
1225f29dbc25Smrg#endif
1226f29dbc25Smrg
1227f29dbc25Smrg#if DBUF
1228f29dbc25Smrg    pPriv->currentBuffer ^= 1;
1229f29dbc25Smrg#endif
1230f29dbc25Smrg
1231f29dbc25Smrg    pPriv->videoStatus = CLIENT_VIDEO_ON;
1232f29dbc25Smrg    pGeode->OverlayON = TRUE;
1233f29dbc25Smrg    return Success;
1234f29dbc25Smrg}
1235f29dbc25Smrg
1236f29dbc25Smrg/*----------------------------------------------------------------------------
1237f29dbc25Smrg * GXQueryImageAttributes
1238f29dbc25Smrg *
1239f29dbc25Smrg * Description	:This function is called to let the driver specify how data
1240f29dbc25Smrg *				 for a particular image of size width by height should be
1241f29dbc25Smrg *				 stored.
1242f29dbc25Smrg *
1243f29dbc25Smrg * Parameters.
1244f29dbc25Smrg *		pScrni	:Screen handler pointer having screen information.
1245f29dbc25Smrg *		id		:Id for the video format
1246f29dbc25Smrg *		width	:width  of the image (can be modified by the driver)
1247f29dbc25Smrg *		height	:height of the image (can be modified by the driver)
1248f29dbc25Smrg * Returns		: Size of the memory required for storing this image
1249f29dbc25Smrg *
1250f29dbc25Smrg * Comments		:None
1251f29dbc25Smrg *
1252f29dbc25Smrg *----------------------------------------------------------------------------
1253f29dbc25Smrg */
1254f29dbc25Smrg
1255f29dbc25Smrgint
1256f29dbc25SmrgGeodeQueryImageAttributes(ScrnInfoPtr pScrni,
1257f29dbc25Smrg    int id, unsigned short *w, unsigned short *h, int *pitches, int *offsets)
1258f29dbc25Smrg{
1259f29dbc25Smrg    int size;
1260f29dbc25Smrg    int tmp;
1261f29dbc25Smrg
1262f29dbc25Smrg    DEBUGMSG(0, (0, X_NONE, "QueryImageAttributes %X\n", id));
1263f29dbc25Smrg
1264f29dbc25Smrg    if (*w > 1024)
1265f29dbc25Smrg	*w = 1024;
1266f29dbc25Smrg    if (*h > 1024)
1267f29dbc25Smrg	*h = 1024;
1268f29dbc25Smrg
1269f29dbc25Smrg    *w = (*w + 1) & ~1;
1270f29dbc25Smrg    if (offsets)
1271f29dbc25Smrg	offsets[0] = 0;
1272f29dbc25Smrg
1273f29dbc25Smrg    switch (id) {
1274f29dbc25Smrg    case FOURCC_YV12:
1275f29dbc25Smrg    case FOURCC_I420:
1276f29dbc25Smrg	*h = (*h + 1) & ~1;
1277f29dbc25Smrg	size = (*w + 3) & ~3;
1278f29dbc25Smrg	if (pitches)
1279f29dbc25Smrg	    pitches[0] = size;
1280f29dbc25Smrg
1281f29dbc25Smrg	size *= *h;
1282f29dbc25Smrg	if (offsets)
1283f29dbc25Smrg	    offsets[1] = size;
1284f29dbc25Smrg
1285f29dbc25Smrg	tmp = ((*w >> 1) + 3) & ~3;
1286f29dbc25Smrg	if (pitches)
1287f29dbc25Smrg	    pitches[1] = pitches[2] = tmp;
1288f29dbc25Smrg
1289f29dbc25Smrg	tmp *= (*h >> 1);
1290f29dbc25Smrg	size += tmp;
1291f29dbc25Smrg	if (offsets)
1292f29dbc25Smrg	    offsets[2] = size;
1293f29dbc25Smrg
1294f29dbc25Smrg	size += tmp;
1295f29dbc25Smrg	break;
1296f29dbc25Smrg    case FOURCC_UYVY:
1297f29dbc25Smrg    case FOURCC_YUY2:
1298f29dbc25Smrg    case FOURCC_Y800:
1299f29dbc25Smrg    default:
1300f29dbc25Smrg	size = *w << 1;
1301f29dbc25Smrg	if (pitches)
1302f29dbc25Smrg	    pitches[0] = size;
1303f29dbc25Smrg
1304f29dbc25Smrg	size *= *h;
1305f29dbc25Smrg	break;
1306f29dbc25Smrg    }
1307f29dbc25Smrg    return size;
1308f29dbc25Smrg}
1309f29dbc25Smrg
1310f29dbc25Smrgstatic void
1311f29dbc25SmrgGXBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
1312f29dbc25Smrg{
1313f29dbc25Smrg    ScreenPtr pScrn = screenInfo.screens[i];
1314f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[i];
1315f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1316f29dbc25Smrg    GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni);
1317f29dbc25Smrg
1318f29dbc25Smrg    pScrn->BlockHandler = pGeode->BlockHandler;
1319f29dbc25Smrg    (*pScrn->BlockHandler) (i, blockData, pTimeout, pReadmask);
1320f29dbc25Smrg    pScrn->BlockHandler = GXBlockHandler;
1321f29dbc25Smrg
1322f29dbc25Smrg    if (pPriv->videoStatus & TIMER_MASK) {
1323f29dbc25Smrg	GXAccelSync(pScrni);
1324f29dbc25Smrg	UpdateCurrentTime();
1325f29dbc25Smrg	if (pPriv->videoStatus & OFF_TIMER) {
1326f29dbc25Smrg	    if (pPriv->offTime < currentTime.milliseconds) {
1327f29dbc25Smrg		GFX(set_video_enable(0));
1328f29dbc25Smrg
1329f29dbc25Smrg		/* If we have saved graphics LUT data - restore it */
1330f29dbc25Smrg		/* Otherwise, turn bypass on */
1331f29dbc25Smrg
1332f29dbc25Smrg		if (lutflag)
1333f29dbc25Smrg		    GFX(set_graphics_palette(graphics_lut));
1334f29dbc25Smrg		else
1335f29dbc25Smrg		    GFX(set_video_palette_bypass(1));
1336f29dbc25Smrg
1337f29dbc25Smrg		lutflag = 0;
1338f29dbc25Smrg
1339f29dbc25Smrg		pPriv->videoStatus = FREE_TIMER;
1340f29dbc25Smrg		pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
1341f29dbc25Smrg	    }
1342f29dbc25Smrg	} else {		       /* FREE_TIMER */
1343f29dbc25Smrg	    if (pPriv->freeTime < currentTime.milliseconds) {
1344f29dbc25Smrg
1345f29dbc25Smrg		if (pPriv->area) {
1346f29dbc25Smrg#ifdef XF86EXA
1347f29dbc25Smrg		    if (pGeode->useEXA)
1348f29dbc25Smrg			exaOffscreenFree(pScrn, pPriv->area);
1349f29dbc25Smrg#endif
1350f29dbc25Smrg		    if (!pGeode->useEXA)
1351f29dbc25Smrg			xf86FreeOffscreenArea(pPriv->area);
1352f29dbc25Smrg
1353f29dbc25Smrg		    pPriv->area = NULL;
1354f29dbc25Smrg		}
1355f29dbc25Smrg
1356f29dbc25Smrg		pPriv->videoStatus = 0;
1357f29dbc25Smrg	    }
1358f29dbc25Smrg	}
1359f29dbc25Smrg    }
1360f29dbc25Smrg}
1361f29dbc25Smrg
1362f29dbc25Smrg/****************** Offscreen stuff ***************/
1363f29dbc25Smrg
1364f29dbc25Smrgtypedef struct
1365f29dbc25Smrg{
1366f29dbc25Smrg    void *area;
1367f29dbc25Smrg    int offset;
1368f29dbc25Smrg    Bool isOn;
1369f29dbc25Smrg} OffscreenPrivRec, *OffscreenPrivPtr;
1370f29dbc25Smrg
1371f29dbc25Smrg/*----------------------------------------------------------------------------
1372f29dbc25Smrg * GXAllocateSurface
1373f29dbc25Smrg *
1374f29dbc25Smrg * Description	:This function allocates an area of w by h in the offscreen
1375f29dbc25Smrg *
1376f29dbc25Smrg * Parameters.
1377f29dbc25Smrg *		pScrni	:Screen handler pointer having screen information.
1378f29dbc25Smrg *
1379f29dbc25Smrg * Returns		:None
1380f29dbc25Smrg *
1381f29dbc25Smrg * Comments		:None
1382f29dbc25Smrg *----------------------------------------------------------------------------
1383f29dbc25Smrg */
1384f29dbc25Smrgstatic int
1385f29dbc25SmrgGXAllocateSurface(ScrnInfoPtr pScrni,
1386f29dbc25Smrg    int id, unsigned short w, unsigned short h, XF86SurfacePtr surface)
1387f29dbc25Smrg{
1388f29dbc25Smrg    void *area = NULL;
1389f29dbc25Smrg    int pitch, fbpitch, numlines;
1390f29dbc25Smrg    OffscreenPrivRec *pPriv;
1391f29dbc25Smrg
1392f29dbc25Smrg    if ((w > 1024) || (h > 1024))
1393f29dbc25Smrg	return BadAlloc;
1394f29dbc25Smrg
1395f29dbc25Smrg    w = (w + 1) & ~1;
1396f29dbc25Smrg    pitch = ((w << 1) + 15) & ~15;
1397f29dbc25Smrg    fbpitch = pScrni->bitsPerPixel * pScrni->displayWidth >> 3;
1398f29dbc25Smrg    numlines = ((pitch * h) + fbpitch - 1) / fbpitch;
1399f29dbc25Smrg
1400f29dbc25Smrg    if (!(offset = GXAllocateMemory(pScrni, &area, numlines)))
1401f29dbc25Smrg	return BadAlloc;
1402f29dbc25Smrg
1403f29dbc25Smrg    surface->width = w;
1404f29dbc25Smrg    surface->height = h;
1405f29dbc25Smrg
1406f29dbc25Smrg    if (!(surface->pitches = xalloc(sizeof(int))))
1407f29dbc25Smrg	return BadAlloc;
1408f29dbc25Smrg
1409f29dbc25Smrg    if (!(surface->offsets = xalloc(sizeof(int)))) {
1410f29dbc25Smrg	xfree(surface->pitches);
1411f29dbc25Smrg	return BadAlloc;
1412f29dbc25Smrg    }
1413f29dbc25Smrg
1414f29dbc25Smrg    if (!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
1415f29dbc25Smrg	xfree(surface->pitches);
1416f29dbc25Smrg	xfree(surface->offsets);
1417f29dbc25Smrg	return BadAlloc;
1418f29dbc25Smrg    }
1419f29dbc25Smrg
1420f29dbc25Smrg    pPriv->area = area;
1421f29dbc25Smrg    pPriv->offset = offset;
1422f29dbc25Smrg
1423f29dbc25Smrg    pPriv->isOn = FALSE;
1424f29dbc25Smrg
1425f29dbc25Smrg    surface->pScrn = pScrni;
1426f29dbc25Smrg    surface->id = id;
1427f29dbc25Smrg    surface->pitches[0] = pitch;
1428f29dbc25Smrg    surface->offsets[0] = offset;
1429f29dbc25Smrg    surface->devPrivate.ptr = (pointer) pPriv;
1430f29dbc25Smrg
1431f29dbc25Smrg    return Success;
1432f29dbc25Smrg}
1433f29dbc25Smrg
1434f29dbc25Smrgstatic int
1435f29dbc25SmrgGXStopSurface(XF86SurfacePtr surface)
1436f29dbc25Smrg{
1437f29dbc25Smrg    OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr;
1438f29dbc25Smrg
1439f29dbc25Smrg    if (pPriv->isOn) {
1440f29dbc25Smrg	pPriv->isOn = FALSE;
1441f29dbc25Smrg    }
1442f29dbc25Smrg
1443f29dbc25Smrg    return Success;
1444f29dbc25Smrg}
1445f29dbc25Smrg
1446f29dbc25Smrgstatic int
1447f29dbc25SmrgGXFreeSurface(XF86SurfacePtr surface)
1448f29dbc25Smrg{
1449f29dbc25Smrg    OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr;
1450f29dbc25Smrg
1451f29dbc25Smrg    if (pPriv->isOn)
1452f29dbc25Smrg	GXStopSurface(surface);
1453f29dbc25Smrg
1454f29dbc25Smrg    xf86FreeOffscreenArea(pPriv->area);
1455f29dbc25Smrg    xfree(surface->pitches);
1456f29dbc25Smrg    xfree(surface->offsets);
1457f29dbc25Smrg    xfree(surface->devPrivate.ptr);
1458f29dbc25Smrg
1459f29dbc25Smrg    return Success;
1460f29dbc25Smrg}
1461f29dbc25Smrg
1462f29dbc25Smrgstatic int
1463f29dbc25SmrgGXGetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 * value)
1464f29dbc25Smrg{
1465f29dbc25Smrg    return GXGetPortAttribute(pScrni, attribute, value,
1466f29dbc25Smrg	(pointer) (GET_PORT_PRIVATE(pScrni)));
1467f29dbc25Smrg}
1468f29dbc25Smrg
1469f29dbc25Smrgstatic int
1470f29dbc25SmrgGXSetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 value)
1471f29dbc25Smrg{
1472f29dbc25Smrg    return GXSetPortAttribute(pScrni, attribute, value,
1473f29dbc25Smrg	(pointer) (GET_PORT_PRIVATE(pScrni)));
1474f29dbc25Smrg}
1475f29dbc25Smrg
1476f29dbc25Smrgstatic int
1477f29dbc25SmrgGXDisplaySurface(XF86SurfacePtr surface,
1478f29dbc25Smrg    short src_x, short src_y,
1479f29dbc25Smrg    short drw_x, short drw_y,
1480f29dbc25Smrg    short src_w, short src_h, short drw_w, short drw_h, RegionPtr clipBoxes)
1481f29dbc25Smrg{
1482f29dbc25Smrg    OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr;
1483f29dbc25Smrg    ScrnInfoPtr pScrni = surface->pScrn;
1484f29dbc25Smrg    GeodePortPrivRec *portPriv = GET_PORT_PRIVATE(pScrni);
1485f29dbc25Smrg    INT32 x1, y1, x2, y2;
1486f29dbc25Smrg    BoxRec dstBox;
1487f29dbc25Smrg
1488f29dbc25Smrg    DEBUGMSG(0, (0, X_NONE, "DisplaySuface\n"));
1489f29dbc25Smrg    x1 = src_x;
1490f29dbc25Smrg    x2 = src_x + src_w;
1491f29dbc25Smrg    y1 = src_y;
1492f29dbc25Smrg    y2 = src_y + src_h;
1493f29dbc25Smrg
1494f29dbc25Smrg    dstBox.x1 = drw_x;
1495f29dbc25Smrg    dstBox.x2 = drw_x + drw_w;
1496f29dbc25Smrg    dstBox.y1 = drw_y;
1497f29dbc25Smrg    dstBox.y2 = drw_y + drw_h;
1498f29dbc25Smrg
1499f29dbc25Smrg    if ((x1 >= x2) || (y1 >= y2))
1500f29dbc25Smrg	return Success;
1501f29dbc25Smrg
1502f29dbc25Smrg    dstBox.x1 -= pScrni->frameX0;
1503f29dbc25Smrg    dstBox.x2 -= pScrni->frameX0;
1504f29dbc25Smrg    dstBox.y1 -= pScrni->frameY0;
1505f29dbc25Smrg    dstBox.y2 -= pScrni->frameY0;
1506f29dbc25Smrg
1507f29dbc25Smrg    xf86XVFillKeyHelper(pScrni->pScreen, portPriv->colorKey, clipBoxes);
1508f29dbc25Smrg
1509f29dbc25Smrg    GXDisplayVideo(pScrni, surface->id, surface->offsets[0],
1510f29dbc25Smrg	surface->width, surface->height, surface->pitches[0],
1511f29dbc25Smrg	x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
1512f29dbc25Smrg
1513f29dbc25Smrg    pPriv->isOn = TRUE;
1514f29dbc25Smrg    if (portPriv->videoStatus & CLIENT_VIDEO_ON) {
1515f29dbc25Smrg	REGION_EMPTY(pScrni->pScreen, &portPriv->clip);
1516f29dbc25Smrg	UpdateCurrentTime();
1517f29dbc25Smrg	portPriv->videoStatus = FREE_TIMER;
1518f29dbc25Smrg	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
1519f29dbc25Smrg    }
1520f29dbc25Smrg
1521f29dbc25Smrg    return Success;
1522f29dbc25Smrg}
1523f29dbc25Smrg
1524f29dbc25Smrg/*----------------------------------------------------------------------------
1525f29dbc25Smrg * GXInitOffscreenImages
1526f29dbc25Smrg *
1527f29dbc25Smrg * Description	:This function sets up the offscreen memory management. It
1528f29dbc25Smrg * 				fills in the XF86OffscreenImagePtr structure with functions to
1529f29dbc25Smrg * 				handle offscreen memory operations.
1530f29dbc25Smrg *
1531f29dbc25Smrg * Parameters.
1532f29dbc25Smrg *		pScrn	:Screen handler pointer having screen information.
1533f29dbc25Smrg *
1534f29dbc25Smrg * Returns		: None
1535f29dbc25Smrg *
1536f29dbc25Smrg * Comments		:None
1537f29dbc25Smrg *----------------------------------------------------------------------------
1538f29dbc25Smrg */
1539f29dbc25Smrgstatic void
1540f29dbc25SmrgGXInitOffscreenImages(ScreenPtr pScrn)
1541f29dbc25Smrg{
1542f29dbc25Smrg    XF86OffscreenImagePtr offscreenImages;
1543f29dbc25Smrg
1544f29dbc25Smrg    /* need to free this someplace */
1545f29dbc25Smrg    if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
1546f29dbc25Smrg	return;
1547f29dbc25Smrg
1548f29dbc25Smrg    offscreenImages[0].image = &Images[0];
1549f29dbc25Smrg    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
1550f29dbc25Smrg    offscreenImages[0].alloc_surface = GXAllocateSurface;
1551f29dbc25Smrg    offscreenImages[0].free_surface = GXFreeSurface;
1552f29dbc25Smrg    offscreenImages[0].display = GXDisplaySurface;
1553f29dbc25Smrg    offscreenImages[0].stop = GXStopSurface;
1554f29dbc25Smrg    offscreenImages[0].setAttribute = GXSetSurfaceAttribute;
1555f29dbc25Smrg    offscreenImages[0].getAttribute = GXGetSurfaceAttribute;
1556f29dbc25Smrg    offscreenImages[0].max_width = 1024;
1557f29dbc25Smrg    offscreenImages[0].max_height = 1024;
1558f29dbc25Smrg    offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
1559f29dbc25Smrg    offscreenImages[0].attributes = Attributes;
1560f29dbc25Smrg
1561f29dbc25Smrg    xf86XVRegisterOffscreenImages(pScrn, offscreenImages, 1);
1562f29dbc25Smrg}
1563f29dbc25Smrg
1564f29dbc25Smrg#endif /* !XvExtension */
1565