7 #include "xf86_OSproc.h"
8 #include "xf86Resources.h"
10 #include "xf86PciInfo.h"
12 #include "xf86fbman.h"
13 #include "regionstr.h"
16 #include <X11/extensions/Xv.h>
21 #include "dixstruct.h"
24 #include "nv_include.h"
27 #define IMAGE_MAX_W 2046
28 #define IMAGE_MAX_H 2046
30 #define OFF_DELAY 500 /* milliseconds */
31 #define FREE_DELAY 5000
33 #define OFF_TIMER 0x01
34 #define FREE_TIMER 0x02
35 #define CLIENT_VIDEO_ON 0x04
37 #define TIMER_MASK (OFF_TIMER | FREE_TIMER)
39 #define NUM_BLIT_PORTS 32
41 /* Value taken by pPriv -> currentHostBuffer when we failed to allocate the two private buffers in TT memory, so that we can catch this case
42 and attempt no other allocation afterwards (performance reasons) */
43 #define NO_PRIV_HOST_BUFFER_AVAILABLE 9999
45 typedef struct _NVPortPrivRec {
52 Bool autopaintColorKey;
61 NVAllocRec * video_mem;
64 NVAllocRec * TT_mem_chunk[2];
65 int currentHostBuffer;
66 struct drm_nouveau_notifierobj_alloc *DMANotifier[2];
67 } NVPortPrivRec, *NVPortPrivPtr;
70 /* Xv DMA notifiers status tracing */
73 XV_DMA_NOTIFIER_NOALLOC=0, //notifier not allocated
74 XV_DMA_NOTIFIER_INUSE=1,
75 XV_DMA_NOTIFIER_FREE=2, //notifier allocated, ready for use
78 /* We have six notifiers available, they are not allocated at startup */
79 int XvDMANotifierStatus[6]= { XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC ,
80 XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC };
81 struct drm_nouveau_notifierobj_alloc * XvDMANotifiers[6];
83 /* NVPutImage action flags */
90 IS_RGB=32, //I am not sure how long we will support it
93 #define GET_OVERLAY_PRIVATE(pNv) \
94 (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr)
96 #define GET_BLIT_PRIVATE(pNv) \
97 (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr)
99 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
101 static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
102 xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
103 xvITURBT709, xvSyncToVBlank;
105 /* client libraries expect an encoding */
106 static XF86VideoEncodingRec DummyEncoding =
110 IMAGE_MAX_W, IMAGE_MAX_H,
114 #define NUM_FORMATS_ALL 6
116 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
118 {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
119 {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
122 #define NUM_OVERLAY_ATTRIBUTES 9
123 XF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] =
125 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
126 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
127 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
128 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
129 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
130 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
131 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
132 {XvSettable | XvGettable, 0, 360, "XV_HUE"},
133 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"}
136 #define NUM_BLIT_ATTRIBUTES 2
137 XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
139 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
140 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
144 #define NUM_IMAGES_YUV 4
145 #define NUM_IMAGES_ALL 5
147 #define FOURCC_RGB 0x0000003
148 #define XVIMAGE_RGB \
153 { 0x03, 0x00, 0x00, 0x00, \
154 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
158 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
163 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}, \
167 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
177 NVWaitVSync(ScrnInfoPtr pScrn)
179 NVPtr pNv = NVPTR(pScrn);
181 NVDmaStart(pNv, NvImageBlit, 0x0000012C, 1);
183 NVDmaStart(pNv, NvImageBlit, 0x00000134, 1);
184 /* If crtc1 is active, this will produce one, otherwise zero */
185 /* The assumption is that at least one is active */
186 NVDmaNext (pNv, pNv->crtc_active[1]);
187 NVDmaStart(pNv, NvImageBlit, 0x00000100, 1);
189 NVDmaStart(pNv, NvImageBlit, 0x00000130, 1);
195 * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
197 * @param pScrn screen to get the default colorKey from
198 * @param pPriv port to reset to defaults
201 NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
203 NVPtr pNv = NVPTR(pScrn);
205 pPriv->brightness = 0;
206 pPriv->contrast = 4096;
207 pPriv->saturation = 4096;
209 pPriv->colorKey = pNv->videoKey;
210 pPriv->autopaintColorKey = TRUE;
211 pPriv->doubleBuffer = TRUE;
212 pPriv->iturbt_709 = FALSE;
213 pPriv->currentHostBuffer = 0;
218 * writes the current attributes from the overlay port to the hardware
221 NVResetVideo (ScrnInfoPtr pScrn)
223 NVPtr pNv = NVPTR(pScrn);
224 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
225 int satSine, satCosine;
228 angle = (double)pPriv->hue * 3.1415927 / 180.0;
230 satSine = pPriv->saturation * sin(angle);
233 satCosine = pPriv->saturation * cos(angle);
234 if (satCosine < -1024)
237 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
239 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
241 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
242 (satCosine & 0xffff));
243 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
244 (satCosine & 0xffff));
245 nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
250 * Tell the hardware to stop the overlay
253 NVStopOverlay (ScrnInfoPtr pScrn)
255 NVPtr pNv = NVPTR(pScrn);
257 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
261 * NVXvDMANotifierAlloc
262 * allocates a notifier from the table of 6 we have
264 * @return a notifier instance or NULL on error
266 static struct drm_nouveau_notifierobj_alloc * NVXvDMANotifierAlloc(ScrnInfoPtr pScrn)
269 for ( i = 0; i < 6; i ++ )
271 if ( XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_INUSE )
274 if ( XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_FREE )
276 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
277 return XvDMANotifiers[i];
280 if ( XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_NOALLOC )
282 XvDMANotifiers[i] = NVNotifierAlloc(pScrn, NvDmaXvNotifier0 + i);
283 if (XvDMANotifiers[i])
285 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
286 return XvDMANotifiers[i];
296 * NVXvDMANotifierFree
297 * frees a notifier from the table of 6 we have
301 static void NVXvDMANotifierFree(ScrnInfoPtr pScrn, struct drm_nouveau_notifierobj_alloc * target)
304 for ( i = 0; i < 6; i ++ )
306 if ( XvDMANotifiers[i] == target )
309 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_FREE;
313 * NVAllocateVideoMemory
314 * allocates video memory for a given port
316 * @param pScrn screen which requests the memory
317 * @param mem pointer to previously allocated memory for reallocation
318 * @param size size of requested memory segment
319 * @return pointer to the allocated memory
322 NVAllocateVideoMemory(ScrnInfoPtr pScrn, NVAllocRec *mem, int size)
324 NVPtr pNv = NVPTR(pScrn);
328 if(mem->size >= size)
330 NVFreeMemory(pNv, mem);
333 return NVAllocateMemory(pNv, NOUVEAU_MEM_FB, size); /* align 32? */
338 * allocates TT memory for a given port
340 * @param pScrn screen which requests the memory
341 * @param mem pointer to previously allocated memory for reallocation
342 * @param size size of requested memory segment
343 * @return pointer to the allocated memory
346 NVAllocateTTMemory(ScrnInfoPtr pScrn, NVAllocRec *mem, int size)
348 NVPtr pNv = NVPTR(pScrn);
352 if(mem->size >= size)
354 NVFreeMemory(pNv, mem);
356 return NVAllocateMemory(pNv, NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE, size); /* align 32? */
361 * frees memory held by a given port
363 * @param pScrn screen whose port wants to free memory
364 * @param pPriv port to free memory of
367 NVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
369 NVPtr pNv = NVPTR(pScrn);
371 //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]);
373 if(pPriv->video_mem) {
374 NVFreeMemory(pNv, pPriv->video_mem);
375 pPriv->video_mem = NULL;
378 if ( pPriv->TT_mem_chunk[ 0 ] && pPriv->DMANotifier [ 0 ] )
380 NVNotifierWaitStatus(pScrn, pPriv->DMANotifier [ 0 ] , 0, 1000);
383 if ( pPriv->TT_mem_chunk[ 1 ] && pPriv->DMANotifier [ 1 ] )
385 NVNotifierWaitStatus(pScrn, pPriv->DMANotifier [ 1 ] , 0, 1000);
388 if(pPriv->TT_mem_chunk[0]) {
389 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
390 pPriv->TT_mem_chunk[0] = NULL;
393 if(pPriv->TT_mem_chunk[1]) {
394 NVFreeMemory(pNv, pPriv->TT_mem_chunk[1]);
395 pPriv->TT_mem_chunk[1] = NULL;
398 if(pPriv->DMANotifier[0]) {
399 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[0]);
400 pPriv->DMANotifier[0] = NULL;
403 if(pPriv->DMANotifier[1]) {
404 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[1]);
405 pPriv->DMANotifier[1] = NULL;
411 * NVFreeOverlayMemory
412 * frees memory held by the overlay port
414 * @param pScrn screen whose overlay port wants to free memory
417 NVFreeOverlayMemory(ScrnInfoPtr pScrn)
419 NVPtr pNv = NVPTR(pScrn);
420 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
421 NVFreePortMemory(pScrn, pPriv);
422 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) & 0xEFFFFFFF));
423 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) | 0x10000000));
428 * frees memory held by the blit port
430 * @param pScrn screen whose blit port wants to free memory
433 NVFreeBlitMemory(ScrnInfoPtr pScrn)
435 NVPtr pNv = NVPTR(pScrn);
436 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
437 NVFreePortMemory(pScrn, pPriv);
441 * NVVideoTimerCallback
442 * callback function which perform cleanup tasks (stop overlay, free memory).
443 * within the driver it is only called once from NVBlockHandler in nv_driver.c
446 NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
448 NVPtr pNv = NVPTR(pScrn);
449 NVPortPrivPtr pOverPriv = NULL;
450 NVPortPrivPtr pBlitPriv = NULL;
451 Bool needCallback = FALSE;
456 if (pNv->overlayAdaptor) {
457 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
458 if (!pOverPriv->videoStatus)
462 if (pNv->blitAdaptor) {
463 pBlitPriv = GET_BLIT_PRIVATE(pNv);
464 if (!pBlitPriv->videoStatus)
469 if (pOverPriv->videoTime < currentTime) {
470 if (pOverPriv->videoStatus & OFF_TIMER) {
471 NVStopOverlay(pScrn);
472 pOverPriv->videoStatus = FREE_TIMER;
473 pOverPriv->videoTime = currentTime + FREE_DELAY;
476 if (pOverPriv->videoStatus & FREE_TIMER) {
477 NVFreeOverlayMemory(pScrn);
478 pOverPriv->videoStatus = 0;
486 if (pBlitPriv->videoTime < currentTime) {
487 NVFreeBlitMemory(pScrn);
488 pBlitPriv->videoStatus = 0;
494 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
499 * program hardware to overlay image into front buffer
501 * @param pScrn screen
502 * @param offset card offset to the pixel data
503 * @param id format of image
504 * @param dstPitch pitch of the pixel data in VRAM
505 * @param dstBox destination box
506 * @param x1 first source point - x
507 * @param y1 first source point - y
508 * @param x2 second source point - x
509 * @param y2 second source point - y
510 * @param width width of the source image = x2 - x1
511 * @param height height
512 * @param src_w width of the image data in VRAM
513 * @param src_h height
514 * @param drw_w width of the image to draw to screen
515 * @param drw_h height
516 * @param clipBoxes ???
519 NVPutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
520 int dstPitch, BoxPtr dstBox,
521 int x1, int y1, int x2, int y2,
522 short width, short height,
523 short src_w, short src_h,
524 short drw_w, short drw_h,
527 NVPtr pNv = NVPTR(pScrn);
528 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
529 int buffer = pPriv->currentBuffer;
531 /* paint the color key */
532 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
533 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
534 /* we always paint V4L's color key */
535 if (!pPriv->grabbedByV4L)
536 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
538 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
542 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
548 //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));
550 nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer) , 0);
551 nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer) , offset);
552 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer) , (height << 16) | width);
553 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
554 ((y1 << 4) & 0xffff0000) | (x1 >> 12));
555 nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer) , (src_w << 20) / drw_w);
556 nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer) , (src_h << 20) / drw_h);
557 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
558 (dstBox->y1 << 16) | dstBox->x1);
559 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
560 ((dstBox->y2 - dstBox->y1) << 16) |
561 (dstBox->x2 - dstBox->x1));
563 dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; /* use color key */
564 if(id != FOURCC_UYVY)
565 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
566 if(pPriv->iturbt_709)
567 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
569 if( id == FOURCC_YV12 || id == FOURCC_I420 )
570 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
572 /* Those are important only for planar formats (NV12) */
575 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_BASE(buffer), 0);
576 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer), uvoffset);
579 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
580 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
581 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
583 pPriv->videoStatus = CLIENT_VIDEO_ON;
587 NV04PutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
588 int dstPitch, BoxPtr dstBox,
589 int x1, int y1, int x2, int y2,
590 short width, short height,
591 short src_w, short src_h,
592 short drw_w, short drw_h,
595 NVPtr pNv = NVPTR(pScrn);
596 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
597 int buffer = pPriv->currentBuffer;
599 /* paint the color key */
600 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
601 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
602 /* we always paint V4L's color key */
603 if (!pPriv->grabbedByV4L)
604 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
606 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
610 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
617 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x224, 0);
618 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x228, 0);
619 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x22C, 0);
620 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x20C + 4*buffer , offset);
621 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x21C + 4*buffer , 0);
622 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x214 + 4*buffer , dstPitch);
623 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x230 , (dstBox->y1 << 16) | dstBox->x1);
624 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x234/* + 4*buffer UNKNOWN*/, (height << 16) | width);
625 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x200/* + 4*buffer UNKNOWN*/, (uint32_t)((src_h - 1 << 11) / (dstBox->y2 - dstBox->y1)) << 16 | (uint32_t)((src_w - 1 << 11) / (dstBox->x2 - dstBox->x1)));
627 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x280, 0x69);
628 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x284, 0x3e);
629 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x288, 0x89);
630 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x28C, 0x0);
632 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x204, 0x001);
633 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x208, 0x111);
635 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x23C, 0x03);
636 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x238, 0x38);
638 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x240, pPriv->colorKey);
640 /*NV_PVIDEO_OVERLAY (KEY_ON, VIDEO_ON, FORMAT_CCIR) */
641 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x240, 0x111);
642 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x228, 1 << 16);
644 /*dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;
645 if(id != FOURCC_UYVY)
646 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
647 if(pPriv->iturbt_709)
648 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
650 if( id == FOURCC_YV12 || id == FOURCC_I420 )
651 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
653 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
654 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
655 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
658 pPriv->videoStatus = CLIENT_VIDEO_ON;
660 #ifndef ExaOffscreenMarkUsed
661 extern void ExaOffscreenMarkUsed(PixmapPtr);
663 #ifndef exaGetDrawablePixmap
664 extern PixmapPtr exaGetDrawablePixmap(DrawablePtr);
666 #ifndef exaPixmapIsOffscreen
667 extern Bool exaPixmapIsOffscreen(PixmapPtr p);
669 /* To support EXA 2.0, 2.1 has this in the header */
670 #ifndef exaMoveInPixmap
671 extern void exaMoveInPixmap(PixmapPtr pPixmap);
677 * @param pScrn screen
679 * @param id colorspace of image
696 NVPutBlitImage(ScrnInfoPtr pScrn, int src_offset, int id,
697 int src_pitch, BoxPtr dstBox,
698 int x1, int y1, int x2, int y2,
699 short width, short height,
700 short src_w, short src_h,
701 short drw_w, short drw_h,
705 NVPtr pNv = NVPTR(pScrn);
706 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
710 CARD32 dst_size, dst_point;
711 CARD32 src_point, src_format;
713 ScreenPtr pScreen = pScrn->pScreen;
714 PixmapPtr pPix = exaGetDrawablePixmap(pDraw);
717 /* Try to get the dest drawable into vram */
718 if (!exaPixmapIsOffscreen(pPix)) {
719 exaMoveInPixmap(pPix);
720 ExaOffscreenMarkUsed(pPix);
723 /* If we failed, draw directly onto the screen pixmap.
724 * Not sure if this is the best approach, maybe failing
725 * with BadAlloc would be better?
727 if (!exaPixmapIsOffscreen(pPix)) {
728 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
729 "XV: couldn't move dst surface into vram\n");
730 pPix = pScreen->GetScreenPixmap(pScreen);
733 NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format);
734 NVAccelSetCtxSurf2D(pPix, pPix, dst_format);
737 /* Adjust coordinates if drawing to an offscreen pixmap */
738 if (pPix->screen_x || pPix->screen_y) {
739 REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
742 dstBox->x1 -= pPix->screen_x;
743 dstBox->x2 -= pPix->screen_x;
744 dstBox->y1 -= pPix->screen_y;
745 dstBox->y2 -= pPix->screen_y;
748 DamageDamageRegion((DrawablePtr)pPix, clipBoxes);
751 pbox = REGION_RECTS(clipBoxes);
752 nbox = REGION_NUM_RECTS(clipBoxes);
754 dsdx = (src_w << 20) / drw_w;
755 dtdy = (src_h << 20) / drw_h;
757 dst_size = ((dstBox->y2 - dstBox->y1) << 16) |
758 (dstBox->x2 - dstBox->x1);
759 dst_point = (dstBox->y1 << 16) | dstBox->x1;
761 src_pitch |= (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER << 16) |
762 (STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR << 24);
763 src_point = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
767 src_format = STRETCH_BLIT_FORMAT_X8R8G8B8;
770 src_format = STRETCH_BLIT_FORMAT_UYVY;
773 src_format = STRETCH_BLIT_FORMAT_YUYV;
777 if(pPriv->SyncToVBlank) {
782 if(pNv->BlendingPossible) {
783 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_FORMAT, 2);
784 NVDmaNext (pNv, src_format);
785 NVDmaNext (pNv, STRETCH_BLIT_OPERATION_COPY);
787 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_FORMAT, 1);
788 NVDmaNext (pNv, src_format);
792 NVDmaStart(pNv, NvRectangle, RECT_SOLID_COLOR, 1);
795 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_CLIP_POINT, 6);
796 NVDmaNext (pNv, (pbox->y1 << 16) | pbox->x1);
797 NVDmaNext (pNv, ((pbox->y2 - pbox->y1) << 16) |
798 (pbox->x2 - pbox->x1));
799 NVDmaNext (pNv, dst_point);
800 NVDmaNext (pNv, dst_size);
801 NVDmaNext (pNv, dsdx);
802 NVDmaNext (pNv, dtdy);
804 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_SRC_SIZE, 4);
805 NVDmaNext (pNv, (height << 16) | width);
806 NVDmaNext (pNv, src_pitch);
807 NVDmaNext (pNv, src_offset);
808 NVDmaNext (pNv, src_point);
814 exaMarkSync(pScrn->pScreen);
816 pPriv->videoStatus = FREE_TIMER;
817 pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
818 pNv->VideoTimerCallback = NVVideoTimerCallback;
825 NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
827 NVPtr pNv = NVPTR(pScrn);
828 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
830 if(pPriv->grabbedByV4L) return;
832 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
835 if (pPriv->videoStatus & CLIENT_VIDEO_ON)
836 NVStopOverlay(pScrn);
837 NVFreeOverlayMemory(pScrn);
838 pPriv->videoStatus = 0;
840 if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
841 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
842 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
843 pNv->VideoTimerCallback = NVVideoTimerCallback;
852 NVStopBlitVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
857 * NVSetOverlayPortAttribute
858 * sets the attribute "attribute" of port "data" to value "value"
859 * calls NVResetVideo(pScrn) to apply changes to hardware
862 * @param attribute attribute to set
863 * @param value value to which attribute is to be set
864 * @param data port from which the attribute is to be set
866 * @return Success, if setting is successful
867 * BadValue/BadMatch, if value/attribute are invalid
868 * @see NVResetVideo(ScrnInfoPtr pScrn)
871 NVSetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
872 INT32 value, pointer data)
874 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
876 if (attribute == xvBrightness) {
877 if ((value < -512) || (value > 512))
879 pPriv->brightness = value;
881 if (attribute == xvDoubleBuffer) {
882 if ((value < 0) || (value > 1))
884 pPriv->doubleBuffer = value;
886 if (attribute == xvContrast) {
887 if ((value < 0) || (value > 8191))
889 pPriv->contrast = value;
891 if (attribute == xvHue) {
897 if (attribute == xvSaturation) {
898 if ((value < 0) || (value > 8191))
900 pPriv->saturation = value;
902 if (attribute == xvColorKey) {
903 pPriv->colorKey = value;
904 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
906 if (attribute == xvAutopaintColorKey) {
907 if ((value < 0) || (value > 1))
909 pPriv->autopaintColorKey = value;
911 if (attribute == xvITURBT709) {
912 if ((value < 0) || (value > 1))
914 pPriv->iturbt_709 = value;
916 if (attribute == xvSetDefaults) {
917 NVSetPortDefaults(pScrn, pPriv);
926 * NVGetOverlayPortAttribute
928 * @param pScrn unused
929 * @param attribute attribute to be read
930 * @param value value of attribute will be stored in this pointer
931 * @param data port from which attribute will be read
932 * @return Success, if queried attribute exists
935 NVGetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
936 INT32 *value, pointer data)
938 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
940 if (attribute == xvBrightness)
941 *value = pPriv->brightness;
942 else if (attribute == xvDoubleBuffer)
943 *value = (pPriv->doubleBuffer) ? 1 : 0;
944 else if (attribute == xvContrast)
945 *value = pPriv->contrast;
946 else if (attribute == xvSaturation)
947 *value = pPriv->saturation;
948 else if (attribute == xvHue)
950 else if (attribute == xvColorKey)
951 *value = pPriv->colorKey;
952 else if (attribute == xvAutopaintColorKey)
953 *value = (pPriv->autopaintColorKey) ? 1 : 0;
954 else if (attribute == xvITURBT709)
955 *value = (pPriv->iturbt_709) ? 1 : 0;
963 * NVSetBlitPortAttribute
964 * sets the attribute "attribute" of port "data" to value "value"
965 * supported attributes:
966 * - xvSyncToVBlank (values: 0,1)
967 * - xvSetDefaults (values: NA; SyncToVBlank will be set, if hardware supports it)
970 * @param attribute attribute to set
971 * @param value value to which attribute is to be set
972 * @param data port from which the attribute is to be set
974 * @return Success, if setting is successful
975 * BadValue/BadMatch, if value/attribute are invalid
978 NVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
979 INT32 value, pointer data)
981 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
982 NVPtr pNv = NVPTR(pScrn);
984 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
985 if ((value < 0) || (value > 1))
987 pPriv->SyncToVBlank = value;
989 if (attribute == xvSetDefaults) {
990 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
998 * NVGetBlitPortAttribute
999 * reads the value of attribute "attribute" from port "data" into INT32 "*value"
1000 * currently only one attribute supported: xvSyncToVBlank
1002 * @param pScrn unused
1003 * @param attribute attribute to be read
1004 * @param value value of attribute will be stored here
1005 * @param data port from which attribute will be read
1006 * @return Success, if queried attribute exists
1009 NVGetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1010 INT32 *value, pointer data)
1012 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1014 if(attribute == xvSyncToVBlank)
1015 *value = (pPriv->SyncToVBlank) ? 1 : 0;
1025 * used by client applications to ask the driver:
1026 * how would you actually scale a video of dimensions
1027 * vid_w, vid_h, if i wanted you to scale it to dimensions
1029 * function stores actual scaling size in pointers p_w, p_h.
1032 * @param pScrn unused
1033 * @param motion unused
1034 * @param vid_w width of source video
1035 * @param vid_h height of source video
1036 * @param drw_w desired scaled width as requested by client
1037 * @param drw_h desired scaled height as requested by client
1038 * @param p_w actual scaled width as the driver is capable of
1039 * @param p_h actual scaled height as the driver is capable of
1040 * @param data unused
1043 NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
1044 short vid_w, short vid_h,
1045 short drw_w, short drw_h,
1046 unsigned int *p_w, unsigned int *p_h,
1049 if(vid_w > (drw_w << 3))
1051 if(vid_h > (drw_h << 3))
1060 * used to convert YV12 to YUY2 for the blitter
1062 * @param src1 source buffer of luma
1063 * @param src2 source buffer of chroma1
1064 * @param src3 source buffer of chroma2
1065 * @param dst1 destination buffer
1066 * @param srcPitch pitch of src1
1067 * @param srcPitch2 pitch of src2, src3
1068 * @param dstPitch pitch of dst1
1069 * @param h number of lines to copy
1070 * @param w length of lines to copy
1072 static inline void NVCopyData420(unsigned char *src1, unsigned char *src2,
1073 unsigned char *src3, unsigned char *dst1,
1074 int srcPitch, int srcPitch2,
1079 CARD8 *s1, *s2, *s3;
1084 for (j = 0; j < h; j++) {
1085 dst = (CARD32*)dst1;
1086 s1 = src1; s2 = src2; s3 = src3;
1090 #if X_BYTE_ORDER == X_BIG_ENDIAN
1091 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
1092 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1];
1093 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2];
1094 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3];
1096 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
1097 dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
1098 dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
1099 dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
1101 dst += 4; s2 += 4; s3 += 4; s1 += 8;
1106 #if X_BYTE_ORDER == X_BIG_ENDIAN
1107 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
1109 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
1125 * NVCopyNV12ColorPlanes
1126 * Used to convert YV12 color planes to NV12 (interleaved UV) for the overlay
1128 * @param src1 source buffer of chroma1
1129 * @param dst1 destination buffer
1130 * @param h number of lines to copy
1131 * @param w length of lines to copy
1132 * @param id source pixel format (YV12 or I420)
1134 static inline void NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char * src2, unsigned char *dst, int dstPitch, int srcPitch2,
1144 for ( j = 0; j < h; j++ )
1146 unsigned char * us = src1;
1147 unsigned char * vs = src2;
1148 unsigned int * vuvud = (unsigned int *) dst;
1149 for ( i = 0; i < l; i++ )
1151 #if X_BYTE_ORDER == X_BIG_ENDIAN
1152 *vuvud++ = (vs[0]<<24) | (us[0]<<16) | (vs[1]<<8) | us[1];
1154 *vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24);
1160 unsigned short *vud = (unsigned short *) vuvud;
1161 #if X_BYTE_ORDER == X_BIG_ENDIAN
1162 *vud = (vs[0]<<8) | (us[0] << 0);
1164 *vud = vs[0] | (us[0]<<8);
1175 static int NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 * xa, INT32 * xb, INT32 * ya, INT32 * yb,
1176 short * src_x, short * src_y, short * src_w, short * src_h,
1177 short * drw_x, short * drw_y, short * drw_w, short * drw_h,
1178 int * left, int * top, int * right, int * bottom,
1180 int * npixels, int * nlines,
1181 RegionPtr clipBoxes, short width, short height
1185 if ( action_flags & USE_OVERLAY )
1186 { /* overlay hardware scaler limitation - copied from nv, UNCHECKED*/
1187 if (*src_w > (*drw_w << 3))
1188 *drw_w = *src_w >> 3;
1189 if (*src_h > (*drw_h << 3))
1190 *drw_h = *src_h >> 3;
1196 *xb = *src_x + *src_w;
1198 *yb = *src_y + *src_h;
1200 dstBox->x1 = *drw_x;
1201 dstBox->x2 = *drw_x + *drw_w;
1202 dstBox->y1 = *drw_y;
1203 dstBox->y2 = *drw_y + *drw_h;
1205 if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
1209 if ( action_flags & USE_OVERLAY )
1211 dstBox->x1 -= pScrn->frameX0;
1212 dstBox->x2 -= pScrn->frameX0;
1213 dstBox->y1 -= pScrn->frameY0;
1214 dstBox->y2 -= pScrn->frameY0;
1219 /* Convert fixed point to integer, as xf86XVClipVideoHelper probably turns its parameter into fixed point values */
1220 *left = (*xa) >> 16;
1221 if (*left < 0) *left = 0;
1223 if (*top < 0) *top = 0;
1224 *right = (*xb) >> 16;
1225 if (*right > width) *right = width;
1226 *bottom = (*yb) >> 16;
1227 if (*bottom > height) *bottom = height;
1229 if ( action_flags & IS_YV12 )
1231 *left &= ~1; //even "left", even "top", even number of pixels per line and even number of lines
1232 *npixels = ((*right + 1) & ~1) - *left;
1234 *nlines = ((*bottom + 1) & ~1) - *top;
1236 else if ( action_flags & IS_YUY2 )
1238 *left &= ~1; //even "left"
1239 *npixels = ((*right + 1) & ~1) - *left; //even number of pixels per line
1240 *nlines = *bottom - *top;
1241 *left <<= 1; //16bpp
1243 else if (action_flags & IS_RGB )
1245 *npixels = *right - *left;
1246 *nlines = *bottom - *top;
1247 *left <<= 2; //32bpp
1253 static int NV_calculate_pitches_and_mem_size(int action_flags, int * srcPitch, int * srcPitch2, int * dstPitch,
1254 int * s2offset, int * s3offset,
1255 int * newFBSize, int * newTTSize,
1256 int * line_len, int npixels, int nlines, int width, int height)
1260 if ( action_flags & IS_YV12 )
1262 *srcPitch = (width + 3) & ~3; /* of luma */
1263 *s2offset = *srcPitch * height;
1264 *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
1265 *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
1266 *dstPitch = (npixels + 63) &~ 63; /*luma and chroma pitch*/
1267 *line_len = npixels;
1268 *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1269 *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1271 else if ( action_flags & IS_YUY2 )
1273 *srcPitch = width << 1; /* one luma, one chroma per pixel */
1274 *dstPitch = ((npixels << 1) + 63) & ~63;
1275 *line_len = npixels << 1;
1276 *newFBSize = nlines * *dstPitch;
1277 *newTTSize = nlines * *line_len;
1279 else if ( action_flags & IS_RGB )
1281 *srcPitch = width << 2; /* one R, one G, one B, one X per pixel */
1282 *dstPitch = ((npixels << 2) + 63) & ~63;
1283 *line_len = npixels << 2;
1284 *newFBSize = nlines * *dstPitch;
1285 *newTTSize = nlines * *dstPitch;
1289 if ( action_flags & CONVERT_TO_YUY2 )
1291 *dstPitch = ((npixels << 1) + 63) & ~63;
1292 *line_len = npixels << 1;
1293 *newFBSize = nlines * *dstPitch;
1294 *newTTSize = nlines * *line_len;
1297 if ( action_flags & SWAP_UV )
1298 { //I420 swaps U and V
1300 *s2offset = *s3offset;
1304 if ( action_flags & USE_OVERLAY ) // overlay double buffering ...
1305 (*newFBSize) <<= 1; // ... means double the amount of VRAM needed
1312 * NV_set_action_flags
1313 * This function computes the action flags from the input image,
1314 * that is, it decides what NVPutImage and its helpers must do.
1315 * This eases readability by avoiding lots of switch-case statements in the core NVPutImage
1317 static void NV_set_action_flags(NVPtr pNv, ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, int id, int * action_flags)
1320 if ( id == FOURCC_YUY2 || id == FOURCC_UYVY )
1321 *action_flags |= IS_YUY2;
1323 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1324 *action_flags |= IS_YV12;
1326 if ( id == FOURCC_RGB ) /*How long will we support it?*/
1327 *action_flags |= IS_RGB;
1329 if ( id == FOURCC_I420 ) /*I420 is YV12 with swapped UV*/
1330 *action_flags |= SWAP_UV;
1332 if ( !pPriv -> blitter )
1333 *action_flags |= USE_OVERLAY;
1336 WindowPtr pWin = NULL;
1338 if (!noCompositeExtension && WindowDrawable(pDraw->type))
1340 pWin = (WindowPtr)pDraw;
1344 if ( pWin->redirectDraw )
1345 *action_flags &= ~USE_OVERLAY;
1349 if ( ! ( *action_flags & USE_OVERLAY) )
1351 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1352 { /*The blitter does not handle YV12 natively*/
1353 *action_flags |= CONVERT_TO_YUY2;
1357 if ( pNv->Architecture == NV_ARCH_03 || pNv->Architecture == NV_ARCH_04 )
1358 if ( * action_flags & IS_YV12 ) //NV04-05 don't support native YV12 AFAIK
1359 *action_flags |= CONVERT_TO_YUY2;
1361 if ( pNv->Architecture == NV_ARCH_10 )
1363 switch ( pNv->Chipset & 0xfff0 )
1368 case CHIPSET_NFORCE: /*XXX: unsure about nforce and nforce2*/
1369 case CHIPSET_NFORCE2:
1370 *action_flags |= CONVERT_TO_YUY2; break;
1380 * PutImage is "the" important function of the Xv extension.
1381 * a client (e.g. video player) calls this function for every
1382 * image (of the video) to be displayed. this function then
1383 * scales and displays the image.
1385 * @param pScrn screen which hold the port where the image is put
1386 * @param src_x source point in the source image to start displaying from
1387 * @param src_y see above
1388 * @param src_w width of the source image to display
1389 * @param src_h see above
1390 * @param drw_x screen point to display to
1392 * @param drw_w width of the screen drawable
1394 * @param id pixel format of image
1395 * @param buf pointer to buffer containing the source image
1396 * @param width total width of the source image we are passed
1398 * @param Sync unused
1399 * @param clipBoxes ??
1400 * @param data pointer to port
1401 * @param pDraw drawable pointer
1404 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
1405 short drw_x, short drw_y,
1406 short src_w, short src_h,
1407 short drw_w, short drw_h,
1410 short width, short height,
1411 Bool Sync, /*FIXME: need to honor the Sync*/
1412 RegionPtr clipBoxes,
1417 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1418 NVPtr pNv = NVPTR(pScrn);
1419 INT32 xa = 0, xb = 0, ya = 0, yb = 0; //source box
1420 int newFBSize = 0, newTTSize = 0; //size to allocate in VRAM and in GART respectively
1421 int offset = 0, s2offset = 0, s3offset = 0; //card VRAM offset, source offsets for U and V planes
1422 int srcPitch = 0, srcPitch2 = 0, dstPitch = 0; //source pitch, source pitch of U and V planes in case of YV12, VRAM destination pitch
1423 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
1427 int line_len = 0; //length of a line, like npixels, but in bytes
1428 int DMAoffset = 0; //additional VRAM offset to start the DMA copy to
1429 int UVDMAoffset = 0;
1430 NVAllocRec * destination_buffer = NULL;
1431 unsigned char * video_mem_destination = NULL;
1432 int action_flags; //what shall we do?
1435 if (pPriv->grabbedByV4L)
1439 NV_set_action_flags(pNv, pScrn, pDraw, pPriv, id, &action_flags);
1441 if ( NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
1442 &src_x, &src_y, &src_w, &src_h,
1443 &drw_x, &drw_y, &drw_w, &drw_h,
1444 &left, &top, &right, &bottom, &dstBox,
1446 clipBoxes, width, height ) )
1452 if ( NV_calculate_pitches_and_mem_size(action_flags, &srcPitch, &srcPitch2, &dstPitch,
1453 &s2offset, &s3offset,
1454 & newFBSize, &newTTSize ,&line_len ,
1455 npixels, nlines, width, height) )
1457 return BadImplementation;
1460 /* There are some cases (tvtime with overscan for example) where the input image is larger (width/height) than
1461 the source rectangle for the overlay (src_w, src_h). In those cases, we try to do something optimal by uploading only
1462 the necessary data. */
1463 if ( action_flags & IS_YUY2 || action_flags & IS_RGB )
1465 buf += (top * srcPitch) + left;
1466 DMAoffset += left + (top * dstPitch);
1469 if ( action_flags & IS_YV12 )
1471 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1475 if ( action_flags & CONVERT_TO_YUY2 )
1477 DMAoffset += (left << 1) + (top * dstPitch);
1482 //real YV12 - we offset only the luma plane, and copy the whole color plane, for easiness
1483 DMAoffset += left + (top * dstPitch);
1484 UVDMAoffset += left + (top >> 1) * dstPitch;
1488 pPriv->video_mem = NVAllocateVideoMemory(pScrn, pPriv->video_mem,
1490 if (!pPriv->video_mem)
1493 offset = pPriv->video_mem->offset;
1495 /*The overlay supports hardware double buffering. We handle this here*/
1496 if (pPriv->doubleBuffer) {
1497 int mask = 1 << (pPriv->currentBuffer << 2);
1499 /* overwrite the newest buffer if there's not one free */
1500 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1501 if (!pPriv->currentBuffer)
1502 offset += newFBSize >> 1;
1506 else if (pPriv->currentBuffer)
1507 offset += newFBSize >> 1;
1510 /*Now we take a decision regarding the way we send the data to the card.
1511 Either we use double buffering of "private" TT memory
1512 Either we rely on X's GARTScratch
1513 Either we fallback on CPU copy
1516 /* Try to allocate host-side double buffers, unless we have already failed*/
1517 /* We take only nlines * line_len bytes - that is, only the pixel data we are interested in - because the stuff in the GART is
1518 written contiguously */
1519 if ( pPriv -> currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1521 pPriv->TT_mem_chunk[0] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[0],
1523 if ( pPriv->TT_mem_chunk[0] )
1525 pPriv->TT_mem_chunk[1] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[1],
1528 if ( ! pPriv->TT_mem_chunk[1] )
1530 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
1531 pPriv->TT_mem_chunk[0] = NULL;
1532 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1533 //xf86DrvMsg(0, X_INFO, "Alloc 1 failed\n");
1538 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1539 //xf86DrvMsg(0, X_INFO, "Alloc 0 failed\n");
1543 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1544 { //if we have a private buffer
1545 destination_buffer = pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1546 //xf86DrvMsg(0, X_INFO, "Using private mem chunk #%d\n", pPriv->currentHostBuffer);
1548 /* We know where we are going to write, but we are not sure yet whether we can do it directly, because
1549 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.
1550 If we do, then we must wait for it before overwriting the buffer.
1551 Else we need one, so we call the Xv notifier allocator.*/
1552 if ( pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1554 //xf86DrvMsg(0, X_INFO, "Waiting for notifier %p (%d)\n", pPriv->DMANotifier[pPriv->currentHostBuffer], pPriv->currentHostBuffer);
1555 if (!NVNotifierWaitStatus(pScrn, pPriv->DMANotifier[pPriv->currentHostBuffer], 0, 0))
1560 //xf86DrvMsg(0, X_INFO, "Allocating notifier...\n");
1561 pPriv->DMANotifier [ pPriv->currentHostBuffer ] = NVXvDMANotifierAlloc(pScrn);
1562 if (! pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1563 { /* 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.
1564 I know that's a lot of code but I believe it's necessary to properly handle all the cases*/
1565 xf86DrvMsg(0, X_ERROR, "Ran out of Xv notifiers!\n");
1566 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
1567 pPriv->TT_mem_chunk[0] = NULL;
1568 NVFreeMemory(pNv, pPriv->TT_mem_chunk[1]);
1569 pPriv->TT_mem_chunk[1] = NULL;
1570 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1572 //xf86DrvMsg(0, X_INFO, "Got notifier %p\n", pPriv->DMANotifier [ pPriv->currentHostBuffer ]);
1576 if ( pPriv -> currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE )
1577 { //otherwise we fall back on DDX's GARTScratch
1578 destination_buffer = pNv->GARTScratch;
1579 //xf86DrvMsg(0, X_INFO, "Using global GART memory chunk\n");
1582 if ( !destination_buffer) //if we have no GART at all
1585 if(newTTSize <= destination_buffer->size)
1587 unsigned char *dst = destination_buffer->map;
1590 /* Upload to GART */
1591 if ( action_flags & IS_YV12)
1593 if ( action_flags & CONVERT_TO_YUY2 )
1595 NVCopyData420(buf + (top * srcPitch) + left,
1596 buf + s2offset, buf + s3offset,
1597 dst, srcPitch, srcPitch2,
1598 line_len, nlines, npixels);
1602 unsigned char * tbuf = buf + top * srcPitch + left;
1603 unsigned char * tdst = dst;
1604 //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);
1606 for ( i=0; i < nlines; i++)
1608 memcpy(tdst, tbuf, line_len);
1612 dst += line_len * nlines;
1613 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, dst, line_len, srcPitch2, nlines, line_len);
1618 for ( i=0; i < nlines; i++)
1620 memcpy(dst, buf, line_len);
1627 NVDmaStart(pNv, NvMemFormat, MEMFORMAT_DMA_OBJECT_IN, 2);
1628 NVDmaNext (pNv, NvDmaTT);
1629 NVDmaNext (pNv, NvDmaFB);
1630 pNv->M2MFDirection = 1;
1633 if ( action_flags & IS_YV12 && ! (action_flags & CONVERT_TO_YUY2) )
1634 { /*we start the color plane transfer separately*/
1635 NVDmaStart(pNv, NvMemFormat,
1636 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1637 NVDmaNext (pNv, (uint32_t)destination_buffer->offset + line_len * nlines);
1638 NVDmaNext (pNv, (uint32_t)offset + dstPitch * nlines);
1639 NVDmaNext (pNv, line_len);
1640 NVDmaNext (pNv, dstPitch);
1641 NVDmaNext (pNv, line_len);
1642 NVDmaNext (pNv, (nlines >> 1));
1643 NVDmaNext (pNv, (1<<8)|1);
1648 NVDmaStart(pNv, NvMemFormat,
1649 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1650 NVDmaNext (pNv, (uint32_t)destination_buffer->offset);
1651 NVDmaNext (pNv, (uint32_t)offset /*+ DMAoffset*/);
1652 NVDmaNext (pNv, line_len);
1653 NVDmaNext (pNv, dstPitch);
1654 NVDmaNext (pNv, line_len);
1655 NVDmaNext (pNv, nlines);
1656 NVDmaNext (pNv, (1<<8)|1);
1659 if ( destination_buffer == pNv->GARTScratch )
1661 NVNotifierReset(pScrn, pNv->Notifier0);
1664 NVNotifierReset(pScrn, pPriv->DMANotifier[pPriv->currentHostBuffer]);
1665 NVDmaStart(pNv, NvMemFormat,
1666 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1667 NVDmaNext (pNv, pPriv->DMANotifier[pPriv->currentHostBuffer]->handle);
1671 NVDmaStart(pNv, NvMemFormat,
1672 NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1675 NVDmaStart(pNv, NvMemFormat, 0x100, 1);
1678 //Put back NvDmaNotifier0 for EXA
1679 NVDmaStart(pNv, NvMemFormat,
1680 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1681 NVDmaNext (pNv, NvDmaNotifier0);
1685 if ( destination_buffer == pNv->GARTScratch )
1686 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 0))
1689 else { //GART is too small, we fallback on CPU copy
1691 video_mem_destination = pPriv->video_mem->map + (offset - (uint32_t)pPriv->video_mem->offset);
1693 if ( action_flags & IS_YV12 )
1695 if ( action_flags & CONVERT_TO_YUY2 )
1697 NVCopyData420(buf + (top * srcPitch) + left,
1698 buf + s2offset, buf + s3offset,
1699 video_mem_destination, srcPitch, srcPitch2,
1700 dstPitch, nlines, npixels);
1703 unsigned char * tbuf = buf + left + top * srcPitch;
1704 for ( i=0; i < nlines; i++)
1706 int dwords = npixels << 1;
1707 while (dwords & ~0x03)
1709 *video_mem_destination = *tbuf;
1710 *(video_mem_destination + 1) = *(tbuf + 1);
1711 *(video_mem_destination + 2) = *(tbuf + 2);
1712 *(video_mem_destination + 3) = *(tbuf + 3);
1713 video_mem_destination += 4;
1720 *(video_mem_destination + 2) = *(tbuf + 2);
1722 *(video_mem_destination + 1) = *(tbuf + 1);
1724 *video_mem_destination = *tbuf;
1727 video_mem_destination += dstPitch - (npixels << 1);
1728 tbuf += srcPitch - (npixels << 1);
1731 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, video_mem_destination, dstPitch, srcPitch2, nlines, line_len);
1736 for ( i=0; i < nlines; i++)
1738 int dwords = npixels << 1;
1739 while (dwords & ~0x03)
1741 *video_mem_destination = *buf;
1742 *(video_mem_destination + 1) = *(buf + 1);
1743 *(video_mem_destination + 2) = *(buf + 2);
1744 *(video_mem_destination + 3) = *(buf + 3);
1745 video_mem_destination += 4;
1752 *(video_mem_destination + 2) = *(buf + 2);
1754 *(video_mem_destination + 1) = *(buf + 1);
1756 *video_mem_destination = *buf;
1759 video_mem_destination += dstPitch - (npixels << 1);
1760 buf += srcPitch - (npixels << 1);
1768 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1769 pPriv->currentHostBuffer ^= 1;
1771 if ( action_flags & USE_OVERLAY )
1773 NVPutOverlayImage(pScrn, offset, ((action_flags & IS_YUY2) || (action_flags & CONVERT_TO_YUY2)) ? 0 : offset + nlines * dstPitch, id,
1777 src_w, src_h, drw_w, drw_h,
1779 pPriv->currentBuffer ^= 1;
1784 NVPutBlitImage(pScrn, offset, id,
1788 src_w, src_h, drw_w, drw_h,
1796 * QueryImageAttributes
1799 * - size (memory required to store image),
1803 * depending on colorspace (id) and dimensions (w,h) of image
1807 * may be adjusted as needed
1809 * @param pScrn unused
1810 * @param id colorspace of image
1811 * @param w pointer to width of image
1812 * @param h pointer to height of image
1813 * @param pitches pitches[i] = length of a scanline in plane[i]
1814 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1815 * @return size of the memory required for the XvImage queried
1818 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1819 unsigned short *w, unsigned short *h,
1820 int *pitches, int *offsets)
1824 if (*w > IMAGE_MAX_W)
1826 if (*h > IMAGE_MAX_H)
1829 *w = (*w + 1) & ~1; // width rounded up to an even number
1836 *h = (*h + 1) & ~1; // height rounded up to an even number
1837 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1839 pitches[0] = size; // width rounded up to a multiple of 4
1842 offsets[1] = size; // number of pixels in "rounded up" image
1843 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1845 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1846 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1847 size += tmp; // 5/4*number of pixels in "rounded up" image
1849 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1850 size += tmp; // = 3/2*number of pixels in "rounded up" image
1854 size = *w << 1; // 2*width
1856 pitches[0] = size; // 2*width
1857 size *= *h; // 2*width*height
1860 size = *w << 2; // 4*width (32 bit per pixel)
1862 pitches[0] = size; // 4*width
1863 size *= *h; // 4*width*height
1873 /***** Exported offscreen surface stuff ****/
1877 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1878 unsigned short w, unsigned short h,
1879 XF86SurfacePtr surface)
1881 NVPtr pNv = NVPTR(pScrn);
1882 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1885 bpp = pScrn->bitsPerPixel >> 3;
1887 if (pPriv->grabbedByV4L)
1890 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1894 pPriv->pitch = ((w << 1) + 63) & ~63;
1895 size = h * pPriv->pitch / bpp;
1897 pPriv->video_mem = NVAllocateVideoMemory(pScrn,
1900 if (!pPriv->video_mem)
1906 surface->height = h;
1907 surface->pScrn = pScrn;
1908 surface->pitches = &pPriv->pitch;
1909 surface->offsets = &pPriv->offset;
1910 surface->devPrivate.ptr = (pointer)pPriv;
1913 /* grab the video */
1914 NVStopOverlay(pScrn);
1915 pPriv->videoStatus = 0;
1916 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1917 pPriv->grabbedByV4L = TRUE;
1923 NVStopSurface(XF86SurfacePtr surface)
1925 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1927 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
1928 NVStopOverlay(surface->pScrn);
1929 pPriv->videoStatus = 0;
1936 NVFreeSurface(XF86SurfacePtr surface)
1938 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1940 if (pPriv->grabbedByV4L) {
1941 NVStopSurface(surface);
1942 NVFreeOverlayMemory(surface->pScrn);
1943 pPriv->grabbedByV4L = FALSE;
1950 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
1952 NVPtr pNv = NVPTR(pScrn);
1953 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1955 return NVGetOverlayPortAttribute(pScrn, attribute,
1956 value, (pointer)pPriv);
1960 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
1962 NVPtr pNv = NVPTR(pScrn);
1963 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1965 return NVSetOverlayPortAttribute(pScrn, attribute,
1966 value, (pointer)pPriv);
1970 NVDisplaySurface(XF86SurfacePtr surface,
1971 short src_x, short src_y,
1972 short drw_x, short drw_y,
1973 short src_w, short src_h,
1974 short drw_w, short drw_h,
1975 RegionPtr clipBoxes)
1977 ScrnInfoPtr pScrn = surface->pScrn;
1978 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1979 INT32 xa, xb, ya, yb;
1982 if (!pPriv->grabbedByV4L)
1985 if (src_w > (drw_w << 3))
1987 if (src_h > (drw_h << 3))
1997 dstBox.x2 = drw_x + drw_w;
1999 dstBox.y2 = drw_y + drw_h;
2001 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
2002 surface->width, surface->height))
2005 dstBox.x1 -= pScrn->frameX0;
2006 dstBox.x2 -= pScrn->frameX0;
2007 dstBox.y1 -= pScrn->frameY0;
2008 dstBox.y2 -= pScrn->frameY0;
2010 pPriv->currentBuffer = 0;
2012 NVPutOverlayImage(pScrn, surface->offsets[0], 0, surface->id,
2013 surface->pitches[0], &dstBox, xa, ya, xb, yb,
2014 surface->width, surface->height, src_w, src_h,
2015 drw_w, drw_h, clipBoxes);
2022 * this function does all the work setting up a blit port
2026 static XF86VideoAdaptorPtr
2027 NVSetupBlitVideo (ScreenPtr pScreen)
2029 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2030 NVPtr pNv = NVPTR(pScrn);
2031 XF86VideoAdaptorPtr adapt;
2032 NVPortPrivPtr pPriv;
2035 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2036 sizeof(NVPortPrivRec) +
2037 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
2041 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2043 adapt->name = "NV Video Blitter";
2044 adapt->nEncodings = 1;
2045 adapt->pEncodings = &DummyEncoding;
2046 adapt->nFormats = NUM_FORMATS_ALL;
2047 adapt->pFormats = NVFormats;
2048 adapt->nPorts = NUM_BLIT_PORTS;
2049 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2051 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
2052 for(i = 0; i < NUM_BLIT_PORTS; i++)
2053 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2055 if(pNv->WaitVSyncPossible) {
2056 adapt->pAttributes = NVBlitAttributes;
2057 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
2059 adapt->pAttributes = NULL;
2060 adapt->nAttributes = 0;
2063 adapt->pImages = NVImages;
2064 adapt->nImages = NUM_IMAGES_ALL;
2065 adapt->PutVideo = NULL;
2066 adapt->PutStill = NULL;
2067 adapt->GetVideo = NULL;
2068 adapt->GetStill = NULL;
2069 adapt->StopVideo = NVStopBlitVideo;
2070 adapt->SetPortAttribute = NVSetBlitPortAttribute;
2071 adapt->GetPortAttribute = NVGetBlitPortAttribute;
2072 adapt->QueryBestSize = NVQueryBestSize;
2073 adapt->PutImage = NVPutImage;
2074 adapt->QueryImageAttributes = NVQueryImageAttributes;
2076 pPriv->videoStatus = 0;
2077 pPriv->grabbedByV4L = FALSE;
2078 pPriv->blitter = TRUE;
2079 pPriv->doubleBuffer = FALSE;
2080 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
2082 pNv->blitAdaptor = adapt;
2083 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
2089 * NV10SetupOverlayVideo
2090 * this function does all the work setting up an overlay port
2092 * @return overlay port
2093 * @see NVResetVideo(ScrnInfoPtr pScrn)
2095 static XF86VideoAdaptorPtr
2096 NV10SetupOverlayVideo(ScreenPtr pScreen)
2098 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2099 NVPtr pNv = NVPTR(pScrn);
2100 XF86VideoAdaptorPtr adapt;
2101 NVPortPrivPtr pPriv;
2103 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2104 sizeof(NVPortPrivRec) +
2105 sizeof(DevUnion)))) {
2109 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2110 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
2111 adapt->name = "NV Video Overlay";
2112 adapt->nEncodings = 1;
2113 adapt->pEncodings = &DummyEncoding;
2114 adapt->nFormats = NUM_FORMATS_ALL;
2115 adapt->pFormats = NVFormats;
2117 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2119 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
2120 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
2122 adapt->pAttributes = NVOverlayAttributes;
2123 adapt->nAttributes = NUM_OVERLAY_ATTRIBUTES;
2124 adapt->pImages = NVImages;
2125 adapt->nImages = NUM_IMAGES_YUV;
2126 adapt->PutVideo = NULL;
2127 adapt->PutStill = NULL;
2128 adapt->GetVideo = NULL;
2129 adapt->GetStill = NULL;
2130 adapt->StopVideo = NVStopOverlayVideo;
2131 adapt->SetPortAttribute = NVSetOverlayPortAttribute;
2132 adapt->GetPortAttribute = NVGetOverlayPortAttribute;
2133 adapt->QueryBestSize = NVQueryBestSize;
2134 adapt->PutImage = NVPutImage;
2135 adapt->QueryImageAttributes = NVQueryImageAttributes;
2137 pPriv->videoStatus = 0;
2138 pPriv->currentBuffer = 0;
2139 pPriv->grabbedByV4L = FALSE;
2140 pPriv->blitter = FALSE;
2142 NVSetPortDefaults (pScrn, pPriv);
2144 /* gotta uninit this someplace */
2145 REGION_NULL(pScreen, &pPriv->clip);
2147 pNv->overlayAdaptor = adapt;
2149 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
2150 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
2151 xvContrast = MAKE_ATOM("XV_CONTRAST");
2152 xvColorKey = MAKE_ATOM("XV_COLORKEY");
2153 xvSaturation = MAKE_ATOM("XV_SATURATION");
2154 xvHue = MAKE_ATOM("XV_HUE");
2155 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
2156 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
2157 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
2159 NVResetVideo(pScrn);
2164 XF86OffscreenImageRec NVOffscreenImages[2] = {
2167 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2172 NVGetSurfaceAttribute,
2173 NVSetSurfaceAttribute,
2174 IMAGE_MAX_W, IMAGE_MAX_H,
2175 NUM_OVERLAY_ATTRIBUTES - 1,
2176 &NVOverlayAttributes[1]
2180 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2185 NVGetSurfaceAttribute,
2186 NVSetSurfaceAttribute,
2187 IMAGE_MAX_W, IMAGE_MAX_H,
2188 NUM_OVERLAY_ATTRIBUTES - 1,
2189 &NVOverlayAttributes[1]
2194 NVInitOffscreenImages (ScreenPtr pScreen)
2196 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
2200 * NVChipsetHasOverlay
2202 * newer chips don't support overlay anymore.
2203 * overlay feature is emulated via textures.
2206 * @return true, if chipset supports overlay
2209 NVChipsetHasOverlay(NVPtr pNv)
2211 switch (pNv->Architecture) {
2217 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
2228 * NVSetupOverlayVideo
2229 * check if chipset supports Overlay and CompositeExtension is disabled.
2230 * if so, setup overlay port
2232 * @return overlay port
2233 * @see NVChipsetHasOverlay(NVPtr pNv)
2234 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
2235 * @see NVInitOffscreenImages(ScreenPtr pScreen)
2237 static XF86VideoAdaptorPtr
2238 NVSetupOverlayVideo(ScreenPtr pScreen)
2240 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2241 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2242 NVPtr pNv = NVPTR(pScrn);
2244 if (!NVChipsetHasOverlay(pNv))
2247 overlayAdaptor = NV10SetupOverlayVideo(pScreen);
2249 NVInitOffscreenImages(pScreen); //I am not sure what this call does.
2252 if (!noCompositeExtension) {
2253 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2254 "XV: Composite is enabled, enabling overlay with smart blitter fallback\n");
2255 overlayAdaptor -> name = "NV Video Overlay with Composite";
2259 return overlayAdaptor;
2264 * tries to initialize one new overlay port and one new blit port
2265 * and add them to the list of ports on screen "pScreen".
2268 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
2269 * @see NVSetupBlitVideo(ScreenPtr pScreen)
2271 void NVInitVideo (ScreenPtr pScreen)
2273 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2274 NVPtr pNv = NVPTR(pScrn);
2275 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
2276 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2277 XF86VideoAdaptorPtr blitAdaptor = NULL;
2281 * Driving the blitter requires the DMA FIFO. Using the FIFO
2282 * without accel causes DMA errors. While the overlay might
2283 * might work without accel, we also disable it for now when
2284 * acceleration is disabled:
2286 if (pScrn->bitsPerPixel != 8 && pNv->Architecture < NV_ARCH_50 && !pNv->NoAccel) {
2287 overlayAdaptor = NVSetupOverlayVideo(pScreen);
2288 blitAdaptor = NVSetupBlitVideo(pScreen);
2291 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
2292 if(blitAdaptor || overlayAdaptor) {
2293 int size = num_adaptors;
2295 if(overlayAdaptor) size++;
2296 if(blitAdaptor) size++;
2298 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
2301 memcpy(newAdaptors, adaptors, num_adaptors *
2302 sizeof(XF86VideoAdaptorPtr));
2305 if(overlayAdaptor) {
2306 newAdaptors[num_adaptors] = overlayAdaptor;
2311 newAdaptors[num_adaptors] = blitAdaptor;
2315 adaptors = newAdaptors;
2320 xf86XVScreenInit(pScreen, adaptors, num_adaptors);