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