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

« back to all changes in this revision

Viewing changes to hw/kdrive/ati/ati_video.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
 * Copyright ļæ½ 2004 Keith Packard
 
3
 * Copyright ļæ½ 2005 Eric Anholt
 
4
 *
 
5
 * Permission to use, copy, modify, distribute, and sell this software and its
 
6
 * documentation for any purpose is hereby granted without fee, provided that
 
7
 * the above copyright notice appear in all copies and that both that
 
8
 * copyright notice and this permission notice appear in supporting
 
9
 * documentation, and that the name of Eric Anholt not be used in
 
10
 * advertising or publicity pertaining to distribution of the software without
 
11
 * specific, written prior permission.  Eric Anholt makes no
 
12
 * representations about the suitability of this software for any purpose.  It
 
13
 * is provided "as is" without express or implied warranty.
 
14
 *
 
15
 * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
16
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
17
 * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
18
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
19
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
20
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
21
 * PERFORMANCE OF THIS SOFTWARE.
 
22
 *
 
23
 * Based on mach64video.c by Keith Packard.
 
24
 */
 
25
/* $RCSId$ */
 
26
 
 
27
#ifdef HAVE_CONFIG_H
 
28
#include <kdrive-config.h>
 
29
#endif
 
30
#include "ati.h"
 
31
#include "ati_dma.h"
 
32
#include "ati_draw.h"
 
33
#include "ati_reg.h"
 
34
#include "kaa.h"
 
35
 
 
36
#include <X11/extensions/Xv.h>
 
37
#include "fourcc.h"
 
38
 
 
39
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
 
40
 
 
41
static Atom xvBrightness, xvSaturation;
 
42
 
 
43
extern CARD8 ATIBltRop[16];
 
44
 
 
45
#define IMAGE_MAX_WIDTH         2048
 
46
#define IMAGE_MAX_HEIGHT        2048
 
47
 
 
48
static void
 
49
ATIStopVideo(KdScreenInfo *screen, pointer data, Bool exit)
 
50
{
 
51
        ScreenPtr pScreen = screen->pScreen;
 
52
        ATIPortPrivPtr pPortPriv = (ATIPortPrivPtr)data;
 
53
 
 
54
        REGION_EMPTY(screen->pScreen, &pPortPriv->clip);   
 
55
 
 
56
        if (pPortPriv->off_screen) {
 
57
                KdOffscreenFree (pScreen, pPortPriv->off_screen);
 
58
                pPortPriv->off_screen = 0;
 
59
        }
 
60
}
 
61
 
 
62
static int
 
63
ATISetPortAttribute(KdScreenInfo *screen, Atom attribute, int value,
 
64
    pointer data)
 
65
{
 
66
        return BadMatch;
 
67
}
 
68
 
 
69
static int
 
70
ATIGetPortAttribute(KdScreenInfo *screen, Atom attribute, int *value,
 
71
    pointer data)
 
72
{
 
73
        return BadMatch;
 
74
}
 
75
 
 
76
static void
 
77
ATIQueryBestSize(KdScreenInfo *screen, Bool motion, short vid_w, short vid_h,
 
78
    short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h,
 
79
    pointer data)
 
80
{
 
81
        *p_w = drw_w;
 
82
        *p_h = drw_h;
 
83
}
 
84
 
 
85
/* ATIClipVideo -  
 
86
 
 
87
   Takes the dst box in standard X BoxRec form (top and left
 
88
   edges inclusive, bottom and right exclusive).  The new dst
 
89
   box is returned.  The source boundaries are given (x1, y1 
 
90
   inclusive, x2, y2 exclusive) and returned are the new source 
 
91
   boundaries in 16.16 fixed point. 
 
92
*/
 
93
 
 
94
static void
 
95
ATIClipVideo(BoxPtr dst, INT32 *x1, INT32 *x2, INT32 *y1, INT32 *y2,
 
96
    BoxPtr extents, INT32 width, INT32 height)
 
97
{
 
98
        INT32 vscale, hscale, delta;
 
99
        int diff;
 
100
 
 
101
        hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
 
102
        vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
 
103
 
 
104
        *x1 <<= 16; *x2 <<= 16;
 
105
        *y1 <<= 16; *y2 <<= 16;
 
106
 
 
107
        diff = extents->x1 - dst->x1;
 
108
        if (diff > 0) {
 
109
                dst->x1 = extents->x1;
 
110
                *x1 += diff * hscale;
 
111
        }
 
112
        diff = dst->x2 - extents->x2;
 
113
        if (diff > 0) {
 
114
                dst->x2 = extents->x2;
 
115
                *x2 -= diff * hscale;
 
116
        }
 
117
        diff = extents->y1 - dst->y1;
 
118
        if (diff > 0) {
 
119
                dst->y1 = extents->y1;
 
120
                *y1 += diff * vscale;
 
121
        }
 
122
        diff = dst->y2 - extents->y2;
 
123
        if (diff > 0) {
 
124
                dst->y2 = extents->y2;
 
125
                *y2 -= diff * vscale;
 
126
        }
 
127
 
 
128
        if (*x1 < 0) {
 
129
                diff =  (- *x1 + hscale - 1)/ hscale;
 
130
                dst->x1 += diff;
 
131
                *x1 += diff * hscale;
 
132
        }
 
133
        delta = *x2 - (width << 16);
 
134
        if (delta > 0) {
 
135
                diff = (delta + hscale - 1)/ hscale;
 
136
                dst->x2 -= diff;
 
137
                *x2 -= diff * hscale;
 
138
        }
 
139
        if (*y1 < 0) {
 
140
                diff =  (- *y1 + vscale - 1)/ vscale;
 
141
                dst->y1 += diff;
 
142
                *y1 += diff * vscale;
 
143
        }
 
144
        delta = *y2 - (height << 16);
 
145
        if (delta > 0) {
 
146
                diff = (delta + vscale - 1)/ vscale;
 
147
                dst->y2 -= diff;
 
148
                *y2 -= diff * vscale;
 
149
        }
 
150
}
 
