nv_video.c revision 6086d97e
1fc5a983dSmrg#ifdef HAVE_CONFIG_H
2fc5a983dSmrg#include "config.h"
3fc5a983dSmrg#endif
4fc5a983dSmrg
5fc5a983dSmrg#include "xf86.h"
6fc5a983dSmrg#include "xf86_OSproc.h"
7fc5a983dSmrg#include "compiler.h"
8fc5a983dSmrg#include "xf86PciInfo.h"
9fc5a983dSmrg#include "xf86Pci.h"
10fc5a983dSmrg#include "xf86fbman.h"
11fc5a983dSmrg#include "regionstr.h"
12fc5a983dSmrg
13fc5a983dSmrg#include "xf86xv.h"
14fc5a983dSmrg#include <X11/extensions/Xv.h>
15fc5a983dSmrg#include "xaa.h"
16fc5a983dSmrg#include "xaalocal.h"
17fc5a983dSmrg#include "dixstruct.h"
18fc5a983dSmrg#include "fourcc.h"
19fc5a983dSmrg
20fc5a983dSmrg#include "nv_include.h"
21fc5a983dSmrg#include "nv_dma.h"
22fc5a983dSmrg
23fc5a983dSmrg#define OFF_DELAY 	500  /* milliseconds */
24fc5a983dSmrg#define FREE_DELAY 	5000
25fc5a983dSmrg
26fc5a983dSmrg#define OFF_TIMER 	0x01
27fc5a983dSmrg#define FREE_TIMER	0x02
28fc5a983dSmrg#define CLIENT_VIDEO_ON	0x04
29fc5a983dSmrg
30fc5a983dSmrg#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
31fc5a983dSmrg
32fc5a983dSmrg#define NUM_BLIT_PORTS 32
33fc5a983dSmrg
34fc5a983dSmrgtypedef struct _NVPortPrivRec {
35fc5a983dSmrg   short        brightness;
36fc5a983dSmrg   short        contrast;
37fc5a983dSmrg   short        saturation;
38fc5a983dSmrg   short        hue;
39fc5a983dSmrg   RegionRec    clip;
40fc5a983dSmrg   CARD32       colorKey;
41fc5a983dSmrg   Bool         autopaintColorKey;
42fc5a983dSmrg   Bool		doubleBuffer;
43fc5a983dSmrg   CARD32       videoStatus;
44fc5a983dSmrg   int		currentBuffer;
45fc5a983dSmrg   Time         videoTime;
46fc5a983dSmrg   Bool		grabbedByV4L;
47fc5a983dSmrg   Bool         iturbt_709;
48fc5a983dSmrg   Bool         blitter;
49fc5a983dSmrg   Bool         SyncToVBlank;
50fc5a983dSmrg   FBLinearPtr  linear;
51fc5a983dSmrg   int pitch;
52fc5a983dSmrg   int offset;
53fc5a983dSmrg} NVPortPrivRec, *NVPortPrivPtr;
54fc5a983dSmrg
55fc5a983dSmrg
56fc5a983dSmrgstatic XF86VideoAdaptorPtr NVSetupOverlayVideo(ScreenPtr);
57fc5a983dSmrgstatic XF86VideoAdaptorPtr NVSetupBlitVideo(ScreenPtr);
58fc5a983dSmrg
59fc5a983dSmrgstatic void NVStopOverlay (ScrnInfoPtr);
60fc5a983dSmrgstatic void NVPutOverlayImage(ScrnInfoPtr pScrnInfo,
61fc5a983dSmrg                              int offset,
62fc5a983dSmrg			      int id,
63fc5a983dSmrg			      int dstPitch,
64fc5a983dSmrg                              BoxPtr dstBox,
65fc5a983dSmrg			      int x1, int y1, int x2, int y2,
66fc5a983dSmrg                              short width, short height,
67fc5a983dSmrg                              short src_w, short src_h,
68fc5a983dSmrg                              short dst_w, short dst_h,
69fc5a983dSmrg                              RegionPtr cliplist);
70fc5a983dSmrg
71fc5a983dSmrgstatic int  NVSetOverlayPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
72fc5a983dSmrgstatic int  NVGetOverlayPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
73fc5a983dSmrgstatic int  NVSetBlitPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
74fc5a983dSmrgstatic int  NVGetBlitPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
75fc5a983dSmrg
76fc5a983dSmrg
77fc5a983dSmrgstatic void NVStopOverlayVideo(ScrnInfoPtr, pointer, Bool);
78fc5a983dSmrgstatic void NVStopBlitVideo(ScrnInfoPtr, pointer, Bool);
79fc5a983dSmrg
80fc5a983dSmrgstatic int  NVPutImage( ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr);
81fc5a983dSmrg
82fc5a983dSmrgstatic void NVQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer);
83fc5a983dSmrgstatic int  NVQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *,  int *, int *);
84fc5a983dSmrg
85fc5a983dSmrgstatic void NVVideoTimerCallback(ScrnInfoPtr, Time);
86fc5a983dSmrg
87fc5a983dSmrgstatic void NVInitOffscreenImages (ScreenPtr pScreen);
88fc5a983dSmrg
89fc5a983dSmrg
90fc5a983dSmrg#define GET_OVERLAY_PRIVATE(pNv) \
91fc5a983dSmrg   (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr)
92fc5a983dSmrg
93fc5a983dSmrg#define GET_BLIT_PRIVATE(pNv) \
94fc5a983dSmrg   (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr)
95fc5a983dSmrg
96fc5a983dSmrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
97fc5a983dSmrg
98fc5a983dSmrgstatic Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
99fc5a983dSmrg            xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
100fc5a983dSmrg            xvITURBT709, xvSyncToVBlank;
101fc5a983dSmrg
102fc5a983dSmrg/* client libraries expect an encoding */
103fc5a983dSmrgstatic XF86VideoEncodingRec DummyEncoding =
104fc5a983dSmrg{
105fc5a983dSmrg   0,
106fc5a983dSmrg   "XV_IMAGE",
107fc5a983dSmrg   2046, 2046,
108fc5a983dSmrg   {1, 1}
109fc5a983dSmrg};
110fc5a983dSmrg
111fc5a983dSmrg#define NUM_FORMATS_ALL 6
112fc5a983dSmrg
113fc5a983dSmrgXF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
114fc5a983dSmrg{
115fc5a983dSmrg   {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
116fc5a983dSmrg   {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
117fc5a983dSmrg};
118fc5a983dSmrg
119fc5a983dSmrg#define NUM_OVERLAY_ATTRIBUTES 9
120fc5a983dSmrgXF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] =
121fc5a983dSmrg{
122fc5a983dSmrg   {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
123fc5a983dSmrg   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
124fc5a983dSmrg   {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
125fc5a983dSmrg   {XvSettable             , 0, 0, "XV_SET_DEFAULTS"},
126fc5a983dSmrg   {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
127fc5a983dSmrg   {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
128fc5a983dSmrg   {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
129fc5a983dSmrg   {XvSettable | XvGettable, 0, 360, "XV_HUE"},
130fc5a983dSmrg   {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"}
131fc5a983dSmrg};
132fc5a983dSmrg
133fc5a983dSmrg#define NUM_BLIT_ATTRIBUTES 2
134fc5a983dSmrgXF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
135fc5a983dSmrg{
136fc5a983dSmrg   {XvSettable             , 0, 0, "XV_SET_DEFAULTS"},
137fc5a983dSmrg   {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
138fc5a983dSmrg};
139fc5a983dSmrg
140fc5a983dSmrg
141fc5a983dSmrg#define NUM_IMAGES_YUV 4
142fc5a983dSmrg#define NUM_IMAGES_ALL 5
143fc5a983dSmrg
144fc5a983dSmrg#define FOURCC_RGB 0x0000003
145fc5a983dSmrg#define XVIMAGE_RGB \
146fc5a983dSmrg   { \
147fc5a983dSmrg        FOURCC_RGB, \
148fc5a983dSmrg        XvRGB, \
149fc5a983dSmrg        LSBFirst, \
150fc5a983dSmrg        { 0x03, 0x00, 0x00, 0x00, \
151fc5a983dSmrg          0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
152fc5a983dSmrg        32, \
153fc5a983dSmrg        XvPacked, \
154fc5a983dSmrg        1, \
155fc5a983dSmrg        24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
156fc5a983dSmrg        0, 0, 0, \
157fc5a983dSmrg        0, 0, 0, \
158fc5a983dSmrg        0, 0, 0, \
159fc5a983dSmrg        {'B','G','R','X',\
160fc5a983dSmrg          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}, \
161fc5a983dSmrg        XvTopToBottom \
162fc5a983dSmrg   }
163fc5a983dSmrg
164fc5a983dSmrgstatic XF86ImageRec NVImages[NUM_IMAGES_ALL] =
165fc5a983dSmrg{
166fc5a983dSmrg    XVIMAGE_YUY2,
167fc5a983dSmrg    XVIMAGE_YV12,
168fc5a983dSmrg    XVIMAGE_UYVY,
169fc5a983dSmrg    XVIMAGE_I420,
170fc5a983dSmrg    XVIMAGE_RGB
171fc5a983dSmrg};
172fc5a983dSmrg
173fc5a983dSmrgstatic void
174fc5a983dSmrgNVSetPortDefaults (ScrnInfoPtr pScrnInfo, NVPortPrivPtr pPriv)
175fc5a983dSmrg{
176fc5a983dSmrg    NVPtr pNv = NVPTR(pScrnInfo);
177fc5a983dSmrg
178fc5a983dSmrg    pPriv->brightness           = 0;
179fc5a983dSmrg    pPriv->contrast             = 4096;
180fc5a983dSmrg    pPriv->saturation           = 4096;
181fc5a983dSmrg    pPriv->hue                  = 0;
182fc5a983dSmrg    pPriv->colorKey             = pNv->videoKey;
183fc5a983dSmrg    pPriv->autopaintColorKey    = TRUE;
184fc5a983dSmrg    pPriv->doubleBuffer		= TRUE;
185fc5a983dSmrg    pPriv->iturbt_709           = FALSE;
186fc5a983dSmrg}
187fc5a983dSmrg
188fc5a983dSmrg
189fc5a983dSmrgvoid
190fc5a983dSmrgNVResetVideo (ScrnInfoPtr pScrnInfo)
191fc5a983dSmrg{
192fc5a983dSmrg    NVPtr          pNv     = NVPTR(pScrnInfo);
193fc5a983dSmrg    NVPortPrivPtr  pPriv   = GET_OVERLAY_PRIVATE(pNv);
194fc5a983dSmrg    int            satSine, satCosine;
195fc5a983dSmrg    double         angle;
196fc5a983dSmrg
197fc5a983dSmrg    angle = (double)pPriv->hue * 3.1415927 / 180.0;
198fc5a983dSmrg
199fc5a983dSmrg    satSine = pPriv->saturation * sin(angle);
200fc5a983dSmrg    if (satSine < -1024)
201fc5a983dSmrg        satSine = -1024;
202fc5a983dSmrg    satCosine = pPriv->saturation * cos(angle);
203fc5a983dSmrg    if (satCosine < -1024)
204fc5a983dSmrg        satCosine = -1024;
205fc5a983dSmrg
206fc5a983dSmrg    pNv->PMC[0x8910/4] = (pPriv->brightness << 16) | pPriv->contrast;
207fc5a983dSmrg    pNv->PMC[0x8914/4] = (pPriv->brightness << 16) | pPriv->contrast;
208fc5a983dSmrg    pNv->PMC[0x8918/4] = (satSine << 16) | (satCosine & 0xffff);
209fc5a983dSmrg    pNv->PMC[0x891C/4] = (satSine << 16) | (satCosine & 0xffff);
210fc5a983dSmrg    pNv->PMC[0x8b00/4] = pPriv->colorKey;
211fc5a983dSmrg}
212fc5a983dSmrg
213fc5a983dSmrg
214fc5a983dSmrg
215fc5a983dSmrgstatic void
216fc5a983dSmrgNVStopOverlay (ScrnInfoPtr pScrnInfo)
217fc5a983dSmrg{
218fc5a983dSmrg    NVPtr          pNv     = NVPTR(pScrnInfo);
219fc5a983dSmrg
220fc5a983dSmrg    pNv->PMC[0x00008704/4] = 1;
221fc5a983dSmrg}
222fc5a983dSmrg
223fc5a983dSmrgstatic FBLinearPtr
224fc5a983dSmrgNVAllocateOverlayMemory(
225fc5a983dSmrg   ScrnInfoPtr pScrn,
226fc5a983dSmrg   FBLinearPtr linear,
227fc5a983dSmrg   int size
228fc5a983dSmrg){
229fc5a983dSmrg   ScreenPtr pScreen;
230fc5a983dSmrg   FBLinearPtr new_linear;
231fc5a983dSmrg
232fc5a983dSmrg   if(linear) {
233fc5a983dSmrg        if(linear->size >= size)
234fc5a983dSmrg           return linear;
235fc5a983dSmrg
236fc5a983dSmrg        if(xf86ResizeOffscreenLinear(linear, size))
237fc5a983dSmrg           return linear;
238fc5a983dSmrg
239fc5a983dSmrg        xf86FreeOffscreenLinear(linear);
240fc5a983dSmrg   }
241fc5a983dSmrg
242fc5a983dSmrg   pScreen = screenInfo.screens[pScrn->scrnIndex];
243fc5a983dSmrg
244fc5a983dSmrg   new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32,
245fc5a983dSmrg                                                NULL, NULL, NULL);
246fc5a983dSmrg
247fc5a983dSmrg   if(!new_linear) {
248fc5a983dSmrg        int max_size;
249fc5a983dSmrg
250fc5a983dSmrg        xf86QueryLargestOffscreenLinear(pScreen, &max_size, 32,
251fc5a983dSmrg                                                PRIORITY_EXTREME);
252fc5a983dSmrg
253fc5a983dSmrg        if(max_size < size)
254fc5a983dSmrg           return NULL;
255fc5a983dSmrg
256fc5a983dSmrg        xf86PurgeUnlockedOffscreenAreas(pScreen);
257fc5a983dSmrg        new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32,
258fc5a983dSmrg                                                NULL, NULL, NULL);
259fc5a983dSmrg   }
260fc5a983dSmrg
261fc5a983dSmrg   return new_linear;
262fc5a983dSmrg}
263fc5a983dSmrg
264fc5a983dSmrgstatic void NVFreeOverlayMemory(ScrnInfoPtr pScrnInfo)
265fc5a983dSmrg{
266fc5a983dSmrg    NVPtr               pNv   = NVPTR(pScrnInfo);
267fc5a983dSmrg    NVPortPrivPtr  pPriv   = GET_OVERLAY_PRIVATE(pNv);
268fc5a983dSmrg
269fc5a983dSmrg    if(pPriv->linear) {
270fc5a983dSmrg        xf86FreeOffscreenLinear(pPriv->linear);
271fc5a983dSmrg	pPriv->linear = NULL;
272fc5a983dSmrg    }
273fc5a983dSmrg}
274fc5a983dSmrg
275fc5a983dSmrg
276fc5a983dSmrgstatic void NVFreeBlitMemory(ScrnInfoPtr pScrnInfo)
277fc5a983dSmrg{
278fc5a983dSmrg    NVPtr               pNv   = NVPTR(pScrnInfo);
279fc5a983dSmrg    NVPortPrivPtr  pPriv   = GET_BLIT_PRIVATE(pNv);
280fc5a983dSmrg
281fc5a983dSmrg    if(pPriv->linear) {
282fc5a983dSmrg        xf86FreeOffscreenLinear(pPriv->linear);
283fc5a983dSmrg        pPriv->linear = NULL;
284fc5a983dSmrg    }
285fc5a983dSmrg}
286fc5a983dSmrg
287fc5a983dSmrg
288fc5a983dSmrgvoid NVInitVideo (ScreenPtr pScreen)
289fc5a983dSmrg{
290fc5a983dSmrg    ScrnInfoPtr 	pScrn = xf86Screens[pScreen->myNum];
291fc5a983dSmrg    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
292fc5a983dSmrg    XF86VideoAdaptorPtr overlayAdaptor = NULL;
293fc5a983dSmrg    XF86VideoAdaptorPtr blitAdaptor = NULL;
294fc5a983dSmrg    NVPtr         	pNv   = NVPTR(pScrn);
295fc5a983dSmrg    int 		num_adaptors;
296fc5a983dSmrg
297fc5a983dSmrg    if((pScrn->bitsPerPixel != 8) && (pNv->Architecture >= NV_ARCH_10) &&
298fc5a983dSmrg         ((pNv->Architecture <= NV_ARCH_30) ||
299fc5a983dSmrg            ((pNv->Chipset & 0xfff0) == 0x0040)))
300fc5a983dSmrg    {
301fc5a983dSmrg	overlayAdaptor = NVSetupOverlayVideo(pScreen);
302fc5a983dSmrg
303fc5a983dSmrg	if(overlayAdaptor)
304fc5a983dSmrg	    NVInitOffscreenImages(pScreen);
305fc5a983dSmrg    }
306fc5a983dSmrg
307fc5a983dSmrg    if((pScrn->bitsPerPixel != 8) && !pNv->NoAccel)
308fc5a983dSmrg        blitAdaptor = NVSetupBlitVideo(pScreen);
309fc5a983dSmrg
310fc5a983dSmrg    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
311fc5a983dSmrg
312fc5a983dSmrg    if(blitAdaptor || overlayAdaptor) {
313fc5a983dSmrg        int size = num_adaptors;
314fc5a983dSmrg
315fc5a983dSmrg        if(overlayAdaptor) size++;
316fc5a983dSmrg        if(blitAdaptor)    size++;
317fc5a983dSmrg
3186086d97eSmrg        if((newAdaptors = malloc(size * sizeof(XF86VideoAdaptorPtr*)))) {
319fc5a983dSmrg            if(num_adaptors) {
320fc5a983dSmrg                 memcpy(newAdaptors, adaptors,
321fc5a983dSmrg                        num_adaptors * sizeof(XF86VideoAdaptorPtr));
322fc5a983dSmrg            }
323fc5a983dSmrg            if(overlayAdaptor) {
324fc5a983dSmrg                newAdaptors[num_adaptors] = overlayAdaptor;
325fc5a983dSmrg                num_adaptors++;
326fc5a983dSmrg	    }
327fc5a983dSmrg            if(blitAdaptor) {
328fc5a983dSmrg                newAdaptors[num_adaptors] = blitAdaptor;
329fc5a983dSmrg                num_adaptors++;
330fc5a983dSmrg            }
331fc5a983dSmrg	    adaptors = newAdaptors;
332fc5a983dSmrg        }
333fc5a983dSmrg    }
334fc5a983dSmrg
335fc5a983dSmrg    if (num_adaptors)
336fc5a983dSmrg        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
337fc5a983dSmrg
338fc5a983dSmrg    if (newAdaptors)
3396086d97eSmrg	free(newAdaptors);
340fc5a983dSmrg}
341fc5a983dSmrg
342fc5a983dSmrg
343fc5a983dSmrgstatic XF86VideoAdaptorPtr
344fc5a983dSmrgNVSetupBlitVideo (ScreenPtr pScreen)
345fc5a983dSmrg{
346fc5a983dSmrg    ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum];
347fc5a983dSmrg    NVPtr       pNv       = NVPTR(pScrnInfo);
348fc5a983dSmrg    XF86VideoAdaptorPtr adapt;
349fc5a983dSmrg    NVPortPrivPtr       pPriv;
350fc5a983dSmrg    int         i;
351fc5a983dSmrg
3526086d97eSmrg    if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
353fc5a983dSmrg                             sizeof(NVPortPrivRec) +
354fc5a983dSmrg                             (sizeof(DevUnion) * NUM_BLIT_PORTS))))
355fc5a983dSmrg    {
356fc5a983dSmrg        return NULL;
357fc5a983dSmrg    }
358fc5a983dSmrg
359fc5a983dSmrg    adapt->type                 = XvWindowMask | XvInputMask | XvImageMask;
360fc5a983dSmrg    adapt->flags                = 0;
361fc5a983dSmrg    adapt->name                 = "NV Video Blitter";
362fc5a983dSmrg    adapt->nEncodings           = 1;
363fc5a983dSmrg    adapt->pEncodings           = &DummyEncoding;
364fc5a983dSmrg    adapt->nFormats             = NUM_FORMATS_ALL;
365fc5a983dSmrg    adapt->pFormats             = NVFormats;
366fc5a983dSmrg    adapt->nPorts               = NUM_BLIT_PORTS;
367fc5a983dSmrg    adapt->pPortPrivates        = (DevUnion*)(&adapt[1]);
368fc5a983dSmrg
369fc5a983dSmrg    pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
370fc5a983dSmrg    for(i = 0; i < NUM_BLIT_PORTS; i++)
371fc5a983dSmrg       adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
372fc5a983dSmrg
373fc5a983dSmrg    if(pNv->WaitVSyncPossible) {
374fc5a983dSmrg       adapt->pAttributes          = NVBlitAttributes;
375fc5a983dSmrg       adapt->nAttributes          = NUM_BLIT_ATTRIBUTES;
376fc5a983dSmrg    } else {
377fc5a983dSmrg       adapt->pAttributes          = NULL;
378fc5a983dSmrg       adapt->nAttributes          = 0;
379fc5a983dSmrg    }
380fc5a983dSmrg    adapt->pImages              = NVImages;
381fc5a983dSmrg    adapt->nImages              = NUM_IMAGES_ALL;
382fc5a983dSmrg    adapt->PutVideo             = NULL;
383fc5a983dSmrg    adapt->PutStill             = NULL;
384fc5a983dSmrg    adapt->GetVideo             = NULL;
385fc5a983dSmrg    adapt->GetStill             = NULL;
386fc5a983dSmrg    adapt->StopVideo            = NVStopBlitVideo;
387fc5a983dSmrg    adapt->SetPortAttribute     = NVSetBlitPortAttribute;
388fc5a983dSmrg    adapt->GetPortAttribute     = NVGetBlitPortAttribute;
389fc5a983dSmrg    adapt->QueryBestSize        = NVQueryBestSize;
390fc5a983dSmrg    adapt->PutImage             = NVPutImage;
391fc5a983dSmrg    adapt->QueryImageAttributes = NVQueryImageAttributes;
392fc5a983dSmrg
393fc5a983dSmrg    pPriv->videoStatus          = 0;
394fc5a983dSmrg    pPriv->grabbedByV4L         = FALSE;
395fc5a983dSmrg    pPriv->blitter              = TRUE;
396fc5a983dSmrg    pPriv->doubleBuffer         = FALSE;
397fc5a983dSmrg    pPriv->SyncToVBlank         = pNv->WaitVSyncPossible;
398fc5a983dSmrg
399fc5a983dSmrg    pNv->blitAdaptor            = adapt;
400fc5a983dSmrg
401fc5a983dSmrg    xvSyncToVBlank              = MAKE_ATOM("XV_SYNC_TO_VBLANK");
402fc5a983dSmrg
403fc5a983dSmrg    return adapt;
404fc5a983dSmrg}
405fc5a983dSmrg
406fc5a983dSmrgstatic XF86VideoAdaptorPtr
407fc5a983dSmrgNVSetupOverlayVideo (ScreenPtr pScreen)
408fc5a983dSmrg{
409fc5a983dSmrg    ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum];
410fc5a983dSmrg    NVPtr       pNv       = NVPTR(pScrnInfo);
411fc5a983dSmrg    XF86VideoAdaptorPtr adapt;
412fc5a983dSmrg    NVPortPrivPtr       pPriv;
413fc5a983dSmrg
4146086d97eSmrg    if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
415fc5a983dSmrg                             sizeof(NVPortPrivRec) +
416fc5a983dSmrg                             sizeof(DevUnion))))
417fc5a983dSmrg    {
418fc5a983dSmrg        return NULL;
419fc5a983dSmrg    }
420fc5a983dSmrg
421fc5a983dSmrg    adapt->type                 = XvWindowMask | XvInputMask | XvImageMask;
422fc5a983dSmrg    adapt->flags                = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
423fc5a983dSmrg    adapt->name                 = "NV Video Overlay";
424fc5a983dSmrg    adapt->nEncodings           = 1;
425fc5a983dSmrg    adapt->pEncodings           = &DummyEncoding;
426fc5a983dSmrg    adapt->nFormats             = NUM_FORMATS_ALL;
427fc5a983dSmrg    adapt->pFormats             = NVFormats;
428fc5a983dSmrg    adapt->nPorts               = 1;
429fc5a983dSmrg    adapt->pPortPrivates        = (DevUnion*)(&adapt[1]);
430fc5a983dSmrg    pPriv                       = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
431fc5a983dSmrg    adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
432fc5a983dSmrg    adapt->pAttributes          = NVOverlayAttributes;
433fc5a983dSmrg    adapt->nAttributes          = NUM_OVERLAY_ATTRIBUTES;
434fc5a983dSmrg    adapt->pImages              = NVImages;
435fc5a983dSmrg    adapt->nImages              = NUM_IMAGES_YUV;
436fc5a983dSmrg    adapt->PutVideo             = NULL;
437fc5a983dSmrg    adapt->PutStill             = NULL;
438fc5a983dSmrg    adapt->GetVideo             = NULL;
439fc5a983dSmrg    adapt->GetStill             = NULL;
440fc5a983dSmrg    adapt->StopVideo            = NVStopOverlayVideo;
441fc5a983dSmrg    adapt->SetPortAttribute     = NVSetOverlayPortAttribute;
442fc5a983dSmrg    adapt->GetPortAttribute     = NVGetOverlayPortAttribute;
443fc5a983dSmrg    adapt->QueryBestSize        = NVQueryBestSize;
444fc5a983dSmrg    adapt->PutImage             = NVPutImage;
445fc5a983dSmrg    adapt->QueryImageAttributes = NVQueryImageAttributes;
446fc5a983dSmrg
447fc5a983dSmrg    pPriv->videoStatus		= 0;
448fc5a983dSmrg    pPriv->currentBuffer	= 0;
449fc5a983dSmrg    pPriv->grabbedByV4L		= FALSE;
450fc5a983dSmrg    pPriv->blitter              = FALSE;
451fc5a983dSmrg
452fc5a983dSmrg    NVSetPortDefaults (pScrnInfo, pPriv);
453fc5a983dSmrg
454fc5a983dSmrg    /* gotta uninit this someplace */
455fc5a983dSmrg    REGION_NULL(pScreen, &pPriv->clip);
456fc5a983dSmrg
457fc5a983dSmrg    pNv->overlayAdaptor		= adapt;
458fc5a983dSmrg
459fc5a983dSmrg    xvBrightness        = MAKE_ATOM("XV_BRIGHTNESS");
460fc5a983dSmrg    xvDoubleBuffer      = MAKE_ATOM("XV_DOUBLE_BUFFER");
461fc5a983dSmrg    xvContrast          = MAKE_ATOM("XV_CONTRAST");
462fc5a983dSmrg    xvColorKey          = MAKE_ATOM("XV_COLORKEY");
463fc5a983dSmrg    xvSaturation        = MAKE_ATOM("XV_SATURATION");
464fc5a983dSmrg    xvHue               = MAKE_ATOM("XV_HUE");
465fc5a983dSmrg    xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
466fc5a983dSmrg    xvSetDefaults       = MAKE_ATOM("XV_SET_DEFAULTS");
467fc5a983dSmrg    xvITURBT709         = MAKE_ATOM("XV_ITURBT_709");
468fc5a983dSmrg
469fc5a983dSmrg    NVResetVideo(pScrnInfo);
470fc5a983dSmrg
471fc5a983dSmrg    return adapt;
472fc5a983dSmrg}
473fc5a983dSmrg
474fc5a983dSmrgstatic void
475fc5a983dSmrgNVPutOverlayImage (
476fc5a983dSmrg    ScrnInfoPtr pScrnInfo,
477fc5a983dSmrg    int         offset,
478fc5a983dSmrg    int         id,
479fc5a983dSmrg    int         dstPitch,
480fc5a983dSmrg    BoxPtr      dstBox,
481fc5a983dSmrg    int         x1,
482fc5a983dSmrg    int         y1,
483fc5a983dSmrg    int		x2,
484fc5a983dSmrg    int		y2,
485fc5a983dSmrg    short       width,
486fc5a983dSmrg    short       height,
487fc5a983dSmrg    short       src_w,
488fc5a983dSmrg    short       src_h,
489fc5a983dSmrg    short       drw_w,
490fc5a983dSmrg    short       drw_h,
491fc5a983dSmrg    RegionPtr   clipBoxes
492fc5a983dSmrg)
493fc5a983dSmrg{
494fc5a983dSmrg    NVPtr          pNv     = NVPTR(pScrnInfo);
495fc5a983dSmrg    NVPortPrivPtr  pPriv   = GET_OVERLAY_PRIVATE(pNv);
496fc5a983dSmrg    int buffer = pPriv->currentBuffer;
497fc5a983dSmrg
498fc5a983dSmrg    /* paint the color key */
499fc5a983dSmrg    if(pPriv->autopaintColorKey &&
500fc5a983dSmrg       (pPriv->grabbedByV4L ||
501fc5a983dSmrg	!REGION_EQUAL(pScrnInfo->pScreen, &pPriv->clip, clipBoxes)))
502fc5a983dSmrg    {
503fc5a983dSmrg	/* we always paint V4L's color key */
504fc5a983dSmrg	if(!pPriv->grabbedByV4L)
505fc5a983dSmrg           REGION_COPY(pScrnInfo->pScreen, &pPriv->clip, clipBoxes);
506fc5a983dSmrg        xf86XVFillKeyHelper(pScrnInfo->pScreen, pPriv->colorKey, clipBoxes);
507fc5a983dSmrg    }
508fc5a983dSmrg
509fc5a983dSmrg    if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
510fc5a983dSmrg        dstBox->y1 <<= 1;
511fc5a983dSmrg        dstBox->y2 <<= 1;
512fc5a983dSmrg        drw_h <<= 1;
513fc5a983dSmrg    }
514fc5a983dSmrg
515fc5a983dSmrg    pNv->PMC[(0x8900/4) + buffer] = offset;
516fc5a983dSmrg    pNv->PMC[(0x8928/4) + buffer] = (height << 16) | width;
517fc5a983dSmrg    pNv->PMC[(0x8930/4) + buffer] = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
518fc5a983dSmrg    pNv->PMC[(0x8938/4) + buffer] = (src_w << 20) / drw_w;
519fc5a983dSmrg    pNv->PMC[(0x8940/4) + buffer] = (src_h << 20) / drw_h;
520fc5a983dSmrg    pNv->PMC[(0x8948/4) + buffer] = (dstBox->y1 << 16) | dstBox->x1;
521fc5a983dSmrg    pNv->PMC[(0x8950/4) + buffer] = ((dstBox->y2 - dstBox->y1) << 16) |
522fc5a983dSmrg                               	       (dstBox->x2 - dstBox->x1);
523fc5a983dSmrg
524fc5a983dSmrg    dstPitch |= 1 << 20;   /* use color key */
525fc5a983dSmrg
526fc5a983dSmrg    if(id != FOURCC_UYVY)
527fc5a983dSmrg	dstPitch |= 1 << 16;
528fc5a983dSmrg    if(pPriv->iturbt_709)
529fc5a983dSmrg        dstPitch |= 1 << 24;
530fc5a983dSmrg
531fc5a983dSmrg    pNv->PMC[(0x8958/4) + buffer] = dstPitch;
532fc5a983dSmrg    pNv->PMC[0x00008704/4] = 0;
533fc5a983dSmrg    pNv->PMC[0x8700/4] = 1 << (buffer << 2);
534fc5a983dSmrg
535fc5a983dSmrg    pPriv->videoStatus = CLIENT_VIDEO_ON;
536fc5a983dSmrg}
537fc5a983dSmrg
538fc5a983dSmrg
539fc5a983dSmrg
540fc5a983dSmrgstatic void
541fc5a983dSmrgNVPutBlitImage (
542fc5a983dSmrg    ScrnInfoPtr pScrnInfo,
543fc5a983dSmrg    int         offset,
544fc5a983dSmrg    int         id,
545fc5a983dSmrg    int         dstPitch,
546fc5a983dSmrg    BoxPtr      dstBox,
547fc5a983dSmrg    int         x1,
548fc5a983dSmrg    int         y1,
549fc5a983dSmrg    int         x2,
550fc5a983dSmrg    int         y2,
551fc5a983dSmrg    short       width,
552fc5a983dSmrg    short       height,
553fc5a983dSmrg    short       src_w,
554fc5a983dSmrg    short       src_h,
555fc5a983dSmrg    short       drw_w,
556fc5a983dSmrg    short       drw_h,
557fc5a983dSmrg    RegionPtr   clipBoxes
558fc5a983dSmrg)
559fc5a983dSmrg{
560fc5a983dSmrg    NVPtr          pNv     = NVPTR(pScrnInfo);
561fc5a983dSmrg    NVPortPrivPtr  pPriv   = GET_BLIT_PRIVATE(pNv);
562fc5a983dSmrg    BoxPtr         pbox    = REGION_RECTS(clipBoxes);
563fc5a983dSmrg    int            nbox    = REGION_NUM_RECTS(clipBoxes);
564fc5a983dSmrg    CARD32         dsdx, dtdy, size, point, srcpoint, format;
565fc5a983dSmrg
566fc5a983dSmrg    dsdx = (src_w << 20) / drw_w;
567fc5a983dSmrg    dtdy = (src_h << 20) / drw_h;
568fc5a983dSmrg
569fc5a983dSmrg    size = ((dstBox->y2 - dstBox->y1) << 16) | (dstBox->x2 - dstBox->x1);
570fc5a983dSmrg    point = (dstBox->y1 << 16) | dstBox->x1;
571fc5a983dSmrg
572fc5a983dSmrg    dstPitch |= (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER << 16) |
573fc5a983dSmrg                (STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR << 24);
574fc5a983dSmrg
575fc5a983dSmrg    srcpoint = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
576fc5a983dSmrg
577fc5a983dSmrg    switch(id) {
578fc5a983dSmrg    case FOURCC_RGB:
579fc5a983dSmrg        format = STRETCH_BLIT_FORMAT_X8R8G8B8;
580fc5a983dSmrg        break;
581fc5a983dSmrg    case FOURCC_UYVY:
582fc5a983dSmrg        format = STRETCH_BLIT_FORMAT_UYVY;
583fc5a983dSmrg        break;
584fc5a983dSmrg    default:
585fc5a983dSmrg        format = STRETCH_BLIT_FORMAT_YUYV;
586fc5a983dSmrg        break;
587fc5a983dSmrg    }
588fc5a983dSmrg
589fc5a983dSmrg    if(pNv->CurrentLayout.depth == 15) {
590fc5a983dSmrg        NVDmaStart(pNv, SURFACE_FORMAT, 1);
591fc5a983dSmrg        NVDmaNext (pNv, SURFACE_FORMAT_DEPTH15);
592fc5a983dSmrg    }
593fc5a983dSmrg
594fc5a983dSmrg    if(pPriv->SyncToVBlank) {
595fc5a983dSmrg       NVDmaKickoff(pNv);
596fc5a983dSmrg       NVWaitVSync(pNv);
597fc5a983dSmrg    }
598fc5a983dSmrg
599fc5a983dSmrg    if(pNv->BlendingPossible) {
600fc5a983dSmrg       NVDmaStart(pNv, STRETCH_BLIT_FORMAT, 2);
601fc5a983dSmrg       NVDmaNext (pNv, format);
602fc5a983dSmrg       NVDmaNext (pNv, STRETCH_BLIT_OPERATION_COPY);
603fc5a983dSmrg    } else {
604fc5a983dSmrg       NVDmaStart(pNv, STRETCH_BLIT_FORMAT, 1);
605fc5a983dSmrg       NVDmaNext (pNv, format);
606fc5a983dSmrg    }
607fc5a983dSmrg
608fc5a983dSmrg    while(nbox--) {
609fc5a983dSmrg       NVDmaStart(pNv, RECT_SOLID_COLOR, 1);
610fc5a983dSmrg       NVDmaNext (pNv, 0);
611fc5a983dSmrg
612fc5a983dSmrg       NVDmaStart(pNv, STRETCH_BLIT_CLIP_POINT, 6);
613fc5a983dSmrg       NVDmaNext (pNv, (pbox->y1 << 16) | pbox->x1);
614fc5a983dSmrg       NVDmaNext (pNv, ((pbox->y2 - pbox->y1) << 16) | (pbox->x2 - pbox->x1));
615fc5a983dSmrg       NVDmaNext (pNv, point);
616fc5a983dSmrg       NVDmaNext (pNv, size);
617fc5a983dSmrg       NVDmaNext (pNv, dsdx);
618fc5a983dSmrg       NVDmaNext (pNv, dtdy);
619fc5a983dSmrg
620fc5a983dSmrg       NVDmaStart(pNv, STRETCH_BLIT_SRC_SIZE, 4);
621fc5a983dSmrg       NVDmaNext (pNv, (height << 16) | width);
622fc5a983dSmrg       NVDmaNext (pNv, dstPitch);
623fc5a983dSmrg       NVDmaNext (pNv, offset);
624fc5a983dSmrg       NVDmaNext (pNv, srcpoint);
625fc5a983dSmrg       pbox++;
626fc5a983dSmrg    }
627fc5a983dSmrg
628fc5a983dSmrg    if(pNv->CurrentLayout.depth == 15) {
629fc5a983dSmrg        NVDmaStart(pNv, SURFACE_FORMAT, 1);
630fc5a983dSmrg        NVDmaNext (pNv, SURFACE_FORMAT_DEPTH16);
631fc5a983dSmrg    }
632fc5a983dSmrg
633fc5a983dSmrg    NVDmaKickoff(pNv);
634fc5a983dSmrg    SET_SYNC_FLAG(pNv->AccelInfoRec);
635fc5a983dSmrg
636fc5a983dSmrg    pPriv->videoStatus = FREE_TIMER;
637fc5a983dSmrg    pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
638fc5a983dSmrg    pNv->VideoTimerCallback = NVVideoTimerCallback;
639fc5a983dSmrg}
640fc5a983dSmrg
641fc5a983dSmrg/*
642fc5a983dSmrg * StopVideo
643fc5a983dSmrg */
644fc5a983dSmrgstatic void NVStopOverlayVideo
645fc5a983dSmrg(
646fc5a983dSmrg    ScrnInfoPtr pScrnInfo,
647fc5a983dSmrg    pointer     data,
648fc5a983dSmrg    Bool        Exit
649fc5a983dSmrg)
650fc5a983dSmrg{
651fc5a983dSmrg    NVPtr pNv = NVPTR(pScrnInfo);
652fc5a983dSmrg    NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
653fc5a983dSmrg
654fc5a983dSmrg    if(pPriv->grabbedByV4L) return;
655fc5a983dSmrg
656fc5a983dSmrg    REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
657fc5a983dSmrg
658fc5a983dSmrg    if(Exit) {
659fc5a983dSmrg	if(pPriv->videoStatus & CLIENT_VIDEO_ON)
660fc5a983dSmrg            NVStopOverlay(pScrnInfo);
661fc5a983dSmrg	NVFreeOverlayMemory(pScrnInfo);
662fc5a983dSmrg	pPriv->videoStatus = 0;
663fc5a983dSmrg    } else {
664fc5a983dSmrg	if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
665fc5a983dSmrg	    pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
666fc5a983dSmrg	    pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
667fc5a983dSmrg	    pNv->VideoTimerCallback = NVVideoTimerCallback;
668fc5a983dSmrg	}
669fc5a983dSmrg    }
670fc5a983dSmrg}
671fc5a983dSmrg
672fc5a983dSmrgstatic void NVStopBlitVideo
673fc5a983dSmrg(
674fc5a983dSmrg    ScrnInfoPtr pScrnInfo,
675fc5a983dSmrg    pointer     data,
676fc5a983dSmrg    Bool        Exit
677fc5a983dSmrg)
678fc5a983dSmrg{
679fc5a983dSmrg}
680fc5a983dSmrg
681fc5a983dSmrgstatic int NVSetOverlayPortAttribute
682fc5a983dSmrg(
683fc5a983dSmrg    ScrnInfoPtr pScrnInfo,
684fc5a983dSmrg    Atom        attribute,
685fc5a983dSmrg    INT32       value,
686fc5a983dSmrg    pointer     data
687fc5a983dSmrg)
688fc5a983dSmrg{
689fc5a983dSmrg    NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
690fc5a983dSmrg
691fc5a983dSmrg    if (attribute == xvBrightness)
692fc5a983dSmrg    {
693fc5a983dSmrg        if ((value < -512) || (value > 512))
694fc5a983dSmrg            return BadValue;
695fc5a983dSmrg        pPriv->brightness = value;
696fc5a983dSmrg    }
697fc5a983dSmrg    else if (attribute == xvDoubleBuffer)
698fc5a983dSmrg    {
699fc5a983dSmrg        if ((value < 0) || (value > 1))
700fc5a983dSmrg            return BadValue;
701fc5a983dSmrg        pPriv->doubleBuffer = value;
702fc5a983dSmrg    }
703fc5a983dSmrg    else if (attribute == xvContrast)
704fc5a983dSmrg    {
705fc5a983dSmrg        if ((value < 0) || (value > 8191))
706fc5a983dSmrg            return BadValue;
707fc5a983dSmrg        pPriv->contrast = value;
708fc5a983dSmrg    }
709fc5a983dSmrg    else if (attribute == xvHue)
710fc5a983dSmrg    {
711fc5a983dSmrg        value %= 360;
712fc5a983dSmrg        if (value < 0)
713fc5a983dSmrg            value += 360;
714fc5a983dSmrg        pPriv->hue = value;
715fc5a983dSmrg    }
716fc5a983dSmrg    else if (attribute == xvSaturation)
717fc5a983dSmrg    {
718fc5a983dSmrg        if ((value < 0) || (value > 8191))
719fc5a983dSmrg            return BadValue;
720fc5a983dSmrg        pPriv->saturation = value;
721fc5a983dSmrg    }
722fc5a983dSmrg    else if (attribute == xvColorKey)
723fc5a983dSmrg    {
724fc5a983dSmrg        pPriv->colorKey = value;
725fc5a983dSmrg        REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
726fc5a983dSmrg    }
727fc5a983dSmrg    else if (attribute == xvAutopaintColorKey)
728fc5a983dSmrg    {
729fc5a983dSmrg        if ((value < 0) || (value > 1))
730fc5a983dSmrg            return BadValue;
731fc5a983dSmrg        pPriv->autopaintColorKey = value;
732fc5a983dSmrg    }
733fc5a983dSmrg    else if (attribute == xvITURBT709)
734fc5a983dSmrg    {
735fc5a983dSmrg        if ((value < 0) || (value > 1))
736fc5a983dSmrg            return BadValue;
737fc5a983dSmrg        pPriv->iturbt_709 = value;
738fc5a983dSmrg    }
739fc5a983dSmrg    else if (attribute == xvSetDefaults)
740fc5a983dSmrg    {
741fc5a983dSmrg        NVSetPortDefaults(pScrnInfo, pPriv);
742fc5a983dSmrg    }
743fc5a983dSmrg    else
744fc5a983dSmrg        return BadMatch;
745fc5a983dSmrg
746fc5a983dSmrg    NVResetVideo(pScrnInfo);
747fc5a983dSmrg    return Success;
748fc5a983dSmrg}
749fc5a983dSmrg
750fc5a983dSmrg
751fc5a983dSmrgstatic int NVGetOverlayPortAttribute
752fc5a983dSmrg(
753fc5a983dSmrg    ScrnInfoPtr  pScrnInfo,
754fc5a983dSmrg    Atom         attribute,
755fc5a983dSmrg    INT32       *value,
756fc5a983dSmrg    pointer      data
757fc5a983dSmrg)
758fc5a983dSmrg{
759fc5a983dSmrg    NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
760fc5a983dSmrg
761fc5a983dSmrg    if (attribute == xvBrightness)
762fc5a983dSmrg        *value = pPriv->brightness;
763fc5a983dSmrg    else if (attribute == xvDoubleBuffer)
764fc5a983dSmrg        *value = (pPriv->doubleBuffer) ? 1 : 0;
765fc5a983dSmrg    else if (attribute == xvContrast)
766fc5a983dSmrg        *value = pPriv->contrast;
767fc5a983dSmrg    else if (attribute == xvSaturation)
768fc5a983dSmrg        *value = pPriv->saturation;
769fc5a983dSmrg    else if (attribute == xvHue)
770fc5a983dSmrg        *value = pPriv->hue;
771fc5a983dSmrg    else if (attribute == xvColorKey)
772fc5a983dSmrg        *value = pPriv->colorKey;
773fc5a983dSmrg    else if (attribute == xvAutopaintColorKey)
774fc5a983dSmrg        *value = (pPriv->autopaintColorKey) ? 1 : 0;
775fc5a983dSmrg    else if (attribute == xvITURBT709)
776fc5a983dSmrg        *value = (pPriv->iturbt_709) ? 1 : 0;
777fc5a983dSmrg    else
778fc5a983dSmrg        return BadMatch;
779fc5a983dSmrg
780fc5a983dSmrg    return Success;
781fc5a983dSmrg}
782fc5a983dSmrg
783fc5a983dSmrgstatic int NVSetBlitPortAttribute
784fc5a983dSmrg(
785fc5a983dSmrg    ScrnInfoPtr pScrnInfo,
786fc5a983dSmrg    Atom        attribute,
787fc5a983dSmrg    INT32       value,
788fc5a983dSmrg    pointer     data
789fc5a983dSmrg)
790fc5a983dSmrg{
791fc5a983dSmrg    NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
792fc5a983dSmrg    NVPtr pNv = NVPTR(pScrnInfo);
793fc5a983dSmrg
794fc5a983dSmrg    if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
795fc5a983dSmrg        if ((value < 0) || (value > 1))
796fc5a983dSmrg            return BadValue;
797fc5a983dSmrg        pPriv->SyncToVBlank = value;
798fc5a983dSmrg    } else
799fc5a983dSmrg    if (attribute == xvSetDefaults) {
800fc5a983dSmrg        pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
801fc5a983dSmrg    } else
802fc5a983dSmrg       return BadMatch;
803fc5a983dSmrg
804fc5a983dSmrg    return Success;
805fc5a983dSmrg}
806fc5a983dSmrg
807fc5a983dSmrgstatic int NVGetBlitPortAttribute
808fc5a983dSmrg(
809fc5a983dSmrg    ScrnInfoPtr  pScrnInfo,
810fc5a983dSmrg    Atom         attribute,
811fc5a983dSmrg    INT32       *value,
812fc5a983dSmrg    pointer      data
813fc5a983dSmrg)
814fc5a983dSmrg{
815fc5a983dSmrg    NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
816fc5a983dSmrg
817fc5a983dSmrg    if(attribute == xvSyncToVBlank)
818fc5a983dSmrg       *value = (pPriv->SyncToVBlank) ? 1 : 0;
819fc5a983dSmrg    else
820fc5a983dSmrg       return BadMatch;
821fc5a983dSmrg
822fc5a983dSmrg    return Success;
823fc5a983dSmrg}
824fc5a983dSmrg
825fc5a983dSmrg
826fc5a983dSmrg/*
827fc5a983dSmrg * QueryBestSize
828fc5a983dSmrg */
829fc5a983dSmrgstatic void NVQueryBestSize
830fc5a983dSmrg(
831fc5a983dSmrg    ScrnInfoPtr   pScrnInfo,
832fc5a983dSmrg    Bool          motion,
833fc5a983dSmrg    short         vid_w,
834fc5a983dSmrg    short         vid_h,
835fc5a983dSmrg    short         drw_w,
836fc5a983dSmrg    short         drw_h,
837fc5a983dSmrg    unsigned int *p_w,
838fc5a983dSmrg    unsigned int *p_h,
839fc5a983dSmrg    pointer       data
840fc5a983dSmrg)
841fc5a983dSmrg{
842fc5a983dSmrg    if(vid_w > (drw_w << 3))
843fc5a983dSmrg	drw_w = vid_w >> 3;
844fc5a983dSmrg    if(vid_h > (drw_h << 3))
845fc5a983dSmrg	drw_h = vid_h >> 3;
846fc5a983dSmrg
847fc5a983dSmrg    *p_w = drw_w;
848fc5a983dSmrg    *p_h = drw_h;
849fc5a983dSmrg}
850fc5a983dSmrg
851fc5a983dSmrgstatic void NVCopyData420
852fc5a983dSmrg(
853fc5a983dSmrg    unsigned char *src1,
854fc5a983dSmrg    unsigned char *src2,
855fc5a983dSmrg    unsigned char *src3,
856fc5a983dSmrg    unsigned char *dst1,
857fc5a983dSmrg    int            srcPitch,
858fc5a983dSmrg    int            srcPitch2,
859fc5a983dSmrg    int            dstPitch,
860fc5a983dSmrg    int            h,
861fc5a983dSmrg    int            w
862fc5a983dSmrg)
863fc5a983dSmrg{
864fc5a983dSmrg   CARD32 *dst;
865fc5a983dSmrg   CARD8 *s1, *s2, *s3;
866fc5a983dSmrg   int i, j;
867fc5a983dSmrg
868fc5a983dSmrg   w >>= 1;
869fc5a983dSmrg
870fc5a983dSmrg   for(j = 0; j < h; j++) {
871fc5a983dSmrg        dst = (CARD32*)dst1;
872fc5a983dSmrg        s1 = src1;  s2 = src2;  s3 = src3;
873fc5a983dSmrg        i = w;
874fc5a983dSmrg        while(i > 4) {
875fc5a983dSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
876fc5a983dSmrg           dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
877fc5a983dSmrg           dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1];
878fc5a983dSmrg           dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2];
879fc5a983dSmrg           dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3];
880fc5a983dSmrg#else
881fc5a983dSmrg           dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
882fc5a983dSmrg           dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
883fc5a983dSmrg           dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
884fc5a983dSmrg           dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
885fc5a983dSmrg#endif
886fc5a983dSmrg           dst += 4; s2 += 4; s3 += 4; s1 += 8;
887fc5a983dSmrg           i -= 4;
888fc5a983dSmrg        }
889fc5a983dSmrg
890fc5a983dSmrg        while(i--) {
891fc5a983dSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
892fc5a983dSmrg           dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
893fc5a983dSmrg#else
894fc5a983dSmrg           dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
895fc5a983dSmrg#endif
896fc5a983dSmrg           dst++; s2++; s3++;
897fc5a983dSmrg           s1 += 2;
898fc5a983dSmrg        }
899fc5a983dSmrg
900fc5a983dSmrg        dst1 += dstPitch;
901fc5a983dSmrg        src1 += srcPitch;
902fc5a983dSmrg        if(j & 1) {
903fc5a983dSmrg            src2 += srcPitch2;
904fc5a983dSmrg            src3 += srcPitch2;
905fc5a983dSmrg        }
906fc5a983dSmrg   }
907fc5a983dSmrg}
908fc5a983dSmrg
909fc5a983dSmrg
910fc5a983dSmrgstatic void NVMoveDWORDS(
911fc5a983dSmrg   CARD32* dest,
912fc5a983dSmrg   CARD32* src,
913fc5a983dSmrg   int dwords )
914fc5a983dSmrg{
915fc5a983dSmrg     while(dwords & ~0x03) {
916fc5a983dSmrg        *dest = *src;
917fc5a983dSmrg        *(dest + 1) = *(src + 1);
918fc5a983dSmrg        *(dest + 2) = *(src + 2);
919fc5a983dSmrg        *(dest + 3) = *(src + 3);
920fc5a983dSmrg        src += 4;
921fc5a983dSmrg        dest += 4;
922fc5a983dSmrg        dwords -= 4;
923fc5a983dSmrg     }
924fc5a983dSmrg     if(!dwords) return;
925fc5a983dSmrg     *dest = *src;
926fc5a983dSmrg     if(dwords == 1) return;
927fc5a983dSmrg     *(dest + 1) = *(src + 1);
928fc5a983dSmrg     if(dwords == 2) return;
929fc5a983dSmrg     *(dest + 2) = *(src + 2);
930fc5a983dSmrg}
931fc5a983dSmrg
932fc5a983dSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
933fc5a983dSmrgstatic void NVMoveDWORDSSwapped(
934fc5a983dSmrg   CARD32* dest,
935fc5a983dSmrg   CARD8* src,
936fc5a983dSmrg   int dwords )
937fc5a983dSmrg{
938fc5a983dSmrg     while(dwords--) {
939fc5a983dSmrg        *dest++ = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
940fc5a983dSmrg        src += 4;
941fc5a983dSmrg     }
942fc5a983dSmrg}
943fc5a983dSmrg#endif
944fc5a983dSmrg
945fc5a983dSmrgstatic void NVCopyData422
946fc5a983dSmrg(
947fc5a983dSmrg  unsigned char *src,
948fc5a983dSmrg  unsigned char *dst,
949fc5a983dSmrg  int            srcPitch,
950fc5a983dSmrg  int            dstPitch,
951fc5a983dSmrg  int            h,
952fc5a983dSmrg  int            w
953fc5a983dSmrg)
954fc5a983dSmrg{
955fc5a983dSmrg    w >>= 1;  /* pixels to DWORDS */
956fc5a983dSmrg    while(h--) {
957fc5a983dSmrg        NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w);
958fc5a983dSmrg        src += srcPitch;
959fc5a983dSmrg        dst += dstPitch;
960fc5a983dSmrg    }
961fc5a983dSmrg}
962fc5a983dSmrg
963fc5a983dSmrgstatic void NVCopyDataRGB
964fc5a983dSmrg(
965fc5a983dSmrg  unsigned char *src,
966fc5a983dSmrg  unsigned char *dst,
967fc5a983dSmrg  int            srcPitch,
968fc5a983dSmrg  int            dstPitch,
969fc5a983dSmrg  int            h,
970fc5a983dSmrg  int            w
971fc5a983dSmrg)
972fc5a983dSmrg{
973fc5a983dSmrg    while(h--) {
974fc5a983dSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
975fc5a983dSmrg        NVMoveDWORDSSwapped((CARD32*)dst, (CARD8*)src, w);
976fc5a983dSmrg#else
977fc5a983dSmrg        NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w);
978fc5a983dSmrg#endif
979fc5a983dSmrg        src += srcPitch;
980fc5a983dSmrg        dst += dstPitch;
981fc5a983dSmrg    }
982fc5a983dSmrg}
983fc5a983dSmrg
984fc5a983dSmrg
985fc5a983dSmrg/*
986fc5a983dSmrg * PutImage
987fc5a983dSmrg */
988fc5a983dSmrgstatic int NVPutImage
989fc5a983dSmrg(
990fc5a983dSmrg    ScrnInfoPtr  pScrnInfo,
991fc5a983dSmrg    short        src_x,
992fc5a983dSmrg    short        src_y,
993fc5a983dSmrg    short        drw_x,
994fc5a983dSmrg    short        drw_y,
995fc5a983dSmrg    short        src_w,
996fc5a983dSmrg    short        src_h,
997fc5a983dSmrg    short        drw_w,
998fc5a983dSmrg    short        drw_h,
999fc5a983dSmrg    int          id,
1000fc5a983dSmrg    unsigned char *buf,
1001fc5a983dSmrg    short        width,
1002fc5a983dSmrg    short        height,
1003fc5a983dSmrg    Bool         Sync,
1004fc5a983dSmrg    RegionPtr    clipBoxes,
1005fc5a983dSmrg    pointer      data,
1006fc5a983dSmrg    DrawablePtr  pDraw
1007fc5a983dSmrg)
1008fc5a983dSmrg{
1009fc5a983dSmrg    NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1010fc5a983dSmrg    NVPtr pNv = NVPTR(pScrnInfo);
1011fc5a983dSmrg    INT32 xa, xb, ya, yb;
1012fc5a983dSmrg    unsigned char *dst_start;
1013fc5a983dSmrg    int newSize, offset, s2offset, s3offset;
1014fc5a983dSmrg    int srcPitch, srcPitch2, dstPitch;
1015fc5a983dSmrg    int top, left, right, bottom, npixels, nlines, bpp;
1016fc5a983dSmrg    Bool skip = FALSE;
1017fc5a983dSmrg    BoxRec dstBox;
1018fc5a983dSmrg    CARD32 tmp;
1019fc5a983dSmrg
1020fc5a983dSmrg   /*
1021fc5a983dSmrg    * s2offset, s3offset - byte offsets into U and V plane of the
1022fc5a983dSmrg    *                      source where copying starts.  Y plane is
1023fc5a983dSmrg    *                      done by editing "buf".
1024fc5a983dSmrg    *
1025fc5a983dSmrg    * offset - byte offset to the first line of the destination.
1026fc5a983dSmrg    *
1027fc5a983dSmrg    * dst_start - byte address to the first displayed pel.
1028fc5a983dSmrg    *
1029fc5a983dSmrg    */
1030fc5a983dSmrg
1031fc5a983dSmrg    if(pPriv->grabbedByV4L) return Success;
1032fc5a983dSmrg
1033fc5a983dSmrg    /* make the compiler happy */
1034fc5a983dSmrg    s2offset = s3offset = srcPitch2 = 0;
1035fc5a983dSmrg
1036fc5a983dSmrg    if(!pPriv->blitter) {
1037fc5a983dSmrg       if(src_w > (drw_w << 3))
1038fc5a983dSmrg          drw_w = src_w >> 3;
1039fc5a983dSmrg       if(src_h > (drw_h << 3))
1040fc5a983dSmrg          drw_h = src_h >> 3;
1041fc5a983dSmrg    }
1042fc5a983dSmrg
1043fc5a983dSmrg    /* Clip */
1044fc5a983dSmrg    xa = src_x;
1045fc5a983dSmrg    xb = src_x + src_w;
1046fc5a983dSmrg    ya = src_y;
1047fc5a983dSmrg    yb = src_y + src_h;
1048fc5a983dSmrg
1049fc5a983dSmrg    dstBox.x1 = drw_x;
1050fc5a983dSmrg    dstBox.x2 = drw_x + drw_w;
1051fc5a983dSmrg    dstBox.y1 = drw_y;
1052fc5a983dSmrg    dstBox.y2 = drw_y + drw_h;
1053fc5a983dSmrg
1054fc5a983dSmrg    if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1055fc5a983dSmrg                              width, height))
1056fc5a983dSmrg    	return Success;
1057fc5a983dSmrg
1058fc5a983dSmrg    if(!pPriv->blitter) {
1059fc5a983dSmrg        dstBox.x1 -= pScrnInfo->frameX0;
1060fc5a983dSmrg        dstBox.x2 -= pScrnInfo->frameX0;
1061fc5a983dSmrg        dstBox.y1 -= pScrnInfo->frameY0;
1062fc5a983dSmrg        dstBox.y2 -= pScrnInfo->frameY0;
1063fc5a983dSmrg    }
1064fc5a983dSmrg
1065fc5a983dSmrg    bpp = pScrnInfo->bitsPerPixel >> 3;
1066fc5a983dSmrg
1067fc5a983dSmrg    switch(id) {
1068fc5a983dSmrg    case FOURCC_YV12:
1069fc5a983dSmrg    case FOURCC_I420:
1070fc5a983dSmrg        srcPitch = (width + 3) & ~3;	/* of luma */
1071fc5a983dSmrg        s2offset = srcPitch * height;
1072fc5a983dSmrg        srcPitch2 = ((width >> 1) + 3) & ~3;
1073fc5a983dSmrg        s3offset = (srcPitch2 * (height >> 1)) + s2offset;
1074fc5a983dSmrg        dstPitch = ((width << 1) + 63) & ~63;
1075fc5a983dSmrg        break;
1076fc5a983dSmrg    case FOURCC_UYVY:
1077fc5a983dSmrg    case FOURCC_YUY2:
1078fc5a983dSmrg        srcPitch = width << 1;
1079fc5a983dSmrg        dstPitch = ((width << 1) + 63) & ~63;
1080fc5a983dSmrg        break;
1081fc5a983dSmrg    case FOURCC_RGB:
1082fc5a983dSmrg        srcPitch = width << 2;
1083fc5a983dSmrg        dstPitch = ((width << 2) + 63) & ~63;
1084fc5a983dSmrg        break;
1085fc5a983dSmrg    default:
1086fc5a983dSmrg        return BadImplementation;
1087fc5a983dSmrg    }
1088fc5a983dSmrg
1089fc5a983dSmrg    newSize = height * dstPitch / bpp;
1090fc5a983dSmrg
1091fc5a983dSmrg    if(pPriv->doubleBuffer)
1092fc5a983dSmrg	newSize <<= 1;
1093fc5a983dSmrg
1094fc5a983dSmrg    pPriv->linear = NVAllocateOverlayMemory(pScrnInfo,
1095fc5a983dSmrg					    pPriv->linear,
1096fc5a983dSmrg					    newSize);
1097fc5a983dSmrg
1098fc5a983dSmrg    if(!pPriv->linear) return BadAlloc;
1099fc5a983dSmrg
1100fc5a983dSmrg    offset = pPriv->linear->offset * bpp;
1101fc5a983dSmrg
1102fc5a983dSmrg    if(pPriv->doubleBuffer) {
1103fc5a983dSmrg        int mask = 1 << (pPriv->currentBuffer << 2);
1104fc5a983dSmrg
1105fc5a983dSmrg#if 0
1106fc5a983dSmrg        /* burn the CPU until the next buffer is available */
1107fc5a983dSmrg        while(pNv->PMC[0x00008700/4] & mask);
1108fc5a983dSmrg#else
1109fc5a983dSmrg        /* overwrite the newest buffer if there's not one free */
1110fc5a983dSmrg        if(pNv->PMC[0x00008700/4] & mask) {
1111fc5a983dSmrg           if(!pPriv->currentBuffer)
1112fc5a983dSmrg              offset += (newSize * bpp) >> 1;
1113fc5a983dSmrg           skip = TRUE;
1114fc5a983dSmrg        } else
1115fc5a983dSmrg#endif
1116fc5a983dSmrg        if(pPriv->currentBuffer)
1117fc5a983dSmrg            offset += (newSize * bpp) >> 1;
1118fc5a983dSmrg    }
1119fc5a983dSmrg
1120fc5a983dSmrg    dst_start = pNv->FbStart + offset;
1121fc5a983dSmrg
1122fc5a983dSmrg    /* We need to enlarge the copied rectangle by a pixel so the HW
1123fc5a983dSmrg       filtering doesn't pick up junk laying outside of the source */
1124fc5a983dSmrg
1125fc5a983dSmrg    left = (xa - 0x00010000) >> 16;
1126fc5a983dSmrg    if(left < 0) left = 0;
1127fc5a983dSmrg    top = (ya - 0x00010000) >> 16;
1128fc5a983dSmrg    if(top < 0) top = 0;
1129fc5a983dSmrg    right = (xb + 0x0001ffff) >> 16;
1130fc5a983dSmrg    if(right > width) right = width;
1131fc5a983dSmrg    bottom = (yb + 0x0001ffff) >> 16;
1132fc5a983dSmrg    if(bottom > height) bottom = height;
1133fc5a983dSmrg
1134fc5a983dSmrg    if(pPriv->blitter) NVSync(pScrnInfo);
1135fc5a983dSmrg
1136fc5a983dSmrg    switch(id) {
1137fc5a983dSmrg    case FOURCC_YV12:
1138fc5a983dSmrg    case FOURCC_I420:
1139fc5a983dSmrg        left &= ~1;
1140fc5a983dSmrg        npixels = ((right + 1) & ~1) - left;
1141fc5a983dSmrg        top &= ~1;
1142fc5a983dSmrg        nlines = ((bottom + 1) & ~1) - top;
1143fc5a983dSmrg
1144fc5a983dSmrg        dst_start += (left << 1) + (top * dstPitch);
1145fc5a983dSmrg        tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1146fc5a983dSmrg        s2offset += tmp;
1147fc5a983dSmrg        s3offset += tmp;
1148fc5a983dSmrg        if(id == FOURCC_I420) {
1149fc5a983dSmrg           tmp = s2offset;
1150fc5a983dSmrg           s2offset = s3offset;
1151fc5a983dSmrg           s3offset = tmp;
1152fc5a983dSmrg        }
1153fc5a983dSmrg        NVCopyData420(buf + (top * srcPitch) + left,
1154fc5a983dSmrg				buf + s2offset, buf + s3offset,
1155fc5a983dSmrg				dst_start, srcPitch, srcPitch2,
1156fc5a983dSmrg				dstPitch, nlines, npixels);
1157fc5a983dSmrg        break;
1158fc5a983dSmrg    case FOURCC_UYVY:
1159fc5a983dSmrg    case FOURCC_YUY2:
1160fc5a983dSmrg        left &= ~1;
1161fc5a983dSmrg        npixels = ((right + 1) & ~1) - left;
1162fc5a983dSmrg        nlines = bottom - top;
1163fc5a983dSmrg
1164fc5a983dSmrg        left <<= 1;
1165fc5a983dSmrg        buf += (top * srcPitch) + left;
1166fc5a983dSmrg        dst_start += left + (top * dstPitch);
1167fc5a983dSmrg
1168fc5a983dSmrg        NVCopyData422(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
1169fc5a983dSmrg        break;
1170fc5a983dSmrg    case FOURCC_RGB:
1171fc5a983dSmrg        npixels = right - left;
1172fc5a983dSmrg        nlines = bottom - top;
1173fc5a983dSmrg
1174fc5a983dSmrg        left <<= 2;
1175fc5a983dSmrg        buf += (top * srcPitch) + left;
1176fc5a983dSmrg        dst_start += left + (top * dstPitch);
1177fc5a983dSmrg
1178fc5a983dSmrg        NVCopyDataRGB(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
1179fc5a983dSmrg        break;
1180fc5a983dSmrg    default:
1181fc5a983dSmrg        return BadImplementation;
1182fc5a983dSmrg    }
1183fc5a983dSmrg
1184fc5a983dSmrg    if(!skip) {
1185fc5a983dSmrg       if(pPriv->blitter) {
1186fc5a983dSmrg            NVPutBlitImage(pScrnInfo, offset, id, dstPitch, &dstBox,
1187fc5a983dSmrg                           xa, ya, xb, yb,
1188fc5a983dSmrg                           width, height, src_w, src_h, drw_w, drw_h,
1189fc5a983dSmrg                           clipBoxes);
1190fc5a983dSmrg       } else {
1191fc5a983dSmrg            NVPutOverlayImage(pScrnInfo, offset, id, dstPitch, &dstBox,
1192fc5a983dSmrg                             xa, ya, xb, yb,
1193fc5a983dSmrg                             width, height, src_w, src_h, drw_w, drw_h,
1194fc5a983dSmrg                             clipBoxes);
1195fc5a983dSmrg            pPriv->currentBuffer ^= 1;
1196fc5a983dSmrg       }
1197fc5a983dSmrg    }
1198fc5a983dSmrg
1199fc5a983dSmrg    return Success;
1200fc5a983dSmrg}
1201fc5a983dSmrg/*
1202fc5a983dSmrg * QueryImageAttributes
1203fc5a983dSmrg */
1204fc5a983dSmrgstatic int NVQueryImageAttributes
1205fc5a983dSmrg(
1206fc5a983dSmrg    ScrnInfoPtr pScrnInfo,
1207fc5a983dSmrg    int         id,
1208fc5a983dSmrg    unsigned short *w,
1209fc5a983dSmrg    unsigned short *h,
1210fc5a983dSmrg    int         *pitches,
1211fc5a983dSmrg    int         *offsets
1212fc5a983dSmrg)
1213fc5a983dSmrg{
1214fc5a983dSmrg    int size, tmp;
1215fc5a983dSmrg
1216fc5a983dSmrg    if(*w > 2046)
1217fc5a983dSmrg        *w = 2046;
1218fc5a983dSmrg    if(*h > 2046)
1219fc5a983dSmrg        *h = 2046;
1220fc5a983dSmrg
1221fc5a983dSmrg    *w = (*w + 1) & ~1;
1222fc5a983dSmrg    if (offsets)
1223fc5a983dSmrg        offsets[0] = 0;
1224fc5a983dSmrg
1225fc5a983dSmrg    switch (id)
1226fc5a983dSmrg    {
1227fc5a983dSmrg        case FOURCC_YV12:
1228fc5a983dSmrg        case FOURCC_I420:
1229fc5a983dSmrg            *h = (*h + 1) & ~1;
1230fc5a983dSmrg            size = (*w + 3) & ~3;
1231fc5a983dSmrg            if (pitches)
1232fc5a983dSmrg                pitches[0] = size;
1233fc5a983dSmrg            size *= *h;
1234fc5a983dSmrg            if (offsets)
1235fc5a983dSmrg                offsets[1] = size;
1236fc5a983dSmrg            tmp = ((*w >> 1) + 3) & ~3;
1237fc5a983dSmrg            if (pitches)
1238fc5a983dSmrg                pitches[1] = pitches[2] = tmp;
1239fc5a983dSmrg            tmp *= (*h >> 1);
1240fc5a983dSmrg            size += tmp;
1241fc5a983dSmrg            if (offsets)
1242fc5a983dSmrg                offsets[2] = size;
1243fc5a983dSmrg            size += tmp;
1244fc5a983dSmrg            break;
1245fc5a983dSmrg        case FOURCC_UYVY:
1246fc5a983dSmrg        case FOURCC_YUY2:
1247fc5a983dSmrg            size = *w << 1;
1248fc5a983dSmrg            if (pitches)
1249fc5a983dSmrg                pitches[0] = size;
1250fc5a983dSmrg            size *= *h;
1251fc5a983dSmrg            break;
1252fc5a983dSmrg        case FOURCC_RGB:
1253fc5a983dSmrg            size = *w << 2;
1254fc5a983dSmrg            if(pitches)
1255fc5a983dSmrg               pitches[0] = size;
1256fc5a983dSmrg            size *= *h;
1257fc5a983dSmrg            break;
1258fc5a983dSmrg        default:
1259fc5a983dSmrg            *w = *h = size = 0;
1260fc5a983dSmrg            break;
1261fc5a983dSmrg    }
1262fc5a983dSmrg    return size;
1263fc5a983dSmrg}
1264fc5a983dSmrg
1265fc5a983dSmrgstatic void NVVideoTimerCallback
1266fc5a983dSmrg(
1267fc5a983dSmrg    ScrnInfoPtr pScrnInfo,
1268fc5a983dSmrg    Time currentTime
1269fc5a983dSmrg)
1270fc5a983dSmrg{
1271fc5a983dSmrg    NVPtr         pNv = NVPTR(pScrnInfo);
1272fc5a983dSmrg    NVPortPrivPtr pOverPriv = NULL;
1273fc5a983dSmrg    NVPortPrivPtr pBlitPriv = NULL;
1274fc5a983dSmrg    Bool needCallback = FALSE;
1275fc5a983dSmrg
1276fc5a983dSmrg    if(!pScrnInfo->vtSema) return;
1277fc5a983dSmrg
1278fc5a983dSmrg    if(pNv->overlayAdaptor) {
1279fc5a983dSmrg	pOverPriv = GET_OVERLAY_PRIVATE(pNv);
1280fc5a983dSmrg	if(!pOverPriv->videoStatus)
1281fc5a983dSmrg	   pOverPriv = NULL;
1282fc5a983dSmrg    }
1283fc5a983dSmrg
1284fc5a983dSmrg    if(pNv->blitAdaptor) {
1285fc5a983dSmrg        pBlitPriv = GET_BLIT_PRIVATE(pNv);
1286fc5a983dSmrg        if(!pBlitPriv->videoStatus)
1287fc5a983dSmrg           pBlitPriv = NULL;
1288fc5a983dSmrg    }
1289fc5a983dSmrg
1290fc5a983dSmrg    if(pOverPriv) {
1291fc5a983dSmrg         if(pOverPriv->videoTime < currentTime) {
1292fc5a983dSmrg	    if(pOverPriv->videoStatus & OFF_TIMER) {
1293fc5a983dSmrg		NVStopOverlay(pScrnInfo);
1294fc5a983dSmrg		pOverPriv->videoStatus = FREE_TIMER;
1295fc5a983dSmrg                pOverPriv->videoTime = currentTime + FREE_DELAY;
1296fc5a983dSmrg                needCallback = TRUE;
1297fc5a983dSmrg	    } else
1298fc5a983dSmrg            if(pOverPriv->videoStatus & FREE_TIMER) {
1299fc5a983dSmrg		NVFreeOverlayMemory(pScrnInfo);
1300fc5a983dSmrg		pOverPriv->videoStatus = 0;
1301fc5a983dSmrg	    }
1302fc5a983dSmrg	 } else {
1303fc5a983dSmrg            needCallback = TRUE;
1304fc5a983dSmrg         }
1305fc5a983dSmrg    }
1306fc5a983dSmrg
1307fc5a983dSmrg    if(pBlitPriv) {
1308fc5a983dSmrg        if(pBlitPriv->videoTime < currentTime) {
1309fc5a983dSmrg            NVFreeBlitMemory(pScrnInfo);
1310fc5a983dSmrg            pBlitPriv->videoStatus = 0;
1311fc5a983dSmrg        } else {
1312fc5a983dSmrg            needCallback = TRUE;
1313fc5a983dSmrg        }
1314fc5a983dSmrg    }
1315fc5a983dSmrg
1316fc5a983dSmrg    pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
1317fc5a983dSmrg}
1318fc5a983dSmrg
1319fc5a983dSmrg
1320fc5a983dSmrg/***** Exported offscreen surface stuff ****/
1321fc5a983dSmrg
1322fc5a983dSmrg
1323fc5a983dSmrgstatic int
1324fc5a983dSmrgNVAllocSurface (
1325fc5a983dSmrg    ScrnInfoPtr pScrnInfo,
1326fc5a983dSmrg    int id,
1327fc5a983dSmrg    unsigned short w,
1328fc5a983dSmrg    unsigned short h,
1329fc5a983dSmrg    XF86SurfacePtr surface
1330fc5a983dSmrg)
1331fc5a983dSmrg{
1332fc5a983dSmrg    NVPtr pNv = NVPTR(pScrnInfo);
1333fc5a983dSmrg    NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1334fc5a983dSmrg    int size, bpp;
1335fc5a983dSmrg
1336fc5a983dSmrg    bpp = pScrnInfo->bitsPerPixel >> 3;
1337fc5a983dSmrg
1338fc5a983dSmrg    if(pPriv->grabbedByV4L) return BadAlloc;
1339fc5a983dSmrg
1340fc5a983dSmrg    if((w > 2046) || (h > 2046)) return BadValue;
1341fc5a983dSmrg
1342fc5a983dSmrg    w = (w + 1) & ~1;
1343fc5a983dSmrg    pPriv->pitch = ((w << 1) + 63) & ~63;
1344fc5a983dSmrg    size = h * pPriv->pitch / bpp;
1345fc5a983dSmrg
1346fc5a983dSmrg    pPriv->linear = NVAllocateOverlayMemory(pScrnInfo, pPriv->linear,
1347fc5a983dSmrg					    size);
1348fc5a983dSmrg
1349fc5a983dSmrg    if(!pPriv->linear) return BadAlloc;
1350fc5a983dSmrg
1351fc5a983dSmrg    pPriv->offset = pPriv->linear->offset * bpp;
1352fc5a983dSmrg
1353fc5a983dSmrg    surface->width = w;
1354fc5a983dSmrg    surface->height = h;
1355fc5a983dSmrg    surface->pScrn = pScrnInfo;
1356fc5a983dSmrg    surface->pitches = &pPriv->pitch;
1357fc5a983dSmrg    surface->offsets = &pPriv->offset;
1358fc5a983dSmrg    surface->devPrivate.ptr = (pointer)pPriv;
1359fc5a983dSmrg    surface->id = id;
1360fc5a983dSmrg
1361fc5a983dSmrg    /* grab the video */
1362fc5a983dSmrg    NVStopOverlay(pScrnInfo);
1363fc5a983dSmrg    pPriv->videoStatus = 0;
1364fc5a983dSmrg    REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
1365fc5a983dSmrg    pPriv->grabbedByV4L = TRUE;
1366fc5a983dSmrg
1367fc5a983dSmrg    return Success;
1368fc5a983dSmrg}
1369fc5a983dSmrg
1370fc5a983dSmrgstatic int
1371fc5a983dSmrgNVStopSurface (XF86SurfacePtr surface)
1372fc5a983dSmrg{
1373fc5a983dSmrg    NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1374fc5a983dSmrg
1375fc5a983dSmrg    if(pPriv->grabbedByV4L && pPriv->videoStatus) {
1376fc5a983dSmrg	NVStopOverlay(surface->pScrn);
1377fc5a983dSmrg	pPriv->videoStatus = 0;
1378fc5a983dSmrg    }
1379fc5a983dSmrg
1380fc5a983dSmrg    return Success;
1381fc5a983dSmrg}
1382fc5a983dSmrg
1383fc5a983dSmrgstatic int
1384fc5a983dSmrgNVFreeSurface (XF86SurfacePtr surface)
1385fc5a983dSmrg{
1386fc5a983dSmrg    NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1387fc5a983dSmrg
1388fc5a983dSmrg    if(pPriv->grabbedByV4L) {
1389fc5a983dSmrg	NVStopSurface(surface);
1390fc5a983dSmrg	NVFreeOverlayMemory(surface->pScrn);
1391fc5a983dSmrg	pPriv->grabbedByV4L = FALSE;
1392fc5a983dSmrg    }
1393fc5a983dSmrg
1394fc5a983dSmrg    return Success;
1395fc5a983dSmrg}
1396fc5a983dSmrg
1397fc5a983dSmrgstatic int
1398fc5a983dSmrgNVGetSurfaceAttribute (
1399fc5a983dSmrg    ScrnInfoPtr pScrnInfo,
1400fc5a983dSmrg    Atom attribute,
1401fc5a983dSmrg    INT32 *value
1402fc5a983dSmrg)
1403fc5a983dSmrg{
1404fc5a983dSmrg    NVPtr pNv = NVPTR(pScrnInfo);
1405fc5a983dSmrg    NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1406fc5a983dSmrg
1407fc5a983dSmrg    return NVGetOverlayPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv);
1408fc5a983dSmrg}
1409fc5a983dSmrg
1410fc5a983dSmrgstatic int
1411fc5a983dSmrgNVSetSurfaceAttribute(
1412fc5a983dSmrg    ScrnInfoPtr pScrnInfo,
1413fc5a983dSmrg    Atom attribute,
1414fc5a983dSmrg    INT32 value
1415fc5a983dSmrg)
1416fc5a983dSmrg{
1417fc5a983dSmrg    NVPtr pNv = NVPTR(pScrnInfo);
1418fc5a983dSmrg    NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1419fc5a983dSmrg
1420fc5a983dSmrg    return NVSetOverlayPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv);
1421fc5a983dSmrg}
1422fc5a983dSmrg
1423fc5a983dSmrgstatic int
1424fc5a983dSmrgNVDisplaySurface (
1425fc5a983dSmrg    XF86SurfacePtr surface,
1426fc5a983dSmrg    short src_x, short src_y,
1427fc5a983dSmrg    short drw_x, short drw_y,
1428fc5a983dSmrg    short src_w, short src_h,
1429fc5a983dSmrg    short drw_w, short drw_h,
1430fc5a983dSmrg    RegionPtr clipBoxes
1431fc5a983dSmrg)
1432fc5a983dSmrg{
1433fc5a983dSmrg    ScrnInfoPtr pScrnInfo = surface->pScrn;
1434fc5a983dSmrg    NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1435fc5a983dSmrg    INT32 xa, xb, ya, yb;
1436fc5a983dSmrg    BoxRec dstBox;
1437fc5a983dSmrg
1438fc5a983dSmrg    if(!pPriv->grabbedByV4L) return Success;
1439fc5a983dSmrg
1440fc5a983dSmrg    if(src_w > (drw_w << 3))
1441fc5a983dSmrg	drw_w = src_w >> 3;
1442fc5a983dSmrg    if(src_h > (drw_h << 3))
1443fc5a983dSmrg	drw_h = src_h >> 3;
1444fc5a983dSmrg
1445fc5a983dSmrg    /* Clip */
1446fc5a983dSmrg    xa = src_x;
1447fc5a983dSmrg    xb = src_x + src_w;
1448fc5a983dSmrg    ya = src_y;
1449fc5a983dSmrg    yb = src_y + src_h;
1450fc5a983dSmrg
1451fc5a983dSmrg    dstBox.x1 = drw_x;
1452fc5a983dSmrg    dstBox.x2 = drw_x + drw_w;
1453fc5a983dSmrg    dstBox.y1 = drw_y;
1454fc5a983dSmrg    dstBox.y2 = drw_y + drw_h;
1455fc5a983dSmrg
1456fc5a983dSmrg    if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1457fc5a983dSmrg		    surface->width, surface->height))
1458fc5a983dSmrg    {
1459fc5a983dSmrg        return Success;
1460fc5a983dSmrg    }
1461fc5a983dSmrg
1462fc5a983dSmrg    dstBox.x1 -= pScrnInfo->frameX0;
1463fc5a983dSmrg    dstBox.x2 -= pScrnInfo->frameX0;
1464fc5a983dSmrg    dstBox.y1 -= pScrnInfo->frameY0;
1465fc5a983dSmrg    dstBox.y2 -= pScrnInfo->frameY0;
1466fc5a983dSmrg
1467fc5a983dSmrg    pPriv->currentBuffer = 0;
1468fc5a983dSmrg
1469fc5a983dSmrg    NVPutOverlayImage (pScrnInfo, surface->offsets[0], surface->id,
1470fc5a983dSmrg			surface->pitches[0], &dstBox, xa, ya, xb, yb,
1471fc5a983dSmrg			surface->width, surface->height, src_w, src_h,
1472fc5a983dSmrg			drw_w, drw_h, clipBoxes);
1473fc5a983dSmrg
1474fc5a983dSmrg    return Success;
1475fc5a983dSmrg}
1476fc5a983dSmrg
1477fc5a983dSmrgXF86OffscreenImageRec NVOffscreenImages[2] =
1478fc5a983dSmrg{
1479fc5a983dSmrg {
1480fc5a983dSmrg   &NVImages[0],
1481fc5a983dSmrg   VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1482fc5a983dSmrg   NVAllocSurface,
1483fc5a983dSmrg   NVFreeSurface,
1484fc5a983dSmrg   NVDisplaySurface,
1485fc5a983dSmrg   NVStopSurface,
1486fc5a983dSmrg   NVGetSurfaceAttribute,
1487fc5a983dSmrg   NVSetSurfaceAttribute,
1488fc5a983dSmrg   2046, 2046,
1489fc5a983dSmrg   NUM_OVERLAY_ATTRIBUTES - 1,
1490fc5a983dSmrg   &NVOverlayAttributes[1]
1491fc5a983dSmrg  },
1492fc5a983dSmrg {
1493fc5a983dSmrg   &NVImages[2],
1494fc5a983dSmrg   VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1495fc5a983dSmrg   NVAllocSurface,
1496fc5a983dSmrg   NVFreeSurface,
1497fc5a983dSmrg   NVDisplaySurface,
1498fc5a983dSmrg   NVStopSurface,
1499fc5a983dSmrg   NVGetSurfaceAttribute,
1500fc5a983dSmrg   NVSetSurfaceAttribute,
1501fc5a983dSmrg   2046, 2046,
1502fc5a983dSmrg   NUM_OVERLAY_ATTRIBUTES - 1,
1503fc5a983dSmrg   &NVOverlayAttributes[1]
1504fc5a983dSmrg  },
1505fc5a983dSmrg};
1506fc5a983dSmrg
1507fc5a983dSmrgstatic void
1508fc5a983dSmrgNVInitOffscreenImages (ScreenPtr pScreen)
1509fc5a983dSmrg{
1510fc5a983dSmrg    xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
1511fc5a983dSmrg}
1512