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 TEX_IMAGE_MAX_W 4096
51 #define TEX_IMAGE_MAX_H 4096
53 #define OFF_DELAY 500 /* milliseconds */
54 #define FREE_DELAY 5000
56 #define OFF_TIMER 0x01
57 #define FREE_TIMER 0x02
58 #define CLIENT_VIDEO_ON 0x04
60 #define TIMER_MASK (OFF_TIMER | FREE_TIMER)
62 #define NUM_BLIT_PORTS 32
64 /* Value taken by pPriv -> currentHostBuffer when we failed to allocate the two private buffers in TT memory, so that we can catch this case
65 and attempt no other allocation afterwards (performance reasons) */
66 #define NO_PRIV_HOST_BUFFER_AVAILABLE 9999
69 /* Xv DMA notifiers status tracing */
72 XV_DMA_NOTIFIER_NOALLOC=0, //notifier not allocated
73 XV_DMA_NOTIFIER_INUSE=1,
74 XV_DMA_NOTIFIER_FREE=2, //notifier allocated, ready for use
77 /* We have six notifiers available, they are not allocated at startup */
78 int XvDMANotifierStatus[6]= { XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC ,
79 XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC , XV_DMA_NOTIFIER_NOALLOC };
80 struct nouveau_notifier *XvDMANotifiers[6];
82 /* NVPutImage action flags */
90 IS_RGB=64, //I am not sure how long we will support it
93 #define GET_OVERLAY_PRIVATE(pNv) \
94 (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr)
96 #define GET_BLIT_PRIVATE(pNv) \
97 (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr)
99 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
101 static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
102 xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
103 xvITURBT709, xvSyncToVBlank, xvOnCRTCNb;
105 /* client libraries expect an encoding */
106 static XF86VideoEncodingRec DummyEncoding =
110 IMAGE_MAX_W, IMAGE_MAX_H,
114 static XF86VideoEncodingRec DummyEncodingTex =
118 TEX_IMAGE_MAX_W, TEX_IMAGE_MAX_H,
122 #define NUM_FORMATS_ALL 6
124 XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
126 {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
127 {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
130 #define NUM_NV04_OVERLAY_ATTRIBUTES 1
131 XF86AttributeRec NV04OverlayAttributes[NUM_NV04_OVERLAY_ATTRIBUTES] =
133 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
137 #define NUM_OVERLAY_ATTRIBUTES 10
138 XF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] =
140 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
141 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
142 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
143 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
144 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
145 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
146 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
147 {XvSettable | XvGettable, 0, 360, "XV_HUE"},
148 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"},
149 {XvSettable | XvGettable, 0, 1, "XV_ON_CRTC_NB"},
152 #define NUM_BLIT_ATTRIBUTES 2
153 XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
155 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
156 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
159 #define NUM_TEXTURED_ATTRIBUTES 2
160 XF86AttributeRec NVTexturedAttributes[NUM_TEXTURED_ATTRIBUTES] =
162 {XvSettable , 0, 0, "XV_SET_DEFAULTS"},
163 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
167 #define NUM_IMAGES_YUV 4
168 #define NUM_IMAGES_ALL 5
170 #define FOURCC_RGB 0x0000003
171 #define XVIMAGE_RGB \
176 { 0x03, 0x00, 0x00, 0x00, \
177 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
181 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
186 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}, \
190 static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
200 nv_window_belongs_to_crtc(ScrnInfoPtr pScrn, int x, int y, int w, int h)
202 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
209 for (i = 0; i < xf86_config->num_crtc; i++) {
210 crtc = xf86_config->crtc[i];
215 if ((x < (crtc->x + crtc->mode.HDisplay)) &&
216 (y < (crtc->y + crtc->mode.VDisplay)) &&
217 ((x + w) > crtc->x) &&
226 NVWaitVSync(ScrnInfoPtr pScrn, int crtc)
228 NVPtr pNv = NVPTR(pScrn);
230 BEGIN_RING(NvImageBlit, 0x0000012C, 1);
232 BEGIN_RING(NvImageBlit, 0x00000134, 1);
234 BEGIN_RING(NvImageBlit, 0x00000100, 1);
236 BEGIN_RING(NvImageBlit, 0x00000130, 1);
242 * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
244 * @param pScrn screen to get the default colorKey from
245 * @param pPriv port to reset to defaults
248 NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
250 NVPtr pNv = NVPTR(pScrn);
252 pPriv->brightness = 0;
253 pPriv->contrast = 4096;
254 pPriv->saturation = 4096;
256 pPriv->colorKey = pNv->videoKey;
257 pPriv->autopaintColorKey = TRUE;
258 pPriv->doubleBuffer = TRUE;
259 pPriv->iturbt_709 = FALSE;
260 pPriv->currentHostBuffer = 0;
265 * writes the current attributes from the overlay port to the hardware
268 NVResetVideo (ScrnInfoPtr pScrn)
270 NVPtr pNv = NVPTR(pScrn);
271 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
272 int satSine, satCosine;
275 angle = (double)pPriv->hue * 3.1415927 / 180.0;
277 satSine = pPriv->saturation * sin(angle);
280 satCosine = pPriv->saturation * cos(angle);
281 if (satCosine < -1024)
284 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
286 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
288 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
289 (satCosine & 0xffff));
290 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
291 (satCosine & 0xffff));
292 nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
297 * Tell the hardware to stop the overlay
300 NVStopOverlay (ScrnInfoPtr pScrn)
302 NVPtr pNv = NVPTR(pScrn);
304 if ( pNv -> Architecture != NV_ARCH_04 )
305 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
308 nvWriteRAMDAC(pNv, 0, 0x244, nvReadRAMDAC(pNv, 0, 0x244) &~ 0x1);
309 nvWriteRAMDAC(pNv, 0, 0x224, 0);
310 nvWriteRAMDAC(pNv, 0, 0x228, 0);
311 nvWriteRAMDAC(pNv, 0, 0x22c, 0);
316 * NVXvDMANotifierAlloc
317 * allocates a notifier from the table of 6 we have
319 * @return a notifier instance or NULL on error
321 static struct nouveau_notifier *
322 NVXvDMANotifierAlloc(ScrnInfoPtr pScrn)
324 NVPtr pNv = NVPTR(pScrn);
327 for (i = 0; i < 6; i++) {
328 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_INUSE)
331 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_FREE) {
332 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
333 return XvDMANotifiers[i];
336 if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_NOALLOC) {
337 if (nouveau_notifier_alloc(pNv->chan,
338 NvDmaXvNotifier0 + i,
339 1, &XvDMANotifiers[i]))
341 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
342 return XvDMANotifiers[i];
350 * NVXvDMANotifierFree
351 * frees a notifier from the table of 6 we have
356 NVXvDMANotifierFree(ScrnInfoPtr pScrn, struct nouveau_notifier *target)
359 for ( i = 0; i < 6; i ++ )
361 if ( XvDMANotifiers[i] == target )
364 XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_FREE;
368 * NVAllocateVideoMemory
369 * allocates video memory for a given port
371 * @param pScrn screen which requests the memory
372 * @param mem pointer to previously allocated memory for reallocation
373 * @param size size of requested memory segment
374 * @return pointer to the allocated memory
376 static struct nouveau_bo *
377 NVAllocateVideoMemory(ScrnInfoPtr pScrn, struct nouveau_bo *mem, int size)
379 NVPtr pNv = NVPTR(pScrn);
380 struct nouveau_bo *bo = NULL;
383 if(mem->size >= size)
385 nouveau_bo_del(&mem);
388 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN, 0,
392 if (nouveau_bo_map(bo, NOUVEAU_BO_RDWR)) {
402 * allocates TT memory for a given port
404 * @param pScrn screen which requests the memory
405 * @param mem pointer to previously allocated memory for reallocation
406 * @param size size of requested memory segment
407 * @return pointer to the allocated memory
409 static struct nouveau_bo *
410 NVAllocateTTMemory(ScrnInfoPtr pScrn, struct nouveau_bo *mem, int size)
412 NVPtr pNv = NVPTR(pScrn);
413 struct nouveau_bo *bo = NULL;
416 if(mem->size >= size)
418 nouveau_bo_del(&mem);
421 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_GART | NOUVEAU_BO_PIN, 0,
425 if (nouveau_bo_map(bo, NOUVEAU_BO_RDWR)) {
435 * frees memory held by a given port
437 * @param pScrn screen whose port wants to free memory
438 * @param pPriv port to free memory of
441 NVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
443 //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]);
445 if(pPriv->video_mem) {
446 nouveau_bo_del(&pPriv->video_mem);
447 pPriv->video_mem = NULL;
450 if ( pPriv->TT_mem_chunk[ 0 ] && pPriv->DMANotifier [ 0 ] )
452 nouveau_notifier_wait_status(pPriv->DMANotifier[0], 0, 0, 1000);
455 if ( pPriv->TT_mem_chunk[ 1 ] && pPriv->DMANotifier [ 1 ] )
457 nouveau_notifier_wait_status(pPriv->DMANotifier[1], 0, 0, 1000);
460 if(pPriv->TT_mem_chunk[0]) {
461 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
462 pPriv->TT_mem_chunk[0] = NULL;
465 if(pPriv->TT_mem_chunk[1]) {
466 nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
467 pPriv->TT_mem_chunk[1] = NULL;
470 if(pPriv->DMANotifier[0]) {
471 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[0]);
472 pPriv->DMANotifier[0] = NULL;
475 if(pPriv->DMANotifier[1]) {
476 NVXvDMANotifierFree(pScrn, pPriv->DMANotifier[1]);
477 pPriv->DMANotifier[1] = NULL;
483 * NVFreeOverlayMemory
484 * frees memory held by the overlay port
486 * @param pScrn screen whose overlay port wants to free memory
489 NVFreeOverlayMemory(ScrnInfoPtr pScrn)
491 NVPtr pNv = NVPTR(pScrn);
492 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
493 NVFreePortMemory(pScrn, pPriv);
494 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) & 0xEFFFFFFF));
495 nvWriteMC(pNv, 0x200, (nvReadMC(pNv, 0x200) | 0x10000000));
500 * frees memory held by the blit port
502 * @param pScrn screen whose blit port wants to free memory
505 NVFreeBlitMemory(ScrnInfoPtr pScrn)
507 NVPtr pNv = NVPTR(pScrn);
508 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
509 NVFreePortMemory(pScrn, pPriv);
513 * NVVideoTimerCallback
514 * callback function which perform cleanup tasks (stop overlay, free memory).
515 * within the driver it is only called once from NVBlockHandler in nv_driver.c
518 NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
520 NVPtr pNv = NVPTR(pScrn);
521 NVPortPrivPtr pOverPriv = NULL;
522 NVPortPrivPtr pBlitPriv = NULL;
523 Bool needCallback = FALSE;
528 if (pNv->overlayAdaptor) {
529 pOverPriv = GET_OVERLAY_PRIVATE(pNv);
530 if (!pOverPriv->videoStatus)
534 if (pNv->blitAdaptor) {
535 pBlitPriv = GET_BLIT_PRIVATE(pNv);
536 if (!pBlitPriv->videoStatus)
541 if (pOverPriv->videoTime < currentTime) {
542 if (pOverPriv->videoStatus & OFF_TIMER) {
543 NVStopOverlay(pScrn);
544 pOverPriv->videoStatus = FREE_TIMER;
545 pOverPriv->videoTime = currentTime + FREE_DELAY;
548 if (pOverPriv->videoStatus & FREE_TIMER) {
549 NVFreeOverlayMemory(pScrn);
550 pOverPriv->videoStatus = 0;
558 if (pBlitPriv->videoTime < currentTime) {
559 NVFreeBlitMemory(pScrn);
560 pBlitPriv->videoStatus = 0;
566 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
571 * program hardware to overlay image into front buffer
573 * @param pScrn screen
574 * @param offset card offset to the pixel data
575 * @param id format of image
576 * @param dstPitch pitch of the pixel data in VRAM
577 * @param dstBox destination box
578 * @param x1 first source point - x
579 * @param y1 first source point - y
580 * @param x2 second source point - x
581 * @param y2 second source point - y
582 * @param width width of the source image = x2 - x1
583 * @param height height
584 * @param src_w width of the image data in VRAM
585 * @param src_h height
586 * @param drw_w width of the image to draw to screen
587 * @param drw_h height
588 * @param clipBoxes ???
591 NVPutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
592 int dstPitch, BoxPtr dstBox,
593 int x1, int y1, int x2, int y2,
594 short width, short height,
595 short src_w, short src_h,
596 short drw_w, short drw_h,
599 NVPtr pNv = NVPTR(pScrn);
600 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
601 int buffer = pPriv->currentBuffer;
603 /* paint the color key */
604 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
605 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
606 /* we always paint V4L's color key */
607 if (!pPriv->grabbedByV4L)
608 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
610 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
614 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
620 //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));
622 nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer) , 0);
623 nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer) , offset);
624 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer) , (height << 16) | width);
625 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
626 ((y1 << 4) & 0xffff0000) | (x1 >> 12));
627 nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer) , (src_w << 20) / drw_w);
628 nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer) , (src_h << 20) / drw_h);
629 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
630 (dstBox->y1 << 16) | dstBox->x1);
631 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
632 ((dstBox->y2 - dstBox->y1) << 16) |
633 (dstBox->x2 - dstBox->x1));
635 dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; /* use color key */
636 if(id != FOURCC_UYVY)
637 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
638 if(pPriv->iturbt_709)
639 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
641 if( id == FOURCC_YV12 || id == FOURCC_I420 )
642 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
644 /* Those are important only for planar formats (NV12) */
647 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_BASE(buffer), 0);
648 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer), uvoffset);
651 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
652 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
653 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
655 pPriv->videoStatus = CLIENT_VIDEO_ON;
659 NV04PutOverlayImage(ScrnInfoPtr pScrn, int offset, int id,
660 int dstPitch, BoxPtr dstBox,
661 int x1, int y1, int x2, int y2,
662 short width, short height,
663 short src_w, short src_h,
664 short drw_w, short drw_h,
667 NVPtr pNv = NVPTR(pScrn);
668 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
670 /* paint the color key */
671 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
672 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
673 /* we always paint V4L's color key */
674 if (!pPriv->grabbedByV4L)
675 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
677 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
681 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) { /*This may not work with NV04 overlay according to rivatv source*/
687 /* NV_PVIDEO_OE_STATE */
688 /* NV_PVIDEO_SU_STATE */
689 /* NV_PVIDEO_RM_STATE */
690 nvWriteRAMDAC(pNv, 0, 0x224, 0);
691 nvWriteRAMDAC(pNv, 0, 0x228, 0);
692 nvWriteRAMDAC(pNv, 0, 0x22c, 0);
694 /* NV_PVIDEO_BUFF0_START_ADDRESS */
695 nvWriteRAMDAC(pNv, 0, 0x20C, offset);
696 nvWriteRAMDAC(pNv, 0, 0x20C + 4, offset);
697 /* NV_PVIDEO_BUFF0_PITCH_LENGTH */
698 nvWriteRAMDAC(pNv, 0, 0x214, dstPitch);
699 nvWriteRAMDAC(pNv, 0, 0x214 + 4, dstPitch);
701 /* NV_PVIDEO_BUFF0_OFFSET */
702 nvWriteRAMDAC(pNv, 0, 0x21C, 0);
703 nvWriteRAMDAC(pNv, 0, 0x21C + 4, 0);
705 /* NV_PVIDEO_WINDOW_START */
706 nvWriteRAMDAC(pNv, 0, 0x230, (dstBox->y1 << 16) | dstBox->x1);
707 /* NV_PVIDEO_WINDOW_SIZE */
708 nvWriteRAMDAC(pNv, 0, 0x234, ((dstBox->y2 - dstBox->y1) << 16) |
709 (dstBox->x2 - dstBox->x1));
710 /* NV_PVIDEO_STEP_SIZE */
711 nvWriteRAMDAC(pNv, 0, 0x200, (uint32_t)(((src_h - 1) << 11) / (drw_h - 1)) << 16 | (uint32_t)(((src_w - 1) << 11) / (drw_w - 1)));
713 /* NV_PVIDEO_RED_CSC_OFFSET */
714 /* NV_PVIDEO_GREEN_CSC_OFFSET */
715 /* NV_PVIDEO_BLUE_CSC_OFFSET */
716 /* NV_PVIDEO_CSC_ADJUST */
717 nvWriteRAMDAC(pNv, 0, 0x280, 0x69);
718 nvWriteRAMDAC(pNv, 0, 0x284, 0x3e);
719 nvWriteRAMDAC(pNv, 0, 0x288, 0x89);
720 nvWriteRAMDAC(pNv, 0, 0x28C, 0x0);
722 /* NV_PVIDEO_CONTROL_Y (BLUR_ON, LINE_HALF) */
723 nvWriteRAMDAC(pNv, 0, 0x204, 0x001);
724 /* NV_PVIDEO_CONTROL_X (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */
725 nvWriteRAMDAC(pNv, 0, 0x208, 0x111);
727 /* NV_PVIDEO_FIFO_BURST_LENGTH */
728 nvWriteRAMDAC(pNv, 0, 0x23C, 0x03);
729 /* NV_PVIDEO_FIFO_THRES_SIZE */
730 nvWriteRAMDAC(pNv, 0, 0x238, 0x38);
733 nvWriteRAMDAC(pNv, 0, 0x240, pPriv->colorKey);
739 nvWriteRAMDAC(pNv, 0, 0x244, 0x111);
741 /* NV_PVIDEO_SU_STATE */
742 nvWriteRAMDAC(pNv, 0, 0x228, (nvReadRAMDAC(pNv, 0, 0x228) ^ (1 << 16)));
744 pPriv->videoStatus = CLIENT_VIDEO_ON;
746 #ifndef ExaOffscreenMarkUsed
747 extern void ExaOffscreenMarkUsed(PixmapPtr);
749 #ifndef exaGetDrawablePixmap
750 extern PixmapPtr exaGetDrawablePixmap(DrawablePtr);
752 #ifndef exaPixmapIsOffscreen
753 extern Bool exaPixmapIsOffscreen(PixmapPtr p);
755 /* To support EXA 2.0, 2.1 has this in the header */
756 #ifndef exaMoveInPixmap
757 extern void exaMoveInPixmap(PixmapPtr pPixmap);
763 * @param pScrn screen
765 * @param id colorspace of image
782 NVPutBlitImage(ScrnInfoPtr pScrn, int src_offset, int id,
783 int src_pitch, BoxPtr dstBox,
784 int x1, int y1, int x2, int y2,
785 short width, short height,
786 short src_w, short src_h,
787 short drw_w, short drw_h,
791 NVPtr pNv = NVPTR(pScrn);
792 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
796 CARD32 dst_size, dst_point;
797 CARD32 src_point, src_format;
801 ScreenPtr pScreen = pScrn->pScreen;
802 PixmapPtr pPix = exaGetDrawablePixmap(pDraw);
805 /* Try to get the dest drawable into vram */
806 if (!exaPixmapIsOffscreen(pPix)) {
807 exaMoveInPixmap(pPix);
808 ExaOffscreenMarkUsed(pPix);
811 /* If we failed, draw directly onto the screen pixmap.
812 * Not sure if this is the best approach, maybe failing
813 * with BadAlloc would be better?
815 if (!exaPixmapIsOffscreen(pPix)) {
816 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
817 "XV: couldn't move dst surface into vram\n");
818 pPix = pScreen->GetScreenPixmap(pScreen);
821 NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format);
822 BEGIN_RING(NvContextSurfaces, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
823 OUT_RING (dst_format);
824 OUT_RING ((exaGetPixmapPitch(pPix) << 16) | exaGetPixmapPitch(pPix));
825 OUT_PIXMAPl(pPix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
826 OUT_PIXMAPl(pPix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
829 /* Adjust coordinates if drawing to an offscreen pixmap */
830 if (pPix->screen_x || pPix->screen_y) {
831 REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
834 dstBox->x1 -= pPix->screen_x;
835 dstBox->x2 -= pPix->screen_x;
836 dstBox->y1 -= pPix->screen_y;
837 dstBox->y2 -= pPix->screen_y;
840 DamageDamageRegion((DrawablePtr)pPix, clipBoxes);
843 pbox = REGION_RECTS(clipBoxes);
844 nbox = REGION_NUM_RECTS(clipBoxes);
846 dsdx = (src_w << 20) / drw_w;
847 dtdy = (src_h << 20) / drw_h;
849 dst_size = ((dstBox->y2 - dstBox->y1) << 16) |
850 (dstBox->x2 - dstBox->x1);
851 dst_point = (dstBox->y1 << 16) | dstBox->x1;
853 src_pitch |= (NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
854 NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_BILINEAR);
855 src_point = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
860 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
864 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_YB8V8YA8U8;
868 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_V8YB8U8YA8;
872 if(pPriv->SyncToVBlank) {
873 crtcs = nv_window_belongs_to_crtc(pScrn, dstBox->x1, dstBox->y1,
874 dstBox->x2, dstBox->y2);
878 NVWaitVSync(pScrn, 0);
880 NVWaitVSync(pScrn, 1);
883 if(pNv->BlendingPossible) {
884 BEGIN_RING(NvScaledImage,
885 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 2);
886 OUT_RING (src_format);
887 OUT_RING (NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
889 BEGIN_RING(NvScaledImage,
890 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 2);
891 OUT_RING (src_format);
895 BEGIN_RING(NvRectangle,
896 NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
899 BEGIN_RING(NvScaledImage,
900 NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT, 6);
901 OUT_RING ((pbox->y1 << 16) | pbox->x1);
902 OUT_RING (((pbox->y2 - pbox->y1) << 16) |
903 (pbox->x2 - pbox->x1));
904 OUT_RING (dst_point);
909 BEGIN_RING(NvScaledImage,
910 NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
911 OUT_RING ((height << 16) | width);
912 OUT_RING (src_pitch);
913 OUT_RING (src_offset);
914 OUT_RING (src_point);
920 exaMarkSync(pScrn->pScreen);
922 pPriv->videoStatus = FREE_TIMER;
923 pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
924 pNv->VideoTimerCallback = NVVideoTimerCallback;
931 NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
933 NVPtr pNv = NVPTR(pScrn);
934 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
936 if(pPriv->grabbedByV4L) return;
938 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
941 if (pPriv->videoStatus & CLIENT_VIDEO_ON)
942 NVStopOverlay(pScrn);
943 NVFreeOverlayMemory(pScrn);
944 pPriv->videoStatus = 0;
946 if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
947 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
948 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
949 pNv->VideoTimerCallback = NVVideoTimerCallback;
958 NVStopBlitVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
963 * NVSetOverlayPortAttribute
964 * sets the attribute "attribute" of port "data" to value "value"
965 * calls NVResetVideo(pScrn) to apply changes to hardware
968 * @param attribute attribute to set
969 * @param value value to which attribute is to be set
970 * @param data port from which the attribute is to be set
972 * @return Success, if setting is successful
973 * BadValue/BadMatch, if value/attribute are invalid
974 * @see NVResetVideo(ScrnInfoPtr pScrn)
977 NVSetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
978 INT32 value, pointer data)
980 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
981 NVPtr pNv = NVPTR(pScrn);
983 if (attribute == xvBrightness) {
984 if ((value < -512) || (value > 512))
986 pPriv->brightness = value;
988 if (attribute == xvDoubleBuffer) {
989 if ((value < 0) || (value > 1))
991 pPriv->doubleBuffer = value;
993 if (attribute == xvContrast) {
994 if ((value < 0) || (value > 8191))
996 pPriv->contrast = value;
998 if (attribute == xvHue) {
1004 if (attribute == xvSaturation) {
1005 if ((value < 0) || (value > 8191))
1007 pPriv->saturation = value;
1009 if (attribute == xvColorKey) {
1010 pPriv->colorKey = value;
1011 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1013 if (attribute == xvAutopaintColorKey) {
1014 if ((value < 0) || (value > 1))
1016 pPriv->autopaintColorKey = value;
1018 if (attribute == xvITURBT709) {
1019 if ((value < 0) || (value > 1))
1021 pPriv->iturbt_709 = value;
1023 if (attribute == xvSetDefaults) {
1024 NVSetPortDefaults(pScrn, pPriv);
1026 if ( attribute == xvOnCRTCNb) {
1027 if ((value < 0) || (value > 1))
1029 pPriv->overlayCRTC = value;
1030 nvWriteCRTC(pNv, value, NV_CRTC_FSEL, nvReadCRTC(pNv, value, NV_CRTC_FSEL) | NV_CRTC_FSEL_OVERLAY);
1031 nvWriteCRTC(pNv, !value, NV_CRTC_FSEL, nvReadCRTC(pNv, !value, NV_CRTC_FSEL) & ~NV_CRTC_FSEL_OVERLAY);
1035 NVResetVideo(pScrn);
1040 * NVGetOverlayPortAttribute
1042 * @param pScrn unused
1043 * @param attribute attribute to be read
1044 * @param value value of attribute will be stored in this pointer
1045 * @param data port from which attribute will be read
1046 * @return Success, if queried attribute exists
1049 NVGetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1050 INT32 *value, pointer data)
1052 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1054 if (attribute == xvBrightness)
1055 *value = pPriv->brightness;
1056 else if (attribute == xvDoubleBuffer)
1057 *value = (pPriv->doubleBuffer) ? 1 : 0;
1058 else if (attribute == xvContrast)
1059 *value = pPriv->contrast;
1060 else if (attribute == xvSaturation)
1061 *value = pPriv->saturation;
1062 else if (attribute == xvHue)
1063 *value = pPriv->hue;
1064 else if (attribute == xvColorKey)
1065 *value = pPriv->colorKey;
1066 else if (attribute == xvAutopaintColorKey)
1067 *value = (pPriv->autopaintColorKey) ? 1 : 0;
1068 else if (attribute == xvITURBT709)
1069 *value = (pPriv->iturbt_709) ? 1 : 0;
1070 else if (attribute == xvOnCRTCNb)
1071 *value = (pPriv->overlayCRTC) ? 1 : 0;
1079 * NVSetBlitPortAttribute
1080 * sets the attribute "attribute" of port "data" to value "value"
1081 * supported attributes:
1082 * - xvSyncToVBlank (values: 0,1)
1083 * - xvSetDefaults (values: NA; SyncToVBlank will be set, if hardware supports it)
1086 * @param attribute attribute to set
1087 * @param value value to which attribute is to be set
1088 * @param data port from which the attribute is to be set
1090 * @return Success, if setting is successful
1091 * BadValue/BadMatch, if value/attribute are invalid
1094 NVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1095 INT32 value, pointer data)
1097 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1098 NVPtr pNv = NVPTR(pScrn);
1100 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
1101 if ((value < 0) || (value > 1))
1103 pPriv->SyncToVBlank = value;
1105 if (attribute == xvSetDefaults) {
1106 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1114 * NVGetBlitPortAttribute
1115 * reads the value of attribute "attribute" from port "data" into INT32 "*value"
1116 * currently only one attribute supported: xvSyncToVBlank
1118 * @param pScrn unused
1119 * @param attribute attribute to be read
1120 * @param value value of attribute will be stored here
1121 * @param data port from which attribute will be read
1122 * @return Success, if queried attribute exists
1125 NVGetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1126 INT32 *value, pointer data)
1128 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1130 if(attribute == xvSyncToVBlank)
1131 *value = (pPriv->SyncToVBlank) ? 1 : 0;
1141 * used by client applications to ask the driver:
1142 * how would you actually scale a video of dimensions
1143 * vid_w, vid_h, if i wanted you to scale it to dimensions
1145 * function stores actual scaling size in pointers p_w, p_h.
1148 * @param pScrn unused
1149 * @param motion unused
1150 * @param vid_w width of source video
1151 * @param vid_h height of source video
1152 * @param drw_w desired scaled width as requested by client
1153 * @param drw_h desired scaled height as requested by client
1154 * @param p_w actual scaled width as the driver is capable of
1155 * @param p_h actual scaled height as the driver is capable of
1156 * @param data unused
1159 NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
1160 short vid_w, short vid_h,
1161 short drw_w, short drw_h,
1162 unsigned int *p_w, unsigned int *p_h,
1165 if(vid_w > (drw_w << 3))
1167 if(vid_h > (drw_h << 3))
1176 * used to convert YV12 to YUY2 for the blitter
1178 * @param src1 source buffer of luma
1179 * @param src2 source buffer of chroma1
1180 * @param src3 source buffer of chroma2
1181 * @param dst1 destination buffer
1182 * @param srcPitch pitch of src1
1183 * @param srcPitch2 pitch of src2, src3
1184 * @param dstPitch pitch of dst1
1185 * @param h number of lines to copy
1186 * @param w length of lines to copy
1188 static inline void NVCopyData420(unsigned char *src1, unsigned char *src2,
1189 unsigned char *src3, unsigned char *dst1,
1190 int srcPitch, int srcPitch2,
1195 CARD8 *s1, *s2, *s3;
1196 #define su(X) (((j & 1) && j < (h-1)) ? ((unsigned)((signed int)s2[X] + (signed int)(s2 + srcPitch2)[X]) / 2) : (s2[X]))
1197 #define sv(X) (((j & 1) && j < (h-1)) ? ((unsigned)((signed int)s3[X] + (signed int)(s3 + srcPitch2)[X]) / 2) : (s3[X]))
1203 for (j = 0; j < h; j++) {
1204 dst = (CARD32*)dst1;
1205 s1 = src1; s2 = src2; s3 = src3;
1209 #if X_BYTE_ORDER == X_BIG_ENDIAN
1210 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (sv(0) << 16) | su(0);
1211 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (sv(1) << 16) | su(1);
1212 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (sv(2) << 16) | su(2);
1213 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (sv(3) << 16) | su(3);
1215 dst[0] = s1[0] | (s1[1] << 16) | (sv(0) << 8) | (su(0) << 24);
1216 dst[1] = s1[2] | (s1[3] << 16) | (sv(1) << 8) | (su(1) << 24);
1217 dst[2] = s1[4] | (s1[5] << 16) | (sv(2) << 8) | (su(2) << 24);
1218 dst[3] = s1[6] | (s1[7] << 16) | (sv(3) << 8) | (su(3) << 24);
1220 dst += 4; s2 += 4; s3 += 4; s1 += 8;
1225 #if X_BYTE_ORDER == X_BIG_ENDIAN
1226 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (sv(0) << 16) | su(0);
1228 dst[0] = s1[0] | (s1[1] << 16) | (sv(0) << 8) | (su(0) << 24);
1244 * NVCopyNV12ColorPlanes
1245 * Used to convert YV12 color planes to NV12 (interleaved UV) for the overlay
1247 * @param src1 source buffer of chroma1
1248 * @param dst1 destination buffer
1249 * @param h number of lines to copy
1250 * @param w length of lines to copy
1251 * @param id source pixel format (YV12 or I420)
1253 static inline void NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char * src2, unsigned char *dst, int dstPitch, int srcPitch2,
1263 for ( j = 0; j < h; j++ )
1265 unsigned char * us = src1;
1266 unsigned char * vs = src2;
1267 unsigned int * vuvud = (unsigned int *) dst;
1268 for ( i = 0; i < l; i++ )
1270 #if X_BYTE_ORDER == X_BIG_ENDIAN
1271 *vuvud++ = (vs[0]<<24) | (us[0]<<16) | (vs[1]<<8) | us[1];
1273 *vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24);
1279 unsigned short *vud = (unsigned short *) vuvud;
1280 #if X_BYTE_ORDER == X_BIG_ENDIAN
1281 *vud = (vs[0]<<8) | (us[0] << 0);
1283 *vud = vs[0] | (us[0]<<8);
1294 static int NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 * xa, INT32 * xb, INT32 * ya, INT32 * yb,
1295 short * src_x, short * src_y, short * src_w, short * src_h,
1296 short * drw_x, short * drw_y, short * drw_w, short * drw_h,
1297 int * left, int * top, int * right, int * bottom,
1299 int * npixels, int * nlines,
1300 RegionPtr clipBoxes, short width, short height
1304 if ( action_flags & USE_OVERLAY )
1305 { /* overlay hardware scaler limitation - copied from nv, UNCHECKED*/
1306 if (*src_w > (*drw_w << 3))
1307 *drw_w = *src_w >> 3;
1308 if (*src_h > (*drw_h << 3))
1309 *drw_h = *src_h >> 3;
1315 *xb = *src_x + *src_w;
1317 *yb = *src_y + *src_h;
1319 dstBox->x1 = *drw_x;
1320 dstBox->x2 = *drw_x + *drw_w;
1321 dstBox->y1 = *drw_y;
1322 dstBox->y2 = *drw_y + *drw_h;
1324 if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
1328 if ( action_flags & USE_OVERLAY )
1330 dstBox->x1 -= pScrn->frameX0;
1331 dstBox->x2 -= pScrn->frameX0;
1332 dstBox->y1 -= pScrn->frameY0;
1333 dstBox->y2 -= pScrn->frameY0;
1338 /* Convert fixed point to integer, as xf86XVClipVideoHelper probably turns its parameter into fixed point values */
1339 *left = (*xa) >> 16;
1340 if (*left < 0) *left = 0;
1342 if (*top < 0) *top = 0;
1343 *right = (*xb) >> 16;
1344 if (*right > width) *right = width;
1345 *bottom = (*yb) >> 16;
1346 if (*bottom > height) *bottom = height;
1348 if ( action_flags & IS_YV12 )
1350 *left &= ~1; //even "left", even "top", even number of pixels per line and even number of lines
1351 *npixels = ((*right + 1) & ~1) - *left;
1353 *nlines = ((*bottom + 1) & ~1) - *top;
1355 else if ( action_flags & IS_YUY2 )
1357 *left &= ~1; //even "left"
1358 *npixels = ((*right + 1) & ~1) - *left; //even number of pixels per line
1359 *nlines = *bottom - *top;
1360 *left <<= 1; //16bpp
1362 else if (action_flags & IS_RGB )
1364 *npixels = *right - *left;
1365 *nlines = *bottom - *top;
1366 *left <<= 2; //32bpp
1372 static int NV_calculate_pitches_and_mem_size(int action_flags, int * srcPitch, int * srcPitch2, int * dstPitch,
1373 int * s2offset, int * s3offset,
1374 int * newFBSize, int * newTTSize,
1375 int * line_len, int npixels, int nlines, int width, int height)
1379 if ( action_flags & IS_YV12 )
1381 *srcPitch = (width + 3) & ~3; /* of luma */
1382 *s2offset = *srcPitch * height;
1383 *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
1384 *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
1385 *dstPitch = (npixels + 63) & ~63; /*luma and chroma pitch*/
1386 *line_len = npixels;
1387 *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1388 *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
1390 else if ( action_flags & IS_YUY2 )
1392 *srcPitch = width << 1; /* one luma, one chroma per pixel */
1393 *dstPitch = ((npixels << 1) + 63) & ~63;
1394 *line_len = npixels << 1;
1395 *newFBSize = nlines * *dstPitch;
1396 *newTTSize = nlines * *line_len;
1398 else if ( action_flags & IS_RGB )
1400 *srcPitch = width << 2; /* one R, one G, one B, one X per pixel */
1401 *dstPitch = ((npixels << 2) + 63) & ~63;
1402 *line_len = npixels << 2;
1403 *newFBSize = nlines * *dstPitch;
1404 *newTTSize = nlines * *dstPitch;
1408 if ( action_flags & CONVERT_TO_YUY2 )
1410 *dstPitch = ((npixels << 1) + 63) & ~63;
1411 *line_len = npixels << 1;
1412 *newFBSize = nlines * *dstPitch;
1413 *newTTSize = nlines * *line_len;
1416 if ( action_flags & SWAP_UV )
1417 { //I420 swaps U and V
1419 *s2offset = *s3offset;
1423 if ( action_flags & USE_OVERLAY ) // overlay double buffering ...
1424 (*newFBSize) <<= 1; // ... means double the amount of VRAM needed
1431 * NV_set_action_flags
1432 * This function computes the action flags from the input image,
1433 * that is, it decides what NVPutImage and its helpers must do.
1434 * This eases readability by avoiding lots of switch-case statements in the core NVPutImage
1436 static void NV_set_action_flags(NVPtr pNv, ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, int id, int * action_flags)
1439 if ( id == FOURCC_YUY2 || id == FOURCC_UYVY )
1440 *action_flags |= IS_YUY2;
1442 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1443 *action_flags |= IS_YV12;
1445 if ( id == FOURCC_RGB ) /*How long will we support it?*/
1446 *action_flags |= IS_RGB;
1448 if ( id == FOURCC_I420 ) /*I420 is YV12 with swapped UV*/
1449 *action_flags |= SWAP_UV;
1451 if ( !pPriv -> blitter && !pPriv -> texture )
1452 *action_flags |= USE_OVERLAY;
1454 if ( !pPriv -> blitter && pPriv->texture )
1455 *action_flags |= USE_TEXTURE;
1458 WindowPtr pWin = NULL;
1460 if (!noCompositeExtension && WindowDrawable(pDraw->type))
1462 pWin = (WindowPtr)pDraw;
1466 if ( pWin->redirectDraw )
1467 *action_flags &= ~USE_OVERLAY;
1471 if ( !(*action_flags & USE_OVERLAY) && !(*action_flags & USE_TEXTURE) )
1473 if ( id == FOURCC_YV12 || id == FOURCC_I420 )
1474 { /*The blitter does not handle YV12 natively*/
1475 *action_flags |= CONVERT_TO_YUY2;
1479 if ( pNv->Architecture == NV_ARCH_04 )
1480 if ( * action_flags & IS_YV12 ) //NV04-05 don't support native YV12, only YUY2 and ITU-R BT.601)
1481 *action_flags |= CONVERT_TO_YUY2;
1483 if ( pNv->Architecture == NV_ARCH_10 || pNv->Architecture == NV_ARCH_20 )
1485 switch ( pNv->Chipset & 0xfff0 )
1490 case CHIPSET_NFORCE: /*XXX: unsure about nforce*/
1491 case CHIPSET_NV20: /*reported by pq - in fact all cards older than geforce4 ti probably don't have YV12 overlay*/
1492 *action_flags |= CONVERT_TO_YUY2; break;
1503 * PutImage is "the" important function of the Xv extension.
1504 * a client (e.g. video player) calls this function for every
1505 * image (of the video) to be displayed. this function then
1506 * scales and displays the image.
1508 * @param pScrn screen which hold the port where the image is put
1509 * @param src_x source point in the source image to start displaying from
1510 * @param src_y see above
1511 * @param src_w width of the source image to display
1512 * @param src_h see above
1513 * @param drw_x screen point to display to
1515 * @param drw_w width of the screen drawable
1517 * @param id pixel format of image
1518 * @param buf pointer to buffer containing the source image
1519 * @param width total width of the source image we are passed
1521 * @param Sync unused
1522 * @param clipBoxes ??
1523 * @param data pointer to port
1524 * @param pDraw drawable pointer
1527 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
1528 short drw_x, short drw_y,
1529 short src_w, short src_h,
1530 short drw_w, short drw_h,
1533 short width, short height,
1534 Bool Sync, /*FIXME: need to honor the Sync*/
1535 RegionPtr clipBoxes,
1540 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1541 NVPtr pNv = NVPTR(pScrn);
1542 INT32 xa = 0, xb = 0, ya = 0, yb = 0; //source box
1543 int newFBSize = 0, newTTSize = 0; //size to allocate in VRAM and in GART respectively
1544 int offset = 0, s2offset = 0, s3offset = 0; //card VRAM offset, source offsets for U and V planes
1545 int srcPitch = 0, srcPitch2 = 0, dstPitch = 0; //source pitch, source pitch of U and V planes in case of YV12, VRAM destination pitch
1546 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
1550 int line_len = 0; //length of a line, like npixels, but in bytes
1551 int DMAoffset = 0; //additional VRAM offset to start the DMA copy to
1552 int UVDMAoffset = 0;
1553 struct nouveau_bo *destination_buffer = NULL;
1554 unsigned char * video_mem_destination = NULL;
1555 int action_flags; //what shall we do?
1558 if (pPriv->grabbedByV4L)
1562 NV_set_action_flags(pNv, pScrn, pDraw, pPriv, id, &action_flags);
1564 if ( NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
1565 &src_x, &src_y, &src_w, &src_h,
1566 &drw_x, &drw_y, &drw_w, &drw_h,
1567 &left, &top, &right, &bottom, &dstBox,
1569 clipBoxes, width, height ) )
1575 if ( NV_calculate_pitches_and_mem_size(action_flags, &srcPitch, &srcPitch2, &dstPitch,
1576 &s2offset, &s3offset,
1577 & newFBSize, &newTTSize ,&line_len ,
1578 npixels, nlines, width, height) )
1580 return BadImplementation;
1583 /* There are some cases (tvtime with overscan for example) where the input image is larger (width/height) than
1584 the source rectangle for the overlay (src_w, src_h). In those cases, we try to do something optimal by uploading only
1585 the necessary data. */
1586 if ( action_flags & IS_YUY2 || action_flags & IS_RGB )
1588 buf += (top * srcPitch) + left;
1589 DMAoffset += left + (top * dstPitch);
1592 if ( action_flags & IS_YV12 )
1594 tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1598 if ( action_flags & CONVERT_TO_YUY2 )
1600 DMAoffset += (left << 1) + (top * dstPitch);
1605 //real YV12 - we offset only the luma plane, and copy the whole color plane, for easiness
1606 DMAoffset += left + (top * dstPitch);
1607 UVDMAoffset += left + (top >> 1) * dstPitch;
1611 pPriv->video_mem = NVAllocateVideoMemory(pScrn, pPriv->video_mem,
1613 if (!pPriv->video_mem)
1616 offset = pPriv->video_mem->offset;
1618 /*The overlay supports hardware double buffering. We handle this here*/
1619 if (pPriv->doubleBuffer) {
1620 int mask = 1 << (pPriv->currentBuffer << 2);
1621 /* overwrite the newest buffer if there's not one free */
1622 if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1623 if (!pPriv->currentBuffer)
1624 offset += newFBSize >> 1;
1628 if (pPriv->currentBuffer)
1629 offset += newFBSize >> 1;
1632 /*Now we take a decision regarding the way we send the data to the card.
1633 Either we use double buffering of "private" TT memory
1634 Either we rely on X's GARTScratch
1635 Either we fallback on CPU copy
1638 /* Try to allocate host-side double buffers, unless we have already failed*/
1639 /* We take only nlines * line_len bytes - that is, only the pixel data we are interested in - because the stuff in the GART is
1640 written contiguously */
1641 if ( pPriv -> currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1643 pPriv->TT_mem_chunk[0] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[0],
1645 if ( pPriv->TT_mem_chunk[0] )
1647 pPriv->TT_mem_chunk[1] = NVAllocateTTMemory(pScrn, pPriv->TT_mem_chunk[1],
1650 if ( ! pPriv->TT_mem_chunk[1] )
1652 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1653 pPriv->TT_mem_chunk[0] = NULL;
1654 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1655 //xf86DrvMsg(0, X_INFO, "Alloc 1 failed\n");
1660 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1661 //xf86DrvMsg(0, X_INFO, "Alloc 0 failed\n");
1665 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1666 { //if we have a private buffer
1667 destination_buffer = pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1668 //xf86DrvMsg(0, X_INFO, "Using private mem chunk #%d\n", pPriv->currentHostBuffer);
1670 /* We know where we are going to write, but we are not sure yet whether we can do it directly, because
1671 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.
1672 If we do, then we must wait for it before overwriting the buffer.
1673 Else we need one, so we call the Xv notifier allocator.*/
1674 if ( pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1676 //xf86DrvMsg(0, X_INFO, "Waiting for notifier %p (%d)\n", pPriv->DMANotifier[pPriv->currentHostBuffer], pPriv->currentHostBuffer);
1677 if (nouveau_notifier_wait_status(pPriv->DMANotifier[pPriv->currentHostBuffer], 0, 0, 0))
1682 //xf86DrvMsg(0, X_INFO, "Allocating notifier...\n");
1683 pPriv->DMANotifier [ pPriv->currentHostBuffer ] = NVXvDMANotifierAlloc(pScrn);
1684 if (! pPriv->DMANotifier [ pPriv->currentHostBuffer ] )
1685 { /* 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.
1686 I know that's a lot of code but I believe it's necessary to properly handle all the cases*/
1687 xf86DrvMsg(0, X_ERROR, "Ran out of Xv notifiers!\n");
1688 nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1689 pPriv->TT_mem_chunk[0] = NULL;
1690 nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
1691 pPriv->TT_mem_chunk[1] = NULL;
1692 pPriv -> currentHostBuffer = NO_PRIV_HOST_BUFFER_AVAILABLE;
1694 //xf86DrvMsg(0, X_INFO, "Got notifier %p\n", pPriv->DMANotifier [ pPriv->currentHostBuffer ]);
1698 if ( pPriv -> currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE )
1699 { //otherwise we fall back on DDX's GARTScratch
1700 destination_buffer = pNv->GART;
1701 //xf86DrvMsg(0, X_INFO, "Using global GART memory chunk\n");
1704 if ( !destination_buffer) //if we have no GART at all
1707 if(newTTSize <= destination_buffer->size)
1709 unsigned char *dst = destination_buffer->map;
1712 /* Upload to GART */
1713 if ( action_flags & IS_YV12)
1715 if ( action_flags & CONVERT_TO_YUY2 )
1717 NVCopyData420(buf + (top * srcPitch) + left,
1718 buf + s2offset, buf + s3offset,
1719 dst, srcPitch, srcPitch2,
1720 line_len, nlines, npixels);
1724 unsigned char * tbuf = buf + top * srcPitch + left;
1725 unsigned char * tdst = dst;
1726 //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);
1728 for ( i=0; i < nlines; i++)
1730 memcpy(tdst, tbuf, line_len);
1734 dst += line_len * nlines;
1735 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, dst, line_len, srcPitch2, nlines, line_len);
1740 for ( i=0; i < nlines; i++)
1742 memcpy(dst, buf, line_len);
1749 BEGIN_RING(NvMemFormat,
1750 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
1751 OUT_RING (pNv->chan->gart->handle);
1752 OUT_RING (pNv->chan->vram->handle);
1755 if (action_flags & IS_YV12 && ! (action_flags & CONVERT_TO_YUY2) )
1756 { /*we start the color plane transfer separately*/
1757 BEGIN_RING(NvMemFormat,
1758 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1759 OUT_RING ((uint32_t)destination_buffer->offset + line_len * nlines);
1760 OUT_RING ((uint32_t)offset + dstPitch * nlines);
1761 OUT_RING (line_len);
1762 OUT_RING (dstPitch);
1763 OUT_RING (line_len);
1764 OUT_RING ((nlines >> 1));
1765 OUT_RING ((1<<8)|1);
1770 BEGIN_RING(NvMemFormat,
1771 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1772 OUT_RING ((uint32_t)destination_buffer->offset);
1773 OUT_RING ((uint32_t)offset /*+ DMAoffset*/);
1774 OUT_RING (line_len);
1775 OUT_RING (dstPitch);
1776 OUT_RING (line_len);
1778 OUT_RING ((1<<8)|1);
1781 if ( destination_buffer == pNv->GART )
1783 nouveau_notifier_reset(pNv->notify0, 0);
1786 nouveau_notifier_reset(pPriv->DMANotifier[pPriv->currentHostBuffer], 0);
1787 BEGIN_RING(NvMemFormat,
1788 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1789 OUT_RING (pPriv->DMANotifier[pPriv->currentHostBuffer]->handle);
1793 BEGIN_RING(NvMemFormat, NV04_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1796 BEGIN_RING(NvMemFormat, 0x100, 1);
1799 //Put back NvDmaNotifier0 for EXA
1800 BEGIN_RING(NvMemFormat,
1801 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1802 OUT_RING (pNv->notify0->handle);
1806 if ( destination_buffer == pNv->GART )
1807 if (nouveau_notifier_wait_status(pNv->notify0, 0, 0, 0))
1810 else { //GART is too small, we fallback on CPU copy
1812 video_mem_destination = pPriv->video_mem->map + (offset - (uint32_t)pPriv->video_mem->offset);
1814 if ( action_flags & IS_YV12 )
1816 if ( action_flags & CONVERT_TO_YUY2 )
1818 NVCopyData420(buf + (top * srcPitch) + left,
1819 buf + s2offset, buf + s3offset,
1820 video_mem_destination, srcPitch, srcPitch2,
1821 dstPitch, nlines, npixels);
1824 unsigned char * tbuf = buf + left + top * srcPitch;
1825 for ( i=0; i < nlines; i++)
1827 int dwords = npixels << 1;
1828 while (dwords & ~0x03)
1830 *video_mem_destination = *tbuf;
1831 *(video_mem_destination + 1) = *(tbuf + 1);
1832 *(video_mem_destination + 2) = *(tbuf + 2);
1833 *(video_mem_destination + 3) = *(tbuf + 3);
1834 video_mem_destination += 4;
1841 *(video_mem_destination + 2) = *(tbuf + 2);
1843 *(video_mem_destination + 1) = *(tbuf + 1);
1845 *video_mem_destination = *tbuf;
1848 video_mem_destination += dstPitch - (npixels << 1);
1849 tbuf += srcPitch - (npixels << 1);
1852 NVCopyNV12ColorPlanes(buf + s2offset, buf + s3offset, video_mem_destination, dstPitch, srcPitch2, nlines, line_len);
1857 for ( i=0; i < nlines; i++)
1859 int dwords = npixels << 1;
1860 while (dwords & ~0x03)
1862 *video_mem_destination = *buf;
1863 *(video_mem_destination + 1) = *(buf + 1);
1864 *(video_mem_destination + 2) = *(buf + 2);
1865 *(video_mem_destination + 3) = *(buf + 3);
1866 video_mem_destination += 4;
1873 *(video_mem_destination + 2) = *(buf + 2);
1875 *(video_mem_destination + 1) = *(buf + 1);
1877 *video_mem_destination = *buf;
1880 video_mem_destination += dstPitch - (npixels << 1);
1881 buf += srcPitch - (npixels << 1);
1889 if ( pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE )
1890 pPriv->currentHostBuffer ^= 1;
1892 if ( action_flags & USE_OVERLAY )
1894 if ( pNv->Architecture == NV_ARCH_04 )
1895 NV04PutOverlayImage(pScrn, offset, id,
1899 src_w, src_h, drw_w, drw_h,
1902 NVPutOverlayImage(pScrn, offset, ((action_flags & IS_YUY2) || (action_flags & CONVERT_TO_YUY2)) ? 0 : offset + nlines * dstPitch, id,
1906 src_w, src_h, drw_w, drw_h,
1908 pPriv->currentBuffer ^= 1;
1913 if (action_flags & USE_TEXTURE) { /* Texture adapter */
1914 int rval = NV40PutTextureImage(pScrn, offset, offset + nlines * dstPitch, id,
1918 src_w, src_h, drw_w, drw_h,
1920 if (rval != Success)
1922 } else { /* Blit adapter */
1923 NVPutBlitImage(pScrn, offset, id,
1927 src_w, src_h, drw_w, drw_h,
1936 * QueryImageAttributes
1939 * - size (memory required to store image),
1943 * depending on colorspace (id) and dimensions (w,h) of image
1947 * may be adjusted as needed
1949 * @param pScrn unused
1950 * @param id colorspace of image
1951 * @param w pointer to width of image
1952 * @param h pointer to height of image
1953 * @param pitches pitches[i] = length of a scanline in plane[i]
1954 * @param offsets offsets[i] = offset of plane i from the beginning of the image
1955 * @return size of the memory required for the XvImage queried
1958 NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1959 unsigned short *w, unsigned short *h,
1960 int *pitches, int *offsets)
1964 if (*w > IMAGE_MAX_W)
1966 if (*h > IMAGE_MAX_H)
1969 *w = (*w + 1) & ~1; // width rounded up to an even number
1976 *h = (*h + 1) & ~1; // height rounded up to an even number
1977 size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1979 pitches[0] = size; // width rounded up to a multiple of 4
1982 offsets[1] = size; // number of pixels in "rounded up" image
1983 tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1985 pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1986 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1987 size += tmp; // 5/4*number of pixels in "rounded up" image
1989 offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1990 size += tmp; // = 3/2*number of pixels in "rounded up" image
1994 size = *w << 1; // 2*width
1996 pitches[0] = size; // 2*width
1997 size *= *h; // 2*width*height
2000 size = *w << 2; // 4*width (32 bit per pixel)
2002 pitches[0] = size; // 4*width
2003 size *= *h; // 4*width*height
2013 /***** Exported offscreen surface stuff ****/
2017 NVAllocSurface(ScrnInfoPtr pScrn, int id,
2018 unsigned short w, unsigned short h,
2019 XF86SurfacePtr surface)
2021 NVPtr pNv = NVPTR(pScrn);
2022 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
2025 bpp = pScrn->bitsPerPixel >> 3;
2027 if (pPriv->grabbedByV4L)
2030 if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
2034 pPriv->pitch = ((w << 1) + 63) & ~63;
2035 size = h * pPriv->pitch / bpp;
2037 pPriv->video_mem = NVAllocateVideoMemory(pScrn,
2040 if (!pPriv->video_mem)
2046 surface->height = h;
2047 surface->pScrn = pScrn;
2048 surface->pitches = &pPriv->pitch;
2049 surface->offsets = &pPriv->offset;
2050 surface->devPrivate.ptr = (pointer)pPriv;
2053 /* grab the video */
2054 NVStopOverlay(pScrn);
2055 pPriv->videoStatus = 0;
2056 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
2057 pPriv->grabbedByV4L = TRUE;
2063 NVStopSurface(XF86SurfacePtr surface)
2065 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
2067 if (pPriv->grabbedByV4L && pPriv->videoStatus) {
2068 NVStopOverlay(surface->pScrn);
2069 pPriv->videoStatus = 0;
2076 NVFreeSurface(XF86SurfacePtr surface)
2078 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
2080 if (pPriv->grabbedByV4L) {
2081 NVStopSurface(surface);
2082 NVFreeOverlayMemory(surface->pScrn);
2083 pPriv->grabbedByV4L = FALSE;
2090 NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
2092 NVPtr pNv = NVPTR(pScrn);
2093 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
2095 return NVGetOverlayPortAttribute(pScrn, attribute,
2096 value, (pointer)pPriv);
2100 NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
2102 NVPtr pNv = NVPTR(pScrn);
2103 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
2105 return NVSetOverlayPortAttribute(pScrn, attribute,
2106 value, (pointer)pPriv);
2110 NVDisplaySurface(XF86SurfacePtr surface,
2111 short src_x, short src_y,
2112 short drw_x, short drw_y,
2113 short src_w, short src_h,
2114 short drw_w, short drw_h,
2115 RegionPtr clipBoxes)
2117 ScrnInfoPtr pScrn = surface->pScrn;
2118 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
2119 INT32 xa, xb, ya, yb;
2122 if (!pPriv->grabbedByV4L)
2125 if (src_w > (drw_w << 3))
2127 if (src_h > (drw_h << 3))
2137 dstBox.x2 = drw_x + drw_w;
2139 dstBox.y2 = drw_y + drw_h;
2141 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
2142 surface->width, surface->height))
2145 dstBox.x1 -= pScrn->frameX0;
2146 dstBox.x2 -= pScrn->frameX0;
2147 dstBox.y1 -= pScrn->frameY0;
2148 dstBox.y2 -= pScrn->frameY0;
2150 pPriv->currentBuffer = 0;
2152 NVPutOverlayImage(pScrn, surface->offsets[0], 0, surface->id,
2153 surface->pitches[0], &dstBox, xa, ya, xb, yb,
2154 surface->width, surface->height, src_w, src_h,
2155 drw_w, drw_h, clipBoxes);
2162 * this function does all the work setting up a blit port
2166 static XF86VideoAdaptorPtr
2167 NVSetupBlitVideo (ScreenPtr pScreen)
2169 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2170 NVPtr pNv = NVPTR(pScrn);
2171 XF86VideoAdaptorPtr adapt;
2172 NVPortPrivPtr pPriv;
2175 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2176 sizeof(NVPortPrivRec) +
2177 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
2181 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2183 adapt->name = "NV Video Blitter";
2184 adapt->nEncodings = 1;
2185 adapt->pEncodings = &DummyEncoding;
2186 adapt->nFormats = NUM_FORMATS_ALL;
2187 adapt->pFormats = NVFormats;
2188 adapt->nPorts = NUM_BLIT_PORTS;
2189 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2191 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
2192 for(i = 0; i < NUM_BLIT_PORTS; i++)
2193 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2195 if(pNv->WaitVSyncPossible) {
2196 adapt->pAttributes = NVBlitAttributes;
2197 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
2199 adapt->pAttributes = NULL;
2200 adapt->nAttributes = 0;
2203 adapt->pImages = NVImages;
2204 adapt->nImages = NUM_IMAGES_ALL;
2205 adapt->PutVideo = NULL;
2206 adapt->PutStill = NULL;
2207 adapt->GetVideo = NULL;
2208 adapt->GetStill = NULL;
2209 adapt->StopVideo = NVStopBlitVideo;
2210 adapt->SetPortAttribute = NVSetBlitPortAttribute;
2211 adapt->GetPortAttribute = NVGetBlitPortAttribute;
2212 adapt->QueryBestSize = NVQueryBestSize;
2213 adapt->PutImage = NVPutImage;
2214 adapt->QueryImageAttributes = NVQueryImageAttributes;
2216 pPriv->videoStatus = 0;
2217 pPriv->grabbedByV4L = FALSE;
2218 pPriv->blitter = TRUE;
2219 pPriv->texture = FALSE;
2220 pPriv->doubleBuffer = FALSE;
2221 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
2223 pNv->blitAdaptor = adapt;
2224 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
2230 * NVSetupOverlayVideo
2231 * this function does all the work setting up an overlay port
2233 * @return overlay port
2234 * @see NVResetVideo(ScrnInfoPtr pScrn)
2236 static XF86VideoAdaptorPtr
2237 NVSetupOverlayVideoAdapter(ScreenPtr pScreen)
2239 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2240 NVPtr pNv = NVPTR(pScrn);
2241 XF86VideoAdaptorPtr adapt;
2242 NVPortPrivPtr pPriv;
2244 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2245 sizeof(NVPortPrivRec) +
2246 sizeof(DevUnion)))) {
2250 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2251 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
2252 adapt->name = "NV Video Overlay";
2253 adapt->nEncodings = 1;
2254 adapt->pEncodings = &DummyEncoding;
2255 adapt->nFormats = NUM_FORMATS_ALL;
2256 adapt->pFormats = NVFormats;
2258 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2260 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
2261 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
2263 adapt->pAttributes = (pNv->Architecture != NV_ARCH_04) ? NVOverlayAttributes : NV04OverlayAttributes;
2264 adapt->nAttributes = (pNv->Architecture != NV_ARCH_04) ? NUM_OVERLAY_ATTRIBUTES : NUM_NV04_OVERLAY_ATTRIBUTES;
2265 adapt->pImages = NVImages;
2266 adapt->nImages = NUM_IMAGES_YUV;
2267 adapt->PutVideo = NULL;
2268 adapt->PutStill = NULL;
2269 adapt->GetVideo = NULL;
2270 adapt->GetStill = NULL;
2271 adapt->StopVideo = NVStopOverlayVideo;
2272 adapt->SetPortAttribute = NVSetOverlayPortAttribute;
2273 adapt->GetPortAttribute = NVGetOverlayPortAttribute;
2274 adapt->QueryBestSize = NVQueryBestSize;
2275 adapt->PutImage = NVPutImage;
2276 adapt->QueryImageAttributes = NVQueryImageAttributes;
2278 pPriv->videoStatus = 0;
2279 pPriv->currentBuffer = 0;
2280 pPriv->grabbedByV4L = FALSE;
2281 pPriv->blitter = FALSE;
2282 pPriv->texture = FALSE;
2283 if ( pNv->Architecture == NV_ARCH_04 )
2284 pPriv->doubleBuffer = 0;
2286 NVSetPortDefaults (pScrn, pPriv);
2288 /* gotta uninit this someplace */
2289 REGION_NULL(pScreen, &pPriv->clip);
2291 pNv->overlayAdaptor = adapt;
2293 xvColorKey = MAKE_ATOM("XV_COLORKEY");
2294 if ( pNv->Architecture != NV_ARCH_04 )
2296 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
2297 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
2298 xvContrast = MAKE_ATOM("XV_CONTRAST");
2299 xvSaturation = MAKE_ATOM("XV_SATURATION");
2300 xvHue = MAKE_ATOM("XV_HUE");
2301 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
2302 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
2303 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
2304 xvOnCRTCNb = MAKE_ATOM("XV_ON_CRTC_NB");
2307 NVResetVideo(pScrn);
2313 XF86OffscreenImageRec NVOffscreenImages[2] = {
2316 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2321 NVGetSurfaceAttribute,
2322 NVSetSurfaceAttribute,
2323 IMAGE_MAX_W, IMAGE_MAX_H,
2324 NUM_OVERLAY_ATTRIBUTES - 1,
2325 &NVOverlayAttributes[1]
2329 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
2334 NVGetSurfaceAttribute,
2335 NVSetSurfaceAttribute,
2336 IMAGE_MAX_W, IMAGE_MAX_H,
2337 NUM_OVERLAY_ATTRIBUTES - 1,
2338 &NVOverlayAttributes[1]
2343 NVInitOffscreenImages (ScreenPtr pScreen)
2345 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
2349 * NVChipsetHasOverlay
2351 * newer chips don't support overlay anymore.
2352 * overlay feature is emulated via textures.
2355 * @return true, if chipset supports overlay
2358 NVChipsetHasOverlay(NVPtr pNv)
2360 switch (pNv->Architecture) {
2361 case NV_ARCH_04: /*NV04 has a different overlay than NV10+*/
2367 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
2378 * NVSetupOverlayVideo
2379 * check if chipset supports Overlay and CompositeExtension is disabled.
2380 * if so, setup overlay port
2382 * @return overlay port
2383 * @see NVChipsetHasOverlay(NVPtr pNv)
2384 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
2385 * @see NVInitOffscreenImages(ScreenPtr pScreen)
2387 static XF86VideoAdaptorPtr
2388 NVSetupOverlayVideo(ScreenPtr pScreen)
2390 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2391 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2392 NVPtr pNv = NVPTR(pScrn);
2394 if (!NVChipsetHasOverlay(pNv))
2397 overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen);
2398 if (overlayAdaptor && pNv->Architecture != NV_ARCH_04 )
2399 NVInitOffscreenImages(pScreen); //I am not sure what this call does.
2402 if (!noCompositeExtension) {
2403 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2404 "XV: Composite is enabled, enabling overlay with smart blitter fallback\n");
2405 overlayAdaptor -> name = "NV Video Overlay with Composite";
2409 return overlayAdaptor;
2413 * NV40 texture adapter.
2416 #define NUM_TEXTURE_PORTS 32
2418 #define NUM_FORMAT_TEXTURED 2
2420 static XF86ImageRec NV40TexturedImages[NUM_FORMAT_TEXTURED] =
2427 * NV40StopTexturedVideo
2430 NV40StopTexturedVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
2435 * NVSetTexturePortAttribute
2436 * sets the attribute "attribute" of port "data" to value "value"
2437 * supported attributes:
2441 * @param attribute attribute to set
2442 * @param value value to which attribute is to be set
2443 * @param data port from which the attribute is to be set
2445 * @return Success, if setting is successful
2446 * BadValue/BadMatch, if value/attribute are invalid
2449 NVSetTexturePortAttribute(ScrnInfoPtr pScrn, Atom attribute,
2450 INT32 value, pointer data)
2452 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
2453 NVPtr pNv = NVPTR(pScrn);
2455 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
2456 if ((value < 0) || (value > 1))
2458 pPriv->SyncToVBlank = value;
2460 if (attribute == xvSetDefaults) {
2461 pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
2469 * NVGetTexturePortAttribute
2470 * reads the value of attribute "attribute" from port "data" into INT32 "*value"
2473 * @param pScrn unused
2474 * @param attribute attribute to be read
2475 * @param value value of attribute will be stored here
2476 * @param data port from which attribute will be read
2477 * @return Success, if queried attribute exists
2480 NVGetTexturePortAttribute(ScrnInfoPtr pScrn, Atom attribute,
2481 INT32 *value, pointer data)
2483 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
2485 if(attribute == xvSyncToVBlank)
2486 *value = (pPriv->SyncToVBlank) ? 1 : 0;
2495 * NV40SetupTexturedVideo
2496 * this function does all the work setting up a blit port
2498 * @return texture port
2500 static XF86VideoAdaptorPtr
2501 NV40SetupTexturedVideo (ScreenPtr pScreen)
2503 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2504 NVPtr pNv = NVPTR(pScrn);
2505 XF86VideoAdaptorPtr adapt;
2506 NVPortPrivPtr pPriv;
2509 if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2510 sizeof(NVPortPrivRec) +
2511 (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
2515 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2517 adapt->name = "NV40 Texture adapter";
2518 adapt->nEncodings = 1;
2519 adapt->pEncodings = &DummyEncodingTex;
2520 adapt->nFormats = NUM_FORMATS_ALL;
2521 adapt->pFormats = NVFormats;
2522 adapt->nPorts = NUM_TEXTURE_PORTS;
2523 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2525 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
2526 for(i = 0; i < NUM_TEXTURE_PORTS; i++)
2527 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2529 if(pNv->WaitVSyncPossible) {
2530 adapt->pAttributes = NVTexturedAttributes;
2531 adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
2533 adapt->pAttributes = NULL;
2534 adapt->nAttributes = 0;
2537 adapt->pImages = NV40TexturedImages;
2538 adapt->nImages = NUM_FORMAT_TEXTURED;
2539 adapt->PutVideo = NULL;
2540 adapt->PutStill = NULL;
2541 adapt->GetVideo = NULL;
2542 adapt->GetStill = NULL;
2543 adapt->StopVideo = NV40StopTexturedVideo;
2544 adapt->SetPortAttribute = NVSetTexturePortAttribute;
2545 adapt->GetPortAttribute = NVGetTexturePortAttribute;
2546 adapt->QueryBestSize = NVQueryBestSize;
2547 adapt->PutImage = NVPutImage;
2548 adapt->QueryImageAttributes = NVQueryImageAttributes;
2550 pPriv->videoStatus = 0;
2551 pPriv->grabbedByV4L = FALSE;
2552 pPriv->blitter = FALSE;
2553 pPriv->texture = TRUE;
2554 pPriv->doubleBuffer = FALSE;
2555 pPriv->SyncToVBlank = FALSE;
2557 pNv->textureAdaptor = adapt;
2564 * tries to initialize one new overlay port and one new blit port
2565 * and add them to the list of ports on screen "pScreen".
2568 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
2569 * @see NVSetupBlitVideo(ScreenPtr pScreen)
2571 void NVInitVideo (ScreenPtr pScreen)
2573 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2574 NVPtr pNv = NVPTR(pScrn);
2575 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
2576 XF86VideoAdaptorPtr overlayAdaptor = NULL;
2577 XF86VideoAdaptorPtr blitAdaptor = NULL;
2578 XF86VideoAdaptorPtr textureAdaptor = NULL;
2582 * Driving the blitter requires the DMA FIFO. Using the FIFO
2583 * without accel causes DMA errors. While the overlay might
2584 * might work without accel, we also disable it for now when
2585 * acceleration is disabled:
2587 if (pScrn->bitsPerPixel != 8 && pNv->Architecture < NV_ARCH_50 && !pNv->NoAccel) {
2588 overlayAdaptor = NVSetupOverlayVideo(pScreen);
2589 blitAdaptor = NVSetupBlitVideo(pScreen);
2590 if (pNv->Architecture == NV_ARCH_40)
2591 textureAdaptor = NV40SetupTexturedVideo(pScreen);
2594 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
2595 if(blitAdaptor || overlayAdaptor) {
2596 int size = num_adaptors;
2598 if(overlayAdaptor) size++;
2599 if(blitAdaptor) size++;
2601 newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
2604 memcpy(newAdaptors, adaptors, num_adaptors *
2605 sizeof(XF86VideoAdaptorPtr));
2608 if(overlayAdaptor) {
2609 newAdaptors[num_adaptors] = overlayAdaptor;
2613 if (textureAdaptor) {
2614 newAdaptors[num_adaptors] = textureAdaptor;
2619 newAdaptors[num_adaptors] = blitAdaptor;
2623 adaptors = newAdaptors;
2628 xf86XVScreenInit(pScreen, adaptors, num_adaptors);