2
* Copyright 2007 Arthur Huillet
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
11
* The above copyright notice and this permission notice shall be included in
12
* all copies or substantial portions of the Software.
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
#include <X11/extensions/Xv.h>
32
#include "dixstruct.h"
35
#include "nv_include.h"
38
#define IMAGE_MAX_W 2046
39
#define IMAGE_MAX_H 2046
41
#define TEX_IMAGE_MAX_W 4096
42
#define TEX_IMAGE_MAX_H 4096
44
#define OFF_DELAY 500 /* milliseconds */
45
#define FREE_DELAY 5000
47
#define NUM_BLIT_PORTS 16
48
#define NUM_TEXTURE_PORTS 32
51
#define NVStopOverlay(X) (((pNv->Architecture == NV_ARCH_04) ? NV04StopOverlay(X) : NV10StopOverlay(X)))
53
/* Value taken by pPriv -> currentHostBuffer when we failed to allocate the two private buffers in TT memory, so that we can catch this case
54
and attempt no other allocation afterwards (performance reasons) */
55
#define NO_PRIV_HOST_BUFFER_AVAILABLE 9999
57
/* Xv DMA notifiers status tracing */
59
XV_DMA_NOTIFIER_NOALLOC=0, //notifier not allocated
60
XV_DMA_NOTIFIER_INUSE=1,
61
XV_DMA_NOTIFIER_FREE=2, //notifier allocated, ready for use
64
/* We have six notifiers available, they are not allocated at startup */
65
static int XvDMANotifierStatus[6] = { XV_DMA_NOTIFIER_NOALLOC,
66
XV_DMA_NOTIFIER_NOALLOC,
67
XV_DMA_NOTIFIER_NOALLOC,
68
XV_DMA_NOTIFIER_NOALLOC,
69
XV_DMA_NOTIFIER_NOALLOC,
70
XV_DMA_NOTIFIER_NOALLOC };
71
static struct nouveau_notifier *XvDMANotifiers[6];
73
/* NVPutImage action flags */
81
IS_RGB=64, //I am not sure how long we will support it
84
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
86
Atom xvBrightness, xvContrast, xvColorKey, xvSaturation;
87
Atom xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer;
88
Atom xvITURBT709, xvSyncToVBlank, xvOnCRTCNb;
90
/* client libraries expect an encoding */
91
static XF86VideoEncodingRec DummyEncoding =
95
IMAGE_MAX_W, IMAGE_MAX_H,
99
static XF86VideoEncodingRec DummyEncodingTex =
103
TEX_IMAGE_MAX_W, TEX_IMAGE_MAX_H,
107
#define NUM_FORMATS_ALL 6
109
XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
111
{15, TrueColor}, {16, TrueColor}, {24, TrueColor},
112
{15, DirectColor}, {16, DirectColor}, {24, DirectColor}
115
#define NUM_NV04_OVERLAY_ATTRIBUTES 4
116
XF86AttributeRec NV04OverlayAttributes[NUM_NV04_OVERLAY_ATTRIBUTES] =
118
{XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
119
{XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
120
{XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
121
{XvSettable , 0, 0, "XV_SET_DEFAULTS"},
125
#define NUM_NV10_OVERLAY_ATTRIBUTES 10
126
XF86AttributeRec NV10OverlayAttributes[NUM_NV10_OVERLAY_ATTRIBUTES] =
128
{XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
129
{XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
130
{XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
131
{XvSettable , 0, 0, "XV_SET_DEFAULTS"},
132
{XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
133
{XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
134
{XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
135
{XvSettable | XvGettable, 0, 360, "XV_HUE"},
136
{XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"},
137
{XvSettable | XvGettable, 0, 1, "XV_ON_CRTC_NB"},
140
#define NUM_BLIT_ATTRIBUTES 2
141
XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
143
{XvSettable , 0, 0, "XV_SET_DEFAULTS"},
144
{XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
147
#define NUM_TEXTURED_ATTRIBUTES 2
148
XF86AttributeRec NVTexturedAttributes[NUM_TEXTURED_ATTRIBUTES] =
150
{XvSettable , 0, 0, "XV_SET_DEFAULTS"},
151
{XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
155
#define NUM_IMAGES_YUV 4
156
#define NUM_IMAGES_ALL 5
158
#define FOURCC_RGB 0x0000003
159
#define XVIMAGE_RGB \
164
{ 0x03, 0x00, 0x00, 0x00, \
165
0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
169
24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
174
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}, \
178
static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
188
nv_window_belongs_to_crtc(ScrnInfoPtr pScrn, int x, int y, int w, int h)
190
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
191
NVPtr pNv = NVPTR(pScrn);
198
if (!pNv->randr12_enable) {
200
* Without RandR 1.2, we'll just return which CRTCs
203
if (pNv->crtc_active[0])
205
else if (pNv->crtc_active[1])
211
for (i = 0; i < xf86_config->num_crtc; i++) {
212
crtc = xf86_config->crtc[i];
217
if ((x < (crtc->x + crtc->mode.HDisplay)) &&
218
(y < (crtc->y + crtc->mode.VDisplay)) &&
219
((x + w) > crtc->x) &&
228
NVWaitVSync(ScrnInfoPtr pScrn, int crtc)
230
NVPtr pNv = NVPTR(pScrn);
232
BEGIN_RING(NvImageBlit, 0x0000012C, 1);
234
BEGIN_RING(NvImageBlit, 0x00000134, 1);
236
BEGIN_RING(NvImageBlit, 0x00000100, 1);
238
BEGIN_RING(NvImageBlit, 0x00000130, 1);
244
* set attributes of port "pPriv" to compiled-in (except for colorKey) defaults
245
* this function does not care about the kind of adapter the port is for
247
* @param pScrn screen to get the default colorKey from
248
* @param pPriv port to reset to defaults
251
NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
253
NVPtr pNv = NVPTR(pScrn);
255
pPriv->brightness = 0;
256
pPriv->contrast = 4096;
257
pPriv->saturation = 4096;
259
pPriv->colorKey = pNv->videoKey;
260
pPriv->autopaintColorKey = TRUE;
261
pPriv->doubleBuffer = pNv->Architecture != NV_ARCH_04;
262
pPriv->iturbt_709 = FALSE;
263
pPriv->currentHostBuffer = 0;
267
* NVXvDMANotifierAlloc
268
* allocates a notifier from the table of 6 we have
270
* @return a notifier instance or NULL on error
272
static struct nouveau_notifier *
273
NVXvDMANotifierAlloc(ScrnInfoPtr pScrn)
275
NVPtr pNv = NVPTR(pScrn);
278
for (i = 0; i < 6; i++) {
279
if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_INUSE)
282
if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_FREE) {
283
XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
284
return XvDMANotifiers[i];
287
if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_NOALLOC) {
288
if (nouveau_notifier_alloc(pNv->chan,
289
NvDmaXvNotifier0 + i,
290
1, &XvDMANotifiers[i]))
292
XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
293
return XvDMANotifiers[i];
301
* NVXvDMANotifierFree
302
* frees a notifier from the table of 6 we have
307
NVXvDMANotifierFree(ScrnInfoPtr pScrn, struct nouveau_notifier **ptarget)
309
struct nouveau_notifier *target;
312
if (!ptarget || !*ptarget)
317
for (i = 0; i < 6; i ++) {
318
if (XvDMANotifiers[i] == target)
322
XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_FREE;
326
nouveau_xv_bo_realloc(ScrnInfoPtr pScrn, unsigned flags, unsigned size,
327
struct nouveau_bo **pbo)
329
NVPtr pNv = NVPTR(pScrn);
333
if ((*pbo)->size >= size)
338
ret = nouveau_bo_new(pNv->dev, flags | NOUVEAU_BO_PIN, 0, size, pbo);
342
ret = nouveau_bo_map(*pbo, NOUVEAU_BO_RDWR);
353
* frees memory held by a given port
355
* @param pScrn screen whose port wants to free memory
356
* @param pPriv port to free memory of
359
NVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
361
if(pPriv->video_mem) {
362
nouveau_bo_del(&pPriv->video_mem);
363
pPriv->video_mem = NULL;
366
if (pPriv->TT_mem_chunk[0] && pPriv->DMANotifier[0])
367
nouveau_notifier_wait_status(pPriv->DMANotifier[0], 0, 0, 1000);
369
if (pPriv->TT_mem_chunk[1] && pPriv->DMANotifier[1])
370
nouveau_notifier_wait_status(pPriv->DMANotifier[1], 0, 0, 1000);
372
nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
373
nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
374
NVXvDMANotifierFree(pScrn, &pPriv->DMANotifier[0]);
375
NVXvDMANotifierFree(pScrn, &pPriv->DMANotifier[1]);
380
* NVFreeOverlayMemory
381
* frees memory held by the overlay port
383
* @param pScrn screen whose overlay port wants to free memory
386
NVFreeOverlayMemory(ScrnInfoPtr pScrn)
388
NVPtr pNv = NVPTR(pScrn);
389
NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
391
NVFreePortMemory(pScrn, pPriv);
393
/* "power cycle" the overlay */
394
nvWriteMC(pNv, NV_PMC_ENABLE,
395
(nvReadMC(pNv, NV_PMC_ENABLE) & 0xEFFFFFFF));
396
nvWriteMC(pNv, NV_PMC_ENABLE,
397
(nvReadMC(pNv, NV_PMC_ENABLE) | 0x10000000));
402
* frees memory held by the blit port
404
* @param pScrn screen whose blit port wants to free memory
407
NVFreeBlitMemory(ScrnInfoPtr pScrn)
409
NVPtr pNv = NVPTR(pScrn);
410
NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
412
NVFreePortMemory(pScrn, pPriv);
416
* NVVideoTimerCallback
417
* callback function which perform cleanup tasks (stop overlay, free memory).
419
* purpose and use is unknown
422
NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
424
NVPtr pNv = NVPTR(pScrn);
425
NVPortPrivPtr pOverPriv = NULL;
426
NVPortPrivPtr pBlitPriv = NULL;
427
Bool needCallback = FALSE;
432
if (pNv->overlayAdaptor) {
433
pOverPriv = GET_OVERLAY_PRIVATE(pNv);
434
if (!pOverPriv->videoStatus)
438
if (pNv->blitAdaptor) {
439
pBlitPriv = GET_BLIT_PRIVATE(pNv);
440
if (!pBlitPriv->videoStatus)
445
if (pOverPriv->videoTime < currentTime) {
446
if (pOverPriv->videoStatus & OFF_TIMER) {
447
NVStopOverlay(pScrn);
448
pOverPriv->videoStatus = FREE_TIMER;
449
pOverPriv->videoTime = currentTime + FREE_DELAY;
452
if (pOverPriv->videoStatus & FREE_TIMER) {
453
NVFreeOverlayMemory(pScrn);
454
pOverPriv->videoStatus = 0;
462
if (pBlitPriv->videoTime < currentTime) {
463
NVFreeBlitMemory(pScrn);
464
pBlitPriv->videoStatus = 0;
470
pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
473
#ifndef ExaOffscreenMarkUsed
474
extern void ExaOffscreenMarkUsed(PixmapPtr);
481
NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
483
NVPtr pNv = NVPTR(pScrn);
484
NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
486
if (pPriv->grabbedByV4L)
489
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
492
if (pPriv->videoStatus & CLIENT_VIDEO_ON)
493
NVStopOverlay(pScrn);
494
NVFreeOverlayMemory(pScrn);
495
pPriv->videoStatus = 0;
497
if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
498
pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
499
pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
500
pNv->VideoTimerCallback = NVVideoTimerCallback;
507
* used by client applications to ask the driver:
508
* how would you actually scale a video of dimensions
509
* vid_w, vid_h, if i wanted you to scale it to dimensions
511
* function stores actual scaling size in pointers p_w, p_h.
514
* @param pScrn unused
515
* @param motion unused
516
* @param vid_w width of source video
517
* @param vid_h height of source video
518
* @param drw_w desired scaled width as requested by client
519
* @param drw_h desired scaled height as requested by client
520
* @param p_w actual scaled width as the driver is capable of
521
* @param p_h actual scaled height as the driver is capable of
525
NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
526
short vid_w, short vid_h,
527
short drw_w, short drw_h,
528
unsigned int *p_w, unsigned int *p_h,
531
if(vid_w > (drw_w << 3))
533
if(vid_h > (drw_h << 3))
542
* used to convert YV12 to YUY2 for the blitter and NV04 overlay.
543
* The U and V samples generated are linearly interpolated on the vertical
544
* axis for better quality
546
* @param src1 source buffer of luma
547
* @param src2 source buffer of chroma1
548
* @param src3 source buffer of chroma2
549
* @param dst1 destination buffer
550
* @param srcPitch pitch of src1
551
* @param srcPitch2 pitch of src2, src3
552
* @param dstPitch pitch of dst1
553
* @param h number of lines to copy
554
* @param w length of lines to copy
557
NVCopyData420(unsigned char *src1, unsigned char *src2, unsigned char *src3,
558
unsigned char *dst1, int srcPitch, int srcPitch2, int dstPitch,
565
#define su(X) (((j & 1) && j < (h-1)) ? ((unsigned)((signed int)s2[X] + \
566
(signed int)(s2 + srcPitch2)[X]) / 2) : (s2[X]))
567
#define sv(X) (((j & 1) && j < (h-1)) ? ((unsigned)((signed int)s3[X] + \
568
(signed int)(s3 + srcPitch2)[X]) / 2) : (s3[X]))
572
for (j = 0; j < h; j++) {
574
s1 = src1; s2 = src2; s3 = src3;
578
#if X_BYTE_ORDER == X_BIG_ENDIAN
579
dst[0] = (s1[0] << 24) | (s1[1] << 8) | (sv(0) << 16) | su(0);
580
dst[1] = (s1[2] << 24) | (s1[3] << 8) | (sv(1) << 16) | su(1);
581
dst[2] = (s1[4] << 24) | (s1[5] << 8) | (sv(2) << 16) | su(2);
582
dst[3] = (s1[6] << 24) | (s1[7] << 8) | (sv(3) << 16) | su(3);
584
dst[0] = s1[0] | (s1[1] << 16) | (sv(0) << 8) | (su(0) << 24);
585
dst[1] = s1[2] | (s1[3] << 16) | (sv(1) << 8) | (su(1) << 24);
586
dst[2] = s1[4] | (s1[5] << 16) | (sv(2) << 8) | (su(2) << 24);
587
dst[3] = s1[6] | (s1[7] << 16) | (sv(3) << 8) | (su(3) << 24);
589
dst += 4; s2 += 4; s3 += 4; s1 += 8;
594
#if X_BYTE_ORDER == X_BIG_ENDIAN
595
dst[0] = (s1[0] << 24) | (s1[1] << 8) | (sv(0) << 16) | su(0);
597
dst[0] = s1[0] | (s1[1] << 16) | (sv(0) << 8) | (su(0) << 24);
613
* NVCopyNV12ColorPlanes
614
* Used to convert YV12 color planes to NV12 (interleaved UV) for the overlay
616
* @param src1 source buffer of chroma1
617
* @param dst1 destination buffer
618
* @param h number of lines to copy
619
* @param w length of lines to copy
620
* @param id source pixel format (YV12 or I420)
623
NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char *src2,
624
unsigned char *dst, int dstPitch, int srcPitch2,
634
for (j = 0; j < h; j++) {
635
unsigned char *us = src1;
636
unsigned char *vs = src2;
637
unsigned int *vuvud = (unsigned int *) dst;
639
for (i = 0; i < l; i++) {
640
#if X_BYTE_ORDER == X_BIG_ENDIAN
641
*vuvud++ = (vs[0]<<24) | (us[0]<<16) | (vs[1]<<8) | us[1];
643
*vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24);
650
unsigned short *vud = (unsigned short *) vuvud;
652
*vud = vs[0] | (us[0]<<8);
664
NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 *xa, INT32 *xb,
665
INT32 *ya, INT32 *yb, short *src_x, short *src_y,
666
short *src_w, short *src_h, short *drw_x, short *drw_y,
667
short *drw_w, short *drw_h, int *left, int *top, int *right,
668
int *bottom, BoxRec *dstBox, int *npixels, int *nlines,
669
RegionPtr clipBoxes, short width, short height)
671
NVPtr pNv = NVPTR(pScrn);
673
if (action_flags & USE_OVERLAY) {
674
switch (pNv->Architecture) {
676
/* NV0x overlay can't scale down. at all. */
683
/* According to DirectFB, NV3x can't scale down by
686
if (*drw_w < (*src_w) >> 1)
688
if (*drw_h < (*src_h) >> 1)
691
default: /*NV10, NV20*/
692
/* NV1x overlay can't scale down by a ratio > 8 */
693
if (*drw_w < (*src_w) >> 3)
694
*drw_w = *src_w >> 3;
695
if (*drw_h < (*src_h >> 3))
696
*drw_h = *src_h >> 3;
702
*xb = *src_x + *src_w;
704
*yb = *src_y + *src_h;
707
dstBox->x2 = *drw_x + *drw_w;
709
dstBox->y2 = *drw_y + *drw_h;
711
/* In randr 1.2 mode VIDEO_CLIP_TO_VIEWPORT is broken (hence it is not
712
* set in the overlay adapter flags) since pScrn->frame{X,Y}1 do not get
713
* updated. Hence manual clipping against the CRTC dimensions
715
if (pNv->randr12_enable && action_flags & USE_OVERLAY) {
716
NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
717
unsigned id = pPriv->overlayCRTC;
718
xf86CrtcPtr crtc = XF86_CRTC_CONFIG_PTR(pScrn)->crtc[id];
724
VPBox.x2 = crtc->x + crtc->mode.HDisplay;
725
VPBox.y2 = crtc->y + crtc->mode.VDisplay;
727
REGION_INIT(pScreen, &VPReg, &VPBox, 1);
728
REGION_INTERSECT(pScreen, clipBoxes, clipBoxes, &VPReg);
729
REGION_UNINIT(pScreen, &VPReg);
732
if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
736
if (action_flags & USE_OVERLAY) {
737
if (!pNv->randr12_enable) {
738
dstBox->x1 -= pScrn->frameX0;
739
dstBox->x2 -= pScrn->frameX0;
740
dstBox->y1 -= pScrn->frameY0;
741
dstBox->y2 -= pScrn->frameY0;
743
xf86CrtcConfigPtr xf86_config =
744
XF86_CRTC_CONFIG_PTR(pScrn);
745
NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
747
dstBox->x1 -= xf86_config->crtc[pPriv->overlayCRTC]->x;
748
dstBox->x2 -= xf86_config->crtc[pPriv->overlayCRTC]->x;
749
dstBox->y1 -= xf86_config->crtc[pPriv->overlayCRTC]->y;
750
dstBox->y2 -= xf86_config->crtc[pPriv->overlayCRTC]->y;
754
/* Convert fixed point to integer, as xf86XVClipVideoHelper probably
755
* turns its parameter into fixed point values
765
*right = (*xb) >> 16;
769
*bottom = (*yb) >> 16;
770
if (*bottom > height)
773
if (action_flags & IS_YV12) {
774
/* even "left", even "top", even number of pixels per line
775
* and even number of lines
778
*npixels = ((*right + 1) & ~1) - *left;
780
*nlines = ((*bottom + 1) & ~1) - *top;
782
if (action_flags & IS_YUY2) {
785
/* even number of pixels per line */
786
*npixels = ((*right + 1) & ~1) - *left;
787
*nlines = *bottom - *top;
791
if (action_flags & IS_RGB) {
792
*npixels = *right - *left;
793
*nlines = *bottom - *top;
802
NV_calculate_pitches_and_mem_size(int action_flags, int *srcPitch,
803
int *srcPitch2, int *dstPitch, int *s2offset,
804
int *s3offset, int *newFBSize, int *newTTSize,
805
int *line_len, int npixels, int nlines,
806
int width, int height)
810
if (action_flags & IS_YV12) {
811
*srcPitch = (width + 3) & ~3; /* of luma */
812
*s2offset = *srcPitch * height;
813
*srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/
814
*s3offset = (*srcPitch2 * (height >> 1)) + *s2offset;
815
*dstPitch = (npixels + 63) & ~63; /*luma and chroma pitch*/
817
*newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
818
*newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
820
if (action_flags & IS_YUY2) {
821
*srcPitch = width << 1; /* one luma, one chroma per pixel */
822
*dstPitch = ((npixels << 1) + 63) & ~63;
823
*line_len = npixels << 1;
824
*newFBSize = nlines * *dstPitch;
825
*newTTSize = nlines * *line_len;
827
if (action_flags & IS_RGB) {
828
/* one R, one G, one B, one X per pixel */
829
*srcPitch = width << 2;
830
*dstPitch = ((npixels << 2) + 63) & ~63;
831
*line_len = npixels << 2;
832
*newFBSize = nlines * *dstPitch;
833
*newTTSize = nlines * *dstPitch;
836
if (action_flags & CONVERT_TO_YUY2) {
837
*dstPitch = ((npixels << 1) + 63) & ~63;
838
*line_len = npixels << 1;
839
*newFBSize = nlines * *dstPitch;
840
*newTTSize = nlines * *line_len;
843
if (action_flags & SWAP_UV) {
844
/* I420 swaps U and V */
846
*s2offset = *s3offset;
850
/* Overlay double buffering... */
851
if (action_flags & USE_OVERLAY)
859
* NV_set_action_flags
860
* This function computes the action flags from the input image,
861
* that is, it decides what NVPutImage and its helpers must do.
862
* This eases readability by avoiding lots of switch-case statements in the
866
NV_set_action_flags(ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv,
867
int id, short drw_x, short drw_y, short drw_w, short drw_h,
870
NVPtr pNv = NVPTR(pScrn);
872
#define USING_OVERLAY (*action_flags & USE_OVERLAY)
873
#define USING_TEXTURE (*action_flags & USE_TEXTURE)
874
#define USING_BLITTER ((!(*action_flags & USE_OVERLAY)) && \
875
(!(*action_flags & USE_TEXTURE)))
879
/* Pixel format-related bits */
880
if (id == FOURCC_YUY2 || id == FOURCC_UYVY)
881
*action_flags |= IS_YUY2;
883
if (id == FOURCC_YV12 || id == FOURCC_I420)
884
*action_flags |= IS_YV12;
886
if (id == FOURCC_RGB) /*How long will we support it?*/
887
*action_flags |= IS_RGB;
889
if (id == FOURCC_I420) /* I420 is YV12 with swapped UV */
890
*action_flags |= SWAP_UV;
892
/* Desired adapter */
893
if (!pPriv->blitter && !pPriv->texture)
894
*action_flags |= USE_OVERLAY;
896
if (!pPriv->blitter && pPriv->texture)
897
*action_flags |= USE_TEXTURE;
899
/* Adapter fallbacks (when the desired one can't be used)*/
902
PixmapPtr ppix = NVGetDrawablePixmap(pDraw);
904
if (!NVExaPixmapIsOnscreen(ppix))
905
*action_flags &= ~USE_OVERLAY;
909
if (USING_OVERLAY && pNv->randr12_enable) {
910
char crtc = nv_window_belongs_to_crtc(pScrn, drw_x, drw_y,
913
if ((crtc & (1 << 0)) && (crtc & (1 << 1))) {
914
/* The overlay cannot be used on two CRTCs at a time,
915
* so we need to fallback on the blitter
917
*action_flags &= ~USE_OVERLAY;
919
if ((crtc & (1 << 0))) {
920
/* We need to put the overlay on CRTC0 - if it's not
923
if (pPriv->overlayCRTC == 1) {
924
NVWriteCRTC(pNv, 0, NV_CRTC_FSEL,
925
NVReadCRTC(pNv, 0, NV_CRTC_FSEL) |
926
NV_CRTC_FSEL_OVERLAY);
927
NVWriteCRTC(pNv, 1, NV_CRTC_FSEL,
928
NVReadCRTC(pNv, 1, NV_CRTC_FSEL) &
929
~NV_CRTC_FSEL_OVERLAY);
930
pPriv->overlayCRTC = 0;
933
if ((crtc & (1 << 1))) {
934
if (pPriv->overlayCRTC == 0) {
935
NVWriteCRTC(pNv, 1, NV_CRTC_FSEL,
936
NVReadCRTC(pNv, 1, NV_CRTC_FSEL) |
937
NV_CRTC_FSEL_OVERLAY);
938
NVWriteCRTC(pNv, 0, NV_CRTC_FSEL,
939
NVReadCRTC(pNv, 0, NV_CRTC_FSEL) &
940
~NV_CRTC_FSEL_OVERLAY);
941
pPriv->overlayCRTC = 1;
945
if (XF86_CRTC_CONFIG_PTR(pScrn)->crtc[pPriv->overlayCRTC]
946
->rotation != RR_Rotate_0)
947
*action_flags &= ~USE_OVERLAY;
950
/* At this point the adapter we're going to use is _known_.
951
* You cannot change it now.
954
/* Card/adapter format restrictions */
956
/* The blitter does not handle YV12 natively */
957
if (id == FOURCC_YV12 || id == FOURCC_I420)
958
*action_flags |= CONVERT_TO_YUY2;
961
if (USING_OVERLAY && (pNv->Architecture == NV_ARCH_04)) {
962
/* NV04-05 don't support YV12, only YUY2 and ITU-R BT.601 */
963
if (*action_flags & IS_YV12)
964
*action_flags |= CONVERT_TO_YUY2;
967
if (USING_OVERLAY && (pNv->Architecture == NV_ARCH_10 ||
968
pNv->Architecture == NV_ARCH_20)) {
969
/* No YV12 overlay on NV10, 11, 15, 20, NFORCE */
970
switch (pNv->Chipset & 0xfff0) {
974
case CHIPSET_NFORCE: /*XXX: unsure about nforce*/
976
*action_flags |= CONVERT_TO_YUY2;
987
* PutImage is "the" important function of the Xv extension.
988
* a client (e.g. video player) calls this function for every
989
* image (of the video) to be displayed. this function then
990
* scales and displays the image.
992
* @param pScrn screen which hold the port where the image is put
993
* @param src_x source point in the source image to start displaying from
994
* @param src_y see above
995
* @param src_w width of the source image to display
996
* @param src_h see above
997
* @param drw_x screen point to display to
999
* @param drw_w width of the screen drawable
1001
* @param id pixel format of image
1002
* @param buf pointer to buffer containing the source image
1003
* @param width total width of the source image we are passed
1005
* @param Sync unused
1006
* @param clipBoxes ??
1007
* @param data pointer to port
1008
* @param pDraw drawable pointer
1011
NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x,
1012
short drw_y, short src_w, short src_h, short drw_w, short drw_h,
1013
int id, unsigned char *buf, short width, short height,
1014
Bool Sync, RegionPtr clipBoxes, pointer data, DrawablePtr pDraw)
1016
NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
1017
NVPtr pNv = NVPTR(pScrn);
1020
INT32 xa = 0, xb = 0, ya = 0, yb = 0;
1021
/* size to allocate in VRAM and in GART respectively */
1022
int newFBSize = 0, newTTSize = 0;
1023
/* card VRAM offset, source offsets for U and V planes */
1024
int offset = 0, s2offset = 0, s3offset = 0;
1025
/* source pitch, source pitch of U and V planes in case of YV12,
1026
* VRAM destination pitch
1028
int srcPitch = 0, srcPitch2 = 0, dstPitch = 0;
1029
/* position of the given source data (using src_*), number of pixels
1030
* and lines we are interested in
1032
int top = 0, left = 0, right = 0, bottom = 0, npixels = 0, nlines = 0;
1036
int line_len = 0; /* length of a line, like npixels, but in bytes */
1037
struct nouveau_bo *destination_buffer = NULL;
1038
int action_flags; /* what shall we do? */
1042
if (pPriv->grabbedByV4L)
1046
NV_set_action_flags(pScrn, pDraw, pPriv, id, drw_x, drw_y, drw_w,
1047
drw_h, &action_flags);
1049
if (NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
1050
&src_x, &src_y, &src_w, &src_h,
1051
&drw_x, &drw_y, &drw_w, &drw_h,
1052
&left, &top, &right, &bottom, &dstBox,
1053
&npixels, &nlines, clipBoxes, width, height))
1056
if (NV_calculate_pitches_and_mem_size(action_flags, &srcPitch,
1057
&srcPitch2, &dstPitch, &s2offset,
1058
&s3offset, &newFBSize, &newTTSize,
1059
&line_len, npixels, nlines,
1061
return BadImplementation;
1063
/* There are some cases (tvtime with overscan for example) where the
1064
* input image is larger (width/height) than the source rectangle for
1065
* the overlay (src_w, src_h). In those cases, we try to do something
1066
* optimal by uploading only the necessary data.
1068
if (action_flags & IS_YUY2 || action_flags & IS_RGB)
1069
buf += (top * srcPitch) + left;
1071
if (action_flags & IS_YV12) {
1072
tmp = ((top >> 1) * srcPitch2) + (left >> 1);
1077
ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_VRAM, newFBSize,
1082
/* The overlay supports hardware double buffering. We handle this here*/
1084
if (pPriv->doubleBuffer) {
1085
int mask = 1 << (pPriv->currentBuffer << 2);
1087
/* overwrite the newest buffer if there's not one free */
1088
if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) {
1089
if (!pPriv->currentBuffer)
1090
offset += newFBSize >> 1;
1093
if (pPriv->currentBuffer)
1094
offset += newFBSize >> 1;
1098
/* Now we take a decision regarding the way we send the data to the
1101
* Either we use double buffering of "private" TT memory
1102
* Either we rely on X's GARTScratch
1103
* Either we fallback on CPU copy
1106
/* Try to allocate host-side double buffers, unless we have already
1110
/* We take only nlines * line_len bytes - that is, only the pixel
1111
* data we are interested in - because the stuff in the GART is
1112
* written contiguously
1114
if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE) {
1115
ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_GART, newTTSize,
1116
&pPriv->TT_mem_chunk[0]);
1118
ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_GART,
1120
&pPriv->TT_mem_chunk[1]);
1122
nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1123
pPriv->currentHostBuffer =
1124
NO_PRIV_HOST_BUFFER_AVAILABLE;
1127
pPriv->currentHostBuffer =
1128
NO_PRIV_HOST_BUFFER_AVAILABLE;
1132
if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE) {
1133
destination_buffer =
1134
pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
1136
/* We know where we are going to write, but we are not sure
1137
* yet whether we can do it directly, because the card could
1138
* be working on the buffer for the last-but-one frame. So we
1139
* check if we have a notifier ready or not.
1141
* If we do, then we must wait for it before overwriting the
1142
* buffer. Else we need one, so we call the Xv notifier
1145
if (pPriv->DMANotifier[pPriv->currentHostBuffer]) {
1146
struct nouveau_notifier *n =
1147
pPriv->DMANotifier[pPriv->currentHostBuffer];
1149
if (nouveau_notifier_wait_status(n, 0, 0, 0))
1152
pPriv->DMANotifier[pPriv->currentHostBuffer] =
1153
NVXvDMANotifierAlloc(pScrn);
1155
if (!pPriv->DMANotifier[pPriv->currentHostBuffer]) {
1156
/* In case we are out of notifiers (then our
1157
* guy is watching 3 movies at a time!!), we
1158
* fallback on global GART, and free the
1159
* private buffers. I know that's a lot of code
1160
* but I believe it's necessary to properly
1161
* handle all the cases
1163
xf86DrvMsg(0, X_ERROR,
1164
"Ran out of Xv notifiers!\n");
1165
nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
1166
pPriv->TT_mem_chunk[0] = NULL;
1167
nouveau_bo_del(&pPriv->TT_mem_chunk[1]);
1168
pPriv->TT_mem_chunk[1] = NULL;
1169
pPriv->currentHostBuffer =
1170
NO_PRIV_HOST_BUFFER_AVAILABLE;
1175
/* Otherwise we fall back on DDX's GARTScratch */
1176
if (pPriv->currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE)
1177
destination_buffer = pNv->GART;
1179
/* If we have no GART at all... */
1180
if (!destination_buffer)
1183
if (newTTSize <= destination_buffer->size) {
1184
unsigned char *dst = destination_buffer->map;
1187
/* Upload to GART */
1188
if (action_flags & IS_YV12) {
1189
if (action_flags & CONVERT_TO_YUY2) {
1190
NVCopyData420(buf + (top * srcPitch) + left,
1191
buf + s2offset, buf + s3offset,
1192
dst, srcPitch, srcPitch2,
1193
line_len, nlines, npixels);
1196
unsigned char *tbuf = buf + top *
1198
unsigned char *tdst = dst;
1201
for (i = 0; i < nlines; i++) {
1202
memcpy(tdst, tbuf, line_len);
1206
dst += line_len * nlines;
1208
NVCopyNV12ColorPlanes(buf + s2offset,
1209
buf + s3offset, dst,
1210
line_len, srcPitch2,
1214
for (i = 0; i < nlines; i++) {
1215
memcpy(dst, buf, line_len);
1221
BEGIN_RING(NvMemFormat,
1222
NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
1223
OUT_RING (pNv->chan->gart->handle);
1224
OUT_RING (pNv->chan->vram->handle);
1227
if ( (action_flags & IS_YV12) &&
1228
!(action_flags & CONVERT_TO_YUY2)) {
1229
/* we start the color plane transfer separately */
1231
BEGIN_RING(NvMemFormat,
1232
NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1233
OUT_RELOCl(destination_buffer, line_len * nlines,
1234
NOUVEAU_BO_GART | NOUVEAU_BO_RD);
1235
OUT_RELOCl(pPriv->video_mem, offset + dstPitch * nlines,
1236
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
1237
OUT_RING (line_len);
1238
OUT_RING (dstPitch);
1239
OUT_RING (line_len);
1240
OUT_RING ((nlines >> 1));
1241
OUT_RING ((1<<8)|1);
1246
BEGIN_RING(NvMemFormat,
1247
NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1248
OUT_RELOCl(destination_buffer, 0,
1249
NOUVEAU_BO_GART | NOUVEAU_BO_RD);
1250
OUT_RELOCl(pPriv->video_mem, offset,
1251
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
1252
OUT_RING (line_len);
1253
OUT_RING (dstPitch);
1254
OUT_RING (line_len);
1256
OUT_RING ((1<<8)|1);
1259
if (destination_buffer == pNv->GART) {
1260
nouveau_notifier_reset(pNv->notify0, 0);
1262
struct nouveau_notifier *n =
1263
pPriv->DMANotifier[pPriv->currentHostBuffer];
1265
nouveau_notifier_reset(n, 0);
1267
BEGIN_RING(NvMemFormat,
1268
NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1269
OUT_RING (n->handle);
1273
BEGIN_RING(NvMemFormat, NV04_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
1275
BEGIN_RING(NvMemFormat, 0x100, 1);
1278
/* Put back NvDmaNotifier0 for EXA */
1279
BEGIN_RING(NvMemFormat,
1280
NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
1281
OUT_RING (pNv->notify0->handle);
1285
if (destination_buffer == pNv->GART) {
1286
if (nouveau_notifier_wait_status(pNv->notify0, 0, 0, 0))
1292
map = pPriv->video_mem->map + offset;
1294
if (action_flags & IS_YV12) {
1295
if (action_flags & CONVERT_TO_YUY2) {
1296
NVCopyData420(buf + (top * srcPitch) + left,
1297
buf + s2offset, buf + s3offset,
1298
map, srcPitch, srcPitch2,
1299
dstPitch, nlines, npixels);
1301
unsigned char *tbuf =
1302
buf + left + top * srcPitch;
1304
for (i = 0; i < nlines; i++) {
1305
int dwords = npixels << 1;
1307
while (dwords & ~0x03) {
1309
*(map + 1) = *(tbuf + 1);
1310
*(map + 2) = *(tbuf + 2);
1311
*(map + 3) = *(tbuf + 3);
1318
case 3: *(map + 2) = *(tbuf + 2);
1319
case 2: *(map + 1) = *(tbuf + 1);
1320
case 1: *map = *tbuf;
1323
map += dstPitch - (npixels << 1);
1324
tbuf += srcPitch - (npixels << 1);
1327
NVCopyNV12ColorPlanes(buf + s2offset,
1329
map, dstPitch, srcPitch2,
1334
for (i = 0; i < nlines; i++) {
1335
int dwords = npixels << 1;
1337
while (dwords & ~0x03) {
1339
*(map + 1) = *(buf + 1);
1340
*(map + 2) = *(buf + 2);
1341
*(map + 3) = *(buf + 3);
1348
case 3: *(map + 2) = *(buf + 2);
1349
case 2: *(map + 1) = *(buf + 1);
1350
case 1: *map = *buf;
1353
map += dstPitch - (npixels << 1);
1354
buf += srcPitch - (npixels << 1);
1362
if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE)
1363
pPriv->currentHostBuffer ^= 1;
1365
/* If we're not using the hw overlay, we're rendering into a pixmap
1366
* and need to take a couple of additional steps...
1368
if (!(action_flags & USE_OVERLAY)) {
1369
ppix = NVGetDrawablePixmap(pDraw);
1371
/* Ensure pixmap is in offscreen memory */
1372
exaMoveInPixmap(ppix);
1373
ExaOffscreenMarkUsed(ppix);
1376
/* Convert screen coords to pixmap coords */
1377
if (ppix->screen_x || ppix->screen_y) {
1378
REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
1379
-ppix->screen_x, -ppix->screen_y);
1380
dstBox.x1 -= ppix->screen_x;
1381
dstBox.x2 -= ppix->screen_x;
1382
dstBox.y1 -= ppix->screen_y;
1383
dstBox.y2 -= ppix->screen_y;
1386
/* Damage tracking */
1387
DamageDamageRegion(&ppix->drawable, clipBoxes);
1391
if (action_flags & USE_OVERLAY) {
1392
if (pNv->Architecture == NV_ARCH_04) {
1393
NV04PutOverlayImage(pScrn, pPriv->video_mem, offset,
1394
id, dstPitch, &dstBox, 0, 0,
1395
xb, yb, npixels, nlines,
1396
src_w, src_h, drw_w, drw_h,
1399
unsigned uvoffset = 0;
1401
if (action_flags & (IS_YUY2 | CONVERT_TO_YUY2))
1402
uvoffset = offset + nlines * dstPitch;
1404
NV10PutOverlayImage(pScrn, pPriv->video_mem, offset,
1405
uvoffset, id, dstPitch, &dstBox,
1407
npixels, nlines, src_w, src_h,
1408
drw_w, drw_h, clipBoxes);
1411
pPriv->currentBuffer ^= 1;
1413
if (action_flags & USE_TEXTURE) {
1414
int ret = BadImplementation;
1416
if (pNv->Architecture == NV_ARCH_30) {
1417
ret = NV30PutTextureImage(pScrn, pPriv->video_mem,
1419
offset + nlines * dstPitch,
1420
id, dstPitch, &dstBox, 0, 0,
1421
xb, yb, npixels, nlines,
1422
src_w, src_h, drw_w, drw_h,
1423
clipBoxes, ppix, pPriv);
1425
if (pNv->Architecture == NV_ARCH_40) {
1426
ret = NV40PutTextureImage(pScrn, pPriv->video_mem,
1428
offset + nlines * dstPitch,
1429
id, dstPitch, &dstBox, 0, 0,
1430
xb, yb, npixels, nlines,
1431
src_w, src_h, drw_w, drw_h,
1432
clipBoxes, ppix, pPriv);
1438
NVPutBlitImage(pScrn, pPriv->video_mem, offset, id, dstPitch,
1439
&dstBox, 0, 0, xb, yb, npixels, nlines,
1440
src_w, src_h, drw_w, drw_h, clipBoxes, ppix);
1447
* QueryImageAttributes
1450
* - size (memory required to store image),
1454
* depending on colorspace (id) and dimensions (w,h) of image
1458
* may be adjusted as needed
1460
* @param pScrn unused
1461
* @param id colorspace of image
1462
* @param w pointer to width of image
1463
* @param h pointer to height of image
1464
* @param pitches pitches[i] = length of a scanline in plane[i]
1465
* @param offsets offsets[i] = offset of plane i from the beginning of the image
1466
* @return size of the memory required for the XvImage queried
1469
NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1470
unsigned short *w, unsigned short *h,
1471
int *pitches, int *offsets)
1475
if (*w > IMAGE_MAX_W)
1477
if (*h > IMAGE_MAX_H)
1480
*w = (*w + 1) & ~1; // width rounded up to an even number
1487
*h = (*h + 1) & ~1; // height rounded up to an even number
1488
size = (*w + 3) & ~3; // width rounded up to a multiple of 4
1490
pitches[0] = size; // width rounded up to a multiple of 4
1493
offsets[1] = size; // number of pixels in "rounded up" image
1494
tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
1496
pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
1497
tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
1498
size += tmp; // 5/4*number of pixels in "rounded up" image
1500
offsets[2] = size; // 5/4*number of pixels in "rounded up" image
1501
size += tmp; // = 3/2*number of pixels in "rounded up" image
1505
size = *w << 1; // 2*width
1507
pitches[0] = size; // 2*width
1508
size *= *h; // 2*width*height
1511
size = *w << 2; // 4*width (32 bit per pixel)
1513
pitches[0] = size; // 4*width
1514
size *= *h; // 4*width*height
1524
/***** Exported offscreen surface stuff ****/
1528
NVAllocSurface(ScrnInfoPtr pScrn, int id,
1529
unsigned short w, unsigned short h,
1530
XF86SurfacePtr surface)
1532
NVPtr pNv = NVPTR(pScrn);
1533
NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1536
bpp = pScrn->bitsPerPixel >> 3;
1538
if (pPriv->grabbedByV4L)
1541
if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
1545
pPriv->pitch = ((w << 1) + 63) & ~63;
1546
size = h * pPriv->pitch / bpp;
1548
ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_VRAM, size,
1555
surface->height = h;
1556
surface->pScrn = pScrn;
1557
surface->pitches = &pPriv->pitch;
1558
surface->offsets = &pPriv->offset;
1559
surface->devPrivate.ptr = (pointer)pPriv;
1562
/* grab the video */
1563
NVStopOverlay(pScrn);
1564
pPriv->videoStatus = 0;
1565
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1566
pPriv->grabbedByV4L = TRUE;
1572
NVStopSurface(XF86SurfacePtr surface)
1574
NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1576
if (pPriv->grabbedByV4L && pPriv->videoStatus) {
1577
NV10StopOverlay(surface->pScrn);
1578
pPriv->videoStatus = 0;
1585
NVFreeSurface(XF86SurfacePtr surface)
1587
NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1589
if (pPriv->grabbedByV4L) {
1590
NVStopSurface(surface);
1591
NVFreeOverlayMemory(surface->pScrn);
1592
pPriv->grabbedByV4L = FALSE;
1599
NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
1601
NVPtr pNv = NVPTR(pScrn);
1602
NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1604
return NV10GetOverlayPortAttribute(pScrn, attribute,
1605
value, (pointer)pPriv);
1609
NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
1611
NVPtr pNv = NVPTR(pScrn);
1612
NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
1614
return NV10SetOverlayPortAttribute(pScrn, attribute,
1615
value, (pointer)pPriv);
1619
NVDisplaySurface(XF86SurfacePtr surface,
1620
short src_x, short src_y,
1621
short drw_x, short drw_y,
1622
short src_w, short src_h,
1623
short drw_w, short drw_h,
1624
RegionPtr clipBoxes)
1626
ScrnInfoPtr pScrn = surface->pScrn;
1627
NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
1628
INT32 xa, xb, ya, yb;
1631
if (!pPriv->grabbedByV4L)
1634
if (src_w > (drw_w << 3))
1636
if (src_h > (drw_h << 3))
1646
dstBox.x2 = drw_x + drw_w;
1648
dstBox.y2 = drw_y + drw_h;
1650
if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
1651
surface->width, surface->height))
1654
dstBox.x1 -= pScrn->frameX0;
1655
dstBox.x2 -= pScrn->frameX0;
1656
dstBox.y1 -= pScrn->frameY0;
1657
dstBox.y2 -= pScrn->frameY0;
1659
pPriv->currentBuffer = 0;
1661
NV10PutOverlayImage(pScrn, pPriv->video_mem, surface->offsets[0],
1662
0, surface->id, surface->pitches[0], &dstBox,
1663
xa, ya, xb, yb, surface->width, surface->height,
1664
src_w, src_h, drw_w, drw_h, clipBoxes);
1671
* this function does all the work setting up a blit port
1675
static XF86VideoAdaptorPtr
1676
NVSetupBlitVideo (ScreenPtr pScreen)
1678
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1679
NVPtr pNv = NVPTR(pScrn);
1680
XF86VideoAdaptorPtr adapt;
1681
NVPortPrivPtr pPriv;
1684
if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1685
sizeof(NVPortPrivRec) +
1686
(sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
1690
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1692
adapt->name = "NV Video Blitter";
1693
adapt->nEncodings = 1;
1694
adapt->pEncodings = &DummyEncoding;
1695
adapt->nFormats = NUM_FORMATS_ALL;
1696
adapt->pFormats = NVFormats;
1697
adapt->nPorts = NUM_BLIT_PORTS;
1698
adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1700
pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
1701
for(i = 0; i < NUM_BLIT_PORTS; i++)
1702
adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1704
if(pNv->WaitVSyncPossible) {
1705
adapt->pAttributes = NVBlitAttributes;
1706
adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
1708
adapt->pAttributes = NULL;
1709
adapt->nAttributes = 0;
1712
adapt->pImages = NVImages;
1713
adapt->nImages = NUM_IMAGES_ALL;
1714
adapt->PutVideo = NULL;
1715
adapt->PutStill = NULL;
1716
adapt->GetVideo = NULL;
1717
adapt->GetStill = NULL;
1718
adapt->StopVideo = NVStopBlitVideo;
1719
adapt->SetPortAttribute = NVSetBlitPortAttribute;
1720
adapt->GetPortAttribute = NVGetBlitPortAttribute;
1721
adapt->QueryBestSize = NVQueryBestSize;
1722
adapt->PutImage = NVPutImage;
1723
adapt->QueryImageAttributes = NVQueryImageAttributes;
1725
pPriv->videoStatus = 0;
1726
pPriv->grabbedByV4L = FALSE;
1727
pPriv->blitter = TRUE;
1728
pPriv->texture = FALSE;
1729
pPriv->bicubic = FALSE;
1730
pPriv->doubleBuffer = FALSE;
1731
pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
1733
pNv->blitAdaptor = adapt;
1734
xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
1740
* NVSetupOverlayVideo
1741
* this function does all the work setting up an overlay port
1743
* @return overlay port
1745
static XF86VideoAdaptorPtr
1746
NVSetupOverlayVideoAdapter(ScreenPtr pScreen)
1748
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1749
NVPtr pNv = NVPTR(pScrn);
1750
XF86VideoAdaptorPtr adapt;
1751
NVPortPrivPtr pPriv;
1753
if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1754
sizeof(NVPortPrivRec) +
1755
sizeof(DevUnion)))) {
1759
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1760
if (pNv->randr12_enable)
1761
adapt->flags = VIDEO_OVERLAID_IMAGES;
1763
adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
1764
adapt->name = "NV Video Overlay";
1765
adapt->nEncodings = 1;
1766
adapt->pEncodings = &DummyEncoding;
1767
adapt->nFormats = NUM_FORMATS_ALL;
1768
adapt->pFormats = NVFormats;
1770
adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1772
pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
1773
adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
1775
adapt->pAttributes = (pNv->Architecture != NV_ARCH_04) ? NV10OverlayAttributes : NV04OverlayAttributes;
1776
adapt->nAttributes = (pNv->Architecture != NV_ARCH_04) ? NUM_NV10_OVERLAY_ATTRIBUTES : NUM_NV04_OVERLAY_ATTRIBUTES;
1777
adapt->pImages = NVImages;
1778
adapt->nImages = NUM_IMAGES_YUV;
1779
adapt->PutVideo = NULL;
1780
adapt->PutStill = NULL;
1781
adapt->GetVideo = NULL;
1782
adapt->GetStill = NULL;
1783
adapt->StopVideo = NVStopOverlayVideo;
1784
adapt->SetPortAttribute = (pNv->Architecture != NV_ARCH_04) ? NV10SetOverlayPortAttribute : NV04SetOverlayPortAttribute;
1785
adapt->GetPortAttribute = (pNv->Architecture != NV_ARCH_04) ? NV10GetOverlayPortAttribute : NV04GetOverlayPortAttribute;
1786
adapt->QueryBestSize = NVQueryBestSize;
1787
adapt->PutImage = NVPutImage;
1788
adapt->QueryImageAttributes = NVQueryImageAttributes;
1790
pPriv->videoStatus = 0;
1791
pPriv->currentBuffer = 0;
1792
pPriv->grabbedByV4L = FALSE;
1793
pPriv->blitter = FALSE;
1794
pPriv->texture = FALSE;
1795
pPriv->bicubic = FALSE;
1797
NVSetPortDefaults (pScrn, pPriv);
1799
/* gotta uninit this someplace */
1800
REGION_NULL(pScreen, &pPriv->clip);
1802
pNv->overlayAdaptor = adapt;
1804
xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
1805
xvColorKey = MAKE_ATOM("XV_COLORKEY");
1806
xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
1807
xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
1809
if ( pNv->Architecture != NV_ARCH_04 )
1811
xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
1812
xvContrast = MAKE_ATOM("XV_CONTRAST");
1813
xvSaturation = MAKE_ATOM("XV_SATURATION");
1814
xvHue = MAKE_ATOM("XV_HUE");
1815
xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
1816
xvOnCRTCNb = MAKE_ATOM("XV_ON_CRTC_NB");
1817
NV10WriteOverlayParameters(pScrn);
1824
XF86OffscreenImageRec NVOffscreenImages[2] = {
1827
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1832
NVGetSurfaceAttribute,
1833
NVSetSurfaceAttribute,
1834
IMAGE_MAX_W, IMAGE_MAX_H,
1835
NUM_NV10_OVERLAY_ATTRIBUTES - 1,
1836
&NV10OverlayAttributes[1]
1840
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
1845
NVGetSurfaceAttribute,
1846
NVSetSurfaceAttribute,
1847
IMAGE_MAX_W, IMAGE_MAX_H,
1848
NUM_NV10_OVERLAY_ATTRIBUTES - 1,
1849
&NV10OverlayAttributes[1]
1854
NVInitOffscreenImages (ScreenPtr pScreen)
1856
xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
1860
* NVChipsetHasOverlay
1862
* newer chips don't support overlay anymore.
1863
* overlay feature is emulated via textures.
1866
* @return true, if chipset supports overlay
1869
NVChipsetHasOverlay(NVPtr pNv)
1871
switch (pNv->Architecture) {
1872
case NV_ARCH_04: /*NV04 has a different overlay than NV10+*/
1878
if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
1889
* NVSetupOverlayVideo
1890
* check if chipset supports Overla
1891
* if so, setup overlay port
1893
* @return overlay port
1894
* @see NVChipsetHasOverlay(NVPtr pNv)
1895
* @see NV10SetupOverlayVideo(ScreenPtr pScreen)
1896
* @see NVInitOffscreenImages(ScreenPtr pScreen)
1898
static XF86VideoAdaptorPtr
1899
NVSetupOverlayVideo(ScreenPtr pScreen)
1901
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1902
XF86VideoAdaptorPtr overlayAdaptor = NULL;
1903
NVPtr pNv = NVPTR(pScrn);
1905
if (!NVChipsetHasOverlay(pNv))
1908
overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen);
1909
/* I am not sure what this call does. */
1910
if (overlayAdaptor && pNv->Architecture != NV_ARCH_04 )
1911
NVInitOffscreenImages(pScreen);
1914
if (!noCompositeExtension) {
1915
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1916
"Xv: Composite is enabled, enabling overlay with "
1917
"smart blitter fallback\n");
1918
overlayAdaptor->name = "NV Video Overlay with Composite";
1922
if (pNv->randr12_enable) {
1923
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1924
"Xv: Randr12 is enabled, using overlay with smart "
1925
"blitter fallback and automatic CRTC switching\n");
1929
return overlayAdaptor;
1933
* NV30 texture adapter.
1936
#define NUM_FORMAT_TEXTURED 2
1938
static XF86ImageRec NV30TexturedImages[NUM_FORMAT_TEXTURED] =
1945
* NV30SetupTexturedVideo
1946
* this function does all the work setting up textured video port
1948
* @return texture port
1950
static XF86VideoAdaptorPtr
1951
NV30SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic)
1953
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1954
NVPtr pNv = NVPTR(pScrn);
1955
XF86VideoAdaptorPtr adapt;
1956
NVPortPrivPtr pPriv;
1959
if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1960
sizeof(NVPortPrivRec) +
1961
(sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
1965
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1968
adapt->name = "NV30 high quality adapter";
1970
adapt->name = "NV30 texture adapter";
1971
adapt->nEncodings = 1;
1972
adapt->pEncodings = &DummyEncodingTex;
1973
adapt->nFormats = NUM_FORMATS_ALL;
1974
adapt->pFormats = NVFormats;
1975
adapt->nPorts = NUM_TEXTURE_PORTS;
1976
adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1978
pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
1979
for(i = 0; i < NUM_TEXTURE_PORTS; i++)
1980
adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1982
if(pNv->WaitVSyncPossible) {
1983
adapt->pAttributes = NVTexturedAttributes;
1984
adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
1986
adapt->pAttributes = NULL;
1987
adapt->nAttributes = 0;
1990
adapt->pImages = NV30TexturedImages;
1991
adapt->nImages = NUM_FORMAT_TEXTURED;
1992
adapt->PutVideo = NULL;
1993
adapt->PutStill = NULL;
1994
adapt->GetVideo = NULL;
1995
adapt->GetStill = NULL;
1996
adapt->StopVideo = NV30StopTexturedVideo;
1997
adapt->SetPortAttribute = NV30SetTexturePortAttribute;
1998
adapt->GetPortAttribute = NV30GetTexturePortAttribute;
1999
adapt->QueryBestSize = NVQueryBestSize;
2000
adapt->PutImage = NVPutImage;
2001
adapt->QueryImageAttributes = NVQueryImageAttributes;
2003
pPriv->videoStatus = 0;
2004
pPriv->grabbedByV4L = FALSE;
2005
pPriv->blitter = FALSE;
2006
pPriv->texture = TRUE;
2007
pPriv->bicubic = bicubic;
2008
pPriv->doubleBuffer = FALSE;
2009
pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
2012
pNv->textureAdaptor[1] = adapt;
2014
pNv->textureAdaptor[0] = adapt;
2020
* NV40 texture adapter.
2023
#define NUM_FORMAT_TEXTURED 2
2025
static XF86ImageRec NV40TexturedImages[NUM_FORMAT_TEXTURED] =
2032
* NV40SetupTexturedVideo
2033
* this function does all the work setting up textured video port
2035
* @return texture port
2037
static XF86VideoAdaptorPtr
2038
NV40SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic)
2040
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2041
NVPtr pNv = NVPTR(pScrn);
2042
XF86VideoAdaptorPtr adapt;
2043
NVPortPrivPtr pPriv;
2046
if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
2047
sizeof(NVPortPrivRec) +
2048
(sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
2052
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
2055
adapt->name = "NV40 high quality adapter";
2057
adapt->name = "NV40 texture adapter";
2058
adapt->nEncodings = 1;
2059
adapt->pEncodings = &DummyEncodingTex;
2060
adapt->nFormats = NUM_FORMATS_ALL;
2061
adapt->pFormats = NVFormats;
2062
adapt->nPorts = NUM_TEXTURE_PORTS;
2063
adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2065
pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
2066
for(i = 0; i < NUM_TEXTURE_PORTS; i++)
2067
adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
2069
if(pNv->WaitVSyncPossible) {
2070
adapt->pAttributes = NVTexturedAttributes;
2071
adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
2073
adapt->pAttributes = NULL;
2074
adapt->nAttributes = 0;
2077
adapt->pImages = NV40TexturedImages;
2078
adapt->nImages = NUM_FORMAT_TEXTURED;
2079
adapt->PutVideo = NULL;
2080
adapt->PutStill = NULL;
2081
adapt->GetVideo = NULL;
2082
adapt->GetStill = NULL;
2083
adapt->StopVideo = NV40StopTexturedVideo;
2084
adapt->SetPortAttribute = NV40SetTexturePortAttribute;
2085
adapt->GetPortAttribute = NV40GetTexturePortAttribute;
2086
adapt->QueryBestSize = NVQueryBestSize;
2087
adapt->PutImage = NVPutImage;
2088
adapt->QueryImageAttributes = NVQueryImageAttributes;
2090
pPriv->videoStatus = 0;
2091
pPriv->grabbedByV4L = FALSE;
2092
pPriv->blitter = FALSE;
2093
pPriv->texture = TRUE;
2094
pPriv->bicubic = bicubic;
2095
pPriv->doubleBuffer = FALSE;
2096
pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
2099
pNv->textureAdaptor[1] = adapt;
2101
pNv->textureAdaptor[0] = adapt;
2108
* tries to initialize the various supported adapters
2109
* and add them to the list of ports on screen "pScreen".
2112
* @see NVSetupOverlayVideo(ScreenPtr pScreen)
2113
* @see NVSetupBlitVideo(ScreenPtr pScreen)
2116
NVInitVideo(ScreenPtr pScreen)
2118
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2119
NVPtr pNv = NVPTR(pScrn);
2120
XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
2121
XF86VideoAdaptorPtr overlayAdaptor = NULL;
2122
XF86VideoAdaptorPtr blitAdaptor = NULL;
2123
XF86VideoAdaptorPtr textureAdaptor[2] = {NULL, NULL};
2127
* Driving the blitter requires the DMA FIFO. Using the FIFO
2128
* without accel causes DMA errors. While the overlay might
2129
* might work without accel, we also disable it for now when
2130
* acceleration is disabled:
2132
if (pScrn->bitsPerPixel != 8 &&
2133
pNv->Architecture < NV_ARCH_50 && !pNv->NoAccel) {
2134
overlayAdaptor = NVSetupOverlayVideo(pScreen);
2135
blitAdaptor = NVSetupBlitVideo(pScreen);
2136
if (pNv->Architecture == NV_ARCH_30) {
2137
textureAdaptor[0] = NV30SetupTexturedVideo(pScreen, FALSE);
2138
textureAdaptor[1] = NV30SetupTexturedVideo(pScreen, TRUE);
2140
if (pNv->Architecture == NV_ARCH_40) {
2141
textureAdaptor[0] = NV40SetupTexturedVideo(pScreen, FALSE);
2142
textureAdaptor[1] = NV40SetupTexturedVideo(pScreen, TRUE);
2146
num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
2147
if(blitAdaptor || overlayAdaptor) {
2148
int size = num_adaptors;
2150
if(overlayAdaptor) size++;
2151
if(blitAdaptor) size++;
2152
if(textureAdaptor[0]) size++;
2153
if(textureAdaptor[1]) size++;
2155
newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
2158
memcpy(newAdaptors, adaptors, num_adaptors *
2159
sizeof(XF86VideoAdaptorPtr));
2162
if(overlayAdaptor) {
2163
newAdaptors[num_adaptors] = overlayAdaptor;
2167
if (textureAdaptor[0]) { /* bilinear */
2168
newAdaptors[num_adaptors] = textureAdaptor[0];
2172
if (textureAdaptor[1]) { /* bicubic */
2173
newAdaptors[num_adaptors] = textureAdaptor[1];
2178
newAdaptors[num_adaptors] = blitAdaptor;
2182
adaptors = newAdaptors;
2187
xf86XVScreenInit(pScreen, adaptors, num_adaptors);