~ubuntu-branches/ubuntu/karmic/xserver-xorg-video-nouveau/karmic

« back to all changes in this revision

Viewing changes to src/nouveau_xv.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Lamb
  • Date: 2008-07-06 20:26:53 UTC
  • Revision ID: james.westby@ubuntu.com-20080706202653-e99oiii765j3a0qn
Tags: upstream-0.0.10~git+20080706+b1f3169
ImportĀ upstreamĀ versionĀ 0.0.10~git+20080706+b1f3169

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2007 Arthur Huillet
 
3
 *
 
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:
 
10
 *
 
11
 * The above copyright notice and this permission notice shall be included in
 
12
 * all copies or substantial portions of the Software.
 
13
 *
 
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
 
20
 * SOFTWARE.
 
21
 */
 
22
 
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include "config.h"
 
26
#endif
 
27
 
 
28
#include "xf86xv.h"
 
29
#include <X11/extensions/Xv.h>
 
30
#include "exa.h"
 
31
#include "damage.h"
 
32
#include "dixstruct.h"
 
33
#include "fourcc.h"
 
34
 
 
35
#include "nv_include.h"
 
36
#include "nv_dma.h"
 
37
 
 
38
#define IMAGE_MAX_W 2046
 
39
#define IMAGE_MAX_H 2046
 
40
 
 
41
#define TEX_IMAGE_MAX_W 4096
 
42
#define TEX_IMAGE_MAX_H 4096
 
43
 
 
44
#define OFF_DELAY       500  /* milliseconds */
 
45
#define FREE_DELAY      5000
 
46
 
 
47
#define NUM_BLIT_PORTS 16
 
48
#define NUM_TEXTURE_PORTS 32
 
49
 
 
50
 
 
51
#define NVStopOverlay(X) (((pNv->Architecture == NV_ARCH_04) ? NV04StopOverlay(X) : NV10StopOverlay(X)))
 
52
 
 
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
 
56
 
 
57
/* Xv DMA notifiers status tracing */
 
58
enum {
 
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
 
62
};
 
63
 
 
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];
 
72
 
 
73
/* NVPutImage action flags */
 
74
enum {
 
75
        IS_YV12 = 1,
 
76
        IS_YUY2 = 2,
 
77
        CONVERT_TO_YUY2=4,
 
78
        USE_OVERLAY=8,
 
79
        USE_TEXTURE=16,
 
80
        SWAP_UV=32,
 
81
        IS_RGB=64, //I am not sure how long we will support it
 
82
};
 
83
 
 
84
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
 
85
 
 
86
Atom xvBrightness, xvContrast, xvColorKey, xvSaturation;
 
87
Atom xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer;
 
88
Atom xvITURBT709, xvSyncToVBlank, xvOnCRTCNb;
 
89
 
 
90
/* client libraries expect an encoding */
 
91
static XF86VideoEncodingRec DummyEncoding =
 
92
{
 
93
        0,
 
94
        "XV_IMAGE",
 
95
        IMAGE_MAX_W, IMAGE_MAX_H,
 
96
        {1, 1}
 
97
};
 
98
 
 
99
static XF86VideoEncodingRec DummyEncodingTex =
 
100
{
 
101
        0,
 
102
        "XV_IMAGE",
 
103
        TEX_IMAGE_MAX_W, TEX_IMAGE_MAX_H,
 
104
        {1, 1}
 
105
};
 
106
 
 
107
#define NUM_FORMATS_ALL 6
 
108
 
 
109
XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
 
