~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to hw/kdrive/nvidia/nvidiavideo.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: nvidiavideo.c,v 1.3 2005/12/27 08:29:47 ajax Exp $
 
3
 *
 
4
 * Copyright Ā© 2003 Keith Packard
 
5
 *
 
6
 * Permission to use, copy, modify, distribute, and sell this software and its
 
7
 * documentation for any purpose is hereby granted without fee, provided that
 
8
 * the above copyright notice appear in all copies and that both that
 
9
 * copyright notice and this permission notice appear in supporting
 
10
 * documentation, and that the name of Keith Packard not be used in
 
11
 * advertising or publicity pertaining to distribution of the software without
 
12
 * specific, written prior permission.  Keith Packard makes no
 
13
 * representations about the suitability of this software for any purpose.  It
 
14
 * is provided "as is" without express or implied warranty.
 
15
 *
 
16
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
17
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
18
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
19
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
20
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
21
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
22
 * PERFORMANCE OF THIS SOFTWARE.
 
23
 */
 
24
 
 
25
#ifdef HAVE_CONFIG_H
 
26
#include <kdrive-config.h>
 
27
#endif
 
28
#include "nvidia.h"
 
29
 
 
30
#include <X11/extensions/Xv.h>
 
31
#include "fourcc.h"
 
32
 
 
33
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
 
34
 
 
35
static Atom xvBrightness, xvSaturation, xvColorKey;
 
36
 
 
37
#define IMAGE_MAX_WIDTH         720
 
38
#define IMAGE_MAX_HEIGHT        576
 
39
 
 
40
static void
 
41
nvidiaStopVideo(KdScreenInfo *screen, pointer data, Bool exit)
 
42
{
 
43
    ScreenPtr           pScreen = screen->pScreen;
 
44
    KdScreenPriv(pScreen);
 
45
    KdCardInfo          *card = pScreenPriv->card;
 
46
    NvidiaScreenInfo    *nvidias = (NvidiaScreenInfo *) screen->driver;
 
47
    NvidiaCardInfo      *nvidiac = (NvidiaCardInfo *) card->driver;
 
48
    NvidiaPortPrivPtr   pPortPriv = nvidias->pAdaptor->pPortPrivates[0].ptr;
 
49
    Reg                 *reg = nvidiac->reg;
 
50
    MediaReg            *media = nvidiac->media_reg;
 
51
 
 
52
    REGION_EMPTY(screen->pScreen, &pPortPriv->clip);   
 
53
 
 
54
    if (!media)
 
55
        return;
 
56
 
 
57
    if(pPortPriv->videoOn)
 
58
    {
 
59
        nvidiaWaitIdle (reg);
 
60
        /* wait for buffer to be displayed */
 
61
        while (((media->TRIG_CNTL >> 5) & 1) != pPortPriv->currentBuf)
 
62
            ;
 
63
        /* wait for buffer to be finished */
 
64
        while (((media->TRIG_CNTL >> 6) & 1) != 0)
 
65
            ;
 
66
        nvidiaWaitAvail (reg, 1);
 
67
        media->OVERLAY_SCALE_CNTL = 0;
 
68
        pPortPriv->videoOn = FALSE;
 
69
        nvidiaWaitIdle (reg);
 
70
    }
 
71
}
 
72
 
 
73
static int
 
74
nvidiaSetPortAttribute(KdScreenInfo *screen,
 
75
                       Atom         attribute,
 
76
                       int          value,
 
77
                       pointer      data)
 
78
{
 
79
    ScreenPtr           pScreen = screen->pScreen;
 
80
    KdScreenPriv(pScreen);
 
81
    KdCardInfo          *card = pScreenPriv->card;
 
82
    NvidiaScreenInfo    *nvidias = (NvidiaScreenInfo *) screen->driver;
 
83
    NvidiaCardInfo      *nvidiac = (NvidiaCardInfo *) card->driver;
 
84
    NvidiaPortPrivPtr   pPortPriv = nvidias->pAdaptor->pPortPrivates[0].ptr;
 
85
    MediaReg            *media = nvidiac->media_reg;
 
86
 
 
87
    if(attribute == xvBrightness) 
 
88
    {
 
89
        if(value < -1000)
 
90
            value = -1000;
 
91
        if (value > 1000)
 
92
            value = 1000;
 
93
        pPortPriv->brightness = value;
 
94
    }
 
95
    else if(attribute == xvSaturation) 
 
96
    {
 
97
        if (value < -1000)
 
98
            value = -1000;
 
99
        if (value > 1000)
 
100
            value = 1000;
 
101
        pPortPriv->saturation = value;
 
102
    }
 
103
    else if(attribute == xvColorKey) 
 
104
    {
 
105
        if (pPortPriv->colorKey != value)
 
106
        {
 
107
            pPortPriv->colorKey = value;
 
108
            REGION_EMPTY(screen->pScreen, &pPortPriv->clip);   
 
109
        }
 
110
    }
 
111
    else 
 
112
        return BadMatch;
 
113
 
 
114
    return Success;
 
115
}
 
116
 
 
117
static int
 
118
nvidiaGetPortAttribute(KdScreenInfo *screen, 
 
119
                       Atom         attribute,
 
120
                       int          *value,
 
121
                       pointer      data)
 
122
{
 
123
    NvidiaPortPrivPtr pPortPriv = (NvidiaPortPrivPtr)data;
 
124
 
 
125
    if(attribute == xvBrightness) 
 
126
        *value = pPortPriv->brightness;
 
127
    else if(attribute == xvSaturation)
 
128
        *value = pPortPriv->saturation;
 
129
    else if(attribute == xvColorKey)
 
130
        *value = pPortPriv->colorKey;
 
131
    else
 
132
        return BadMatch;
 
133
 
 
134
    return Success;
 
135
}
 
