2 * Copyright 2007 Arthur Huillet
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 #include <X11/extensions/Xv.h>
32 #include "dixstruct.h"
35 #include "nv_include.h"
40 #define IMAGE_MAX_W 2046
41 #define IMAGE_MAX_H 2046
43 #define TEX_IMAGE_MAX_W 4096
44 #define TEX_IMAGE_MAX_H 4096
46 #define OFF_DELAY 500 /* milliseconds */
47 #define FREE_DELAY 5000
49 #define NUM_BLIT_PORTS 16
50 #define NUM_TEXTURE_PORTS 32
53 #define NVStopOverlay(X) (((pNv->Architecture == NV_ARCH_04) ? NV04StopOverlay(X) : NV10StopOverlay(X)))
55 /* Value taken by pPriv -> currentHostBuffer when we failed to allocate the two private buffers in TT memory, so that we can catch this case
56 and attempt no other allocation afterwards (performance reasons) */
57 #define NO_PRIV_HOST_BUFFER_AVAILABLE 9999
59 /* NVPutImage action flags */
67 IS_RGB=64, //I am not sure how long we will support it
70 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
72 Atom xvBrightness, xvContrast, xvColorKey, xvSaturation;
73 Atom xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer;
74 Atom xvITURBT709, xvSyncToVBlank, xvOnCRTCNb;
76 /* client libraries expect an encoding */
77 static XF86VideoEncodingRec DummyEncoding =
81 IMAGE_MAX_W, IMAGE_MAX_H,
85 static XF86VideoEncodingRec DummyEncodingTex =
89 TEX_IMAGE_MAX_W, TEX_IMAGE_MAX_H,
93 #define NUM_FORMATS_ALL 6
95 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
97 {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
98 {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
101 #define NUM_NV04_OVERLAY_ATTRIBUTES 4
102 XF86AttributeRec NV04OverlayAttributes[NUM_NV04_OVERLAY_ATTRIBUTES] =
104 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
105 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
106 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
107 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
111 #define NUM_NV10_OVERLAY_ATTRIBUTES 10
112 XF86AttributeRec NV10OverlayAttributes[NUM_NV10_OVERLAY_ATTRIBUTES] =
114 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
115 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
116 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
117 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
118 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
119 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
120 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
121 {XvSettable | XvGettable, 0, 360, "XV_HUE"},
122 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"},
123 {XvSettable | XvGettable, 0, 1, "XV_ON_CRTC_NB"},
126 #define NUM_BLIT_ATTRIBUTES 2
127 XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
129 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
130 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
133 #define NUM_TEXTURED_ATTRIBUTES 2
134 XF86AttributeRec NVTexturedAttributes[NUM_TEXTURED_ATTRIBUTES] =
136 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
137 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
141 #define NUM_IMAGES_YUV 4
142 #define NUM_IMAGES_ALL 5
144 #define FOURCC_RGB 0x0000003
145 #define XVIMAGE_RGB \
150 { 0x03, 0x00, 0x00, 0x00, \
151 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
155 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
160 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}, \
164 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
174 nv_window_belongs_to_crtc(ScrnInfoPtr pScrn, int x, int y, int w, int h)
176 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
177 NVPtr pNv = NVPTR(pScrn);
179 unsigned int mask = 0;
181 if (!pNv->randr12_enable) {
183 * Without RandR 1.2, we'll just return which CRTCs
186 if (pNv->crtc_active[0])
188 else if (pNv->crtc_active[1])
194 for (i = 0; i < xf86_config->num_crtc; i++) {
195 xf86CrtcPtr crtc = xf86_config->crtc[i];
200 if ((x < (crtc->x + crtc->mode.HDisplay)) &&
201 (y < (crtc->y + crtc->mode.VDisplay)) &&
202 ((x + w) > crtc->x) &&
211 NVWaitVSync(ScrnInfoPtr pScrn, int crtc)
213 NVPtr pNv = NVPTR(pScrn);
214 struct nouveau_channel *chan = pNv->chan;
215 struct nouveau_grobj *blit = pNv->NvImageBlit;
217 BEGIN_RING(chan, blit, 0x0000012C, 1);
219 BEGIN_RING(chan, blit, 0x00000134, 1);
220 OUT_RING (chan, crtc);
221 BEGIN_RING(chan, blit, 0x00000100, 1);
223 BEGIN_RING(chan, blit, 0x00000130, 1);
229 * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
230 * this function does not care about the kind of adapter the port is for
232 * @param pScrn screen to get the default colorKey from
233 * @param pPriv port to reset to defaults
236 NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
238 NVPtr pNv = NVPTR(pScrn);
240 pPriv->brightness = 0;
241 pPriv->contrast = 4096;
242 pPriv->saturation = 4096;
244 pPriv->colorKey = pNv->videoKey;
245 pPriv->autopaintColorKey = TRUE;
246 pPriv->doubleBuffer = pNv->Architecture != NV_ARCH_04;
247 pPriv->iturbt_709 = FALSE;
248 pPriv->currentHostBuffer = 0;
252 nouveau_xv_bo_realloc(ScrnInfoPtr pScrn, unsigned flags, unsigned size,
253 struct nouveau_bo **pbo)
255 NVPtr pNv = NVPTR(pScrn);
259 if ((*pbo)->size >= size)
261 nouveau_bo_ref(NULL, pbo);
264 if (pNv->Architecture >= NV_ARCH_50 && (flags & NOUVEAU_BO_VRAM))
265 flags |= NOUVEAU_BO_TILED;
267 ret = nouveau_bo_new(pNv->dev, flags | NOUVEAU_BO_PIN, 0, size, pbo);
276 * frees memory held by a given port
278 * @param pScrn screen whose port wants to free memory
279 * @param pPriv port to free memory of
282 NVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
284 nouveau_bo_ref(NULL, &pPriv->video_mem);
285 nouveau_bo_ref(NULL, &pPriv->TT_mem_chunk[0]);
286 nouveau_bo_ref(NULL, &pPriv->TT_mem_chunk[1]);
291 * NVFreeOverlayMemory
292 * frees memory held by the overlay port
294 * @param pScrn screen whose overlay port wants to free memory
297 NVFreeOverlayMemory(ScrnInfoPtr pScrn)
299 NVPtr pNv = NVPTR(pScrn);
300 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
302 NVFreePortMemory(pScrn, pPriv);
304 /* "power cycle" the overlay */
305 nvWriteMC(pNv, NV_PMC_ENABLE,
306 (nvReadMC(pNv, NV_PMC_ENABLE) & 0xEFFFFFFF));
307 nvWriteMC(pNv, NV_PMC_ENABLE,
308 (nvReadMC(pNv, NV_PMC_ENABLE) | 0x10000000));
313 * frees memory held by the blit port
315 * @param pScrn screen whose blit port wants to free memory
318 NVFreeBlitMemory(ScrnInfoPtr pScrn)
320 NVPtr pNv = NVPTR(pScrn);
321 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
323 NVFreePortMemory(pScrn, pPriv);
327 * NVVideoTimerCallback
328 * callback function which perform cleanup tasks (stop overlay, free memory).
330 * purpose and use is unknown
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;
384 #ifndef ExaOffscreenMarkUsed
385 extern void ExaOffscreenMarkUsed(PixmapPtr);
392 NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
394 NVPtr pNv = NVPTR(pScrn);
395 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
397 if (pPriv->grabbedByV4L)
400 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
403 if (pPriv->videoStatus & CLIENT_VIDEO_ON)
404 NVStopOverlay(pScrn);
405 NVFreeOverlayMemory(pScrn);
406 pPriv->videoStatus = 0;
408 if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
409 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
410 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
411 pNv->VideoTimerCallback = NVVideoTimerCallback;
418 * used by client applications to ask the driver:
419 * how would you actually scale a video of dimensions
420 * vid_w, vid_h, if i wanted you to scale it to dimensions
422 * function stores actual scaling size in pointers p_w, p_h.
425 * @param pScrn unused
426 * @param motion unused
427 * @param vid_w width of source video
428 * @param vid_h height of source video
429 * @param drw_w desired scaled width as requested by client
430 * @param drw_h desired scaled height as requested by client
431 * @param p_w actual scaled width as the driver is capable of
432 * @param p_h actual scaled height as the driver is capable of
436 NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
437 short vid_w, short vid_h,
438 short drw_w, short drw_h,
439 unsigned int *p_w, unsigned int *p_h,
442 if(vid_w > (drw_w << 3))
444 if(vid_h > (drw_h << 3))
453 * used to convert YV12 to YUY2 for the blitter and NV04 overlay.
454 * The U and V samples generated are linearly interpolated on the vertical
455 * axis for better quality
457 * @param src1 source buffer of luma
458 * @param src2 source buffer of chroma1
459 * @param src3 source buffer of chroma2
460 * @param dst1 destination buffer
461 * @param srcPitch pitch of src1
462 * @param srcPitch2 pitch of src2, src3
463 * @param dstPitch pitch of dst1
464 * @param h number of lines to copy
465 * @param w length of lines to copy
468 NVCopyData420(unsigned char *src1, unsigned char *src2, unsigned char *src3,
469 unsigned char *dst1, int srcPitch, int srcPitch2, int dstPitch,
476 #define su(X) (((j & 1) && j < (h-1)) ? ((unsigned)((signed int)s2[X] + \
477 (signed int)(s2 + srcPitch2)[X]) / 2) : (s2[X]))
478 #define sv(X) (((j & 1) && j < (h-1)) ? ((unsigned)((signed int)s3[X] + \
479 (signed int)(s3 + srcPitch2)[X]) / 2) : (s3[X]))
483 for (j = 0; j < h; j++) {
485 s1 = src1; s2 = src2; s3 = src3;
489 #if X_BYTE_ORDER == X_BIG_ENDIAN
490 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (sv(0) << 16) | su(0);
491 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (sv(1) << 16) | su(1);
492 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (sv(2) << 16) | su(2);
493 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (sv(3) << 16) | su(3);
495 dst[0] = s1[0] | (s1[1] << 16) | (sv(0) << 8) | (su(0) << 24);
496 dst[1] = s1[2] | (s1[3] << 16) | (sv(1) << 8) | (su(1) << 24);
497 dst[2] = s1[4] | (s1[5] << 16) | (sv(2) << 8) | (su(2) << 24);
498 dst[3] = s1[6] | (s1[7] << 16) | (sv(3) << 8) | (su(3) << 24);
500 dst += 4; s2 += 4; s3 += 4; s1 += 8;
505 #if X_BYTE_ORDER == X_BIG_ENDIAN
506 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (sv(0) << 16) | su(0);
508 dst[0] = s1[0] | (s1[1] << 16) | (sv(0) << 8) | (su(0) << 24);
524 * NVCopyNV12ColorPlanes
525 * Used to convert YV12 color planes to NV12 (interleaved UV) for the overlay
527 * @param src1 source buffer of chroma1
528 * @param dst1 destination buffer
529 * @param h number of lines to copy
530 * @param w length of lines to copy
531 * @param id source pixel format (YV12 or I420)
534 NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char *src2,
535 unsigned char *dst, int dstPitch, int srcPitch2,
545 for (j = 0; j < h; j++) {
546 unsigned char *us = src1;
547 unsigned char *vs = src2;
548 unsigned int *vuvud = (unsigned int *) dst;
550 for (i = 0; i < l; i++) {
551 #if X_BYTE_ORDER == X_BIG_ENDIAN
552 *vuvud++ = (vs[0]<<24) | (us[0]<<16) | (vs[1]<<8) | us[1];
554 *vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24);
561 unsigned short *vud = (unsigned short *) vuvud;
563 *vud = vs[0] | (us[0]<<8);
575 NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 *xa, INT32 *xb,
576 INT32 *ya, INT32 *yb, short *src_x, short *src_y,
577 short *src_w, short *src_h, short *drw_x, short *drw_y,
578 short *drw_w, short *drw_h, int *left, int *top, int *right,
579 int *bottom, BoxRec *dstBox, int *npixels, int *nlines,
580 RegionPtr clipBoxes, short width, short height)
582 NVPtr pNv = NVPTR(pScrn);
584 if (action_flags & USE_OVERLAY) {
585 switch (pNv->Architecture) {
587 /* NV0x overlay can't scale down. at all. */
594 /* According to DirectFB, NV3x can't scale down by
597 if (*drw_w < (*src_w) >> 1)
599 if (*drw_h < (*src_h) >> 1)
602 default: /*NV10, NV20*/
603 /* NV1x overlay can't scale down by a ratio > 8 */
604 if (*drw_w < (*src_w) >> 3)
605 *drw_w = *src_w >> 3;
606 if (*drw_h < (*src_h >> 3))
607 *drw_h = *src_h >> 3;
613 *xb = *src_x + *src_w;
615 *yb = *src_y + *src_h;
618 dstBox->x2 = *drw_x + *drw_w;
620 dstBox->y2 = *drw_y + *drw_h;
622 /* In randr 1.2 mode VIDEO_CLIP_TO_VIEWPORT is broken (hence it is not
623 * set in the overlay adapter flags) since pScrn->frame{X,Y}1 do not get
624 * updated. Hence manual clipping against the CRTC dimensions
626 if (pNv->randr12_enable && action_flags & USE_OVERLAY) {
627 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
628 unsigned id = pPriv->overlayCRTC;
629 xf86CrtcPtr crtc = XF86_CRTC_CONFIG_PTR(pScrn)->crtc[id];
635 VPBox.x2 = crtc->x + crtc->mode.HDisplay;
636 VPBox.y2 = crtc->y + crtc->mode.VDisplay;
638 REGION_INIT(pScreen, &VPReg, &VPBox, 1);
639 REGION_INTERSECT(pScreen, clipBoxes, clipBoxes, &VPReg);
640 REGION_UNINIT(pScreen, &VPReg);
643 if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
647 if (action_flags & USE_OVERLAY) {
648 if (!pNv->randr12_enable) {
649 dstBox->x1 -= pScrn->frameX0;
650 dstBox->x2 -= pScrn->frameX0;
651 dstBox->y1 -= pScrn->frameY0;
652 dstBox->y2 -= pScrn->frameY0;
654 xf86CrtcConfigPtr xf86_config =
655 XF86_CRTC_CONFIG_PTR(pScrn);
656 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
658 dstBox->x1 -= xf86_config->crtc[pPriv->overlayCRTC]->x;
659 dstBox->x2 -= xf86_config->crtc[pPriv->overlayCRTC]->x;
660 dstBox->y1 -= xf86_config->crtc[pPriv->overlayCRTC]->y;
661 dstBox->y2 -= xf86_config->crtc[pPriv->overlayCRTC]->y;
665 /* Convert fixed point to integer, as xf86XVClipVideoHelper probably
666 * turns its parameter into fixed point values
676 *right = (*xb) >> 16;
680 *bottom = (*yb) >> 16;
681 if (*bottom > height)
684 if (action_flags & IS_YV12) {
685 /* even "left", even "top", even number of pixels per line
686 * and even number of lines
689 *npixels = ((*right + 1) & ~1) - *left;
691 *nlines = ((*bottom + 1) & ~1) - *top;
693 if (action_flags & IS_YUY2) {
696 /* even number of pixels per line */
697 *npixels = ((*right + 1) & ~1) - *left;
698 *nlines = *bottom - *top;
702 if (action_flags & IS_RGB) {
703 *npixels = *right - *left;
704 *nlines = *bottom - *top;
713 NV_calculate_pitches_and_mem_size(int action_flags, int *srcPitch,
714 int *srcPitch2, int *dstPitch, int *s2offset,
715 int *s3offset, int *newFBSize, int *newTTSize,
716 int *line_len, int npixels, int nlines,
717 int width, int height)
721 if (action_flags & IS_YV12) {
722 *srcPitch = (width + 3) & ~3; /* of luma */
723 *s2offset = *srcPitch * height;
724 *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
725 *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
726 *dstPitch = (npixels + 63) & ~63; /*luma and chroma pitch*/
728 *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
729 *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
731 if (action_flags & IS_YUY2) {
732 *srcPitch = width << 1; /* one luma, one chroma per pixel */
733 *dstPitch = ((npixels << 1) + 63) & ~63;
734 *line_len = npixels << 1;
735 *newFBSize = nlines * *dstPitch;
736 *newTTSize = nlines * *line_len;
738 if (action_flags & IS_RGB) {
739 /* one R, one G, one B, one X per pixel */
740 *srcPitch = width << 2;
741 *dstPitch = ((npixels << 2) + 63) & ~63;
742 *line_len = npixels << 2;
743 *newFBSize = nlines * *dstPitch;
744 *newTTSize = nlines * *dstPitch;
747 if (action_flags & CONVERT_TO_YUY2) {
748 *dstPitch = ((npixels << 1) + 63) & ~63;
749 *line_len = npixels << 1;
750 *newFBSize = nlines * *dstPitch;
751 *newTTSize = nlines * *line_len;
754 if (action_flags & SWAP_UV) {
755 /* I420 swaps U and V */
757 *s2offset = *s3offset;
761 /* Overlay double buffering... */
762 if (action_flags & USE_OVERLAY)
770 * NV_set_action_flags
771 * This function computes the action flags from the input image,
772 * that is, it decides what NVPutImage and its helpers must do.
773 * This eases readability by avoiding lots of switch-case statements in the
777 NV_set_action_flags(ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv,
778 int id, short drw_x, short drw_y, short drw_w, short drw_h,
781 NVPtr pNv = NVPTR(pScrn);
783 #define USING_OVERLAY (*action_flags & USE_OVERLAY)
784 #define USING_TEXTURE (*action_flags & USE_TEXTURE)
785 #define USING_BLITTER ((!(*action_flags & USE_OVERLAY)) && \
786 (!(*action_flags & USE_TEXTURE)))
790 /* Pixel format-related bits */
791 if (id == FOURCC_YUY2 || id == FOURCC_UYVY)
792 *action_flags |= IS_YUY2;
794 if (id == FOURCC_YV12 || id == FOURCC_I420)
795 *action_flags |= IS_YV12;
797 if (id == FOURCC_RGB) /*How long will we support it?*/
798 *action_flags |= IS_RGB;
800 if (id == FOURCC_I420) /* I420 is YV12 with swapped UV */
801 *action_flags |= SWAP_UV;
803 /* Desired adapter */
804 if (!pPriv->blitter && !pPriv->texture)
805 *action_flags |= USE_OVERLAY;
807 if (!pPriv->blitter && pPriv->texture)
808 *action_flags |= USE_TEXTURE;
810 /* Adapter fallbacks (when the desired one can't be used)*/
813 PixmapPtr ppix = NVGetDrawablePixmap(pDraw);
815 if (!NVExaPixmapIsOnscreen(ppix))
816 *action_flags &= ~USE_OVERLAY;
820 if (USING_OVERLAY && pNv->randr12_enable) {
821 char crtc = nv_window_belongs_to_crtc(pScrn, drw_x, drw_y,
824 if ((crtc & (1 << 0)) && (crtc & (1 << 1))) {
825 /* The overlay cannot be used on two CRTCs at a time,
826 * so we need to fallback on the blitter
828 *action_flags &= ~USE_OVERLAY;
830 if ((crtc & (1 << 0))) {
831 /* We need to put the overlay on CRTC0 - if it's not
834 if (pPriv->overlayCRTC == 1) {
835 NVWriteCRTC(pNv, 0, NV_CRTC_FSEL,
836 NVReadCRTC(pNv, 0, NV_CRTC_FSEL) |
837 NV_CRTC_FSEL_OVERLAY);
838 NVWriteCRTC(pNv, 1, NV_CRTC_FSEL,
839 NVReadCRTC(pNv, 1, NV_CRTC_FSEL) &
840 ~NV_CRTC_FSEL_OVERLAY);
841 pPriv->overlayCRTC = 0;
844 if ((crtc & (1 << 1))) {
845 if (pPriv->overlayCRTC == 0) {
846 NVWriteCRTC(pNv, 1, NV_CRTC_FSEL,
847 NVReadCRTC(pNv, 1, NV_CRTC_FSEL) |
848 NV_CRTC_FSEL_OVERLAY);
849 NVWriteCRTC(pNv, 0, NV_CRTC_FSEL,
850 NVReadCRTC(pNv, 0, NV_CRTC_FSEL) &
851 ~NV_CRTC_FSEL_OVERLAY);
852 pPriv->overlayCRTC = 1;
856 if (XF86_CRTC_CONFIG_PTR(pScrn)->crtc[pPriv->overlayCRTC]
857 ->rotation != RR_Rotate_0)
858 *action_flags &= ~USE_OVERLAY;
861 /* At this point the adapter we're going to use is _known_.
862 * You cannot change it now.
865 /* Card/adapter format restrictions */
867 /* The blitter does not handle YV12 natively */
868 if (id == FOURCC_YV12 || id == FOURCC_I420)
869 *action_flags |= CONVERT_TO_YUY2;
872 if (USING_OVERLAY && (pNv->Architecture == NV_ARCH_04)) {
873 /* NV04-05 don't support YV12, only YUY2 and ITU-R BT.601 */
874 if (*action_flags & IS_YV12)
875 *action_flags |= CONVERT_TO_YUY2;
878 if (USING_OVERLAY && (pNv->Architecture == NV_ARCH_10 ||
879 pNv->Architecture == NV_ARCH_20)) {
880 /* No YV12 overlay on NV10, 11, 15, 20, NFORCE */
881 switch (pNv->Chipset & 0xfff0) {
885 case CHIPSET_NFORCE: /*XXX: unsure about nforce*/
887 *action_flags |= CONVERT_TO_YUY2;
898 * PutImage is "the" important function of the Xv extension.
899 * a client (e.g. video player) calls this function for every
900 * image (of the video) to be displayed. this function then
901 * scales and displays the image.
903 * @param pScrn screen which hold the port where the image is put
904 * @param src_x source point in the source image to start displaying from
905 * @param src_y see above
906 * @param src_w width of the source image to display
907 * @param src_h see above
908 * @param drw_x screen point to display to
910 * @param drw_w width of the screen drawable
912 * @param id pixel format of image
913 * @param buf pointer to buffer containing the source image
914 * @param width total width of the source image we are passed
917 * @param clipBoxes ??
918 * @param data pointer to port
919 * @param pDraw drawable pointer
922 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x,
923 short drw_y, short src_w, short src_h, short drw_w, short drw_h,
924 int id, unsigned char *buf, short width, short height,
925 Bool Sync, RegionPtr clipBoxes, pointer data, DrawablePtr pDraw)
927 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
928 NVPtr pNv = NVPTR(pScrn);
931 INT32 xa = 0, xb = 0, ya = 0, yb = 0;
932 /* size to allocate in VRAM and in GART respectively */
933 int newFBSize = 0, newTTSize = 0;
934 /* card VRAM offset, source offsets for U and V planes */
935 int offset = 0, s2offset = 0, s3offset = 0;
936 /* source pitch, source pitch of U and V planes in case of YV12,
937 * VRAM destination pitch
939 int srcPitch = 0, srcPitch2 = 0, dstPitch = 0;
940 /* position of the given source data (using src_*), number of pixels
941 * and lines we are interested in
943 int top = 0, left = 0, right = 0, bottom = 0, npixels = 0, nlines = 0;
944 struct nouveau_channel *chan = pNv->chan;
945 struct nouveau_grobj *m2mf = pNv->NvMemFormat;
949 int line_len = 0; /* length of a line, like npixels, but in bytes */
950 struct nouveau_bo *destination_buffer = NULL;
951 int action_flags; /* what shall we do? */
955 if (pPriv->grabbedByV4L)
959 NV_set_action_flags(pScrn, pDraw, pPriv, id, drw_x, drw_y, drw_w,
960 drw_h, &action_flags);
962 if (NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
963 &src_x, &src_y, &src_w, &src_h,
964 &drw_x, &drw_y, &drw_w, &drw_h,
965 &left, &top, &right, &bottom, &dstBox,
966 &npixels, &nlines, clipBoxes, width, height))
969 if (NV_calculate_pitches_and_mem_size(action_flags, &srcPitch,
970 &srcPitch2, &dstPitch, &s2offset,
971 &s3offset, &newFBSize, &newTTSize,
972 &line_len, npixels, nlines,
974 return BadImplementation;
976 /* There are some cases (tvtime with overscan for example) where the
977 * input image is larger (width/height) than the source rectangle for
978 * the overlay (src_w, src_h). In those cases, we try to do something
979 * optimal by uploading only the necessary data.
981 if (action_flags & IS_YUY2 || action_flags & IS_RGB)
982 buf += (top * srcPitch) + left;
984 if (action_flags & IS_YV12) {
985 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
990 ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_VRAM, newFBSize,
995 /* The overlay supports hardware double buffering. We handle this here*/
997 if (pPriv->doubleBuffer) {
998 int mask = 1 << (pPriv->currentBuffer << 2);
1000 /* overwrite the newest buffer if there's not one free */
1001 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1002 if (!pPriv->currentBuffer)
1003 offset += newFBSize >> 1;
1006 if (pPriv->currentBuffer)
1007 offset += newFBSize >> 1;
1011 /* Now we take a decision regarding the way we send the data to the
1014 * Either we use double buffering of "private" TT memory
1015 * Either we rely on X's GARTScratch
1016 * Either we fallback on CPU copy
1019 /* Try to allocate host-side double buffers, unless we have already
1023 /* We take only nlines * line_len bytes - that is, only the pixel
1024 * data we are interested in - because the stuff in the GART is
1025 * written contiguously
1027 if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE) {
1028 ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_GART, newTTSize,
1029 &pPriv->TT_mem_chunk[0]);
1031 ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_GART,
1033 &pPriv->TT_mem_chunk[1]);
1035 nouveau_bo_ref(NULL, &pPriv->TT_mem_chunk[0]);
1036 pPriv->currentHostBuffer =
1037 NO_PRIV_HOST_BUFFER_AVAILABLE;
1040 pPriv->currentHostBuffer =
1041 NO_PRIV_HOST_BUFFER_AVAILABLE;
1045 if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE) {
1046 destination_buffer =
1047 pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1050 /* Otherwise we fall back on DDX's GARTScratch */
1051 if (pPriv->currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE)
1052 destination_buffer = pNv->GART;
1054 /* If we have no GART at all... */
1055 if (!destination_buffer) {
1056 if (pNv->Architecture >= NV_ARCH_50) {
1057 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1058 "No scratch buffer for tiled upload\n");
1065 if (newTTSize <= destination_buffer->size) {
1069 nouveau_bo_map(destination_buffer, NOUVEAU_BO_WR);
1070 dst = destination_buffer->map;
1072 /* Upload to GART */
1073 if (action_flags & IS_YV12) {
1074 if (action_flags & CONVERT_TO_YUY2) {
1075 NVCopyData420(buf + (top * srcPitch) + left,
1076 buf + s2offset, buf + s3offset,
1077 dst, srcPitch, srcPitch2,
1078 line_len, nlines, npixels);
1081 unsigned char *tbuf = buf + top *
1083 unsigned char *tdst = dst;
1086 for (i = 0; i < nlines; i++) {
1087 memcpy(tdst, tbuf, line_len);
1091 dst += line_len * nlines;
1093 NVCopyNV12ColorPlanes(buf + s2offset,
1094 buf + s3offset, dst,
1095 line_len, srcPitch2,
1099 for (i = 0; i < nlines; i++) {
1100 memcpy(dst, buf, line_len);
1106 nouveau_bo_unmap(destination_buffer);
1108 BEGIN_RING(chan, m2mf,
1109 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
1110 OUT_RING (chan, pNv->chan->gart->handle);
1111 OUT_RING (chan, pNv->chan->vram->handle);
1113 if (pNv->Architecture >= NV_ARCH_50) {
1114 BEGIN_RING(chan, m2mf, 0x0200, 1);
1117 BEGIN_RING(chan, m2mf, 0x021c, 7);
1120 OUT_RING (chan, dstPitch);
1121 OUT_RING (chan, nlines);
1128 if ( (action_flags & IS_YV12) &&
1129 !(action_flags & CONVERT_TO_YUY2)) {
1130 /* we start the color plane transfer separately */
1132 BEGIN_RING(chan, m2mf,
1133 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1134 OUT_RELOCl(chan, destination_buffer, line_len * nlines,
1135 NOUVEAU_BO_GART | NOUVEAU_BO_RD);
1136 OUT_RELOCl(chan, pPriv->video_mem,
1137 offset + dstPitch * nlines,
1138 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
1139 OUT_RING (chan, line_len);
1140 OUT_RING (chan, dstPitch);
1141 OUT_RING (chan, line_len);
1142 OUT_RING (chan, (nlines >> 1));
1143 OUT_RING (chan, (1<<8)|1);
1147 BEGIN_RING(chan, m2mf,
1148 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1149 OUT_RELOCl(chan, destination_buffer, 0,
1150 NOUVEAU_BO_GART | NOUVEAU_BO_RD);
1151 OUT_RELOCl(chan, pPriv->video_mem, offset,
1152 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
1153 OUT_RING (chan, line_len);
1154 OUT_RING (chan, dstPitch);
1155 OUT_RING (chan, line_len);
1156 OUT_RING (chan, nlines);
1157 OUT_RING (chan, (1<<8)|1);
1163 nouveau_bo_map(pPriv->video_mem, NOUVEAU_BO_WR);
1164 map = pPriv->video_mem->map + offset;
1166 if (action_flags & IS_YV12) {
1167 if (action_flags & CONVERT_TO_YUY2) {
1168 NVCopyData420(buf + (top * srcPitch) + left,
1169 buf + s2offset, buf + s3offset,
1170 map, srcPitch, srcPitch2,
1171 dstPitch, nlines, npixels);
1173 unsigned char *tbuf =
1174 buf + left + top * srcPitch;
1176 for (i = 0; i < nlines; i++) {
1177 int dwords = npixels << 1;
1179 while (dwords & ~0x03) {
1181 *(map + 1) = *(tbuf + 1);
1182 *(map + 2) = *(tbuf + 2);
1183 *(map + 3) = *(tbuf + 3);
1190 case 3: *(map + 2) = *(tbuf + 2);
1191 case 2: *(map + 1) = *(tbuf + 1);
1192 case 1: *map = *tbuf;
1195 map += dstPitch - (npixels << 1);
1196 tbuf += srcPitch - (npixels << 1);
1199 NVCopyNV12ColorPlanes(buf + s2offset,
1201 map, dstPitch, srcPitch2,
1206 for (i = 0; i < nlines; i++) {
1207 int dwords = npixels << 1;
1209 while (dwords & ~0x03) {
1211 *(map + 1) = *(buf + 1);
1212 *(map + 2) = *(buf + 2);
1213 *(map + 3) = *(buf + 3);
1220 case 3: *(map + 2) = *(buf + 2);
1221 case 2: *(map + 1) = *(buf + 1);
1222 case 1: *map = *buf;
1225 map += dstPitch - (npixels << 1);
1226 buf += srcPitch - (npixels << 1);
1230 nouveau_bo_unmap(pPriv->video_mem);
1236 if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE)
1237 pPriv->currentHostBuffer ^= 1;
1239 /* If we're not using the hw overlay, we're rendering into a pixmap
1240 * and need to take a couple of additional steps...
1242 if (!(action_flags & USE_OVERLAY)) {
1243 ppix = NVGetDrawablePixmap(pDraw);
1245 /* Ensure pixmap is in offscreen memory */
1246 exaMoveInPixmap(ppix);
1247 ExaOffscreenMarkUsed(ppix);
1250 /* Convert screen coords to pixmap coords */
1251 if (ppix->screen_x || ppix->screen_y) {
1252 REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
1253 -ppix->screen_x, -ppix->screen_y);
1254 dstBox.x1 -= ppix->screen_x;
1255 dstBox.x2 -= ppix->screen_x;
1256 dstBox.y1 -= ppix->screen_y;
1257 dstBox.y2 -= ppix->screen_y;
1260 /* Damage tracking */
1261 DamageDamageRegion(&ppix->drawable, clipBoxes);
1265 if (action_flags & USE_OVERLAY) {
1266 if (pNv->Architecture == NV_ARCH_04) {
1267 NV04PutOverlayImage(pScrn, pPriv->video_mem, offset,
1268 id, dstPitch, &dstBox, 0, 0,
1269 xb, yb, npixels, nlines,
1270 src_w, src_h, drw_w, drw_h,
1275 if (action_flags & (IS_YUY2 | CONVERT_TO_YUY2))
1278 uvoffset = offset + nlines * dstPitch;
1280 NV10PutOverlayImage(pScrn, pPriv->video_mem, offset,
1281 uvoffset, id, dstPitch, &dstBox,
1283 npixels, nlines, src_w, src_h,
1284 drw_w, drw_h, clipBoxes);
1287 pPriv->currentBuffer ^= 1;
1289 if (action_flags & USE_TEXTURE) {
1290 int ret = BadImplementation;
1292 if (pNv->Architecture == NV_ARCH_30) {
1293 ret = NV30PutTextureImage(pScrn, pPriv->video_mem,
1295 offset + nlines * dstPitch,
1296 id, dstPitch, &dstBox, 0, 0,
1297 xb, yb, npixels, nlines,
1298 src_w, src_h, drw_w, drw_h,
1299 clipBoxes, ppix, pPriv);
1301 if (pNv->Architecture == NV_ARCH_40) {
1302 ret = NV40PutTextureImage(pScrn, pPriv->video_mem,
1304 offset + nlines * dstPitch,
1305 id, dstPitch, &dstBox, 0, 0,
1306 xb, yb, npixels, nlines,
1307 src_w, src_h, drw_w, drw_h,
1308 clipBoxes, ppix, pPriv);
1310 if (pNv->Architecture == NV_ARCH_50) {
1311 ret = nv50_xv_image_put(pScrn, pPriv->video_mem,
1313 offset + nlines * dstPitch,
1314 id, dstPitch, &dstBox, 0, 0,
1315 xb, yb, npixels, nlines,
1316 src_w, src_h, drw_w, drw_h,
1317 clipBoxes, ppix, pPriv);
1323 NVPutBlitImage(pScrn, pPriv->video_mem, offset, id, dstPitch,
1324 &dstBox, 0, 0, xb, yb, npixels, nlines,
1325 src_w, src_h, drw_w, drw_h, clipBoxes, ppix);
1332 * QueryImageAttributes
1335 * - size (memory required to store image),
1339 * depending on colorspace (id) and dimensions (w,h) of image
1343 * may be adjusted as needed
1345 * @param pScrn unused
1346 * @param id colorspace of image
1347 * @param w pointer to width of image
1348 * @param h pointer to height of image
1349 * @param pitches pitches[i] = length of a scanline in plane[i]
1350 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1351 * @return size of the memory required for the XvImage queried
1354 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1355 unsigned short *w, unsigned short *h,
1356 int *pitches, int *offsets)
1360 if (*w > IMAGE_MAX_W)
1362 if (*h > IMAGE_MAX_H)
1365 *w = (*w + 1) & ~1; // width rounded up to an even number
1372 *h = (*h + 1) & ~1; // height rounded up to an even number
1373 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1375 pitches[0] = size; // width rounded up to a multiple of 4
1378 offsets[1] = size; // number of pixels in "rounded up" image
1379 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1381 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1382 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1383 size += tmp; // 5/4*number of pixels in "rounded up" image
1385 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1386 size += tmp; // = 3/2*number of pixels in "rounded up" image
1390 size = *w << 1; // 2*width
1392 pitches[0] = size; // 2*width
1393 size *= *h; // 2*width*height
1396 size = *w << 2; // 4*width (32 bit per pixel)
1398 pitches[0] = size; // 4*width
1399 size *= *h; // 4*width*height
1409 /***** Exported offscreen surface stuff ****/
1413 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1414 unsigned short w, unsigned short h,
1415 XF86SurfacePtr surface)
1417 NVPtr pNv = NVPTR(pScrn);
1418 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1421 bpp = pScrn->bitsPerPixel >> 3;
1423 if (pPriv->grabbedByV4L)
1426 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1430 pPriv->pitch = ((w << 1) + 63) & ~63;
1431 size = h * pPriv->pitch / bpp;
1433 ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_VRAM, size,
1440 surface->height = h;
1441 surface->pScrn = pScrn;
1442 surface->pitches = &pPriv->pitch;
1443 surface->offsets = &pPriv->offset;
1444 surface->devPrivate.ptr = (pointer)pPriv;
1447 /* grab the video */
1448 NVStopOverlay(pScrn);
1449 pPriv->videoStatus = 0;
1450 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1451 pPriv->grabbedByV4L = TRUE;
1457 NVStopSurface(XF86SurfacePtr surface)
1459 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1461 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
1462 NV10StopOverlay(surface->pScrn);
1463 pPriv->videoStatus = 0;
1470 NVFreeSurface(XF86SurfacePtr surface)
1472 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1474 if (pPriv->grabbedByV4L) {
1475 NVStopSurface(surface);
1476 NVFreeOverlayMemory(surface->pScrn);
1477 pPriv->grabbedByV4L = FALSE;
1484 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
1486 NVPtr pNv = NVPTR(pScrn);
1487 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1489 return NV10GetOverlayPortAttribute(pScrn, attribute,
1490 value, (pointer)pPriv);
1494 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
1496 NVPtr pNv = NVPTR(pScrn);
1497 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1499 return NV10SetOverlayPortAttribute(pScrn, attribute,
1500 value, (pointer)pPriv);
1504 NVDisplaySurface(XF86SurfacePtr surface,
1505 short src_x, short src_y,
1506 short drw_x, short drw_y,
1507 short src_w, short src_h,
1508 short drw_w, short drw_h,
1509 RegionPtr clipBoxes)
1511 ScrnInfoPtr pScrn = surface->pScrn;
1512 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1513 INT32 xa, xb, ya, yb;
1516 if (!pPriv->grabbedByV4L)
1519 if (src_w > (drw_w << 3))
1521 if (src_h > (drw_h << 3))
1531 dstBox.x2 = drw_x + drw_w;
1533 dstBox.y2 = drw_y + drw_h;
1535 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1536 surface->width, surface->height))
1539 dstBox.x1 -= pScrn->frameX0;
1540 dstBox.x2 -= pScrn->frameX0;
1541 dstBox.y1 -= pScrn->frameY0;
1542 dstBox.y2 -= pScrn->frameY0;
1544 pPriv->currentBuffer = 0;
1546 NV10PutOverlayImage(pScrn, pPriv->video_mem, surface->offsets[0],
1547 0, surface->id, surface->pitches[0], &dstBox,
1548 xa, ya, xb, yb, surface->width, surface->height,
1549 src_w, src_h, drw_w, drw_h, clipBoxes);
1556 * this function does all the work setting up a blit port
1560 static XF86VideoAdaptorPtr
1561 NVSetupBlitVideo (ScreenPtr pScreen)
1563 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1564 NVPtr pNv = NVPTR(pScrn);
1565 XF86VideoAdaptorPtr adapt;
1566 NVPortPrivPtr pPriv;
1569 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1570 sizeof(NVPortPrivRec) +
1571 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
1575 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1577 adapt->name = "NV Video Blitter";
1578 adapt->nEncodings = 1;
1579 adapt->pEncodings = &DummyEncoding;
1580 adapt->nFormats = NUM_FORMATS_ALL;
1581 adapt->pFormats = NVFormats;
1582 adapt->nPorts = NUM_BLIT_PORTS;
1583 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1585 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
1586 for(i = 0; i < NUM_BLIT_PORTS; i++)
1587 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1589 if(pNv->WaitVSyncPossible) {
1590 adapt->pAttributes = NVBlitAttributes;
1591 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
1593 adapt->pAttributes = NULL;
1594 adapt->nAttributes = 0;
1597 adapt->pImages = NVImages;
1598 adapt->nImages = NUM_IMAGES_ALL;
1599 adapt->PutVideo = NULL;
1600 adapt->PutStill = NULL;
1601 adapt->GetVideo = NULL;
1602 adapt->GetStill = NULL;
1603 adapt->StopVideo = NVStopBlitVideo;
1604 adapt->SetPortAttribute = NVSetBlitPortAttribute;
1605 adapt->GetPortAttribute = NVGetBlitPortAttribute;
1606 adapt->QueryBestSize = NVQueryBestSize;
1607 adapt->PutImage = NVPutImage;
1608 adapt->QueryImageAttributes = NVQueryImageAttributes;
1610 pPriv->videoStatus = 0;
1611 pPriv->grabbedByV4L = FALSE;
1612 pPriv->blitter = TRUE;
1613 pPriv->texture = FALSE;
1614 pPriv->bicubic = FALSE;
1615 pPriv->doubleBuffer = FALSE;
1616 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1618 pNv->blitAdaptor = adapt;
1619 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
1625 * NVSetupOverlayVideo
1626 * this function does all the work setting up an overlay port
1628 * @return overlay port
1630 static XF86VideoAdaptorPtr
1631 NVSetupOverlayVideoAdapter(ScreenPtr pScreen)
1633 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1634 NVPtr pNv = NVPTR(pScrn);
1635 XF86VideoAdaptorPtr adapt;
1636 NVPortPrivPtr pPriv;
1638 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1639 sizeof(NVPortPrivRec) +
1640 sizeof(DevUnion)))) {
1644 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1645 if (pNv->randr12_enable)
1646 adapt->flags = VIDEO_OVERLAID_IMAGES;
1648 adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
1649 adapt->name = "NV Video Overlay";
1650 adapt->nEncodings = 1;
1651 adapt->pEncodings = &DummyEncoding;
1652 adapt->nFormats = NUM_FORMATS_ALL;
1653 adapt->pFormats = NVFormats;
1655 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1657 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
1658 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
1660 adapt->pAttributes = (pNv->Architecture != NV_ARCH_04) ? NV10OverlayAttributes : NV04OverlayAttributes;
1661 adapt->nAttributes = (pNv->Architecture != NV_ARCH_04) ? NUM_NV10_OVERLAY_ATTRIBUTES : NUM_NV04_OVERLAY_ATTRIBUTES;
1662 adapt->pImages = NVImages;
1663 adapt->nImages = NUM_IMAGES_YUV;
1664 adapt->PutVideo = NULL;
1665 adapt->PutStill = NULL;
1666 adapt->GetVideo = NULL;
1667 adapt->GetStill = NULL;
1668 adapt->StopVideo = NVStopOverlayVideo;
1669 adapt->SetPortAttribute = (pNv->Architecture != NV_ARCH_04) ? NV10SetOverlayPortAttribute : NV04SetOverlayPortAttribute;
1670 adapt->GetPortAttribute = (pNv->Architecture != NV_ARCH_04) ? NV10GetOverlayPortAttribute : NV04GetOverlayPortAttribute;
1671 adapt->QueryBestSize = NVQueryBestSize;
1672 adapt->PutImage = NVPutImage;
1673 adapt->QueryImageAttributes = NVQueryImageAttributes;
1675 pPriv->videoStatus = 0;
1676 pPriv->currentBuffer = 0;
1677 pPriv->grabbedByV4L = FALSE;
1678 pPriv->blitter = FALSE;
1679 pPriv->texture = FALSE;
1680 pPriv->bicubic = FALSE;
1682 NVSetPortDefaults (pScrn, pPriv);
1684 /* gotta uninit this someplace */
1685 REGION_NULL(pScreen, &pPriv->clip);
1687 pNv->overlayAdaptor = adapt;
1689 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
1690 xvColorKey = MAKE_ATOM("XV_COLORKEY");
1691 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
1692 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
1694 if ( pNv->Architecture != NV_ARCH_04 )
1696 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
1697 xvContrast = MAKE_ATOM("XV_CONTRAST");
1698 xvSaturation = MAKE_ATOM("XV_SATURATION");
1699 xvHue = MAKE_ATOM("XV_HUE");
1700 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
1701 xvOnCRTCNb = MAKE_ATOM("XV_ON_CRTC_NB");
1702 NV10WriteOverlayParameters(pScrn);
1709 XF86OffscreenImageRec NVOffscreenImages[2] = {
1712 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1717 NVGetSurfaceAttribute,
1718 NVSetSurfaceAttribute,
1719 IMAGE_MAX_W, IMAGE_MAX_H,
1720 NUM_NV10_OVERLAY_ATTRIBUTES - 1,
1721 &NV10OverlayAttributes[1]
1725 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1730 NVGetSurfaceAttribute,
1731 NVSetSurfaceAttribute,
1732 IMAGE_MAX_W, IMAGE_MAX_H,
1733 NUM_NV10_OVERLAY_ATTRIBUTES - 1,
1734 &NV10OverlayAttributes[1]
1739 NVInitOffscreenImages (ScreenPtr pScreen)
1741 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
1745 * NVChipsetHasOverlay
1747 * newer chips don't support overlay anymore.
1748 * overlay feature is emulated via textures.
1751 * @return true, if chipset supports overlay
1754 NVChipsetHasOverlay(NVPtr pNv)
1756 switch (pNv->Architecture) {
1757 case NV_ARCH_04: /*NV04 has a different overlay than NV10+*/
1763 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
1774 * NVSetupOverlayVideo
1775 * check if chipset supports Overla
1776 * if so, setup overlay port
1778 * @return overlay port
1779 * @see NVChipsetHasOverlay(NVPtr pNv)
1780 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
1781 * @see NVInitOffscreenImages(ScreenPtr pScreen)
1783 static XF86VideoAdaptorPtr
1784 NVSetupOverlayVideo(ScreenPtr pScreen)
1786 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1787 XF86VideoAdaptorPtr overlayAdaptor = NULL;
1788 NVPtr pNv = NVPTR(pScrn);
1790 if (!NVChipsetHasOverlay(pNv))
1793 overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen);
1794 /* I am not sure what this call does. */
1795 if (overlayAdaptor && pNv->Architecture != NV_ARCH_04 )
1796 NVInitOffscreenImages(pScreen);
1799 if (!noCompositeExtension) {
1800 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1801 "Xv: Composite is enabled, enabling overlay with "
1802 "smart blitter fallback\n");
1803 overlayAdaptor->name = "NV Video Overlay with Composite";
1807 if (pNv->randr12_enable) {
1808 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1809 "Xv: Randr12 is enabled, using overlay with smart "
1810 "blitter fallback and automatic CRTC switching\n");
1814 return overlayAdaptor;
1818 * NV30 texture adapter.
1821 #define NUM_FORMAT_TEXTURED 2
1823 static XF86ImageRec NV30TexturedImages[NUM_FORMAT_TEXTURED] =
1830 * NV30SetupTexturedVideo
1831 * this function does all the work setting up textured video port
1833 * @return texture port
1835 static XF86VideoAdaptorPtr
1836 NV30SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic)
1838 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1839 NVPtr pNv = NVPTR(pScrn);
1840 XF86VideoAdaptorPtr adapt;
1841 NVPortPrivPtr pPriv;
1844 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1845 sizeof(NVPortPrivRec) +
1846 (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
1850 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1853 adapt->name = "NV30 high quality adapter";
1855 adapt->name = "NV30 texture adapter";
1856 adapt->nEncodings = 1;
1857 adapt->pEncodings = &DummyEncodingTex;
1858 adapt->nFormats = NUM_FORMATS_ALL;
1859 adapt->pFormats = NVFormats;
1860 adapt->nPorts = NUM_TEXTURE_PORTS;
1861 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1863 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
1864 for(i = 0; i < NUM_TEXTURE_PORTS; i++)
1865 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1867 if(pNv->WaitVSyncPossible) {
1868 adapt->pAttributes = NVTexturedAttributes;
1869 adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
1871 adapt->pAttributes = NULL;
1872 adapt->nAttributes = 0;
1875 adapt->pImages = NV30TexturedImages;
1876 adapt->nImages = NUM_FORMAT_TEXTURED;
1877 adapt->PutVideo = NULL;
1878 adapt->PutStill = NULL;
1879 adapt->GetVideo = NULL;
1880 adapt->GetStill = NULL;
1881 adapt->StopVideo = NV30StopTexturedVideo;
1882 adapt->SetPortAttribute = NV30SetTexturePortAttribute;
1883 adapt->GetPortAttribute = NV30GetTexturePortAttribute;
1884 adapt->QueryBestSize = NVQueryBestSize;
1885 adapt->PutImage = NVPutImage;
1886 adapt->QueryImageAttributes = NVQueryImageAttributes;
1888 pPriv->videoStatus = 0;
1889 pPriv->grabbedByV4L = FALSE;
1890 pPriv->blitter = FALSE;
1891 pPriv->texture = TRUE;
1892 pPriv->bicubic = bicubic;
1893 pPriv->doubleBuffer = FALSE;
1894 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1897 pNv->textureAdaptor[1] = adapt;
1899 pNv->textureAdaptor[0] = adapt;
1905 * NV40 texture adapter.
1908 #define NUM_FORMAT_TEXTURED 2
1910 static XF86ImageRec NV40TexturedImages[NUM_FORMAT_TEXTURED] =
1917 * NV40SetupTexturedVideo
1918 * this function does all the work setting up textured video port
1920 * @return texture port
1922 static XF86VideoAdaptorPtr
1923 NV40SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic)
1925 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1926 NVPtr pNv = NVPTR(pScrn);
1927 XF86VideoAdaptorPtr adapt;
1928 NVPortPrivPtr pPriv;
1931 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1932 sizeof(NVPortPrivRec) +
1933 (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
1937 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1940 adapt->name = "NV40 high quality adapter";
1942 adapt->name = "NV40 texture adapter";
1943 adapt->nEncodings = 1;
1944 adapt->pEncodings = &DummyEncodingTex;
1945 adapt->nFormats = NUM_FORMATS_ALL;
1946 adapt->pFormats = NVFormats;
1947 adapt->nPorts = NUM_TEXTURE_PORTS;
1948 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1950 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
1951 for(i = 0; i < NUM_TEXTURE_PORTS; i++)
1952 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1954 if(pNv->WaitVSyncPossible) {
1955 adapt->pAttributes = NVTexturedAttributes;
1956 adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
1958 adapt->pAttributes = NULL;
1959 adapt->nAttributes = 0;
1962 adapt->pImages = NV40TexturedImages;
1963 adapt->nImages = NUM_FORMAT_TEXTURED;
1964 adapt->PutVideo = NULL;
1965 adapt->PutStill = NULL;
1966 adapt->GetVideo = NULL;
1967 adapt->GetStill = NULL;
1968 adapt->StopVideo = NV40StopTexturedVideo;
1969 adapt->SetPortAttribute = NV40SetTexturePortAttribute;
1970 adapt->GetPortAttribute = NV40GetTexturePortAttribute;
1971 adapt->QueryBestSize = NVQueryBestSize;
1972 adapt->PutImage = NVPutImage;
1973 adapt->QueryImageAttributes = NVQueryImageAttributes;
1975 pPriv->videoStatus = 0;
1976 pPriv->grabbedByV4L = FALSE;
1977 pPriv->blitter = FALSE;
1978 pPriv->texture = TRUE;
1979 pPriv->bicubic = bicubic;
1980 pPriv->doubleBuffer = FALSE;
1981 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1984 pNv->textureAdaptor[1] = adapt;
1986 pNv->textureAdaptor[0] = adapt;
1992 NV50TexturedImages[] =
1999 static XF86VideoAdaptorPtr
2000 NV50SetupTexturedVideo (ScreenPtr pScreen)
2002 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2003 NVPtr pNv = NVPTR(pScrn);
2004 XF86VideoAdaptorPtr adapt;
2005 NVPortPrivPtr pPriv;
2008 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2009 sizeof(NVPortPrivRec) +
2010 (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
2014 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2016 adapt->name = "Nouveau GeForce 8/9 Textured Video";
2017 adapt->nEncodings = 1;
2018 adapt->pEncodings = &DummyEncodingTex;
2019 adapt->nFormats = NUM_FORMATS_ALL;
2020 adapt->pFormats = NVFormats;
2021 adapt->nPorts = NUM_TEXTURE_PORTS;
2022 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2024 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
2025 for(i = 0; i < NUM_TEXTURE_PORTS; i++)
2026 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2028 adapt->pAttributes = NULL;
2029 adapt->nAttributes = 0;
2030 adapt->pImages = NV50TexturedImages;
2031 adapt->nImages = sizeof(NV50TexturedImages) /
2032 sizeof(NV50TexturedImages[0]);
2033 adapt->PutVideo = NULL;
2034 adapt->PutStill = NULL;
2035 adapt->GetVideo = NULL;
2036 adapt->GetStill = NULL;
2037 adapt->StopVideo = nv50_xv_video_stop;
2038 adapt->SetPortAttribute = nv50_xv_port_attribute_set;
2039 adapt->GetPortAttribute = nv50_xv_port_attribute_get;
2040 adapt->QueryBestSize = NVQueryBestSize;
2041 adapt->PutImage = NVPutImage;
2042 adapt->QueryImageAttributes = NVQueryImageAttributes;
2044 pPriv->videoStatus = 0;
2045 pPriv->grabbedByV4L = FALSE;
2046 pPriv->blitter = FALSE;
2047 pPriv->texture = TRUE;
2048 pPriv->doubleBuffer = FALSE;
2049 pPriv->SyncToVBlank = 0;
2051 pNv->textureAdaptor[0] = adapt;
2058 * tries to initialize the various supported adapters
2059 * and add them to the list of ports on screen "pScreen".
2062 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
2063 * @see NVSetupBlitVideo(ScreenPtr pScreen)
2066 NVInitVideo(ScreenPtr pScreen)
2068 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2069 NVPtr pNv = NVPTR(pScrn);
2070 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
2071 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2072 XF86VideoAdaptorPtr blitAdaptor = NULL;
2073 XF86VideoAdaptorPtr textureAdaptor[2] = {NULL, NULL};
2077 * Driving the blitter requires the DMA FIFO. Using the FIFO
2078 * without accel causes DMA errors. While the overlay might
2079 * might work without accel, we also disable it for now when
2080 * acceleration is disabled:
2082 if (pScrn->bitsPerPixel != 8 && !pNv->NoAccel) {
2083 if (pNv->Architecture < NV_ARCH_50) {
2084 overlayAdaptor = NVSetupOverlayVideo(pScreen);
2085 blitAdaptor = NVSetupBlitVideo(pScreen);
2088 if (pNv->Architecture == NV_ARCH_30) {
2089 textureAdaptor[0] = NV30SetupTexturedVideo(pScreen, FALSE);
2090 textureAdaptor[1] = NV30SetupTexturedVideo(pScreen, TRUE);
2092 if (pNv->Architecture == NV_ARCH_40) {
2093 textureAdaptor[0] = NV40SetupTexturedVideo(pScreen, FALSE);
2094 textureAdaptor[1] = NV40SetupTexturedVideo(pScreen, TRUE);
2096 if (pNv->Architecture == NV_ARCH_50) {
2097 textureAdaptor[0] = NV50SetupTexturedVideo(pScreen);
2101 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
2102 if (blitAdaptor || overlayAdaptor || textureAdaptor[0]) {
2103 int size = num_adaptors;
2105 if(overlayAdaptor) size++;
2106 if(blitAdaptor) size++;
2107 if(textureAdaptor[0]) size++;
2108 if(textureAdaptor[1]) size++;
2110 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
2113 memcpy(newAdaptors, adaptors, num_adaptors *
2114 sizeof(XF86VideoAdaptorPtr));
2117 if(overlayAdaptor) {
2118 newAdaptors[num_adaptors] = overlayAdaptor;
2122 if (textureAdaptor[0]) { /* bilinear */
2123 newAdaptors[num_adaptors] = textureAdaptor[0];
2127 if (textureAdaptor[1]) { /* bicubic */
2128 newAdaptors[num_adaptors] = textureAdaptor[1];
2133 newAdaptors[num_adaptors] = blitAdaptor;
2137 adaptors = newAdaptors;
2142 xf86XVScreenInit(pScreen, adaptors, num_adaptors);
2147 * For now we associate with the plain texture adapter since it is logical, but we can
2148 * associate with any/all adapters since VL doesn't depend on Xv for color conversion.
2150 if (textureAdaptor[0]) {
2151 XF86MCAdaptorPtr *adaptorsXvMC = xalloc(sizeof(XF86MCAdaptorPtr));
2154 adaptorsXvMC[0] = vlCreateAdaptorXvMC(pScreen, textureAdaptor[0]->name);
2156 if (adaptorsXvMC[0]) {
2157 vlInitXvMC(pScreen, 1, adaptorsXvMC);
2158 vlDestroyAdaptorXvMC(adaptorsXvMC[0]);
2161 xfree(adaptorsXvMC);