110
{
 
111
        {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
 
112
        {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
 
113
};
 
114
 
 
115
#define NUM_NV04_OVERLAY_ATTRIBUTES 4
 
116
XF86AttributeRec NV04OverlayAttributes[NUM_NV04_OVERLAY_ATTRIBUTES] =
 
117
{
 
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"},
 
122
};
 
123
 
 
124
 
 
125
#define NUM_NV10_OVERLAY_ATTRIBUTES 10
 
126
XF86AttributeRec NV10OverlayAttributes[NUM_NV10_OVERLAY_ATTRIBUTES] =
 
127
{
 
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"},
 
138
};
 
139
 
 
140
#define NUM_BLIT_ATTRIBUTES 2
 
141
XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
 
142
{
 
143
        {XvSettable             , 0, 0, "XV_SET_DEFAULTS"},
 
144
        {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
 
145
};
 
146
 
 
147
#define NUM_TEXTURED_ATTRIBUTES 2
 
148
XF86AttributeRec NVTexturedAttributes[NUM_TEXTURED_ATTRIBUTES] =
 
149
{
 
150
        {XvSettable             , 0, 0, "XV_SET_DEFAULTS"},
 
151
        {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
 
152
};
 
153
 
 
154
 
 
155
#define NUM_IMAGES_YUV 4
 
156
#define NUM_IMAGES_ALL 5
 
157
 
 
158
#define FOURCC_RGB 0x0000003
 
159
#define XVIMAGE_RGB \
 
160
   { \
 
161
        FOURCC_RGB, \
 
162
        XvRGB, \
 
163
        LSBFirst, \
 
164
        { 0x03, 0x00, 0x00, 0x00, \
 
165
          0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
 
166
        32, \
 
167
        XvPacked, \
 
168
        1, \
 
169
        24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
 
170
        0, 0, 0, \
 
171
        0, 0, 0, \
 
172
        0, 0, 0, \
 
173
        {'B','G','R','X',\
 
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}, \
 
175
        XvTopToBottom \
 
176
   }
 
177
 
 
178
static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
 
179
{
 
180
        XVIMAGE_YUY2,
 
181
        XVIMAGE_YV12,
 
182
        XVIMAGE_UYVY,
 
183
        XVIMAGE_I420,
 
184
        XVIMAGE_RGB
 
185
};
 
186
 
 
187
unsigned int
 
188
nv_window_belongs_to_crtc(ScrnInfoPtr pScrn, int x, int y, int w, int h)
 
189
{
 
190
        xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 
191
        NVPtr pNv = NVPTR(pScrn);
 
192
        xf86CrtcPtr crtc;
 
193
        int i;
 
194
        unsigned int mask;
 
195
 
 
196
        mask = 0;
 
197
 
 
198
        if (!pNv->randr12_enable) {
 
199
                /*
 
200
                 * Without RandR 1.2, we'll just return which CRTCs
 
201
                 * are active.
 
202
                 */
 
203
                if (pNv->crtc_active[0])
 
204
                        mask |= 0x1;
 
205
                else if (pNv->crtc_active[1])
 
206
                        mask |= 0x2;
 
207
 
 
208
                return mask;
 
209
        }
 
210
 
 
211
        for (i = 0; i < xf86_config->num_crtc; i++) {
 
212
                crtc = xf86_config->crtc[i];
 
213
 
 
214
                if (!crtc->enabled)
 
215
                        continue;
 
216
 
 
217
                if ((x < (crtc->x + crtc->mode.HDisplay)) &&
 
218
                    (y < (crtc->y + crtc->mode.VDisplay)) &&
 
219
                    ((x + w) > crtc->x) &&
 
220
                    ((y + h) > crtc->y))
 
221
                    mask |= 1 << i;
 
222
        }
 
223
 
 
224
        return mask;
 
225
}
 
226
 
 
227
void
 
228
NVWaitVSync(ScrnInfoPtr pScrn, int crtc)
 
229
{
 
230
        NVPtr pNv = NVPTR(pScrn);
 
231
 
 
232
        BEGIN_RING(NvImageBlit, 0x0000012C, 1);
 
233
        OUT_RING  (0);
 
234
        BEGIN_RING(NvImageBlit, 0x00000134, 1);
 
235
        OUT_RING  (crtc);
 
236
        BEGIN_RING(NvImageBlit, 0x00000100, 1);
 
237
        OUT_RING  (0);
 
238
        BEGIN_RING(NvImageBlit, 0x00000130, 1);
 
239
        OUT_RING  (0);
 
240
}
 
241
 
 
242
/**
 
243
 * NVSetPortDefaults
 
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
 
246
 *
 
247
 * @param pScrn screen to get the default colorKey from
 
248
 * @param pPriv port to reset to defaults
 
249
 */
 
250
void
 
251
NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
 
252
{
 
253
        NVPtr pNv = NVPTR(pScrn);
 
254
 
 
255
        pPriv->brightness               = 0;
 
256
        pPriv->contrast                 = 4096;
 
257
        pPriv->saturation               = 4096;
 
258
        pPriv->hue                      = 0;
 
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;
 
264
}
 
265
 
 
266
/**
 
267
 * NVXvDMANotifierAlloc
 
268
 * allocates a notifier from the table of 6 we have
 
269
 *
 
270
 * @return a notifier instance or NULL on error
 
271
 */
 
272
static struct nouveau_notifier *
 
273
NVXvDMANotifierAlloc(ScrnInfoPtr pScrn)
 
274
{
 
275
        NVPtr pNv = NVPTR(pScrn);
 
276
        int i;
 
277
 
 
278
        for (i = 0; i < 6; i++) {
 
279
                if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_INUSE)
 
280
                        continue;
 
281
 
 
282
                if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_FREE) {
 
283
                        XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
 
284
                        return XvDMANotifiers[i];
 
285
                }
 
286
 
 
287
                if (XvDMANotifierStatus[i] == XV_DMA_NOTIFIER_NOALLOC) {
 
288
                        if (nouveau_notifier_alloc(pNv->chan,
 
289
                                                   NvDmaXvNotifier0 + i,
 
290
                                                   1, &XvDMANotifiers[i]))
 
291
                                return NULL;
 
292
                        XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_INUSE;
 
293
                        return XvDMANotifiers[i];
 
294
                }
 
295
        }
 
296
 
 
297
        return NULL;
 
298
}
 
299
 
 
300
/**
 
301
 * NVXvDMANotifierFree
 
302
 * frees a notifier from the table of 6 we have
 
303
 *
 
304
 *
 
305
 */
 
306
static void
 
307
NVXvDMANotifierFree(ScrnInfoPtr pScrn, struct nouveau_notifier **ptarget)
 
308
{
 
309
        struct nouveau_notifier *target;
 
310
        int i;
 
311
 
 
312
        if (!ptarget || !*ptarget)
 
313
                return;
 
314
        target = *ptarget;
 
315
        *ptarget = NULL;
 
316
 
 
317
        for (i = 0; i < 6; i ++) {
 
318
                if (XvDMANotifiers[i] == target)
 
319
                        break;
 
320
        }
 
321
 
 
322
        XvDMANotifierStatus[i] = XV_DMA_NOTIFIER_FREE;
 
323
}
 
324
 
 
325
static int
 
326
nouveau_xv_bo_realloc(ScrnInfoPtr pScrn, unsigned flags, unsigned size,
 
327
                      struct nouveau_bo **pbo)
 
328
{
 
329
        NVPtr pNv = NVPTR(pScrn);
 
330
        int ret;
 
331
 
 
332
        if (*pbo) {
 
333
                if ((*pbo)->size >= size)
 
334
                        return 0;
 
335
                nouveau_bo_del(pbo);
 
336
        }
 
337
 
 
338
        ret = nouveau_bo_new(pNv->dev, flags | NOUVEAU_BO_PIN, 0, size, pbo);
 
339
        if (ret)
 
340
                return ret;
 
341
 
 
342
        ret = nouveau_bo_map(*pbo, NOUVEAU_BO_RDWR);
 
343
        if (ret) {
 
344
                nouveau_bo_del(pbo);
 
345
                return ret;
 
346
        }
 
347
 
 
348
        return 0;
 
349
}
 
350
 
 
351
/**
 
352
 * NVFreePortMemory
 
353
 * frees memory held by a given port
 
354
 *
 
355
 * @param pScrn screen whose port wants to free memory
 
356
 * @param pPriv port to free memory of
 
357
 */
 
358
static void
 
359
NVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
 
360
{
 
361
        if(pPriv->video_mem) {
 
362
                nouveau_bo_del(&pPriv->video_mem);
 
363
                pPriv->video_mem = NULL;
 
364
        }
 
365
 
 
366
        if (pPriv->TT_mem_chunk[0] && pPriv->DMANotifier[0])
 
367
                nouveau_notifier_wait_status(pPriv->DMANotifier[0], 0, 0, 1000);
 
368
 
 
369
        if (pPriv->TT_mem_chunk[1] && pPriv->DMANotifier[1])
 
370
                nouveau_notifier_wait_status(pPriv->DMANotifier[1], 0, 0, 1000);
 
371
 
 
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]);
 
376
 
 
377
}
 
378
 
 
379
/**
 
380
 * NVFreeOverlayMemory
 
381
 * frees memory held by the overlay port
 
382
 *
 
383
 * @param pScrn screen whose overlay port wants to free memory
 
384
 */
 
385
static void
 
386
NVFreeOverlayMemory(ScrnInfoPtr pScrn)
 
387
{
 
388
        NVPtr   pNv = NVPTR(pScrn);
 
389
        NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
 
390
 
 
391
        NVFreePortMemory(pScrn, pPriv);
 
392
 
 
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));
 
398
}
 
399
 
 
400
/**
 
401
 * NVFreeBlitMemory
 
402
 * frees memory held by the blit port
 
403
 *
 
404
 * @param pScrn screen whose blit port wants to free memory
 
405
 */
 
406
static void
 
407
NVFreeBlitMemory(ScrnInfoPtr pScrn)
 
408
{
 
409
        NVPtr   pNv = NVPTR(pScrn);
 
410
        NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
 
411
 
 
412
        NVFreePortMemory(pScrn, pPriv);
 
413
}
 
414
 
 
415
/**
 
416
 * NVVideoTimerCallback
 
417
 * callback function which perform cleanup tasks (stop overlay, free memory).
 
418
 * within the driver
 
419
 * purpose and use is unknown
 
420
 */
 
421
void
 
422
NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime)
 
423
{
 
424
        NVPtr         pNv = NVPTR(pScrn);
 
425
        NVPortPrivPtr pOverPriv = NULL;
 
426
        NVPortPrivPtr pBlitPriv = NULL;
 
427
        Bool needCallback = FALSE;
 
428
 
 
429
        if (!pScrn->vtSema)
 
430
                return;
 
431
 
 
432
        if (pNv->overlayAdaptor) {
 
433
                pOverPriv = GET_OVERLAY_PRIVATE(pNv);
 
434
                if (!pOverPriv->videoStatus)
 
435
                        pOverPriv = NULL;
 
436
        }
 
437
 
 
438
        if (pNv->blitAdaptor) {
 
439
                pBlitPriv = GET_BLIT_PRIVATE(pNv);
 
440
                if (!pBlitPriv->videoStatus)
 
441
                        pBlitPriv = NULL;
 
442
        }
 
443
 
 
444
        if (pOverPriv) {
 
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;
 
450
                                needCallback = TRUE;
 
451
                        } else
 
452
                        if (pOverPriv->videoStatus & FREE_TIMER) {
 
453
                                NVFreeOverlayMemory(pScrn);
 
454
                                pOverPriv->videoStatus = 0;
 
455
                        }
 
456
                } else {
 
457
                        needCallback = TRUE;
 
458
                }
 
459
        }
 
460
 
 
461
        if (pBlitPriv) {
 
462
                if (pBlitPriv->videoTime < currentTime) {
 
463
                        NVFreeBlitMemory(pScrn);
 
464
                        pBlitPriv->videoStatus = 0;
 
465
                } else {
 
466
                        needCallback = TRUE;
 
467
                }
 
468
        }
 
469
 
 
470
        pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
 
471
}
 
472
 
 
473
#ifndef ExaOffscreenMarkUsed
 
474
extern void ExaOffscreenMarkUsed(PixmapPtr);
 
475
#endif
 
476
 
 
477
/*
 
478
 * StopVideo
 
479
 */
 
480
static void
 
481
NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
 
482
{
 
483
        NVPtr         pNv   = NVPTR(pScrn);
 
484
        NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
 
485
 
 
486
        if (pPriv->grabbedByV4L)
 
487
                return;
 
488
 
 
489
        REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
 
490
 
 
491
        if(Exit) {
 
492
                if (pPriv->videoStatus & CLIENT_VIDEO_ON)
 
493
                        NVStopOverlay(pScrn);
 
494
                NVFreeOverlayMemory(pScrn);
 
495
                pPriv->videoStatus = 0;
 
496
        } else {
 
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;
 
501
                }
 
502
        }
 
