2 * Copyright 2007 Arthur Huillet
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 #include <X11/extensions/Xv.h>
32 #include "dixstruct.h"
35 #include "nv_include.h"
38 #define IMAGE_MAX_W 2046
39 #define IMAGE_MAX_H 2046
41 #define TEX_IMAGE_MAX_W 4096
42 #define TEX_IMAGE_MAX_H 4096
44 #define OFF_DELAY 500 /* milliseconds */
45 #define FREE_DELAY 5000
47 #define NUM_BLIT_PORTS 16
48 #define NUM_TEXTURE_PORTS 32
51 #define NVStopOverlay(X) (((pNv->Architecture == NV_ARCH_04) ? NV04StopOverlay(X) : NV10StopOverlay(X)))
53 /* Value taken by pPriv -> currentHostBuffer when we failed to allocate the two private buffers in TT memory, so that we can catch this case
54 and attempt no other allocation afterwards (performance reasons) */
55 #define NO_PRIV_HOST_BUFFER_AVAILABLE 9999
57 /* Xv DMA notifiers status tracing */
59 XV_DMA_NOTIFIER_NOALLOC=0, //notifier not allocated
60 XV_DMA_NOTIFIER_INUSE=1,
61 XV_DMA_NOTIFIER_FREE=2, //notifier allocated, ready for use
64 /* We have six notifiers available, they are not allocated at startup */
65 static int XvDMANotifierStatus[6]= { XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC ,
66 XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC };
67 static struct nouveau_notifier *XvDMANotifiers[6];
69 /* NVPutImage action flags */
77 IS_RGB=64, //I am not sure how long we will support it
80 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
82 Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
83 xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
84 xvITURBT709, xvSyncToVBlank, xvOnCRTCNb;
86 /* client libraries expect an encoding */
87 static XF86VideoEncodingRec DummyEncoding =
91 IMAGE_MAX_W, IMAGE_MAX_H,
95 static XF86VideoEncodingRec DummyEncodingTex =
99 TEX_IMAGE_MAX_W, TEX_IMAGE_MAX_H,
103 #define NUM_FORMATS_ALL 6
105 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
107 {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
108 {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
111 #define NUM_NV04_OVERLAY_ATTRIBUTES 4
112 XF86AttributeRec NV04OverlayAttributes[NUM_NV04_OVERLAY_ATTRIBUTES] =
114 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
115 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
116 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
117 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
121 #define NUM_NV10_OVERLAY_ATTRIBUTES 10
122 XF86AttributeRec NV10OverlayAttributes[NUM_NV10_OVERLAY_ATTRIBUTES] =
124 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
125 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
126 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
127 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
128 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
129 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
130 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
131 {XvSettable | XvGettable, 0, 360, "XV_HUE"},
132 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"},
133 {XvSettable | XvGettable, 0, 1, "XV_ON_CRTC_NB"},
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"}
143 #define NUM_TEXTURED_ATTRIBUTES 2
144 XF86AttributeRec NVTexturedAttributes[NUM_TEXTURED_ATTRIBUTES] =
146 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
147 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
151 #define NUM_IMAGES_YUV 4
152 #define NUM_IMAGES_ALL 5
154 #define FOURCC_RGB 0x0000003
155 #define XVIMAGE_RGB \
160 { 0x03, 0x00, 0x00, 0x00, \
161 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
165 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
170 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}, \
174 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
184 nv_window_belongs_to_crtc(ScrnInfoPtr pScrn, int x, int y, int w, int h)
186 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
187 NVPtr pNv = NVPTR(pScrn);
194 if (!pNv->randr12_enable) {
196 * Without RandR 1.2, we'll just return which CRTCs
199 if (pNv->crtc_active[0])
201 else if (pNv->crtc_active[1])
207 for (i = 0; i < xf86_config->num_crtc; i++) {
208 crtc = xf86_config->crtc[i];
213 if ((x < (crtc->x + crtc->mode.HDisplay)) &&
214 (y < (crtc->y + crtc->mode.VDisplay)) &&
215 ((x + w) > crtc->x) &&
224 NVWaitVSync(ScrnInfoPtr pScrn, int crtc)
226 NVPtr pNv = NVPTR(pScrn);
228 BEGIN_RING(NvImageBlit, 0x0000012C, 1);
230 BEGIN_RING(NvImageBlit, 0x00000134, 1);
232 BEGIN_RING(NvImageBlit, 0x00000100, 1);
234 BEGIN_RING(NvImageBlit, 0x00000130, 1);
240 * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
241 * this function does not care about the kind of adapter the port is for
243 * @param pScrn screen to get the default colorKey from
244 * @param pPriv port to reset to defaults
247 NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
249 NVPtr pNv = NVPTR(pScrn);
251 pPriv->brightness = 0;
252 pPriv->contrast = 4096;
253 pPriv->saturation = 4096;
255 pPriv->colorKey = pNv->videoKey;
256 pPriv->autopaintColorKey = TRUE;
257 pPriv->doubleBuffer = TRUE;
258 pPriv->iturbt_709 = FALSE;
259 pPriv->currentHostBuffer = 0;
263 * NVXvDMANotifierAlloc
264 * allocates a notifier from the table of 6 we have
266 * @return a notifier instance or NULL on error
268 static struct nouveau_notifier *
269 NVXvDMANotifierAlloc(ScrnInfoPtr pScrn)
271 NVPtr pNv = NVPTR(pScrn);
274 for (i = 0; i < 6; i++) {
275 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_INUSE)
278 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_FREE) {
279 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
280 return XvDMANotifiers[i];
283 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_NOALLOC) {
284 if (nouveau_notifier_alloc(pNv->chan,
285 NvDmaXvNotifier0 + i,
286 1, &XvDMANotifiers[i]))
288 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
289 return XvDMANotifiers[i];
297 * NVXvDMANotifierFree
298 * frees a notifier from the table of 6 we have
303 NVXvDMANotifierFree(ScrnInfoPtr pScrn, struct nouveau_notifier *target)
306 for ( i = 0; i < 6; i ++ )
308 if ( XvDMANotifiers[i] == target )
311 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_FREE;
315 * NVAllocateVideoMemory
316 * allocates video memory for a given port
318 * @param pScrn screen which requests the memory
319 * @param mem pointer to previously allocated memory for reallocation
320 * @param size size of requested memory segment
321 * @return pointer to the allocated memory
323 static struct nouveau_bo *
324 NVAllocateVideoMemory(ScrnInfoPtr pScrn, struct nouveau_bo *mem, int size)
326 NVPtr pNv = NVPTR(pScrn);
327 struct nouveau_bo *bo = NULL;
330 if(mem->size >= size)
332 nouveau_bo_del(&mem);
335 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN, 0,
339 if (nouveau_bo_map(bo, NOUVEAU_BO_RDWR)) {
349 * allocates TT memory for a given port
351 * @param pScrn screen which requests the memory
352 * @param mem pointer to previously allocated memory for reallocation
353 * @param size size of requested memory segment
354 * @return pointer to the allocated memory
356 static struct nouveau_bo *
357 NVAllocateTTMemory(ScrnInfoPtr pScrn, struct nouveau_bo *mem, int size)
359 NVPtr pNv = NVPTR(pScrn);
360 struct nouveau_bo *bo = NULL;
363 if(mem->size >= size)
365 nouveau_bo_del(&mem);
368 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_GART | NOUVEAU_BO_PIN, 0,
372 if (nouveau_bo_map(bo, NOUVEAU_BO_RDWR)) {
382 * frees memory held by a given port
384 * @param pScrn screen whose port wants to free memory
385 * @param pPriv port to free memory of
388 NVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
390 //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]);
392 if(pPriv->video_mem) {
393 nouveau_bo_del(&pPriv->video_mem);
394 pPriv->video_mem = NULL;
397 if ( pPriv->TT_mem_chunk[ 0 ] && pPriv->DMANotifier [ 0 ] )
399 nouveau_notifier_wait_status(pPriv->DMANotifier[0], 0, 0, 1000);
402 if ( pPriv->TT_mem_chunk[ 1 ] && pPriv->DMANotifier [ 1 ] )
404 nouveau_notifier_wait_status(pPriv->DMANotifier[1], 0, 0, 1000);
407 if(pPriv->TT_mem_chunk[0]) {
408 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
409 pPriv->TT_mem_chunk[0] = NULL;
412 if(pPriv->TT_mem_chunk[1]) {
413 nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
414 pPriv->TT_mem_chunk[1] = NULL;
417 if(pPriv->DMANotifier[0]) {
418 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[0]);
419 pPriv->DMANotifier[0] = NULL;
422 if(pPriv->DMANotifier[1]) {
423 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[1]);
424 pPriv->DMANotifier[1] = NULL;
430 * NVFreeOverlayMemory
431 * frees memory held by the overlay port
433 * @param pScrn screen whose overlay port wants to free memory
436 NVFreeOverlayMemory(ScrnInfoPtr pScrn)
438 NVPtr pNv = NVPTR(pScrn);
439 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
440 NVFreePortMemory(pScrn, pPriv);
442 /* "power cycle" the overlay */
443 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) & 0xEFFFFFFF));
444 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) | 0x10000000));
449 * frees memory held by the blit port
451 * @param pScrn screen whose blit port wants to free memory
454 NVFreeBlitMemory(ScrnInfoPtr pScrn)
456 NVPtr pNv = NVPTR(pScrn);
457 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
458 NVFreePortMemory(pScrn, pPriv);
462 * NVVideoTimerCallback
463 * callback function which perform cleanup tasks (stop overlay, free memory).
465 * purpose and use is unknown
468 NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
470 NVPtr pNv = NVPTR(pScrn);
471 NVPortPrivPtr pOverPriv = NULL;
472 NVPortPrivPtr pBlitPriv = NULL;
473 Bool needCallback = FALSE;
478 if (pNv->overlayAdaptor) {
479 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
480 if (!pOverPriv->videoStatus)
484 if (pNv->blitAdaptor) {
485 pBlitPriv = GET_BLIT_PRIVATE(pNv);
486 if (!pBlitPriv->videoStatus)
491 if (pOverPriv->videoTime < currentTime) {
492 if (pOverPriv->videoStatus & OFF_TIMER) {
493 NVStopOverlay(pScrn);
494 pOverPriv->videoStatus = FREE_TIMER;
495 pOverPriv->videoTime = currentTime + FREE_DELAY;
498 if (pOverPriv->videoStatus & FREE_TIMER) {
499 NVFreeOverlayMemory(pScrn);
500 pOverPriv->videoStatus = 0;
508 if (pBlitPriv->videoTime < currentTime) {
509 NVFreeBlitMemory(pScrn);
510 pBlitPriv->videoStatus = 0;
516 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
519 #ifndef ExaOffscreenMarkUsed
520 extern void ExaOffscreenMarkUsed(PixmapPtr);
526 NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
528 NVPtr pNv = NVPTR(pScrn);
529 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
531 if(pPriv->grabbedByV4L) return;
533 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
536 if (pPriv->videoStatus & CLIENT_VIDEO_ON)
537 NVStopOverlay(pScrn);
538 NVFreeOverlayMemory(pScrn);
539 pPriv->videoStatus = 0;
541 if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
542 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
543 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
544 pNv->VideoTimerCallback = NVVideoTimerCallback;
551 * used by client applications to ask the driver:
552 * how would you actually scale a video of dimensions
553 * vid_w, vid_h, if i wanted you to scale it to dimensions
555 * function stores actual scaling size in pointers p_w, p_h.
558 * @param pScrn unused
559 * @param motion unused
560 * @param vid_w width of source video
561 * @param vid_h height of source video
562 * @param drw_w desired scaled width as requested by client
563 * @param drw_h desired scaled height as requested by client
564 * @param p_w actual scaled width as the driver is capable of
565 * @param p_h actual scaled height as the driver is capable of
569 NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
570 short vid_w, short vid_h,
571 short drw_w, short drw_h,
572 unsigned int *p_w, unsigned int *p_h,
575 if(vid_w > (drw_w << 3))
577 if(vid_h > (drw_h << 3))
586 * used to convert YV12 to YUY2 for the blitter and NV04 overlay.
587 * The U and V samples generated are linearly interpolated on the vertical
588 * axis for better quality
590 * @param src1 source buffer of luma
591 * @param src2 source buffer of chroma1
592 * @param src3 source buffer of chroma2
593 * @param dst1 destination buffer
594 * @param srcPitch pitch of src1
595 * @param srcPitch2 pitch of src2, src3
596 * @param dstPitch pitch of dst1
597 * @param h number of lines to copy
598 * @param w length of lines to copy
600 static inline void NVCopyData420(unsigned char *src1, unsigned char *src2,
601 unsigned char *src3, unsigned char *dst1,
602 int srcPitch, int srcPitch2,
608 #define su(X) (((j & 1) && j < (h-1)) ? ((unsigned)((signed int)s2[X] + (signed int)(s2 + srcPitch2)[X]) / 2) : (s2[X]))
609 #define sv(X) (((j & 1) && j < (h-1)) ? ((unsigned)((signed int)s3[X] + (signed int)(s3 + srcPitch2)[X]) / 2) : (s3[X]))
615 for (j = 0; j < h; j++) {
617 s1 = src1; s2 = src2; s3 = src3;
621 #if X_BYTE_ORDER == X_BIG_ENDIAN
622 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (sv(0) << 16) | su(0);
623 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (sv(1) << 16) | su(1);
624 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (sv(2) << 16) | su(2);
625 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (sv(3) << 16) | su(3);
627 dst[0] = s1[0] | (s1[1] << 16) | (sv(0) << 8) | (su(0) << 24);
628 dst[1] = s1[2] | (s1[3] << 16) | (sv(1) << 8) | (su(1) << 24);
629 dst[2] = s1[4] | (s1[5] << 16) | (sv(2) << 8) | (su(2) << 24);
630 dst[3] = s1[6] | (s1[7] << 16) | (sv(3) << 8) | (su(3) << 24);
632 dst += 4; s2 += 4; s3 += 4; s1 += 8;
637 #if X_BYTE_ORDER == X_BIG_ENDIAN
638 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (sv(0) << 16) | su(0);
640 dst[0] = s1[0] | (s1[1] << 16) | (sv(0) << 8) | (su(0) << 24);
656 * NVCopyNV12ColorPlanes
657 * Used to convert YV12 color planes to NV12 (interleaved UV) for the overlay
659 * @param src1 source buffer of chroma1
660 * @param dst1 destination buffer
661 * @param h number of lines to copy
662 * @param w length of lines to copy
663 * @param id source pixel format (YV12 or I420)
665 static inline void NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char * src2, unsigned char *dst, int dstPitch, int srcPitch2,
675 for ( j = 0; j < h; j++ )
677 unsigned char * us = src1;
678 unsigned char * vs = src2;
679 unsigned int * vuvud = (unsigned int *) dst;
680 for ( i = 0; i < l; i++ )
682 #if X_BYTE_ORDER == X_BIG_ENDIAN
683 *vuvud++ = (vs[0]<<24) | (us[0]<<16) | (vs[1]<<8) | us[1];
685 *vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24);
691 unsigned short *vud = (unsigned short *) vuvud;
692 *vud = vs[0] | (us[0]<<8);
702 static int NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 * xa, INT32 * xb, INT32 * ya, INT32 * yb,
703 short * src_x, short * src_y, short * src_w, short * src_h,
704 short * drw_x, short * drw_y, short * drw_w, short * drw_h,
705 int * left, int * top, int * right, int * bottom,
707 int * npixels, int * nlines,
708 RegionPtr clipBoxes, short width, short height
711 NVPtr pNv = NVPTR(pScrn);
714 if ( action_flags & USE_OVERLAY )
715 { /* overlay hardware scaler limitation - copied from nv, UNCHECKED*/
716 if (*src_w > (*drw_w << 3))
717 *drw_w = *src_w >> 3;
718 if (*src_h > (*drw_h << 3))
719 *drw_h = *src_h >> 3;
725 *xb = *src_x + *src_w;
727 *yb = *src_y + *src_h;
730 dstBox->x2 = *drw_x + *drw_w;
732 dstBox->y2 = *drw_y + *drw_h;
734 if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
738 if ( action_flags & USE_OVERLAY )
740 if ( ! pNv->randr12_enable )
742 dstBox->x1 -= pScrn->frameX0;
743 dstBox->x2 -= pScrn->frameX0;
744 dstBox->y1 -= pScrn->frameY0;
745 dstBox->y2 -= pScrn->frameY0;
749 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
750 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
751 dstBox->x1 -= xf86_config->crtc[pPriv->overlayCRTC]->x;
752 dstBox->x2 -= xf86_config->crtc[pPriv->overlayCRTC]->x;
753 dstBox->y1 -= xf86_config->crtc[pPriv->overlayCRTC]->y;
754 dstBox->y2 -= xf86_config->crtc[pPriv->overlayCRTC]->y;
760 /* Convert fixed point to integer, as xf86XVClipVideoHelper probably turns its parameter into fixed point values */
762 if (*left < 0) *left = 0;
764 if (*top < 0) *top = 0;
765 *right = (*xb) >> 16;
766 if (*right > width) *right = width;
767 *bottom = (*yb) >> 16;
768 if (*bottom > height) *bottom = height;
770 if ( action_flags & IS_YV12 )
772 *left &= ~1; //even "left", even "top", even number of pixels per line and even number of lines
773 *npixels = ((*right + 1) & ~1) - *left;
775 *nlines = ((*bottom + 1) & ~1) - *top;
777 else if ( action_flags & IS_YUY2 )
779 *left &= ~1; //even "left"
780 *npixels = ((*right + 1) & ~1) - *left; //even number of pixels per line
781 *nlines = *bottom - *top;
784 else if (action_flags & IS_RGB )
786 *npixels = *right - *left;
787 *nlines = *bottom - *top;
794 static int NV_calculate_pitches_and_mem_size(int action_flags, int * srcPitch, int * srcPitch2, int * dstPitch,
795 int * s2offset, int * s3offset,
796 int * newFBSize, int * newTTSize,
797 int * line_len, int npixels, int nlines, int width, int height)
801 if ( action_flags & IS_YV12 )
803 *srcPitch = (width + 3) & ~3; /* of luma */
804 *s2offset = *srcPitch * height;
805 *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
806 *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
807 *dstPitch = (npixels + 63) & ~63; /*luma and chroma pitch*/
809 *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
810 *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
812 else if ( action_flags & IS_YUY2 )
814 *srcPitch = width << 1; /* one luma, one chroma per pixel */
815 *dstPitch = ((npixels << 1) + 63) & ~63;
816 *line_len = npixels << 1;
817 *newFBSize = nlines * *dstPitch;
818 *newTTSize = nlines * *line_len;
820 else if ( action_flags & IS_RGB )
822 *srcPitch = width << 2; /* one R, one G, one B, one X per pixel */
823 *dstPitch = ((npixels << 2) + 63) & ~63;
824 *line_len = npixels << 2;
825 *newFBSize = nlines * *dstPitch;
826 *newTTSize = nlines * *dstPitch;
830 if ( action_flags & CONVERT_TO_YUY2 )
832 *dstPitch = ((npixels << 1) + 63) & ~63;
833 *line_len = npixels << 1;
834 *newFBSize = nlines * *dstPitch;
835 *newTTSize = nlines * *line_len;
838 if ( action_flags & SWAP_UV )
839 { //I420 swaps U and V
841 *s2offset = *s3offset;
845 if ( action_flags & USE_OVERLAY ) // overlay double buffering ...
846 (*newFBSize) <<= 1; // ... means double the amount of VRAM needed
853 * NV_set_action_flags
854 * This function computes the action flags from the input image,
855 * that is, it decides what NVPutImage and its helpers must do.
856 * This eases readability by avoiding lots of switch-case statements in the core NVPutImage
858 static void NV_set_action_flags(ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, int id,
859 short drw_x, short drw_y, short drw_w, short drw_h, int * action_flags)
861 #define USING_OVERLAY (*action_flags & USE_OVERLAY)
862 #define USING_TEXTURE (*action_flags & USE_TEXTURE)
863 #define USING_BLITTER ((!(*action_flags & USE_OVERLAY)) && (!(*action_flags & USE_TEXTURE)))
865 NVPtr pNv = NVPTR(pScrn);
869 /* Pixel format-related bits */
870 if ( id == FOURCC_YUY2 || id == FOURCC_UYVY )
871 *action_flags |= IS_YUY2;
873 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
874 *action_flags |= IS_YV12;
876 if ( id == FOURCC_RGB ) /*How long will we support it?*/
877 *action_flags |= IS_RGB;
879 if ( id == FOURCC_I420 ) /*I420 is YV12 with swapped UV*/
880 *action_flags |= SWAP_UV;
882 /* Desired adapter */
883 if ( !pPriv -> blitter && !pPriv -> texture )
884 *action_flags |= USE_OVERLAY;
886 if ( !pPriv -> blitter && pPriv->texture )
887 *action_flags |= USE_TEXTURE;
889 /* Adapter fallbacks (when the desired one can't be used)*/
891 PixmapPtr pPix = NVGetDrawablePixmap(pDraw);
893 if (!NVExaPixmapIsOnscreen(pPix))
895 *action_flags &= ~USE_OVERLAY;
900 if ( USING_OVERLAY && pNv->randr12_enable )
901 { /* We need to check the CRTC we're on */
902 char crtc = nv_window_belongs_to_crtc(pScrn, drw_x, drw_y, drw_w, drw_h);
904 /* We're on CRTC 0, or 1, or both.. */
905 if ( ( crtc & (1 << 0)) && (crtc & (1 << 1)) )
906 { /* The overlay cannot be used on two CRTCs at a time, so we need to fallback on the blitter */
907 *action_flags &= ~USE_OVERLAY;
909 else if ( (crtc & (1 << 0) ) )
910 { /* We need to put the overlay on CRTC0 - if it's not already here */
911 if ( pPriv->overlayCRTC == 1 )
913 NVWriteCRTC(pNv, 0, NV_CRTC_FSEL, NVReadCRTC(pNv, 0, NV_CRTC_FSEL) | NV_CRTC_FSEL_OVERLAY);
914 NVWriteCRTC(pNv, 1, NV_CRTC_FSEL, NVReadCRTC(pNv, 1, NV_CRTC_FSEL) & ~NV_CRTC_FSEL_OVERLAY);
915 pPriv->overlayCRTC = 0;
918 else if ( (crtc & (1 << 1) ) )
920 if ( pPriv->overlayCRTC == 0 )
922 NVWriteCRTC(pNv, 1, NV_CRTC_FSEL, NVReadCRTC(pNv, 1, NV_CRTC_FSEL) | NV_CRTC_FSEL_OVERLAY);
923 NVWriteCRTC(pNv, 0, NV_CRTC_FSEL, NVReadCRTC(pNv, 0, NV_CRTC_FSEL) & ~NV_CRTC_FSEL_OVERLAY);
924 pPriv->overlayCRTC = 1;
929 /* At this point the adapter we're going to use is _known_. You cannot change it now. */
930 /* Card/adapter format restrictions */
933 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
934 { /*The blitter does not handle YV12 natively*/
935 *action_flags |= CONVERT_TO_YUY2;
939 if ( USING_OVERLAY && (pNv->Architecture == NV_ARCH_04 ))
940 if ( * action_flags & IS_YV12 ) /*NV04-05 don't support native YV12, only YUY2 and ITU-R BT.601*/
941 *action_flags |= CONVERT_TO_YUY2;
943 if ( USING_OVERLAY && (pNv->Architecture == NV_ARCH_10 || pNv->Architecture == NV_ARCH_20 ))
944 { /* No YV12 overlay on NV10, 11, 15, 20, NFORCE */
945 switch ( pNv->Chipset & 0xfff0 )
950 case CHIPSET_NFORCE: /*XXX: unsure about nforce*/
952 *action_flags |= CONVERT_TO_YUY2; break;
963 * PutImage is "the" important function of the Xv extension.
964 * a client (e.g. video player) calls this function for every
965 * image (of the video) to be displayed. this function then
966 * scales and displays the image.
968 * @param pScrn screen which hold the port where the image is put
969 * @param src_x source point in the source image to start displaying from
970 * @param src_y see above
971 * @param src_w width of the source image to display
972 * @param src_h see above
973 * @param drw_x screen point to display to
975 * @param drw_w width of the screen drawable
977 * @param id pixel format of image
978 * @param buf pointer to buffer containing the source image
979 * @param width total width of the source image we are passed
982 * @param clipBoxes ??
983 * @param data pointer to port
984 * @param pDraw drawable pointer
987 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
988 short drw_x, short drw_y,
989 short src_w, short src_h,
990 short drw_w, short drw_h,
993 short width, short height,
994 Bool Sync, /*FIXME: need to honor the Sync*/
1000 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1001 NVPtr pNv = NVPTR(pScrn);
1002 INT32 xa = 0, xb = 0, ya = 0, yb = 0; //source box
1003 int newFBSize = 0, newTTSize = 0; //size to allocate in VRAM and in GART respectively
1004 int offset = 0, s2offset = 0, s3offset = 0; //card VRAM offset, source offsets for U and V planes
1005 int srcPitch = 0, srcPitch2 = 0, dstPitch = 0; //source pitch, source pitch of U and V planes in case of YV12, VRAM destination pitch
1006 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
1010 int line_len = 0; //length of a line, like npixels, but in bytes
1011 struct nouveau_bo *destination_buffer = NULL;
1012 unsigned char * video_mem_destination = NULL;
1013 int action_flags; //what shall we do?
1016 if (pPriv->grabbedByV4L)
1020 NV_set_action_flags(pScrn, pDraw, pPriv, id, drw_x, drw_y, drw_w, drw_h, &action_flags);
1022 if ( NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
1023 &src_x, &src_y, &src_w, &src_h,
1024 &drw_x, &drw_y, &drw_w, &drw_h,
1025 &left, &top, &right, &bottom, &dstBox,
1027 clipBoxes, width, height ) )
1033 if ( NV_calculate_pitches_and_mem_size(action_flags, &srcPitch, &srcPitch2, &dstPitch,
1034 &s2offset, &s3offset,
1035 & newFBSize, &newTTSize ,&line_len ,
1036 npixels, nlines, width, height) )
1038 return BadImplementation;
1041 /* There are some cases (tvtime with overscan for example) where the input image is larger (width/height) than
1042 the source rectangle for the overlay (src_w, src_h). In those cases, we try to do something optimal by uploading only
1043 the necessary data. */
1044 if ( action_flags & IS_YUY2 || action_flags & IS_RGB )
1046 buf += (top * srcPitch) + left;
1049 if ( action_flags & IS_YV12 )
1051 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1056 pPriv->video_mem = NVAllocateVideoMemory(pScrn, pPriv->video_mem,
1058 if (!pPriv->video_mem)
1061 offset = pPriv->video_mem->offset;
1063 /*The overlay supports hardware double buffering. We handle this here*/
1064 if (pPriv->doubleBuffer) {
1065 int mask = 1 << (pPriv->currentBuffer << 2);
1066 /* overwrite the newest buffer if there's not one free */
1067 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1068 if (!pPriv->currentBuffer)
1069 offset += newFBSize >> 1;
1073 if (pPriv->currentBuffer)
1074 offset += newFBSize >> 1;
1077 /*Now we take a decision regarding the way we send the data to the card.
1078 Either we use double buffering of "private" TT memory
1079 Either we rely on X's GARTScratch
1080 Either we fallback on CPU copy
1083 /* Try to allocate host-side double buffers, unless we have already failed*/
1084 /* We take only nlines * line_len bytes - that is, only the pixel data we are interested in - because the stuff in the GART is
1085 written contiguously */
1086 if ( pPriv -> currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1088 pPriv->TT_mem_chunk[0] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[0],
1090 if ( pPriv->TT_mem_chunk[0] )
1092 pPriv->TT_mem_chunk[1] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[1],
1095 if ( ! pPriv->TT_mem_chunk[1] )
1097 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1098 pPriv->TT_mem_chunk[0] = NULL;
1099 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1100 //xf86DrvMsg(0, X_INFO, "Alloc 1 failed\n");
1105 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1106 //xf86DrvMsg(0, X_INFO, "Alloc 0 failed\n");
1110 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1111 { //if we have a private buffer
1112 destination_buffer = pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1113 //xf86DrvMsg(0, X_INFO, "Using private mem chunk #%d\n", pPriv->currentHostBuffer);
1115 /* We know where we are going to write, but we are not sure yet whether we can do it directly, because
1116 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.
1117 If we do, then we must wait for it before overwriting the buffer.
1118 Else we need one, so we call the Xv notifier allocator.*/
1119 if ( pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1121 //xf86DrvMsg(0, X_INFO, "Waiting for notifier %p (%d)\n", pPriv->DMANotifier[pPriv->currentHostBuffer], pPriv->currentHostBuffer);
1122 if (nouveau_notifier_wait_status(pPriv->DMANotifier[pPriv->currentHostBuffer], 0, 0, 0))
1127 //xf86DrvMsg(0, X_INFO, "Allocating notifier...\n");
1128 pPriv->DMANotifier [ pPriv->currentHostBuffer ] = NVXvDMANotifierAlloc(pScrn);
1129 if (! pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1130 { /* 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.
1131 I know that's a lot of code but I believe it's necessary to properly handle all the cases*/
1132 xf86DrvMsg(0, X_ERROR, "Ran out of Xv notifiers!\n");
1133 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1134 pPriv->TT_mem_chunk[0] = NULL;
1135 nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
1136 pPriv->TT_mem_chunk[1] = NULL;
1137 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1139 //xf86DrvMsg(0, X_INFO, "Got notifier %p\n", pPriv->DMANotifier [ pPriv->currentHostBuffer ]);
1143 if ( pPriv -> currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE )
1144 { //otherwise we fall back on DDX's GARTScratch
1145 destination_buffer = pNv->GART;
1146 //xf86DrvMsg(0, X_INFO, "Using global GART memory chunk\n");
1149 if ( !destination_buffer) //if we have no GART at all
1152 if(newTTSize <= destination_buffer->size)
1154 unsigned char *dst = destination_buffer->map;
1157 /* Upload to GART */
1158 if ( action_flags & IS_YV12)
1160 if ( action_flags & CONVERT_TO_YUY2 )
1162 NVCopyData420(buf + (top * srcPitch) + left,
1163 buf + s2offset, buf + s3offset,
1164 dst, srcPitch, srcPitch2,
1165 line_len, nlines, npixels);
1169 unsigned char * tbuf = buf + top * srcPitch + left;
1170 unsigned char * tdst = dst;
1171 //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);
1173 for ( i=0; i < nlines; i++)
1175 memcpy(tdst, tbuf, line_len);
1179 dst += line_len * nlines;
1180 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, dst, line_len, srcPitch2, nlines, line_len);
1185 for ( i=0; i < nlines; i++)
1187 memcpy(dst, buf, line_len);
1194 BEGIN_RING(NvMemFormat,
1195 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
1196 OUT_RING (pNv->chan->gart->handle);
1197 OUT_RING (pNv->chan->vram->handle);
1200 if (action_flags & IS_YV12 && ! (action_flags & CONVERT_TO_YUY2) )
1201 { /*we start the color plane transfer separately*/
1202 BEGIN_RING(NvMemFormat,
1203 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1204 OUT_RING ((uint32_t)destination_buffer->offset + line_len * nlines);
1205 OUT_RING ((uint32_t)offset + dstPitch * nlines);
1206 OUT_RING (line_len);
1207 OUT_RING (dstPitch);
1208 OUT_RING (line_len);
1209 OUT_RING ((nlines >> 1));
1210 OUT_RING ((1<<8)|1);
1215 BEGIN_RING(NvMemFormat,
1216 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1217 OUT_RING ((uint32_t)destination_buffer->offset);
1218 OUT_RING ((uint32_t)offset);
1219 OUT_RING (line_len);
1220 OUT_RING (dstPitch);
1221 OUT_RING (line_len);
1223 OUT_RING ((1<<8)|1);
1226 if ( destination_buffer == pNv->GART )
1228 nouveau_notifier_reset(pNv->notify0, 0);
1231 nouveau_notifier_reset(pPriv->DMANotifier[pPriv->currentHostBuffer], 0);
1232 BEGIN_RING(NvMemFormat,
1233 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1234 OUT_RING (pPriv->DMANotifier[pPriv->currentHostBuffer]->handle);
1238 BEGIN_RING(NvMemFormat, NV04_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1241 BEGIN_RING(NvMemFormat, 0x100, 1);
1244 //Put back NvDmaNotifier0 for EXA
1245 BEGIN_RING(NvMemFormat,
1246 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1247 OUT_RING (pNv->notify0->handle);
1251 if ( destination_buffer == pNv->GART )
1252 if (nouveau_notifier_wait_status(pNv->notify0, 0, 0, 0))
1255 else { //GART is too small, we fallback on CPU copy
1257 video_mem_destination = pPriv->video_mem->map + (offset - (uint32_t)pPriv->video_mem->offset);
1259 if ( action_flags & IS_YV12 )
1261 if ( action_flags & CONVERT_TO_YUY2 )
1263 NVCopyData420(buf + (top * srcPitch) + left,
1264 buf + s2offset, buf + s3offset,
1265 video_mem_destination, srcPitch, srcPitch2,
1266 dstPitch, nlines, npixels);
1269 unsigned char * tbuf = buf + left + top * srcPitch;
1270 for ( i=0; i < nlines; i++)
1272 int dwords = npixels << 1;
1273 while (dwords & ~0x03)
1275 *video_mem_destination = *tbuf;
1276 *(video_mem_destination + 1) = *(tbuf + 1);
1277 *(video_mem_destination + 2) = *(tbuf + 2);
1278 *(video_mem_destination + 3) = *(tbuf + 3);
1279 video_mem_destination += 4;
1286 *(video_mem_destination + 2) = *(tbuf + 2);
1288 *(video_mem_destination + 1) = *(tbuf + 1);
1290 *video_mem_destination = *tbuf;
1293 video_mem_destination += dstPitch - (npixels << 1);
1294 tbuf += srcPitch - (npixels << 1);
1297 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, video_mem_destination, dstPitch, srcPitch2, nlines, line_len);
1302 for ( i=0; i < nlines; i++)
1304 int dwords = npixels << 1;
1305 while (dwords & ~0x03)
1307 *video_mem_destination = *buf;
1308 *(video_mem_destination + 1) = *(buf + 1);
1309 *(video_mem_destination + 2) = *(buf + 2);
1310 *(video_mem_destination + 3) = *(buf + 3);
1311 video_mem_destination += 4;
1318 *(video_mem_destination + 2) = *(buf + 2);
1320 *(video_mem_destination + 1) = *(buf + 1);
1322 *video_mem_destination = *buf;
1325 video_mem_destination += dstPitch - (npixels << 1);
1326 buf += srcPitch - (npixels << 1);
1334 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1335 pPriv->currentHostBuffer ^= 1;
1337 if ( action_flags & USE_OVERLAY )
1339 if ( pNv->Architecture == NV_ARCH_04 )
1340 NV04PutOverlayImage(pScrn, offset, id,
1344 src_w, src_h, drw_w, drw_h,
1347 NV10PutOverlayImage(pScrn, offset, ((action_flags & IS_YUY2) || (action_flags & CONVERT_TO_YUY2)) ? 0 : offset + nlines * dstPitch, id,
1351 src_w, src_h, drw_w, drw_h,
1353 pPriv->currentBuffer ^= 1;
1358 if (action_flags & USE_TEXTURE) { /* Texture adapter */
1359 int rval = NV40PutTextureImage(pScrn, offset, offset + nlines * dstPitch, id,
1363 src_w, src_h, drw_w, drw_h,
1365 if (rval != Success)
1367 } else { /* Blit adapter */
1368 NVPutBlitImage(pScrn, offset, id,
1372 src_w, src_h, drw_w, drw_h,
1381 * QueryImageAttributes
1384 * - size (memory required to store image),
1388 * depending on colorspace (id) and dimensions (w,h) of image
1392 * may be adjusted as needed
1394 * @param pScrn unused
1395 * @param id colorspace of image
1396 * @param w pointer to width of image
1397 * @param h pointer to height of image
1398 * @param pitches pitches[i] = length of a scanline in plane[i]
1399 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1400 * @return size of the memory required for the XvImage queried
1403 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1404 unsigned short *w, unsigned short *h,
1405 int *pitches, int *offsets)
1409 if (*w > IMAGE_MAX_W)
1411 if (*h > IMAGE_MAX_H)
1414 *w = (*w + 1) & ~1; // width rounded up to an even number
1421 *h = (*h + 1) & ~1; // height rounded up to an even number
1422 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1424 pitches[0] = size; // width rounded up to a multiple of 4
1427 offsets[1] = size; // number of pixels in "rounded up" image
1428 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1430 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1431 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1432 size += tmp; // 5/4*number of pixels in "rounded up" image
1434 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1435 size += tmp; // = 3/2*number of pixels in "rounded up" image
1439 size = *w << 1; // 2*width
1441 pitches[0] = size; // 2*width
1442 size *= *h; // 2*width*height
1445 size = *w << 2; // 4*width (32 bit per pixel)
1447 pitches[0] = size; // 4*width
1448 size *= *h; // 4*width*height
1458 /***** Exported offscreen surface stuff ****/
1462 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1463 unsigned short w, unsigned short h,
1464 XF86SurfacePtr surface)
1466 NVPtr pNv = NVPTR(pScrn);
1467 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1470 bpp = pScrn->bitsPerPixel >> 3;
1472 if (pPriv->grabbedByV4L)
1475 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1479 pPriv->pitch = ((w << 1) + 63) & ~63;
1480 size = h * pPriv->pitch / bpp;
1482 pPriv->video_mem = NVAllocateVideoMemory(pScrn,
1485 if (!pPriv->video_mem)
1491 surface->height = h;
1492 surface->pScrn = pScrn;
1493 surface->pitches = &pPriv->pitch;
1494 surface->offsets = &pPriv->offset;
1495 surface->devPrivate.ptr = (pointer)pPriv;
1498 /* grab the video */
1499 NVStopOverlay(pScrn);
1500 pPriv->videoStatus = 0;
1501 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1502 pPriv->grabbedByV4L = TRUE;
1508 NVStopSurface(XF86SurfacePtr surface)
1510 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1512 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
1513 NV10StopOverlay(surface->pScrn);
1514 pPriv->videoStatus = 0;
1521 NVFreeSurface(XF86SurfacePtr surface)
1523 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1525 if (pPriv->grabbedByV4L) {
1526 NVStopSurface(surface);
1527 NVFreeOverlayMemory(surface->pScrn);
1528 pPriv->grabbedByV4L = FALSE;
1535 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
1537 NVPtr pNv = NVPTR(pScrn);
1538 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1540 return NV10GetOverlayPortAttribute(pScrn, attribute,
1541 value, (pointer)pPriv);
1545 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
1547 NVPtr pNv = NVPTR(pScrn);
1548 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1550 return NV10SetOverlayPortAttribute(pScrn, attribute,
1551 value, (pointer)pPriv);
1555 NVDisplaySurface(XF86SurfacePtr surface,
1556 short src_x, short src_y,
1557 short drw_x, short drw_y,
1558 short src_w, short src_h,
1559 short drw_w, short drw_h,
1560 RegionPtr clipBoxes)
1562 ScrnInfoPtr pScrn = surface->pScrn;
1563 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1564 INT32 xa, xb, ya, yb;
1567 if (!pPriv->grabbedByV4L)
1570 if (src_w > (drw_w << 3))
1572 if (src_h > (drw_h << 3))
1582 dstBox.x2 = drw_x + drw_w;
1584 dstBox.y2 = drw_y + drw_h;
1586 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1587 surface->width, surface->height))
1590 dstBox.x1 -= pScrn->frameX0;
1591 dstBox.x2 -= pScrn->frameX0;
1592 dstBox.y1 -= pScrn->frameY0;
1593 dstBox.y2 -= pScrn->frameY0;
1595 pPriv->currentBuffer = 0;
1597 NV10PutOverlayImage(pScrn, surface->offsets[0], 0, surface->id,
1598 surface->pitches[0], &dstBox, xa, ya, xb, yb,
1599 surface->width, surface->height, src_w, src_h,
1600 drw_w, drw_h, clipBoxes);
1607 * this function does all the work setting up a blit port
1611 static XF86VideoAdaptorPtr
1612 NVSetupBlitVideo (ScreenPtr pScreen)
1614 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1615 NVPtr pNv = NVPTR(pScrn);
1616 XF86VideoAdaptorPtr adapt;
1617 NVPortPrivPtr pPriv;
1620 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1621 sizeof(NVPortPrivRec) +
1622 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
1626 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1628 adapt->name = "NV Video Blitter";
1629 adapt->nEncodings = 1;
1630 adapt->pEncodings = &DummyEncoding;
1631 adapt->nFormats = NUM_FORMATS_ALL;
1632 adapt->pFormats = NVFormats;
1633 adapt->nPorts = NUM_BLIT_PORTS;
1634 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1636 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
1637 for(i = 0; i < NUM_BLIT_PORTS; i++)
1638 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1640 if(pNv->WaitVSyncPossible) {
1641 adapt->pAttributes = NVBlitAttributes;
1642 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
1644 adapt->pAttributes = NULL;
1645 adapt->nAttributes = 0;
1648 adapt->pImages = NVImages;
1649 adapt->nImages = NUM_IMAGES_ALL;
1650 adapt->PutVideo = NULL;
1651 adapt->PutStill = NULL;
1652 adapt->GetVideo = NULL;
1653 adapt->GetStill = NULL;
1654 adapt->StopVideo = NVStopBlitVideo;
1655 adapt->SetPortAttribute = NVSetBlitPortAttribute;
1656 adapt->GetPortAttribute = NVGetBlitPortAttribute;
1657 adapt->QueryBestSize = NVQueryBestSize;
1658 adapt->PutImage = NVPutImage;
1659 adapt->QueryImageAttributes = NVQueryImageAttributes;
1661 pPriv->videoStatus = 0;
1662 pPriv->grabbedByV4L = FALSE;
1663 pPriv->blitter = TRUE;
1664 pPriv->texture = FALSE;
1665 pPriv->doubleBuffer = FALSE;
1666 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1668 pNv->blitAdaptor = adapt;
1669 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
1675 * NVSetupOverlayVideo
1676 * this function does all the work setting up an overlay port
1678 * @return overlay port
1680 static XF86VideoAdaptorPtr
1681 NVSetupOverlayVideoAdapter(ScreenPtr pScreen)
1683 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1684 NVPtr pNv = NVPTR(pScrn);
1685 XF86VideoAdaptorPtr adapt;
1686 NVPortPrivPtr pPriv;
1688 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1689 sizeof(NVPortPrivRec) +
1690 sizeof(DevUnion)))) {
1694 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1695 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
1696 adapt->name = "NV Video Overlay";
1697 adapt->nEncodings = 1;
1698 adapt->pEncodings = &DummyEncoding;
1699 adapt->nFormats = NUM_FORMATS_ALL;
1700 adapt->pFormats = NVFormats;
1702 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1704 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
1705 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
1707 adapt->pAttributes = (pNv->Architecture != NV_ARCH_04) ? NV10OverlayAttributes : NV04OverlayAttributes;
1708 adapt->nAttributes = (pNv->Architecture != NV_ARCH_04) ? NUM_NV10_OVERLAY_ATTRIBUTES : NUM_NV04_OVERLAY_ATTRIBUTES;
1709 adapt->pImages = NVImages;
1710 adapt->nImages = NUM_IMAGES_YUV;
1711 adapt->PutVideo = NULL;
1712 adapt->PutStill = NULL;
1713 adapt->GetVideo = NULL;
1714 adapt->GetStill = NULL;
1715 adapt->StopVideo = NVStopOverlayVideo;
1716 adapt->SetPortAttribute = (pNv->Architecture != NV_ARCH_04) ? NV10SetOverlayPortAttribute : NV04SetOverlayPortAttribute;
1717 adapt->GetPortAttribute = (pNv->Architecture != NV_ARCH_04) ? NV10GetOverlayPortAttribute : NV04GetOverlayPortAttribute;
1718 adapt->QueryBestSize = NVQueryBestSize;
1719 adapt->PutImage = NVPutImage;
1720 adapt->QueryImageAttributes = NVQueryImageAttributes;
1722 pPriv->videoStatus = 0;
1723 pPriv->currentBuffer = 0;
1724 pPriv->grabbedByV4L = FALSE;
1725 pPriv->blitter = FALSE;
1726 pPriv->texture = FALSE;
1727 if ( pNv->Architecture == NV_ARCH_04 )
1728 pPriv->doubleBuffer = 0;
1730 NVSetPortDefaults (pScrn, pPriv);
1732 /* gotta uninit this someplace */
1733 REGION_NULL(pScreen, &pPriv->clip);
1735 pNv->overlayAdaptor = adapt;
1737 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
1738 xvColorKey = MAKE_ATOM("XV_COLORKEY");
1739 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
1740 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
1742 if ( pNv->Architecture != NV_ARCH_04 )
1744 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
1745 xvContrast = MAKE_ATOM("XV_CONTRAST");
1746 xvSaturation = MAKE_ATOM("XV_SATURATION");
1747 xvHue = MAKE_ATOM("XV_HUE");
1748 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
1749 xvOnCRTCNb = MAKE_ATOM("XV_ON_CRTC_NB");
1750 NV10WriteOverlayParameters(pScrn);
1757 XF86OffscreenImageRec NVOffscreenImages[2] = {
1760 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1765 NVGetSurfaceAttribute,
1766 NVSetSurfaceAttribute,
1767 IMAGE_MAX_W, IMAGE_MAX_H,
1768 NUM_NV10_OVERLAY_ATTRIBUTES - 1,
1769 &NV10OverlayAttributes[1]
1773 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1778 NVGetSurfaceAttribute,
1779 NVSetSurfaceAttribute,
1780 IMAGE_MAX_W, IMAGE_MAX_H,
1781 NUM_NV10_OVERLAY_ATTRIBUTES - 1,
1782 &NV10OverlayAttributes[1]
1787 NVInitOffscreenImages (ScreenPtr pScreen)
1789 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
1793 * NVChipsetHasOverlay
1795 * newer chips don't support overlay anymore.
1796 * overlay feature is emulated via textures.
1799 * @return true, if chipset supports overlay
1802 NVChipsetHasOverlay(NVPtr pNv)
1804 switch (pNv->Architecture) {
1805 case NV_ARCH_04: /*NV04 has a different overlay than NV10+*/
1811 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
1822 * NVSetupOverlayVideo
1823 * check if chipset supports Overla
1824 * if so, setup overlay port
1826 * @return overlay port
1827 * @see NVChipsetHasOverlay(NVPtr pNv)
1828 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
1829 * @see NVInitOffscreenImages(ScreenPtr pScreen)
1831 static XF86VideoAdaptorPtr
1832 NVSetupOverlayVideo(ScreenPtr pScreen)
1834 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1835 XF86VideoAdaptorPtr overlayAdaptor = NULL;
1836 NVPtr pNv = NVPTR(pScrn);
1838 if (!NVChipsetHasOverlay(pNv))
1841 overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen);
1842 if (overlayAdaptor && pNv->Architecture != NV_ARCH_04 )
1843 NVInitOffscreenImages(pScreen); //I am not sure what this call does.
1846 if (!noCompositeExtension) {
1847 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1848 "Xv: Composite is enabled, enabling overlay with smart blitter fallback\n");
1849 overlayAdaptor -> name = "NV Video Overlay with Composite";
1853 if (pNv->randr12_enable) {
1854 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1855 "Xv: Randr12 is enabled, using overlay with smart blitter fallback and automatic CRTC switching\n");
1859 return overlayAdaptor;
1863 * NV40 texture adapter.
1866 #define NUM_FORMAT_TEXTURED 2
1868 static XF86ImageRec NV40TexturedImages[NUM_FORMAT_TEXTURED] =
1875 * NV40SetupTexturedVideo
1876 * this function does all the work setting up textured video port
1878 * @return texture port
1880 static XF86VideoAdaptorPtr
1881 NV40SetupTexturedVideo (ScreenPtr pScreen)
1883 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1884 NVPtr pNv = NVPTR(pScrn);
1885 XF86VideoAdaptorPtr adapt;
1886 NVPortPrivPtr pPriv;
1889 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1890 sizeof(NVPortPrivRec) +
1891 (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
1895 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1897 adapt->name = "NV40 Texture adapter";
1898 adapt->nEncodings = 1;
1899 adapt->pEncodings = &DummyEncodingTex;
1900 adapt->nFormats = NUM_FORMATS_ALL;
1901 adapt->pFormats = NVFormats;
1902 adapt->nPorts = NUM_TEXTURE_PORTS;
1903 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1905 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
1906 for(i = 0; i < NUM_TEXTURE_PORTS; i++)
1907 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1909 if(pNv->WaitVSyncPossible) {
1910 adapt->pAttributes = NVTexturedAttributes;
1911 adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
1913 adapt->pAttributes = NULL;
1914 adapt->nAttributes = 0;
1917 adapt->pImages = NV40TexturedImages;
1918 adapt->nImages = NUM_FORMAT_TEXTURED;
1919 adapt->PutVideo = NULL;
1920 adapt->PutStill = NULL;
1921 adapt->GetVideo = NULL;
1922 adapt->GetStill = NULL;
1923 adapt->StopVideo = NV40StopTexturedVideo;
1924 adapt->SetPortAttribute = NVSetTexturePortAttribute;
1925 adapt->GetPortAttribute = NVGetTexturePortAttribute;
1926 adapt->QueryBestSize = NVQueryBestSize;
1927 adapt->PutImage = NVPutImage;
1928 adapt->QueryImageAttributes = NVQueryImageAttributes;
1930 pPriv->videoStatus = 0;
1931 pPriv->grabbedByV4L = FALSE;
1932 pPriv->blitter = FALSE;
1933 pPriv->texture = TRUE;
1934 pPriv->doubleBuffer = FALSE;
1935 pPriv->SyncToVBlank = FALSE;
1937 pNv->textureAdaptor = adapt;
1944 * tries to initialize the various supported adapters
1945 * and add them to the list of ports on screen "pScreen".
1948 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
1949 * @see NVSetupBlitVideo(ScreenPtr pScreen)
1951 void NVInitVideo (ScreenPtr pScreen)
1953 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1954 NVPtr pNv = NVPTR(pScrn);
1955 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
1956 XF86VideoAdaptorPtr overlayAdaptor = NULL;
1957 XF86VideoAdaptorPtr blitAdaptor = NULL;
1958 XF86VideoAdaptorPtr textureAdaptor = NULL;
1962 * Driving the blitter requires the DMA FIFO. Using the FIFO
1963 * without accel causes DMA errors. While the overlay might
1964 * might work without accel, we also disable it for now when
1965 * acceleration is disabled:
1967 if (pScrn->bitsPerPixel != 8 && pNv->Architecture < NV_ARCH_50 && !pNv->NoAccel) {
1968 overlayAdaptor = NVSetupOverlayVideo(pScreen);
1969 blitAdaptor = NVSetupBlitVideo(pScreen);
1970 if (pNv->Architecture == NV_ARCH_40)
1971 textureAdaptor = NV40SetupTexturedVideo(pScreen);
1974 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
1975 if(blitAdaptor || overlayAdaptor) {
1976 int size = num_adaptors;
1978 if(overlayAdaptor) size++;
1979 if(blitAdaptor) size++;
1981 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
1984 memcpy(newAdaptors, adaptors, num_adaptors *
1985 sizeof(XF86VideoAdaptorPtr));
1988 if(overlayAdaptor) {
1989 newAdaptors[num_adaptors] = overlayAdaptor;
1993 if (textureAdaptor) {
1994 newAdaptors[num_adaptors] = textureAdaptor;
1999 newAdaptors[num_adaptors] = blitAdaptor;
2003 adaptors = newAdaptors;
2008 xf86XVScreenInit(pScreen, adaptors, num_adaptors);