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 #if X_BYTE_ORDER == X_BIG_ENDIAN
693 *vud = (vs[0]<<8) | (us[0] << 0);
695 *vud = vs[0] | (us[0]<<8);
706 static int NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 * xa, INT32 * xb, INT32 * ya, INT32 * yb,
707 short * src_x, short * src_y, short * src_w, short * src_h,
708 short * drw_x, short * drw_y, short * drw_w, short * drw_h,
709 int * left, int * top, int * right, int * bottom,
711 int * npixels, int * nlines,
712 RegionPtr clipBoxes, short width, short height
715 NVPtr pNv = NVPTR(pScrn);
718 if ( action_flags & USE_OVERLAY )
719 { /* overlay hardware scaler limitation - copied from nv, UNCHECKED*/
720 if (*src_w > (*drw_w << 3))
721 *drw_w = *src_w >> 3;
722 if (*src_h > (*drw_h << 3))
723 *drw_h = *src_h >> 3;
729 *xb = *src_x + *src_w;
731 *yb = *src_y + *src_h;
734 dstBox->x2 = *drw_x + *drw_w;
736 dstBox->y2 = *drw_y + *drw_h;
738 if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
742 if ( action_flags & USE_OVERLAY )
744 if ( ! pNv->randr12_enable )
746 dstBox->x1 -= pScrn->frameX0;
747 dstBox->x2 -= pScrn->frameX0;
748 dstBox->y1 -= pScrn->frameY0;
749 dstBox->y2 -= pScrn->frameY0;
753 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
754 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
755 dstBox->x1 -= xf86_config->crtc[pPriv->overlayCRTC]->x;
756 dstBox->x2 -= xf86_config->crtc[pPriv->overlayCRTC]->x;
757 dstBox->y1 -= xf86_config->crtc[pPriv->overlayCRTC]->y;
758 dstBox->y2 -= xf86_config->crtc[pPriv->overlayCRTC]->y;
764 /* Convert fixed point to integer, as xf86XVClipVideoHelper probably turns its parameter into fixed point values */
766 if (*left < 0) *left = 0;
768 if (*top < 0) *top = 0;
769 *right = (*xb) >> 16;
770 if (*right > width) *right = width;
771 *bottom = (*yb) >> 16;
772 if (*bottom > height) *bottom = height;
774 if ( action_flags & IS_YV12 )
776 *left &= ~1; //even "left", even "top", even number of pixels per line and even number of lines
777 *npixels = ((*right + 1) & ~1) - *left;
779 *nlines = ((*bottom + 1) & ~1) - *top;
781 else if ( action_flags & IS_YUY2 )
783 *left &= ~1; //even "left"
784 *npixels = ((*right + 1) & ~1) - *left; //even number of pixels per line
785 *nlines = *bottom - *top;
788 else if (action_flags & IS_RGB )
790 *npixels = *right - *left;
791 *nlines = *bottom - *top;
798 static int NV_calculate_pitches_and_mem_size(int action_flags, int * srcPitch, int * srcPitch2, int * dstPitch,
799 int * s2offset, int * s3offset,
800 int * newFBSize, int * newTTSize,
801 int * line_len, int npixels, int nlines, int width, int height)
805 if ( action_flags & IS_YV12 )
807 *srcPitch = (width + 3) & ~3; /* of luma */
808 *s2offset = *srcPitch * height;
809 *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
810 *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
811 *dstPitch = (npixels + 63) & ~63; /*luma and chroma pitch*/
813 *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
814 *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
816 else if ( action_flags & IS_YUY2 )
818 *srcPitch = width << 1; /* one luma, one chroma per pixel */
819 *dstPitch = ((npixels << 1) + 63) & ~63;
820 *line_len = npixels << 1;
821 *newFBSize = nlines * *dstPitch;
822 *newTTSize = nlines * *line_len;
824 else if ( action_flags & IS_RGB )
826 *srcPitch = width << 2; /* one R, one G, one B, one X per pixel */
827 *dstPitch = ((npixels << 2) + 63) & ~63;
828 *line_len = npixels << 2;
829 *newFBSize = nlines * *dstPitch;
830 *newTTSize = nlines * *dstPitch;
834 if ( action_flags & CONVERT_TO_YUY2 )
836 *dstPitch = ((npixels << 1) + 63) & ~63;
837 *line_len = npixels << 1;
838 *newFBSize = nlines * *dstPitch;
839 *newTTSize = nlines * *line_len;
842 if ( action_flags & SWAP_UV )
843 { //I420 swaps U and V
845 *s2offset = *s3offset;
849 if ( action_flags & USE_OVERLAY ) // overlay double buffering ...
850 (*newFBSize) <<= 1; // ... means double the amount of VRAM needed
857 * NV_set_action_flags
858 * This function computes the action flags from the input image,
859 * that is, it decides what NVPutImage and its helpers must do.
860 * This eases readability by avoiding lots of switch-case statements in the core NVPutImage
862 static void NV_set_action_flags(ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, int id,
863 short drw_x, short drw_y, short drw_w, short drw_h, int * action_flags)
865 #define USING_OVERLAY (*action_flags & USE_OVERLAY)
866 #define USING_TEXTURE (*action_flags & USE_TEXTURE)
867 #define USING_BLITTER ((!(*action_flags & USE_OVERLAY)) && (!(*action_flags & USE_TEXTURE)))
869 NVPtr pNv = NVPTR(pScrn);
873 /* Pixel format-related bits */
874 if ( id == FOURCC_YUY2 || id == FOURCC_UYVY )
875 *action_flags |= IS_YUY2;
877 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
878 *action_flags |= IS_YV12;
880 if ( id == FOURCC_RGB ) /*How long will we support it?*/
881 *action_flags |= IS_RGB;
883 if ( id == FOURCC_I420 ) /*I420 is YV12 with swapped UV*/
884 *action_flags |= SWAP_UV;
886 /* Desired adapter */
887 if ( !pPriv -> blitter && !pPriv -> texture )
888 *action_flags |= USE_OVERLAY;
890 if ( !pPriv -> blitter && pPriv->texture )
891 *action_flags |= USE_TEXTURE;
893 /* Adapter fallbacks (when the desired one can't be used)*/
895 WindowPtr pWin = NULL;
897 if (!noCompositeExtension && WindowDrawable(pDraw->type))
899 pWin = (WindowPtr)pDraw;
903 if ( pWin->redirectDraw )
904 *action_flags &= ~USE_OVERLAY;
908 if ( USING_OVERLAY && pNv->randr12_enable )
909 { /* We need to check the CRTC we're on */
910 char crtc = nv_window_belongs_to_crtc(pScrn, drw_x, drw_y, drw_w, drw_h);
912 /* We're on CRTC 0, or 1, or both.. */
913 if ( ( crtc & (1 << 0)) && (crtc & (1 << 1)) )
914 { /* The overlay cannot be used on two CRTCs at a time, so we need to fallback on the blitter */
915 *action_flags &= ~USE_OVERLAY;
917 else if ( (crtc & (1 << 0) ) )
918 { /* We need to put the overlay on CRTC0 - if it's not already here */
919 if ( pPriv->overlayCRTC == 1 )
921 nvWriteCRTC(pNv, 0, NV_CRTC_FSEL, nvReadCRTC(pNv, 0, NV_CRTC_FSEL) | NV_CRTC_FSEL_OVERLAY);
922 nvWriteCRTC(pNv, 1, NV_CRTC_FSEL, nvReadCRTC(pNv, 1, NV_CRTC_FSEL) & ~NV_CRTC_FSEL_OVERLAY);
923 pPriv->overlayCRTC = 0;
926 else if ( (crtc & (1 << 1) ) )
928 if ( pPriv->overlayCRTC == 0 )
930 nvWriteCRTC(pNv, 1, NV_CRTC_FSEL, nvReadCRTC(pNv, 1, NV_CRTC_FSEL) | NV_CRTC_FSEL_OVERLAY);
931 nvWriteCRTC(pNv, 0, NV_CRTC_FSEL, nvReadCRTC(pNv, 0, NV_CRTC_FSEL) & ~NV_CRTC_FSEL_OVERLAY);
932 pPriv->overlayCRTC = 1;
937 /* At this point the adapter we're going to use is _known_. You cannot change it now. */
938 /* Card/adapter format restrictions */
941 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
942 { /*The blitter does not handle YV12 natively*/
943 *action_flags |= CONVERT_TO_YUY2;
947 if ( USING_OVERLAY && (pNv->Architecture == NV_ARCH_04 ))
948 if ( * action_flags & IS_YV12 ) /*NV04-05 don't support native YV12, only YUY2 and ITU-R BT.601*/
949 *action_flags |= CONVERT_TO_YUY2;
951 if ( USING_OVERLAY && (pNv->Architecture == NV_ARCH_10 || pNv->Architecture == NV_ARCH_20 ))
952 { /* No YV12 overlay on NV10, 11, 15, 20, NFORCE */
953 switch ( pNv->Chipset & 0xfff0 )
958 case CHIPSET_NFORCE: /*XXX: unsure about nforce*/
960 *action_flags |= CONVERT_TO_YUY2; break;
971 * PutImage is "the" important function of the Xv extension.
972 * a client (e.g. video player) calls this function for every
973 * image (of the video) to be displayed. this function then
974 * scales and displays the image.
976 * @param pScrn screen which hold the port where the image is put
977 * @param src_x source point in the source image to start displaying from
978 * @param src_y see above
979 * @param src_w width of the source image to display
980 * @param src_h see above
981 * @param drw_x screen point to display to
983 * @param drw_w width of the screen drawable
985 * @param id pixel format of image
986 * @param buf pointer to buffer containing the source image
987 * @param width total width of the source image we are passed
990 * @param clipBoxes ??
991 * @param data pointer to port
992 * @param pDraw drawable pointer
995 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
996 short drw_x, short drw_y,
997 short src_w, short src_h,
998 short drw_w, short drw_h,
1001 short width, short height,
1002 Bool Sync, /*FIXME: need to honor the Sync*/
1003 RegionPtr clipBoxes,
1008 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1009 NVPtr pNv = NVPTR(pScrn);
1010 INT32 xa = 0, xb = 0, ya = 0, yb = 0; //source box
1011 int newFBSize = 0, newTTSize = 0; //size to allocate in VRAM and in GART respectively
1012 int offset = 0, s2offset = 0, s3offset = 0; //card VRAM offset, source offsets for U and V planes
1013 int srcPitch = 0, srcPitch2 = 0, dstPitch = 0; //source pitch, source pitch of U and V planes in case of YV12, VRAM destination pitch
1014 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
1018 int line_len = 0; //length of a line, like npixels, but in bytes
1019 struct nouveau_bo *destination_buffer = NULL;
1020 unsigned char * video_mem_destination = NULL;
1021 int action_flags; //what shall we do?
1024 if (pPriv->grabbedByV4L)
1028 NV_set_action_flags(pScrn, pDraw, pPriv, id, drw_x, drw_y, drw_w, drw_h, &action_flags);
1030 if ( NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
1031 &src_x, &src_y, &src_w, &src_h,
1032 &drw_x, &drw_y, &drw_w, &drw_h,
1033 &left, &top, &right, &bottom, &dstBox,
1035 clipBoxes, width, height ) )
1041 if ( NV_calculate_pitches_and_mem_size(action_flags, &srcPitch, &srcPitch2, &dstPitch,
1042 &s2offset, &s3offset,
1043 & newFBSize, &newTTSize ,&line_len ,
1044 npixels, nlines, width, height) )
1046 return BadImplementation;
1049 /* There are some cases (tvtime with overscan for example) where the input image is larger (width/height) than
1050 the source rectangle for the overlay (src_w, src_h). In those cases, we try to do something optimal by uploading only
1051 the necessary data. */
1052 if ( action_flags & IS_YUY2 || action_flags & IS_RGB )
1054 buf += (top * srcPitch) + left;
1057 if ( action_flags & IS_YV12 )
1059 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1064 pPriv->video_mem = NVAllocateVideoMemory(pScrn, pPriv->video_mem,
1066 if (!pPriv->video_mem)
1069 offset = pPriv->video_mem->offset;
1071 /*The overlay supports hardware double buffering. We handle this here*/
1072 if (pPriv->doubleBuffer) {
1073 int mask = 1 << (pPriv->currentBuffer << 2);
1074 /* overwrite the newest buffer if there's not one free */
1075 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1076 if (!pPriv->currentBuffer)
1077 offset += newFBSize >> 1;
1081 if (pPriv->currentBuffer)
1082 offset += newFBSize >> 1;
1085 /*Now we take a decision regarding the way we send the data to the card.
1086 Either we use double buffering of "private" TT memory
1087 Either we rely on X's GARTScratch
1088 Either we fallback on CPU copy
1091 /* Try to allocate host-side double buffers, unless we have already failed*/
1092 /* We take only nlines * line_len bytes - that is, only the pixel data we are interested in - because the stuff in the GART is
1093 written contiguously */
1094 if ( pPriv -> currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1096 pPriv->TT_mem_chunk[0] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[0],
1098 if ( pPriv->TT_mem_chunk[0] )
1100 pPriv->TT_mem_chunk[1] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[1],
1103 if ( ! pPriv->TT_mem_chunk[1] )
1105 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1106 pPriv->TT_mem_chunk[0] = NULL;
1107 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1108 //xf86DrvMsg(0, X_INFO, "Alloc 1 failed\n");
1113 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1114 //xf86DrvMsg(0, X_INFO, "Alloc 0 failed\n");
1118 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1119 { //if we have a private buffer
1120 destination_buffer = pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1121 //xf86DrvMsg(0, X_INFO, "Using private mem chunk #%d\n", pPriv->currentHostBuffer);
1123 /* We know where we are going to write, but we are not sure yet whether we can do it directly, because
1124 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.
1125 If we do, then we must wait for it before overwriting the buffer.
1126 Else we need one, so we call the Xv notifier allocator.*/
1127 if ( pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1129 //xf86DrvMsg(0, X_INFO, "Waiting for notifier %p (%d)\n", pPriv->DMANotifier[pPriv->currentHostBuffer], pPriv->currentHostBuffer);
1130 if (nouveau_notifier_wait_status(pPriv->DMANotifier[pPriv->currentHostBuffer], 0, 0, 0))
1135 //xf86DrvMsg(0, X_INFO, "Allocating notifier...\n");
1136 pPriv->DMANotifier [ pPriv->currentHostBuffer ] = NVXvDMANotifierAlloc(pScrn);
1137 if (! pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1138 { /* 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.
1139 I know that's a lot of code but I believe it's necessary to properly handle all the cases*/
1140 xf86DrvMsg(0, X_ERROR, "Ran out of Xv notifiers!\n");
1141 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1142 pPriv->TT_mem_chunk[0] = NULL;
1143 nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
1144 pPriv->TT_mem_chunk[1] = NULL;
1145 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1147 //xf86DrvMsg(0, X_INFO, "Got notifier %p\n", pPriv->DMANotifier [ pPriv->currentHostBuffer ]);
1151 if ( pPriv -> currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE )
1152 { //otherwise we fall back on DDX's GARTScratch
1153 destination_buffer = pNv->GART;
1154 //xf86DrvMsg(0, X_INFO, "Using global GART memory chunk\n");
1157 if ( !destination_buffer) //if we have no GART at all
1160 if(newTTSize <= destination_buffer->size)
1162 unsigned char *dst = destination_buffer->map;
1165 /* Upload to GART */
1166 if ( action_flags & IS_YV12)
1168 if ( action_flags & CONVERT_TO_YUY2 )
1170 NVCopyData420(buf + (top * srcPitch) + left,
1171 buf + s2offset, buf + s3offset,
1172 dst, srcPitch, srcPitch2,
1173 line_len, nlines, npixels);
1177 unsigned char * tbuf = buf + top * srcPitch + left;
1178 unsigned char * tdst = dst;
1179 //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);
1181 for ( i=0; i < nlines; i++)
1183 memcpy(tdst, tbuf, line_len);
1187 dst += line_len * nlines;
1188 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, dst, line_len, srcPitch2, nlines, line_len);
1193 for ( i=0; i < nlines; i++)
1195 memcpy(dst, buf, line_len);
1202 BEGIN_RING(NvMemFormat,
1203 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
1204 OUT_RING (pNv->chan->gart->handle);
1205 OUT_RING (pNv->chan->vram->handle);
1208 if (action_flags & IS_YV12 && ! (action_flags & CONVERT_TO_YUY2) )
1209 { /*we start the color plane transfer separately*/
1210 BEGIN_RING(NvMemFormat,
1211 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1212 OUT_RING ((uint32_t)destination_buffer->offset + line_len * nlines);
1213 OUT_RING ((uint32_t)offset + dstPitch * nlines);
1214 OUT_RING (line_len);
1215 OUT_RING (dstPitch);
1216 OUT_RING (line_len);
1217 OUT_RING ((nlines >> 1));
1218 OUT_RING ((1<<8)|1);
1223 BEGIN_RING(NvMemFormat,
1224 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1225 OUT_RING ((uint32_t)destination_buffer->offset);
1226 OUT_RING ((uint32_t)offset);
1227 OUT_RING (line_len);
1228 OUT_RING (dstPitch);
1229 OUT_RING (line_len);
1231 OUT_RING ((1<<8)|1);
1234 if ( destination_buffer == pNv->GART )
1236 nouveau_notifier_reset(pNv->notify0, 0);
1239 nouveau_notifier_reset(pPriv->DMANotifier[pPriv->currentHostBuffer], 0);
1240 BEGIN_RING(NvMemFormat,
1241 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1242 OUT_RING (pPriv->DMANotifier[pPriv->currentHostBuffer]->handle);
1246 BEGIN_RING(NvMemFormat, NV04_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1249 BEGIN_RING(NvMemFormat, 0x100, 1);
1252 //Put back NvDmaNotifier0 for EXA
1253 BEGIN_RING(NvMemFormat,
1254 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1255 OUT_RING (pNv->notify0->handle);
1259 if ( destination_buffer == pNv->GART )
1260 if (nouveau_notifier_wait_status(pNv->notify0, 0, 0, 0))
1263 else { //GART is too small, we fallback on CPU copy
1265 video_mem_destination = pPriv->video_mem->map + (offset - (uint32_t)pPriv->video_mem->offset);
1267 if ( action_flags & IS_YV12 )
1269 if ( action_flags & CONVERT_TO_YUY2 )
1271 NVCopyData420(buf + (top * srcPitch) + left,
1272 buf + s2offset, buf + s3offset,
1273 video_mem_destination, srcPitch, srcPitch2,
1274 dstPitch, nlines, npixels);
1277 unsigned char * tbuf = buf + left + top * srcPitch;
1278 for ( i=0; i < nlines; i++)
1280 int dwords = npixels << 1;
1281 while (dwords & ~0x03)
1283 *video_mem_destination = *tbuf;
1284 *(video_mem_destination + 1) = *(tbuf + 1);
1285 *(video_mem_destination + 2) = *(tbuf + 2);
1286 *(video_mem_destination + 3) = *(tbuf + 3);
1287 video_mem_destination += 4;
1294 *(video_mem_destination + 2) = *(tbuf + 2);
1296 *(video_mem_destination + 1) = *(tbuf + 1);
1298 *video_mem_destination = *tbuf;
1301 video_mem_destination += dstPitch - (npixels << 1);
1302 tbuf += srcPitch - (npixels << 1);
1305 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, video_mem_destination, dstPitch, srcPitch2, nlines, line_len);
1310 for ( i=0; i < nlines; i++)
1312 int dwords = npixels << 1;
1313 while (dwords & ~0x03)
1315 *video_mem_destination = *buf;
1316 *(video_mem_destination + 1) = *(buf + 1);
1317 *(video_mem_destination + 2) = *(buf + 2);
1318 *(video_mem_destination + 3) = *(buf + 3);
1319 video_mem_destination += 4;
1326 *(video_mem_destination + 2) = *(buf + 2);
1328 *(video_mem_destination + 1) = *(buf + 1);
1330 *video_mem_destination = *buf;
1333 video_mem_destination += dstPitch - (npixels << 1);
1334 buf += srcPitch - (npixels << 1);
1342 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1343 pPriv->currentHostBuffer ^= 1;
1345 if ( action_flags & USE_OVERLAY )
1347 if ( pNv->Architecture == NV_ARCH_04 )
1348 NV04PutOverlayImage(pScrn, offset, id,
1352 src_w, src_h, drw_w, drw_h,
1355 NV10PutOverlayImage(pScrn, offset, ((action_flags & IS_YUY2) || (action_flags & CONVERT_TO_YUY2)) ? 0 : offset + nlines * dstPitch, id,
1359 src_w, src_h, drw_w, drw_h,
1361 pPriv->currentBuffer ^= 1;
1366 if (action_flags & USE_TEXTURE) { /* Texture adapter */
1367 int rval = NV40PutTextureImage(pScrn, offset, offset + nlines * dstPitch, id,
1371 src_w, src_h, drw_w, drw_h,
1373 if (rval != Success)
1375 } else { /* Blit adapter */
1376 NVPutBlitImage(pScrn, offset, id,
1380 src_w, src_h, drw_w, drw_h,
1389 * QueryImageAttributes
1392 * - size (memory required to store image),
1396 * depending on colorspace (id) and dimensions (w,h) of image
1400 * may be adjusted as needed
1402 * @param pScrn unused
1403 * @param id colorspace of image
1404 * @param w pointer to width of image
1405 * @param h pointer to height of image
1406 * @param pitches pitches[i] = length of a scanline in plane[i]
1407 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1408 * @return size of the memory required for the XvImage queried
1411 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1412 unsigned short *w, unsigned short *h,
1413 int *pitches, int *offsets)
1417 if (*w > IMAGE_MAX_W)
1419 if (*h > IMAGE_MAX_H)
1422 *w = (*w + 1) & ~1; // width rounded up to an even number
1429 *h = (*h + 1) & ~1; // height rounded up to an even number
1430 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1432 pitches[0] = size; // width rounded up to a multiple of 4
1435 offsets[1] = size; // number of pixels in "rounded up" image
1436 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1438 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1439 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1440 size += tmp; // 5/4*number of pixels in "rounded up" image
1442 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1443 size += tmp; // = 3/2*number of pixels in "rounded up" image
1447 size = *w << 1; // 2*width
1449 pitches[0] = size; // 2*width
1450 size *= *h; // 2*width*height
1453 size = *w << 2; // 4*width (32 bit per pixel)
1455 pitches[0] = size; // 4*width
1456 size *= *h; // 4*width*height
1466 /***** Exported offscreen surface stuff ****/
1470 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1471 unsigned short w, unsigned short h,
1472 XF86SurfacePtr surface)
1474 NVPtr pNv = NVPTR(pScrn);
1475 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1478 bpp = pScrn->bitsPerPixel >> 3;
1480 if (pPriv->grabbedByV4L)
1483 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1487 pPriv->pitch = ((w << 1) + 63) & ~63;
1488 size = h * pPriv->pitch / bpp;
1490 pPriv->video_mem = NVAllocateVideoMemory(pScrn,
1493 if (!pPriv->video_mem)
1499 surface->height = h;
1500 surface->pScrn = pScrn;
1501 surface->pitches = &pPriv->pitch;
1502 surface->offsets = &pPriv->offset;
1503 surface->devPrivate.ptr = (pointer)pPriv;
1506 /* grab the video */
1507 NVStopOverlay(pScrn);
1508 pPriv->videoStatus = 0;
1509 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1510 pPriv->grabbedByV4L = TRUE;
1516 NVStopSurface(XF86SurfacePtr surface)
1518 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1520 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
1521 NV10StopOverlay(surface->pScrn);
1522 pPriv->videoStatus = 0;
1529 NVFreeSurface(XF86SurfacePtr surface)
1531 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1533 if (pPriv->grabbedByV4L) {
1534 NVStopSurface(surface);
1535 NVFreeOverlayMemory(surface->pScrn);
1536 pPriv->grabbedByV4L = FALSE;
1543 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
1545 NVPtr pNv = NVPTR(pScrn);
1546 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1548 return NV10GetOverlayPortAttribute(pScrn, attribute,
1549 value, (pointer)pPriv);
1553 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
1555 NVPtr pNv = NVPTR(pScrn);
1556 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1558 return NV10SetOverlayPortAttribute(pScrn, attribute,
1559 value, (pointer)pPriv);
1563 NVDisplaySurface(XF86SurfacePtr surface,
1564 short src_x, short src_y,
1565 short drw_x, short drw_y,
1566 short src_w, short src_h,
1567 short drw_w, short drw_h,
1568 RegionPtr clipBoxes)
1570 ScrnInfoPtr pScrn = surface->pScrn;
1571 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1572 INT32 xa, xb, ya, yb;
1575 if (!pPriv->grabbedByV4L)
1578 if (src_w > (drw_w << 3))
1580 if (src_h > (drw_h << 3))
1590 dstBox.x2 = drw_x + drw_w;
1592 dstBox.y2 = drw_y + drw_h;
1594 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1595 surface->width, surface->height))
1598 dstBox.x1 -= pScrn->frameX0;
1599 dstBox.x2 -= pScrn->frameX0;
1600 dstBox.y1 -= pScrn->frameY0;
1601 dstBox.y2 -= pScrn->frameY0;
1603 pPriv->currentBuffer = 0;
1605 NV10PutOverlayImage(pScrn, surface->offsets[0], 0, surface->id,
1606 surface->pitches[0], &dstBox, xa, ya, xb, yb,
1607 surface->width, surface->height, src_w, src_h,
1608 drw_w, drw_h, clipBoxes);
1615 * this function does all the work setting up a blit port
1619 static XF86VideoAdaptorPtr
1620 NVSetupBlitVideo (ScreenPtr pScreen)
1622 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1623 NVPtr pNv = NVPTR(pScrn);
1624 XF86VideoAdaptorPtr adapt;
1625 NVPortPrivPtr pPriv;
1628 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1629 sizeof(NVPortPrivRec) +
1630 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
1634 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1636 adapt->name = "NV Video Blitter";
1637 adapt->nEncodings = 1;
1638 adapt->pEncodings = &DummyEncoding;
1639 adapt->nFormats = NUM_FORMATS_ALL;
1640 adapt->pFormats = NVFormats;
1641 adapt->nPorts = NUM_BLIT_PORTS;
1642 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1644 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
1645 for(i = 0; i < NUM_BLIT_PORTS; i++)
1646 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1648 if(pNv->WaitVSyncPossible) {
1649 adapt->pAttributes = NVBlitAttributes;
1650 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
1652 adapt->pAttributes = NULL;
1653 adapt->nAttributes = 0;
1656 adapt->pImages = NVImages;
1657 adapt->nImages = NUM_IMAGES_ALL;
1658 adapt->PutVideo = NULL;
1659 adapt->PutStill = NULL;
1660 adapt->GetVideo = NULL;
1661 adapt->GetStill = NULL;
1662 adapt->StopVideo = NVStopBlitVideo;
1663 adapt->SetPortAttribute = NVSetBlitPortAttribute;
1664 adapt->GetPortAttribute = NVGetBlitPortAttribute;
1665 adapt->QueryBestSize = NVQueryBestSize;
1666 adapt->PutImage = NVPutImage;
1667 adapt->QueryImageAttributes = NVQueryImageAttributes;
1669 pPriv->videoStatus = 0;
1670 pPriv->grabbedByV4L = FALSE;
1671 pPriv->blitter = TRUE;
1672 pPriv->texture = FALSE;
1673 pPriv->doubleBuffer = FALSE;
1674 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1676 pNv->blitAdaptor = adapt;
1677 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
1683 * NVSetupOverlayVideo
1684 * this function does all the work setting up an overlay port
1686 * @return overlay port
1688 static XF86VideoAdaptorPtr
1689 NVSetupOverlayVideoAdapter(ScreenPtr pScreen)
1691 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1692 NVPtr pNv = NVPTR(pScrn);
1693 XF86VideoAdaptorPtr adapt;
1694 NVPortPrivPtr pPriv;
1696 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1697 sizeof(NVPortPrivRec) +
1698 sizeof(DevUnion)))) {
1702 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1703 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
1704 adapt->name = "NV Video Overlay";
1705 adapt->nEncodings = 1;
1706 adapt->pEncodings = &DummyEncoding;
1707 adapt->nFormats = NUM_FORMATS_ALL;
1708 adapt->pFormats = NVFormats;
1710 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1712 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
1713 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
1715 adapt->pAttributes = (pNv->Architecture != NV_ARCH_04) ? NV10OverlayAttributes : NV04OverlayAttributes;
1716 adapt->nAttributes = (pNv->Architecture != NV_ARCH_04) ? NUM_NV10_OVERLAY_ATTRIBUTES : NUM_NV04_OVERLAY_ATTRIBUTES;
1717 adapt->pImages = NVImages;
1718 adapt->nImages = NUM_IMAGES_YUV;
1719 adapt->PutVideo = NULL;
1720 adapt->PutStill = NULL;
1721 adapt->GetVideo = NULL;
1722 adapt->GetStill = NULL;
1723 adapt->StopVideo = NVStopOverlayVideo;
1724 adapt->SetPortAttribute = (pNv->Architecture != NV_ARCH_04) ? NV10SetOverlayPortAttribute : NV04SetOverlayPortAttribute;
1725 adapt->GetPortAttribute = (pNv->Architecture != NV_ARCH_04) ? NV10GetOverlayPortAttribute : NV04GetOverlayPortAttribute;
1726 adapt->QueryBestSize = NVQueryBestSize;
1727 adapt->PutImage = NVPutImage;
1728 adapt->QueryImageAttributes = NVQueryImageAttributes;
1730 pPriv->videoStatus = 0;
1731 pPriv->currentBuffer = 0;
1732 pPriv->grabbedByV4L = FALSE;
1733 pPriv->blitter = FALSE;
1734 pPriv->texture = FALSE;
1735 if ( pNv->Architecture == NV_ARCH_04 )
1736 pPriv->doubleBuffer = 0;
1738 NVSetPortDefaults (pScrn, pPriv);
1740 /* gotta uninit this someplace */
1741 REGION_NULL(pScreen, &pPriv->clip);
1743 pNv->overlayAdaptor = adapt;
1745 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
1746 xvColorKey = MAKE_ATOM("XV_COLORKEY");
1747 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
1748 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
1750 if ( pNv->Architecture != NV_ARCH_04 )
1752 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
1753 xvContrast = MAKE_ATOM("XV_CONTRAST");
1754 xvSaturation = MAKE_ATOM("XV_SATURATION");
1755 xvHue = MAKE_ATOM("XV_HUE");
1756 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
1757 xvOnCRTCNb = MAKE_ATOM("XV_ON_CRTC_NB");
1758 NV10WriteOverlayParameters(pScrn);
1765 XF86OffscreenImageRec NVOffscreenImages[2] = {
1768 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1773 NVGetSurfaceAttribute,
1774 NVSetSurfaceAttribute,
1775 IMAGE_MAX_W, IMAGE_MAX_H,
1776 NUM_NV10_OVERLAY_ATTRIBUTES - 1,
1777 &NV10OverlayAttributes[1]
1781 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1786 NVGetSurfaceAttribute,
1787 NVSetSurfaceAttribute,
1788 IMAGE_MAX_W, IMAGE_MAX_H,
1789 NUM_NV10_OVERLAY_ATTRIBUTES - 1,
1790 &NV10OverlayAttributes[1]
1795 NVInitOffscreenImages (ScreenPtr pScreen)
1797 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
1801 * NVChipsetHasOverlay
1803 * newer chips don't support overlay anymore.
1804 * overlay feature is emulated via textures.
1807 * @return true, if chipset supports overlay
1810 NVChipsetHasOverlay(NVPtr pNv)
1812 switch (pNv->Architecture) {
1813 case NV_ARCH_04: /*NV04 has a different overlay than NV10+*/
1819 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
1830 * NVSetupOverlayVideo
1831 * check if chipset supports Overla
1832 * if so, setup overlay port
1834 * @return overlay port
1835 * @see NVChipsetHasOverlay(NVPtr pNv)
1836 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
1837 * @see NVInitOffscreenImages(ScreenPtr pScreen)
1839 static XF86VideoAdaptorPtr
1840 NVSetupOverlayVideo(ScreenPtr pScreen)
1842 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1843 XF86VideoAdaptorPtr overlayAdaptor = NULL;
1844 NVPtr pNv = NVPTR(pScrn);
1846 if (!NVChipsetHasOverlay(pNv))
1849 overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen);
1850 if (overlayAdaptor && pNv->Architecture != NV_ARCH_04 )
1851 NVInitOffscreenImages(pScreen); //I am not sure what this call does.
1854 if (!noCompositeExtension) {
1855 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1856 "Xv: Composite is enabled, enabling overlay with smart blitter fallback\n");
1857 overlayAdaptor -> name = "NV Video Overlay with Composite";
1861 if (pNv->randr12_enable) {
1862 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1863 "Xv: Randr12 is enabled, using overlay with smart blitter fallback and automatic CRTC switching\n");
1867 return overlayAdaptor;
1871 * NV40 texture adapter.
1874 #define NUM_FORMAT_TEXTURED 2
1876 static XF86ImageRec NV40TexturedImages[NUM_FORMAT_TEXTURED] =
1883 * NV40SetupTexturedVideo
1884 * this function does all the work setting up textured video port
1886 * @return texture port
1888 static XF86VideoAdaptorPtr
1889 NV40SetupTexturedVideo (ScreenPtr pScreen)
1891 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1892 NVPtr pNv = NVPTR(pScrn);
1893 XF86VideoAdaptorPtr adapt;
1894 NVPortPrivPtr pPriv;
1897 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1898 sizeof(NVPortPrivRec) +
1899 (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
1903 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1905 adapt->name = "NV40 Texture adapter";
1906 adapt->nEncodings = 1;
1907 adapt->pEncodings = &DummyEncodingTex;
1908 adapt->nFormats = NUM_FORMATS_ALL;
1909 adapt->pFormats = NVFormats;
1910 adapt->nPorts = NUM_TEXTURE_PORTS;
1911 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1913 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
1914 for(i = 0; i < NUM_TEXTURE_PORTS; i++)
1915 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1917 if(pNv->WaitVSyncPossible) {
1918 adapt->pAttributes = NVTexturedAttributes;
1919 adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
1921 adapt->pAttributes = NULL;
1922 adapt->nAttributes = 0;
1925 adapt->pImages = NV40TexturedImages;
1926 adapt->nImages = NUM_FORMAT_TEXTURED;
1927 adapt->PutVideo = NULL;
1928 adapt->PutStill = NULL;
1929 adapt->GetVideo = NULL;
1930 adapt->GetStill = NULL;
1931 adapt->StopVideo = NV40StopTexturedVideo;
1932 adapt->SetPortAttribute = NVSetTexturePortAttribute;
1933 adapt->GetPortAttribute = NVGetTexturePortAttribute;
1934 adapt->QueryBestSize = NVQueryBestSize;
1935 adapt->PutImage = NVPutImage;
1936 adapt->QueryImageAttributes = NVQueryImageAttributes;
1938 pPriv->videoStatus = 0;
1939 pPriv->grabbedByV4L = FALSE;
1940 pPriv->blitter = FALSE;
1941 pPriv->texture = TRUE;
1942 pPriv->doubleBuffer = FALSE;
1943 pPriv->SyncToVBlank = FALSE;
1945 pNv->textureAdaptor = adapt;
1952 * tries to initialize the various supported adapters
1953 * and add them to the list of ports on screen "pScreen".
1956 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
1957 * @see NVSetupBlitVideo(ScreenPtr pScreen)
1959 void NVInitVideo (ScreenPtr pScreen)
1961 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1962 NVPtr pNv = NVPTR(pScrn);
1963 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
1964 XF86VideoAdaptorPtr overlayAdaptor = NULL;
1965 XF86VideoAdaptorPtr blitAdaptor = NULL;
1966 XF86VideoAdaptorPtr textureAdaptor = NULL;
1970 * Driving the blitter requires the DMA FIFO. Using the FIFO
1971 * without accel causes DMA errors. While the overlay might
1972 * might work without accel, we also disable it for now when
1973 * acceleration is disabled:
1975 if (pScrn->bitsPerPixel != 8 && pNv->Architecture < NV_ARCH_50 && !pNv->NoAccel) {
1976 overlayAdaptor = NVSetupOverlayVideo(pScreen);
1977 blitAdaptor = NVSetupBlitVideo(pScreen);
1978 if (pNv->Architecture == NV_ARCH_40)
1979 textureAdaptor = NV40SetupTexturedVideo(pScreen);
1982 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
1983 if(blitAdaptor || overlayAdaptor) {
1984 int size = num_adaptors;
1986 if(overlayAdaptor) size++;
1987 if(blitAdaptor) size++;
1989 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
1992 memcpy(newAdaptors, adaptors, num_adaptors *
1993 sizeof(XF86VideoAdaptorPtr));
1996 if(overlayAdaptor) {
1997 newAdaptors[num_adaptors] = overlayAdaptor;
2001 if (textureAdaptor) {
2002 newAdaptors[num_adaptors] = textureAdaptor;
2007 newAdaptors[num_adaptors] = blitAdaptor;
2011 adaptors = newAdaptors;
2016 xf86XVScreenInit(pScreen, adaptors, num_adaptors);