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,
1144 for ( j = 0; j < h; j++ )
1146 unsigned char * us = src1;
1147 unsigned char * vs = src2;
1148 unsigned int * vuvud = (unsigned int *) dst;
1149 for ( i = 0; i < l; i++ )
1151 #if X_BYTE_ORDER == X_BIG_ENDIAN
1152 *vuvud++ = (vs[0]<<24) | (us[0]<<16) | (vs[1]<<8) | us[1];
1154 *vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24);
1160 unsigned short *vud = (unsigned short *) vuvud;
1161 #if X_BYTE_ORDER == X_BIG_ENDIAN
1162 *vud = (vs[0]<<8) | (us[0] << 0);
1164 *vud = vs[0] | (us[0]<<8);
1175 static int NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 * xa, INT32 * xb, INT32 * ya, INT32 * yb,
1176 short * src_x, short * src_y, short * src_w, short * src_h,
1177 short * drw_x, short * drw_y, short * drw_w, short * drw_h,
1178 int * left, int * top, int * right, int * bottom,
1180 int * npixels, int * nlines,
1181 RegionPtr clipBoxes, short width, short height
1185 if ( action_flags & USE_OVERLAY )
1186 { /* overlay hardware scaler limitation - copied from nv, UNCHECKED*/
1187 if (*src_w > (*drw_w << 3))
1188 *drw_w = *src_w >> 3;
1189 if (*src_h > (*drw_h << 3))
1190 *drw_h = *src_h >> 3;
1196 *xb = *src_x + *src_w;
1198 *yb = *src_y + *src_h;
1200 dstBox->x1 = *drw_x;
1201 dstBox->x2 = *drw_x + *drw_w;
1202 dstBox->y1 = *drw_y;
1203 dstBox->y2 = *drw_y + *drw_h;
1205 if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
1209 if ( action_flags & USE_OVERLAY )
1211 dstBox->x1 -= pScrn->frameX0;
1212 dstBox->x2 -= pScrn->frameX0;
1213 dstBox->y1 -= pScrn->frameY0;
1214 dstBox->y2 -= pScrn->frameY0;
1219 /* Convert fixed point to integer, as xf86XVClipVideoHelper probably turns its parameter into fixed point values */
1220 *left = (*xa) >> 16;
1221 if (*left < 0) *left = 0;
1223 if (*top < 0) *top = 0;
1224 *right = (*xb) >> 16;
1225 if (*right > width) *right = width;
1226 *bottom = (*yb) >> 16;
1227 if (*bottom > height) *bottom = height;
1229 if ( action_flags & IS_YV12 )
1231 *left &= ~1; //even "left", even "top", even number of pixels per line and even number of lines
1232 *npixels = ((*right + 1) & ~1) - *left;
1234 *nlines = ((*bottom + 1) & ~1) - *top;
1236 else if ( action_flags & IS_YUY2 )
1238 *left &= ~1; //even "left"
1239 *npixels = ((*right + 1) & ~1) - *left; //even number of pixels per line
1240 *nlines = *bottom - *top;
1241 *left <<= 1; //16bpp
1243 else if (action_flags & IS_RGB )
1245 *npixels = *right - *left;
1246 *nlines = *bottom - *top;
1247 *left <<= 2; //32bpp
1253 static int NV_calculate_pitches_and_mem_size(int action_flags, int * srcPitch, int * srcPitch2, int * dstPitch,
1254 int * s2offset, int * s3offset,
1255 int * newFBSize, int * newTTSize,
1256 int * line_len, int npixels, int nlines, int width, int height)
1260 if ( action_flags & IS_YV12 )
1262 *srcPitch = (width + 3) & ~3; /* of luma */
1263 *s2offset = *srcPitch * height;
1264 *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
1265 *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
1266 *dstPitch = (npixels + 63) &~ 63; /*luma and chroma pitch*/
1267 *line_len = npixels;
1268 *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1269 *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1271 else if ( action_flags & IS_YUY2 )
1273 *srcPitch = width << 1; /* one luma, one chroma per pixel */
1274 *dstPitch = ((npixels << 1) + 63) & ~63;
1275 *line_len = npixels << 1;
1276 *newFBSize = nlines * *dstPitch;
1277 *newTTSize = nlines * *line_len;
1279 else if ( action_flags & IS_RGB )
1281 *srcPitch = width << 2; /* one R, one G, one B, one X per pixel */
1282 *dstPitch = ((npixels << 2) + 63) & ~63;
1283 *line_len = npixels << 2;
1284 *newFBSize = nlines * *dstPitch;
1285 *newTTSize = nlines * *dstPitch;
1289 if ( action_flags & CONVERT_TO_YUY2 )
1291 *dstPitch = ((npixels << 1) + 63) & ~63;
1292 *line_len = npixels << 1;
1293 *newFBSize = nlines * *dstPitch;
1294 *newTTSize = nlines * *line_len;
1297 if ( action_flags & SWAP_UV )
1298 { //I420 swaps U and V
1300 *s2offset = *s3offset;
1304 if ( action_flags & USE_OVERLAY ) // overlay double buffering ...
1305 (*newFBSize) <<= 1; // ... means double the amount of VRAM needed
1312 * NV_set_action_flags
1313 * This function computes the action flags from the input image,
1314 * that is, it decides what NVPutImage and its helpers must do.
1315 * This eases readability by avoiding lots of switch-case statements in the core NVPutImage
1317 static void NV_set_action_flags(NVPtr pNv, ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, int id, int * action_flags)
1320 if ( id == FOURCC_YUY2 || id == FOURCC_UYVY )
1321 *action_flags |= IS_YUY2;
1323 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1324 *action_flags |= IS_YV12;
1326 if ( id == FOURCC_RGB ) /*How long will we support it?*/
1327 *action_flags |= IS_RGB;
1329 if ( id == FOURCC_I420 ) /*I420 is YV12 with swapped UV*/
1330 *action_flags |= SWAP_UV;
1332 if ( !pPriv -> blitter )
1333 *action_flags |= USE_OVERLAY;
1336 WindowPtr pWin = NULL;
1338 if (!noCompositeExtension && WindowDrawable(pDraw->type))
1340 pWin = (WindowPtr)pDraw;
1344 if ( pWin->redirectDraw )
1345 *action_flags &= ~USE_OVERLAY;
1349 if ( ! ( *action_flags & USE_OVERLAY) )
1351 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1352 { /*The blitter does not handle YV12 natively*/
1353 *action_flags |= CONVERT_TO_YUY2;
1357 if ( pNv->Architecture == NV_ARCH_03 || pNv->Architecture == NV_ARCH_04 )
1358 if ( * action_flags & IS_YV12 ) //NV04-05 don't support native YV12 AFAIK
1359 *action_flags |= CONVERT_TO_YUY2;
1361 if ( pNv->Architecture == NV_ARCH_10 )
1363 switch ( pNv->Chipset & 0xfff0 )
1368 case CHIPSET_NFORCE: /*XXX: unsure about nforce and nforce2*/
1369 case CHIPSET_NFORCE2:
1370 *action_flags |= CONVERT_TO_YUY2; break;
1380 * PutImage is "the" important function of the Xv extension.
1381 * a client (e.g. video player) calls this function for every
1382 * image (of the video) to be displayed. this function then
1383 * scales and displays the image.
1385 * @param pScrn screen which hold the port where the image is put
1386 * @param src_x source point in the source image to start displaying from
1387 * @param src_y see above
1388 * @param src_w width of the source image to display
1389 * @param src_h see above
1390 * @param drw_x screen point to display to
1392 * @param drw_w width of the screen drawable
1394 * @param id pixel format of image
1395 * @param buf pointer to buffer containing the source image
1396 * @param width total width of the source image we are passed
1398 * @param Sync unused
1399 * @param clipBoxes ??
1400 * @param data pointer to port
1401 * @param pDraw drawable pointer
1404 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
1405 short drw_x, short drw_y,
1406 short src_w, short src_h,
1407 short drw_w, short drw_h,
1410 short width, short height,
1411 Bool Sync, /*FIXME: need to honor the Sync*/
1412 RegionPtr clipBoxes,
1417 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1418 NVPtr pNv = NVPTR(pScrn);
1419 INT32 xa = 0, xb = 0, ya = 0, yb = 0; //source box
1420 int newFBSize = 0, newTTSize = 0; //size to allocate in VRAM and in GART respectively
1421 int offset = 0, s2offset = 0, s3offset = 0; //card VRAM offset, source offsets for U and V planes
1422 int srcPitch = 0, srcPitch2 = 0, dstPitch = 0; //source pitch, source pitch of U and V planes in case of YV12, VRAM destination pitch
1423 int top = 0, left = 0, right = 0, bottom = 0, npixels = 0, nlines = 0; //position of the given source data (using src_*), number of pixels and lines we are interested in
1427 int line_len = 0; //length of a line, like npixels, but in bytes
1428 int DMAoffset = 0; //additional VRAM offset to start the DMA copy to
1429 int UVDMAoffset = 0;
1430 NVAllocRec * destination_buffer = NULL;
1431 unsigned char * video_mem_destination = NULL;
1432 int action_flags; //what shall we do?
1435 if (pPriv->grabbedByV4L)
1439 NV_set_action_flags(pNv, pScrn, pDraw, pPriv, id, &action_flags);
1441 if ( NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
1442 &src_x, &src_y, &src_w, &src_h,
1443 &drw_x, &drw_y, &drw_w, &drw_h,
1444 &left, &top, &right, &bottom, &dstBox,
1446 clipBoxes, width, height ) )
1452 if ( NV_calculate_pitches_and_mem_size(action_flags, &srcPitch, &srcPitch2, &dstPitch,
1453 &s2offset, &s3offset,
1454 & newFBSize, &newTTSize ,&line_len ,
1455 npixels, nlines, width, height) )
1457 return BadImplementation;
1460 /* There are some cases (tvtime with overscan for example) where the input image is larger (width/height) than
1461 the source rectangle for the overlay (src_w, src_h). In those cases, we try to do something optimal by uploading only
1462 the necessary data. */
1463 if ( action_flags & IS_YUY2 || action_flags & IS_RGB )
1465 buf += (top * srcPitch) + left;
1466 DMAoffset += left + (top * dstPitch);
1469 if ( action_flags & IS_YV12 )
1471 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1475 if ( action_flags & CONVERT_TO_YUY2 )
1477 DMAoffset += (left << 1) + (top * dstPitch);
1482 //real YV12 - we offset only the luma plane, and copy the whole color plane, for easiness
1483 DMAoffset += left + (top * dstPitch);
1484 UVDMAoffset += left + (top >> 1) * dstPitch;
1488 pPriv->video_mem = NVAllocateVideoMemory(pScrn, pPriv->video_mem,
1490 if (!pPriv->video_mem)
1493 offset = pPriv->video_mem->offset;
1495 /*The overlay supports hardware double buffering. We handle this here*/
1496 if (pPriv->doubleBuffer) {
1497 int mask = 1 << (pPriv->currentBuffer << 2);
1499 /* overwrite the newest buffer if there's not one free */
1500 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1501 if (!pPriv->currentBuffer)
1502 offset += newFBSize >> 1;
1506 else if (pPriv->currentBuffer)
1507 offset += newFBSize >> 1;
1510 /*Now we take a decision regarding the way we send the data to the card.
1511 Either we use double buffering of "private" TT memory
1512 Either we rely on X's GARTScratch
1513 Either we fallback on CPU copy
1516 /* Try to allocate host-side double buffers, unless we have already failed*/
1517 /* We take only nlines * line_len bytes - that is, only the pixel data we are interested in - because the stuff in the GART is
1518 written contiguously */
1519 if ( pPriv -> currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1521 pPriv->TT_mem_chunk[0] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[0],
1523 if ( pPriv->TT_mem_chunk[0] )
1525 pPriv->TT_mem_chunk[1] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[1],
1528 if ( ! pPriv->TT_mem_chunk[1] )
1530 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
1531 pPriv->TT_mem_chunk[0] = NULL;
1532 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1533 //xf86DrvMsg(0, X_INFO, "Alloc 1 failed\n");
1538 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1539 //xf86DrvMsg(0, X_INFO, "Alloc 0 failed\n");
1543 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1544 { //if we have a private buffer
1545 destination_buffer = pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1546 //xf86DrvMsg(0, X_INFO, "Using private mem chunk #%d\n", pPriv->currentHostBuffer);
1548 /* We know where we are going to write, but we are not sure yet whether we can do it directly, because
1549 the card could be working on the buffer for the last-but-one frame. So we check if we have a notifier ready or not.
1550 If we do, then we must wait for it before overwriting the buffer.
1551 Else we need one, so we call the Xv notifier allocator.*/
1552 if ( pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1554 //xf86DrvMsg(0, X_INFO, "Waiting for notifier %p (%d)\n", pPriv->DMANotifier[pPriv->currentHostBuffer], pPriv->currentHostBuffer);
1555 if (!NVNotifierWaitStatus(pScrn, pPriv->DMANotifier[pPriv->currentHostBuffer], 0, 0))
1560 //xf86DrvMsg(0, X_INFO, "Allocating notifier...\n");
1561 pPriv->DMANotifier [ pPriv->currentHostBuffer ] = NVXvDMANotifierAlloc(pScrn);
1562 if (! pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1563 { /* In case we are out of notifiers (then our guy is watching 3 movies at a time!!), we fallback on global GART, and free the private buffers.
1564 I know that's a lot of code but I believe it's necessary to properly handle all the cases*/
1565 xf86DrvMsg(0, X_ERROR, "Ran out of Xv notifiers!\n");
1566 NVFreeMemory(pNv, pPriv->TT_mem_chunk[0]);
1567 pPriv->TT_mem_chunk[0] = NULL;
1568 NVFreeMemory(pNv, pPriv->TT_mem_chunk[1]);
1569 pPriv->TT_mem_chunk[1] = NULL;
1570 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1572 //xf86DrvMsg(0, X_INFO, "Got notifier %p\n", pPriv->DMANotifier [ pPriv->currentHostBuffer ]);
1576 if ( pPriv -> currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE )
1577 { //otherwise we fall back on DDX's GARTScratch
1578 destination_buffer = pNv->GARTScratch;
1579 //xf86DrvMsg(0, X_INFO, "Using global GART memory chunk\n");
1582 if ( !destination_buffer) //if we have no GART at all
1585 if(newTTSize <= destination_buffer->size)
1587 unsigned char *dst = destination_buffer->map;
1590 /* Upload to GART */
1591 if ( action_flags & IS_YV12)
1593 if ( action_flags & CONVERT_TO_YUY2 )
1595 NVCopyData420(buf + (top * srcPitch) + left,
1596 buf + s2offset, buf + s3offset,
1597 dst, srcPitch, srcPitch2,
1598 line_len, nlines, npixels);
1602 unsigned char * tbuf = buf + top * srcPitch + left;
1603 unsigned char * tdst = dst;
1604 //xf86DrvMsg(0, X_INFO, "srcPitch %d dstPitch %d srcPitch2 %d nlines %d npixels %d left %d top %d s2offset %d\n", srcPitch, dstPitch, srcPitch2, nlines, npixels, left, top, s2offset);
1606 for ( i=0; i < nlines; i++)
1608 memcpy(tdst, tbuf, line_len);
1612 dst += line_len * nlines;
1613 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, dst, line_len, srcPitch2, nlines, line_len);
1618 for ( i=0; i < nlines; i++)
1620 memcpy(dst, buf, line_len);
1627 NVDmaStart(pNv, NvMemFormat, MEMFORMAT_DMA_OBJECT_IN, 2);
1628 NVDmaNext (pNv, NvDmaTT);
1629 NVDmaNext (pNv, NvDmaFB);
1630 pNv->M2MFDirection = 1;
1633 if ( action_flags & IS_YV12 && ! (action_flags & CONVERT_TO_YUY2) )
1634 { /*we start the color plane transfer separately*/
1635 NVDmaStart(pNv, NvMemFormat,
1636 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1637 NVDmaNext (pNv, (uint32_t)destination_buffer->offset + line_len * nlines);
1638 NVDmaNext (pNv, (uint32_t)offset + dstPitch * nlines);
1639 NVDmaNext (pNv, line_len);
1640 NVDmaNext (pNv, dstPitch);
1641 NVDmaNext (pNv, line_len);
1642 NVDmaNext (pNv, (nlines >> 1));
1643 NVDmaNext (pNv, (1<<8)|1);
1648 NVDmaStart(pNv, NvMemFormat,
1649 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1650 NVDmaNext (pNv, (uint32_t)destination_buffer->offset);
1651 NVDmaNext (pNv, (uint32_t)offset /*+ DMAoffset*/);
1652 NVDmaNext (pNv, line_len);
1653 NVDmaNext (pNv, dstPitch);
1654 NVDmaNext (pNv, line_len);
1655 NVDmaNext (pNv, nlines);
1656 NVDmaNext (pNv, (1<<8)|1);
1659 if ( destination_buffer == pNv->GARTScratch )
1661 NVNotifierReset(pScrn, pNv->Notifier0);
1664 NVNotifierReset(pScrn, pPriv->DMANotifier[pPriv->currentHostBuffer]);
1665 NVDmaStart(pNv, NvMemFormat,
1666 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1667 NVDmaNext (pNv, pPriv->DMANotifier[pPriv->currentHostBuffer]->handle);
1671 NVDmaStart(pNv, NvMemFormat,
1672 NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1675 NVDmaStart(pNv, NvMemFormat, 0x100, 1);
1678 //Put back NvDmaNotifier0 for EXA
1679 NVDmaStart(pNv, NvMemFormat,
1680 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1681 NVDmaNext (pNv, NvDmaNotifier0);
1685 if ( destination_buffer == pNv->GARTScratch )
1686 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 0))
1689 else { //GART is too small, we fallback on CPU copy
1691 video_mem_destination = pPriv->video_mem->map + (offset - (uint32_t)pPriv->video_mem->offset);
1693 if ( action_flags & IS_YV12 )
1695 if ( action_flags & CONVERT_TO_YUY2 )
1697 NVCopyData420(buf + (top * srcPitch) + left,
1698 buf + s2offset, buf + s3offset,
1699 video_mem_destination, srcPitch, srcPitch2,
1700 dstPitch, nlines, npixels);
1703 unsigned char * tbuf = buf + left + top * srcPitch;
1704 for ( i=0; i < nlines; i++)
1706 int dwords = npixels << 1;
1707 while (dwords & ~0x03)
1709 *video_mem_destination = *tbuf;
1710 *(video_mem_destination + 1) = *(tbuf + 1);
1711 *(video_mem_destination + 2) = *(tbuf + 2);
1712 *(video_mem_destination + 3) = *(tbuf + 3);
1713 video_mem_destination += 4;
1720 *(video_mem_destination + 2) = *(tbuf + 2);
1722 *(video_mem_destination + 1) = *(tbuf + 1);
1724 *video_mem_destination = *tbuf;
1727 video_mem_destination += dstPitch - (npixels << 1);
1728 tbuf += srcPitch - (npixels << 1);
1731 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, video_mem_destination, dstPitch, srcPitch2, nlines, line_len);
1736 for ( i=0; i < nlines; i++)
1738 int dwords = npixels << 1;
1739 while (dwords & ~0x03)
1741 *video_mem_destination = *buf;
1742 *(video_mem_destination + 1) = *(buf + 1);
1743 *(video_mem_destination + 2) = *(buf + 2);
1744 *(video_mem_destination + 3) = *(buf + 3);
1745 video_mem_destination += 4;
1752 *(video_mem_destination + 2) = *(buf + 2);
1754 *(video_mem_destination + 1) = *(buf + 1);
1756 *video_mem_destination = *buf;
1759 video_mem_destination += dstPitch - (npixels << 1);
1760 buf += srcPitch - (npixels << 1);
1768 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1769 pPriv->currentHostBuffer ^= 1;
1771 if ( action_flags & USE_OVERLAY )
1773 NVPutOverlayImage(pScrn, offset, ((action_flags & IS_YUY2) || (action_flags & CONVERT_TO_YUY2)) ? 0 : offset + nlines * dstPitch, id,
1777 src_w, src_h, drw_w, drw_h,
1779 pPriv->currentBuffer ^= 1;
1784 NVPutBlitImage(pScrn, offset, id,
1788 src_w, src_h, drw_w, drw_h,
1796 * QueryImageAttributes
1799 * - size (memory required to store image),
1803 * depending on colorspace (id) and dimensions (w,h) of image
1807 * may be adjusted as needed
1809 * @param pScrn unused
1810 * @param id colorspace of image
1811 * @param w pointer to width of image
1812 * @param h pointer to height of image
1813 * @param pitches pitches[i] = length of a scanline in plane[i]
1814 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1815 * @return size of the memory required for the XvImage queried
1818 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1819 unsigned short *w, unsigned short *h,
1820 int *pitches, int *offsets)
1824 if (*w > IMAGE_MAX_W)
1826 if (*h > IMAGE_MAX_H)
1829 *w = (*w + 1) & ~1; // width rounded up to an even number
1836 *h = (*h + 1) & ~1; // height rounded up to an even number
1837 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1839 pitches[0] = size; // width rounded up to a multiple of 4
1842 offsets[1] = size; // number of pixels in "rounded up" image
1843 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1845 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1846 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1847 size += tmp; // 5/4*number of pixels in "rounded up" image
1849 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1850 size += tmp; // = 3/2*number of pixels in "rounded up" image
1854 size = *w << 1; // 2*width
1856 pitches[0] = size; // 2*width
1857 size *= *h; // 2*width*height
1860 size = *w << 2; // 4*width (32 bit per pixel)
1862 pitches[0] = size; // 4*width
1863 size *= *h; // 4*width*height
1873 /***** Exported offscreen surface stuff ****/
1877 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1878 unsigned short w, unsigned short h,
1879 XF86SurfacePtr surface)
1881 NVPtr pNv = NVPTR(pScrn);
1882 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1885 bpp = pScrn->bitsPerPixel >> 3;
1887 if (pPriv->grabbedByV4L)
1890 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1894 pPriv->pitch = ((w << 1) + 63) & ~63;
1895 size = h * pPriv->pitch / bpp;
1897 pPriv->video_mem = NVAllocateVideoMemory(pScrn,
1900 if (!pPriv->video_mem)
1906 surface->height = h;
1907 surface->pScrn = pScrn;
1908 surface->pitches = &pPriv->pitch;
1909 surface->offsets = &pPriv->offset;
1910 surface->devPrivate.ptr = (pointer)pPriv;
1913 /* grab the video */
1914 NVStopOverlay(pScrn);
1915 pPriv->videoStatus = 0;
1916 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1917 pPriv->grabbedByV4L = TRUE;
1923 NVStopSurface(XF86SurfacePtr surface)
1925 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1927 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
1928 NVStopOverlay(surface->pScrn);
1929 pPriv->videoStatus = 0;
1936 NVFreeSurface(XF86SurfacePtr surface)
1938 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1940 if (pPriv->grabbedByV4L) {
1941 NVStopSurface(surface);
1942 NVFreeOverlayMemory(surface->pScrn);
1943 pPriv->grabbedByV4L = FALSE;
1950 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
1952 NVPtr pNv = NVPTR(pScrn);
1953 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1955 return NVGetOverlayPortAttribute(pScrn, attribute,
1956 value, (pointer)pPriv);
1960 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
1962 NVPtr pNv = NVPTR(pScrn);
1963 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1965 return NVSetOverlayPortAttribute(pScrn, attribute,
1966 value, (pointer)pPriv);
1970 NVDisplaySurface(XF86SurfacePtr surface,
1971 short src_x, short src_y,
1972 short drw_x, short drw_y,
1973 short src_w, short src_h,
1974 short drw_w, short drw_h,
1975 RegionPtr clipBoxes)
1977 ScrnInfoPtr pScrn = surface->pScrn;
1978 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1979 INT32 xa, xb, ya, yb;
1982 if (!pPriv->grabbedByV4L)
1985 if (src_w > (drw_w << 3))
1987 if (src_h > (drw_h << 3))
1997 dstBox.x2 = drw_x + drw_w;
1999 dstBox.y2 = drw_y + drw_h;
2001 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
2002 surface->width, surface->height))
2005 dstBox.x1 -= pScrn->frameX0;
2006 dstBox.x2 -= pScrn->frameX0;
2007 dstBox.y1 -= pScrn->frameY0;
2008 dstBox.y2 -= pScrn->frameY0;
2010 pPriv->currentBuffer = 0;
2012 NVPutOverlayImage(pScrn, surface->offsets[0], 0, surface->id,
2013 surface->pitches[0], &dstBox, xa, ya, xb, yb,
2014 surface->width, surface->height, src_w, src_h,
2015 drw_w, drw_h, clipBoxes);
2022 * this function does all the work setting up a blit port
2026 static XF86VideoAdaptorPtr
2027 NVSetupBlitVideo (ScreenPtr pScreen)
2029 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2030 NVPtr pNv = NVPTR(pScrn);
2031 XF86VideoAdaptorPtr adapt;
2032 NVPortPrivPtr pPriv;
2035 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2036 sizeof(NVPortPrivRec) +
2037 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
2041 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2043 adapt->name = "NV Video Blitter";
2044 adapt->nEncodings = 1;
2045 adapt->pEncodings = &DummyEncoding;
2046 adapt->nFormats = NUM_FORMATS_ALL;
2047 adapt->pFormats = NVFormats;
2048 adapt->nPorts = NUM_BLIT_PORTS;
2049 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2051 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
2052 for(i = 0; i < NUM_BLIT_PORTS; i++)
2053 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2055 if(pNv->WaitVSyncPossible) {
2056 adapt->pAttributes = NVBlitAttributes;
2057 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
2059 adapt->pAttributes = NULL;
2060 adapt->nAttributes = 0;
2063 adapt->pImages = NVImages;
2064 adapt->nImages = NUM_IMAGES_ALL;
2065 adapt->PutVideo = NULL;
2066 adapt->PutStill = NULL;
2067 adapt->GetVideo = NULL;
2068 adapt->GetStill = NULL;
2069 adapt->StopVideo = NVStopBlitVideo;
2070 adapt->SetPortAttribute = NVSetBlitPortAttribute;
2071 adapt->GetPortAttribute = NVGetBlitPortAttribute;
2072 adapt->QueryBestSize = NVQueryBestSize;
2073 adapt->PutImage = NVPutImage;
2074 adapt->QueryImageAttributes = NVQueryImageAttributes;
2076 pPriv->videoStatus = 0;
2077 pPriv->grabbedByV4L = FALSE;
2078 pPriv->blitter = TRUE;
2079 pPriv->doubleBuffer = FALSE;
2080 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
2082 pNv->blitAdaptor = adapt;
2083 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
2089 * NV10SetupOverlayVideo
2090 * this function does all the work setting up an overlay port
2092 * @return overlay port
2093 * @see NVResetVideo(ScrnInfoPtr pScrn)
2095 static XF86VideoAdaptorPtr
2096 NV10SetupOverlayVideo(ScreenPtr pScreen)
2098 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2099 NVPtr pNv = NVPTR(pScrn);
2100 XF86VideoAdaptorPtr adapt;
2101 NVPortPrivPtr pPriv;
2103 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2104 sizeof(NVPortPrivRec) +
2105 sizeof(DevUnion)))) {
2109 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2110 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
2111 adapt->name = "NV Video Overlay";
2112 adapt->nEncodings = 1;
2113 adapt->pEncodings = &DummyEncoding;
2114 adapt->nFormats = NUM_FORMATS_ALL;
2115 adapt->pFormats = NVFormats;
2117 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2119 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
2120 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
2122 adapt->pAttributes = NVOverlayAttributes;
2123 adapt->nAttributes = NUM_OVERLAY_ATTRIBUTES;
2124 adapt->pImages = NVImages;
2125 adapt->nImages = NUM_IMAGES_YUV;
2126 adapt->PutVideo = NULL;
2127 adapt->PutStill = NULL;
2128 adapt->GetVideo = NULL;
2129 adapt->GetStill = NULL;
2130 adapt->StopVideo = NVStopOverlayVideo;
2131 adapt->SetPortAttribute = NVSetOverlayPortAttribute;
2132 adapt->GetPortAttribute = NVGetOverlayPortAttribute;
2133 adapt->QueryBestSize = NVQueryBestSize;
2134 adapt->PutImage = NVPutImage;
2135 adapt->QueryImageAttributes = NVQueryImageAttributes;
2137 pPriv->videoStatus = 0;
2138 pPriv->currentBuffer = 0;
2139 pPriv->grabbedByV4L = FALSE;
2140 pPriv->blitter = FALSE;
2142 NVSetPortDefaults (pScrn, pPriv);
2144 /* gotta uninit this someplace */
2145 REGION_NULL(pScreen, &pPriv->clip);
2147 pNv->overlayAdaptor = adapt;
2149 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
2150 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
2151 xvContrast = MAKE_ATOM("XV_CONTRAST");
2152 xvColorKey = MAKE_ATOM("XV_COLORKEY");
2153 xvSaturation = MAKE_ATOM("XV_SATURATION");
2154 xvHue = MAKE_ATOM("XV_HUE");
2155 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
2156 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
2157 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
2159 NVResetVideo(pScrn);
2164 XF86OffscreenImageRec NVOffscreenImages[2] = {
2167 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2172 NVGetSurfaceAttribute,
2173 NVSetSurfaceAttribute,
2174 IMAGE_MAX_W, IMAGE_MAX_H,
2175 NUM_OVERLAY_ATTRIBUTES - 1,
2176 &NVOverlayAttributes[1]
2180 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2185 NVGetSurfaceAttribute,
2186 NVSetSurfaceAttribute,
2187 IMAGE_MAX_W, IMAGE_MAX_H,
2188 NUM_OVERLAY_ATTRIBUTES - 1,
2189 &NVOverlayAttributes[1]
2194 NVInitOffscreenImages (ScreenPtr pScreen)
2196 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
2200 * NVChipsetHasOverlay
2202 * newer chips don't support overlay anymore.
2203 * overlay feature is emulated via textures.
2206 * @return true, if chipset supports overlay
2209 NVChipsetHasOverlay(NVPtr pNv)
2211 switch (pNv->Architecture) {
2217 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
2228 * NVSetupOverlayVideo
2229 * check if chipset supports Overlay and CompositeExtension is disabled.
2230 * if so, setup overlay port
2232 * @return overlay port
2233 * @see NVChipsetHasOverlay(NVPtr pNv)
2234 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
2235 * @see NVInitOffscreenImages(ScreenPtr pScreen)
2237 static XF86VideoAdaptorPtr
2238 NVSetupOverlayVideo(ScreenPtr pScreen)
2240 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2241 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2242 NVPtr pNv = NVPTR(pScrn);
2244 if (!NVChipsetHasOverlay(pNv))
2247 overlayAdaptor = NV10SetupOverlayVideo(pScreen);
2249 NVInitOffscreenImages(pScreen); //I am not sure what this call does.
2252 if (!noCompositeExtension) {
2253 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2254 "XV: Composite is enabled, enabling overlay with smart blitter fallback\n");
2255 overlayAdaptor -> name = "NV Video Overlay with Composite";
2259 return overlayAdaptor;
2264 * tries to initialize one new overlay port and one new blit port
2265 * and add them to the list of ports on screen "pScreen".
2268 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
2269 * @see NVSetupBlitVideo(ScreenPtr pScreen)
2271 void NVInitVideo (ScreenPtr pScreen)
2273 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2274 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
2275 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2276 XF86VideoAdaptorPtr blitAdaptor = NULL;
2279 if (pScrn->bitsPerPixel == 8)
2282 overlayAdaptor = NVSetupOverlayVideo(pScreen);
2283 blitAdaptor = NVSetupBlitVideo(pScreen);
2285 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
2286 if(blitAdaptor || overlayAdaptor) {
2287 int size = num_adaptors;
2289 if(overlayAdaptor) size++;
2290 if(blitAdaptor) size++;
2292 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
2295 memcpy(newAdaptors, adaptors, num_adaptors *
2296 sizeof(XF86VideoAdaptorPtr));
2299 if(overlayAdaptor) {
2300 newAdaptors[num_adaptors] = overlayAdaptor;
2305 newAdaptors[num_adaptors] = blitAdaptor;
2309 adaptors = newAdaptors;
2314 xf86XVScreenInit(pScreen, adaptors, num_adaptors);