7 #include "xf86_OSproc.h"
8 #include "xf86Resources.h"
10 #include "xf86PciInfo.h"
12 #include "xf86fbman.h"
13 #include "regionstr.h"
16 #include <X11/extensions/Xv.h>
21 #include "dixstruct.h"
24 #include "nv_include.h"
27 #define IMAGE_MAX_W 2046
28 #define IMAGE_MAX_H 2046
30 #define OFF_DELAY 500 /* milliseconds */
31 #define FREE_DELAY 5000
33 #define OFF_TIMER 0x01
34 #define FREE_TIMER 0x02
35 #define CLIENT_VIDEO_ON 0x04
37 #define TIMER_MASK (OFF_TIMER | FREE_TIMER)
39 #define NUM_BLIT_PORTS 32
41 typedef struct _NVPortPrivRec {
48 Bool autopaintColorKey;
57 NVAllocRec * video_mem;
60 NVAllocRec * TT_mem_chunk[2];
61 int currentHostBuffer;
62 } NVPortPrivRec, *NVPortPrivPtr;
64 #define GET_OVERLAY_PRIVATE(pNv) \
65 (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr)
67 #define GET_BLIT_PRIVATE(pNv) \
68 (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr)
70 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
72 static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
73 xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
74 xvITURBT709, xvSyncToVBlank;
76 /* client libraries expect an encoding */
77 static XF86VideoEncodingRec DummyEncoding =
81 IMAGE_MAX_W, IMAGE_MAX_H,
85 #define NUM_FORMATS_ALL 6
87 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
89 {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
90 {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
93 #define NUM_OVERLAY_ATTRIBUTES 9
94 XF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] =
96 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
97 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
98 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
99 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
100 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
101 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
102 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
103 {XvSettable | XvGettable, 0, 360, "XV_HUE"},
104 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"}
107 #define NUM_BLIT_ATTRIBUTES 2
108 XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
110 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
111 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
115 #define NUM_IMAGES_YUV 4
116 #define NUM_IMAGES_ALL 5
118 #define FOURCC_RGB 0x0000003
119 #define XVIMAGE_RGB \
124 { 0x03, 0x00, 0x00, 0x00, \
125 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
129 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
134 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}, \
138 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
149 * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
151 * @param pScrn screen to get the default colorKey from
152 * @param pPriv port to reset to defaults
155 NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
157 NVPtr pNv = NVPTR(pScrn);
159 pPriv->brightness = 0;
160 pPriv->contrast = 4096;
161 pPriv->saturation = 4096;
163 pPriv->colorKey = pNv->videoKey;
164 pPriv->autopaintColorKey = TRUE;
165 pPriv->doubleBuffer = TRUE;
166 pPriv->iturbt_709 = FALSE;
167 pPriv->currentHostBuffer = 0;
172 * writes the current attributes from the overlay port to the hardware
175 NVResetVideo (ScrnInfoPtr pScrn)
177 NVPtr pNv = NVPTR(pScrn);
178 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
179 int satSine, satCosine;
182 angle = (double)pPriv->hue * 3.1415927 / 180.0;
184 satSine = pPriv->saturation * sin(angle);
187 satCosine = pPriv->saturation * cos(angle);
188 if (satCosine < -1024)
191 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
193 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
195 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
196 (satCosine & 0xffff));
197 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
198 (satCosine & 0xffff));
199 nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
204 * Tell the hardware to stop the overlay
207 NVStopOverlay (ScrnInfoPtr pScrn)
209 NVPtr pNv = NVPTR(pScrn);
211 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
215 * NVAllocateVideoMemory
216 * allocates video memory for a given port
218 * @param pScrn screen which requests the memory
219 * @param mem pointer to previously allocated memory for reallocation
220 * @param size size of requested memory segment
221 * @return pointer to the allocated memory
224 NVAllocateVideoMemory(ScrnInfoPtr pScrn, NVAllocRec *mem, int size)
226 NVPtr pNv = NVPTR(pScrn);
229 We allocate in bytes, so we need to adapt.
231 size *= (pScrn->bitsPerPixel >> 3);
234 if(mem->size >= size)
236 NVFreeMemory(pNv, mem);
239 return NVAllocateMemory(pNv, NOUVEAU_MEM_FB, size); /* align 32? */
244 * allocates TT memory for a given port
246 * @param pScrn screen which requests the memory
247 * @param mem pointer to previously allocated memory for reallocation
248 * @param size size of requested memory segment
249 * @return pointer to the allocated memory
252 NVAllocateTTMemory(ScrnInfoPtr pScrn, NVAllocRec *mem, int size)
254 NVPtr pNv = NVPTR(pScrn);
257 We allocate in bytes, so we need to adapt.
259 size *= (pScrn->bitsPerPixel >> 3);
262 if(mem->size >= size)
264 NVFreeMemory(pNv, mem);
266 /*We may take PCI memory, but that does not mean we won't fallback on CPU copy in that case.*/
267 return NVAllocateMemory(pNv, NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE, size); /* align 32? */
271 * NVFreeOverlayMemory
272 * frees memory held by the overlay port
273 * this function (unlike NVAllocateOverlayMemory) is "Overlay"-specific
275 * @param pScrn screen whose overlay port wants to free memory
278 NVFreeOverlayMemory(ScrnInfoPtr pScrn)
280 NVPtr pNv = NVPTR(pScrn);
281 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
283 if(pPriv->video_mem) {
284 NVFreeMemory(pNv, pPriv->video_mem);
285 pPriv->video_mem = NULL;
288 if(pPriv->TT_mem_chunk[0]) {
289 NVFreeMemory(pNv, pPriv->video_mem);
290 pPriv->video_mem = NULL;
293 if(pPriv->TT_mem_chunk[1]) {
294 NVFreeMemory(pNv, pPriv->video_mem);
295 pPriv->video_mem = NULL;
301 * frees memory held by the blit port
303 * @param pScrn screen whose blit port wants to free memory
306 NVFreeBlitMemory(ScrnInfoPtr pScrn)
308 NVPtr pNv = NVPTR(pScrn);
309 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
311 if(pPriv->video_mem) {
312 NVFreeMemory(pNv, pPriv->video_mem);
313 pPriv->video_mem = NULL;
316 if(pPriv->TT_mem_chunk[0]) {
317 NVFreeMemory(pNv, pPriv->video_mem);
318 pPriv->video_mem = NULL;
321 if(pPriv->TT_mem_chunk[1]) {
322 NVFreeMemory(pNv, pPriv->video_mem);
323 pPriv->video_mem = NULL;
328 * NVVideoTimerCallback
329 * callback function which perform cleanup tasks (stop overlay, free memory).
330 * within the driver it is only called once from NVBlockHandler in nv_driver.c
333 NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
335 NVPtr pNv = NVPTR(pScrn);
336 NVPortPrivPtr pOverPriv = NULL;
337 NVPortPrivPtr pBlitPriv = NULL;
338 Bool needCallback = FALSE;
343 if (pNv->overlayAdaptor) {
344 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
345 if (!pOverPriv->videoStatus)
349 if (pNv->blitAdaptor) {
350 pBlitPriv = GET_BLIT_PRIVATE(pNv);
351 if (!pBlitPriv->videoStatus)
356 if (pOverPriv->videoTime < currentTime) {
357 if (pOverPriv->videoStatus & OFF_TIMER) {
358 NVStopOverlay(pScrn);
359 pOverPriv->videoStatus = FREE_TIMER;
360 pOverPriv->videoTime = currentTime + FREE_DELAY;
363 if (pOverPriv->videoStatus & FREE_TIMER) {
364 NVFreeOverlayMemory(pScrn);
365 pOverPriv->videoStatus = 0;
373 if (pBlitPriv->videoTime < currentTime) {
374 NVFreeBlitMemory(pScrn);
375 pBlitPriv->videoStatus = 0;
381 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
386 * program hardware to overlay image into front buffer
388 * @param pScrn screen
390 * @param id colorspace of image
406 NVPutOverlayImage(ScrnInfoPtr pScrn, int offset, int id,
407 int dstPitch, BoxPtr dstBox,
408 int x1, int y1, int x2, int y2,
409 short width, short height,
410 short src_w, short src_h,
411 short drw_w, short drw_h,
414 NVPtr pNv = NVPTR(pScrn);
415 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
416 int buffer = pPriv->currentBuffer;
418 /* paint the color key */
419 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
420 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
421 /* we always paint V4L's color key */
422 if (!pPriv->grabbedByV4L)
423 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
424 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
427 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
433 nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer) , offset);
434 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer) , (height << 16) | width);
435 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
436 ((y1 << 4) & 0xffff0000) | (x1 >> 12));
437 nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer) , (src_w << 20) / drw_w);
438 nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer) , (src_h << 20) / drw_h);
439 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
440 (dstBox->y1 << 16) | dstBox->x1);
441 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
442 ((dstBox->y2 - dstBox->y1) << 16) |
443 (dstBox->x2 - dstBox->x1));
445 dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; /* use color key */
446 if(id != FOURCC_UYVY)
447 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
448 if(pPriv->iturbt_709)
449 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
451 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
452 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
453 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
455 pPriv->videoStatus = CLIENT_VIDEO_ON;
458 #ifndef ExaOffscreenMarkUsed
459 extern void ExaOffscreenMarkUsed(PixmapPtr);
461 #ifndef exaGetDrawablePixmap
462 extern PixmapPtr exaGetDrawablePixmap(DrawablePtr);
464 #ifndef exaPixmapIsOffscreen
465 extern Bool exaPixmapIsOffscreen(PixmapPtr p);
467 /* To support EXA 2.0, 2.1 has this in the header */
468 #ifndef exaMoveInPixmap
469 extern void exaMoveInPixmap(PixmapPtr pPixmap);
475 * @param pScrn screen
477 * @param id colorspace of image
494 NVPutBlitImage(ScrnInfoPtr pScrn, int src_offset, int id,
495 int src_pitch, BoxPtr dstBox,
496 int x1, int y1, int x2, int y2,
497 short width, short height,
498 short src_w, short src_h,
499 short drw_w, short drw_h,
503 NVPtr pNv = NVPTR(pScrn);
504 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
508 CARD32 dst_size, dst_point;
509 CARD32 src_point, src_format;
512 ScreenPtr pScreen = pScrn->pScreen;
513 PixmapPtr pPix = exaGetDrawablePixmap(pDraw);
516 /* Try to get the dest drawable into vram */
517 if (!exaPixmapIsOffscreen(pPix)) {
518 exaMoveInPixmap(pPix);
519 ExaOffscreenMarkUsed(pPix);
522 /* If we failed, draw directly onto the screen pixmap.
523 * Not sure if this is the best approach, maybe failing
524 * with BadAlloc would be better?
526 if (!exaPixmapIsOffscreen(pPix)) {
527 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
528 "XV: couldn't move dst surface into vram\n");
529 pPix = pScreen->GetScreenPixmap(pScreen);
532 NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format);
533 NVAccelSetCtxSurf2D(pPix, pPix, dst_format);
536 /* Adjust coordinates if drawing to an offscreen pixmap */
537 if (pPix->screen_x || pPix->screen_y) {
538 REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
541 dstBox->x1 -= pPix->screen_x;
542 dstBox->x2 -= pPix->screen_x;
543 dstBox->y1 -= pPix->screen_y;
544 dstBox->y2 -= pPix->screen_y;
547 DamageDamageRegion((DrawablePtr)pPix, clipBoxes);
550 if (pNv->CurrentLayout.depth == 15) {
551 NVDmaStart(pNv, NvSubContextSurfaces,
553 NVDmaNext (pNv, SURFACE_FORMAT_X1R5G5B5);
557 pbox = REGION_RECTS(clipBoxes);
558 nbox = REGION_NUM_RECTS(clipBoxes);
560 dsdx = (src_w << 20) / drw_w;
561 dtdy = (src_h << 20) / drw_h;
563 dst_size = ((dstBox->y2 - dstBox->y1) << 16) |
564 (dstBox->x2 - dstBox->x1);
565 dst_point = (dstBox->y1 << 16) | dstBox->x1;
567 src_pitch |= (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER << 16) |
568 (STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR << 24);
569 src_point = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
573 src_format = STRETCH_BLIT_FORMAT_X8R8G8B8;
576 src_format = STRETCH_BLIT_FORMAT_UYVY;
579 src_format = STRETCH_BLIT_FORMAT_YUYV;
583 if(pPriv->SyncToVBlank) {
588 if(pNv->BlendingPossible) {
589 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_FORMAT, 2);
590 NVDmaNext (pNv, src_format);
591 NVDmaNext (pNv, STRETCH_BLIT_OPERATION_COPY);
593 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_FORMAT, 1);
594 NVDmaNext (pNv, src_format);
597 NVDmaStart(pNv, NvSubScaledImage,
598 NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
599 NVDmaNext (pNv, NvDmaTT); /* source object */
602 NVDmaStart(pNv, NvSubRectangle, RECT_SOLID_COLOR, 1);
605 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_CLIP_POINT, 6);
606 NVDmaNext (pNv, (pbox->y1 << 16) | pbox->x1);
607 NVDmaNext (pNv, ((pbox->y2 - pbox->y1) << 16) |
608 (pbox->x2 - pbox->x1));
609 NVDmaNext (pNv, dst_point);
610 NVDmaNext (pNv, dst_size);
611 NVDmaNext (pNv, dsdx);
612 NVDmaNext (pNv, dtdy);
614 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_SRC_SIZE, 4);
615 NVDmaNext (pNv, (height << 16) | width);
616 NVDmaNext (pNv, src_pitch);
617 NVDmaNext (pNv, src_offset);
618 NVDmaNext (pNv, src_point);
623 if(pNv->CurrentLayout.depth == 15) {
624 NVDmaStart(pNv, NvSubContextSurfaces,
626 NVDmaNext (pNv, SURFACE_FORMAT_R5G6B5);
633 exaMarkSync(pScrn->pScreen);
635 SET_SYNC_FLAG(pNv->AccelInfoRec);
637 pPriv->videoStatus = FREE_TIMER;
638 pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
639 pNv->VideoTimerCallback = NVVideoTimerCallback;
646 NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
648 NVPtr pNv = NVPTR(pScrn);
649 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
651 if(pPriv->grabbedByV4L) return;
653 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
656 if (pPriv->videoStatus & CLIENT_VIDEO_ON)
657 NVStopOverlay(pScrn);
658 NVFreeOverlayMemory(pScrn);
659 pPriv->videoStatus = 0;
661 if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
662 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
663 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
664 pNv->VideoTimerCallback = NVVideoTimerCallback;
674 NVStopBlitVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
679 * NVSetOverlayPortAttribute
680 * sets the attribute "attribute" of port "data" to value "value"
681 * calls NVResetVideo(pScrn) to apply changes to hardware
684 * @param attribute attribute to set
685 * @param value value to which attribute is to be set
686 * @param data port from which the attribute is to be set
688 * @return Success, if setting is successful
689 * BadValue/BadMatch, if value/attribute are invalid
690 * @see NVResetVideo(ScrnInfoPtr pScrn)
693 NVSetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
694 INT32 value, pointer data)
696 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
698 if (attribute == xvBrightness) {
699 if ((value < -512) || (value > 512))
701 pPriv->brightness = value;
703 if (attribute == xvDoubleBuffer) {
704 if ((value < 0) || (value > 1))
706 pPriv->doubleBuffer = value;
708 if (attribute == xvContrast) {
709 if ((value < 0) || (value > 8191))
711 pPriv->contrast = value;
713 if (attribute == xvHue) {
719 if (attribute == xvSaturation) {
720 if ((value < 0) || (value > 8191))
722 pPriv->saturation = value;
724 if (attribute == xvColorKey) {
725 pPriv->colorKey = value;
726 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
728 if (attribute == xvAutopaintColorKey) {
729 if ((value < 0) || (value > 1))
731 pPriv->autopaintColorKey = value;
733 if (attribute == xvITURBT709) {
734 if ((value < 0) || (value > 1))
736 pPriv->iturbt_709 = value;
738 if (attribute == xvSetDefaults) {
739 NVSetPortDefaults(pScrn, pPriv);
748 * NVGetOverlayPortAttribute
750 * @param pScrn unused
751 * @param attribute attribute to be read
752 * @param value value of attribute will be stored in this pointer
753 * @param data port from which attribute will be read
754 * @return Success, if queried attribute exists
757 NVGetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
758 INT32 *value, pointer data)
760 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
762 if (attribute == xvBrightness)
763 *value = pPriv->brightness;
764 else if (attribute == xvDoubleBuffer)
765 *value = (pPriv->doubleBuffer) ? 1 : 0;
766 else if (attribute == xvContrast)
767 *value = pPriv->contrast;
768 else if (attribute == xvSaturation)
769 *value = pPriv->saturation;
770 else if (attribute == xvHue)
772 else if (attribute == xvColorKey)
773 *value = pPriv->colorKey;
774 else if (attribute == xvAutopaintColorKey)
775 *value = (pPriv->autopaintColorKey) ? 1 : 0;
776 else if (attribute == xvITURBT709)
777 *value = (pPriv->iturbt_709) ? 1 : 0;
785 * NVSetBlitPortAttribute
786 * sets the attribute "attribute" of port "data" to value "value"
787 * supported attributes:
788 * - xvSyncToVBlank (values: 0,1)
789 * - xvSetDefaults (values: NA; SyncToVBlank will be set, if hardware supports it)
792 * @param attribute attribute to set
793 * @param value value to which attribute is to be set
794 * @param data port from which the attribute is to be set
796 * @return Success, if setting is successful
797 * BadValue/BadMatch, if value/attribute are invalid
800 NVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
801 INT32 value, pointer data)
803 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
804 NVPtr pNv = NVPTR(pScrn);
806 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
807 if ((value < 0) || (value > 1))
809 pPriv->SyncToVBlank = value;
811 if (attribute == xvSetDefaults) {
812 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
820 * NVGetBlitPortAttribute
821 * reads the value of attribute "attribute" from port "data" into INT32 "*value"
822 * currently only one attribute supported: xvSyncToVBlank
824 * @param pScrn unused
825 * @param attribute attribute to be read
826 * @param value value of attribute will be stored here
827 * @param data port from which attribute will be read
828 * @return Success, if queried attribute exists
831 NVGetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
832 INT32 *value, pointer data)
834 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
836 if(attribute == xvSyncToVBlank)
837 *value = (pPriv->SyncToVBlank) ? 1 : 0;
847 * used by client applications to ask the driver:
848 * how would you actually scale a video of dimensions
849 * vid_w, vid_h, if i wanted you to scale it to dimensions
851 * function stores actual scaling size in pointers p_w, p_h.
853 * - currently the image cannot be scaled to less than
854 * 1/8th of the original size in either dimension. why?
855 * - what happens if the client requests a scaling to a larger value than
856 * the hardware is capable of (IMAGE_MAX_W, IMAGE_MAX_H)?
858 * @param pScrn unused
859 * @param motion unused
860 * @param vid_w width of source video
861 * @param vid_h height of source video
862 * @param drw_w desired scaled width as requested by client
863 * @param drw_h desired scaled height as requested by client
864 * @param p_w actual scaled width as the driver is capable of
865 * @param p_h actual scaled height as the driver is capable of
869 NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
870 short vid_w, short vid_h,
871 short drw_w, short drw_h,
872 unsigned int *p_w, unsigned int *p_h,
875 if(vid_w > (drw_w << 3))
877 if(vid_h > (drw_h << 3))
886 * used by NVPutImage() function to copy (image)data from
887 * system RAM to VRAM and change data order.
889 * @param src1 source buffer of luma
890 * @param src2 source buffer of chroma1
891 * @param src3 source buffer of chroma2
892 * @param dst1 destination buffer
893 * @param srcPitch pitch of src1
894 * @param srcPitch2 pitch of src2, src3
895 * @param dstPitch pitch of dst1
896 * @param h number of lines to copy
897 * @param w length of lines to copy
899 static inline void NVCopyData420(unsigned char *src1, unsigned char *src2,
900 unsigned char *src3, unsigned char *dst1,
901 int srcPitch, int srcPitch2,
911 for (j = 0; j < h; j++) {
913 s1 = src1; s2 = src2; s3 = src3;
916 while (i > 4) { // wouldn't it be better to write (i >= 4) ?
917 #if X_BYTE_ORDER == X_BIG_ENDIAN
918 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
919 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1];
920 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2];
921 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3];
923 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
924 dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
925 dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
926 dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
928 dst += 4; s2 += 4; s3 += 4; s1 += 8;
933 #if X_BYTE_ORDER == X_BIG_ENDIAN
934 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
936 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
954 * PutImage is "the" important function of the Xv extension.
955 * a client (e.g. video player) calls this function for every
956 * image (of the video) to be displayed. this function then
957 * scales and displays the image.
959 * @param pScrn screen which hold the port where the image is put
968 * @param id colorspace of image
969 * @param buf pointer to buffer containing the source image
974 * @param data pointer to port
978 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
979 short drw_x, short drw_y,
980 short src_w, short src_h,
981 short drw_w, short drw_h,
984 short width, short height,
991 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
992 NVPtr pNv = NVPTR(pScrn);
993 INT32 xa, xb, ya, yb;
994 int newSize, offset, s2offset, s3offset;
995 int srcPitch, srcPitch2, dstPitch;
996 int top, left, right, bottom, npixels, nlines, bpp;
1002 /* s2offset, s3offset - byte offsets into U and V plane of the
1003 * source where copying starts. YV12 is indeed one plane of Y and two subsampled planes of U and V
1004 * offset - byte offset to the first line of the destination.
1005 * dst_start - byte address to the first displayed pel.
1008 if (pPriv->grabbedByV4L)
1011 /* make the compiler happy */
1012 s2offset = s3offset = srcPitch2 = 0;
1014 if (!pPriv->blitter) { /* overlay hardware scaler limitation */
1015 if (src_w > (drw_w << 3))
1017 if (src_h > (drw_h << 3))
1028 dstBox.x2 = drw_x + drw_w;
1030 dstBox.y2 = drw_y + drw_h;
1032 if (!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1036 if (!pPriv->blitter) {
1037 dstBox.x1 -= pScrn->frameX0;
1038 dstBox.x2 -= pScrn->frameX0;
1039 dstBox.y1 -= pScrn->frameY0;
1040 dstBox.y2 -= pScrn->frameY0;
1044 /* determine required memory size */
1045 bpp = pScrn->bitsPerPixel >> 3; // bytes per pixel
1050 srcPitch = (width + 3) & ~3; /* of luma */
1051 s2offset = srcPitch * height;
1052 srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
1053 s3offset = (srcPitch2 * (height >> 1)) + s2offset;
1054 dstPitch = ((width << 1) + 63) & ~63;
1058 srcPitch = width << 1;
1059 dstPitch = ((width << 1) + 63) & ~63;
1062 srcPitch = width << 2;
1063 dstPitch = ((width << 2) + 63) & ~63;
1066 return BadImplementation;
1068 /* dstPitch = number of bytes per row
1069 but the allocation is done is pixel, hence the division to get the real number of bytes */
1070 newSize = height * dstPitch / bpp;
1072 if (pPriv->doubleBuffer) // double buffering ...
1073 newSize <<= 1; // ... means double the amount of VRAM needed
1075 pPriv->video_mem = NVAllocateVideoMemory(pScrn, pPriv->video_mem,
1077 if (!pPriv->video_mem)
1080 offset = pPriv->video_mem->offset;
1081 if (pPriv->doubleBuffer) {
1082 int mask = 1 << (pPriv->currentBuffer << 2);
1084 /* overwrite the newest buffer if there's not one free */
1085 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1086 if (!pPriv->currentBuffer)
1087 offset += (height + 1) * dstPitch;
1091 if (pPriv->currentBuffer)
1092 offset += (height + 1) * dstPitch;
1096 /* We need to enlarge the copied rectangle by a pixel so the HW
1097 * filtering doesn't pick up junk laying outside of the source */
1098 /* fixed point arithmetic */
1099 left = (xa - 0x00010000) >> 16;
1100 if (left < 0) left = 0;
1101 top = (ya - 0x00010000) >> 16;
1102 if (top < 0) top = 0;
1103 right = (xb + 0x0001ffff) >> 16;
1104 if (right > width) right = width;
1105 bottom = (yb + 0x0001ffff) >> 16;
1106 if (bottom > height) bottom = height;
1108 if(pPriv->blitter) NVSync(pScrn);
1115 npixels = ((right + 1) & ~1) - left;
1117 nlines = ((bottom + 1) & ~1) - top;
1119 offset += (left << 1) + (top * dstPitch);
1120 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1123 if (id == FOURCC_I420) {
1125 s2offset = s3offset;
1128 line_len = dstPitch;
1133 npixels = ((right + 1) & ~1) - left;
1134 nlines = bottom - top;
1137 buf += (top * srcPitch) + left;
1138 offset += left + (top * dstPitch);
1139 line_len = width << 1;
1142 npixels = right - left;
1143 nlines = bottom - top;
1145 buf += (top * srcPitch) + left;
1146 offset += left + (top * dstPitch);
1147 line_len = width << 2;
1150 return BadImplementation;
1153 //xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Got fence handle %lld\n", fence_id);
1155 /*Now we take a decision regarding the way we send the data to the card.
1156 Either we use double buffering of "private" TT memory
1157 Either we rely on X's GARTScratch
1158 Either we fallback on CPU copy
1161 pPriv->TT_mem_chunk[0] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[0],
1163 pPriv->TT_mem_chunk[1] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[1],
1167 NVAllocRec * destination_buffer;
1168 unsigned char * video_mem_destination;
1170 if ( pPriv->TT_mem_chunk[pPriv->currentHostBuffer] )
1172 destination_buffer = pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1173 //xf86DrvMsg(0, X_INFO, "Using private TT memory chunk #%d\n", pPriv->currentHostBuffer);
1177 destination_buffer = pNv->GARTScratch;
1178 //xf86DrvMsg(0, X_INFO, "Using global GART memory chunk\n");
1179 //destination_buffer = NULL;
1182 if ( !destination_buffer)
1185 if(nlines * line_len <= destination_buffer->size)
1187 unsigned char *dst = destination_buffer->map;
1189 /* Upload to GART */
1194 NVCopyData420(buf + (top * srcPitch) + left,
1195 buf + s2offset, buf + s3offset,
1196 dst, srcPitch, srcPitch2,
1197 dstPitch, nlines, npixels);
1203 memcpy(dst, buf, srcPitch * nlines);
1206 return BadImplementation;
1209 if ( !pPriv -> blitter )
1211 NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_DMA_OBJECT_IN, 2);
1212 NVDmaNext (pNv, NvDmaTT);
1213 NVDmaNext (pNv, NvDmaFB);
1214 pNv->M2MFDirection = 1;
1218 NVDmaStart(pNv, NvSubMemFormat,
1219 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1220 NVDmaNext (pNv, (uint32_t)destination_buffer->offset);
1221 NVDmaNext (pNv, (uint32_t)offset);
1222 NVDmaNext (pNv, line_len);
1223 NVDmaNext (pNv, dstPitch);
1224 NVDmaNext (pNv, line_len);
1225 NVDmaNext (pNv, nlines);
1226 NVDmaNext (pNv, (1<<8)|1);
1229 if ( destination_buffer == pNv->GARTScratch )
1231 NVNotifierReset(pScrn, pNv->Notifier0);
1232 NVDmaStart(pNv, NvSubMemFormat,
1233 NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1237 NVDmaStart(pNv, NvSubMemFormat, 0x100, 1);
1241 if ( destination_buffer == pNv->GARTScratch )
1242 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 0))
1247 NVDmaStart(pNv, NvSubScaledImage, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
1248 NVDmaNext (pNv, NvDmaTT); /* source object */
1250 NVPutBlitImage(pScrn, destination_buffer->offset, id,
1254 src_w, src_h, drw_w, drw_h,
1257 if ( destination_buffer == pNv->GARTScratch )
1259 NVNotifierReset(pScrn, pNv->Notifier0);
1260 NVDmaStart(pNv, NvSubScaledImage,
1261 NV10_IMAGE_BLIT_NOTIFY, 1);
1265 NVDmaStart(pNv, NvSubScaledImage, 0x100, 1);
1268 NVDmaStart(pNv, NvSubScaledImage, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
1269 NVDmaNext (pNv, NvDmaFB); /* source object */
1272 if ( destination_buffer == pNv->GARTScratch )
1273 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 0))
1278 else { //GART is too small, we fallback on CPU copy for simplicity
1280 video_mem_destination = pPriv->video_mem->map + (offset - (uint32_t)pPriv->video_mem->offset);
1286 NVCopyData420(buf + (top * srcPitch) + left,
1287 buf + s2offset, buf + s3offset,
1288 video_mem_destination, srcPitch, srcPitch2,
1289 dstPitch, nlines, npixels);
1295 memcpy(video_mem_destination, buf, srcPitch * nlines);
1298 return BadImplementation;
1302 pPriv->currentHostBuffer ^= 1;
1305 if (pPriv->blitter) {
1306 NVPutBlitImage(pScrn, offset, id,
1310 src_w, src_h, drw_w, drw_h,
1313 NVPutOverlayImage(pScrn, offset, id,
1317 src_w, src_h, drw_w, drw_h,
1319 pPriv->currentBuffer ^= 1;
1328 * QueryImageAttributes
1331 * - size (memory required to store image),
1335 * depending on colorspace (id) and dimensions (w,h) of image
1339 * may be adjusted as needed
1341 * @param pScrn unused
1342 * @param id colorspace of image
1343 * @param w pointer to width of image
1344 * @param h pointer to height of image
1345 * @param pitches pitches[i] = length of a scanline in plane[i]
1346 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1347 * @return size of the memory required for the XvImage queried
1350 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1351 unsigned short *w, unsigned short *h,
1352 int *pitches, int *offsets)
1356 if (*w > IMAGE_MAX_W)
1358 if (*h > IMAGE_MAX_H)
1361 *w = (*w + 1) & ~1; // width rounded up to an even number
1368 *h = (*h + 1) & ~1; // height rounded up to an even number
1369 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1371 pitches[0] = size; // width rounded up to a multiple of 4
1374 offsets[1] = size; // number of pixels in "rounded up" image
1375 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1377 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1378 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1379 size += tmp; // 5/4*number of pixels in "rounded up" image
1381 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1382 size += tmp; // = 3/2*number of pixels in "rounded up" image
1386 size = *w << 1; // 2*width
1388 pitches[0] = size; // 2*width
1389 size *= *h; // 2*width*height
1392 size = *w << 2; // 4*width (32 bit per pixel)
1394 pitches[0] = size; // 4*width
1395 size *= *h; // 4*width*height
1405 /***** Exported offscreen surface stuff ****/
1409 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1410 unsigned short w, unsigned short h,
1411 XF86SurfacePtr surface)
1413 NVPtr pNv = NVPTR(pScrn);
1414 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1417 bpp = pScrn->bitsPerPixel >> 3;
1419 if (pPriv->grabbedByV4L)
1422 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1426 pPriv->pitch = ((w << 1) + 63) & ~63;
1427 size = h * pPriv->pitch / bpp;
1429 pPriv->video_mem = NVAllocateVideoMemory(pScrn,
1432 if (!pPriv->video_mem)
1438 surface->height = h;
1439 surface->pScrn = pScrn;
1440 surface->pitches = &pPriv->pitch;
1441 surface->offsets = &pPriv->offset;
1442 surface->devPrivate.ptr = (pointer)pPriv;
1445 /* grab the video */
1446 NVStopOverlay(pScrn);
1447 pPriv->videoStatus = 0;
1448 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1449 pPriv->grabbedByV4L = TRUE;
1455 NVStopSurface(XF86SurfacePtr surface)
1457 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1459 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
1460 NVStopOverlay(surface->pScrn);
1461 pPriv->videoStatus = 0;
1468 NVFreeSurface(XF86SurfacePtr surface)
1470 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1472 if (pPriv->grabbedByV4L) {
1473 NVStopSurface(surface);
1474 NVFreeOverlayMemory(surface->pScrn);
1475 pPriv->grabbedByV4L = FALSE;
1482 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
1484 NVPtr pNv = NVPTR(pScrn);
1485 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1487 return NVGetOverlayPortAttribute(pScrn, attribute,
1488 value, (pointer)pPriv);
1492 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
1494 NVPtr pNv = NVPTR(pScrn);
1495 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1497 return NVSetOverlayPortAttribute(pScrn, attribute,
1498 value, (pointer)pPriv);
1502 NVDisplaySurface(XF86SurfacePtr surface,
1503 short src_x, short src_y,
1504 short drw_x, short drw_y,
1505 short src_w, short src_h,
1506 short drw_w, short drw_h,
1507 RegionPtr clipBoxes)
1509 ScrnInfoPtr pScrn = surface->pScrn;
1510 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1511 INT32 xa, xb, ya, yb;
1514 if (!pPriv->grabbedByV4L)
1517 if (src_w > (drw_w << 3))
1519 if (src_h > (drw_h << 3))
1529 dstBox.x2 = drw_x + drw_w;
1531 dstBox.y2 = drw_y + drw_h;
1533 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1534 surface->width, surface->height))
1537 dstBox.x1 -= pScrn->frameX0;
1538 dstBox.x2 -= pScrn->frameX0;
1539 dstBox.y1 -= pScrn->frameY0;
1540 dstBox.y2 -= pScrn->frameY0;
1542 pPriv->currentBuffer = 0;
1544 NVPutOverlayImage(pScrn, surface->offsets[0], surface->id,
1545 surface->pitches[0], &dstBox, xa, ya, xb, yb,
1546 surface->width, surface->height, src_w, src_h,
1547 drw_w, drw_h, clipBoxes);
1554 * this function does all the work setting up a blit port
1558 static XF86VideoAdaptorPtr
1559 NVSetupBlitVideo (ScreenPtr pScreen)
1561 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1562 NVPtr pNv = NVPTR(pScrn);
1563 XF86VideoAdaptorPtr adapt;
1564 NVPortPrivPtr pPriv;
1567 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1568 sizeof(NVPortPrivRec) +
1569 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
1573 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1575 adapt->name = "NV Video Blitter";
1576 adapt->nEncodings = 1;
1577 adapt->pEncodings = &DummyEncoding;
1578 adapt->nFormats = NUM_FORMATS_ALL;
1579 adapt->pFormats = NVFormats;
1580 adapt->nPorts = NUM_BLIT_PORTS;
1581 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1583 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
1584 for(i = 0; i < NUM_BLIT_PORTS; i++)
1585 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1587 if(pNv->WaitVSyncPossible) {
1588 adapt->pAttributes = NVBlitAttributes;
1589 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
1591 adapt->pAttributes = NULL;
1592 adapt->nAttributes = 0;
1595 adapt->pImages = NVImages;
1596 adapt->nImages = NUM_IMAGES_ALL;
1597 adapt->PutVideo = NULL;
1598 adapt->PutStill = NULL;
1599 adapt->GetVideo = NULL;
1600 adapt->GetStill = NULL;
1601 adapt->StopVideo = NVStopBlitVideo;
1602 adapt->SetPortAttribute = NVSetBlitPortAttribute;
1603 adapt->GetPortAttribute = NVGetBlitPortAttribute;
1604 adapt->QueryBestSize = NVQueryBestSize;
1605 adapt->PutImage = NVPutImage;
1606 adapt->QueryImageAttributes = NVQueryImageAttributes;
1608 pPriv->videoStatus = 0;
1609 pPriv->grabbedByV4L = FALSE;
1610 pPriv->blitter = TRUE;
1611 pPriv->doubleBuffer = FALSE;
1612 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1614 pNv->blitAdaptor = adapt;
1615 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
1621 * NV10SetupOverlayVideo
1622 * this function does all the work setting up an overlay port
1624 * @return overlay port
1625 * @see NVResetVideo(ScrnInfoPtr pScrn)
1627 static XF86VideoAdaptorPtr
1628 NV10SetupOverlayVideo(ScreenPtr pScreen)
1630 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1631 NVPtr pNv = NVPTR(pScrn);
1632 XF86VideoAdaptorPtr adapt;
1633 NVPortPrivPtr pPriv;
1635 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1636 sizeof(NVPortPrivRec) +
1637 sizeof(DevUnion)))) {
1641 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1642 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
1643 adapt->name = "NV Video Overlay";
1644 adapt->nEncodings = 1;
1645 adapt->pEncodings = &DummyEncoding;
1646 adapt->nFormats = NUM_FORMATS_ALL;
1647 adapt->pFormats = NVFormats;
1649 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1651 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
1652 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
1654 adapt->pAttributes = NVOverlayAttributes;
1655 adapt->nAttributes = NUM_OVERLAY_ATTRIBUTES;
1656 adapt->pImages = NVImages;
1657 adapt->nImages = NUM_IMAGES_YUV;
1658 adapt->PutVideo = NULL;
1659 adapt->PutStill = NULL;
1660 adapt->GetVideo = NULL;
1661 adapt->GetStill = NULL;
1662 adapt->StopVideo = NVStopOverlayVideo;
1663 adapt->SetPortAttribute = NVSetOverlayPortAttribute;
1664 adapt->GetPortAttribute = NVGetOverlayPortAttribute;
1665 adapt->QueryBestSize = NVQueryBestSize;
1666 adapt->PutImage = NVPutImage;
1667 adapt->QueryImageAttributes = NVQueryImageAttributes;
1669 pPriv->videoStatus = 0;
1670 pPriv->currentBuffer = 0;
1671 pPriv->grabbedByV4L = FALSE;
1672 pPriv->blitter = FALSE;
1674 NVSetPortDefaults (pScrn, pPriv);
1676 /* gotta uninit this someplace */
1677 REGION_NULL(pScreen, &pPriv->clip);
1679 pNv->overlayAdaptor = adapt;
1681 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
1682 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
1683 xvContrast = MAKE_ATOM("XV_CONTRAST");
1684 xvColorKey = MAKE_ATOM("XV_COLORKEY");
1685 xvSaturation = MAKE_ATOM("XV_SATURATION");
1686 xvHue = MAKE_ATOM("XV_HUE");
1687 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
1688 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
1689 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
1691 NVResetVideo(pScrn);
1696 XF86OffscreenImageRec NVOffscreenImages[2] = {
1699 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1704 NVGetSurfaceAttribute,
1705 NVSetSurfaceAttribute,
1706 IMAGE_MAX_W, IMAGE_MAX_H,
1707 NUM_OVERLAY_ATTRIBUTES - 1,
1708 &NVOverlayAttributes[1]
1712 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1717 NVGetSurfaceAttribute,
1718 NVSetSurfaceAttribute,
1719 IMAGE_MAX_W, IMAGE_MAX_H,
1720 NUM_OVERLAY_ATTRIBUTES - 1,
1721 &NVOverlayAttributes[1]
1726 NVInitOffscreenImages (ScreenPtr pScreen)
1728 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
1732 * NVChipsetHasOverlay
1734 * newer chips don't support overlay anymore.
1735 * overlay feature is emulated via textures.
1738 * @return true, if chipset supports overlay
1741 NVChipsetHasOverlay(NVPtr pNv)
1743 switch (pNv->Architecture) {
1749 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
1760 * NVSetupOverlayVideo
1761 * check if chipset supports Overlay and CompositeExtension is disabled.
1762 * if so, setup overlay port
1764 * @return overlay port
1765 * @see NVChipsetHasOverlay(NVPtr pNv)
1766 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
1767 * @see NVInitOffscreenImages(ScreenPtr pScreen)
1769 static XF86VideoAdaptorPtr
1770 NVSetupOverlayVideo(ScreenPtr pScreen)
1772 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1773 XF86VideoAdaptorPtr overlayAdaptor = NULL;
1774 NVPtr pNv = NVPTR(pScrn);
1776 if (!NVChipsetHasOverlay(pNv))
1779 /*XXX: Do we still want to provide the overlay anyway, but make the
1780 * blit adaptor the default if composite is enabled?
1783 if (!noCompositeExtension) {
1784 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1785 "XV: Video overlay not available, composite enabled\n");
1789 overlayAdaptor = NV10SetupOverlayVideo(pScreen);
1791 NVInitOffscreenImages(pScreen);
1793 return overlayAdaptor;
1798 * tries to initialize one new overlay port and one new blit port
1799 * and add them to the list of ports on screen "pScreen".
1802 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
1803 * @see NVSetupBlitVideo(ScreenPtr pScreen)
1805 void NVInitVideo (ScreenPtr pScreen)
1807 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1808 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
1809 XF86VideoAdaptorPtr overlayAdaptor = NULL;
1810 XF86VideoAdaptorPtr blitAdaptor = NULL;
1813 if (pScrn->bitsPerPixel == 8)
1816 overlayAdaptor = NVSetupOverlayVideo(pScreen);
1817 blitAdaptor = NVSetupBlitVideo(pScreen);
1819 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
1820 if(blitAdaptor || overlayAdaptor) {
1821 int size = num_adaptors;
1823 if(overlayAdaptor) size++;
1824 if(blitAdaptor) size++;
1826 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
1829 memcpy(newAdaptors, adaptors, num_adaptors *
1830 sizeof(XF86VideoAdaptorPtr));
1833 if(overlayAdaptor) {
1834 newAdaptors[num_adaptors] = overlayAdaptor;
1839 newAdaptors[num_adaptors] = blitAdaptor;
1843 adaptors = newAdaptors;
1848 xf86XVScreenInit(pScreen, adaptors, num_adaptors);