503
}
 
504
 
 
505
/**
 
506
 * QueryBestSize
 
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
 
510
 * drw_w, drw_h?
 
511
 * function stores actual scaling size in pointers p_w, p_h.
 
512
 *
 
513
 *
 
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
 
522
 * @param data unused
 
523
 */
 
524
static void
 
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,
 
529
                pointer data)
 
530
{
 
531
        if(vid_w > (drw_w << 3))
 
532
                drw_w = vid_w >> 3;
 
533
        if(vid_h > (drw_h << 3))
 
534
                drw_h = vid_h >> 3;
 
535
 
 
536
        *p_w = drw_w;
 
537
        *p_h = drw_h;
 
538
}
 
539
 
 
540
/**
 
541
 * NVCopyData420
 
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
 
545
 *
 
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
 
555
 */
 
556
static inline void
 
557
NVCopyData420(unsigned char *src1, unsigned char *src2, unsigned char *src3,
 
558
              unsigned char *dst1, int srcPitch, int srcPitch2, int dstPitch,
 
559
              int h, int w)
 
560
{
 
561
        CARD32 *dst;
 
562
        CARD8 *s1, *s2, *s3;
 
563
        int i, j;
 
564
 
 
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]))
 
569
 
 
570
        w >>= 1;
 
571
 
 
572
        for (j = 0; j < h; j++) {
 
573
                dst = (CARD32*)dst1;
 
574
                s1 = src1;  s2 = src2;  s3 = src3;
 
575
                i = w;
 
576
 
 
577
                while (i > 4) {
 
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);
 
583
#else
 
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);
 
588
#endif
 
589
                dst += 4; s2 += 4; s3 += 4; s1 += 8;
 
590
                i -= 4;
 
591
                }
 
592
 
 
593
                while (i--) {
 
594
#if X_BYTE_ORDER == X_BIG_ENDIAN
 
595
                dst[0] = (s1[0] << 24) | (s1[1] << 8) | (sv(0) << 16) | su(0);
 
596
#else
 
597
                dst[0] = s1[0] | (s1[1] << 16) | (sv(0) << 8) | (su(0) << 24);
 
598
#endif
 
599
                dst++; s2++; s3++;
 
600
                s1 += 2;
 
601
                }
 
602
 
 
603
                dst1 += dstPitch;
 
604
                src1 += srcPitch;
 
605
                if (j & 1) {
 
606
                        src2 += srcPitch2;
 
607
                        src3 += srcPitch2;
 
608
                }
 
609
        }
 
610
}
 
611
 
 
612
/**
 
613
 * NVCopyNV12ColorPlanes
 
614
 * Used to convert YV12 color planes to NV12 (interleaved UV) for the overlay
 
615
 *
 
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)
 
621
 */
 
622
static inline void
 
623
NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char *src2,
 
624
                      unsigned char *dst, int dstPitch, int srcPitch2,
 
625
                      int h, int w)
 
626
{
 
627
        int i, j, l, e;
 
628
 
 
629
        w >>= 1;
 
630
        h >>= 1;
 
631
        l = w >> 1;
 
632
        e = w & 1;
 
633
 
 
634
        for (j = 0; j < h; j++) {
 
635
                unsigned char *us = src1;
 
636
                unsigned char *vs = src2;
 
637
                unsigned int *vuvud = (unsigned int *) dst;
 
638
 
 
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];
 
642
#else
 
643
                        *vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24);
 
644
#endif
 
645
                        us+=2;
 
646
                        vs+=2;
 
647
                }
 
648
 
 
649
                if (e) {
 
650
                        unsigned short *vud = (unsigned short *) vuvud;
 
651
 
 
652
                        *vud = vs[0] | (us[0]<<8);
 
653
                }
 
654
 
 
655
                dst += dstPitch;
 
656
                src1 += srcPitch2;
 
657
                src2 += srcPitch2;
 
658
        }
 
659
 
 
660
}
 
661
 
 
662
 
 
663
static int
 
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)
 
670
{
 
671
        NVPtr pNv = NVPTR(pScrn);
 
672
 
 
673
        if (action_flags & USE_OVERLAY) {
 
674
                switch (pNv->Architecture) {
 
675
                case NV_ARCH_04:
 
676
                        /* NV0x overlay can't scale down. at all. */
 
677
                        if (*drw_w < *src_w)
 
678
                                *drw_w = *src_w;
 
679
                        if (*drw_h < *src_h)
 
680
                                *drw_h = *src_h;
 
681
                        break;
 
682
                case NV_ARCH_30:
 
683
                        /* According to DirectFB, NV3x can't scale down by
 
684
                         * a ratio > 2
 
685
                         */
 
686
                        if (*drw_w < (*src_w) >> 1)
 
687
                                *drw_w = *src_w;
 
688
                        if (*drw_h < (*src_h) >> 1)
 
689
                                *drw_h = *src_h;
 
690
                        break;
 
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;
 
697
                }
 
698
        }
 
699
 
 
700
        /* Clip */
 
701
        *xa = *src_x;
 
702
        *xb = *src_x + *src_w;
 
703
        *ya = *src_y;
 
704
        *yb = *src_y + *src_h;
 
705
 
 
706
        dstBox->x1 = *drw_x;
 
707
        dstBox->x2 = *drw_x + *drw_w;
 
708
        dstBox->y1 = *drw_y;
 
709
        dstBox->y2 = *drw_y + *drw_h;
 
710
 
 
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
 
714
         */
 
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];
 
719
                RegionRec VPReg;
 
720
                BoxRec VPBox;
 
721
 
 
722
                VPBox.x1 = crtc->x;
 
723
                VPBox.y1 = crtc->y;
 
724
                VPBox.x2 = crtc->x + crtc->mode.HDisplay;
 
725
                VPBox.y2 = crtc->y + crtc->mode.VDisplay;
 
726
 
 
727
                REGION_INIT(pScreen, &VPReg, &VPBox, 1);
 
728
                REGION_INTERSECT(pScreen, clipBoxes, clipBoxes, &VPReg);
 
729
                REGION_UNINIT(pScreen, &VPReg);
 
730
        }
 
731
 
 
732
        if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes,
 
733
                                   width, height))
 
734
                return -1;
 
735
 
 
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;
 
742
                } else {
 
743
                        xf86CrtcConfigPtr xf86_config =
 
744
                                XF86_CRTC_CONFIG_PTR(pScrn);
 
745
                        NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
 
746
 
 
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;
 
751
                }
 
752
        }
 
753
 
 
754
        /* Convert fixed point to integer, as xf86XVClipVideoHelper probably
 
755
         * turns its parameter into fixed point values
 
756
         */
 
757
        *left = (*xa) >> 16;
 
758
        if (*left < 0)
 
759
                *left = 0;
 
760
 
 
761
        *top = (*ya) >> 16;
 
762
        if (*top < 0)
 
763
                *top = 0;
 
764
 
 
765
        *right = (*xb) >> 16;
 
766
        if (*right > width)
 
767
                *right = width;
 
768
 
 
769
        *bottom = (*yb) >> 16;
 
770
        if (*bottom > height)
 
771
                *bottom = height;
 
772
 
 
773
        if (action_flags & IS_YV12) {
 
774
                /* even "left", even "top", even number of pixels per line
 
775
                 * and even number of lines
 
776
                 */
 
777
                *left &= ~1;
 
778
                *npixels = ((*right + 1) & ~1) - *left;
 
779
                *top &= ~1;
 
780
                *nlines = ((*bottom + 1) & ~1) - *top;
 
781
        } else
 
782
        if (action_flags & IS_YUY2) {
 
783
                /* even "left" */
 
784
                *left &= ~1;
 
785
                /* even number of pixels per line */
 
786
                *npixels = ((*right + 1) & ~1) - *left;
 
787
                *nlines = *bottom - *top;
 
788
                /* 16bpp */
 
789
                *left <<= 1;
 
790
        } else
 
791
        if (action_flags & IS_RGB) {
 
792
                *npixels = *right - *left;
 
793
                *nlines = *bottom - *top;
 
794
                /* 32bpp */
 
795
                *left <<= 2;
 
796
        }
 
797
 
 
798
        return 0;
 