151
 
 
152
static void
 
153
R128DisplayVideo(KdScreenInfo *screen, ATIPortPrivPtr pPortPriv)
 
154
{
 
155
        ScreenPtr pScreen = screen->pScreen;
 
156
        KdScreenPriv(pScreen);
 
157
        ATIScreenInfo(pScreenPriv);
 
158
        CARD32 dstDatatype, srcDatatype;
 
159
        CARD32 dst_offset, dst_pitch;
 
160
        int dstxoff, dstyoff;
 
161
        PixmapPtr pPixmap = pPortPriv->pPixmap;
 
162
        int bpp = pPixmap->drawable.bitsPerPixel;
 
163
        RING_LOCALS;
 
164
 
 
165
        BoxPtr pBox = REGION_RECTS(&pPortPriv->clip);
 
166
        int nBox = REGION_NUM_RECTS(&pPortPriv->clip);
 
167
 
 
168
        if (pPortPriv->id == FOURCC_UYVY)
 
169
                srcDatatype = R128_DATATYPE_YVYU_422;
 
170
        else
 
171
                srcDatatype = R128_DATATYPE_VYUY_422;
 
172
 
 
173
        switch (bpp)
 
174
        {
 
175
        case 16:
 
176
                if (pPixmap->drawable.depth == 15)
 
177
                        dstDatatype = R128_DATATYPE_ARGB1555;
 
178
                else
 
179
                        dstDatatype = R128_DATATYPE_RGB565;
 
180
                break;
 
181
        case 32:
 
182
                dstDatatype = R128_DATATYPE_ARGB8888;
 
183
                break;
 
184
        default:
 
185
                return;
 
186
        }
 
187
 
 
188
        dst_offset = ((CARD8 *)pPixmap->devPrivate.ptr -
 
189
            pScreenPriv->screen->memory_base);
 
190
        dst_pitch = pPixmap->devKind;
 
191
#ifdef COMPOSITE
 
192
        dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
 
193
        dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
 
194
#else
 
195
        dstxoff = 0;
 
196
        dstyoff = 0;
 
197
#endif
 
198
 
 
199
        BEGIN_DMA(18);
 
200
        OUT_REG(ATI_REG_DST_PITCH_OFFSET,
 
201
            ((dst_pitch / bpp) << 21) | (dst_offset >> 5));
 
202
        OUT_REG(ATI_REG_DP_GUI_MASTER_CNTL,
 
203
            ATI_GMC_DST_PITCH_OFFSET_CNTL |
 
204
            ATI_GMC_BRUSH_NONE |
 
205
            (dstDatatype << 8) |
 
206
            ATI_GMC_SRC_DATATYPE_COLOR |
 
207
            (ATIBltRop[GXcopy] << 16) |
 
208
            R128_GMC_3D_FCN_EN |
 
209
            ATI_GMC_CLR_CMP_CNTL_DIS |
 
210
            R128_GMC_AUX_CLIP_DIS);
 
211
        OUT_REG(ATI_REG_DP_CNTL, 
 
212
            ATI_DST_X_LEFT_TO_RIGHT | ATI_DST_Y_TOP_TO_BOTTOM );
 
213
        OUT_REG(R128_REG_SCALE_3D_CNTL,
 
214
            R128_SCALE_3D_SCALE |
 
215
            R128_SBLEND_ONE |
 
216
            R128_DBLEND_ZERO);
 
217
        OUT_REG(R128_REG_TEX_CNTL_C, R128_TEX_CACHE_FLUSH);
 
218
        OUT_REG(R128_REG_SCALE_3D_DATATYPE, srcDatatype);
 
219
 
 
220
        OUT_RING(DMA_PACKET0(R128_REG_SCALE_PITCH, 5));
 
221
        OUT_RING_REG(R128_REG_SCALE_PITCH, pPortPriv->src_pitch / 16);
 
222
        OUT_RING_REG(R128_REG_SCALE_X_INC,
 
223
            (pPortPriv->src_w << 16) / pPortPriv->dst_w);
 
224
        OUT_RING_REG(R128_REG_SCALE_Y_INC,
 
225
            (pPortPriv->src_h << 16) / pPortPriv->dst_h);
 
226
        OUT_RING_REG(R128_REG_SCALE_HACC, 0x0);
 
227
        OUT_RING_REG(R128_REG_SCALE_VACC, 0x0);
 
228
 
 
229
        END_DMA();
 
230
 
 
231
        while (nBox--) {
 
232
                int srcX, srcY, dstX, dstY, srcw, srch, dstw, dsth;
 
233
 
 
234
                dstX = pBox->x1 + dstxoff;
 
235
                dstY = pBox->y1 + dstyoff;
 
236
                dstw = pBox->x2 - pBox->x1;
 
237
                dsth = pBox->y2 - pBox->y1;
 
238
                srcX = (pBox->x1 - pPortPriv->dst_x1) *
 
239
                    pPortPriv->src_w / pPortPriv->dst_w;
 
240
                srcY = (pBox->y1 - pPortPriv->dst_y1) *
 
241
                    pPortPriv->src_h / pPortPriv->dst_h;
 
242
                srcw = pPortPriv->src_w - srcX;
 
243
                srch = pPortPriv->src_h - srcY;
 
244
 
 
245
                BEGIN_DMA(6);
 
246
                OUT_RING(DMA_PACKET0(R128_REG_SCALE_SRC_HEIGHT_WIDTH, 2));
 
247
                OUT_RING_REG(R128_REG_SCALE_SRC_HEIGHT_WIDTH,
 
248
                    (srch << 16) | srcw);
 
249
                OUT_RING_REG(R128_REG_SCALE_OFFSET_0, pPortPriv->src_offset +
 
250
                    srcY * pPortPriv->src_pitch + srcX * 2);
 
251
 
 
252
                OUT_RING(DMA_PACKET0(R128_REG_SCALE_DST_X_Y, 2));
 
253
                OUT_RING_REG(R128_REG_SCALE_DST_X_Y, (dstX << 16) | dstY);
 
254
                OUT_RING_REG(R128_REG_SCALE_DST_HEIGHT_WIDTH,
 
255
                    (dsth << 16) | dstw);
 
256
                END_DMA();
 
257
                pBox++;
 
258
        }
 
259
#ifdef DAMAGEEXT
 
260
        /* XXX: Shouldn't this be in kxv.c instead? */
 
261
        DamageDamageRegion(pPortPriv->pDraw, &pPortPriv->clip);
 
262
#endif
 
263
        kaaMarkSync(pScreen);
 
264
}
 
