ct_video.c revision c06b6b69
1c06b6b69Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_video.c,v 1.16tsi Exp $ */
2c06b6b69Smrg
3c06b6b69Smrg#ifdef HAVE_CONFIG_H
4c06b6b69Smrg#include "config.h"
5c06b6b69Smrg#endif
6c06b6b69Smrg
7c06b6b69Smrg#include "xf86.h"
8c06b6b69Smrg#include "xf86_OSproc.h"
9c06b6b69Smrg#include "xf86Resources.h"
10c06b6b69Smrg#include "compiler.h"
11c06b6b69Smrg#include "xf86PciInfo.h"
12c06b6b69Smrg#include "xf86Pci.h"
13c06b6b69Smrg#include "xf86fbman.h"
14c06b6b69Smrg#include "regionstr.h"
15c06b6b69Smrg
16c06b6b69Smrg#include "ct_driver.h"
17c06b6b69Smrg#include <X11/extensions/Xv.h>
18c06b6b69Smrg#include "xaa.h"
19c06b6b69Smrg#include "xaalocal.h"
20c06b6b69Smrg#include "dixstruct.h"
21c06b6b69Smrg#include "fourcc.h"
22c06b6b69Smrg
23c06b6b69Smrg#define OFF_DELAY 	200  /* milliseconds */
24c06b6b69Smrg#define FREE_DELAY 	60000
25c06b6b69Smrg
26c06b6b69Smrg#define OFF_TIMER 	0x01
27c06b6b69Smrg#define FREE_TIMER	0x02
28c06b6b69Smrg#define CLIENT_VIDEO_ON	0x04
29c06b6b69Smrg
30c06b6b69Smrg#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
31c06b6b69Smrg
32c06b6b69Smrgstatic XF86VideoAdaptorPtr CHIPSSetupImageVideo(ScreenPtr);
33c06b6b69Smrgstatic void CHIPSInitOffscreenImages(ScreenPtr);
34c06b6b69Smrgstatic void CHIPSStopVideo(ScrnInfoPtr, pointer, Bool);
35c06b6b69Smrgstatic int CHIPSSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
36c06b6b69Smrgstatic int CHIPSGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
37c06b6b69Smrgstatic void CHIPSQueryBestSize(ScrnInfoPtr, Bool,
38c06b6b69Smrg	short, short, short, short, unsigned int *, unsigned int *, pointer);
39c06b6b69Smrgstatic int CHIPSPutImage( ScrnInfoPtr,
40c06b6b69Smrg	short, short, short, short, short, short, short, short,
41c06b6b69Smrg	int, unsigned char*, short, short, Bool, RegionPtr, pointer,
42c06b6b69Smrg	DrawablePtr);
43c06b6b69Smrgstatic int CHIPSQueryImageAttributes(ScrnInfoPtr,
44c06b6b69Smrg	int, unsigned short *, unsigned short *,  int *, int *);
45c06b6b69Smrgstatic void CHIPSVideoTimerCallback(ScrnInfoPtr pScrn, Time time);
46c06b6b69Smrg
47c06b6b69Smrg
48c06b6b69Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
49c06b6b69Smrg
50c06b6b69Smrgstatic Atom xvColorKey;
51c06b6b69Smrg
52c06b6b69Smrgvoid
53c06b6b69SmrgCHIPSInitVideo(ScreenPtr pScreen)
54c06b6b69Smrg{
55c06b6b69Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
56c06b6b69Smrg    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
57c06b6b69Smrg    XF86VideoAdaptorPtr newAdaptor = NULL;
58c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
59c06b6b69Smrg    int num_adaptors;
60c06b6b69Smrg
61c06b6b69Smrg    if (!(cPtr->Flags & ChipsOverlay8plus16) &&
62c06b6b69Smrg       (cPtr->Flags & ChipsVideoSupport)) {
63c06b6b69Smrg	newAdaptor = CHIPSSetupImageVideo(pScreen);
64c06b6b69Smrg	CHIPSInitOffscreenImages(pScreen);
65c06b6b69Smrg    }
66c06b6b69Smrg
67c06b6b69Smrg    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
68c06b6b69Smrg
69c06b6b69Smrg    if(newAdaptor) {
70c06b6b69Smrg	if(!num_adaptors) {
71c06b6b69Smrg	    num_adaptors = 1;
72c06b6b69Smrg	    adaptors = &newAdaptor;
73c06b6b69Smrg	} else {
74c06b6b69Smrg	    newAdaptors =  /* need to free this someplace */
75c06b6b69Smrg		xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
76c06b6b69Smrg	    if(newAdaptors) {
77c06b6b69Smrg		memcpy(newAdaptors, adaptors, num_adaptors *
78c06b6b69Smrg					sizeof(XF86VideoAdaptorPtr));
79c06b6b69Smrg		newAdaptors[num_adaptors] = newAdaptor;
80c06b6b69Smrg		adaptors = newAdaptors;
81c06b6b69Smrg		num_adaptors++;
82c06b6b69Smrg	    }
83c06b6b69Smrg	}
84c06b6b69Smrg    }
85c06b6b69Smrg
86c06b6b69Smrg    if(num_adaptors)
87c06b6b69Smrg        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
88c06b6b69Smrg
89c06b6b69Smrg    if(newAdaptors)
90c06b6b69Smrg	xfree(newAdaptors);
91c06b6b69Smrg}
92c06b6b69Smrg
93c06b6b69Smrg/* client libraries expect an encoding */
94c06b6b69Smrgstatic
95c06b6b69SmrgXF86VideoEncodingRec DummyEncoding[1] =
96c06b6b69Smrg{
97c06b6b69Smrg {
98c06b6b69Smrg   0,
99c06b6b69Smrg   "XV_IMAGE",
100c06b6b69Smrg   1024, 1024,
101c06b6b69Smrg   {1, 1}
102c06b6b69Smrg }
103c06b6b69Smrg};
104c06b6b69Smrg
105c06b6b69Smrg#define NUM_FORMATS 4
106c06b6b69Smrg
107c06b6b69Smrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] =
108c06b6b69Smrg{
109c06b6b69Smrg  {8, PseudoColor},  {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
110c06b6b69Smrg};
111c06b6b69Smrg
112c06b6b69Smrg#define NUM_ATTRIBUTES 1
113c06b6b69Smrg
114c06b6b69Smrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
115c06b6b69Smrg{
116c06b6b69Smrg   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}
117c06b6b69Smrg};
118c06b6b69Smrg
119c06b6b69Smrg#define NUM_IMAGES 4
120c06b6b69Smrg
121c06b6b69Smrgstatic XF86ImageRec Images[NUM_IMAGES] =
122c06b6b69Smrg{
123c06b6b69Smrg   {
124c06b6b69Smrg	0x35315652,
125c06b6b69Smrg        XvRGB,
126c06b6b69Smrg	LSBFirst,
127c06b6b69Smrg	{'R','V','1','5',
128c06b6b69Smrg	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
129c06b6b69Smrg	16,
130c06b6b69Smrg	XvPacked,
131c06b6b69Smrg	1,
132c06b6b69Smrg	15, 0x7C00, 0x03E0, 0x001F,
133c06b6b69Smrg	0, 0, 0,
134c06b6b69Smrg	0, 0, 0,
135c06b6b69Smrg	0, 0, 0,
136c06b6b69Smrg	{'R','V','B',0,
137c06b6b69Smrg	  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
138c06b6b69Smrg	XvTopToBottom
139c06b6b69Smrg   },
140c06b6b69Smrg   {
141c06b6b69Smrg	0x36315652,
142c06b6b69Smrg        XvRGB,
143c06b6b69Smrg	LSBFirst,
144c06b6b69Smrg	{'R','V','1','6',
145c06b6b69Smrg	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
146c06b6b69Smrg	16,
147c06b6b69Smrg	XvPacked,
148c06b6b69Smrg	1,
149c06b6b69Smrg	16, 0xF800, 0x07E0, 0x001F,
150c06b6b69Smrg	0, 0, 0,
151c06b6b69Smrg	0, 0, 0,
152c06b6b69Smrg	0, 0, 0,
153c06b6b69Smrg	{'R','V','B',0,
154c06b6b69Smrg	  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
155c06b6b69Smrg	XvTopToBottom
156c06b6b69Smrg   },
157c06b6b69Smrg   XVIMAGE_YV12,
158c06b6b69Smrg   XVIMAGE_YUY2
159c06b6b69Smrg};
160c06b6b69Smrg
161c06b6b69Smrgtypedef struct {
162c06b6b69Smrg   FBLinearPtr	linear;
163c06b6b69Smrg   RegionRec	clip;
164c06b6b69Smrg   CARD32	colorKey;
165c06b6b69Smrg   CARD32	videoStatus;
166c06b6b69Smrg   Time		offTime;
167c06b6b69Smrg   Time		freeTime;
168c06b6b69Smrg   Bool         doubleBuffer;
169c06b6b69Smrg   Bool         manualDoubleBuffer;
170c06b6b69Smrg   int          currentBuffer;
171c06b6b69Smrg} CHIPSPortPrivRec, *CHIPSPortPrivPtr;
172c06b6b69Smrg
173c06b6b69Smrg
174c06b6b69Smrg#define GET_PORT_PRIVATE(pScrn) \
175c06b6b69Smrg   (CHIPSPortPrivPtr)((CHIPSPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
176c06b6b69Smrg
177c06b6b69Smrgvoid
178c06b6b69SmrgCHIPSResetVideo(ScrnInfoPtr pScrn)
179c06b6b69Smrg{
180c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
181c06b6b69Smrg    CHIPSPortPrivPtr pPriv = cPtr->adaptor->pPortPrivates[0].ptr;
182c06b6b69Smrg    unsigned char mr3c;
183c06b6b69Smrg    int red, green, blue;
184c06b6b69Smrg
185c06b6b69Smrg    if (cPtr->Flags & ChipsAccelSupport)
186c06b6b69Smrg	CHIPSHiQVSync(pScrn);
187c06b6b69Smrg
188c06b6b69Smrg    mr3c = cPtr->readMR(cPtr, 0x3C);
189c06b6b69Smrg    cPtr->writeMR(cPtr, 0x3C, (mr3c | 0x6));
190c06b6b69Smrg    switch (pScrn->depth) {
191c06b6b69Smrg    case 8:
192c06b6b69Smrg	cPtr->writeMR(cPtr, 0x3D, 0x00);
193c06b6b69Smrg	cPtr->writeMR(cPtr, 0x3E, 0x00);
194c06b6b69Smrg	cPtr->writeMR(cPtr, 0x3F, (pPriv->colorKey & 0xFF));
195c06b6b69Smrg	cPtr->writeMR(cPtr, 0x40, 0xFF);
196c06b6b69Smrg	cPtr->writeMR(cPtr, 0x41, 0xFF);
197c06b6b69Smrg	cPtr->writeMR(cPtr, 0x42, 0x00);
198c06b6b69Smrg	break;
199c06b6b69Smrg    default:
200c06b6b69Smrg	red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
201c06b6b69Smrg	green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
202c06b6b69Smrg	blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
203c06b6b69Smrg	switch (pScrn->depth) {
204c06b6b69Smrg	case 15:
205c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3D, (red << 3));
206c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3E, (green << 3));
207c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3F, (blue << 3));
208c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x40, 0x07);
209c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x41, 0x07);
210c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x42, 0x07);
211c06b6b69Smrg	    break;
212c06b6b69Smrg	case 16:
213c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3D, (red << 3));
214c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3E, (green << 2));
215c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3F, (blue << 3));
216c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x40, 0x07);
217c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x41, 0x03);
218c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x42, 0x07);
219c06b6b69Smrg	    break;
220c06b6b69Smrg	case 24:
221c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3D, red);
222c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3E, green);
223c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3F, blue);
224c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x40, 0x00);
225c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x41, 0x00);
226c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x42, 0x00);
227c06b6b69Smrg	    break;
228c06b6b69Smrg	}
229c06b6b69Smrg    }
230c06b6b69Smrg}
231c06b6b69Smrg
232c06b6b69Smrg
233c06b6b69Smrgstatic XF86VideoAdaptorPtr
234c06b6b69SmrgCHIPSSetupImageVideo(ScreenPtr pScreen)
235c06b6b69Smrg{
236c06b6b69Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
237c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
238c06b6b69Smrg    XF86VideoAdaptorPtr adapt;
239c06b6b69Smrg    CHIPSPortPrivPtr pPriv;
240c06b6b69Smrg
241c06b6b69Smrg    if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
242c06b6b69Smrg			    sizeof(CHIPSPortPrivRec) +
243c06b6b69Smrg			    sizeof(DevUnion))))
244c06b6b69Smrg	return NULL;
245c06b6b69Smrg
246c06b6b69Smrg    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
247c06b6b69Smrg    adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
248c06b6b69Smrg    adapt->name = "Chips and Technologies Backend Scaler";
249c06b6b69Smrg    adapt->nEncodings = 1;
250c06b6b69Smrg    adapt->pEncodings = DummyEncoding;
251c06b6b69Smrg    adapt->nFormats = NUM_FORMATS;
252c06b6b69Smrg    adapt->pFormats = Formats;
253c06b6b69Smrg    adapt->nPorts = 1;
254c06b6b69Smrg    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
255c06b6b69Smrg    pPriv = (CHIPSPortPrivPtr)(&adapt->pPortPrivates[1]);
256c06b6b69Smrg    adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
257c06b6b69Smrg    adapt->pAttributes = Attributes;
258c06b6b69Smrg    adapt->nImages = NUM_IMAGES;
259c06b6b69Smrg    adapt->nAttributes = NUM_ATTRIBUTES;
260c06b6b69Smrg    adapt->pImages = Images;
261c06b6b69Smrg    adapt->PutVideo = NULL;
262c06b6b69Smrg    adapt->PutStill = NULL;
263c06b6b69Smrg    adapt->GetVideo = NULL;
264c06b6b69Smrg    adapt->GetStill = NULL;
265c06b6b69Smrg    adapt->StopVideo = CHIPSStopVideo;
266c06b6b69Smrg    adapt->SetPortAttribute = CHIPSSetPortAttribute;
267c06b6b69Smrg    adapt->GetPortAttribute = CHIPSGetPortAttribute;
268c06b6b69Smrg    adapt->QueryBestSize = CHIPSQueryBestSize;
269c06b6b69Smrg    adapt->PutImage = CHIPSPutImage;
270c06b6b69Smrg    adapt->QueryImageAttributes = CHIPSQueryImageAttributes;
271c06b6b69Smrg
272c06b6b69Smrg    pPriv->colorKey = cPtr->videoKey;
273c06b6b69Smrg    pPriv->videoStatus = 0;
274c06b6b69Smrg    pPriv->manualDoubleBuffer = FALSE;
275c06b6b69Smrg    pPriv->currentBuffer	= 0;
276c06b6b69Smrg
277c06b6b69Smrg    /* gotta uninit this someplace */
278c06b6b69Smrg    REGION_NULL(pScreen, &pPriv->clip);
279c06b6b69Smrg
280c06b6b69Smrg    cPtr->adaptor = adapt;
281c06b6b69Smrg
282c06b6b69Smrg    xvColorKey   = MAKE_ATOM("XV_COLORKEY");
283c06b6b69Smrg
284c06b6b69Smrg    CHIPSResetVideo(pScrn);
285c06b6b69Smrg
286c06b6b69Smrg    return adapt;
287c06b6b69Smrg}
288c06b6b69Smrg
289c06b6b69Smrg
290c06b6b69Smrgstatic void
291c06b6b69SmrgCHIPSStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shadow)
292c06b6b69Smrg{
293c06b6b69Smrg  CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data;
294c06b6b69Smrg  CHIPSPtr cPtr = CHIPSPTR(pScrn);
295c06b6b69Smrg  unsigned char mr3c, tmp;
296c06b6b69Smrg
297c06b6b69Smrg  REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
298c06b6b69Smrg  if (cPtr->Flags & ChipsAccelSupport)
299c06b6b69Smrg      CHIPSHiQVSync(pScrn);
300c06b6b69Smrg  if(shadow) {
301c06b6b69Smrg     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
302c06b6b69Smrg	mr3c = cPtr->readMR(cPtr, 0x3C);
303c06b6b69Smrg	cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE));
304c06b6b69Smrg	tmp = cPtr->readXR(cPtr, 0xD0);
305c06b6b69Smrg	cPtr->writeXR(cPtr, 0xD0, (tmp & 0xf));
306c06b6b69Smrg     }
307c06b6b69Smrg     if(pPriv->linear) {
308c06b6b69Smrg	xf86FreeOffscreenLinear(pPriv->linear);
309c06b6b69Smrg	pPriv->linear = NULL;
310c06b6b69Smrg     }
311c06b6b69Smrg     pPriv->videoStatus = 0;
312c06b6b69Smrg  } else {
313c06b6b69Smrg     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
314c06b6b69Smrg	pPriv->videoStatus |= OFF_TIMER;
315c06b6b69Smrg	pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
316c06b6b69Smrg	cPtr->VideoTimerCallback = CHIPSVideoTimerCallback;
317c06b6b69Smrg     }
318c06b6b69Smrg  }
319c06b6b69Smrg}
320c06b6b69Smrg
321c06b6b69Smrgstatic int
322c06b6b69SmrgCHIPSSetPortAttribute(
323c06b6b69Smrg  ScrnInfoPtr pScrn,
324c06b6b69Smrg  Atom attribute,
325c06b6b69Smrg  INT32 value,
326c06b6b69Smrg  pointer data
327c06b6b69Smrg){
328c06b6b69Smrg  CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data;
329c06b6b69Smrg  CHIPSPtr cPtr = CHIPSPTR(pScrn);
330c06b6b69Smrg
331c06b6b69Smrg  if (cPtr->Flags & ChipsAccelSupport)
332c06b6b69Smrg      CHIPSHiQVSync(pScrn);
333c06b6b69Smrg  if(attribute == xvColorKey) {
334c06b6b69Smrg	int red, green, blue;
335c06b6b69Smrg	pPriv->colorKey = value;
336c06b6b69Smrg	switch (pScrn->depth) {
337c06b6b69Smrg	case 8:
338c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3D, 0x00);
339c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3E, 0x00);
340c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3F, (pPriv->colorKey & 0xFF));
341c06b6b69Smrg	    break;
342c06b6b69Smrg	default:
343c06b6b69Smrg	    red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
344c06b6b69Smrg	    green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
345c06b6b69Smrg	    blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
346c06b6b69Smrg	    switch (pScrn->depth) {
347c06b6b69Smrg	    case 15:
348c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3D, (red << 3));
349c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3E, (green << 3));
350c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3F, (blue << 3));
351c06b6b69Smrg		break;
352c06b6b69Smrg	    case 16:
353c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3D, (red << 3));
354c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3E, (green << 2));
355c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3F, (blue << 3));
356c06b6b69Smrg		break;
357c06b6b69Smrg	    case 24:
358c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3D, red);
359c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3E, green);
360c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3F, blue);
361c06b6b69Smrg		break;
362c06b6b69Smrg	    }
363c06b6b69Smrg	}
364c06b6b69Smrg	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
365c06b6b69Smrg  } else return BadMatch;
366c06b6b69Smrg
367c06b6b69Smrg  return Success;
368c06b6b69Smrg}
369c06b6b69Smrg
370c06b6b69Smrgstatic int
371c06b6b69SmrgCHIPSGetPortAttribute(
372c06b6b69Smrg  ScrnInfoPtr pScrn,
373c06b6b69Smrg  Atom attribute,
374c06b6b69Smrg  INT32 *value,
375c06b6b69Smrg  pointer data
376c06b6b69Smrg){
377c06b6b69Smrg  CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data;
378c06b6b69Smrg
379c06b6b69Smrg  if(attribute == xvColorKey) {
380c06b6b69Smrg	*value = pPriv->colorKey;
381c06b6b69Smrg  } else return BadMatch;
382c06b6b69Smrg
383c06b6b69Smrg  return Success;
384c06b6b69Smrg}
385c06b6b69Smrg
386c06b6b69Smrgstatic void
387c06b6b69SmrgCHIPSQueryBestSize(
388c06b6b69Smrg  ScrnInfoPtr pScrn,
389c06b6b69Smrg  Bool motion,
390c06b6b69Smrg  short vid_w, short vid_h,
391c06b6b69Smrg  short drw_w, short drw_h,
392c06b6b69Smrg  unsigned int *p_w, unsigned int *p_h,
393c06b6b69Smrg  pointer data
394c06b6b69Smrg){
395c06b6b69Smrg  *p_w = drw_w;
396c06b6b69Smrg  *p_h = drw_h;
397c06b6b69Smrg
398c06b6b69Smrg  if(*p_w > 16384) *p_w = 16384;
399c06b6b69Smrg}
400c06b6b69Smrg
401c06b6b69Smrg
402c06b6b69Smrgstatic void
403c06b6b69SmrgCHIPSCopyData(
404c06b6b69Smrg  unsigned char *src,
405c06b6b69Smrg  unsigned char *dst,
406c06b6b69Smrg  int srcPitch,
407c06b6b69Smrg  int dstPitch,
408c06b6b69Smrg  int h,
409c06b6b69Smrg  int w
410c06b6b69Smrg){
411c06b6b69Smrg    w <<= 1;
412c06b6b69Smrg    while(h--) {
413c06b6b69Smrg	memcpy(dst, src, w);
414c06b6b69Smrg	src += srcPitch;
415c06b6b69Smrg	dst += dstPitch;
416c06b6b69Smrg    }
417c06b6b69Smrg}
418c06b6b69Smrg
419c06b6b69Smrgstatic void
420c06b6b69SmrgCHIPSCopyMungedData(
421c06b6b69Smrg   unsigned char *src1,
422c06b6b69Smrg   unsigned char *src2,
423c06b6b69Smrg   unsigned char *src3,
424c06b6b69Smrg   unsigned char *dst1,
425c06b6b69Smrg   int srcPitch,
426c06b6b69Smrg   int srcPitch2,
427c06b6b69Smrg   int dstPitch,
428c06b6b69Smrg   int h,
429c06b6b69Smrg   int w
430c06b6b69Smrg){
431c06b6b69Smrg   CARD32 *dst = (CARD32*)dst1;
432c06b6b69Smrg   int i, j;
433c06b6b69Smrg
434c06b6b69Smrg   dstPitch >>= 2;
435c06b6b69Smrg   w >>= 1;
436c06b6b69Smrg
437c06b6b69Smrg   for(j = 0; j < h; j++) {
438c06b6b69Smrg	for(i = 0; i < w; i++) {
439c06b6b69Smrg	    dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
440c06b6b69Smrg		     (src3[i] << 8) | (src2[i] << 24);
441c06b6b69Smrg	}
442c06b6b69Smrg	dst += dstPitch;
443c06b6b69Smrg	src1 += srcPitch;
444c06b6b69Smrg	if(j & 1) {
445c06b6b69Smrg	    src2 += srcPitch2;
446c06b6b69Smrg	    src3 += srcPitch2;
447c06b6b69Smrg	}
448c06b6b69Smrg   }
449c06b6b69Smrg}
450c06b6b69Smrg
451c06b6b69Smrgstatic FBLinearPtr
452c06b6b69SmrgCHIPSAllocateMemory(
453c06b6b69Smrg   ScrnInfoPtr pScrn,
454c06b6b69Smrg   FBLinearPtr linear,
455c06b6b69Smrg   int size
456c06b6b69Smrg){
457c06b6b69Smrg   ScreenPtr pScreen;
458c06b6b69Smrg   FBLinearPtr new_linear;
459c06b6b69Smrg
460c06b6b69Smrg   if(linear) {
461c06b6b69Smrg	if(linear->size >= size)
462c06b6b69Smrg	   return linear;
463c06b6b69Smrg
464c06b6b69Smrg        if(xf86ResizeOffscreenLinear(linear, size))
465c06b6b69Smrg	   return linear;
466c06b6b69Smrg
467c06b6b69Smrg	xf86FreeOffscreenLinear(linear);
468c06b6b69Smrg   }
469c06b6b69Smrg
470c06b6b69Smrg   pScreen = screenInfo.screens[pScrn->scrnIndex];
471c06b6b69Smrg
472c06b6b69Smrg   new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8,
473c06b6b69Smrg   						NULL, NULL, NULL);
474c06b6b69Smrg
475c06b6b69Smrg   if(!new_linear) {
476c06b6b69Smrg	int max_size;
477c06b6b69Smrg
478c06b6b69Smrg	xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8,
479c06b6b69Smrg						PRIORITY_EXTREME);
480c06b6b69Smrg
481c06b6b69Smrg	if(max_size < size)
482c06b6b69Smrg	   return NULL;
483c06b6b69Smrg
484c06b6b69Smrg	xf86PurgeUnlockedOffscreenAreas(pScreen);
485c06b6b69Smrg	new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8,
486c06b6b69Smrg						NULL, NULL, NULL);
487c06b6b69Smrg   }
488c06b6b69Smrg
489c06b6b69Smrg   return new_linear;
490c06b6b69Smrg}
491c06b6b69Smrg
492c06b6b69Smrgstatic int
493c06b6b69SmrgCHIPSSetCurrentPlaybackBuffer(CHIPSPtr cPtr, int n)
494c06b6b69Smrg{
495c06b6b69Smrg
496c06b6b69Smrg    CARD8 mr20;
497c06b6b69Smrg    mr20 = cPtr->readMR(cPtr, 0x20);
498c06b6b69Smrg    mr20 &= ~0x1B;
499c06b6b69Smrg    if (!n) mr20 |= 0x10;
500c06b6b69Smrg    cPtr->writeMR(cPtr, 0x22, mr20);
501c06b6b69Smrg    return n;
502c06b6b69Smrg}
503c06b6b69Smrg
504c06b6b69Smrgstatic int
505c06b6b69SmrgCHIPSWaitGetNextFrame(CHIPSPtr cPtr)
506c06b6b69Smrg{
507c06b6b69Smrg    volatile CARD8 mr20;
508c06b6b69Smrg    volatile CARD8 mr21;
509c06b6b69Smrg
510c06b6b69Smrg    mr20 = cPtr->readMR(cPtr, 0x20);
511c06b6b69Smrg    while (1) {
512c06b6b69Smrg      mr21 = cPtr->readMR(cPtr, 0x21);
513c06b6b69Smrg      if (!(mr20 & (1 << 5)) || !(mr21 & 1))
514c06b6b69Smrg	break;
515c06b6b69Smrg    }
516c06b6b69Smrg    mr20 &= ~0x4;
517c06b6b69Smrg    mr20 = cPtr->readMR(cPtr, 0x20);
518c06b6b69Smrg    return (mr21 & 2)? 0 : 1;
519c06b6b69Smrg}
520c06b6b69Smrg
521c06b6b69Smrgstatic void
522c06b6b69SmrgCHIPSDisplayVideo(
523c06b6b69Smrg    ScrnInfoPtr pScrn,
524c06b6b69Smrg    int id,
525c06b6b69Smrg    int offset,
526c06b6b69Smrg    short width, short height,
527c06b6b69Smrg    int pitch,
528c06b6b69Smrg    int x1, int y1, int x2, int y2,
529c06b6b69Smrg    BoxPtr dstBox,
530c06b6b69Smrg    short src_w, short src_h,
531c06b6b69Smrg    short drw_w, short drw_h,
532c06b6b69Smrg    Bool triggerBufSwitch
533c06b6b69Smrg){
534c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
535c06b6b69Smrg    CHIPSPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
536c06b6b69Smrg    DisplayModePtr mode = pScrn->currentMode;
537c06b6b69Smrg    unsigned char tmp, m1f, m1e;
538c06b6b69Smrg    int buffer = pPriv->currentBuffer;
539c06b6b69Smrg    Bool dblscan = (pScrn->currentMode->Flags & V_DBLSCAN) == V_DBLSCAN;
540c06b6b69Smrg    int val;
541c06b6b69Smrg
542c06b6b69Smrg    if (cPtr->Flags & ChipsAccelSupport)
543c06b6b69Smrg	CHIPSHiQVSync(pScrn);
544c06b6b69Smrg
545c06b6b69Smrg    tmp = cPtr->readXR(cPtr, 0xD0);
546c06b6b69Smrg    cPtr->writeXR(cPtr, 0xD0, (tmp | 0x10));
547c06b6b69Smrg
548c06b6b69Smrg    m1e = cPtr->readMR(cPtr, 0x1E);
549c06b6b69Smrg    m1e &= 0xE0;		/* Set Zoom and Direction */
550c06b6b69Smrg    if ((!(cPtr->PanelType & ChipsLCD)) && (mode->Flags & V_INTERLACE))
551c06b6b69Smrg	m1e |= 0x10;
552c06b6b69Smrg
553c06b6b69Smrg    m1f = cPtr->readMR(cPtr, 0x1F);
554c06b6b69Smrg    m1f = (m1f & 0x14); /* Mask reserved bits, unset interpolation */
555c06b6b69Smrg    switch(id) {
556c06b6b69Smrg    case 0x35315652:		/* RGB15 */
557c06b6b69Smrg	m1f |= 0x09;
558c06b6b69Smrg	break;
559c06b6b69Smrg    case 0x36315652:		/* RGB16 */
560c06b6b69Smrg	m1f |= 0x08;
561c06b6b69Smrg	break;
562c06b6b69Smrg    case FOURCC_YV12:		/* YV12 */
563c06b6b69Smrg      /* m1f |= 0x03 */
564c06b6b69Smrg	m1f |= 0x00;
565c06b6b69Smrg	break;
566c06b6b69Smrg    case FOURCC_YUY2:		/* YUY2 */
567c06b6b69Smrg    default:
568c06b6b69Smrg	m1f |= 0x00;		/* Do nothing here */
569c06b6b69Smrg	break;
570c06b6b69Smrg    }
571c06b6b69Smrg
572c06b6b69Smrg    offset += (x1 >> 15) & ~0x01;
573c06b6b69Smrg    /* Setup Pointer 1 */
574c06b6b69Smrg    if (!buffer || pPriv->manualDoubleBuffer || !pPriv->doubleBuffer) {
575c06b6b69Smrg        cPtr->writeMR(cPtr, 0x22, (offset & 0xF8));
576c06b6b69Smrg	cPtr->writeMR(cPtr, 0x23, ((offset >> 8) & 0xFF));
577c06b6b69Smrg	cPtr->writeMR(cPtr, 0x24, ((offset >> 16) & 0xFF));
578c06b6b69Smrg    }
579c06b6b69Smrg
580c06b6b69Smrg    /* Setup Pointer 2 */
581c06b6b69Smrg    if ((buffer && !pPriv->manualDoubleBuffer) || !pPriv->doubleBuffer) {
582c06b6b69Smrg        cPtr->writeMR(cPtr, 0x25, (offset & 0xF8));
583c06b6b69Smrg	cPtr->writeMR(cPtr, 0x26, ((offset >> 8) & 0xFF));
584c06b6b69Smrg	cPtr->writeMR(cPtr, 0x27, ((offset >> 16) & 0xFF));
585c06b6b69Smrg    }
586c06b6b69Smrg
587c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x04);
588c06b6b69Smrg    if (pPriv->doubleBuffer && !pPriv->manualDoubleBuffer && triggerBufSwitch)
589c06b6b69Smrg      tmp |= 0x18;
590c06b6b69Smrg    cPtr->writeMR(cPtr, 0x04, tmp);
591c06b6b69Smrg
592c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x20);
593c06b6b69Smrg    tmp &= 0xC3;
594c06b6b69Smrg
595c06b6b69Smrg    if (pPriv->doubleBuffer && !pPriv->manualDoubleBuffer && triggerBufSwitch)
596c06b6b69Smrg	tmp |= ((1 << 2  | 1 << 5) | ((buffer) ? (1 << 4) : 0));
597c06b6b69Smrg    cPtr->writeMR(cPtr, 0x20, tmp);
598c06b6b69Smrg
599c06b6b69Smrg    cPtr->writeMR(cPtr, 0x28, ((width >> 2) - 1)); /* Width */
600c06b6b69Smrg    cPtr->writeMR(cPtr, 0x34, ((width >> 2) - 1));
601c06b6b69Smrg
602c06b6b69Smrg    /* Left Edge of Overlay */
603c06b6b69Smrg    cPtr->writeMR(cPtr, 0x2A, ((cPtr->OverlaySkewX + dstBox->x1) & 0xFF));
604c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x2B);
605c06b6b69Smrg    tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewX + dstBox->x1) >> 8) & 0x07);
606c06b6b69Smrg    cPtr->writeMR(cPtr, 0x2B, tmp);
607c06b6b69Smrg    /* Right Edge of Overlay */
608c06b6b69Smrg    cPtr->writeMR(cPtr, 0x2C, ((cPtr->OverlaySkewX + dstBox->x2 -1)
609c06b6b69Smrg				& 0xFF));
610c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x2D);
611c06b6b69Smrg    tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewX + dstBox->x2 - 1) >> 8) & 0x07);
612c06b6b69Smrg    cPtr->writeMR(cPtr, 0x2D, tmp);
613c06b6b69Smrg    /* Top Edge of Overlay */
614c06b6b69Smrg    val = cPtr->OverlaySkewY + (dstBox->y1 << (dblscan ? 1 : 0));
615c06b6b69Smrg    cPtr->writeMR(cPtr, 0x2E, ((val) & 0xFF));
616c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x2F);
617c06b6b69Smrg    tmp = (tmp & 0xF8) + (((val) >> 8) & 0x07);
618c06b6b69Smrg    cPtr->writeMR(cPtr, 0x2F, tmp);
619c06b6b69Smrg    /* Bottom Edge of Overlay*/
620c06b6b69Smrg    val = cPtr->OverlaySkewY + (dstBox->y2 << (dblscan ? 1 : 0));
621c06b6b69Smrg    cPtr->writeMR(cPtr, 0x30, ((val - 1) & 0xFF));
622c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x31);
623c06b6b69Smrg    tmp = (tmp & 0xF8) + (((val - 1) >> 8) & 0x07);
624c06b6b69Smrg    cPtr->writeMR(cPtr, 0x31, tmp);
625c06b6b69Smrg
626c06b6b69Smrg    /* Horizontal Zoom */
627c06b6b69Smrg    if (drw_w > src_w) {
628c06b6b69Smrg        m1f = m1f | 0x20; /* set H-interpolation */
629c06b6b69Smrg	m1e = m1e | 0x04;
630c06b6b69Smrg	tmp = cPtr->VideoZoomMax * src_w / drw_w;
631c06b6b69Smrg	cPtr->writeMR(cPtr, 0x32, tmp);
632c06b6b69Smrg    }
633c06b6b69Smrg
634c06b6b69Smrg    /* Vertical Zoom */
635c06b6b69Smrg    if (drw_h > src_h || dblscan) {
636c06b6b69Smrg        m1f = m1f | 0x80; /* set V-interpolation */
637c06b6b69Smrg	m1e = m1e | 0x08;
638c06b6b69Smrg	if (dblscan)
639c06b6b69Smrg	    tmp = cPtr->VideoZoomMax >> 1;
640c06b6b69Smrg	if (drw_h > src_h)
641c06b6b69Smrg	    tmp = tmp * src_h / drw_h;
642c06b6b69Smrg	cPtr->writeMR(cPtr, 0x33, tmp);
643c06b6b69Smrg    }
644c06b6b69Smrg    cPtr->writeMR(cPtr, 0x1F, m1f);
645c06b6b69Smrg    cPtr->writeMR(cPtr, 0x1E, m1e);
646c06b6b69Smrg
647c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x3C);
648c06b6b69Smrg    cPtr->writeMR(cPtr, 0x3C, (tmp | 0x7));
649c06b6b69Smrg    if (cPtr->Flags & ChipsAccelSupport)
650c06b6b69Smrg	CHIPSHiQVSync(pScrn);
651c06b6b69Smrg}
652c06b6b69Smrg
653c06b6b69Smrgstatic int
654c06b6b69SmrgCHIPSPutImage(
655c06b6b69Smrg  ScrnInfoPtr pScrn,
656c06b6b69Smrg  short src_x, short src_y,
657c06b6b69Smrg  short drw_x, short drw_y,
658c06b6b69Smrg  short src_w, short src_h,
659c06b6b69Smrg  short drw_w, short drw_h,
660c06b6b69Smrg  int id, unsigned char* buf,
661c06b6b69Smrg  short width, short height,
662c06b6b69Smrg  Bool sync,
663c06b6b69Smrg  RegionPtr clipBoxes, pointer data,
664c06b6b69Smrg  DrawablePtr pDraw
665c06b6b69Smrg){
666c06b6b69Smrg   CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data;
667c06b6b69Smrg   CHIPSPtr cPtr = CHIPSPTR(pScrn);
668c06b6b69Smrg   INT32 x1, x2, y1, y2;
669c06b6b69Smrg   unsigned char *dst_start;
670c06b6b69Smrg   int new_size, offset, offset2 = 0, offset3 = 0;
671c06b6b69Smrg   int srcPitch, srcPitch2 = 0, dstPitch;
672c06b6b69Smrg   int top, left, npixels, nlines, bpp;
673c06b6b69Smrg   BoxRec dstBox;
674c06b6b69Smrg   CARD32 tmp;
675c06b6b69Smrg
676c06b6b69Smrg   if(drw_w > 16384) drw_w = 16384;
677c06b6b69Smrg
678c06b6b69Smrg   /* Clip */
679c06b6b69Smrg   x1 = src_x;
680c06b6b69Smrg   x2 = src_x + src_w;
681c06b6b69Smrg   y1 = src_y;
682c06b6b69Smrg   y2 = src_y + src_h;
683c06b6b69Smrg
684c06b6b69Smrg   dstBox.x1 = drw_x;
685c06b6b69Smrg   dstBox.x2 = drw_x + drw_w;
686c06b6b69Smrg   dstBox.y1 = drw_y;
687c06b6b69Smrg   dstBox.y2 = drw_y + drw_h;
688c06b6b69Smrg
689c06b6b69Smrg   if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2,
690c06b6b69Smrg			      clipBoxes, width, height))
691c06b6b69Smrg	return Success;
692c06b6b69Smrg
693c06b6b69Smrg   dstBox.x1 -= pScrn->frameX0 & cPtr->viewportMask;
694c06b6b69Smrg   dstBox.x2 -= pScrn->frameX0 & cPtr->viewportMask;
695c06b6b69Smrg   dstBox.y1 -= pScrn->frameY0;
696c06b6b69Smrg   dstBox.y2 -= pScrn->frameY0;
697c06b6b69Smrg
698c06b6b69Smrg   bpp = pScrn->bitsPerPixel >> 3;
699c06b6b69Smrg
700c06b6b69Smrg   dstPitch = ((width << 1) + 15) & ~15;
701c06b6b69Smrg   new_size = ((dstPitch * height) + bpp - 1) / bpp;
702c06b6b69Smrg
703c06b6b69Smrg   pPriv->doubleBuffer = (pScrn->currentMode->Flags & V_DBLSCAN) != V_DBLSCAN;
704c06b6b69Smrg
705c06b6b69Smrg   if (pPriv->doubleBuffer)
706c06b6b69Smrg       new_size <<= 1;
707c06b6b69Smrg
708c06b6b69Smrg   switch(id) {
709c06b6b69Smrg   case FOURCC_YV12:		/* YV12 */
710c06b6b69Smrg	srcPitch = (width + 3) & ~3;
711c06b6b69Smrg	offset2 = srcPitch * height;
712c06b6b69Smrg	srcPitch2 = ((width >> 1) + 3) & ~3;
713c06b6b69Smrg	offset3 = (srcPitch2 * (height >> 1)) + offset2;
714c06b6b69Smrg	break;
715c06b6b69Smrg   default:			/* RGB15, RGB16, YUY2 */
716c06b6b69Smrg	srcPitch = (width << 1);
717c06b6b69Smrg	break;
718c06b6b69Smrg   }
719c06b6b69Smrg
720c06b6b69Smrg   if(!(pPriv->linear = CHIPSAllocateMemory(pScrn, pPriv->linear, new_size))) {
721c06b6b69Smrg       if (pPriv->doubleBuffer
722c06b6b69Smrg	   && (pPriv->linear = CHIPSAllocateMemory(pScrn, pPriv->linear,
723c06b6b69Smrg					      new_size >> 1))) {
724c06b6b69Smrg         new_size >>= 1;
725c06b6b69Smrg	 pPriv->doubleBuffer = FALSE;
726c06b6b69Smrg   } else
727c06b6b69Smrg	return BadAlloc;
728c06b6b69Smrg   }
729c06b6b69Smrg
730c06b6b69Smrg   /* copy data */
731c06b6b69Smrg   top = y1 >> 16;
732c06b6b69Smrg   left = (x1 >> 16) & ~1;
733c06b6b69Smrg   npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
734c06b6b69Smrg   left <<= 1;
735c06b6b69Smrg
736c06b6b69Smrg   offset = pPriv->linear->offset * bpp;
737c06b6b69Smrg   if (!pPriv->manualDoubleBuffer)
738c06b6b69Smrg     pPriv->currentBuffer = CHIPSWaitGetNextFrame(cPtr);
739c06b6b69Smrg   if(pPriv->doubleBuffer && pPriv->currentBuffer)
740c06b6b69Smrg	offset += (new_size * bpp) >> 1;
741c06b6b69Smrg
742c06b6b69Smrg   dst_start = cPtr->FbBase + offset + left + (top * dstPitch);
743c06b6b69Smrg
744c06b6b69Smrg   switch(id) {
745c06b6b69Smrg   case FOURCC_YV12:		/* YV12 */
746c06b6b69Smrg        top &= ~1;
747c06b6b69Smrg	tmp = ((top >> 1) * srcPitch2) + (left >> 2);
748c06b6b69Smrg	offset2 += tmp;
749c06b6b69Smrg	offset3 += tmp;
750c06b6b69Smrg	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
751c06b6b69Smrg	CHIPSCopyMungedData(buf + (top * srcPitch) + (left >> 1),
752c06b6b69Smrg			  buf + offset2, buf + offset3, dst_start,
753c06b6b69Smrg			  srcPitch, srcPitch2, dstPitch, nlines, npixels);
754c06b6b69Smrg	break;
755c06b6b69Smrg   default:			/* RGB15, RGB16, YUY2 */
756c06b6b69Smrg	buf += (top * srcPitch) + left;
757c06b6b69Smrg	nlines = ((y2 + 0xffff) >> 16) - top;
758c06b6b69Smrg	CHIPSCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
759c06b6b69Smrg	break;
760c06b6b69Smrg   }
761c06b6b69Smrg
762c06b6b69Smrg   /* update cliplist */
763c06b6b69Smrg   if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
764c06b6b69Smrg	REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
765c06b6b69Smrg        xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
766c06b6b69Smrg   }
767c06b6b69Smrg
768c06b6b69Smrg   offset += top * dstPitch;
769c06b6b69Smrg   CHIPSDisplayVideo(pScrn, id, offset, width, height, dstPitch,
770c06b6b69Smrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h, TRUE);
771c06b6b69Smrg
772c06b6b69Smrg   pPriv->videoStatus = CLIENT_VIDEO_ON;
773c06b6b69Smrg
774c06b6b69Smrg   if (pPriv->manualDoubleBuffer)
775c06b6b69Smrg     pPriv->currentBuffer ^= 1;
776c06b6b69Smrg
777c06b6b69Smrg   return Success;
778c06b6b69Smrg}
779c06b6b69Smrg
780c06b6b69Smrgstatic int
781c06b6b69SmrgCHIPSQueryImageAttributes(
782c06b6b69Smrg  ScrnInfoPtr pScrn,
783c06b6b69Smrg  int id,
784c06b6b69Smrg  unsigned short *w, unsigned short *h,
785c06b6b69Smrg  int *pitches, int *offsets
786c06b6b69Smrg){
787c06b6b69Smrg    int size, tmp;
788c06b6b69Smrg
789c06b6b69Smrg    if(*w > 1024) *w = 1024;
790c06b6b69Smrg    if(*h > 1024) *h = 1024;
791c06b6b69Smrg
792c06b6b69Smrg    *w = (*w + 1) & ~1;
793c06b6b69Smrg    if(offsets) offsets[0] = 0;
794c06b6b69Smrg
795c06b6b69Smrg    switch(id) {
796c06b6b69Smrg    case FOURCC_YV12:		/* YV12 */
797c06b6b69Smrg	*h = (*h + 1) & ~1;
798c06b6b69Smrg	size = (*w + 3) & ~3;
799c06b6b69Smrg	if(pitches) pitches[0] = size;
800c06b6b69Smrg	size *= *h;
801c06b6b69Smrg	if(offsets) offsets[1] = size;
802c06b6b69Smrg	tmp = ((*w >> 1) + 3) & ~3;
803c06b6b69Smrg	if(pitches) pitches[1] = pitches[2] = tmp;
804c06b6b69Smrg	tmp *= (*h >> 1);
805c06b6b69Smrg	size += tmp;
806c06b6b69Smrg	if(offsets) offsets[2] = size;
807c06b6b69Smrg	size += tmp;
808c06b6b69Smrg	break;
809c06b6b69Smrg    default:			/* RGB15, RGB16, YUY2 */
810c06b6b69Smrg	size = *w << 1;
811c06b6b69Smrg	if(pitches) pitches[0] = size;
812c06b6b69Smrg	size *= *h;
813c06b6b69Smrg	break;
814c06b6b69Smrg    }
815c06b6b69Smrg
816c06b6b69Smrg    return size;
817c06b6b69Smrg}
818c06b6b69Smrg
819c06b6b69Smrg
820c06b6b69Smrgstatic void
821c06b6b69SmrgCHIPSVideoTimerCallback(ScrnInfoPtr pScrn, Time time)
822c06b6b69Smrg{
823c06b6b69Smrg    CHIPSPtr    cPtr = CHIPSPTR(pScrn);
824c06b6b69Smrg    CHIPSPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
825c06b6b69Smrg    unsigned char mr3c;
826c06b6b69Smrg
827c06b6b69Smrg    if(pPriv->videoStatus & TIMER_MASK) {
828c06b6b69Smrg	if(pPriv->videoStatus & OFF_TIMER) {
829c06b6b69Smrg	    if(pPriv->offTime < time) {
830c06b6b69Smrg		if (cPtr->Flags & ChipsAccelSupport)
831c06b6b69Smrg		    CHIPSHiQVSync(pScrn);
832c06b6b69Smrg		mr3c = cPtr->readMR(cPtr, 0x3C);
833c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE));
834c06b6b69Smrg		pPriv->videoStatus = FREE_TIMER;
835c06b6b69Smrg		pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
836c06b6b69Smrg	    }
837c06b6b69Smrg	} else {  /* FREE_TIMER */
838c06b6b69Smrg	    if(pPriv->freeTime < time) {
839c06b6b69Smrg		if(pPriv->linear) {
840c06b6b69Smrg		   xf86FreeOffscreenLinear(pPriv->linear);
841c06b6b69Smrg		   pPriv->linear = NULL;
842c06b6b69Smrg		}
843c06b6b69Smrg		pPriv->videoStatus = 0;
844c06b6b69Smrg	        cPtr->VideoTimerCallback = NULL;
845c06b6b69Smrg	    }
846c06b6b69Smrg        }
847c06b6b69Smrg    } else  /* shouldn't get here */
848c06b6b69Smrg	cPtr->VideoTimerCallback = NULL;
849c06b6b69Smrg}
850c06b6b69Smrg
851c06b6b69Smrg
852c06b6b69Smrg/****************** Offscreen stuff ***************/
853c06b6b69Smrg
854c06b6b69Smrgtypedef struct {
855c06b6b69Smrg  FBLinearPtr linear;
856c06b6b69Smrg  Bool isOn;
857c06b6b69Smrg} OffscreenPrivRec, * OffscreenPrivPtr;
858c06b6b69Smrg
859c06b6b69Smrgstatic int
860c06b6b69SmrgCHIPSAllocateSurface(
861c06b6b69Smrg    ScrnInfoPtr pScrn,
862c06b6b69Smrg    int id,
863c06b6b69Smrg    unsigned short w,
864c06b6b69Smrg    unsigned short h,
865c06b6b69Smrg    XF86SurfacePtr surface
866c06b6b69Smrg){
867c06b6b69Smrg    FBLinearPtr linear;
868c06b6b69Smrg    int pitch, size, bpp;
869c06b6b69Smrg    OffscreenPrivPtr pPriv;
870c06b6b69Smrg
871c06b6b69Smrg    if((w > 1024) || (h > 1024))
872c06b6b69Smrg	return BadAlloc;
873c06b6b69Smrg
874c06b6b69Smrg    w = (w + 1) & ~1;
875c06b6b69Smrg    pitch = ((w << 1) + 15) & ~15;
876c06b6b69Smrg    bpp = pScrn->bitsPerPixel >> 3;
877c06b6b69Smrg    size = ((pitch * h) + bpp - 1) / bpp;
878c06b6b69Smrg
879c06b6b69Smrg    if(!(linear = CHIPSAllocateMemory(pScrn, NULL, size)))
880c06b6b69Smrg	return BadAlloc;
881c06b6b69Smrg
882c06b6b69Smrg    surface->width = w;
883c06b6b69Smrg    surface->height = h;
884c06b6b69Smrg
885c06b6b69Smrg    if(!(surface->pitches = xalloc(sizeof(int)))) {
886c06b6b69Smrg	xf86FreeOffscreenLinear(linear);
887c06b6b69Smrg	return BadAlloc;
888c06b6b69Smrg    }
889c06b6b69Smrg    if(!(surface->offsets = xalloc(sizeof(int)))) {
890c06b6b69Smrg	xfree(surface->pitches);
891c06b6b69Smrg	xf86FreeOffscreenLinear(linear);
892c06b6b69Smrg	return BadAlloc;
893c06b6b69Smrg    }
894c06b6b69Smrg    if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
895c06b6b69Smrg	xfree(surface->pitches);
896c06b6b69Smrg	xfree(surface->offsets);
897c06b6b69Smrg	xf86FreeOffscreenLinear(linear);
898c06b6b69Smrg	return BadAlloc;
899c06b6b69Smrg    }
900c06b6b69Smrg
901c06b6b69Smrg    pPriv->linear = linear;
902c06b6b69Smrg    pPriv->isOn = FALSE;
903c06b6b69Smrg
904c06b6b69Smrg    surface->pScrn = pScrn;
905c06b6b69Smrg    surface->id = id;
906c06b6b69Smrg    surface->pitches[0] = pitch;
907c06b6b69Smrg    surface->offsets[0] = linear->offset * bpp;
908c06b6b69Smrg    surface->devPrivate.ptr = (pointer)pPriv;
909c06b6b69Smrg
910c06b6b69Smrg    return Success;
911c06b6b69Smrg}
912c06b6b69Smrg
913c06b6b69Smrgstatic int
914c06b6b69SmrgCHIPSStopSurface(
915c06b6b69Smrg    XF86SurfacePtr surface
916c06b6b69Smrg){
917c06b6b69Smrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
918c06b6b69Smrg
919c06b6b69Smrg    if(pPriv->isOn) {
920c06b6b69Smrg	CHIPSPtr cPtr = CHIPSPTR(surface->pScrn);
921c06b6b69Smrg	unsigned char mr3c, tmp;
922c06b6b69Smrg	tmp = cPtr->readXR(cPtr, 0xD0);
923c06b6b69Smrg	cPtr->writeXR(cPtr, 0xD0, (tmp & 0xf));
924c06b6b69Smrg	mr3c = cPtr->readMR(cPtr, 0x3C);
925c06b6b69Smrg	cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE));
926c06b6b69Smrg	pPriv->isOn = FALSE;
927c06b6b69Smrg    }
928c06b6b69Smrg
929c06b6b69Smrg    return Success;
930c06b6b69Smrg}
931c06b6b69Smrg
932c06b6b69Smrg
933c06b6b69Smrgstatic int
934c06b6b69SmrgCHIPSFreeSurface(
935c06b6b69Smrg    XF86SurfacePtr surface
936c06b6b69Smrg){
937c06b6b69Smrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
938c06b6b69Smrg
939c06b6b69Smrg    if(pPriv->isOn)
940c06b6b69Smrg	CHIPSStopSurface(surface);
941c06b6b69Smrg    xf86FreeOffscreenLinear(pPriv->linear);
942c06b6b69Smrg    xfree(surface->pitches);
943c06b6b69Smrg    xfree(surface->offsets);
944c06b6b69Smrg    xfree(surface->devPrivate.ptr);
945c06b6b69Smrg
946c06b6b69Smrg    return Success;
947c06b6b69Smrg}
948c06b6b69Smrg
949c06b6b69Smrgstatic int
950c06b6b69SmrgCHIPSGetSurfaceAttribute(
951c06b6b69Smrg    ScrnInfoPtr pScrn,
952c06b6b69Smrg    Atom attribute,
953c06b6b69Smrg    INT32 *value
954c06b6b69Smrg){
955c06b6b69Smrg    return CHIPSGetPortAttribute(pScrn, attribute, value,
956c06b6b69Smrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
957c06b6b69Smrg}
958c06b6b69Smrg
959c06b6b69Smrgstatic int
960c06b6b69SmrgCHIPSSetSurfaceAttribute(
961c06b6b69Smrg    ScrnInfoPtr pScrn,
962c06b6b69Smrg    Atom attribute,
963c06b6b69Smrg    INT32 value
964c06b6b69Smrg){
965c06b6b69Smrg    return CHIPSSetPortAttribute(pScrn, attribute, value,
966c06b6b69Smrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
967c06b6b69Smrg}
968c06b6b69Smrg
969c06b6b69Smrg
970c06b6b69Smrgstatic int
971c06b6b69SmrgCHIPSDisplaySurface(
972c06b6b69Smrg    XF86SurfacePtr surface,
973c06b6b69Smrg    short src_x, short src_y,
974c06b6b69Smrg    short drw_x, short drw_y,
975c06b6b69Smrg    short src_w, short src_h,
976c06b6b69Smrg    short drw_w, short drw_h,
977c06b6b69Smrg    RegionPtr clipBoxes
978c06b6b69Smrg){
979c06b6b69Smrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
980c06b6b69Smrg    ScrnInfoPtr pScrn = surface->pScrn;
981c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
982c06b6b69Smrg    CHIPSPortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn);
983c06b6b69Smrg    INT32 x1, y1, x2, y2;
984c06b6b69Smrg    BoxRec dstBox;
985c06b6b69Smrg
986c06b6b69Smrg    x1 = src_x;
987c06b6b69Smrg    x2 = src_x + src_w;
988c06b6b69Smrg    y1 = src_y;
989c06b6b69Smrg    y2 = src_y + src_h;
990c06b6b69Smrg
991c06b6b69Smrg    dstBox.x1 = drw_x;
992c06b6b69Smrg    dstBox.x2 = drw_x + drw_w;
993c06b6b69Smrg    dstBox.y1 = drw_y;
994c06b6b69Smrg    dstBox.y2 = drw_y + drw_h;
995c06b6b69Smrg
996c06b6b69Smrg    if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
997c06b6b69Smrg			      surface->width, surface->height))
998c06b6b69Smrg	return Success;
999c06b6b69Smrg
1000c06b6b69Smrg    dstBox.x1 -= pScrn->frameX0;
1001c06b6b69Smrg    dstBox.x2 -= pScrn->frameX0;
1002c06b6b69Smrg    dstBox.y1 -= pScrn->frameY0;
1003c06b6b69Smrg    dstBox.y2 -= pScrn->frameY0;
1004c06b6b69Smrg
1005c06b6b69Smrg    if (portPriv->doubleBuffer)
1006c06b6b69Smrg      portPriv->currentBuffer = CHIPSSetCurrentPlaybackBuffer(cPtr,0);
1007c06b6b69Smrg    else
1008c06b6b69Smrg      portPriv->currentBuffer = 0;
1009c06b6b69Smrg
1010c06b6b69Smrg    CHIPSDisplayVideo(pScrn, surface->id, surface->offsets[0],
1011c06b6b69Smrg	     surface->width, surface->height, surface->pitches[0],
1012c06b6b69Smrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h, FALSE);
1013c06b6b69Smrg    xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
1014c06b6b69Smrg
1015c06b6b69Smrg    pPriv->isOn = TRUE;
1016c06b6b69Smrg    if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
1017c06b6b69Smrg	REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
1018c06b6b69Smrg	UpdateCurrentTime();
1019c06b6b69Smrg	portPriv->videoStatus = FREE_TIMER;
1020c06b6b69Smrg	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
1021c06b6b69Smrg	cPtr->VideoTimerCallback = CHIPSVideoTimerCallback;
1022c06b6b69Smrg    }
1023c06b6b69Smrg
1024c06b6b69Smrg    return Success;
1025c06b6b69Smrg}
1026c06b6b69Smrg
1027c06b6b69Smrg
1028c06b6b69Smrgstatic void
1029c06b6b69SmrgCHIPSInitOffscreenImages(ScreenPtr pScreen)
1030c06b6b69Smrg{
1031c06b6b69Smrg    XF86OffscreenImagePtr offscreenImages;
1032c06b6b69Smrg
1033c06b6b69Smrg    /* need to free this someplace */
1034c06b6b69Smrg    if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
1035c06b6b69Smrg	return;
1036c06b6b69Smrg
1037c06b6b69Smrg    offscreenImages[0].image = &Images[0];
1038c06b6b69Smrg    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
1039c06b6b69Smrg			       VIDEO_CLIP_TO_VIEWPORT;
1040c06b6b69Smrg    offscreenImages[0].alloc_surface = CHIPSAllocateSurface;
1041c06b6b69Smrg    offscreenImages[0].free_surface = CHIPSFreeSurface;
1042c06b6b69Smrg    offscreenImages[0].display = CHIPSDisplaySurface;
1043c06b6b69Smrg    offscreenImages[0].stop = CHIPSStopSurface;
1044c06b6b69Smrg    offscreenImages[0].setAttribute = CHIPSSetSurfaceAttribute;
1045c06b6b69Smrg    offscreenImages[0].getAttribute = CHIPSGetSurfaceAttribute;
1046c06b6b69Smrg    offscreenImages[0].max_width = 1024;
1047c06b6b69Smrg    offscreenImages[0].max_height = 1024;
1048c06b6b69Smrg    offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
1049c06b6b69Smrg    offscreenImages[0].attributes = Attributes;
1050c06b6b69Smrg
1051c06b6b69Smrg    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
1052c06b6b69Smrg}
1053