1 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_video.c,v 1.23 2004/03/20 22:07:06 mvojkovi Exp $ */
8 #include "xf86_OSproc.h"
9 #include "xf86Resources.h"
11 #include "xf86PciInfo.h"
13 #include "xf86fbman.h"
14 #include "regionstr.h"
17 #include <X11/extensions/Xv.h>
22 #include "dixstruct.h"
25 #include "nv_include.h"
28 #define OFF_DELAY 500 /* milliseconds */
29 #define FREE_DELAY 5000
31 #define OFF_TIMER 0x01
32 #define FREE_TIMER 0x02
33 #define CLIENT_VIDEO_ON 0x04
35 #define TIMER_MASK (OFF_TIMER | FREE_TIMER)
37 #define NUM_BLIT_PORTS 32
39 typedef struct _NVPortPrivRec {
46 Bool autopaintColorKey;
55 NVAllocRec * video_mem;
58 } NVPortPrivRec, *NVPortPrivPtr;
60 #define GET_OVERLAY_PRIVATE(pNv) \
61 (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr)
63 #define GET_BLIT_PRIVATE(pNv) \
64 (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr)
66 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
68 static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
69 xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
70 xvITURBT709, xvSyncToVBlank;
72 /* client libraries expect an encoding */
73 static XF86VideoEncodingRec DummyEncoding =
81 #define NUM_FORMATS_ALL 6
83 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
85 {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
86 {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
89 #define NUM_OVERLAY_ATTRIBUTES 9
90 XF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] =
92 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
93 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
94 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
95 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
96 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
97 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
98 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
99 {XvSettable | XvGettable, 0, 360, "XV_HUE"},
100 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"}
103 #define NUM_BLIT_ATTRIBUTES 2
104 XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
106 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
107 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
111 #define NUM_IMAGES_YUV 4
112 #define NUM_IMAGES_ALL 5
114 #define FOURCC_RGB 0x0000003
115 #define XVIMAGE_RGB \
120 { 0x03, 0x00, 0x00, 0x00, \
121 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
125 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
130 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}, \
134 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
144 NVSetPortDefaults (ScrnInfoPtr pScrnInfo, NVPortPrivPtr pPriv)
146 NVPtr pNv = NVPTR(pScrnInfo);
148 pPriv->brightness = 0;
149 pPriv->contrast = 4096;
150 pPriv->saturation = 4096;
152 pPriv->colorKey = pNv->videoKey;
153 pPriv->autopaintColorKey = TRUE;
154 pPriv->doubleBuffer = TRUE;
155 pPriv->iturbt_709 = FALSE;
160 NVResetVideo (ScrnInfoPtr pScrnInfo)
162 NVPtr pNv = NVPTR(pScrnInfo);
163 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
164 int satSine, satCosine;
167 angle = (double)pPriv->hue * 3.1415927 / 180.0;
169 satSine = pPriv->saturation * sin(angle);
172 satCosine = pPriv->saturation * cos(angle);
173 if (satCosine < -1024)
176 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
178 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
180 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
181 (satCosine & 0xffff));
182 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
183 (satCosine & 0xffff));
184 nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
190 NVStopOverlay (ScrnInfoPtr pScrnInfo)
192 NVPtr pNv = NVPTR(pScrnInfo);
194 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
198 NVAllocateOverlayMemory(ScrnInfoPtr pScrn, NVAllocRec *mem, int size)
200 NVPtr pNv = NVPTR(pScrn);
202 /* The code assumes the XAA fb manager is being used here,
203 * which allocates in pixels. We allocate in bytes so we
204 * need to adjust the size here.
206 size *= (pScrn->bitsPerPixel >> 3);
209 if(mem->size >= size)
211 NVFreeMemory(pNv, mem);
214 return NVAllocateMemory(pNv, NOUVEAU_MEM_FB, size); /* align 32? */
218 NVFreeOverlayMemory(ScrnInfoPtr pScrnInfo)
220 NVPtr pNv = NVPTR(pScrnInfo);
221 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
223 if(pPriv->video_mem) {
224 NVFreeMemory(pNv, pPriv->video_mem);
225 pPriv->video_mem = NULL;
231 NVFreeBlitMemory(ScrnInfoPtr pScrnInfo)
233 NVPtr pNv = NVPTR(pScrnInfo);
234 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
236 if(pPriv->video_mem) {
237 NVFreeMemory(pNv, pPriv->video_mem);
238 pPriv->video_mem = NULL;
243 NVVideoTimerCallback(ScrnInfoPtr pScrnInfo, Time currentTime)
245 NVPtr pNv = NVPTR(pScrnInfo);
246 NVPortPrivPtr pOverPriv = NULL;
247 NVPortPrivPtr pBlitPriv = NULL;
248 Bool needCallback = FALSE;
250 if (!pScrnInfo->vtSema)
253 if (pNv->overlayAdaptor) {
254 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
255 if (!pOverPriv->videoStatus)
259 if (pNv->blitAdaptor) {
260 pBlitPriv = GET_BLIT_PRIVATE(pNv);
261 if (!pBlitPriv->videoStatus)
266 if (pOverPriv->videoTime < currentTime) {
267 if (pOverPriv->videoStatus & OFF_TIMER) {
268 NVStopOverlay(pScrnInfo);
269 pOverPriv->videoStatus = FREE_TIMER;
270 pOverPriv->videoTime = currentTime + FREE_DELAY;
273 if (pOverPriv->videoStatus & FREE_TIMER) {
274 NVFreeOverlayMemory(pScrnInfo);
275 pOverPriv->videoStatus = 0;
283 if (pBlitPriv->videoTime < currentTime) {
284 NVFreeBlitMemory(pScrnInfo);
285 pBlitPriv->videoStatus = 0;
291 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
295 NVPutOverlayImage(ScrnInfoPtr pScrnInfo, int offset, int id,
296 int dstPitch, BoxPtr dstBox,
297 int x1, int y1, int x2, int y2,
298 short width, short height,
299 short src_w, short src_h,
300 short drw_w, short drw_h,
303 NVPtr pNv = NVPTR(pScrnInfo);
304 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
305 int buffer = pPriv->currentBuffer;
307 /* paint the color key */
308 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
309 !REGION_EQUAL(pScrnInfo->pScreen, &pPriv->clip, clipBoxes))) {
310 /* we always paint V4L's color key */
311 if (!pPriv->grabbedByV4L)
312 REGION_COPY(pScrnInfo->pScreen, &pPriv->clip, clipBoxes);
313 xf86XVFillKeyHelper(pScrnInfo->pScreen, pPriv->colorKey, clipBoxes);
316 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
322 nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer) , offset);
323 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer) , (height << 16) | width);
324 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
325 ((y1 << 4) & 0xffff0000) | (x1 >> 12));
326 nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer) , (src_w << 20) / drw_w);
327 nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer) , (src_h << 20) / drw_h);
328 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
329 (dstBox->y1 << 16) | dstBox->x1);
330 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
331 ((dstBox->y2 - dstBox->y1) << 16) |
332 (dstBox->x2 - dstBox->x1));
334 dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; /* use color key */
335 if(id != FOURCC_UYVY)
336 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
337 if(pPriv->iturbt_709)
338 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
340 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
341 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
342 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
344 pPriv->videoStatus = CLIENT_VIDEO_ON;
347 #ifndef ExaOffscreenMarkUsed
348 extern void ExaOffscreenMarkUsed(PixmapPtr);
350 #ifndef exaGetDrawablePixmap
351 extern PixmapPtr exaGetDrawablePixmap(DrawablePtr);
353 #ifndef exaPixmapIsOffscreen
354 extern Bool exaPixmapIsOffscreen(PixmapPtr p);
356 /* To support EXA 2.0, 2.1 has this in the header */
357 #ifndef exaMoveInPixmap
358 extern void exaMoveInPixmap(PixmapPtr pPixmap);
362 NVPutBlitImage(ScrnInfoPtr pScrnInfo, int src_offset, int id,
363 int src_pitch, BoxPtr dstBox,
364 int x1, int y1, int x2, int y2,
365 short width, short height,
366 short src_w, short src_h,
367 short drw_w, short drw_h,
371 NVPtr pNv = NVPTR(pScrnInfo);
372 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
376 CARD32 dst_size, dst_point;
377 CARD32 src_point, src_format;
380 ScreenPtr pScreen = pScrnInfo->pScreen;
381 PixmapPtr pPix = exaGetDrawablePixmap(pDraw);
384 /* Try to get the dest drawable into vram */
385 if (!exaPixmapIsOffscreen(pPix)) {
386 exaMoveInPixmap(pPix);
387 ExaOffscreenMarkUsed(pPix);
390 /* If we failed, draw directly onto the screen pixmap.
391 * Not sure if this is the best approach, maybe failing
392 * with BadAlloc would be better?
394 if (!exaPixmapIsOffscreen(pPix)) {
395 xf86DrvMsg(pScrnInfo->scrnIndex, X_ERROR,
396 "XV: couldn't move dst surface into vram\n");
397 pPix = pScreen->GetScreenPixmap(pScreen);
400 NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format);
401 NVAccelSetCtxSurf2D(pNv, pPix, pPix, dst_format);
404 /* Adjust coordinates if drawing to an offscreen pixmap */
405 if (pPix->screen_x || pPix->screen_y) {
406 REGION_TRANSLATE(pScrnInfo->pScreen, clipBoxes,
409 dstBox->x1 -= pPix->screen_x;
410 dstBox->x2 -= pPix->screen_x;
411 dstBox->y1 -= pPix->screen_y;
412 dstBox->y2 -= pPix->screen_y;
415 DamageDamageRegion((DrawablePtr)pPix, clipBoxes);
418 if (pNv->CurrentLayout.depth == 15) {
419 NVDmaStart(pNv, NvSubContextSurfaces,
421 NVDmaNext (pNv, SURFACE_FORMAT_X1R5G5B5);
425 pbox = REGION_RECTS(clipBoxes);
426 nbox = REGION_NUM_RECTS(clipBoxes);
428 dsdx = (src_w << 20) / drw_w;
429 dtdy = (src_h << 20) / drw_h;
431 dst_size = ((dstBox->y2 - dstBox->y1) << 16) |
432 (dstBox->x2 - dstBox->x1);
433 dst_point = (dstBox->y1 << 16) | dstBox->x1;
435 src_pitch |= (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER << 16) |
436 (STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR << 24);
437 src_point = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
441 src_format = STRETCH_BLIT_FORMAT_X8R8G8B8;
444 src_format = STRETCH_BLIT_FORMAT_UYVY;
447 src_format = STRETCH_BLIT_FORMAT_YUYV;
451 if(pPriv->SyncToVBlank) {
456 if(pNv->BlendingPossible) {
457 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_FORMAT, 2);
458 NVDmaNext (pNv, src_format);
459 NVDmaNext (pNv, STRETCH_BLIT_OPERATION_COPY);
461 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_FORMAT, 1);
462 NVDmaNext (pNv, src_format);
466 NVDmaStart(pNv, NvSubRectangle, RECT_SOLID_COLOR, 1);
469 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_CLIP_POINT, 6);
470 NVDmaNext (pNv, (pbox->y1 << 16) | pbox->x1);
471 NVDmaNext (pNv, ((pbox->y2 - pbox->y1) << 16) |
472 (pbox->x2 - pbox->x1));
473 NVDmaNext (pNv, dst_point);
474 NVDmaNext (pNv, dst_size);
475 NVDmaNext (pNv, dsdx);
476 NVDmaNext (pNv, dtdy);
478 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_SRC_SIZE, 4);
479 NVDmaNext (pNv, (height << 16) | width);
480 NVDmaNext (pNv, src_pitch);
481 NVDmaNext (pNv, src_offset);
482 NVDmaNext (pNv, src_point);
487 if(pNv->CurrentLayout.depth == 15) {
488 NVDmaStart(pNv, NvSubContextSurfaces,
490 NVDmaNext (pNv, SURFACE_FORMAT_R5G6B5);
497 exaMarkSync(pScrnInfo->pScreen);
499 SET_SYNC_FLAG(pNv->AccelInfoRec);
501 pPriv->videoStatus = FREE_TIMER;
502 pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
503 pNv->VideoTimerCallback = NVVideoTimerCallback;
510 NVStopOverlayVideo(ScrnInfoPtr pScrnInfo, pointer data, Bool Exit)
512 NVPtr pNv = NVPTR(pScrnInfo);
513 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
515 if(pPriv->grabbedByV4L) return;
517 REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
520 if (pPriv->videoStatus & CLIENT_VIDEO_ON)
521 NVStopOverlay(pScrnInfo);
522 NVFreeOverlayMemory(pScrnInfo);
523 pPriv->videoStatus = 0;
525 if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
526 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
527 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
528 pNv->VideoTimerCallback = NVVideoTimerCallback;
534 NVStopBlitVideo(ScrnInfoPtr pScrnInfo, pointer data, Bool Exit)
539 NVSetOverlayPortAttribute(ScrnInfoPtr pScrnInfo, Atom attribute,
540 INT32 value, pointer data)
542 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
544 if (attribute == xvBrightness) {
545 if ((value < -512) || (value > 512))
547 pPriv->brightness = value;
549 if (attribute == xvDoubleBuffer) {
550 if ((value < 0) || (value > 1))
552 pPriv->doubleBuffer = value;
554 if (attribute == xvContrast) {
555 if ((value < 0) || (value > 8191))
557 pPriv->contrast = value;
559 if (attribute == xvHue) {
565 if (attribute == xvSaturation) {
566 if ((value < 0) || (value > 8191))
568 pPriv->saturation = value;
570 if (attribute == xvColorKey) {
571 pPriv->colorKey = value;
572 REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
574 if (attribute == xvAutopaintColorKey) {
575 if ((value < 0) || (value > 1))
577 pPriv->autopaintColorKey = value;
579 if (attribute == xvITURBT709) {
580 if ((value < 0) || (value > 1))
582 pPriv->iturbt_709 = value;
584 if (attribute == xvSetDefaults) {
585 NVSetPortDefaults(pScrnInfo, pPriv);
589 NVResetVideo(pScrnInfo);
595 NVGetOverlayPortAttribute(ScrnInfoPtr pScrnInfo, Atom attribute,
596 INT32 *value, pointer data)
598 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
600 if (attribute == xvBrightness)
601 *value = pPriv->brightness;
602 else if (attribute == xvDoubleBuffer)
603 *value = (pPriv->doubleBuffer) ? 1 : 0;
604 else if (attribute == xvContrast)
605 *value = pPriv->contrast;
606 else if (attribute == xvSaturation)
607 *value = pPriv->saturation;
608 else if (attribute == xvHue)
610 else if (attribute == xvColorKey)
611 *value = pPriv->colorKey;
612 else if (attribute == xvAutopaintColorKey)
613 *value = (pPriv->autopaintColorKey) ? 1 : 0;
614 else if (attribute == xvITURBT709)
615 *value = (pPriv->iturbt_709) ? 1 : 0;
623 NVSetBlitPortAttribute(ScrnInfoPtr pScrnInfo, Atom attribute,
624 INT32 value, pointer data)
626 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
627 NVPtr pNv = NVPTR(pScrnInfo);
629 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
630 if ((value < 0) || (value > 1))
632 pPriv->SyncToVBlank = value;
634 if (attribute == xvSetDefaults) {
635 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
643 NVGetBlitPortAttribute(ScrnInfoPtr pScrnInfo, Atom attribute,
644 INT32 *value, pointer data)
646 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
648 if(attribute == xvSyncToVBlank)
649 *value = (pPriv->SyncToVBlank) ? 1 : 0;
661 NVQueryBestSize(ScrnInfoPtr pScrnInfo, Bool motion,
662 short vid_w, short vid_h,
663 short drw_w, short drw_h,
664 unsigned int *p_w, unsigned int *p_h,
667 if(vid_w > (drw_w << 3))
669 if(vid_h > (drw_h << 3))
676 static void NVCopyData420(unsigned char *src1, unsigned char *src2,
677 unsigned char *src3, unsigned char *dst1,
678 int srcPitch, int srcPitch2,
688 for (j = 0; j < h; j++) {
690 s1 = src1; s2 = src2; s3 = src3;
694 #if X_BYTE_ORDER == X_BIG_ENDIAN
695 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
696 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1];
697 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2];
698 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3];
700 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
701 dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
702 dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
703 dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
705 dst += 4; s2 += 4; s3 += 4; s1 += 8;
710 #if X_BYTE_ORDER == X_BIG_ENDIAN
711 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
713 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
730 NVMoveDWORDS(CARD32* dest, CARD32* src, int dwords)
732 while (dwords & ~0x03) {
734 *(dest + 1) = *(src + 1);
735 *(dest + 2) = *(src + 2);
736 *(dest + 3) = *(src + 3);
748 *(dest + 1) = *(src + 1);
752 *(dest + 2) = *(src + 2);
755 #if X_BYTE_ORDER == X_BIG_ENDIAN
757 NVMoveDWORDSSwapped(CARD32* dest, CARD8* src, int dwords)
760 *dest++ = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
767 NVCopyData422(unsigned char *src, unsigned char *dst,
768 int srcPitch, int dstPitch,
771 w >>= 1; /* pixels to DWORDS */
773 NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w);
780 NVCopyDataRGB(unsigned char *src, unsigned char *dst,
781 int srcPitch, int dstPitch,
785 #if X_BYTE_ORDER == X_BIG_ENDIAN
786 NVMoveDWORDSSwapped((CARD32*)dst, (CARD8*)src, w);
788 NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w);
800 NVPutImage(ScrnInfoPtr pScrnInfo, short src_x, short src_y,
801 short drw_x, short drw_y,
802 short src_w, short src_h,
803 short drw_w, short drw_h,
806 short width, short height,
813 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
814 NVPtr pNv = NVPTR(pScrnInfo);
815 INT32 xa, xb, ya, yb;
816 unsigned char *dst_start;
817 int newSize, offset, s2offset, s3offset;
818 int srcPitch, srcPitch2, dstPitch;
819 int top, left, right, bottom, npixels, nlines, bpp;
824 /* s2offset, s3offset - byte offsets into U and V plane of the
825 * source where copying starts. Y plane is
826 * done by editing "buf".
827 * offset - byte offset to the first line of the destination.
828 * dst_start - byte address to the first displayed pel.
831 if (pPriv->grabbedByV4L)
834 /* make the compiler happy */
835 s2offset = s3offset = srcPitch2 = 0;
837 if (!pPriv->blitter) {
838 if (src_w > (drw_w << 3))
840 if (src_h > (drw_h << 3))
851 dstBox.x2 = drw_x + drw_w;
853 dstBox.y2 = drw_y + drw_h;
855 if (!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
859 if (!pPriv->blitter) {
860 dstBox.x1 -= pScrnInfo->frameX0;
861 dstBox.x2 -= pScrnInfo->frameX0;
862 dstBox.y1 -= pScrnInfo->frameY0;
863 dstBox.y2 -= pScrnInfo->frameY0;
866 bpp = pScrnInfo->bitsPerPixel >> 3;
871 srcPitch = (width + 3) & ~3; /* of luma */
872 s2offset = srcPitch * height;
873 srcPitch2 = ((width >> 1) + 3) & ~3;
874 s3offset = (srcPitch2 * (height >> 1)) + s2offset;
875 dstPitch = ((width << 1) + 63) & ~63;
879 srcPitch = width << 1;
880 dstPitch = ((width << 1) + 63) & ~63;
883 srcPitch = width << 2;
884 dstPitch = ((width << 2) + 63) & ~63;
887 return BadImplementation;
889 newSize = height * dstPitch / bpp;
891 if (pPriv->doubleBuffer)
894 pPriv->video_mem = NVAllocateOverlayMemory(pScrnInfo, pPriv->video_mem,
896 if (!pPriv->video_mem)
899 offset = pPriv->video_mem->offset;
900 if (pPriv->doubleBuffer) {
901 int mask = 1 << (pPriv->currentBuffer << 2);
904 /* burn the CPU until the next buffer is available */
905 while(nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask);
907 /* overwrite the newest buffer if there's not one free */
908 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
909 if (!pPriv->currentBuffer)
910 offset += (newSize * bpp) >> 1;
914 if (pPriv->currentBuffer)
915 offset += (newSize * bpp) >> 1;
918 dst_start = pPriv->video_mem->map +
919 (offset - (uint32_t)pPriv->video_mem->offset);
921 /* We need to enlarge the copied rectangle by a pixel so the HW
922 * filtering doesn't pick up junk laying outside of the source */
923 left = (xa - 0x00010000) >> 16;
924 if (left < 0) left = 0;
925 top = (ya - 0x00010000) >> 16;
926 if (top < 0) top = 0;
927 right = (xb + 0x0001ffff) >> 16;
928 if (right > width) right = width;
929 bottom = (yb + 0x0001ffff) >> 16;
930 if (bottom > height) bottom = height;
932 if(pPriv->blitter) NVSync(pScrnInfo);
938 npixels = ((right + 1) & ~1) - left;
940 nlines = ((bottom + 1) & ~1) - top;
942 dst_start += (left << 1) + (top * dstPitch);
943 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
946 if (id == FOURCC_I420) {
952 NVCopyData420(buf + (top * srcPitch) + left,
953 buf + s2offset, buf + s3offset,
954 dst_start, srcPitch, srcPitch2,
955 dstPitch, nlines, npixels);
960 npixels = ((right + 1) & ~1) - left;
961 nlines = bottom - top;
964 buf += (top * srcPitch) + left;
965 dst_start += left + (top * dstPitch);
967 NVCopyData422(buf, dst_start, srcPitch,
968 dstPitch, nlines, npixels);
971 npixels = right - left;
972 nlines = bottom - top;
975 buf += (top * srcPitch) + left;
976 dst_start += left + (top * dstPitch);
978 NVCopyDataRGB(buf, dst_start, srcPitch,
979 dstPitch, nlines, npixels);
982 return BadImplementation;
986 if (pPriv->blitter) {
987 NVPutBlitImage(pScrnInfo, offset, id,
991 src_w, src_h, drw_w, drw_h,
994 NVPutOverlayImage(pScrnInfo, offset, id,
998 src_w, src_h, drw_w, drw_h,
1000 pPriv->currentBuffer ^= 1;
1007 * QueryImageAttributes
1010 NVQueryImageAttributes(ScrnInfoPtr pScrnInfo, int id,
1011 unsigned short *w, unsigned short *h,
1012 int *pitches, int *offsets)
1029 size = (*w + 3) & ~3;
1035 tmp = ((*w >> 1) + 3) & ~3;
1037 pitches[1] = pitches[2] = tmp;
1065 /***** Exported offscreen surface stuff ****/
1069 NVAllocSurface(ScrnInfoPtr pScrnInfo, int id,
1070 unsigned short w, unsigned short h,
1071 XF86SurfacePtr surface)
1073 NVPtr pNv = NVPTR(pScrnInfo);
1074 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1077 bpp = pScrnInfo->bitsPerPixel >> 3;
1079 if (pPriv->grabbedByV4L)
1082 if ((w > 2046) || (h > 2046))
1086 pPriv->pitch = ((w << 1) + 63) & ~63;
1087 size = h * pPriv->pitch / bpp;
1089 pPriv->video_mem = NVAllocateOverlayMemory(pScrnInfo,
1092 if (!pPriv->video_mem)
1098 surface->height = h;
1099 surface->pScrn = pScrnInfo;
1100 surface->pitches = &pPriv->pitch;
1101 surface->offsets = &pPriv->offset;
1102 surface->devPrivate.ptr = (pointer)pPriv;
1105 /* grab the video */
1106 NVStopOverlay(pScrnInfo);
1107 pPriv->videoStatus = 0;
1108 REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
1109 pPriv->grabbedByV4L = TRUE;
1115 NVStopSurface(XF86SurfacePtr surface)
1117 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1119 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
1120 NVStopOverlay(surface->pScrn);
1121 pPriv->videoStatus = 0;
1128 NVFreeSurface(XF86SurfacePtr surface)
1130 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1132 if (pPriv->grabbedByV4L) {
1133 NVStopSurface(surface);
1134 NVFreeOverlayMemory(surface->pScrn);
1135 pPriv->grabbedByV4L = FALSE;
1142 NVGetSurfaceAttribute(ScrnInfoPtr pScrnInfo, Atom attribute, INT32 *value)
1144 NVPtr pNv = NVPTR(pScrnInfo);
1145 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1147 return NVGetOverlayPortAttribute(pScrnInfo, attribute,
1148 value, (pointer)pPriv);
1152 NVSetSurfaceAttribute(ScrnInfoPtr pScrnInfo, Atom attribute, INT32 value)
1154 NVPtr pNv = NVPTR(pScrnInfo);
1155 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1157 return NVSetOverlayPortAttribute(pScrnInfo, attribute,
1158 value, (pointer)pPriv);
1162 NVDisplaySurface(XF86SurfacePtr surface,
1163 short src_x, short src_y,
1164 short drw_x, short drw_y,
1165 short src_w, short src_h,
1166 short drw_w, short drw_h,
1167 RegionPtr clipBoxes)
1169 ScrnInfoPtr pScrnInfo = surface->pScrn;
1170 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1171 INT32 xa, xb, ya, yb;
1174 if (!pPriv->grabbedByV4L)
1177 if (src_w > (drw_w << 3))
1179 if (src_h > (drw_h << 3))
1189 dstBox.x2 = drw_x + drw_w;
1191 dstBox.y2 = drw_y + drw_h;
1193 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1194 surface->width, surface->height))
1197 dstBox.x1 -= pScrnInfo->frameX0;
1198 dstBox.x2 -= pScrnInfo->frameX0;
1199 dstBox.y1 -= pScrnInfo->frameY0;
1200 dstBox.y2 -= pScrnInfo->frameY0;
1202 pPriv->currentBuffer = 0;
1204 NVPutOverlayImage(pScrnInfo, surface->offsets[0], surface->id,
1205 surface->pitches[0], &dstBox, xa, ya, xb, yb,
1206 surface->width, surface->height, src_w, src_h,
1207 drw_w, drw_h, clipBoxes);
1212 static XF86VideoAdaptorPtr
1213 NVSetupBlitVideo (ScreenPtr pScreen)
1215 ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum];
1216 NVPtr pNv = NVPTR(pScrnInfo);
1217 XF86VideoAdaptorPtr adapt;
1218 NVPortPrivPtr pPriv;
1221 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1222 sizeof(NVPortPrivRec) +
1223 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
1227 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1229 adapt->name = "NV Video Blitter";
1230 adapt->nEncodings = 1;
1231 adapt->pEncodings = &DummyEncoding;
1232 adapt->nFormats = NUM_FORMATS_ALL;
1233 adapt->pFormats = NVFormats;
1234 adapt->nPorts = NUM_BLIT_PORTS;
1235 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1237 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
1238 for(i = 0; i < NUM_BLIT_PORTS; i++)
1239 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1241 if(pNv->WaitVSyncPossible) {
1242 adapt->pAttributes = NVBlitAttributes;
1243 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
1245 adapt->pAttributes = NULL;
1246 adapt->nAttributes = 0;
1249 adapt->pImages = NVImages;
1250 adapt->nImages = NUM_IMAGES_ALL;
1251 adapt->PutVideo = NULL;
1252 adapt->PutStill = NULL;
1253 adapt->GetVideo = NULL;
1254 adapt->GetStill = NULL;
1255 adapt->StopVideo = NVStopBlitVideo;
1256 adapt->SetPortAttribute = NVSetBlitPortAttribute;
1257 adapt->GetPortAttribute = NVGetBlitPortAttribute;
1258 adapt->QueryBestSize = NVQueryBestSize;
1259 adapt->PutImage = NVPutImage;
1260 adapt->QueryImageAttributes = NVQueryImageAttributes;
1262 pPriv->videoStatus = 0;
1263 pPriv->grabbedByV4L = FALSE;
1264 pPriv->blitter = TRUE;
1265 pPriv->doubleBuffer = FALSE;
1266 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1268 pNv->blitAdaptor = adapt;
1269 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
1274 static XF86VideoAdaptorPtr
1275 NV10SetupOverlayVideo(ScreenPtr pScreen)
1277 ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum];
1278 NVPtr pNv = NVPTR(pScrnInfo);
1279 XF86VideoAdaptorPtr adapt;
1280 NVPortPrivPtr pPriv;
1282 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1283 sizeof(NVPortPrivRec) +
1284 sizeof(DevUnion)))) {
1288 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1289 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
1290 adapt->name = "NV Video Overlay";
1291 adapt->nEncodings = 1;
1292 adapt->pEncodings = &DummyEncoding;
1293 adapt->nFormats = NUM_FORMATS_ALL;
1294 adapt->pFormats = NVFormats;
1296 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1298 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
1299 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
1301 adapt->pAttributes = NVOverlayAttributes;
1302 adapt->nAttributes = NUM_OVERLAY_ATTRIBUTES;
1303 adapt->pImages = NVImages;
1304 adapt->nImages = NUM_IMAGES_YUV;
1305 adapt->PutVideo = NULL;
1306 adapt->PutStill = NULL;
1307 adapt->GetVideo = NULL;
1308 adapt->GetStill = NULL;
1309 adapt->StopVideo = NVStopOverlayVideo;
1310 adapt->SetPortAttribute = NVSetOverlayPortAttribute;
1311 adapt->GetPortAttribute = NVGetOverlayPortAttribute;
1312 adapt->QueryBestSize = NVQueryBestSize;
1313 adapt->PutImage = NVPutImage;
1314 adapt->QueryImageAttributes = NVQueryImageAttributes;
1316 pPriv->videoStatus = 0;
1317 pPriv->currentBuffer = 0;
1318 pPriv->grabbedByV4L = FALSE;
1319 pPriv->blitter = FALSE;
1321 NVSetPortDefaults (pScrnInfo, pPriv);
1323 /* gotta uninit this someplace */
1324 REGION_NULL(pScreen, &pPriv->clip);
1326 pNv->overlayAdaptor = adapt;
1328 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
1329 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
1330 xvContrast = MAKE_ATOM("XV_CONTRAST");
1331 xvColorKey = MAKE_ATOM("XV_COLORKEY");
1332 xvSaturation = MAKE_ATOM("XV_SATURATION");
1333 xvHue = MAKE_ATOM("XV_HUE");
1334 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
1335 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
1336 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
1338 NVResetVideo(pScrnInfo);
1343 XF86OffscreenImageRec NVOffscreenImages[2] = {
1346 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1351 NVGetSurfaceAttribute,
1352 NVSetSurfaceAttribute,
1354 NUM_OVERLAY_ATTRIBUTES - 1,
1355 &NVOverlayAttributes[1]
1359 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1364 NVGetSurfaceAttribute,
1365 NVSetSurfaceAttribute,
1367 NUM_OVERLAY_ATTRIBUTES - 1,
1368 &NVOverlayAttributes[1]
1373 NVInitOffscreenImages (ScreenPtr pScreen)
1375 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
1379 NVChipsetHasOverlay(NVPtr pNv)
1381 switch (pNv->Architecture) {
1387 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
1397 static XF86VideoAdaptorPtr
1398 NVSetupOverlayVideo(ScreenPtr pScreen)
1400 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1401 XF86VideoAdaptorPtr overlayAdaptor = NULL;
1402 NVPtr pNv = NVPTR(pScrn);
1404 if (!NVChipsetHasOverlay(pNv))
1407 /*XXX: Do we still want to provide the overlay anyway, but make the
1408 * blit adaptor the default if composite is enabled?
1411 if (!noCompositeExtension) {
1412 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1413 "XV: Video overlay not available, composite enabled\n");
1418 overlayAdaptor = NV10SetupOverlayVideo(pScreen);
1420 NVInitOffscreenImages(pScreen);
1422 return overlayAdaptor;
1425 void NVInitVideo (ScreenPtr pScreen)
1427 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1428 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
1429 XF86VideoAdaptorPtr overlayAdaptor = NULL;
1430 XF86VideoAdaptorPtr blitAdaptor = NULL;
1433 if (pScrn->bitsPerPixel == 8)
1436 overlayAdaptor = NVSetupOverlayVideo(pScreen);
1437 blitAdaptor = NVSetupBlitVideo(pScreen);
1439 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
1440 if(blitAdaptor || overlayAdaptor) {
1441 int size = num_adaptors;
1443 if(overlayAdaptor) size++;
1444 if(blitAdaptor) size++;
1446 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
1449 memcpy(newAdaptors, adaptors, num_adaptors *
1450 sizeof(XF86VideoAdaptorPtr));
1453 if(overlayAdaptor) {
1454 newAdaptors[num_adaptors] = overlayAdaptor;
1459 newAdaptors[num_adaptors] = blitAdaptor;
1463 adaptors = newAdaptors;
1468 xf86XVScreenInit(pScreen, adaptors, num_adaptors);