136
 
 
137
static void
 
138
nvidiaQueryBestSize(KdScreenInfo    *screen,
 
139
                    Bool            motion,
 
140
                    short           vid_w,
 
141
                    short           vid_h,
 
142
                    short           drw_w,
 
143
                    short           drw_h, 
 
144
                    unsigned int    *p_w,
 
145
                    unsigned int    *p_h,
 
146
                    pointer         data)
 
147
{
 
148
    *p_w = drw_w;
 
149
    *p_h = drw_h; 
 
150
}
 
151
 
 
152
 
 
153
static void
 
154
nvidiaCopyPackedData(KdScreenInfo   *screen, 
 
155
                     unsigned char  *buf,
 
156
                     int            randr,
 
157
                     int            srcPitch,
 
158
                     int            dstPitch,
 
159
                     int            srcW,
 
160
                     int            srcH,
 
161
                     int            top,
 
162
                     int            left,
 
163
                     int            h,
 
164
                     int            w)
 
165
{
 
166
    ScreenPtr           pScreen = screen->pScreen;
 
167
    KdScreenPriv(pScreen);
 
168
    KdCardInfo          *card = pScreenPriv->card;
 
169
    NvidiaScreenInfo    *nvidias = (NvidiaScreenInfo *) screen->driver;
 
170
    NvidiaCardInfo      *nvidiac = (NvidiaCardInfo *) card->driver;
 
171
    NvidiaPortPrivPtr   pPortPriv = nvidias->pAdaptor->pPortPrivates[0].ptr;
 
172
    CARD8               *src, *dst;
 
173
    int                 srcDown, srcRight, srcNext;
 
174
    int                 p;
 
175
 
 
176
    switch (randr & RR_Rotate_All) {
 
177
    case RR_Rotate_0:
 
178
        src = buf;
 
179
        srcDown = srcPitch;
 
180
        srcRight = 2;
 
181
        break;
 
182
    case RR_Rotate_90:
 
183
        src = buf + (srcH - 1) * 2;
 
184
        srcDown = -2;
 
185
        srcRight = srcPitch;
 
186
        break;
 
187
    case RR_Rotate_180:
 
188
        src = buf + srcPitch * (srcH - 1) + (srcW - 1) * 2;
 
189
        srcDown = -srcPitch;
 
190
        srcRight = -2;
 
191
        break;
 
192
    case RR_Rotate_270:
 
193
        src = buf + srcPitch * (srcW - 1);
 
194
        srcDown = 2;
 
195
        srcRight = -srcPitch;
 
196
        break;
 
197
    }
 
198
 
 
199
    src = src + top*srcDown + left*srcRight;
 
200
 
 
201
    if (pPortPriv->currentBuf == 0)
 
202
        dst = (CARD8 *) nvidias->vesa.fb + pPortPriv->YBuf0Offset;
 
203
    else
 
204
        dst = (CARD8 *) nvidias->vesa.fb + pPortPriv->YBuf1Offset;
 
205
 
 
206
    w >>= 1;
 
207
    srcRight >>= 1;
 
208
    srcNext = srcRight >> 1;
 
209
    while(h--) 
 
210
    {
 
211
        CARD16  *s = (CARD16 *) src;
 
212
        CARD32  *d = (CARD32 *) dst;
 
213
        p = w;
 
214
        while (p--)
 
215
        {
 
216
            *d++ = s[0] | (s[srcNext] << 16);
 
217
            s += srcRight;
 
218
        }
 
219
        src += srcPitch;
 
220
        dst += dstPitch;
 
221
    }
 
222
}
 
223
 
 
224
static void
 
225
nvidiaCopyPlanarData(KdScreenInfo   *screen, 
 
226
                     unsigned char  *buf,
 
227
                     int            randr,
 
228
                     int            srcPitch,
 
229
                     int            srcPitch2,
 
230
                     int            dstPitch,  /* of chroma */
 
231
                     int            srcW,
 
232
                     int            srcH,
 
233
                     int            height,
 
234
                     int            top,
 
235
                     int            left,
 
236
                     int            h,
 
237
                     int            w,
 
238
                     int            id)
 
239
{
 
240
    ScreenPtr           pScreen = screen->pScreen;
 
241
    KdScreenPriv(pScreen);
 
242
    KdCardInfo          *card = pScreenPriv->card;
 
243
    NvidiaScreenInfo    *nvidias = (NvidiaScreenInfo *) screen->driver;
 
244
    NvidiaCardInfo      *nvidiac = (NvidiaCardInfo *) card->driver;
 
245
    NvidiaPortPrivPtr   pPortPriv = nvidias->pAdaptor->pPortPrivates[0].ptr;
 
246
    int                 i, j;
 
247
    CARD8               *src1, *src2, *src3, *dst1;
 
248
    int                 srcDown, srcDown2, srcRight, srcRight2, srcNext;
 
249
 
 
250
    /* compute source data pointers */
 
251
    src1 = buf;
 
252
    src2 = src1 + height * srcPitch;
 
253
    src3 = src2 + (height >> 1) * srcPitch2;
 
254
    switch (randr & RR_Rotate_All) {
 
255
    case RR_Rotate_0:
 
256
        srcDown = srcPitch;
 
257
        srcDown2 = srcPitch2;
 
258
        srcRight = 2;
 
259
        srcRight2 = 1;
 
260
        srcNext = 1;
 
261
        break;
 
262
    case RR_Rotate_90:
 
263
        src1 = src1 + srcH - 1;
 
264
        src2 = src2 + (srcH >> 1) - 1;
 
265
        src3 = src3 + (srcH >> 1) - 1;
 
266
        srcDown = -1;
 
267
        srcDown2 = -1;
 
268
        srcRight = srcPitch * 2;
 
269
        srcRight2 = srcPitch2;
 
270
        srcNext = srcPitch;
 
271
        break;
 
272
    case RR_Rotate_180:
 
273
        src1 = src1 + srcPitch * (srcH - 1) + (srcW - 1);
 
274
        src2 = src2 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1);
 
275
        src3 = src3 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1);
 
