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 } NVPortPrivRec, *NVPortPrivPtr;
62 #define GET_OVERLAY_PRIVATE(pNv) \
63 (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr)
65 #define GET_BLIT_PRIVATE(pNv) \
66 (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr)
68 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
70 static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
71 xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
72 xvITURBT709, xvSyncToVBlank;
74 /* client libraries expect an encoding */
75 static XF86VideoEncodingRec DummyEncoding =
79 IMAGE_MAX_W, IMAGE_MAX_H,
83 #define NUM_FORMATS_ALL 6
85 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
87 {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
88 {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
91 #define NUM_OVERLAY_ATTRIBUTES 9
92 XF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] =
94 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
95 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
96 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
97 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
98 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
99 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
100 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
101 {XvSettable | XvGettable, 0, 360, "XV_HUE"},
102 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"}
105 #define NUM_BLIT_ATTRIBUTES 2
106 XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
108 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
109 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
113 #define NUM_IMAGES_YUV 4
114 #define NUM_IMAGES_ALL 5
116 #define FOURCC_RGB 0x0000003
117 #define XVIMAGE_RGB \
122 { 0x03, 0x00, 0x00, 0x00, \
123 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
127 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
132 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}, \
136 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
147 * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
149 * @param pScrn screen to get the default colorKey from
150 * @param pPriv port to reset to defaults
153 NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
155 NVPtr pNv = NVPTR(pScrn);
157 pPriv->brightness = 0;
158 pPriv->contrast = 4096;
159 pPriv->saturation = 4096;
161 pPriv->colorKey = pNv->videoKey;
162 pPriv->autopaintColorKey = TRUE;
163 pPriv->doubleBuffer = TRUE;
164 pPriv->iturbt_709 = FALSE;
169 * writes the current attributes from the overlay port to the hardware
172 NVResetVideo (ScrnInfoPtr pScrn)
174 NVPtr pNv = NVPTR(pScrn);
175 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
176 int satSine, satCosine;
179 angle = (double)pPriv->hue * 3.1415927 / 180.0;
181 satSine = pPriv->saturation * sin(angle);
184 satCosine = pPriv->saturation * cos(angle);
185 if (satCosine < -1024)
188 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
190 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
192 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
193 (satCosine & 0xffff));
194 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
195 (satCosine & 0xffff));
196 nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
201 * Tell the hardware to stop the overlay
204 NVStopOverlay (ScrnInfoPtr pScrn)
206 NVPtr pNv = NVPTR(pScrn);
208 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
212 * NVAllocateOverlayMemory
215 * - why does the funciton have "Overlay" in its name? It does not
216 * have anything "Overlay"-specific in its function body and it is called by
217 * non-"Overlay"-specific functions.
218 * TODO: rename to something like NVAllocateVideoMemory or NVAllocateXvMemory
219 * - the function only (re-)allocates memory if it absolutely necessary,
220 * that is, if the requested size is larger than the current size. that means,
221 * that the size of allocated memory never shrinks, even if the requested
222 * does. from a performance point of view this is most likely the best
223 * alternative. but how often does the requested size of memory for video
224 * playback change? whenever video-size/scaling changes? probably not very
225 * often. so maybe sacrifice a tiny bit of performance (whenever the video is
226 * rescaled) and not waste (RAM-)resources?
227 * - the function makes assumptions about the XAA fb manager being used. isn't
228 * there a way to check? what aboaut EXA?
230 * @param pScrn screen which requests the memory
231 * @param mem pointer to previously allocated memory for reallocation
232 * @param size size of requested memory segment
233 * @return pointer to the allocated memory
236 NVAllocateOverlayMemory(ScrnInfoPtr pScrn, NVAllocRec *mem, int size)
238 NVPtr pNv = NVPTR(pScrn);
240 /* The code assumes the XAA fb manager is being used here,
241 * which allocates in pixels. We allocate in bytes so we
242 * need to adjust the size here.
244 size *= (pScrn->bitsPerPixel >> 3);
247 if(mem->size >= size) // if(mem->size == size)
249 NVFreeMemory(pNv, mem);
252 return NVAllocateMemory(pNv, NOUVEAU_MEM_FB, size); /* align 32? */
256 * NVFreeOverlayMemory
257 * frees memory held by the overlay port
258 * this function (unlike NVAllocateOverlayMemory) is "Overlay"-specific
260 * @param pScrn screen whose overlay port wants to free memory
263 NVFreeOverlayMemory(ScrnInfoPtr pScrn)
265 NVPtr pNv = NVPTR(pScrn);
266 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
268 if(pPriv->video_mem) {
269 NVFreeMemory(pNv, pPriv->video_mem);
270 pPriv->video_mem = NULL;
276 * frees memory held by the blit port
278 * @param pScrn screen whose blit port wants to free memory
281 NVFreeBlitMemory(ScrnInfoPtr pScrn)
283 NVPtr pNv = NVPTR(pScrn);
284 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
286 if(pPriv->video_mem) {
287 NVFreeMemory(pNv, pPriv->video_mem);
288 pPriv->video_mem = NULL;
293 * NVVideoTimerCallback
294 * callback function which perform cleanup tasks (stop overlay, free memory).
295 * within the driver it is only called once from NVBlockHandler in nv_driver.c
298 NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
300 NVPtr pNv = NVPTR(pScrn);
301 NVPortPrivPtr pOverPriv = NULL;
302 NVPortPrivPtr pBlitPriv = NULL;
303 Bool needCallback = FALSE;
308 if (pNv->overlayAdaptor) {
309 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
310 if (!pOverPriv->videoStatus)
314 if (pNv->blitAdaptor) {
315 pBlitPriv = GET_BLIT_PRIVATE(pNv);
316 if (!pBlitPriv->videoStatus)
321 if (pOverPriv->videoTime < currentTime) {
322 if (pOverPriv->videoStatus & OFF_TIMER) {
323 NVStopOverlay(pScrn);
324 pOverPriv->videoStatus = FREE_TIMER;
325 pOverPriv->videoTime = currentTime + FREE_DELAY;
328 if (pOverPriv->videoStatus & FREE_TIMER) {
329 NVFreeOverlayMemory(pScrn);
330 pOverPriv->videoStatus = 0;
338 if (pBlitPriv->videoTime < currentTime) {
339 NVFreeBlitMemory(pScrn);
340 pBlitPriv->videoStatus = 0;
346 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
351 * program hardware to overlay image into front buffer
353 * @param pScrn screen
355 * @param id colorspace of image
371 NVPutOverlayImage(ScrnInfoPtr pScrn, int offset, int id,
372 int dstPitch, BoxPtr dstBox,
373 int x1, int y1, int x2, int y2,
374 short width, short height,
375 short src_w, short src_h,
376 short drw_w, short drw_h,
379 NVPtr pNv = NVPTR(pScrn);
380 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
381 int buffer = pPriv->currentBuffer;
383 /* paint the color key */
384 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
385 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
386 /* we always paint V4L's color key */
387 if (!pPriv->grabbedByV4L)
388 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
389 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
392 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
398 nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer) , offset);
399 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer) , (height << 16) | width);
400 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
401 ((y1 << 4) & 0xffff0000) | (x1 >> 12));
402 nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer) , (src_w << 20) / drw_w);
403 nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer) , (src_h << 20) / drw_h);
404 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
405 (dstBox->y1 << 16) | dstBox->x1);
406 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
407 ((dstBox->y2 - dstBox->y1) << 16) |
408 (dstBox->x2 - dstBox->x1));
410 dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; /* use color key */
411 if(id != FOURCC_UYVY)
412 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
413 if(pPriv->iturbt_709)
414 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
416 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
417 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
418 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
420 pPriv->videoStatus = CLIENT_VIDEO_ON;
423 #ifndef ExaOffscreenMarkUsed
424 extern void ExaOffscreenMarkUsed(PixmapPtr);
426 #ifndef exaGetDrawablePixmap
427 extern PixmapPtr exaGetDrawablePixmap(DrawablePtr);
429 #ifndef exaPixmapIsOffscreen
430 extern Bool exaPixmapIsOffscreen(PixmapPtr p);
432 /* To support EXA 2.0, 2.1 has this in the header */
433 #ifndef exaMoveInPixmap
434 extern void exaMoveInPixmap(PixmapPtr pPixmap);
440 * @param pScrn screen
442 * @param id colorspace of image
459 NVPutBlitImage(ScrnInfoPtr pScrn, int src_offset, int id,
460 int src_pitch, BoxPtr dstBox,
461 int x1, int y1, int x2, int y2,
462 short width, short height,
463 short src_w, short src_h,
464 short drw_w, short drw_h,
468 NVPtr pNv = NVPTR(pScrn);
469 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
473 CARD32 dst_size, dst_point;
474 CARD32 src_point, src_format;
477 ScreenPtr pScreen = pScrn->pScreen;
478 PixmapPtr pPix = exaGetDrawablePixmap(pDraw);
481 /* Try to get the dest drawable into vram */
482 if (!exaPixmapIsOffscreen(pPix)) {
483 exaMoveInPixmap(pPix);
484 ExaOffscreenMarkUsed(pPix);
487 /* If we failed, draw directly onto the screen pixmap.
488 * Not sure if this is the best approach, maybe failing
489 * with BadAlloc would be better?
491 if (!exaPixmapIsOffscreen(pPix)) {
492 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
493 "XV: couldn't move dst surface into vram\n");
494 pPix = pScreen->GetScreenPixmap(pScreen);
497 NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format);
498 NVAccelSetCtxSurf2D(pPix, pPix, dst_format);
501 /* Adjust coordinates if drawing to an offscreen pixmap */
502 if (pPix->screen_x || pPix->screen_y) {
503 REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
506 dstBox->x1 -= pPix->screen_x;
507 dstBox->x2 -= pPix->screen_x;
508 dstBox->y1 -= pPix->screen_y;
509 dstBox->y2 -= pPix->screen_y;
512 DamageDamageRegion((DrawablePtr)pPix, clipBoxes);
515 if (pNv->CurrentLayout.depth == 15) {
516 NVDmaStart(pNv, NvSubContextSurfaces,
518 NVDmaNext (pNv, SURFACE_FORMAT_X1R5G5B5);
522 pbox = REGION_RECTS(clipBoxes);
523 nbox = REGION_NUM_RECTS(clipBoxes);
525 dsdx = (src_w << 20) / drw_w;
526 dtdy = (src_h << 20) / drw_h;
528 dst_size = ((dstBox->y2 - dstBox->y1) << 16) |
529 (dstBox->x2 - dstBox->x1);
530 dst_point = (dstBox->y1 << 16) | dstBox->x1;
532 src_pitch |= (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER << 16) |
533 (STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR << 24);
534 src_point = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
538 src_format = STRETCH_BLIT_FORMAT_X8R8G8B8;
541 src_format = STRETCH_BLIT_FORMAT_UYVY;
544 src_format = STRETCH_BLIT_FORMAT_YUYV;
548 if(pPriv->SyncToVBlank) {
553 if(pNv->BlendingPossible) {
554 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_FORMAT, 2);
555 NVDmaNext (pNv, src_format);
556 NVDmaNext (pNv, STRETCH_BLIT_OPERATION_COPY);
558 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_FORMAT, 1);
559 NVDmaNext (pNv, src_format);
562 NVDmaStart(pNv, NvSubScaledImage,
563 NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
564 NVDmaNext (pNv, NvDmaTT); /* source object */
567 NVDmaStart(pNv, NvSubRectangle, RECT_SOLID_COLOR, 1);
570 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_CLIP_POINT, 6);
571 NVDmaNext (pNv, (pbox->y1 << 16) | pbox->x1);
572 NVDmaNext (pNv, ((pbox->y2 - pbox->y1) << 16) |
573 (pbox->x2 - pbox->x1));
574 NVDmaNext (pNv, dst_point);
575 NVDmaNext (pNv, dst_size);
576 NVDmaNext (pNv, dsdx);
577 NVDmaNext (pNv, dtdy);
579 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_SRC_SIZE, 4);
580 NVDmaNext (pNv, (height << 16) | width);
581 NVDmaNext (pNv, src_pitch);
582 NVDmaNext (pNv, src_offset);
583 NVDmaNext (pNv, src_point);
588 if(pNv->CurrentLayout.depth == 15) {
589 NVDmaStart(pNv, NvSubContextSurfaces,
591 NVDmaNext (pNv, SURFACE_FORMAT_R5G6B5);
598 exaMarkSync(pScrn->pScreen);
600 SET_SYNC_FLAG(pNv->AccelInfoRec);
602 pPriv->videoStatus = FREE_TIMER;
603 pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
604 pNv->VideoTimerCallback = NVVideoTimerCallback;
611 NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
613 NVPtr pNv = NVPTR(pScrn);
614 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
616 if(pPriv->grabbedByV4L) return;
618 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
621 if (pPriv->videoStatus & CLIENT_VIDEO_ON)
622 NVStopOverlay(pScrn);
623 NVFreeOverlayMemory(pScrn);
624 pPriv->videoStatus = 0;
626 if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
627 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
628 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
629 pNv->VideoTimerCallback = NVVideoTimerCallback;
639 NVStopBlitVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
644 * NVSetOverlayPortAttribute
645 * sets the attribute "attribute" of port "data" to value "value"
646 * calls NVResetVideo(pScrn) to apply changes to hardware
649 * @param attribute attribute to set
650 * @param value value to which attribute is to be set
651 * @param data port from which the attribute is to be set
653 * @return Success, if setting is successful
654 * BadValue/BadMatch, if value/attribute are invalid
655 * @see NVResetVideo(ScrnInfoPtr pScrn)
658 NVSetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
659 INT32 value, pointer data)
661 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
663 if (attribute == xvBrightness) {
664 if ((value < -512) || (value > 512))
666 pPriv->brightness = value;
668 if (attribute == xvDoubleBuffer) {
669 if ((value < 0) || (value > 1))
671 pPriv->doubleBuffer = value;
673 if (attribute == xvContrast) {
674 if ((value < 0) || (value > 8191))
676 pPriv->contrast = value;
678 if (attribute == xvHue) {
684 if (attribute == xvSaturation) {
685 if ((value < 0) || (value > 8191))
687 pPriv->saturation = value;
689 if (attribute == xvColorKey) {
690 pPriv->colorKey = value;
691 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
693 if (attribute == xvAutopaintColorKey) {
694 if ((value < 0) || (value > 1))
696 pPriv->autopaintColorKey = value;
698 if (attribute == xvITURBT709) {
699 if ((value < 0) || (value > 1))
701 pPriv->iturbt_709 = value;
703 if (attribute == xvSetDefaults) {
704 NVSetPortDefaults(pScrn, pPriv);
713 * NVGetOverlayPortAttribute
715 * @param pScrn unused
716 * @param attribute attribute to be read
717 * @param value value of attribute will be stored in this pointer
718 * @param data port from which attribute will be read
719 * @return Success, if queried attribute exists
722 NVGetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
723 INT32 *value, pointer data)
725 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
727 if (attribute == xvBrightness)
728 *value = pPriv->brightness;
729 else if (attribute == xvDoubleBuffer)
730 *value = (pPriv->doubleBuffer) ? 1 : 0;
731 else if (attribute == xvContrast)
732 *value = pPriv->contrast;
733 else if (attribute == xvSaturation)
734 *value = pPriv->saturation;
735 else if (attribute == xvHue)
737 else if (attribute == xvColorKey)
738 *value = pPriv->colorKey;
739 else if (attribute == xvAutopaintColorKey)
740 *value = (pPriv->autopaintColorKey) ? 1 : 0;
741 else if (attribute == xvITURBT709)
742 *value = (pPriv->iturbt_709) ? 1 : 0;
750 * NVSetBlitPortAttribute
751 * sets the attribute "attribute" of port "data" to value "value"
752 * supported attributes:
753 * - xvSyncToVBlank (values: 0,1)
754 * - xvSetDefaults (values: NA; SyncToVBlank will be set, if hardware supports it)
757 * @param attribute attribute to set
758 * @param value value to which attribute is to be set
759 * @param data port from which the attribute is to be set
761 * @return Success, if setting is successful
762 * BadValue/BadMatch, if value/attribute are invalid
765 NVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
766 INT32 value, pointer data)
768 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
769 NVPtr pNv = NVPTR(pScrn);
771 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
772 if ((value < 0) || (value > 1))
774 pPriv->SyncToVBlank = value;
776 if (attribute == xvSetDefaults) {
777 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
785 * NVGetBlitPortAttribute
786 * reads the value of attribute "attribute" from port "data" into INT32 "*value"
787 * currently only one attribute supported: xvSyncToVBlank
789 * @param pScrn unused
790 * @param attribute attribute to be read
791 * @param value value of attribute will be stored here
792 * @param data port from which attribute will be read
793 * @return Success, if queried attribute exists
796 NVGetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
797 INT32 *value, pointer data)
799 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
801 if(attribute == xvSyncToVBlank)
802 *value = (pPriv->SyncToVBlank) ? 1 : 0;
812 * used by client applications to ask the driver:
813 * how would you actually scale a video of dimensions
814 * vid_w, vid_h, if i wanted you to scale it to dimensions
816 * function stores actual scaling size in pointers p_w, p_h.
818 * - currently the image cannot be scaled to less than
819 * 1/8th of the original size in either dimension. why?
820 * - what happens if the client requests a scaling to a larger value than
821 * the hardware is capable of (IMAGE_MAX_W, IMAGE_MAX_H)?
823 * @param pScrn unused
824 * @param motion unused
825 * @param vid_w width of source video
826 * @param vid_h height of source video
827 * @param drw_w desired scaled width as requested by client
828 * @param drw_h desired scaled height as requested by client
829 * @param p_w actual scaled width as the driver is capable of
830 * @param p_h actual scaled height as the driver is capable of
834 NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
835 short vid_w, short vid_h,
836 short drw_w, short drw_h,
837 unsigned int *p_w, unsigned int *p_h,
840 if(vid_w > (drw_w << 3))
842 if(vid_h > (drw_h << 3))
851 * used by NVPutImage() function to copy (image)data from
852 * system RAM to VRAM and change data order.
854 * @param src1 source buffer of luma
855 * @param src2 source buffer of chroma1
856 * @param src3 source buffer of chroma2
857 * @param dst1 destination buffer
858 * @param srcPitch pitch of src1
859 * @param srcPitch2 pitch of src2, src3
860 * @param dstPitch pitch of dst1
861 * @param h number of lines to copy
862 * @param w length of lines to copy
864 static inline void NVCopyData420(unsigned char *src1, unsigned char *src2,
865 unsigned char *src3, unsigned char *dst1,
866 int srcPitch, int srcPitch2,
876 for (j = 0; j < h; j++) {
878 s1 = src1; s2 = src2; s3 = src3;
881 while (i > 4) { // wouldn't it be better to write (i >= 4) ?
882 #if X_BYTE_ORDER == X_BIG_ENDIAN
883 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
884 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1];
885 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2];
886 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3];
888 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
889 dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
890 dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
891 dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
893 dst += 4; s2 += 4; s3 += 4; s1 += 8;
898 #if X_BYTE_ORDER == X_BIG_ENDIAN
899 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
901 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
919 * PutImage is "the" important function of the Xv extention.
920 * a client (e.g. video player) calls this function for every
921 * image (of the video) to be displayed. this function then
922 * scales and displays the image.
924 * @param pScrn screen which hold the port where the image is put
933 * @param id colorspace of image
934 * @param buf pointer to buffer containing the source image
939 * @param data pointer to port
943 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
944 short drw_x, short drw_y,
945 short src_w, short src_h,
946 short drw_w, short drw_h,
949 short width, short height,
956 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
957 NVPtr pNv = NVPTR(pScrn);
958 INT32 xa, xb, ya, yb;
959 int newSize, offset, s2offset, s3offset;
960 int srcPitch, srcPitch2, dstPitch;
961 int top, left, right, bottom, npixels, nlines, bpp;
967 /* s2offset, s3offset - byte offsets into U and V plane of the
968 * source where copying starts. YV12 is indeed one plane of Y and two subsampled planes of U and V
969 * offset - byte offset to the first line of the destination.
970 * dst_start - byte address to the first displayed pel.
973 if (pPriv->grabbedByV4L)
976 /* make the compiler happy */
977 s2offset = s3offset = srcPitch2 = 0;
979 if (!pPriv->blitter) { /* overlay hardware scaler limitation */
980 if (src_w > (drw_w << 3))
982 if (src_h > (drw_h << 3))
993 dstBox.x2 = drw_x + drw_w;
995 dstBox.y2 = drw_y + drw_h;
997 if (!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1001 if (!pPriv->blitter) {
1002 dstBox.x1 -= pScrn->frameX0;
1003 dstBox.x2 -= pScrn->frameX0;
1004 dstBox.y1 -= pScrn->frameY0;
1005 dstBox.y2 -= pScrn->frameY0;
1009 /* determine required memory size */
1010 bpp = pScrn->bitsPerPixel >> 3; // bytes per pixel
1015 srcPitch = (width + 3) & ~3; /* of luma */
1016 s2offset = srcPitch * height;
1017 srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
1018 s3offset = (srcPitch2 * (height >> 1)) + s2offset;
1019 dstPitch = ((width << 1) + 63) & ~63;
1023 srcPitch = width << 1;
1024 dstPitch = ((width << 1) + 63) & ~63;
1027 srcPitch = width << 2;
1028 dstPitch = ((width << 2) + 63) & ~63;
1031 return BadImplementation;
1033 /* dstPitch = number of bytes per row
1034 but the allocation is done is pixel, hence the division to get the real number of bytes */
1035 newSize = height * dstPitch / bpp;
1037 if (pPriv->doubleBuffer) // double buffering ...
1038 newSize <<= 1; // ... means double the amount of VRAM needed
1040 pPriv->video_mem = NVAllocateOverlayMemory(pScrn, pPriv->video_mem,
1042 if (!pPriv->video_mem)
1045 offset = pPriv->video_mem->offset;
1046 if (pPriv->doubleBuffer) {
1047 int mask = 1 << (pPriv->currentBuffer << 2);
1049 /* overwrite the newest buffer if there's not one free */
1050 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1051 if (!pPriv->currentBuffer)
1052 offset += (height + 1) * dstPitch;
1056 if (pPriv->currentBuffer)
1057 offset += (height + 1) * dstPitch;
1061 /* We need to enlarge the copied rectangle by a pixel so the HW
1062 * filtering doesn't pick up junk laying outside of the source */
1063 /* fixed point arithmetic */
1064 left = (xa - 0x00010000) >> 16;
1065 if (left < 0) left = 0;
1066 top = (ya - 0x00010000) >> 16;
1067 if (top < 0) top = 0;
1068 right = (xb + 0x0001ffff) >> 16;
1069 if (right > width) right = width;
1070 bottom = (yb + 0x0001ffff) >> 16;
1071 if (bottom > height) bottom = height;
1073 if(pPriv->blitter) NVSync(pScrn);
1080 npixels = ((right + 1) & ~1) - left;
1082 nlines = ((bottom + 1) & ~1) - top;
1084 offset += (left << 1) + (top * dstPitch);
1085 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1088 if (id == FOURCC_I420) {
1090 s2offset = s3offset;
1093 line_len = dstPitch;
1098 npixels = ((right + 1) & ~1) - left;
1099 nlines = bottom - top;
1102 buf += (top * srcPitch) + left;
1103 offset += left + (top * dstPitch);
1104 line_len = width << 1;
1107 npixels = right - left;
1108 nlines = bottom - top;
1110 buf += (top * srcPitch) + left;
1111 offset += left + (top * dstPitch);
1112 line_len = width << 2;
1115 return BadImplementation;
1120 /*Below is *almost* a copypaste from NvAccelUploadM2MF, cannot use it directly because of YV12 -> YUY2 conversion */
1121 if ( nlines * line_len <= pNv->GARTScratch->size)
1123 char *dst = pNv->GARTScratch->map;
1125 /* Upload to GART */
1130 NVCopyData420(buf + (top * srcPitch) + left,
1131 buf + s2offset, buf + s3offset,
1132 dst, srcPitch, srcPitch2,
1133 dstPitch, nlines, npixels);
1139 memcpy(dst, buf, srcPitch * nlines);
1142 return BadImplementation;
1145 if ( !pPriv -> blitter )
1147 NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_DMA_OBJECT_IN, 2);
1148 NVDmaNext (pNv, NvDmaTT);
1149 NVDmaNext (pNv, NvDmaFB);
1150 pNv->M2MFDirection = 1;
1154 NVDmaStart(pNv, NvSubMemFormat,
1155 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1156 NVDmaNext (pNv, (uint32_t)pNv->GARTScratch->offset);
1157 NVDmaNext (pNv, (uint32_t)offset);
1158 NVDmaNext (pNv, line_len);
1159 NVDmaNext (pNv, dstPitch);
1160 NVDmaNext (pNv, line_len);
1161 NVDmaNext (pNv, nlines);
1162 NVDmaNext (pNv, (1<<8)|1);
1165 NVNotifierReset(pScrn, pNv->Notifier0);
1166 NVDmaStart(pNv, NvSubMemFormat,
1167 NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1169 NVDmaStart(pNv, NvSubMemFormat, 0x100, 1);
1173 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 0))
1178 NVDmaStart(pNv, NvSubScaledImage, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
1179 NVDmaNext (pNv, NvDmaTT); /* source object */
1181 NVPutBlitImage(pScrn, pNv->GARTScratch->offset, id,
1185 src_w, src_h, drw_w, drw_h,
1188 NVNotifierReset(pScrn, pNv->Notifier0);
1189 NVDmaStart(pNv, NvSubScaledImage,
1190 NV10_IMAGE_BLIT_NOTIFY, 1);
1192 NVDmaStart(pNv, NvSubScaledImage, 0x100, 1);
1193 NVDmaNext (pNv, 106);
1195 NVDmaStart(pNv, NvSubScaledImage, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
1196 NVDmaNext (pNv, NvDmaFB); /* source object */
1198 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 0))
1203 else //GART is too small, we fallback on CPU copy for simplicity
1210 if (pPriv->blitter) {
1211 NVPutBlitImage(pScrn, offset, id,
1215 src_w, src_h, drw_w, drw_h,
1218 NVPutOverlayImage(pScrn, offset, id,
1222 src_w, src_h, drw_w, drw_h,
1224 pPriv->currentBuffer ^= 1;
1233 * QueryImageAttributes
1236 * - size (memory required to store image),
1240 * depending on colorspace (id) and dimensions (w,h) of image
1244 * may be adjusted as needed
1246 * @param pScrn unused
1247 * @param id colorspace of image
1248 * @param w pointer to width of image
1249 * @param h pointer to height of image
1250 * @param pitches pitches[i] = length of a scanline in plane[i]
1251 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1252 * @return size of the memory required for the XvImage queried
1255 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1256 unsigned short *w, unsigned short *h,
1257 int *pitches, int *offsets)
1261 if (*w > IMAGE_MAX_W)
1263 if (*h > IMAGE_MAX_H)
1266 *w = (*w + 1) & ~1; // width rounded up to an even number
1273 *h = (*h + 1) & ~1; // height rounded up to an even number
1274 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1276 pitches[0] = size; // width rounded up to a multiple of 4
1279 offsets[1] = size; // number of pixels in "rounded up" image
1280 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1282 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1283 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1284 size += tmp; // 5/4*number of pixels in "rounded up" image
1286 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1287 size += tmp; // = 3/2*number of pixels in "rounded up" image
1291 size = *w << 1; // 2*width
1293 pitches[0] = size; // 2*width
1294 size *= *h; // 2*width*height
1297 size = *w << 2; // 4*width (32 bit per pixel)
1299 pitches[0] = size; // 4*width
1300 size *= *h; // 4*width*height
1310 /***** Exported offscreen surface stuff ****/
1314 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1315 unsigned short w, unsigned short h,
1316 XF86SurfacePtr surface)
1318 NVPtr pNv = NVPTR(pScrn);
1319 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1322 bpp = pScrn->bitsPerPixel >> 3;
1324 if (pPriv->grabbedByV4L)
1327 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1331 pPriv->pitch = ((w << 1) + 63) & ~63;
1332 size = h * pPriv->pitch / bpp;
1334 pPriv->video_mem = NVAllocateOverlayMemory(pScrn,
1337 if (!pPriv->video_mem)
1343 surface->height = h;
1344 surface->pScrn = pScrn;
1345 surface->pitches = &pPriv->pitch;
1346 surface->offsets = &pPriv->offset;
1347 surface->devPrivate.ptr = (pointer)pPriv;
1350 /* grab the video */
1351 NVStopOverlay(pScrn);
1352 pPriv->videoStatus = 0;
1353 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1354 pPriv->grabbedByV4L = TRUE;
1360 NVStopSurface(XF86SurfacePtr surface)
1362 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1364 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
1365 NVStopOverlay(surface->pScrn);
1366 pPriv->videoStatus = 0;
1373 NVFreeSurface(XF86SurfacePtr surface)
1375 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1377 if (pPriv->grabbedByV4L) {
1378 NVStopSurface(surface);
1379 NVFreeOverlayMemory(surface->pScrn);
1380 pPriv->grabbedByV4L = FALSE;
1387 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
1389 NVPtr pNv = NVPTR(pScrn);
1390 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1392 return NVGetOverlayPortAttribute(pScrn, attribute,
1393 value, (pointer)pPriv);
1397 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
1399 NVPtr pNv = NVPTR(pScrn);
1400 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1402 return NVSetOverlayPortAttribute(pScrn, attribute,
1403 value, (pointer)pPriv);
1407 NVDisplaySurface(XF86SurfacePtr surface,
1408 short src_x, short src_y,
1409 short drw_x, short drw_y,
1410 short src_w, short src_h,
1411 short drw_w, short drw_h,
1412 RegionPtr clipBoxes)
1414 ScrnInfoPtr pScrn = surface->pScrn;
1415 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1416 INT32 xa, xb, ya, yb;
1419 if (!pPriv->grabbedByV4L)
1422 if (src_w > (drw_w << 3))
1424 if (src_h > (drw_h << 3))
1434 dstBox.x2 = drw_x + drw_w;
1436 dstBox.y2 = drw_y + drw_h;
1438 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1439 surface->width, surface->height))
1442 dstBox.x1 -= pScrn->frameX0;
1443 dstBox.x2 -= pScrn->frameX0;
1444 dstBox.y1 -= pScrn->frameY0;
1445 dstBox.y2 -= pScrn->frameY0;
1447 pPriv->currentBuffer = 0;
1449 NVPutOverlayImage(pScrn, surface->offsets[0], surface->id,
1450 surface->pitches[0], &dstBox, xa, ya, xb, yb,
1451 surface->width, surface->height, src_w, src_h,
1452 drw_w, drw_h, clipBoxes);
1459 * this function does all the work setting up a blit port
1463 static XF86VideoAdaptorPtr
1464 NVSetupBlitVideo (ScreenPtr pScreen)
1466 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1467 NVPtr pNv = NVPTR(pScrn);
1468 XF86VideoAdaptorPtr adapt;
1469 NVPortPrivPtr pPriv;
1472 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1473 sizeof(NVPortPrivRec) +
1474 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
1478 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1480 adapt->name = "NV Video Blitter";
1481 adapt->nEncodings = 1;
1482 adapt->pEncodings = &DummyEncoding;
1483 adapt->nFormats = NUM_FORMATS_ALL;
1484 adapt->pFormats = NVFormats;
1485 adapt->nPorts = NUM_BLIT_PORTS;
1486 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1488 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
1489 for(i = 0; i < NUM_BLIT_PORTS; i++)
1490 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1492 if(pNv->WaitVSyncPossible) {
1493 adapt->pAttributes = NVBlitAttributes;
1494 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
1496 adapt->pAttributes = NULL;
1497 adapt->nAttributes = 0;
1500 adapt->pImages = NVImages;
1501 adapt->nImages = NUM_IMAGES_ALL;
1502 adapt->PutVideo = NULL;
1503 adapt->PutStill = NULL;
1504 adapt->GetVideo = NULL;
1505 adapt->GetStill = NULL;
1506 adapt->StopVideo = NVStopBlitVideo;
1507 adapt->SetPortAttribute = NVSetBlitPortAttribute;
1508 adapt->GetPortAttribute = NVGetBlitPortAttribute;
1509 adapt->QueryBestSize = NVQueryBestSize;
1510 adapt->PutImage = NVPutImage;
1511 adapt->QueryImageAttributes = NVQueryImageAttributes;
1513 pPriv->videoStatus = 0;
1514 pPriv->grabbedByV4L = FALSE;
1515 pPriv->blitter = TRUE;
1516 pPriv->doubleBuffer = FALSE;
1517 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1519 pNv->blitAdaptor = adapt;
1520 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
1526 * NV10SetupOverlayVideo
1527 * this function does all the work setting up an overlay port
1529 * @return overlay port
1530 * @see NVResetVideo(ScrnInfoPtr pScrn)
1532 static XF86VideoAdaptorPtr
1533 NV10SetupOverlayVideo(ScreenPtr pScreen)
1535 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1536 NVPtr pNv = NVPTR(pScrn);
1537 XF86VideoAdaptorPtr adapt;
1538 NVPortPrivPtr pPriv;
1540 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1541 sizeof(NVPortPrivRec) +
1542 sizeof(DevUnion)))) {
1546 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1547 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
1548 adapt->name = "NV Video Overlay";
1549 adapt->nEncodings = 1;
1550 adapt->pEncodings = &DummyEncoding;
1551 adapt->nFormats = NUM_FORMATS_ALL;
1552 adapt->pFormats = NVFormats;
1554 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1556 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
1557 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
1559 adapt->pAttributes = NVOverlayAttributes;
1560 adapt->nAttributes = NUM_OVERLAY_ATTRIBUTES;
1561 adapt->pImages = NVImages;
1562 adapt->nImages = NUM_IMAGES_YUV;
1563 adapt->PutVideo = NULL;
1564 adapt->PutStill = NULL;
1565 adapt->GetVideo = NULL;
1566 adapt->GetStill = NULL;
1567 adapt->StopVideo = NVStopOverlayVideo;
1568 adapt->SetPortAttribute = NVSetOverlayPortAttribute;
1569 adapt->GetPortAttribute = NVGetOverlayPortAttribute;
1570 adapt->QueryBestSize = NVQueryBestSize;
1571 adapt->PutImage = NVPutImage;
1572 adapt->QueryImageAttributes = NVQueryImageAttributes;
1574 pPriv->videoStatus = 0;
1575 pPriv->currentBuffer = 0;
1576 pPriv->grabbedByV4L = FALSE;
1577 pPriv->blitter = FALSE;
1579 NVSetPortDefaults (pScrn, pPriv);
1581 /* gotta uninit this someplace */
1582 REGION_NULL(pScreen, &pPriv->clip);
1584 pNv->overlayAdaptor = adapt;
1586 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
1587 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
1588 xvContrast = MAKE_ATOM("XV_CONTRAST");
1589 xvColorKey = MAKE_ATOM("XV_COLORKEY");
1590 xvSaturation = MAKE_ATOM("XV_SATURATION");
1591 xvHue = MAKE_ATOM("XV_HUE");
1592 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
1593 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
1594 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
1596 NVResetVideo(pScrn);
1601 XF86OffscreenImageRec NVOffscreenImages[2] = {
1604 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1609 NVGetSurfaceAttribute,
1610 NVSetSurfaceAttribute,
1611 IMAGE_MAX_W, IMAGE_MAX_H,
1612 NUM_OVERLAY_ATTRIBUTES - 1,
1613 &NVOverlayAttributes[1]
1617 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1622 NVGetSurfaceAttribute,
1623 NVSetSurfaceAttribute,
1624 IMAGE_MAX_W, IMAGE_MAX_H,
1625 NUM_OVERLAY_ATTRIBUTES - 1,
1626 &NVOverlayAttributes[1]
1631 NVInitOffscreenImages (ScreenPtr pScreen)
1633 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
1637 * NVChipsetHasOverlay
1639 * newer chips don't support overlay anymore.
1640 * overlay feature is emulated via textures.
1643 * @return true, if chipset supports overlay
1646 NVChipsetHasOverlay(NVPtr pNv)
1648 switch (pNv->Architecture) {
1654 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
1665 * NVSetupOverlayVideo
1666 * check if chipset supports Overlay and CompositeExtension is disabled.
1667 * if so, setup overlay port
1669 * @return overlay port
1670 * @see NVChipsetHasOverlay(NVPtr pNv)
1671 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
1672 * @see NVInitOffscreenImages(ScreenPtr pScreen)
1674 static XF86VideoAdaptorPtr
1675 NVSetupOverlayVideo(ScreenPtr pScreen)
1677 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1678 XF86VideoAdaptorPtr overlayAdaptor = NULL;
1679 NVPtr pNv = NVPTR(pScrn);
1681 if (!NVChipsetHasOverlay(pNv))
1684 /*XXX: Do we still want to provide the overlay anyway, but make the
1685 * blit adaptor the default if composite is enabled?
1688 /* if (!noCompositeExtension) {
1689 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1690 "XV: Video overlay not available, composite enabled\n");
1694 overlayAdaptor = NV10SetupOverlayVideo(pScreen);
1696 NVInitOffscreenImages(pScreen);
1698 return overlayAdaptor;
1703 * tries to initialize one new overlay port and one new blit port
1704 * and add them to the list of ports on screen "pScreen".
1707 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
1708 * @see NVSetupBlitVideo(ScreenPtr pScreen)
1710 void NVInitVideo (ScreenPtr pScreen)
1712 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1713 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
1714 XF86VideoAdaptorPtr overlayAdaptor = NULL;
1715 XF86VideoAdaptorPtr blitAdaptor = NULL;
1718 if (pScrn->bitsPerPixel == 8)
1721 overlayAdaptor = NVSetupOverlayVideo(pScreen);
1722 blitAdaptor = NVSetupBlitVideo(pScreen);
1724 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
1725 if(blitAdaptor || overlayAdaptor) {
1726 int size = num_adaptors;
1728 if(overlayAdaptor) size++;
1729 if(blitAdaptor) size++;
1731 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
1734 memcpy(newAdaptors, adaptors, num_adaptors *
1735 sizeof(XF86VideoAdaptorPtr));
1738 if(overlayAdaptor) {
1739 newAdaptors[num_adaptors] = overlayAdaptor;
1744 newAdaptors[num_adaptors] = blitAdaptor;
1748 adaptors = newAdaptors;
1753 xf86XVScreenInit(pScreen, adaptors, num_adaptors);