265
 
 
266
union intfloat {
 
267
        float f;
 
268
        CARD32 i;
 
269
};
 
270
 
 
271
struct blend_vertex {
 
272
        union intfloat x, y;
 
273
        union intfloat s0, t0;
 
274
};
 
275
 
 
276
#define VTX_DWORD_COUNT 4
 
277
 
 
278
#define VTX_OUT(vtx)            \
 
279
do {                            \
 
280
        OUT_RING(vtx.x.i);      \
 
281
        OUT_RING(vtx.y.i);      \
 
282
        OUT_RING(vtx.s0.i);     \
 
283
        OUT_RING(vtx.t0.i);     \
 
284
} while (0)
 
285
 
 
286
static void
 
287
RadeonDisplayVideo(KdScreenInfo *screen, ATIPortPrivPtr pPortPriv)
 
288
{
 
289
        ScreenPtr pScreen = screen->pScreen;
 
290
        KdScreenPriv(pScreen);
 
291
        ATICardInfo(pScreenPriv);
 
292
        ATIScreenInfo(pScreenPriv);
 
293
        struct blend_vertex vtx[4];
 
294
        PixmapPtr pPixmap = pPortPriv->pPixmap;
 
295
        CARD32 txformat;
 
296
        CARD32 dst_offset, dst_pitch, dst_format;
 
297
        int dstxoff, dstyoff, pixel_shift;
 
298
        RING_LOCALS;
 
299
 
 
300
        BoxPtr pBox = REGION_RECTS(&pPortPriv->clip);
 
301
        int nBox = REGION_NUM_RECTS(&pPortPriv->clip);
 
302
 
 
303
        switch (pPixmap->drawable.bitsPerPixel) {
 
304
        case 16:
 
305
                if (pPixmap->drawable.depth == 15)
 
306
                        dst_format = RADEON_COLOR_FORMAT_ARGB1555;
 
307
                else
 
308
                        dst_format = RADEON_COLOR_FORMAT_RGB565;
 
309
                pixel_shift = 1;
 
310
                break;
 
311
        case 32:
 
312
                dst_format = RADEON_COLOR_FORMAT_ARGB8888;
 
313
                pixel_shift = 2;
 
314
                break;
 
315
        default:
 
316
                return;
 
317
        }
 
318
 
 
319
        dst_offset = ((CARD8 *)pPixmap->devPrivate.ptr -
 
320
            pScreenPriv->screen->memory_base);
 
321
        dst_pitch = pPixmap->devKind;
 
322
 
 
323
#ifdef COMPOSITE
 
324
        dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
 
325
        dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
 
326
#else
 
327
        dstxoff = 0;
 
328
        dstyoff = 0;
 
329
#endif
 
330
 
 
331
        /* Same for R100/R200 */
 
332
        if (pPortPriv->id == FOURCC_UYVY)
 
333
                txformat = RADEON_TXFORMAT_YVYU422;
 
334
        else
 
335
                txformat = RADEON_TXFORMAT_VYUY422;
 
336
 
 
337
        txformat |= RADEON_TXFORMAT_NON_POWER2;
 
338
 
 
339
        RadeonSwitchTo3D(atis);
 
340
 
 
341
        BEGIN_DMA(8);
 
342
 
 
343
        OUT_RING(DMA_PACKET0(RADEON_REG_PP_CNTL, 3));
 
344
        OUT_RING_REG(RADEON_REG_PP_CNTL,
 
345
            RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE);
 
346
        OUT_RING_REG(RADEON_REG_RB3D_CNTL,
 
347
            dst_format | RADEON_ALPHA_BLEND_ENABLE);
 
348
        OUT_RING_REG(RADEON_REG_RB3D_COLOROFFSET, dst_offset);
 
349
 
 
350
        OUT_REG(RADEON_REG_RB3D_COLORPITCH, dst_pitch >> pixel_shift);
 
351
 
 
352
        OUT_REG(RADEON_REG_RB3D_BLENDCNTL,
 
353
            RADEON_SBLEND_GL_ONE | RADEON_DBLEND_GL_ZERO);
 
354
 
 
355
        END_DMA();
 
356
 
 
357
        if (atic->is_r200) {
 
358
                BEGIN_DMA(17);
 
359
 
 
360
                OUT_REG(R200_REG_SE_VTX_FMT_0, R200_VTX_XY);
 
361
                OUT_REG(R200_REG_SE_VTX_FMT_1,
 
362
                    (2 << R200_VTX_TEX0_COMP_CNT_SHIFT));
 
363
 
 
364
                OUT_RING(DMA_PACKET0(R200_REG_PP_TXFILTER_0, 5));
 
365
                OUT_RING_REG(R200_REG_PP_TXFILTER_0,
 
366
                    R200_MAG_FILTER_LINEAR |
 
367
                    R200_MIN_FILTER_LINEAR |
 
368
                    R200_YUV_TO_RGB);
 
369
                OUT_RING_REG(R200_REG_PP_TXFORMAT_0, txformat);
 
370
                OUT_RING_REG(R200_REG_PP_TXFORMAT_X_0, 0);
 
371
                OUT_RING_REG(R200_REG_PP_TXSIZE_0,
 
372
                    (pPixmap->drawable.width - 1) |
 
373
                    ((pPixmap->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
 
374
                OUT_RING_REG(R200_REG_PP_TXPITCH_0, pPortPriv->src_pitch - 32);
 
375
 
 
376
                OUT_REG(R200_PP_TXOFFSET_0, pPortPriv->src_offset);
 
377
 
 
378
                OUT_RING(DMA_PACKET0(R200_REG_PP_TXCBLEND_0, 4));
 
379
                OUT_RING_REG(R200_REG_PP_TXCBLEND_0,
 
380
                    R200_TXC_ARG_A_ZERO |
 
381
                    R200_TXC_ARG_B_ZERO |
 
382
                    R200_TXC_ARG_C_R0_COLOR |
 
383
                    R200_TXC_OP_MADD);
 
384
                OUT_RING_REG(R200_REG_PP_TXCBLEND2_0,
 
385
                    R200_TXC_CLAMP_0_1 | R200_TXC_OUTPUT_REG_R0);
 
386
                OUT_RING_REG(R200_REG_PP_TXABLEND_0,
 
387
                    R200_TXA_ARG_A_ZERO |
 
388
                    R200_TXA_ARG_B_ZERO |
 
389
                    R200_TXA_ARG_C_R0_ALPHA |
 
390
                    R200_TXA_OP_MADD);
 
391
                OUT_RING_REG(R200_REG_PP_TXABLEND2_0,
 
392
                    R200_TXA_CLAMP_0_1 | R200_TXA_OUTPUT_REG_R0);
 
393
 
 
394
                END_DMA();
 
395
        } else {
 
396
//              BEGIN_DMA(11);
 
397
                BEGIN_DMA(9);
 
398
 
 
399
                OUT_RING(DMA_PACKET0(RADEON_REG_PP_TXFILTER_0, 5));
 
400
                OUT_RING_REG(RADEON_REG_PP_TXFILTER_0, RADEON_MAG_FILTER_LINEAR |
 
401
                    RADEON_MIN_FILTER_LINEAR |
 
402
                    RADEON_YUV_TO_RGB);
 
403
                OUT_RING_REG(RADEON_REG_PP_TXFORMAT_0, txformat);
 
404
                OUT_RING_REG(RADEON_REG_PP_TXOFFSET_0, pPortPriv->src_offset);
 
405
                OUT_RING_REG(RADEON_REG_PP_TXCBLEND_0,
 
406
                    RADEON_COLOR_ARG_A_ZERO |
 
407
                    RADEON_COLOR_ARG_B_ZERO |
 
408
                    RADEON_COLOR_ARG_C_T0_COLOR |
 
409
                    RADEON_BLEND_CTL_ADD |
 
410
                    RADEON_CLAMP_TX);
 
411
                OUT_RING_REG(RADEON_REG_PP_TXABLEND_0,
 
412
                    RADEON_ALPHA_ARG_A_ZERO |
 
413
                    RADEON_ALPHA_ARG_B_ZERO |
 
414
                    RADEON_ALPHA_ARG_C_T0_ALPHA |
 
415
                    RADEON_BLEND_CTL_ADD |
 
416
                    RADEON_CLAMP_TX);
 
417
 
 
418
                OUT_RING(DMA_PACKET0(RADEON_REG_PP_TEX_SIZE_0, 2));
 
419
                OUT_RING_REG(RADEON_REG_PP_TEX_SIZE_0,
 
420
                    (pPixmap->drawable.width - 1) |
 
421
                    ((pPixmap->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
 
422
                OUT_RING_REG(RADEON_REG_PP_TEX_PITCH_0,
 
423
                    pPortPriv->src_pitch - 32);
 
424
 
 
425
//              OUT_RING_REG(ATI_REG_WAIT_UNTIL, ATI_WAIT_CRTC_VLINE);
 
426
 
 
427
                END_DMA();
 
428
        }
 
429
 
 
430
        while (nBox--) {
 
431
                float srcX, srcY, dstX, dstY, srcw, srch, dstw, dsth;
 
432
 
 
433
                dstX = pBox->x1 + dstxoff;
 
434
                dstY = pBox->y1 + dstyoff;
 
435
                dstw = pBox->x2 - pBox->x1;
 
436
                dsth = pBox->y2 - pBox->y1;
 
437
                srcX = (pBox->x1 - pPortPriv->dst_x1) *
 
438
                    pPortPriv->src_w / pPortPriv->dst_w;
 
439
                srcY = (pBox->y1 - pPortPriv->dst_y1) *
 
440
                    pPortPriv->src_h / pPortPriv->dst_h;
 
441
                srcw = pPortPriv->src_w * (dstw / pPortPriv->dst_w);
 
442
                srch = pPortPriv->src_h * (dsth / pPortPriv->dst_h);
 
443
        
 
444
                vtx[0].x.f = dstX;
 
445
                vtx[0].y.f = dstY;
 
446
                vtx[0].s0.f = srcX;
 
447
                vtx[0].t0.f = srcY;
 
448
 
 
449
                vtx[1].x.f = dstX;
 
450
                vtx[1].y.f = dstY + dsth;
 
451
                vtx[1].s0.f = srcX;
 
452
                vtx[1].t0.f = srcY + srch;
 
453
 
 
454
                vtx[2].x.f = dstX + dstw;
 
455
                vtx[2].y.f = dstY + dsth;
 
456
                vtx[2].s0.f = srcX + srcw;
 
457
                vtx[2].t0.f = srcY + srch;
 
458
 
 
459
                vtx[3].x.f = dstX + dstw;
 
460
                vtx[3].y.f = dstY;
 
461
                vtx[3].s0.f = srcX + srcw;
 
462
                vtx[3].t0.f = srcY;
 
463
 
 
464
                if (atic->is_r100) {
 
465
                        BEGIN_DMA(4 * VTX_DWORD_COUNT + 3);
 
466
                        OUT_RING(DMA_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
 
467
                            4 * VTX_DWORD_COUNT + 2));
 
468
                        OUT_RING(RADEON_CP_VC_FRMT_XY |
 
469
                            RADEON_CP_VC_FRMT_ST0);
 
470
                        OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
 
471
                            RADEON_CP_VC_CNTL_PRIM_WALK_RING |
 
472
                            RADEON_CP_VC_CNTL_MAOS_ENABLE |
 
473
                            RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
 
474
                            (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
 
475
                } else {
 
476
                        BEGIN_DMA(4 * VTX_DWORD_COUNT + 2);
 
477
                        OUT_RING(DMA_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
 
478
                            4 * VTX_DWORD_COUNT + 1));
 
479
                        OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
 
480
                            RADEON_CP_VC_CNTL_PRIM_WALK_RING |
 
481
                            (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
 
482
                }
 
483
 
 
484
                VTX_OUT(vtx[0]);
 
485
                VTX_OUT(vtx[1]);
 
486
                VTX_OUT(vtx[2]);
 
487
                VTX_OUT(vtx[3]);
 
488
 
 
489
                END_DMA();
 
490
 
 
491
                pBox++;
 
492
        }
 
493
#ifdef DAMAGEEXT
 
494
        /* XXX: Shouldn't this be in kxv.c instead? */
 
495
        DamageDamageRegion(pPortPriv->pDraw, &pPortPriv->clip);
 
496
#endif
 
497
        kaaMarkSync(pScreen);
 
498
}
 
499
 
 
500
static void
 
501
ATIVideoSave(ScreenPtr pScreen, KdOffscreenArea *area)
 
502
{
 
503
        KdScreenPriv(pScreen);
 
504
        ATIScreenInfo(pScreenPriv);
 
505
        ATIPortPrivPtr pPortPriv = atis->pAdaptor->pPortPrivates[0].ptr;
 
506
 
 
507
        if (pPortPriv->off_screen == area)
 
508
                pPortPriv->off_screen = 0;
 
509
}
 
510
 
 
511
static int
 
512
ATIPutImage(KdScreenInfo *screen, DrawablePtr pDraw,
 
513
               short src_x, short src_y,
 
514
               short drw_x, short drw_y,
 
515
               short src_w, short src_h,
 
516
               short drw_w, short drw_h,
 
517
               int id,
 
518
               unsigned char *buf,
 
519
               short width,
 
520
               short height,
 
521
               Bool sync,
 
522
               RegionPtr clipBoxes,
 
523
               pointer data)
 
524
{
 
525
        ScreenPtr pScreen = screen->pScreen;
 
526
        KdScreenPriv(pScreen);
 
527
        ATICardInfo(pScreenPriv);
 
528
        ATIScreenInfo(pScreenPriv);
 
529
        ATIPortPrivPtr pPortPriv = (ATIPortPrivPtr)data;
 
530
        char *mmio = atic->reg_base;
 
531
        INT32 x1, x2, y1, y2;
 
532
        int randr = RR_Rotate_0 /* XXX */;
 
533
        int srcPitch, srcPitch2, dstPitch;
 
534
        int top, left, npixels, nlines, size;
 
535
        BoxRec dstBox;
 
536
        int dst_width = width, dst_height = height;
 
537
        int rot_x1, rot_y1, rot_x2, rot_y2;
 
538
        int dst_x1, dst_y1, dst_x2, dst_y2;
 
539
        int rot_src_w, rot_src_h, rot_drw_w, rot_drw_h;
 
540
 
 
541
        /* Clip */
 
542
        x1 = src_x;
 
543
        x2 = src_x + src_w;
 
544
        y1 = src_y;
 
545
        y2 = src_y + src_h;
 
546
 
 
547
        dstBox.x1 = drw_x;
 
548
        dstBox.x2 = drw_x + drw_w;
 
549
        dstBox.y1 = drw_y;
 
550
        dstBox.y2 = drw_y + drw_h;
 
551
 
 
552
        ATIClipVideo(&dstBox, &x1, &x2, &y1, &y2,
 
553
            REGION_EXTENTS(pScreen, clipBoxes), width, height);
 
554
 
 
555
        src_w = (x2 - x1) >> 16;
 
556
        src_h = (y2 - y1) >> 16;
 
557
        drw_w = dstBox.x2 - dstBox.x1;
 
558
        drw_h = dstBox.y2 - dstBox.y1;
 
559
 
 
560
        if ((x1 >= x2) || (y1 >= y2))
 
561
                return Success;
 
562
 
 
563
        if (mmio == NULL)
 
564
                return BadAlloc;
 
565
 
 
566
        if (randr & (RR_Rotate_0|RR_Rotate_180)) {
 
567
                dst_width = width;
 
568
                dst_height = height;
 
569
                rot_src_w = src_w;
 
570
                rot_src_h = src_h;
 
571
                rot_drw_w = drw_w;
 
572
                rot_drw_h = drw_h;
 
573
        } else {
 
574
                dst_width = height;
 
575
                dst_height = width;
 
576
                rot_src_w = src_h;
 
577
                rot_src_h = src_w;
 
578
                rot_drw_w = drw_h;
 
579
                rot_drw_h = drw_w;
 
580
        }
 
581
 
 
582
        switch (randr & RR_Rotate_All) {
 
583
        case RR_Rotate_0:
 
584
        default:
 
585
                dst_x1 = dstBox.x1;
 
586
                dst_y1 = dstBox.y1;
 
587
                dst_x2 = dstBox.x2;
 
588
                dst_y2 = dstBox.y2;
 
589
                rot_x1 = x1;
 
590
                rot_y1 = y1;
 
591
                rot_x2 = x2;
 
592
                rot_y2 = y2;
 
593
                break;
 
594
        case RR_Rotate_90:
 
595
                dst_x1 = dstBox.y1;
 
596
                dst_y1 = screen->height - dstBox.x2;
 
597
                dst_x2 = dstBox.y2;
 
598
                dst_y2 = screen->height - dstBox.x1;
 
599
                rot_x1 = y1;
 
600
                rot_y1 = (src_w << 16) - x2;
 
601
                rot_x2 = y2;
 
602
                rot_y2 = (src_w << 16) - x1;
 
603
                break;
 
604
        case RR_Rotate_180:
 
605
                dst_x1 = screen->width - dstBox.x2;
 
606
                dst_y1 = screen->height - dstBox.y2;
 
607
                dst_x2 = screen->width - dstBox.x1;
 
608
                dst_y2 = screen->height - dstBox.y1;
 
609
                rot_x1 = (src_w << 16) - x2;
 
610
                rot_y1 = (src_h << 16) - y2;
 
611
                rot_x2 = (src_w << 16) - x1;
 
612
                rot_y2 = (src_h << 16) - y1;
 
613
                break;
 
614
        case RR_Rotate_270:
 
615
                dst_x1 = screen->width - dstBox.y2;
 
616
                dst_y1 = dstBox.x1;
 
617
                dst_x2 = screen->width - dstBox.y1;
 
618
                dst_y2 = dstBox.x2;
 
619
                rot_x1 = (src_h << 16) - y2;
 
620
                rot_y1 = x1;
 
621
                rot_x2 = (src_h << 16) - y1;
 
622
                rot_y2 = x2;
 
623
                break;
 
624
        }
 
625
 
 
626
        switch(id) {
 
627
        case FOURCC_YV12:
 
628
        case FOURCC_I420:
 
629
                dstPitch = ((dst_width << 1) + 15) & ~15;
 
630
                srcPitch = (width + 3) & ~3;
 
631
                srcPitch2 = ((width >> 1) + 3) & ~3;
 
632
                size = dstPitch * dst_height;
 
633
                break;
 
634
        case FOURCC_UYVY:
 
635
        case FOURCC_YUY2:
 
636
        default:
 
637
                dstPitch = ((dst_width << 1) + 15) & ~15;
 
638
                srcPitch = (width << 1);
 
639
                srcPitch2 = 0;
 
640
                size = dstPitch * dst_height;
 
641
                break;
 
642
        }
 
643
 
 
644
        if (pPortPriv->off_screen != NULL && size != pPortPriv->size) {
 
645
                KdOffscreenFree(screen->pScreen, pPortPriv->off_screen);
 
646
                pPortPriv->off_screen = 0;
 
647
        }
 
648
 
 
649
        if (pPortPriv->off_screen == NULL) {
 
650
                pPortPriv->off_screen = KdOffscreenAlloc(screen->pScreen,
 
651
                    size * 2, 64, TRUE, ATIVideoSave, pPortPriv);
 
652
                if (pPortPriv->off_screen == NULL)
 
653
                        return BadAlloc;
 
654
        }
 
655
 
 
656
 
 
657
        if (pDraw->type == DRAWABLE_WINDOW)
 
658
                pPortPriv->pPixmap =
 
659
                    (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
 
660
        else
 
661
                pPortPriv->pPixmap = (PixmapPtr)pDraw;
 
662
 
 
663
        /* Migrate the pixmap to offscreen if necessary. */
 
664
        if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap))
 
665
                kaaMoveInPixmap(pPortPriv->pPixmap);
 
666
 
 
667
        if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap)) {
 
668
                return BadAlloc;
 
669
        }
 
670
 
 
671
        pPortPriv->src_offset = pPortPriv->off_screen->offset;
 
672
        pPortPriv->src_addr = (CARD8 *)(pScreenPriv->screen->memory_base +
 
673
            pPortPriv->src_offset);
 
674
        pPortPriv->src_pitch = dstPitch;
 
675
        pPortPriv->size = size;
 
676
        pPortPriv->pDraw = pDraw;
 
677
 
 
678
        /* copy data */
 
679
        top = rot_y1 >> 16;
 
680
        left = (rot_x1 >> 16) & ~1;
 
681
        npixels = ((((rot_x2 + 0xffff) >> 16) + 1) & ~1) - left;
 
682
 
 
683
        /* Since we're probably overwriting the area that might still be used
 
684
         * for the last PutImage request, wait for idle.
 
685
         */
 
686
        ATIWaitIdle(atis);
 
687
 
 
688
        switch(id) {
 
689
        case FOURCC_YV12:
 
690
        case FOURCC_I420:
 
691
                top &= ~1;
 
692
                nlines = ((((rot_y2 + 0xffff) >> 16) + 1) & ~1) - top;
 
693
                KdXVCopyPlanarData(screen, buf, pPortPriv->src_addr, randr,
 
694
                    srcPitch, srcPitch2, dstPitch, rot_src_w, rot_src_h,
 
695
                    height, top, left, nlines, npixels, id);
 
696
                break;
 
697
        case FOURCC_UYVY:
 
698
        case FOURCC_YUY2:
 
699
        default:
 
700
                nlines = ((rot_y2 + 0xffff) >> 16) - top;
 
701
                KdXVCopyPackedData(screen, buf, pPortPriv->src_addr, randr,
 
702
                    srcPitch, dstPitch, rot_src_w, rot_src_h, top, left,
 
703
                    nlines, npixels);
 
704
                break;
 
705
        }
 
706
 
 
707
        /* update cliplist */
 
708
        if (!REGION_EQUAL(screen->pScreen, &pPortPriv->clip, clipBoxes)) {
 
709
                REGION_COPY(screen->pScreen, &pPortPriv->clip, clipBoxes);
 
710
        }
 
711
 
 
712
        pPortPriv->id = id;
 
713
        pPortPriv->src_x1 = rot_x1;
 
714
        pPortPriv->src_y1 = rot_y1;
 
715
        pPortPriv->src_x2 = rot_x2;
 
716
        pPortPriv->src_y2 = rot_y2;
 
717
        pPortPriv->src_w = rot_src_w;
 
718
        pPortPriv->src_h = rot_src_h;
 
719
        pPortPriv->dst_x1 = dst_x1;
 
720
        pPortPriv->dst_y1 = dst_y1;
 
721
        pPortPriv->dst_x2 = dst_x2;
 
722
        pPortPriv->dst_y2 = dst_y2;
 
723
        pPortPriv->dst_w = rot_drw_w;
 
724
        pPortPriv->dst_h = rot_drw_h;
 
725
 
 
726
        if (atic->is_radeon)
 
727
                RadeonDisplayVideo(screen, pPortPriv);
 
728
        else
 
729
                R128DisplayVideo(screen, pPortPriv);
 
730
 
 
731
        return Success;
 
732
}
 
733
 
 
734
static int
 
735
ATIReputImage(KdScreenInfo *screen, DrawablePtr pDraw, short drw_x, short drw_y,
 
736
    RegionPtr clipBoxes, pointer data)
 
737
{
 
738
        ScreenPtr pScreen = screen->pScreen;
 
739
        KdScreenPriv(pScreen);
 
740
        ATICardInfo(pScreenPriv);
 
741
        ATIPortPrivPtr  pPortPriv = (ATIPortPrivPtr)data;
 
742
        BoxPtr pOldExtents = REGION_EXTENTS(screen->pScreen, &pPortPriv->clip);
 
743
        BoxPtr pNewExtents = REGION_EXTENTS(screen->pScreen, clipBoxes);
 
744
 
 
745
        if (pOldExtents->x1 != pNewExtents->x1 ||
 
746
            pOldExtents->x2 != pNewExtents->x2 ||
 
747
            pOldExtents->y1 != pNewExtents->y1 ||
 
748
            pOldExtents->y2 != pNewExtents->y2)
 
749
                return BadMatch;
 
750
 
 
751
        if (pDraw->type == DRAWABLE_WINDOW)
 
752
                pPortPriv->pPixmap =
 
753
                    (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
 
754
        else
 
755
                pPortPriv->pPixmap = (PixmapPtr)pDraw;
 
756
 
 
757
        if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap))
 
758
                kaaMoveInPixmap(pPortPriv->pPixmap);
 
759
 
 
760
        if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap)) {
 
761
                ErrorF("err\n");
 
762
                return BadAlloc;
 
763
        }
 
764
 
 
765
 
 
766
        /* update cliplist */
 
767
        if (!REGION_EQUAL(screen->pScreen, &pPortPriv->clip, clipBoxes))
 
768
                REGION_COPY(screen->pScreen, &pPortPriv->clip, clipBoxes);
 
769
 
 
770
        /* XXX: What do the drw_x and drw_y here mean for us? */
 
771
 
 
772
        if (atic->is_radeon)
 
773
                RadeonDisplayVideo(screen, pPortPriv);
 
774
        else
 
775
                R128DisplayVideo(screen, pPortPriv);
 
776
 
 
777
        return Success;
 
778
}
 