799
}
 
800
 
 
801
static int
 
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)
 
807
{
 
808
        int tmp;
 
809
 
 
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*/
 
816
                *line_len = npixels;
 
817
                *newFBSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
 
818
                *newTTSize = nlines * *dstPitch + (nlines >> 1) * *dstPitch;
 
819
        } else
 
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;
 
826
        } else
 
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;
 
834
        }
 
835
 
 
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;
 
841
        }
 
842
 
 
843
        if (action_flags & SWAP_UV)  {
 
844
                /* I420 swaps U and V */
 
845
                tmp = *s2offset;
 
846
                *s2offset = *s3offset;
 
847
                *s3offset = tmp;
 
848
        }
 
849
 
 
850
        /* Overlay double buffering... */
 
851
        if (action_flags & USE_OVERLAY)
 
852
                (*newFBSize) <<= 1;
 
853
 
 
854
        return 0;
 
855
}
 
856
 
 
857
 
 
858
/**
 
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
 
863
 * core NVPutImage
 
864
 */
 
865
static void
 
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,
 
868
                    int *action_flags)
 
869
{
 
870
        NVPtr pNv = NVPTR(pScrn);
 
871
 
 
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)))
 
876
 
 
877
        *action_flags = 0;
 
878
 
 
879
        /* Pixel format-related bits */
 
880
        if (id == FOURCC_YUY2 || id == FOURCC_UYVY)
 
881
                *action_flags |= IS_YUY2;
 
882
 
 
883
        if (id == FOURCC_YV12 || id == FOURCC_I420)
 
884
                *action_flags |= IS_YV12;
 
885
 
 
886
        if (id == FOURCC_RGB) /*How long will we support it?*/
 
887
                *action_flags |= IS_RGB;
 
888
 
 
889
        if (id == FOURCC_I420) /* I420 is YV12 with swapped UV */
 
890
                *action_flags |= SWAP_UV;
 
891
 
 
892
        /* Desired adapter */
 
893
        if (!pPriv->blitter && !pPriv->texture)
 
894
                *action_flags |= USE_OVERLAY;
 
895
 
 
896
        if (!pPriv->blitter && pPriv->texture)
 
897
                *action_flags |= USE_TEXTURE;
 
898
 
 
899
        /* Adapter fallbacks (when the desired one can't be used)*/
 
900
#ifdef COMPOSITE
 
901
        {
 
902
                PixmapPtr ppix = NVGetDrawablePixmap(pDraw);
 
903
 
 
904
                if (!NVExaPixmapIsOnscreen(ppix))
 
905
                        *action_flags &= ~USE_OVERLAY;
 
906
        }
 
907
#endif
 
908
 
 
909
        if (USING_OVERLAY && pNv->randr12_enable) {
 
910
                char crtc = nv_window_belongs_to_crtc(pScrn, drw_x, drw_y,
 
911
                                                      drw_w, drw_h);
 
912
 
 
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
 
916
                         */
 
917
                        *action_flags &= ~USE_OVERLAY;
 
918
                } else
 
919
                if ((crtc & (1 << 0))) {
 
920
                        /* We need to put the overlay on CRTC0 - if it's not
 
921
                         * already here
 
922
                         */
 
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;
 
931
                        }
 
932
                } else
 
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;
 
942
                        }
 
943
                }
 
944
 
 
945
                if (XF86_CRTC_CONFIG_PTR(pScrn)->crtc[pPriv->overlayCRTC]
 
946
                                                 ->rotation != RR_Rotate_0)
 
947
                        *action_flags &= ~USE_OVERLAY;
 
948
        }
 
949
 
 
950
        /* At this point the adapter we're going to use is _known_.
 
951
         * You cannot change it now.
 
952
         */
 
953
 
 
954
        /* Card/adapter format restrictions */
 
955
        if (USING_BLITTER) {
 
956
                /* The blitter does not handle YV12 natively */
 
957
                if (id == FOURCC_YV12 || id == FOURCC_I420)
 
958
                        *action_flags |= CONVERT_TO_YUY2;
 
959
        }
 
960
 
 
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;
 
965
        }
 
966
 
 
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) {
 
971
                case CHIPSET_NV10:
 
972
                case CHIPSET_NV11:
 
973
                case CHIPSET_NV15:
 
974
                case CHIPSET_NFORCE: /*XXX: unsure about nforce*/
 
975
                case CHIPSET_NV20:
 
976
                        *action_flags |= CONVERT_TO_YUY2;
 
977
                        break;
 
978
                default:
 
979
                        break;
 
980
                }
 
981
        }
 
982
}
 
983
 
 
984
 
 
985
/**
 
986
 * NVPutImage
 
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.
 
991
 *
 
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
 
998
 * @param drw_y
 
999
 * @param drw_w width of the screen drawable
 
1000
 * @param drw_h
 
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
 
1004
 * @param height
 
1005
 * @param Sync unused
 
1006
 * @param clipBoxes ??
 
1007
 * @param data pointer to port
 
1008
 * @param pDraw drawable pointer
 
1009
 */
 
1010
static int
 
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)
 
1015
{
 
1016
        NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
 
1017
        NVPtr pNv = NVPTR(pScrn);
 
1018
        PixmapPtr ppix;
 
1019
        /* source box */
 
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
 
1027
         */
 
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
 
1031
         */
 
1032
        int top = 0, left = 0, right = 0, bottom = 0, npixels = 0, nlines = 0;
 
1033
        Bool skip = FALSE;
 
1034
        BoxRec dstBox;
 
1035
        CARD32 tmp = 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? */
 
1039
        unsigned char *map;
 
1040
        int ret, i;
 
1041
 
 
1042
        if (pPriv->grabbedByV4L)
 
1043
                return Success;
 
1044
 
 
1045
 
 
1046
        NV_set_action_flags(pScrn, pDraw, pPriv, id, drw_x, drw_y, drw_w,
 
1047
                            drw_h, &action_flags);
 
1048
 
 
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))
 
1054
                return Success;
 
1055
 
 
1056
        if (NV_calculate_pitches_and_mem_size(action_flags, &srcPitch,
 
1057
                                              &srcPitch2, &dstPitch, &s2offset,
 
1058
                                              &s3offset, &newFBSize, &newTTSize,
 
1059
                                              &line_len, npixels, nlines,
 
1060
                                              width, height))
 
1061
                return BadImplementation;
 
1062
 
 
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.
 
1067
         */
 
1068
        if (action_flags & IS_YUY2 || action_flags & IS_RGB)
 
1069
                buf += (top * srcPitch) + left;
 
1070
 
 
1071
        if (action_flags & IS_YV12) {
 
1072
                tmp = ((top >> 1) * srcPitch2) + (left >> 1);
 
1073
                s2offset += tmp;
 
1074
                s3offset += tmp;
 
1075
        }
 
1076
 
 
1077
        ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_VRAM, newFBSize,
 
1078
                                    &pPriv->video_mem);
 
1079
        if (ret)
 
1080
                return BadAlloc;
 
1081
 
 
1082
        /* The overlay supports hardware double buffering. We handle this here*/
 
1083
        offset = 0;
 
1084
        if (pPriv->doubleBuffer) {
 
1085
                int mask = 1 << (pPriv->currentBuffer << 2);
 
1086
 
 
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;
 
1091
                        skip = TRUE;
 
1092
                } else {
 
1093
                        if (pPriv->currentBuffer)
 
1094
                                offset += newFBSize >> 1;
 
1095
                }
 
1096
        }
 
1097
 
 
1098
        /* Now we take a decision regarding the way we send the data to the
 
1099
         * card.
 
1100
         *
 
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
 
1104
         */
 
1105
 
 
1106
        /* Try to allocate host-side double buffers, unless we have already
 
1107
         * failed
 
1108
         */
 
1109
 
 
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
 
1113
         */
 
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]);
 
1117
                if (ret == 0) {
 
1118
                        ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_GART,
 
1119
                                                    newTTSize,
 
1120
                                                    &pPriv->TT_mem_chunk[1]);
 
1121
                        if (ret) {
 
1122
                                nouveau_bo_del(&pPriv->TT_mem_chunk[0]);
 
1123
                                pPriv->currentHostBuffer =
 
1124
                                        NO_PRIV_HOST_BUFFER_AVAILABLE;
 
1125
                        }
 
