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 "xf86_OSproc.h"
30 #include "xf86Resources.h"
32 #include "xf86PciInfo.h"
34 #include "xf86fbman.h"
35 #include "regionstr.h"
38 #include <X11/extensions/Xv.h>
41 #include "dixstruct.h"
44 #include "nv_include.h"
47 #define IMAGE_MAX_W 2046
48 #define IMAGE_MAX_H 2046
50 #define OFF_DELAY 500 /* milliseconds */
51 #define FREE_DELAY 5000
53 #define OFF_TIMER 0x01
54 #define FREE_TIMER 0x02
55 #define CLIENT_VIDEO_ON 0x04
57 #define TIMER_MASK (OFF_TIMER | FREE_TIMER)
59 #define NUM_BLIT_PORTS 32
61 /* Value taken by pPriv -> currentHostBuffer when we failed to allocate the two private buffers in TT memory, so that we can catch this case
62 and attempt no other allocation afterwards (performance reasons) */
63 #define NO_PRIV_HOST_BUFFER_AVAILABLE 9999
65 typedef struct _NVPortPrivRec {
72 Bool autopaintColorKey;
82 struct nouveau_bo *video_mem;
85 struct nouveau_bo *TT_mem_chunk[2];
86 int currentHostBuffer;
87 struct nouveau_notifier *DMANotifier[2];
88 } NVPortPrivRec, *NVPortPrivPtr;
91 /* Xv DMA notifiers status tracing */
94 XV_DMA_NOTIFIER_NOALLOC=0, //notifier not allocated
95 XV_DMA_NOTIFIER_INUSE=1,
96 XV_DMA_NOTIFIER_FREE=2, //notifier allocated, ready for use
99 /* We have six notifiers available, they are not allocated at startup */
100 int XvDMANotifierStatus[6]= { XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC ,
101 XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC };
102 struct nouveau_notifier *XvDMANotifiers[6];
104 /* NVPutImage action flags */
111 IS_RGB=32, //I am not sure how long we will support it
114 #define GET_OVERLAY_PRIVATE(pNv) \
115 (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr)
117 #define GET_BLIT_PRIVATE(pNv) \
118 (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr)
120 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
122 static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
123 xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
124 xvITURBT709, xvSyncToVBlank, xvOnCRTCNb;
126 /* client libraries expect an encoding */
127 static XF86VideoEncodingRec DummyEncoding =
131 IMAGE_MAX_W, IMAGE_MAX_H,
135 #define NUM_FORMATS_ALL 6
137 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
139 {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
140 {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
143 #define NUM_NV04_OVERLAY_ATTRIBUTES 1
144 XF86AttributeRec NV04OverlayAttributes[NUM_NV04_OVERLAY_ATTRIBUTES] =
146 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
150 #define NUM_OVERLAY_ATTRIBUTES 10
151 XF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] =
153 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
154 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
155 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
156 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
157 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
158 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
159 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
160 {XvSettable | XvGettable, 0, 360, "XV_HUE"},
161 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"},
162 {XvSettable | XvGettable, 0, 1, "XV_ON_CRTC_NB"},
165 #define NUM_BLIT_ATTRIBUTES 2
166 XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
168 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
169 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
173 #define NUM_IMAGES_YUV 4
174 #define NUM_IMAGES_ALL 5
176 #define FOURCC_RGB 0x0000003
177 #define XVIMAGE_RGB \
182 { 0x03, 0x00, 0x00, 0x00, \
183 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
187 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
192 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}, \
196 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
206 NVWaitVSync(ScrnInfoPtr pScrn)
208 NVPtr pNv = NVPTR(pScrn);
210 BEGIN_RING(NvImageBlit, 0x0000012C, 1);
212 BEGIN_RING(NvImageBlit, 0x00000134, 1);
213 /* If crtc1 is active, this will produce one, otherwise zero */
214 /* The assumption is that at least one is active */
215 OUT_RING (pNv->crtc_active[1]);
216 BEGIN_RING(NvImageBlit, 0x00000100, 1);
218 BEGIN_RING(NvImageBlit, 0x00000130, 1);
224 * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
226 * @param pScrn screen to get the default colorKey from
227 * @param pPriv port to reset to defaults
230 NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
232 NVPtr pNv = NVPTR(pScrn);
234 pPriv->brightness = 0;
235 pPriv->contrast = 4096;
236 pPriv->saturation = 4096;
238 pPriv->colorKey = pNv->videoKey;
239 pPriv->autopaintColorKey = TRUE;
240 pPriv->doubleBuffer = TRUE;
241 pPriv->iturbt_709 = FALSE;
242 pPriv->currentHostBuffer = 0;
247 * writes the current attributes from the overlay port to the hardware
250 NVResetVideo (ScrnInfoPtr pScrn)
252 NVPtr pNv = NVPTR(pScrn);
253 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
254 int satSine, satCosine;
257 angle = (double)pPriv->hue * 3.1415927 / 180.0;
259 satSine = pPriv->saturation * sin(angle);
262 satCosine = pPriv->saturation * cos(angle);
263 if (satCosine < -1024)
266 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
268 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
270 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
271 (satCosine & 0xffff));
272 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
273 (satCosine & 0xffff));
274 nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
279 * Tell the hardware to stop the overlay
282 NVStopOverlay (ScrnInfoPtr pScrn)
284 NVPtr pNv = NVPTR(pScrn);
286 if ( pNv -> Architecture != NV_ARCH_04 )
287 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
290 nvWriteRAMDAC(pNv, 0, 0x244, nvReadRAMDAC(pNv, 0, 0x244) &~ 0x1);
291 nvWriteRAMDAC(pNv, 0, 0x224, 0);
292 nvWriteRAMDAC(pNv, 0, 0x228, 0);
293 nvWriteRAMDAC(pNv, 0, 0x22c, 0);
298 * NVXvDMANotifierAlloc
299 * allocates a notifier from the table of 6 we have
301 * @return a notifier instance or NULL on error
303 static struct nouveau_notifier *
304 NVXvDMANotifierAlloc(ScrnInfoPtr pScrn)
306 NVPtr pNv = NVPTR(pScrn);
309 for (i = 0; i < 6; i++) {
310 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_INUSE)
313 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_FREE) {
314 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
315 return XvDMANotifiers[i];
318 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_NOALLOC) {
319 if (nouveau_notifier_alloc(pNv->chan,
320 NvDmaXvNotifier0 + i,
321 1, &XvDMANotifiers[i]))
323 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
324 return XvDMANotifiers[i];
332 * NVXvDMANotifierFree
333 * frees a notifier from the table of 6 we have
338 NVXvDMANotifierFree(ScrnInfoPtr pScrn, struct nouveau_notifier *target)
341 for ( i = 0; i < 6; i ++ )
343 if ( XvDMANotifiers[i] == target )
346 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_FREE;
350 * NVAllocateVideoMemory
351 * allocates video memory for a given port
353 * @param pScrn screen which requests the memory
354 * @param mem pointer to previously allocated memory for reallocation
355 * @param size size of requested memory segment
356 * @return pointer to the allocated memory
358 static struct nouveau_bo *
359 NVAllocateVideoMemory(ScrnInfoPtr pScrn, struct nouveau_bo *mem, int size)
361 NVPtr pNv = NVPTR(pScrn);
362 struct nouveau_bo *bo = NULL;
365 if(mem->size >= size)
367 nouveau_bo_del(&mem);
370 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN, 0,
374 if (nouveau_bo_map(bo, NOUVEAU_BO_RDWR)) {
384 * allocates TT memory for a given port
386 * @param pScrn screen which requests the memory
387 * @param mem pointer to previously allocated memory for reallocation
388 * @param size size of requested memory segment
389 * @return pointer to the allocated memory
391 static struct nouveau_bo *
392 NVAllocateTTMemory(ScrnInfoPtr pScrn, struct nouveau_bo *mem, int size)
394 NVPtr pNv = NVPTR(pScrn);
395 struct nouveau_bo *bo = NULL;
398 if(mem->size >= size)
400 nouveau_bo_del(&mem);
403 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_GART | NOUVEAU_BO_PIN, 0,
407 if (nouveau_bo_map(bo, NOUVEAU_BO_RDWR)) {
417 * frees memory held by a given port
419 * @param pScrn screen whose port wants to free memory
420 * @param pPriv port to free memory of
423 NVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
425 //xf86DrvMsg(0, X_INFO, "Freeing port memory - TTmem chunks %p %p, notifiers %p %p\n", pPriv->TT_mem_chunk[0], pPriv->TT_mem_chunk[1], pPriv->DMANotifier[0], pPriv->DMANotifier[1]);
427 if(pPriv->video_mem) {
428 nouveau_bo_del(&pPriv->video_mem);
429 pPriv->video_mem = NULL;
432 if ( pPriv->TT_mem_chunk[ 0 ] && pPriv->DMANotifier [ 0 ] )
434 nouveau_notifier_wait_status(pPriv->DMANotifier[0], 0, 0, 1000);
437 if ( pPriv->TT_mem_chunk[ 1 ] && pPriv->DMANotifier [ 1 ] )
439 nouveau_notifier_wait_status(pPriv->DMANotifier[1], 0, 0, 1000);
442 if(pPriv->TT_mem_chunk[0]) {
443 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
444 pPriv->TT_mem_chunk[0] = NULL;
447 if(pPriv->TT_mem_chunk[1]) {
448 nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
449 pPriv->TT_mem_chunk[1] = NULL;
452 if(pPriv->DMANotifier[0]) {
453 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[0]);
454 pPriv->DMANotifier[0] = NULL;
457 if(pPriv->DMANotifier[1]) {
458 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[1]);
459 pPriv->DMANotifier[1] = NULL;
465 * NVFreeOverlayMemory
466 * frees memory held by the overlay port
468 * @param pScrn screen whose overlay port wants to free memory
471 NVFreeOverlayMemory(ScrnInfoPtr pScrn)
473 NVPtr pNv = NVPTR(pScrn);
474 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
475 NVFreePortMemory(pScrn, pPriv);
476 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) & 0xEFFFFFFF));
477 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) | 0x10000000));
482 * frees memory held by the blit port
484 * @param pScrn screen whose blit port wants to free memory
487 NVFreeBlitMemory(ScrnInfoPtr pScrn)
489 NVPtr pNv = NVPTR(pScrn);
490 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
491 NVFreePortMemory(pScrn, pPriv);
495 * NVVideoTimerCallback
496 * callback function which perform cleanup tasks (stop overlay, free memory).
497 * within the driver it is only called once from NVBlockHandler in nv_driver.c
500 NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
502 NVPtr pNv = NVPTR(pScrn);
503 NVPortPrivPtr pOverPriv = NULL;
504 NVPortPrivPtr pBlitPriv = NULL;
505 Bool needCallback = FALSE;
510 if (pNv->overlayAdaptor) {
511 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
512 if (!pOverPriv->videoStatus)
516 if (pNv->blitAdaptor) {
517 pBlitPriv = GET_BLIT_PRIVATE(pNv);
518 if (!pBlitPriv->videoStatus)
523 if (pOverPriv->videoTime < currentTime) {
524 if (pOverPriv->videoStatus & OFF_TIMER) {
525 NVStopOverlay(pScrn);
526 pOverPriv->videoStatus = FREE_TIMER;
527 pOverPriv->videoTime = currentTime + FREE_DELAY;
530 if (pOverPriv->videoStatus & FREE_TIMER) {
531 NVFreeOverlayMemory(pScrn);
532 pOverPriv->videoStatus = 0;
540 if (pBlitPriv->videoTime < currentTime) {
541 NVFreeBlitMemory(pScrn);
542 pBlitPriv->videoStatus = 0;
548 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
553 * program hardware to overlay image into front buffer
555 * @param pScrn screen
556 * @param offset card offset to the pixel data
557 * @param id format of image
558 * @param dstPitch pitch of the pixel data in VRAM
559 * @param dstBox destination box
560 * @param x1 first source point - x
561 * @param y1 first source point - y
562 * @param x2 second source point - x
563 * @param y2 second source point - y
564 * @param width width of the source image = x2 - x1
565 * @param height height
566 * @param src_w width of the image data in VRAM
567 * @param src_h height
568 * @param drw_w width of the image to draw to screen
569 * @param drw_h height
570 * @param clipBoxes ???
573 NVPutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
574 int dstPitch, BoxPtr dstBox,
575 int x1, int y1, int x2, int y2,
576 short width, short height,
577 short src_w, short src_h,
578 short drw_w, short drw_h,
581 NVPtr pNv = NVPTR(pScrn);
582 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
583 int buffer = pPriv->currentBuffer;
585 /* paint the color key */
586 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
587 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
588 /* we always paint V4L's color key */
589 if (!pPriv->grabbedByV4L)
590 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
592 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
596 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
602 //xf86DrvMsg(0, X_INFO, "SIZE_IN h %d w %d, POINT_IN x %d y %d, DS_DX %d DT_DY %d, POINT_OUT x %d y %d SIZE_OUT h %d w %d\n", height, width, x1 >> 16,y1>>16, (src_w << 20) / drw_w, (src_h << 20) / drw_h, (dstBox->x1),(dstBox->y1), (dstBox->y2 - dstBox->y1), (dstBox->x2 - dstBox->x1));
604 nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer) , 0);
605 nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer) , offset);
606 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer) , (height << 16) | width);
607 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
608 ((y1 << 4) & 0xffff0000) | (x1 >> 12));
609 nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer) , (src_w << 20) / drw_w);
610 nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer) , (src_h << 20) / drw_h);
611 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
612 (dstBox->y1 << 16) | dstBox->x1);
613 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
614 ((dstBox->y2 - dstBox->y1) << 16) |
615 (dstBox->x2 - dstBox->x1));
617 dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; /* use color key */
618 if(id != FOURCC_UYVY)
619 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
620 if(pPriv->iturbt_709)
621 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
623 if( id == FOURCC_YV12 || id == FOURCC_I420 )
624 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
626 /* Those are important only for planar formats (NV12) */
629 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_BASE(buffer), 0);
630 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer), uvoffset);
633 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
634 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
635 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
637 pPriv->videoStatus = CLIENT_VIDEO_ON;
641 NV04PutOverlayImage(ScrnInfoPtr pScrn, int offset, int id,
642 int dstPitch, BoxPtr dstBox,
643 int x1, int y1, int x2, int y2,
644 short width, short height,
645 short src_w, short src_h,
646 short drw_w, short drw_h,
649 NVPtr pNv = NVPTR(pScrn);
650 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
652 /* paint the color key */
653 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
654 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
655 /* we always paint V4L's color key */
656 if (!pPriv->grabbedByV4L)
657 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
659 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
663 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) { /*This may not work with NV04 overlay according to rivatv source*/
669 /* NV_PVIDEO_OE_STATE */
670 /* NV_PVIDEO_SU_STATE */
671 /* NV_PVIDEO_RM_STATE */
672 nvWriteRAMDAC(pNv, 0, 0x224, 0);
673 nvWriteRAMDAC(pNv, 0, 0x228, 0);
674 nvWriteRAMDAC(pNv, 0, 0x22c, 0);
676 /* NV_PVIDEO_BUFF0_START_ADDRESS */
677 nvWriteRAMDAC(pNv, 0, 0x20C, offset);
678 nvWriteRAMDAC(pNv, 0, 0x20C + 4, offset);
679 /* NV_PVIDEO_BUFF0_PITCH_LENGTH */
680 nvWriteRAMDAC(pNv, 0, 0x214, dstPitch);
681 nvWriteRAMDAC(pNv, 0, 0x214 + 4, dstPitch);
683 /* NV_PVIDEO_BUFF0_OFFSET */
684 nvWriteRAMDAC(pNv, 0, 0x21C, 0);
685 nvWriteRAMDAC(pNv, 0, 0x21C + 4, 0);
687 /* NV_PVIDEO_WINDOW_START */
688 nvWriteRAMDAC(pNv, 0, 0x230, (dstBox->y1 << 16) | dstBox->x1);
689 /* NV_PVIDEO_WINDOW_SIZE */
690 nvWriteRAMDAC(pNv, 0, 0x234, ((dstBox->y2 - dstBox->y1) << 16) |
691 (dstBox->x2 - dstBox->x1));
692 /* NV_PVIDEO_STEP_SIZE */
693 nvWriteRAMDAC(pNv, 0, 0x200, (uint32_t)(((src_h - 1) << 11) / (drw_h - 1)) << 16 | (uint32_t)(((src_w - 1) << 11) / (drw_w - 1)));
695 /* NV_PVIDEO_RED_CSC_OFFSET */
696 /* NV_PVIDEO_GREEN_CSC_OFFSET */
697 /* NV_PVIDEO_BLUE_CSC_OFFSET */
698 /* NV_PVIDEO_CSC_ADJUST */
699 nvWriteRAMDAC(pNv, 0, 0x280, 0x69);
700 nvWriteRAMDAC(pNv, 0, 0x284, 0x3e);
701 nvWriteRAMDAC(pNv, 0, 0x288, 0x89);
702 nvWriteRAMDAC(pNv, 0, 0x28C, 0x0);
704 /* NV_PVIDEO_CONTROL_Y (BLUR_ON, LINE_HALF) */
705 nvWriteRAMDAC(pNv, 0, 0x204, 0x001);
706 /* NV_PVIDEO_CONTROL_X (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */
707 nvWriteRAMDAC(pNv, 0, 0x208, 0x111);
709 /* NV_PVIDEO_FIFO_BURST_LENGTH */
710 nvWriteRAMDAC(pNv, 0, 0x23C, 0x03);
711 /* NV_PVIDEO_FIFO_THRES_SIZE */
712 nvWriteRAMDAC(pNv, 0, 0x238, 0x38);
715 nvWriteRAMDAC(pNv, 0, 0x240, pPriv->colorKey);
721 nvWriteRAMDAC(pNv, 0, 0x244, 0x111);
723 /* NV_PVIDEO_SU_STATE */
724 nvWriteRAMDAC(pNv, 0, 0x228, (nvReadRAMDAC(pNv, 0, 0x228) ^ (1 << 16)));
726 pPriv->videoStatus = CLIENT_VIDEO_ON;
728 #ifndef ExaOffscreenMarkUsed
729 extern void ExaOffscreenMarkUsed(PixmapPtr);
731 #ifndef exaGetDrawablePixmap
732 extern PixmapPtr exaGetDrawablePixmap(DrawablePtr);
734 #ifndef exaPixmapIsOffscreen
735 extern Bool exaPixmapIsOffscreen(PixmapPtr p);
737 /* To support EXA 2.0, 2.1 has this in the header */
738 #ifndef exaMoveInPixmap
739 extern void exaMoveInPixmap(PixmapPtr pPixmap);
745 * @param pScrn screen
747 * @param id colorspace of image
764 NVPutBlitImage(ScrnInfoPtr pScrn, int src_offset, int id,
765 int src_pitch, BoxPtr dstBox,
766 int x1, int y1, int x2, int y2,
767 short width, short height,
768 short src_w, short src_h,
769 short drw_w, short drw_h,
773 NVPtr pNv = NVPTR(pScrn);
774 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
778 CARD32 dst_size, dst_point;
779 CARD32 src_point, src_format;
781 ScreenPtr pScreen = pScrn->pScreen;
782 PixmapPtr pPix = exaGetDrawablePixmap(pDraw);
785 /* Try to get the dest drawable into vram */
786 if (!exaPixmapIsOffscreen(pPix)) {
787 exaMoveInPixmap(pPix);
788 ExaOffscreenMarkUsed(pPix);
791 /* If we failed, draw directly onto the screen pixmap.
792 * Not sure if this is the best approach, maybe failing
793 * with BadAlloc would be better?
795 if (!exaPixmapIsOffscreen(pPix)) {
796 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
797 "XV: couldn't move dst surface into vram\n");
798 pPix = pScreen->GetScreenPixmap(pScreen);
801 NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format);
802 BEGIN_RING(NvContextSurfaces, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
803 OUT_RING (dst_format);
804 OUT_RING ((exaGetPixmapPitch(pPix) << 16) | exaGetPixmapPitch(pPix));
805 OUT_PIXMAPl(pPix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
806 OUT_PIXMAPl(pPix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
809 /* Adjust coordinates if drawing to an offscreen pixmap */
810 if (pPix->screen_x || pPix->screen_y) {
811 REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
814 dstBox->x1 -= pPix->screen_x;
815 dstBox->x2 -= pPix->screen_x;
816 dstBox->y1 -= pPix->screen_y;
817 dstBox->y2 -= pPix->screen_y;
820 DamageDamageRegion((DrawablePtr)pPix, clipBoxes);
823 pbox = REGION_RECTS(clipBoxes);
824 nbox = REGION_NUM_RECTS(clipBoxes);
826 dsdx = (src_w << 20) / drw_w;
827 dtdy = (src_h << 20) / drw_h;
829 dst_size = ((dstBox->y2 - dstBox->y1) << 16) |
830 (dstBox->x2 - dstBox->x1);
831 dst_point = (dstBox->y1 << 16) | dstBox->x1;
833 src_pitch |= (NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
834 NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_BILINEAR);
835 src_point = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
840 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
844 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_YB8V8YA8U8;
848 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_V8YB8U8YA8;
852 if(pPriv->SyncToVBlank) {
857 if(pNv->BlendingPossible) {
858 BEGIN_RING(NvScaledImage,
859 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 2);
860 OUT_RING (src_format);
861 OUT_RING (NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
863 BEGIN_RING(NvScaledImage,
864 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 2);
865 OUT_RING (src_format);
869 BEGIN_RING(NvRectangle,
870 NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
873 BEGIN_RING(NvScaledImage,
874 NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT, 6);
875 OUT_RING ((pbox->y1 << 16) | pbox->x1);
876 OUT_RING (((pbox->y2 - pbox->y1) << 16) |
877 (pbox->x2 - pbox->x1));
878 OUT_RING (dst_point);
883 BEGIN_RING(NvScaledImage,
884 NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
885 OUT_RING ((height << 16) | width);
886 OUT_RING (src_pitch);
887 OUT_RING (src_offset);
888 OUT_RING (src_point);
894 exaMarkSync(pScrn->pScreen);
896 pPriv->videoStatus = FREE_TIMER;
897 pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
898 pNv->VideoTimerCallback = NVVideoTimerCallback;
905 NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
907 NVPtr pNv = NVPTR(pScrn);
908 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
910 if(pPriv->grabbedByV4L) return;
912 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
915 if (pPriv->videoStatus & CLIENT_VIDEO_ON)
916 NVStopOverlay(pScrn);
917 NVFreeOverlayMemory(pScrn);
918 pPriv->videoStatus = 0;
920 if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
921 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
922 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
923 pNv->VideoTimerCallback = NVVideoTimerCallback;
932 NVStopBlitVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
937 * NVSetOverlayPortAttribute
938 * sets the attribute "attribute" of port "data" to value "value"
939 * calls NVResetVideo(pScrn) to apply changes to hardware
942 * @param attribute attribute to set
943 * @param value value to which attribute is to be set
944 * @param data port from which the attribute is to be set
946 * @return Success, if setting is successful
947 * BadValue/BadMatch, if value/attribute are invalid
948 * @see NVResetVideo(ScrnInfoPtr pScrn)
951 NVSetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
952 INT32 value, pointer data)
954 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
955 NVPtr pNv = NVPTR(pScrn);
957 if (attribute == xvBrightness) {
958 if ((value < -512) || (value > 512))
960 pPriv->brightness = value;
962 if (attribute == xvDoubleBuffer) {
963 if ((value < 0) || (value > 1))
965 pPriv->doubleBuffer = value;
967 if (attribute == xvContrast) {
968 if ((value < 0) || (value > 8191))
970 pPriv->contrast = value;
972 if (attribute == xvHue) {
978 if (attribute == xvSaturation) {
979 if ((value < 0) || (value > 8191))
981 pPriv->saturation = value;
983 if (attribute == xvColorKey) {
984 pPriv->colorKey = value;
985 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
987 if (attribute == xvAutopaintColorKey) {
988 if ((value < 0) || (value > 1))
990 pPriv->autopaintColorKey = value;
992 if (attribute == xvITURBT709) {
993 if ((value < 0) || (value > 1))
995 pPriv->iturbt_709 = value;
997 if (attribute == xvSetDefaults) {
998 NVSetPortDefaults(pScrn, pPriv);
1000 if ( attribute == xvOnCRTCNb) {
1001 if ((value < 0) || (value > 1))
1003 pPriv->overlayCRTC = value;
1004 nvWriteCRTC(pNv, value, NV_CRTC_FSEL, nvReadCRTC(pNv, value, NV_CRTC_FSEL) | NV_CRTC_FSEL_OVERLAY);
1005 nvWriteCRTC(pNv, !value, NV_CRTC_FSEL, nvReadCRTC(pNv, !value, NV_CRTC_FSEL) & ~NV_CRTC_FSEL_OVERLAY);
1009 NVResetVideo(pScrn);
1014 * NVGetOverlayPortAttribute
1016 * @param pScrn unused
1017 * @param attribute attribute to be read
1018 * @param value value of attribute will be stored in this pointer
1019 * @param data port from which attribute will be read
1020 * @return Success, if queried attribute exists
1023 NVGetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1024 INT32 *value, pointer data)
1026 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1028 if (attribute == xvBrightness)
1029 *value = pPriv->brightness;
1030 else if (attribute == xvDoubleBuffer)
1031 *value = (pPriv->doubleBuffer) ? 1 : 0;
1032 else if (attribute == xvContrast)
1033 *value = pPriv->contrast;
1034 else if (attribute == xvSaturation)
1035 *value = pPriv->saturation;
1036 else if (attribute == xvHue)
1037 *value = pPriv->hue;
1038 else if (attribute == xvColorKey)
1039 *value = pPriv->colorKey;
1040 else if (attribute == xvAutopaintColorKey)
1041 *value = (pPriv->autopaintColorKey) ? 1 : 0;
1042 else if (attribute == xvITURBT709)
1043 *value = (pPriv->iturbt_709) ? 1 : 0;
1044 else if (attribute == xvOnCRTCNb)
1045 *value = (pPriv->overlayCRTC) ? 1 : 0;
1053 * NVSetBlitPortAttribute
1054 * sets the attribute "attribute" of port "data" to value "value"
1055 * supported attributes:
1056 * - xvSyncToVBlank (values: 0,1)
1057 * - xvSetDefaults (values: NA; SyncToVBlank will be set, if hardware supports it)
1060 * @param attribute attribute to set
1061 * @param value value to which attribute is to be set
1062 * @param data port from which the attribute is to be set
1064 * @return Success, if setting is successful
1065 * BadValue/BadMatch, if value/attribute are invalid
1068 NVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1069 INT32 value, pointer data)
1071 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1072 NVPtr pNv = NVPTR(pScrn);
1074 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
1075 if ((value < 0) || (value > 1))
1077 pPriv->SyncToVBlank = value;
1079 if (attribute == xvSetDefaults) {
1080 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1088 * NVGetBlitPortAttribute
1089 * reads the value of attribute "attribute" from port "data" into INT32 "*value"
1090 * currently only one attribute supported: xvSyncToVBlank
1092 * @param pScrn unused
1093 * @param attribute attribute to be read
1094 * @param value value of attribute will be stored here
1095 * @param data port from which attribute will be read
1096 * @return Success, if queried attribute exists
1099 NVGetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1100 INT32 *value, pointer data)
1102 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1104 if(attribute == xvSyncToVBlank)
1105 *value = (pPriv->SyncToVBlank) ? 1 : 0;
1115 * used by client applications to ask the driver:
1116 * how would you actually scale a video of dimensions
1117 * vid_w, vid_h, if i wanted you to scale it to dimensions
1119 * function stores actual scaling size in pointers p_w, p_h.
1122 * @param pScrn unused
1123 * @param motion unused
1124 * @param vid_w width of source video
1125 * @param vid_h height of source video
1126 * @param drw_w desired scaled width as requested by client
1127 * @param drw_h desired scaled height as requested by client
1128 * @param p_w actual scaled width as the driver is capable of
1129 * @param p_h actual scaled height as the driver is capable of
1130 * @param data unused
1133 NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
1134 short vid_w, short vid_h,
1135 short drw_w, short drw_h,
1136 unsigned int *p_w, unsigned int *p_h,
1139 if(vid_w > (drw_w << 3))
1141 if(vid_h > (drw_h << 3))
1150 * used to convert YV12 to YUY2 for the blitter
1152 * @param src1 source buffer of luma
1153 * @param src2 source buffer of chroma1
1154 * @param src3 source buffer of chroma2
1155 * @param dst1 destination buffer
1156 * @param srcPitch pitch of src1
1157 * @param srcPitch2 pitch of src2, src3
1158 * @param dstPitch pitch of dst1
1159 * @param h number of lines to copy
1160 * @param w length of lines to copy
1162 static inline void NVCopyData420(unsigned char *src1, unsigned char *src2,
1163 unsigned char *src3, unsigned char *dst1,
1164 int srcPitch, int srcPitch2,
1169 CARD8 *s1, *s2, *s3;
1174 for (j = 0; j < h; j++) {
1175 dst = (CARD32*)dst1;
1176 s1 = src1; s2 = src2; s3 = src3;
1180 #if X_BYTE_ORDER == X_BIG_ENDIAN
1181 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
1182 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1];
1183 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2];
1184 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3];
1186 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
1187 dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
1188 dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
1189 dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
1191 dst += 4; s2 += 4; s3 += 4; s1 += 8;
1196 #if X_BYTE_ORDER == X_BIG_ENDIAN
1197 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
1199 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
1215 * NVCopyNV12ColorPlanes
1216 * Used to convert YV12 color planes to NV12 (interleaved UV) for the overlay
1218 * @param src1 source buffer of chroma1
1219 * @param dst1 destination buffer
1220 * @param h number of lines to copy
1221 * @param w length of lines to copy
1222 * @param id source pixel format (YV12 or I420)
1224 static inline void NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char * src2, unsigned char *dst, int dstPitch, int srcPitch2,
1234 for ( j = 0; j < h; j++ )
1236 unsigned char * us = src1;
1237 unsigned char * vs = src2;
1238 unsigned int * vuvud = (unsigned int *) dst;
1239 for ( i = 0; i < l; i++ )
1241 #if X_BYTE_ORDER == X_BIG_ENDIAN
1242 *vuvud++ = (vs[0]<<24) | (us[0]<<16) | (vs[1]<<8) | us[1];
1244 *vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24);
1250 unsigned short *vud = (unsigned short *) vuvud;
1251 #if X_BYTE_ORDER == X_BIG_ENDIAN
1252 *vud = (vs[0]<<8) | (us[0] << 0);
1254 *vud = vs[0] | (us[0]<<8);
1265 static int NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 * xa, INT32 * xb, INT32 * ya, INT32 * yb,
1266 short * src_x, short * src_y, short * src_w, short * src_h,
1267 short * drw_x, short * drw_y, short * drw_w, short * drw_h,
1268 int * left, int * top, int * right, int * bottom,
1270 int * npixels, int * nlines,
1271 RegionPtr clipBoxes, short width, short height
1275 if ( action_flags & USE_OVERLAY )
1276 { /* overlay hardware scaler limitation - copied from nv, UNCHECKED*/
1277 if (*src_w > (*drw_w << 3))
1278 *drw_w = *src_w >> 3;
1279 if (*src_h > (*drw_h << 3))
1280 *drw_h = *src_h >> 3;
1286 *xb = *src_x + *src_w;
1288 *yb = *src_y + *src_h;
1290 dstBox->x1 = *drw_x;
1291 dstBox->x2 = *drw_x + *drw_w;
1292 dstBox->y1 = *drw_y;
1293 dstBox->y2 = *drw_y + *drw_h;
1295 if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
1299 if ( action_flags & USE_OVERLAY )
1301 dstBox->x1 -= pScrn->frameX0;
1302 dstBox->x2 -= pScrn->frameX0;
1303 dstBox->y1 -= pScrn->frameY0;
1304 dstBox->y2 -= pScrn->frameY0;
1309 /* Convert fixed point to integer, as xf86XVClipVideoHelper probably turns its parameter into fixed point values */
1310 *left = (*xa) >> 16;
1311 if (*left < 0) *left = 0;
1313 if (*top < 0) *top = 0;
1314 *right = (*xb) >> 16;
1315 if (*right > width) *right = width;
1316 *bottom = (*yb) >> 16;
1317 if (*bottom > height) *bottom = height;
1319 if ( action_flags & IS_YV12 )
1321 *left &= ~1; //even "left", even "top", even number of pixels per line and even number of lines
1322 *npixels = ((*right + 1) & ~1) - *left;
1324 *nlines = ((*bottom + 1) & ~1) - *top;
1326 else if ( action_flags & IS_YUY2 )
1328 *left &= ~1; //even "left"
1329 *npixels = ((*right + 1) & ~1) - *left; //even number of pixels per line
1330 *nlines = *bottom - *top;
1331 *left <<= 1; //16bpp
1333 else if (action_flags & IS_RGB )
1335 *npixels = *right - *left;
1336 *nlines = *bottom - *top;
1337 *left <<= 2; //32bpp
1343 static int NV_calculate_pitches_and_mem_size(int action_flags, int * srcPitch, int * srcPitch2, int * dstPitch,
1344 int * s2offset, int * s3offset,
1345 int * newFBSize, int * newTTSize,
1346 int * line_len, int npixels, int nlines, int width, int height)
1350 if ( action_flags & IS_YV12 )
1352 *srcPitch = (width + 3) & ~3; /* of luma */
1353 *s2offset = *srcPitch * height;
1354 *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
1355 *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
1356 *dstPitch = (npixels + 63) &~ 63; /*luma and chroma pitch*/
1357 *line_len = npixels;
1358 *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1359 *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1361 else if ( action_flags & IS_YUY2 )
1363 *srcPitch = width << 1; /* one luma, one chroma per pixel */
1364 *dstPitch = ((npixels << 1) + 63) & ~63;
1365 *line_len = npixels << 1;
1366 *newFBSize = nlines * *dstPitch;
1367 *newTTSize = nlines * *line_len;
1369 else if ( action_flags & IS_RGB )
1371 *srcPitch = width << 2; /* one R, one G, one B, one X per pixel */
1372 *dstPitch = ((npixels << 2) + 63) & ~63;
1373 *line_len = npixels << 2;
1374 *newFBSize = nlines * *dstPitch;
1375 *newTTSize = nlines * *dstPitch;
1379 if ( action_flags & CONVERT_TO_YUY2 )
1381 *dstPitch = ((npixels << 1) + 63) & ~63;
1382 *line_len = npixels << 1;
1383 *newFBSize = nlines * *dstPitch;
1384 *newTTSize = nlines * *line_len;
1387 if ( action_flags & SWAP_UV )
1388 { //I420 swaps U and V
1390 *s2offset = *s3offset;
1394 if ( action_flags & USE_OVERLAY ) // overlay double buffering ...
1395 (*newFBSize) <<= 1; // ... means double the amount of VRAM needed
1402 * NV_set_action_flags
1403 * This function computes the action flags from the input image,
1404 * that is, it decides what NVPutImage and its helpers must do.
1405 * This eases readability by avoiding lots of switch-case statements in the core NVPutImage
1407 static void NV_set_action_flags(NVPtr pNv, ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, int id, int * action_flags)
1410 if ( id == FOURCC_YUY2 || id == FOURCC_UYVY )
1411 *action_flags |= IS_YUY2;
1413 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1414 *action_flags |= IS_YV12;
1416 if ( id == FOURCC_RGB ) /*How long will we support it?*/
1417 *action_flags |= IS_RGB;
1419 if ( id == FOURCC_I420 ) /*I420 is YV12 with swapped UV*/
1420 *action_flags |= SWAP_UV;
1422 if ( !pPriv -> blitter )
1423 *action_flags |= USE_OVERLAY;
1426 WindowPtr pWin = NULL;
1428 if (!noCompositeExtension && WindowDrawable(pDraw->type))
1430 pWin = (WindowPtr)pDraw;
1434 if ( pWin->redirectDraw )
1435 *action_flags &= ~USE_OVERLAY;
1439 if ( ! ( *action_flags & USE_OVERLAY) )
1441 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1442 { /*The blitter does not handle YV12 natively*/
1443 *action_flags |= CONVERT_TO_YUY2;
1447 if ( pNv->Architecture == NV_ARCH_04 )
1448 if ( * action_flags & IS_YV12 ) //NV04-05 don't support native YV12, only YUY2 and ITU-R BT.601)
1449 *action_flags |= CONVERT_TO_YUY2;
1451 if ( pNv->Architecture == NV_ARCH_10 || pNv->Architecture == NV_ARCH_20 )
1453 switch ( pNv->Chipset & 0xfff0 )
1458 case CHIPSET_NFORCE: /*XXX: unsure about nforce*/
1459 case CHIPSET_NV20: /*reported by pq - in fact all cards older than geforce4 ti probably don't have YV12 overlay*/
1460 *action_flags |= CONVERT_TO_YUY2; break;
1471 * PutImage is "the" important function of the Xv extension.
1472 * a client (e.g. video player) calls this function for every
1473 * image (of the video) to be displayed. this function then
1474 * scales and displays the image.
1476 * @param pScrn screen which hold the port where the image is put
1477 * @param src_x source point in the source image to start displaying from
1478 * @param src_y see above
1479 * @param src_w width of the source image to display
1480 * @param src_h see above
1481 * @param drw_x screen point to display to
1483 * @param drw_w width of the screen drawable
1485 * @param id pixel format of image
1486 * @param buf pointer to buffer containing the source image
1487 * @param width total width of the source image we are passed
1489 * @param Sync unused
1490 * @param clipBoxes ??
1491 * @param data pointer to port
1492 * @param pDraw drawable pointer
1495 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
1496 short drw_x, short drw_y,
1497 short src_w, short src_h,
1498 short drw_w, short drw_h,
1501 short width, short height,
1502 Bool Sync, /*FIXME: need to honor the Sync*/
1503 RegionPtr clipBoxes,
1508 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1509 NVPtr pNv = NVPTR(pScrn);
1510 INT32 xa = 0, xb = 0, ya = 0, yb = 0; //source box
1511 int newFBSize = 0, newTTSize = 0; //size to allocate in VRAM and in GART respectively
1512 int offset = 0, s2offset = 0, s3offset = 0; //card VRAM offset, source offsets for U and V planes
1513 int srcPitch = 0, srcPitch2 = 0, dstPitch = 0; //source pitch, source pitch of U and V planes in case of YV12, VRAM destination pitch
1514 int top = 0, left = 0, right = 0, bottom = 0, npixels = 0, nlines = 0; //position of the given source data (using src_*), number of pixels and lines we are interested in
1518 int line_len = 0; //length of a line, like npixels, but in bytes
1519 int DMAoffset = 0; //additional VRAM offset to start the DMA copy to
1520 int UVDMAoffset = 0;
1521 struct nouveau_bo *destination_buffer = NULL;
1522 unsigned char * video_mem_destination = NULL;
1523 int action_flags; //what shall we do?
1526 if (pPriv->grabbedByV4L)
1530 NV_set_action_flags(pNv, pScrn, pDraw, pPriv, id, &action_flags);
1532 if ( NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
1533 &src_x, &src_y, &src_w, &src_h,
1534 &drw_x, &drw_y, &drw_w, &drw_h,
1535 &left, &top, &right, &bottom, &dstBox,
1537 clipBoxes, width, height ) )
1543 if ( NV_calculate_pitches_and_mem_size(action_flags, &srcPitch, &srcPitch2, &dstPitch,
1544 &s2offset, &s3offset,
1545 & newFBSize, &newTTSize ,&line_len ,
1546 npixels, nlines, width, height) )
1548 return BadImplementation;
1551 /* There are some cases (tvtime with overscan for example) where the input image is larger (width/height) than
1552 the source rectangle for the overlay (src_w, src_h). In those cases, we try to do something optimal by uploading only
1553 the necessary data. */
1554 if ( action_flags & IS_YUY2 || action_flags & IS_RGB )
1556 buf += (top * srcPitch) + left;
1557 DMAoffset += left + (top * dstPitch);
1560 if ( action_flags & IS_YV12 )
1562 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1566 if ( action_flags & CONVERT_TO_YUY2 )
1568 DMAoffset += (left << 1) + (top * dstPitch);
1573 //real YV12 - we offset only the luma plane, and copy the whole color plane, for easiness
1574 DMAoffset += left + (top * dstPitch);
1575 UVDMAoffset += left + (top >> 1) * dstPitch;
1579 pPriv->video_mem = NVAllocateVideoMemory(pScrn, pPriv->video_mem,
1581 if (!pPriv->video_mem)
1584 offset = pPriv->video_mem->offset;
1586 /*The overlay supports hardware double buffering. We handle this here*/
1587 if (pPriv->doubleBuffer) {
1588 int mask = 1 << (pPriv->currentBuffer << 2);
1589 /* overwrite the newest buffer if there's not one free */
1590 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1591 if (!pPriv->currentBuffer)
1592 offset += newFBSize >> 1;
1596 if (pPriv->currentBuffer)
1597 offset += newFBSize >> 1;
1600 /*Now we take a decision regarding the way we send the data to the card.
1601 Either we use double buffering of "private" TT memory
1602 Either we rely on X's GARTScratch
1603 Either we fallback on CPU copy
1606 /* Try to allocate host-side double buffers, unless we have already failed*/
1607 /* We take only nlines * line_len bytes - that is, only the pixel data we are interested in - because the stuff in the GART is
1608 written contiguously */
1609 if ( pPriv -> currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1611 pPriv->TT_mem_chunk[0] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[0],
1613 if ( pPriv->TT_mem_chunk[0] )
1615 pPriv->TT_mem_chunk[1] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[1],
1618 if ( ! pPriv->TT_mem_chunk[1] )
1620 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1621 pPriv->TT_mem_chunk[0] = NULL;
1622 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1623 //xf86DrvMsg(0, X_INFO, "Alloc 1 failed\n");
1628 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1629 //xf86DrvMsg(0, X_INFO, "Alloc 0 failed\n");
1633 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1634 { //if we have a private buffer
1635 destination_buffer = pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1636 //xf86DrvMsg(0, X_INFO, "Using private mem chunk #%d\n", pPriv->currentHostBuffer);
1638 /* We know where we are going to write, but we are not sure yet whether we can do it directly, because
1639 the card could be working on the buffer for the last-but-one frame. So we check if we have a notifier ready or not.
1640 If we do, then we must wait for it before overwriting the buffer.
1641 Else we need one, so we call the Xv notifier allocator.*/
1642 if ( pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1644 //xf86DrvMsg(0, X_INFO, "Waiting for notifier %p (%d)\n", pPriv->DMANotifier[pPriv->currentHostBuffer], pPriv->currentHostBuffer);
1645 if (nouveau_notifier_wait_status(pPriv->DMANotifier[pPriv->currentHostBuffer], 0, 0, 0))
1650 //xf86DrvMsg(0, X_INFO, "Allocating notifier...\n");
1651 pPriv->DMANotifier [ pPriv->currentHostBuffer ] = NVXvDMANotifierAlloc(pScrn);
1652 if (! pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1653 { /* In case we are out of notifiers (then our guy is watching 3 movies at a time!!), we fallback on global GART, and free the private buffers.
1654 I know that's a lot of code but I believe it's necessary to properly handle all the cases*/
1655 xf86DrvMsg(0, X_ERROR, "Ran out of Xv notifiers!\n");
1656 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1657 pPriv->TT_mem_chunk[0] = NULL;
1658 nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
1659 pPriv->TT_mem_chunk[1] = NULL;
1660 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1662 //xf86DrvMsg(0, X_INFO, "Got notifier %p\n", pPriv->DMANotifier [ pPriv->currentHostBuffer ]);
1666 if ( pPriv -> currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE )
1667 { //otherwise we fall back on DDX's GARTScratch
1668 destination_buffer = pNv->GART;
1669 //xf86DrvMsg(0, X_INFO, "Using global GART memory chunk\n");
1672 if ( !destination_buffer) //if we have no GART at all
1675 if(newTTSize <= destination_buffer->size)
1677 unsigned char *dst = destination_buffer->map;
1680 /* Upload to GART */
1681 if ( action_flags & IS_YV12)
1683 if ( action_flags & CONVERT_TO_YUY2 )
1685 NVCopyData420(buf + (top * srcPitch) + left,
1686 buf + s2offset, buf + s3offset,
1687 dst, srcPitch, srcPitch2,
1688 line_len, nlines, npixels);
1692 unsigned char * tbuf = buf + top * srcPitch + left;
1693 unsigned char * tdst = dst;
1694 //xf86DrvMsg(0, X_INFO, "srcPitch %d dstPitch %d srcPitch2 %d nlines %d npixels %d left %d top %d s2offset %d\n", srcPitch, dstPitch, srcPitch2, nlines, npixels, left, top, s2offset);
1696 for ( i=0; i < nlines; i++)
1698 memcpy(tdst, tbuf, line_len);
1702 dst += line_len * nlines;
1703 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, dst, line_len, srcPitch2, nlines, line_len);
1708 for ( i=0; i < nlines; i++)
1710 memcpy(dst, buf, line_len);
1717 BEGIN_RING(NvMemFormat,
1718 NV_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
1719 OUT_RING (pNv->chan->gart->handle);
1720 OUT_RING (pNv->chan->vram->handle);
1723 if ( action_flags & IS_YV12 && ! (action_flags & CONVERT_TO_YUY2) )
1724 { /*we start the color plane transfer separately*/
1725 BEGIN_RING(NvMemFormat,
1726 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1727 OUT_RING ((uint32_t)destination_buffer->offset + line_len * nlines);
1728 OUT_RING ((uint32_t)offset + dstPitch * nlines);
1729 OUT_RING (line_len);
1730 OUT_RING (dstPitch);
1731 OUT_RING (line_len);
1732 OUT_RING ((nlines >> 1));
1733 OUT_RING ((1<<8)|1);
1738 BEGIN_RING(NvMemFormat,
1739 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1740 OUT_RING ((uint32_t)destination_buffer->offset);
1741 OUT_RING ((uint32_t)offset /*+ DMAoffset*/);
1742 OUT_RING (line_len);
1743 OUT_RING (dstPitch);
1744 OUT_RING (line_len);
1746 OUT_RING ((1<<8)|1);
1749 if ( destination_buffer == pNv->GART )
1751 nouveau_notifier_reset(pNv->notify0, 0);
1754 nouveau_notifier_reset(pPriv->DMANotifier[pPriv->currentHostBuffer], 0);
1755 BEGIN_RING(NvMemFormat,
1756 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1757 OUT_RING (pPriv->DMANotifier[pPriv->currentHostBuffer]->handle);
1761 BEGIN_RING(NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1764 BEGIN_RING(NvMemFormat, 0x100, 1);
1767 //Put back NvDmaNotifier0 for EXA
1768 BEGIN_RING(NvMemFormat,
1769 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1770 OUT_RING (pNv->notify0->handle);
1774 if ( destination_buffer == pNv->GART )
1775 if (nouveau_notifier_wait_status(pNv->notify0, 0, 0, 0))
1778 else { //GART is too small, we fallback on CPU copy
1780 video_mem_destination = pPriv->video_mem->map + (offset - (uint32_t)pPriv->video_mem->offset);
1782 if ( action_flags & IS_YV12 )
1784 if ( action_flags & CONVERT_TO_YUY2 )
1786 NVCopyData420(buf + (top * srcPitch) + left,
1787 buf + s2offset, buf + s3offset,
1788 video_mem_destination, srcPitch, srcPitch2,
1789 dstPitch, nlines, npixels);
1792 unsigned char * tbuf = buf + left + top * srcPitch;
1793 for ( i=0; i < nlines; i++)
1795 int dwords = npixels << 1;
1796 while (dwords & ~0x03)
1798 *video_mem_destination = *tbuf;
1799 *(video_mem_destination + 1) = *(tbuf + 1);
1800 *(video_mem_destination + 2) = *(tbuf + 2);
1801 *(video_mem_destination + 3) = *(tbuf + 3);
1802 video_mem_destination += 4;
1809 *(video_mem_destination + 2) = *(tbuf + 2);
1811 *(video_mem_destination + 1) = *(tbuf + 1);
1813 *video_mem_destination = *tbuf;
1816 video_mem_destination += dstPitch - (npixels << 1);
1817 tbuf += srcPitch - (npixels << 1);
1820 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, video_mem_destination, dstPitch, srcPitch2, nlines, line_len);
1825 for ( i=0; i < nlines; i++)
1827 int dwords = npixels << 1;
1828 while (dwords & ~0x03)
1830 *video_mem_destination = *buf;
1831 *(video_mem_destination + 1) = *(buf + 1);
1832 *(video_mem_destination + 2) = *(buf + 2);
1833 *(video_mem_destination + 3) = *(buf + 3);
1834 video_mem_destination += 4;
1841 *(video_mem_destination + 2) = *(buf + 2);
1843 *(video_mem_destination + 1) = *(buf + 1);
1845 *video_mem_destination = *buf;
1848 video_mem_destination += dstPitch - (npixels << 1);
1849 buf += srcPitch - (npixels << 1);
1857 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1858 pPriv->currentHostBuffer ^= 1;
1860 if ( action_flags & USE_OVERLAY )
1862 if ( pNv->Architecture == NV_ARCH_04 )
1863 NV04PutOverlayImage(pScrn, offset, id,
1867 src_w, src_h, drw_w, drw_h,
1870 NVPutOverlayImage(pScrn, offset, ((action_flags & IS_YUY2) || (action_flags & CONVERT_TO_YUY2)) ? 0 : offset + nlines * dstPitch, id,
1874 src_w, src_h, drw_w, drw_h,
1876 pPriv->currentBuffer ^= 1;
1881 NVPutBlitImage(pScrn, offset, id,
1885 src_w, src_h, drw_w, drw_h,
1893 * QueryImageAttributes
1896 * - size (memory required to store image),
1900 * depending on colorspace (id) and dimensions (w,h) of image
1904 * may be adjusted as needed
1906 * @param pScrn unused
1907 * @param id colorspace of image
1908 * @param w pointer to width of image
1909 * @param h pointer to height of image
1910 * @param pitches pitches[i] = length of a scanline in plane[i]
1911 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1912 * @return size of the memory required for the XvImage queried
1915 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1916 unsigned short *w, unsigned short *h,
1917 int *pitches, int *offsets)
1921 if (*w > IMAGE_MAX_W)
1923 if (*h > IMAGE_MAX_H)
1926 *w = (*w + 1) & ~1; // width rounded up to an even number
1933 *h = (*h + 1) & ~1; // height rounded up to an even number
1934 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1936 pitches[0] = size; // width rounded up to a multiple of 4
1939 offsets[1] = size; // number of pixels in "rounded up" image
1940 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1942 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1943 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1944 size += tmp; // 5/4*number of pixels in "rounded up" image
1946 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1947 size += tmp; // = 3/2*number of pixels in "rounded up" image
1951 size = *w << 1; // 2*width
1953 pitches[0] = size; // 2*width
1954 size *= *h; // 2*width*height
1957 size = *w << 2; // 4*width (32 bit per pixel)
1959 pitches[0] = size; // 4*width
1960 size *= *h; // 4*width*height
1970 /***** Exported offscreen surface stuff ****/
1974 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1975 unsigned short w, unsigned short h,
1976 XF86SurfacePtr surface)
1978 NVPtr pNv = NVPTR(pScrn);
1979 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1982 bpp = pScrn->bitsPerPixel >> 3;
1984 if (pPriv->grabbedByV4L)
1987 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1991 pPriv->pitch = ((w << 1) + 63) & ~63;
1992 size = h * pPriv->pitch / bpp;
1994 pPriv->video_mem = NVAllocateVideoMemory(pScrn,
1997 if (!pPriv->video_mem)
2003 surface->height = h;
2004 surface->pScrn = pScrn;
2005 surface->pitches = &pPriv->pitch;
2006 surface->offsets = &pPriv->offset;
2007 surface->devPrivate.ptr = (pointer)pPriv;
2010 /* grab the video */
2011 NVStopOverlay(pScrn);
2012 pPriv->videoStatus = 0;
2013 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
2014 pPriv->grabbedByV4L = TRUE;
2020 NVStopSurface(XF86SurfacePtr surface)
2022 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
2024 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
2025 NVStopOverlay(surface->pScrn);
2026 pPriv->videoStatus = 0;
2033 NVFreeSurface(XF86SurfacePtr surface)
2035 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
2037 if (pPriv->grabbedByV4L) {
2038 NVStopSurface(surface);
2039 NVFreeOverlayMemory(surface->pScrn);
2040 pPriv->grabbedByV4L = FALSE;
2047 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
2049 NVPtr pNv = NVPTR(pScrn);
2050 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
2052 return NVGetOverlayPortAttribute(pScrn, attribute,
2053 value, (pointer)pPriv);
2057 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
2059 NVPtr pNv = NVPTR(pScrn);
2060 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
2062 return NVSetOverlayPortAttribute(pScrn, attribute,
2063 value, (pointer)pPriv);
2067 NVDisplaySurface(XF86SurfacePtr surface,
2068 short src_x, short src_y,
2069 short drw_x, short drw_y,
2070 short src_w, short src_h,
2071 short drw_w, short drw_h,
2072 RegionPtr clipBoxes)
2074 ScrnInfoPtr pScrn = surface->pScrn;
2075 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
2076 INT32 xa, xb, ya, yb;
2079 if (!pPriv->grabbedByV4L)
2082 if (src_w > (drw_w << 3))
2084 if (src_h > (drw_h << 3))
2094 dstBox.x2 = drw_x + drw_w;
2096 dstBox.y2 = drw_y + drw_h;
2098 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
2099 surface->width, surface->height))
2102 dstBox.x1 -= pScrn->frameX0;
2103 dstBox.x2 -= pScrn->frameX0;
2104 dstBox.y1 -= pScrn->frameY0;
2105 dstBox.y2 -= pScrn->frameY0;
2107 pPriv->currentBuffer = 0;
2109 NVPutOverlayImage(pScrn, surface->offsets[0], 0, surface->id,
2110 surface->pitches[0], &dstBox, xa, ya, xb, yb,
2111 surface->width, surface->height, src_w, src_h,
2112 drw_w, drw_h, clipBoxes);
2119 * this function does all the work setting up a blit port
2123 static XF86VideoAdaptorPtr
2124 NVSetupBlitVideo (ScreenPtr pScreen)
2126 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2127 NVPtr pNv = NVPTR(pScrn);
2128 XF86VideoAdaptorPtr adapt;
2129 NVPortPrivPtr pPriv;
2132 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2133 sizeof(NVPortPrivRec) +
2134 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
2138 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2140 adapt->name = "NV Video Blitter";
2141 adapt->nEncodings = 1;
2142 adapt->pEncodings = &DummyEncoding;
2143 adapt->nFormats = NUM_FORMATS_ALL;
2144 adapt->pFormats = NVFormats;
2145 adapt->nPorts = NUM_BLIT_PORTS;
2146 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2148 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
2149 for(i = 0; i < NUM_BLIT_PORTS; i++)
2150 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2152 if(pNv->WaitVSyncPossible) {
2153 adapt->pAttributes = NVBlitAttributes;
2154 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
2156 adapt->pAttributes = NULL;
2157 adapt->nAttributes = 0;
2160 adapt->pImages = NVImages;
2161 adapt->nImages = NUM_IMAGES_ALL;
2162 adapt->PutVideo = NULL;
2163 adapt->PutStill = NULL;
2164 adapt->GetVideo = NULL;
2165 adapt->GetStill = NULL;
2166 adapt->StopVideo = NVStopBlitVideo;
2167 adapt->SetPortAttribute = NVSetBlitPortAttribute;
2168 adapt->GetPortAttribute = NVGetBlitPortAttribute;
2169 adapt->QueryBestSize = NVQueryBestSize;
2170 adapt->PutImage = NVPutImage;
2171 adapt->QueryImageAttributes = NVQueryImageAttributes;
2173 pPriv->videoStatus = 0;
2174 pPriv->grabbedByV4L = FALSE;
2175 pPriv->blitter = TRUE;
2176 pPriv->doubleBuffer = FALSE;
2177 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
2179 pNv->blitAdaptor = adapt;
2180 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
2186 * NVSetupOverlayVideo
2187 * this function does all the work setting up an overlay port
2189 * @return overlay port
2190 * @see NVResetVideo(ScrnInfoPtr pScrn)
2192 static XF86VideoAdaptorPtr
2193 NVSetupOverlayVideoAdapter(ScreenPtr pScreen)
2195 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2196 NVPtr pNv = NVPTR(pScrn);
2197 XF86VideoAdaptorPtr adapt;
2198 NVPortPrivPtr pPriv;
2200 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2201 sizeof(NVPortPrivRec) +
2202 sizeof(DevUnion)))) {
2206 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2207 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
2208 adapt->name = "NV Video Overlay";
2209 adapt->nEncodings = 1;
2210 adapt->pEncodings = &DummyEncoding;
2211 adapt->nFormats = NUM_FORMATS_ALL;
2212 adapt->pFormats = NVFormats;
2214 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2216 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
2217 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
2219 adapt->pAttributes = (pNv->Architecture != NV_ARCH_04) ? NVOverlayAttributes : NV04OverlayAttributes;
2220 adapt->nAttributes = (pNv->Architecture != NV_ARCH_04) ? NUM_OVERLAY_ATTRIBUTES : NUM_NV04_OVERLAY_ATTRIBUTES;
2221 adapt->pImages = NVImages;
2222 adapt->nImages = NUM_IMAGES_YUV;
2223 adapt->PutVideo = NULL;
2224 adapt->PutStill = NULL;
2225 adapt->GetVideo = NULL;
2226 adapt->GetStill = NULL;
2227 adapt->StopVideo = NVStopOverlayVideo;
2228 adapt->SetPortAttribute = NVSetOverlayPortAttribute;
2229 adapt->GetPortAttribute = NVGetOverlayPortAttribute;
2230 adapt->QueryBestSize = NVQueryBestSize;
2231 adapt->PutImage = NVPutImage;
2232 adapt->QueryImageAttributes = NVQueryImageAttributes;
2234 pPriv->videoStatus = 0;
2235 pPriv->currentBuffer = 0;
2236 pPriv->grabbedByV4L = FALSE;
2237 pPriv->blitter = FALSE;
2238 if ( pNv->Architecture == NV_ARCH_04 )
2239 pPriv->doubleBuffer = 0;
2241 NVSetPortDefaults (pScrn, pPriv);
2243 /* gotta uninit this someplace */
2244 REGION_NULL(pScreen, &pPriv->clip);
2246 pNv->overlayAdaptor = adapt;
2248 xvColorKey = MAKE_ATOM("XV_COLORKEY");
2249 if ( pNv->Architecture != NV_ARCH_04 )
2251 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
2252 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
2253 xvContrast = MAKE_ATOM("XV_CONTRAST");
2254 xvSaturation = MAKE_ATOM("XV_SATURATION");
2255 xvHue = MAKE_ATOM("XV_HUE");
2256 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
2257 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
2258 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
2259 xvOnCRTCNb = MAKE_ATOM("XV_ON_CRTC_NB");
2262 NVResetVideo(pScrn);
2268 XF86OffscreenImageRec NVOffscreenImages[2] = {
2271 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2276 NVGetSurfaceAttribute,
2277 NVSetSurfaceAttribute,
2278 IMAGE_MAX_W, IMAGE_MAX_H,
2279 NUM_OVERLAY_ATTRIBUTES - 1,
2280 &NVOverlayAttributes[1]
2284 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2289 NVGetSurfaceAttribute,
2290 NVSetSurfaceAttribute,
2291 IMAGE_MAX_W, IMAGE_MAX_H,
2292 NUM_OVERLAY_ATTRIBUTES - 1,
2293 &NVOverlayAttributes[1]
2298 NVInitOffscreenImages (ScreenPtr pScreen)
2300 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
2304 * NVChipsetHasOverlay
2306 * newer chips don't support overlay anymore.
2307 * overlay feature is emulated via textures.
2310 * @return true, if chipset supports overlay
2313 NVChipsetHasOverlay(NVPtr pNv)
2315 switch (pNv->Architecture) {
2316 case NV_ARCH_04: /*NV04 has a different overlay than NV10+*/
2322 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
2333 * NVSetupOverlayVideo
2334 * check if chipset supports Overlay and CompositeExtension is disabled.
2335 * if so, setup overlay port
2337 * @return overlay port
2338 * @see NVChipsetHasOverlay(NVPtr pNv)
2339 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
2340 * @see NVInitOffscreenImages(ScreenPtr pScreen)
2342 static XF86VideoAdaptorPtr
2343 NVSetupOverlayVideo(ScreenPtr pScreen)
2345 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2346 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2347 NVPtr pNv = NVPTR(pScrn);
2349 if (!NVChipsetHasOverlay(pNv))
2352 overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen);
2353 if (overlayAdaptor && pNv->Architecture != NV_ARCH_04 )
2354 NVInitOffscreenImages(pScreen); //I am not sure what this call does.
2357 if (!noCompositeExtension) {
2358 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2359 "XV: Composite is enabled, enabling overlay with smart blitter fallback\n");
2360 overlayAdaptor -> name = "NV Video Overlay with Composite";
2364 return overlayAdaptor;
2369 * tries to initialize one new overlay port and one new blit port
2370 * and add them to the list of ports on screen "pScreen".
2373 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
2374 * @see NVSetupBlitVideo(ScreenPtr pScreen)
2376 void NVInitVideo (ScreenPtr pScreen)
2378 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2379 NVPtr pNv = NVPTR(pScrn);
2380 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
2381 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2382 XF86VideoAdaptorPtr blitAdaptor = NULL;
2386 * Driving the blitter requires the DMA FIFO. Using the FIFO
2387 * without accel causes DMA errors. While the overlay might
2388 * might work without accel, we also disable it for now when
2389 * acceleration is disabled:
2391 if (pScrn->bitsPerPixel != 8 && pNv->Architecture < NV_ARCH_50 && !pNv->NoAccel) {
2392 overlayAdaptor = NVSetupOverlayVideo(pScreen);
2393 blitAdaptor = NVSetupBlitVideo(pScreen);
2396 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
2397 if(blitAdaptor || overlayAdaptor) {
2398 int size = num_adaptors;
2400 if(overlayAdaptor) size++;
2401 if(blitAdaptor) size++;
2403 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
2406 memcpy(newAdaptors, adaptors, num_adaptors *
2407 sizeof(XF86VideoAdaptorPtr));
2410 if(overlayAdaptor) {
2411 newAdaptors[num_adaptors] = overlayAdaptor;
2416 newAdaptors[num_adaptors] = blitAdaptor;
2420 adaptors = newAdaptors;
2425 xf86XVScreenInit(pScreen, adaptors, num_adaptors);