276
        srcDown = -srcPitch;
 
277
        srcDown2 = -srcPitch2;
 
278
        srcRight = -2;
 
279
        srcRight2 = -1;
 
280
        srcNext = -1;
 
281
        break;
 
282
    case RR_Rotate_270:
 
283
        src1 = src1 + srcPitch * (srcW - 1);
 
284
        src2 = src2 + srcPitch2 * ((srcW >> 1) - 1);
 
285
        src3 = src3 + srcPitch2 * ((srcW >> 1) - 1);
 
286
        srcDown = 1;
 
287
        srcDown2 = 1;
 
288
        srcRight = -srcPitch * 2;
 
289
        srcRight2 = -srcPitch2;
 
290
        srcNext = -srcPitch;
 
291
        break;
 
292
    }
 
293
    
 
294
    /* adjust for origin */
 
295
    src1 += top * srcDown + left * srcNext;
 
296
    src2 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2;
 
297
    src3 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2;
 
298
    
 
299
    if (id == FOURCC_I420)
 
300
    {
 
301
        CARD8   *srct = src2;
 
302
        src2 = src3;
 
303
        src3 = srct;
 
304
    }
 
305
    
 
306
    if (pPortPriv->currentBuf == 0)
 
307
        dst1 = (CARD8 *) nvidias->vesa.fb + pPortPriv->YBuf0Offset;
 
308
    else
 
309
        dst1 = (CARD8 *) nvidias->vesa.fb + pPortPriv->YBuf1Offset;
 
310
 
 
311
    w >>= 1;
 
312
    for (j = 0; j < h; j++) 
 
313
    {
 
314
        CARD32  *dst = (CARD32 *) dst1;
 
315
        CARD8   *s1l = src1;
 
316
        CARD8   *s1r = src1 + srcNext;
 
317
        CARD8   *s2 = src2;
 
318
        CARD8   *s3 = src3;
 
319
 
 
320
        for (i = 0; i < w; i++)
 
321
        {
 
322
            *dst++ = *s1l | (*s1r << 16) | (*s3 << 8) | (*s2 << 24);
 
323
            s1l += srcRight;
 
324
            s1r += srcRight;
 
325
            s2 += srcRight2;
 
326
            s3 += srcRight2;
 
327
        }
 
328
        src1 += srcDown;
 
329
        dst1 += dstPitch;
 
330
        if (j & 1)
 
331
        {
 
332
            src2 += srcDown2;
 
333
            src3 += srcDown2;
 
334
        }
 
335
    }
 
336
}
 
337
 
 
338
static void
 
339
nvidiaPaintRegion (ScreenPtr pScreen, RegionPtr pRgn, Pixel fg)
 
340
{
 
341
    WindowPtr   pRoot = WindowTable[pScreen->myNum];
 
342
    GCPtr       pGC;
 
343
    CARD32      val[2];
 
344
    xRectangle  *rects, *r;
 
345
    BoxPtr      pBox = REGION_RECTS (pRgn);
 
346
    int         nBox = REGION_NUM_RECTS (pRgn);
 
347
    
 
348
    rects = ALLOCATE_LOCAL (nBox * sizeof (xRectangle));
 
349
    if (!rects)
 
350
        goto bail0;
 
351
    r = rects;
 
352
    while (nBox--)
 
353
    {
 
354
        r->x = pBox->x1;
 
355
        r->y = pBox->y1;
 
356
        r->width = pBox->x2 - pBox->x1;
 
357
        r->height = pBox->y2 - pBox->y1;
 
358
        r++;
 
359
        pBox++;
 
360
    }
 
361
    
 
362
    pGC = GetScratchGC (pRoot->drawable.depth, pScreen);
 
363
    if (!pGC)
 
364
        goto bail1;
 
365
    
 
366
    val[0] = fg;
 
367
    val[1] = IncludeInferiors;
 
368
    ChangeGC (pGC, GCForeground|GCSubwindowMode, val);
 
369
    
 
370
    ValidateGC (&pRoot->drawable, pGC);
 
371
    
 
372
    (*pGC->ops->PolyFillRect) (&pRoot->drawable, pGC, 
 
373
                               REGION_NUM_RECTS (pRgn), rects);
 
374
 
 
375
    FreeScratchGC (pGC);
 
376
bail1:
 
377
    DEALLOCATE_LOCAL (rects);
 
378
bail0:
 
379
    ;
 
380
}
 
381
 
 
382
/* NvidiaClipVideo -  
 
383
 
 
384
   Takes the dst box in standard X BoxRec form (top and left
 
385
   edges inclusive, bottom and right exclusive).  The new dst
 
386
   box is returned.  The source boundaries are given (x1, y1 
 
387
   inclusive, x2, y2 exclusive) and returned are the new source 
 
388
   boundaries in 16.16 fixed point. 
 
389
*/
 
390
 
 
391
static void
 
392
NvidiaClipVideo(BoxPtr dst, 
 
393
                INT32 *x1, 
 
394
                INT32 *x2, 
 
395
                INT32 *y1, 
 
396
                INT32 *y2,
 
397
                BoxPtr extents,            /* extents of the clip region */
 
398
                INT32 width, 
 
399
                INT32 height)
 
