1 /*
2  * Copyright 2003 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of Marc Aurele La France not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  Marc Aurele La France makes no representations
11  * about the suitability of this software for any purpose.  It is provided
12  * "as-is" without express or implied warranty.
13  *
14  * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
16  * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  */
22 /*
23  * Copyright 1999-2000 Precision Insight, Inc., Cedar Park, Texas.
24  * All Rights Reserved.
25  *
26  * Permission is hereby granted, free of charge, to any person obtaining a copy
27  * of this software and associated documentation files (the "Software"), to
28  * deal in the Software without restriction, including without limitation the
29  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
30  * sell copies of the Software, and to permit persons to whom the Software is
31  * furnished to do so, subject to the following conditions:
32  *
33  * The above copyright notice and this permission notice (including the next
34  * paragraph) shall be included in all copies or substantial portions of the
35  * Software.
36  *
37  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
39  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
40  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
41  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
42  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
43  * DEALINGS IN THE SOFTWARE.
44  */
45 /*
46  * DRI support by:
47  *    Manuel Teira
48  *    Leif Delgass <ldelgass@retinalburn.net>
49  *
50  * EXA support by:
51  *    Jakub Stachowski <qbast@go2.pl>
52  *    George Sapountzis <gsap7@yahoo.gr>
53  */
54 
55 #ifdef HAVE_CONFIG_H
56 #include "config.h"
57 #endif
58 
59 #include <string.h>
60 
61 #include "ati.h"
62 #include "atichip.h"
63 #include "atidri.h"
64 #include "atimach64accel.h"
65 #include "atimach64io.h"
66 #include "atipriv.h"
67 #include "atiregs.h"
68 
69 #ifdef XF86DRI_DEVEL
70 #include "mach64_dri.h"
71 #include "mach64_sarea.h"
72 #endif
73 
74 #ifdef USE_EXA
75 extern CARD8 ATIMach64ALU[];
76 
77 extern void
78 ATIMach64ValidateClip
79 (
80     ATIPtr pATI,
81     int sc_left,
82     int sc_right,
83     int sc_top,
84     int sc_bottom
85 );
86 
87 #if 0
88 #define MACH64_TRACE(x)				\
89 do {						\
90     ErrorF("Mach64(%s): ", __FUNCTION__);	\
91     ErrorF x;					\
92 } while(0)
93 #else
94 #define MACH64_TRACE(x) do { } while(0)
95 #endif
96 
97 #if 0
98 #define MACH64_FALLBACK(x)			\
99 do {						\
100     ErrorF("Fallback(%s): ", __FUNCTION__);	\
101     ErrorF x;					\
102     return FALSE;				\
103 } while (0)
104 #else
105 #define MACH64_FALLBACK(x) return FALSE
106 #endif
107 
108 static void
Mach64WaitMarker(ScreenPtr pScreenInfo,int Marker)109 Mach64WaitMarker(ScreenPtr pScreenInfo, int Marker)
110 {
111     ATIMach64Sync(xf86ScreenToScrn(pScreenInfo));
112 }
113 
114 static Bool
Mach64GetDatatypeBpp(PixmapPtr pPix,CARD32 * pix_width)115 Mach64GetDatatypeBpp(PixmapPtr pPix, CARD32 *pix_width)
116 {
117 	int bpp = pPix->drawable.bitsPerPixel;
118 
119 	switch (bpp) {
120 	case 8:
121 		*pix_width =
122 			SetBits(PIX_WIDTH_8BPP, DP_DST_PIX_WIDTH) |
123 			SetBits(PIX_WIDTH_8BPP, DP_SRC_PIX_WIDTH) |
124 			SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
125 		break;
126 	case 16:
127 		*pix_width =
128 			SetBits(PIX_WIDTH_16BPP, DP_DST_PIX_WIDTH) |
129 			SetBits(PIX_WIDTH_16BPP, DP_SRC_PIX_WIDTH) |
130 			SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
131 		break;
132 	case 24:
133 		*pix_width =
134 			SetBits(PIX_WIDTH_8BPP, DP_DST_PIX_WIDTH) |
135 			SetBits(PIX_WIDTH_8BPP, DP_SRC_PIX_WIDTH) |
136 			SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
137 		break;
138 	case 32:
139 		*pix_width =
140 			SetBits(PIX_WIDTH_32BPP, DP_DST_PIX_WIDTH) |
141 			SetBits(PIX_WIDTH_32BPP, DP_SRC_PIX_WIDTH) |
142 			SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
143 		break;
144 	default:
145 		MACH64_FALLBACK(("Unsupported bpp: %d\n", bpp));
146 	}
147 
148 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
149 
150         *pix_width |= DP_BYTE_PIX_ORDER;
151 
152 #endif /* X_BYTE_ORDER */
153 
154 	return TRUE;
155 }
156 
157 static Bool
Mach64GetOffsetPitch(PixmapPtr pPix,int bpp,CARD32 * pitch_offset,unsigned int offset,unsigned int pitch)158 Mach64GetOffsetPitch(PixmapPtr pPix, int bpp, CARD32 *pitch_offset,
159 		     unsigned int offset, unsigned int pitch)
160 {
161 #if 0
162     ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pPix->drawable.pScreen);
163     ATIPtr pATI = ATIPTR(pScreenInfo);
164 
165     if (pitch % pATI->pExa->pixmapPitchAlign != 0)
166         MACH64_FALLBACK(("Bad pitch 0x%08x\n", pitch));
167 
168     if (offset % pATI->pExa->pixmapOffsetAlign != 0)
169         MACH64_FALLBACK(("Bad offset 0x%08x\n", offset));
170 #endif
171 
172     /* pixels / 8 = ((bytes * 8) / bpp) / 8 = bytes / bpp */
173     pitch = pitch / bpp;
174 
175     /* bytes / 8 */
176     offset = offset >> 3;
177 
178     *pitch_offset = ((pitch  << 22) | (offset <<  0));
179 
180     return TRUE;
181 }
182 
183 static Bool
Mach64GetPixmapOffsetPitch(PixmapPtr pPix,CARD32 * pitch_offset)184 Mach64GetPixmapOffsetPitch(PixmapPtr pPix, CARD32 *pitch_offset)
185 {
186     CARD32 pitch, offset;
187     int bpp;
188 
189     bpp = pPix->drawable.bitsPerPixel;
190     if (bpp == 24)
191         bpp = 8;
192 
193     pitch = exaGetPixmapPitch(pPix);
194     offset = exaGetPixmapOffset(pPix);
195 
196     return Mach64GetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
197 }
198 
199 static Bool
Mach64PrepareCopy(PixmapPtr pSrcPixmap,PixmapPtr pDstPixmap,int xdir,int ydir,int alu,Pixel planemask)200 Mach64PrepareCopy
201 (
202     PixmapPtr pSrcPixmap,
203     PixmapPtr pDstPixmap,
204     int       xdir,
205     int       ydir,
206     int       alu,
207     Pixel     planemask
208 )
209 {
210     ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
211     ATIPtr pATI = ATIPTR(pScreenInfo);
212     CARD32 src_pitch_offset, dst_pitch_offset, dp_pix_width;
213 
214     ATIDRISync(pScreenInfo);
215 
216     if (!Mach64GetDatatypeBpp(pDstPixmap, &dp_pix_width))
217         return FALSE;
218     if (!Mach64GetPixmapOffsetPitch(pSrcPixmap, &src_pitch_offset))
219         return FALSE;
220     if (!Mach64GetPixmapOffsetPitch(pDstPixmap, &dst_pitch_offset))
221         return FALSE;
222 
223     ATIMach64WaitForFIFO(pATI, 7);
224     outf(DP_WRITE_MASK, planemask);
225     outf(DP_PIX_WIDTH, dp_pix_width);
226     outf(SRC_OFF_PITCH, src_pitch_offset);
227     outf(DST_OFF_PITCH, dst_pitch_offset);
228 
229     outf(DP_SRC, DP_MONO_SRC_ALLONES |
230         SetBits(SRC_BLIT, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
231     outf(DP_MIX, SetBits(ATIMach64ALU[alu], DP_FRGD_MIX));
232 
233     outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
234 
235     pATI->dst_cntl = 0;
236 
237     if (ydir > 0)
238         pATI->dst_cntl |= DST_Y_DIR;
239     if (xdir > 0)
240         pATI->dst_cntl |= DST_X_DIR;
241 
242     if (pATI->XModifier == 1)
243         outf(DST_CNTL, pATI->dst_cntl);
244     else
245         pATI->dst_cntl |= DST_24_ROT_EN;
246 
247     return TRUE;
248 }
249 
250 static void
Mach64Copy(PixmapPtr pDstPixmap,int srcX,int srcY,int dstX,int dstY,int w,int h)251 Mach64Copy
252 (
253     PixmapPtr pDstPixmap,
254     int       srcX,
255     int       srcY,
256     int       dstX,
257     int       dstY,
258     int       w,
259     int       h
260 )
261 {
262     ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
263     ATIPtr pATI = ATIPTR(pScreenInfo);
264 
265     srcX *= pATI->XModifier;
266     dstY *= pATI->XModifier;
267     w    *= pATI->XModifier;
268 
269     ATIDRISync(pScreenInfo);
270 
271     /* Disable clipping if it gets in the way */
272     ATIMach64ValidateClip(pATI, dstX, dstX + w - 1, dstY, dstY + h - 1);
273 
274     if (!(pATI->dst_cntl & DST_X_DIR))
275     {
276         srcX += w - 1;
277         dstX += w - 1;
278     }
279 
280     if (!(pATI->dst_cntl & DST_Y_DIR))
281     {
282         srcY += h - 1;
283         dstY += h - 1;
284     }
285 
286     if (pATI->XModifier != 1)
287         outf(DST_CNTL, pATI->dst_cntl | SetBits((dstX / 4) % 6, DST_24_ROT));
288 
289     ATIMach64WaitForFIFO(pATI, 4);
290     outf(SRC_Y_X, SetWord(srcX, 1) | SetWord(srcY, 0));
291     outf(SRC_WIDTH1, w);
292     outf(DST_Y_X, SetWord(dstX, 1) | SetWord(dstY, 0));
293     outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0));
294 
295     /*
296      * On VTB's and later, the engine will randomly not wait for a copy
297      * operation to commit its results to video memory before starting the next
298      * one.  The probability of such occurrences increases with GUI_WB_FLUSH
299      * (or GUI_WB_FLUSH_P) setting, bitsPerPixel and/or CRTC clock.  This
300      * would point to some kind of video memory bandwidth problem were it noti
301      * for the fact that the problem occurs less often (but still occurs) when
302      * copying larger rectangles.
303      */
304     if ((pATI->Chip >= ATI_CHIP_264VTB) && !pATI->OptionDevel)
305     {
306         exaMarkSync(pScreenInfo->pScreen); /* Force sync. */
307         exaWaitSync(pScreenInfo->pScreen); /* Sync and notify EXA. */
308     }
309 }
310 
Mach64DoneCopy(PixmapPtr pDstPixmap)311 static void Mach64DoneCopy(PixmapPtr pDstPixmap) { }
312 
313 static Bool
Mach64PrepareSolid(PixmapPtr pPixmap,int alu,Pixel planemask,Pixel fg)314 Mach64PrepareSolid
315 (
316     PixmapPtr pPixmap,
317     int       alu,
318     Pixel     planemask,
319     Pixel     fg
320 )
321 {
322     ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pPixmap->drawable.pScreen);
323     ATIPtr pATI = ATIPTR(pScreenInfo);
324     CARD32 dst_pitch_offset, dp_pix_width;
325 
326     ATIDRISync(pScreenInfo);
327 
328     if (!Mach64GetDatatypeBpp(pPixmap, &dp_pix_width))
329         return FALSE;
330     if (!Mach64GetPixmapOffsetPitch(pPixmap, &dst_pitch_offset))
331         return FALSE;
332 
333     ATIMach64WaitForFIFO(pATI, 7);
334     outf(DP_WRITE_MASK, planemask);
335     outf(DP_PIX_WIDTH, dp_pix_width);
336     outf(DST_OFF_PITCH, dst_pitch_offset);
337 
338     outf(DP_SRC, DP_MONO_SRC_ALLONES |
339         SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
340     outf(DP_FRGD_CLR, fg);
341     outf(DP_MIX, SetBits(ATIMach64ALU[alu], DP_FRGD_MIX));
342 
343     outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
344 
345     if (pATI->XModifier == 1)
346         outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
347 
348     return TRUE;
349 }
350 
351 static void
Mach64Solid(PixmapPtr pPixmap,int x1,int y1,int x2,int y2)352 Mach64Solid
353 (
354     PixmapPtr pPixmap,
355     int       x1,
356     int       y1,
357     int       x2,
358     int       y2
359 )
360 {
361     ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pPixmap->drawable.pScreen);
362     ATIPtr pATI = ATIPTR(pScreenInfo);
363 
364     int x = x1;
365     int y = y1;
366     int w = x2-x1;
367     int h = y2-y1;
368 
369     ATIDRISync(pScreenInfo);
370 
371     if (pATI->XModifier != 1)
372     {
373         x *= pATI->XModifier;
374         w *= pATI->XModifier;
375 
376         outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) |
377             (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN));
378     }
379 
380     /* Disable clipping if it gets in the way */
381     ATIMach64ValidateClip(pATI, x, x + w - 1, y, y + h - 1);
382 
383     ATIMach64WaitForFIFO(pATI, 2);
384     outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
385     outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0));
386 }
387 
Mach64DoneSolid(PixmapPtr pPixmap)388 static void Mach64DoneSolid(PixmapPtr pPixmap) { }
389 
390 #include "atimach64render.c"
391 
392 /* Compute log base 2 of val. */
Mach64Log2(int val)393 static __inline__ int Mach64Log2(int val)
394 {
395     int bits;
396 
397     for (bits = 0; val != 0; val >>= 1, ++bits)
398         ;
399     return bits - 1;
400 }
401 
402 /*
403  * Memory layour for EXA with DRI (no local_textures):
404  * | front  | back   | depth  | textures | pixmaps, xv | c |
405  *
406  * 1024x768@16bpp with 8 MB:
407  * | 1.5 MB | 1.5 MB | 1.5 MB | 0        | ~3.5 MB     | c |
408  *
409  * 1024x768@32bpp with 8 MB:
410  * | 3.0 MB | 3.0 MB | 1.5 MB | 0        | ~0.5 MB     | c |
411  *
412  * "c" is the hw cursor which occupies 1KB
413  */
414 static void
Mach64SetupMemEXA(ScreenPtr pScreen)415 Mach64SetupMemEXA(ScreenPtr pScreen)
416 {
417     ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
418     ATIPtr pATI = ATIPTR(pScreenInfo);
419 
420     int cpp = (pScreenInfo->bitsPerPixel + 7) / 8;
421     /* front and back buffer */
422     int bufferSize = pScreenInfo->virtualY * pScreenInfo->displayWidth * cpp;
423     /* always 16-bit z-buffer */
424     int depthSize  = pScreenInfo->virtualY * pScreenInfo->displayWidth * 2;
425 
426     ExaDriverPtr pExa = pATI->pExa;
427 
428     pExa->memoryBase = pATI->pMemory;
429     pExa->memorySize = pScreenInfo->videoRam * 1024;
430     pExa->offScreenBase = bufferSize;
431 
432 #ifdef XF86DRI_DEVEL
433     if (pATI->directRenderingEnabled)
434     {
435 	ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
436 	Bool is_pci = pATIDRIServer->IsPCI;
437 
438 	int textureSize = 0;
439 	int pixmapCache = 0;
440 	int next = 0;
441 
442 	/* front buffer */
443 	pATIDRIServer->frontOffset = 0;
444 	pATIDRIServer->frontPitch = pScreenInfo->displayWidth;
445 	next += bufferSize;
446 
447 	/* back buffer */
448 	pATIDRIServer->backOffset = next;
449 	pATIDRIServer->backPitch = pScreenInfo->displayWidth;
450 	next += bufferSize;
451 
452 	/* depth buffer */
453 	pATIDRIServer->depthOffset = next;
454 	pATIDRIServer->depthPitch = pScreenInfo->displayWidth;
455 	next += depthSize;
456 
457 	/* ATIScreenInit does check for the this condition. */
458 	if (next > pExa->memorySize)
459 	{
460 	    xf86DrvMsg(pScreen->myNum, X_WARNING,
461 		"DRI static buffer allocation failed, disabling DRI --"
462 		"need at least %d kB video memory\n", next / 1024 );
463 	    ATIDRICloseScreen(pScreen);
464 	    pATI->directRenderingEnabled = FALSE;
465 	}
466 
467 	/* local textures */
468 
469 	/* Reserve approx. half of offscreen memory for local textures */
470 	textureSize = (pExa->memorySize - next) / 2;
471 
472 	/* In case DRI requires more offscreen memory than available,
473 	 * should not happen as ATIScreenInit would have not enabled DRI */
474 	if (textureSize < 0)
475 	    textureSize = 0;
476 
477 	/* Try for enough pixmap cache for a full viewport */
478 	pixmapCache = (pExa->memorySize - next) - textureSize;
479 	if (pixmapCache < bufferSize)
480 	    textureSize = 0;
481 
482 	/* Don't allocate a local texture heap for AGP unless requested */
483 	if ( !is_pci && !pATI->OptionLocalTextures )
484 	    textureSize = 0;
485 
486 	if (textureSize > 0)
487 	{
488 	    int l = Mach64Log2(textureSize / MACH64_NR_TEX_REGIONS);
489 	    if (l < MACH64_LOG_TEX_GRANULARITY)
490 		l = MACH64_LOG_TEX_GRANULARITY;
491 	    pATIDRIServer->logTextureGranularity = l;
492 
493 	    /* Round the texture size down to the nearest whole number of
494 	     * texture regions.
495 	     */
496 	    textureSize = (textureSize >> l) << l;
497 	}
498 
499 	/* Set a minimum usable local texture heap size.  This will fit
500 	 * two 256x256 textures.  We check this after any rounding of
501 	 * the texture area.
502 	 */
503 	if (textureSize < 256*256 * cpp * 2)
504 	    textureSize = 0;
505 
506 	/* Disable DRI for PCI if cannot allocate a local texture heap */
507 	if ( is_pci && textureSize == 0 )
508 	{
509 	    xf86DrvMsg(pScreen->myNum, X_WARNING,
510 		"Not enough memory for local textures, disabling DRI\n");
511 	    ATIDRICloseScreen(pScreen);
512 	    pATI->directRenderingEnabled = FALSE;
513 	}
514 
515 	pATIDRIServer->textureOffset = next;
516 	pATIDRIServer->textureSize = textureSize;
517 	next += textureSize;
518 
519 	/* pExa->offScreenBase is moved to `next' when DRI gets activated */
520     }
521 #endif /* XF86DRI_DEVEL */
522 
523     xf86DrvMsg(pScreen->myNum, X_INFO,
524         "EXA memory management initialized\n"
525         "\t base     :  %10p\n"
526         "\t offscreen: +%10lx\n"
527         "\t size     : +%10lx\n"
528         "\t cursor   :  %10p\n",
529         pExa->memoryBase,
530         pExa->offScreenBase,
531         pExa->memorySize,
532         pATI->pCursorImage);
533 
534     if (TRUE || xf86GetVerbosity() > 1)
535     {
536         int offscreen = pExa->memorySize - pExa->offScreenBase;
537         int viewport = bufferSize;
538         int dvdframe = 720*480*cpp; /* enough for single-buffered DVD */
539 
540         xf86DrvMsg(pScreen->myNum, X_INFO,
541             "Will use %d kB of offscreen memory for EXA\n"
542             "\t\t or %5.2f viewports (composite)\n"
543             "\t\t or %5.2f dvdframes (xvideo)\n",
544             offscreen / 1024,
545             1.0 * offscreen / viewport,
546             1.0 * offscreen / dvdframe);
547     }
548 
549 #ifdef XF86DRI_DEVEL
550     if (pATI->directRenderingEnabled)
551     {
552         ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
553 
554         xf86DrvMsg(pScreen->myNum, X_INFO,
555                    "Will use back  buffer at offset 0x%x\n",
556                    pATIDRIServer->backOffset);
557 
558         xf86DrvMsg(pScreen->myNum, X_INFO,
559                    "Will use depth buffer at offset 0x%x\n",
560                    pATIDRIServer->depthOffset);
561 
562         if (pATIDRIServer->textureSize > 0)
563         {
564             xf86DrvMsg(pScreen->myNum, X_INFO,
565                    "Will use %d kB for local textures at offset 0x%x\n",
566                    pATIDRIServer->textureSize/1024,
567                    pATIDRIServer->textureOffset);
568         }
569     }
570 #endif /* XF86DRI_DEVEL */
571 
572     pExa->pixmapOffsetAlign = 64;
573     pExa->pixmapPitchAlign = 64;
574 
575     pExa->flags = EXA_OFFSCREEN_PIXMAPS;
576 
577     pExa->maxX = ATIMach64MaxX;
578     pExa->maxY = ATIMach64MaxY;
579 }
580 
ATIMach64ExaInit(ScreenPtr pScreen)581 Bool ATIMach64ExaInit(ScreenPtr pScreen)
582 {
583     ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
584     ATIPtr pATI = ATIPTR(pScreenInfo);
585     ExaDriverPtr pExa;
586 
587     pExa = exaDriverAlloc();
588     if (!pExa)
589         return FALSE;
590 
591     pATI->pExa = pExa;
592 
593     pExa->exa_major = 2;
594     pExa->exa_minor = 0;
595 
596     Mach64SetupMemEXA(pScreen);
597 
598     pExa->WaitMarker = Mach64WaitMarker;
599 
600     pExa->PrepareSolid = Mach64PrepareSolid;
601     pExa->Solid = Mach64Solid;
602     pExa->DoneSolid = Mach64DoneSolid;
603 
604     pExa->PrepareCopy = Mach64PrepareCopy;
605     pExa->Copy = Mach64Copy;
606     pExa->DoneCopy = Mach64DoneCopy;
607 
608     if (pATI->RenderAccelEnabled) {
609 	if (pATI->Chip >= ATI_CHIP_264GTPRO) {
610 	    /* 3D Rage Pro does not support NPOT textures. */
611 	    pExa->flags |= EXA_OFFSCREEN_ALIGN_POT;
612 
613 	    pExa->CheckComposite = Mach64CheckComposite;
614 	    pExa->PrepareComposite = Mach64PrepareComposite;
615 	    pExa->Composite = Mach64Composite;
616 	    pExa->DoneComposite = Mach64DoneComposite;
617 	} else {
618 	    xf86DrvMsg(pScreen->myNum, X_INFO,
619 		       "Render acceleration is not supported for ATI chips "
620 		       "earlier than the ATI 3D Rage Pro.\n");
621 	    pATI->RenderAccelEnabled = FALSE;
622 	}
623     }
624 
625     xf86DrvMsg(pScreen->myNum, X_INFO, "Render acceleration %s\n",
626 	       pATI->RenderAccelEnabled ? "enabled" : "disabled");
627 
628     if (!exaDriverInit(pScreen, pATI->pExa)) {
629 	free(pATI->pExa);
630 	pATI->pExa = NULL;
631 	return FALSE;
632     }
633 
634     return TRUE;
635 }
636 #endif
637