radeon_exa_funcs.c revision b7e1c893
1/*
2 * Copyright 2005 Eric Anholt
3 * Copyright 2005 Benjamin Herrenschmidt
4 * Copyright 2006 Tungsten Graphics, Inc.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 *
26 * Authors:
27 *    Eric Anholt <anholt@FreeBSD.org>
28 *    Zack Rusin <zrusin@trolltech.com>
29 *    Benjamin Herrenschmidt <benh@kernel.crashing.org>
30 *    Michel Dänzer <michel@tungstengraphics.com>
31 *
32 */
33
34#if defined(ACCEL_MMIO) && defined(ACCEL_CP)
35#error Cannot define both MMIO and CP acceleration!
36#endif
37
38#if !defined(UNIXCPP) || defined(ANSICPP)
39#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix
40#else
41#define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix
42#endif
43
44#ifdef ACCEL_MMIO
45#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO)
46#else
47#ifdef ACCEL_CP
48#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP)
49#else
50#error No accel type defined!
51#endif
52#endif
53
54#include <errno.h>
55#include <string.h>
56
57#include "radeon.h"
58
59#include "exa.h"
60
61static int
62FUNC_NAME(RADEONMarkSync)(ScreenPtr pScreen)
63{
64    RINFO_FROM_SCREEN(pScreen);
65
66    TRACE;
67
68    return ++info->accel_state->exaSyncMarker;
69}
70
71static void
72FUNC_NAME(RADEONSync)(ScreenPtr pScreen, int marker)
73{
74    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
75    RADEONInfoPtr info = RADEONPTR(pScrn);
76
77    TRACE;
78
79    if (info->accel_state->exaMarkerSynced != marker) {
80	FUNC_NAME(RADEONWaitForIdle)(pScrn);
81	info->accel_state->exaMarkerSynced = marker;
82    }
83
84    RADEONPTR(pScrn)->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
85}
86
87static Bool
88FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
89{
90    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
91    uint32_t datatype, dst_pitch_offset;
92    ACCEL_PREAMBLE();
93
94    TRACE;
95
96    if (pPix->drawable.bitsPerPixel == 24)
97	RADEON_FALLBACK(("24bpp unsupported\n"));
98    if (!RADEONGetDatatypeBpp(pPix->drawable.bitsPerPixel, &datatype))
99	RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n"));
100    if (!RADEONGetPixmapOffsetPitch(pPix, &dst_pitch_offset))
101	RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch failed\n"));
102
103    RADEON_SWITCH_TO_2D();
104
105    BEGIN_ACCEL(5);
106    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL,
107	    RADEON_GMC_DST_PITCH_OFFSET_CNTL |
108	    RADEON_GMC_BRUSH_SOLID_COLOR |
109	    (datatype << 8) |
110	    RADEON_GMC_SRC_DATATYPE_COLOR |
111	    RADEON_ROP[alu].pattern |
112	    RADEON_GMC_CLR_CMP_CNTL_DIS);
113    OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg);
114    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, pm);
115    OUT_ACCEL_REG(RADEON_DP_CNTL,
116	(RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM));
117    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset);
118    FINISH_ACCEL();
119
120    return TRUE;
121}
122
123
124static void
125FUNC_NAME(RADEONSolid)(PixmapPtr pPix, int x1, int y1, int x2, int y2)
126{
127    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
128    ACCEL_PREAMBLE();
129
130    TRACE;
131
132    if (info->accel_state->vsync)
133	FUNC_NAME(RADEONWaitForVLine)(pScrn, pPix, RADEONBiggerCrtcArea(pPix), y1, y2);
134
135    BEGIN_ACCEL(2);
136    OUT_ACCEL_REG(RADEON_DST_Y_X, (y1 << 16) | x1);
137    OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, ((y2 - y1) << 16) | (x2 - x1));
138    FINISH_ACCEL();
139}
140
141static void
142FUNC_NAME(RADEONDoneSolid)(PixmapPtr pPix)
143{
144    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
145    ACCEL_PREAMBLE();
146
147    TRACE;
148
149    BEGIN_ACCEL(2);
150    OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
151    OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
152                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
153    FINISH_ACCEL();
154}
155
156void
157FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, uint32_t src_pitch_offset,
158			       uint32_t dst_pitch_offset, uint32_t datatype, int rop,
159			       Pixel planemask)
160{
161    RADEONInfoPtr info = RADEONPTR(pScrn);
162    ACCEL_PREAMBLE();
163
164    RADEON_SWITCH_TO_2D();
165
166    BEGIN_ACCEL(5);
167    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL,
168	RADEON_GMC_DST_PITCH_OFFSET_CNTL |
169	RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
170	RADEON_GMC_BRUSH_NONE |
171	(datatype << 8) |
172	RADEON_GMC_SRC_DATATYPE_COLOR |
173	RADEON_ROP[rop].rop |
174	RADEON_DP_SRC_SOURCE_MEMORY |
175	RADEON_GMC_CLR_CMP_CNTL_DIS);
176    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
177    OUT_ACCEL_REG(RADEON_DP_CNTL,
178	((info->accel_state->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) |
179	 (info->accel_state->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)));
180    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset);
181    OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset);
182    FINISH_ACCEL();
183}
184
185static Bool
186FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc,   PixmapPtr pDst,
187			     int xdir, int ydir,
188			     int rop,
189			     Pixel planemask)
190{
191    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
192    uint32_t datatype, src_pitch_offset, dst_pitch_offset;
193
194    TRACE;
195
196    info->accel_state->xdir = xdir;
197    info->accel_state->ydir = ydir;
198
199    if (pDst->drawable.bitsPerPixel == 24)
200	RADEON_FALLBACK(("24bpp unsupported"));
201    if (!RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype))
202	RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n"));
203    if (!RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset))
204	RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n"));
205    if (!RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset))
206	RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n"));
207
208    FUNC_NAME(RADEONDoPrepareCopy)(pScrn, src_pitch_offset, dst_pitch_offset,
209				   datatype, rop, planemask);
210
211    return TRUE;
212}
213
214void
215FUNC_NAME(RADEONCopy)(PixmapPtr pDst,
216		      int srcX, int srcY,
217		      int dstX, int dstY,
218		      int w, int h)
219{
220    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
221    ACCEL_PREAMBLE();
222
223    TRACE;
224
225    if (info->accel_state->xdir < 0) {
226	srcX += w - 1;
227	dstX += w - 1;
228    }
229    if (info->accel_state->ydir < 0) {
230	srcY += h - 1;
231	dstY += h - 1;
232    }
233
234    if (info->accel_state->vsync)
235	FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst), dstY, dstY + h);
236
237    BEGIN_ACCEL(3);
238
239    OUT_ACCEL_REG(RADEON_SRC_Y_X,	   (srcY << 16) | srcX);
240    OUT_ACCEL_REG(RADEON_DST_Y_X,	   (dstY << 16) | dstX);
241    OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h  << 16) | w);
242
243    FINISH_ACCEL();
244}
245
246static void
247FUNC_NAME(RADEONDoneCopy)(PixmapPtr pDst)
248{
249    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
250    ACCEL_PREAMBLE();
251
252    TRACE;
253
254    BEGIN_ACCEL(2);
255    OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
256    OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
257                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
258    FINISH_ACCEL();
259}
260
261
262#ifdef ACCEL_CP
263
264static Bool
265RADEONUploadToScreenCP(PixmapPtr pDst, int x, int y, int w, int h,
266		       char *src, int src_pitch)
267{
268    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
269    unsigned int   bpp	     = pDst->drawable.bitsPerPixel;
270    unsigned int   hpass;
271    uint32_t	   buf_pitch, dst_pitch_off;
272
273    TRACE;
274
275    if (bpp < 8)
276	return FALSE;
277
278    if (info->directRenderingEnabled &&
279	RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_off)) {
280	uint8_t *buf;
281	int cpp = bpp / 8;
282	ACCEL_PREAMBLE();
283
284	RADEON_SWITCH_TO_2D();
285
286	if (info->accel_state->vsync)
287	    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst), y, y + h);
288
289	while ((buf = RADEONHostDataBlit(pScrn,
290					 cpp, w, dst_pitch_off, &buf_pitch,
291					 x, &y, (unsigned int*)&h, &hpass)) != 0) {
292	    RADEONHostDataBlitCopyPass(pScrn, cpp, buf, (uint8_t *)src,
293				       hpass, buf_pitch, src_pitch);
294	    src += hpass * src_pitch;
295	}
296
297	exaMarkSync(pDst->drawable.pScreen);
298	return TRUE;
299    }
300
301    return FALSE;
302}
303
304/* Emit blit with arbitrary source and destination offsets and pitches */
305static void
306RADEONBlitChunk(ScrnInfoPtr pScrn, uint32_t datatype, uint32_t src_pitch_offset,
307		uint32_t dst_pitch_offset, int srcX, int srcY, int dstX, int dstY,
308		int w, int h)
309{
310    RADEONInfoPtr info = RADEONPTR(pScrn);
311    ACCEL_PREAMBLE();
312
313    BEGIN_ACCEL(6);
314    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL,
315		  RADEON_GMC_DST_PITCH_OFFSET_CNTL |
316		  RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
317		  RADEON_GMC_BRUSH_NONE |
318		  (datatype << 8) |
319		  RADEON_GMC_SRC_DATATYPE_COLOR |
320		  RADEON_ROP3_S |
321		  RADEON_DP_SRC_SOURCE_MEMORY |
322		  RADEON_GMC_CLR_CMP_CNTL_DIS |
323		  RADEON_GMC_WR_MSK_DIS);
324    OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset);
325    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset);
326    OUT_ACCEL_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX);
327    OUT_ACCEL_REG(RADEON_DST_Y_X, (dstY << 16) | dstX);
328    OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
329    FINISH_ACCEL();
330    BEGIN_ACCEL(2);
331    OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
332    OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
333                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
334    FINISH_ACCEL();
335}
336
337
338static Bool
339RADEONDownloadFromScreenCP(PixmapPtr pSrc, int x, int y, int w, int h,
340				    char *dst, int dst_pitch)
341{
342    RINFO_FROM_SCREEN(pSrc->drawable.pScreen);
343    uint8_t	  *src	     = info->FB + exaGetPixmapOffset(pSrc);
344    int		   bpp	     = pSrc->drawable.bitsPerPixel;
345    uint32_t datatype, src_pitch_offset, scratch_pitch = (w * bpp/8 + 63) & ~63, scratch_off = 0;
346    drmBufPtr scratch;
347
348    TRACE;
349
350    /*
351     * Try to accelerate download. Use an indirect buffer as scratch space,
352     * blitting the bits to one half while copying them out of the other one and
353     * then swapping the halves.
354     */
355    if (bpp != 24 && RADEONGetDatatypeBpp(bpp, &datatype) &&
356	RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset) &&
357	(scratch = RADEONCPGetBuffer(pScrn)))
358    {
359	int swap = RADEON_HOST_DATA_SWAP_NONE, wpass = w * bpp / 8;
360	int hpass = min(h, scratch->total/2 / scratch_pitch);
361	uint32_t scratch_pitch_offset = scratch_pitch << 16
362				    | (info->gartLocation + info->dri->bufStart
363				       + scratch->idx * scratch->total) >> 10;
364	drm_radeon_indirect_t indirect;
365	ACCEL_PREAMBLE();
366
367	RADEON_SWITCH_TO_2D();
368
369	/* Kick the first blit as early as possible */
370	RADEONBlitChunk(pScrn, datatype, src_pitch_offset, scratch_pitch_offset,
371			x, y, 0, 0, w, hpass);
372	FLUSH_RING();
373
374#if X_BYTE_ORDER == X_BIG_ENDIAN
375	switch (bpp) {
376	case 16:
377	  swap = RADEON_HOST_DATA_SWAP_16BIT;
378	  break;
379	case 32:
380	  swap = RADEON_HOST_DATA_SWAP_32BIT;
381	  break;
382	}
383#endif
384
385	while (h) {
386	    int oldhpass = hpass, i = 0;
387
388	    src = (uint8_t*)scratch->address + scratch_off;
389
390	    y += oldhpass;
391	    h -= oldhpass;
392	    hpass = min(h, scratch->total/2 / scratch_pitch);
393
394	    /* Prepare next blit if anything's left */
395	    if (hpass) {
396		scratch_off = scratch->total/2 - scratch_off;
397		RADEONBlitChunk(pScrn, datatype, src_pitch_offset, scratch_pitch_offset + (scratch_off >> 10),
398				x, y, 0, 0, w, hpass);
399	    }
400
401	    /*
402	     * Wait for previous blit to complete.
403	     *
404	     * XXX: Doing here essentially the same things this ioctl does in
405	     * the DRM results in corruption with 'small' transfers, apparently
406	     * because the data doesn't actually land in system RAM before the
407	     * memcpy. I suspect the ioctl helps mostly due to its latency; what
408	     * we'd really need is a way to reliably wait for the host interface
409	     * to be done with pushing the data to the host.
410	     */
411	    while ((drmCommandNone(info->dri->drmFD, DRM_RADEON_CP_IDLE) == -EBUSY)
412		   && (i++ < RADEON_TIMEOUT))
413		;
414
415	    /* Kick next blit */
416	    if (hpass)
417		FLUSH_RING();
418
419	    /* Copy out data from previous blit */
420	    if (wpass == scratch_pitch && wpass == dst_pitch) {
421		RADEONCopySwap((uint8_t*)dst, src, wpass * oldhpass, swap);
422		dst += dst_pitch * oldhpass;
423	    } else while (oldhpass--) {
424		RADEONCopySwap((uint8_t*)dst, src, wpass, swap);
425		src += scratch_pitch;
426		dst += dst_pitch;
427	    }
428	}
429
430	indirect.idx = scratch->idx;
431	indirect.start = indirect.end = 0;
432	indirect.discard = 1;
433
434	drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INDIRECT,
435			    &indirect, sizeof(drm_radeon_indirect_t));
436
437	info->accel_state->exaMarkerSynced = info->accel_state->exaSyncMarker;
438
439	return TRUE;
440    }
441
442    return FALSE;
443}
444
445#endif	/* def ACCEL_CP */
446
447
448Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
449{
450    RINFO_FROM_SCREEN(pScreen);
451
452    if (info->accel_state->exa == NULL) {
453	xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map not set up\n");
454	return FALSE;
455    }
456
457    info->accel_state->exa->exa_major = EXA_VERSION_MAJOR;
458    info->accel_state->exa->exa_minor = EXA_VERSION_MINOR;
459
460    info->accel_state->exa->PrepareSolid = FUNC_NAME(RADEONPrepareSolid);
461    info->accel_state->exa->Solid = FUNC_NAME(RADEONSolid);
462    info->accel_state->exa->DoneSolid = FUNC_NAME(RADEONDoneSolid);
463
464    info->accel_state->exa->PrepareCopy = FUNC_NAME(RADEONPrepareCopy);
465    info->accel_state->exa->Copy = FUNC_NAME(RADEONCopy);
466    info->accel_state->exa->DoneCopy = FUNC_NAME(RADEONDoneCopy);
467
468    info->accel_state->exa->MarkSync = FUNC_NAME(RADEONMarkSync);
469    info->accel_state->exa->WaitMarker = FUNC_NAME(RADEONSync);
470#ifdef ACCEL_CP
471    info->accel_state->exa->UploadToScreen = RADEONUploadToScreenCP;
472    if (info->accelDFS)
473	info->accel_state->exa->DownloadFromScreen = RADEONDownloadFromScreenCP;
474#endif
475
476#if X_BYTE_ORDER == X_BIG_ENDIAN
477    info->accel_state->exa->PrepareAccess = RADEONPrepareAccess;
478    info->accel_state->exa->FinishAccess = RADEONFinishAccess;
479#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
480
481    info->accel_state->exa->flags = EXA_OFFSCREEN_PIXMAPS;
482#ifdef EXA_SUPPORTS_PREPARE_AUX
483    info->accel_state->exa->flags |= EXA_SUPPORTS_PREPARE_AUX;
484#endif
485    info->accel_state->exa->pixmapOffsetAlign = RADEON_BUFFER_ALIGN + 1;
486    info->accel_state->exa->pixmapPitchAlign = 64;
487
488#ifdef RENDER
489    if (info->RenderAccel) {
490	if (info->ChipFamily >= CHIP_FAMILY_R600)
491		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration "
492			       "unsupported on R600 and newer cards.\n");
493	else if (IS_R300_3D || IS_R500_3D) {
494	    if ((info->ChipFamily < CHIP_FAMILY_RS400)
495#ifdef XF86DRI
496		|| (info->directRenderingEnabled)
497#endif
498		) {
499		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration "
500			       "enabled for R300/R400/R500 type cards.\n");
501		info->accel_state->exa->CheckComposite = R300CheckComposite;
502		info->accel_state->exa->PrepareComposite =
503		    FUNC_NAME(R300PrepareComposite);
504		info->accel_state->exa->Composite = FUNC_NAME(RadeonComposite);
505		info->accel_state->exa->DoneComposite = FUNC_NAME(RadeonDoneComposite);
506	    } else
507		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA Composite requires CP on R5xx/IGP\n");
508	} else if ((info->ChipFamily == CHIP_FAMILY_RV250) ||
509		   (info->ChipFamily == CHIP_FAMILY_RV280) ||
510		   (info->ChipFamily == CHIP_FAMILY_RS300) ||
511		   (info->ChipFamily == CHIP_FAMILY_R200)) {
512		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration "
513			       "enabled for R200 type cards.\n");
514		info->accel_state->exa->CheckComposite = R200CheckComposite;
515		info->accel_state->exa->PrepareComposite =
516		    FUNC_NAME(R200PrepareComposite);
517		info->accel_state->exa->Composite = FUNC_NAME(RadeonComposite);
518		info->accel_state->exa->DoneComposite = FUNC_NAME(RadeonDoneComposite);
519	} else {
520		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration "
521			       "enabled for R100 type cards.\n");
522		info->accel_state->exa->CheckComposite = R100CheckComposite;
523		info->accel_state->exa->PrepareComposite =
524		    FUNC_NAME(R100PrepareComposite);
525		info->accel_state->exa->Composite = FUNC_NAME(RadeonComposite);
526		info->accel_state->exa->DoneComposite = FUNC_NAME(RadeonDoneComposite);
527	}
528    }
529#endif
530
531#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3)
532    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting EXA maxPitchBytes\n");
533
534    info->accel_state->exa->maxPitchBytes = 16320;
535    info->accel_state->exa->maxX = 8192;
536#else
537    info->accel_state->exa->maxX = 16320 / 4;
538#endif
539    info->accel_state->exa->maxY = 8192;
540
541    if (xf86ReturnOptValBool(info->Options, OPTION_EXA_VSYNC, FALSE)) {
542	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA VSync enabled\n");
543	info->accel_state->vsync = TRUE;
544    } else
545	info->accel_state->vsync = FALSE;
546
547    RADEONEngineInit(pScrn);
548
549    if (!exaDriverInit(pScreen, info->accel_state->exa)) {
550	xfree(info->accel_state->exa);
551	return FALSE;
552    }
553    exaMarkSync(pScreen);
554
555    return TRUE;
556}
557
558#undef FUNC_NAME
559