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;
83 struct nouveau_bo *video_mem;
86 struct nouveau_bo *TT_mem_chunk[2];
87 int currentHostBuffer;
88 struct nouveau_notifier *DMANotifier[2];
89 } NVPortPrivRec, *NVPortPrivPtr;
92 /* Xv DMA notifiers status tracing */
95 XV_DMA_NOTIFIER_NOALLOC=0, //notifier not allocated
96 XV_DMA_NOTIFIER_INUSE=1,
97 XV_DMA_NOTIFIER_FREE=2, //notifier allocated, ready for use
100 /* We have six notifiers available, they are not allocated at startup */
101 int XvDMANotifierStatus[6]= { XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC ,
102 XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC };
103 struct nouveau_notifier *XvDMANotifiers[6];
105 /* NVPutImage action flags */
113 IS_RGB=64, //I am not sure how long we will support it
116 #define GET_OVERLAY_PRIVATE(pNv) \
117 (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr)
119 #define GET_BLIT_PRIVATE(pNv) \
120 (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr)
122 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
124 static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
125 xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
126 xvITURBT709, xvSyncToVBlank, xvOnCRTCNb;
128 /* client libraries expect an encoding */
129 static XF86VideoEncodingRec DummyEncoding =
133 IMAGE_MAX_W, IMAGE_MAX_H,
137 #define NUM_FORMATS_ALL 6
139 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
141 {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
142 {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
145 #define NUM_NV04_OVERLAY_ATTRIBUTES 1
146 XF86AttributeRec NV04OverlayAttributes[NUM_NV04_OVERLAY_ATTRIBUTES] =
148 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
152 #define NUM_OVERLAY_ATTRIBUTES 10
153 XF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] =
155 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
156 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
157 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
158 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
159 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
160 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
161 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
162 {XvSettable | XvGettable, 0, 360, "XV_HUE"},
163 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"},
164 {XvSettable | XvGettable, 0, 1, "XV_ON_CRTC_NB"},
167 #define NUM_BLIT_ATTRIBUTES 2
168 XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
170 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
171 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
175 #define NUM_IMAGES_YUV 4
176 #define NUM_IMAGES_ALL 5
178 #define FOURCC_RGB 0x0000003
179 #define XVIMAGE_RGB \
184 { 0x03, 0x00, 0x00, 0x00, \
185 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
189 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
194 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}, \
198 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
208 NVWaitVSync(ScrnInfoPtr pScrn)
210 NVPtr pNv = NVPTR(pScrn);
212 BEGIN_RING(NvImageBlit, 0x0000012C, 1);
214 BEGIN_RING(NvImageBlit, 0x00000134, 1);
215 /* If crtc1 is active, this will produce one, otherwise zero */
216 /* The assumption is that at least one is active */
217 OUT_RING (pNv->crtc_active[1]);
218 BEGIN_RING(NvImageBlit, 0x00000100, 1);
220 BEGIN_RING(NvImageBlit, 0x00000130, 1);
226 * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
228 * @param pScrn screen to get the default colorKey from
229 * @param pPriv port to reset to defaults
232 NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
234 NVPtr pNv = NVPTR(pScrn);
236 pPriv->brightness = 0;
237 pPriv->contrast = 4096;
238 pPriv->saturation = 4096;
240 pPriv->colorKey = pNv->videoKey;
241 pPriv->autopaintColorKey = TRUE;
242 pPriv->doubleBuffer = TRUE;
243 pPriv->iturbt_709 = FALSE;
244 pPriv->currentHostBuffer = 0;
249 * writes the current attributes from the overlay port to the hardware
252 NVResetVideo (ScrnInfoPtr pScrn)
254 NVPtr pNv = NVPTR(pScrn);
255 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
256 int satSine, satCosine;
259 angle = (double)pPriv->hue * 3.1415927 / 180.0;
261 satSine = pPriv->saturation * sin(angle);
264 satCosine = pPriv->saturation * cos(angle);
265 if (satCosine < -1024)
268 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
270 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
272 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
273 (satCosine & 0xffff));
274 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
275 (satCosine & 0xffff));
276 nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
281 * Tell the hardware to stop the overlay
284 NVStopOverlay (ScrnInfoPtr pScrn)
286 NVPtr pNv = NVPTR(pScrn);
288 if ( pNv -> Architecture != NV_ARCH_04 )
289 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
292 nvWriteRAMDAC(pNv, 0, 0x244, nvReadRAMDAC(pNv, 0, 0x244) &~ 0x1);
293 nvWriteRAMDAC(pNv, 0, 0x224, 0);
294 nvWriteRAMDAC(pNv, 0, 0x228, 0);
295 nvWriteRAMDAC(pNv, 0, 0x22c, 0);
300 * NVXvDMANotifierAlloc
301 * allocates a notifier from the table of 6 we have
303 * @return a notifier instance or NULL on error
305 static struct nouveau_notifier *
306 NVXvDMANotifierAlloc(ScrnInfoPtr pScrn)
308 NVPtr pNv = NVPTR(pScrn);
311 for (i = 0; i < 6; i++) {
312 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_INUSE)
315 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_FREE) {
316 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
317 return XvDMANotifiers[i];
320 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_NOALLOC) {
321 if (nouveau_notifier_alloc(pNv->chan,
322 NvDmaXvNotifier0 + i,
323 1, &XvDMANotifiers[i]))
325 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
326 return XvDMANotifiers[i];
334 * NVXvDMANotifierFree
335 * frees a notifier from the table of 6 we have
340 NVXvDMANotifierFree(ScrnInfoPtr pScrn, struct nouveau_notifier *target)
343 for ( i = 0; i < 6; i ++ )
345 if ( XvDMANotifiers[i] == target )
348 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_FREE;
352 * NVAllocateVideoMemory
353 * allocates video memory for a given port
355 * @param pScrn screen which requests the memory
356 * @param mem pointer to previously allocated memory for reallocation
357 * @param size size of requested memory segment
358 * @return pointer to the allocated memory
360 static struct nouveau_bo *
361 NVAllocateVideoMemory(ScrnInfoPtr pScrn, struct nouveau_bo *mem, int size)
363 NVPtr pNv = NVPTR(pScrn);
364 struct nouveau_bo *bo = NULL;
367 if(mem->size >= size)
369 nouveau_bo_del(&mem);
372 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN, 0,
376 if (nouveau_bo_map(bo, NOUVEAU_BO_RDWR)) {
386 * allocates TT memory for a given port
388 * @param pScrn screen which requests the memory
389 * @param mem pointer to previously allocated memory for reallocation
390 * @param size size of requested memory segment
391 * @return pointer to the allocated memory
393 static struct nouveau_bo *
394 NVAllocateTTMemory(ScrnInfoPtr pScrn, struct nouveau_bo *mem, int size)
396 NVPtr pNv = NVPTR(pScrn);
397 struct nouveau_bo *bo = NULL;
400 if(mem->size >= size)
402 nouveau_bo_del(&mem);
405 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_GART | NOUVEAU_BO_PIN, 0,
409 if (nouveau_bo_map(bo, NOUVEAU_BO_RDWR)) {
419 * frees memory held by a given port
421 * @param pScrn screen whose port wants to free memory
422 * @param pPriv port to free memory of
425 NVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
427 //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]);
429 if(pPriv->video_mem) {
430 nouveau_bo_del(&pPriv->video_mem);
431 pPriv->video_mem = NULL;
434 if ( pPriv->TT_mem_chunk[ 0 ] && pPriv->DMANotifier [ 0 ] )
436 nouveau_notifier_wait_status(pPriv->DMANotifier[0], 0, 0, 1000);
439 if ( pPriv->TT_mem_chunk[ 1 ] && pPriv->DMANotifier [ 1 ] )
441 nouveau_notifier_wait_status(pPriv->DMANotifier[1], 0, 0, 1000);
444 if(pPriv->TT_mem_chunk[0]) {
445 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
446 pPriv->TT_mem_chunk[0] = NULL;
449 if(pPriv->TT_mem_chunk[1]) {
450 nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
451 pPriv->TT_mem_chunk[1] = NULL;
454 if(pPriv->DMANotifier[0]) {
455 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[0]);
456 pPriv->DMANotifier[0] = NULL;
459 if(pPriv->DMANotifier[1]) {
460 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[1]);
461 pPriv->DMANotifier[1] = NULL;
467 * NVFreeOverlayMemory
468 * frees memory held by the overlay port
470 * @param pScrn screen whose overlay port wants to free memory
473 NVFreeOverlayMemory(ScrnInfoPtr pScrn)
475 NVPtr pNv = NVPTR(pScrn);
476 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
477 NVFreePortMemory(pScrn, pPriv);
478 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) & 0xEFFFFFFF));
479 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) | 0x10000000));
484 * frees memory held by the blit port
486 * @param pScrn screen whose blit port wants to free memory
489 NVFreeBlitMemory(ScrnInfoPtr pScrn)
491 NVPtr pNv = NVPTR(pScrn);
492 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
493 NVFreePortMemory(pScrn, pPriv);
497 * NVVideoTimerCallback
498 * callback function which perform cleanup tasks (stop overlay, free memory).
499 * within the driver it is only called once from NVBlockHandler in nv_driver.c
502 NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
504 NVPtr pNv = NVPTR(pScrn);
505 NVPortPrivPtr pOverPriv = NULL;
506 NVPortPrivPtr pBlitPriv = NULL;
507 Bool needCallback = FALSE;
512 if (pNv->overlayAdaptor) {
513 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
514 if (!pOverPriv->videoStatus)
518 if (pNv->blitAdaptor) {
519 pBlitPriv = GET_BLIT_PRIVATE(pNv);
520 if (!pBlitPriv->videoStatus)
525 if (pOverPriv->videoTime < currentTime) {
526 if (pOverPriv->videoStatus & OFF_TIMER) {
527 NVStopOverlay(pScrn);
528 pOverPriv->videoStatus = FREE_TIMER;
529 pOverPriv->videoTime = currentTime + FREE_DELAY;
532 if (pOverPriv->videoStatus & FREE_TIMER) {
533 NVFreeOverlayMemory(pScrn);
534 pOverPriv->videoStatus = 0;
542 if (pBlitPriv->videoTime < currentTime) {
543 NVFreeBlitMemory(pScrn);
544 pBlitPriv->videoStatus = 0;
550 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
555 * program hardware to overlay image into front buffer
557 * @param pScrn screen
558 * @param offset card offset to the pixel data
559 * @param id format of image
560 * @param dstPitch pitch of the pixel data in VRAM
561 * @param dstBox destination box
562 * @param x1 first source point - x
563 * @param y1 first source point - y
564 * @param x2 second source point - x
565 * @param y2 second source point - y
566 * @param width width of the source image = x2 - x1
567 * @param height height
568 * @param src_w width of the image data in VRAM
569 * @param src_h height
570 * @param drw_w width of the image to draw to screen
571 * @param drw_h height
572 * @param clipBoxes ???
575 NVPutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
576 int dstPitch, BoxPtr dstBox,
577 int x1, int y1, int x2, int y2,
578 short width, short height,
579 short src_w, short src_h,
580 short drw_w, short drw_h,
583 NVPtr pNv = NVPTR(pScrn);
584 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
585 int buffer = pPriv->currentBuffer;
587 /* paint the color key */
588 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
589 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
590 /* we always paint V4L's color key */
591 if (!pPriv->grabbedByV4L)
592 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
594 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
598 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
604 //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));
606 nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer) , 0);
607 nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer) , offset);
608 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer) , (height << 16) | width);
609 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
610 ((y1 << 4) & 0xffff0000) | (x1 >> 12));
611 nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer) , (src_w << 20) / drw_w);
612 nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer) , (src_h << 20) / drw_h);
613 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
614 (dstBox->y1 << 16) | dstBox->x1);
615 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
616 ((dstBox->y2 - dstBox->y1) << 16) |
617 (dstBox->x2 - dstBox->x1));
619 dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; /* use color key */
620 if(id != FOURCC_UYVY)
621 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
622 if(pPriv->iturbt_709)
623 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
625 if( id == FOURCC_YV12 || id == FOURCC_I420 )
626 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
628 /* Those are important only for planar formats (NV12) */
631 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_BASE(buffer), 0);
632 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer), uvoffset);
635 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
636 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
637 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
639 pPriv->videoStatus = CLIENT_VIDEO_ON;
643 NV04PutOverlayImage(ScrnInfoPtr pScrn, int offset, int id,
644 int dstPitch, BoxPtr dstBox,
645 int x1, int y1, int x2, int y2,
646 short width, short height,
647 short src_w, short src_h,
648 short drw_w, short drw_h,
651 NVPtr pNv = NVPTR(pScrn);
652 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
654 /* paint the color key */
655 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
656 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
657 /* we always paint V4L's color key */
658 if (!pPriv->grabbedByV4L)
659 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
661 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
665 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) { /*This may not work with NV04 overlay according to rivatv source*/
671 /* NV_PVIDEO_OE_STATE */
672 /* NV_PVIDEO_SU_STATE */
673 /* NV_PVIDEO_RM_STATE */
674 nvWriteRAMDAC(pNv, 0, 0x224, 0);
675 nvWriteRAMDAC(pNv, 0, 0x228, 0);
676 nvWriteRAMDAC(pNv, 0, 0x22c, 0);
678 /* NV_PVIDEO_BUFF0_START_ADDRESS */
679 nvWriteRAMDAC(pNv, 0, 0x20C, offset);
680 nvWriteRAMDAC(pNv, 0, 0x20C + 4, offset);
681 /* NV_PVIDEO_BUFF0_PITCH_LENGTH */
682 nvWriteRAMDAC(pNv, 0, 0x214, dstPitch);
683 nvWriteRAMDAC(pNv, 0, 0x214 + 4, dstPitch);
685 /* NV_PVIDEO_BUFF0_OFFSET */
686 nvWriteRAMDAC(pNv, 0, 0x21C, 0);
687 nvWriteRAMDAC(pNv, 0, 0x21C + 4, 0);
689 /* NV_PVIDEO_WINDOW_START */
690 nvWriteRAMDAC(pNv, 0, 0x230, (dstBox->y1 << 16) | dstBox->x1);
691 /* NV_PVIDEO_WINDOW_SIZE */
692 nvWriteRAMDAC(pNv, 0, 0x234, ((dstBox->y2 - dstBox->y1) << 16) |
693 (dstBox->x2 - dstBox->x1));
694 /* NV_PVIDEO_STEP_SIZE */
695 nvWriteRAMDAC(pNv, 0, 0x200, (uint32_t)(((src_h - 1) << 11) / (drw_h - 1)) << 16 | (uint32_t)(((src_w - 1) << 11) / (drw_w - 1)));
697 /* NV_PVIDEO_RED_CSC_OFFSET */
698 /* NV_PVIDEO_GREEN_CSC_OFFSET */
699 /* NV_PVIDEO_BLUE_CSC_OFFSET */
700 /* NV_PVIDEO_CSC_ADJUST */
701 nvWriteRAMDAC(pNv, 0, 0x280, 0x69);
702 nvWriteRAMDAC(pNv, 0, 0x284, 0x3e);
703 nvWriteRAMDAC(pNv, 0, 0x288, 0x89);
704 nvWriteRAMDAC(pNv, 0, 0x28C, 0x0);
706 /* NV_PVIDEO_CONTROL_Y (BLUR_ON, LINE_HALF) */
707 nvWriteRAMDAC(pNv, 0, 0x204, 0x001);
708 /* NV_PVIDEO_CONTROL_X (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */
709 nvWriteRAMDAC(pNv, 0, 0x208, 0x111);
711 /* NV_PVIDEO_FIFO_BURST_LENGTH */
712 nvWriteRAMDAC(pNv, 0, 0x23C, 0x03);
713 /* NV_PVIDEO_FIFO_THRES_SIZE */
714 nvWriteRAMDAC(pNv, 0, 0x238, 0x38);
717 nvWriteRAMDAC(pNv, 0, 0x240, pPriv->colorKey);
723 nvWriteRAMDAC(pNv, 0, 0x244, 0x111);
725 /* NV_PVIDEO_SU_STATE */
726 nvWriteRAMDAC(pNv, 0, 0x228, (nvReadRAMDAC(pNv, 0, 0x228) ^ (1 << 16)));
728 pPriv->videoStatus = CLIENT_VIDEO_ON;
730 #ifndef ExaOffscreenMarkUsed
731 extern void ExaOffscreenMarkUsed(PixmapPtr);
733 #ifndef exaGetDrawablePixmap
734 extern PixmapPtr exaGetDrawablePixmap(DrawablePtr);
736 #ifndef exaPixmapIsOffscreen
737 extern Bool exaPixmapIsOffscreen(PixmapPtr p);
739 /* To support EXA 2.0, 2.1 has this in the header */
740 #ifndef exaMoveInPixmap
741 extern void exaMoveInPixmap(PixmapPtr pPixmap);
747 * @param pScrn screen
749 * @param id colorspace of image
766 NVPutBlitImage(ScrnInfoPtr pScrn, int src_offset, int id,
767 int src_pitch, BoxPtr dstBox,
768 int x1, int y1, int x2, int y2,
769 short width, short height,
770 short src_w, short src_h,
771 short drw_w, short drw_h,
775 NVPtr pNv = NVPTR(pScrn);
776 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
780 CARD32 dst_size, dst_point;
781 CARD32 src_point, src_format;
783 ScreenPtr pScreen = pScrn->pScreen;
784 PixmapPtr pPix = exaGetDrawablePixmap(pDraw);
787 /* Try to get the dest drawable into vram */
788 if (!exaPixmapIsOffscreen(pPix)) {
789 exaMoveInPixmap(pPix);
790 ExaOffscreenMarkUsed(pPix);
793 /* If we failed, draw directly onto the screen pixmap.
794 * Not sure if this is the best approach, maybe failing
795 * with BadAlloc would be better?
797 if (!exaPixmapIsOffscreen(pPix)) {
798 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
799 "XV: couldn't move dst surface into vram\n");
800 pPix = pScreen->GetScreenPixmap(pScreen);
803 NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format);
804 BEGIN_RING(NvContextSurfaces, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
805 OUT_RING (dst_format);
806 OUT_RING ((exaGetPixmapPitch(pPix) << 16) | exaGetPixmapPitch(pPix));
807 OUT_PIXMAPl(pPix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
808 OUT_PIXMAPl(pPix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
811 /* Adjust coordinates if drawing to an offscreen pixmap */
812 if (pPix->screen_x || pPix->screen_y) {
813 REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
816 dstBox->x1 -= pPix->screen_x;
817 dstBox->x2 -= pPix->screen_x;
818 dstBox->y1 -= pPix->screen_y;
819 dstBox->y2 -= pPix->screen_y;
822 DamageDamageRegion((DrawablePtr)pPix, clipBoxes);
825 pbox = REGION_RECTS(clipBoxes);
826 nbox = REGION_NUM_RECTS(clipBoxes);
828 dsdx = (src_w << 20) / drw_w;
829 dtdy = (src_h << 20) / drw_h;
831 dst_size = ((dstBox->y2 - dstBox->y1) << 16) |
832 (dstBox->x2 - dstBox->x1);
833 dst_point = (dstBox->y1 << 16) | dstBox->x1;
835 src_pitch |= (NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
836 NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_BILINEAR);
837 src_point = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
842 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
846 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_YB8V8YA8U8;
850 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_V8YB8U8YA8;
854 if(pPriv->SyncToVBlank) {
859 if(pNv->BlendingPossible) {
860 BEGIN_RING(NvScaledImage,
861 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 2);
862 OUT_RING (src_format);
863 OUT_RING (NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
865 BEGIN_RING(NvScaledImage,
866 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 2);
867 OUT_RING (src_format);
871 BEGIN_RING(NvRectangle,
872 NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
875 BEGIN_RING(NvScaledImage,
876 NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT, 6);
877 OUT_RING ((pbox->y1 << 16) | pbox->x1);
878 OUT_RING (((pbox->y2 - pbox->y1) << 16) |
879 (pbox->x2 - pbox->x1));
880 OUT_RING (dst_point);
885 BEGIN_RING(NvScaledImage,
886 NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
887 OUT_RING ((height << 16) | width);
888 OUT_RING (src_pitch);
889 OUT_RING (src_offset);
890 OUT_RING (src_point);
896 exaMarkSync(pScrn->pScreen);
898 pPriv->videoStatus = FREE_TIMER;
899 pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
900 pNv->VideoTimerCallback = NVVideoTimerCallback;
907 NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
909 NVPtr pNv = NVPTR(pScrn);
910 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
912 if(pPriv->grabbedByV4L) return;
914 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
917 if (pPriv->videoStatus & CLIENT_VIDEO_ON)
918 NVStopOverlay(pScrn);
919 NVFreeOverlayMemory(pScrn);
920 pPriv->videoStatus = 0;
922 if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
923 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
924 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
925 pNv->VideoTimerCallback = NVVideoTimerCallback;
934 NVStopBlitVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
939 * NVSetOverlayPortAttribute
940 * sets the attribute "attribute" of port "data" to value "value"
941 * calls NVResetVideo(pScrn) to apply changes to hardware
944 * @param attribute attribute to set
945 * @param value value to which attribute is to be set
946 * @param data port from which the attribute is to be set
948 * @return Success, if setting is successful
949 * BadValue/BadMatch, if value/attribute are invalid
950 * @see NVResetVideo(ScrnInfoPtr pScrn)
953 NVSetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
954 INT32 value, pointer data)
956 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
957 NVPtr pNv = NVPTR(pScrn);
959 if (attribute == xvBrightness) {
960 if ((value < -512) || (value > 512))
962 pPriv->brightness = value;
964 if (attribute == xvDoubleBuffer) {
965 if ((value < 0) || (value > 1))
967 pPriv->doubleBuffer = value;
969 if (attribute == xvContrast) {
970 if ((value < 0) || (value > 8191))
972 pPriv->contrast = value;
974 if (attribute == xvHue) {
980 if (attribute == xvSaturation) {
981 if ((value < 0) || (value > 8191))
983 pPriv->saturation = value;
985 if (attribute == xvColorKey) {
986 pPriv->colorKey = value;
987 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
989 if (attribute == xvAutopaintColorKey) {
990 if ((value < 0) || (value > 1))
992 pPriv->autopaintColorKey = value;
994 if (attribute == xvITURBT709) {
995 if ((value < 0) || (value > 1))
997 pPriv->iturbt_709 = value;
999 if (attribute == xvSetDefaults) {
1000 NVSetPortDefaults(pScrn, pPriv);
1002 if ( attribute == xvOnCRTCNb) {
1003 if ((value < 0) || (value > 1))
1005 pPriv->overlayCRTC = value;
1006 nvWriteCRTC(pNv, value, NV_CRTC_FSEL, nvReadCRTC(pNv, value, NV_CRTC_FSEL) | NV_CRTC_FSEL_OVERLAY);
1007 nvWriteCRTC(pNv, !value, NV_CRTC_FSEL, nvReadCRTC(pNv, !value, NV_CRTC_FSEL) & ~NV_CRTC_FSEL_OVERLAY);
1011 NVResetVideo(pScrn);
1016 * NVGetOverlayPortAttribute
1018 * @param pScrn unused
1019 * @param attribute attribute to be read
1020 * @param value value of attribute will be stored in this pointer
1021 * @param data port from which attribute will be read
1022 * @return Success, if queried attribute exists
1025 NVGetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1026 INT32 *value, pointer data)
1028 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1030 if (attribute == xvBrightness)
1031 *value = pPriv->brightness;
1032 else if (attribute == xvDoubleBuffer)
1033 *value = (pPriv->doubleBuffer) ? 1 : 0;
1034 else if (attribute == xvContrast)
1035 *value = pPriv->contrast;
1036 else if (attribute == xvSaturation)
1037 *value = pPriv->saturation;
1038 else if (attribute == xvHue)
1039 *value = pPriv->hue;
1040 else if (attribute == xvColorKey)
1041 *value = pPriv->colorKey;
1042 else if (attribute == xvAutopaintColorKey)
1043 *value = (pPriv->autopaintColorKey) ? 1 : 0;
1044 else if (attribute == xvITURBT709)
1045 *value = (pPriv->iturbt_709) ? 1 : 0;
1046 else if (attribute == xvOnCRTCNb)
1047 *value = (pPriv->overlayCRTC) ? 1 : 0;
1055 * NVSetBlitPortAttribute
1056 * sets the attribute "attribute" of port "data" to value "value"
1057 * supported attributes:
1058 * - xvSyncToVBlank (values: 0,1)
1059 * - xvSetDefaults (values: NA; SyncToVBlank will be set, if hardware supports it)
1062 * @param attribute attribute to set
1063 * @param value value to which attribute is to be set
1064 * @param data port from which the attribute is to be set
1066 * @return Success, if setting is successful
1067 * BadValue/BadMatch, if value/attribute are invalid
1070 NVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1071 INT32 value, pointer data)
1073 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1074 NVPtr pNv = NVPTR(pScrn);
1076 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
1077 if ((value < 0) || (value > 1))
1079 pPriv->SyncToVBlank = value;
1081 if (attribute == xvSetDefaults) {
1082 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1090 * NVGetBlitPortAttribute
1091 * reads the value of attribute "attribute" from port "data" into INT32 "*value"
1092 * currently only one attribute supported: xvSyncToVBlank
1094 * @param pScrn unused
1095 * @param attribute attribute to be read
1096 * @param value value of attribute will be stored here
1097 * @param data port from which attribute will be read
1098 * @return Success, if queried attribute exists
1101 NVGetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1102 INT32 *value, pointer data)
1104 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1106 if(attribute == xvSyncToVBlank)
1107 *value = (pPriv->SyncToVBlank) ? 1 : 0;
1117 * used by client applications to ask the driver:
1118 * how would you actually scale a video of dimensions
1119 * vid_w, vid_h, if i wanted you to scale it to dimensions
1121 * function stores actual scaling size in pointers p_w, p_h.
1124 * @param pScrn unused
1125 * @param motion unused
1126 * @param vid_w width of source video
1127 * @param vid_h height of source video
1128 * @param drw_w desired scaled width as requested by client
1129 * @param drw_h desired scaled height as requested by client
1130 * @param p_w actual scaled width as the driver is capable of
1131 * @param p_h actual scaled height as the driver is capable of
1132 * @param data unused
1135 NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
1136 short vid_w, short vid_h,
1137 short drw_w, short drw_h,
1138 unsigned int *p_w, unsigned int *p_h,
1141 if(vid_w > (drw_w << 3))
1143 if(vid_h > (drw_h << 3))
1152 * used to convert YV12 to YUY2 for the blitter
1154 * @param src1 source buffer of luma
1155 * @param src2 source buffer of chroma1
1156 * @param src3 source buffer of chroma2
1157 * @param dst1 destination buffer
1158 * @param srcPitch pitch of src1
1159 * @param srcPitch2 pitch of src2, src3
1160 * @param dstPitch pitch of dst1
1161 * @param h number of lines to copy
1162 * @param w length of lines to copy
1164 static inline void NVCopyData420(unsigned char *src1, unsigned char *src2,
1165 unsigned char *src3, unsigned char *dst1,
1166 int srcPitch, int srcPitch2,
1171 CARD8 *s1, *s2, *s3;
1176 for (j = 0; j < h; j++) {
1177 dst = (CARD32*)dst1;
1178 s1 = src1; s2 = src2; s3 = src3;
1182 #if X_BYTE_ORDER == X_BIG_ENDIAN
1183 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
1184 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1];
1185 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2];
1186 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3];
1188 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
1189 dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
1190 dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
1191 dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
1193 dst += 4; s2 += 4; s3 += 4; s1 += 8;
1198 #if X_BYTE_ORDER == X_BIG_ENDIAN
1199 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
1201 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
1217 * NVCopyNV12ColorPlanes
1218 * Used to convert YV12 color planes to NV12 (interleaved UV) for the overlay
1220 * @param src1 source buffer of chroma1
1221 * @param dst1 destination buffer
1222 * @param h number of lines to copy
1223 * @param w length of lines to copy
1224 * @param id source pixel format (YV12 or I420)
1226 static inline void NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char * src2, unsigned char *dst, int dstPitch, int srcPitch2,
1236 for ( j = 0; j < h; j++ )
1238 unsigned char * us = src1;
1239 unsigned char * vs = src2;
1240 unsigned int * vuvud = (unsigned int *) dst;
1241 for ( i = 0; i < l; i++ )
1243 #if X_BYTE_ORDER == X_BIG_ENDIAN
1244 *vuvud++ = (vs[0]<<24) | (us[0]<<16) | (vs[1]<<8) | us[1];
1246 *vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24);
1252 unsigned short *vud = (unsigned short *) vuvud;
1253 #if X_BYTE_ORDER == X_BIG_ENDIAN
1254 *vud = (vs[0]<<8) | (us[0] << 0);
1256 *vud = vs[0] | (us[0]<<8);
1267 static int NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 * xa, INT32 * xb, INT32 * ya, INT32 * yb,
1268 short * src_x, short * src_y, short * src_w, short * src_h,
1269 short * drw_x, short * drw_y, short * drw_w, short * drw_h,
1270 int * left, int * top, int * right, int * bottom,
1272 int * npixels, int * nlines,
1273 RegionPtr clipBoxes, short width, short height
1277 if ( action_flags & USE_OVERLAY )
1278 { /* overlay hardware scaler limitation - copied from nv, UNCHECKED*/
1279 if (*src_w > (*drw_w << 3))
1280 *drw_w = *src_w >> 3;
1281 if (*src_h > (*drw_h << 3))
1282 *drw_h = *src_h >> 3;
1288 *xb = *src_x + *src_w;
1290 *yb = *src_y + *src_h;
1292 dstBox->x1 = *drw_x;
1293 dstBox->x2 = *drw_x + *drw_w;
1294 dstBox->y1 = *drw_y;
1295 dstBox->y2 = *drw_y + *drw_h;
1297 if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
1301 if ( action_flags & USE_OVERLAY )
1303 dstBox->x1 -= pScrn->frameX0;
1304 dstBox->x2 -= pScrn->frameX0;
1305 dstBox->y1 -= pScrn->frameY0;
1306 dstBox->y2 -= pScrn->frameY0;
1311 /* Convert fixed point to integer, as xf86XVClipVideoHelper probably turns its parameter into fixed point values */
1312 *left = (*xa) >> 16;
1313 if (*left < 0) *left = 0;
1315 if (*top < 0) *top = 0;
1316 *right = (*xb) >> 16;
1317 if (*right > width) *right = width;
1318 *bottom = (*yb) >> 16;
1319 if (*bottom > height) *bottom = height;
1321 if ( action_flags & IS_YV12 )
1323 *left &= ~1; //even "left", even "top", even number of pixels per line and even number of lines
1324 *npixels = ((*right + 1) & ~1) - *left;
1326 *nlines = ((*bottom + 1) & ~1) - *top;
1328 else if ( action_flags & IS_YUY2 )
1330 *left &= ~1; //even "left"
1331 *npixels = ((*right + 1) & ~1) - *left; //even number of pixels per line
1332 *nlines = *bottom - *top;
1333 *left <<= 1; //16bpp
1335 else if (action_flags & IS_RGB )
1337 *npixels = *right - *left;
1338 *nlines = *bottom - *top;
1339 *left <<= 2; //32bpp
1345 static int NV_calculate_pitches_and_mem_size(int action_flags, int * srcPitch, int * srcPitch2, int * dstPitch,
1346 int * s2offset, int * s3offset,
1347 int * newFBSize, int * newTTSize,
1348 int * line_len, int npixels, int nlines, int width, int height)
1352 if ( action_flags & IS_YV12 )
1354 *srcPitch = (width + 3) & ~3; /* of luma */
1355 *s2offset = *srcPitch * height;
1356 *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
1357 *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
1358 *dstPitch = (npixels + 63) & ~63; /*luma and chroma pitch*/
1359 *line_len = npixels;
1360 *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1361 *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1363 else if ( action_flags & IS_YUY2 )
1365 *srcPitch = width << 1; /* one luma, one chroma per pixel */
1366 *dstPitch = ((npixels << 1) + 63) & ~63;
1367 *line_len = npixels << 1;
1368 *newFBSize = nlines * *dstPitch;
1369 *newTTSize = nlines * *line_len;
1371 else if ( action_flags & IS_RGB )
1373 *srcPitch = width << 2; /* one R, one G, one B, one X per pixel */
1374 *dstPitch = ((npixels << 2) + 63) & ~63;
1375 *line_len = npixels << 2;
1376 *newFBSize = nlines * *dstPitch;
1377 *newTTSize = nlines * *dstPitch;
1381 if ( action_flags & CONVERT_TO_YUY2 )
1383 *dstPitch = ((npixels << 1) + 63) & ~63;
1384 *line_len = npixels << 1;
1385 *newFBSize = nlines * *dstPitch;
1386 *newTTSize = nlines * *line_len;
1389 if ( action_flags & SWAP_UV )
1390 { //I420 swaps U and V
1392 *s2offset = *s3offset;
1396 if ( action_flags & USE_OVERLAY ) // overlay double buffering ...
1397 (*newFBSize) <<= 1; // ... means double the amount of VRAM needed
1404 * NV_set_action_flags
1405 * This function computes the action flags from the input image,
1406 * that is, it decides what NVPutImage and its helpers must do.
1407 * This eases readability by avoiding lots of switch-case statements in the core NVPutImage
1409 static void NV_set_action_flags(NVPtr pNv, ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, int id, int * action_flags)
1412 if ( id == FOURCC_YUY2 || id == FOURCC_UYVY )
1413 *action_flags |= IS_YUY2;
1415 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1416 *action_flags |= IS_YV12;
1418 if ( id == FOURCC_RGB ) /*How long will we support it?*/
1419 *action_flags |= IS_RGB;
1421 if ( id == FOURCC_I420 ) /*I420 is YV12 with swapped UV*/
1422 *action_flags |= SWAP_UV;
1424 if ( !pPriv -> blitter && !pPriv -> texture )
1425 *action_flags |= USE_OVERLAY;
1427 if ( !pPriv -> blitter && pPriv->texture )
1428 *action_flags |= USE_TEXTURE;
1431 WindowPtr pWin = NULL;
1433 if (!noCompositeExtension && WindowDrawable(pDraw->type))
1435 pWin = (WindowPtr)pDraw;
1439 if ( pWin->redirectDraw )
1440 *action_flags &= ~USE_OVERLAY;
1444 if ( !(*action_flags & USE_OVERLAY) && !(*action_flags & USE_TEXTURE) )
1446 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1447 { /*The blitter does not handle YV12 natively*/
1448 *action_flags |= CONVERT_TO_YUY2;
1452 if ( pNv->Architecture == NV_ARCH_04 )
1453 if ( * action_flags & IS_YV12 ) //NV04-05 don't support native YV12, only YUY2 and ITU-R BT.601)
1454 *action_flags |= CONVERT_TO_YUY2;
1456 if ( pNv->Architecture == NV_ARCH_10 || pNv->Architecture == NV_ARCH_20 )
1458 switch ( pNv->Chipset & 0xfff0 )
1463 case CHIPSET_NFORCE: /*XXX: unsure about nforce*/
1464 case CHIPSET_NV20: /*reported by pq - in fact all cards older than geforce4 ti probably don't have YV12 overlay*/
1465 *action_flags |= CONVERT_TO_YUY2; break;
1476 * PutImage is "the" important function of the Xv extension.
1477 * a client (e.g. video player) calls this function for every
1478 * image (of the video) to be displayed. this function then
1479 * scales and displays the image.
1481 * @param pScrn screen which hold the port where the image is put
1482 * @param src_x source point in the source image to start displaying from
1483 * @param src_y see above
1484 * @param src_w width of the source image to display
1485 * @param src_h see above
1486 * @param drw_x screen point to display to
1488 * @param drw_w width of the screen drawable
1490 * @param id pixel format of image
1491 * @param buf pointer to buffer containing the source image
1492 * @param width total width of the source image we are passed
1494 * @param Sync unused
1495 * @param clipBoxes ??
1496 * @param data pointer to port
1497 * @param pDraw drawable pointer
1500 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
1501 short drw_x, short drw_y,
1502 short src_w, short src_h,
1503 short drw_w, short drw_h,
1506 short width, short height,
1507 Bool Sync, /*FIXME: need to honor the Sync*/
1508 RegionPtr clipBoxes,
1513 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1514 NVPtr pNv = NVPTR(pScrn);
1515 INT32 xa = 0, xb = 0, ya = 0, yb = 0; //source box
1516 int newFBSize = 0, newTTSize = 0; //size to allocate in VRAM and in GART respectively
1517 int offset = 0, s2offset = 0, s3offset = 0; //card VRAM offset, source offsets for U and V planes
1518 int srcPitch = 0, srcPitch2 = 0, dstPitch = 0; //source pitch, source pitch of U and V planes in case of YV12, VRAM destination pitch
1519 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
1523 int line_len = 0; //length of a line, like npixels, but in bytes
1524 int DMAoffset = 0; //additional VRAM offset to start the DMA copy to
1525 int UVDMAoffset = 0;
1526 struct nouveau_bo *destination_buffer = NULL;
1527 unsigned char * video_mem_destination = NULL;
1528 int action_flags; //what shall we do?
1531 if (pPriv->grabbedByV4L)
1535 NV_set_action_flags(pNv, pScrn, pDraw, pPriv, id, &action_flags);
1537 if ( NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
1538 &src_x, &src_y, &src_w, &src_h,
1539 &drw_x, &drw_y, &drw_w, &drw_h,
1540 &left, &top, &right, &bottom, &dstBox,
1542 clipBoxes, width, height ) )
1548 if ( NV_calculate_pitches_and_mem_size(action_flags, &srcPitch, &srcPitch2, &dstPitch,
1549 &s2offset, &s3offset,
1550 & newFBSize, &newTTSize ,&line_len ,
1551 npixels, nlines, width, height) )
1553 return BadImplementation;
1556 /* There are some cases (tvtime with overscan for example) where the input image is larger (width/height) than
1557 the source rectangle for the overlay (src_w, src_h). In those cases, we try to do something optimal by uploading only
1558 the necessary data. */
1559 if ( action_flags & IS_YUY2 || action_flags & IS_RGB )
1561 buf += (top * srcPitch) + left;
1562 DMAoffset += left + (top * dstPitch);
1565 if ( action_flags & IS_YV12 )
1567 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1571 if ( action_flags & CONVERT_TO_YUY2 )
1573 DMAoffset += (left << 1) + (top * dstPitch);
1578 //real YV12 - we offset only the luma plane, and copy the whole color plane, for easiness
1579 DMAoffset += left + (top * dstPitch);
1580 UVDMAoffset += left + (top >> 1) * dstPitch;
1584 pPriv->video_mem = NVAllocateVideoMemory(pScrn, pPriv->video_mem,
1586 if (!pPriv->video_mem)
1589 offset = pPriv->video_mem->offset;
1591 /*The overlay supports hardware double buffering. We handle this here*/
1592 if (pPriv->doubleBuffer) {
1593 int mask = 1 << (pPriv->currentBuffer << 2);
1594 /* overwrite the newest buffer if there's not one free */
1595 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1596 if (!pPriv->currentBuffer)
1597 offset += newFBSize >> 1;
1601 if (pPriv->currentBuffer)
1602 offset += newFBSize >> 1;
1605 /*Now we take a decision regarding the way we send the data to the card.
1606 Either we use double buffering of "private" TT memory
1607 Either we rely on X's GARTScratch
1608 Either we fallback on CPU copy
1611 /* Try to allocate host-side double buffers, unless we have already failed*/
1612 /* We take only nlines * line_len bytes - that is, only the pixel data we are interested in - because the stuff in the GART is
1613 written contiguously */
1614 if ( pPriv -> currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1616 pPriv->TT_mem_chunk[0] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[0],
1618 if ( pPriv->TT_mem_chunk[0] )
1620 pPriv->TT_mem_chunk[1] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[1],
1623 if ( ! pPriv->TT_mem_chunk[1] )
1625 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1626 pPriv->TT_mem_chunk[0] = NULL;
1627 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1628 //xf86DrvMsg(0, X_INFO, "Alloc 1 failed\n");
1633 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1634 //xf86DrvMsg(0, X_INFO, "Alloc 0 failed\n");
1638 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1639 { //if we have a private buffer
1640 destination_buffer = pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1641 //xf86DrvMsg(0, X_INFO, "Using private mem chunk #%d\n", pPriv->currentHostBuffer);
1643 /* We know where we are going to write, but we are not sure yet whether we can do it directly, because
1644 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.
1645 If we do, then we must wait for it before overwriting the buffer.
1646 Else we need one, so we call the Xv notifier allocator.*/
1647 if ( pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1649 //xf86DrvMsg(0, X_INFO, "Waiting for notifier %p (%d)\n", pPriv->DMANotifier[pPriv->currentHostBuffer], pPriv->currentHostBuffer);
1650 if (nouveau_notifier_wait_status(pPriv->DMANotifier[pPriv->currentHostBuffer], 0, 0, 0))
1655 //xf86DrvMsg(0, X_INFO, "Allocating notifier...\n");
1656 pPriv->DMANotifier [ pPriv->currentHostBuffer ] = NVXvDMANotifierAlloc(pScrn);
1657 if (! pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1658 { /* 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.
1659 I know that's a lot of code but I believe it's necessary to properly handle all the cases*/
1660 xf86DrvMsg(0, X_ERROR, "Ran out of Xv notifiers!\n");
1661 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1662 pPriv->TT_mem_chunk[0] = NULL;
1663 nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
1664 pPriv->TT_mem_chunk[1] = NULL;
1665 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1667 //xf86DrvMsg(0, X_INFO, "Got notifier %p\n", pPriv->DMANotifier [ pPriv->currentHostBuffer ]);
1671 if ( pPriv -> currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE )
1672 { //otherwise we fall back on DDX's GARTScratch
1673 destination_buffer = pNv->GART;
1674 //xf86DrvMsg(0, X_INFO, "Using global GART memory chunk\n");
1677 if ( !destination_buffer) //if we have no GART at all
1680 if(newTTSize <= destination_buffer->size)
1682 unsigned char *dst = destination_buffer->map;
1685 /* Upload to GART */
1686 if ( action_flags & IS_YV12)
1688 if ( action_flags & CONVERT_TO_YUY2 )
1690 NVCopyData420(buf + (top * srcPitch) + left,
1691 buf + s2offset, buf + s3offset,
1692 dst, srcPitch, srcPitch2,
1693 line_len, nlines, npixels);
1697 unsigned char * tbuf = buf + top * srcPitch + left;
1698 unsigned char * tdst = dst;
1699 //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);
1701 for ( i=0; i < nlines; i++)
1703 memcpy(tdst, tbuf, line_len);
1707 dst += line_len * nlines;
1708 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, dst, line_len, srcPitch2, nlines, line_len);
1713 for ( i=0; i < nlines; i++)
1715 memcpy(dst, buf, line_len);
1722 BEGIN_RING(NvMemFormat,
1723 NV_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
1724 OUT_RING (pNv->chan->gart->handle);
1725 OUT_RING (pNv->chan->vram->handle);
1728 if (action_flags & IS_YV12 && ! (action_flags & CONVERT_TO_YUY2) )
1729 { /*we start the color plane transfer separately*/
1730 BEGIN_RING(NvMemFormat,
1731 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1732 OUT_RING ((uint32_t)destination_buffer->offset + line_len * nlines);
1733 OUT_RING ((uint32_t)offset + dstPitch * nlines);
1734 OUT_RING (line_len);
1735 OUT_RING (dstPitch);
1736 OUT_RING (line_len);
1737 OUT_RING ((nlines >> 1));
1738 OUT_RING ((1<<8)|1);
1743 BEGIN_RING(NvMemFormat,
1744 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1745 OUT_RING ((uint32_t)destination_buffer->offset);
1746 OUT_RING ((uint32_t)offset /*+ DMAoffset*/);
1747 OUT_RING (line_len);
1748 OUT_RING (dstPitch);
1749 OUT_RING (line_len);
1751 OUT_RING ((1<<8)|1);
1754 if ( destination_buffer == pNv->GART )
1756 nouveau_notifier_reset(pNv->notify0, 0);
1759 nouveau_notifier_reset(pPriv->DMANotifier[pPriv->currentHostBuffer], 0);
1760 BEGIN_RING(NvMemFormat,
1761 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1762 OUT_RING (pPriv->DMANotifier[pPriv->currentHostBuffer]->handle);
1766 BEGIN_RING(NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1769 BEGIN_RING(NvMemFormat, 0x100, 1);
1772 //Put back NvDmaNotifier0 for EXA
1773 BEGIN_RING(NvMemFormat,
1774 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1775 OUT_RING (pNv->notify0->handle);
1779 if ( destination_buffer == pNv->GART )
1780 if (nouveau_notifier_wait_status(pNv->notify0, 0, 0, 0))
1783 else { //GART is too small, we fallback on CPU copy
1785 video_mem_destination = pPriv->video_mem->map + (offset - (uint32_t)pPriv->video_mem->offset);
1787 if ( action_flags & IS_YV12 )
1789 if ( action_flags & CONVERT_TO_YUY2 )
1791 NVCopyData420(buf + (top * srcPitch) + left,
1792 buf + s2offset, buf + s3offset,
1793 video_mem_destination, srcPitch, srcPitch2,
1794 dstPitch, nlines, npixels);
1797 unsigned char * tbuf = buf + left + top * srcPitch;
1798 for ( i=0; i < nlines; i++)
1800 int dwords = npixels << 1;
1801 while (dwords & ~0x03)
1803 *video_mem_destination = *tbuf;
1804 *(video_mem_destination + 1) = *(tbuf + 1);
1805 *(video_mem_destination + 2) = *(tbuf + 2);
1806 *(video_mem_destination + 3) = *(tbuf + 3);
1807 video_mem_destination += 4;
1814 *(video_mem_destination + 2) = *(tbuf + 2);
1816 *(video_mem_destination + 1) = *(tbuf + 1);
1818 *video_mem_destination = *tbuf;
1821 video_mem_destination += dstPitch - (npixels << 1);
1822 tbuf += srcPitch - (npixels << 1);
1825 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, video_mem_destination, dstPitch, srcPitch2, nlines, line_len);
1830 for ( i=0; i < nlines; i++)
1832 int dwords = npixels << 1;
1833 while (dwords & ~0x03)
1835 *video_mem_destination = *buf;
1836 *(video_mem_destination + 1) = *(buf + 1);
1837 *(video_mem_destination + 2) = *(buf + 2);
1838 *(video_mem_destination + 3) = *(buf + 3);
1839 video_mem_destination += 4;
1846 *(video_mem_destination + 2) = *(buf + 2);
1848 *(video_mem_destination + 1) = *(buf + 1);
1850 *video_mem_destination = *buf;
1853 video_mem_destination += dstPitch - (npixels << 1);
1854 buf += srcPitch - (npixels << 1);
1862 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1863 pPriv->currentHostBuffer ^= 1;
1865 if ( action_flags & USE_OVERLAY )
1867 if ( pNv->Architecture == NV_ARCH_04 )
1868 NV04PutOverlayImage(pScrn, offset, id,
1872 src_w, src_h, drw_w, drw_h,
1875 NVPutOverlayImage(pScrn, offset, ((action_flags & IS_YUY2) || (action_flags & CONVERT_TO_YUY2)) ? 0 : offset + nlines * dstPitch, id,
1879 src_w, src_h, drw_w, drw_h,
1881 pPriv->currentBuffer ^= 1;
1886 if (action_flags & USE_TEXTURE) { /* Texture adapter */
1887 NV40PutTextureImage(pScrn, offset, offset + nlines * dstPitch, id,
1891 src_w, src_h, drw_w, drw_h,
1893 } else { /* Blit adapter */
1894 NVPutBlitImage(pScrn, offset, id,
1898 src_w, src_h, drw_w, drw_h,
1907 * QueryImageAttributes
1910 * - size (memory required to store image),
1914 * depending on colorspace (id) and dimensions (w,h) of image
1918 * may be adjusted as needed
1920 * @param pScrn unused
1921 * @param id colorspace of image
1922 * @param w pointer to width of image
1923 * @param h pointer to height of image
1924 * @param pitches pitches[i] = length of a scanline in plane[i]
1925 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1926 * @return size of the memory required for the XvImage queried
1929 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1930 unsigned short *w, unsigned short *h,
1931 int *pitches, int *offsets)
1935 if (*w > IMAGE_MAX_W)
1937 if (*h > IMAGE_MAX_H)
1940 *w = (*w + 1) & ~1; // width rounded up to an even number
1947 *h = (*h + 1) & ~1; // height rounded up to an even number
1948 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1950 pitches[0] = size; // width rounded up to a multiple of 4
1953 offsets[1] = size; // number of pixels in "rounded up" image
1954 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1956 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1957 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1958 size += tmp; // 5/4*number of pixels in "rounded up" image
1960 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1961 size += tmp; // = 3/2*number of pixels in "rounded up" image
1965 size = *w << 1; // 2*width
1967 pitches[0] = size; // 2*width
1968 size *= *h; // 2*width*height
1971 size = *w << 2; // 4*width (32 bit per pixel)
1973 pitches[0] = size; // 4*width
1974 size *= *h; // 4*width*height
1984 /***** Exported offscreen surface stuff ****/
1988 NVAllocSurface(ScrnInfoPtr pScrn, int id,
1989 unsigned short w, unsigned short h,
1990 XF86SurfacePtr surface)
1992 NVPtr pNv = NVPTR(pScrn);
1993 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1996 bpp = pScrn->bitsPerPixel >> 3;
1998 if (pPriv->grabbedByV4L)
2001 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
2005 pPriv->pitch = ((w << 1) + 63) & ~63;
2006 size = h * pPriv->pitch / bpp;
2008 pPriv->video_mem = NVAllocateVideoMemory(pScrn,
2011 if (!pPriv->video_mem)
2017 surface->height = h;
2018 surface->pScrn = pScrn;
2019 surface->pitches = &pPriv->pitch;
2020 surface->offsets = &pPriv->offset;
2021 surface->devPrivate.ptr = (pointer)pPriv;
2024 /* grab the video */
2025 NVStopOverlay(pScrn);
2026 pPriv->videoStatus = 0;
2027 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
2028 pPriv->grabbedByV4L = TRUE;
2034 NVStopSurface(XF86SurfacePtr surface)
2036 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
2038 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
2039 NVStopOverlay(surface->pScrn);
2040 pPriv->videoStatus = 0;
2047 NVFreeSurface(XF86SurfacePtr surface)
2049 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
2051 if (pPriv->grabbedByV4L) {
2052 NVStopSurface(surface);
2053 NVFreeOverlayMemory(surface->pScrn);
2054 pPriv->grabbedByV4L = FALSE;
2061 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
2063 NVPtr pNv = NVPTR(pScrn);
2064 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
2066 return NVGetOverlayPortAttribute(pScrn, attribute,
2067 value, (pointer)pPriv);
2071 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
2073 NVPtr pNv = NVPTR(pScrn);
2074 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
2076 return NVSetOverlayPortAttribute(pScrn, attribute,
2077 value, (pointer)pPriv);
2081 NVDisplaySurface(XF86SurfacePtr surface,
2082 short src_x, short src_y,
2083 short drw_x, short drw_y,
2084 short src_w, short src_h,
2085 short drw_w, short drw_h,
2086 RegionPtr clipBoxes)
2088 ScrnInfoPtr pScrn = surface->pScrn;
2089 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
2090 INT32 xa, xb, ya, yb;
2093 if (!pPriv->grabbedByV4L)
2096 if (src_w > (drw_w << 3))
2098 if (src_h > (drw_h << 3))
2108 dstBox.x2 = drw_x + drw_w;
2110 dstBox.y2 = drw_y + drw_h;
2112 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
2113 surface->width, surface->height))
2116 dstBox.x1 -= pScrn->frameX0;
2117 dstBox.x2 -= pScrn->frameX0;
2118 dstBox.y1 -= pScrn->frameY0;
2119 dstBox.y2 -= pScrn->frameY0;
2121 pPriv->currentBuffer = 0;
2123 NVPutOverlayImage(pScrn, surface->offsets[0], 0, surface->id,
2124 surface->pitches[0], &dstBox, xa, ya, xb, yb,
2125 surface->width, surface->height, src_w, src_h,
2126 drw_w, drw_h, clipBoxes);
2133 * this function does all the work setting up a blit port
2137 static XF86VideoAdaptorPtr
2138 NVSetupBlitVideo (ScreenPtr pScreen)
2140 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2141 NVPtr pNv = NVPTR(pScrn);
2142 XF86VideoAdaptorPtr adapt;
2143 NVPortPrivPtr pPriv;
2146 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2147 sizeof(NVPortPrivRec) +
2148 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
2152 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2154 adapt->name = "NV Video Blitter";
2155 adapt->nEncodings = 1;
2156 adapt->pEncodings = &DummyEncoding;
2157 adapt->nFormats = NUM_FORMATS_ALL;
2158 adapt->pFormats = NVFormats;
2159 adapt->nPorts = NUM_BLIT_PORTS;
2160 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2162 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
2163 for(i = 0; i < NUM_BLIT_PORTS; i++)
2164 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2166 if(pNv->WaitVSyncPossible) {
2167 adapt->pAttributes = NVBlitAttributes;
2168 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
2170 adapt->pAttributes = NULL;
2171 adapt->nAttributes = 0;
2174 adapt->pImages = NVImages;
2175 adapt->nImages = NUM_IMAGES_ALL;
2176 adapt->PutVideo = NULL;
2177 adapt->PutStill = NULL;
2178 adapt->GetVideo = NULL;
2179 adapt->GetStill = NULL;
2180 adapt->StopVideo = NVStopBlitVideo;
2181 adapt->SetPortAttribute = NVSetBlitPortAttribute;
2182 adapt->GetPortAttribute = NVGetBlitPortAttribute;
2183 adapt->QueryBestSize = NVQueryBestSize;
2184 adapt->PutImage = NVPutImage;
2185 adapt->QueryImageAttributes = NVQueryImageAttributes;
2187 pPriv->videoStatus = 0;
2188 pPriv->grabbedByV4L = FALSE;
2189 pPriv->blitter = TRUE;
2190 pPriv->texture = FALSE;
2191 pPriv->doubleBuffer = FALSE;
2192 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
2194 pNv->blitAdaptor = adapt;
2195 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
2201 * NVSetupOverlayVideo
2202 * this function does all the work setting up an overlay port
2204 * @return overlay port
2205 * @see NVResetVideo(ScrnInfoPtr pScrn)
2207 static XF86VideoAdaptorPtr
2208 NVSetupOverlayVideoAdapter(ScreenPtr pScreen)
2210 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2211 NVPtr pNv = NVPTR(pScrn);
2212 XF86VideoAdaptorPtr adapt;
2213 NVPortPrivPtr pPriv;
2215 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2216 sizeof(NVPortPrivRec) +
2217 sizeof(DevUnion)))) {
2221 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2222 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
2223 adapt->name = "NV Video Overlay";
2224 adapt->nEncodings = 1;
2225 adapt->pEncodings = &DummyEncoding;
2226 adapt->nFormats = NUM_FORMATS_ALL;
2227 adapt->pFormats = NVFormats;
2229 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2231 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
2232 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
2234 adapt->pAttributes = (pNv->Architecture != NV_ARCH_04) ? NVOverlayAttributes : NV04OverlayAttributes;
2235 adapt->nAttributes = (pNv->Architecture != NV_ARCH_04) ? NUM_OVERLAY_ATTRIBUTES : NUM_NV04_OVERLAY_ATTRIBUTES;
2236 adapt->pImages = NVImages;
2237 adapt->nImages = NUM_IMAGES_YUV;
2238 adapt->PutVideo = NULL;
2239 adapt->PutStill = NULL;
2240 adapt->GetVideo = NULL;
2241 adapt->GetStill = NULL;
2242 adapt->StopVideo = NVStopOverlayVideo;
2243 adapt->SetPortAttribute = NVSetOverlayPortAttribute;
2244 adapt->GetPortAttribute = NVGetOverlayPortAttribute;
2245 adapt->QueryBestSize = NVQueryBestSize;
2246 adapt->PutImage = NVPutImage;
2247 adapt->QueryImageAttributes = NVQueryImageAttributes;
2249 pPriv->videoStatus = 0;
2250 pPriv->currentBuffer = 0;
2251 pPriv->grabbedByV4L = FALSE;
2252 pPriv->blitter = FALSE;
2253 pPriv->texture = FALSE;
2254 if ( pNv->Architecture == NV_ARCH_04 )
2255 pPriv->doubleBuffer = 0;
2257 NVSetPortDefaults (pScrn, pPriv);
2259 /* gotta uninit this someplace */
2260 REGION_NULL(pScreen, &pPriv->clip);
2262 pNv->overlayAdaptor = adapt;
2264 xvColorKey = MAKE_ATOM("XV_COLORKEY");
2265 if ( pNv->Architecture != NV_ARCH_04 )
2267 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
2268 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
2269 xvContrast = MAKE_ATOM("XV_CONTRAST");
2270 xvSaturation = MAKE_ATOM("XV_SATURATION");
2271 xvHue = MAKE_ATOM("XV_HUE");
2272 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
2273 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
2274 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
2275 xvOnCRTCNb = MAKE_ATOM("XV_ON_CRTC_NB");
2278 NVResetVideo(pScrn);
2284 XF86OffscreenImageRec NVOffscreenImages[2] = {
2287 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2292 NVGetSurfaceAttribute,
2293 NVSetSurfaceAttribute,
2294 IMAGE_MAX_W, IMAGE_MAX_H,
2295 NUM_OVERLAY_ATTRIBUTES - 1,
2296 &NVOverlayAttributes[1]
2300 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2305 NVGetSurfaceAttribute,
2306 NVSetSurfaceAttribute,
2307 IMAGE_MAX_W, IMAGE_MAX_H,
2308 NUM_OVERLAY_ATTRIBUTES - 1,
2309 &NVOverlayAttributes[1]
2314 NVInitOffscreenImages (ScreenPtr pScreen)
2316 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
2320 * NVChipsetHasOverlay
2322 * newer chips don't support overlay anymore.
2323 * overlay feature is emulated via textures.
2326 * @return true, if chipset supports overlay
2329 NVChipsetHasOverlay(NVPtr pNv)
2331 switch (pNv->Architecture) {
2332 case NV_ARCH_04: /*NV04 has a different overlay than NV10+*/
2338 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
2349 * NVSetupOverlayVideo
2350 * check if chipset supports Overlay and CompositeExtension is disabled.
2351 * if so, setup overlay port
2353 * @return overlay port
2354 * @see NVChipsetHasOverlay(NVPtr pNv)
2355 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
2356 * @see NVInitOffscreenImages(ScreenPtr pScreen)
2358 static XF86VideoAdaptorPtr
2359 NVSetupOverlayVideo(ScreenPtr pScreen)
2361 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2362 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2363 NVPtr pNv = NVPTR(pScrn);
2365 if (!NVChipsetHasOverlay(pNv))
2368 overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen);
2369 if (overlayAdaptor && pNv->Architecture != NV_ARCH_04 )
2370 NVInitOffscreenImages(pScreen); //I am not sure what this call does.
2373 if (!noCompositeExtension) {
2374 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2375 "XV: Composite is enabled, enabling overlay with smart blitter fallback\n");
2376 overlayAdaptor -> name = "NV Video Overlay with Composite";
2380 return overlayAdaptor;
2384 * NV40 texture adapter.
2387 #define NUM_TEXTURE_PORTS 32
2389 #define NUM_FORMAT_TEXTURED 2
2391 static XF86ImageRec NV40TexturedImages[NUM_FORMAT_TEXTURED] =
2398 * NV40StopTexturedVideo
2401 NV40StopTexturedVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
2406 * NVSetTexturePortAttribute
2407 * sets the attribute "attribute" of port "data" to value "value"
2408 * supported attributes:
2412 * @param attribute attribute to set
2413 * @param value value to which attribute is to be set
2414 * @param data port from which the attribute is to be set
2416 * @return Success, if setting is successful
2417 * BadValue/BadMatch, if value/attribute are invalid
2420 NVSetTexturePortAttribute(ScrnInfoPtr pScrn, Atom attribute,
2421 INT32 value, pointer data)
2427 * NVGetTexturePortAttribute
2428 * reads the value of attribute "attribute" from port "data" into INT32 "*value"
2429 * currently no attriutes are supported.
2431 * @param pScrn unused
2432 * @param attribute attribute to be read
2433 * @param value value of attribute will be stored here
2434 * @param data port from which attribute will be read
2435 * @return Success, if queried attribute exists
2438 NVGetTexturePortAttribute(ScrnInfoPtr pScrn, Atom attribute,
2439 INT32 *value, pointer data)
2446 * NV40SetupTexturedVideo
2447 * this function does all the work setting up a blit port
2449 * @return texture port
2451 static XF86VideoAdaptorPtr
2452 NV40SetupTexturedVideo (ScreenPtr pScreen)
2454 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2455 NVPtr pNv = NVPTR(pScrn);
2456 XF86VideoAdaptorPtr adapt;
2457 NVPortPrivPtr pPriv;
2460 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2461 sizeof(NVPortPrivRec) +
2462 (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
2466 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2468 adapt->name = "NV40 Texture adapter";
2469 adapt->nEncodings = 1;
2470 adapt->pEncodings = &DummyEncoding;
2471 adapt->nFormats = NUM_FORMATS_ALL;
2472 adapt->pFormats = NVFormats;
2473 adapt->nPorts = NUM_TEXTURE_PORTS;
2474 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2476 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
2477 for(i = 0; i < NUM_TEXTURE_PORTS; i++)
2478 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2480 adapt->pAttributes = NULL;
2481 adapt->nAttributes = 0;
2483 adapt->pImages = NV40TexturedImages;
2484 adapt->nImages = NUM_FORMAT_TEXTURED;
2485 adapt->PutVideo = NULL;
2486 adapt->PutStill = NULL;
2487 adapt->GetVideo = NULL;
2488 adapt->GetStill = NULL;
2489 adapt->StopVideo = NV40StopTexturedVideo;
2490 adapt->SetPortAttribute = NVSetTexturePortAttribute;
2491 adapt->GetPortAttribute = NVGetTexturePortAttribute;
2492 adapt->QueryBestSize = NVQueryBestSize;
2493 adapt->PutImage = NVPutImage;
2494 adapt->QueryImageAttributes = NVQueryImageAttributes;
2496 pPriv->videoStatus = 0;
2497 pPriv->grabbedByV4L = FALSE;
2498 pPriv->blitter = FALSE;
2499 pPriv->texture = TRUE;
2500 pPriv->doubleBuffer = FALSE;
2501 pPriv->SyncToVBlank = FALSE;
2503 pNv->textureAdaptor = adapt;
2510 * tries to initialize one new overlay port and one new blit port
2511 * and add them to the list of ports on screen "pScreen".
2514 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
2515 * @see NVSetupBlitVideo(ScreenPtr pScreen)
2517 void NVInitVideo (ScreenPtr pScreen)
2519 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2520 NVPtr pNv = NVPTR(pScrn);
2521 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
2522 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2523 XF86VideoAdaptorPtr blitAdaptor = NULL;
2524 XF86VideoAdaptorPtr textureAdaptor = NULL;
2528 * Driving the blitter requires the DMA FIFO. Using the FIFO
2529 * without accel causes DMA errors. While the overlay might
2530 * might work without accel, we also disable it for now when
2531 * acceleration is disabled:
2533 if (pScrn->bitsPerPixel != 8 && pNv->Architecture < NV_ARCH_50 && !pNv->NoAccel) {
2534 overlayAdaptor = NVSetupOverlayVideo(pScreen);
2535 blitAdaptor = NVSetupBlitVideo(pScreen);
2536 if (pNv->Architecture == NV_ARCH_40)
2537 textureAdaptor = NV40SetupTexturedVideo(pScreen);
2540 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
2541 if(blitAdaptor || overlayAdaptor) {
2542 int size = num_adaptors;
2544 if(overlayAdaptor) size++;
2545 if(blitAdaptor) size++;
2547 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
2550 memcpy(newAdaptors, adaptors, num_adaptors *
2551 sizeof(XF86VideoAdaptorPtr));
2554 if(overlayAdaptor) {
2555 newAdaptors[num_adaptors] = overlayAdaptor;
2559 if (textureAdaptor) {
2560 newAdaptors[num_adaptors] = textureAdaptor;
2565 newAdaptors[num_adaptors] = blitAdaptor;
2569 adaptors = newAdaptors;
2574 xf86XVScreenInit(pScreen, adaptors, num_adaptors);