1/*
2 * Copyright 2006 Joseph Garvin
3 * Copyright 2012 Connor Behan
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 *    Joseph Garvin <joseph.h.garvin@gmail.com>
27 *    Connor Behan <connor.behan@gmail.com>
28 *
29 */
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
35#include "r128.h"
36#include "exa.h"
37
38#include "r128_reg.h"
39#include "r128_rop.h"
40
41#include "xf86.h"
42
43/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
44 * require src and dest datatypes to be equal.
45 */
46Bool R128GetDatatypeBpp(int bpp, uint32_t *type)
47{
48    switch (bpp) {
49    case 8:
50        *type = R128_DATATYPE_CI8;
51        return TRUE;
52    case 16:
53        *type = R128_DATATYPE_RGB565;
54        return TRUE;
55    case 24:
56        *type = R128_DATATYPE_RGB888;
57        return TRUE;
58    case 32:
59        *type = R128_DATATYPE_ARGB8888;
60        return TRUE;
61    default:
62        return FALSE;
63    }
64}
65
66static Bool R128GetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset,
67				 unsigned int offset, unsigned int pitch)
68{
69    ScreenPtr     pScreen   = pPix->drawable.pScreen;
70    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
71    R128InfoPtr   info      = R128PTR(pScrn);
72
73    if (pitch > 16320 || pitch % info->ExaDriver->pixmapPitchAlign != 0) {
74        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
75                            "Bad pitch 0x%08x\n", pitch));
76	return FALSE;
77    }
78
79    if (offset % info->ExaDriver->pixmapOffsetAlign != 0) {
80        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
81                            "Bad offset 0x%08x\n", offset));
82	return FALSE;
83    }
84
85    *pitch_offset = ((pitch / bpp) << 21) | (offset >> 5);
86
87    return TRUE;
88}
89
90Bool R128GetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
91{
92    uint32_t pitch, offset;
93    int bpp;
94
95    bpp = pPix->drawable.bitsPerPixel;
96    if (bpp == 24)
97        bpp = 8;
98
99    offset = exaGetPixmapOffset(pPix);
100    pitch = exaGetPixmapPitch(pPix);
101
102    return R128GetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
103}
104
105static void Emit2DState(ScrnInfoPtr pScrn)
106{
107    R128InfoPtr   info      = R128PTR(pScrn);
108    int has_src		    = info->state_2d.src_pitch_offset;
109    unsigned char *R128MMIO = info->MMIO;
110
111    R128WaitForFifo(pScrn, (has_src ? 10 : 9));
112
113    OUTREG(R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right);
114    OUTREG(R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl);
115    OUTREG(R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr);
116    OUTREG(R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr);
117    OUTREG(R128_DP_SRC_FRGD_CLR,   info->state_2d.dp_src_frgd_clr);
118    OUTREG(R128_DP_SRC_BKGD_CLR,   info->state_2d.dp_src_bkgd_clr);
119    OUTREG(R128_DP_WRITE_MASK, info->state_2d.dp_write_mask);
120    OUTREG(R128_DP_CNTL, info->state_2d.dp_cntl);
121
122    OUTREG(R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset);
123    if (has_src) OUTREG(R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset);
124}
125
126#ifdef R128DRI
127void EmitCCE2DState(ScrnInfoPtr pScrn)
128{
129    R128InfoPtr   info      = R128PTR(pScrn);
130    int has_src		    = info->state_2d.src_pitch_offset;
131    RING_LOCALS;
132
133    R128CCE_REFRESH( pScrn, info );
134
135    BEGIN_RING( (has_src ? 20 : 18) );
136
137    OUT_RING_REG( R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right );
138    OUT_RING_REG( R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl );
139    OUT_RING_REG( R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr );
140    OUT_RING_REG( R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr );
141    OUT_RING_REG( R128_DP_SRC_FRGD_CLR,   info->state_2d.dp_src_frgd_clr );
142    OUT_RING_REG( R128_DP_SRC_BKGD_CLR,   info->state_2d.dp_src_bkgd_clr );
143    OUT_RING_REG( R128_DP_WRITE_MASK, info->state_2d.dp_write_mask );
144    OUT_RING_REG( R128_DP_CNTL, info->state_2d.dp_cntl );
145
146    OUT_RING_REG( R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset );
147    if (has_src) OUT_RING_REG( R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset );
148
149    ADVANCE_RING();
150}
151#endif
152
153/* EXA Callbacks */
154
155static Bool
156R128PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
157{
158    ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
159    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
160    R128InfoPtr   info      = R128PTR(pScrn);
161
162    int bpp = pPixmap->drawable.bitsPerPixel;
163    uint32_t datatype, dst_pitch_offset;
164
165    if (!R128GetDatatypeBpp(bpp, &datatype)) {
166        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
167                            "R128GetDatatypeBpp failed\n"));
168	return FALSE;
169    }
170    if (!R128GetPixmapOffsetPitch(pPixmap, &dst_pitch_offset)) {
171        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
172                            "R128GetPixmapOffsetPitch failed\n"));
173	return FALSE;
174    }
175    if (info->state_2d.in_use) return FALSE;
176
177    info->state_2d.in_use = TRUE;
178    info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
179    info->state_2d.dp_brush_bkgd_clr = 0x00000000;
180    info->state_2d.dp_src_frgd_clr = 0xffffffff;
181    info->state_2d.dp_src_bkgd_clr = 0x00000000;
182    info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
183					  R128_GMC_BRUSH_SOLID_COLOR |
184					  (datatype >> 8) |
185					  R128_GMC_SRC_DATATYPE_COLOR |
186					  R128_ROP[alu].pattern |
187					  R128_GMC_CLR_CMP_CNTL_DIS);
188    info->state_2d.dp_brush_frgd_clr = fg;
189    info->state_2d.dp_cntl = (R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM);
190    info->state_2d.dp_write_mask = planemask;
191    info->state_2d.dst_pitch_offset = dst_pitch_offset;
192    info->state_2d.src_pitch_offset = 0;
193
194#ifdef R128DRI
195    if (info->directRenderingEnabled) {
196        EmitCCE2DState(pScrn);
197    } else
198#endif
199    {
200        Emit2DState(pScrn);
201    }
202    return TRUE;
203}
204
205static void
206R128Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
207{
208    ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
209    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
210    R128InfoPtr   info      = R128PTR(pScrn);
211    unsigned char *R128MMIO = info->MMIO;
212
213    R128WaitForFifo(pScrn, 2);
214    OUTREG(R128_DST_Y_X,          (y1 << 16) | x1);
215    OUTREG(R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1));
216    exaMarkSync(pScreen);
217}
218
219#define R128DoneSolid R128Done
220
221void
222R128DoPrepareCopy(ScrnInfoPtr pScrn, uint32_t src_pitch_offset,
223			uint32_t dst_pitch_offset, uint32_t datatype, int alu, Pixel planemask)
224{
225    R128InfoPtr   info      = R128PTR(pScrn);
226
227    info->state_2d.in_use = TRUE;
228    info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
229					  R128_GMC_SRC_PITCH_OFFSET_CNTL |
230					  R128_GMC_BRUSH_NONE |
231					  (datatype >> 8) |
232					  R128_GMC_SRC_DATATYPE_COLOR |
233					  R128_ROP[alu].rop |
234					  R128_DP_SRC_SOURCE_MEMORY |
235					  R128_GMC_CLR_CMP_CNTL_DIS);
236    info->state_2d.dp_cntl = ((info->xdir >= 0 ? R128_DST_X_LEFT_TO_RIGHT : 0) |
237			       (info->ydir >= 0 ? R128_DST_Y_TOP_TO_BOTTOM : 0));
238    info->state_2d.dp_brush_frgd_clr = 0xffffffff;
239    info->state_2d.dp_brush_bkgd_clr = 0x00000000;
240    info->state_2d.dp_src_frgd_clr = 0xffffffff;
241    info->state_2d.dp_src_bkgd_clr = 0x00000000;
242    info->state_2d.dp_write_mask = planemask;
243    info->state_2d.dst_pitch_offset = dst_pitch_offset;
244    info->state_2d.src_pitch_offset = src_pitch_offset;
245    info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
246
247#ifdef R128DRI
248    if (info->directRenderingEnabled) {
249        EmitCCE2DState(pScrn);
250    } else
251#endif
252    {
253        Emit2DState(pScrn);
254    }
255}
256
257static Bool
258R128PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, int alu, Pixel planemask)
259{
260    ScreenPtr     pScreen   = pSrcPixmap->drawable.pScreen;
261    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
262    R128InfoPtr   info      = R128PTR(pScrn);
263
264    int bpp = pDstPixmap->drawable.bitsPerPixel;
265    uint32_t datatype, src_pitch_offset, dst_pitch_offset;
266
267    if (!R128GetDatatypeBpp(bpp, &datatype)) {
268        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
269                            "R128GetDatatypeBpp failed\n"));
270	return FALSE;
271    }
272    if (!R128GetPixmapOffsetPitch(pSrcPixmap, &src_pitch_offset)) {
273        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
274                            "R128GetPixmapOffsetPitch source "
275                            "failed\n"));
276	return FALSE;
277    }
278    if (!R128GetPixmapOffsetPitch(pDstPixmap, &dst_pitch_offset)) {
279        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
280                            "R128GetPixmapOffsetPitch dest failed\n"));
281	return FALSE;
282    }
283    if (info->state_2d.in_use) return FALSE;
284
285    info->xdir = xdir;
286    info->ydir = ydir;
287
288    R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, alu, planemask);
289
290    return TRUE;
291}
292
293static void
294R128Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height)
295{
296    ScreenPtr     pScreen   = pDstPixmap->drawable.pScreen;
297    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
298    R128InfoPtr   info      = R128PTR(pScrn);
299    unsigned char *R128MMIO = info->MMIO;
300
301    if (info->xdir < 0) srcX += width - 1, dstX += width - 1;
302    if (info->ydir < 0) srcY += height - 1, dstY += height - 1;
303
304    R128WaitForFifo(pScrn, 3);
305    OUTREG(R128_SRC_Y_X,          (srcY << 16) | srcX);
306    OUTREG(R128_DST_Y_X,          (dstY << 16) | dstX);
307    OUTREG(R128_DST_HEIGHT_WIDTH, (height << 16) | width);
308    exaMarkSync(pScreen);
309}
310
311#define R128DoneCopy R128Done
312
313static void
314R128Sync(ScreenPtr pScreen, int marker)
315{
316    R128WaitForIdle(xf86ScreenToScrn(pScreen));
317}
318
319void
320R128Done(PixmapPtr pPixmap)
321{
322    ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
323    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
324    R128InfoPtr   info      = R128PTR(pScrn);
325
326    info->state_2d.in_use = FALSE;
327#if defined(R128DRI) && defined(RENDER)
328    if (info->state_2d.src_pix) {
329        pScreen->DestroyPixmap(info->state_2d.src_pix);
330	info->state_2d.src_pix = NULL;
331    }
332    if (info->state_2d.msk_pix) {
333        pScreen->DestroyPixmap(info->state_2d.msk_pix);
334	info->state_2d.msk_pix = NULL;
335    }
336#endif
337}
338
339#ifdef R128DRI
340
341#define R128CCEPrepareSolid R128PrepareSolid
342
343static void
344R128CCESolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
345{
346    ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
347    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
348    R128InfoPtr   info      = R128PTR(pScrn);
349    RING_LOCALS;
350
351    R128CCE_REFRESH( pScrn, info );
352
353    BEGIN_RING( 4 );
354
355    OUT_RING_REG( R128_DST_Y_X,          (y1 << 16) | x1 );
356    OUT_RING_REG( R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1) );
357
358    ADVANCE_RING();
359}
360
361#define R128CCEDoneSolid R128Done
362
363#define R128CCEPrepareCopy R128PrepareCopy
364
365static void
366R128CCECopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
367	 int width, int height)
368{
369    ScreenPtr     pScreen   = pDstPixmap->drawable.pScreen;
370    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
371    R128InfoPtr   info      = R128PTR(pScrn);
372    RING_LOCALS;
373
374    R128CCE_REFRESH( pScrn, info );
375
376    if (info->xdir < 0) srcX += width - 1, dstX += width - 1;
377    if (info->ydir < 0) srcY += height - 1, dstY += height - 1;
378
379    BEGIN_RING( 6 );
380
381    OUT_RING_REG( R128_SRC_Y_X,          (srcY << 16) | srcX );
382    OUT_RING_REG( R128_DST_Y_X,          (dstY << 16) | dstX );
383    OUT_RING_REG( R128_DST_HEIGHT_WIDTH, (height << 16) | width );
384
385    ADVANCE_RING();
386}
387
388#define R128CCEDoneCopy R128Done
389
390static void
391R128CCESync(ScreenPtr pScreen, int marker)
392{
393    R128CCEWaitForIdle(xf86ScreenToScrn(pScreen));
394}
395
396#endif
397
398/*
399 * Memcpy-based UTS.
400 */
401static Bool
402R128UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
403    char *src, int src_pitch)
404{
405    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
406    R128InfoPtr	info      = R128PTR(pScrn);
407    char	*dst        = info->FB + exaGetPixmapOffset(pDst);
408    int		dst_pitch  = exaGetPixmapPitch(pDst);
409    int		bpp    = pDst->drawable.bitsPerPixel;
410    int		cpp    = (bpp + 7) >> 3;
411    int		wBytes = w * cpp;
412
413    dst += (x * cpp) + (y * dst_pitch);
414
415    R128WaitForIdle(pScrn);
416
417    while (h--) {
418	memcpy(dst, src, wBytes);
419	src += src_pitch;
420	dst += dst_pitch;
421    }
422
423    return TRUE;
424}
425
426/*
427 * Hostblit-based UTS.
428 * this assumes 32bit pixels
429 */
430static Bool
431R128UploadToScreenHW(PixmapPtr pDst, int x, int y, int w, int h,
432    char *src, int src_pitch)
433{
434    ScrnInfoPtr	pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
435    R128InfoPtr	info      = R128PTR(pScrn);
436    uint32_t	dst_pitch_offset, datatype;
437    int		cnt, line, px;
438    unsigned char *R128MMIO = info->MMIO;
439    int		bpp = pDst->drawable.bitsPerPixel;
440    uint32_t	*s;
441
442    if (!R128GetDatatypeBpp(bpp, &datatype)) {
443	return FALSE;
444    }
445
446    if (!R128GetPixmapOffsetPitch(pDst, &dst_pitch_offset)) {
447	return FALSE;
448    }
449
450    info->state_2d.in_use = TRUE;
451    info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
452					  R128_GMC_BRUSH_NONE |
453					  (datatype >> 8) |
454					  R128_GMC_SRC_DATATYPE_COLOR |
455					  R128_ROP3_S |
456					  R128_DP_SRC_SOURCE_HOST_DATA |
457					  R128_GMC_CLR_CMP_CNTL_DIS);
458    info->state_2d.dp_cntl = R128_DST_X_LEFT_TO_RIGHT |
459                             R128_DST_Y_TOP_TO_BOTTOM;
460    info->state_2d.dp_write_mask = 0xffffffff;
461    info->state_2d.dst_pitch_offset = dst_pitch_offset;
462    info->state_2d.default_sc_bottom_right = R128_DEFAULT_SC_RIGHT_MAX |
463                                             R128_DEFAULT_SC_BOTTOM_MAX;
464    Emit2DState(pScrn);
465
466    R128WaitForFifo(pScrn, 3);
467    OUTREG(R128_SRC_Y_X, 0);
468    OUTREG(R128_DST_Y_X, (y << 16) | x);
469    OUTREG(R128_DST_HEIGHT_WIDTH, (h << 16) | w);
470
471    R128WaitForFifo(pScrn, 32);
472    cnt = 0;
473
474    for (line = 0; line < h; line++) {
475    	s = (void *)src;
476    	for (px = 0; px < w; px++) {
477    	    OUTREG(R128_HOST_DATA0, cpu_to_le32(*s));
478    	    s++;
479    	    cnt++;
480    	    if (cnt > 31) {
481		R128WaitForFifo(pScrn, 32);
482		cnt = 0;
483	    }
484	}
485	src += src_pitch;
486    }
487    info->state_2d.in_use = FALSE;
488    exaMarkSync(pDst->drawable.pScreen);
489    return TRUE;
490}
491
492/*
493 * Memcpy-based DFS.
494 */
495static Bool
496R128DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
497    char *dst, int dst_pitch)
498{
499    ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
500    R128InfoPtr   info      = R128PTR(pScrn);
501    char  *src        = info->FB + exaGetPixmapOffset(pSrc);
502    int    src_pitch  = exaGetPixmapPitch(pSrc);
503
504    int bpp    = pSrc->drawable.bitsPerPixel;
505    int cpp    = (bpp + 7) >> 3;
506    int wBytes = w * cpp;
507
508    src += (x * cpp) + (y * src_pitch);
509
510    R128WaitForIdle(pScrn);
511
512    while (h--) {
513	memcpy(dst, src, wBytes);
514	src += src_pitch;
515	dst += dst_pitch;
516    }
517
518    return TRUE;
519}
520
521Bool
522R128EXAInit(ScreenPtr pScreen, int total)
523{
524    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
525    R128InfoPtr info  = R128PTR(pScrn);
526
527    info->ExaDriver = exaDriverAlloc();
528    if (!info->ExaDriver) {
529        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
530                    "Could not allocate EXA driver...\n");
531        return FALSE;
532    }
533
534    info->ExaDriver->exa_major = EXA_VERSION_MAJOR;
535    info->ExaDriver->exa_minor = EXA_VERSION_MINOR;
536
537    info->ExaDriver->memoryBase = info->FB + pScrn->fbOffset;
538    info->ExaDriver->offScreenBase = pScrn->virtualY *
539                                        (pScrn->displayWidth *
540                                        info->CurrentLayout.pixel_bytes);
541    info->ExaDriver->memorySize = total;
542    info->ExaDriver->flags = EXA_OFFSCREEN_PIXMAPS;
543
544#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3)
545    info->ExaDriver->maxPitchBytes = 16320;
546#endif
547    /* Pitch alignment is in sets of 8 pixels, and we need to cover 32bpp, so it's 32 bytes */
548    info->ExaDriver->pixmapPitchAlign = 32;
549    info->ExaDriver->pixmapOffsetAlign = 32;
550    info->ExaDriver->maxX = 2048;
551    info->ExaDriver->maxY = 2048;
552
553    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
554	       "Setting up EXA callbacks\n");
555
556#ifdef R128DRI
557    if (info->directRenderingEnabled) {
558	info->ExaDriver->PrepareSolid = R128CCEPrepareSolid;
559	info->ExaDriver->Solid = R128CCESolid;
560	info->ExaDriver->DoneSolid = R128CCEDoneSolid;
561
562	info->ExaDriver->PrepareCopy = R128CCEPrepareCopy;
563	info->ExaDriver->Copy = R128CCECopy;
564	info->ExaDriver->DoneCopy = R128CCEDoneCopy;
565
566#ifdef RENDER
567	if (info->RenderAccel) {
568	    info->ExaDriver->flags |= EXA_OFFSCREEN_ALIGN_POT;
569	    info->ExaDriver->CheckComposite = R128CCECheckComposite;
570	    info->ExaDriver->PrepareComposite = R128CCEPrepareComposite;
571	    info->ExaDriver->Composite = R128CCEComposite;
572	    info->ExaDriver->DoneComposite = R128CCEDoneComposite;
573	}
574#endif
575
576	info->ExaDriver->WaitMarker = R128CCESync;
577    } else
578#endif
579    {
580	info->ExaDriver->PrepareSolid = R128PrepareSolid;
581	info->ExaDriver->Solid = R128Solid;
582	info->ExaDriver->DoneSolid = R128DoneSolid;
583
584	info->ExaDriver->PrepareCopy = R128PrepareCopy;
585	info->ExaDriver->Copy = R128Copy;
586	info->ExaDriver->DoneCopy = R128DoneCopy;
587
588	if (pScrn->bitsPerPixel < 24) {
589	    info->ExaDriver->UploadToScreen = R128UploadToScreen;
590	} else {
591	    info->ExaDriver->UploadToScreen = R128UploadToScreenHW;
592	}
593	info->ExaDriver->DownloadFromScreen = R128DownloadFromScreen;
594
595	/* The registers used for r128 compositing are CCE specific, just like the
596	 * registers used for radeon compositing are CP specific. The radeon driver
597	 * falls back to different registers when there is no DRI. The equivalent
598	 * registers on the r128 (if they even exist) are not listed in the register
599	 * file so I can't implement compositing without DRI.
600	 */
601
602	info->ExaDriver->WaitMarker = R128Sync;
603    }
604
605    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
606	       "Initializing 2D acceleration engine...\n");
607
608    R128EngineInit(pScrn);
609
610    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
611	       "Initializing EXA driver...\n");
612
613    if (!exaDriverInit(pScreen, info->ExaDriver)) {
614        free(info->ExaDriver);
615	return FALSE;
616    }
617
618    info->state_2d.composite_setup = FALSE;
619    return TRUE;
620}
621