summit_accel.c revision bf977f5f
1/*
2 * hardware acceleration for Visualize FX 4
3 *
4 * Copyright (C) 2024 Michael Lorenz
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * MICHAEL LORENZ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24/* $NetBSD: summit_accel.c,v 1.7 2025/02/18 12:17:20 macallan Exp $ */
25
26#include <sys/types.h>
27#include <dev/ic/summitreg.h>
28
29
30#include "ngle.h"
31#include "mipict.h"
32
33//#define DEBUG
34
35void
36 exaPrepareAccess(DrawablePtr pDrawable, int index);
37
38void
39 exaFinishAccess(DrawablePtr pDrawable, int index);
40
41#ifdef DEBUG
42#define ENTER xf86Msg(X_ERROR, "%s\n", __func__)
43#define LEAVE xf86Msg(X_ERROR, "%s done\n", __func__)
44#define DBGMSG xf86Msg
45#else
46#define ENTER
47#define DBGMSG if (0) xf86Msg
48#define LEAVE
49#endif
50
51#define SUMMIT_READ_MODE(m) \
52	if ((m) != fPtr->read_mode) { \
53		SummitWait(fPtr); \
54		NGLEWrite4(fPtr, VISFX_VRAM_READ_MODE, (m)); \
55		fPtr->read_mode = (m); \
56	}
57
58#define SUMMIT_WRITE_MODE(m) \
59	if ((m) != fPtr->write_mode) { \
60		SummitWait(fPtr); \
61		NGLEWrite4(fPtr, VISFX_VRAM_WRITE_MODE, (m)); \
62		fPtr->write_mode = (m); \
63	}
64
65static inline void
66SummitWait(NGLEPtr fPtr)
67{
68	int reg, count = 0;;
69
70	ENTER;
71	do {
72		reg = NGLERead4(fPtr, VISFX_STATUS);
73		count++;
74	} while ((reg & 0x01000000) != 0);
75	if (reg != 0) {
76		xf86Msg(X_ERROR, "%s status %08x\n", __func__, reg);
77		xf86Msg(X_ERROR, "fault %08x\n", NGLERead4(fPtr, 0x641040));
78	}
79	DBGMSG(X_ERROR, "%s: %d\n", __func__, count);
80}
81
82static void
83SummitWaitMarker(ScreenPtr pScreen, int Marker)
84{
85	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
86	NGLEPtr fPtr = NGLEPTR(pScrn);
87	int reg, count = 0;
88
89	ENTER;
90	do {
91		reg = NGLERead4(fPtr, VISFX_STATUS);
92		count++;
93	} while ((reg & 0x01000000) != 0);
94	if (reg != 0) {
95		xf86Msg(X_ERROR, "%s status %08x\n", __func__, reg);
96		xf86Msg(X_ERROR, "fault %08x\n", NGLERead4(fPtr, 0x641040));
97	}
98	DBGMSG(X_ERROR, "%s: %d\n", __func__, count);
99}
100
101static void
102SummitWaitFifo(NGLEPtr fPtr, int count)
103{
104	int reg;
105	do {
106		reg = NGLERead4(fPtr, VISFX_FIFO);
107	} while (reg < count);
108#ifdef DEBUG
109	if (reg != 0x800) xf86Msg(X_ERROR, "%s %x\n", __func__, reg);
110#endif
111}
112
113static Bool
114SummitPrepareCopy
115(
116    PixmapPtr pSrcPixmap,
117    PixmapPtr pDstPixmap,
118    int       xdir,
119    int       ydir,
120    int       alu,
121    Pixel     planemask
122)
123{
124	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
125	NGLEPtr fPtr = NGLEPTR(pScrn);
126	int dstoff = exaGetPixmapOffset(pDstPixmap);
127	int srcoff = exaGetPixmapOffset(pSrcPixmap);
128	uint32_t sm, dm;
129	int y;
130
131	ENTER;
132
133	sm = dm = OTC01 | BIN8F | BUFFL;
134	DBGMSG(X_ERROR, "%s %d %d\n", __func__, srcoff, dstoff);
135
136	y = (srcoff >> 13);	/* pitch is 8192 bytes in 24 bit */
137	if (y >= fPtr->fbi.fbi_height) {
138		sm = OTC01 | BIN8F | BUFBL;
139		y -= fPtr->fbi.fbi_height;
140	}
141	fPtr->offset = y;
142	SUMMIT_READ_MODE(sm);
143
144	y = (dstoff >> 13);	/* pitch is 8192 bytes in 24 bit */
145	if (y >= fPtr->fbi.fbi_height) {
146		dm = OTC01 | BIN8F | BUFBL;
147		y -= fPtr->fbi.fbi_height;
148	}
149	fPtr->offsetd = y;
150	SUMMIT_WRITE_MODE(dm);
151
152	SummitWaitFifo(fPtr, 8);
153	if (alu == GXcopy) {
154		NGLEWrite4(fPtr, VISFX_FOE, 0);
155	} else {
156		NGLEWrite4(fPtr, VISFX_FOE, FOE_BLEND_ROP);
157		NGLEWrite4(fPtr, VISFX_IBO, alu);
158	}
159	NGLEWrite4(fPtr, VISFX_PLANE_MASK, planemask);
160	LEAVE;
161	return TRUE;
162}
163
164static void
165SummitCopy
166(
167    PixmapPtr pDstPixmap,
168    int       xs,
169    int       ys,
170    int       xd,
171    int       yd,
172    int       wi,
173    int       he
174)
175{
176	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
177	NGLEPtr fPtr = NGLEPTR(pScrn);
178
179	ENTER;
180	SummitWaitFifo(fPtr, 8);
181	NGLEWrite4(fPtr, VISFX_COPY_SRC, (xs << 16) | (ys + fPtr->offset));
182	NGLEWrite4(fPtr, VISFX_COPY_WH, (wi << 16) | he);
183	NGLEWrite4(fPtr, VISFX_COPY_DST, (xd << 16) | (yd + fPtr->offsetd));
184
185	LEAVE;
186}
187
188static void
189SummitDoneCopy(PixmapPtr pDstPixmap)
190{
191    ENTER;
192    LEAVE;
193}
194
195static Bool
196SummitPrepareSolid(
197    PixmapPtr pPixmap,
198    int alu,
199    Pixel planemask,
200    Pixel fg)
201{
202	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
203	NGLEPtr fPtr = NGLEPTR(pScrn);
204	int	ofs =  exaGetPixmapOffset(pPixmap);
205	int	y;
206	uint32_t wm = OTC32 | BIN8F | BUFFL | 0x8c0, rm = OTC01 | BIN8F | BUFFL;
207
208	ENTER;
209	y = (ofs >> 13);	/* pitch is 8192 bytes in 24 bit */
210	if (y >= fPtr->fbi.fbi_height) {
211		wm = OTC32 | BIN8F | BUFBL | 0x8c0;
212		rm = OTC01 | BIN8F | BUFBL;
213		y -= fPtr->fbi.fbi_height;
214	}
215	SUMMIT_READ_MODE(rm);
216	SUMMIT_WRITE_MODE(wm);
217	fPtr->offset = y;
218	SummitWaitFifo(fPtr, 10);
219	if (alu == GXcopy) {
220		NGLEWrite4(fPtr, VISFX_FOE, 0);
221	} else {
222		NGLEWrite4(fPtr, VISFX_FOE, FOE_BLEND_ROP);
223		NGLEWrite4(fPtr, VISFX_IBO, alu);
224	}
225	NGLEWrite4(fPtr, VISFX_FG_COLOUR, fg);
226	NGLEWrite4(fPtr, VISFX_PLANE_MASK, planemask);
227	LEAVE;
228	return TRUE;
229}
230
231static void
232SummitSolid(
233    PixmapPtr pPixmap,
234    int x1,
235    int y1,
236    int x2,
237    int y2)
238{
239	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
240	NGLEPtr fPtr = NGLEPTR(pScrn);
241	int wi = x2 - x1, he = y2 - y1;
242
243	ENTER;
244
245	y1 += fPtr->offset;
246
247	SummitWaitFifo(fPtr, 6);
248	NGLEWrite4(fPtr, VISFX_START, (x1 << 16) | y1);
249	NGLEWrite4(fPtr, VISFX_SIZE, (wi << 16) | he);
250
251	LEAVE;
252}
253
254static Bool
255SummitUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
256    char *src, int src_pitch)
257{
258	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
259	NGLEPtr fPtr = NGLEPTR(pScrn);
260	int	ofs =  exaGetPixmapOffset(pDst);
261	int i;
262	uint32_t *line, mode = OTC01 | BIN8F | BUFFL;
263	uint8_t *dst;
264
265	ENTER;
266	y += (ofs >> 13);	/* pitch is 8192 bytes in 24 bit */
267	if (y >= fPtr->fbi.fbi_height) {
268		mode = OTC01 | BIN8F | BUFBL;
269		y -= fPtr->fbi.fbi_height;
270	}
271
272	dst = fPtr->fbmem;
273	dst += (y << 13) + (x << 2);
274
275	SUMMIT_WRITE_MODE(mode);
276	NGLEWrite4(fPtr, VISFX_PLANE_MASK, 0xffffffff);
277	NGLEWrite4(fPtr, VISFX_FOE, 0);
278
279	while (h--) {
280		/*
281		 * it *should* be impossible to overrun the FIFO using BINC
282		 * writes, but overruns are annoying if they do happen so be
283		 * overly cautious and make sure there is at least some room
284		 */
285		SummitWaitFifo(fPtr, w + 1);
286		NGLEWrite4(fPtr, VISFX_VRAM_WRITE_DEST, (y << 16) | x);
287		line = (uint32_t *)src;
288
289		for (i = 0; i < w; i++)
290			NGLEWrite4(fPtr, VISFX_VRAM_WRITE_DATA_INCRX, line[i]);
291		//memcpy(dst, src, w << 2);
292		src += src_pitch;
293		dst += 8192;
294		y++;
295	}
296
297	LEAVE;
298
299	return TRUE;
300}
301
302static Bool
303SummitDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
304    char *dst, int dst_pitch)
305{
306	ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
307	NGLEPtr fPtr = NGLEPTR(pScrn);
308	uint8_t *src;
309	int	ofs =  exaGetPixmapOffset(pSrc);
310	uint32_t mode = OTC01 | BIN8F | BUFFL;
311
312	ENTER;
313
314	y += (ofs >> 13);
315	if (y >= fPtr->fbi.fbi_height) {
316		mode = OTC01 | BIN8F | BUFBL;
317		y -= fPtr->fbi.fbi_height;
318	}
319	SUMMIT_READ_MODE(mode);
320	SummitWait(fPtr);
321	NGLEWrite4(fPtr, VISFX_RPH, VISFX_RPH_LTR);
322	SummitWait(fPtr);
323
324	src = fPtr->fbmem;
325	src += (y << 13) + (x << 2);
326
327	while (h--) {
328		memcpy(dst, src, w << 2);
329		src += 8192;
330		dst += dst_pitch;
331	}
332
333	LEAVE;
334
335	return TRUE;
336}
337
338Bool
339SummitPrepareAccess(PixmapPtr pPixmap, int index)
340{
341	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
342	NGLEPtr fPtr = NGLEPTR(pScrn);
343	int	ofs =  exaGetPixmapOffset(pPixmap);
344	int	y;
345
346	ENTER;
347	//xf86Msg(X_ERROR, "%s %d\n", __func__, ofs);
348	if (ofs == 0) {
349		/* accessing the visible framebuffer */
350		SUMMIT_READ_MODE(OTC01 | BIN8F | BUFFL);
351		SUMMIT_WRITE_MODE(OTC01 | BIN8F | BUFFL);
352	} else {
353		SUMMIT_READ_MODE(OTC01 | BIN8F | BUFBL);
354		SUMMIT_WRITE_MODE(OTC01 | BIN8F | BUFBL);
355		y = ofs >> 13;
356		y -= fPtr->fbi.fbi_height;
357		pPixmap->devPrivate.ptr = fPtr->fbmem + (y << 13);
358	}
359	NGLEWrite4(fPtr, VISFX_FOE, 0);
360	NGLEWrite4(fPtr, VISFX_RPH, VISFX_RPH_LTR);
361	//NGLEWrite4(fPtr, VISFX_CONTROL, 0x200);
362	SummitWait(fPtr);
363	LEAVE;
364	return TRUE;
365}
366
367void
368SummitFinishAccess(PixmapPtr pPixmap, int index)
369{
370	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
371	NGLEPtr fPtr = NGLEPTR(pScrn);
372
373	ENTER;
374	//NGLEWrite4(fPtr, VISFX_CONTROL, 0);
375	//SummitWait(fPtr);
376	LEAVE;
377}
378
379PixmapPtr
380SummitGetDrawablePixmap(DrawablePtr pDrawable)
381{
382    if (pDrawable->type == DRAWABLE_WINDOW)
383        return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable);
384    else
385        return (PixmapPtr) pDrawable;
386}
387
388static void
389SummitDrawGlyph8(NGLEPtr fPtr, int32_t fg, PixmapPtr mask, int p,
390    int xm, int ym, int xd, int yd, int w, int h)
391{
392	uint8_t *gdata = mask->devPrivate.ptr;
393	uint32_t msk;
394	int i, j;
395
396	gdata += xm;
397	gdata += (p * ym);
398	for (i = 0; i < h; i++) {
399		SummitWaitFifo(fPtr, w * 2);
400		NGLEWrite4(fPtr, VISFX_VRAM_WRITE_DEST,
401		    ((yd + i) << 16) | xd);
402		for (j = 0; j < w; j++) {
403			msk = gdata[j];
404			msk = (msk << 24) | fg;
405			NGLEWrite4(fPtr,
406			    VISFX_VRAM_WRITE_DATA_INCRX, msk);
407		}
408		gdata += p;
409	}
410}
411
412static void
413SummitDrawGlyph32(NGLEPtr fPtr, uint32_t fg, PixmapPtr mask, int p,
414    int xm, int ym, int xd, int yd, int w, int h)
415{
416	uint32_t *gdata = mask->devPrivate.ptr;
417	uint32_t msk;
418	int i, j;
419
420	gdata += xm;
421	gdata += (p * ym);
422
423	for (i = 0; i < h; i++) {
424		SummitWaitFifo(fPtr, w * 2);
425		NGLEWrite4(fPtr, VISFX_VRAM_WRITE_DEST,
426		    ((yd + i) << 16) | xd);
427		for (j = 0; j < w; j++) {
428			msk = gdata[j];
429			msk = (msk & 0xff000000) | fg;
430			NGLEWrite4(fPtr,
431			    VISFX_VRAM_WRITE_DATA_INCRX, msk);
432		}
433		gdata += p >> 2;
434	}
435}
436
437static void
438SummitGlyphs (CARD8	op,
439	  PicturePtr	pSrc,
440	  PicturePtr	pDst,
441	  PictFormatPtr	maskFormat,
442	  INT16		xSrc,
443	  INT16		ySrc,
444	  int		nlist,
445	  GlyphListPtr	list,
446	  GlyphPtr	*glyphs)
447{
448	ScreenPtr	pScreen = pDst->pDrawable->pScreen;
449	ScrnInfoPtr 	pScrn = xf86Screens[pScreen->myNum];
450	NGLEPtr 	fPtr = NGLEPTR(pScrn);
451	PicturePtr	pPicture;
452	PixmapPtr	mask, dst;
453	GlyphPtr	glyph;
454	int		xDst = list->xOff, yDst = list->yOff;
455	int		x = 0, y = 0, i, n, ofs, p, j, wi, he;
456	uint32_t fg = 0xffffffff, msk;
457
458	if (op != PictOpOver) goto fallback;
459
460	if (!exaDrawableIsOffscreen(pDst->pDrawable)) goto fallback;
461
462	dst = SummitGetDrawablePixmap(pDst->pDrawable);
463	ofs = exaGetPixmapOffset(dst);
464	ofs = ofs >> 13;
465
466	if (pDst->pDrawable->type == DRAWABLE_WINDOW) {
467		x += pDst->pDrawable->x;
468		y += pDst->pDrawable->y;
469	}
470
471	if (pSrc->pSourcePict != NULL) {
472		if (pSrc->pSourcePict->type == SourcePictTypeSolidFill) {
473			fg = pSrc->pSourcePict->solidFill.color;
474		}
475	}
476	fg &= 0x00ffffff;
477
478	if (ofs == 0) {
479		/* accessing the visible framebuffer */
480		SUMMIT_WRITE_MODE(OTC01 | BIN8F | BUFFL);
481	} else {
482		SUMMIT_WRITE_MODE(OTC01 | BIN8F | BUFBL);
483	}
484
485	SummitWaitFifo(fPtr, 4);
486	NGLEWrite4(fPtr, VISFX_FOE, FOE_BLEND_ROP);
487	NGLEWrite4(fPtr, VISFX_IBO,
488	    IBO_ADD | SRC(IBO_SRC) | DST(IBO_ONE_MINUS_SRC));
489
490	while (nlist--)     {
491		x += list->xOff;
492		y += list->yOff;
493		n = list->len;
494		while (n--) {
495			glyph = *glyphs++;
496			pPicture = GlyphPicture (glyph)[pScreen->myNum];
497			if (pPicture) {
498				int xd = x - glyph->info.x;
499				int yd = y - glyph->info.y;
500				RegionRec region;
501				BoxPtr pbox;
502				int nbox;
503
504				if (ofs == 0) {
505					/*
506					 * we're drawing to the visible screen,
507					 * so we must take care not to scribble
508					 * over other windows
509					 */
510					if (!miComputeCompositeRegion(&region,
511					  pSrc, pPicture, pDst,
512                        	          0, 0, 0, 0, xd, yd,
513                        	          glyph->info.width,
514                        	          glyph->info.height))
515						goto skip;
516
517					fbGetDrawablePixmap(pPicture->pDrawable,
518					    mask, wi, he);
519					exaPrepareAccess(pPicture->pDrawable,
520					    EXA_PREPARE_SRC);
521					p = exaGetPixmapPitch(mask);
522
523					nbox = RegionNumRects(&region);
524					pbox = RegionRects(&region);
525					while (nbox--) {
526						if (pPicture->format == PICT_a8) {
527							SummitDrawGlyph8(fPtr,
528							    fg, mask, p,
529							    pbox->x1 - xd,
530							    pbox->y1 - yd,
531							    pbox->x1, pbox->y1,
532							    pbox->x2 - pbox->x1,
533							    pbox->y2 - pbox->y1);
534						} else {
535							SummitDrawGlyph32(fPtr,
536							    fg, mask, p,
537							    pbox->x1 - xd,
538							    pbox->y1 - yd,
539							    pbox->x1, pbox->y1,
540							    pbox->x2 - pbox->x1,
541							    pbox->y2 - pbox->y1);
542						}
543        					pbox++;
544    					}
545					RegionUninit(&region);
546					exaFinishAccess(pPicture->pDrawable,
547					    EXA_PREPARE_SRC);
548				} else {
549					/*
550					 * drawing into off-screen memory, we
551					 * only need to clip to the destination
552					 * pixmap's boundaries
553					 */
554					yd += (ofs - fPtr->fbi.fbi_height);
555
556					fbGetDrawablePixmap(pPicture->pDrawable,
557					    mask, wi, he);
558					exaPrepareAccess(pPicture->pDrawable,
559					    EXA_PREPARE_SRC);
560					p = exaGetPixmapPitch(mask);
561
562					if (pPicture->format == PICT_a8) {
563						SummitDrawGlyph8(fPtr,
564						    fg, mask, p,
565						    0, 0,
566						    xd, yd,
567						    glyph->info.width,
568						    glyph->info.height);
569					} else {
570						SummitDrawGlyph32(fPtr,
571						    fg, mask, p,
572						    0, 0,
573						    xd, yd,
574						    glyph->info.width,
575						    glyph->info.height);
576					}
577					exaFinishAccess(pPicture->pDrawable,
578					    EXA_PREPARE_SRC);
579				}
580			}
581skip:
582			x += glyph->info.xOff;
583			y += glyph->info.yOff;
584		}
585		list++;
586	}
587	return;
588fallback:
589	fPtr->glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
590}
591
592Bool
593SummitInitAccel(ScreenPtr pScreen)
594{
595	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
596	PictureScreenPtr ps = GetPictureScreen(pScreen);
597	NGLEPtr fPtr = NGLEPTR(pScrn);
598	ExaDriverPtr pExa;
599	int bpp = pScrn->bitsPerPixel >> 3, ret;
600
601	pExa = exaDriverAlloc();
602	if (!pExa)
603		return FALSE;
604
605	fPtr->pExa = pExa;
606
607	pExa->exa_major = EXA_VERSION_MAJOR;
608	pExa->exa_minor = EXA_VERSION_MINOR;
609
610	pExa->memoryBase = fPtr->fbmem;
611	pExa->memorySize = fPtr->fbi.fbi_stride * (fPtr->fbi.fbi_height * 2);
612	pExa->offScreenBase = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height;
613	pExa->pixmapOffsetAlign = fPtr->fbi.fbi_stride;
614	pExa->pixmapPitchAlign = fPtr->fbi.fbi_stride;
615
616	pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_MIXED_PIXMAPS;
617
618	pExa->maxX = 2048;
619	pExa->maxY = 2048;
620
621	pExa->WaitMarker = SummitWaitMarker;
622	pExa->Solid = SummitSolid;
623	pExa->DoneSolid = SummitDoneCopy;
624	pExa->Copy = SummitCopy;
625	pExa->DoneCopy = SummitDoneCopy;
626	pExa->PrepareCopy = SummitPrepareCopy;
627	pExa->PrepareSolid = SummitPrepareSolid;
628	pExa->UploadToScreen = SummitUploadToScreen;
629	pExa->DownloadFromScreen = SummitDownloadFromScreen;
630	pExa->PrepareAccess = SummitPrepareAccess;
631	pExa->FinishAccess = SummitFinishAccess;
632
633	fPtr->read_mode = -1;
634	fPtr->write_mode = -1;
635	SUMMIT_READ_MODE(OTC01 | BIN8F | BUFFL);
636	SUMMIT_WRITE_MODE(OTC01 | BIN8F | BUFFL);
637	NGLEWrite4(fPtr, VISFX_FOE, FOE_BLEND_ROP);
638	NGLEWrite4(fPtr, VISFX_IBO, GXcopy);
639	NGLEWrite4(fPtr, VISFX_CONTROL, 0);
640
641	ret = exaDriverInit(pScreen, pExa);
642
643	fPtr->glyphs = ps->Glyphs;
644	ps->Glyphs = SummitGlyphs;
645	return ret;
646}
647