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