1126
                } else {
 
1127
                        pPriv->currentHostBuffer =
 
1128
                                NO_PRIV_HOST_BUFFER_AVAILABLE;
 
1129
                }
 
1130
        }
 
1131
 
 
1132
        if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE) {
 
1133
                destination_buffer =
 
1134
                        pPriv->TT_mem_chunk[pPriv->currentHostBuffer];
 
1135
 
 
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.
 
1140
                 *
 
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
 
1143
                 * allocator.
 
1144
                 */
 
1145
                if (pPriv->DMANotifier[pPriv->currentHostBuffer]) {
 
1146
                        struct nouveau_notifier *n =
 
1147
                                pPriv->DMANotifier[pPriv->currentHostBuffer];
 
1148
 
 
1149
                        if (nouveau_notifier_wait_status(n, 0, 0, 0))
 
1150
                                return FALSE;
 
1151
                } else {
 
1152
                        pPriv->DMANotifier[pPriv->currentHostBuffer] =
 
1153
                                NVXvDMANotifierAlloc(pScrn);
 
1154
 
 
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
 
1162
                                 */
 
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;
 
1171
                        }
 
1172
                }
 
1173
        }
 
1174
 
 
1175
        /* Otherwise we fall back on DDX's GARTScratch */
 
1176
        if (pPriv->currentHostBuffer == NO_PRIV_HOST_BUFFER_AVAILABLE)
 
1177
                destination_buffer = pNv->GART;
 
1178
 
 
1179
        /* If we have no GART at all... */
 
1180
        if (!destination_buffer)
 
1181
                goto CPU_copy;
 
1182
 
 
1183
        if (newTTSize <= destination_buffer->size) {
 
1184
                unsigned char *dst = destination_buffer->map;
 
1185
                int i = 0;
 
1186
 
 
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);
 
1194
                        } else {
 
1195
                                /* Native YV12 */
 
1196
                                unsigned char *tbuf = buf + top *
 
1197
                                                      srcPitch + left;
 
1198
                                unsigned char *tdst = dst;
 
1199
 
 
1200
                                /* luma upload */
 
1201
                                for (i = 0; i < nlines; i++) {
 
1202
                                        memcpy(tdst, tbuf, line_len);
 
1203
                                        tdst += line_len;
 
1204
                                        tbuf += srcPitch;
 
1205
                                }
 
1206
                                dst += line_len * nlines;
 
1207
 
 
1208
                                NVCopyNV12ColorPlanes(buf + s2offset,
 
1209
                                                      buf + s3offset, dst,
 
1210
                                                      line_len, srcPitch2,
 
1211
                                                      nlines, line_len);
 
1212
                        }
 
1213
                } else {
 
1214
                        for (i = 0; i < nlines; i++) {
 
1215
                                memcpy(dst, buf, line_len);
 
1216
                                dst += line_len;
 
1217
                                buf += srcPitch;
 
1218
                        }
 
1219
                }
 
1220
 
 
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);
 
1225
 
 
1226
                /* DMA to VRAM */
 
1227
                if ( (action_flags & IS_YV12) &&
 
1228
                    !(action_flags & CONVERT_TO_YUY2)) {
 
1229
                        /* we start the color plane transfer separately */
 
1230
 
 
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);
 
1242
                        OUT_RING  (0);
 
1243
                        FIRE_RING();
 
1244
                }
 
1245
 
 
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);
 
1255
                OUT_RING  (nlines);
 
1256
                OUT_RING  ((1<<8)|1);
 
1257
                OUT_RING  (0);
 
1258
 
 
1259
                if (destination_buffer == pNv->GART) {
 
1260
                        nouveau_notifier_reset(pNv->notify0, 0);
 
1261
                } else {
 
1262
                        struct nouveau_notifier *n =
 
1263
                                pPriv->DMANotifier[pPriv->currentHostBuffer];
 
1264
 
 
1265
                        nouveau_notifier_reset(n, 0);
 
1266
 
 
1267
                        BEGIN_RING(NvMemFormat,
 
1268
                                   NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
 
1269
                        OUT_RING  (n->handle);
 
1270
                }
 
1271
 
 
1272
 
 
1273
                BEGIN_RING(NvMemFormat, NV04_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
 
1274
                OUT_RING  (0);
 
1275
                BEGIN_RING(NvMemFormat, 0x100, 1);
 
1276
                OUT_RING  (0);
 
1277
 
 
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);
 
1282
 
 
1283
                FIRE_RING();
 
1284
 
 
1285
                if (destination_buffer == pNv->GART) {
 
1286
                        if (nouveau_notifier_wait_status(pNv->notify0, 0, 0, 0))
 
1287
                                return FALSE;
 
1288
                }
 
1289
 
 
1290
        } else {
 
1291
CPU_copy:
 
1292
                map = pPriv->video_mem->map + offset;
 
1293
 
 
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);
 
1300
                        } else {
 
1301
                                unsigned char *tbuf =
 
1302
                                        buf + left + top * srcPitch;
 
1303
 
 
1304
                                for (i = 0; i < nlines; i++) {
 
1305
                                        int dwords = npixels << 1;
 
1306
 
 
1307
                                        while (dwords & ~0x03) {
 
1308
                                                *map = *tbuf;
 
1309
                                                *(map + 1) = *(tbuf + 1);
 
1310
                                                *(map + 2) = *(tbuf + 2);
 
1311
                                                *(map + 3) = *(tbuf + 3);
 
1312
                                                map += 4;
 
1313
                                                tbuf += 4;
 
1314
                                                dwords -= 4;
 
1315
                                        }
 
1316
 
 
1317
                                        switch (dwords) {
 
1318
                                        case 3: *(map + 2) = *(tbuf + 2);
 
1319
                                        case 2: *(map + 1) = *(tbuf + 1);
 
1320
                                        case 1: *map = *tbuf;
 
1321
                                        }
 
1322
 
 
1323
                                        map += dstPitch - (npixels << 1);
 
1324
                                        tbuf += srcPitch - (npixels << 1);
 
1325
                                }
 
1326
 
 
1327
                                NVCopyNV12ColorPlanes(buf + s2offset,
 
1328
                                                      buf + s3offset,
 
1329
                                                      map, dstPitch, srcPitch2,
 
1330
                                                      nlines, line_len);
 
1331
                        }
 
1332
                } else {
 
1333
                        /* YUY2 and RGB */
 
1334
                        for (i = 0; i < nlines; i++) {
 
1335
                                int dwords = npixels << 1;
 
1336
 
 
1337
                                while (dwords & ~0x03) {
 
1338
                                        *map = *buf;
 
1339
                                        *(map + 1) = *(buf + 1);
 
1340
                                        *(map + 2) = *(buf + 2);
 
1341
                                        *(map + 3) = *(buf + 3);
 
1342
                                        map += 4;
 
1343
                                        buf += 4;
 
1344
                                        dwords -= 4;
 
1345
                                }
 
1346
 
 
1347
                                switch (dwords) {
 
1348
                                case 3: *(map + 2) = *(buf + 2);
 
1349
                                case 2: *(map + 1) = *(buf + 1);
 
1350
                                case 1: *map = *buf;
 
1351
                                }
 
1352
 
 
1353
                                map += dstPitch - (npixels << 1);
 
1354
                                buf += srcPitch - (npixels << 1);
 
1355
                        }
 
1356
                }
 
1357
        }
 
1358
 
 
1359
        if (skip)
 
1360
                return Success;
 
1361
 
 
1362
        if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE)
 
1363
                pPriv->currentHostBuffer ^= 1;
 
1364
 
 
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...
 
1367
         */
 
1368
        if (!(action_flags & USE_OVERLAY)) {
 
1369
                ppix = NVGetDrawablePixmap(pDraw);
 
1370
 
 
1371
                /* Ensure pixmap is in offscreen memory */
 
1372
                exaMoveInPixmap(ppix);
 
1373
                ExaOffscreenMarkUsed(ppix);
 
1374
 
 
1375
#ifdef COMPOSITE
 
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;
 
1384
                }
 
1385
 
 
1386
                /* Damage tracking */
 
1387
                DamageDamageRegion(&ppix->drawable, clipBoxes);
 
