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 /* Xv DMA notifiers status tracing */
61 XV_DMA_NOTIFIER_NOALLOC=0, //notifier not allocated
62 XV_DMA_NOTIFIER_INUSE=1,
63 XV_DMA_NOTIFIER_FREE=2, //notifier allocated, ready for use
66 /* We have six notifiers available, they are not allocated at startup */
67 static int XvDMANotifierStatus[6] = { XV_DMA_NOTIFIER_NOALLOC,
68 XV_DMA_NOTIFIER_NOALLOC,
69 XV_DMA_NOTIFIER_NOALLOC,
70 XV_DMA_NOTIFIER_NOALLOC,
71 XV_DMA_NOTIFIER_NOALLOC,
72 XV_DMA_NOTIFIER_NOALLOC };
73 static struct nouveau_notifier *XvDMANotifiers[6];
75 /* NVPutImage action flags */
83 IS_RGB=64, //I am not sure how long we will support it
86 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
88 Atom xvBrightness, xvContrast, xvColorKey, xvSaturation;
89 Atom xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer;
90 Atom xvITURBT709, xvSyncToVBlank, xvOnCRTCNb;
92 /* client libraries expect an encoding */
93 static XF86VideoEncodingRec DummyEncoding =
97 IMAGE_MAX_W, IMAGE_MAX_H,
101 static XF86VideoEncodingRec DummyEncodingTex =
105 TEX_IMAGE_MAX_W, TEX_IMAGE_MAX_H,
109 #define NUM_FORMATS_ALL 6
111 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
113 {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
114 {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
117 #define NUM_NV04_OVERLAY_ATTRIBUTES 4
118 XF86AttributeRec NV04OverlayAttributes[NUM_NV04_OVERLAY_ATTRIBUTES] =
120 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
121 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
122 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
123 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
127 #define NUM_NV10_OVERLAY_ATTRIBUTES 10
128 XF86AttributeRec NV10OverlayAttributes[NUM_NV10_OVERLAY_ATTRIBUTES] =
130 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
131 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
132 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
133 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
134 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
135 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
136 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
137 {XvSettable | XvGettable, 0, 360, "XV_HUE"},
138 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"},
139 {XvSettable | XvGettable, 0, 1, "XV_ON_CRTC_NB"},
142 #define NUM_BLIT_ATTRIBUTES 2
143 XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
145 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
146 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
149 #define NUM_TEXTURED_ATTRIBUTES 2
150 XF86AttributeRec NVTexturedAttributes[NUM_TEXTURED_ATTRIBUTES] =
152 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
153 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
157 #define NUM_IMAGES_YUV 4
158 #define NUM_IMAGES_ALL 5
160 #define FOURCC_RGB 0x0000003
161 #define XVIMAGE_RGB \
166 { 0x03, 0x00, 0x00, 0x00, \
167 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
171 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
176 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}, \
180 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
190 nv_window_belongs_to_crtc(ScrnInfoPtr pScrn, int x, int y, int w, int h)
192 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
193 NVPtr pNv = NVPTR(pScrn);
195 unsigned int mask = 0;
197 if (!pNv->randr12_enable) {
199 * Without RandR 1.2, we'll just return which CRTCs
202 if (pNv->crtc_active[0])
204 else if (pNv->crtc_active[1])
210 for (i = 0; i < xf86_config->num_crtc; i++) {
211 xf86CrtcPtr crtc = xf86_config->crtc[i];
216 if ((x < (crtc->x + crtc->mode.HDisplay)) &&
217 (y < (crtc->y + crtc->mode.VDisplay)) &&
218 ((x + w) > crtc->x) &&
227 NVWaitVSync(ScrnInfoPtr pScrn, int crtc)
229 NVPtr pNv = NVPTR(pScrn);
230 struct nouveau_channel *chan = pNv->chan;
231 struct nouveau_grobj *blit = pNv->NvImageBlit;
233 BEGIN_RING(chan, blit, 0x0000012C, 1);
235 BEGIN_RING(chan, blit, 0x00000134, 1);
236 OUT_RING (chan, crtc);
237 BEGIN_RING(chan, blit, 0x00000100, 1);
239 BEGIN_RING(chan, blit, 0x00000130, 1);
245 * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
246 * this function does not care about the kind of adapter the port is for
248 * @param pScrn screen to get the default colorKey from
249 * @param pPriv port to reset to defaults
252 NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
254 NVPtr pNv = NVPTR(pScrn);
256 pPriv->brightness = 0;
257 pPriv->contrast = 4096;
258 pPriv->saturation = 4096;
260 pPriv->colorKey = pNv->videoKey;
261 pPriv->autopaintColorKey = TRUE;
262 pPriv->doubleBuffer = pNv->Architecture != NV_ARCH_04;
263 pPriv->iturbt_709 = FALSE;
264 pPriv->currentHostBuffer = 0;
268 * NVXvDMANotifierAlloc
269 * allocates a notifier from the table of 6 we have
271 * @return a notifier instance or NULL on error
273 static struct nouveau_notifier *
274 NVXvDMANotifierAlloc(ScrnInfoPtr pScrn)
276 NVPtr pNv = NVPTR(pScrn);
279 for (i = 0; i < 6; i++) {
280 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_INUSE)
283 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_FREE) {
284 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
285 return XvDMANotifiers[i];
288 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_NOALLOC) {
289 if (nouveau_notifier_alloc(pNv->chan,
290 NvDmaXvNotifier0 + i,
291 1, &XvDMANotifiers[i]))
293 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
294 return XvDMANotifiers[i];
302 * NVXvDMANotifierFree
303 * frees a notifier from the table of 6 we have
308 NVXvDMANotifierFree(ScrnInfoPtr pScrn, struct nouveau_notifier **ptarget)
310 struct nouveau_notifier *target;
313 if (!ptarget || !*ptarget)
318 for (i = 0; i < 6; i ++) {
319 if (XvDMANotifiers[i] == target)
323 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_FREE;
327 nouveau_xv_bo_realloc(ScrnInfoPtr pScrn, unsigned flags, unsigned size,
328 struct nouveau_bo **pbo)
330 NVPtr pNv = NVPTR(pScrn);
334 if ((*pbo)->size >= size)
339 if (pNv->Architecture >= NV_ARCH_50 && (flags & NOUVEAU_BO_VRAM))
340 flags |= NOUVEAU_BO_TILE;
342 ret = nouveau_bo_new(pNv->dev, flags | NOUVEAU_BO_PIN, 0, size, pbo);
346 ret = nouveau_bo_map(*pbo, NOUVEAU_BO_RDWR);
357 * frees memory held by a given port
359 * @param pScrn screen whose port wants to free memory
360 * @param pPriv port to free memory of
363 NVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
365 if(pPriv->video_mem) {
366 nouveau_bo_del(&pPriv->video_mem);
367 pPriv->video_mem = NULL;
370 if (pPriv->TT_mem_chunk[0] && pPriv->DMANotifier[0])
371 nouveau_notifier_wait_status(pPriv->DMANotifier[0], 0, 0, 1000);
373 if (pPriv->TT_mem_chunk[1] && pPriv->DMANotifier[1])
374 nouveau_notifier_wait_status(pPriv->DMANotifier[1], 0, 0, 1000);
376 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
377 nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
378 NVXvDMANotifierFree(pScrn, &pPriv->DMANotifier[0]);
379 NVXvDMANotifierFree(pScrn, &pPriv->DMANotifier[1]);
384 * NVFreeOverlayMemory
385 * frees memory held by the overlay port
387 * @param pScrn screen whose overlay port wants to free memory
390 NVFreeOverlayMemory(ScrnInfoPtr pScrn)
392 NVPtr pNv = NVPTR(pScrn);
393 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
395 NVFreePortMemory(pScrn, pPriv);
397 /* "power cycle" the overlay */
398 nvWriteMC(pNv, NV_PMC_ENABLE,
399 (nvReadMC(pNv, NV_PMC_ENABLE) & 0xEFFFFFFF));
400 nvWriteMC(pNv, NV_PMC_ENABLE,
401 (nvReadMC(pNv, NV_PMC_ENABLE) | 0x10000000));
406 * frees memory held by the blit port
408 * @param pScrn screen whose blit port wants to free memory
411 NVFreeBlitMemory(ScrnInfoPtr pScrn)
413 NVPtr pNv = NVPTR(pScrn);
414 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
416 NVFreePortMemory(pScrn, pPriv);
420 * NVVideoTimerCallback
421 * callback function which perform cleanup tasks (stop overlay, free memory).
423 * purpose and use is unknown
426 NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
428 NVPtr pNv = NVPTR(pScrn);
429 NVPortPrivPtr pOverPriv = NULL;
430 NVPortPrivPtr pBlitPriv = NULL;
431 Bool needCallback = FALSE;
436 if (pNv->overlayAdaptor) {
437 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
438 if (!pOverPriv->videoStatus)
442 if (pNv->blitAdaptor) {
443 pBlitPriv = GET_BLIT_PRIVATE(pNv);
444 if (!pBlitPriv->videoStatus)
449 if (pOverPriv->videoTime < currentTime) {
450 if (pOverPriv->videoStatus & OFF_TIMER) {
451 NVStopOverlay(pScrn);
452 pOverPriv->videoStatus = FREE_TIMER;
453 pOverPriv->videoTime = currentTime + FREE_DELAY;
456 if (pOverPriv->videoStatus & FREE_TIMER) {
457 NVFreeOverlayMemory(pScrn);
458 pOverPriv->videoStatus = 0;
466 if (pBlitPriv->videoTime < currentTime) {
467 NVFreeBlitMemory(pScrn);
468 pBlitPriv->videoStatus = 0;
474 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
477 #ifndef ExaOffscreenMarkUsed
478 extern void ExaOffscreenMarkUsed(PixmapPtr);
485 NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
487 NVPtr pNv = NVPTR(pScrn);
488 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
490 if (pPriv->grabbedByV4L)
493 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
496 if (pPriv->videoStatus & CLIENT_VIDEO_ON)
497 NVStopOverlay(pScrn);
498 NVFreeOverlayMemory(pScrn);
499 pPriv->videoStatus = 0;
501 if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
502 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
503 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
504 pNv->VideoTimerCallback = NVVideoTimerCallback;
511 * used by client applications to ask the driver:
512 * how would you actually scale a video of dimensions
513 * vid_w, vid_h, if i wanted you to scale it to dimensions
515 * function stores actual scaling size in pointers p_w, p_h.
518 * @param pScrn unused
519 * @param motion unused
520 * @param vid_w width of source video
521 * @param vid_h height of source video
522 * @param drw_w desired scaled width as requested by client
523 * @param drw_h desired scaled height as requested by client
524 * @param p_w actual scaled width as the driver is capable of
525 * @param p_h actual scaled height as the driver is capable of
529 NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
530 short vid_w, short vid_h,
531 short drw_w, short drw_h,
532 unsigned int *p_w, unsigned int *p_h,
535 if(vid_w > (drw_w << 3))
537 if(vid_h > (drw_h << 3))
546 * used to convert YV12 to YUY2 for the blitter and NV04 overlay.
547 * The U and V samples generated are linearly interpolated on the vertical
548 * axis for better quality
550 * @param src1 source buffer of luma
551 * @param src2 source buffer of chroma1
552 * @param src3 source buffer of chroma2
553 * @param dst1 destination buffer
554 * @param srcPitch pitch of src1
555 * @param srcPitch2 pitch of src2, src3
556 * @param dstPitch pitch of dst1
557 * @param h number of lines to copy
558 * @param w length of lines to copy
561 NVCopyData420(unsigned char *src1, unsigned char *src2, unsigned char *src3,
562 unsigned char *dst1, int srcPitch, int srcPitch2, int dstPitch,
569 #define su(X) (((j & 1) && j < (h-1)) ? ((unsigned)((signed int)s2[X] + \
570 (signed int)(s2 + srcPitch2)[X]) / 2) : (s2[X]))
571 #define sv(X) (((j & 1) && j < (h-1)) ? ((unsigned)((signed int)s3[X] + \
572 (signed int)(s3 + srcPitch2)[X]) / 2) : (s3[X]))
576 for (j = 0; j < h; j++) {
578 s1 = src1; s2 = src2; s3 = src3;
582 #if X_BYTE_ORDER == X_BIG_ENDIAN
583 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (sv(0) << 16) | su(0);
584 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (sv(1) << 16) | su(1);
585 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (sv(2) << 16) | su(2);
586 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (sv(3) << 16) | su(3);
588 dst[0] = s1[0] | (s1[1] << 16) | (sv(0) << 8) | (su(0) << 24);
589 dst[1] = s1[2] | (s1[3] << 16) | (sv(1) << 8) | (su(1) << 24);
590 dst[2] = s1[4] | (s1[5] << 16) | (sv(2) << 8) | (su(2) << 24);
591 dst[3] = s1[6] | (s1[7] << 16) | (sv(3) << 8) | (su(3) << 24);
593 dst += 4; s2 += 4; s3 += 4; s1 += 8;
598 #if X_BYTE_ORDER == X_BIG_ENDIAN
599 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (sv(0) << 16) | su(0);
601 dst[0] = s1[0] | (s1[1] << 16) | (sv(0) << 8) | (su(0) << 24);
617 * NVCopyNV12ColorPlanes
618 * Used to convert YV12 color planes to NV12 (interleaved UV) for the overlay
620 * @param src1 source buffer of chroma1
621 * @param dst1 destination buffer
622 * @param h number of lines to copy
623 * @param w length of lines to copy
624 * @param id source pixel format (YV12 or I420)
627 NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char *src2,
628 unsigned char *dst, int dstPitch, int srcPitch2,
638 for (j = 0; j < h; j++) {
639 unsigned char *us = src1;
640 unsigned char *vs = src2;
641 unsigned int *vuvud = (unsigned int *) dst;
643 for (i = 0; i < l; i++) {
644 #if X_BYTE_ORDER == X_BIG_ENDIAN
645 *vuvud++ = (vs[0]<<24) | (us[0]<<16) | (vs[1]<<8) | us[1];
647 *vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24);
654 unsigned short *vud = (unsigned short *) vuvud;
656 *vud = vs[0] | (us[0]<<8);
668 NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 *xa, INT32 *xb,
669 INT32 *ya, INT32 *yb, short *src_x, short *src_y,
670 short *src_w, short *src_h, short *drw_x, short *drw_y,
671 short *drw_w, short *drw_h, int *left, int *top, int *right,
672 int *bottom, BoxRec *dstBox, int *npixels, int *nlines,
673 RegionPtr clipBoxes, short width, short height)
675 NVPtr pNv = NVPTR(pScrn);
677 if (action_flags & USE_OVERLAY) {
678 switch (pNv->Architecture) {
680 /* NV0x overlay can't scale down. at all. */
687 /* According to DirectFB, NV3x can't scale down by
690 if (*drw_w < (*src_w) >> 1)
692 if (*drw_h < (*src_h) >> 1)
695 default: /*NV10, NV20*/
696 /* NV1x overlay can't scale down by a ratio > 8 */
697 if (*drw_w < (*src_w) >> 3)
698 *drw_w = *src_w >> 3;
699 if (*drw_h < (*src_h >> 3))
700 *drw_h = *src_h >> 3;
706 *xb = *src_x + *src_w;
708 *yb = *src_y + *src_h;
711 dstBox->x2 = *drw_x + *drw_w;
713 dstBox->y2 = *drw_y + *drw_h;
715 /* In randr 1.2 mode VIDEO_CLIP_TO_VIEWPORT is broken (hence it is not
716 * set in the overlay adapter flags) since pScrn->frame{X,Y}1 do not get
717 * updated. Hence manual clipping against the CRTC dimensions
719 if (pNv->randr12_enable && action_flags & USE_OVERLAY) {
720 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
721 unsigned id = pPriv->overlayCRTC;
722 xf86CrtcPtr crtc = XF86_CRTC_CONFIG_PTR(pScrn)->crtc[id];
728 VPBox.x2 = crtc->x + crtc->mode.HDisplay;
729 VPBox.y2 = crtc->y + crtc->mode.VDisplay;
731 REGION_INIT(pScreen, &VPReg, &VPBox, 1);
732 REGION_INTERSECT(pScreen, clipBoxes, clipBoxes, &VPReg);
733 REGION_UNINIT(pScreen, &VPReg);
736 if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
740 if (action_flags & USE_OVERLAY) {
741 if (!pNv->randr12_enable) {
742 dstBox->x1 -= pScrn->frameX0;
743 dstBox->x2 -= pScrn->frameX0;
744 dstBox->y1 -= pScrn->frameY0;
745 dstBox->y2 -= pScrn->frameY0;
747 xf86CrtcConfigPtr xf86_config =
748 XF86_CRTC_CONFIG_PTR(pScrn);
749 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
751 dstBox->x1 -= xf86_config->crtc[pPriv->overlayCRTC]->x;
752 dstBox->x2 -= xf86_config->crtc[pPriv->overlayCRTC]->x;
753 dstBox->y1 -= xf86_config->crtc[pPriv->overlayCRTC]->y;
754 dstBox->y2 -= xf86_config->crtc[pPriv->overlayCRTC]->y;
758 /* Convert fixed point to integer, as xf86XVClipVideoHelper probably
759 * turns its parameter into fixed point values
769 *right = (*xb) >> 16;
773 *bottom = (*yb) >> 16;
774 if (*bottom > height)
777 if (action_flags & IS_YV12) {
778 /* even "left", even "top", even number of pixels per line
779 * and even number of lines
782 *npixels = ((*right + 1) & ~1) - *left;
784 *nlines = ((*bottom + 1) & ~1) - *top;
786 if (action_flags & IS_YUY2) {
789 /* even number of pixels per line */
790 *npixels = ((*right + 1) & ~1) - *left;
791 *nlines = *bottom - *top;
795 if (action_flags & IS_RGB) {
796 *npixels = *right - *left;
797 *nlines = *bottom - *top;
806 NV_calculate_pitches_and_mem_size(int action_flags, int *srcPitch,
807 int *srcPitch2, int *dstPitch, int *s2offset,
808 int *s3offset, int *newFBSize, int *newTTSize,
809 int *line_len, int npixels, int nlines,
810 int width, int height)
814 if (action_flags & IS_YV12) {
815 *srcPitch = (width + 3) & ~3; /* of luma */
816 *s2offset = *srcPitch * height;
817 *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
818 *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
819 *dstPitch = (npixels + 63) & ~63; /*luma and chroma pitch*/
821 *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
822 *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
824 if (action_flags & IS_YUY2) {
825 *srcPitch = width << 1; /* one luma, one chroma per pixel */
826 *dstPitch = ((npixels << 1) + 63) & ~63;
827 *line_len = npixels << 1;
828 *newFBSize = nlines * *dstPitch;
829 *newTTSize = nlines * *line_len;
831 if (action_flags & IS_RGB) {
832 /* one R, one G, one B, one X per pixel */
833 *srcPitch = width << 2;
834 *dstPitch = ((npixels << 2) + 63) & ~63;
835 *line_len = npixels << 2;
836 *newFBSize = nlines * *dstPitch;
837 *newTTSize = nlines * *dstPitch;
840 if (action_flags & CONVERT_TO_YUY2) {
841 *dstPitch = ((npixels << 1) + 63) & ~63;
842 *line_len = npixels << 1;
843 *newFBSize = nlines * *dstPitch;
844 *newTTSize = nlines * *line_len;
847 if (action_flags & SWAP_UV) {
848 /* I420 swaps U and V */
850 *s2offset = *s3offset;
854 /* Overlay double buffering... */
855 if (action_flags & USE_OVERLAY)
863 * NV_set_action_flags
864 * This function computes the action flags from the input image,
865 * that is, it decides what NVPutImage and its helpers must do.
866 * This eases readability by avoiding lots of switch-case statements in the
870 NV_set_action_flags(ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv,
871 int id, short drw_x, short drw_y, short drw_w, short drw_h,
874 NVPtr pNv = NVPTR(pScrn);
876 #define USING_OVERLAY (*action_flags & USE_OVERLAY)
877 #define USING_TEXTURE (*action_flags & USE_TEXTURE)
878 #define USING_BLITTER ((!(*action_flags & USE_OVERLAY)) && \
879 (!(*action_flags & USE_TEXTURE)))
883 /* Pixel format-related bits */
884 if (id == FOURCC_YUY2 || id == FOURCC_UYVY)
885 *action_flags |= IS_YUY2;
887 if (id == FOURCC_YV12 || id == FOURCC_I420)
888 *action_flags |= IS_YV12;
890 if (id == FOURCC_RGB) /*How long will we support it?*/
891 *action_flags |= IS_RGB;
893 if (id == FOURCC_I420) /* I420 is YV12 with swapped UV */
894 *action_flags |= SWAP_UV;
896 /* Desired adapter */
897 if (!pPriv->blitter && !pPriv->texture)
898 *action_flags |= USE_OVERLAY;
900 if (!pPriv->blitter && pPriv->texture)
901 *action_flags |= USE_TEXTURE;
903 /* Adapter fallbacks (when the desired one can't be used)*/
906 PixmapPtr ppix = NVGetDrawablePixmap(pDraw);
908 if (!NVExaPixmapIsOnscreen(ppix))
909 *action_flags &= ~USE_OVERLAY;
913 if (USING_OVERLAY && pNv->randr12_enable) {
914 char crtc = nv_window_belongs_to_crtc(pScrn, drw_x, drw_y,
917 if ((crtc & (1 << 0)) && (crtc & (1 << 1))) {
918 /* The overlay cannot be used on two CRTCs at a time,
919 * so we need to fallback on the blitter
921 *action_flags &= ~USE_OVERLAY;
923 if ((crtc & (1 << 0))) {
924 /* We need to put the overlay on CRTC0 - if it's not
927 if (pPriv->overlayCRTC == 1) {
928 NVWriteCRTC(pNv, 0, NV_CRTC_FSEL,
929 NVReadCRTC(pNv, 0, NV_CRTC_FSEL) |
930 NV_CRTC_FSEL_OVERLAY);
931 NVWriteCRTC(pNv, 1, NV_CRTC_FSEL,
932 NVReadCRTC(pNv, 1, NV_CRTC_FSEL) &
933 ~NV_CRTC_FSEL_OVERLAY);
934 pPriv->overlayCRTC = 0;
937 if ((crtc & (1 << 1))) {
938 if (pPriv->overlayCRTC == 0) {
939 NVWriteCRTC(pNv, 1, NV_CRTC_FSEL,
940 NVReadCRTC(pNv, 1, NV_CRTC_FSEL) |
941 NV_CRTC_FSEL_OVERLAY);
942 NVWriteCRTC(pNv, 0, NV_CRTC_FSEL,
943 NVReadCRTC(pNv, 0, NV_CRTC_FSEL) &
944 ~NV_CRTC_FSEL_OVERLAY);
945 pPriv->overlayCRTC = 1;
949 if (XF86_CRTC_CONFIG_PTR(pScrn)->crtc[pPriv->overlayCRTC]
950 ->rotation != RR_Rotate_0)
951 *action_flags &= ~USE_OVERLAY;
954 /* At this point the adapter we're going to use is _known_.
955 * You cannot change it now.
958 /* Card/adapter format restrictions */
960 /* The blitter does not handle YV12 natively */
961 if (id == FOURCC_YV12 || id == FOURCC_I420)
962 *action_flags |= CONVERT_TO_YUY2;
965 if (USING_OVERLAY && (pNv->Architecture == NV_ARCH_04)) {
966 /* NV04-05 don't support YV12, only YUY2 and ITU-R BT.601 */
967 if (*action_flags & IS_YV12)
968 *action_flags |= CONVERT_TO_YUY2;
971 if (USING_OVERLAY && (pNv->Architecture == NV_ARCH_10 ||
972 pNv->Architecture == NV_ARCH_20)) {
973 /* No YV12 overlay on NV10, 11, 15, 20, NFORCE */
974 switch (pNv->Chipset & 0xfff0) {
978 case CHIPSET_NFORCE: /*XXX: unsure about nforce*/
980 *action_flags |= CONVERT_TO_YUY2;
991 * PutImage is "the" important function of the Xv extension.
992 * a client (e.g. video player) calls this function for every
993 * image (of the video) to be displayed. this function then
994 * scales and displays the image.
996 * @param pScrn screen which hold the port where the image is put
997 * @param src_x source point in the source image to start displaying from
998 * @param src_y see above
999 * @param src_w width of the source image to display
1000 * @param src_h see above
1001 * @param drw_x screen point to display to
1003 * @param drw_w width of the screen drawable
1005 * @param id pixel format of image
1006 * @param buf pointer to buffer containing the source image
1007 * @param width total width of the source image we are passed
1009 * @param Sync unused
1010 * @param clipBoxes ??
1011 * @param data pointer to port
1012 * @param pDraw drawable pointer
1015 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x,
1016 short drw_y, short src_w, short src_h, short drw_w, short drw_h,
1017 int id, unsigned char *buf, short width, short height,
1018 Bool Sync, RegionPtr clipBoxes, pointer data, DrawablePtr pDraw)
1020 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1021 NVPtr pNv = NVPTR(pScrn);
1024 INT32 xa = 0, xb = 0, ya = 0, yb = 0;
1025 /* size to allocate in VRAM and in GART respectively */
1026 int newFBSize = 0, newTTSize = 0;
1027 /* card VRAM offset, source offsets for U and V planes */
1028 int offset = 0, s2offset = 0, s3offset = 0;
1029 /* source pitch, source pitch of U and V planes in case of YV12,
1030 * VRAM destination pitch
1032 int srcPitch = 0, srcPitch2 = 0, dstPitch = 0;
1033 /* position of the given source data (using src_*), number of pixels
1034 * and lines we are interested in
1036 int top = 0, left = 0, right = 0, bottom = 0, npixels = 0, nlines = 0;
1037 struct nouveau_channel *chan = pNv->chan;
1038 struct nouveau_grobj *m2mf = pNv->NvMemFormat;
1042 int line_len = 0; /* length of a line, like npixels, but in bytes */
1043 struct nouveau_bo *destination_buffer = NULL;
1044 int action_flags; /* what shall we do? */
1048 if (pPriv->grabbedByV4L)
1052 NV_set_action_flags(pScrn, pDraw, pPriv, id, drw_x, drw_y, drw_w,
1053 drw_h, &action_flags);
1055 if (NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
1056 &src_x, &src_y, &src_w, &src_h,
1057 &drw_x, &drw_y, &drw_w, &drw_h,
1058 &left, &top, &right, &bottom, &dstBox,
1059 &npixels, &nlines, clipBoxes, width, height))
1062 if (NV_calculate_pitches_and_mem_size(action_flags, &srcPitch,
1063 &srcPitch2, &dstPitch, &s2offset,
1064 &s3offset, &newFBSize, &newTTSize,
1065 &line_len, npixels, nlines,
1067 return BadImplementation;
1069 /* There are some cases (tvtime with overscan for example) where the
1070 * input image is larger (width/height) than the source rectangle for
1071 * the overlay (src_w, src_h). In those cases, we try to do something
1072 * optimal by uploading only the necessary data.
1074 if (action_flags & IS_YUY2 || action_flags & IS_RGB)
1075 buf += (top * srcPitch) + left;
1077 if (action_flags & IS_YV12) {
1078 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1083 ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_VRAM, newFBSize,
1088 /* The overlay supports hardware double buffering. We handle this here*/
1090 if (pPriv->doubleBuffer) {
1091 int mask = 1 << (pPriv->currentBuffer << 2);
1093 /* overwrite the newest buffer if there's not one free */
1094 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1095 if (!pPriv->currentBuffer)
1096 offset += newFBSize >> 1;
1099 if (pPriv->currentBuffer)
1100 offset += newFBSize >> 1;
1104 /* Now we take a decision regarding the way we send the data to the
1107 * Either we use double buffering of "private" TT memory
1108 * Either we rely on X's GARTScratch
1109 * Either we fallback on CPU copy
1112 /* Try to allocate host-side double buffers, unless we have already
1116 /* We take only nlines * line_len bytes - that is, only the pixel
1117 * data we are interested in - because the stuff in the GART is
1118 * written contiguously
1120 if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE) {
1121 ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_GART, newTTSize,
1122 &pPriv->TT_mem_chunk[0]);
1124 ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_GART,
1126 &pPriv->TT_mem_chunk[1]);
1128 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1129 pPriv->currentHostBuffer =
1130 NO_PRIV_HOST_BUFFER_AVAILABLE;
1133 pPriv->currentHostBuffer =
1134 NO_PRIV_HOST_BUFFER_AVAILABLE;
1138 if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE) {
1139 destination_buffer =
1140 pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1142 /* We know where we are going to write, but we are not sure
1143 * yet whether we can do it directly, because the card could
1144 * be working on the buffer for the last-but-one frame. So we
1145 * check if we have a notifier ready or not.
1147 * If we do, then we must wait for it before overwriting the
1148 * buffer. Else we need one, so we call the Xv notifier
1151 if (pPriv->DMANotifier[pPriv->currentHostBuffer]) {
1152 struct nouveau_notifier *n =
1153 pPriv->DMANotifier[pPriv->currentHostBuffer];
1155 if (nouveau_notifier_wait_status(n, 0, 0, 0))
1158 pPriv->DMANotifier[pPriv->currentHostBuffer] =
1159 NVXvDMANotifierAlloc(pScrn);
1161 if (!pPriv->DMANotifier[pPriv->currentHostBuffer]) {
1162 /* In case we are out of notifiers (then our
1163 * guy is watching 3 movies at a time!!), we
1164 * fallback on global GART, and free the
1165 * private buffers. I know that's a lot of code
1166 * but I believe it's necessary to properly
1167 * handle all the cases
1169 xf86DrvMsg(0, X_ERROR,
1170 "Ran out of Xv notifiers!\n");
1171 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1172 pPriv->TT_mem_chunk[0] = NULL;
1173 nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
1174 pPriv->TT_mem_chunk[1] = NULL;
1175 pPriv->currentHostBuffer =
1176 NO_PRIV_HOST_BUFFER_AVAILABLE;
1181 /* Otherwise we fall back on DDX's GARTScratch */
1182 if (pPriv->currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE)
1183 destination_buffer = pNv->GART;
1185 /* If we have no GART at all... */
1186 if (!destination_buffer) {
1187 if (pNv->Architecture >= NV_ARCH_50) {
1188 NOUVEAU_ERR("No scratch buffer for tiled upload\n");
1195 if (newTTSize <= destination_buffer->size) {
1196 unsigned char *dst = destination_buffer->map;
1199 /* Upload to GART */
1200 if (action_flags & IS_YV12) {
1201 if (action_flags & CONVERT_TO_YUY2) {
1202 NVCopyData420(buf + (top * srcPitch) + left,
1203 buf + s2offset, buf + s3offset,
1204 dst, srcPitch, srcPitch2,
1205 line_len, nlines, npixels);
1208 unsigned char *tbuf = buf + top *
1210 unsigned char *tdst = dst;
1213 for (i = 0; i < nlines; i++) {
1214 memcpy(tdst, tbuf, line_len);
1218 dst += line_len * nlines;
1220 NVCopyNV12ColorPlanes(buf + s2offset,
1221 buf + s3offset, dst,
1222 line_len, srcPitch2,
1226 for (i = 0; i < nlines; i++) {
1227 memcpy(dst, buf, line_len);
1233 BEGIN_RING(chan, m2mf,
1234 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
1235 OUT_RING (chan, pNv->chan->gart->handle);
1236 OUT_RING (chan, pNv->chan->vram->handle);
1238 if (pNv->Architecture >= NV_ARCH_50) {
1239 BEGIN_RING(chan, m2mf, 0x0200, 1);
1242 BEGIN_RING(chan, m2mf, 0x021c, 7);
1245 OUT_RING (chan, dstPitch);
1246 OUT_RING (chan, nlines);
1253 if ( (action_flags & IS_YV12) &&
1254 !(action_flags & CONVERT_TO_YUY2)) {
1255 /* we start the color plane transfer separately */
1257 BEGIN_RING(chan, m2mf,
1258 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1259 OUT_RELOCl(chan, destination_buffer, line_len * nlines,
1260 NOUVEAU_BO_GART | NOUVEAU_BO_RD);
1261 OUT_RELOCl(chan, pPriv->video_mem,
1262 offset + dstPitch * nlines,
1263 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
1264 OUT_RING (chan, line_len);
1265 OUT_RING (chan, dstPitch);
1266 OUT_RING (chan, line_len);
1267 OUT_RING (chan, (nlines >> 1));
1268 OUT_RING (chan, (1<<8)|1);
1272 BEGIN_RING(chan, m2mf,
1273 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1274 OUT_RELOCl(chan, destination_buffer, 0,
1275 NOUVEAU_BO_GART | NOUVEAU_BO_RD);
1276 OUT_RELOCl(chan, pPriv->video_mem, offset,
1277 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
1278 OUT_RING (chan, line_len);
1279 OUT_RING (chan, dstPitch);
1280 OUT_RING (chan, line_len);
1281 OUT_RING (chan, nlines);
1282 OUT_RING (chan, (1<<8)|1);
1285 if (destination_buffer == pNv->GART) {
1286 nouveau_notifier_reset(pNv->notify0, 0);
1288 struct nouveau_notifier *n =
1289 pPriv->DMANotifier[pPriv->currentHostBuffer];
1291 nouveau_notifier_reset(n, 0);
1293 BEGIN_RING(chan, m2mf,
1294 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1295 OUT_RING (chan, n->handle);
1299 BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1301 BEGIN_RING(chan, m2mf, 0x100, 1);
1304 /* Put back NvDmaNotifier0 for EXA */
1305 BEGIN_RING(chan, m2mf,
1306 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1307 OUT_RING (chan, pNv->notify0->handle);
1311 if (destination_buffer == pNv->GART) {
1312 if (nouveau_notifier_wait_status(pNv->notify0, 0, 0, 0))
1318 map = pPriv->video_mem->map + offset;
1320 if (action_flags & IS_YV12) {
1321 if (action_flags & CONVERT_TO_YUY2) {
1322 NVCopyData420(buf + (top * srcPitch) + left,
1323 buf + s2offset, buf + s3offset,
1324 map, srcPitch, srcPitch2,
1325 dstPitch, nlines, npixels);
1327 unsigned char *tbuf =
1328 buf + left + top * srcPitch;
1330 for (i = 0; i < nlines; i++) {
1331 int dwords = npixels << 1;
1333 while (dwords & ~0x03) {
1335 *(map + 1) = *(tbuf + 1);
1336 *(map + 2) = *(tbuf + 2);
1337 *(map + 3) = *(tbuf + 3);
1344 case 3: *(map + 2) = *(tbuf + 2);
1345 case 2: *(map + 1) = *(tbuf + 1);
1346 case 1: *map = *tbuf;
1349 map += dstPitch - (npixels << 1);
1350 tbuf += srcPitch - (npixels << 1);
1353 NVCopyNV12ColorPlanes(buf + s2offset,
1355 map, dstPitch, srcPitch2,
1360 for (i = 0; i < nlines; i++) {
1361 int dwords = npixels << 1;
1363 while (dwords & ~0x03) {
1365 *(map + 1) = *(buf + 1);
1366 *(map + 2) = *(buf + 2);
1367 *(map + 3) = *(buf + 3);
1374 case 3: *(map + 2) = *(buf + 2);
1375 case 2: *(map + 1) = *(buf + 1);
1376 case 1: *map = *buf;
1379 map += dstPitch - (npixels << 1);
1380 buf += srcPitch - (npixels << 1);
1388 if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE)
1389 pPriv->currentHostBuffer ^= 1;
1391 /* If we're not using the hw overlay, we're rendering into a pixmap
1392 * and need to take a couple of additional steps...
1394 if (!(action_flags & USE_OVERLAY)) {
1395 ppix = NVGetDrawablePixmap(pDraw);
1397 /* Ensure pixmap is in offscreen memory */
1398 exaMoveInPixmap(ppix);
1399 ExaOffscreenMarkUsed(ppix);
1402 /* Convert screen coords to pixmap coords */
1403 if (ppix->screen_x || ppix->screen_y) {
1404 REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
1405 -ppix->screen_x, -ppix->screen_y);
1406 dstBox.x1 -= ppix->screen_x;
1407 dstBox.x2 -= ppix->screen_x;
1408 dstBox.y1 -= ppix->screen_y;
1409 dstBox.y2 -= ppix->screen_y;
1412 /* Damage tracking */
1413 DamageDamageRegion(&ppix->drawable, clipBoxes);
1417 if (action_flags & USE_OVERLAY) {
1418 if (pNv->Architecture == NV_ARCH_04) {
1419 NV04PutOverlayImage(pScrn, pPriv->video_mem, offset,
1420 id, dstPitch, &dstBox, 0, 0,
1421 xb, yb, npixels, nlines,
1422 src_w, src_h, drw_w, drw_h,
1427 if (action_flags & (IS_YUY2 | CONVERT_TO_YUY2))
1430 uvoffset = offset + nlines * dstPitch;
1432 NV10PutOverlayImage(pScrn, pPriv->video_mem, offset,
1433 uvoffset, id, dstPitch, &dstBox,
1435 npixels, nlines, src_w, src_h,
1436 drw_w, drw_h, clipBoxes);
1439 pPriv->currentBuffer ^= 1;
1441 if (action_flags & USE_TEXTURE) {
1442 int ret = BadImplementation;
1444 if (pNv->Architecture == NV_ARCH_30) {
1445 ret = NV30PutTextureImage(pScrn, pPriv->video_mem,
1447 offset + nlines * dstPitch,
1448 id, dstPitch, &dstBox, 0, 0,
1449 xb, yb, npixels, nlines,
1450 src_w, src_h, drw_w, drw_h,
1451 clipBoxes, ppix, pPriv);
1453 if (pNv->Architecture == NV_ARCH_40) {
1454 ret = NV40PutTextureImage(pScrn, pPriv->video_mem,
1456 offset + nlines * dstPitch,
1457 id, dstPitch, &dstBox, 0, 0,
1458 xb, yb, npixels, nlines,
1459 src_w, src_h, drw_w, drw_h,
1460 clipBoxes, ppix, pPriv);
1462 if (pNv->Architecture == NV_ARCH_50) {
1463 ret = nv50_xv_image_put(pScrn, pPriv->video_mem,
1465 offset + nlines * dstPitch,
1466 id, dstPitch, &dstBox, 0, 0,
1467 xb, yb, npixels, nlines,
1468 src_w, src_h, drw_w, drw_h,
1469 clipBoxes, ppix, pPriv);
1475 NVPutBlitImage(pScrn, pPriv->video_mem, offset, id, dstPitch,
1476 &dstBox, 0, 0, xb, yb, npixels, nlines,
1477 src_w, src_h, drw_w, drw_h, clipBoxes, ppix);
1484 * QueryImageAttributes
1487 * - size (memory required to store image),
1491 * depending on colorspace (id) and dimensions (w,h) of image
1495 * may be adjusted as needed
1497 * @param pScrn unused
1498 * @param id colorspace of image
1499 * @param w pointer to width of image
1500 * @param h pointer to height of image
1501 * @param pitches pitches[i] = length of a scanline in plane[i]
1502 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1503 * @return size of the memory required for the XvImage queried
1506 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1507 unsigned short *w, unsigned short *h,
1508 int *pitches, int *offsets)
1512 if (*w > IMAGE_MAX_W)
1514 if (*h > IMAGE_MAX_H)
1517 *w = (*w + 1) & ~1; // width rounded up to an even number
1524 *h = (*h + 1) & ~1; // height rounded up to an even number
1525 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1527 pitches[0] = size; // width rounded up to a multiple of 4
1530 offsets[1] = size; // number of pixels in "rounded up" image
1531 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1533 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1534 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1535 size += tmp; // 5/4*number of pixels in "rounded up" image
1537 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1538 size += tmp; // = 3/2*number of pixels in "rounded up" image
1542 size = *w << 1; // 2*width
1544 pitches[0] = size; // 2*width
1545 size *= *h; // 2*width*height
1548 size = *w << 2; // 4*width (32 bit per pixel)
1550 pitches[0] = size; // 4*width
1551 size *= *h; // 4*width*height
1561 /***** Exported offscreen surface stuff ****/
1565 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1566 unsigned short w, unsigned short h,
1567 XF86SurfacePtr surface)
1569 NVPtr pNv = NVPTR(pScrn);
1570 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1573 bpp = pScrn->bitsPerPixel >> 3;
1575 if (pPriv->grabbedByV4L)
1578 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1582 pPriv->pitch = ((w << 1) + 63) & ~63;
1583 size = h * pPriv->pitch / bpp;
1585 ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_VRAM, size,
1592 surface->height = h;
1593 surface->pScrn = pScrn;
1594 surface->pitches = &pPriv->pitch;
1595 surface->offsets = &pPriv->offset;
1596 surface->devPrivate.ptr = (pointer)pPriv;
1599 /* grab the video */
1600 NVStopOverlay(pScrn);
1601 pPriv->videoStatus = 0;
1602 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1603 pPriv->grabbedByV4L = TRUE;
1609 NVStopSurface(XF86SurfacePtr surface)
1611 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1613 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
1614 NV10StopOverlay(surface->pScrn);
1615 pPriv->videoStatus = 0;
1622 NVFreeSurface(XF86SurfacePtr surface)
1624 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1626 if (pPriv->grabbedByV4L) {
1627 NVStopSurface(surface);
1628 NVFreeOverlayMemory(surface->pScrn);
1629 pPriv->grabbedByV4L = FALSE;
1636 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
1638 NVPtr pNv = NVPTR(pScrn);
1639 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1641 return NV10GetOverlayPortAttribute(pScrn, attribute,
1642 value, (pointer)pPriv);
1646 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
1648 NVPtr pNv = NVPTR(pScrn);
1649 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1651 return NV10SetOverlayPortAttribute(pScrn, attribute,
1652 value, (pointer)pPriv);
1656 NVDisplaySurface(XF86SurfacePtr surface,
1657 short src_x, short src_y,
1658 short drw_x, short drw_y,
1659 short src_w, short src_h,
1660 short drw_w, short drw_h,
1661 RegionPtr clipBoxes)
1663 ScrnInfoPtr pScrn = surface->pScrn;
1664 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1665 INT32 xa, xb, ya, yb;
1668 if (!pPriv->grabbedByV4L)
1671 if (src_w > (drw_w << 3))
1673 if (src_h > (drw_h << 3))
1683 dstBox.x2 = drw_x + drw_w;
1685 dstBox.y2 = drw_y + drw_h;
1687 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1688 surface->width, surface->height))
1691 dstBox.x1 -= pScrn->frameX0;
1692 dstBox.x2 -= pScrn->frameX0;
1693 dstBox.y1 -= pScrn->frameY0;
1694 dstBox.y2 -= pScrn->frameY0;
1696 pPriv->currentBuffer = 0;
1698 NV10PutOverlayImage(pScrn, pPriv->video_mem, surface->offsets[0],
1699 0, surface->id, surface->pitches[0], &dstBox,
1700 xa, ya, xb, yb, surface->width, surface->height,
1701 src_w, src_h, drw_w, drw_h, clipBoxes);
1708 * this function does all the work setting up a blit port
1712 static XF86VideoAdaptorPtr
1713 NVSetupBlitVideo (ScreenPtr pScreen)
1715 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1716 NVPtr pNv = NVPTR(pScrn);
1717 XF86VideoAdaptorPtr adapt;
1718 NVPortPrivPtr pPriv;
1721 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1722 sizeof(NVPortPrivRec) +
1723 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
1727 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1729 adapt->name = "NV Video Blitter";
1730 adapt->nEncodings = 1;
1731 adapt->pEncodings = &DummyEncoding;
1732 adapt->nFormats = NUM_FORMATS_ALL;
1733 adapt->pFormats = NVFormats;
1734 adapt->nPorts = NUM_BLIT_PORTS;
1735 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1737 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
1738 for(i = 0; i < NUM_BLIT_PORTS; i++)
1739 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1741 if(pNv->WaitVSyncPossible) {
1742 adapt->pAttributes = NVBlitAttributes;
1743 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
1745 adapt->pAttributes = NULL;
1746 adapt->nAttributes = 0;
1749 adapt->pImages = NVImages;
1750 adapt->nImages = NUM_IMAGES_ALL;
1751 adapt->PutVideo = NULL;
1752 adapt->PutStill = NULL;
1753 adapt->GetVideo = NULL;
1754 adapt->GetStill = NULL;
1755 adapt->StopVideo = NVStopBlitVideo;
1756 adapt->SetPortAttribute = NVSetBlitPortAttribute;
1757 adapt->GetPortAttribute = NVGetBlitPortAttribute;
1758 adapt->QueryBestSize = NVQueryBestSize;
1759 adapt->PutImage = NVPutImage;
1760 adapt->QueryImageAttributes = NVQueryImageAttributes;
1762 pPriv->videoStatus = 0;
1763 pPriv->grabbedByV4L = FALSE;
1764 pPriv->blitter = TRUE;
1765 pPriv->texture = FALSE;
1766 pPriv->bicubic = FALSE;
1767 pPriv->doubleBuffer = FALSE;
1768 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1770 pNv->blitAdaptor = adapt;
1771 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
1777 * NVSetupOverlayVideo
1778 * this function does all the work setting up an overlay port
1780 * @return overlay port
1782 static XF86VideoAdaptorPtr
1783 NVSetupOverlayVideoAdapter(ScreenPtr pScreen)
1785 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1786 NVPtr pNv = NVPTR(pScrn);
1787 XF86VideoAdaptorPtr adapt;
1788 NVPortPrivPtr pPriv;
1790 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1791 sizeof(NVPortPrivRec) +
1792 sizeof(DevUnion)))) {
1796 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1797 if (pNv->randr12_enable)
1798 adapt->flags = VIDEO_OVERLAID_IMAGES;
1800 adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
1801 adapt->name = "NV Video Overlay";
1802 adapt->nEncodings = 1;
1803 adapt->pEncodings = &DummyEncoding;
1804 adapt->nFormats = NUM_FORMATS_ALL;
1805 adapt->pFormats = NVFormats;
1807 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1809 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
1810 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
1812 adapt->pAttributes = (pNv->Architecture != NV_ARCH_04) ? NV10OverlayAttributes : NV04OverlayAttributes;
1813 adapt->nAttributes = (pNv->Architecture != NV_ARCH_04) ? NUM_NV10_OVERLAY_ATTRIBUTES : NUM_NV04_OVERLAY_ATTRIBUTES;
1814 adapt->pImages = NVImages;
1815 adapt->nImages = NUM_IMAGES_YUV;
1816 adapt->PutVideo = NULL;
1817 adapt->PutStill = NULL;
1818 adapt->GetVideo = NULL;
1819 adapt->GetStill = NULL;
1820 adapt->StopVideo = NVStopOverlayVideo;
1821 adapt->SetPortAttribute = (pNv->Architecture != NV_ARCH_04) ? NV10SetOverlayPortAttribute : NV04SetOverlayPortAttribute;
1822 adapt->GetPortAttribute = (pNv->Architecture != NV_ARCH_04) ? NV10GetOverlayPortAttribute : NV04GetOverlayPortAttribute;
1823 adapt->QueryBestSize = NVQueryBestSize;
1824 adapt->PutImage = NVPutImage;
1825 adapt->QueryImageAttributes = NVQueryImageAttributes;
1827 pPriv->videoStatus = 0;
1828 pPriv->currentBuffer = 0;
1829 pPriv->grabbedByV4L = FALSE;
1830 pPriv->blitter = FALSE;
1831 pPriv->texture = FALSE;
1832 pPriv->bicubic = FALSE;
1834 NVSetPortDefaults (pScrn, pPriv);
1836 /* gotta uninit this someplace */
1837 REGION_NULL(pScreen, &pPriv->clip);
1839 pNv->overlayAdaptor = adapt;
1841 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
1842 xvColorKey = MAKE_ATOM("XV_COLORKEY");
1843 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
1844 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
1846 if ( pNv->Architecture != NV_ARCH_04 )
1848 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
1849 xvContrast = MAKE_ATOM("XV_CONTRAST");
1850 xvSaturation = MAKE_ATOM("XV_SATURATION");
1851 xvHue = MAKE_ATOM("XV_HUE");
1852 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
1853 xvOnCRTCNb = MAKE_ATOM("XV_ON_CRTC_NB");
1854 NV10WriteOverlayParameters(pScrn);
1861 XF86OffscreenImageRec NVOffscreenImages[2] = {
1864 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1869 NVGetSurfaceAttribute,
1870 NVSetSurfaceAttribute,
1871 IMAGE_MAX_W, IMAGE_MAX_H,
1872 NUM_NV10_OVERLAY_ATTRIBUTES - 1,
1873 &NV10OverlayAttributes[1]
1877 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1882 NVGetSurfaceAttribute,
1883 NVSetSurfaceAttribute,
1884 IMAGE_MAX_W, IMAGE_MAX_H,
1885 NUM_NV10_OVERLAY_ATTRIBUTES - 1,
1886 &NV10OverlayAttributes[1]
1891 NVInitOffscreenImages (ScreenPtr pScreen)
1893 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
1897 * NVChipsetHasOverlay
1899 * newer chips don't support overlay anymore.
1900 * overlay feature is emulated via textures.
1903 * @return true, if chipset supports overlay
1906 NVChipsetHasOverlay(NVPtr pNv)
1908 switch (pNv->Architecture) {
1909 case NV_ARCH_04: /*NV04 has a different overlay than NV10+*/
1915 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
1926 * NVSetupOverlayVideo
1927 * check if chipset supports Overla
1928 * if so, setup overlay port
1930 * @return overlay port
1931 * @see NVChipsetHasOverlay(NVPtr pNv)
1932 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
1933 * @see NVInitOffscreenImages(ScreenPtr pScreen)
1935 static XF86VideoAdaptorPtr
1936 NVSetupOverlayVideo(ScreenPtr pScreen)
1938 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1939 XF86VideoAdaptorPtr overlayAdaptor = NULL;
1940 NVPtr pNv = NVPTR(pScrn);
1942 if (!NVChipsetHasOverlay(pNv))
1945 overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen);
1946 /* I am not sure what this call does. */
1947 if (overlayAdaptor && pNv->Architecture != NV_ARCH_04 )
1948 NVInitOffscreenImages(pScreen);
1951 if (!noCompositeExtension) {
1952 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1953 "Xv: Composite is enabled, enabling overlay with "
1954 "smart blitter fallback\n");
1955 overlayAdaptor->name = "NV Video Overlay with Composite";
1959 if (pNv->randr12_enable) {
1960 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1961 "Xv: Randr12 is enabled, using overlay with smart "
1962 "blitter fallback and automatic CRTC switching\n");
1966 return overlayAdaptor;
1970 * NV30 texture adapter.
1973 #define NUM_FORMAT_TEXTURED 2
1975 static XF86ImageRec NV30TexturedImages[NUM_FORMAT_TEXTURED] =
1982 * NV30SetupTexturedVideo
1983 * this function does all the work setting up textured video port
1985 * @return texture port
1987 static XF86VideoAdaptorPtr
1988 NV30SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic)
1990 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1991 NVPtr pNv = NVPTR(pScrn);
1992 XF86VideoAdaptorPtr adapt;
1993 NVPortPrivPtr pPriv;
1996 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1997 sizeof(NVPortPrivRec) +
1998 (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
2002 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2005 adapt->name = "NV30 high quality adapter";
2007 adapt->name = "NV30 texture adapter";
2008 adapt->nEncodings = 1;
2009 adapt->pEncodings = &DummyEncodingTex;
2010 adapt->nFormats = NUM_FORMATS_ALL;
2011 adapt->pFormats = NVFormats;
2012 adapt->nPorts = NUM_TEXTURE_PORTS;
2013 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2015 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
2016 for(i = 0; i < NUM_TEXTURE_PORTS; i++)
2017 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2019 if(pNv->WaitVSyncPossible) {
2020 adapt->pAttributes = NVTexturedAttributes;
2021 adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
2023 adapt->pAttributes = NULL;
2024 adapt->nAttributes = 0;
2027 adapt->pImages = NV30TexturedImages;
2028 adapt->nImages = NUM_FORMAT_TEXTURED;
2029 adapt->PutVideo = NULL;
2030 adapt->PutStill = NULL;
2031 adapt->GetVideo = NULL;
2032 adapt->GetStill = NULL;
2033 adapt->StopVideo = NV30StopTexturedVideo;
2034 adapt->SetPortAttribute = NV30SetTexturePortAttribute;
2035 adapt->GetPortAttribute = NV30GetTexturePortAttribute;
2036 adapt->QueryBestSize = NVQueryBestSize;
2037 adapt->PutImage = NVPutImage;
2038 adapt->QueryImageAttributes = NVQueryImageAttributes;
2040 pPriv->videoStatus = 0;
2041 pPriv->grabbedByV4L = FALSE;
2042 pPriv->blitter = FALSE;
2043 pPriv->texture = TRUE;
2044 pPriv->bicubic = bicubic;
2045 pPriv->doubleBuffer = FALSE;
2046 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
2049 pNv->textureAdaptor[1] = adapt;
2051 pNv->textureAdaptor[0] = adapt;
2057 * NV40 texture adapter.
2060 #define NUM_FORMAT_TEXTURED 2
2062 static XF86ImageRec NV40TexturedImages[NUM_FORMAT_TEXTURED] =
2069 * NV40SetupTexturedVideo
2070 * this function does all the work setting up textured video port
2072 * @return texture port
2074 static XF86VideoAdaptorPtr
2075 NV40SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic)
2077 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2078 NVPtr pNv = NVPTR(pScrn);
2079 XF86VideoAdaptorPtr adapt;
2080 NVPortPrivPtr pPriv;
2083 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2084 sizeof(NVPortPrivRec) +
2085 (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
2089 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2092 adapt->name = "NV40 high quality adapter";
2094 adapt->name = "NV40 texture adapter";
2095 adapt->nEncodings = 1;
2096 adapt->pEncodings = &DummyEncodingTex;
2097 adapt->nFormats = NUM_FORMATS_ALL;
2098 adapt->pFormats = NVFormats;
2099 adapt->nPorts = NUM_TEXTURE_PORTS;
2100 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2102 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
2103 for(i = 0; i < NUM_TEXTURE_PORTS; i++)
2104 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2106 if(pNv->WaitVSyncPossible) {
2107 adapt->pAttributes = NVTexturedAttributes;
2108 adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
2110 adapt->pAttributes = NULL;
2111 adapt->nAttributes = 0;
2114 adapt->pImages = NV40TexturedImages;
2115 adapt->nImages = NUM_FORMAT_TEXTURED;
2116 adapt->PutVideo = NULL;
2117 adapt->PutStill = NULL;
2118 adapt->GetVideo = NULL;
2119 adapt->GetStill = NULL;
2120 adapt->StopVideo = NV40StopTexturedVideo;
2121 adapt->SetPortAttribute = NV40SetTexturePortAttribute;
2122 adapt->GetPortAttribute = NV40GetTexturePortAttribute;
2123 adapt->QueryBestSize = NVQueryBestSize;
2124 adapt->PutImage = NVPutImage;
2125 adapt->QueryImageAttributes = NVQueryImageAttributes;
2127 pPriv->videoStatus = 0;
2128 pPriv->grabbedByV4L = FALSE;
2129 pPriv->blitter = FALSE;
2130 pPriv->texture = TRUE;
2131 pPriv->bicubic = bicubic;
2132 pPriv->doubleBuffer = FALSE;
2133 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
2136 pNv->textureAdaptor[1] = adapt;
2138 pNv->textureAdaptor[0] = adapt;
2144 NV50TexturedImages[] =
2151 static XF86VideoAdaptorPtr
2152 NV50SetupTexturedVideo (ScreenPtr pScreen)
2154 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2155 NVPtr pNv = NVPTR(pScrn);
2156 XF86VideoAdaptorPtr adapt;
2157 NVPortPrivPtr pPriv;
2160 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2161 sizeof(NVPortPrivRec) +
2162 (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
2166 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2168 adapt->name = "Nouveau GeForce 8/9 Textured Video";
2169 adapt->nEncodings = 1;
2170 adapt->pEncodings = &DummyEncodingTex;
2171 adapt->nFormats = NUM_FORMATS_ALL;
2172 adapt->pFormats = NVFormats;
2173 adapt->nPorts = NUM_TEXTURE_PORTS;
2174 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2176 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
2177 for(i = 0; i < NUM_TEXTURE_PORTS; i++)
2178 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2180 adapt->pAttributes = NULL;
2181 adapt->nAttributes = 0;
2182 adapt->pImages = NV50TexturedImages;
2183 adapt->nImages = sizeof(NV50TexturedImages) /
2184 sizeof(NV50TexturedImages[0]);
2185 adapt->PutVideo = NULL;
2186 adapt->PutStill = NULL;
2187 adapt->GetVideo = NULL;
2188 adapt->GetStill = NULL;
2189 adapt->StopVideo = nv50_xv_video_stop;
2190 adapt->SetPortAttribute = nv50_xv_port_attribute_set;
2191 adapt->GetPortAttribute = nv50_xv_port_attribute_get;
2192 adapt->QueryBestSize = NVQueryBestSize;
2193 adapt->PutImage = NVPutImage;
2194 adapt->QueryImageAttributes = NVQueryImageAttributes;
2196 pPriv->videoStatus = 0;
2197 pPriv->grabbedByV4L = FALSE;
2198 pPriv->blitter = FALSE;
2199 pPriv->texture = TRUE;
2200 pPriv->doubleBuffer = FALSE;
2201 pPriv->SyncToVBlank = 0;
2203 pNv->textureAdaptor[0] = adapt;
2210 * tries to initialize the various supported adapters
2211 * and add them to the list of ports on screen "pScreen".
2214 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
2215 * @see NVSetupBlitVideo(ScreenPtr pScreen)
2218 NVInitVideo(ScreenPtr pScreen)
2220 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2221 NVPtr pNv = NVPTR(pScrn);
2222 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
2223 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2224 XF86VideoAdaptorPtr blitAdaptor = NULL;
2225 XF86VideoAdaptorPtr textureAdaptor[2] = {NULL, NULL};
2229 * Driving the blitter requires the DMA FIFO. Using the FIFO
2230 * without accel causes DMA errors. While the overlay might
2231 * might work without accel, we also disable it for now when
2232 * acceleration is disabled:
2234 if (pScrn->bitsPerPixel != 8 && !pNv->NoAccel) {
2235 if (pNv->Architecture < NV_ARCH_50) {
2236 overlayAdaptor = NVSetupOverlayVideo(pScreen);
2237 blitAdaptor = NVSetupBlitVideo(pScreen);
2240 if (pNv->Architecture == NV_ARCH_30) {
2241 textureAdaptor[0] = NV30SetupTexturedVideo(pScreen, FALSE);
2242 textureAdaptor[1] = NV30SetupTexturedVideo(pScreen, TRUE);
2244 if (pNv->Architecture == NV_ARCH_40) {
2245 textureAdaptor[0] = NV40SetupTexturedVideo(pScreen, FALSE);
2246 textureAdaptor[1] = NV40SetupTexturedVideo(pScreen, TRUE);
2248 if (pNv->Architecture == NV_ARCH_50) {
2249 textureAdaptor[0] = NV50SetupTexturedVideo(pScreen);
2253 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
2254 if (blitAdaptor || overlayAdaptor || textureAdaptor[0]) {
2255 int size = num_adaptors;
2257 if(overlayAdaptor) size++;
2258 if(blitAdaptor) size++;
2259 if(textureAdaptor[0]) size++;
2260 if(textureAdaptor[1]) size++;
2262 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
2265 memcpy(newAdaptors, adaptors, num_adaptors *
2266 sizeof(XF86VideoAdaptorPtr));
2269 if(overlayAdaptor) {
2270 newAdaptors[num_adaptors] = overlayAdaptor;
2274 if (textureAdaptor[0]) { /* bilinear */
2275 newAdaptors[num_adaptors] = textureAdaptor[0];
2279 if (textureAdaptor[1]) { /* bicubic */
2280 newAdaptors[num_adaptors] = textureAdaptor[1];
2285 newAdaptors[num_adaptors] = blitAdaptor;
2289 adaptors = newAdaptors;
2294 xf86XVScreenInit(pScreen, adaptors, num_adaptors);
2299 * For now we associate with the plain texture adapter since it is logical, but we can
2300 * associate with any/all adapters since VL doesn't depend on Xv for color conversion.
2302 if (textureAdaptor[0]) {
2303 XF86MCAdaptorPtr *adaptorsXvMC = xalloc(sizeof(XF86MCAdaptorPtr));
2306 adaptorsXvMC[0] = vlCreateAdaptorXvMC(pScreen, textureAdaptor[0]->name);
2308 if (adaptorsXvMC[0]) {
2309 vlInitXvMC(pScreen, 1, adaptorsXvMC);
2310 vlDestroyAdaptorXvMC(adaptorsXvMC[0]);
2313 xfree(adaptorsXvMC);