1 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_video.c,v 1.19 2003/09/01 20:54:26 mvojkovi Exp $ */
4 #include "xf86_OSproc.h"
5 #include "xf86Resources.h"
6 #include "xf86_ansic.h"
8 #include "xf86PciInfo.h"
10 #include "xf86fbman.h"
11 #include "regionstr.h"
17 #include "dixstruct.h"
20 #include "nv_include.h"
23 #define OFF_DELAY 500 /* milliseconds */
24 #define FREE_DELAY 5000
26 #define OFF_TIMER 0x01
27 #define FREE_TIMER 0x02
28 #define CLIENT_VIDEO_ON 0x04
30 #define TIMER_MASK (OFF_TIMER | FREE_TIMER)
32 #define NUM_BLIT_PORTS 32
34 typedef struct _NVPortPrivRec {
41 Bool autopaintColorKey;
52 } NVPortPrivRec, *NVPortPrivPtr;
55 static XF86VideoAdaptorPtr NVSetupOverlayVideo(ScreenPtr);
56 static XF86VideoAdaptorPtr NVSetupBlitVideo(ScreenPtr);
58 static void NVStopOverlay (ScrnInfoPtr);
59 static void NVPutOverlayImage(ScrnInfoPtr pScrnInfo,
64 int x1, int y1, int x2, int y2,
65 short width, short height,
66 short src_w, short src_h,
67 short dst_w, short dst_h,
70 static int NVSetOverlayPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
71 static int NVGetOverlayPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
72 static int NVSetBlitPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
73 static int NVGetBlitPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
76 static void NVStopOverlayVideo(ScrnInfoPtr, pointer, Bool);
77 static void NVStopBlitVideo(ScrnInfoPtr, pointer, Bool);
79 static int NVPutImage( ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer);
80 static void NVQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer);
81 static int NVQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *);
83 static void NVVideoTimerCallback(ScrnInfoPtr, Time);
85 static void NVInitOffscreenImages (ScreenPtr pScreen);
88 #define GET_OVERLAY_PRIVATE(pNv) \
89 (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr)
91 #define GET_BLIT_PRIVATE(pNv) \
92 (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr)
94 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
96 static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
97 xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
100 /* client libraries expect an encoding */
101 static XF86VideoEncodingRec DummyEncoding =
109 #define NUM_FORMATS_ALL 6
111 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
113 {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
114 {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
117 #define NUM_ATTRIBUTES 9
119 XF86AttributeRec NVAttributes[NUM_ATTRIBUTES] =
121 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
122 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
123 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
124 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
125 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
126 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
127 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
128 {XvSettable | XvGettable, 0, 360, "XV_HUE"},
129 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"}
132 #define NUM_IMAGES_YUV 4
133 #define NUM_IMAGES_ALL 5
135 #define FOURCC_RGB 0x0000003
136 #define XVIMAGE_RGB \
141 { 0x03, 0x00, 0x00, 0x00, \
142 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
146 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
151 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}, \
155 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
165 NVSetPortDefaults (ScrnInfoPtr pScrnInfo, NVPortPrivPtr pPriv)
167 NVPtr pNv = NVPTR(pScrnInfo);
169 pPriv->brightness = 0;
170 pPriv->contrast = 4096;
171 pPriv->saturation = 4096;
173 pPriv->colorKey = pNv->videoKey;
174 pPriv->autopaintColorKey = TRUE;
175 pPriv->doubleBuffer = TRUE;
176 pPriv->iturbt_709 = FALSE;
181 NVResetVideo (ScrnInfoPtr pScrnInfo)
183 NVPtr pNv = NVPTR(pScrnInfo);
184 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
185 int satSine, satCosine;
188 angle = (double)pPriv->hue * 3.1415927 / 180.0;
190 satSine = pPriv->saturation * sin(angle);
193 satCosine = pPriv->saturation * cos(angle);
194 if (satCosine < -1024)
197 pNv->PMC[0x8910/4] = (pPriv->brightness << 16) | pPriv->contrast;
198 pNv->PMC[0x8914/4] = (pPriv->brightness << 16) | pPriv->contrast;
199 pNv->PMC[0x8918/4] = (satSine << 16) | (satCosine & 0xffff);
200 pNv->PMC[0x891C/4] = (satSine << 16) | (satCosine & 0xffff);
201 pNv->PMC[0x8b00/4] = pPriv->colorKey;
207 NVStopOverlay (ScrnInfoPtr pScrnInfo)
209 NVPtr pNv = NVPTR(pScrnInfo);
211 pNv->PMC[0x00008704/4] = 1;
215 NVAllocateOverlayMemory(
221 FBLinearPtr new_linear;
224 if(linear->size >= size)
227 if(xf86ResizeOffscreenLinear(linear, size))
230 xf86FreeOffscreenLinear(linear);
233 pScreen = screenInfo.screens[pScrn->scrnIndex];
235 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32,
241 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 32,
247 xf86PurgeUnlockedOffscreenAreas(pScreen);
248 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32,
255 static void NVFreeOverlayMemory(ScrnInfoPtr pScrnInfo)
257 NVPtr pNv = NVPTR(pScrnInfo);
258 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
261 xf86FreeOffscreenLinear(pPriv->linear);
262 pPriv->linear = NULL;
267 static void NVFreeBlitMemory(ScrnInfoPtr pScrnInfo)
269 NVPtr pNv = NVPTR(pScrnInfo);
270 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
273 xf86FreeOffscreenLinear(pPriv->linear);
274 pPriv->linear = NULL;
279 void NVInitVideo (ScreenPtr pScreen)
281 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
282 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
283 XF86VideoAdaptorPtr overlayAdaptor = NULL;
284 XF86VideoAdaptorPtr blitAdaptor = NULL;
285 NVPtr pNv = NVPTR(pScrn);
288 if((pScrn->bitsPerPixel != 8) && (pNv->Architecture >= NV_ARCH_10)) {
289 overlayAdaptor = NVSetupOverlayVideo(pScreen);
292 NVInitOffscreenImages(pScreen);
295 if((pScrn->bitsPerPixel != 8) && !pNv->NoAccel)
296 blitAdaptor = NVSetupBlitVideo(pScreen);
298 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
300 if(blitAdaptor || overlayAdaptor) {
301 int size = num_adaptors;
303 if(overlayAdaptor) size++;
304 if(blitAdaptor) size++;
306 if((newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr*)))) {
308 memcpy(newAdaptors, adaptors,
309 num_adaptors * sizeof(XF86VideoAdaptorPtr));
312 newAdaptors[num_adaptors] = overlayAdaptor;
316 newAdaptors[num_adaptors] = blitAdaptor;
319 adaptors = newAdaptors;
324 xf86XVScreenInit(pScreen, adaptors, num_adaptors);
331 static XF86VideoAdaptorPtr
332 NVSetupBlitVideo (ScreenPtr pScreen)
334 ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum];
335 NVPtr pNv = NVPTR(pScrnInfo);
336 XF86VideoAdaptorPtr adapt;
340 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
341 sizeof(NVPortPrivRec) +
342 (sizeof(DevUnion) * NUM_BLIT_PORTS))))
347 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
349 adapt->name = "NV Video Blitter";
350 adapt->nEncodings = 1;
351 adapt->pEncodings = &DummyEncoding;
352 adapt->nFormats = NUM_FORMATS_ALL;
353 adapt->pFormats = NVFormats;
354 adapt->nPorts = NUM_BLIT_PORTS;
355 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
357 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
358 for(i = 0; i < NUM_BLIT_PORTS; i++)
359 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
361 adapt->pAttributes = NULL;
362 adapt->nAttributes = 0;
363 adapt->pImages = NVImages;
364 adapt->nImages = NUM_IMAGES_ALL;
365 adapt->PutVideo = NULL;
366 adapt->PutStill = NULL;
367 adapt->GetVideo = NULL;
368 adapt->GetStill = NULL;
369 adapt->StopVideo = NVStopBlitVideo;
370 adapt->SetPortAttribute = NVSetBlitPortAttribute;
371 adapt->GetPortAttribute = NVGetBlitPortAttribute;
372 adapt->QueryBestSize = NVQueryBestSize;
373 adapt->PutImage = NVPutImage;
374 adapt->QueryImageAttributes = NVQueryImageAttributes;
376 pPriv->videoStatus = 0;
377 pPriv->grabbedByV4L = FALSE;
378 pPriv->blitter = TRUE;
379 pPriv->doubleBuffer = FALSE;
381 pNv->blitAdaptor = adapt;
386 static XF86VideoAdaptorPtr
387 NVSetupOverlayVideo (ScreenPtr pScreen)
389 ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum];
390 NVPtr pNv = NVPTR(pScrnInfo);
391 XF86VideoAdaptorPtr adapt;
394 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
395 sizeof(NVPortPrivRec) +
401 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
402 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
403 adapt->name = "NV Video Overlay";
404 adapt->nEncodings = 1;
405 adapt->pEncodings = &DummyEncoding;
406 adapt->nFormats = NUM_FORMATS_ALL;
407 adapt->pFormats = NVFormats;
409 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
410 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
411 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
412 adapt->pAttributes = NVAttributes;
413 adapt->nAttributes = NUM_ATTRIBUTES;
414 adapt->pImages = NVImages;
415 adapt->nImages = NUM_IMAGES_YUV;
416 adapt->PutVideo = NULL;
417 adapt->PutStill = NULL;
418 adapt->GetVideo = NULL;
419 adapt->GetStill = NULL;
420 adapt->StopVideo = NVStopOverlayVideo;
421 adapt->SetPortAttribute = NVSetOverlayPortAttribute;
422 adapt->GetPortAttribute = NVGetOverlayPortAttribute;
423 adapt->QueryBestSize = NVQueryBestSize;
424 adapt->PutImage = NVPutImage;
425 adapt->QueryImageAttributes = NVQueryImageAttributes;
427 pPriv->videoStatus = 0;
428 pPriv->currentBuffer = 0;
429 pPriv->grabbedByV4L = FALSE;
430 pPriv->blitter = FALSE;
432 NVSetPortDefaults (pScrnInfo, pPriv);
434 /* gotta uninit this someplace */
435 REGION_INIT(pScreen, &pPriv->clip, NullBox, 0);
437 pNv->overlayAdaptor = adapt;
439 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
440 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
441 xvContrast = MAKE_ATOM("XV_CONTRAST");
442 xvColorKey = MAKE_ATOM("XV_COLORKEY");
443 xvSaturation = MAKE_ATOM("XV_SATURATION");
444 xvHue = MAKE_ATOM("XV_HUE");
445 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
446 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
447 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
449 NVResetVideo(pScrnInfo);
456 ScrnInfoPtr pScrnInfo,
474 NVPtr pNv = NVPTR(pScrnInfo);
475 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
476 int buffer = pPriv->currentBuffer;
478 /* paint the color key */
479 if(pPriv->autopaintColorKey &&
480 (pPriv->grabbedByV4L ||
481 !REGION_EQUAL(pScrnInfo->pScreen, &pPriv->clip, clipBoxes)))
483 /* we always paint V4L's color key */
484 if(!pPriv->grabbedByV4L)
485 REGION_COPY(pScrnInfo->pScreen, &pPriv->clip, clipBoxes);
486 xf86XVFillKeyHelper(pScrnInfo->pScreen, pPriv->colorKey, clipBoxes);
489 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
495 pNv->PMC[(0x8900/4) + buffer] = offset;
496 pNv->PMC[(0x8928/4) + buffer] = (height << 16) | width;
497 pNv->PMC[(0x8930/4) + buffer] = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
498 pNv->PMC[(0x8938/4) + buffer] = (src_w << 20) / drw_w;
499 pNv->PMC[(0x8940/4) + buffer] = (src_h << 20) / drw_h;
500 pNv->PMC[(0x8948/4) + buffer] = (dstBox->y1 << 16) | dstBox->x1;
501 pNv->PMC[(0x8950/4) + buffer] = ((dstBox->y2 - dstBox->y1) << 16) |
502 (dstBox->x2 - dstBox->x1);
504 dstPitch |= 1 << 20; /* use color key */
506 if(id != FOURCC_UYVY)
508 if(pPriv->iturbt_709)
511 pNv->PMC[(0x8958/4) + buffer] = dstPitch;
512 pNv->PMC[0x00008704/4] = 0;
513 pNv->PMC[0x8700/4] = 1 << (buffer << 2);
515 pPriv->videoStatus = CLIENT_VIDEO_ON;
522 ScrnInfoPtr pScrnInfo,
540 NVPtr pNv = NVPTR(pScrnInfo);
541 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
542 BoxPtr pbox = REGION_RECTS(clipBoxes);
543 int nbox = REGION_NUM_RECTS(clipBoxes);
544 CARD32 dsdx, dtdy, size, point, srcpoint, format;
546 dsdx = (src_w << 20) / drw_w;
547 dtdy = (src_h << 20) / drw_h;
549 size = ((dstBox->y2 - dstBox->y1) << 16) | (dstBox->x2 - dstBox->x1);
550 point = (dstBox->y1 << 16) | dstBox->x1;
552 dstPitch |= (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER << 16) |
553 (STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR << 24);
555 srcpoint = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
559 format = STRETCH_BLIT_FORMAT_X8R8G8B8;
562 format = STRETCH_BLIT_FORMAT_UYVY;
565 format = STRETCH_BLIT_FORMAT_YUYV;
569 if(pNv->CurrentLayout.depth == 15) {
570 NVDmaStart(pNv, SURFACE_FORMAT, 1);
571 NVDmaNext (pNv, SURFACE_FORMAT_DEPTH15);
574 NVDmaStart(pNv, STRETCH_BLIT_FORMAT, 1);
575 NVDmaNext (pNv, format);
578 NVDmaStart(pNv, RECT_SOLID_COLOR, 1);
581 NVDmaStart(pNv, STRETCH_BLIT_CLIP_POINT, 6);
582 NVDmaNext (pNv, (pbox->y1 << 16) | pbox->x1);
583 NVDmaNext (pNv, ((pbox->y2 - pbox->y1) << 16) | (pbox->x2 - pbox->x1));
584 NVDmaNext (pNv, point);
585 NVDmaNext (pNv, size);
586 NVDmaNext (pNv, dsdx);
587 NVDmaNext (pNv, dtdy);
589 NVDmaStart(pNv, STRETCH_BLIT_SRC_SIZE, 4);
590 NVDmaNext (pNv, (height << 16) | width);
591 NVDmaNext (pNv, dstPitch);
592 NVDmaNext (pNv, offset);
593 NVDmaNext (pNv, srcpoint);
597 if(pNv->CurrentLayout.depth == 15) {
598 NVDmaStart(pNv, SURFACE_FORMAT, 1);
599 NVDmaNext (pNv, SURFACE_FORMAT_DEPTH16);
603 SET_SYNC_FLAG(pNv->AccelInfoRec);
605 pPriv->videoStatus = FREE_TIMER;
606 pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
607 pNv->VideoTimerCallback = NVVideoTimerCallback;
613 static void NVStopOverlayVideo
615 ScrnInfoPtr pScrnInfo,
620 NVPtr pNv = NVPTR(pScrnInfo);
621 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
623 if(pPriv->grabbedByV4L) return;
625 REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
628 if(pPriv->videoStatus & CLIENT_VIDEO_ON)
629 NVStopOverlay(pScrnInfo);
630 NVFreeOverlayMemory(pScrnInfo);
631 pPriv->videoStatus = 0;
633 if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
634 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
635 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
636 pNv->VideoTimerCallback = NVVideoTimerCallback;
641 static void NVStopBlitVideo
643 ScrnInfoPtr pScrnInfo,
650 static int NVSetOverlayPortAttribute
652 ScrnInfoPtr pScrnInfo,
658 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
660 if (attribute == xvBrightness)
662 if ((value < -512) || (value > 512))
664 pPriv->brightness = value;
666 else if (attribute == xvDoubleBuffer)
668 if ((value < 0) || (value > 1))
670 pPriv->doubleBuffer = value;
672 else if (attribute == xvContrast)
674 if ((value < 0) || (value > 8191))
676 pPriv->contrast = value;
678 else if (attribute == xvHue)
685 else if (attribute == xvSaturation)
687 if ((value < 0) || (value > 8191))
689 pPriv->saturation = value;
691 else if (attribute == xvColorKey)
693 pPriv->colorKey = value;
694 REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
696 else if (attribute == xvAutopaintColorKey)
698 if ((value < 0) || (value > 1))
700 pPriv->autopaintColorKey = value;
702 else if (attribute == xvITURBT709)
704 if ((value < 0) || (value > 1))
706 pPriv->iturbt_709 = value;
708 else if (attribute == xvSetDefaults)
710 NVSetPortDefaults(pScrnInfo, pPriv);
715 NVResetVideo(pScrnInfo);
720 static int NVGetOverlayPortAttribute
722 ScrnInfoPtr pScrnInfo,
728 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
730 if (attribute == xvBrightness)
731 *value = pPriv->brightness;
732 else if (attribute == xvDoubleBuffer)
733 *value = (pPriv->doubleBuffer) ? 1 : 0;
734 else if (attribute == xvContrast)
735 *value = pPriv->contrast;
736 else if (attribute == xvSaturation)
737 *value = pPriv->saturation;
738 else if (attribute == xvHue)
740 else if (attribute == xvColorKey)
741 *value = pPriv->colorKey;
742 else if (attribute == xvAutopaintColorKey)
743 *value = (pPriv->autopaintColorKey) ? 1 : 0;
744 else if (attribute == xvITURBT709)
745 *value = (pPriv->iturbt_709) ? 1 : 0;
752 static int NVSetBlitPortAttribute
754 ScrnInfoPtr pScrnInfo,
763 static int NVGetBlitPortAttribute
765 ScrnInfoPtr pScrnInfo,
778 static void NVQueryBestSize
780 ScrnInfoPtr pScrnInfo,
791 if(vid_w > (drw_w << 3))
793 if(vid_h > (drw_h << 3))
800 static void NVCopyData420
819 for(j = 0; j < h; j++) {
821 s1 = src1; s2 = src2; s3 = src3;
824 #if X_BYTE_ORDER == X_BIG_ENDIAN
825 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
826 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1];
827 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2];
828 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3];
830 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
831 dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
832 dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
833 dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
835 dst += 4; s2 += 4; s3 += 4; s1 += 8;
840 #if X_BYTE_ORDER == X_BIG_ENDIAN
841 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
843 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
859 static void NVMoveDWORDS(
864 while(dwords & ~0x03) {
866 *(dest + 1) = *(src + 1);
867 *(dest + 2) = *(src + 2);
868 *(dest + 3) = *(src + 3);
875 if(dwords == 1) return;
876 *(dest + 1) = *(src + 1);
877 if(dwords == 2) return;
878 *(dest + 2) = *(src + 2);
881 #if X_BYTE_ORDER == X_BIG_ENDIAN
882 static void NVMoveDWORDSSwapped(
888 *dest++ = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
894 static void NVCopyData422
904 w >>= 1; /* pixels to DWORDS */
906 NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w);
912 static void NVCopyDataRGB
923 #if X_BYTE_ORDER == X_BIG_ENDIAN
924 NVMoveDWORDSSwapped((CARD32*)dst, (CARD8*)src, w);
926 NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w);
937 static int NVPutImage
939 ScrnInfoPtr pScrnInfo,
957 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
958 NVPtr pNv = NVPTR(pScrnInfo);
959 INT32 xa, xb, ya, yb;
960 unsigned char *dst_start;
961 int pitch, newSize, offset, s2offset, s3offset;
962 int srcPitch, srcPitch2, dstPitch;
963 int top, left, right, bottom, npixels, nlines, bpp;
969 * s2offset, s3offset - byte offsets into U and V plane of the
970 * source where copying starts. Y plane is
971 * done by editing "buf".
973 * offset - byte offset to the first line of the destination.
975 * dst_start - byte address to the first displayed pel.
979 if(pPriv->grabbedByV4L) return Success;
981 /* make the compiler happy */
982 s2offset = s3offset = srcPitch2 = 0;
984 if(!pPriv->blitter) {
985 if(src_w > (drw_w << 3))
987 if(src_h > (drw_h << 3))
998 dstBox.x2 = drw_x + drw_w;
1000 dstBox.y2 = drw_y + drw_h;
1002 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1006 if(!pPriv->blitter) {
1007 dstBox.x1 -= pScrnInfo->frameX0;
1008 dstBox.x2 -= pScrnInfo->frameX0;
1009 dstBox.y1 -= pScrnInfo->frameY0;
1010 dstBox.y2 -= pScrnInfo->frameY0;
1013 bpp = pScrnInfo->bitsPerPixel >> 3;
1014 pitch = bpp * pScrnInfo->displayWidth;
1019 srcPitch = (width + 3) & ~3; /* of luma */
1020 s2offset = srcPitch * height;
1021 srcPitch2 = ((width >> 1) + 3) & ~3;
1022 s3offset = (srcPitch2 * (height >> 1)) + s2offset;
1023 dstPitch = ((width << 1) + 63) & ~63;
1027 srcPitch = width << 1;
1028 dstPitch = ((width << 1) + 63) & ~63;
1031 srcPitch = width << 2;
1032 dstPitch = ((width << 2) + 63) & ~63;
1035 return BadImplementation;
1038 newSize = height * dstPitch / bpp;
1040 if(pPriv->doubleBuffer)
1043 pPriv->linear = NVAllocateOverlayMemory(pScrnInfo,
1047 if(!pPriv->linear) return BadAlloc;
1049 offset = pPriv->linear->offset * bpp;
1051 if(pPriv->doubleBuffer) {
1052 int mask = 1 << (pPriv->currentBuffer << 2);
1055 /* burn the CPU until the next buffer is available */
1056 while(pNv->PMC[0x00008700/4] & mask);
1058 /* overwrite the newest buffer if there's not one free */
1059 if(pNv->PMC[0x00008700/4] & mask) {
1060 if(!pPriv->currentBuffer)
1061 offset += (newSize * bpp) >> 1;
1065 if(pPriv->currentBuffer)
1066 offset += (newSize * bpp) >> 1;
1069 dst_start = pNv->FbStart + offset;
1071 /* We need to enlarge the copied rectangle by a pixel so the HW
1072 filtering doesn't pick up junk laying outside of the source */
1074 left = (xa - 0x00010000) >> 16;
1075 if(left < 0) left = 0;
1076 top = (ya - 0x00010000) >> 16;
1077 if(top < 0) top = 0;
1078 right = (xb + 0x0001ffff) >> 16;
1079 if(right > width) right = width;
1080 bottom = (yb + 0x0001ffff) >> 16;
1081 if(bottom > height) bottom = height;
1083 if(pPriv->blitter) NVSync(pScrnInfo);
1089 npixels = ((right + 1) & ~1) - left;
1091 nlines = ((bottom + 1) & ~1) - top;
1093 dst_start += (left << 1) + (top * dstPitch);
1094 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1097 if(id == FOURCC_I420) {
1099 s2offset = s3offset;
1102 NVCopyData420(buf + (top * srcPitch) + left,
1103 buf + s2offset, buf + s3offset,
1104 dst_start, srcPitch, srcPitch2,
1105 dstPitch, nlines, npixels);
1110 npixels = ((right + 1) & ~1) - left;
1111 nlines = bottom - top;
1114 buf += (top * srcPitch) + left;
1115 dst_start += left + (top * dstPitch);
1117 NVCopyData422(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
1120 npixels = right - left;
1121 nlines = bottom - top;
1124 buf += (top * srcPitch) + left;
1125 dst_start += left + (top * dstPitch);
1127 NVCopyDataRGB(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
1130 return BadImplementation;
1134 if(pPriv->blitter) {
1135 NVPutBlitImage(pScrnInfo, offset, id, dstPitch, &dstBox,
1137 width, height, src_w, src_h, drw_w, drw_h,
1140 NVPutOverlayImage(pScrnInfo, offset, id, dstPitch, &dstBox,
1142 width, height, src_w, src_h, drw_w, drw_h,
1144 pPriv->currentBuffer ^= 1;
1151 * QueryImageAttributes
1153 static int NVQueryImageAttributes
1155 ScrnInfoPtr pScrnInfo,
1179 size = (*w + 3) & ~3;
1185 tmp = ((*w >> 1) + 3) & ~3;
1187 pitches[1] = pitches[2] = tmp;
1214 static void NVVideoTimerCallback
1216 ScrnInfoPtr pScrnInfo,
1220 NVPtr pNv = NVPTR(pScrnInfo);
1221 NVPortPrivPtr pOverPriv = NULL;
1222 NVPortPrivPtr pBlitPriv = NULL;
1223 Bool needCallback = FALSE;
1225 if(!pScrnInfo->vtSema) return;
1227 if(pNv->overlayAdaptor) {
1228 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
1229 if(!pOverPriv->videoStatus)
1233 if(pNv->blitAdaptor) {
1234 pBlitPriv = GET_BLIT_PRIVATE(pNv);
1235 if(!pBlitPriv->videoStatus)
1240 if(pOverPriv->videoTime < currentTime) {
1241 if(pOverPriv->videoStatus & OFF_TIMER) {
1242 NVStopOverlay(pScrnInfo);
1243 pOverPriv->videoStatus = FREE_TIMER;
1244 pOverPriv->videoTime = currentTime + FREE_DELAY;
1245 needCallback = TRUE;
1247 if(pOverPriv->videoStatus & FREE_TIMER) {
1248 NVFreeOverlayMemory(pScrnInfo);
1249 pOverPriv->videoStatus = 0;
1252 needCallback = TRUE;
1257 if(pBlitPriv->videoTime < currentTime) {
1258 NVFreeBlitMemory(pScrnInfo);
1259 pBlitPriv->videoStatus = 0;
1261 needCallback = TRUE;
1265 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
1269 /***** Exported offscreen surface stuff ****/
1274 ScrnInfoPtr pScrnInfo,
1278 XF86SurfacePtr surface
1281 NVPtr pNv = NVPTR(pScrnInfo);
1282 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1285 bpp = pScrnInfo->bitsPerPixel >> 3;
1287 if(pPriv->grabbedByV4L) return BadAlloc;
1289 if((w > 2046) || (h > 2046)) return BadValue;
1292 pPriv->pitch = ((w << 1) + 63) & ~63;
1293 size = h * pPriv->pitch / bpp;
1295 pPriv->linear = NVAllocateOverlayMemory(pScrnInfo, pPriv->linear,
1298 if(!pPriv->linear) return BadAlloc;
1300 pPriv->offset = pPriv->linear->offset * bpp;
1303 surface->height = h;
1304 surface->pScrn = pScrnInfo;
1305 surface->pitches = &pPriv->pitch;
1306 surface->offsets = &pPriv->offset;
1307 surface->devPrivate.ptr = (pointer)pPriv;
1310 /* grab the video */
1311 NVStopOverlay(pScrnInfo);
1312 pPriv->videoStatus = 0;
1313 REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
1314 pPriv->grabbedByV4L = TRUE;
1320 NVStopSurface (XF86SurfacePtr surface)
1322 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1324 if(pPriv->grabbedByV4L && pPriv->videoStatus) {
1325 NVStopOverlay(surface->pScrn);
1326 pPriv->videoStatus = 0;
1333 NVFreeSurface (XF86SurfacePtr surface)
1335 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1337 if(pPriv->grabbedByV4L) {
1338 NVStopSurface(surface);
1339 NVFreeOverlayMemory(surface->pScrn);
1340 pPriv->grabbedByV4L = FALSE;
1347 NVGetSurfaceAttribute (
1348 ScrnInfoPtr pScrnInfo,
1353 NVPtr pNv = NVPTR(pScrnInfo);
1354 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1356 return NVGetOverlayPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv);
1360 NVSetSurfaceAttribute(
1361 ScrnInfoPtr pScrnInfo,
1366 NVPtr pNv = NVPTR(pScrnInfo);
1367 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1369 return NVSetOverlayPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv);
1374 XF86SurfacePtr surface,
1375 short src_x, short src_y,
1376 short drw_x, short drw_y,
1377 short src_w, short src_h,
1378 short drw_w, short drw_h,
1382 ScrnInfoPtr pScrnInfo = surface->pScrn;
1383 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1384 INT32 xa, xb, ya, yb;
1387 if(!pPriv->grabbedByV4L) return Success;
1389 if(src_w > (drw_w << 3))
1391 if(src_h > (drw_h << 3))
1401 dstBox.x2 = drw_x + drw_w;
1403 dstBox.y2 = drw_y + drw_h;
1405 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1406 surface->width, surface->height))
1411 dstBox.x1 -= pScrnInfo->frameX0;
1412 dstBox.x2 -= pScrnInfo->frameX0;
1413 dstBox.y1 -= pScrnInfo->frameY0;
1414 dstBox.y2 -= pScrnInfo->frameY0;
1416 pPriv->currentBuffer = 0;
1418 NVPutOverlayImage (pScrnInfo, surface->offsets[0], surface->id,
1419 surface->pitches[0], &dstBox, xa, ya, xb, yb,
1420 surface->width, surface->height, src_w, src_h,
1421 drw_w, drw_h, clipBoxes);
1426 XF86OffscreenImageRec NVOffscreenImages[2] =
1430 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1435 NVGetSurfaceAttribute,
1436 NVSetSurfaceAttribute,
1443 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1448 NVGetSurfaceAttribute,
1449 NVSetSurfaceAttribute,
1457 NVInitOffscreenImages (ScreenPtr pScreen)
1459 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);