1388
#endif
 
1389
        }
 
1390
 
 
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,
 
1397
                                            clipBoxes);
 
1398
                } else {
 
1399
                        unsigned uvoffset = 0;
 
1400
 
 
1401
                        if (action_flags & (IS_YUY2 | CONVERT_TO_YUY2))
 
1402
                                uvoffset = offset + nlines * dstPitch;
 
1403
 
 
1404
                        NV10PutOverlayImage(pScrn, pPriv->video_mem, offset,
 
1405
                                            uvoffset, id, dstPitch, &dstBox,
 
1406
                                            0, 0, xb, yb,
 
1407
                                            npixels, nlines, src_w, src_h,
 
1408
                                            drw_w, drw_h, clipBoxes);
 
1409
                }
 
1410
 
 
1411
                pPriv->currentBuffer ^= 1;
 
1412
        } else 
 
1413
        if (action_flags & USE_TEXTURE) {
 
1414
                int ret = BadImplementation;
 
1415
 
 
1416
                if (pNv->Architecture == NV_ARCH_30) {
 
1417
                        ret = NV30PutTextureImage(pScrn, pPriv->video_mem,
 
1418
                                                  offset,
 
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);
 
1424
                } else
 
1425
                if (pNv->Architecture == NV_ARCH_40) {
 
1426
                        ret = NV40PutTextureImage(pScrn, pPriv->video_mem, 
 
1427
                                                  offset,
 
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);
 
1433
                }
 
1434
 
 
1435
                if (ret != Success)
 
1436
                        return ret;
 
1437
        } else {
 
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);
 
1441
        }
 
1442
 
 
1443
        return Success;
 
1444
}
 
1445
 
 
1446
/**
 
1447
 * QueryImageAttributes
 
1448
 *
 
1449
 * calculates
 
1450
 * - size (memory required to store image),
 
1451
 * - pitches,
 
1452
 * - offsets
 
1453
 * of image
 
1454
 * depending on colorspace (id) and dimensions (w,h) of image
 
1455
 * values of
 
1456
 * - w,
 
1457
 * - h
 
1458
 * may be adjusted as needed
 
1459
 *
 
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
 
1467
 */
 
1468
static int
 
1469
NVQueryImageAttributes(ScrnInfoPtr pScrn, int id,
 
1470
                       unsigned short *w, unsigned short *h,
 
1471
                       int *pitches, int *offsets)
 
1472
{
 
1473
        int size, tmp;
 
1474
 
 
1475
        if (*w > IMAGE_MAX_W)
 
1476
                *w = IMAGE_MAX_W;
 
1477
        if (*h > IMAGE_MAX_H)
 
1478
                *h = IMAGE_MAX_H;
 
1479
 
 
1480
        *w = (*w + 1) & ~1; // width rounded up to an even number
 
1481
        if (offsets)
 
1482
                offsets[0] = 0;
 
1483
 
 
1484
        switch (id) {
 
1485
        case FOURCC_YV12:
 
1486
        case FOURCC_I420:
 
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
 
1489
                if (pitches)
 
1490
                        pitches[0] = size; // width rounded up to a multiple of 4
 
1491
                size *= *h;
 
1492
                if (offsets)
 
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
 
1495
                if (pitches)
 
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
 
1499
                if (offsets)
 
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
 
1502
                break;
 
1503
        case FOURCC_UYVY:
 
1504
        case FOURCC_YUY2:
 
1505
                size = *w << 1; // 2*width
 
1506
                if (pitches)
 
1507
                        pitches[0] = size; // 2*width
 
1508
                size *= *h; // 2*width*height
 
1509
                break;
 
1510
        case FOURCC_RGB:
 
1511
                size = *w << 2; // 4*width (32 bit per pixel)
 
1512
                if (pitches)
 
1513
                        pitches[0] = size; // 4*width
 
1514
                size *= *h; // 4*width*height
 
1515
                break;
 
1516
        default:
 
1517
                *w = *h = size = 0;
 
1518
                break;
 
1519
        }
 
1520
 
 
1521
        return size;
 
1522
}
 
1523
 
 
1524
/***** Exported offscreen surface stuff ****/
 
1525
 
 
1526
 
 
1527
static int
 
1528
NVAllocSurface(ScrnInfoPtr pScrn, int id,
 
1529
               unsigned short w, unsigned short h,
 
1530
               XF86SurfacePtr surface)
 
1531
{
 
1532
        NVPtr pNv = NVPTR(pScrn);
 
1533
        NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
 
1534
        int size, bpp, ret;
 
1535
 
 
1536
        bpp = pScrn->bitsPerPixel >> 3;
 
1537
 
 
1538
        if (pPriv->grabbedByV4L)
 
1539
                return BadAlloc;
 
1540
 
 
1541
        if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H))
 
1542
                return BadValue;
 
1543
 
 
1544
        w = (w + 1) & ~1;
 
1545
        pPriv->pitch = ((w << 1) + 63) & ~63;
 
1546
        size = h * pPriv->pitch / bpp;
 
1547
 
 
1548
        ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_VRAM, size,
 
1549
                                    &pPriv->video_mem);
 
1550
        if (ret)
 
1551
                return BadAlloc;
 
1552
        pPriv->offset = 0;
 
1553
 
 
1554
        surface->width = w;
 
1555
        surface->height = h;
 
1556
        surface->pScrn = pScrn;
 
1557
        surface->pitches = &pPriv->pitch;
 
1558
        surface->offsets = &pPriv->offset;
 
1559
        surface->devPrivate.ptr = (pointer)pPriv;
 
1560
        surface->id = id;
 
1561
 
 
1562
        /* grab the video */
 
1563
        NVStopOverlay(pScrn);
 
1564
        pPriv->videoStatus = 0;
 
1565
        REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
 
1566
        pPriv->grabbedByV4L = TRUE;
 
1567
 
 
1568
        return Success;
 
1569
}
 
1570
 
 
1571
static int
 
1572
NVStopSurface(XF86SurfacePtr surface)
 
1573
{
 
1574
        NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
 
1575
 
 
1576
        if (pPriv->grabbedByV4L && pPriv->videoStatus) {
 
1577
                NV10StopOverlay(surface->pScrn);
 
1578
                pPriv->videoStatus = 0;
 
1579
        }
 
1580
 
 
1581
        return Success;
 
1582
}
 
1583
 
 
1584
static int
 
1585
NVFreeSurface(XF86SurfacePtr surface)
 
1586
{
 
1587
        NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
 
1588
 
 
1589
        if (pPriv->grabbedByV4L) {
 
1590
                NVStopSurface(surface);
 
1591
                NVFreeOverlayMemory(surface->pScrn);
 
1592
                pPriv->grabbedByV4L = FALSE;
 
1593
        }
 
1594
 
 
1595
        return Success;
 
1596
}
 
1597
 
 
1598
static int
 
1599
NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
 
1600
{
 
1601
        NVPtr pNv = NVPTR(pScrn);
 
1602
        NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
 
1603
 
 
1604
        return NV10GetOverlayPortAttribute(pScrn, attribute,
 
1605
                                         value, (pointer)pPriv);
 
1606
}
 
1607
 
 
1608
static int
 
1609
NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
 
1610
{
 
1611
        NVPtr pNv = NVPTR(pScrn);
 
1612
        NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
 
1613
 
 
1614
        return NV10SetOverlayPortAttribute(pScrn, attribute,
 
1615
                                         value, (pointer)pPriv);
 
1616
}
 
1617
 
 
1618
static int
 
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)
 
1625
{
 
1626
        ScrnInfoPtr pScrn = surface->pScrn;
 
1627
        NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
 
1628
        INT32 xa, xb, ya, yb;
 
1629
        BoxRec dstBox;
 
1630
 
 
1631
        if (!pPriv->grabbedByV4L)
 
1632
                return Success;
 
1633
 
 
1634
        if (src_w > (drw_w << 3))
 
1635
                drw_w = src_w >> 3;
 
1636
        if (src_h > (drw_h << 3))
 
1637
                drw_h = src_h >> 3;
 
1638
 
 
1639
        /* Clip */
 
1640
        xa = src_x;
 
1641
        xb = src_x + src_w;
 
1642
        ya = src_y;
 
1643
        yb = src_y + src_h;
 
1644
 
 
1645
        dstBox.x1 = drw_x;
 
1646
        dstBox.x2 = drw_x + drw_w;
 
1647
        dstBox.y1 = drw_y;
 
1648
        dstBox.y2 = drw_y + drw_h;
 
1649
 
 
1650
        if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
 
1651
                                  surface->width, surface->height))
 
