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 NVDmaNext (pNv, pNv->CRTCnumber);
185 NVDmaStart(pNv, NvImageBlit, 0x00000100, 1);
187 NVDmaStart(pNv, NvImageBlit, 0x00000130, 1);
193 * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
195 * @param pScrn screen to get the default colorKey from
196 * @param pPriv port to reset to defaults
199 NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
201 NVPtr pNv = NVPTR(pScrn);
203 pPriv->brightness = 0;
204 pPriv->contrast = 4096;
205 pPriv->saturation = 4096;
207 pPriv->colorKey = pNv->videoKey;
208 pPriv->autopaintColorKey = TRUE;
209 pPriv->doubleBuffer = TRUE;
210 pPriv->iturbt_709 = FALSE;
211 pPriv->currentHostBuffer = 0;
216 * writes the current attributes from the overlay port to the hardware
219 NVResetVideo (ScrnInfoPtr pScrn)
221 NVPtr pNv = NVPTR(pScrn);
222 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
223 int satSine, satCosine;
226 angle = (double)pPriv->hue * 3.1415927 / 180.0;
228 satSine = pPriv->saturation * sin(angle);
231 satCosine = pPriv->saturation * cos(angle);
232 if (satCosine < -1024)
235 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
237 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
239 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
240 (satCosine & 0xffff));
241 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
242 (satCosine & 0xffff));
243 nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
248 * Tell the hardware to stop the overlay
251 NVStopOverlay (ScrnInfoPtr pScrn)
253 NVPtr pNv = NVPTR(pScrn);
255 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
259 * NVXvDMANotifierAlloc
260 * allocates a notifier from the table of 6 we have
262 * @return a notifier instance or NULL on error
264 static struct drm_nouveau_notifierobj_alloc * NVXvDMANotifierAlloc(ScrnInfoPtr pScrn)
267 for ( i = 0; i < 6; i ++ )
269 if ( XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_INUSE )
272 if ( XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_FREE )
274 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
275 return XvDMANotifiers[i];
278 if ( XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_NOALLOC )
280 XvDMANotifiers[i] = NVNotifierAlloc(pScrn, NvDmaXvNotifier0 + i);
281 if (XvDMANotifiers[i])
283 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
284 return XvDMANotifiers[i];
294 * NVXvDMANotifierFree
295 * frees a notifier from the table of 6 we have
299 static void NVXvDMANotifierFree(ScrnInfoPtr pScrn, struct drm_nouveau_notifierobj_alloc * target)
302 for ( i = 0; i < 6; i ++ )
304 if ( XvDMANotifiers[i] == target )
307 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_FREE;
311 * NVAllocateVideoMemory
312 * allocates video memory for a given port
314 * @param pScrn screen which requests the memory
315 * @param mem pointer to previously allocated memory for reallocation
316 * @param size size of requested memory segment
317 * @return pointer to the allocated memory
320 NVAllocateVideoMemory(ScrnInfoPtr pScrn, NVAllocRec *mem, int size)
322 NVPtr pNv = NVPTR(pScrn);
326 if(mem->size >= size)
328 NVFreeMemory(pNv, mem);
331 return NVAllocateMemory(pNv, NOUVEAU_MEM_FB, size); /* align 32? */
336 * allocates TT memory for a given port
338 * @param pScrn screen which requests the memory
339 * @param mem pointer to previously allocated memory for reallocation
340 * @param size size of requested memory segment
341 * @return pointer to the allocated memory
344 NVAllocateTTMemory(ScrnInfoPtr pScrn, NVAllocRec *mem, int size)
346 NVPtr pNv = NVPTR(pScrn);
350 if(mem->size >= size)
352 NVFreeMemory(pNv, mem);
354 return NVAllocateMemory(pNv, NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE, size); /* align 32? */
359 * frees memory held by a given port
361 * @param pScrn screen whose port wants to free memory
362 * @param pPriv port to free memory of
365 NVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
367 NVPtr pNv = NVPTR(pScrn);
369 //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]);
371 if(pPriv->video_mem) {
372 NVFreeMemory(pNv, pPriv->video_mem);
373 pPriv->video_mem = NULL;
376 if ( pPriv->TT_mem_chunk[ 0 ] && pPriv->DMANotifier [ 0 ] )
378 NVNotifierWaitStatus(pScrn, pPriv->DMANotifier [ 0 ] , 0, 1000);
381 if ( pPriv->TT_mem_chunk[ 1 ] && pPriv->DMANotifier [ 1 ] )
383 NVNotifierWaitStatus(pScrn, pPriv->DMANotifier [ 1 ] , 0, 1000);
386 if(pPriv->TT_mem_chunk[0]) {
387 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
388 pPriv->TT_mem_chunk[0] = NULL;
391 if(pPriv->TT_mem_chunk[1]) {
392 NVFreeMemory(pNv, pPriv->TT_mem_chunk[1]);
393 pPriv->TT_mem_chunk[1] = NULL;
396 if(pPriv->DMANotifier[0]) {
397 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[0]);
398 pPriv->DMANotifier[0] = NULL;
401 if(pPriv->DMANotifier[1]) {
402 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[1]);
403 pPriv->DMANotifier[1] = NULL;
409 * NVFreeOverlayMemory
410 * frees memory held by the overlay port
412 * @param pScrn screen whose overlay port wants to free memory
415 NVFreeOverlayMemory(ScrnInfoPtr pScrn)
417 NVPtr pNv = NVPTR(pScrn);
418 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
419 NVFreePortMemory(pScrn, pPriv);
420 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) & 0xEFFFFFFF));
421 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) | 0x10000000));
426 * frees memory held by the blit port
428 * @param pScrn screen whose blit port wants to free memory
431 NVFreeBlitMemory(ScrnInfoPtr pScrn)
433 NVPtr pNv = NVPTR(pScrn);
434 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
435 NVFreePortMemory(pScrn, pPriv);
439 * NVVideoTimerCallback
440 * callback function which perform cleanup tasks (stop overlay, free memory).
441 * within the driver it is only called once from NVBlockHandler in nv_driver.c
444 NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
446 NVPtr pNv = NVPTR(pScrn);
447 NVPortPrivPtr pOverPriv = NULL;
448 NVPortPrivPtr pBlitPriv = NULL;
449 Bool needCallback = FALSE;
454 if (pNv->overlayAdaptor) {
455 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
456 if (!pOverPriv->videoStatus)
460 if (pNv->blitAdaptor) {
461 pBlitPriv = GET_BLIT_PRIVATE(pNv);
462 if (!pBlitPriv->videoStatus)
467 if (pOverPriv->videoTime < currentTime) {
468 if (pOverPriv->videoStatus & OFF_TIMER) {
469 NVStopOverlay(pScrn);
470 pOverPriv->videoStatus = FREE_TIMER;
471 pOverPriv->videoTime = currentTime + FREE_DELAY;
474 if (pOverPriv->videoStatus & FREE_TIMER) {
475 NVFreeOverlayMemory(pScrn);
476 pOverPriv->videoStatus = 0;
484 if (pBlitPriv->videoTime < currentTime) {
485 NVFreeBlitMemory(pScrn);
486 pBlitPriv->videoStatus = 0;
492 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
497 * program hardware to overlay image into front buffer
499 * @param pScrn screen
500 * @param offset card offset to the pixel data
501 * @param id format of image
502 * @param dstPitch pitch of the pixel data in VRAM
503 * @param dstBox destination box
504 * @param x1 first source point - x
505 * @param y1 first source point - y
506 * @param x2 second source point - x
507 * @param y2 second source point - y
508 * @param width width of the source image = x2 - x1
509 * @param height height
510 * @param src_w width of the image data in VRAM
511 * @param src_h height
512 * @param drw_w width of the image to draw to screen
513 * @param drw_h height
514 * @param clipBoxes ???
517 NVPutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
518 int dstPitch, BoxPtr dstBox,
519 int x1, int y1, int x2, int y2,
520 short width, short height,
521 short src_w, short src_h,
522 short drw_w, short drw_h,
525 NVPtr pNv = NVPTR(pScrn);
526 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
527 int buffer = pPriv->currentBuffer;
529 /* paint the color key */
530 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
531 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
532 /* we always paint V4L's color key */
533 if (!pPriv->grabbedByV4L)
534 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
536 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
540 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
546 //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));
548 nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer) , 0);
549 nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer) , offset);
550 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer) , (height << 16) | width);
551 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
552 ((y1 << 4) & 0xffff0000) | (x1 >> 12));
553 nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer) , (src_w << 20) / drw_w);
554 nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer) , (src_h << 20) / drw_h);
555 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
556 (dstBox->y1 << 16) | dstBox->x1);
557 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
558 ((dstBox->y2 - dstBox->y1) << 16) |
559 (dstBox->x2 - dstBox->x1));
561 dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; /* use color key */
562 if(id != FOURCC_UYVY)
563 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
564 if(pPriv->iturbt_709)
565 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
567 if( id == FOURCC_YV12 || id == FOURCC_I420 )
568 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
570 /* Those are important only for planar formats (NV12) */
573 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_BASE(buffer), 0);
574 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer), uvoffset);
577 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
578 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
579 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
581 pPriv->videoStatus = CLIENT_VIDEO_ON;
585 NV04PutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
586 int dstPitch, BoxPtr dstBox,
587 int x1, int y1, int x2, int y2,
588 short width, short height,
589 short src_w, short src_h,
590 short drw_w, short drw_h,
593 NVPtr pNv = NVPTR(pScrn);
594 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
595 int buffer = pPriv->currentBuffer;
597 /* paint the color key */
598 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
599 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
600 /* we always paint V4L's color key */
601 if (!pPriv->grabbedByV4L)
602 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
604 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
608 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
615 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x224, 0);
616 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x228, 0);
617 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x22C, 0);
618 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x20C + 4*buffer , offset);
619 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x21C + 4*buffer , 0);
620 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x214 + 4*buffer , dstPitch);
621 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x230 , (dstBox->y1 << 16) | dstBox->x1);
622 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x234/* + 4*buffer UNKNOWN*/, (height << 16) | width);
623 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)));
625 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x280, 0x69);
626 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x284, 0x3e);
627 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x288, 0x89);
628 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x28C, 0x0);
630 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x204, 0x001);
631 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x208, 0x111);
633 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x23C, 0x03);
634 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x238, 0x38);
636 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x240, pPriv->colorKey);
638 /*NV_PVIDEO_OVERLAY (KEY_ON, VIDEO_ON, FORMAT_CCIR) */
639 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x240, 0x111);
640 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x228, 1 << 16);
642 /*dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;
643 if(id != FOURCC_UYVY)
644 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
645 if(pPriv->iturbt_709)
646 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
648 if( id == FOURCC_YV12 || id == FOURCC_I420 )
649 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
651 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
652 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
653 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
656 pPriv->videoStatus = CLIENT_VIDEO_ON;
658 #ifndef ExaOffscreenMarkUsed
659 extern void ExaOffscreenMarkUsed(PixmapPtr);
661 #ifndef exaGetDrawablePixmap
662 extern PixmapPtr exaGetDrawablePixmap(DrawablePtr);
664 #ifndef exaPixmapIsOffscreen
665 extern Bool exaPixmapIsOffscreen(PixmapPtr p);
667 /* To support EXA 2.0, 2.1 has this in the header */
668 #ifndef exaMoveInPixmap
669 extern void exaMoveInPixmap(PixmapPtr pPixmap);
675 * @param pScrn screen
677 * @param id colorspace of image
694 NVPutBlitImage(ScrnInfoPtr pScrn, int src_offset, int id,
695 int src_pitch, BoxPtr dstBox,
696 int x1, int y1, int x2, int y2,
697 short width, short height,
698 short src_w, short src_h,
699 short drw_w, short drw_h,
703 NVPtr pNv = NVPTR(pScrn);
704 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
708 CARD32 dst_size, dst_point;
709 CARD32 src_point, src_format;
711 ScreenPtr pScreen = pScrn->pScreen;
712 PixmapPtr pPix = exaGetDrawablePixmap(pDraw);
715 /* Try to get the dest drawable into vram */
716 if (!exaPixmapIsOffscreen(pPix)) {
717 exaMoveInPixmap(pPix);
718 ExaOffscreenMarkUsed(pPix);
721 /* If we failed, draw directly onto the screen pixmap.
722 * Not sure if this is the best approach, maybe failing
723 * with BadAlloc would be better?
725 if (!exaPixmapIsOffscreen(pPix)) {
726 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
727 "XV: couldn't move dst surface into vram\n");
728 pPix = pScreen->GetScreenPixmap(pScreen);
731 NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format);
732 NVAccelSetCtxSurf2D(pPix, pPix, dst_format);
735 /* Adjust coordinates if drawing to an offscreen pixmap */
736 if (pPix->screen_x || pPix->screen_y) {
737 REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
740 dstBox->x1 -= pPix->screen_x;
741 dstBox->x2 -= pPix->screen_x;
742 dstBox->y1 -= pPix->screen_y;
743 dstBox->y2 -= pPix->screen_y;
746 DamageDamageRegion((DrawablePtr)pPix, clipBoxes);
749 pbox = REGION_RECTS(clipBoxes);
750 nbox = REGION_NUM_RECTS(clipBoxes);
752 dsdx = (src_w << 20) / drw_w;
753 dtdy = (src_h << 20) / drw_h;
755 dst_size = ((dstBox->y2 - dstBox->y1) << 16) |
756 (dstBox->x2 - dstBox->x1);
757 dst_point = (dstBox->y1 << 16) | dstBox->x1;
759 src_pitch |= (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER << 16) |
760 (STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR << 24);
761 src_point = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
765 src_format = STRETCH_BLIT_FORMAT_X8R8G8B8;
768 src_format = STRETCH_BLIT_FORMAT_UYVY;
771 src_format = STRETCH_BLIT_FORMAT_YUYV;
775 if(pPriv->SyncToVBlank) {
780 if(pNv->BlendingPossible) {
781 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_FORMAT, 2);
782 NVDmaNext (pNv, src_format);
783 NVDmaNext (pNv, STRETCH_BLIT_OPERATION_COPY);
785 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_FORMAT, 1);
786 NVDmaNext (pNv, src_format);
790 NVDmaStart(pNv, NvRectangle, RECT_SOLID_COLOR, 1);
793 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_CLIP_POINT, 6);
794 NVDmaNext (pNv, (pbox->y1 << 16) | pbox->x1);
795 NVDmaNext (pNv, ((pbox->y2 - pbox->y1) << 16) |
796 (pbox->x2 - pbox->x1));
797 NVDmaNext (pNv, dst_point);
798 NVDmaNext (pNv, dst_size);
799 NVDmaNext (pNv, dsdx);
800 NVDmaNext (pNv, dtdy);
802 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_SRC_SIZE, 4);
803 NVDmaNext (pNv, (height << 16) | width);
804 NVDmaNext (pNv, src_pitch);
805 NVDmaNext (pNv, src_offset);
806 NVDmaNext (pNv, src_point);
812 exaMarkSync(pScrn->pScreen);
814 pPriv->videoStatus = FREE_TIMER;
815 pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
816 pNv->VideoTimerCallback = NVVideoTimerCallback;
823 NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
825 NVPtr pNv = NVPTR(pScrn);
826 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
828 if(pPriv->grabbedByV4L) return;
830 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
833 if (pPriv->videoStatus & CLIENT_VIDEO_ON)
834 NVStopOverlay(pScrn);
835 NVFreeOverlayMemory(pScrn);
836 pPriv->videoStatus = 0;
838 if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
839 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
840 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
841 pNv->VideoTimerCallback = NVVideoTimerCallback;
850 NVStopBlitVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
855 * NVSetOverlayPortAttribute
856 * sets the attribute "attribute" of port "data" to value "value"
857 * calls NVResetVideo(pScrn) to apply changes to hardware
860 * @param attribute attribute to set
861 * @param value value to which attribute is to be set
862 * @param data port from which the attribute is to be set
864 * @return Success, if setting is successful
865 * BadValue/BadMatch, if value/attribute are invalid
866 * @see NVResetVideo(ScrnInfoPtr pScrn)
869 NVSetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
870 INT32 value, pointer data)
872 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
874 if (attribute == xvBrightness) {
875 if ((value < -512) || (value > 512))
877 pPriv->brightness = value;
879 if (attribute == xvDoubleBuffer) {
880 if ((value < 0) || (value > 1))
882 pPriv->doubleBuffer = value;
884 if (attribute == xvContrast) {
885 if ((value < 0) || (value > 8191))
887 pPriv->contrast = value;
889 if (attribute == xvHue) {
895 if (attribute == xvSaturation) {
896 if ((value < 0) || (value > 8191))
898 pPriv->saturation = value;
900 if (attribute == xvColorKey) {
901 pPriv->colorKey = value;
902 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
904 if (attribute == xvAutopaintColorKey) {
905 if ((value < 0) || (value > 1))
907 pPriv->autopaintColorKey = value;
909 if (attribute == xvITURBT709) {
910 if ((value < 0) || (value > 1))
912 pPriv->iturbt_709 = value;
914 if (attribute == xvSetDefaults) {
915 NVSetPortDefaults(pScrn, pPriv);
924 * NVGetOverlayPortAttribute
926 * @param pScrn unused
927 * @param attribute attribute to be read
928 * @param value value of attribute will be stored in this pointer
929 * @param data port from which attribute will be read
930 * @return Success, if queried attribute exists
933 NVGetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
934 INT32 *value, pointer data)
936 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
938 if (attribute == xvBrightness)
939 *value = pPriv->brightness;
940 else if (attribute == xvDoubleBuffer)
941 *value = (pPriv->doubleBuffer) ? 1 : 0;
942 else if (attribute == xvContrast)
943 *value = pPriv->contrast;
944 else if (attribute == xvSaturation)
945 *value = pPriv->saturation;
946 else if (attribute == xvHue)
948 else if (attribute == xvColorKey)
949 *value = pPriv->colorKey;
950 else if (attribute == xvAutopaintColorKey)
951 *value = (pPriv->autopaintColorKey) ? 1 : 0;
952 else if (attribute == xvITURBT709)
953 *value = (pPriv->iturbt_709) ? 1 : 0;
961 * NVSetBlitPortAttribute
962 * sets the attribute "attribute" of port "data" to value "value"
963 * supported attributes:
964 * - xvSyncToVBlank (values: 0,1)
965 * - xvSetDefaults (values: NA; SyncToVBlank will be set, if hardware supports it)
968 * @param attribute attribute to set
969 * @param value value to which attribute is to be set
970 * @param data port from which the attribute is to be set
972 * @return Success, if setting is successful
973 * BadValue/BadMatch, if value/attribute are invalid
976 NVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
977 INT32 value, pointer data)
979 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
980 NVPtr pNv = NVPTR(pScrn);
982 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
983 if ((value < 0) || (value > 1))
985 pPriv->SyncToVBlank = value;
987 if (attribute == xvSetDefaults) {
988 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
996 * NVGetBlitPortAttribute
997 * reads the value of attribute "attribute" from port "data" into INT32 "*value"
998 * currently only one attribute supported: xvSyncToVBlank
1000 * @param pScrn unused
1001 * @param attribute attribute to be read
1002 * @param value value of attribute will be stored here
1003 * @param data port from which attribute will be read
1004 * @return Success, if queried attribute exists
1007 NVGetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1008 INT32 *value, pointer data)
1010 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1012 if(attribute == xvSyncToVBlank)
1013 *value = (pPriv->SyncToVBlank) ? 1 : 0;
1023 * used by client applications to ask the driver:
1024 * how would you actually scale a video of dimensions
1025 * vid_w, vid_h, if i wanted you to scale it to dimensions
1027 * function stores actual scaling size in pointers p_w, p_h.
1030 * @param pScrn unused
1031 * @param motion unused
1032 * @param vid_w width of source video
1033 * @param vid_h height of source video
1034 * @param drw_w desired scaled width as requested by client
1035 * @param drw_h desired scaled height as requested by client
1036 * @param p_w actual scaled width as the driver is capable of
1037 * @param p_h actual scaled height as the driver is capable of
1038 * @param data unused
1041 NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
1042 short vid_w, short vid_h,
1043 short drw_w, short drw_h,
1044 unsigned int *p_w, unsigned int *p_h,
1047 if(vid_w > (drw_w << 3))
1049 if(vid_h > (drw_h << 3))
1058 * used to convert YV12 to YUY2 for the blitter
1060 * @param src1 source buffer of luma
1061 * @param src2 source buffer of chroma1
1062 * @param src3 source buffer of chroma2
1063 * @param dst1 destination buffer
1064 * @param srcPitch pitch of src1
1065 * @param srcPitch2 pitch of src2, src3
1066 * @param dstPitch pitch of dst1
1067 * @param h number of lines to copy
1068 * @param w length of lines to copy
1070 static inline void NVCopyData420(unsigned char *src1, unsigned char *src2,
1071 unsigned char *src3, unsigned char *dst1,
1072 int srcPitch, int srcPitch2,
1077 CARD8 *s1, *s2, *s3;
1082 for (j = 0; j < h; j++) {
1083 dst = (CARD32*)dst1;
1084 s1 = src1; s2 = src2; s3 = src3;
1088 #if X_BYTE_ORDER == X_BIG_ENDIAN
1089 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
1090 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1];
1091 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2];
1092 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3];
1094 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
1095 dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
1096 dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
1097 dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
1099 dst += 4; s2 += 4; s3 += 4; s1 += 8;
1104 #if X_BYTE_ORDER == X_BIG_ENDIAN
1105 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
1107 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
1123 * NVCopyNV12ColorPlanes
1124 * Used to convert YV12 color planes to NV12 (interleaved UV) for the overlay
1126 * @param src1 source buffer of chroma1
1127 * @param dst1 destination buffer
1128 * @param h number of lines to copy
1129 * @param w length of lines to copy
1130 * @param id source pixel format (YV12 or I420)
1132 static inline void NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char * src2, unsigned char *dst, int dstPitch, int srcPitch2,
1142 for ( j = 0; j < h; j++ )
1144 unsigned char * us = src1;
1145 unsigned char * vs = src2;
1146 unsigned int * vuvud = (unsigned int *) dst;
1147 for ( i = 0; i < l; i++ )
1149 #if X_BYTE_ORDER == X_BIG_ENDIAN
1150 *vuvud++ = (vs[0]<<24) | (us[0]<<16) | (vs[1]<<8) | us[1];
1152 *vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24);
1158 unsigned short *vud = (unsigned short *) vuvud;
1159 #if X_BYTE_ORDER == X_BIG_ENDIAN
1160 *vud = (vs[0]<<8) | (us[0] << 0);
1162 *vud = vs[0] | (us[0]<<8);
1173 static int NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 * xa, INT32 * xb, INT32 * ya, INT32 * yb,
1174 short * src_x, short * src_y, short * src_w, short * src_h,
1175 short * drw_x, short * drw_y, short * drw_w, short * drw_h,
1176 int * left, int * top, int * right, int * bottom,
1178 int * npixels, int * nlines,
1179 RegionPtr clipBoxes, short width, short height
1183 if ( action_flags & USE_OVERLAY )
1184 { /* overlay hardware scaler limitation - copied from nv, UNCHECKED*/
1185 if (*src_w > (*drw_w << 3))
1186 *drw_w = *src_w >> 3;
1187 if (*src_h > (*drw_h << 3))
1188 *drw_h = *src_h >> 3;
1194 *xb = *src_x + *src_w;
1196 *yb = *src_y + *src_h;
1198 dstBox->x1 = *drw_x;
1199 dstBox->x2 = *drw_x + *drw_w;
1200 dstBox->y1 = *drw_y;
1201 dstBox->y2 = *drw_y + *drw_h;
1203 if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
1207 if ( action_flags & USE_OVERLAY )
1209 dstBox->x1 -= pScrn->frameX0;
1210 dstBox->x2 -= pScrn->frameX0;
1211 dstBox->y1 -= pScrn->frameY0;
1212 dstBox->y2 -= pScrn->frameY0;
1217 /* Convert fixed point to integer, as xf86XVClipVideoHelper probably turns its parameter into fixed point values */
1218 *left = (*xa) >> 16;
1219 if (*left < 0) *left = 0;
1221 if (*top < 0) *top = 0;
1222 *right = (*xb) >> 16;
1223 if (*right > width) *right = width;
1224 *bottom = (*yb) >> 16;
1225 if (*bottom > height) *bottom = height;
1227 if ( action_flags & IS_YV12 )
1229 *left &= ~1; //even "left", even "top", even number of pixels per line and even number of lines
1230 *npixels = ((*right + 1) & ~1) - *left;
1232 *nlines = ((*bottom + 1) & ~1) - *top;
1234 else if ( action_flags & IS_YUY2 )
1236 *left &= ~1; //even "left"
1237 *npixels = ((*right + 1) & ~1) - *left; //even number of pixels per line
1238 *nlines = *bottom - *top;
1239 *left <<= 1; //16bpp
1241 else if (action_flags & IS_RGB )
1243 *npixels = *right - *left;
1244 *nlines = *bottom - *top;
1245 *left <<= 2; //32bpp
1251 static int NV_calculate_pitches_and_mem_size(int action_flags, int * srcPitch, int * srcPitch2, int * dstPitch,
1252 int * s2offset, int * s3offset,
1253 int * newFBSize, int * newTTSize,
1254 int * line_len, int npixels, int nlines, int width, int height)
1258 if ( action_flags & IS_YV12 )
1260 *srcPitch = (width + 3) & ~3; /* of luma */
1261 *s2offset = *srcPitch * height;
1262 *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
1263 *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
1264 *dstPitch = (npixels + 63) &~ 63; /*luma and chroma pitch*/
1265 *line_len = npixels;
1266 *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1267 *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1269 else if ( action_flags & IS_YUY2 )
1271 *srcPitch = width << 1; /* one luma, one chroma per pixel */
1272 *dstPitch = ((npixels << 1) + 63) & ~63;
1273 *line_len = npixels << 1;
1274 *newFBSize = nlines * *dstPitch;
1275 *newTTSize = nlines * *line_len;
1277 else if ( action_flags & IS_RGB )
1279 *srcPitch = width << 2; /* one R, one G, one B, one X per pixel */
1280 *dstPitch = ((npixels << 2) + 63) & ~63;
1281 *line_len = npixels << 2;
1282 *newFBSize = nlines * *dstPitch;
1283 *newTTSize = nlines * *dstPitch;
1287 if ( action_flags & CONVERT_TO_YUY2 )
1289 *dstPitch = ((npixels << 1) + 63) & ~63;
1290 *line_len = npixels << 1;
1291 *newFBSize = nlines * *dstPitch;
1292 *newTTSize = nlines * *line_len;
1295 if ( action_flags & SWAP_UV )
1296 { //I420 swaps U and V
1298 *s2offset = *s3offset;
1302 if ( action_flags & USE_OVERLAY ) // overlay double buffering ...
1303 (*newFBSize) <<= 1; // ... means double the amount of VRAM needed
1310 * NV_set_action_flags
1311 * This function computes the action flags from the input image,
1312 * that is, it decides what NVPutImage and its helpers must do.
1313 * This eases readability by avoiding lots of switch-case statements in the core NVPutImage
1315 static void NV_set_action_flags(NVPtr pNv, ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, int id, int * action_flags)
1318 if ( id == FOURCC_YUY2 || id == FOURCC_UYVY )
1319 *action_flags |= IS_YUY2;
1321 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1322 *action_flags |= IS_YV12;
1324 if ( id == FOURCC_RGB ) /*How long will we support it?*/
1325 *action_flags |= IS_RGB;
1327 if ( id == FOURCC_I420 ) /*I420 is YV12 with swapped UV*/
1328 *action_flags |= SWAP_UV;
1330 if ( !pPriv -> blitter )
1331 *action_flags |= USE_OVERLAY;
1334 WindowPtr pWin = NULL;
1336 if (!noCompositeExtension && WindowDrawable(pDraw->type))
1338 pWin = (WindowPtr)pDraw;
1342 if ( pWin->redirectDraw )
1343 *action_flags &= ~USE_OVERLAY;
1347 if ( ! ( *action_flags & USE_OVERLAY) )
1349 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1350 { /*The blitter does not handle YV12 natively*/
1351 *action_flags |= CONVERT_TO_YUY2;
1355 if ( pNv->Architecture == NV_ARCH_03 || pNv->Architecture == NV_ARCH_04 )
1356 if ( * action_flags & IS_YV12 ) //NV04-05 don't support native YV12 AFAIK
1357 *action_flags |= CONVERT_TO_YUY2;
1359 if ( pNv->Architecture == NV_ARCH_10 )
1361 switch ( pNv->Chipset & 0xfff0 )
1366 case CHIPSET_NFORCE: /*XXX: unsure about nforce and nforce2*/
1367 case CHIPSET_NFORCE2:
1368 *action_flags |= CONVERT_TO_YUY2; break;
1378 * PutImage is "the" important function of the Xv extension.
1379 * a client (e.g. video player) calls this function for every
1380 * image (of the video) to be displayed. this function then
1381 * scales and displays the image.
1383 * @param pScrn screen which hold the port where the image is put
1384 * @param src_x source point in the source image to start displaying from
1385 * @param src_y see above
1386 * @param src_w width of the source image to display
1387 * @param src_h see above
1388 * @param drw_x screen point to display to
1390 * @param drw_w width of the screen drawable
1392 * @param id pixel format of image
1393 * @param buf pointer to buffer containing the source image
1394 * @param width total width of the source image we are passed
1396 * @param Sync unused
1397 * @param clipBoxes ??
1398 * @param data pointer to port
1399 * @param pDraw drawable pointer
1402 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
1403 short drw_x, short drw_y,
1404 short src_w, short src_h,
1405 short drw_w, short drw_h,
1408 short width, short height,
1409 Bool Sync, /*FIXME: need to honor the Sync*/
1410 RegionPtr clipBoxes,
1415 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1416 NVPtr pNv = NVPTR(pScrn);
1417 INT32 xa = 0, xb = 0, ya = 0, yb = 0; //source box
1418 int newFBSize = 0, newTTSize = 0; //size to allocate in VRAM and in GART respectively
1419 int offset = 0, s2offset = 0, s3offset = 0; //card VRAM offset, source offsets for U and V planes
1420 int srcPitch = 0, srcPitch2 = 0, dstPitch = 0; //source pitch, source pitch of U and V planes in case of YV12, VRAM destination pitch
1421 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
1425 int line_len = 0; //length of a line, like npixels, but in bytes
1426 int DMAoffset = 0; //additional VRAM offset to start the DMA copy to
1427 int UVDMAoffset = 0;
1428 NVAllocRec * destination_buffer = NULL;
1429 unsigned char * video_mem_destination = NULL;
1430 int action_flags; //what shall we do?
1433 if (pPriv->grabbedByV4L)
1437 NV_set_action_flags(pNv, pScrn, pDraw, pPriv, id, &action_flags);
1439 if ( NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
1440 &src_x, &src_y, &src_w, &src_h,
1441 &drw_x, &drw_y, &drw_w, &drw_h,
1442 &left, &top, &right, &bottom, &dstBox,
1444 clipBoxes, width, height ) )
1450 if ( NV_calculate_pitches_and_mem_size(action_flags, &srcPitch, &srcPitch2, &dstPitch,
1451 &s2offset, &s3offset,
1452 & newFBSize, &newTTSize ,&line_len ,
1453 npixels, nlines, width, height) )
1455 return BadImplementation;
1458 /* There are some cases (tvtime with overscan for example) where the input image is larger (width/height) than
1459 the source rectangle for the overlay (src_w, src_h). In those cases, we try to do something optimal by uploading only
1460 the necessary data. */
1461 if ( action_flags & IS_YUY2 || action_flags & IS_RGB )
1463 buf += (top * srcPitch) + left;
1464 DMAoffset += left + (top * dstPitch);
1467 if ( action_flags & IS_YV12 )
1469 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1473 if ( action_flags & CONVERT_TO_YUY2 )
1475 DMAoffset += (left << 1) + (top * dstPitch);
1480 //real YV12 - we offset only the luma plane, and copy the whole color plane, for easiness
1481 DMAoffset += left + (top * dstPitch);
1482 UVDMAoffset += left + (top >> 1) * dstPitch;
1486 pPriv->video_mem = NVAllocateVideoMemory(pScrn, pPriv->video_mem,
1488 if (!pPriv->video_mem)
1491 offset = pPriv->video_mem->offset;
1493 /*The overlay supports hardware double buffering. We handle this here*/
1494 if (pPriv->doubleBuffer) {
1495 int mask = 1 << (pPriv->currentBuffer << 2);
1497 /* overwrite the newest buffer if there's not one free */
1498 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1499 if (!pPriv->currentBuffer)
1500 offset += newFBSize >> 1;
1504 else if (pPriv->currentBuffer)
1505 offset += newFBSize >> 1;
1508 /*Now we take a decision regarding the way we send the data to the card.
1509 Either we use double buffering of "private" TT memory
1510 Either we rely on X's GARTScratch
1511 Either we fallback on CPU copy
1514 /* Try to allocate host-side double buffers, unless we have already failed*/
1515 /* We take only nlines * line_len bytes - that is, only the pixel data we are interested in - because the stuff in the GART is
1516 written contiguously */
1517 if ( pPriv -> currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1519 pPriv->TT_mem_chunk[0] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[0],
1521 if ( pPriv->TT_mem_chunk[0] )
1523 pPriv->TT_mem_chunk[1] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[1],
1526 if ( ! pPriv->TT_mem_chunk[1] )
1528 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
1529 pPriv->TT_mem_chunk[0] = NULL;
1530 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1531 //xf86DrvMsg(0, X_INFO, "Alloc 1 failed\n");
1536 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1537 //xf86DrvMsg(0, X_INFO, "Alloc 0 failed\n");
1541 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1542 { //if we have a private buffer
1543 destination_buffer = pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1544 //xf86DrvMsg(0, X_INFO, "Using private mem chunk #%d\n", pPriv->currentHostBuffer);
1546 /* We know where we are going to write, but we are not sure yet whether we can do it directly, because
1547 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.
1548 If we do, then we must wait for it before overwriting the buffer.
1549 Else we need one, so we call the Xv notifier allocator.*/
1550 if ( pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1552 //xf86DrvMsg(0, X_INFO, "Waiting for notifier %p (%d)\n", pPriv->DMANotifier[pPriv->currentHostBuffer], pPriv->currentHostBuffer);
1553 if (!NVNotifierWaitStatus(pScrn, pPriv->DMANotifier[pPriv->currentHostBuffer], 0, 0))
1558 //xf86DrvMsg(0, X_INFO, "Allocating notifier...\n");
1559 pPriv->DMANotifier [ pPriv->currentHostBuffer ] = NVXvDMANotifierAlloc(pScrn);
1560 if (! pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1561 { /* 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.
1562 I know that's a lot of code but I believe it's necessary to properly handle all the cases*/
1563 xf86DrvMsg(0, X_ERROR, "Ran out of Xv notifiers!\n");
1564 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
1565 pPriv->TT_mem_chunk[0] = NULL;
1566 NVFreeMemory(pNv, pPriv->TT_mem_chunk[1]);
1567 pPriv->TT_mem_chunk[1] = NULL;
1568 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1570 //xf86DrvMsg(0, X_INFO, "Got notifier %p\n", pPriv->DMANotifier [ pPriv->currentHostBuffer ]);
1574 if ( pPriv -> currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE )
1575 { //otherwise we fall back on DDX's GARTScratch
1576 destination_buffer = pNv->GARTScratch;
1577 //xf86DrvMsg(0, X_INFO, "Using global GART memory chunk\n");
1580 if ( !destination_buffer) //if we have no GART at all
1583 if(newTTSize <= destination_buffer->size)
1585 unsigned char *dst = destination_buffer->map;
1588 /* Upload to GART */
1589 if ( action_flags & IS_YV12)
1591 if ( action_flags & CONVERT_TO_YUY2 )
1593 NVCopyData420(buf + (top * srcPitch) + left,
1594 buf + s2offset, buf + s3offset,
1595 dst, srcPitch, srcPitch2,
1596 line_len, nlines, npixels);
1600 unsigned char * tbuf = buf + top * srcPitch + left;
1601 unsigned char * tdst = dst;
1602 //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);
1604 for ( i=0; i < nlines; i++)
1606 memcpy(tdst, tbuf, line_len);
1610 dst += line_len * nlines;
1611 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, dst, line_len, srcPitch2, nlines, line_len);
1616 for ( i=0; i < nlines; i++)
1618 memcpy(dst, buf, line_len);
1625 NVDmaStart(pNv, NvMemFormat, MEMFORMAT_DMA_OBJECT_IN, 2);
1626 NVDmaNext (pNv, NvDmaTT);
1627 NVDmaNext (pNv, NvDmaFB);
1628 pNv->M2MFDirection = 1;
1631 if ( action_flags & IS_YV12 && ! (action_flags & CONVERT_TO_YUY2) )
1632 { /*we start the color plane transfer separately*/
1633 NVDmaStart(pNv, NvMemFormat,
1634 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1635 NVDmaNext (pNv, (uint32_t)destination_buffer->offset + line_len * nlines);
1636 NVDmaNext (pNv, (uint32_t)offset + dstPitch * nlines);
1637 NVDmaNext (pNv, line_len);
1638 NVDmaNext (pNv, dstPitch);
1639 NVDmaNext (pNv, line_len);
1640 NVDmaNext (pNv, (nlines >> 1));
1641 NVDmaNext (pNv, (1<<8)|1);
1646 NVDmaStart(pNv, NvMemFormat,
1647 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1648 NVDmaNext (pNv, (uint32_t)destination_buffer->offset);
1649 NVDmaNext (pNv, (uint32_t)offset /*+ DMAoffset*/);
1650 NVDmaNext (pNv, line_len);
1651 NVDmaNext (pNv, dstPitch);
1652 NVDmaNext (pNv, line_len);
1653 NVDmaNext (pNv, nlines);
1654 NVDmaNext (pNv, (1<<8)|1);
1657 if ( destination_buffer == pNv->GARTScratch )
1659 NVNotifierReset(pScrn, pNv->Notifier0);
1662 NVNotifierReset(pScrn, pPriv->DMANotifier[pPriv->currentHostBuffer]);
1663 NVDmaStart(pNv, NvMemFormat,
1664 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1665 NVDmaNext (pNv, pPriv->DMANotifier[pPriv->currentHostBuffer]->handle);
1669 NVDmaStart(pNv, NvMemFormat,
1670 NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1673 NVDmaStart(pNv, NvMemFormat, 0x100, 1);
1676 //Put back NvDmaNotifier0 for EXA
1677 NVDmaStart(pNv, NvMemFormat,
1678 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1679 NVDmaNext (pNv, NvDmaNotifier0);
1683 if ( destination_buffer == pNv->GARTScratch )
1684 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 0))
1687 else { //GART is too small, we fallback on CPU copy
1689 video_mem_destination = pPriv->video_mem->map + (offset - (uint32_t)pPriv->video_mem->offset);
1691 if ( action_flags & IS_YV12 )
1693 if ( action_flags & CONVERT_TO_YUY2 )
1695 NVCopyData420(buf + (top * srcPitch) + left,
1696 buf + s2offset, buf + s3offset,
1697 video_mem_destination, srcPitch, srcPitch2,
1698 dstPitch, nlines, npixels);
1701 unsigned char * tbuf = buf + left + top * srcPitch;
1702 for ( i=0; i < nlines; i++)
1704 int dwords = npixels << 1;
1705 while (dwords & ~0x03)
1707 *video_mem_destination = *tbuf;
1708 *(video_mem_destination + 1) = *(tbuf + 1);
1709 *(video_mem_destination + 2) = *(tbuf + 2);
1710 *(video_mem_destination + 3) = *(tbuf + 3);
1711 video_mem_destination += 4;
1718 *(video_mem_destination + 2) = *(tbuf + 2);
1720 *(video_mem_destination + 1) = *(tbuf + 1);
1722 *video_mem_destination = *tbuf;
1725 video_mem_destination += dstPitch - (npixels << 1);
1726 tbuf += srcPitch - (npixels << 1);
1729 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, video_mem_destination, dstPitch, srcPitch2, nlines, line_len);
1734 for ( i=0; i < nlines; i++)
1736 int dwords = npixels << 1;
1737 while (dwords & ~0x03)
1739 *video_mem_destination = *buf;
1740 *(video_mem_destination + 1) = *(buf + 1);
1741 *(video_mem_destination + 2) = *(buf + 2);
1742 *(video_mem_destination + 3) = *(buf + 3);
1743 video_mem_destination += 4;
1750 *(video_mem_destination + 2) = *(buf + 2);
1752 *(video_mem_destination + 1) = *(buf + 1);
1754 *video_mem_destination = *buf;
1757 video_mem_destination += dstPitch - (npixels << 1);
1758 buf += srcPitch - (npixels << 1);
1766 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1767 pPriv->currentHostBuffer ^= 1;
1769 if ( action_flags & USE_OVERLAY )
1771 NVPutOverlayImage(pScrn, offset, ((action_flags & IS_YUY2) || (action_flags & CONVERT_TO_YUY2)) ? 0 : offset + nlines * dstPitch, id,
1775 src_w, src_h, drw_w, drw_h,
1777 pPriv->currentBuffer ^= 1;
1782 NVPutBlitImage(pScrn, offset, id,
1786 src_w, src_h, drw_w, drw_h,
1794 * QueryImageAttributes
1797 * - size (memory required to store image),
1801 * depending on colorspace (id) and dimensions (w,h) of image
1805 * may be adjusted as needed
1807 * @param pScrn unused
1808 * @param id colorspace of image
1809 * @param w pointer to width of image
1810 * @param h pointer to height of image
1811 * @param pitches pitches[i] = length of a scanline in plane[i]
1812 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1813 * @return size of the memory required for the XvImage queried
1816 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1817 unsigned short *w, unsigned short *h,
1818 int *pitches, int *offsets)
1822 if (*w > IMAGE_MAX_W)
1824 if (*h > IMAGE_MAX_H)
1827 *w = (*w + 1) & ~1; // width rounded up to an even number
1834 *h = (*h + 1) & ~1; // height rounded up to an even number
1835 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1837 pitches[0] = size; // width rounded up to a multiple of 4
1840 offsets[1] = size; // number of pixels in "rounded up" image
1841 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1843 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1844 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1845 size += tmp; // 5/4*number of pixels in "rounded up" image
1847 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1848 size += tmp; // = 3/2*number of pixels in "rounded up" image
1852 size = *w << 1; // 2*width
1854 pitches[0] = size; // 2*width
1855 size *= *h; // 2*width*height
1858 size = *w << 2; // 4*width (32 bit per pixel)
1860 pitches[0] = size; // 4*width
1861 size *= *h; // 4*width*height
1871 /***** Exported offscreen surface stuff ****/
1875 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1876 unsigned short w, unsigned short h,
1877 XF86SurfacePtr surface)
1879 NVPtr pNv = NVPTR(pScrn);
1880 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1883 bpp = pScrn->bitsPerPixel >> 3;
1885 if (pPriv->grabbedByV4L)
1888 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1892 pPriv->pitch = ((w << 1) + 63) & ~63;
1893 size = h * pPriv->pitch / bpp;
1895 pPriv->video_mem = NVAllocateVideoMemory(pScrn,
1898 if (!pPriv->video_mem)
1904 surface->height = h;
1905 surface->pScrn = pScrn;
1906 surface->pitches = &pPriv->pitch;
1907 surface->offsets = &pPriv->offset;
1908 surface->devPrivate.ptr = (pointer)pPriv;
1911 /* grab the video */
1912 NVStopOverlay(pScrn);
1913 pPriv->videoStatus = 0;
1914 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1915 pPriv->grabbedByV4L = TRUE;
1921 NVStopSurface(XF86SurfacePtr surface)
1923 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1925 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
1926 NVStopOverlay(surface->pScrn);
1927 pPriv->videoStatus = 0;
1934 NVFreeSurface(XF86SurfacePtr surface)
1936 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1938 if (pPriv->grabbedByV4L) {
1939 NVStopSurface(surface);
1940 NVFreeOverlayMemory(surface->pScrn);
1941 pPriv->grabbedByV4L = FALSE;
1948 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
1950 NVPtr pNv = NVPTR(pScrn);
1951 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1953 return NVGetOverlayPortAttribute(pScrn, attribute,
1954 value, (pointer)pPriv);
1958 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
1960 NVPtr pNv = NVPTR(pScrn);
1961 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1963 return NVSetOverlayPortAttribute(pScrn, attribute,
1964 value, (pointer)pPriv);
1968 NVDisplaySurface(XF86SurfacePtr surface,
1969 short src_x, short src_y,
1970 short drw_x, short drw_y,
1971 short src_w, short src_h,
1972 short drw_w, short drw_h,
1973 RegionPtr clipBoxes)
1975 ScrnInfoPtr pScrn = surface->pScrn;
1976 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1977 INT32 xa, xb, ya, yb;
1980 if (!pPriv->grabbedByV4L)
1983 if (src_w > (drw_w << 3))
1985 if (src_h > (drw_h << 3))
1995 dstBox.x2 = drw_x + drw_w;
1997 dstBox.y2 = drw_y + drw_h;
1999 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
2000 surface->width, surface->height))
2003 dstBox.x1 -= pScrn->frameX0;
2004 dstBox.x2 -= pScrn->frameX0;
2005 dstBox.y1 -= pScrn->frameY0;
2006 dstBox.y2 -= pScrn->frameY0;
2008 pPriv->currentBuffer = 0;
2010 NVPutOverlayImage(pScrn, surface->offsets[0], 0, surface->id,
2011 surface->pitches[0], &dstBox, xa, ya, xb, yb,
2012 surface->width, surface->height, src_w, src_h,
2013 drw_w, drw_h, clipBoxes);
2020 * this function does all the work setting up a blit port
2024 static XF86VideoAdaptorPtr
2025 NVSetupBlitVideo (ScreenPtr pScreen)
2027 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2028 NVPtr pNv = NVPTR(pScrn);
2029 XF86VideoAdaptorPtr adapt;
2030 NVPortPrivPtr pPriv;
2033 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2034 sizeof(NVPortPrivRec) +
2035 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
2039 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2041 adapt->name = "NV Video Blitter";
2042 adapt->nEncodings = 1;
2043 adapt->pEncodings = &DummyEncoding;
2044 adapt->nFormats = NUM_FORMATS_ALL;
2045 adapt->pFormats = NVFormats;
2046 adapt->nPorts = NUM_BLIT_PORTS;
2047 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2049 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
2050 for(i = 0; i < NUM_BLIT_PORTS; i++)
2051 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2053 if(pNv->WaitVSyncPossible) {
2054 adapt->pAttributes = NVBlitAttributes;
2055 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
2057 adapt->pAttributes = NULL;
2058 adapt->nAttributes = 0;
2061 adapt->pImages = NVImages;
2062 adapt->nImages = NUM_IMAGES_ALL;
2063 adapt->PutVideo = NULL;
2064 adapt->PutStill = NULL;
2065 adapt->GetVideo = NULL;
2066 adapt->GetStill = NULL;
2067 adapt->StopVideo = NVStopBlitVideo;
2068 adapt->SetPortAttribute = NVSetBlitPortAttribute;
2069 adapt->GetPortAttribute = NVGetBlitPortAttribute;
2070 adapt->QueryBestSize = NVQueryBestSize;
2071 adapt->PutImage = NVPutImage;
2072 adapt->QueryImageAttributes = NVQueryImageAttributes;
2074 pPriv->videoStatus = 0;
2075 pPriv->grabbedByV4L = FALSE;
2076 pPriv->blitter = TRUE;
2077 pPriv->doubleBuffer = FALSE;
2078 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
2080 pNv->blitAdaptor = adapt;
2081 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
2087 * NV10SetupOverlayVideo
2088 * this function does all the work setting up an overlay port
2090 * @return overlay port
2091 * @see NVResetVideo(ScrnInfoPtr pScrn)
2093 static XF86VideoAdaptorPtr
2094 NV10SetupOverlayVideo(ScreenPtr pScreen)
2096 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2097 NVPtr pNv = NVPTR(pScrn);
2098 XF86VideoAdaptorPtr adapt;
2099 NVPortPrivPtr pPriv;
2101 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2102 sizeof(NVPortPrivRec) +
2103 sizeof(DevUnion)))) {
2107 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2108 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
2109 adapt->name = "NV Video Overlay";
2110 adapt->nEncodings = 1;
2111 adapt->pEncodings = &DummyEncoding;
2112 adapt->nFormats = NUM_FORMATS_ALL;
2113 adapt->pFormats = NVFormats;
2115 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2117 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
2118 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
2120 adapt->pAttributes = NVOverlayAttributes;
2121 adapt->nAttributes = NUM_OVERLAY_ATTRIBUTES;
2122 adapt->pImages = NVImages;
2123 adapt->nImages = NUM_IMAGES_YUV;
2124 adapt->PutVideo = NULL;
2125 adapt->PutStill = NULL;
2126 adapt->GetVideo = NULL;
2127 adapt->GetStill = NULL;
2128 adapt->StopVideo = NVStopOverlayVideo;
2129 adapt->SetPortAttribute = NVSetOverlayPortAttribute;
2130 adapt->GetPortAttribute = NVGetOverlayPortAttribute;
2131 adapt->QueryBestSize = NVQueryBestSize;
2132 adapt->PutImage = NVPutImage;
2133 adapt->QueryImageAttributes = NVQueryImageAttributes;
2135 pPriv->videoStatus = 0;
2136 pPriv->currentBuffer = 0;
2137 pPriv->grabbedByV4L = FALSE;
2138 pPriv->blitter = FALSE;
2140 NVSetPortDefaults (pScrn, pPriv);
2142 /* gotta uninit this someplace */
2143 REGION_NULL(pScreen, &pPriv->clip);
2145 pNv->overlayAdaptor = adapt;
2147 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
2148 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
2149 xvContrast = MAKE_ATOM("XV_CONTRAST");
2150 xvColorKey = MAKE_ATOM("XV_COLORKEY");
2151 xvSaturation = MAKE_ATOM("XV_SATURATION");
2152 xvHue = MAKE_ATOM("XV_HUE");
2153 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
2154 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
2155 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
2157 NVResetVideo(pScrn);
2162 XF86OffscreenImageRec NVOffscreenImages[2] = {
2165 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2170 NVGetSurfaceAttribute,
2171 NVSetSurfaceAttribute,
2172 IMAGE_MAX_W, IMAGE_MAX_H,
2173 NUM_OVERLAY_ATTRIBUTES - 1,
2174 &NVOverlayAttributes[1]
2178 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2183 NVGetSurfaceAttribute,
2184 NVSetSurfaceAttribute,
2185 IMAGE_MAX_W, IMAGE_MAX_H,
2186 NUM_OVERLAY_ATTRIBUTES - 1,
2187 &NVOverlayAttributes[1]
2192 NVInitOffscreenImages (ScreenPtr pScreen)
2194 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
2198 * NVChipsetHasOverlay
2200 * newer chips don't support overlay anymore.
2201 * overlay feature is emulated via textures.
2204 * @return true, if chipset supports overlay
2207 NVChipsetHasOverlay(NVPtr pNv)
2209 switch (pNv->Architecture) {
2215 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
2226 * NVSetupOverlayVideo
2227 * check if chipset supports Overlay and CompositeExtension is disabled.
2228 * if so, setup overlay port
2230 * @return overlay port
2231 * @see NVChipsetHasOverlay(NVPtr pNv)
2232 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
2233 * @see NVInitOffscreenImages(ScreenPtr pScreen)
2235 static XF86VideoAdaptorPtr
2236 NVSetupOverlayVideo(ScreenPtr pScreen)
2238 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2239 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2240 NVPtr pNv = NVPTR(pScrn);
2242 if (!NVChipsetHasOverlay(pNv))
2245 overlayAdaptor = NV10SetupOverlayVideo(pScreen);
2247 NVInitOffscreenImages(pScreen); //I am not sure what this call does.
2250 if (!noCompositeExtension) {
2251 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2252 "XV: Composite is enabled, enabling overlay with smart blitter fallback\n");
2253 overlayAdaptor -> name = "NV Video Overlay with Composite";
2257 return overlayAdaptor;
2262 * tries to initialize one new overlay port and one new blit port
2263 * and add them to the list of ports on screen "pScreen".
2266 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
2267 * @see NVSetupBlitVideo(ScreenPtr pScreen)
2269 void NVInitVideo (ScreenPtr pScreen)
2271 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2272 NVPtr pNv = NVPTR(pScrn);
2273 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
2274 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2275 XF86VideoAdaptorPtr blitAdaptor = NULL;
2279 * Driving the blitter requires the DMA FIFO. Using the FIFO
2280 * without accel causes DMA errors. While the overlay might
2281 * might work without accel, we also disable it for now when
2282 * acceleration is disabled:
2284 if (pScrn->bitsPerPixel != 8 && pNv->Architecture < NV_ARCH_50 && !pNv->NoAccel) {
2285 overlayAdaptor = NVSetupOverlayVideo(pScreen);
2286 blitAdaptor = NVSetupBlitVideo(pScreen);
2289 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
2290 if(blitAdaptor || overlayAdaptor) {
2291 int size = num_adaptors;
2293 if(overlayAdaptor) size++;
2294 if(blitAdaptor) size++;
2296 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
2299 memcpy(newAdaptors, adaptors, num_adaptors *
2300 sizeof(XF86VideoAdaptorPtr));
2303 if(overlayAdaptor) {
2304 newAdaptors[num_adaptors] = overlayAdaptor;
2309 newAdaptors[num_adaptors] = blitAdaptor;
2313 adaptors = newAdaptors;
2318 xf86XVScreenInit(pScreen, adaptors, num_adaptors);