779
 
 
780
static int
 
781
ATIQueryImageAttributes(KdScreenInfo *screen, int id, unsigned short *w,
 
782
    unsigned short *h, int *pitches, int *offsets)
 
783
{
 
784
        int size, tmp;
 
785
 
 
786
        if (*w > IMAGE_MAX_WIDTH) 
 
787
                *w = IMAGE_MAX_WIDTH;
 
788
        if (*h > IMAGE_MAX_HEIGHT) 
 
789
                *h = IMAGE_MAX_HEIGHT;
 
790
 
 
791
        *w = (*w + 1) & ~1;
 
792
        if (offsets)
 
793
                offsets[0] = 0;
 
794
 
 
795
        switch (id)
 
796
        {
 
797
        case FOURCC_YV12:
 
798
        case FOURCC_I420:
 
799
                *h = (*h + 1) & ~1;
 
800
                size = (*w + 3) & ~3;
 
801
                if (pitches) 
 
802
                        pitches[0] = size;
 
803
                size *= *h;
 
804
                if (offsets) 
 
805
                        offsets[1] = size;
 
806
                tmp = ((*w >> 1) + 3) & ~3;
 
807
                if (pitches) 
 
808
                        pitches[1] = pitches[2] = tmp;
 
809
                tmp *= (*h >> 1);
 
810
                size += tmp;
 
811
                if (offsets) 
 
812
                        offsets[2] = size;
 
813
                size += tmp;
 
814
                break;
 
815
        case FOURCC_UYVY:
 
816
        case FOURCC_YUY2:
 
817
        default:
 
818
                size = *w << 1;
 
819
                if (pitches) 
 
820
                        pitches[0] = size;
 
821
                size *= *h;
 
822
                break;
 
823
        }
 
824
 
 
825
        return size;
 
826
}
 