1652
                return Success;
 
1653
 
 
1654
        dstBox.x1 -= pScrn->frameX0;
 
1655
        dstBox.x2 -= pScrn->frameX0;
 
1656
        dstBox.y1 -= pScrn->frameY0;
 
1657
        dstBox.y2 -= pScrn->frameY0;
 
1658
 
 
1659
        pPriv->currentBuffer = 0;
 
1660
 
 
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);
 
1665
 
 
1666
        return Success;
 
1667
}
 
1668
 
 
1669
/**
 
1670
 * NVSetupBlitVideo
 
1671
 * this function does all the work setting up a blit port
 
1672
 *
 
1673
 * @return blit port
 
1674
 */
 
1675
static XF86VideoAdaptorPtr
 
1676
NVSetupBlitVideo (ScreenPtr pScreen)
 
1677
{
 
1678
        ScrnInfoPtr         pScrn = xf86Screens[pScreen->myNum];
 
1679
        NVPtr               pNv       = NVPTR(pScrn);
 
1680
        XF86VideoAdaptorPtr adapt;
 
1681
        NVPortPrivPtr       pPriv;
 
1682
        int i;
 
1683
 
 
1684
        if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
 
1685
                                        sizeof(NVPortPrivRec) +
 
1686
                                        (sizeof(DevUnion) * NUM_BLIT_PORTS)))) {
 
1687
                return NULL;
 
1688
        }
 
1689
 
 
1690
        adapt->type             = XvWindowMask | XvInputMask | XvImageMask;
 
1691
        adapt->flags            = 0;
 
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]);
 
1699
 
 
1700
        pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
 
1701
        for(i = 0; i < NUM_BLIT_PORTS; i++)
 
1702
                adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
 
1703
 
 
1704
        if(pNv->WaitVSyncPossible) {
 
1705
                adapt->pAttributes = NVBlitAttributes;
 
1706
                adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
 
1707
        } else {
 
1708
                adapt->pAttributes = NULL;
 
1709
                adapt->nAttributes = 0;
 
1710
        }
 
1711
 
 
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;
 
1724
 
 
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;
 
1732
 
 
1733
        pNv->blitAdaptor                = adapt;
 
1734
        xvSyncToVBlank                  = MAKE_ATOM("XV_SYNC_TO_VBLANK");
 
1735
 
 
1736
        return adapt;
 
1737
}
 
1738
 
 
1739
/**
 
1740
 * NVSetupOverlayVideo
 
1741
 * this function does all the work setting up an overlay port
 
1742
 *
 
1743
 * @return overlay port
 
1744
 */
 
1745
static XF86VideoAdaptorPtr
 
1746
NVSetupOverlayVideoAdapter(ScreenPtr pScreen)
 
1747
{
 
1748
        ScrnInfoPtr         pScrn = xf86Screens[pScreen->myNum];
 
1749
        NVPtr               pNv       = NVPTR(pScrn);
 
1750
        XF86VideoAdaptorPtr adapt;
 
1751
        NVPortPrivPtr       pPriv;
 
1752
 
 
1753
        if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
 
1754
                                        sizeof(NVPortPrivRec) +
 
1755
                                        sizeof(DevUnion)))) {
 
1756
                return NULL;
 
1757
        }
 
1758
 
 
1759
        adapt->type             = XvWindowMask | XvInputMask | XvImageMask;
 
1760
        if (pNv->randr12_enable)
 
1761
                adapt->flags            = VIDEO_OVERLAID_IMAGES;
 
1762
        else
 
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;
 
1769
        adapt->nPorts           = 1;
 
1770
        adapt->pPortPrivates    = (DevUnion*)(&adapt[1]);
 
1771
 
 
1772
        pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
 
1773
        adapt->pPortPrivates[0].ptr     = (pointer)(pPriv);
 
1774
 
 
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;
 
1789
 
 
1790
        pPriv->videoStatus              = 0;
 
1791
        pPriv->currentBuffer            = 0;
 
1792
        pPriv->grabbedByV4L             = FALSE;
 
1793
        pPriv->blitter                  = FALSE;
 
1794
        pPriv->texture                  = FALSE;
 
1795
        pPriv->bicubic                  = FALSE;
 
1796
 
 
1797
        NVSetPortDefaults (pScrn, pPriv);
 
1798
 
 
1799
        /* gotta uninit this someplace */
 
1800
        REGION_NULL(pScreen, &pPriv->clip);
 
1801
 
 
1802
        pNv->overlayAdaptor     = adapt;
 
1803
 
 
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");
 
1808
 
 
1809
        if ( pNv->Architecture != NV_ARCH_04 )
 
1810
                {
 
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);
 
1818
                }
 
1819
 
 
1820
        return adapt;
 
1821
}
 
1822
 
 
1823
 
 
1824
XF86OffscreenImageRec NVOffscreenImages[2] = {
 
1825
        {
 
1826
                &NVImages[0],
 
1827
                VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
 
1828
                NVAllocSurface,
 
1829
                NVFreeSurface,
 
1830
                NVDisplaySurface,
 
1831
                NVStopSurface,
 
1832
                NVGetSurfaceAttribute,
 
1833
                NVSetSurfaceAttribute,
 
1834
                IMAGE_MAX_W, IMAGE_MAX_H,
 
1835
                NUM_NV10_OVERLAY_ATTRIBUTES - 1,
 
1836
                &NV10OverlayAttributes[1]
 
1837
        },
 
1838
        {
 
1839
                &NVImages[2],
 
1840
                VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
 
1841
                NVAllocSurface,
 
1842
                NVFreeSurface,
 
1843
                NVDisplaySurface,
 
1844
                NVStopSurface,
 
1845
                NVGetSurfaceAttribute,
 
1846
                NVSetSurfaceAttribute,
 
1847
                IMAGE_MAX_W, IMAGE_MAX_H,
 
1848
                NUM_NV10_OVERLAY_ATTRIBUTES - 1,
 
1849
                &NV10OverlayAttributes[1]
 
1850
        }
 
1851
};
 
1852
 
 
1853
static void
 
1854
NVInitOffscreenImages (ScreenPtr pScreen)
 
1855
{
 
1856
        xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
 
1857
}
 
1858
 
 
1859
/**
 
1860
 * NVChipsetHasOverlay
 
1861
 *
 
1862
 * newer chips don't support overlay anymore.
 
1863
 * overlay feature is emulated via textures.
 
1864
 *
 
1865
 * @param pNv
 
1866
 * @return true, if chipset supports overlay
 
1867
 */
 
1868
static Bool
 
1869
NVChipsetHasOverlay(NVPtr pNv)
 
1870
{
 
1871
        switch (pNv->Architecture) {
 
1872
        case NV_ARCH_04: /*NV04 has a different overlay than NV10+*/
 
1873
        case NV_ARCH_10:
 
1874
        case NV_ARCH_20:
 
1875
        case NV_ARCH_30:
 
1876
                return TRUE;
 
1877
        case NV_ARCH_40:
 
1878
                if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)
 
1879
                        return TRUE;
 
1880
                break;
 
1881
        default:
 
1882
                break;
 
1883
        }
 
1884
 
 
1885
        return FALSE;
 
1886
}
 
1887
 
 
1888
/**
 
1889
 * NVSetupOverlayVideo
 
1890
 * check if chipset supports Overla
 
1891
 * if so, setup overlay port
 
1892
 *
 
1893
 * @return overlay port
 
1894
 * @see NVChipsetHasOverlay(NVPtr pNv)
 
1895
 * @see NV10SetupOverlayVideo(ScreenPtr pScreen)
 
1896
 * @see NVInitOffscreenImages(ScreenPtr pScreen)
 
1897
 */
 
1898
static XF86VideoAdaptorPtr
 
1899
NVSetupOverlayVideo(ScreenPtr pScreen)
 
