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] =
178 * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
180 * @param pScrn screen to get the default colorKey from
181 * @param pPriv port to reset to defaults
184 NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
186 NVPtr pNv = NVPTR(pScrn);
188 pPriv->brightness = 0;
189 pPriv->contrast = 4096;
190 pPriv->saturation = 4096;
192 pPriv->colorKey = pNv->videoKey;
193 pPriv->autopaintColorKey = TRUE;
194 pPriv->doubleBuffer = TRUE;
195 pPriv->iturbt_709 = FALSE;
196 pPriv->currentHostBuffer = 0;
201 * writes the current attributes from the overlay port to the hardware
204 NVResetVideo (ScrnInfoPtr pScrn)
206 NVPtr pNv = NVPTR(pScrn);
207 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
208 int satSine, satCosine;
211 angle = (double)pPriv->hue * 3.1415927 / 180.0;
213 satSine = pPriv->saturation * sin(angle);
216 satCosine = pPriv->saturation * cos(angle);
217 if (satCosine < -1024)
220 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
222 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
224 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
225 (satCosine & 0xffff));
226 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
227 (satCosine & 0xffff));
228 nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
233 * Tell the hardware to stop the overlay
236 NVStopOverlay (ScrnInfoPtr pScrn)
238 NVPtr pNv = NVPTR(pScrn);
240 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
244 * NVXvDMANotifierAlloc
245 * allocates a notifier from the table of 6 we have
247 * @return a notifier instance or NULL on error
249 static struct drm_nouveau_notifierobj_alloc * NVXvDMANotifierAlloc(ScrnInfoPtr pScrn)
252 for ( i = 0; i < 6; i ++ )
254 if ( XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_INUSE )
257 if ( XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_FREE )
259 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
260 return XvDMANotifiers[i];
263 if ( XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_NOALLOC )
265 XvDMANotifiers[i] = NVNotifierAlloc(pScrn, NvDmaXvNotifier0 + i);
266 if (XvDMANotifiers[i])
268 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
269 return XvDMANotifiers[i];
279 * NVXvDMANotifierFree
280 * frees a notifier from the table of 6 we have
284 static void NVXvDMANotifierFree(ScrnInfoPtr pScrn, struct drm_nouveau_notifierobj_alloc * target)
287 for ( i = 0; i < 6; i ++ )
289 if ( XvDMANotifiers[i] == target )
292 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_FREE;
296 * NVAllocateVideoMemory
297 * allocates video memory for a given port
299 * @param pScrn screen which requests the memory
300 * @param mem pointer to previously allocated memory for reallocation
301 * @param size size of requested memory segment
302 * @return pointer to the allocated memory
305 NVAllocateVideoMemory(ScrnInfoPtr pScrn, NVAllocRec *mem, int size)
307 NVPtr pNv = NVPTR(pScrn);
311 if(mem->size >= size)
313 NVFreeMemory(pNv, mem);
316 return NVAllocateMemory(pNv, NOUVEAU_MEM_FB, size); /* align 32? */
321 * allocates TT memory for a given port
323 * @param pScrn screen which requests the memory
324 * @param mem pointer to previously allocated memory for reallocation
325 * @param size size of requested memory segment
326 * @return pointer to the allocated memory
329 NVAllocateTTMemory(ScrnInfoPtr pScrn, NVAllocRec *mem, int size)
331 NVPtr pNv = NVPTR(pScrn);
335 if(mem->size >= size)
337 NVFreeMemory(pNv, mem);
339 return NVAllocateMemory(pNv, NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE, size); /* align 32? */
344 * frees memory held by a given port
346 * @param pScrn screen whose port wants to free memory
347 * @param pPriv port to free memory of
350 NVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
352 NVPtr pNv = NVPTR(pScrn);
354 //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]);
356 if(pPriv->video_mem) {
357 NVFreeMemory(pNv, pPriv->video_mem);
358 pPriv->video_mem = NULL;
361 if ( pPriv->TT_mem_chunk[ 0 ] && pPriv->DMANotifier [ 0 ] )
363 NVNotifierWaitStatus(pScrn, pPriv->DMANotifier [ 0 ] , 0, 1000);
366 if ( pPriv->TT_mem_chunk[ 1 ] && pPriv->DMANotifier [ 1 ] )
368 NVNotifierWaitStatus(pScrn, pPriv->DMANotifier [ 1 ] , 0, 1000);
371 if(pPriv->TT_mem_chunk[0]) {
372 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
373 pPriv->TT_mem_chunk[0] = NULL;
376 if(pPriv->TT_mem_chunk[1]) {
377 NVFreeMemory(pNv, pPriv->TT_mem_chunk[1]);
378 pPriv->TT_mem_chunk[1] = NULL;
381 if(pPriv->DMANotifier[0]) {
382 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[0]);
383 pPriv->DMANotifier[0] = NULL;
386 if(pPriv->DMANotifier[1]) {
387 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[1]);
388 pPriv->DMANotifier[1] = NULL;
394 * NVFreeOverlayMemory
395 * frees memory held by the overlay port
397 * @param pScrn screen whose overlay port wants to free memory
400 NVFreeOverlayMemory(ScrnInfoPtr pScrn)
402 NVPtr pNv = NVPTR(pScrn);
403 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
404 NVFreePortMemory(pScrn, pPriv);
409 * frees memory held by the blit port
411 * @param pScrn screen whose blit port wants to free memory
414 NVFreeBlitMemory(ScrnInfoPtr pScrn)
416 NVPtr pNv = NVPTR(pScrn);
417 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
418 NVFreePortMemory(pScrn, pPriv);
422 * NVVideoTimerCallback
423 * callback function which perform cleanup tasks (stop overlay, free memory).
424 * within the driver it is only called once from NVBlockHandler in nv_driver.c
427 NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
429 NVPtr pNv = NVPTR(pScrn);
430 NVPortPrivPtr pOverPriv = NULL;
431 NVPortPrivPtr pBlitPriv = NULL;
432 Bool needCallback = FALSE;
437 if (pNv->overlayAdaptor) {
438 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
439 if (!pOverPriv->videoStatus)
443 if (pNv->blitAdaptor) {
444 pBlitPriv = GET_BLIT_PRIVATE(pNv);
445 if (!pBlitPriv->videoStatus)
450 if (pOverPriv->videoTime < currentTime) {
451 if (pOverPriv->videoStatus & OFF_TIMER) {
452 NVStopOverlay(pScrn);
453 pOverPriv->videoStatus = FREE_TIMER;
454 pOverPriv->videoTime = currentTime + FREE_DELAY;
457 if (pOverPriv->videoStatus & FREE_TIMER) {
458 NVFreeOverlayMemory(pScrn);
459 pOverPriv->videoStatus = 0;
467 if (pBlitPriv->videoTime < currentTime) {
468 NVFreeBlitMemory(pScrn);
469 pBlitPriv->videoStatus = 0;
475 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
480 * program hardware to overlay image into front buffer
482 * @param pScrn screen
483 * @param offset card offset to the pixel data
484 * @param id format of image
485 * @param dstPitch pitch of the pixel data in VRAM
486 * @param dstBox destination box
487 * @param x1 first source point - x
488 * @param y1 first source point - y
489 * @param x2 second source point - x
490 * @param y2 second source point - y
491 * @param width width of the source image = x2 - x1
492 * @param height height
493 * @param src_w width of the image data in VRAM
494 * @param src_h height
495 * @param drw_w width of the image to draw to screen
496 * @param drw_h height
497 * @param clipBoxes ???
500 NVPutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
501 int dstPitch, BoxPtr dstBox,
502 int x1, int y1, int x2, int y2,
503 short width, short height,
504 short src_w, short src_h,
505 short drw_w, short drw_h,
508 NVPtr pNv = NVPTR(pScrn);
509 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
510 int buffer = pPriv->currentBuffer;
512 /* paint the color key */
513 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
514 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
515 /* we always paint V4L's color key */
516 if (!pPriv->grabbedByV4L)
517 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
519 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
523 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
529 //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));
531 nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer) , 0);
532 nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer) , offset);
533 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer) , (height << 16) | width);
534 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
535 ((y1 << 4) & 0xffff0000) | (x1 >> 12));
536 nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer) , (src_w << 20) / drw_w);
537 nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer) , (src_h << 20) / drw_h);
538 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
539 (dstBox->y1 << 16) | dstBox->x1);
540 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
541 ((dstBox->y2 - dstBox->y1) << 16) |
542 (dstBox->x2 - dstBox->x1));
544 dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; /* use color key */
545 if(id != FOURCC_UYVY)
546 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
547 if(pPriv->iturbt_709)
548 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
550 if( id == FOURCC_YV12 || id == FOURCC_I420 )
551 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
553 /* Those are important only for planar formats (NV12) */
556 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_BASE(buffer), 0);
557 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer), uvoffset);
560 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
561 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
562 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
564 pPriv->videoStatus = CLIENT_VIDEO_ON;
568 NV04PutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
569 int dstPitch, BoxPtr dstBox,
570 int x1, int y1, int x2, int y2,
571 short width, short height,
572 short src_w, short src_h,
573 short drw_w, short drw_h,
576 NVPtr pNv = NVPTR(pScrn);
577 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
578 int buffer = pPriv->currentBuffer;
580 /* paint the color key */
581 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
582 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
583 /* we always paint V4L's color key */
584 if (!pPriv->grabbedByV4L)
585 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
587 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
591 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
598 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x224, 0);
599 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x228, 0);
600 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x22C, 0);
601 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x20C + 4*buffer , offset);
602 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x21C + 4*buffer , 0);
603 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x214 + 4*buffer , dstPitch);
604 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x230 , (dstBox->y1 << 16) | dstBox->x1);
605 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x234/* + 4*buffer UNKNOWN*/, (height << 16) | width);
606 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)));
608 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x280, 0x69);
609 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x284, 0x3e);
610 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x288, 0x89);
611 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x28C, 0x0);
613 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x204, 0x001);
614 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x208, 0x111);
616 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x23C, 0x03);
617 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x238, 0x38);
619 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x240, pPriv->colorKey);
621 /*NV_PVIDEO_OVERLAY (KEY_ON, VIDEO_ON, FORMAT_CCIR) */
622 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x240, 0x111);
623 nvWriteVIDEO(pNv, 0x680000 - 0x8000+ 0x228, 1 << 16);
625 /*dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;
626 if(id != FOURCC_UYVY)
627 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
628 if(pPriv->iturbt_709)
629 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
631 if( id == FOURCC_YV12 || id == FOURCC_I420 )
632 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
634 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
635 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
636 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
639 pPriv->videoStatus = CLIENT_VIDEO_ON;
641 #ifndef ExaOffscreenMarkUsed
642 extern void ExaOffscreenMarkUsed(PixmapPtr);
644 #ifndef exaGetDrawablePixmap
645 extern PixmapPtr exaGetDrawablePixmap(DrawablePtr);
647 #ifndef exaPixmapIsOffscreen
648 extern Bool exaPixmapIsOffscreen(PixmapPtr p);
650 /* To support EXA 2.0, 2.1 has this in the header */
651 #ifndef exaMoveInPixmap
652 extern void exaMoveInPixmap(PixmapPtr pPixmap);
658 * @param pScrn screen
660 * @param id colorspace of image
677 NVPutBlitImage(ScrnInfoPtr pScrn, int src_offset, int id,
678 int src_pitch, BoxPtr dstBox,
679 int x1, int y1, int x2, int y2,
680 short width, short height,
681 short src_w, short src_h,
682 short drw_w, short drw_h,
686 NVPtr pNv = NVPTR(pScrn);
687 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
691 CARD32 dst_size, dst_point;
692 CARD32 src_point, src_format;
695 ScreenPtr pScreen = pScrn->pScreen;
696 PixmapPtr pPix = exaGetDrawablePixmap(pDraw);
699 /* Try to get the dest drawable into vram */
700 if (!exaPixmapIsOffscreen(pPix)) {
701 exaMoveInPixmap(pPix);
702 ExaOffscreenMarkUsed(pPix);
705 /* If we failed, draw directly onto the screen pixmap.
706 * Not sure if this is the best approach, maybe failing
707 * with BadAlloc would be better?
709 if (!exaPixmapIsOffscreen(pPix)) {
710 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
711 "XV: couldn't move dst surface into vram\n");
712 pPix = pScreen->GetScreenPixmap(pScreen);
715 NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format);
716 NVAccelSetCtxSurf2D(pPix, pPix, dst_format);
719 /* Adjust coordinates if drawing to an offscreen pixmap */
720 if (pPix->screen_x || pPix->screen_y) {
721 REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
724 dstBox->x1 -= pPix->screen_x;
725 dstBox->x2 -= pPix->screen_x;
726 dstBox->y1 -= pPix->screen_y;
727 dstBox->y2 -= pPix->screen_y;
730 DamageDamageRegion((DrawablePtr)pPix, clipBoxes);
733 if (pNv->CurrentLayout.depth == 15) {
734 NVDmaStart(pNv, NvContextSurfaces,
736 NVDmaNext (pNv, SURFACE_FORMAT_X1R5G5B5);
740 pbox = REGION_RECTS(clipBoxes);
741 nbox = REGION_NUM_RECTS(clipBoxes);
743 dsdx = (src_w << 20) / drw_w;
744 dtdy = (src_h << 20) / drw_h;
746 dst_size = ((dstBox->y2 - dstBox->y1) << 16) |
747 (dstBox->x2 - dstBox->x1);
748 dst_point = (dstBox->y1 << 16) | dstBox->x1;
750 src_pitch |= (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER << 16) |
751 (STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR << 24);
752 src_point = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
756 src_format = STRETCH_BLIT_FORMAT_X8R8G8B8;
759 src_format = STRETCH_BLIT_FORMAT_UYVY;
762 src_format = STRETCH_BLIT_FORMAT_YUYV;
766 if(pPriv->SyncToVBlank) {
771 if(pNv->BlendingPossible) {
772 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_FORMAT, 2);
773 NVDmaNext (pNv, src_format);
774 NVDmaNext (pNv, STRETCH_BLIT_OPERATION_COPY);
776 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_FORMAT, 1);
777 NVDmaNext (pNv, src_format);
781 NVDmaStart(pNv, NvRectangle, RECT_SOLID_COLOR, 1);
784 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_CLIP_POINT, 6);
785 NVDmaNext (pNv, (pbox->y1 << 16) | pbox->x1);
786 NVDmaNext (pNv, ((pbox->y2 - pbox->y1) << 16) |
787 (pbox->x2 - pbox->x1));
788 NVDmaNext (pNv, dst_point);
789 NVDmaNext (pNv, dst_size);
790 NVDmaNext (pNv, dsdx);
791 NVDmaNext (pNv, dtdy);
793 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_SRC_SIZE, 4);
794 NVDmaNext (pNv, (height << 16) | width);
795 NVDmaNext (pNv, src_pitch);
796 NVDmaNext (pNv, src_offset);
797 NVDmaNext (pNv, src_point);
802 if(pNv->CurrentLayout.depth == 15) {
803 NVDmaStart(pNv, NvContextSurfaces,
805 NVDmaNext (pNv, SURFACE_FORMAT_R5G6B5);
812 exaMarkSync(pScrn->pScreen);
814 SET_SYNC_FLAG(pNv->AccelInfoRec);
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,
1142 for (j = 0; j < h; j++) {
1144 unsigned char * us = src1;
1145 unsigned char * vs = src2;
1146 unsigned char * ud = dst + 1;
1147 unsigned char * vd = dst;
1165 static int NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 * xa, INT32 * xb, INT32 * ya, INT32 * yb,
1166 short * src_x, short * src_y, short * src_w, short * src_h,
1167 short * drw_x, short * drw_y, short * drw_w, short * drw_h,
1168 int * left, int * top, int * right, int * bottom,
1170 int * npixels, int * nlines,
1171 RegionPtr clipBoxes, short width, short height
1175 if ( action_flags & USE_OVERLAY )
1176 { /* overlay hardware scaler limitation - copied from nv, UNCHECKED*/
1177 if (*src_w > (*drw_w << 3))
1178 *drw_w = *src_w >> 3;
1179 if (*src_h > (*drw_h << 3))
1180 *drw_h = *src_h >> 3;
1186 *xb = *src_x + *src_w;
1188 *yb = *src_y + *src_h;
1190 dstBox->x1 = *drw_x;
1191 dstBox->x2 = *drw_x + *drw_w;
1192 dstBox->y1 = *drw_y;
1193 dstBox->y2 = *drw_y + *drw_h;
1195 if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
1199 if ( action_flags & USE_OVERLAY )
1201 dstBox->x1 -= pScrn->frameX0;
1202 dstBox->x2 -= pScrn->frameX0;
1203 dstBox->y1 -= pScrn->frameY0;
1204 dstBox->y2 -= pScrn->frameY0;
1209 /* Convert fixed point to integer, as xf86XVClipVideoHelper probably turns its parameter into fixed point values */
1210 *left = (*xa) >> 16;
1211 if (*left < 0) *left = 0;
1213 if (*top < 0) *top = 0;
1214 *right = (*xb) >> 16;
1215 if (*right > width) *right = width;
1216 *bottom = (*yb) >> 16;
1217 if (*bottom > height) *bottom = height;
1219 if ( action_flags & IS_YV12 )
1221 *left &= ~1; //even "left", even "top", even number of pixels per line and even number of lines
1222 *npixels = ((*right + 1) & ~1) - *left;
1224 *nlines = ((*bottom + 1) & ~1) - *top;
1226 else if ( action_flags & IS_YUY2 )
1228 *left &= ~1; //even "left"
1229 *npixels = ((*right + 1) & ~1) - *left; //even number of pixels per line
1230 *nlines = *bottom - *top;
1231 *left <<= 1; //16bpp
1233 else if (action_flags & IS_RGB )
1235 *npixels = *right - *left;
1236 *nlines = *bottom - *top;
1237 *left <<= 2; //32bpp
1243 static int NV_calculate_pitches_and_mem_size(int action_flags, int * srcPitch, int * srcPitch2, int * dstPitch,
1244 int * s2offset, int * s3offset,
1245 int * newFBSize, int * newTTSize,
1246 int * line_len, int npixels, int nlines, int width, int height)
1250 if ( action_flags & IS_YV12 )
1252 *srcPitch = (width + 3) & ~3; /* of luma */
1253 *s2offset = *srcPitch * height;
1254 *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
1255 *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
1256 *dstPitch = (npixels + 63) &~ 63; /*luma and chroma pitch*/
1257 *line_len = npixels;
1258 *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1259 *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1261 else if ( action_flags & IS_YUY2 )
1263 *srcPitch = width << 1; /* one luma, one chroma per pixel */
1264 *dstPitch = ((npixels << 1) + 63) & ~63;
1265 *line_len = npixels << 1;
1266 *newFBSize = nlines * *dstPitch;
1267 *newTTSize = nlines * *line_len;
1269 else if ( action_flags & IS_RGB )
1271 *srcPitch = width << 2; /* one R, one G, one B, one X per pixel */
1272 *dstPitch = ((npixels << 2) + 63) & ~63;
1273 *line_len = npixels << 2;
1274 *newFBSize = nlines * *dstPitch;
1275 *newTTSize = nlines * *dstPitch;
1279 if ( action_flags & CONVERT_TO_YUY2 )
1281 *dstPitch = ((npixels << 1) + 63) & ~63;
1282 *line_len = npixels << 1;
1283 *newFBSize = nlines * *dstPitch;
1284 *newTTSize = nlines * *line_len;
1287 if ( action_flags & SWAP_UV )
1288 { //I420 swaps U and V
1290 *s2offset = *s3offset;
1294 if ( action_flags & USE_OVERLAY ) // overlay double buffering ...
1295 (*newFBSize) <<= 1; // ... means double the amount of VRAM needed
1302 * NV_set_action_flags
1303 * This function computes the action flags from the input image,
1304 * that is, it decides what NVPutImage and its helpers must do.
1305 * This eases readability by avoiding lots of switch-case statements in the core NVPutImage
1307 static void NV_set_action_flags(NVPtr pNv, ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, int id, int * action_flags)
1310 if ( id == FOURCC_YUY2 || id == FOURCC_UYVY )
1311 *action_flags |= IS_YUY2;
1313 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1314 *action_flags |= IS_YV12;
1316 if ( id == FOURCC_RGB ) /*How long will we support it?*/
1317 *action_flags |= IS_RGB;
1319 if ( id == FOURCC_I420 ) /*I420 is YV12 with swapped UV*/
1320 *action_flags |= SWAP_UV;
1322 if ( !pPriv -> blitter )
1323 *action_flags |= USE_OVERLAY;
1326 WindowPtr pWin = NULL;
1328 if (!noCompositeExtension && WindowDrawable(pDraw->type))
1330 pWin = (WindowPtr)pDraw;
1334 if ( pWin->redirectDraw )
1335 *action_flags &= ~USE_OVERLAY;
1339 if ( ! ( *action_flags & USE_OVERLAY) )
1341 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1342 { /*The blitter does not handle YV12 natively*/
1343 *action_flags |= CONVERT_TO_YUY2;
1347 if ( pNv->Architecture == NV_ARCH_03 || pNv->Architecture == NV_ARCH_04 )
1348 if ( * action_flags & IS_YV12 ) //NV04-05 don't support native YV12 AFAIK
1349 *action_flags |= CONVERT_TO_YUY2;
1351 if ( pNv->Architecture == NV_ARCH_10 )
1353 if ( pNv->Chipset < CHIPSET_NV17 )
1355 *action_flags |= CONVERT_TO_YUY2;
1364 * PutImage is "the" important function of the Xv extension.
1365 * a client (e.g. video player) calls this function for every
1366 * image (of the video) to be displayed. this function then
1367 * scales and displays the image.
1369 * @param pScrn screen which hold the port where the image is put
1370 * @param src_x source point in the source image to start displaying from
1371 * @param src_y see above
1372 * @param src_w width of the source image to display
1373 * @param src_h see above
1374 * @param drw_x screen point to display to
1376 * @param drw_w width of the screen drawable
1378 * @param id pixel format of image
1379 * @param buf pointer to buffer containing the source image
1380 * @param width total width of the source image we are passed
1382 * @param Sync unused
1383 * @param clipBoxes ??
1384 * @param data pointer to port
1385 * @param pDraw drawable pointer
1388 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
1389 short drw_x, short drw_y,
1390 short src_w, short src_h,
1391 short drw_w, short drw_h,
1394 short width, short height,
1395 Bool Sync, /*FIXME: need to honor the Sync*/
1396 RegionPtr clipBoxes,
1401 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1402 NVPtr pNv = NVPTR(pScrn);
1403 INT32 xa = 0, xb = 0, ya = 0, yb = 0; //source box
1404 int newFBSize = 0, newTTSize = 0; //size to allocate in VRAM and in GART respectively
1405 int offset = 0, s2offset = 0, s3offset = 0; //card VRAM offset, source offsets for U and V planes
1406 int srcPitch = 0, srcPitch2 = 0, dstPitch = 0; //source pitch, source pitch of U and V planes in case of YV12, VRAM destination pitch
1407 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
1411 int line_len = 0; //length of a line, like npixels, but in bytes
1412 int DMAoffset = 0; //additional VRAM offset to start the DMA copy to
1413 int UVDMAoffset = 0;
1414 NVAllocRec * destination_buffer = NULL;
1415 unsigned char * video_mem_destination = NULL;
1416 int action_flags; //what shall we do?
1419 if (pPriv->grabbedByV4L)
1423 NV_set_action_flags(pNv, pScrn, pDraw, pPriv, id, &action_flags);
1425 if ( NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
1426 &src_x, &src_y, &src_w, &src_h,
1427 &drw_x, &drw_y, &drw_w, &drw_h,
1428 &left, &top, &right, &bottom, &dstBox,
1430 clipBoxes, width, height ) )
1436 if ( NV_calculate_pitches_and_mem_size(action_flags, &srcPitch, &srcPitch2, &dstPitch,
1437 &s2offset, &s3offset,
1438 & newFBSize, &newTTSize ,&line_len ,
1439 npixels, nlines, width, height) )
1441 return BadImplementation;
1444 /* There are some cases (tvtime with overscan for example) where the input image is larger (width/height) than
1445 the source rectangle for the overlay (src_w, src_h). In those cases, we try to do something optimal by uploading only
1446 the necessary data. */
1447 if ( action_flags & IS_YUY2 || action_flags & IS_RGB )
1449 buf += (top * srcPitch) + left;
1450 DMAoffset += left + (top * dstPitch);
1453 if ( action_flags & IS_YV12 )
1455 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1459 if ( action_flags & CONVERT_TO_YUY2 )
1461 DMAoffset += (left << 1) + (top * dstPitch);
1466 //real YV12 - we offset only the luma plane, and copy the whole color plane, for easiness
1467 DMAoffset += left + (top * dstPitch);
1468 UVDMAoffset += left + (top >> 1) * dstPitch;
1472 pPriv->video_mem = NVAllocateVideoMemory(pScrn, pPriv->video_mem,
1474 if (!pPriv->video_mem)
1477 offset = pPriv->video_mem->offset;
1479 /*The overlay supports hardware double buffering. We handle this here*/
1480 if (pPriv->doubleBuffer) {
1481 int mask = 1 << (pPriv->currentBuffer << 2);
1483 /* overwrite the newest buffer if there's not one free */
1484 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1485 if (!pPriv->currentBuffer)
1486 offset += newFBSize >> 1;
1490 else if (pPriv->currentBuffer)
1491 offset += newFBSize >> 1;
1494 /*Now we take a decision regarding the way we send the data to the card.
1495 Either we use double buffering of "private" TT memory
1496 Either we rely on X's GARTScratch
1497 Either we fallback on CPU copy
1500 /* Try to allocate host-side double buffers, unless we have already failed*/
1501 /* We take only nlines * line_len bytes - that is, only the pixel data we are interested in - because the stuff in the GART is
1502 written contiguously */
1503 if ( pPriv -> currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1505 pPriv->TT_mem_chunk[0] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[0],
1507 if ( pPriv->TT_mem_chunk[0] )
1509 pPriv->TT_mem_chunk[1] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[1],
1512 if ( ! pPriv->TT_mem_chunk[1] )
1514 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
1515 pPriv->TT_mem_chunk[0] = NULL;
1516 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1517 //xf86DrvMsg(0, X_INFO, "Alloc 1 failed\n");
1522 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1523 //xf86DrvMsg(0, X_INFO, "Alloc 0 failed\n");
1527 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1528 { //if we have a private buffer
1529 destination_buffer = pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1530 //xf86DrvMsg(0, X_INFO, "Using private mem chunk #%d\n", pPriv->currentHostBuffer);
1532 /* We know where we are going to write, but we are not sure yet whether we can do it directly, because
1533 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.
1534 If we do, then we must wait for it before overwriting the buffer.
1535 Else we need one, so we call the Xv notifier allocator.*/
1536 if ( pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1538 //xf86DrvMsg(0, X_INFO, "Waiting for notifier %p (%d)\n", pPriv->DMANotifier[pPriv->currentHostBuffer], pPriv->currentHostBuffer);
1539 if (!NVNotifierWaitStatus(pScrn, pPriv->DMANotifier[pPriv->currentHostBuffer], 0, 0))
1544 //xf86DrvMsg(0, X_INFO, "Allocating notifier...\n");
1545 pPriv->DMANotifier [ pPriv->currentHostBuffer ] = NVXvDMANotifierAlloc(pScrn);
1546 if (! pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1547 { /* 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.
1548 I know that's a lot of code but I believe it's necessary to properly handle all the cases*/
1549 xf86DrvMsg(0, X_ERROR, "Ran out of Xv notifiers!\n");
1550 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
1551 pPriv->TT_mem_chunk[0] = NULL;
1552 NVFreeMemory(pNv, pPriv->TT_mem_chunk[1]);
1553 pPriv->TT_mem_chunk[1] = NULL;
1554 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1556 //xf86DrvMsg(0, X_INFO, "Got notifier %p\n", pPriv->DMANotifier [ pPriv->currentHostBuffer ]);
1560 if ( pPriv -> currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE )
1561 { //otherwise we fall back on DDX's GARTScratch
1562 destination_buffer = pNv->GARTScratch;
1563 //xf86DrvMsg(0, X_INFO, "Using global GART memory chunk\n");
1566 if ( !destination_buffer) //if we have no GART at all
1569 if(newTTSize <= destination_buffer->size)
1571 unsigned char *dst = destination_buffer->map;
1574 /* Upload to GART */
1575 if ( action_flags & IS_YV12)
1577 if ( action_flags & CONVERT_TO_YUY2 )
1579 NVCopyData420(buf + (top * srcPitch) + left,
1580 buf + s2offset, buf + s3offset,
1581 dst, srcPitch, srcPitch2,
1582 line_len, nlines, npixels);
1586 unsigned char * tbuf = buf + top * srcPitch + left;
1587 unsigned char * tdst = dst;
1588 //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);
1590 for ( i=0; i < nlines; i++)
1592 memcpy(tdst, tbuf, line_len);
1596 dst += line_len * nlines;
1597 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, dst, line_len, srcPitch2, nlines, line_len);
1602 for ( i=0; i < nlines; i++)
1604 memcpy(dst, buf, line_len);
1611 NVDmaStart(pNv, NvMemFormat, MEMFORMAT_DMA_OBJECT_IN, 2);
1612 NVDmaNext (pNv, NvDmaTT);
1613 NVDmaNext (pNv, NvDmaFB);
1614 pNv->M2MFDirection = 1;
1617 if ( action_flags & IS_YV12 && ! (action_flags & CONVERT_TO_YUY2) )
1618 { /*we start the color plane transfer separately*/
1619 NVDmaStart(pNv, NvMemFormat,
1620 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1621 NVDmaNext (pNv, (uint32_t)destination_buffer->offset + line_len * nlines);
1622 NVDmaNext (pNv, (uint32_t)offset + dstPitch * nlines);
1623 NVDmaNext (pNv, line_len);
1624 NVDmaNext (pNv, dstPitch);
1625 NVDmaNext (pNv, line_len);
1626 NVDmaNext (pNv, (nlines >> 1));
1627 NVDmaNext (pNv, (1<<8)|1);
1632 NVDmaStart(pNv, NvMemFormat,
1633 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1634 NVDmaNext (pNv, (uint32_t)destination_buffer->offset);
1635 NVDmaNext (pNv, (uint32_t)offset /*+ DMAoffset*/);
1636 NVDmaNext (pNv, line_len);
1637 NVDmaNext (pNv, dstPitch);
1638 NVDmaNext (pNv, line_len);
1639 NVDmaNext (pNv, nlines);
1640 NVDmaNext (pNv, (1<<8)|1);
1643 if ( destination_buffer == pNv->GARTScratch )
1645 NVNotifierReset(pScrn, pNv->Notifier0);
1648 NVNotifierReset(pScrn, pPriv->DMANotifier[pPriv->currentHostBuffer]);
1649 NVDmaStart(pNv, NvMemFormat,
1650 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1651 NVDmaNext (pNv, pPriv->DMANotifier[pPriv->currentHostBuffer]->handle);
1655 NVDmaStart(pNv, NvMemFormat,
1656 NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1659 NVDmaStart(pNv, NvMemFormat, 0x100, 1);
1662 //Put back NvDmaNotifier0 for EXA
1663 NVDmaStart(pNv, NvMemFormat,
1664 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1665 NVDmaNext (pNv, NvDmaNotifier0);
1669 if ( destination_buffer == pNv->GARTScratch )
1670 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 0))
1673 else { //GART is too small, we fallback on CPU copy
1675 video_mem_destination = pPriv->video_mem->map + (offset - (uint32_t)pPriv->video_mem->offset);
1677 if ( action_flags & IS_YV12 )
1679 if ( action_flags & CONVERT_TO_YUY2 )
1681 NVCopyData420(buf + (top * srcPitch) + left,
1682 buf + s2offset, buf + s3offset,
1683 video_mem_destination, srcPitch, srcPitch2,
1684 dstPitch, nlines, npixels);
1687 unsigned char * tbuf = buf + left + top * srcPitch;
1688 for ( i=0; i < nlines; i++)
1690 int dwords = npixels << 1;
1691 while (dwords & ~0x03)
1693 *video_mem_destination = *tbuf;
1694 *(video_mem_destination + 1) = *(tbuf + 1);
1695 *(video_mem_destination + 2) = *(tbuf + 2);
1696 *(video_mem_destination + 3) = *(tbuf + 3);
1697 video_mem_destination += 4;
1704 *(video_mem_destination + 2) = *(tbuf + 2);
1706 *(video_mem_destination + 1) = *(tbuf + 1);
1708 *video_mem_destination = *tbuf;
1711 video_mem_destination += dstPitch - (npixels << 1);
1712 tbuf += srcPitch - (npixels << 1);
1715 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, video_mem_destination, dstPitch, srcPitch2, nlines, line_len);
1720 for ( i=0; i < nlines; i++)
1722 int dwords = npixels << 1;
1723 while (dwords & ~0x03)
1725 *video_mem_destination = *buf;
1726 *(video_mem_destination + 1) = *(buf + 1);
1727 *(video_mem_destination + 2) = *(buf + 2);
1728 *(video_mem_destination + 3) = *(buf + 3);
1729 video_mem_destination += 4;
1736 *(video_mem_destination + 2) = *(buf + 2);
1738 *(video_mem_destination + 1) = *(buf + 1);
1740 *video_mem_destination = *buf;
1743 video_mem_destination += dstPitch - (npixels << 1);
1744 buf += srcPitch - (npixels << 1);
1752 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1753 pPriv->currentHostBuffer ^= 1;
1755 if ( action_flags & USE_OVERLAY )
1757 NVPutOverlayImage(pScrn, offset, ((action_flags & IS_YUY2) || (action_flags & CONVERT_TO_YUY2)) ? 0 : offset + nlines * dstPitch, id,
1761 src_w, src_h, drw_w, drw_h,
1763 pPriv->currentBuffer ^= 1;
1768 NVPutBlitImage(pScrn, offset, id,
1772 src_w, src_h, drw_w, drw_h,
1780 * QueryImageAttributes
1783 * - size (memory required to store image),
1787 * depending on colorspace (id) and dimensions (w,h) of image
1791 * may be adjusted as needed
1793 * @param pScrn unused
1794 * @param id colorspace of image
1795 * @param w pointer to width of image
1796 * @param h pointer to height of image
1797 * @param pitches pitches[i] = length of a scanline in plane[i]
1798 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1799 * @return size of the memory required for the XvImage queried
1802 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1803 unsigned short *w, unsigned short *h,
1804 int *pitches, int *offsets)
1808 if (*w > IMAGE_MAX_W)
1810 if (*h > IMAGE_MAX_H)
1813 *w = (*w + 1) & ~1; // width rounded up to an even number
1820 *h = (*h + 1) & ~1; // height rounded up to an even number
1821 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1823 pitches[0] = size; // width rounded up to a multiple of 4
1826 offsets[1] = size; // number of pixels in "rounded up" image
1827 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1829 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1830 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1831 size += tmp; // 5/4*number of pixels in "rounded up" image
1833 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1834 size += tmp; // = 3/2*number of pixels in "rounded up" image
1838 size = *w << 1; // 2*width
1840 pitches[0] = size; // 2*width
1841 size *= *h; // 2*width*height
1844 size = *w << 2; // 4*width (32 bit per pixel)
1846 pitches[0] = size; // 4*width
1847 size *= *h; // 4*width*height
1857 /***** Exported offscreen surface stuff ****/
1861 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1862 unsigned short w, unsigned short h,
1863 XF86SurfacePtr surface)
1865 NVPtr pNv = NVPTR(pScrn);
1866 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1869 bpp = pScrn->bitsPerPixel >> 3;
1871 if (pPriv->grabbedByV4L)
1874 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1878 pPriv->pitch = ((w << 1) + 63) & ~63;
1879 size = h * pPriv->pitch / bpp;
1881 pPriv->video_mem = NVAllocateVideoMemory(pScrn,
1884 if (!pPriv->video_mem)
1890 surface->height = h;
1891 surface->pScrn = pScrn;
1892 surface->pitches = &pPriv->pitch;
1893 surface->offsets = &pPriv->offset;
1894 surface->devPrivate.ptr = (pointer)pPriv;
1897 /* grab the video */
1898 NVStopOverlay(pScrn);
1899 pPriv->videoStatus = 0;
1900 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1901 pPriv->grabbedByV4L = TRUE;
1907 NVStopSurface(XF86SurfacePtr surface)
1909 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1911 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
1912 NVStopOverlay(surface->pScrn);
1913 pPriv->videoStatus = 0;
1920 NVFreeSurface(XF86SurfacePtr surface)
1922 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1924 if (pPriv->grabbedByV4L) {
1925 NVStopSurface(surface);
1926 NVFreeOverlayMemory(surface->pScrn);
1927 pPriv->grabbedByV4L = FALSE;
1934 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
1936 NVPtr pNv = NVPTR(pScrn);
1937 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1939 return NVGetOverlayPortAttribute(pScrn, attribute,
1940 value, (pointer)pPriv);
1944 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
1946 NVPtr pNv = NVPTR(pScrn);
1947 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1949 return NVSetOverlayPortAttribute(pScrn, attribute,
1950 value, (pointer)pPriv);
1954 NVDisplaySurface(XF86SurfacePtr surface,
1955 short src_x, short src_y,
1956 short drw_x, short drw_y,
1957 short src_w, short src_h,
1958 short drw_w, short drw_h,
1959 RegionPtr clipBoxes)
1961 ScrnInfoPtr pScrn = surface->pScrn;
1962 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1963 INT32 xa, xb, ya, yb;
1966 if (!pPriv->grabbedByV4L)
1969 if (src_w > (drw_w << 3))
1971 if (src_h > (drw_h << 3))
1981 dstBox.x2 = drw_x + drw_w;
1983 dstBox.y2 = drw_y + drw_h;
1985 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1986 surface->width, surface->height))
1989 dstBox.x1 -= pScrn->frameX0;
1990 dstBox.x2 -= pScrn->frameX0;
1991 dstBox.y1 -= pScrn->frameY0;
1992 dstBox.y2 -= pScrn->frameY0;
1994 pPriv->currentBuffer = 0;
1996 NVPutOverlayImage(pScrn, surface->offsets[0], 0, surface->id,
1997 surface->pitches[0], &dstBox, xa, ya, xb, yb,
1998 surface->width, surface->height, src_w, src_h,
1999 drw_w, drw_h, clipBoxes);
2006 * this function does all the work setting up a blit port
2010 static XF86VideoAdaptorPtr
2011 NVSetupBlitVideo (ScreenPtr pScreen)
2013 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2014 NVPtr pNv = NVPTR(pScrn);
2015 XF86VideoAdaptorPtr adapt;
2016 NVPortPrivPtr pPriv;
2019 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2020 sizeof(NVPortPrivRec) +
2021 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
2025 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2027 adapt->name = "NV Video Blitter";
2028 adapt->nEncodings = 1;
2029 adapt->pEncodings = &DummyEncoding;
2030 adapt->nFormats = NUM_FORMATS_ALL;
2031 adapt->pFormats = NVFormats;
2032 adapt->nPorts = NUM_BLIT_PORTS;
2033 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2035 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
2036 for(i = 0; i < NUM_BLIT_PORTS; i++)
2037 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2039 if(pNv->WaitVSyncPossible) {
2040 adapt->pAttributes = NVBlitAttributes;
2041 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
2043 adapt->pAttributes = NULL;
2044 adapt->nAttributes = 0;
2047 adapt->pImages = NVImages;
2048 adapt->nImages = NUM_IMAGES_ALL;
2049 adapt->PutVideo = NULL;
2050 adapt->PutStill = NULL;
2051 adapt->GetVideo = NULL;
2052 adapt->GetStill = NULL;
2053 adapt->StopVideo = NVStopBlitVideo;
2054 adapt->SetPortAttribute = NVSetBlitPortAttribute;
2055 adapt->GetPortAttribute = NVGetBlitPortAttribute;
2056 adapt->QueryBestSize = NVQueryBestSize;
2057 adapt->PutImage = NVPutImage;
2058 adapt->QueryImageAttributes = NVQueryImageAttributes;
2060 pPriv->videoStatus = 0;
2061 pPriv->grabbedByV4L = FALSE;
2062 pPriv->blitter = TRUE;
2063 pPriv->doubleBuffer = FALSE;
2064 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
2066 pNv->blitAdaptor = adapt;
2067 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
2073 * NV10SetupOverlayVideo
2074 * this function does all the work setting up an overlay port
2076 * @return overlay port
2077 * @see NVResetVideo(ScrnInfoPtr pScrn)
2079 static XF86VideoAdaptorPtr
2080 NV10SetupOverlayVideo(ScreenPtr pScreen)
2082 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2083 NVPtr pNv = NVPTR(pScrn);
2084 XF86VideoAdaptorPtr adapt;
2085 NVPortPrivPtr pPriv;
2087 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2088 sizeof(NVPortPrivRec) +
2089 sizeof(DevUnion)))) {
2093 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2094 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
2095 adapt->name = "NV Video Overlay";
2096 adapt->nEncodings = 1;
2097 adapt->pEncodings = &DummyEncoding;
2098 adapt->nFormats = NUM_FORMATS_ALL;
2099 adapt->pFormats = NVFormats;
2101 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2103 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
2104 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
2106 adapt->pAttributes = NVOverlayAttributes;
2107 adapt->nAttributes = NUM_OVERLAY_ATTRIBUTES;
2108 adapt->pImages = NVImages;
2109 adapt->nImages = NUM_IMAGES_YUV;
2110 adapt->PutVideo = NULL;
2111 adapt->PutStill = NULL;
2112 adapt->GetVideo = NULL;
2113 adapt->GetStill = NULL;
2114 adapt->StopVideo = NVStopOverlayVideo;
2115 adapt->SetPortAttribute = NVSetOverlayPortAttribute;
2116 adapt->GetPortAttribute = NVGetOverlayPortAttribute;
2117 adapt->QueryBestSize = NVQueryBestSize;
2118 adapt->PutImage = NVPutImage;
2119 adapt->QueryImageAttributes = NVQueryImageAttributes;
2121 pPriv->videoStatus = 0;
2122 pPriv->currentBuffer = 0;
2123 pPriv->grabbedByV4L = FALSE;
2124 pPriv->blitter = FALSE;
2126 NVSetPortDefaults (pScrn, pPriv);
2128 /* gotta uninit this someplace */
2129 REGION_NULL(pScreen, &pPriv->clip);
2131 pNv->overlayAdaptor = adapt;
2133 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
2134 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
2135 xvContrast = MAKE_ATOM("XV_CONTRAST");
2136 xvColorKey = MAKE_ATOM("XV_COLORKEY");
2137 xvSaturation = MAKE_ATOM("XV_SATURATION");
2138 xvHue = MAKE_ATOM("XV_HUE");
2139 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
2140 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
2141 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
2143 NVResetVideo(pScrn);
2148 XF86OffscreenImageRec NVOffscreenImages[2] = {
2151 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2156 NVGetSurfaceAttribute,
2157 NVSetSurfaceAttribute,
2158 IMAGE_MAX_W, IMAGE_MAX_H,
2159 NUM_OVERLAY_ATTRIBUTES - 1,
2160 &NVOverlayAttributes[1]
2164 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2169 NVGetSurfaceAttribute,
2170 NVSetSurfaceAttribute,
2171 IMAGE_MAX_W, IMAGE_MAX_H,
2172 NUM_OVERLAY_ATTRIBUTES - 1,
2173 &NVOverlayAttributes[1]
2178 NVInitOffscreenImages (ScreenPtr pScreen)
2180 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
2184 * NVChipsetHasOverlay
2186 * newer chips don't support overlay anymore.
2187 * overlay feature is emulated via textures.
2190 * @return true, if chipset supports overlay
2193 NVChipsetHasOverlay(NVPtr pNv)
2195 switch (pNv->Architecture) {
2201 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
2212 * NVSetupOverlayVideo
2213 * check if chipset supports Overlay and CompositeExtension is disabled.
2214 * if so, setup overlay port
2216 * @return overlay port
2217 * @see NVChipsetHasOverlay(NVPtr pNv)
2218 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
2219 * @see NVInitOffscreenImages(ScreenPtr pScreen)
2221 static XF86VideoAdaptorPtr
2222 NVSetupOverlayVideo(ScreenPtr pScreen)
2224 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2225 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2226 NVPtr pNv = NVPTR(pScrn);
2228 if (!NVChipsetHasOverlay(pNv))
2231 overlayAdaptor = NV10SetupOverlayVideo(pScreen);
2233 NVInitOffscreenImages(pScreen); //I am not sure what this call does.
2236 if (!noCompositeExtension) {
2237 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2238 "XV: Composite is enabled, enabling overlay with smart blitter fallback\n");
2239 overlayAdaptor -> name = "NV Video Overlay with Composite";
2243 return overlayAdaptor;
2248 * tries to initialize one new overlay port and one new blit port
2249 * and add them to the list of ports on screen "pScreen".
2252 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
2253 * @see NVSetupBlitVideo(ScreenPtr pScreen)
2255 void NVInitVideo (ScreenPtr pScreen)
2257 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2258 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
2259 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2260 XF86VideoAdaptorPtr blitAdaptor = NULL;
2263 if (pScrn->bitsPerPixel == 8)
2266 overlayAdaptor = NVSetupOverlayVideo(pScreen);
2267 blitAdaptor = NVSetupBlitVideo(pScreen);
2269 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
2270 if(blitAdaptor || overlayAdaptor) {
2271 int size = num_adaptors;
2273 if(overlayAdaptor) size++;
2274 if(blitAdaptor) size++;
2276 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
2279 memcpy(newAdaptors, adaptors, num_adaptors *
2280 sizeof(XF86VideoAdaptorPtr));
2283 if(overlayAdaptor) {
2284 newAdaptors[num_adaptors] = overlayAdaptor;
2289 newAdaptors[num_adaptors] = blitAdaptor;
2293 adaptors = newAdaptors;
2298 xf86XVScreenInit(pScreen, adaptors, num_adaptors);