pm3_video.c revision 1fb744b4
1c35d236eSmrg/*
2c35d236eSmrg * Copyright 2001 by Alan Hourihane, Sychdyn, North Wales.
3c35d236eSmrg *
4c35d236eSmrg * Permission to use, copy, modify, distribute, and sell this software and its
5c35d236eSmrg * documentation for any purpose is hereby granted without fee, provided that
6c35d236eSmrg * the above copyright notice appear in all copies and that both that
7c35d236eSmrg * copyright notice and this permission notice appear in supporting
8c35d236eSmrg * documentation, and that the name of Alan Hourihane not be used in
9c35d236eSmrg * advertising or publicity pertaining to distribution of the software without
10c35d236eSmrg * specific, written prior permission.  Alan Hourihane makes no representations
11c35d236eSmrg * about the suitability of this software for any purpose.  It is provided
12c35d236eSmrg * "as is" without express or implied warranty.
13c35d236eSmrg *
14c35d236eSmrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15c35d236eSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16c35d236eSmrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17c35d236eSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18c35d236eSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19c35d236eSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20c35d236eSmrg * PERFORMANCE OF THIS SOFTWARE.
21c35d236eSmrg *
22c35d236eSmrg * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk
23c35d236eSmrg *          Sven Luther <luther@dpt-info.u-strasbg.fr>
24c35d236eSmrg */
25c35d236eSmrg
26c35d236eSmrg#ifdef HAVE_CONFIG_H
27c35d236eSmrg#include "config.h"
28c35d236eSmrg#endif
29c35d236eSmrg
30c35d236eSmrg#include "xf86.h"
31c35d236eSmrg#include "xf86_OSproc.h"
32c35d236eSmrg#include "compiler.h"
33c35d236eSmrg#include "xf86Pci.h"
34c35d236eSmrg#include "xf86fbman.h"
35c35d236eSmrg#include "regionstr.h"
36c35d236eSmrg
37c35d236eSmrg#include "glint.h"
38c35d236eSmrg#include "glint_regs.h"
39c35d236eSmrg#include "pm3_regs.h"
40c35d236eSmrg#include <X11/extensions/Xv.h>
41c35d236eSmrg#include "dixstruct.h"
42c35d236eSmrg#include "fourcc.h"
43c35d236eSmrg
44c35d236eSmrg#define OFF_DELAY 	200  /* milliseconds */
45c35d236eSmrg#define FREE_DELAY 	60000
46c35d236eSmrg
47c35d236eSmrg#define OFF_TIMER 	0x01
48c35d236eSmrg#define FREE_TIMER	0x02
49c35d236eSmrg#define CLIENT_VIDEO_ON	0x04
50c35d236eSmrg
51c35d236eSmrg#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
52c35d236eSmrg
53c35d236eSmrgstatic XF86VideoAdaptorPtr Permedia3SetupImageVideo(ScreenPtr);
54c35d236eSmrgstatic void Permedia3InitOffscreenImages(ScreenPtr);
55c35d236eSmrgstatic void Permedia3StopVideo(ScrnInfoPtr, pointer, Bool);
56c35d236eSmrgstatic int Permedia3SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
57c35d236eSmrgstatic int Permedia3GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
58c35d236eSmrgstatic void Permedia3QueryBestSize(ScrnInfoPtr, Bool,
59c35d236eSmrg	short, short, short, short, unsigned int *, unsigned int *, pointer);
60c35d236eSmrgstatic int Permedia3PutImage( ScrnInfoPtr,
61c35d236eSmrg	short, short, short, short, short, short, short, short,
62c35d236eSmrg	int, unsigned char*, short, short, Bool, RegionPtr, pointer,
63c35d236eSmrg	DrawablePtr);
64c35d236eSmrgstatic int Permedia3QueryImageAttributes(ScrnInfoPtr,
65c35d236eSmrg	int, unsigned short *, unsigned short *,  int *, int *);
66c35d236eSmrgstatic void Permedia3VideoTimerCallback(ScrnInfoPtr pScrn, Time time);
67c35d236eSmrg
68c35d236eSmrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
69c35d236eSmrg
70c35d236eSmrgstatic Atom xvColorKey, xvDoubleBuffer, xvAutopaintColorKey, xvFilter;
71c35d236eSmrg
72c35d236eSmrgvoid Permedia3InitVideo(ScreenPtr pScreen)
73c35d236eSmrg{
741fb744b4Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
75c35d236eSmrg    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
76c35d236eSmrg    XF86VideoAdaptorPtr newAdaptor = NULL;
77c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
78c35d236eSmrg    int num_adaptors;
79c35d236eSmrg
80c35d236eSmrg    /* Because of bugs in the PM3 when uploading images via the
81c35d236eSmrg     * bypass to the framebuffer, we always have to use the accelerator.
82c35d236eSmrg     */
83c35d236eSmrg    if (pGlint->NoAccel)
84c35d236eSmrg	return;
85c35d236eSmrg
86c35d236eSmrg    newAdaptor = Permedia3SetupImageVideo(pScreen);
87c35d236eSmrg    Permedia3InitOffscreenImages(pScreen);
88c35d236eSmrg
89c35d236eSmrg    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
90c35d236eSmrg
91c35d236eSmrg    if(newAdaptor) {
92c35d236eSmrg	if(!num_adaptors) {
93c35d236eSmrg	    num_adaptors = 1;
94c35d236eSmrg	    adaptors = &newAdaptor;
95c35d236eSmrg	} else {
96c35d236eSmrg	    newAdaptors =  /* need to free this someplace */
971fb744b4Smrg		malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *));
98c35d236eSmrg	    if(newAdaptors) {
99c35d236eSmrg		memcpy(newAdaptors, adaptors, num_adaptors *
100c35d236eSmrg					sizeof(XF86VideoAdaptorPtr));
101c35d236eSmrg		newAdaptors[num_adaptors] = newAdaptor;
102c35d236eSmrg		adaptors = newAdaptors;
103c35d236eSmrg		num_adaptors++;
104c35d236eSmrg	    }
105c35d236eSmrg	}
106c35d236eSmrg    }
107c35d236eSmrg
108c35d236eSmrg    if(num_adaptors)
109c35d236eSmrg        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
110c35d236eSmrg
1111fb744b4Smrg    free(newAdaptors);
112c35d236eSmrg}
113c35d236eSmrg
114c35d236eSmrg/* client libraries expect an encoding */
115c35d236eSmrgstatic XF86VideoEncodingRec DummyEncoding[1] =
116c35d236eSmrg{
117c35d236eSmrg {
118c35d236eSmrg   0,
119c35d236eSmrg   "XV_IMAGE",
120c35d236eSmrg   2047, 2047,
121c35d236eSmrg   {1, 1}
122c35d236eSmrg }
123c35d236eSmrg};
124c35d236eSmrg
125c35d236eSmrg#define NUM_FORMATS 4
126c35d236eSmrg
127c35d236eSmrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] =
128c35d236eSmrg{
129c35d236eSmrg  {8, PseudoColor},  {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
130c35d236eSmrg};
131c35d236eSmrg
132c35d236eSmrg#define NUM_ATTRIBUTES 4
133c35d236eSmrg
134c35d236eSmrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
135c35d236eSmrg{
136c35d236eSmrg   {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
137c35d236eSmrg   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
138c35d236eSmrg   {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
139c35d236eSmrg   {XvSettable | XvGettable, 0, 2, "XV_FILTER"},
140c35d236eSmrg};
141c35d236eSmrg
142c35d236eSmrg/*
143c35d236eSmrg *  FOURCC from http://www.webartz.com/fourcc
144c35d236eSmrg *  Generic GUID for legacy FOURCC XXXXXXXX-0000-0010-8000-00AA00389B71
145c35d236eSmrg */
146c35d236eSmrg#define LE4CC(a,b,c,d) (((CARD32)(a)&0xFF)|(((CARD32)(b)&0xFF)<<8)|(((CARD32)(c)&0xFF)<<16)|(((CARD32)(d)&0xFF)<<24))
147c35d236eSmrg#define GUID4CC(a,b,c,d) { a,b,c,d,0,0,0,0x10,0x80,0,0,0xAA,0,0x38,0x9B,0x71 }
148c35d236eSmrg
149c35d236eSmrg#define NoOrder LSBFirst
150c35d236eSmrg
151c35d236eSmrg#define NUM_IMAGES 15
152c35d236eSmrg
153c35d236eSmrgstatic XF86ImageRec Images[NUM_IMAGES] =
154c35d236eSmrg{
155c35d236eSmrg    /* Planar YVU 4:2:0 (emulated) */
156c35d236eSmrg    { LE4CC('Y','V','1','2'), XvYUV, NoOrder, GUID4CC('Y','V','1','2'),
157c35d236eSmrg      12, XvPlanar, 3, 0, 0, 0, 0,
158c35d236eSmrg      8, 8, 8,  1, 2, 2,  1, 2, 2, "YVU", XvTopToBottom },
159c35d236eSmrg
160c35d236eSmrg    /* Packed YUYV 4:2:2 */
161c35d236eSmrg    { LE4CC('Y','U','Y','2'), XvYUV, NoOrder, GUID4CC('Y','U','Y','2'),
162c35d236eSmrg      16, XvPacked, 1, 0, 0, 0, 0,
163c35d236eSmrg      8, 8, 8,  1, 2, 2,  1, 1, 1, "YUYV", XvTopToBottom },
164c35d236eSmrg
165c35d236eSmrg    /* Packed UYVY 4:2:2 */
166c35d236eSmrg    { LE4CC('U','Y','V','Y'), XvYUV, NoOrder, GUID4CC('U','Y','V','Y'),
167c35d236eSmrg      16, XvPacked, 1, 0, 0, 0, 0,
168c35d236eSmrg      8, 8, 8,  1, 2, 2,  1, 1, 1, "UYVY", XvTopToBottom },
169c35d236eSmrg
170c35d236eSmrg    /* Packed YUVA 4:4:4 */
171c35d236eSmrg    { LE4CC('Y','U','V','A') /* XXX not registered */, XvYUV, LSBFirst, { 0 },
172c35d236eSmrg      32, XvPacked, 1, 0, 0, 0, 0,
173c35d236eSmrg      8, 8, 8,  1, 1, 1,  1, 1, 1, "YUVA", XvTopToBottom },
174c35d236eSmrg
175c35d236eSmrg    /* Packed VUYA 4:4:4 */
176c35d236eSmrg    { LE4CC('V','U','Y','A') /* XXX not registered */, XvYUV, LSBFirst, { 0 },
177c35d236eSmrg      32, XvPacked, 1, 0, 0, 0, 0,
178c35d236eSmrg      8, 8, 8,  1, 1, 1,  1, 1, 1, "VUYA", XvTopToBottom },
179c35d236eSmrg
180c35d236eSmrg    /* RGBA 8:8:8:8 */
181c35d236eSmrg    { 0x41, XvRGB, LSBFirst, { 0 },
182c35d236eSmrg      32, XvPacked, 1, 24, 0x0000FF, 0x00FF00, 0xFF0000,
183c35d236eSmrg      0, 0, 0,  0, 0, 0,  0, 0, 0, "RGBA", XvTopToBottom },
184c35d236eSmrg
185c35d236eSmrg    /* RGB 5:6:5 */
186c35d236eSmrg    { 0x42, XvRGB, LSBFirst, { 0 },
187c35d236eSmrg      16, XvPacked, 1, 16, 0x001F, 0x07E0, 0xF800,
188c35d236eSmrg      0, 0, 0,  0, 0, 0,  0, 0, 0, "RGB", XvTopToBottom },
189c35d236eSmrg
190c35d236eSmrg    /* RGBA 5:5:5:1 */
191c35d236eSmrg    { 0x43, XvRGB, LSBFirst, { 0 },
192c35d236eSmrg      16, XvPacked, 1, 15, 0x001F, 0x03E0, 0x7C00,
193c35d236eSmrg      0, 0, 0,  0, 0, 0,  0, 0, 0, "RGBA", XvTopToBottom },
194c35d236eSmrg
195c35d236eSmrg    /* RGBA 4:4:4:4 */
196c35d236eSmrg    { 0x44, XvRGB, LSBFirst, { 0 },
197c35d236eSmrg      16, XvPacked, 1, 12, 0x000F, 0x00F0, 0x0F00,
198c35d236eSmrg      0, 0, 0,  0, 0, 0,  0, 0, 0, "RGBA", XvTopToBottom },
199c35d236eSmrg
200c35d236eSmrg    /* RGB 3:3:2 */
201c35d236eSmrg    { 0x46, XvRGB, NoOrder, { 0 },
202c35d236eSmrg      8, XvPacked, 1, 8, 0x07, 0x38, 0xC0,
203c35d236eSmrg      0, 0, 0,  0, 0, 0,  0, 0, 0, "RGB", XvTopToBottom },
204c35d236eSmrg
205c35d236eSmrg    /* BGRA 8:8:8:8 */
206c35d236eSmrg    { 0x47, XvRGB, LSBFirst, { 0 },
207c35d236eSmrg      32, XvPacked, 1, 24, 0xFF0000, 0x00FF00, 0x0000FF,
208c35d236eSmrg      0, 0, 0,  0, 0, 0,  0, 0, 0, "BGRA", XvTopToBottom },
209c35d236eSmrg
210c35d236eSmrg    /* BGR 5:6:5 */
211c35d236eSmrg    { 0x48, XvRGB, LSBFirst, { 0 },
212c35d236eSmrg      16, XvPacked, 1, 16, 0xF800, 0x07E0, 0x001F,
213c35d236eSmrg      0, 0, 0,  0, 0, 0,  0, 0, 0, "BGR", XvTopToBottom },
214c35d236eSmrg
215c35d236eSmrg    /* BGRA 5:5:5:1 */
216c35d236eSmrg    { 0x49, XvRGB, LSBFirst, { 0 },
217c35d236eSmrg      16, XvPacked, 1, 15, 0x7C00, 0x03E0, 0x001F,
218c35d236eSmrg      0, 0, 0,  0, 0, 0,  0, 0, 0, "BGRA", XvTopToBottom },
219c35d236eSmrg
220c35d236eSmrg    /* BGRA 4:4:4:4 */
221c35d236eSmrg    { 0x4A, XvRGB, LSBFirst, { 0 },
222c35d236eSmrg      16, XvPacked, 1, 12, 0x0F00, 0x00F0, 0x000F,
223c35d236eSmrg      0, 0, 0,  0, 0, 0,  0, 0, 0, "BGRA", XvTopToBottom },
224c35d236eSmrg
225c35d236eSmrg    /* BGR 2:3:3 */
226c35d236eSmrg    { 0x4C, XvRGB, NoOrder, { 0 },
227c35d236eSmrg      8, XvPacked, 1, 8, 0xC0, 0x38, 0x07,
228c35d236eSmrg      0, 0, 0,  0, 0, 0,  0, 0, 0, "BGR", XvTopToBottom },
229c35d236eSmrg};
230c35d236eSmrg
231c35d236eSmrg#define MAX_BUFFERS 2
232c35d236eSmrg
233c35d236eSmrgtypedef struct {
234c35d236eSmrg   FBAreaPtr	area[MAX_BUFFERS];
235c35d236eSmrg   RegionRec	clip;
236c35d236eSmrg   CARD32	colorKey;
237c35d236eSmrg   CARD32	videoStatus;
238c35d236eSmrg   Time		offTime;
239c35d236eSmrg   Time		freeTime;
240c35d236eSmrg   int		Video_Shift;
241c35d236eSmrg   int		Format;
242c35d236eSmrg   Bool		ramdacOn;
243c35d236eSmrg   Bool		doubleBuffer;
244c35d236eSmrg   Bool		autopaintColorKey;
245c35d236eSmrg   int		Filter;
246c35d236eSmrg   int		sx, sy;
247c35d236eSmrg   int		offset[MAX_BUFFERS];
248c35d236eSmrg   int		buffer;
249c35d236eSmrg} GLINTPortPrivRec, *GLINTPortPrivPtr;
250c35d236eSmrg
251c35d236eSmrg#define GET_PORT_PRIVATE(pScrn) \
252c35d236eSmrg   (GLINTPortPrivPtr)((GLINTPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
253c35d236eSmrg
254c35d236eSmrg#define	RAMDAC_WRITE(data,index)				\
255c35d236eSmrgdo{                                                             \
256c35d236eSmrg	GLINT_WRITE_REG(((index)>>8)&0xff, PM3RD_IndexHigh);	\
257c35d236eSmrg 	GLINT_WRITE_REG((index)&0xff, PM3RD_IndexLow);		\
258c35d236eSmrg	GLINT_WRITE_REG(data, PM3RD_IndexedData);		\
259c35d236eSmrg}while(0)
260c35d236eSmrg
261c35d236eSmrgvoid Permedia3ResetVideo(ScrnInfoPtr pScrn)
262c35d236eSmrg{
263c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
264c35d236eSmrg    GLINTPortPrivPtr pPriv = pGlint->adaptor->pPortPrivates[0].ptr;
265c35d236eSmrg
266c35d236eSmrg    GLINT_WAIT(15);
267c35d236eSmrg    GLINT_WRITE_REG(0xfff0|(0xffff<<16), PM3VideoOverlayFifoControl);
268c35d236eSmrg    GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE, PM3VideoOverlayMode);
269c35d236eSmrg    pPriv->ramdacOn = FALSE;
270c35d236eSmrg    RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE, PM3RD_VideoOverlayControl);
271c35d236eSmrg    RAMDAC_WRITE((pPriv->colorKey&0xff0000)>>16, PM3RD_VideoOverlayKeyR);
272c35d236eSmrg    RAMDAC_WRITE((pPriv->colorKey&0x00ff00)>>8, PM3RD_VideoOverlayKeyG);
273c35d236eSmrg    RAMDAC_WRITE(pPriv->colorKey&0x0000ff, PM3RD_VideoOverlayKeyB);
274c35d236eSmrg    GLINT_WRITE_REG(PM3VideoOverlayUpdate_ENABLE, PM3VideoOverlayUpdate);
275c35d236eSmrg}
276c35d236eSmrg
277c35d236eSmrg
278c35d236eSmrgstatic XF86VideoAdaptorPtr
279c35d236eSmrgPermedia3SetupImageVideo(ScreenPtr pScreen)
280c35d236eSmrg{
2811fb744b4Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
282c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
283c35d236eSmrg    XF86VideoAdaptorPtr adapt;
284c35d236eSmrg    GLINTPortPrivPtr pPriv;
285c35d236eSmrg
2861fb744b4Smrg    if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
287c35d236eSmrg			    sizeof(GLINTPortPrivRec) +
288c35d236eSmrg			    sizeof(DevUnion))))
289c35d236eSmrg	return NULL;
290c35d236eSmrg
291c35d236eSmrg    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
292c35d236eSmrg    adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
293c35d236eSmrg    adapt->name = "Permedia3 Backend Scaler";
294c35d236eSmrg    adapt->nEncodings = 1;
295c35d236eSmrg    adapt->pEncodings = DummyEncoding;
296c35d236eSmrg    adapt->nFormats = NUM_FORMATS;
297c35d236eSmrg    adapt->pFormats = Formats;
298c35d236eSmrg    adapt->nPorts = 1;
299c35d236eSmrg    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
300c35d236eSmrg    pPriv = (GLINTPortPrivPtr)(&adapt->pPortPrivates[1]);
301c35d236eSmrg    adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
302c35d236eSmrg    adapt->pAttributes = Attributes;
303c35d236eSmrg    adapt->nImages = NUM_IMAGES;
304c35d236eSmrg    adapt->nAttributes = NUM_ATTRIBUTES;
305c35d236eSmrg    adapt->pImages = Images;
306c35d236eSmrg    adapt->PutVideo = NULL;
307c35d236eSmrg    adapt->PutStill = NULL;
308c35d236eSmrg    adapt->GetVideo = NULL;
309c35d236eSmrg    adapt->GetStill = NULL;
310c35d236eSmrg    adapt->StopVideo = Permedia3StopVideo;
311c35d236eSmrg    adapt->SetPortAttribute = Permedia3SetPortAttribute;
312c35d236eSmrg    adapt->GetPortAttribute = Permedia3GetPortAttribute;
313c35d236eSmrg    adapt->QueryBestSize = Permedia3QueryBestSize;
314c35d236eSmrg    adapt->PutImage = Permedia3PutImage;
315c35d236eSmrg    adapt->QueryImageAttributes = Permedia3QueryImageAttributes;
316c35d236eSmrg
317c35d236eSmrg    /* FIXME : depth 15 and 16 doesn't work here */
318c35d236eSmrg    pPriv->colorKey = pGlint->videoKey;
319c35d236eSmrg    pPriv->videoStatus = 0;
320c35d236eSmrg    pPriv->buffer = 0; /* double buffer (or maybe triple later) */
321c35d236eSmrg    pPriv->doubleBuffer = TRUE;
322c35d236eSmrg    pPriv->autopaintColorKey = TRUE;
323c35d236eSmrg    pPriv->Filter = PM3VideoOverlayMode_FILTER_FULL;
324c35d236eSmrg
325c35d236eSmrg    /* gotta uninit this someplace */
326c35d236eSmrg    REGION_NULL(pScreen, &pPriv->clip);
327c35d236eSmrg
328c35d236eSmrg    pGlint->adaptor = adapt;
329c35d236eSmrg
330c35d236eSmrg    xvDoubleBuffer      = MAKE_ATOM("XV_DOUBLE_BUFFER");
331c35d236eSmrg    xvColorKey          = MAKE_ATOM("XV_COLORKEY");
332c35d236eSmrg    xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
333c35d236eSmrg    xvFilter		= MAKE_ATOM("XV_FILTER");
334c35d236eSmrg
335c35d236eSmrg    Permedia3ResetVideo(pScrn);
336c35d236eSmrg
337c35d236eSmrg    return adapt;
338c35d236eSmrg}
339c35d236eSmrg
340c35d236eSmrg
341c35d236eSmrgstatic void
342c35d236eSmrgPermedia3StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
343c35d236eSmrg{
344c35d236eSmrg  GLINTPtr pGlint = GLINTPTR(pScrn);
345c35d236eSmrg  GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data;
346c35d236eSmrg  int i;
347c35d236eSmrg
348c35d236eSmrg  REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
349c35d236eSmrg
350c35d236eSmrg  if(shutdown) {
351c35d236eSmrg     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
352c35d236eSmrg    	pPriv->ramdacOn = FALSE;
353c35d236eSmrg	GLINT_WAIT(4);
354c35d236eSmrg        RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE,
355c35d236eSmrg		PM3RD_VideoOverlayControl);
356c35d236eSmrg	GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE,
357c35d236eSmrg		PM3VideoOverlayMode);
358c35d236eSmrg     }
359c35d236eSmrg     for (i = 0; i < (pPriv->doubleBuffer ? 2 : 1); i++) {
360c35d236eSmrg        if(pPriv->area[i]) {
361c35d236eSmrg	   xf86FreeOffscreenArea(pPriv->area[i]);
362c35d236eSmrg	   pPriv->area[i] = NULL;
363c35d236eSmrg        }
364c35d236eSmrg     }
365c35d236eSmrg     pPriv->videoStatus = 0;
366c35d236eSmrg  } else {
367c35d236eSmrg     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
368c35d236eSmrg	pPriv->videoStatus |= OFF_TIMER;
369c35d236eSmrg	pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
370c35d236eSmrg     }
371c35d236eSmrg  }
372c35d236eSmrg}
373c35d236eSmrg
374c35d236eSmrgstatic int
375c35d236eSmrgPermedia3SetPortAttribute(
376c35d236eSmrg  ScrnInfoPtr pScrn,
377c35d236eSmrg  Atom attribute,
378c35d236eSmrg  INT32 value,
379c35d236eSmrg  pointer data
380c35d236eSmrg){
381c35d236eSmrg    GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data;
382c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
383c35d236eSmrg
384c35d236eSmrg    if (attribute == xvDoubleBuffer)
385c35d236eSmrg    {
386c35d236eSmrg        if ((value < 0) || (value > 1))
387c35d236eSmrg            return BadValue;
388c35d236eSmrg        pPriv->doubleBuffer = value;
389c35d236eSmrg    }
390c35d236eSmrg    else if (attribute == xvColorKey)
391c35d236eSmrg    {
392c35d236eSmrg        pPriv->colorKey = value;
393c35d236eSmrg	GLINT_WAIT(9);
394c35d236eSmrg    	RAMDAC_WRITE((value & 0xff0000)>>16, PM3RD_VideoOverlayKeyR);
395c35d236eSmrg    	RAMDAC_WRITE((value & 0x00ff00)>>8, PM3RD_VideoOverlayKeyG);
396c35d236eSmrg    	RAMDAC_WRITE((value & 0x0000ff), PM3RD_VideoOverlayKeyB);
397c35d236eSmrg	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
398c35d236eSmrg    }
399c35d236eSmrg    else if (attribute == xvAutopaintColorKey)
400c35d236eSmrg    {
401c35d236eSmrg        if ((value < 0) || (value > 1))
402c35d236eSmrg            return BadValue;
403c35d236eSmrg        pPriv->autopaintColorKey = value;
404c35d236eSmrg    }
405c35d236eSmrg    else if (attribute == xvFilter)
406c35d236eSmrg    {
407c35d236eSmrg        if ((value < 0) || (value > 2))
408c35d236eSmrg            return BadValue;
409c35d236eSmrg	switch (value) {
410c35d236eSmrg	    case 0:
411c35d236eSmrg    		pPriv->Filter = PM3VideoOverlayMode_FILTER_OFF;
412c35d236eSmrg		break;
413c35d236eSmrg	    case 1:
414c35d236eSmrg    		pPriv->Filter = PM3VideoOverlayMode_FILTER_FULL;
415c35d236eSmrg		break;
416c35d236eSmrg	    case 2:
417c35d236eSmrg    		pPriv->Filter = PM3VideoOverlayMode_FILTER_PARTIAL;
418c35d236eSmrg		break;
419c35d236eSmrg	}
420c35d236eSmrg    }
421c35d236eSmrg    else
422c35d236eSmrg        return BadMatch;
423c35d236eSmrg
424c35d236eSmrg  return Success;
425c35d236eSmrg}
426c35d236eSmrg
427c35d236eSmrgstatic int
428c35d236eSmrgPermedia3GetPortAttribute(
429c35d236eSmrg  ScrnInfoPtr pScrn,
430c35d236eSmrg  Atom attribute,
431c35d236eSmrg  INT32 *value,
432c35d236eSmrg  pointer data
433c35d236eSmrg){
434c35d236eSmrg    GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data;
435c35d236eSmrg
436c35d236eSmrg    if (attribute == xvDoubleBuffer)
437c35d236eSmrg        *value = (pPriv->doubleBuffer) ? 1 : 0;
438c35d236eSmrg    else if (attribute == xvColorKey)
439c35d236eSmrg        *value = pPriv->colorKey;
440c35d236eSmrg    else if (attribute == xvAutopaintColorKey)
441c35d236eSmrg        *value = (pPriv->autopaintColorKey) ? 1 : 0;
442c35d236eSmrg    else if (attribute == xvFilter)
443c35d236eSmrg        *value = pPriv->Filter >> 14;
444c35d236eSmrg    else
445c35d236eSmrg        return BadMatch;
446c35d236eSmrg
447c35d236eSmrg    return Success;
448c35d236eSmrg}
449c35d236eSmrg
450c35d236eSmrgstatic void
451c35d236eSmrgPermedia3QueryBestSize(
452c35d236eSmrg  ScrnInfoPtr pScrn,
453c35d236eSmrg  Bool motion,
454c35d236eSmrg  short vid_w, short vid_h,
455c35d236eSmrg  short drw_w, short drw_h,
456c35d236eSmrg  unsigned int *p_w, unsigned int *p_h,
457c35d236eSmrg  pointer data
458c35d236eSmrg){
459c35d236eSmrg    if(vid_w > (drw_w << 3))
460c35d236eSmrg	drw_w = vid_w >> 3;
461c35d236eSmrg    if(vid_h > (drw_h << 3))
462c35d236eSmrg	drw_h = vid_h >> 3;
463c35d236eSmrg
464c35d236eSmrg    *p_w = drw_w;
465c35d236eSmrg    *p_h = drw_h;
466c35d236eSmrg}
467c35d236eSmrg
468c35d236eSmrgstatic void
469c35d236eSmrgHWCopySetup(ScrnInfoPtr pScrn, int x, int y, int w, int h)
470c35d236eSmrg{
471c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
472c35d236eSmrg
473c35d236eSmrg    GLINT_WAIT(4);
474c35d236eSmrg    GLINT_WRITE_REG(0xffffffff, FBHardwareWriteMask);
475c35d236eSmrg    GLINT_WRITE_REG(
476c35d236eSmrg	PM3Config2D_ForegroundROPEnable |
477c35d236eSmrg	PM3Config2D_ForegroundROP(GXcopy) |
478c35d236eSmrg	PM3Config2D_FBWriteEnable,
479c35d236eSmrg	PM3Config2D);
480c35d236eSmrg    GLINT_WRITE_REG(
481c35d236eSmrg	PM3RectanglePosition_XOffset(x) |
482c35d236eSmrg	PM3RectanglePosition_YOffset(y),
483c35d236eSmrg	PM3RectanglePosition);
484c35d236eSmrg    GLINT_WRITE_REG(
485c35d236eSmrg	PM3Render2D_SpanOperation |
486c35d236eSmrg	PM3Render2D_XPositive |
487c35d236eSmrg	PM3Render2D_YPositive |
488c35d236eSmrg	PM3Render2D_Operation_SyncOnHostData |
489c35d236eSmrg	PM3Render2D_Width(w) | PM3Render2D_Height(h),
490c35d236eSmrg	PM3Render2D);
491c35d236eSmrg}
492c35d236eSmrg
493c35d236eSmrgstatic void
494c35d236eSmrgHWCopyYV12(ScrnInfoPtr pScrn, CARD8 *Y, int w, int h)
495c35d236eSmrg{
496c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
497c35d236eSmrg    int size = w * h;
498c35d236eSmrg    CARD8 *V = Y + size;
499c35d236eSmrg    CARD8 *U = V + (size >> 2);
500c35d236eSmrg    CARD32 *dst;
501c35d236eSmrg    int pass2 = 0;
502c35d236eSmrg    int dwords, i, x = 0;
503c35d236eSmrg
504c35d236eSmrg    dwords = size >> 1;
505c35d236eSmrg
506c35d236eSmrg    w >>= 1;
507c35d236eSmrg
508c35d236eSmrg    while (dwords >= pGlint->FIFOSize) {
509c35d236eSmrg	dst = (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4);
510c35d236eSmrg	GLINT_WAIT(pGlint->FIFOSize);
511c35d236eSmrg	/* (0x15 << 4) | 0x05 is the TAG for FBSourceData */
512c35d236eSmrg	GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | (0x15 << 4) |
513c35d236eSmrg	    0x05, OutputFIFO);
514c35d236eSmrg	for (i = pGlint->FIFOSize - 1; i; i--, Y += 2, x++) {
515c35d236eSmrg	    if (x == w) {
516c35d236eSmrg		x = 0;
517c35d236eSmrg		if (pass2 == 0)
518c35d236eSmrg		    pass2 = 1;
519c35d236eSmrg		else
520c35d236eSmrg		if (pass2 == 1) {
521c35d236eSmrg		    pass2 = 0;
522c35d236eSmrg		    U += w;
523c35d236eSmrg		    V += w;
524c35d236eSmrg		}
525c35d236eSmrg	    }
526c35d236eSmrg	    *dst++ = Y[0] + (U[x] << 8) + (Y[1] << 16) + (V[x] << 24);
527c35d236eSmrg	}
528c35d236eSmrg	dwords -= pGlint->FIFOSize - 1;
529c35d236eSmrg    }
530c35d236eSmrg    if (dwords) {
531c35d236eSmrg	dst = (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4);
532c35d236eSmrg	GLINT_WAIT(dwords + 1);
533c35d236eSmrg	/* (0x15 << 4) | 0x05 is the TAG for FBSourceData */
534c35d236eSmrg	GLINT_WRITE_REG(((dwords - 1) << 16) | (0x15 << 4) |
535c35d236eSmrg	    0x05, OutputFIFO);
536c35d236eSmrg	for (i = dwords; i; i--, Y += 2, x++) {
537c35d236eSmrg	    if (x == w) {
538c35d236eSmrg		x = 0;
539c35d236eSmrg		if (pass2 == 0)
540c35d236eSmrg		    pass2 = 1;
541c35d236eSmrg		else
542c35d236eSmrg		if (pass2 == 1) {
543c35d236eSmrg		    pass2 = 0;
544c35d236eSmrg		    U += w;
545c35d236eSmrg		    V += w;
546c35d236eSmrg		}
547c35d236eSmrg	    }
548c35d236eSmrg	    *dst++ = Y[0] + (U[x] << 8) + (Y[1] << 16) + (V[x] << 24);
549c35d236eSmrg	}
550c35d236eSmrg    }
551c35d236eSmrg}
552c35d236eSmrg
553c35d236eSmrgstatic void
554c35d236eSmrgHWCopyFlat(ScrnInfoPtr pScrn, CARD8 *src, int w, int h)
555c35d236eSmrg{
556c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
557c35d236eSmrg    GLINTPortPrivPtr pPriv = pGlint->adaptor->pPortPrivates[0].ptr;
558c35d236eSmrg    int pitch = pScrn->displayWidth;
559c35d236eSmrg    CARD8 *tmp_src;
560c35d236eSmrg    int dwords;
561c35d236eSmrg
562c35d236eSmrg    if (w == pitch) {
563c35d236eSmrg    	dwords = (w * h) >> (2 - pPriv->Video_Shift);
564c35d236eSmrg    	while(dwords >= pGlint->FIFOSize) {
565c35d236eSmrg	    GLINT_WAIT(pGlint->FIFOSize);
566c35d236eSmrg            GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | (0x15 << 4) |
567c35d236eSmrg			0x05, OutputFIFO);
568c35d236eSmrg	    GLINT_MoveDWORDS(
569c35d236eSmrg		(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
570c35d236eSmrg	 	(CARD32*)src, pGlint->FIFOSize - 1);
571c35d236eSmrg	    dwords -= (pGlint->FIFOSize - 1);
572c35d236eSmrg	    src += (pGlint->FIFOSize << 2) - 4;
573c35d236eSmrg    	}
574c35d236eSmrg    	if(dwords) {
575c35d236eSmrg	    GLINT_WAIT(dwords + 1);
576c35d236eSmrg            GLINT_WRITE_REG(((dwords - 1) << 16)|(0x15 << 4) |0x05, OutputFIFO);
577c35d236eSmrg	    GLINT_MoveDWORDS(
578c35d236eSmrg		(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
579c35d236eSmrg	 	(CARD32*)src, dwords);
580c35d236eSmrg    	}
581c35d236eSmrg    } else {
582c35d236eSmrg  	while (h--) {
583c35d236eSmrg    	    tmp_src = src;
584c35d236eSmrg    	    dwords = w >> (2 - pPriv->Video_Shift);
585c35d236eSmrg    	    while(dwords >= pGlint->FIFOSize) {
586c35d236eSmrg		GLINT_WAIT(pGlint->FIFOSize);
587c35d236eSmrg        	GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | (0x15 << 4) |
588c35d236eSmrg			0x05, OutputFIFO);
589c35d236eSmrg		GLINT_MoveDWORDS(
590c35d236eSmrg			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
591c35d236eSmrg	 		(CARD32*)src, pGlint->FIFOSize - 1);
592c35d236eSmrg		dwords -= (pGlint->FIFOSize - 1);
593c35d236eSmrg		src += (pGlint->FIFOSize << 2) - 4;
594c35d236eSmrg    	    }
595c35d236eSmrg    	    if(dwords) {
596c35d236eSmrg		GLINT_WAIT(dwords + 1);
597c35d236eSmrg        	GLINT_WRITE_REG(((dwords-1)<<16)|(0x15<<4) | 0x05, OutputFIFO);
598c35d236eSmrg		GLINT_MoveDWORDS(
599c35d236eSmrg			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
600c35d236eSmrg	 		(CARD32*)src, dwords);
601c35d236eSmrg    	    }
602c35d236eSmrg    	    src = tmp_src + (w << pPriv->Video_Shift);
603c35d236eSmrg  	}
604c35d236eSmrg    }
605c35d236eSmrg}
606c35d236eSmrg
607c35d236eSmrgstatic FBAreaPtr
608c35d236eSmrgPermedia3AllocateMemory(ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height)
609c35d236eSmrg{
610c35d236eSmrg  ScreenPtr pScreen;
611c35d236eSmrg  FBAreaPtr new_area;
612c35d236eSmrg
613c35d236eSmrg  if (area) {
614c35d236eSmrg    if ((area->box.x2 - area->box.x1 >= width) &&
615c35d236eSmrg        (area->box.y2 - area->box.y1 >= height))
616c35d236eSmrg      return area;
617c35d236eSmrg
618c35d236eSmrg    if (xf86ResizeOffscreenArea(area, width, height))
619c35d236eSmrg      return area;
620c35d236eSmrg
621c35d236eSmrg    xf86FreeOffscreenArea(area);
622c35d236eSmrg  }
623c35d236eSmrg
6241fb744b4Smrg  pScreen = xf86ScrnToScreen(pScrn);
625c35d236eSmrg
626c35d236eSmrg  new_area = xf86AllocateOffscreenArea(pScreen, width, height, pScrn->bitsPerPixel / 8, NULL, NULL, NULL);
627c35d236eSmrg
628c35d236eSmrg  if (!new_area) {
629c35d236eSmrg    int max_width, max_height;
630c35d236eSmrg
631c35d236eSmrg    xf86QueryLargestOffscreenArea(pScreen, &max_width, &max_height, pScrn->bitsPerPixel / 8, 0, PRIORITY_EXTREME);
632c35d236eSmrg
633c35d236eSmrg    if (max_width < width || max_height < height)
634c35d236eSmrg      return NULL;
635c35d236eSmrg
636c35d236eSmrg    xf86PurgeUnlockedOffscreenAreas(pScreen);
637c35d236eSmrg    new_area = xf86AllocateOffscreenArea(pScreen, width, height, pScrn->bitsPerPixel / 8, NULL, NULL, NULL);
638c35d236eSmrg  }
639c35d236eSmrg
640c35d236eSmrg  return new_area;
641c35d236eSmrg}
642c35d236eSmrg
643c35d236eSmrg#define FORMAT_RGB8888	PM3VideoOverlayMode_COLORFORMAT_RGB8888
644c35d236eSmrg#define FORMAT_RGB4444	PM3VideoOverlayMode_COLORFORMAT_RGB4444
645c35d236eSmrg#define FORMAT_RGB5551	PM3VideoOverlayMode_COLORFORMAT_RGB5551
646c35d236eSmrg#define FORMAT_RGB565	PM3VideoOverlayMode_COLORFORMAT_RGB565
647c35d236eSmrg#define FORMAT_RGB332	PM3VideoOverlayMode_COLORFORMAT_RGB332
648c35d236eSmrg#define FORMAT_BGR8888	PM3VideoOverlayMode_COLORFORMAT_BGR8888
649c35d236eSmrg#define FORMAT_BGR4444	PM3VideoOverlayMode_COLORFORMAT_BGR4444
650c35d236eSmrg#define FORMAT_BGR5551	PM3VideoOverlayMode_COLORFORMAT_BGR5551
651c35d236eSmrg#define FORMAT_BGR565	PM3VideoOverlayMode_COLORFORMAT_BGR565
652c35d236eSmrg#define FORMAT_BGR332	PM3VideoOverlayMode_COLORFORMAT_BGR332
653c35d236eSmrg#define FORMAT_CI8	PM3VideoOverlayMode_COLORFORMAT_CI8
654c35d236eSmrg#define FORMAT_VUY444	PM3VideoOverlayMode_COLORFORMAT_VUY444
655c35d236eSmrg#define FORMAT_YUV444	PM3VideoOverlayMode_COLORFORMAT_YUV444
656c35d236eSmrg#define FORMAT_VUY422	PM3VideoOverlayMode_COLORFORMAT_VUY422
657c35d236eSmrg#define FORMAT_YUV422	PM3VideoOverlayMode_COLORFORMAT_YUV422
658c35d236eSmrg
659c35d236eSmrg/* Notice, have to check that we dont overflow the deltas here ... */
660c35d236eSmrgstatic void
661c35d236eSmrgcompute_scale_factor(
662c35d236eSmrg    short* src_w, short* dst_w,
663c35d236eSmrg    unsigned int* shrink_delta, unsigned int* zoom_delta)
664c35d236eSmrg{
665c35d236eSmrg    /* NOTE: If we don't return reasonable values here then the video
666c35d236eSmrg     * unit can potential shut off and won't display an image until re-enabled.
667c35d236eSmrg     * Seems as though the zoom_delta is o.k, and I've not had the problem.
668c35d236eSmrg     * The 'shrink_delta' is prone to this the most - FIXME ! */
669c35d236eSmrg
670c35d236eSmrg    if (*src_w >= *dst_w) {
671c35d236eSmrg	*src_w &= ~0x3;
672c35d236eSmrg	*dst_w &= ~0x3;
673c35d236eSmrg	*shrink_delta = (((*src_w << 16) / *dst_w) + 0x0f) & 0x0ffffff0;
674c35d236eSmrg	*zoom_delta = 1<<16;
675c35d236eSmrg	if ( ((*shrink_delta * *dst_w) >> 16) & 0x03 )
676c35d236eSmrg	    *shrink_delta += 0x10;
677c35d236eSmrg    } else {
678c35d236eSmrg	*src_w &= ~0x3;
679c35d236eSmrg	*dst_w &= ~0x3;
680c35d236eSmrg	*zoom_delta = (((*src_w << 16) / *dst_w) + 0x0f) & 0x0001fff0;
681c35d236eSmrg	*shrink_delta = 1<<16;
682c35d236eSmrg	if ( ((*zoom_delta * *dst_w) >> 16) & 0x03 )
683c35d236eSmrg	    *zoom_delta += 0x10;
684c35d236eSmrg    }
685c35d236eSmrg}
686c35d236eSmrg
687c35d236eSmrgstatic void
688c35d236eSmrgPermedia3DisplayVideo(
689c35d236eSmrg    ScrnInfoPtr pScrn,
690c35d236eSmrg    int id,
691c35d236eSmrg    int offset,
692c35d236eSmrg    short width, short height,
693c35d236eSmrg    int x1, int y1, int x2, int y2,
694c35d236eSmrg    BoxPtr dstBox,
695c35d236eSmrg    short src_w, short src_h,
696c35d236eSmrg    short drw_w, short drw_h
697c35d236eSmrg){
698c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
699c35d236eSmrg    GLINTPortPrivPtr portPriv = pGlint->adaptor->pPortPrivates[0].ptr;
700c35d236eSmrg    unsigned int shrink, zoom;
701c35d236eSmrg    unsigned int newx2;
702c35d236eSmrg
703c35d236eSmrg    /* Let's overlay only to visible parts of the screen */
704c35d236eSmrg    if (dstBox->x1 == 0) {
705c35d236eSmrg	x1 = drw_w - dstBox->x2;
706c35d236eSmrg	drw_w = dstBox->x2;
707c35d236eSmrg    }
708c35d236eSmrg    if (dstBox->x2 == pScrn->frameX1) {
709c35d236eSmrg	x2 = drw_w - (dstBox->x2 - dstBox->x1);
710c35d236eSmrg	drw_w = (dstBox->x2 - dstBox->x1);
711c35d236eSmrg    }
712c35d236eSmrg
713c35d236eSmrg    /* Avoid divide by zero in compute_scale_factor. */
714c35d236eSmrg    if (drw_w < 8)
715c35d236eSmrg	return;
716c35d236eSmrg
717c35d236eSmrg    /* Let's adjust the width of source and dest to be compliant with
718c35d236eSmrg     * the Permedia3 overlay unit requirement, and compute the X deltas. */
719c35d236eSmrg    newx2 = drw_w;
720c35d236eSmrg    compute_scale_factor(&src_w, &drw_w, &shrink, &zoom);
721c35d236eSmrg    dstBox->x2 -= (newx2 - drw_w);
722c35d236eSmrg
723c35d236eSmrg    /* We do a long wait here - for everything that needs to be written */
724c35d236eSmrg    GLINT_WAIT(39);
725c35d236eSmrg    GLINT_WRITE_REG(offset>>portPriv->Video_Shift,
726c35d236eSmrg	portPriv->buffer ? PM3VideoOverlayBase1 : PM3VideoOverlayBase0);
727c35d236eSmrg    /* Let's set the source pitch. */
728c35d236eSmrg    GLINT_WRITE_REG(PM3VideoOverlayStride_STRIDE(pScrn->displayWidth<<
729c35d236eSmrg	(pScrn->bitsPerPixel>>4) >>portPriv->Video_Shift),
730c35d236eSmrg	PM3VideoOverlayStride);
731c35d236eSmrg    /* Let's set the position and size of the visible part of the source. */
732c35d236eSmrg    GLINT_WRITE_REG(PM3VideoOverlayWidth_WIDTH(src_w),
733c35d236eSmrg	PM3VideoOverlayWidth);
734c35d236eSmrg    GLINT_WRITE_REG(PM3VideoOverlayHeight_HEIGHT(src_h),
735c35d236eSmrg	PM3VideoOverlayHeight);
736c35d236eSmrg    GLINT_WRITE_REG(
737c35d236eSmrg	PM3VideoOverlayOrigin_XORIGIN(x1) |
738c35d236eSmrg	PM3VideoOverlayOrigin_YORIGIN(y1),
739c35d236eSmrg	PM3VideoOverlayOrigin);
740c35d236eSmrg    /* Scale the source to the destinationsize */
741c35d236eSmrg    if (src_h == drw_h) {
742c35d236eSmrg	GLINT_WRITE_REG(
743c35d236eSmrg	    PM3VideoOverlayYDelta_NONE,
744c35d236eSmrg	    PM3VideoOverlayYDelta);
745c35d236eSmrg    } else {
746c35d236eSmrg	GLINT_WRITE_REG(
747c35d236eSmrg	    PM3VideoOverlayYDelta_DELTA(src_h,drw_h),
748c35d236eSmrg	    PM3VideoOverlayYDelta);
749c35d236eSmrg    }
750c35d236eSmrg    if (src_w == drw_w) {
751c35d236eSmrg    	GLINT_WRITE_REG(1<<16, PM3VideoOverlayShrinkXDelta);
752c35d236eSmrg    	GLINT_WRITE_REG(1<<16, PM3VideoOverlayZoomXDelta);
753c35d236eSmrg    } else {
754c35d236eSmrg    	GLINT_WRITE_REG(shrink, PM3VideoOverlayShrinkXDelta);
755c35d236eSmrg    	GLINT_WRITE_REG(zoom, PM3VideoOverlayZoomXDelta);
756c35d236eSmrg    }
757c35d236eSmrg    GLINT_WRITE_REG(portPriv->buffer, PM3VideoOverlayIndex);
758c35d236eSmrg
759c35d236eSmrg    /* Now set the ramdac video overlay region and mode */
760c35d236eSmrg    RAMDAC_WRITE((dstBox->x1&0xff), PM3RD_VideoOverlayXStartLow);
761c35d236eSmrg    RAMDAC_WRITE((dstBox->x1&0xf00)>>8, PM3RD_VideoOverlayXStartHigh);
762c35d236eSmrg    RAMDAC_WRITE((dstBox->x2&0xff), PM3RD_VideoOverlayXEndLow);
763c35d236eSmrg    RAMDAC_WRITE((dstBox->x2&0xf00)>>8,PM3RD_VideoOverlayXEndHigh);
764c35d236eSmrg    RAMDAC_WRITE((dstBox->y1&0xff), PM3RD_VideoOverlayYStartLow);
765c35d236eSmrg    RAMDAC_WRITE((dstBox->y1&0xf00)>>8, PM3RD_VideoOverlayYStartHigh);
766c35d236eSmrg    RAMDAC_WRITE((dstBox->y2&0xff), PM3RD_VideoOverlayYEndLow);
767c35d236eSmrg    RAMDAC_WRITE((dstBox->y2&0xf00)>>8,PM3RD_VideoOverlayYEndHigh);
768c35d236eSmrg
769c35d236eSmrg    GLINT_WRITE_REG(portPriv->Video_Shift << 5 |
770c35d236eSmrg	portPriv->Format |
771c35d236eSmrg	portPriv->Filter |
772c35d236eSmrg	PM3VideoOverlayMode_BUFFERSYNC_MANUAL |
773c35d236eSmrg	PM3VideoOverlayMode_FLIP_VIDEO |
774c35d236eSmrg	PM3VideoOverlayMode_ENABLE,
775c35d236eSmrg	PM3VideoOverlayMode);
776c35d236eSmrg
777c35d236eSmrg    if (!portPriv->ramdacOn) {
778c35d236eSmrg    	RAMDAC_WRITE(PM3RD_VideoOverlayControl_ENABLE |
779c35d236eSmrg		PM3RD_VideoOverlayControl_KEY_COLOR |
780c35d236eSmrg		PM3RD_VideoOverlayControl_MODE_MAINKEY |
781c35d236eSmrg		PM3RD_VideoOverlayControl_DIRECTCOLOR_ENABLED,
782c35d236eSmrg		PM3RD_VideoOverlayControl);
783c35d236eSmrg	portPriv->ramdacOn = TRUE;
784c35d236eSmrg    }
785c35d236eSmrg    GLINT_WRITE_REG(PM3VideoOverlayUpdate_ENABLE,
786c35d236eSmrg	PM3VideoOverlayUpdate);
787c35d236eSmrg}
788c35d236eSmrg
789c35d236eSmrgstatic int
790c35d236eSmrgPermedia3PutImage(
791c35d236eSmrg  ScrnInfoPtr pScrn,
792c35d236eSmrg  short src_x, short src_y,
793c35d236eSmrg  short drw_x, short drw_y,
794c35d236eSmrg  short src_w, short src_h,
795c35d236eSmrg  short drw_w, short drw_h,
796c35d236eSmrg  int id, unsigned char* buf,
797c35d236eSmrg  short width, short height,
798c35d236eSmrg  Bool sync,
799c35d236eSmrg  RegionPtr clipBoxes, pointer data,
800c35d236eSmrg  DrawablePtr pDraw
801c35d236eSmrg){
802c35d236eSmrg#if 0
803c35d236eSmrg   GLINTPtr pGlint = GLINTPTR(pScrn);
804c35d236eSmrg#endif
805c35d236eSmrg   GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data;
806c35d236eSmrg   INT32 x1, x2, y1, y2;
807c35d236eSmrg   int pitch;
808c35d236eSmrg   int i;
809c35d236eSmrg   int w_bpp, bpp;
810c35d236eSmrg   Bool copy_flat = TRUE;
811c35d236eSmrg   BoxRec dstBox;
812c35d236eSmrg
813c35d236eSmrg   /* Let's find the image format and Video_Shift values */
814c35d236eSmrg   switch (id) {
815c35d236eSmrg	case LE4CC('Y','V','1','2'):
816c35d236eSmrg	    pPriv->Format = FORMAT_YUV422;
817c35d236eSmrg	    pPriv->Video_Shift = 1;
818c35d236eSmrg	    copy_flat = FALSE;
819c35d236eSmrg	    break;
820c35d236eSmrg	case LE4CC('Y','U','Y','2'):
821c35d236eSmrg	    pPriv->Format = FORMAT_YUV422;
822c35d236eSmrg	    pPriv->Video_Shift = 1;
823c35d236eSmrg	    break;
824c35d236eSmrg	case LE4CC('U','Y','V','Y'):
825c35d236eSmrg	    pPriv->Format = FORMAT_VUY422;
826c35d236eSmrg	    pPriv->Video_Shift = 1;
827c35d236eSmrg	    break;
828c35d236eSmrg	case LE4CC('Y','U','V','A'):
829c35d236eSmrg	    pPriv->Format = FORMAT_YUV444;
830c35d236eSmrg	    pPriv->Video_Shift = 2;
831c35d236eSmrg	    break;
832c35d236eSmrg	case LE4CC('V','U','Y','A'):
833c35d236eSmrg	    pPriv->Format = FORMAT_VUY444;
834c35d236eSmrg	    pPriv->Video_Shift = 2;
835c35d236eSmrg	    break;
836c35d236eSmrg	case 0x41: /* RGBA 8:8:8:8 */
837c35d236eSmrg	    pPriv->Format = FORMAT_RGB8888;
838c35d236eSmrg	    pPriv->Video_Shift = 2;
839c35d236eSmrg	    break;
840c35d236eSmrg	case 0x42: /* RGB 5:6:5 */
841c35d236eSmrg	    pPriv->Format = FORMAT_RGB565;
842c35d236eSmrg	    pPriv->Video_Shift = 1;
843c35d236eSmrg	    break;
844c35d236eSmrg	case 0x43: /* RGB 1:5:5:5 */
845c35d236eSmrg	    pPriv->Format = FORMAT_RGB5551;
846c35d236eSmrg	    pPriv->Video_Shift = 1;
847c35d236eSmrg	    break;
848c35d236eSmrg	case 0x44: /* RGB 4:4:4:4 */
849c35d236eSmrg	    pPriv->Format = FORMAT_RGB4444;
850c35d236eSmrg	    pPriv->Video_Shift = 1;
851c35d236eSmrg	    break;
852c35d236eSmrg	case 0x46: /* RGB 2:3:3 */
853c35d236eSmrg	    pPriv->Format = FORMAT_RGB332;
854c35d236eSmrg	    pPriv->Video_Shift = 0;
855c35d236eSmrg	    break;
856c35d236eSmrg	case 0x47: /* BGRA 8:8:8:8 */
857c35d236eSmrg	    pPriv->Format = FORMAT_BGR8888;
858c35d236eSmrg	    pPriv->Video_Shift = 2;
859c35d236eSmrg	    break;
860c35d236eSmrg	case 0x48: /* BGR 5:6:5 */
861c35d236eSmrg	    pPriv->Format = FORMAT_BGR565;
862c35d236eSmrg	    pPriv->Video_Shift = 1;
863c35d236eSmrg	    break;
864c35d236eSmrg	case 0x49: /* BGR 1:5:5:5 */
865c35d236eSmrg	    pPriv->Format = FORMAT_BGR5551;
866c35d236eSmrg	    pPriv->Video_Shift = 1;
867c35d236eSmrg	    break;
868c35d236eSmrg	case 0x4A: /* BGR 4:4:4:4 */
869c35d236eSmrg	    pPriv->Format = FORMAT_BGR4444;
870c35d236eSmrg	    pPriv->Video_Shift = 1;
871c35d236eSmrg	    break;
872c35d236eSmrg	case 0x4C: /* BGR 2:3:3 */
873c35d236eSmrg	    pPriv->Format = FORMAT_BGR332;
874c35d236eSmrg	    pPriv->Video_Shift = 0;
875c35d236eSmrg	    break;
876c35d236eSmrg	default:
877c35d236eSmrg	    return XvBadAlloc;
878c35d236eSmrg    }
879c35d236eSmrg
880c35d236eSmrg    /* Clip */
881c35d236eSmrg    x1 = src_x;
882c35d236eSmrg    x2 = src_x + src_w;
883c35d236eSmrg    y1 = src_y;
884c35d236eSmrg    y2 = src_y + src_h;
885c35d236eSmrg
886c35d236eSmrg    dstBox.x1 = drw_x;
887c35d236eSmrg    dstBox.x2 = drw_x + drw_w;
888c35d236eSmrg    dstBox.y1 = drw_y;
889c35d236eSmrg    dstBox.y2 = drw_y + drw_h;
890c35d236eSmrg
891c35d236eSmrg    if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
892c35d236eSmrg                              width, height))
893c35d236eSmrg    	return Success;
894c35d236eSmrg
895c35d236eSmrg    dstBox.x1 -= pScrn->frameX0;
896c35d236eSmrg    dstBox.x2 -= pScrn->frameX0;
897c35d236eSmrg    dstBox.y1 -= pScrn->frameY0;
898c35d236eSmrg    dstBox.y2 -= pScrn->frameY0;
899c35d236eSmrg
900c35d236eSmrg    bpp = pScrn->bitsPerPixel >> 3;
901c35d236eSmrg    pitch = bpp * pScrn->displayWidth;
902c35d236eSmrg
903c35d236eSmrg    w_bpp = (width << pPriv->Video_Shift) >> (pScrn->bitsPerPixel >> 4);
904c35d236eSmrg
905c35d236eSmrg    for (i = 0; i < (pPriv->doubleBuffer ? 2 : 1); i++) {
906c35d236eSmrg      if (!(pPriv->area[i] =
907c35d236eSmrg		Permedia3AllocateMemory(pScrn,pPriv->area[i],w_bpp,src_h)))
908c35d236eSmrg        return BadAlloc;
909c35d236eSmrg
910c35d236eSmrg      pPriv->offset[i] = (pPriv->area[i]->box.x1 * bpp) +
911c35d236eSmrg					(pPriv->area[i]->box.y1 * pitch);
912c35d236eSmrg    }
913c35d236eSmrg
914c35d236eSmrg    HWCopySetup(pScrn, pPriv->area[pPriv->buffer]->box.x1,
915c35d236eSmrg		       pPriv->area[pPriv->buffer]->box.y1, w_bpp, height);
916c35d236eSmrg
917c35d236eSmrg    if (copy_flat)
918c35d236eSmrg	HWCopyFlat(pScrn, buf, width, height);
919c35d236eSmrg    else
920c35d236eSmrg	HWCopyYV12(pScrn, buf, width, height);
921c35d236eSmrg
922c35d236eSmrg    /* paint the color key */
923c35d236eSmrg    if(pPriv->autopaintColorKey &&
924c35d236eSmrg       !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
925c35d236eSmrg    	/* update cliplist */
926c35d236eSmrg        REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
927c35d236eSmrg#if 0
928c35d236eSmrg	GLINT_WAIT(1);
929c35d236eSmrg    	GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE,
930c35d236eSmrg						PM3VideoOverlayMode);
931c35d236eSmrg	pPriv->ramdacOn = FALSE;
932c35d236eSmrg#endif
933c35d236eSmrg        xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
934c35d236eSmrg    }
935c35d236eSmrg
936c35d236eSmrg    Permedia3Sync(pScrn);
937c35d236eSmrg
938c35d236eSmrg    Permedia3DisplayVideo(pScrn, id, pPriv->offset[pPriv->buffer], width,height,
939c35d236eSmrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
940c35d236eSmrg
941c35d236eSmrg    /* Switch buffer on next run - double buffer */
942c35d236eSmrg    if (pPriv->doubleBuffer) {
943c35d236eSmrg    	if (!pPriv->buffer)
944c35d236eSmrg	    pPriv->buffer = 1;
945c35d236eSmrg    	else
946c35d236eSmrg	    pPriv->buffer = 0;
947c35d236eSmrg    }
948c35d236eSmrg
949c35d236eSmrg    pPriv->videoStatus = CLIENT_VIDEO_ON;
950c35d236eSmrg
951c35d236eSmrg    return Success;
952c35d236eSmrg}
953c35d236eSmrg
954c35d236eSmrgstatic int
955c35d236eSmrgPermedia3QueryImageAttributes(
956c35d236eSmrg  ScrnInfoPtr pScrn,
957c35d236eSmrg  int id,
958c35d236eSmrg  unsigned short *w, unsigned short *h,
959c35d236eSmrg  int *pitches, int *offsets
960c35d236eSmrg){
961c35d236eSmrg    int size, tmp;
962c35d236eSmrg
963c35d236eSmrg    if(*w > 2047) *w = 2047;
964c35d236eSmrg    if(*h > 2047) *h = 2047;
965c35d236eSmrg
966c35d236eSmrg    *w = (*w + 1) & ~1;
967c35d236eSmrg    if(offsets) offsets[0] = 0;
968c35d236eSmrg
969c35d236eSmrg    switch(id) {
970c35d236eSmrg    case FOURCC_YV12:		/* YV12 */
971c35d236eSmrg	*h = (*h + 1) & ~1;
972c35d236eSmrg	size = (*w + 3) & ~3;
973c35d236eSmrg	if(pitches) pitches[0] = size;
974c35d236eSmrg	size *= *h;
975c35d236eSmrg	if(offsets) offsets[1] = size;
976c35d236eSmrg	tmp = ((*w >> 1) + 3) & ~3;
977c35d236eSmrg	if(pitches) pitches[1] = pitches[2] = tmp;
978c35d236eSmrg	tmp *= (*h >> 1);
979c35d236eSmrg	size += tmp;
980c35d236eSmrg	if(offsets) offsets[2] = size;
981c35d236eSmrg	size += tmp;
982c35d236eSmrg	break;
983c35d236eSmrg    default:			/* RGB15, RGB16, YUY2 */
984c35d236eSmrg	size = *w << 1;
985c35d236eSmrg	if(pitches) pitches[0] = size;
986c35d236eSmrg	size *= *h;
987c35d236eSmrg	break;
988c35d236eSmrg    }
989c35d236eSmrg
990c35d236eSmrg    return size;
991c35d236eSmrg}
992c35d236eSmrg
993c35d236eSmrg/****************** Offscreen stuff ***************/
994c35d236eSmrg
995c35d236eSmrgtypedef struct {
996c35d236eSmrg  FBAreaPtr area;
997c35d236eSmrg  Bool isOn;
998c35d236eSmrg  int Video_Shift;
999c35d236eSmrg  int Format;
1000c35d236eSmrg  Bool ramdacOn;
1001c35d236eSmrg} OffscreenPrivRec, * OffscreenPrivPtr;
1002c35d236eSmrg
1003c35d236eSmrgstatic int
1004c35d236eSmrgPermedia3AllocateSurface(
1005c35d236eSmrg    ScrnInfoPtr pScrn,
1006c35d236eSmrg    int id,
1007c35d236eSmrg    unsigned short w,
1008c35d236eSmrg    unsigned short h,
1009c35d236eSmrg    XF86SurfacePtr surface
1010c35d236eSmrg){
1011c35d236eSmrg    FBAreaPtr area;
1012c35d236eSmrg    int fbpitch, bpp;
1013c35d236eSmrg    OffscreenPrivPtr pPriv;
1014c35d236eSmrg
1015c35d236eSmrg    if((w > 2047) || (h > 2047))
1016c35d236eSmrg	return BadAlloc;
1017c35d236eSmrg
1018c35d236eSmrg    w = (w + 1) & ~1;
1019c35d236eSmrg    bpp = pScrn->bitsPerPixel >> 3;
1020c35d236eSmrg    fbpitch = bpp * pScrn->displayWidth;
1021c35d236eSmrg
1022c35d236eSmrg    if(!(area = Permedia3AllocateMemory(pScrn, NULL, w, h)))
1023c35d236eSmrg	return BadAlloc;
1024c35d236eSmrg
1025c35d236eSmrg    surface->width = w;
1026c35d236eSmrg    surface->height = h;
1027c35d236eSmrg
10281fb744b4Smrg    if(!(surface->offsets = malloc(sizeof(int)))) {
1029c35d236eSmrg	xf86FreeOffscreenArea(area);
1030c35d236eSmrg	return BadAlloc;
1031c35d236eSmrg    }
10321fb744b4Smrg    if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
10331fb744b4Smrg	free(surface->offsets);
1034c35d236eSmrg	xf86FreeOffscreenArea(area);
1035c35d236eSmrg	return BadAlloc;
1036c35d236eSmrg    }
1037c35d236eSmrg
1038c35d236eSmrg    pPriv->area = area;
1039c35d236eSmrg    pPriv->isOn = FALSE;
1040c35d236eSmrg
1041c35d236eSmrg    surface->pScrn = pScrn;
1042c35d236eSmrg    surface->id = id;
1043c35d236eSmrg    surface->offsets[0] = (area->box.x1 * bpp) + (area->box.y1 * fbpitch);
1044c35d236eSmrg    surface->devPrivate.ptr = (pointer)pPriv;
1045c35d236eSmrg
1046c35d236eSmrg    return Success;
1047c35d236eSmrg}
1048c35d236eSmrg
1049c35d236eSmrgstatic int
1050c35d236eSmrgPermedia3StopSurface(
1051c35d236eSmrg    XF86SurfacePtr surface
1052c35d236eSmrg){
1053c35d236eSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1054c35d236eSmrg
1055c35d236eSmrg    if(pPriv->isOn) {
1056c35d236eSmrg	GLINTPtr pGlint = GLINTPTR(surface->pScrn);
1057c35d236eSmrg    	pPriv->ramdacOn = FALSE;
1058c35d236eSmrg	GLINT_WAIT(4);
1059c35d236eSmrg        RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE,
1060c35d236eSmrg		PM3RD_VideoOverlayControl);
1061c35d236eSmrg	GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE,
1062c35d236eSmrg		PM3VideoOverlayMode);
1063c35d236eSmrg	pPriv->isOn = FALSE;
1064c35d236eSmrg    }
1065c35d236eSmrg
1066c35d236eSmrg    return Success;
1067c35d236eSmrg}
1068c35d236eSmrg
1069c35d236eSmrgstatic int
1070c35d236eSmrgPermedia3FreeSurface(
1071c35d236eSmrg    XF86SurfacePtr surface
1072c35d236eSmrg){
1073c35d236eSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1074c35d236eSmrg
1075c35d236eSmrg    if(pPriv->isOn)
1076c35d236eSmrg	Permedia3StopSurface(surface);
1077c35d236eSmrg    xf86FreeOffscreenArea(pPriv->area);
10781fb744b4Smrg    free(surface->pitches);
10791fb744b4Smrg    free(surface->offsets);
10801fb744b4Smrg    free(surface->devPrivate.ptr);
1081c35d236eSmrg
1082c35d236eSmrg    return Success;
1083c35d236eSmrg}
1084c35d236eSmrg
1085c35d236eSmrgstatic int
1086c35d236eSmrgPermedia3GetSurfaceAttribute(
1087c35d236eSmrg    ScrnInfoPtr pScrn,
1088c35d236eSmrg    Atom attribute,
1089c35d236eSmrg    INT32 *value
1090c35d236eSmrg){
1091c35d236eSmrg    return Permedia3GetPortAttribute(pScrn, attribute, value,
1092c35d236eSmrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
1093c35d236eSmrg}
1094c35d236eSmrg
1095c35d236eSmrgstatic int
1096c35d236eSmrgPermedia3SetSurfaceAttribute(
1097c35d236eSmrg    ScrnInfoPtr pScrn,
1098c35d236eSmrg    Atom attribute,
1099c35d236eSmrg    INT32 value
1100c35d236eSmrg){
1101c35d236eSmrg    return Permedia3SetPortAttribute(pScrn, attribute, value,
1102c35d236eSmrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
1103c35d236eSmrg}
1104c35d236eSmrg
1105c35d236eSmrgstatic int
1106c35d236eSmrgPermedia3DisplaySurface(
1107c35d236eSmrg    XF86SurfacePtr surface,
1108c35d236eSmrg    short src_x, short src_y,
1109c35d236eSmrg    short drw_x, short drw_y,
1110c35d236eSmrg    short src_w, short src_h,
1111c35d236eSmrg    short drw_w, short drw_h,
1112c35d236eSmrg    RegionPtr clipBoxes
1113c35d236eSmrg){
1114c35d236eSmrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1115c35d236eSmrg    ScrnInfoPtr pScrn = surface->pScrn;
1116c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
1117c35d236eSmrg    GLINTPortPrivPtr portPriv = pGlint->adaptor->pPortPrivates[0].ptr;
1118c35d236eSmrg    INT32 x1, y1, x2, y2;
1119c35d236eSmrg    BoxRec dstBox;
1120c35d236eSmrg
1121c35d236eSmrg    x1 = src_x;
1122c35d236eSmrg    x2 = src_x + src_w;
1123c35d236eSmrg    y1 = src_y;
1124c35d236eSmrg    y2 = src_y + src_h;
1125c35d236eSmrg
1126c35d236eSmrg    dstBox.x1 = drw_x;
1127c35d236eSmrg    dstBox.x2 = drw_x + drw_w;
1128c35d236eSmrg    dstBox.y1 = drw_y;
1129c35d236eSmrg    dstBox.y2 = drw_y + drw_h;
1130c35d236eSmrg
1131c35d236eSmrg    if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
1132c35d236eSmrg		    surface->width, surface->height))
1133c35d236eSmrg    {
1134c35d236eSmrg        return Success;
1135c35d236eSmrg    }
1136c35d236eSmrg
1137c35d236eSmrg    dstBox.x1 -= pScrn->frameX0;
1138c35d236eSmrg    dstBox.x2 -= pScrn->frameX0;
1139c35d236eSmrg    dstBox.y1 -= pScrn->frameY0;
1140c35d236eSmrg    dstBox.y2 -= pScrn->frameY0;
1141c35d236eSmrg
1142c35d236eSmrg   /* Let's find the image format and Video_Shift values */
1143c35d236eSmrg   switch (surface->id) {
1144c35d236eSmrg	case LE4CC('Y','V','1','2'):
1145c35d236eSmrg	    pPriv->Format = FORMAT_YUV422;
1146c35d236eSmrg	    pPriv->Video_Shift = 1;
1147c35d236eSmrg	    break;
1148c35d236eSmrg	case LE4CC('Y','U','Y','2'):
1149c35d236eSmrg	    pPriv->Format = FORMAT_YUV422;
1150c35d236eSmrg	    pPriv->Video_Shift = 1;
1151c35d236eSmrg	    break;
1152c35d236eSmrg	case LE4CC('U','Y','V','Y'):
1153c35d236eSmrg	    pPriv->Format = FORMAT_VUY422;
1154c35d236eSmrg	    pPriv->Video_Shift = 1;
1155c35d236eSmrg	    break;
1156c35d236eSmrg	case LE4CC('Y','U','V','A'):
1157c35d236eSmrg	    pPriv->Format = FORMAT_YUV444;
1158c35d236eSmrg	    pPriv->Video_Shift = 2;
1159c35d236eSmrg	    break;
1160c35d236eSmrg	case LE4CC('V','U','Y','A'):
1161c35d236eSmrg	    pPriv->Format = FORMAT_VUY444;
1162c35d236eSmrg	    pPriv->Video_Shift = 2;
1163c35d236eSmrg	    break;
1164c35d236eSmrg	case 0x41: /* RGBA 8:8:8:8 */
1165c35d236eSmrg	    pPriv->Format = FORMAT_RGB8888;
1166c35d236eSmrg	    pPriv->Video_Shift = 2;
1167c35d236eSmrg	    break;
1168c35d236eSmrg	case 0x42: /* RGB 5:6:5 */
1169c35d236eSmrg	    pPriv->Format = FORMAT_RGB565;
1170c35d236eSmrg	    pPriv->Video_Shift = 1;
1171c35d236eSmrg	    break;
1172c35d236eSmrg	case 0x43: /* RGB 1:5:5:5 */
1173c35d236eSmrg	    pPriv->Format = FORMAT_RGB5551;
1174c35d236eSmrg	    pPriv->Video_Shift = 1;
1175c35d236eSmrg	    break;
1176c35d236eSmrg	case 0x44: /* RGB 4:4:4:4 */
1177c35d236eSmrg	    pPriv->Format = FORMAT_RGB4444;
1178c35d236eSmrg	    pPriv->Video_Shift = 1;
1179c35d236eSmrg	    break;
1180c35d236eSmrg	case 0x46: /* RGB 2:3:3 */
1181c35d236eSmrg	    pPriv->Format = FORMAT_RGB332;
1182c35d236eSmrg	    pPriv->Video_Shift = 0;
1183c35d236eSmrg	    break;
1184c35d236eSmrg	case 0x47: /* BGRA 8:8:8:8 */
1185c35d236eSmrg	    pPriv->Format = FORMAT_BGR8888;
1186c35d236eSmrg	    pPriv->Video_Shift = 2;
1187c35d236eSmrg	    break;
1188c35d236eSmrg	case 0x48: /* BGR 5:6:5 */
1189c35d236eSmrg	    pPriv->Format = FORMAT_BGR565;
1190c35d236eSmrg	    pPriv->Video_Shift = 1;
1191c35d236eSmrg	    break;
1192c35d236eSmrg	case 0x49: /* BGR 1:5:5:5 */
1193c35d236eSmrg	    pPriv->Format = FORMAT_BGR5551;
1194c35d236eSmrg	    pPriv->Video_Shift = 1;
1195c35d236eSmrg	    break;
1196c35d236eSmrg	case 0x4A: /* BGR 4:4:4:4 */
1197c35d236eSmrg	    pPriv->Format = FORMAT_BGR4444;
1198c35d236eSmrg	    pPriv->Video_Shift = 1;
1199c35d236eSmrg	    break;
1200c35d236eSmrg	case 0x4C: /* BGR 2:3:3 */
1201c35d236eSmrg	    pPriv->Format = FORMAT_BGR332;
1202c35d236eSmrg	    pPriv->Video_Shift = 0;
1203c35d236eSmrg	    break;
1204c35d236eSmrg	default:
1205c35d236eSmrg	    return XvBadAlloc;
1206c35d236eSmrg    }
1207c35d236eSmrg
1208c35d236eSmrg    Permedia3DisplayVideo(pScrn, surface->id, surface->offsets[0],
1209c35d236eSmrg	     surface->width, surface->height,
1210c35d236eSmrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
1211c35d236eSmrg
1212c35d236eSmrg    xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
1213c35d236eSmrg
1214c35d236eSmrg    pPriv->isOn = TRUE;
1215c35d236eSmrg    /* we've prempted the XvImage stream so set its free timer */
1216c35d236eSmrg    if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
1217c35d236eSmrg	REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
1218c35d236eSmrg	UpdateCurrentTime();
1219c35d236eSmrg	portPriv->videoStatus = FREE_TIMER;
1220c35d236eSmrg	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
1221c35d236eSmrg	pGlint->VideoTimerCallback = Permedia3VideoTimerCallback;
1222c35d236eSmrg    }
1223c35d236eSmrg
1224c35d236eSmrg    return Success;
1225c35d236eSmrg}
1226c35d236eSmrg
1227c35d236eSmrgstatic void
1228c35d236eSmrgPermedia3InitOffscreenImages(ScreenPtr pScreen)
1229c35d236eSmrg{
1230c35d236eSmrg    XF86OffscreenImagePtr offscreenImages;
1231c35d236eSmrg
1232c35d236eSmrg    /* need to free this someplace */
12331fb744b4Smrg    if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec))))
1234c35d236eSmrg	return;
1235c35d236eSmrg
1236c35d236eSmrg    offscreenImages[0].image = &Images[0];
1237c35d236eSmrg    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
1238c35d236eSmrg			       VIDEO_CLIP_TO_VIEWPORT;
1239c35d236eSmrg    offscreenImages[0].alloc_surface = Permedia3AllocateSurface;
1240c35d236eSmrg    offscreenImages[0].free_surface = Permedia3FreeSurface;
1241c35d236eSmrg    offscreenImages[0].display = Permedia3DisplaySurface;
1242c35d236eSmrg    offscreenImages[0].stop = Permedia3StopSurface;
1243c35d236eSmrg    offscreenImages[0].setAttribute = Permedia3SetSurfaceAttribute;
1244c35d236eSmrg    offscreenImages[0].getAttribute = Permedia3GetSurfaceAttribute;
1245c35d236eSmrg    offscreenImages[0].max_width = 2047;
1246c35d236eSmrg    offscreenImages[0].max_height = 2047;
1247c35d236eSmrg    offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
1248c35d236eSmrg    offscreenImages[0].attributes = Attributes;
1249c35d236eSmrg
1250c35d236eSmrg    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
1251c35d236eSmrg}
1252c35d236eSmrg
1253c35d236eSmrgstatic void
1254c35d236eSmrgPermedia3VideoTimerCallback(ScrnInfoPtr pScrn, Time time)
1255c35d236eSmrg{
1256c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
1257c35d236eSmrg    GLINTPortPrivPtr pPriv = pGlint->adaptor->pPortPrivates[0].ptr;
1258c35d236eSmrg    int i;
1259c35d236eSmrg
1260c35d236eSmrg    if(pPriv->videoStatus & TIMER_MASK) {
1261c35d236eSmrg	if(pPriv->videoStatus & OFF_TIMER) {
1262c35d236eSmrg	    if(pPriv->offTime < time) {
1263c35d236eSmrg		pPriv->ramdacOn = FALSE;
1264c35d236eSmrg		GLINT_WAIT(4);
1265c35d236eSmrg        	RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE,
1266c35d236eSmrg					PM3RD_VideoOverlayControl);
1267c35d236eSmrg		GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE,
1268c35d236eSmrg					PM3VideoOverlayMode);
1269c35d236eSmrg		pPriv->videoStatus = FREE_TIMER;
1270c35d236eSmrg		pPriv->freeTime = time + FREE_DELAY;
1271c35d236eSmrg	    }
1272c35d236eSmrg	} else {  /* FREE_TIMER */
1273c35d236eSmrg	    if(pPriv->freeTime < time) {
1274c35d236eSmrg		for (i = 0; i < (pPriv->doubleBuffer ? 2 : 1); i++) {
1275c35d236eSmrg		   if(pPriv->area[i]) {
1276c35d236eSmrg		      xf86FreeOffscreenArea(pPriv->area[i]);
1277c35d236eSmrg		      pPriv->area[i] = NULL;
1278c35d236eSmrg		   }
1279c35d236eSmrg		}
1280c35d236eSmrg		pPriv->videoStatus = 0;
1281c35d236eSmrg	        pGlint->VideoTimerCallback = NULL;
1282c35d236eSmrg	    }
1283c35d236eSmrg        }
1284c35d236eSmrg    } else  /* shouldn't get here */
1285c35d236eSmrg	pGlint->VideoTimerCallback = NULL;
1286c35d236eSmrg}
1287