1 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_video.c,v 1.23 2004/03/20 22:07:06 mvojkovi Exp $ */
4 #include "xf86_OSproc.h"
5 #include "xf86Resources.h"
7 #include "xf86_ansic.h"
10 #include "xf86PciInfo.h"
12 #include "xf86fbman.h"
13 #include "regionstr.h"
16 #include <X11/extensions/Xv.h>
19 #include "dixstruct.h"
22 #include "nv_include.h"
25 #define OFF_DELAY 500 /* milliseconds */
26 #define FREE_DELAY 5000
28 #define OFF_TIMER 0x01
29 #define FREE_TIMER 0x02
30 #define CLIENT_VIDEO_ON 0x04
32 #define TIMER_MASK (OFF_TIMER | FREE_TIMER)
34 #define NUM_BLIT_PORTS 32
36 typedef struct _NVPortPrivRec {
43 Bool autopaintColorKey;
55 } NVPortPrivRec, *NVPortPrivPtr;
58 static XF86VideoAdaptorPtr NVSetupOverlayVideo(ScreenPtr);
59 static XF86VideoAdaptorPtr NVSetupBlitVideo(ScreenPtr);
61 static void NVStopOverlay (ScrnInfoPtr);
62 static void NVPutOverlayImage(ScrnInfoPtr pScrnInfo,
67 int x1, int y1, int x2, int y2,
68 short width, short height,
69 short src_w, short src_h,
70 short dst_w, short dst_h,
73 static int NVSetOverlayPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
74 static int NVGetOverlayPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
75 static int NVSetBlitPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
76 static int NVGetBlitPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
79 static void NVStopOverlayVideo(ScrnInfoPtr, pointer, Bool);
80 static void NVStopBlitVideo(ScrnInfoPtr, pointer, Bool);
83 static int NVPutImage( ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr);
85 static int NVPutImage( ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer);
88 static void NVQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer);
89 static int NVQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *);
91 static void NVVideoTimerCallback(ScrnInfoPtr, Time);
93 static void NVInitOffscreenImages (ScreenPtr pScreen);
96 #define GET_OVERLAY_PRIVATE(pNv) \
97 (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr)
99 #define GET_BLIT_PRIVATE(pNv) \
100 (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr)
102 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
104 static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
105 xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
106 xvITURBT709, xvSyncToVBlank;
108 /* client libraries expect an encoding */
109 static XF86VideoEncodingRec DummyEncoding =
117 #define NUM_FORMATS_ALL 6
119 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
121 {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
122 {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
125 #define NUM_OVERLAY_ATTRIBUTES 9
126 XF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] =
128 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
129 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
130 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
131 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
132 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
133 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
134 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
135 {XvSettable | XvGettable, 0, 360, "XV_HUE"},
136 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"}
139 #define NUM_BLIT_ATTRIBUTES 2
140 XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
142 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
143 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
147 #define NUM_IMAGES_YUV 4
148 #define NUM_IMAGES_ALL 5
150 #define FOURCC_RGB 0x0000003
151 #define XVIMAGE_RGB \
156 { 0x03, 0x00, 0x00, 0x00, \
157 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
161 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
166 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}, \
170 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
180 NVSetPortDefaults (ScrnInfoPtr pScrnInfo, NVPortPrivPtr pPriv)
182 NVPtr pNv = NVPTR(pScrnInfo);
184 pPriv->brightness = 0;
185 pPriv->contrast = 4096;
186 pPriv->saturation = 4096;
188 pPriv->colorKey = pNv->videoKey;
189 pPriv->autopaintColorKey = TRUE;
190 pPriv->doubleBuffer = TRUE;
191 pPriv->iturbt_709 = FALSE;
196 NVResetVideo (ScrnInfoPtr pScrnInfo)
198 NVPtr pNv = NVPTR(pScrnInfo);
199 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
200 int satSine, satCosine;
203 angle = (double)pPriv->hue * 3.1415927 / 180.0;
205 satSine = pPriv->saturation * sin(angle);
208 satCosine = pPriv->saturation * cos(angle);
209 if (satCosine < -1024)
212 pNv->PMC[0x8910/4] = (pPriv->brightness << 16) | pPriv->contrast;
213 pNv->PMC[0x8914/4] = (pPriv->brightness << 16) | pPriv->contrast;
214 pNv->PMC[0x8918/4] = (satSine << 16) | (satCosine & 0xffff);
215 pNv->PMC[0x891C/4] = (satSine << 16) | (satCosine & 0xffff);
216 pNv->PMC[0x8b00/4] = pPriv->colorKey;
222 NVStopOverlay (ScrnInfoPtr pScrnInfo)
224 NVPtr pNv = NVPTR(pScrnInfo);
226 pNv->PMC[0x00008704/4] = 1;
230 NVAllocateOverlayMemory(
236 FBLinearPtr new_linear;
239 if(linear->size >= size)
242 if(xf86ResizeOffscreenLinear(linear, size))
245 xf86FreeOffscreenLinear(linear);
248 pScreen = screenInfo.screens[pScrn->scrnIndex];
250 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32,
256 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 32,
262 xf86PurgeUnlockedOffscreenAreas(pScreen);
263 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32,
270 static void NVFreeOverlayMemory(ScrnInfoPtr pScrnInfo)
272 NVPtr pNv = NVPTR(pScrnInfo);
273 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
276 xf86FreeOffscreenLinear(pPriv->linear);
277 pPriv->linear = NULL;
282 static void NVFreeBlitMemory(ScrnInfoPtr pScrnInfo)
284 NVPtr pNv = NVPTR(pScrnInfo);
285 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
288 xf86FreeOffscreenLinear(pPriv->linear);
289 pPriv->linear = NULL;
294 void NVInitVideo (ScreenPtr pScreen)
296 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
297 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
298 XF86VideoAdaptorPtr overlayAdaptor = NULL;
299 XF86VideoAdaptorPtr blitAdaptor = NULL;
300 NVPtr pNv = NVPTR(pScrn);
303 if((pScrn->bitsPerPixel != 8) && (pNv->Architecture >= NV_ARCH_10) &&
304 ((pNv->Architecture <= NV_ARCH_30) ||
305 ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)))
307 overlayAdaptor = NVSetupOverlayVideo(pScreen);
310 NVInitOffscreenImages(pScreen);
313 if((pScrn->bitsPerPixel != 8) && !pNv->NoAccel)
314 blitAdaptor = NVSetupBlitVideo(pScreen);
316 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
318 if(blitAdaptor || overlayAdaptor) {
319 int size = num_adaptors;
321 if(overlayAdaptor) size++;
322 if(blitAdaptor) size++;
324 if((newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr*)))) {
326 memcpy(newAdaptors, adaptors,
327 num_adaptors * sizeof(XF86VideoAdaptorPtr));
330 newAdaptors[num_adaptors] = overlayAdaptor;
334 newAdaptors[num_adaptors] = blitAdaptor;
337 adaptors = newAdaptors;
342 xf86XVScreenInit(pScreen, adaptors, num_adaptors);
349 static XF86VideoAdaptorPtr
350 NVSetupBlitVideo (ScreenPtr pScreen)
352 ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum];
353 NVPtr pNv = NVPTR(pScrnInfo);
354 XF86VideoAdaptorPtr adapt;
358 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
359 sizeof(NVPortPrivRec) +
360 (sizeof(DevUnion) * NUM_BLIT_PORTS))))
365 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
367 adapt->name = "NV Video Blitter";
368 adapt->nEncodings = 1;
369 adapt->pEncodings = &DummyEncoding;
370 adapt->nFormats = NUM_FORMATS_ALL;
371 adapt->pFormats = NVFormats;
372 adapt->nPorts = NUM_BLIT_PORTS;
373 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
375 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
376 for(i = 0; i < NUM_BLIT_PORTS; i++)
377 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
379 if(pNv->WaitVSyncPossible) {
380 adapt->pAttributes = NVBlitAttributes;
381 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
383 adapt->pAttributes = NULL;
384 adapt->nAttributes = 0;
386 adapt->pImages = NVImages;
387 adapt->nImages = NUM_IMAGES_ALL;
388 adapt->PutVideo = NULL;
389 adapt->PutStill = NULL;
390 adapt->GetVideo = NULL;
391 adapt->GetStill = NULL;
392 adapt->StopVideo = NVStopBlitVideo;
393 adapt->SetPortAttribute = NVSetBlitPortAttribute;
394 adapt->GetPortAttribute = NVGetBlitPortAttribute;
395 adapt->QueryBestSize = NVQueryBestSize;
396 adapt->PutImage = NVPutImage;
397 adapt->QueryImageAttributes = NVQueryImageAttributes;
399 pPriv->videoStatus = 0;
400 pPriv->grabbedByV4L = FALSE;
401 pPriv->blitter = TRUE;
402 pPriv->doubleBuffer = FALSE;
403 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
405 pNv->blitAdaptor = adapt;
407 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
412 static XF86VideoAdaptorPtr
413 NVSetupOverlayVideo (ScreenPtr pScreen)
415 ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum];
416 NVPtr pNv = NVPTR(pScrnInfo);
417 XF86VideoAdaptorPtr adapt;
420 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
421 sizeof(NVPortPrivRec) +
427 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
428 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
429 adapt->name = "NV Video Overlay";
430 adapt->nEncodings = 1;
431 adapt->pEncodings = &DummyEncoding;
432 adapt->nFormats = NUM_FORMATS_ALL;
433 adapt->pFormats = NVFormats;
435 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
436 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
437 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
438 adapt->pAttributes = NVOverlayAttributes;
439 adapt->nAttributes = NUM_OVERLAY_ATTRIBUTES;
440 adapt->pImages = NVImages;
441 adapt->nImages = NUM_IMAGES_YUV;
442 adapt->PutVideo = NULL;
443 adapt->PutStill = NULL;
444 adapt->GetVideo = NULL;
445 adapt->GetStill = NULL;
446 adapt->StopVideo = NVStopOverlayVideo;
447 adapt->SetPortAttribute = NVSetOverlayPortAttribute;
448 adapt->GetPortAttribute = NVGetOverlayPortAttribute;
449 adapt->QueryBestSize = NVQueryBestSize;
450 adapt->PutImage = NVPutImage;
451 adapt->QueryImageAttributes = NVQueryImageAttributes;
453 pPriv->videoStatus = 0;
454 pPriv->currentBuffer = 0;
455 pPriv->grabbedByV4L = FALSE;
456 pPriv->blitter = FALSE;
458 NVSetPortDefaults (pScrnInfo, pPriv);
460 /* gotta uninit this someplace */
461 REGION_NULL(pScreen, &pPriv->clip);
463 pNv->overlayAdaptor = adapt;
465 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
466 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
467 xvContrast = MAKE_ATOM("XV_CONTRAST");
468 xvColorKey = MAKE_ATOM("XV_COLORKEY");
469 xvSaturation = MAKE_ATOM("XV_SATURATION");
470 xvHue = MAKE_ATOM("XV_HUE");
471 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
472 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
473 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
475 NVResetVideo(pScrnInfo);
482 ScrnInfoPtr pScrnInfo,
500 NVPtr pNv = NVPTR(pScrnInfo);
501 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
502 int buffer = pPriv->currentBuffer;
504 /* paint the color key */
505 if(pPriv->autopaintColorKey &&
506 (pPriv->grabbedByV4L ||
507 !REGION_EQUAL(pScrnInfo->pScreen, &pPriv->clip, clipBoxes)))
509 /* we always paint V4L's color key */
510 if(!pPriv->grabbedByV4L)
511 REGION_COPY(pScrnInfo->pScreen, &pPriv->clip, clipBoxes);
512 xf86XVFillKeyHelper(pScrnInfo->pScreen, pPriv->colorKey, clipBoxes);
515 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
521 pNv->PMC[(0x8900/4) + buffer] = offset;
522 pNv->PMC[(0x8928/4) + buffer] = (height << 16) | width;
523 pNv->PMC[(0x8930/4) + buffer] = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
524 pNv->PMC[(0x8938/4) + buffer] = (src_w << 20) / drw_w;
525 pNv->PMC[(0x8940/4) + buffer] = (src_h << 20) / drw_h;
526 pNv->PMC[(0x8948/4) + buffer] = (dstBox->y1 << 16) | dstBox->x1;
527 pNv->PMC[(0x8950/4) + buffer] = ((dstBox->y2 - dstBox->y1) << 16) |
528 (dstBox->x2 - dstBox->x1);
530 dstPitch |= 1 << 20; /* use color key */
532 if(id != FOURCC_UYVY)
534 if(pPriv->iturbt_709)
537 pNv->PMC[(0x8958/4) + buffer] = dstPitch;
538 pNv->PMC[0x00008704/4] = 0;
539 pNv->PMC[0x8700/4] = 1 << (buffer << 2);
541 pPriv->videoStatus = CLIENT_VIDEO_ON;
548 ScrnInfoPtr pScrnInfo,
566 NVPtr pNv = NVPTR(pScrnInfo);
567 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
568 BoxPtr pbox = REGION_RECTS(clipBoxes);
569 int nbox = REGION_NUM_RECTS(clipBoxes);
570 CARD32 dsdx, dtdy, size, point, srcpoint, format;
572 dsdx = (src_w << 20) / drw_w;
573 dtdy = (src_h << 20) / drw_h;
575 size = ((dstBox->y2 - dstBox->y1) << 16) | (dstBox->x2 - dstBox->x1);
576 point = (dstBox->y1 << 16) | dstBox->x1;
578 dstPitch |= (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER << 16) |
579 (STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR << 24);
581 srcpoint = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
585 format = STRETCH_BLIT_FORMAT_X8R8G8B8;
588 format = STRETCH_BLIT_FORMAT_UYVY;
591 format = STRETCH_BLIT_FORMAT_YUYV;
595 if(pNv->CurrentLayout.depth == 15) {
596 NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_FORMAT, 1);
597 NVDmaNext (pNv, SURFACE_FORMAT_X1R5G5B5);
600 if(pPriv->SyncToVBlank) {
605 if(pNv->BlendingPossible) {
606 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_FORMAT, 2);
607 NVDmaNext (pNv, format);
608 NVDmaNext (pNv, STRETCH_BLIT_OPERATION_COPY);
610 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_FORMAT, 1);
611 NVDmaNext (pNv, format);
615 NVDmaStart(pNv, NvSubRectangle, RECT_SOLID_COLOR, 1);
618 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_CLIP_POINT, 6);
619 NVDmaNext (pNv, (pbox->y1 << 16) | pbox->x1);
620 NVDmaNext (pNv, ((pbox->y2 - pbox->y1) << 16) | (pbox->x2 - pbox->x1));
621 NVDmaNext (pNv, point);
622 NVDmaNext (pNv, size);
623 NVDmaNext (pNv, dsdx);
624 NVDmaNext (pNv, dtdy);
626 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_SRC_SIZE, 4);
627 NVDmaNext (pNv, (height << 16) | width);
628 NVDmaNext (pNv, dstPitch);
629 NVDmaNext (pNv, offset);
630 NVDmaNext (pNv, srcpoint);
634 if(pNv->CurrentLayout.depth == 15) {
635 NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_FORMAT, 1);
636 NVDmaNext (pNv, SURFACE_FORMAT_R5G6B5);
640 SET_SYNC_FLAG(pNv->AccelInfoRec);
642 pPriv->videoStatus = FREE_TIMER;
643 pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
644 pNv->VideoTimerCallback = NVVideoTimerCallback;
650 static void NVStopOverlayVideo
652 ScrnInfoPtr pScrnInfo,
657 NVPtr pNv = NVPTR(pScrnInfo);
658 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
660 if(pPriv->grabbedByV4L) return;
662 REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
665 if(pPriv->videoStatus & CLIENT_VIDEO_ON)
666 NVStopOverlay(pScrnInfo);
667 NVFreeOverlayMemory(pScrnInfo);
668 pPriv->videoStatus = 0;
670 if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
671 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
672 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
673 pNv->VideoTimerCallback = NVVideoTimerCallback;
678 static void NVStopBlitVideo
680 ScrnInfoPtr pScrnInfo,
687 static int NVSetOverlayPortAttribute
689 ScrnInfoPtr pScrnInfo,
695 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
697 if (attribute == xvBrightness)
699 if ((value < -512) || (value > 512))
701 pPriv->brightness = value;
703 else if (attribute == xvDoubleBuffer)
705 if ((value < 0) || (value > 1))
707 pPriv->doubleBuffer = value;
709 else if (attribute == xvContrast)
711 if ((value < 0) || (value > 8191))
713 pPriv->contrast = value;
715 else if (attribute == xvHue)
722 else if (attribute == xvSaturation)
724 if ((value < 0) || (value > 8191))
726 pPriv->saturation = value;
728 else if (attribute == xvColorKey)
730 pPriv->colorKey = value;
731 REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
733 else if (attribute == xvAutopaintColorKey)
735 if ((value < 0) || (value > 1))
737 pPriv->autopaintColorKey = value;
739 else if (attribute == xvITURBT709)
741 if ((value < 0) || (value > 1))
743 pPriv->iturbt_709 = value;
745 else if (attribute == xvSetDefaults)
747 NVSetPortDefaults(pScrnInfo, pPriv);
752 NVResetVideo(pScrnInfo);
757 static int NVGetOverlayPortAttribute
759 ScrnInfoPtr pScrnInfo,
765 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
767 if (attribute == xvBrightness)
768 *value = pPriv->brightness;
769 else if (attribute == xvDoubleBuffer)
770 *value = (pPriv->doubleBuffer) ? 1 : 0;
771 else if (attribute == xvContrast)
772 *value = pPriv->contrast;
773 else if (attribute == xvSaturation)
774 *value = pPriv->saturation;
775 else if (attribute == xvHue)
777 else if (attribute == xvColorKey)
778 *value = pPriv->colorKey;
779 else if (attribute == xvAutopaintColorKey)
780 *value = (pPriv->autopaintColorKey) ? 1 : 0;
781 else if (attribute == xvITURBT709)
782 *value = (pPriv->iturbt_709) ? 1 : 0;
789 static int NVSetBlitPortAttribute
791 ScrnInfoPtr pScrnInfo,
797 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
798 NVPtr pNv = NVPTR(pScrnInfo);
800 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
801 if ((value < 0) || (value > 1))
803 pPriv->SyncToVBlank = value;
805 if (attribute == xvSetDefaults) {
806 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
813 static int NVGetBlitPortAttribute
815 ScrnInfoPtr pScrnInfo,
821 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
823 if(attribute == xvSyncToVBlank)
824 *value = (pPriv->SyncToVBlank) ? 1 : 0;
835 static void NVQueryBestSize
837 ScrnInfoPtr pScrnInfo,
848 if(vid_w > (drw_w << 3))
850 if(vid_h > (drw_h << 3))
857 static void NVCopyData420
876 for(j = 0; j < h; j++) {
878 s1 = src1; s2 = src2; s3 = src3;
881 #if X_BYTE_ORDER == X_BIG_ENDIAN
882 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
883 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1];
884 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2];
885 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3];
887 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
888 dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
889 dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
890 dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
892 dst += 4; s2 += 4; s3 += 4; s1 += 8;
897 #if X_BYTE_ORDER == X_BIG_ENDIAN
898 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
900 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
916 static void NVMoveDWORDS(
921 while(dwords & ~0x03) {
923 *(dest + 1) = *(src + 1);
924 *(dest + 2) = *(src + 2);
925 *(dest + 3) = *(src + 3);
932 if(dwords == 1) return;
933 *(dest + 1) = *(src + 1);
934 if(dwords == 2) return;
935 *(dest + 2) = *(src + 2);
938 #if X_BYTE_ORDER == X_BIG_ENDIAN
939 static void NVMoveDWORDSSwapped(
945 *dest++ = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
951 static void NVCopyData422
961 w >>= 1; /* pixels to DWORDS */
963 NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w);
969 static void NVCopyDataRGB
980 #if X_BYTE_ORDER == X_BIG_ENDIAN
981 NVMoveDWORDSSwapped((CARD32*)dst, (CARD8*)src, w);
983 NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w);
994 static int NVPutImage
996 ScrnInfoPtr pScrnInfo,
1010 RegionPtr clipBoxes,
1012 #if HAVE_XV_DRAWABLE
1017 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1018 NVPtr pNv = NVPTR(pScrnInfo);
1019 INT32 xa, xb, ya, yb;
1020 unsigned char *dst_start;
1021 int newSize, offset, s2offset, s3offset;
1022 int srcPitch, srcPitch2, dstPitch;
1023 int top, left, right, bottom, npixels, nlines, bpp;
1029 * s2offset, s3offset - byte offsets into U and V plane of the
1030 * source where copying starts. Y plane is
1031 * done by editing "buf".
1033 * offset - byte offset to the first line of the destination.
1035 * dst_start - byte address to the first displayed pel.
1039 if(pPriv->grabbedByV4L) return Success;
1041 /* make the compiler happy */
1042 s2offset = s3offset = srcPitch2 = 0;
1044 if(!pPriv->blitter) {
1045 if(src_w > (drw_w << 3))
1047 if(src_h > (drw_h << 3))
1058 dstBox.x2 = drw_x + drw_w;
1060 dstBox.y2 = drw_y + drw_h;
1062 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1066 if(!pPriv->blitter) {
1067 dstBox.x1 -= pScrnInfo->frameX0;
1068 dstBox.x2 -= pScrnInfo->frameX0;
1069 dstBox.y1 -= pScrnInfo->frameY0;
1070 dstBox.y2 -= pScrnInfo->frameY0;
1073 bpp = pScrnInfo->bitsPerPixel >> 3;
1078 srcPitch = (width + 3) & ~3; /* of luma */
1079 s2offset = srcPitch * height;
1080 srcPitch2 = ((width >> 1) + 3) & ~3;
1081 s3offset = (srcPitch2 * (height >> 1)) + s2offset;
1082 dstPitch = ((width << 1) + 63) & ~63;
1086 srcPitch = width << 1;
1087 dstPitch = ((width << 1) + 63) & ~63;
1090 srcPitch = width << 2;
1091 dstPitch = ((width << 2) + 63) & ~63;
1094 return BadImplementation;
1097 newSize = height * dstPitch / bpp;
1099 if(pPriv->doubleBuffer)
1102 pPriv->linear = NVAllocateOverlayMemory(pScrnInfo,
1106 if(!pPriv->linear) return BadAlloc;
1108 offset = pPriv->linear->offset * bpp;
1110 if(pPriv->doubleBuffer) {
1111 int mask = 1 << (pPriv->currentBuffer << 2);
1114 /* burn the CPU until the next buffer is available */
1115 while(pNv->PMC[0x00008700/4] & mask);
1117 /* overwrite the newest buffer if there's not one free */
1118 if(pNv->PMC[0x00008700/4] & mask) {
1119 if(!pPriv->currentBuffer)
1120 offset += (newSize * bpp) >> 1;
1124 if(pPriv->currentBuffer)
1125 offset += (newSize * bpp) >> 1;
1128 dst_start = pNv->FbStart + offset;
1130 /* We need to enlarge the copied rectangle by a pixel so the HW
1131 filtering doesn't pick up junk laying outside of the source */
1133 left = (xa - 0x00010000) >> 16;
1134 if(left < 0) left = 0;
1135 top = (ya - 0x00010000) >> 16;
1136 if(top < 0) top = 0;
1137 right = (xb + 0x0001ffff) >> 16;
1138 if(right > width) right = width;
1139 bottom = (yb + 0x0001ffff) >> 16;
1140 if(bottom > height) bottom = height;
1142 if(pPriv->blitter) NVSync(pScrnInfo);
1148 npixels = ((right + 1) & ~1) - left;
1150 nlines = ((bottom + 1) & ~1) - top;
1152 dst_start += (left << 1) + (top * dstPitch);
1153 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1156 if(id == FOURCC_I420) {
1158 s2offset = s3offset;
1161 NVCopyData420(buf + (top * srcPitch) + left,
1162 buf + s2offset, buf + s3offset,
1163 dst_start, srcPitch, srcPitch2,
1164 dstPitch, nlines, npixels);
1169 npixels = ((right + 1) & ~1) - left;
1170 nlines = bottom - top;
1173 buf += (top * srcPitch) + left;
1174 dst_start += left + (top * dstPitch);
1176 NVCopyData422(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
1179 npixels = right - left;
1180 nlines = bottom - top;
1183 buf += (top * srcPitch) + left;
1184 dst_start += left + (top * dstPitch);
1186 NVCopyDataRGB(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
1189 return BadImplementation;
1193 if(pPriv->blitter) {
1194 NVPutBlitImage(pScrnInfo, offset, id, dstPitch, &dstBox,
1196 width, height, src_w, src_h, drw_w, drw_h,
1199 NVPutOverlayImage(pScrnInfo, offset, id, dstPitch, &dstBox,
1201 width, height, src_w, src_h, drw_w, drw_h,
1203 pPriv->currentBuffer ^= 1;
1210 * QueryImageAttributes
1212 static int NVQueryImageAttributes
1214 ScrnInfoPtr pScrnInfo,
1238 size = (*w + 3) & ~3;
1244 tmp = ((*w >> 1) + 3) & ~3;
1246 pitches[1] = pitches[2] = tmp;
1273 static void NVVideoTimerCallback
1275 ScrnInfoPtr pScrnInfo,
1279 NVPtr pNv = NVPTR(pScrnInfo);
1280 NVPortPrivPtr pOverPriv = NULL;
1281 NVPortPrivPtr pBlitPriv = NULL;
1282 Bool needCallback = FALSE;
1284 if(!pScrnInfo->vtSema) return;
1286 if(pNv->overlayAdaptor) {
1287 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
1288 if(!pOverPriv->videoStatus)
1292 if(pNv->blitAdaptor) {
1293 pBlitPriv = GET_BLIT_PRIVATE(pNv);
1294 if(!pBlitPriv->videoStatus)
1299 if(pOverPriv->videoTime < currentTime) {
1300 if(pOverPriv->videoStatus & OFF_TIMER) {
1301 NVStopOverlay(pScrnInfo);
1302 pOverPriv->videoStatus = FREE_TIMER;
1303 pOverPriv->videoTime = currentTime + FREE_DELAY;
1304 needCallback = TRUE;
1306 if(pOverPriv->videoStatus & FREE_TIMER) {
1307 NVFreeOverlayMemory(pScrnInfo);
1308 pOverPriv->videoStatus = 0;
1311 needCallback = TRUE;
1316 if(pBlitPriv->videoTime < currentTime) {
1317 NVFreeBlitMemory(pScrnInfo);
1318 pBlitPriv->videoStatus = 0;
1320 needCallback = TRUE;
1324 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
1328 /***** Exported offscreen surface stuff ****/
1333 ScrnInfoPtr pScrnInfo,
1337 XF86SurfacePtr surface
1340 NVPtr pNv = NVPTR(pScrnInfo);
1341 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1344 bpp = pScrnInfo->bitsPerPixel >> 3;
1346 if(pPriv->grabbedByV4L) return BadAlloc;
1348 if((w > 2046) || (h > 2046)) return BadValue;
1351 pPriv->pitch = ((w << 1) + 63) & ~63;
1352 size = h * pPriv->pitch / bpp;
1354 pPriv->linear = NVAllocateOverlayMemory(pScrnInfo, pPriv->linear,
1357 if(!pPriv->linear) return BadAlloc;
1359 pPriv->offset = pPriv->linear->offset * bpp;
1362 surface->height = h;
1363 surface->pScrn = pScrnInfo;
1364 surface->pitches = &pPriv->pitch;
1365 surface->offsets = &pPriv->offset;
1366 surface->devPrivate.ptr = (pointer)pPriv;
1369 /* grab the video */
1370 NVStopOverlay(pScrnInfo);
1371 pPriv->videoStatus = 0;
1372 REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
1373 pPriv->grabbedByV4L = TRUE;
1379 NVStopSurface (XF86SurfacePtr surface)
1381 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1383 if(pPriv->grabbedByV4L && pPriv->videoStatus) {
1384 NVStopOverlay(surface->pScrn);
1385 pPriv->videoStatus = 0;
1392 NVFreeSurface (XF86SurfacePtr surface)
1394 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1396 if(pPriv->grabbedByV4L) {
1397 NVStopSurface(surface);
1398 NVFreeOverlayMemory(surface->pScrn);
1399 pPriv->grabbedByV4L = FALSE;
1406 NVGetSurfaceAttribute (
1407 ScrnInfoPtr pScrnInfo,
1412 NVPtr pNv = NVPTR(pScrnInfo);
1413 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1415 return NVGetOverlayPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv);
1419 NVSetSurfaceAttribute(
1420 ScrnInfoPtr pScrnInfo,
1425 NVPtr pNv = NVPTR(pScrnInfo);
1426 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1428 return NVSetOverlayPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv);
1433 XF86SurfacePtr surface,
1434 short src_x, short src_y,
1435 short drw_x, short drw_y,
1436 short src_w, short src_h,
1437 short drw_w, short drw_h,
1441 ScrnInfoPtr pScrnInfo = surface->pScrn;
1442 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1443 INT32 xa, xb, ya, yb;
1446 if(!pPriv->grabbedByV4L) return Success;
1448 if(src_w > (drw_w << 3))
1450 if(src_h > (drw_h << 3))
1460 dstBox.x2 = drw_x + drw_w;
1462 dstBox.y2 = drw_y + drw_h;
1464 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1465 surface->width, surface->height))
1470 dstBox.x1 -= pScrnInfo->frameX0;
1471 dstBox.x2 -= pScrnInfo->frameX0;
1472 dstBox.y1 -= pScrnInfo->frameY0;
1473 dstBox.y2 -= pScrnInfo->frameY0;
1475 pPriv->currentBuffer = 0;
1477 NVPutOverlayImage (pScrnInfo, surface->offsets[0], surface->id,
1478 surface->pitches[0], &dstBox, xa, ya, xb, yb,
1479 surface->width, surface->height, src_w, src_h,
1480 drw_w, drw_h, clipBoxes);
1485 XF86OffscreenImageRec NVOffscreenImages[2] =
1489 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1494 NVGetSurfaceAttribute,
1495 NVSetSurfaceAttribute,
1497 NUM_OVERLAY_ATTRIBUTES - 1,
1498 &NVOverlayAttributes[1]
1502 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1507 NVGetSurfaceAttribute,
1508 NVSetSurfaceAttribute,
1510 NUM_OVERLAY_ATTRIBUTES - 1,
1511 &NVOverlayAttributes[1]
1516 NVInitOffscreenImages (ScreenPtr pScreen)
1518 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);