1900
{
 
1901
        ScrnInfoPtr          pScrn = xf86Screens[pScreen->myNum];
 
1902
        XF86VideoAdaptorPtr  overlayAdaptor = NULL;
 
1903
        NVPtr                pNv   = NVPTR(pScrn);
 
1904
 
 
1905
        if (!NVChipsetHasOverlay(pNv))
 
1906
                return NULL;
 
1907
 
 
1908
        overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen);
 
1909
        /* I am not sure what this call does. */
 
1910
        if (overlayAdaptor && pNv->Architecture != NV_ARCH_04 )
 
1911
                NVInitOffscreenImages(pScreen);
 
1912
 
 
1913
        #ifdef COMPOSITE
 
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";
 
1919
        }
 
1920
        #endif
 
1921
 
 
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");
 
1926
        }
 
1927
 
 
1928
 
 
1929
        return overlayAdaptor;
 
1930
}
 
1931
 
 
1932
/**
 
1933
 * NV30 texture adapter.
 
1934
 */
 
1935
 
 
1936
#define NUM_FORMAT_TEXTURED 2
 
1937
 
 
1938
static XF86ImageRec NV30TexturedImages[NUM_FORMAT_TEXTURED] =
 
1939
{
 
1940
        XVIMAGE_YV12,
 
1941
        XVIMAGE_I420,
 
1942
};
 
1943
 
 
1944
/**
 
1945
 * NV30SetupTexturedVideo
 
1946
 * this function does all the work setting up textured video port
 
1947
 *
 
1948
 * @return texture port
 
1949
 */
 
1950
static XF86VideoAdaptorPtr
 
1951
NV30SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic)
 
1952
{
 
1953
        ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 
1954
        NVPtr pNv = NVPTR(pScrn);
 
1955
        XF86VideoAdaptorPtr adapt;
 
1956
        NVPortPrivPtr pPriv;
 
1957
        int i;
 
1958
 
 
1959
        if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
 
1960
                                 sizeof(NVPortPrivRec) +
 
1961
                                 (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
 
1962
                return NULL;
 
1963
        }
 
1964
 
 
1965
        adapt->type             = XvWindowMask | XvInputMask | XvImageMask;
 
1966
        adapt->flags            = 0;
 
1967
        if (bicubic)
 
1968
                adapt->name             = "NV30 high quality adapter";
 
1969
        else
 
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]);
 
1977
 
 
1978
        pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
 
1979
        for(i = 0; i < NUM_TEXTURE_PORTS; i++)
 
1980
                adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
 
1981
 
 
1982
        if(pNv->WaitVSyncPossible) {
 
1983
                adapt->pAttributes = NVTexturedAttributes;
 
1984
                adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
 
1985
        } else {
 
1986
                adapt->pAttributes = NULL;
 
1987
                adapt->nAttributes = 0;
 
1988
        }
 
1989
 
 
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;
 
2002
 
 
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;
 
2010
 
 
2011
        if (bicubic)
 
2012
                pNv->textureAdaptor[1]  = adapt;
 
2013
        else
 
2014
                pNv->textureAdaptor[0]  = adapt;
 
2015
 
 
2016
        return adapt;
 
2017
}
 
2018
 
 
2019
/**
 
2020
 * NV40 texture adapter.
 
2021
 */
 
2022
 
 
2023
#define NUM_FORMAT_TEXTURED 2
 
2024
 
 
2025
static XF86ImageRec NV40TexturedImages[NUM_FORMAT_TEXTURED] =
 
2026
{
 
2027
        XVIMAGE_YV12,
 
2028
        XVIMAGE_I420,
 
2029
};
 
2030
 
 
2031
/**
 
2032
 * NV40SetupTexturedVideo
 
2033
 * this function does all the work setting up textured video port
 
2034
 *
 
2035
 * @return texture port
 
2036
 */
 
2037
static XF86VideoAdaptorPtr
 
2038
NV40SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic)
 
2039
{
 
2040
        ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 
2041
        NVPtr pNv = NVPTR(pScrn);
 
2042
        XF86VideoAdaptorPtr adapt;
 
2043
        NVPortPrivPtr pPriv;
 
2044
        int i;
 
2045
 
 
2046
        if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
 
2047
                                 sizeof(NVPortPrivRec) +
 
2048
                                 (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
 
2049
                return NULL;
 
2050
        }
 
2051
 
 
2052
        adapt->type             = XvWindowMask | XvInputMask | XvImageMask;
 
2053
        adapt->flags            = 0;
 
2054
        if (bicubic)
 
2055
                adapt->name             = "NV40 high quality adapter";
 
2056
        else
 
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]);
 
2064
 
 
2065
        pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
 
2066
        for(i = 0; i < NUM_TEXTURE_PORTS; i++)
 
2067
                adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
 
2068
 
 
2069
        if(pNv->WaitVSyncPossible) {
 
2070
                adapt->pAttributes = NVTexturedAttributes;
 
2071
                adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
 
2072
        } else {
 
2073
                adapt->pAttributes = NULL;
 
2074
                adapt->nAttributes = 0;
 
2075
        }
 
2076
 
 
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;
 
2089
 
 
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;
 
2097
 
 
2098
        if (bicubic)
 
2099
                pNv->textureAdaptor[1]  = adapt;
 
2100
        else
 
2101
                pNv->textureAdaptor[0]  = adapt;
 
2102
 
 
2103
        return adapt;
 
2104
}
 
2105
 
 
2106
/**
 
2107
 * NVInitVideo
 
2108
 * tries to initialize the various supported adapters
 
2109
 * and add them to the list of ports on screen "pScreen".
 
2110
 *
 
2111
 * @param pScreen
 
2112
 * @see NVSetupOverlayVideo(ScreenPtr pScreen)
 
2113
 * @see NVSetupBlitVideo(ScreenPtr pScreen)
 
2114
 */
 
2115
void
 
2116
NVInitVideo(ScreenPtr pScreen)
 
2117
{
 
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};
 
2124
        int                  num_adaptors;
 
2125
 
 
2126
        /*
 
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:
 
2131
         */
 
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);
 
2139
                }
 
2140
                if (pNv->Architecture == NV_ARCH_40) {
 
2141
                        textureAdaptor[0] = NV40SetupTexturedVideo(pScreen, FALSE);
 
2142
                        textureAdaptor[1] = NV40SetupTexturedVideo(pScreen, TRUE);
 
2143
                }
 
2144
        }
 
2145
 
 
2146
        num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
 
2147
        if(blitAdaptor || overlayAdaptor) {
 
2148
                int size = num_adaptors;
 
2149
 
 
2150
                if(overlayAdaptor) size++;
 
2151
                if(blitAdaptor)    size++;
 
2152
                if(textureAdaptor[0]) size++;
 
2153
                if(textureAdaptor[1]) size++;
 
2154
 
 
2155
                newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr *));
 
2156
                if(newAdaptors) {
 
2157
                        if(num_adaptors) {
 
2158
                                memcpy(newAdaptors, adaptors, num_adaptors *
 
2159
                                                sizeof(XF86VideoAdaptorPtr));
 
2160
                        }
 
2161
 
 
2162
                        if(overlayAdaptor) {
 
2163
                                newAdaptors[num_adaptors] = overlayAdaptor;
 
2164
                                num_adaptors++;
 
2165
                        }
 
2166
 
 
2167
                        if (textureAdaptor[0]) { /* bilinear */
 
2168
                                newAdaptors[num_adaptors] = textureAdaptor[0];
 
2169
                                num_adaptors++;
 
2170
                        }
 
2171
 
 
2172
                        if (textureAdaptor[1]) { /* bicubic */
 
2173
                                newAdaptors[num_adaptors] = textureAdaptor[1];
 
2174
                                num_adaptors++;
 
2175
                        }
 
2176
 
 
2177
                        if(blitAdaptor) {
 
2178
                                newAdaptors[num_adaptors] = blitAdaptor;
 
2179
                                num_adaptors++;
 
2180
                        }
 
2181
 
 
2182
                        adaptors = newAdaptors;
 
2183
                }
 
2184
        }
 
2185
 
 
2186
        if (num_adaptors)
 
2187
                xf86XVScreenInit(pScreen, adaptors, num_adaptors);
 
2188
        if (newAdaptors)
 
2189
                xfree(newAdaptors);
 
2190
}