400
{
 
401
    INT32 vscale, hscale, delta;
 
402
    int diff;
 
403
 
 
404
    hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
 
405
    vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
 
406
 
 
407
    *x1 <<= 16; *x2 <<= 16;
 
408
    *y1 <<= 16; *y2 <<= 16;
 
409
 
 
410
    diff = extents->x1 - dst->x1;
 
411
    if(diff > 0) {
 
412
        dst->x1 = extents->x1;
 
413
        *x1 += diff * hscale;     
 
414
    }
 
415
    diff = dst->x2 - extents->x2;
 
416
    if(diff > 0) {
 
417
        dst->x2 = extents->x2;
 
418
        *x2 -= diff * hscale;     
 
419
    }
 
420
    diff = extents->y1 - dst->y1;
 
421
    if(diff > 0) {
 
422
        dst->y1 = extents->y1;
 
423
        *y1 += diff * vscale;     
 
424
    }
 
425
    diff = dst->y2 - extents->y2;
 
426
    if(diff > 0) {
 
427
        dst->y2 = extents->y2;
 
428
        *y2 -= diff * vscale;     
 
429
    }
 
430
 
 
431
    if(*x1 < 0) {
 
432
        diff =  (- *x1 + hscale - 1)/ hscale;
 
433
        dst->x1 += diff;
 
434
        *x1 += diff * hscale;
 
435
    }
 
436
    delta = *x2 - (width << 16);
 
437
    if(delta > 0) {
 
438
        diff = (delta + hscale - 1)/ hscale;
 
439
        dst->x2 -= diff;
 
440
        *x2 -= diff * hscale;
 
441
    }
 
442
    if(*y1 < 0) {
 
443
        diff =  (- *y1 + vscale - 1)/ vscale;
 
444
        dst->y1 += diff;
 
445
        *y1 += diff * vscale;
 
446
    }
 
447
    delta = *y2 - (height << 16);
 
448
    if(delta > 0) {
 
449
        diff = (delta + vscale - 1)/ vscale;
 
450
        dst->y2 -= diff;
 
451
        *y2 -= diff * vscale;
 
452
    }
 
453
 
454
 
 
455
static void
 
456
nvidiaDisplayVideo(KdScreenInfo *screen,
 
457
                   int          id,
 
458
                   int          dstPitch,  /* of chroma for 4:2:0 */
 
459
                   int          x1,
 
460
                   int          y1,
 
461
                   int          x2,
 
462
                   int          y2,
 
463
                   int          dst_x1,
 
464
                   int          dst_y1,
 
465
                   int          dst_x2,
 
466
                   int          dst_y2,
 
467
                   short        src_w,
 
468
                   short        src_h,
 
469
                   short        drw_w, 
 
470
                   short        drw_h)
 
471
{
 
472
    ScreenPtr           pScreen = screen->pScreen;
 
473
    KdScreenPriv(pScreen);
 
474
    KdCardInfo          *card = pScreenPriv->card;
 
475
    NvidiaScreenInfo    *nvidias = (NvidiaScreenInfo *) screen->driver;
 
476
    NvidiaCardInfo      *nvidiac = (NvidiaCardInfo *) card->driver;
 
477
    NvidiaPortPrivPtr   pPortPriv = nvidias->pAdaptor->pPortPrivates[0].ptr;
 
478
    Reg                 *reg = nvidiac->reg;
 
479
    MediaReg            *media = nvidiac->media_reg;
 
480
    int                 xscaleInt, xscaleFract, yscaleInt, yscaleFract;
 
481
    int                 xscaleIntUV = 0, xscaleFractUV = 0;
 
482
    int                 yscaleIntUV = 0, yscaleFractUV = 0;
 
483
    int                 randr = nvidias->vesa.randr;
 
484
    int                 HORZ_INC, VERT_INC;
 
485
    CARD32              SCALER_IN;
 
486
    CARD32              OVERLAY_SCALE_CNTL;
 
487
    int                 tmp;
 
488
    int                 left;
 
489
    int                 bright;
 
490
    int                 sat;
 
491
 
 
492
    if (id == FOURCC_UYVY)
 
493
        SCALER_IN = SCALER_IN_YVYU422;
 
494
    else
 
495
        SCALER_IN = SCALER_IN_VYUY422;
 
496
 
 
497
    nvidiaWaitAvail (reg, 4);
 
498
    
 
499
    media->VIDEO_FORMAT = SCALER_IN | VIDEO_IN_VYUY422;
 
500
 
 
501
    /* color key */
 
502
    media->OVERLAY_GRAPHICS_KEY_MSK = (1 << screen->fb[0].depth) - 1;
 
503
    media->OVERLAY_GRAPHICS_KEY_CLR = pPortPriv->colorKey;
 
504
    /* set key control to obey only graphics color key */
 
505
    media->OVERLAY_KEY_CNTL = 0x50;
 
506
    
 
507
    nvidiaWaitAvail (reg, 9);
 
508
    media->CAPTURE_DEBUG = 0;
 
509
    /* no exclusive video region */
 
510
    media->OVERLAY_EXCLUSIVE_HORZ = 0;
 
511
    media->OVERLAY_EXCLUSIVE_VERT = 0;
 
512
    /* scaling coefficients */
 
513
    media->SCALER_H_COEFF0 = 0x00002000;
 
514
    media->SCALER_H_COEFF1 = 0x0D06200D;
 
515
    media->SCALER_H_COEFF2 = 0x0D0A1C0D;
 
516
    media->SCALER_H_COEFF3 = 0x0C0E1A0C;
 
517
    media->SCALER_H_COEFF4 = 0x0C14140C;
 
518
    media->SCALER_TEST = 0;
 
519
 
 
520
    nvidiaWaitAvail (reg, 2);
 
521
    media->OVERLAY_SCALE_CNTL = (SCALE_PIX_EXPAND |
 
522
                                 SCALE_GAMMA_BRIGHT |
 
523
                                 SCALE_BANDWIDTH |
 
524
                                 SCALE_OVERLAY_EN |
 
525
                                 SCALE_EN);
 
526
 
 
527
    bright = (pPortPriv->brightness * 64 / 1000);
 
528
    if (bright < -0x40)
 
529
        bright = -0x40;
 
530
    if (bright > 0x3f)
 
531
        bright = 0x3f;
 
532
    bright = bright & 0x7f;
 
533
    sat = ((pPortPriv->saturation * 31 + 31000) / 2000);
 
534
    if (sat > 0x1f)
 
535
        sat = 0x1f;
 
536
    if (sat < 0)
 
537
        sat = 0;
 
538
    
 
539
    media->SCALER_COLOUR_CNTL = ((bright << 0) |        /* BRIGHTNESS */
 
540
                                 (sat << 8) |   /* SATURATION_U */
 
541
                                 (sat << 16) |  /* SATURATION_V */
 
542
                                 (0 << 21) |    /* SCALER_VERT_ADJ_UV */
 
543
                                 (0 << 28));    /* SCALER_HORZ_ADJ_UV */
 
544
 
 
545
    VERT_INC = (src_h << 12) / drw_h;
 
546
    HORZ_INC = (src_w << 12) / drw_w;
 
547
 
 
548
    nvidiaWaitAvail (reg, 13);
 
549
 
 
550
    /* lock registers to prevent non-atomic update */
 
551
    media->OVERLAY_Y_X_START = 0x80000000 | NVIDIA_YX (dst_x1, dst_y1);
 
552
    /* ending screen coordinate */
 
553
    media->OVERLAY_Y_X_END = 0x80000000 | NVIDIA_YX (dst_x2, dst_y2);
 
554
    
 
555
    media->OVERLAY_SCALE_INC = NVIDIA_YX(HORZ_INC, VERT_INC);
 
556
 
 
557
    media->SCALER_BUF0_OFFSET = pPortPriv->YBuf0Offset;
 
558
    media->SCALER_BUF1_OFFSET = pPortPriv->YBuf1Offset;
 
559
    
 
560
    media->SCALER_BUF0_OFFSET_U = pPortPriv->YBuf0Offset;
 
561
    media->SCALER_BUF1_OFFSET_U = pPortPriv->YBuf1Offset;
 
562
    
 
563
    media->SCALER_BUF0_OFFSET_V = pPortPriv->YBuf0Offset;
 
564
    media->SCALER_BUF1_OFFSET_V = pPortPriv->YBuf1Offset;
 
565
    
 
566
    media->SCALER_BUF_PITCH = dstPitch >> 1;
 
567
    media->SCALER_HEIGHT_WIDTH = NVIDIA_YX(src_w - (x1 >> 16), src_h - (y1 >> 16));
 
568
 
 
569
    media->CAPTURE_CONFIG = pPortPriv->currentBuf << 28;
 
570
 
 
571
    /* set XY location and unlock */
 
572
    media->OVERLAY_Y_X_START = NVIDIA_YX (dst_x1, dst_y1);
 
573
}
 
574
 
 
575
static int
 
576
nvidiaPutImage(KdScreenInfo         *screen, 
 
577
               short                src_x,
 
578
               short                src_y,
 
579
               short                drw_x,
 
580
               short                drw_y,
 
581
               short                src_w,
 
582
               short                src_h,
 
583
               short                drw_w,
 
584
               short                drw_h,
 
585
               int                   id,
 
586
               unsigned char        *buf,
 
587
               short                width,
 
588
               short                height,
 
589
               Bool                 sync,
 
590
               RegionPtr            clipBoxes,
 
591
               pointer              data)
 
592
{
 
593
    KdCardInfo          *card = screen->card;
 
594
    NvidiaScreenInfo    *nvidias = (NvidiaScreenInfo *) screen->driver;
 
595
    NvidiaCardInfo      *nvidiac = (NvidiaCardInfo *) card->driver;
 
596
    NvidiaPortPrivPtr   pPortPriv = (NvidiaPortPrivPtr)data;
 
597
    Reg                 *reg = nvidiac->reg;
 
598
    MediaReg            *media = nvidiac->media_reg;
 
599
    INT32               x1, x2, y1, y2;
 
600
    int                 randr = nvidias->vesa.randr;
 
601
    int                 srcPitch, srcPitch2, dstPitch;
 
602
    int                 top, left, npixels, nlines, size;
 
603
    BoxRec              dstBox;
 
604
    int                 dst_width = width, dst_height = height;
 
605
    int                 rot_x1, rot_y1, rot_x2, rot_y2;
 
606
    int                 dst_x1, dst_y1, dst_x2, dst_y2;
 
607
    int                 rot_src_w, rot_src_h, rot_drw_w, rot_drw_h;
 
608
 
 
609
    /* Clip */
 
610
    x1 = src_x;
 
611
    x2 = src_x + src_w;
 
612
    y1 = src_y;
 
613
    y2 = src_y + src_h;
 
614
 
 
615
    dstBox.x1 = drw_x;
 
616
    dstBox.x2 = drw_x + drw_w;
 
617
    dstBox.y1 = drw_y;
 
618
    dstBox.y2 = drw_y + drw_h;
 
619
 
 
620
    NvidiaClipVideo(&dstBox, &x1, &x2, &y1, &y2, 
 
621
                  REGION_EXTENTS(pScreen, clipBoxes), width, height);
 
622
 
 
623
    if((x1 >= x2) || (y1 >= y2))
 
624
        return Success;
 
625
 
 
626
    if (!media)
 
627
        return BadAlloc;
 
628
 
 
629
    if (randr & (RR_Rotate_0|RR_Rotate_180))
 
630
    {
 
631
        dst_width = width;
 
632
        dst_height = height;
 
633
        rot_src_w = src_w;
 
634
        rot_src_h = src_h;
 
635
        rot_drw_w = drw_w;
 
636
        rot_drw_h = drw_h;
 
637
    }
 
638
    else
 
639
    {
 
640
        dst_width = height;
 
641
        dst_height = width;
 
642
        rot_src_w = src_h;
 
643
        rot_src_h = src_w;
 
644
        rot_drw_w = drw_h;
 
645
        rot_drw_h = drw_w;
 
646
    }
 
647
        
 
648
    switch (randr & RR_Rotate_All) {
 
649
    case RR_Rotate_0:
 
650
        dst_x1 = dstBox.x1;
 
651
        dst_y1 = dstBox.y1;
 
652
        dst_x2 = dstBox.x2;
 
653
        dst_y2 = dstBox.y2;
 
654
        rot_x1 = x1;
 
655
        rot_y1 = y1;
 
656
        rot_x2 = x2;
 
657
        rot_y2 = y2;
 
658
        break;
 
659
    case RR_Rotate_90:
 
660
        dst_x1 = dstBox.y1;
 
661
        dst_y1 = screen->height - dstBox.x2;
 
662
        dst_x2 = dstBox.y2;
 
663
        dst_y2 = screen->height - dstBox.x1;
 
664
        
 
665
        rot_x1 = y1;
 
666
        rot_y1 = (src_w << 16) - x2;
 
667
        rot_x2 = y2;
 
668
        rot_y2 = (src_w << 16) - x1;
 
669
        break;
 
670
    case RR_Rotate_180:
 
671
        dst_x1 = screen->width - dstBox.x2;
 
672
        dst_y1 = screen->height - dstBox.y2;
 
673
        dst_x2 = screen->width - dstBox.x1;
 
674
        dst_y2 = screen->height - dstBox.y1;
 
675
        rot_x1 = (src_w << 16) - x2;
 
676
        rot_y1 = (src_h << 16) - y2;
 
677
        rot_x2 = (src_w << 16) - x1;
 
678
        rot_y2 = (src_h << 16) - y1;
 
679
        break;
 
680
    case RR_Rotate_270:
 
681
        dst_x1 = screen->width - dstBox.y2;
 
682
        dst_y1 = dstBox.x1;
 
683
        dst_x2 = screen->width - dstBox.y1;
 
684
        dst_y2 = dstBox.x2;
 
685
        rot_x1 = (src_h << 16) - y2;
 
686
        rot_y1 = x1;
 
687
        rot_x2 = (src_h << 16) - y1;
 
688
        rot_y2 = x2;
 
689
        break;
 
690
    }
 
691
 
 
692
    switch(id) {
 
693
    case FOURCC_YV12:
 
694
    case FOURCC_I420:
 
695
        dstPitch = ((dst_width << 1) + 15) & ~15;
 
696
        srcPitch = (width + 3) & ~3;
 
697
        srcPitch2 = ((width >> 1) + 3) & ~3;
 
698
        size =  dstPitch * (int) dst_height;
 
699
        break;
 
700
    case FOURCC_UYVY:
 
701
    case FOURCC_YUY2:
 
702
    default:
 
703
        dstPitch = ((dst_width << 1) + 15) & ~15;
 
704
        srcPitch = (width << 1);
 
705
        size = dstPitch * (int) dst_height;
 
706
        break;
 
707
    }  
 
708
 
 
709
    pPortPriv->offset = nvidias->off_screen - (CARD8 *) nvidias->vesa.fb;
 
710
    /* fixup pointers */
 
711
    
 
712
    pPortPriv->YBuf0Offset = pPortPriv->offset;
 
713
    pPortPriv->YBuf1Offset = pPortPriv->offset + size;
 
714
 
 
715
#if 0
 
716
    nvidiaWaitIdle (reg);
 
717
 
 
718
    if (pPortPriv->videoOn)
 
719
    {
 
720
        /* wait for buffer to be displayed */
 
721
        while (((media->TRIG_CNTL >> 5) & 1) != pPortPriv->currentBuf)
 
722
            ;
 
723
    }
 
724
#endif
 
725
    /*
 
726
     * Use the other buffer
 
727
     */
 
728
    pPortPriv->currentBuf = 1 - pPortPriv->currentBuf;
 
729
    
 
730
    /* copy data */
 
731
    top = rot_y1 >> 16;
 
732
    left = (rot_x1 >> 16) & ~1;
 
733
    npixels = ((((rot_x2 + 0xffff) >> 16) + 1) & ~1) - left;
 
734
 
 
735
    switch(id) {
 
736
    case FOURCC_YV12:
 
737
    case FOURCC_I420:
 
738
        top &= ~1;
 
739
        nlines = ((((rot_y2 + 0xffff) >> 16) + 1) & ~1) - top;
 
740
        nvidiaCopyPlanarData(screen, buf, randr,
 
741
                             srcPitch, srcPitch2, dstPitch,  
 
742
                             rot_src_w, rot_src_h, height,
 
743
                             top, left, nlines, npixels, id);
 
744
        break;
 
745
    case FOURCC_UYVY:
 
746
    case FOURCC_YUY2:
 
747
    default:
 
748
        nlines = ((rot_y2 + 0xffff) >> 16) - top;
 
749
        nvidiaCopyPackedData(screen, buf, randr,
 
750
                             srcPitch, dstPitch,
 
751
                             rot_src_w, rot_src_h,
 
752
                             top, left, nlines, 
 
753
                             npixels);
 
754
        break;
 
755
    }
 
756
 
 
757
    nvidiaDisplayVideo(screen, id, dstPitch, 
 
758
                       rot_x1, rot_y1, rot_x2, rot_y2, 
 
759
                       dst_x1, dst_y1,
 
760
                       dst_x2, dst_y2,
 
761
                       rot_src_w, rot_src_h, rot_drw_w, rot_drw_h);
 
762
 
 
763
    /* update cliplist */
 
764
    if (!REGION_EQUAL (screen->pScreen, &pPortPriv->clip, clipBoxes))
 
765
    {
 
766
        REGION_COPY (screen->pScreen, &pPortPriv->clip, clipBoxes);
 
767
        nvidiaPaintRegion (screen->pScreen, &pPortPriv->clip, pPortPriv->colorKey);
 
768
    }
 
769
 
 
770
    pPortPriv->videoOn = TRUE;
 
771
 
 
772
    return Success;
 
773
}
 
774
 
 
775
static int
 
776
nvidiaQueryImageAttributes(KdScreenInfo     *screen, 
 
777
                           int              id,
 
778
                           unsigned short   *w,
 
779
                           unsigned short   *h,  
 
780
                           int              *pitches,
 
781
                           int              *offsets)
 
782
{
 
783
    int size, tmp;
 
784
 
 
785
    if(*w > IMAGE_MAX_WIDTH) 
 
786
        *w = IMAGE_MAX_WIDTH;
 
787
    if(*h > IMAGE_MAX_HEIGHT) 
 
788
        *h = IMAGE_MAX_HEIGHT;
 
789
 
 
790
    *w = (*w + 1) & ~1;
 
791
    if(offsets) offsets[0] = 0;
 
792
 
 
793
    switch(id) {
 
794
    case FOURCC_YV12:
 
795
    case FOURCC_I420:
 
796
        *h = (*h + 1) & ~1;
 
797
        size = (*w + 3) & ~3;
 
798
        if(pitches) 
 
799
            pitches[0] = size;
 
800
        size *= *h;
 
801
        if(offsets) 
 
802
            offsets[1] = size;
 
803
        tmp = ((*w >> 1) + 3) & ~3;
 
804
        if(pitches) 
 
805
            pitches[1] = pitches[2] = tmp;
 
806
        tmp *= (*h >> 1);
 
807
        size += tmp;
 
808
        if(offsets) 
 
809
            offsets[2] = size;
 
810
        size += tmp;
 
811
        break;
 
812
    case FOURCC_UYVY:
 
813
    case FOURCC_YUY2:
 
814
    default:
 
815
        size = *w << 1;
 
816
        if(pitches) 
 
817
            pitches[0] = size;
 
818
        size *= *h;
 
819
        break;
 
820
    }
 
821
 
 
822
    return size;
 
823
}
 
824
 
 
825
 
 
826
/* client libraries expect an encoding */
 
827
static KdVideoEncodingRec DummyEncoding[1] =
 
828
{
 
829
 {
 
830
   0,
 
831
   "XV_IMAGE",
 
832
   IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
 
833
   {1, 1}
 
834
 }
 
835
};
 
836
 
 
837
#define NUM_FORMATS 3
 
838
 
 
839
static KdVideoFormatRec Formats[NUM_FORMATS] = 
 
840
{
 
841
  {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
 
842
};
 
843
 
 
844
#define NUM_ATTRIBUTES 3
 
845
 
 
846
static KdAttributeRec Attributes[NUM_ATTRIBUTES] =
 
847
{
 
848
   {XvSettable | XvGettable, 0, ~0, "XV_COLORKEY"},
 
849
   {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
 
850
   {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}
 
851
};
 
852
 
 
853
#define NUM_IMAGES 4
 
854
 
 
855
static KdImageRec Images[NUM_IMAGES] =
 
856
{
 
857
        XVIMAGE_YUY2,
 
858
        XVIMAGE_YV12,
 
859
        XVIMAGE_I420,
 
860
        XVIMAGE_UYVY
 
861
};
 
862
 
 
863
static void nvidiaResetVideo(KdScreenInfo *screen) 
 
864
{
 
865
    ScreenPtr           pScreen = screen->pScreen;
 
866
    KdScreenPriv(pScreen);
 
867
    KdCardInfo          *card = pScreenPriv->card;
 
868
    NvidiaScreenInfo    *nvidias = (NvidiaScreenInfo *) screen->driver;
 
869
    NvidiaCardInfo      *nvidiac = (NvidiaCardInfo *) card->driver;
 
870
    NvidiaPortPrivPtr   pPortPriv = nvidias->pAdaptor->pPortPrivates[0].ptr;
 
871
    MediaReg            *media = nvidiac->media_reg;
 
872
 
 
873
    /*
 
874
     * Default to maximum image size in YV12
 
875
     */
 
876
    
 
877
}
 
878
 
 
879
static int
 
880
nvidiaReputImage (KdScreenInfo      *screen,
 
881
                  short             drw_x,
 
882
                  short             drw_y,
 
883
                  RegionPtr         clipBoxes,
 
884
                  pointer           data)
 
885
{
 
886
    ScreenPtr           pScreen = screen->pScreen;
 
887
    NvidiaPortPrivPtr   pPortPriv = (NvidiaPortPrivPtr)data;
 
888
    BoxPtr              pOldExtents = REGION_EXTENTS (pScreen, &pPortPriv->clip);
 
889
    BoxPtr              pNewExtents = REGION_EXTENTS (pScreen, clipBoxes);
 
890
 
 
891
    if (pOldExtents->x1 == pNewExtents->x1 &&
 
892
        pOldExtents->x2 == pNewExtents->x2 &&
 
893
        pOldExtents->y1 == pNewExtents->y1 &&
 
894
        pOldExtents->y2 == pNewExtents->y2)
 
895
    {
 
896
        /* update cliplist */
 
897
        if (!REGION_EQUAL (screen->pScreen, &pPortPriv->clip, clipBoxes))
 
898
        {
 
899
            REGION_COPY (screen->pScreen, &pPortPriv->clip, clipBoxes);
 
900
            nvidiaPaintRegion (screen->pScreen, &pPortPriv->clip, pPortPriv->colorKey);
 
901
        }
 
902
        return Success;
 
903
    }
 
904
    return BadMatch;
 
905
}
 
906
 
 
907
static KdVideoAdaptorPtr 
 
908
nvidiaSetupImageVideo(ScreenPtr pScreen)
 
909
{
 
910
    KdScreenPriv(pScreen);
 
911
    nvidiaCardInfo(pScreenPriv);
 
912
    nvidiaScreenInfo(pScreenPriv);
 
913
    KdScreenInfo        *screen = pScreenPriv->screen;
 
914
    KdCardInfo          *card = pScreenPriv->card;
 
915
    KdVideoAdaptorPtr   adapt;
 
916
    NvidiaPortPrivPtr   pPortPriv;
 
917
 
 
918
    if(!(adapt = xcalloc(1, sizeof(KdVideoAdaptorRec) +
 
919
                            sizeof(NvidiaPortPrivRec) +
 
920
                            sizeof(DevUnion))))
 
921
        return NULL;
 
922
 
 
923
    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
 
924
    adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
 
925
    adapt->name = "Nvidia Video Overlay";
 
926
    adapt->nEncodings = 1;
 
927
    adapt->pEncodings = DummyEncoding;
 
928
    adapt->nFormats = NUM_FORMATS;
 
929
    adapt->pFormats = Formats;
 
930
    adapt->nPorts = 1;
 
931
    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
 
932
 
 
933
    pPortPriv = (NvidiaPortPrivPtr)(&adapt->pPortPrivates[1]);
 
934
 
 
935
    adapt->pPortPrivates[0].ptr = (pointer)(pPortPriv);
 
936
    adapt->pAttributes = Attributes;
 
937
    adapt->nImages = NUM_IMAGES;
 
938
    adapt->nAttributes = NUM_ATTRIBUTES;
 
939
    adapt->pImages = Images;
 
940
    adapt->PutVideo = NULL;
 
941
    adapt->PutStill = NULL;
 
942
    adapt->GetVideo = NULL;
 
943
    adapt->GetStill = NULL;
 
944
    adapt->StopVideo = nvidiaStopVideo;
 
945
    adapt->SetPortAttribute = nvidiaSetPortAttribute;
 
946
    adapt->GetPortAttribute = nvidiaGetPortAttribute;
 
947
    adapt->QueryBestSize = nvidiaQueryBestSize;
 
948
    adapt->PutImage = nvidiaPutImage;
 
949
    adapt->ReputImage = nvidiaReputImage;
 
950
    adapt->QueryImageAttributes = nvidiaQueryImageAttributes;
 
951
 
 
952
    pPortPriv->colorKey = nvidias->colorKey;
 
953
    pPortPriv->videoOn = FALSE;
 
954
    pPortPriv->brightness = 0;
 
955
    pPortPriv->saturation = 0;
 
956
    pPortPriv->currentBuf = 0;
 
957
 
 
958
    /* gotta uninit this someplace */
 
959
    REGION_INIT(pScreen, &pPortPriv->clip, NullBox, 0); 
 
960
 
 
961
    nvidias->pAdaptor = adapt;
 
962
 
 
963
    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
 
964
    xvSaturation = MAKE_ATOM("XV_SATURATION");
 
965
    xvColorKey   = MAKE_ATOM("XV_COLORKEY");
 
966
 
 
967
    nvidiaResetVideo(screen);
 
968
 
 
969
    return adapt;
 
970
}
 
971
 
 
972
Bool nvidiaInitVideo(ScreenPtr pScreen)
 
973
{
 
974
    KdScreenPriv(pScreen);
 
975
    KdScreenInfo        *screen = pScreenPriv->screen;
 
976
    KdVideoAdaptorPtr   *adaptors, *newAdaptors = NULL;
 
977
    KdVideoAdaptorPtr   newAdaptor = NULL;
 
978
    int                 num_adaptors;
 
979
    KdCardInfo          *card = pScreenPriv->card;
 
980
    NvidiaScreenInfo    *nvidias = (NvidiaScreenInfo *) screen->driver;
 
981
    NvidiaCardInfo      *nvidiac = (NvidiaCardInfo *) card->driver;
 
982
    
 
983
    if (!nvidiac->media_reg)
 
984
        return FALSE;
 
985
 
 
986
    newAdaptor = nvidiaSetupImageVideo(pScreen);
 
987
 
 
988
    num_adaptors = KdXVListGenericAdaptors(screen, &adaptors);
 
989
 
 
990
    if(newAdaptor) 
 
991
    {
 
992
        if(!num_adaptors) 
 
993
        {
 
994
            num_adaptors = 1;
 
995
            adaptors = &newAdaptor;
 
996
        }
 
997
        else 
 
998
        {
 
999
            newAdaptors = xalloc((num_adaptors + 1) * 
 
1000
                                 sizeof(KdVideoAdaptorPtr*));
 
1001
            if(newAdaptors) 
 
1002
            {
 
1003
                memcpy(newAdaptors, adaptors, 
 
1004
                       num_adaptors * sizeof(KdVideoAdaptorPtr));
 
1005
                newAdaptors[num_adaptors] = newAdaptor;
 
1006
                adaptors = newAdaptors;
 
1007
                num_adaptors++;
 
1008
            }
 
1009
        }
 
1010
    }
 
1011
 
 
1012
    if(num_adaptors)
 
1013
        KdXVScreenInit(pScreen, adaptors, num_adaptors);
 
1014
 
 
1015
    if(newAdaptors)
 
1016
        xfree(newAdaptors);
 
1017
    return TRUE;
 
1018
}