827
 
 
828
 
 
829
/* client libraries expect an encoding */
 
830
static KdVideoEncodingRec DummyEncoding[1] =
 
831
{
 
832
        {
 
833
                0,
 
834
                "XV_IMAGE",
 
835
                IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
 
836
                {1, 1}
 
837
        }
 
838
};
 
839
 
 
840
#define NUM_FORMATS 3
 
841
 
 
842
static KdVideoFormatRec Formats[NUM_FORMATS] = 
 
843
{
 
844
        {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
 
845
};
 
846
 
 
847
#define NUM_ATTRIBUTES 0
 
848
 
 
849
static KdAttributeRec Attributes[NUM_ATTRIBUTES] =
 
850
{
 
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 KdVideoAdaptorPtr 
 
864
ATISetupImageVideo(ScreenPtr pScreen)
 
865
{
 
866
        KdScreenPriv(pScreen);
 
867
        ATIScreenInfo(pScreenPriv);
 
868
        KdVideoAdaptorPtr adapt;
 
869
        ATIPortPrivPtr pPortPriv;
 
870
        int i;
 
871
 
 
872
        atis->num_texture_ports = 16;
 
873
 
 
874
        adapt = xcalloc(1, sizeof(KdVideoAdaptorRec) + atis->num_texture_ports *
 
875
            (sizeof(ATIPortPrivRec) + sizeof(DevUnion)));
 
876
        if (adapt == NULL)
 
877
                return NULL;
 
878
 
 
879
        adapt->type = XvWindowMask | XvInputMask | XvImageMask;
 
880
        adapt->flags = VIDEO_CLIP_TO_VIEWPORT;
 
881
        adapt->name = "ATI Texture Video";
 
882
        adapt->nEncodings = 1;
 
883
        adapt->pEncodings = DummyEncoding;
 
884
        adapt->nFormats = NUM_FORMATS;
 
885
        adapt->pFormats = Formats;
 
886
        adapt->nPorts = atis->num_texture_ports;
 
887
        adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
 
888
 
 
889
        pPortPriv =
 
890
            (ATIPortPrivPtr)(&adapt->pPortPrivates[atis->num_texture_ports]);
 
891
 
 
892
        for (i = 0; i < atis->num_texture_ports; i++)
 
893
                adapt->pPortPrivates[i].ptr = &pPortPriv[i];
 
894
 
 
895
        adapt->nAttributes = NUM_ATTRIBUTES;
 
896
        adapt->pAttributes = Attributes;
 
897
        adapt->pImages = Images;
 
898
        adapt->nImages = NUM_IMAGES;
 
899
        adapt->PutVideo = NULL;
 
900
        adapt->PutStill = NULL;
 
901
        adapt->GetVideo = NULL;
 
902
        adapt->GetStill = NULL;
 
903
        adapt->StopVideo = ATIStopVideo;
 
904
        adapt->SetPortAttribute = ATISetPortAttribute;
 
905
        adapt->GetPortAttribute = ATIGetPortAttribute;
 
906
        adapt->QueryBestSize = ATIQueryBestSize;
 
907
        adapt->PutImage = ATIPutImage;
 
908
        adapt->ReputImage = ATIReputImage;
 
909
        adapt->QueryImageAttributes = ATIQueryImageAttributes;
 
910
 
 
911
        /* gotta uninit this someplace */
 
912
        REGION_INIT(pScreen, &pPortPriv->clip, NullBox, 0); 
 
913
 
 
914
        atis->pAdaptor = adapt;
 
915
 
 
916
        xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
 
917
        xvSaturation = MAKE_ATOM("XV_SATURATION");
 
918
 
 
919
        return adapt;
 
920
}
 
921
 
 
922
Bool ATIInitVideo(ScreenPtr pScreen)
 
923
{
 
924
        KdScreenPriv(pScreen);
 
925
        ATIScreenInfo(pScreenPriv);
 
926
        ATICardInfo(pScreenPriv);
 
927
        KdScreenInfo *screen = pScreenPriv->screen;
 
928
        KdVideoAdaptorPtr *adaptors, *newAdaptors = NULL;
 
929
        KdVideoAdaptorPtr newAdaptor = NULL;
 
930
        int num_adaptors;
 
931
    
 
932
        atis->pAdaptor = NULL;
 
933
 
 
934
        if (atic->reg_base == NULL)
 
935
                return FALSE;
 
936
        if (atic->is_r300)
 
937
                return FALSE;
 
938
 
 
939
        num_adaptors = KdXVListGenericAdaptors(screen, &adaptors);
 
940
 
 
941
        newAdaptor = ATISetupImageVideo(pScreen);
 
942
 
 
943
        if (newAdaptor)  {
 
944
                if (!num_adaptors) {
 
945
                        num_adaptors = 1;
 
946
                        adaptors = &newAdaptor;
 
947
                } else {
 
948
                        newAdaptors = xalloc((num_adaptors + 1) * 
 
949
                            sizeof(KdVideoAdaptorPtr *));
 
950
                        if (newAdaptors) {
 
951
                                memcpy(newAdaptors, adaptors, num_adaptors *
 
952
                                    sizeof(KdVideoAdaptorPtr));
 
953
                                newAdaptors[num_adaptors] = newAdaptor;
 
954
                                adaptors = newAdaptors;
 
955
                                num_adaptors++;
 
956
                        }
 
957
                }
 
958
        }
 
959
 
 
960
        if (num_adaptors)
 
961
                KdXVScreenInit(pScreen, adaptors, num_adaptors);
 
962
 
 
963
        if (newAdaptors)
 
964
                xfree(newAdaptors);
 
965
 
 
966
        return TRUE;
 
967
}
 
968
 
 
969
void
 
970
ATIFiniVideo(ScreenPtr pScreen)
 
971
{
 
972
        KdScreenPriv(pScreen);
 
973
        ATIScreenInfo(pScreenPriv);
 
974
        KdVideoAdaptorPtr adapt = atis->pAdaptor;
 
975
        ATIPortPrivPtr pPortPriv;
 
976
        int i;
 
977
 
 
978
        if (!adapt)
 
979
                return;
 
980
 
 
981
        for (i = 0; i < atis->num_texture_ports; i++) {
 
982
                pPortPriv = (ATIPortPrivPtr)(&adapt->pPortPrivates[i].ptr);
 
983
                REGION_UNINIT(pScreen, &pPortPriv->clip);
 
984
        }
 
985
        xfree(adapt);
 
986
        atis->pAdaptor = NULL;
 
987
}