s/#define ABC ;/#define ABC do { ; } while(0);/
[nouveau] / src / nv_video.c
1
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5
6 #include "xf86.h"
7 #include "xf86_OSproc.h"
8 #include "xf86Resources.h"
9 #include "compiler.h"
10 #include "xf86PciInfo.h"
11 #include "xf86Pci.h"
12 #include "xf86fbman.h"
13 #include "regionstr.h"
14
15 #include "xf86xv.h"
16 #include <X11/extensions/Xv.h>
17 #include "exa.h"
18 #include "damage.h"
19 #include "dixstruct.h"
20 #include "fourcc.h"
21
22 #include "nv_include.h"
23 #include "nv_dma.h"
24
25 #define IMAGE_MAX_W 2046
26 #define IMAGE_MAX_H 2046
27
28 #define OFF_DELAY       500  /* milliseconds */
29 #define FREE_DELAY      5000
30
31 #define OFF_TIMER       0x01
32 #define FREE_TIMER      0x02
33 #define CLIENT_VIDEO_ON 0x04
34
35 #define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
36
37 #define NUM_BLIT_PORTS 32
38
39 /* Value taken by pPriv -> currentHostBuffer when we failed to allocate the two private buffers in TT memory, so that we can catch this case
40 and attempt no other allocation afterwards (performance reasons) */
41 #define NO_PRIV_HOST_BUFFER_AVAILABLE 9999 
42
43 typedef struct _NVPortPrivRec {
44         short           brightness;
45         short           contrast;
46         short           saturation;
47         short           hue;
48         RegionRec       clip;
49         CARD32          colorKey;
50         Bool            autopaintColorKey;
51         Bool            doubleBuffer;
52         CARD32          videoStatus;
53         int             currentBuffer;
54         Time            videoTime;
55         Bool            grabbedByV4L;
56         Bool            iturbt_709;
57         Bool            blitter;
58         Bool            SyncToVBlank;
59         NVAllocRec *    video_mem;
60         int             pitch;
61         int             offset;
62         NVAllocRec *    TT_mem_chunk[2];
63         int             currentHostBuffer;
64         struct drm_nouveau_notifierobj_alloc *DMANotifier[2];
65 } NVPortPrivRec, *NVPortPrivPtr;
66
67
68 /* Xv DMA notifiers status tracing */
69
70 enum {
71 XV_DMA_NOTIFIER_NOALLOC=0, //notifier not allocated 
72 XV_DMA_NOTIFIER_INUSE=1,
73 XV_DMA_NOTIFIER_FREE=2, //notifier allocated, ready for use
74 };
75
76 /* We have six notifiers available, they are not allocated at startup */
77 int XvDMANotifierStatus[6]= { XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC ,
78                                         XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC };
79 struct drm_nouveau_notifierobj_alloc * XvDMANotifiers[6];
80
81 /* NVPutImage action flags */
82 enum {
83                 IS_YV12 = 1,
84                 IS_YUY2 = 2,
85                 CONVERT_TO_YUY2=4,
86                 USE_OVERLAY=8,
87                 SWAP_UV=16,
88                 IS_RGB=32, //I am not sure how long we will support it
89         };
90         
91 #define GET_OVERLAY_PRIVATE(pNv) \
92         (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr)
93
94 #define GET_BLIT_PRIVATE(pNv) \
95         (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr)
96
97 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
98
99 static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation, 
100             xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
101             xvITURBT709, xvSyncToVBlank;
102
103 /* client libraries expect an encoding */
104 static XF86VideoEncodingRec DummyEncoding =
105
106         0,
107         "XV_IMAGE",
108         IMAGE_MAX_W, IMAGE_MAX_H,
109         {1, 1}
110 };
111
112 #define NUM_FORMATS_ALL 6
113
114 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] = 
115 {
116         {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
117         {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
118 };
119
120 #define NUM_NV04_OVERLAY_ATTRIBUTES 1
121 XF86AttributeRec NV04OverlayAttributes[NUM_NV04_OVERLAY_ATTRIBUTES] =
122 {
123         {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
124 };
125
126
127 #define NUM_OVERLAY_ATTRIBUTES 9
128 XF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] =
129 {
130         {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
131         {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
132         {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
133         {XvSettable             , 0, 0, "XV_SET_DEFAULTS"},
134         {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
135         {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
136         {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
137         {XvSettable | XvGettable, 0, 360, "XV_HUE"},
138         {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"}
139 };
140
141 #define NUM_BLIT_ATTRIBUTES 2
142 XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
143 {
144         {XvSettable             , 0, 0, "XV_SET_DEFAULTS"},
145         {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
146 };
147
148
149 #define NUM_IMAGES_YUV 4
150 #define NUM_IMAGES_ALL 5
151
152 #define FOURCC_RGB 0x0000003
153 #define XVIMAGE_RGB \
154    { \
155         FOURCC_RGB, \
156         XvRGB, \
157         LSBFirst, \
158         { 0x03, 0x00, 0x00, 0x00, \
159           0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
160         32, \
161         XvPacked, \
162         1, \
163         24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
164         0, 0, 0, \
165         0, 0, 0, \
166         0, 0, 0, \
167         {'B','G','R','X',\
168           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}, \
169         XvTopToBottom \
170    }
171
172 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
173 {
174         XVIMAGE_YUY2,
175         XVIMAGE_YV12,
176         XVIMAGE_UYVY,
177         XVIMAGE_I420,
178         XVIMAGE_RGB
179 };
180
181 static void
182 NVWaitVSync(ScrnInfoPtr pScrn)
183 {
184         NVPtr pNv = NVPTR(pScrn);
185
186         BEGIN_RING(NvImageBlit, 0x0000012C, 1);
187         OUT_RING  (0);
188         BEGIN_RING(NvImageBlit, 0x00000134, 1);
189         /* If crtc1 is active, this will produce one, otherwise zero */
190         /* The assumption is that at least one is active */
191         OUT_RING  (pNv->crtc_active[1]);
192         BEGIN_RING(NvImageBlit, 0x00000100, 1);
193         OUT_RING  (0);
194         BEGIN_RING(NvImageBlit, 0x00000130, 1);
195         OUT_RING  (0);
196 }
197
198 /**
199  * NVSetPortDefaults
200  * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
201  * 
202  * @param pScrn screen to get the default colorKey from
203  * @param pPriv port to reset to defaults
204  */
205 static void 
206 NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
207 {
208         NVPtr pNv = NVPTR(pScrn);
209
210         pPriv->brightness               = 0;
211         pPriv->contrast                 = 4096;
212         pPriv->saturation               = 4096;
213         pPriv->hue                      = 0;
214         pPriv->colorKey                 = pNv->videoKey;
215         pPriv->autopaintColorKey        = TRUE;
216         pPriv->doubleBuffer             = TRUE;
217         pPriv->iturbt_709               = FALSE;
218         pPriv->currentHostBuffer        = 0;
219 }
220
221 /**
222  * NVResetVideo
223  * writes the current attributes from the overlay port to the hardware
224  */
225 void 
226 NVResetVideo (ScrnInfoPtr pScrn)
227 {
228         NVPtr          pNv     = NVPTR(pScrn);
229         NVPortPrivPtr  pPriv   = GET_OVERLAY_PRIVATE(pNv);
230         int            satSine, satCosine;
231         double         angle;
232
233         angle = (double)pPriv->hue * 3.1415927 / 180.0;
234
235         satSine = pPriv->saturation * sin(angle);
236         if (satSine < -1024)
237                 satSine = -1024;
238         satCosine = pPriv->saturation * cos(angle);
239         if (satCosine < -1024)
240                 satCosine = -1024;
241
242         nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
243                                                    pPriv->contrast);
244         nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
245                                                    pPriv->contrast);
246         nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
247                                                     (satCosine & 0xffff));
248         nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
249                                                     (satCosine & 0xffff));
250         nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
251 }
252
253 /**
254  * NVStopOverlay
255  * Tell the hardware to stop the overlay
256  */
257 static void 
258 NVStopOverlay (ScrnInfoPtr pScrn)
259 {
260         NVPtr pNv = NVPTR(pScrn);
261         
262         if ( pNv -> Architecture != NV_ARCH_04 )
263                 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
264         else
265                 {
266                 nvWriteRAMDAC(pNv, 0, 0x244, nvReadRAMDAC(pNv, 0, 0x244) &~ 0x1);
267                 nvWriteRAMDAC(pNv, 0, 0x224, 0);
268                 nvWriteRAMDAC(pNv, 0, 0x228, 0);
269                 nvWriteRAMDAC(pNv, 0, 0x22c, 0);
270                 }
271 }
272
273 /**
274  * NVXvDMANotifierAlloc
275  * allocates a notifier from the table of 6 we have
276  *
277  * @return a notifier instance or NULL on error
278  */
279 static struct drm_nouveau_notifierobj_alloc * NVXvDMANotifierAlloc(ScrnInfoPtr pScrn)
280 {
281 int i;
282 for ( i = 0; i < 6; i ++ )
283         {
284         if ( XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_INUSE ) 
285                 continue;
286         
287         if ( XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_FREE )
288                 {
289                 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
290                 return XvDMANotifiers[i];
291                 }
292         
293         if ( XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_NOALLOC )
294                 {
295                 XvDMANotifiers[i] = NVNotifierAlloc(pScrn, NvDmaXvNotifier0 + i);
296                 if (XvDMANotifiers[i]) 
297                         {
298                         XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
299                         return XvDMANotifiers[i];
300                         }
301                 else return NULL;
302                 }
303         }
304         
305 return NULL;
306 }
307
308 /**
309  * NVXvDMANotifierFree
310  * frees a notifier from the table of 6 we have
311  *
312  * 
313  */
314 static void NVXvDMANotifierFree(ScrnInfoPtr pScrn, struct drm_nouveau_notifierobj_alloc * target)
315 {
316 int i;
317 for ( i = 0; i < 6; i ++ )
318         {
319         if ( XvDMANotifiers[i] == target )
320                 break;
321         }
322 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_FREE;
323 }
324
325 /**
326  * NVAllocateVideoMemory
327  * allocates video memory for a given port
328  * 
329  * @param pScrn screen which requests the memory
330  * @param mem pointer to previously allocated memory for reallocation
331  * @param size size of requested memory segment
332  * @return pointer to the allocated memory
333  */
334 static NVAllocRec *
335 NVAllocateVideoMemory(ScrnInfoPtr pScrn, NVAllocRec *mem, int size)
336 {
337         NVPtr pNv = NVPTR(pScrn);
338
339
340         if(mem) {
341                 if(mem->size >= size)
342                         return mem;
343                 NVFreeMemory(pNv, mem);
344         }
345
346         return NVAllocateMemory(pNv, NOUVEAU_MEM_FB, size); /* align 32? */
347 }
348
349 /**
350  * NVAllocateTTMemory
351  * allocates TT memory for a given port
352  * 
353  * @param pScrn screen which requests the memory
354  * @param mem pointer to previously allocated memory for reallocation
355  * @param size size of requested memory segment
356  * @return pointer to the allocated memory
357  */
358 static NVAllocRec *
359 NVAllocateTTMemory(ScrnInfoPtr pScrn, NVAllocRec *mem, int size)
360 {
361         NVPtr pNv = NVPTR(pScrn);
362
363
364         if(mem) {
365                 if(mem->size >= size)
366                         return mem;
367                 NVFreeMemory(pNv, mem);
368         }
369         return NVAllocateMemory(pNv, NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE, size); /* align 32? */
370 }
371
372 /**
373  * NVFreePortMemory
374  * frees memory held by a given port
375  * 
376  * @param pScrn screen whose port wants to free memory
377  * @param pPriv port to free memory of
378  */
379 static void
380 NVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
381 {
382         NVPtr         pNv   = NVPTR(pScrn);
383
384         //xf86DrvMsg(0, X_INFO, "Freeing port memory - TTmem chunks %p %p, notifiers %p %p\n", pPriv->TT_mem_chunk[0], pPriv->TT_mem_chunk[1], pPriv->DMANotifier[0], pPriv->DMANotifier[1]);
385         
386         if(pPriv->video_mem) {
387                 NVFreeMemory(pNv, pPriv->video_mem);
388                 pPriv->video_mem = NULL;
389         }
390         
391         if ( pPriv->TT_mem_chunk[ 0 ] && pPriv->DMANotifier [ 0 ] )
392                 {
393                 NVNotifierWaitStatus(pScrn, pPriv->DMANotifier [ 0 ] ,  0, 1000);
394                 }
395         
396         if ( pPriv->TT_mem_chunk[ 1 ] && pPriv->DMANotifier [ 1 ] )
397                 {
398                 NVNotifierWaitStatus(pScrn, pPriv->DMANotifier [ 1 ] , 0, 1000);
399                 }               
400                 
401         if(pPriv->TT_mem_chunk[0]) {
402                 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
403                 pPriv->TT_mem_chunk[0] = NULL;
404         }
405         
406         if(pPriv->TT_mem_chunk[1]) {
407                 NVFreeMemory(pNv, pPriv->TT_mem_chunk[1]);
408                 pPriv->TT_mem_chunk[1] = NULL;
409         }
410         
411         if(pPriv->DMANotifier[0]) {
412                 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[0]);
413                 pPriv->DMANotifier[0] = NULL;
414         }
415         
416         if(pPriv->DMANotifier[1]) {
417                 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[1]);
418                 pPriv->DMANotifier[1] = NULL;
419         }
420         
421 }
422
423 /**
424  * NVFreeOverlayMemory
425  * frees memory held by the overlay port
426  * 
427  * @param pScrn screen whose overlay port wants to free memory
428  */
429 static void
430 NVFreeOverlayMemory(ScrnInfoPtr pScrn)
431 {
432         NVPtr   pNv = NVPTR(pScrn);
433         NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
434         NVFreePortMemory(pScrn, pPriv);
435         nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) & 0xEFFFFFFF));
436         nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) | 0x10000000));
437 }
438
439 /**
440  * NVFreeBlitMemory
441  * frees memory held by the blit port
442  * 
443  * @param pScrn screen whose blit port wants to free memory
444  */
445 static void
446 NVFreeBlitMemory(ScrnInfoPtr pScrn)
447 {
448         NVPtr   pNv = NVPTR(pScrn);
449         NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
450         NVFreePortMemory(pScrn, pPriv);
451 }
452
453 /**
454  * NVVideoTimerCallback
455  * callback function which perform cleanup tasks (stop overlay, free memory).
456  * within the driver it is only called once from NVBlockHandler in nv_driver.c
457  */
458 static void
459 NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
460 {
461         NVPtr         pNv = NVPTR(pScrn);
462         NVPortPrivPtr pOverPriv = NULL;
463         NVPortPrivPtr pBlitPriv = NULL;
464         Bool needCallback = FALSE;
465
466         if (!pScrn->vtSema)
467                 return; 
468
469         if (pNv->overlayAdaptor) {
470                 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
471                 if (!pOverPriv->videoStatus)
472                         pOverPriv = NULL;
473         }
474
475         if (pNv->blitAdaptor) {
476                 pBlitPriv = GET_BLIT_PRIVATE(pNv);
477                 if (!pBlitPriv->videoStatus)
478                         pBlitPriv = NULL;
479         }
480
481         if (pOverPriv) {
482                 if (pOverPriv->videoTime < currentTime) {
483                         if (pOverPriv->videoStatus & OFF_TIMER) {
484                                 NVStopOverlay(pScrn);
485                                 pOverPriv->videoStatus = FREE_TIMER;
486                                 pOverPriv->videoTime = currentTime + FREE_DELAY;
487                                 needCallback = TRUE;
488                         } else
489                         if (pOverPriv->videoStatus & FREE_TIMER) {
490                                 NVFreeOverlayMemory(pScrn);
491                                 pOverPriv->videoStatus = 0;
492                         }
493                 } else {
494                         needCallback = TRUE;
495                 }
496         }
497
498         if (pBlitPriv) {
499                 if (pBlitPriv->videoTime < currentTime) {
500                         NVFreeBlitMemory(pScrn);
501                         pBlitPriv->videoStatus = 0;              
502                 } else {
503                         needCallback = TRUE;
504                 }
505         }
506
507         pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
508 }
509
510 /**
511  * NVPutOverlayImage
512  * program hardware to overlay image into front buffer
513  * 
514  * @param pScrn screen
515  * @param offset card offset to the pixel data
516  * @param id format of image
517  * @param dstPitch pitch of the pixel data in VRAM
518  * @param dstBox destination box
519  * @param x1 first source point - x
520  * @param y1 first source point - y
521  * @param x2 second source point - x
522  * @param y2 second source point - y
523  * @param width width of the source image = x2 - x1
524  * @param height height
525  * @param src_w width of the image data in VRAM
526  * @param src_h height
527  * @param drw_w width of the image to draw to screen
528  * @param drw_h height
529  * @param clipBoxes ???
530  */
531 static void
532 NVPutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
533                   int dstPitch, BoxPtr dstBox,
534                   int x1, int y1, int x2, int y2,
535                   short width, short height,
536                   short src_w, short src_h,
537                   short drw_w, short drw_h,
538                   RegionPtr clipBoxes)
539 {
540         NVPtr         pNv    = NVPTR(pScrn);
541         NVPortPrivPtr pPriv  = GET_OVERLAY_PRIVATE(pNv);
542         int           buffer = pPriv->currentBuffer;
543
544         /* paint the color key */
545         if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
546                 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
547                 /* we always paint V4L's color key */
548                 if (!pPriv->grabbedByV4L)
549                         REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
550                 {
551                 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
552                 }
553         }
554
555         if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
556                 dstBox->y1 <<= 1;
557                 dstBox->y2 <<= 1;
558                 drw_h <<= 1;
559         }
560         
561         //xf86DrvMsg(0, X_INFO, "SIZE_IN h %d w %d, POINT_IN x %d y %d, DS_DX %d DT_DY %d, POINT_OUT x %d y %d SIZE_OUT h %d w %d\n", height, width, x1 >> 16,y1>>16, (src_w << 20) / drw_w, (src_h << 20) / drw_h,  (dstBox->x1),(dstBox->y1), (dstBox->y2 - dstBox->y1), (dstBox->x2 - dstBox->x1));
562
563         nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer)     , 0);
564         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer)     , offset);
565         nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer)  , (height << 16) | width);
566         nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
567                           ((y1 << 4) & 0xffff0000) | (x1 >> 12));
568         nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer)    , (src_w << 20) / drw_w);
569         nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer)    , (src_h << 20) / drw_h);
570         nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
571                           (dstBox->y1 << 16) | dstBox->x1);
572         nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
573                           ((dstBox->y2 - dstBox->y1) << 16) |
574                            (dstBox->x2 - dstBox->x1));
575
576         dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;   /* use color key */
577         if(id != FOURCC_UYVY)
578                 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
579         if(pPriv->iturbt_709)
580                 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
581         
582         if( id == FOURCC_YV12 || id == FOURCC_I420 )
583                 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
584
585         /* Those are important only for planar formats (NV12) */
586         if ( uvoffset )
587                 {
588                 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_BASE(buffer), 0); 
589                 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer), uvoffset);
590                 }
591         
592         nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
593         nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
594         nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 :  0x1);
595
596         pPriv->videoStatus = CLIENT_VIDEO_ON;
597 }
598
599 static void
600 NV04PutOverlayImage(ScrnInfoPtr pScrn, int offset, int id,
601                   int dstPitch, BoxPtr dstBox,
602                   int x1, int y1, int x2, int y2,
603                   short width, short height,
604                   short src_w, short src_h,
605                   short drw_w, short drw_h,
606                   RegionPtr clipBoxes)
607 {
608         NVPtr         pNv    = NVPTR(pScrn);
609         NVPortPrivPtr pPriv  = GET_OVERLAY_PRIVATE(pNv);
610
611         /* paint the color key */
612         if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
613                 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
614                 /* we always paint V4L's color key */
615                 if (!pPriv->grabbedByV4L)
616                         REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
617                 {
618                 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
619                 }
620         }
621
622         if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) { /*This may not work with NV04 overlay according to rivatv source*/
623                 dstBox->y1 <<= 1;
624                 dstBox->y2 <<= 1;
625                 drw_h <<= 1;
626         }
627
628         /* NV_PVIDEO_OE_STATE */
629         /* NV_PVIDEO_SU_STATE */
630         /* NV_PVIDEO_RM_STATE */
631         nvWriteRAMDAC(pNv, 0, 0x224, 0);
632         nvWriteRAMDAC(pNv, 0, 0x228, 0);
633         nvWriteRAMDAC(pNv, 0, 0x22c, 0);
634         
635         /* NV_PVIDEO_BUFF0_START_ADDRESS */
636         nvWriteRAMDAC(pNv, 0, 0x20C, offset);
637         nvWriteRAMDAC(pNv, 0, 0x20C + 4, offset);
638         /* NV_PVIDEO_BUFF0_PITCH_LENGTH */
639         nvWriteRAMDAC(pNv, 0, 0x214, dstPitch);
640         nvWriteRAMDAC(pNv, 0, 0x214 + 4, dstPitch);
641         
642         /* NV_PVIDEO_BUFF0_OFFSET */
643         nvWriteRAMDAC(pNv, 0, 0x21C, 0);
644         nvWriteRAMDAC(pNv, 0, 0x21C + 4, 0);
645         
646         /* NV_PVIDEO_WINDOW_START */
647         nvWriteRAMDAC(pNv, 0, 0x230, (dstBox->y1 << 16) | dstBox->x1);
648         /* NV_PVIDEO_WINDOW_SIZE */
649         nvWriteRAMDAC(pNv, 0, 0x234, ((dstBox->y2 - dstBox->y1) << 16) |
650                            (dstBox->x2 - dstBox->x1));
651         /* NV_PVIDEO_STEP_SIZE */
652         nvWriteRAMDAC(pNv,  0,  0x200, (uint32_t)((src_h - 1 << 11) / (drw_h - 1)) << 16 | (uint32_t)((src_w - 1 << 11) / (drw_w - 1)));
653         
654         /* NV_PVIDEO_RED_CSC_OFFSET */
655         /* NV_PVIDEO_GREEN_CSC_OFFSET */
656         /* NV_PVIDEO_BLUE_CSC_OFFSET */
657         /* NV_PVIDEO_CSC_ADJUST */
658         nvWriteRAMDAC(pNv, 0, 0x280, 0x69);
659         nvWriteRAMDAC(pNv, 0, 0x284, 0x3e);
660         nvWriteRAMDAC(pNv, 0, 0x288, 0x89);
661         nvWriteRAMDAC(pNv, 0, 0x28C, 0x0);
662
663         /* NV_PVIDEO_CONTROL_Y (BLUR_ON, LINE_HALF) */
664         nvWriteRAMDAC(pNv, 0, 0x204, 0x001);
665         /* NV_PVIDEO_CONTROL_X (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */
666         nvWriteRAMDAC(pNv, 0, 0x208, 0x111);
667         
668         /* NV_PVIDEO_FIFO_BURST_LENGTH */  
669         nvWriteRAMDAC(pNv, 0, 0x23C, 0x03);
670         /* NV_PVIDEO_FIFO_THRES_SIZE */
671         nvWriteRAMDAC(pNv, 0, 0x238, 0x38);
672         
673         /* Color key */
674         nvWriteRAMDAC(pNv, 0, 0x240, pPriv->colorKey);
675         
676         /*NV_PVIDEO_OVERLAY
677                 0x1 Video on
678                 0x10 Use colorkey
679                 0x100 Format YUY2 */
680         nvWriteRAMDAC(pNv, 0, 0x244, 0x111);
681         
682         /* NV_PVIDEO_SU_STATE */
683         nvWriteRAMDAC(pNv, 0, 0x228, (nvReadRAMDAC(pNv, 0, 0x228) ^ (1 << 16)));
684         
685         pPriv->videoStatus = CLIENT_VIDEO_ON;
686 }
687 #ifndef ExaOffscreenMarkUsed
688 extern void ExaOffscreenMarkUsed(PixmapPtr);
689 #endif
690 #ifndef exaGetDrawablePixmap
691 extern PixmapPtr exaGetDrawablePixmap(DrawablePtr);
692 #endif
693 #ifndef exaPixmapIsOffscreen
694 extern Bool exaPixmapIsOffscreen(PixmapPtr p);
695 #endif
696 /* To support EXA 2.0, 2.1 has this in the header */
697 #ifndef exaMoveInPixmap
698 extern void exaMoveInPixmap(PixmapPtr pPixmap);
699 #endif
700
701 /**
702  * NVPutBlitImage
703  * 
704  * @param pScrn screen
705  * @param src_offset
706  * @param id colorspace of image
707  * @param src_pitch
708  * @param dstBox
709  * @param x1
710  * @param y1
711  * @param x2
712  * @param y2
713  * @param width
714  * @param height
715  * @param src_w
716  * @param src_h
717  * @param drw_w
718  * @param drw_h
719  * @param clipBoxes
720  * @param pDraw
721  */
722 static void
723 NVPutBlitImage(ScrnInfoPtr pScrn, int src_offset, int id,
724                int src_pitch, BoxPtr dstBox,
725                int x1, int y1, int x2, int y2,
726                short width, short height,
727                short src_w, short src_h,
728                short drw_w, short drw_h,
729                RegionPtr clipBoxes,
730                DrawablePtr pDraw)
731 {
732         NVPtr          pNv   = NVPTR(pScrn);
733         NVPortPrivPtr  pPriv = GET_BLIT_PRIVATE(pNv);
734         BoxPtr         pbox;
735         int            nbox;
736         CARD32         dsdx, dtdy;
737         CARD32         dst_size, dst_point;
738         CARD32         src_point, src_format;
739
740         ScreenPtr pScreen = pScrn->pScreen;
741         PixmapPtr pPix    = exaGetDrawablePixmap(pDraw);
742         int dst_format;
743
744         /* Try to get the dest drawable into vram */
745         if (!exaPixmapIsOffscreen(pPix)) {
746                 exaMoveInPixmap(pPix);
747                 ExaOffscreenMarkUsed(pPix);
748         }
749
750         /* If we failed, draw directly onto the screen pixmap.
751          * Not sure if this is the best approach, maybe failing
752          * with BadAlloc would be better?
753          */
754         if (!exaPixmapIsOffscreen(pPix)) {
755                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
756                         "XV: couldn't move dst surface into vram\n");
757                 pPix = pScreen->GetScreenPixmap(pScreen);
758         }
759
760         NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format);
761         NVAccelSetCtxSurf2D(pPix, pPix, dst_format);
762
763 #ifdef COMPOSITE
764         /* Adjust coordinates if drawing to an offscreen pixmap */
765         if (pPix->screen_x || pPix->screen_y) {
766                 REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
767                                                      -pPix->screen_x,
768                                                      -pPix->screen_y);
769                 dstBox->x1 -= pPix->screen_x;
770                 dstBox->x2 -= pPix->screen_x;
771                 dstBox->y1 -= pPix->screen_y;
772                 dstBox->y2 -= pPix->screen_y;
773         }
774
775         DamageDamageRegion((DrawablePtr)pPix, clipBoxes);
776 #endif
777
778         pbox = REGION_RECTS(clipBoxes);
779         nbox = REGION_NUM_RECTS(clipBoxes);
780
781         dsdx = (src_w << 20) / drw_w;
782         dtdy = (src_h << 20) / drw_h;
783
784         dst_size  = ((dstBox->y2 - dstBox->y1) << 16) |
785                      (dstBox->x2 - dstBox->x1);
786         dst_point = (dstBox->y1 << 16) | dstBox->x1;
787
788         src_pitch |= (NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
789                       NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_BILINEAR);
790         src_point = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
791
792         switch(id) {
793         case FOURCC_RGB:
794                 src_format =
795                         NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
796                 break;
797         case FOURCC_UYVY:
798                 src_format =
799                         NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_YB8V8YA8U8;
800                 break;
801         default:
802                 src_format =
803                         NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_V8YB8U8YA8;
804                 break;
805         }
806
807         if(pPriv->SyncToVBlank) {
808                 FIRE_RING();
809                 NVWaitVSync(pScrn);
810         }
811
812         if(pNv->BlendingPossible) {
813                 BEGIN_RING(NvScaledImage,
814                                 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 2);
815                 OUT_RING  (src_format);
816                 OUT_RING  (NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
817         } else {
818                 BEGIN_RING(NvScaledImage,
819                                 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 2);
820                 OUT_RING  (src_format);
821         }
822
823         while(nbox--) {
824                 BEGIN_RING(NvRectangle,
825                                 NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
826                 OUT_RING  (0);
827
828                 BEGIN_RING(NvScaledImage,
829                                 NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT, 6);
830                 OUT_RING  ((pbox->y1 << 16) | pbox->x1); 
831                 OUT_RING  (((pbox->y2 - pbox->y1) << 16) |
832                                  (pbox->x2 - pbox->x1));
833                 OUT_RING  (dst_point);
834                 OUT_RING  (dst_size);
835                 OUT_RING  (dsdx);
836                 OUT_RING  (dtdy);
837
838                 BEGIN_RING(NvScaledImage,
839                                 NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
840                 OUT_RING  ((height << 16) | width);
841                 OUT_RING  (src_pitch);
842                 OUT_RING  (src_offset);
843                 OUT_RING  (src_point);
844                 pbox++;
845         }
846
847         FIRE_RING();
848
849         exaMarkSync(pScrn->pScreen);
850
851         pPriv->videoStatus = FREE_TIMER;
852         pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
853         pNv->VideoTimerCallback = NVVideoTimerCallback;
854 }
855
856 /*
857  * StopVideo
858  */
859 static void
860 NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
861 {
862         NVPtr         pNv   = NVPTR(pScrn);
863         NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
864
865         if(pPriv->grabbedByV4L) return;
866
867         REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
868
869         if(Exit) {
870                 if (pPriv->videoStatus & CLIENT_VIDEO_ON)
871                         NVStopOverlay(pScrn);
872                 NVFreeOverlayMemory(pScrn);
873                 pPriv->videoStatus = 0;
874         } else {
875                 if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
876                         pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
877                         pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
878                         pNv->VideoTimerCallback = NVVideoTimerCallback;
879                 }
880         }
881 }
882
883 /**
884  * NVStopBlitVideo
885  */
886 static void
887 NVStopBlitVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
888 {
889 }
890
891 /**
892  * NVSetOverlayPortAttribute
893  * sets the attribute "attribute" of port "data" to value "value"
894  * calls NVResetVideo(pScrn) to apply changes to hardware
895  * 
896  * @param pScrenInfo
897  * @param attribute attribute to set
898  * @param value value to which attribute is to be set
899  * @param data port from which the attribute is to be set
900  * 
901  * @return Success, if setting is successful
902  * BadValue/BadMatch, if value/attribute are invalid
903  * @see NVResetVideo(ScrnInfoPtr pScrn)
904  */
905 static int
906 NVSetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
907                           INT32 value, pointer data)
908 {
909         NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
910
911         if (attribute == xvBrightness) {
912                 if ((value < -512) || (value > 512))
913                         return BadValue;
914                 pPriv->brightness = value;
915         } else
916         if (attribute == xvDoubleBuffer) {
917                 if ((value < 0) || (value > 1))
918                         return BadValue;
919                 pPriv->doubleBuffer = value;
920         } else
921         if (attribute == xvContrast) {
922                 if ((value < 0) || (value > 8191))
923                         return BadValue;
924                 pPriv->contrast = value;
925         } else
926         if (attribute == xvHue) {
927                 value %= 360;
928                 if (value < 0)
929                         value += 360;
930                 pPriv->hue = value;
931         } else
932         if (attribute == xvSaturation) {
933                 if ((value < 0) || (value > 8191))
934                         return BadValue;
935                 pPriv->saturation = value;
936         } else
937         if (attribute == xvColorKey) {
938                 pPriv->colorKey = value;
939                 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
940         } else
941         if (attribute == xvAutopaintColorKey) {
942                 if ((value < 0) || (value > 1))
943                         return BadValue;
944                 pPriv->autopaintColorKey = value;
945         } else
946         if (attribute == xvITURBT709) {
947                 if ((value < 0) || (value > 1))
948                         return BadValue;
949                 pPriv->iturbt_709 = value;
950         } else
951         if (attribute == xvSetDefaults) {
952                 NVSetPortDefaults(pScrn, pPriv);
953         } else
954                 return BadMatch;
955
956         NVResetVideo(pScrn);
957         return Success;
958 }
959
960 /**
961  * NVGetOverlayPortAttribute
962  * 
963  * @param pScrn unused
964  * @param attribute attribute to be read
965  * @param value value of attribute will be stored in this pointer
966  * @param data port from which attribute will be read
967  * @return Success, if queried attribute exists
968  */
969 static int
970 NVGetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
971                           INT32 *value, pointer data)
972 {
973         NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
974
975         if (attribute == xvBrightness)
976                 *value = pPriv->brightness;
977         else if (attribute == xvDoubleBuffer)
978                 *value = (pPriv->doubleBuffer) ? 1 : 0;
979         else if (attribute == xvContrast)
980                 *value = pPriv->contrast;
981         else if (attribute == xvSaturation)
982                 *value = pPriv->saturation;
983         else if (attribute == xvHue)
984                 *value = pPriv->hue;
985         else if (attribute == xvColorKey)
986                 *value = pPriv->colorKey;
987         else if (attribute == xvAutopaintColorKey)
988                 *value = (pPriv->autopaintColorKey) ? 1 : 0;
989         else if (attribute == xvITURBT709)
990                 *value = (pPriv->iturbt_709) ? 1 : 0;
991         else
992                 return BadMatch;
993
994         return Success;
995 }
996
997 /**
998  * NVSetBlitPortAttribute
999  * sets the attribute "attribute" of port "data" to value "value"
1000  * supported attributes:
1001  * - xvSyncToVBlank (values: 0,1)
1002  * - xvSetDefaults (values: NA; SyncToVBlank will be set, if hardware supports it)
1003  * 
1004  * @param pScrenInfo
1005  * @param attribute attribute to set
1006  * @param value value to which attribute is to be set
1007  * @param data port from which the attribute is to be set
1008  * 
1009  * @return Success, if setting is successful
1010  * BadValue/BadMatch, if value/attribute are invalid
1011  */
1012 static int
1013 NVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1014                        INT32 value, pointer data)
1015 {
1016         NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1017         NVPtr           pNv = NVPTR(pScrn);
1018
1019         if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
1020                 if ((value < 0) || (value > 1))
1021                         return BadValue;
1022                 pPriv->SyncToVBlank = value;
1023         } else
1024         if (attribute == xvSetDefaults) {
1025                 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1026         } else
1027                 return BadMatch;
1028
1029         return Success;
1030 }
1031
1032 /**
1033  * NVGetBlitPortAttribute
1034  * reads the value of attribute "attribute" from port "data" into INT32 "*value"
1035  * currently only one attribute supported: xvSyncToVBlank
1036  * 
1037  * @param pScrn unused
1038  * @param attribute attribute to be read
1039  * @param value value of attribute will be stored here
1040  * @param data port from which attribute will be read
1041  * @return Success, if queried attribute exists
1042  */
1043 static int
1044 NVGetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1045                        INT32 *value, pointer data)
1046 {
1047         NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1048
1049         if(attribute == xvSyncToVBlank)
1050                 *value = (pPriv->SyncToVBlank) ? 1 : 0;
1051         else
1052                 return BadMatch;
1053
1054         return Success;
1055 }
1056
1057
1058 /**
1059  * QueryBestSize
1060  * used by client applications to ask the driver:
1061  * how would you actually scale a video of dimensions
1062  * vid_w, vid_h, if i wanted you to scale it to dimensions
1063  * drw_w, drw_h?
1064  * function stores actual scaling size in pointers p_w, p_h.
1065  * 
1066  * 
1067  * @param pScrn unused
1068  * @param motion unused
1069  * @param vid_w width of source video
1070  * @param vid_h height of source video
1071  * @param drw_w desired scaled width as requested by client
1072  * @param drw_h desired scaled height as requested by client
1073  * @param p_w actual scaled width as the driver is capable of
1074  * @param p_h actual scaled height as the driver is capable of
1075  * @param data unused
1076  */
1077 static void
1078 NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
1079                 short vid_w, short vid_h, 
1080                 short drw_w, short drw_h, 
1081                 unsigned int *p_w, unsigned int *p_h, 
1082                 pointer data)
1083 {
1084         if(vid_w > (drw_w << 3))
1085                 drw_w = vid_w >> 3;
1086         if(vid_h > (drw_h << 3))
1087                 drw_h = vid_h >> 3;
1088
1089         *p_w = drw_w;
1090         *p_h = drw_h; 
1091 }
1092
1093 /**
1094  * NVCopyData420
1095  * used to convert YV12 to YUY2 for the blitter
1096  * 
1097  * @param src1 source buffer of luma
1098  * @param src2 source buffer of chroma1
1099  * @param src3 source buffer of chroma2
1100  * @param dst1 destination buffer
1101  * @param srcPitch pitch of src1
1102  * @param srcPitch2 pitch of src2, src3
1103  * @param dstPitch pitch of dst1
1104  * @param h number of lines to copy
1105  * @param w length of lines to copy
1106  */
1107 static inline void NVCopyData420(unsigned char *src1, unsigned char *src2,
1108                           unsigned char *src3, unsigned char *dst1,
1109                           int srcPitch, int srcPitch2,
1110                           int dstPitch,
1111                           int h, int w)
1112 {
1113         CARD32 *dst;
1114         CARD8 *s1, *s2, *s3;
1115         int i, j;
1116
1117         w >>= 1;
1118
1119         for (j = 0; j < h; j++) {
1120                 dst = (CARD32*)dst1;
1121                 s1 = src1;  s2 = src2;  s3 = src3;
1122                 i = w;
1123
1124                 while (i > 4) {
1125 #if X_BYTE_ORDER == X_BIG_ENDIAN
1126                 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
1127                 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1];
1128                 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2];
1129                 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3];
1130 #else
1131                 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
1132                 dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
1133                 dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
1134                 dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
1135 #endif
1136                 dst += 4; s2 += 4; s3 += 4; s1 += 8;
1137                 i -= 4;
1138                 }
1139
1140                 while (i--) {
1141 #if X_BYTE_ORDER == X_BIG_ENDIAN
1142                 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
1143 #else
1144                 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
1145 #endif
1146                 dst++; s2++; s3++;
1147                 s1 += 2;
1148                 }
1149
1150                 dst1 += dstPitch;
1151                 src1 += srcPitch;
1152                 if (j & 1) {
1153                         src2 += srcPitch2;
1154                         src3 += srcPitch2;
1155                 }
1156         }
1157 }
1158
1159 /**
1160  * NVCopyNV12ColorPlanes
1161  * Used to convert YV12 color planes to NV12 (interleaved UV) for the overlay
1162  * 
1163  * @param src1 source buffer of chroma1
1164  * @param dst1 destination buffer
1165  * @param h number of lines to copy
1166  * @param w length of lines to copy
1167  * @param id source pixel format (YV12 or I420)
1168  */
1169 static inline void NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char * src2, unsigned char *dst, int dstPitch, int srcPitch2, 
1170                           int h, int w)
1171 {
1172         
1173         int i,j,l,e;
1174         
1175         w >>= 1;
1176         h >>= 1;
1177         l = w >> 1;
1178         e = w & 1;
1179         for ( j = 0; j < h; j++ ) 
1180                 {
1181                 unsigned char * us = src1;
1182                 unsigned char * vs = src2;
1183                 unsigned int * vuvud = (unsigned int *) dst;
1184                 for ( i = 0; i < l; i++ )
1185                         {
1186 #if X_BYTE_ORDER == X_BIG_ENDIAN
1187                         *vuvud++ = (vs[0]<<24) | (us[0]<<16) | (vs[1]<<8) | us[1];
1188 #else
1189                         *vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24);
1190 #endif
1191                         us+=2;
1192                         vs+=2;
1193                         }
1194                 if (e)  {
1195                         unsigned short *vud = (unsigned short *) vuvud;
1196 #if X_BYTE_ORDER == X_BIG_ENDIAN
1197                         *vud = (vs[0]<<8) | (us[0] << 0);
1198 #else
1199                         *vud = vs[0] | (us[0]<<8);
1200 #endif
1201                         }
1202                 dst += dstPitch ;
1203                 src1 += srcPitch2;
1204                 src2 += srcPitch2;
1205                 }       
1206
1207 }
1208
1209
1210 static int NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 * xa, INT32 * xb, INT32 * ya, INT32 * yb, 
1211                                                         short * src_x, short * src_y, short * src_w, short * src_h,
1212                                                         short * drw_x, short * drw_y, short * drw_w, short * drw_h,
1213                                                         int * left, int * top, int * right, int * bottom,
1214                                                         BoxRec * dstBox, 
1215                                                         int * npixels, int * nlines,
1216                                                         RegionPtr clipBoxes, short width, short height
1217                                                         )
1218 {
1219         
1220         if ( action_flags & USE_OVERLAY ) 
1221                 { /* overlay hardware scaler limitation - copied from nv, UNCHECKED*/
1222                 if (*src_w > (*drw_w << 3))
1223                         *drw_w = *src_w >> 3;
1224                 if (*src_h > (*drw_h << 3))
1225                         *drw_h = *src_h >> 3;
1226                 }
1227         
1228
1229         /* Clip */
1230         *xa = *src_x;
1231         *xb = *src_x + *src_w;
1232         *ya = *src_y;
1233         *yb = *src_y + *src_h;
1234
1235         dstBox->x1 = *drw_x;
1236         dstBox->x2 = *drw_x + *drw_w;
1237         dstBox->y1 = *drw_y;
1238         dstBox->y2 = *drw_y + *drw_h;
1239
1240         if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
1241                                    width, height))
1242                 return -1;
1243
1244         if ( action_flags & USE_OVERLAY )
1245                 {
1246                 dstBox->x1 -= pScrn->frameX0;
1247                 dstBox->x2 -= pScrn->frameX0;
1248                 dstBox->y1 -= pScrn->frameY0;
1249                 dstBox->y2 -= pScrn->frameY0;
1250                 }
1251                 
1252         
1253         
1254         /* Convert fixed point to integer, as xf86XVClipVideoHelper probably turns its parameter into fixed point values */
1255         *left = (*xa) >> 16;
1256         if (*left < 0) *left = 0;
1257         *top = (*ya) >> 16;
1258         if (*top < 0) *top = 0;
1259         *right = (*xb) >> 16;
1260         if (*right > width) *right = width;
1261         *bottom = (*yb) >> 16;
1262         if (*bottom > height) *bottom = height;
1263         
1264         if ( action_flags & IS_YV12 )
1265                 {
1266                 *left &= ~1; //even "left", even "top", even number of pixels per line and even number of lines
1267                 *npixels = ((*right + 1) & ~1) - *left;
1268                 *top &= ~1;
1269                 *nlines = ((*bottom + 1) & ~1) - *top;
1270                 }
1271         else if ( action_flags & IS_YUY2 )
1272                 {
1273                 *left &= ~1; //even "left"
1274                 *npixels = ((*right + 1) & ~1) - *left; //even number of pixels per line
1275                 *nlines = *bottom - *top; 
1276                 *left <<= 1; //16bpp
1277                 }
1278         else if (action_flags & IS_RGB )
1279                 {
1280                 *npixels = *right - *left;
1281                 *nlines = *bottom - *top;
1282                 *left <<= 2; //32bpp
1283                 }
1284         
1285         return 0;
1286 }
1287
1288 static int NV_calculate_pitches_and_mem_size(int action_flags, int * srcPitch, int * srcPitch2, int * dstPitch, 
1289                                                                                 int * s2offset, int * s3offset, 
1290                                                                                 int * newFBSize, int * newTTSize,
1291                                                                                 int * line_len, int npixels, int nlines, int width, int height)
1292 {
1293         int tmp;
1294                 
1295         if ( action_flags & IS_YV12 ) 
1296                 {       /*YV12 or I420*/
1297                 *srcPitch = (width + 3) & ~3;   /* of luma */
1298                 *s2offset = *srcPitch * height;
1299                 *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
1300                 *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
1301                 *dstPitch = (npixels + 63) &~ 63; /*luma and chroma pitch*/
1302                 *line_len = npixels;
1303                 *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1304                 *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1305                 }
1306         else if ( action_flags & IS_YUY2 )
1307                 {
1308                 *srcPitch = width << 1; /* one luma, one chroma per pixel */
1309                 *dstPitch = ((npixels << 1) + 63) & ~63;
1310                 *line_len = npixels << 1;
1311                 *newFBSize = nlines * *dstPitch;
1312                 *newTTSize = nlines * *line_len;
1313                 }
1314         else if ( action_flags & IS_RGB )
1315                 {
1316                 *srcPitch = width << 2; /* one R, one G, one B, one X per pixel */
1317                 *dstPitch = ((npixels << 2) + 63) & ~63;
1318                 *line_len = npixels << 2;
1319                 *newFBSize = nlines * *dstPitch;
1320                 *newTTSize = nlines * *dstPitch;                
1321                 }
1322         
1323         
1324         if ( action_flags & CONVERT_TO_YUY2 )
1325                 {
1326                 *dstPitch = ((npixels << 1) + 63) & ~63;
1327                 *line_len = npixels << 1;
1328                 *newFBSize = nlines * *dstPitch;
1329                 *newTTSize = nlines * *line_len;
1330                 }
1331         
1332         if ( action_flags & SWAP_UV ) 
1333                 { //I420 swaps U and V
1334                 tmp = *s2offset;
1335                 *s2offset = *s3offset;
1336                 *s3offset = tmp;
1337                 }
1338         
1339         if ( action_flags & USE_OVERLAY ) // overlay double buffering ...
1340                 (*newFBSize) <<= 1; // ... means double the amount of VRAM needed
1341         
1342         return 0;
1343 }
1344
1345
1346 /**
1347  * NV_set_action_flags
1348  * This function computes the action flags from the input image,
1349  * that is, it decides what NVPutImage and its helpers must do.
1350  * This eases readability by avoiding lots of switch-case statements in the core NVPutImage
1351  */
1352 static void NV_set_action_flags(NVPtr pNv, ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, int id, int * action_flags)
1353 {
1354         *action_flags = 0;
1355         if ( id == FOURCC_YUY2 || id == FOURCC_UYVY )
1356                 *action_flags |= IS_YUY2;
1357         
1358         if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1359                 *action_flags |= IS_YV12;
1360         
1361         if ( id == FOURCC_RGB ) /*How long will we support it?*/
1362                 *action_flags |= IS_RGB; 
1363         
1364         if ( id == FOURCC_I420 ) /*I420 is YV12 with swapped UV*/
1365                 *action_flags |= SWAP_UV;
1366         
1367         if ( !pPriv -> blitter )
1368                 *action_flags |= USE_OVERLAY;
1369         
1370         #ifdef COMPOSITE
1371         WindowPtr pWin = NULL;
1372                 
1373         if (!noCompositeExtension && WindowDrawable(pDraw->type)) 
1374                 {
1375                 pWin = (WindowPtr)pDraw;
1376                 }
1377                         
1378         if ( pWin )
1379                 if ( pWin->redirectDraw )
1380                         *action_flags &= ~USE_OVERLAY;
1381                                 
1382         #endif
1383                 
1384         if ( ! ( *action_flags & USE_OVERLAY) )
1385                 {
1386                 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1387                         { /*The blitter does not handle YV12 natively*/
1388                         *action_flags |= CONVERT_TO_YUY2;
1389                         }
1390                 }
1391
1392         if ( pNv->Architecture == NV_ARCH_04 )
1393                 if ( * action_flags & IS_YV12 ) //NV04-05 don't support native YV12, only YUY2 and ITU-R BT.601)
1394                         *action_flags |= CONVERT_TO_YUY2;
1395                 
1396         if ( pNv->Architecture == NV_ARCH_10 || pNv->Architecture == NV_ARCH_20 )
1397                 {
1398                 switch ( pNv->Chipset & 0xfff0 )
1399                         {
1400                         case CHIPSET_NV10:
1401                         case CHIPSET_NV11:
1402                         case CHIPSET_NV15:
1403                         case CHIPSET_NFORCE: /*XXX: unsure about nforce and nforce2*/
1404                         case CHIPSET_NFORCE2:
1405                         case CHIPSET_NV20: /*reported by pq - in fact all cards older than geforce4 ti probably don't have YV12 overlay*/
1406                                         *action_flags |= CONVERT_TO_YUY2; break;
1407                         
1408                         default : break;
1409                         }
1410                 }
1411         
1412 }
1413
1414
1415 /**
1416  * NVPutImage
1417  * PutImage is "the" important function of the Xv extension.
1418  * a client (e.g. video player) calls this function for every
1419  * image (of the video) to be displayed. this function then
1420  * scales and displays the image.
1421  * 
1422  * @param pScrn screen which hold the port where the image is put
1423  * @param src_x source point in the source image to start displaying from
1424  * @param src_y see above
1425  * @param src_w width of the source image to display
1426  * @param src_h see above
1427  * @param drw_x  screen point to display to
1428  * @param drw_y
1429  * @param drw_w width of the screen drawable
1430  * @param drw_h
1431  * @param id pixel format of image
1432  * @param buf pointer to buffer containing the source image
1433  * @param width total width of the source image we are passed
1434  * @param height 
1435  * @param Sync unused
1436  * @param clipBoxes ??
1437  * @param data pointer to port 
1438  * @param pDraw drawable pointer
1439  */
1440 static int
1441 NVPutImage(ScrnInfoPtr  pScrn, short src_x, short src_y,
1442                                    short drw_x, short drw_y,
1443                                    short src_w, short src_h, 
1444                                    short drw_w, short drw_h,
1445                                    int id,
1446                                    unsigned char *buf, 
1447                                    short width, short height, 
1448                                    Bool         Sync, /*FIXME: need to honor the Sync*/
1449                                    RegionPtr    clipBoxes,
1450                                    pointer      data,
1451                                    DrawablePtr  pDraw
1452 )
1453 {
1454         NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1455         NVPtr pNv = NVPTR(pScrn);
1456         INT32 xa = 0, xb = 0, ya = 0, yb = 0; //source box
1457         int newFBSize = 0, newTTSize = 0; //size to allocate in VRAM and in GART respectively
1458         int offset = 0, s2offset = 0, s3offset = 0; //card VRAM offset, source offsets for U and V planes
1459         int srcPitch = 0, srcPitch2 = 0, dstPitch = 0; //source pitch, source pitch of U and V planes in case of YV12, VRAM destination pitch
1460         int top = 0, left = 0, right = 0, bottom = 0, npixels = 0, nlines = 0; //position of the given source data (using src_*), number of pixels and lines we are interested in
1461         Bool skip = FALSE;
1462         BoxRec dstBox;
1463         CARD32 tmp = 0;
1464         int line_len = 0; //length of a line, like npixels, but in bytes 
1465         int DMAoffset = 0; //additional VRAM offset to start the DMA copy to
1466         int UVDMAoffset = 0;
1467         NVAllocRec * destination_buffer = NULL;
1468         unsigned char * video_mem_destination = NULL;  
1469         int action_flags; //what shall we do?
1470         
1471         
1472         if (pPriv->grabbedByV4L)
1473                 return Success;
1474
1475         
1476         NV_set_action_flags(pNv, pScrn, pDraw, pPriv, id, &action_flags);
1477         
1478         if ( NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb, 
1479                                                         &src_x,  &src_y, &src_w, &src_h,
1480                                                         &drw_x, &drw_y, &drw_w, &drw_h, 
1481                                                         &left, &top, &right, &bottom, &dstBox, 
1482                                                         &npixels, &nlines,
1483                                                         clipBoxes, width, height ) )
1484                 {
1485                 return Success;
1486                 }
1487         
1488
1489         if ( NV_calculate_pitches_and_mem_size(action_flags, &srcPitch, &srcPitch2, &dstPitch, 
1490                                                                                 &s2offset, &s3offset, 
1491                                                                                 & newFBSize, &newTTSize ,&line_len ,
1492                                                                                 npixels, nlines, width, height) )
1493                 {
1494                 return BadImplementation;
1495                 }
1496         
1497         /* There are some cases (tvtime with overscan for example) where the input image is larger (width/height) than 
1498                 the source rectangle for the overlay (src_w, src_h). In those cases, we try to do something optimal by uploading only 
1499                 the necessary data. */
1500         if ( action_flags & IS_YUY2 || action_flags & IS_RGB )
1501                 {
1502                 buf += (top * srcPitch) + left;
1503                 DMAoffset += left + (top * dstPitch);
1504                 }
1505                 
1506         if ( action_flags & IS_YV12 )
1507                 {
1508                 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1509                 s2offset += tmp;
1510                 s3offset += tmp;
1511                         
1512                 if ( action_flags & CONVERT_TO_YUY2 )
1513                         {
1514                         DMAoffset += (left << 1) + (top * dstPitch);
1515                         }
1516                         
1517                 else
1518                         {
1519                         //real YV12 - we offset only the luma plane, and copy the whole color plane, for easiness
1520                         DMAoffset += left + (top * dstPitch);
1521                         UVDMAoffset += left + (top >> 1) * dstPitch;
1522                         }       
1523                 }
1524         
1525         pPriv->video_mem = NVAllocateVideoMemory(pScrn, pPriv->video_mem, 
1526                                                               newFBSize);
1527         if (!pPriv->video_mem)
1528                 return BadAlloc;
1529
1530         offset = pPriv->video_mem->offset;
1531         
1532         /*The overlay supports hardware double buffering. We handle this here*/
1533         if (pPriv->doubleBuffer) {
1534                 int mask = 1 << (pPriv->currentBuffer << 2);
1535                 /* overwrite the newest buffer if there's not one free */
1536                 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1537                         if (!pPriv->currentBuffer)
1538                                 offset += newFBSize >> 1;
1539                         skip = TRUE;
1540                 } 
1541                 else 
1542                         if (pPriv->currentBuffer)
1543                                 offset += newFBSize >> 1;
1544                 }
1545
1546         /*Now we take a decision regarding the way we send the data to the card.
1547         Either we use double buffering of "private" TT memory
1548         Either we rely on X's GARTScratch 
1549         Either we fallback on CPU copy
1550         */
1551
1552         /* Try to allocate host-side double buffers, unless we have already failed*/
1553         /* We take only nlines * line_len bytes - that is, only the pixel data we are interested in - because the stuff in the GART is 
1554                  written contiguously */
1555         if ( pPriv -> currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1556                 {
1557                 pPriv->TT_mem_chunk[0] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[0], 
1558                                                               newTTSize);
1559                 if ( pPriv->TT_mem_chunk[0] )
1560                         {
1561                         pPriv->TT_mem_chunk[1] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[1], 
1562                                                               newTTSize);
1563                         
1564                         if ( ! pPriv->TT_mem_chunk[1] )
1565                                 {
1566                                 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
1567                                 pPriv->TT_mem_chunk[0] = NULL;
1568                                 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1569                                 //xf86DrvMsg(0, X_INFO, "Alloc 1 failed\n");
1570                                 }
1571                         }
1572                 else 
1573                         {
1574                         pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1575                         //xf86DrvMsg(0, X_INFO, "Alloc 0 failed\n");
1576                         }
1577                 }
1578         
1579         if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1580                 { //if we have a private buffer
1581                 destination_buffer = pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1582                 //xf86DrvMsg(0, X_INFO, "Using private mem chunk #%d\n", pPriv->currentHostBuffer);
1583                         
1584                 /* We know where we are going to write, but we are not sure yet whether we can do it directly, because
1585                         the card could be working on the buffer for the last-but-one frame. So we check if we have a notifier ready or not. 
1586                         If we do, then we must wait for it before overwriting the buffer.
1587                         Else we need one, so we call the Xv notifier allocator.*/
1588                 if ( pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1589                         {
1590                         //xf86DrvMsg(0, X_INFO, "Waiting for notifier %p (%d)\n", pPriv->DMANotifier[pPriv->currentHostBuffer], pPriv->currentHostBuffer);
1591                         if (!NVNotifierWaitStatus(pScrn, pPriv->DMANotifier[pPriv->currentHostBuffer], 0, 0))
1592                                 return FALSE;
1593                         }
1594                 else 
1595                         {
1596                         //xf86DrvMsg(0, X_INFO, "Allocating notifier...\n");
1597                         pPriv->DMANotifier [ pPriv->currentHostBuffer ] = NVXvDMANotifierAlloc(pScrn);
1598                         if (! pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1599                                 { /* In case we are out of notifiers (then our guy is watching 3 movies at a time!!), we fallback on global GART, and free the private buffers.
1600                                         I know that's a lot of code but I believe it's necessary to properly handle all the cases*/
1601                                 xf86DrvMsg(0, X_ERROR, "Ran out of Xv notifiers!\n");
1602                                 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
1603                                 pPriv->TT_mem_chunk[0] = NULL;
1604                                 NVFreeMemory(pNv, pPriv->TT_mem_chunk[1]);
1605                                 pPriv->TT_mem_chunk[1] = NULL;
1606                                 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1607                                 }
1608                         //xf86DrvMsg(0, X_INFO, "Got notifier %p\n", pPriv->DMANotifier [ pPriv->currentHostBuffer ]);
1609                         }
1610                 }
1611         
1612         if ( pPriv -> currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE )
1613                 { //otherwise we fall back on DDX's GARTScratch
1614                 destination_buffer = pNv->GARTScratch;
1615                 //xf86DrvMsg(0, X_INFO, "Using global GART memory chunk\n");
1616                 }
1617
1618         if ( !destination_buffer) //if we have no GART at all
1619                 goto CPU_copy;
1620         
1621         if(newTTSize <= destination_buffer->size)
1622                 {
1623                 unsigned char *dst = destination_buffer->map;
1624                 int i = 0;
1625                         
1626                 /* Upload to GART */
1627                 if ( action_flags & IS_YV12)
1628                         {
1629                         if ( action_flags & CONVERT_TO_YUY2 )
1630                                 {
1631                                 NVCopyData420(buf + (top * srcPitch) + left,
1632                                 buf + s2offset, buf + s3offset,
1633                                 dst, srcPitch, srcPitch2,
1634                                 line_len, nlines, npixels);
1635                                 }
1636                         else
1637                                 { /*Native YV12*/
1638                                 unsigned char * tbuf = buf + top * srcPitch + left;
1639                                 unsigned char * tdst = dst;
1640                                 //xf86DrvMsg(0, X_INFO, "srcPitch %d dstPitch %d srcPitch2 %d nlines %d npixels %d left %d top %d s2offset %d\n", srcPitch, dstPitch, srcPitch2, nlines, npixels, left, top, s2offset);
1641                                 /* luma upload */
1642                                 for ( i=0; i < nlines; i++)
1643                                         {
1644                                         memcpy(tdst, tbuf, line_len);
1645                                         tdst += line_len;
1646                                         tbuf += srcPitch;
1647                                         }
1648                                 dst += line_len * nlines;
1649                                 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, dst, line_len, srcPitch2, nlines, line_len);
1650                                 }
1651                         }
1652                 else 
1653                         {
1654                         for ( i=0; i < nlines; i++)
1655                                 {
1656                                 memcpy(dst, buf, line_len);
1657                                 dst += line_len;
1658                                 buf += srcPitch;
1659                                 }
1660                         }
1661                 
1662                 
1663                 BEGIN_RING(NvMemFormat,
1664                            NV_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
1665                 OUT_RING  (NvDmaTT);
1666                 OUT_RING  (NvDmaFB);
1667                 pNv->M2MFDirection = 1;
1668                 
1669                 /* DMA to VRAM */
1670                 if ( action_flags & IS_YV12 && ! (action_flags & CONVERT_TO_YUY2) )
1671                         { /*we start the color plane transfer separately*/
1672                         BEGIN_RING(NvMemFormat,
1673                                    NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1674                         OUT_RING  ((uint32_t)destination_buffer->offset + line_len * nlines);
1675                         OUT_RING  ((uint32_t)offset + dstPitch * nlines);
1676                         OUT_RING  (line_len);
1677                         OUT_RING  (dstPitch);
1678                         OUT_RING  (line_len);
1679                         OUT_RING  ((nlines >> 1));
1680                         OUT_RING  ((1<<8)|1);
1681                         OUT_RING  (0);
1682                         FIRE_RING();            
1683                         }
1684                                 
1685                 BEGIN_RING(NvMemFormat,
1686                            NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1687                 OUT_RING  ((uint32_t)destination_buffer->offset);
1688                 OUT_RING  ((uint32_t)offset /*+ DMAoffset*/);
1689                 OUT_RING  (line_len);
1690                 OUT_RING  (dstPitch);
1691                 OUT_RING  (line_len);
1692                 OUT_RING  (nlines);
1693                 OUT_RING  ((1<<8)|1);
1694                 OUT_RING  (0);
1695                         
1696                 if ( destination_buffer == pNv->GARTScratch ) 
1697                         {
1698                         NVNotifierReset(pScrn, pNv->Notifier0);
1699                         }
1700                 else {
1701                         NVNotifierReset(pScrn, pPriv->DMANotifier[pPriv->currentHostBuffer]);
1702                         BEGIN_RING(NvMemFormat,
1703                                    NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1704                         OUT_RING  (pPriv->DMANotifier[pPriv->currentHostBuffer]->handle);
1705                         }
1706                         
1707                         
1708                 BEGIN_RING(NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1709                 OUT_RING  (0);
1710                         
1711                 BEGIN_RING(NvMemFormat, 0x100, 1);
1712                 OUT_RING  (0);
1713                                 
1714                 //Put back NvDmaNotifier0 for EXA
1715                 BEGIN_RING(NvMemFormat,
1716                            NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1717                 OUT_RING  (NvDmaNotifier0);
1718                 
1719                 FIRE_RING();                    
1720
1721                 if ( destination_buffer == pNv->GARTScratch ) 
1722                         if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 0))
1723                                 return FALSE;
1724                 }
1725         else { //GART is too small, we fallback on CPU copy
1726                 CPU_copy:
1727                 video_mem_destination = pPriv->video_mem->map + (offset - (uint32_t)pPriv->video_mem->offset);
1728                 int i = 0;
1729                 if ( action_flags & IS_YV12 )
1730                         {
1731                         if ( action_flags & CONVERT_TO_YUY2 )
1732                                 {
1733                                 NVCopyData420(buf + (top * srcPitch) + left,
1734                                         buf + s2offset, buf + s3offset,
1735                                         video_mem_destination, srcPitch, srcPitch2,
1736                                         dstPitch, nlines, npixels);
1737                                 }
1738                         else {
1739                                 unsigned char * tbuf = buf + left + top * srcPitch;
1740                                 for ( i=0; i < nlines; i++)
1741                                 {
1742                                 int dwords = npixels << 1;
1743                                 while (dwords & ~0x03) 
1744                                         {
1745                                         *video_mem_destination = *tbuf;
1746                                         *(video_mem_destination + 1) = *(tbuf + 1);
1747                                         *(video_mem_destination + 2) = *(tbuf + 2);
1748                                         *(video_mem_destination + 3) = *(tbuf + 3);
1749                                         video_mem_destination += 4;
1750                                         tbuf += 4;
1751                                         dwords -= 4;
1752                                         }
1753                                 switch ( dwords ) 
1754                                         {
1755                                         case 3:
1756                                                 *(video_mem_destination + 2) = *(tbuf + 2);
1757                                         case 2:
1758                                                 *(video_mem_destination + 1) = *(tbuf + 1);
1759                                         case 1:
1760                                                 *video_mem_destination = *tbuf;
1761                                         }
1762                                 
1763                                 video_mem_destination += dstPitch - (npixels << 1);
1764                                 tbuf += srcPitch - (npixels << 1);
1765                                 }
1766                                 
1767                                 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, video_mem_destination, dstPitch, srcPitch2, nlines, line_len);
1768                                 }
1769                         }
1770                 else //YUY2 and RGB
1771                         {
1772                         for ( i=0; i < nlines; i++)
1773                                 {
1774                                 int dwords = npixels << 1;
1775                                 while (dwords & ~0x03) 
1776                                         {
1777                                         *video_mem_destination = *buf;
1778                                         *(video_mem_destination + 1) = *(buf + 1);
1779                                         *(video_mem_destination + 2) = *(buf + 2);
1780                                         *(video_mem_destination + 3) = *(buf + 3);
1781                                         video_mem_destination += 4;
1782                                         buf += 4;
1783                                         dwords -= 4;
1784                                         }
1785                                 switch ( dwords ) 
1786                                         {
1787                                         case 3:
1788                                                 *(video_mem_destination + 2) = *(buf + 2);
1789                                         case 2:
1790                                                 *(video_mem_destination + 1) = *(buf + 1);
1791                                         case 1:
1792                                                 *video_mem_destination = *buf;
1793                                         }
1794                                 
1795                                 video_mem_destination += dstPitch - (npixels << 1);
1796                                 buf += srcPitch - (npixels << 1);
1797                                 }
1798                         }
1799                 } //CPU copy
1800                 
1801
1802         if (!skip) 
1803                 {
1804                 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1805                         pPriv->currentHostBuffer ^= 1;
1806                 
1807                 if ( action_flags & USE_OVERLAY )
1808                         {
1809                         if ( pNv->Architecture == NV_ARCH_04 )
1810                                 NV04PutOverlayImage(pScrn, offset, id,
1811                                           dstPitch, &dstBox, 
1812                                           0,0, xb, yb,
1813                                           npixels, nlines,
1814                                           src_w, src_h, drw_w, drw_h,
1815                                           clipBoxes);
1816                         else
1817                                 NVPutOverlayImage(pScrn, offset, ((action_flags & IS_YUY2) || (action_flags & CONVERT_TO_YUY2)) ? 0 : offset + nlines * dstPitch, id,
1818                                           dstPitch, &dstBox, 
1819                                           0,0, xb, yb,
1820                                           npixels, nlines,
1821                                           src_w, src_h, drw_w, drw_h,
1822                                           clipBoxes);
1823                         pPriv->currentBuffer ^= 1;
1824
1825                         }
1826                 else 
1827                         { //Blitter
1828                         NVPutBlitImage(pScrn, offset, id,
1829                                        dstPitch, &dstBox,
1830                                        0, 0, xb, yb,
1831                                        npixels, nlines,
1832                                        src_w, src_h, drw_w, drw_h,
1833                                        clipBoxes, pDraw);
1834                         }
1835                 }
1836         return Success;
1837 }
1838
1839 /**
1840  * QueryImageAttributes
1841  * 
1842  * calculates
1843  * - size (memory required to store image),
1844  * - pitches,
1845  * - offsets
1846  * of image
1847  * depending on colorspace (id) and dimensions (w,h) of image
1848  * values of
1849  * - w,
1850  * - h
1851  * may be adjusted as needed
1852  * 
1853  * @param pScrn unused
1854  * @param id colorspace of image
1855  * @param w pointer to width of image
1856  * @param h pointer to height of image
1857  * @param pitches pitches[i] = length of a scanline in plane[i]
1858  * @param offsets offsets[i] = offset of plane i from the beginning of the image
1859  * @return size of the memory required for the XvImage queried
1860  */
1861 static int
1862 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id, 
1863                        unsigned short *w, unsigned short *h, 
1864                        int *pitches, int *offsets)
1865 {
1866         int size, tmp;
1867
1868         if (*w > IMAGE_MAX_W)
1869                 *w = IMAGE_MAX_W;
1870         if (*h > IMAGE_MAX_H)
1871                 *h = IMAGE_MAX_H;
1872
1873         *w = (*w + 1) & ~1; // width rounded up to an even number
1874         if (offsets)
1875                 offsets[0] = 0;
1876
1877         switch (id) {
1878         case FOURCC_YV12:
1879         case FOURCC_I420:
1880                 *h = (*h + 1) & ~1; // height rounded up to an even number
1881                 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1882                 if (pitches)
1883                         pitches[0] = size; // width rounded up to a multiple of 4
1884                 size *= *h;
1885                 if (offsets)
1886                         offsets[1] = size; // number of pixels in "rounded up" image
1887                 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1888                 if (pitches)
1889                         pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1890                 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1891                 size += tmp; // 5/4*number of pixels in "rounded up" image
1892                 if (offsets)
1893                         offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1894                 size += tmp; // = 3/2*number of pixels in "rounded up" image
1895                 break;
1896         case FOURCC_UYVY:
1897         case FOURCC_YUY2:
1898                 size = *w << 1; // 2*width
1899                 if (pitches)
1900                         pitches[0] = size; // 2*width
1901                 size *= *h; // 2*width*height
1902                 break;
1903         case FOURCC_RGB:
1904                 size = *w << 2; // 4*width (32 bit per pixel)
1905                 if (pitches)
1906                         pitches[0] = size; // 4*width
1907                 size *= *h; // 4*width*height
1908                 break;
1909         default:
1910                 *w = *h = size = 0;
1911                 break;
1912         }
1913
1914         return size;
1915 }
1916
1917 /***** Exported offscreen surface stuff ****/
1918
1919
1920 static int
1921 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1922                unsigned short w, unsigned short h,
1923                XF86SurfacePtr surface)
1924 {
1925         NVPtr pNv = NVPTR(pScrn);
1926         NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 
1927         int size, bpp;
1928
1929         bpp = pScrn->bitsPerPixel >> 3;
1930
1931         if (pPriv->grabbedByV4L)
1932                 return BadAlloc;
1933
1934         if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1935                 return BadValue;
1936
1937         w = (w + 1) & ~1;
1938         pPriv->pitch = ((w << 1) + 63) & ~63;
1939         size = h * pPriv->pitch / bpp;
1940
1941         pPriv->video_mem = NVAllocateVideoMemory(pScrn,
1942                                                    pPriv->video_mem,
1943                                                    size);
1944         if (!pPriv->video_mem)
1945                 return BadAlloc;
1946
1947         pPriv->offset = 0;
1948         
1949         surface->width = w;
1950         surface->height = h;
1951         surface->pScrn = pScrn;
1952         surface->pitches = &pPriv->pitch; 
1953         surface->offsets = &pPriv->offset;
1954         surface->devPrivate.ptr = (pointer)pPriv;
1955         surface->id = id;
1956
1957         /* grab the video */
1958         NVStopOverlay(pScrn);
1959         pPriv->videoStatus = 0;
1960         REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1961         pPriv->grabbedByV4L = TRUE;
1962
1963         return Success;
1964 }
1965
1966 static int
1967 NVStopSurface(XF86SurfacePtr surface)
1968 {
1969         NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1970
1971         if (pPriv->grabbedByV4L && pPriv->videoStatus) {
1972                 NVStopOverlay(surface->pScrn);
1973                 pPriv->videoStatus = 0;
1974         }
1975
1976         return Success;
1977 }
1978
1979 static int 
1980 NVFreeSurface(XF86SurfacePtr surface)
1981 {
1982         NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1983
1984         if (pPriv->grabbedByV4L) {
1985                 NVStopSurface(surface);
1986                 NVFreeOverlayMemory(surface->pScrn);
1987                 pPriv->grabbedByV4L = FALSE;
1988         }
1989
1990         return Success;
1991 }
1992
1993 static int
1994 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
1995 {
1996         NVPtr pNv = NVPTR(pScrn);
1997         NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1998
1999         return NVGetOverlayPortAttribute(pScrn, attribute,
2000                                          value, (pointer)pPriv);
2001 }
2002
2003 static int
2004 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
2005 {
2006         NVPtr pNv = NVPTR(pScrn);
2007         NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
2008
2009         return NVSetOverlayPortAttribute(pScrn, attribute,
2010                                          value, (pointer)pPriv);
2011 }
2012
2013 static int
2014 NVDisplaySurface(XF86SurfacePtr surface,
2015                  short src_x, short src_y, 
2016                  short drw_x, short drw_y,
2017                  short src_w, short src_h, 
2018                  short drw_w, short drw_h,
2019                  RegionPtr clipBoxes)
2020 {
2021         ScrnInfoPtr pScrn = surface->pScrn;
2022         NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
2023         INT32 xa, xb, ya, yb;
2024         BoxRec dstBox;
2025
2026         if (!pPriv->grabbedByV4L)
2027                 return Success;
2028
2029         if (src_w > (drw_w << 3))
2030                 drw_w = src_w >> 3;
2031         if (src_h > (drw_h << 3))
2032                 drw_h = src_h >> 3;
2033
2034         /* Clip */
2035         xa = src_x;
2036         xb = src_x + src_w;
2037         ya = src_y;
2038         yb = src_y + src_h;
2039
2040         dstBox.x1 = drw_x;
2041         dstBox.x2 = drw_x + drw_w;
2042         dstBox.y1 = drw_y;
2043         dstBox.y2 = drw_y + drw_h;
2044
2045         if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, 
2046                                   surface->width, surface->height))
2047                 return Success;
2048
2049         dstBox.x1 -= pScrn->frameX0;
2050         dstBox.x2 -= pScrn->frameX0;
2051         dstBox.y1 -= pScrn->frameY0;
2052         dstBox.y2 -= pScrn->frameY0;
2053
2054         pPriv->currentBuffer = 0;
2055
2056         NVPutOverlayImage(pScrn, surface->offsets[0], 0, surface->id,
2057                           surface->pitches[0], &dstBox, xa, ya, xb, yb,
2058                           surface->width, surface->height, src_w, src_h,
2059                           drw_w, drw_h, clipBoxes);
2060
2061         return Success;
2062 }
2063
2064 /**
2065  * NVSetupBlitVideo
2066  * this function does all the work setting up a blit port
2067  * 
2068  * @return blit port
2069  */
2070 static XF86VideoAdaptorPtr
2071 NVSetupBlitVideo (ScreenPtr pScreen)
2072 {
2073         ScrnInfoPtr         pScrn = xf86Screens[pScreen->myNum];
2074         NVPtr               pNv       = NVPTR(pScrn);
2075         XF86VideoAdaptorPtr adapt;
2076         NVPortPrivPtr       pPriv;
2077         int i;
2078
2079         if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2080                                         sizeof(NVPortPrivRec) +
2081                                         (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
2082                 return NULL;
2083         }
2084
2085         adapt->type             = XvWindowMask | XvInputMask | XvImageMask;
2086         adapt->flags            = 0;
2087         adapt->name             = "NV Video Blitter";
2088         adapt->nEncodings       = 1;
2089         adapt->pEncodings       = &DummyEncoding;
2090         adapt->nFormats         = NUM_FORMATS_ALL;
2091         adapt->pFormats         = NVFormats;
2092         adapt->nPorts           = NUM_BLIT_PORTS;
2093         adapt->pPortPrivates    = (DevUnion*)(&adapt[1]);
2094
2095         pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
2096         for(i = 0; i < NUM_BLIT_PORTS; i++)
2097                 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2098
2099         if(pNv->WaitVSyncPossible) {
2100                 adapt->pAttributes = NVBlitAttributes;
2101                 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
2102         } else {
2103                 adapt->pAttributes = NULL;
2104                 adapt->nAttributes = 0;
2105         }
2106
2107         adapt->pImages                  = NVImages;
2108         adapt->nImages                  = NUM_IMAGES_ALL;
2109         adapt->PutVideo                 = NULL;
2110         adapt->PutStill                 = NULL;
2111         adapt->GetVideo                 = NULL;
2112         adapt->GetStill                 = NULL;
2113         adapt->StopVideo                = NVStopBlitVideo;
2114         adapt->SetPortAttribute         = NVSetBlitPortAttribute;
2115         adapt->GetPortAttribute         = NVGetBlitPortAttribute;
2116         adapt->QueryBestSize            = NVQueryBestSize;
2117         adapt->PutImage                 = NVPutImage;
2118         adapt->QueryImageAttributes     = NVQueryImageAttributes;
2119
2120         pPriv->videoStatus              = 0;
2121         pPriv->grabbedByV4L             = FALSE;
2122         pPriv->blitter                  = TRUE;
2123         pPriv->doubleBuffer             = FALSE;
2124         pPriv->SyncToVBlank             = pNv->WaitVSyncPossible;
2125
2126         pNv->blitAdaptor                = adapt;
2127         xvSyncToVBlank                  = MAKE_ATOM("XV_SYNC_TO_VBLANK");
2128
2129         return adapt;
2130 }
2131
2132 /**
2133  * NVSetupOverlayVideo
2134  * this function does all the work setting up an overlay port
2135  * 
2136  * @return overlay port
2137  * @see NVResetVideo(ScrnInfoPtr pScrn)
2138  */
2139 static XF86VideoAdaptorPtr 
2140 NVSetupOverlayVideoAdapter(ScreenPtr pScreen)
2141 {
2142         ScrnInfoPtr         pScrn = xf86Screens[pScreen->myNum];
2143         NVPtr               pNv       = NVPTR(pScrn);
2144         XF86VideoAdaptorPtr adapt;
2145         NVPortPrivPtr       pPriv;
2146
2147         if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + 
2148                                         sizeof(NVPortPrivRec) + 
2149                                         sizeof(DevUnion)))) {
2150                 return NULL;
2151         }
2152
2153         adapt->type             = XvWindowMask | XvInputMask | XvImageMask;
2154         adapt->flags            = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
2155         adapt->name             = "NV Video Overlay";
2156         adapt->nEncodings       = 1;
2157         adapt->pEncodings       = &DummyEncoding;
2158         adapt->nFormats         = NUM_FORMATS_ALL;
2159         adapt->pFormats         = NVFormats;
2160         adapt->nPorts           = 1;
2161         adapt->pPortPrivates    = (DevUnion*)(&adapt[1]);
2162
2163         pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
2164         adapt->pPortPrivates[0].ptr     = (pointer)(pPriv);
2165
2166         adapt->pAttributes              = (pNv->Architecture != NV_ARCH_04) ? NVOverlayAttributes : NV04OverlayAttributes;
2167         adapt->nAttributes              = (pNv->Architecture != NV_ARCH_04) ? NUM_OVERLAY_ATTRIBUTES : NUM_NV04_OVERLAY_ATTRIBUTES;
2168         adapt->pImages                  = NVImages;
2169         adapt->nImages                  = NUM_IMAGES_YUV;
2170         adapt->PutVideo                 = NULL;
2171         adapt->PutStill                 = NULL;
2172         adapt->GetVideo                 = NULL;
2173         adapt->GetStill                 = NULL;
2174         adapt->StopVideo                = NVStopOverlayVideo;
2175         adapt->SetPortAttribute         = NVSetOverlayPortAttribute;
2176         adapt->GetPortAttribute         = NVGetOverlayPortAttribute;
2177         adapt->QueryBestSize            = NVQueryBestSize;
2178         adapt->PutImage                 = NVPutImage;
2179         adapt->QueryImageAttributes     = NVQueryImageAttributes;
2180
2181         pPriv->videoStatus              = 0;
2182         pPriv->currentBuffer            = 0;
2183         pPriv->grabbedByV4L             = FALSE;
2184         pPriv->blitter                  = FALSE;
2185         if ( pNv->Architecture == NV_ARCH_04 )
2186                 pPriv->doubleBuffer             = 0;
2187         
2188         NVSetPortDefaults (pScrn, pPriv);
2189
2190         /* gotta uninit this someplace */
2191         REGION_NULL(pScreen, &pPriv->clip);
2192
2193         pNv->overlayAdaptor     = adapt;
2194
2195         xvColorKey              = MAKE_ATOM("XV_COLORKEY");
2196         if ( pNv->Architecture != NV_ARCH_04 )
2197                 {
2198                 xvBrightness            = MAKE_ATOM("XV_BRIGHTNESS");
2199                 xvDoubleBuffer          = MAKE_ATOM("XV_DOUBLE_BUFFER");
2200                 xvContrast              = MAKE_ATOM("XV_CONTRAST");
2201                 xvSaturation            = MAKE_ATOM("XV_SATURATION");
2202                 xvHue                   = MAKE_ATOM("XV_HUE");
2203                 xvAutopaintColorKey     = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
2204                 xvSetDefaults           = MAKE_ATOM("XV_SET_DEFAULTS");
2205                 xvITURBT709             = MAKE_ATOM("XV_ITURBT_709");
2206                 }
2207
2208         NVResetVideo(pScrn);
2209
2210         return adapt;
2211 }
2212
2213
2214 XF86OffscreenImageRec NVOffscreenImages[2] = {
2215         {
2216                 &NVImages[0],
2217                 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2218                 NVAllocSurface,
2219                 NVFreeSurface,
2220                 NVDisplaySurface,
2221                 NVStopSurface,
2222                 NVGetSurfaceAttribute,
2223                 NVSetSurfaceAttribute,
2224                 IMAGE_MAX_W, IMAGE_MAX_H,
2225                 NUM_OVERLAY_ATTRIBUTES - 1,
2226                 &NVOverlayAttributes[1]
2227         },
2228         {
2229                 &NVImages[2],
2230                 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2231                 NVAllocSurface,
2232                 NVFreeSurface,
2233                 NVDisplaySurface,
2234                 NVStopSurface,
2235                 NVGetSurfaceAttribute,
2236                 NVSetSurfaceAttribute,
2237                 IMAGE_MAX_W, IMAGE_MAX_H,
2238                 NUM_OVERLAY_ATTRIBUTES - 1,
2239                 &NVOverlayAttributes[1]
2240         }
2241 };
2242
2243 static void
2244 NVInitOffscreenImages (ScreenPtr pScreen)
2245 {
2246         xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
2247 }
2248
2249 /**
2250  * NVChipsetHasOverlay
2251  * 
2252  * newer chips don't support overlay anymore.
2253  * overlay feature is emulated via textures.
2254  * 
2255  * @param pNv 
2256  * @return true, if chipset supports overlay
2257  */
2258 static Bool
2259 NVChipsetHasOverlay(NVPtr pNv)
2260 {
2261         switch (pNv->Architecture) {
2262         case NV_ARCH_04: /*NV04 has a different overlay than NV10+*/
2263         case NV_ARCH_10:
2264         case NV_ARCH_20:
2265         case NV_ARCH_30:
2266                 return TRUE;
2267         case NV_ARCH_40:
2268                 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
2269                         return TRUE;
2270                 break;
2271         default:
2272                 break;
2273         }
2274
2275         return FALSE;
2276 }
2277
2278 /**
2279  * NVSetupOverlayVideo
2280  * check if chipset supports Overlay and CompositeExtension is disabled.
2281  * if so, setup overlay port
2282  * 
2283  * @return overlay port
2284  * @see NVChipsetHasOverlay(NVPtr pNv)
2285  * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
2286  * @see NVInitOffscreenImages(ScreenPtr pScreen)
2287  */
2288 static XF86VideoAdaptorPtr
2289 NVSetupOverlayVideo(ScreenPtr pScreen)
2290 {
2291         ScrnInfoPtr          pScrn = xf86Screens[pScreen->myNum];
2292         XF86VideoAdaptorPtr  overlayAdaptor = NULL;
2293         NVPtr                pNv   = NVPTR(pScrn);
2294
2295         if (!NVChipsetHasOverlay(pNv))
2296                 return NULL;
2297
2298         overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen);
2299         if (overlayAdaptor && pNv->Architecture != NV_ARCH_04 )
2300                 NVInitOffscreenImages(pScreen); //I am not sure what this call does.
2301         
2302         #ifdef COMPOSITE
2303         if (!noCompositeExtension) {
2304                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2305                         "XV: Composite is enabled, enabling overlay with smart blitter fallback\n");
2306                 overlayAdaptor -> name = "NV Video Overlay with Composite";
2307         }
2308         #endif
2309
2310         return overlayAdaptor;
2311 }
2312
2313 /**
2314  * NVInitVideo
2315  * tries to initialize one new overlay port and one new blit port
2316  * and add them to the list of ports on screen "pScreen".
2317  * 
2318  * @param pScreen
2319  * @see NVSetupOverlayVideo(ScreenPtr pScreen)
2320  * @see NVSetupBlitVideo(ScreenPtr pScreen)
2321  */
2322 void NVInitVideo (ScreenPtr pScreen)
2323 {
2324         ScrnInfoPtr          pScrn = xf86Screens[pScreen->myNum];
2325         NVPtr                pNv = NVPTR(pScrn);
2326         XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
2327         XF86VideoAdaptorPtr  overlayAdaptor = NULL;
2328         XF86VideoAdaptorPtr  blitAdaptor = NULL;
2329         int                  num_adaptors;
2330
2331         /*
2332          * Driving the blitter requires the DMA FIFO. Using the FIFO
2333          * without accel causes DMA errors. While the overlay might
2334          * might work without accel, we also disable it for now when
2335          * acceleration is disabled:
2336          */
2337         if (pScrn->bitsPerPixel != 8 && pNv->Architecture < NV_ARCH_50 && !pNv->NoAccel) {
2338                 overlayAdaptor = NVSetupOverlayVideo(pScreen);
2339                 blitAdaptor    = NVSetupBlitVideo(pScreen);
2340         }
2341
2342         num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
2343         if(blitAdaptor || overlayAdaptor) {
2344                 int size = num_adaptors;
2345
2346                 if(overlayAdaptor) size++;
2347                 if(blitAdaptor)    size++;
2348
2349                 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
2350                 if(newAdaptors) {
2351                         if(num_adaptors) {
2352                                 memcpy(newAdaptors, adaptors, num_adaptors *
2353                                                 sizeof(XF86VideoAdaptorPtr));
2354                         }
2355
2356                         if(overlayAdaptor) {
2357                                 newAdaptors[num_adaptors] = overlayAdaptor;
2358                                 num_adaptors++;
2359                         }
2360
2361                         if(blitAdaptor) {
2362                                 newAdaptors[num_adaptors] = blitAdaptor;
2363                                 num_adaptors++;
2364                         }
2365
2366                         adaptors = newAdaptors;
2367                 }
2368         }
2369
2370         if (num_adaptors)
2371                 xf86XVScreenInit(pScreen, adaptors, num_adaptors);
2372         if (newAdaptors)
2373                 xfree(newAdaptors);
2374 }
2375