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;
81 struct nouveau_bo *video_mem;
84 struct nouveau_bo *TT_mem_chunk[2];
85 int currentHostBuffer;
86 struct nouveau_notifier *DMANotifier[2];
87 } NVPortPrivRec, *NVPortPrivPtr;
90 /* Xv DMA notifiers status tracing */
93 XV_DMA_NOTIFIER_NOALLOC=0, //notifier not allocated
94 XV_DMA_NOTIFIER_INUSE=1,
95 XV_DMA_NOTIFIER_FREE=2, //notifier allocated, ready for use
98 /* We have six notifiers available, they are not allocated at startup */
99 int XvDMANotifierStatus[6]= { XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC ,
100 XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC };
101 struct nouveau_notifier *XvDMANotifiers[6];
103 /* NVPutImage action flags */
110 IS_RGB=32, //I am not sure how long we will support it
113 #define GET_OVERLAY_PRIVATE(pNv) \
114 (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr)
116 #define GET_BLIT_PRIVATE(pNv) \
117 (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr)
119 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
121 static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
122 xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
123 xvITURBT709, xvSyncToVBlank;
125 /* client libraries expect an encoding */
126 static XF86VideoEncodingRec DummyEncoding =
130 IMAGE_MAX_W, IMAGE_MAX_H,
134 #define NUM_FORMATS_ALL 6
136 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
138 {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
139 {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
142 #define NUM_NV04_OVERLAY_ATTRIBUTES 1
143 XF86AttributeRec NV04OverlayAttributes[NUM_NV04_OVERLAY_ATTRIBUTES] =
145 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
149 #define NUM_OVERLAY_ATTRIBUTES 9
150 XF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] =
152 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
153 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
154 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
155 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
156 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
157 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
158 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
159 {XvSettable | XvGettable, 0, 360, "XV_HUE"},
160 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"}
163 #define NUM_BLIT_ATTRIBUTES 2
164 XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
166 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
167 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
171 #define NUM_IMAGES_YUV 4
172 #define NUM_IMAGES_ALL 5
174 #define FOURCC_RGB 0x0000003
175 #define XVIMAGE_RGB \
180 { 0x03, 0x00, 0x00, 0x00, \
181 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
185 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
190 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}, \
194 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
204 NVWaitVSync(ScrnInfoPtr pScrn)
206 NVPtr pNv = NVPTR(pScrn);
208 BEGIN_RING(NvImageBlit, 0x0000012C, 1);
210 BEGIN_RING(NvImageBlit, 0x00000134, 1);
211 /* If crtc1 is active, this will produce one, otherwise zero */
212 /* The assumption is that at least one is active */
213 OUT_RING (pNv->crtc_active[1]);
214 BEGIN_RING(NvImageBlit, 0x00000100, 1);
216 BEGIN_RING(NvImageBlit, 0x00000130, 1);
222 * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
224 * @param pScrn screen to get the default colorKey from
225 * @param pPriv port to reset to defaults
228 NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
230 NVPtr pNv = NVPTR(pScrn);
232 pPriv->brightness = 0;
233 pPriv->contrast = 4096;
234 pPriv->saturation = 4096;
236 pPriv->colorKey = pNv->videoKey;
237 pPriv->autopaintColorKey = TRUE;
238 pPriv->doubleBuffer = TRUE;
239 pPriv->iturbt_709 = FALSE;
240 pPriv->currentHostBuffer = 0;
245 * writes the current attributes from the overlay port to the hardware
248 NVResetVideo (ScrnInfoPtr pScrn)
250 NVPtr pNv = NVPTR(pScrn);
251 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
252 int satSine, satCosine;
255 angle = (double)pPriv->hue * 3.1415927 / 180.0;
257 satSine = pPriv->saturation * sin(angle);
260 satCosine = pPriv->saturation * cos(angle);
261 if (satCosine < -1024)
264 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
266 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
268 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
269 (satCosine & 0xffff));
270 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
271 (satCosine & 0xffff));
272 nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
277 * Tell the hardware to stop the overlay
280 NVStopOverlay (ScrnInfoPtr pScrn)
282 NVPtr pNv = NVPTR(pScrn);
284 if ( pNv -> Architecture != NV_ARCH_04 )
285 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
288 nvWriteRAMDAC(pNv, 0, 0x244, nvReadRAMDAC(pNv, 0, 0x244) &~ 0x1);
289 nvWriteRAMDAC(pNv, 0, 0x224, 0);
290 nvWriteRAMDAC(pNv, 0, 0x228, 0);
291 nvWriteRAMDAC(pNv, 0, 0x22c, 0);
296 * NVXvDMANotifierAlloc
297 * allocates a notifier from the table of 6 we have
299 * @return a notifier instance or NULL on error
301 static struct nouveau_notifier *
302 NVXvDMANotifierAlloc(ScrnInfoPtr pScrn)
304 NVPtr pNv = NVPTR(pScrn);
307 for (i = 0; i < 6; i++) {
308 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_INUSE)
311 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_FREE) {
312 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
313 return XvDMANotifiers[i];
316 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_NOALLOC) {
317 if (nouveau_notifier_alloc(pNv->chan,
318 NvDmaXvNotifier0 + i,
319 1, &XvDMANotifiers[i]))
321 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
322 return XvDMANotifiers[i];
330 * NVXvDMANotifierFree
331 * frees a notifier from the table of 6 we have
336 NVXvDMANotifierFree(ScrnInfoPtr pScrn, struct nouveau_notifier *target)
339 for ( i = 0; i < 6; i ++ )
341 if ( XvDMANotifiers[i] == target )
344 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_FREE;
348 * NVAllocateVideoMemory
349 * allocates video memory for a given port
351 * @param pScrn screen which requests the memory
352 * @param mem pointer to previously allocated memory for reallocation
353 * @param size size of requested memory segment
354 * @return pointer to the allocated memory
356 static struct nouveau_bo *
357 NVAllocateVideoMemory(ScrnInfoPtr pScrn, struct nouveau_bo *mem, int size)
359 NVPtr pNv = NVPTR(pScrn);
360 struct nouveau_bo *bo = NULL;
363 if(mem->size >= size)
365 nouveau_bo_del(&mem);
368 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN, 0,
372 if (nouveau_bo_map(bo, NOUVEAU_BO_RDWR)) {
382 * allocates TT memory for a given port
384 * @param pScrn screen which requests the memory
385 * @param mem pointer to previously allocated memory for reallocation
386 * @param size size of requested memory segment
387 * @return pointer to the allocated memory
389 static struct nouveau_bo *
390 NVAllocateTTMemory(ScrnInfoPtr pScrn, struct nouveau_bo *mem, int size)
392 NVPtr pNv = NVPTR(pScrn);
393 struct nouveau_bo *bo = NULL;
396 if(mem->size >= size)
398 nouveau_bo_del(&mem);
401 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_GART | NOUVEAU_BO_PIN, 0,
405 if (nouveau_bo_map(bo, NOUVEAU_BO_RDWR)) {
415 * frees memory held by a given port
417 * @param pScrn screen whose port wants to free memory
418 * @param pPriv port to free memory of
421 NVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
423 //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]);
425 if(pPriv->video_mem) {
426 nouveau_bo_del(&pPriv->video_mem);
427 pPriv->video_mem = NULL;
430 if ( pPriv->TT_mem_chunk[ 0 ] && pPriv->DMANotifier [ 0 ] )
432 nouveau_notifier_wait_status(pPriv->DMANotifier[0], 0, 0, 1000);
435 if ( pPriv->TT_mem_chunk[ 1 ] && pPriv->DMANotifier [ 1 ] )
437 nouveau_notifier_wait_status(pPriv->DMANotifier[1], 0, 0, 1000);
440 if(pPriv->TT_mem_chunk[0]) {
441 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
442 pPriv->TT_mem_chunk[0] = NULL;
445 if(pPriv->TT_mem_chunk[1]) {
446 nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
447 pPriv->TT_mem_chunk[1] = NULL;
450 if(pPriv->DMANotifier[0]) {
451 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[0]);
452 pPriv->DMANotifier[0] = NULL;
455 if(pPriv->DMANotifier[1]) {
456 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[1]);
457 pPriv->DMANotifier[1] = NULL;
463 * NVFreeOverlayMemory
464 * frees memory held by the overlay port
466 * @param pScrn screen whose overlay port wants to free memory
469 NVFreeOverlayMemory(ScrnInfoPtr pScrn)
471 NVPtr pNv = NVPTR(pScrn);
472 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
473 NVFreePortMemory(pScrn, pPriv);
474 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) & 0xEFFFFFFF));
475 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) | 0x10000000));
480 * frees memory held by the blit port
482 * @param pScrn screen whose blit port wants to free memory
485 NVFreeBlitMemory(ScrnInfoPtr pScrn)
487 NVPtr pNv = NVPTR(pScrn);
488 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
489 NVFreePortMemory(pScrn, pPriv);
493 * NVVideoTimerCallback
494 * callback function which perform cleanup tasks (stop overlay, free memory).
495 * within the driver it is only called once from NVBlockHandler in nv_driver.c
498 NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
500 NVPtr pNv = NVPTR(pScrn);
501 NVPortPrivPtr pOverPriv = NULL;
502 NVPortPrivPtr pBlitPriv = NULL;
503 Bool needCallback = FALSE;
508 if (pNv->overlayAdaptor) {
509 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
510 if (!pOverPriv->videoStatus)
514 if (pNv->blitAdaptor) {
515 pBlitPriv = GET_BLIT_PRIVATE(pNv);
516 if (!pBlitPriv->videoStatus)
521 if (pOverPriv->videoTime < currentTime) {
522 if (pOverPriv->videoStatus & OFF_TIMER) {
523 NVStopOverlay(pScrn);
524 pOverPriv->videoStatus = FREE_TIMER;
525 pOverPriv->videoTime = currentTime + FREE_DELAY;
528 if (pOverPriv->videoStatus & FREE_TIMER) {
529 NVFreeOverlayMemory(pScrn);
530 pOverPriv->videoStatus = 0;
538 if (pBlitPriv->videoTime < currentTime) {
539 NVFreeBlitMemory(pScrn);
540 pBlitPriv->videoStatus = 0;
546 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
551 * program hardware to overlay image into front buffer
553 * @param pScrn screen
554 * @param offset card offset to the pixel data
555 * @param id format of image
556 * @param dstPitch pitch of the pixel data in VRAM
557 * @param dstBox destination box
558 * @param x1 first source point - x
559 * @param y1 first source point - y
560 * @param x2 second source point - x
561 * @param y2 second source point - y
562 * @param width width of the source image = x2 - x1
563 * @param height height
564 * @param src_w width of the image data in VRAM
565 * @param src_h height
566 * @param drw_w width of the image to draw to screen
567 * @param drw_h height
568 * @param clipBoxes ???
571 NVPutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
572 int dstPitch, BoxPtr dstBox,
573 int x1, int y1, int x2, int y2,
574 short width, short height,
575 short src_w, short src_h,
576 short drw_w, short drw_h,
579 NVPtr pNv = NVPTR(pScrn);
580 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
581 int buffer = pPriv->currentBuffer;
583 /* paint the color key */
584 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
585 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
586 /* we always paint V4L's color key */
587 if (!pPriv->grabbedByV4L)
588 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
590 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
594 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
600 //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));
602 nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer) , 0);
603 nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer) , offset);
604 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer) , (height << 16) | width);
605 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
606 ((y1 << 4) & 0xffff0000) | (x1 >> 12));
607 nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer) , (src_w << 20) / drw_w);
608 nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer) , (src_h << 20) / drw_h);
609 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
610 (dstBox->y1 << 16) | dstBox->x1);
611 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
612 ((dstBox->y2 - dstBox->y1) << 16) |
613 (dstBox->x2 - dstBox->x1));
615 dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; /* use color key */
616 if(id != FOURCC_UYVY)
617 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
618 if(pPriv->iturbt_709)
619 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
621 if( id == FOURCC_YV12 || id == FOURCC_I420 )
622 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
624 /* Those are important only for planar formats (NV12) */
627 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_BASE(buffer), 0);
628 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer), uvoffset);
631 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
632 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
633 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
635 pPriv->videoStatus = CLIENT_VIDEO_ON;
639 NV04PutOverlayImage(ScrnInfoPtr pScrn, int offset, int id,
640 int dstPitch, BoxPtr dstBox,
641 int x1, int y1, int x2, int y2,
642 short width, short height,
643 short src_w, short src_h,
644 short drw_w, short drw_h,
647 NVPtr pNv = NVPTR(pScrn);
648 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
650 /* paint the color key */
651 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
652 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
653 /* we always paint V4L's color key */
654 if (!pPriv->grabbedByV4L)
655 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
657 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
661 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) { /*This may not work with NV04 overlay according to rivatv source*/
667 /* NV_PVIDEO_OE_STATE */
668 /* NV_PVIDEO_SU_STATE */
669 /* NV_PVIDEO_RM_STATE */
670 nvWriteRAMDAC(pNv, 0, 0x224, 0);
671 nvWriteRAMDAC(pNv, 0, 0x228, 0);
672 nvWriteRAMDAC(pNv, 0, 0x22c, 0);
674 /* NV_PVIDEO_BUFF0_START_ADDRESS */
675 nvWriteRAMDAC(pNv, 0, 0x20C, offset);
676 nvWriteRAMDAC(pNv, 0, 0x20C + 4, offset);
677 /* NV_PVIDEO_BUFF0_PITCH_LENGTH */
678 nvWriteRAMDAC(pNv, 0, 0x214, dstPitch);
679 nvWriteRAMDAC(pNv, 0, 0x214 + 4, dstPitch);
681 /* NV_PVIDEO_BUFF0_OFFSET */
682 nvWriteRAMDAC(pNv, 0, 0x21C, 0);
683 nvWriteRAMDAC(pNv, 0, 0x21C + 4, 0);
685 /* NV_PVIDEO_WINDOW_START */
686 nvWriteRAMDAC(pNv, 0, 0x230, (dstBox->y1 << 16) | dstBox->x1);
687 /* NV_PVIDEO_WINDOW_SIZE */
688 nvWriteRAMDAC(pNv, 0, 0x234, ((dstBox->y2 - dstBox->y1) << 16) |
689 (dstBox->x2 - dstBox->x1));
690 /* NV_PVIDEO_STEP_SIZE */
691 nvWriteRAMDAC(pNv, 0, 0x200, (uint32_t)(((src_h - 1) << 11) / (drw_h - 1)) << 16 | (uint32_t)(((src_w - 1) << 11) / (drw_w - 1)));
693 /* NV_PVIDEO_RED_CSC_OFFSET */
694 /* NV_PVIDEO_GREEN_CSC_OFFSET */
695 /* NV_PVIDEO_BLUE_CSC_OFFSET */
696 /* NV_PVIDEO_CSC_ADJUST */
697 nvWriteRAMDAC(pNv, 0, 0x280, 0x69);
698 nvWriteRAMDAC(pNv, 0, 0x284, 0x3e);
699 nvWriteRAMDAC(pNv, 0, 0x288, 0x89);
700 nvWriteRAMDAC(pNv, 0, 0x28C, 0x0);
702 /* NV_PVIDEO_CONTROL_Y (BLUR_ON, LINE_HALF) */
703 nvWriteRAMDAC(pNv, 0, 0x204, 0x001);
704 /* NV_PVIDEO_CONTROL_X (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */
705 nvWriteRAMDAC(pNv, 0, 0x208, 0x111);
707 /* NV_PVIDEO_FIFO_BURST_LENGTH */
708 nvWriteRAMDAC(pNv, 0, 0x23C, 0x03);
709 /* NV_PVIDEO_FIFO_THRES_SIZE */
710 nvWriteRAMDAC(pNv, 0, 0x238, 0x38);
713 nvWriteRAMDAC(pNv, 0, 0x240, pPriv->colorKey);
719 nvWriteRAMDAC(pNv, 0, 0x244, 0x111);
721 /* NV_PVIDEO_SU_STATE */
722 nvWriteRAMDAC(pNv, 0, 0x228, (nvReadRAMDAC(pNv, 0, 0x228) ^ (1 << 16)));
724 pPriv->videoStatus = CLIENT_VIDEO_ON;
726 #ifndef ExaOffscreenMarkUsed
727 extern void ExaOffscreenMarkUsed(PixmapPtr);
729 #ifndef exaGetDrawablePixmap
730 extern PixmapPtr exaGetDrawablePixmap(DrawablePtr);
732 #ifndef exaPixmapIsOffscreen
733 extern Bool exaPixmapIsOffscreen(PixmapPtr p);
735 /* To support EXA 2.0, 2.1 has this in the header */
736 #ifndef exaMoveInPixmap
737 extern void exaMoveInPixmap(PixmapPtr pPixmap);
743 * @param pScrn screen
745 * @param id colorspace of image
762 NVPutBlitImage(ScrnInfoPtr pScrn, int src_offset, int id,
763 int src_pitch, BoxPtr dstBox,
764 int x1, int y1, int x2, int y2,
765 short width, short height,
766 short src_w, short src_h,
767 short drw_w, short drw_h,
771 NVPtr pNv = NVPTR(pScrn);
772 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
776 CARD32 dst_size, dst_point;
777 CARD32 src_point, src_format;
779 ScreenPtr pScreen = pScrn->pScreen;
780 PixmapPtr pPix = exaGetDrawablePixmap(pDraw);
783 /* Try to get the dest drawable into vram */
784 if (!exaPixmapIsOffscreen(pPix)) {
785 exaMoveInPixmap(pPix);
786 ExaOffscreenMarkUsed(pPix);
789 /* If we failed, draw directly onto the screen pixmap.
790 * Not sure if this is the best approach, maybe failing
791 * with BadAlloc would be better?
793 if (!exaPixmapIsOffscreen(pPix)) {
794 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
795 "XV: couldn't move dst surface into vram\n");
796 pPix = pScreen->GetScreenPixmap(pScreen);
799 NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format);
800 BEGIN_RING(NvContextSurfaces, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
801 OUT_RING (dst_format);
802 OUT_RING ((exaGetPixmapPitch(pPix) << 16) | exaGetPixmapPitch(pPix));
803 OUT_PIXMAPl(pPix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
804 OUT_PIXMAPl(pPix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
807 /* Adjust coordinates if drawing to an offscreen pixmap */
808 if (pPix->screen_x || pPix->screen_y) {
809 REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
812 dstBox->x1 -= pPix->screen_x;
813 dstBox->x2 -= pPix->screen_x;
814 dstBox->y1 -= pPix->screen_y;
815 dstBox->y2 -= pPix->screen_y;
818 DamageDamageRegion((DrawablePtr)pPix, clipBoxes);
821 pbox = REGION_RECTS(clipBoxes);
822 nbox = REGION_NUM_RECTS(clipBoxes);
824 dsdx = (src_w << 20) / drw_w;
825 dtdy = (src_h << 20) / drw_h;
827 dst_size = ((dstBox->y2 - dstBox->y1) << 16) |
828 (dstBox->x2 - dstBox->x1);
829 dst_point = (dstBox->y1 << 16) | dstBox->x1;
831 src_pitch |= (NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
832 NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_BILINEAR);
833 src_point = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
838 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
842 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_YB8V8YA8U8;
846 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_V8YB8U8YA8;
850 if(pPriv->SyncToVBlank) {
855 if(pNv->BlendingPossible) {
856 BEGIN_RING(NvScaledImage,
857 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 2);
858 OUT_RING (src_format);
859 OUT_RING (NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
861 BEGIN_RING(NvScaledImage,
862 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 2);
863 OUT_RING (src_format);
867 BEGIN_RING(NvRectangle,
868 NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
871 BEGIN_RING(NvScaledImage,
872 NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT, 6);
873 OUT_RING ((pbox->y1 << 16) | pbox->x1);
874 OUT_RING (((pbox->y2 - pbox->y1) << 16) |
875 (pbox->x2 - pbox->x1));
876 OUT_RING (dst_point);
881 BEGIN_RING(NvScaledImage,
882 NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
883 OUT_RING ((height << 16) | width);
884 OUT_RING (src_pitch);
885 OUT_RING (src_offset);
886 OUT_RING (src_point);
892 exaMarkSync(pScrn->pScreen);
894 pPriv->videoStatus = FREE_TIMER;
895 pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
896 pNv->VideoTimerCallback = NVVideoTimerCallback;
903 NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
905 NVPtr pNv = NVPTR(pScrn);
906 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
908 if(pPriv->grabbedByV4L) return;
910 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
913 if (pPriv->videoStatus & CLIENT_VIDEO_ON)
914 NVStopOverlay(pScrn);
915 NVFreeOverlayMemory(pScrn);
916 pPriv->videoStatus = 0;
918 if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
919 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
920 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
921 pNv->VideoTimerCallback = NVVideoTimerCallback;
930 NVStopBlitVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
935 * NVSetOverlayPortAttribute
936 * sets the attribute "attribute" of port "data" to value "value"
937 * calls NVResetVideo(pScrn) to apply changes to hardware
940 * @param attribute attribute to set
941 * @param value value to which attribute is to be set
942 * @param data port from which the attribute is to be set
944 * @return Success, if setting is successful
945 * BadValue/BadMatch, if value/attribute are invalid
946 * @see NVResetVideo(ScrnInfoPtr pScrn)
949 NVSetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
950 INT32 value, pointer data)
952 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
954 if (attribute == xvBrightness) {
955 if ((value < -512) || (value > 512))
957 pPriv->brightness = value;
959 if (attribute == xvDoubleBuffer) {
960 if ((value < 0) || (value > 1))
962 pPriv->doubleBuffer = value;
964 if (attribute == xvContrast) {
965 if ((value < 0) || (value > 8191))
967 pPriv->contrast = value;
969 if (attribute == xvHue) {
975 if (attribute == xvSaturation) {
976 if ((value < 0) || (value > 8191))
978 pPriv->saturation = value;
980 if (attribute == xvColorKey) {
981 pPriv->colorKey = value;
982 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
984 if (attribute == xvAutopaintColorKey) {
985 if ((value < 0) || (value > 1))
987 pPriv->autopaintColorKey = value;
989 if (attribute == xvITURBT709) {
990 if ((value < 0) || (value > 1))
992 pPriv->iturbt_709 = value;
994 if (attribute == xvSetDefaults) {
995 NVSetPortDefaults(pScrn, pPriv);
1004 * NVGetOverlayPortAttribute
1006 * @param pScrn unused
1007 * @param attribute attribute to be read
1008 * @param value value of attribute will be stored in this pointer
1009 * @param data port from which attribute will be read
1010 * @return Success, if queried attribute exists
1013 NVGetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1014 INT32 *value, pointer data)
1016 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1018 if (attribute == xvBrightness)
1019 *value = pPriv->brightness;
1020 else if (attribute == xvDoubleBuffer)
1021 *value = (pPriv->doubleBuffer) ? 1 : 0;
1022 else if (attribute == xvContrast)
1023 *value = pPriv->contrast;
1024 else if (attribute == xvSaturation)
1025 *value = pPriv->saturation;
1026 else if (attribute == xvHue)
1027 *value = pPriv->hue;
1028 else if (attribute == xvColorKey)
1029 *value = pPriv->colorKey;
1030 else if (attribute == xvAutopaintColorKey)
1031 *value = (pPriv->autopaintColorKey) ? 1 : 0;
1032 else if (attribute == xvITURBT709)
1033 *value = (pPriv->iturbt_709) ? 1 : 0;
1041 * NVSetBlitPortAttribute
1042 * sets the attribute "attribute" of port "data" to value "value"
1043 * supported attributes:
1044 * - xvSyncToVBlank (values: 0,1)
1045 * - xvSetDefaults (values: NA; SyncToVBlank will be set, if hardware supports it)
1048 * @param attribute attribute to set
1049 * @param value value to which attribute is to be set
1050 * @param data port from which the attribute is to be set
1052 * @return Success, if setting is successful
1053 * BadValue/BadMatch, if value/attribute are invalid
1056 NVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1057 INT32 value, pointer data)
1059 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1060 NVPtr pNv = NVPTR(pScrn);
1062 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
1063 if ((value < 0) || (value > 1))
1065 pPriv->SyncToVBlank = value;
1067 if (attribute == xvSetDefaults) {
1068 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1076 * NVGetBlitPortAttribute
1077 * reads the value of attribute "attribute" from port "data" into INT32 "*value"
1078 * currently only one attribute supported: xvSyncToVBlank
1080 * @param pScrn unused
1081 * @param attribute attribute to be read
1082 * @param value value of attribute will be stored here
1083 * @param data port from which attribute will be read
1084 * @return Success, if queried attribute exists
1087 NVGetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1088 INT32 *value, pointer data)
1090 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1092 if(attribute == xvSyncToVBlank)
1093 *value = (pPriv->SyncToVBlank) ? 1 : 0;
1103 * used by client applications to ask the driver:
1104 * how would you actually scale a video of dimensions
1105 * vid_w, vid_h, if i wanted you to scale it to dimensions
1107 * function stores actual scaling size in pointers p_w, p_h.
1110 * @param pScrn unused
1111 * @param motion unused
1112 * @param vid_w width of source video
1113 * @param vid_h height of source video
1114 * @param drw_w desired scaled width as requested by client
1115 * @param drw_h desired scaled height as requested by client
1116 * @param p_w actual scaled width as the driver is capable of
1117 * @param p_h actual scaled height as the driver is capable of
1118 * @param data unused
1121 NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
1122 short vid_w, short vid_h,
1123 short drw_w, short drw_h,
1124 unsigned int *p_w, unsigned int *p_h,
1127 if(vid_w > (drw_w << 3))
1129 if(vid_h > (drw_h << 3))
1138 * used to convert YV12 to YUY2 for the blitter
1140 * @param src1 source buffer of luma
1141 * @param src2 source buffer of chroma1
1142 * @param src3 source buffer of chroma2
1143 * @param dst1 destination buffer
1144 * @param srcPitch pitch of src1
1145 * @param srcPitch2 pitch of src2, src3
1146 * @param dstPitch pitch of dst1
1147 * @param h number of lines to copy
1148 * @param w length of lines to copy
1150 static inline void NVCopyData420(unsigned char *src1, unsigned char *src2,
1151 unsigned char *src3, unsigned char *dst1,
1152 int srcPitch, int srcPitch2,
1157 CARD8 *s1, *s2, *s3;
1162 for (j = 0; j < h; j++) {
1163 dst = (CARD32*)dst1;
1164 s1 = src1; s2 = src2; s3 = src3;
1168 #if X_BYTE_ORDER == X_BIG_ENDIAN
1169 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
1170 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1];
1171 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2];
1172 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3];
1174 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
1175 dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
1176 dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
1177 dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
1179 dst += 4; s2 += 4; s3 += 4; s1 += 8;
1184 #if X_BYTE_ORDER == X_BIG_ENDIAN
1185 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
1187 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
1203 * NVCopyNV12ColorPlanes
1204 * Used to convert YV12 color planes to NV12 (interleaved UV) for the overlay
1206 * @param src1 source buffer of chroma1
1207 * @param dst1 destination buffer
1208 * @param h number of lines to copy
1209 * @param w length of lines to copy
1210 * @param id source pixel format (YV12 or I420)
1212 static inline void NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char * src2, unsigned char *dst, int dstPitch, int srcPitch2,
1222 for ( j = 0; j < h; j++ )
1224 unsigned char * us = src1;
1225 unsigned char * vs = src2;
1226 unsigned int * vuvud = (unsigned int *) dst;
1227 for ( i = 0; i < l; i++ )
1229 #if X_BYTE_ORDER == X_BIG_ENDIAN
1230 *vuvud++ = (vs[0]<<24) | (us[0]<<16) | (vs[1]<<8) | us[1];
1232 *vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24);
1238 unsigned short *vud = (unsigned short *) vuvud;
1239 #if X_BYTE_ORDER == X_BIG_ENDIAN
1240 *vud = (vs[0]<<8) | (us[0] << 0);
1242 *vud = vs[0] | (us[0]<<8);
1253 static int NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 * xa, INT32 * xb, INT32 * ya, INT32 * yb,
1254 short * src_x, short * src_y, short * src_w, short * src_h,
1255 short * drw_x, short * drw_y, short * drw_w, short * drw_h,
1256 int * left, int * top, int * right, int * bottom,
1258 int * npixels, int * nlines,
1259 RegionPtr clipBoxes, short width, short height
1263 if ( action_flags & USE_OVERLAY )
1264 { /* overlay hardware scaler limitation - copied from nv, UNCHECKED*/
1265 if (*src_w > (*drw_w << 3))
1266 *drw_w = *src_w >> 3;
1267 if (*src_h > (*drw_h << 3))
1268 *drw_h = *src_h >> 3;
1274 *xb = *src_x + *src_w;
1276 *yb = *src_y + *src_h;
1278 dstBox->x1 = *drw_x;
1279 dstBox->x2 = *drw_x + *drw_w;
1280 dstBox->y1 = *drw_y;
1281 dstBox->y2 = *drw_y + *drw_h;
1283 if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
1287 if ( action_flags & USE_OVERLAY )
1289 dstBox->x1 -= pScrn->frameX0;
1290 dstBox->x2 -= pScrn->frameX0;
1291 dstBox->y1 -= pScrn->frameY0;
1292 dstBox->y2 -= pScrn->frameY0;
1297 /* Convert fixed point to integer, as xf86XVClipVideoHelper probably turns its parameter into fixed point values */
1298 *left = (*xa) >> 16;
1299 if (*left < 0) *left = 0;
1301 if (*top < 0) *top = 0;
1302 *right = (*xb) >> 16;
1303 if (*right > width) *right = width;
1304 *bottom = (*yb) >> 16;
1305 if (*bottom > height) *bottom = height;
1307 if ( action_flags & IS_YV12 )
1309 *left &= ~1; //even "left", even "top", even number of pixels per line and even number of lines
1310 *npixels = ((*right + 1) & ~1) - *left;
1312 *nlines = ((*bottom + 1) & ~1) - *top;
1314 else if ( action_flags & IS_YUY2 )
1316 *left &= ~1; //even "left"
1317 *npixels = ((*right + 1) & ~1) - *left; //even number of pixels per line
1318 *nlines = *bottom - *top;
1319 *left <<= 1; //16bpp
1321 else if (action_flags & IS_RGB )
1323 *npixels = *right - *left;
1324 *nlines = *bottom - *top;
1325 *left <<= 2; //32bpp
1331 static int NV_calculate_pitches_and_mem_size(int action_flags, int * srcPitch, int * srcPitch2, int * dstPitch,
1332 int * s2offset, int * s3offset,
1333 int * newFBSize, int * newTTSize,
1334 int * line_len, int npixels, int nlines, int width, int height)
1338 if ( action_flags & IS_YV12 )
1340 *srcPitch = (width + 3) & ~3; /* of luma */
1341 *s2offset = *srcPitch * height;
1342 *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
1343 *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
1344 *dstPitch = (npixels + 63) &~ 63; /*luma and chroma pitch*/
1345 *line_len = npixels;
1346 *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1347 *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1349 else if ( action_flags & IS_YUY2 )
1351 *srcPitch = width << 1; /* one luma, one chroma per pixel */
1352 *dstPitch = ((npixels << 1) + 63) & ~63;
1353 *line_len = npixels << 1;
1354 *newFBSize = nlines * *dstPitch;
1355 *newTTSize = nlines * *line_len;
1357 else if ( action_flags & IS_RGB )
1359 *srcPitch = width << 2; /* one R, one G, one B, one X per pixel */
1360 *dstPitch = ((npixels << 2) + 63) & ~63;
1361 *line_len = npixels << 2;
1362 *newFBSize = nlines * *dstPitch;
1363 *newTTSize = nlines * *dstPitch;
1367 if ( action_flags & CONVERT_TO_YUY2 )
1369 *dstPitch = ((npixels << 1) + 63) & ~63;
1370 *line_len = npixels << 1;
1371 *newFBSize = nlines * *dstPitch;
1372 *newTTSize = nlines * *line_len;
1375 if ( action_flags & SWAP_UV )
1376 { //I420 swaps U and V
1378 *s2offset = *s3offset;
1382 if ( action_flags & USE_OVERLAY ) // overlay double buffering ...
1383 (*newFBSize) <<= 1; // ... means double the amount of VRAM needed
1390 * NV_set_action_flags
1391 * This function computes the action flags from the input image,
1392 * that is, it decides what NVPutImage and its helpers must do.
1393 * This eases readability by avoiding lots of switch-case statements in the core NVPutImage
1395 static void NV_set_action_flags(NVPtr pNv, ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, int id, int * action_flags)
1398 if ( id == FOURCC_YUY2 || id == FOURCC_UYVY )
1399 *action_flags |= IS_YUY2;
1401 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1402 *action_flags |= IS_YV12;
1404 if ( id == FOURCC_RGB ) /*How long will we support it?*/
1405 *action_flags |= IS_RGB;
1407 if ( id == FOURCC_I420 ) /*I420 is YV12 with swapped UV*/
1408 *action_flags |= SWAP_UV;
1410 if ( !pPriv -> blitter )
1411 *action_flags |= USE_OVERLAY;
1414 WindowPtr pWin = NULL;
1416 if (!noCompositeExtension && WindowDrawable(pDraw->type))
1418 pWin = (WindowPtr)pDraw;
1422 if ( pWin->redirectDraw )
1423 *action_flags &= ~USE_OVERLAY;
1427 if ( ! ( *action_flags & USE_OVERLAY) )
1429 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1430 { /*The blitter does not handle YV12 natively*/
1431 *action_flags |= CONVERT_TO_YUY2;
1435 if ( pNv->Architecture == NV_ARCH_04 )
1436 if ( * action_flags & IS_YV12 ) //NV04-05 don't support native YV12, only YUY2 and ITU-R BT.601)
1437 *action_flags |= CONVERT_TO_YUY2;
1439 if ( pNv->Architecture == NV_ARCH_10 || pNv->Architecture == NV_ARCH_20 )
1441 switch ( pNv->Chipset & 0xfff0 )
1446 case CHIPSET_NFORCE: /*XXX: unsure about nforce and nforce2*/
1447 case CHIPSET_NFORCE2:
1448 case CHIPSET_NV20: /*reported by pq - in fact all cards older than geforce4 ti probably don't have YV12 overlay*/
1449 *action_flags |= CONVERT_TO_YUY2; break;
1460 * PutImage is "the" important function of the Xv extension.
1461 * a client (e.g. video player) calls this function for every
1462 * image (of the video) to be displayed. this function then
1463 * scales and displays the image.
1465 * @param pScrn screen which hold the port where the image is put
1466 * @param src_x source point in the source image to start displaying from
1467 * @param src_y see above
1468 * @param src_w width of the source image to display
1469 * @param src_h see above
1470 * @param drw_x screen point to display to
1472 * @param drw_w width of the screen drawable
1474 * @param id pixel format of image
1475 * @param buf pointer to buffer containing the source image
1476 * @param width total width of the source image we are passed
1478 * @param Sync unused
1479 * @param clipBoxes ??
1480 * @param data pointer to port
1481 * @param pDraw drawable pointer
1484 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
1485 short drw_x, short drw_y,
1486 short src_w, short src_h,
1487 short drw_w, short drw_h,
1490 short width, short height,
1491 Bool Sync, /*FIXME: need to honor the Sync*/
1492 RegionPtr clipBoxes,
1497 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1498 NVPtr pNv = NVPTR(pScrn);
1499 INT32 xa = 0, xb = 0, ya = 0, yb = 0; //source box
1500 int newFBSize = 0, newTTSize = 0; //size to allocate in VRAM and in GART respectively
1501 int offset = 0, s2offset = 0, s3offset = 0; //card VRAM offset, source offsets for U and V planes
1502 int srcPitch = 0, srcPitch2 = 0, dstPitch = 0; //source pitch, source pitch of U and V planes in case of YV12, VRAM destination pitch
1503 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
1507 int line_len = 0; //length of a line, like npixels, but in bytes
1508 int DMAoffset = 0; //additional VRAM offset to start the DMA copy to
1509 int UVDMAoffset = 0;
1510 struct nouveau_bo *destination_buffer = NULL;
1511 unsigned char * video_mem_destination = NULL;
1512 int action_flags; //what shall we do?
1515 if (pPriv->grabbedByV4L)
1519 NV_set_action_flags(pNv, pScrn, pDraw, pPriv, id, &action_flags);
1521 if ( NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
1522 &src_x, &src_y, &src_w, &src_h,
1523 &drw_x, &drw_y, &drw_w, &drw_h,
1524 &left, &top, &right, &bottom, &dstBox,
1526 clipBoxes, width, height ) )
1532 if ( NV_calculate_pitches_and_mem_size(action_flags, &srcPitch, &srcPitch2, &dstPitch,
1533 &s2offset, &s3offset,
1534 & newFBSize, &newTTSize ,&line_len ,
1535 npixels, nlines, width, height) )
1537 return BadImplementation;
1540 /* There are some cases (tvtime with overscan for example) where the input image is larger (width/height) than
1541 the source rectangle for the overlay (src_w, src_h). In those cases, we try to do something optimal by uploading only
1542 the necessary data. */
1543 if ( action_flags & IS_YUY2 || action_flags & IS_RGB )
1545 buf += (top * srcPitch) + left;
1546 DMAoffset += left + (top * dstPitch);
1549 if ( action_flags & IS_YV12 )
1551 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1555 if ( action_flags & CONVERT_TO_YUY2 )
1557 DMAoffset += (left << 1) + (top * dstPitch);
1562 //real YV12 - we offset only the luma plane, and copy the whole color plane, for easiness
1563 DMAoffset += left + (top * dstPitch);
1564 UVDMAoffset += left + (top >> 1) * dstPitch;
1568 pPriv->video_mem = NVAllocateVideoMemory(pScrn, pPriv->video_mem,
1570 if (!pPriv->video_mem)
1573 offset = pPriv->video_mem->offset;
1575 /*The overlay supports hardware double buffering. We handle this here*/
1576 if (pPriv->doubleBuffer) {
1577 int mask = 1 << (pPriv->currentBuffer << 2);
1578 /* overwrite the newest buffer if there's not one free */
1579 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1580 if (!pPriv->currentBuffer)
1581 offset += newFBSize >> 1;
1585 if (pPriv->currentBuffer)
1586 offset += newFBSize >> 1;
1589 /*Now we take a decision regarding the way we send the data to the card.
1590 Either we use double buffering of "private" TT memory
1591 Either we rely on X's GARTScratch
1592 Either we fallback on CPU copy
1595 /* Try to allocate host-side double buffers, unless we have already failed*/
1596 /* We take only nlines * line_len bytes - that is, only the pixel data we are interested in - because the stuff in the GART is
1597 written contiguously */
1598 if ( pPriv -> currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1600 pPriv->TT_mem_chunk[0] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[0],
1602 if ( pPriv->TT_mem_chunk[0] )
1604 pPriv->TT_mem_chunk[1] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[1],
1607 if ( ! pPriv->TT_mem_chunk[1] )
1609 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1610 pPriv->TT_mem_chunk[0] = NULL;
1611 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1612 //xf86DrvMsg(0, X_INFO, "Alloc 1 failed\n");
1617 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1618 //xf86DrvMsg(0, X_INFO, "Alloc 0 failed\n");
1622 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1623 { //if we have a private buffer
1624 destination_buffer = pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1625 //xf86DrvMsg(0, X_INFO, "Using private mem chunk #%d\n", pPriv->currentHostBuffer);
1627 /* We know where we are going to write, but we are not sure yet whether we can do it directly, because
1628 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.
1629 If we do, then we must wait for it before overwriting the buffer.
1630 Else we need one, so we call the Xv notifier allocator.*/
1631 if ( pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1633 //xf86DrvMsg(0, X_INFO, "Waiting for notifier %p (%d)\n", pPriv->DMANotifier[pPriv->currentHostBuffer], pPriv->currentHostBuffer);
1634 if (nouveau_notifier_wait_status(pPriv->DMANotifier[pPriv->currentHostBuffer], 0, 0, 0))
1639 //xf86DrvMsg(0, X_INFO, "Allocating notifier...\n");
1640 pPriv->DMANotifier [ pPriv->currentHostBuffer ] = NVXvDMANotifierAlloc(pScrn);
1641 if (! pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1642 { /* 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.
1643 I know that's a lot of code but I believe it's necessary to properly handle all the cases*/
1644 xf86DrvMsg(0, X_ERROR, "Ran out of Xv notifiers!\n");
1645 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1646 pPriv->TT_mem_chunk[0] = NULL;
1647 nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
1648 pPriv->TT_mem_chunk[1] = NULL;
1649 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1651 //xf86DrvMsg(0, X_INFO, "Got notifier %p\n", pPriv->DMANotifier [ pPriv->currentHostBuffer ]);
1655 if ( pPriv -> currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE )
1656 { //otherwise we fall back on DDX's GARTScratch
1657 destination_buffer = pNv->GART;
1658 //xf86DrvMsg(0, X_INFO, "Using global GART memory chunk\n");
1661 if ( !destination_buffer) //if we have no GART at all
1664 if(newTTSize <= destination_buffer->size)
1666 unsigned char *dst = destination_buffer->map;
1669 /* Upload to GART */
1670 if ( action_flags & IS_YV12)
1672 if ( action_flags & CONVERT_TO_YUY2 )
1674 NVCopyData420(buf + (top * srcPitch) + left,
1675 buf + s2offset, buf + s3offset,
1676 dst, srcPitch, srcPitch2,
1677 line_len, nlines, npixels);
1681 unsigned char * tbuf = buf + top * srcPitch + left;
1682 unsigned char * tdst = dst;
1683 //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);
1685 for ( i=0; i < nlines; i++)
1687 memcpy(tdst, tbuf, line_len);
1691 dst += line_len * nlines;
1692 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, dst, line_len, srcPitch2, nlines, line_len);
1697 for ( i=0; i < nlines; i++)
1699 memcpy(dst, buf, line_len);
1706 BEGIN_RING(NvMemFormat,
1707 NV_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
1708 OUT_RING (pNv->chan->gart->handle);
1709 OUT_RING (pNv->chan->vram->handle);
1712 if ( action_flags & IS_YV12 && ! (action_flags & CONVERT_TO_YUY2) )
1713 { /*we start the color plane transfer separately*/
1714 BEGIN_RING(NvMemFormat,
1715 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1716 OUT_RING ((uint32_t)destination_buffer->offset + line_len * nlines);
1717 OUT_RING ((uint32_t)offset + dstPitch * nlines);
1718 OUT_RING (line_len);
1719 OUT_RING (dstPitch);
1720 OUT_RING (line_len);
1721 OUT_RING ((nlines >> 1));
1722 OUT_RING ((1<<8)|1);
1727 BEGIN_RING(NvMemFormat,
1728 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1729 OUT_RING ((uint32_t)destination_buffer->offset);
1730 OUT_RING ((uint32_t)offset /*+ DMAoffset*/);
1731 OUT_RING (line_len);
1732 OUT_RING (dstPitch);
1733 OUT_RING (line_len);
1735 OUT_RING ((1<<8)|1);
1738 if ( destination_buffer == pNv->GART )
1740 nouveau_notifier_reset(pNv->notify0, 0);
1743 nouveau_notifier_reset(pPriv->DMANotifier[pPriv->currentHostBuffer], 0);
1744 BEGIN_RING(NvMemFormat,
1745 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1746 OUT_RING (pPriv->DMANotifier[pPriv->currentHostBuffer]->handle);
1750 BEGIN_RING(NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1753 BEGIN_RING(NvMemFormat, 0x100, 1);
1756 //Put back NvDmaNotifier0 for EXA
1757 BEGIN_RING(NvMemFormat,
1758 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1759 OUT_RING (pNv->notify0->handle);
1763 if ( destination_buffer == pNv->GART )
1764 if (nouveau_notifier_wait_status(pNv->notify0, 0, 0, 0))
1767 else { //GART is too small, we fallback on CPU copy
1769 video_mem_destination = pPriv->video_mem->map + (offset - (uint32_t)pPriv->video_mem->offset);
1771 if ( action_flags & IS_YV12 )
1773 if ( action_flags & CONVERT_TO_YUY2 )
1775 NVCopyData420(buf + (top * srcPitch) + left,
1776 buf + s2offset, buf + s3offset,
1777 video_mem_destination, srcPitch, srcPitch2,
1778 dstPitch, nlines, npixels);
1781 unsigned char * tbuf = buf + left + top * srcPitch;
1782 for ( i=0; i < nlines; i++)
1784 int dwords = npixels << 1;
1785 while (dwords & ~0x03)
1787 *video_mem_destination = *tbuf;
1788 *(video_mem_destination + 1) = *(tbuf + 1);
1789 *(video_mem_destination + 2) = *(tbuf + 2);
1790 *(video_mem_destination + 3) = *(tbuf + 3);
1791 video_mem_destination += 4;
1798 *(video_mem_destination + 2) = *(tbuf + 2);
1800 *(video_mem_destination + 1) = *(tbuf + 1);
1802 *video_mem_destination = *tbuf;
1805 video_mem_destination += dstPitch - (npixels << 1);
1806 tbuf += srcPitch - (npixels << 1);
1809 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, video_mem_destination, dstPitch, srcPitch2, nlines, line_len);
1814 for ( i=0; i < nlines; i++)
1816 int dwords = npixels << 1;
1817 while (dwords & ~0x03)
1819 *video_mem_destination = *buf;
1820 *(video_mem_destination + 1) = *(buf + 1);
1821 *(video_mem_destination + 2) = *(buf + 2);
1822 *(video_mem_destination + 3) = *(buf + 3);
1823 video_mem_destination += 4;
1830 *(video_mem_destination + 2) = *(buf + 2);
1832 *(video_mem_destination + 1) = *(buf + 1);
1834 *video_mem_destination = *buf;
1837 video_mem_destination += dstPitch - (npixels << 1);
1838 buf += srcPitch - (npixels << 1);
1846 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1847 pPriv->currentHostBuffer ^= 1;
1849 if ( action_flags & USE_OVERLAY )
1851 if ( pNv->Architecture == NV_ARCH_04 )
1852 NV04PutOverlayImage(pScrn, offset, id,
1856 src_w, src_h, drw_w, drw_h,
1859 NVPutOverlayImage(pScrn, offset, ((action_flags & IS_YUY2) || (action_flags & CONVERT_TO_YUY2)) ? 0 : offset + nlines * dstPitch, id,
1863 src_w, src_h, drw_w, drw_h,
1865 pPriv->currentBuffer ^= 1;
1870 NVPutBlitImage(pScrn, offset, id,
1874 src_w, src_h, drw_w, drw_h,
1882 * QueryImageAttributes
1885 * - size (memory required to store image),
1889 * depending on colorspace (id) and dimensions (w,h) of image
1893 * may be adjusted as needed
1895 * @param pScrn unused
1896 * @param id colorspace of image
1897 * @param w pointer to width of image
1898 * @param h pointer to height of image
1899 * @param pitches pitches[i] = length of a scanline in plane[i]
1900 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1901 * @return size of the memory required for the XvImage queried
1904 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1905 unsigned short *w, unsigned short *h,
1906 int *pitches, int *offsets)
1910 if (*w > IMAGE_MAX_W)
1912 if (*h > IMAGE_MAX_H)
1915 *w = (*w + 1) & ~1; // width rounded up to an even number
1922 *h = (*h + 1) & ~1; // height rounded up to an even number
1923 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1925 pitches[0] = size; // width rounded up to a multiple of 4
1928 offsets[1] = size; // number of pixels in "rounded up" image
1929 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1931 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1932 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1933 size += tmp; // 5/4*number of pixels in "rounded up" image
1935 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1936 size += tmp; // = 3/2*number of pixels in "rounded up" image
1940 size = *w << 1; // 2*width
1942 pitches[0] = size; // 2*width
1943 size *= *h; // 2*width*height
1946 size = *w << 2; // 4*width (32 bit per pixel)
1948 pitches[0] = size; // 4*width
1949 size *= *h; // 4*width*height
1959 /***** Exported offscreen surface stuff ****/
1963 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1964 unsigned short w, unsigned short h,
1965 XF86SurfacePtr surface)
1967 NVPtr pNv = NVPTR(pScrn);
1968 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1971 bpp = pScrn->bitsPerPixel >> 3;
1973 if (pPriv->grabbedByV4L)
1976 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1980 pPriv->pitch = ((w << 1) + 63) & ~63;
1981 size = h * pPriv->pitch / bpp;
1983 pPriv->video_mem = NVAllocateVideoMemory(pScrn,
1986 if (!pPriv->video_mem)
1992 surface->height = h;
1993 surface->pScrn = pScrn;
1994 surface->pitches = &pPriv->pitch;
1995 surface->offsets = &pPriv->offset;
1996 surface->devPrivate.ptr = (pointer)pPriv;
1999 /* grab the video */
2000 NVStopOverlay(pScrn);
2001 pPriv->videoStatus = 0;
2002 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
2003 pPriv->grabbedByV4L = TRUE;
2009 NVStopSurface(XF86SurfacePtr surface)
2011 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
2013 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
2014 NVStopOverlay(surface->pScrn);
2015 pPriv->videoStatus = 0;
2022 NVFreeSurface(XF86SurfacePtr surface)
2024 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
2026 if (pPriv->grabbedByV4L) {
2027 NVStopSurface(surface);
2028 NVFreeOverlayMemory(surface->pScrn);
2029 pPriv->grabbedByV4L = FALSE;
2036 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
2038 NVPtr pNv = NVPTR(pScrn);
2039 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
2041 return NVGetOverlayPortAttribute(pScrn, attribute,
2042 value, (pointer)pPriv);
2046 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
2048 NVPtr pNv = NVPTR(pScrn);
2049 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
2051 return NVSetOverlayPortAttribute(pScrn, attribute,
2052 value, (pointer)pPriv);
2056 NVDisplaySurface(XF86SurfacePtr surface,
2057 short src_x, short src_y,
2058 short drw_x, short drw_y,
2059 short src_w, short src_h,
2060 short drw_w, short drw_h,
2061 RegionPtr clipBoxes)
2063 ScrnInfoPtr pScrn = surface->pScrn;
2064 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
2065 INT32 xa, xb, ya, yb;
2068 if (!pPriv->grabbedByV4L)
2071 if (src_w > (drw_w << 3))
2073 if (src_h > (drw_h << 3))
2083 dstBox.x2 = drw_x + drw_w;
2085 dstBox.y2 = drw_y + drw_h;
2087 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
2088 surface->width, surface->height))
2091 dstBox.x1 -= pScrn->frameX0;
2092 dstBox.x2 -= pScrn->frameX0;
2093 dstBox.y1 -= pScrn->frameY0;
2094 dstBox.y2 -= pScrn->frameY0;
2096 pPriv->currentBuffer = 0;
2098 NVPutOverlayImage(pScrn, surface->offsets[0], 0, surface->id,
2099 surface->pitches[0], &dstBox, xa, ya, xb, yb,
2100 surface->width, surface->height, src_w, src_h,
2101 drw_w, drw_h, clipBoxes);
2108 * this function does all the work setting up a blit port
2112 static XF86VideoAdaptorPtr
2113 NVSetupBlitVideo (ScreenPtr pScreen)
2115 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2116 NVPtr pNv = NVPTR(pScrn);
2117 XF86VideoAdaptorPtr adapt;
2118 NVPortPrivPtr pPriv;
2121 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2122 sizeof(NVPortPrivRec) +
2123 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
2127 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2129 adapt->name = "NV Video Blitter";
2130 adapt->nEncodings = 1;
2131 adapt->pEncodings = &DummyEncoding;
2132 adapt->nFormats = NUM_FORMATS_ALL;
2133 adapt->pFormats = NVFormats;
2134 adapt->nPorts = NUM_BLIT_PORTS;
2135 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2137 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
2138 for(i = 0; i < NUM_BLIT_PORTS; i++)
2139 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2141 if(pNv->WaitVSyncPossible) {
2142 adapt->pAttributes = NVBlitAttributes;
2143 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
2145 adapt->pAttributes = NULL;
2146 adapt->nAttributes = 0;
2149 adapt->pImages = NVImages;
2150 adapt->nImages = NUM_IMAGES_ALL;
2151 adapt->PutVideo = NULL;
2152 adapt->PutStill = NULL;
2153 adapt->GetVideo = NULL;
2154 adapt->GetStill = NULL;
2155 adapt->StopVideo = NVStopBlitVideo;
2156 adapt->SetPortAttribute = NVSetBlitPortAttribute;
2157 adapt->GetPortAttribute = NVGetBlitPortAttribute;
2158 adapt->QueryBestSize = NVQueryBestSize;
2159 adapt->PutImage = NVPutImage;
2160 adapt->QueryImageAttributes = NVQueryImageAttributes;
2162 pPriv->videoStatus = 0;
2163 pPriv->grabbedByV4L = FALSE;
2164 pPriv->blitter = TRUE;
2165 pPriv->doubleBuffer = FALSE;
2166 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
2168 pNv->blitAdaptor = adapt;
2169 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
2175 * NVSetupOverlayVideo
2176 * this function does all the work setting up an overlay port
2178 * @return overlay port
2179 * @see NVResetVideo(ScrnInfoPtr pScrn)
2181 static XF86VideoAdaptorPtr
2182 NVSetupOverlayVideoAdapter(ScreenPtr pScreen)
2184 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2185 NVPtr pNv = NVPTR(pScrn);
2186 XF86VideoAdaptorPtr adapt;
2187 NVPortPrivPtr pPriv;
2189 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2190 sizeof(NVPortPrivRec) +
2191 sizeof(DevUnion)))) {
2195 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2196 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
2197 adapt->name = "NV Video Overlay";
2198 adapt->nEncodings = 1;
2199 adapt->pEncodings = &DummyEncoding;
2200 adapt->nFormats = NUM_FORMATS_ALL;
2201 adapt->pFormats = NVFormats;
2203 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2205 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
2206 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
2208 adapt->pAttributes = (pNv->Architecture != NV_ARCH_04) ? NVOverlayAttributes : NV04OverlayAttributes;
2209 adapt->nAttributes = (pNv->Architecture != NV_ARCH_04) ? NUM_OVERLAY_ATTRIBUTES : NUM_NV04_OVERLAY_ATTRIBUTES;
2210 adapt->pImages = NVImages;
2211 adapt->nImages = NUM_IMAGES_YUV;
2212 adapt->PutVideo = NULL;
2213 adapt->PutStill = NULL;
2214 adapt->GetVideo = NULL;
2215 adapt->GetStill = NULL;
2216 adapt->StopVideo = NVStopOverlayVideo;
2217 adapt->SetPortAttribute = NVSetOverlayPortAttribute;
2218 adapt->GetPortAttribute = NVGetOverlayPortAttribute;
2219 adapt->QueryBestSize = NVQueryBestSize;
2220 adapt->PutImage = NVPutImage;
2221 adapt->QueryImageAttributes = NVQueryImageAttributes;
2223 pPriv->videoStatus = 0;
2224 pPriv->currentBuffer = 0;
2225 pPriv->grabbedByV4L = FALSE;
2226 pPriv->blitter = FALSE;
2227 if ( pNv->Architecture == NV_ARCH_04 )
2228 pPriv->doubleBuffer = 0;
2230 NVSetPortDefaults (pScrn, pPriv);
2232 /* gotta uninit this someplace */
2233 REGION_NULL(pScreen, &pPriv->clip);
2235 pNv->overlayAdaptor = adapt;
2237 xvColorKey = MAKE_ATOM("XV_COLORKEY");
2238 if ( pNv->Architecture != NV_ARCH_04 )
2240 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
2241 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
2242 xvContrast = MAKE_ATOM("XV_CONTRAST");
2243 xvSaturation = MAKE_ATOM("XV_SATURATION");
2244 xvHue = MAKE_ATOM("XV_HUE");
2245 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
2246 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
2247 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
2250 NVResetVideo(pScrn);
2256 XF86OffscreenImageRec NVOffscreenImages[2] = {
2259 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2264 NVGetSurfaceAttribute,
2265 NVSetSurfaceAttribute,
2266 IMAGE_MAX_W, IMAGE_MAX_H,
2267 NUM_OVERLAY_ATTRIBUTES - 1,
2268 &NVOverlayAttributes[1]
2272 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2277 NVGetSurfaceAttribute,
2278 NVSetSurfaceAttribute,
2279 IMAGE_MAX_W, IMAGE_MAX_H,
2280 NUM_OVERLAY_ATTRIBUTES - 1,
2281 &NVOverlayAttributes[1]
2286 NVInitOffscreenImages (ScreenPtr pScreen)
2288 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
2292 * NVChipsetHasOverlay
2294 * newer chips don't support overlay anymore.
2295 * overlay feature is emulated via textures.
2298 * @return true, if chipset supports overlay
2301 NVChipsetHasOverlay(NVPtr pNv)
2303 switch (pNv->Architecture) {
2304 case NV_ARCH_04: /*NV04 has a different overlay than NV10+*/
2310 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
2321 * NVSetupOverlayVideo
2322 * check if chipset supports Overlay and CompositeExtension is disabled.
2323 * if so, setup overlay port
2325 * @return overlay port
2326 * @see NVChipsetHasOverlay(NVPtr pNv)
2327 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
2328 * @see NVInitOffscreenImages(ScreenPtr pScreen)
2330 static XF86VideoAdaptorPtr
2331 NVSetupOverlayVideo(ScreenPtr pScreen)
2333 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2334 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2335 NVPtr pNv = NVPTR(pScrn);
2337 if (!NVChipsetHasOverlay(pNv))
2340 overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen);
2341 if (overlayAdaptor && pNv->Architecture != NV_ARCH_04 )
2342 NVInitOffscreenImages(pScreen); //I am not sure what this call does.
2345 if (!noCompositeExtension) {
2346 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2347 "XV: Composite is enabled, enabling overlay with smart blitter fallback\n");
2348 overlayAdaptor -> name = "NV Video Overlay with Composite";
2352 return overlayAdaptor;
2357 * tries to initialize one new overlay port and one new blit port
2358 * and add them to the list of ports on screen "pScreen".
2361 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
2362 * @see NVSetupBlitVideo(ScreenPtr pScreen)
2364 void NVInitVideo (ScreenPtr pScreen)
2366 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2367 NVPtr pNv = NVPTR(pScrn);
2368 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
2369 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2370 XF86VideoAdaptorPtr blitAdaptor = NULL;
2374 * Driving the blitter requires the DMA FIFO. Using the FIFO
2375 * without accel causes DMA errors. While the overlay might
2376 * might work without accel, we also disable it for now when
2377 * acceleration is disabled:
2379 if (pScrn->bitsPerPixel != 8 && pNv->Architecture < NV_ARCH_50 && !pNv->NoAccel) {
2380 overlayAdaptor = NVSetupOverlayVideo(pScreen);
2381 blitAdaptor = NVSetupBlitVideo(pScreen);
2384 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
2385 if(blitAdaptor || overlayAdaptor) {
2386 int size = num_adaptors;
2388 if(overlayAdaptor) size++;
2389 if(blitAdaptor) size++;
2391 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
2394 memcpy(newAdaptors, adaptors, num_adaptors *
2395 sizeof(XF86VideoAdaptorPtr));
2398 if(overlayAdaptor) {
2399 newAdaptors[num_adaptors] = overlayAdaptor;
2404 newAdaptors[num_adaptors] = blitAdaptor;
2408 adaptors = newAdaptors;
2413 xf86XVScreenInit(pScreen, adaptors, num_adaptors);