i128exa.c revision 50806d53
1/*
2 * Copyright 1997-2000 by Robin Cutshaw <robin@XFree86.Org>
3 * Copyright 2005 Adam Jackson <ajax@nwnk.net>
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 names of the authors not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission.  The authors make no representations
12 * about the suitability of this software for any purpose.  It is provided
13 * "as is" without express or implied warranty.
14 *
15 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL THE AUTHORS 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
24/* Solid and Copy support derived from the i128 XAA code */
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#include "exa.h"
31#include "miline.h"
32#include "servermd.h"
33#include "picture.h"
34
35#include "xf86.h"
36#include "xf86_OSproc.h"
37#include "xf86_ansic.h"
38#include "xf86Pci.h"
39#include "xf86PciInfo.h"
40
41#include "i128.h"
42#include "i128reg.h"
43
44#define PI128_FROM_PIXMAP(x) \
45    I128Ptr pI128 = I128PTR(xf86Screens[x->drawable.pScreen->myNum])
46#define PI128_FROM_SCREEN(x) \
47    I128Ptr pI128 = I128PTR(xf86Screens[x->myNum])
48#define PI128_FROM_PICTURE(x) \
49    I128Ptr pI128 = I128PTR(xf86Screens[x->pDrawable->pScreen->myNum])
50
51/* we might be able to do something smarter than this */
52#define ENG_PIPELINE_READY() \
53    while (pI128->mem.rbase_a[BUSY] & BUSY_BUSY)
54#define ENG_DONE() \
55    while (pI128->mem.rbase_a[FLOW] & (FLOW_DEB | FLOW_MCB | FLOW_PRV))
56
57#if 1
58#define I128_EXA_DEBUG(x)
59#else
60#define I128_EXA_DEBUG(x) ErrorF x
61#endif
62
63/* technically we should set the caches to bogus things during init... */
64#define CACHE_DEBUG 0
65
66#define CACHED_UPDATE(val, reg) \
67    do if (pI128->val != val) { \
68        if (CACHE_DEBUG) I128_EXA_DEBUG(("Updated cache for " #reg "\n")); \
69        pI128->mem.rbase_a[reg] = pI128->val = val; \
70    } while (0)
71
72static void
73i128SetBufCtrl(I128Ptr pI128, int dest_bpp)
74{
75    unsigned int buf_ctrl;
76
77    switch (dest_bpp) {
78        case 8:  buf_ctrl = BC_PSIZ_8B;  break;
79        case 16: buf_ctrl = BC_PSIZ_16B; break;
80        case 24:
81        case 32: buf_ctrl = BC_PSIZ_32B; break;
82        default: buf_ctrl = 0;           break; /* error */
83    }
84    if (pI128->Chipset == PCI_CHIP_I128_T2R) {
85        if (pI128->MemoryType == I128_MEMORY_SGRAM)
86            buf_ctrl |= BC_MDM_PLN;
87        else
88            buf_ctrl |= BC_BLK_ENA;
89    }
90
91    CACHED_UPDATE(buf_ctrl, BUF_CTRL);
92}
93
94static const CARD32 i128alu[16] =
95{
96    CR_CLEAR << 8,
97    CR_AND << 8,
98    CR_AND_REV << 8,
99    CR_COPY << 8,
100    CR_AND_INV << 8,
101    CR_NOOP << 8,
102    CR_XOR << 8,
103    CR_OR << 8,
104    CR_NOR << 8,
105    CR_EQUIV << 8,
106    CR_INVERT << 8,
107    CR_OR_REV << 8,
108    CR_COPY_INV << 8,
109    CR_OR_INV << 8,
110    CR_NAND << 8,
111    CR_SET << 8
112};
113
114/*                                8bpp   16bpp  32bpp unused */
115static const int min_size[]   = { 0x62,  0x32,  0x1A, 0x00 };
116static const int max_size[]   = { 0x80,  0x40,  0x20, 0x00 };
117static const int split_size[] = { 0x20,  0x10,  0x08, 0x00 };
118
119/*
120 * this is the workhorse for our solid and copy routines.  this works because
121 * when CS_SOLID is set, the color comes from the FORE register regardless of
122 * the source pixmap coords.
123 */
124
125static void
126i128ExaBlit(PixmapPtr dst, int x1, int y1, int x2, int y2, int w, int h)
127{
128    int wh;
129    PI128_FROM_PIXMAP(dst);
130
131    I128_EXA_DEBUG(("Blit: %d %d %d %d %d %d\n", x1, y1, x2, y2, w, h));
132    ENG_PIPELINE_READY();
133
134    /*
135     * this deserves explanation.  XY3_DIR == 0 means left to right, top to
136     * bottom.  setting bit zero (DIR_LR_BT) switches to bottom to top, and
137     * setting bit one (DIR_RL_TB) switches to right to left. XXX rewrite me.
138     */
139    if (pI128->blitdir & DIR_RL_TB) { /* right-to-left */
140        x1 += w; x1--;
141        x2 += w; x2--;
142    }
143    if (pI128->blitdir & DIR_LR_BT) { /* bottom-to-top */
144        y1 += h; y1--;
145        y2 += h; y2--;
146    }
147
148    if (pI128->Chipset == PCI_CHIP_I128) {
149        int bppi;
150
151        /* The I128-1 has a nasty bitblit bug
152         * that occurs when dest is exactly 8 pages wide
153         */
154
155        bppi = (pI128->mem.rbase_a[BUF_CTRL] & BC_PSIZ_MSK) >> 24;
156
157        if ((w >= min_size[bppi]) && (w <= max_size[bppi])) {
158            bppi = split_size[bppi];
159#if 1
160            /* split method */
161
162            wh = (bppi << 16) | h;
163            CACHED_UPDATE(wh, XY2_WH);
164            pI128->mem.rbase_a[XY0_SRC] = (x1 << 16) | y1;    MB;
165            pI128->mem.rbase_a[XY1_DST] = (x2 << 16) | y2;    MB;
166
167            ENG_PIPELINE_READY();
168
169            w -= bppi;
170
171            if (pI128->blitdir & DIR_RL_TB) {
172                /* right to left blit */
173                x1 -= bppi;
174                x2 -= bppi;
175            } else {
176                /* left to right blit */
177                x1 += bppi;
178                x2 += bppi;
179            }
180#else
181            /* clip method */
182            pI128->mem.rbase_a[CLPTL] = (x2 << 16) | y2;
183            pI128->mem.rbase_a[CLPBR] = ((x2 + w) << 16) | (y2 + h);
184            w += bppi;
185#endif
186        }
187    }
188
189    /* this is overkill, but you can never have too much overkill */
190    wh = (w << 16) | h;
191    CACHED_UPDATE(wh, XY2_WH);
192
193    pI128->mem.rbase_a[XY0_SRC] = (x1 << 16) | y1;    MB;
194    pI128->mem.rbase_a[XY1_DST] = (x2 << 16) | y2;    MB;
195}
196
197static void
198i128WaitMarker(ScreenPtr pScreen, int Marker)
199{
200    PI128_FROM_SCREEN(pScreen);
201    ENG_DONE();
202}
203
204static void
205i128SetPlanemask(I128Ptr pI128, Pixel p)
206{
207    Pixel planemask;
208    I128_EXA_DEBUG(("SetPlanemask: %d\n", (int)p));
209    if (p == -1)
210        planemask = -1;
211    else switch (pI128->bitsPerPixel) {
212        case 8:
213            planemask = p * 0x01010101; break;
214        case 16:
215            planemask = p * 0x00010001; break;
216        default:
217            planemask = p; break;
218    }
219
220    CACHED_UPDATE(planemask, MASK);
221}
222
223/* this should be superfluous... */
224static void
225i128SetClip(I128Ptr pI128)
226{
227#if 0
228    pI128->clptl = pI128->mem.rbase_a[CLPTL] = 0x00000000;
229    pI128->clpbr = pI128->mem.rbase_a[CLPBR] = (4095 << 16) | 2047;
230#endif
231}
232
233static void
234i128SetBlitDirection(I128Ptr pI128, int dx, int dy)
235{
236    int blitdir;
237
238    I128_EXA_DEBUG(("SetBlitDirection: %d %d\n", dx, dy));
239
240    if (dx < 0) {
241        if (dy < 0) blitdir = DIR_RL_BT;
242        else blitdir = DIR_RL_TB;
243    } else {
244        if (dy < 0) blitdir = DIR_LR_BT;
245        else blitdir = DIR_LR_TB;
246    }
247
248    CACHED_UPDATE(blitdir, XY3_DIR);
249}
250
251static void
252i128SetRop(I128Ptr pI128, int alu, int solid)
253{
254    int cmd;
255
256    I128_EXA_DEBUG(("SetRop: %d %d\n", alu, solid));
257
258    cmd = i128alu[alu] | CO_BITBLT | (solid ? (CS_SOLID << 16) : 0);
259
260    CACHED_UPDATE(cmd, CMD);
261}
262
263static void
264i128SetSourcePixmap(I128Ptr pI128, PixmapPtr src)
265{
266    unsigned int sorg = exaGetPixmapOffset(src);
267    unsigned int sptch = exaGetPixmapPitch(src);
268
269    I128_EXA_DEBUG(("SetSourcePixmap: %x, %d\n", sorg, sptch));
270
271    CACHED_UPDATE(sorg, DE_SORG);
272    CACHED_UPDATE(sptch, DE_SPTCH);
273}
274
275static void
276i128SetDestPixmap(I128Ptr pI128, PixmapPtr dst)
277{
278    unsigned int dorg = exaGetPixmapOffset(dst);
279    unsigned int dptch = exaGetPixmapPitch(dst);
280
281    I128_EXA_DEBUG(("SetDestPixmap: %x, %d\n", dorg, dptch));
282
283    CACHED_UPDATE(dorg, DE_DORG);
284    CACHED_UPDATE(dptch, DE_DPTCH);
285}
286
287static void
288i128SetTexture(I128Ptr pI128, PixmapPtr tex)
289{
290    unsigned int torg = exaGetPixmapOffset(tex);
291    unsigned int tptch = exaGetPixmapPitch(tex);
292
293    I128_EXA_DEBUG(("SetTexture: %x, %d\n", torg, tptch));
294
295    CACHED_UPDATE(torg, LOD0_ORG);
296    CACHED_UPDATE(tptch, DE_TPTCH);
297}
298
299static const int func_tab[13][2] = {
300        /* source function,         destination function */
301        { ABLEND_SRC_ZERO,          ABLEND_DST_ZERO        }, /* clear */
302        { ABLEND_SRC_ONE,           ABLEND_DST_ZERO        }, /* src */
303        { ABLEND_SRC_ZERO,          ABLEND_DST_ONE         }, /* dst */
304        { ABLEND_SRC_ONE,           ABLEND_DST_OMSRC_ALPHA }, /* over */
305        { ABLEND_SRC_OMDST_ALPHA,   ABLEND_DST_ONE         }, /* overreverse */
306        { ABLEND_SRC_DST_ALPHA,     ABLEND_DST_ZERO        }, /* in */
307        { ABLEND_SRC_ZERO,          ABLEND_DST_SRC_ALPHA   }, /* inreverse */
308        { ABLEND_SRC_OMDST_ALPHA,   ABLEND_DST_ZERO        }, /* out */
309        { ABLEND_SRC_ZERO,          ABLEND_DST_OMSRC_ALPHA }, /* outreverse */
310        { ABLEND_SRC_DST_ALPHA,     ABLEND_DST_OMSRC_ALPHA }, /* atop */
311        { ABLEND_SRC_OMDST_ALPHA,   ABLEND_DST_SRC_ALPHA   }, /* atopreverse */
312        { ABLEND_SRC_OMDST_ALPHA,   ABLEND_DST_OMSRC_ALPHA }, /* xor */
313        { ABLEND_SRC_ONE,           ABLEND_DST_ONE         }  /* add */
314};
315
316static void
317i128SetAlphaForOp(I128Ptr pI128, int op, int enable)
318{
319    int acntrl = 0;
320
321    if (enable) {
322        acntrl |= ACTL_BE;  /* blend enable */
323        acntrl |= func_tab[op][0];  /* source factor */
324        acntrl |= func_tab[op][1];  /* dest_factor */
325        acntrl |= 0; /* ACTL_AMD; / * modulate alpha */
326    } else {
327        acntrl = 0;
328    }
329
330    I128_EXA_DEBUG(("SetAlphaForOp: %d, %d\n", op, enable));
331
332    CACHED_UPDATE(acntrl, ACNTRL);
333}
334
335/* we don't need a finalizer, yet */
336static void
337i128Done(PixmapPtr p) {
338    I128_EXA_DEBUG(("Done\n\n"));
339    return;
340}
341
342/* Solid */
343
344static Bool
345i128PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
346{
347    PI128_FROM_PIXMAP(pPixmap);
348
349    ENG_PIPELINE_READY();
350
351    i128SetPlanemask(pI128, planemask);
352
353    if (alu != GXclear && alu != GXset)
354        pI128->mem.rbase_a[FORE] = fg;
355
356    i128SetClip(pI128);
357    i128SetBlitDirection(pI128, 1, 1); /* probably unnecessary/ignored */
358
359    i128SetAlphaForOp(pI128, 0, 0);
360    i128SetRop(pI128, alu, 1);
361
362    /* no need to set the source, the chip ignores it */
363    i128SetDestPixmap(pI128, pPixmap);
364
365    return TRUE;
366}
367
368static void
369i128Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
370{
371    i128ExaBlit(pPixmap, 0, 0, x1, y1, x2 - x1, y2 - y1);
372}
373
374/* Copy */
375
376static Bool
377i128PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int dx, int dy,
378                int alu, Pixel planemask)
379{
380    PI128_FROM_PIXMAP(pSrcPixmap);
381
382    ENG_PIPELINE_READY();
383
384    i128SetPlanemask(pI128, planemask);
385    i128SetClip(pI128);
386    i128SetBlitDirection(pI128, dx, dy);
387
388    i128SetAlphaForOp(pI128, 0, 0);
389    i128SetRop(pI128, alu, 0);
390
391    i128SetSourcePixmap(pI128, pSrcPixmap);
392    i128SetDestPixmap(pI128, pDstPixmap);
393
394    return TRUE;
395}
396
397static void
398i128Copy(PixmapPtr pDstPixmap, int x1, int y1, int x2, int y2, int w, int h)
399{
400    i128ExaBlit(pDstPixmap, x1, y1, x2, y2, w, h);
401}
402
403/* Composite */
404
405static const struct source_format source_formats[] = {
406    /* 32bpp */
407    { PICT_a8r8g8b8,    0x14,   0,  0 },
408    { PICT_x8r8g8b8,    0x14,   0,  1 },
409#if 0
410    { PICT_a8b8g8r8,    0x14,   0,  0 },
411    { PICT_x8b8g8r8,    0x14,   0,  1 },
412    /* no direct 24bpp formats */
413    /* 16bpp */
414    { PICT_r5g6b5,      0x12,   0,  0 },
415    { PICT_b5g6r5,      0x12,   0,  0 },
416    { PICT_a1r5g5b5,    0x11,   0,  0 },
417    { PICT_x1r5g5b5,    0x11,   0,  1 },
418    { PICT_a1b5g5r5,    0x11,   0,  0 },
419    { PICT_x1b5g5r5,    0x11,   0,  1 },
420    { PICT_a4r4g4b4,    0x10,   0,  0 },
421    { PICT_x4r4g4b4,    0x10,   0,  1 },
422    { PICT_a4b4g4r4,    0x10,   0,  0 },
423    { PICT_x4b4g4r4,    0x10,   0,  1 },
424    /* 8bpp */
425    { PICT_a8,          0x21,   0,  0 },
426    { PICT_r3g3b2,      0x0D,   0,  0 },
427    { PICT_b2g3r3,      0x0D,   0,  0 },
428    { PICT_a2r2g2b2,    0x30,   0,  0 },
429    { PICT_a2b2g2r2,    0x30,   0,  0 },
430    /* 4bpp */
431    { PICT_a4,          0x20,   0,  0 },
432#endif
433    /* terminator */
434    { 0,                0,      0,  0 }
435};
436
437static struct source_format *
438i128MapSourceFormat(int fmt)
439{
440    struct source_format *f;
441    for (f = (struct source_format *)source_formats; f->render_format; f++)
442        if (f->render_format == fmt)
443            return f;
444    return NULL;
445}
446
447struct dest_format {
448    int render_format;
449    int i128_format;
450};
451
452static const struct dest_format dest_formats[] = {
453    { 0, 0 }
454};
455
456static struct dest_format *
457i128MapDestFormat(int fmt)
458{
459    return NULL;
460}
461
462/* Composite is probably t2r and t2r4 only */
463static Bool
464i128CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
465                   PicturePtr pDstPicture)
466{
467    PI128_FROM_PICTURE(pDstPicture);
468
469    if (op >= PictOpSaturate) return FALSE;
470
471    /*
472     * no direct alpha mask support.  we only have one TMU, so while we
473     * can emulate it, we should emulate it in the generic EXA layer.
474     */
475    if (pMaskPicture) return FALSE;
476
477    /* when transforms added, be sure to check for linear/nearest */
478    /* if (pSrcPicture->transform) return FALSE; */
479
480    /* no support for external alpha */
481    if (pSrcPicture->alphaMap || pDstPicture->alphaMap) return FALSE;
482
483    pI128->source = i128MapSourceFormat(pSrcPicture->format);
484    if (!pI128->source)
485        return FALSE;
486#if 0
487    if (!i128MapDestFormat(pDstPicture->format)) return FALSE;
488#endif
489
490    return TRUE;
491}
492
493static Bool
494i128PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
495                     PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask,
496                     PixmapPtr pDst)
497{
498    unsigned int cmd;
499    unsigned int tex_ctl = 0;
500    unsigned int threedctl = 0;
501    PI128_FROM_PIXMAP(pDst);
502
503    /* 2D setup */
504    i128SetBufCtrl(pI128, pDst->drawable.bitsPerPixel);
505    i128SetPlanemask(pI128, -1);
506    i128SetSourcePixmap(pI128, pSrc);
507    i128SetDestPixmap(pI128, pDst);
508
509    /* TEX_INV command here? */
510
511    cmd = CO_TRIAN3D;
512    CACHED_UPDATE(cmd, CMD);
513
514    /* 3D setup */
515    i128SetTexture(pI128, pSrc);
516
517    i128SetAlphaForOp(pI128, op, 1);
518
519    /* it looks pointless to cache these, but we'll need it for DRI */
520
521    tex_ctl |= TEX_TM;  /* enable texture mapping */
522    tex_ctl |= TEX_NMG | TEX_NMN;   /* nearest interpolation */
523    tex_ctl |= 0; /* TEX_RM;  / * modulate RGB */
524    CACHED_UPDATE(tex_ctl, TEX_CTL);
525
526    threedctl |= 0; /* COMP_TRUE << TCTL_ZOP_SHIFT;   / * always pass Z check */
527    threedctl |= TCTL_ABS;  /* enable alpha blend */
528    threedctl |= TCTL_TBS;  /* enable texture blend */
529    threedctl |= TCTL_RT;   /* draw textured rectangle */
530    CACHED_UPDATE(threedctl, THREEDCTL);
531
532    return TRUE;
533}
534
535static void
536i128Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
537              int dstX, int dstY, int width, int height)
538{
539    PI128_FROM_PIXMAP(pDst);
540
541    /*
542     * vertex setup.  vertex layout must be:
543     * V0    V1
544     * V2   (V3 is implicit)
545     */
546
547    pI128->mem.rbase_af[V0_X] = 0.0;
548    pI128->mem.rbase_af[V0_Y] = 0.0;
549    pI128->mem.rbase_af[V0_W] = 1.0;
550    pI128->mem.rbase_af[V0_U] = 0.0;
551    pI128->mem.rbase_af[V0_V] = 0.0;
552    pI128->mem.rbase_af[V1_X] = 300.0;
553    pI128->mem.rbase_af[V1_Y] = 0.0;
554    pI128->mem.rbase_af[V1_W] = 1.0;
555    pI128->mem.rbase_af[V1_U] = 1.0;
556    pI128->mem.rbase_af[V1_V] = 0.0;
557    pI128->mem.rbase_af[V2_X] = 0.0;
558    pI128->mem.rbase_af[V2_Y] = 300.0;
559    pI128->mem.rbase_af[V2_W] = 1.0;
560    pI128->mem.rbase_af[V2_U] = 0.0;
561    pI128->mem.rbase_af[V2_V] = 1.0;
562
563    /* and fire */
564    pI128->mem.rbase_a[TRIGGER3D] = 1; MB;
565
566#if 0
567    static int i = 0;
568    /* test for raster */
569    if (!(i = (i + 1) % 32)) {
570        ErrorF("Composite test: %d %d %d %d %d %d\n", srcX, srcY, dstX, dstY,
571                width, height);
572    }
573    i128SetRop(pI128, GXxor, 0);
574    i128ExaBlit(pDst, srcX, srcY, dstX, dstY, width, height);
575#endif
576}
577
578#if 0
579/*
580 * upload and download will require a DRM.  AGP DMA only works on T2R4, and
581 * then only for upload.  we could probably use memory windows on other chips,
582 * but those have goofy alignment restrictions and need to be disabled when
583 * not in use.
584 */
585static Bool
586i128DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst,
587                       int dst_pitch)
588{
589}
590
591static Bool
592i128UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src,
593                   int src_pitch)
594{
595}
596#endif
597
598Bool
599I128ExaInit(ScreenPtr pScreen)
600{
601    ExaDriverPtr pExa;
602    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
603    I128Ptr pI128 = I128PTR(pScrn);
604
605    if (!(pExa = exaDriverAlloc())) {
606        pI128->NoAccel = TRUE;
607        return FALSE;
608    }
609    pI128->ExaDriver = pExa;
610
611    pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_OFFSCREEN_ALIGN_POT;
612    pExa->memoryBase = pI128->MemoryPtr;
613    pExa->memorySize = pI128->MemorySize * 1024;
614    pExa->offScreenBase = (pScrn->virtualX * pScrn->virtualY) *
615                               (pScrn->bitsPerPixel / 8) + 4096;
616    /* these two are probably right */
617    pExa->pixmapOffsetAlign = 16;
618    pExa->pixmapPitchAlign = 16;
619    /* these two are guesses */
620    pExa->maxX = 2048;
621    pExa->maxY = 2048;
622
623    pExa->WaitMarker = i128WaitMarker;
624
625    pExa->PrepareSolid = i128PrepareSolid;
626    pExa->Solid = i128Solid;
627    pExa->DoneSolid = i128Done;
628
629    pExa->PrepareCopy = i128PrepareCopy;
630    pExa->Copy = i128Copy;
631    pExa->DoneCopy = i128Done;
632
633    if (0 && (pI128->Chipset == PCI_CHIP_I128_T2R ||
634        pI128->Chipset == PCI_CHIP_I128_T2R4))
635    {
636#if 0
637        pExa->DownloadFromScreen = i128DownloadFromScreen;
638        pExa->UploadToScreen = i128UploadToScreen;
639#endif
640        pExa->CheckComposite = i128CheckComposite;
641        pExa->PrepareComposite = i128PrepareComposite;
642        pExa->Composite = i128Composite;
643        pExa->DoneComposite = i128Done;
644    }
645
646    /*
647     * XXX much of this is duplicated from the XAA code, but I expect the XAA
648     * support to disappear eventually.
649     */
650    pI128->buf_ctrl = 0; /* force write */
651    i128SetBufCtrl(pI128, pI128->bitsPerPixel);
652
653    /* all of this needs to be properly documented */
654    {
655        pI128->mem.rbase_a[DE_PGE] = 0x00;
656        pI128->mem.rbase_a[DE_SORG] = pI128->displayOffset;
657        pI128->mem.rbase_a[DE_DORG] = pI128->displayOffset;
658        pI128->mem.rbase_a[DE_MSRC] = 0x00;
659        pI128->mem.rbase_a[DE_WKEY] = 0x00;
660        pI128->mem.rbase_a[DE_SPTCH] = pI128->mem.rbase_g[DB_PTCH];
661        pI128->mem.rbase_a[DE_DPTCH] = pI128->mem.rbase_g[DB_PTCH];
662        if (pI128->Chipset == PCI_CHIP_I128_T2R4)
663            pI128->mem.rbase_a[DE_ZPTCH] = pI128->mem.rbase_g[DB_PTCH];
664        pI128->mem.rbase_a[RMSK] = 0x00000000;
665        pI128->mem.rbase_a[XY4_ZM] = ZOOM_NONE;
666        pI128->mem.rbase_a[LPAT] = 0xffffffff;  /* for lines */
667        pI128->mem.rbase_a[PCTRL] = 0x00000000; /* for lines */
668        pI128->mem.rbase_a[CLPTL] = 0x00000000;
669        pI128->mem.rbase_a[CLPBR] = (4095 << 16) | 2047 ;
670        pI128->mem.rbase_a[ACNTRL] = 0x00000000;
671        pI128->mem.rbase_a[INTM] = 0x03;
672    }
673
674    /* need this as a float * for vertex setup */
675    pI128->mem.rbase_af = (float *)pI128->mem.rbase_a;
676
677    if (pI128->Debug) {
678        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I128ExaInit done\n");
679        I128DumpActiveRegisters(pScrn);
680    }
681
682    return(exaDriverInit(pScreen, pExa));
683}
684