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.9 2025/02/25 13:21:24 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, needs_coords;
395
396	gdata += xm;
397	gdata += (p * ym);
398	for (i = 0; i < h; i++) {
399		SummitWaitFifo(fPtr, w * 2);
400		needs_coords = 1;
401		for (j = 0; j < w; j++) {
402			msk = gdata[j];
403			if (msk == 0) {
404				needs_coords = 1;
405				continue;
406			}
407			if (needs_coords) {
408				NGLEWrite4(fPtr, VISFX_VRAM_WRITE_DEST,
409				    ((yd + i) << 16) | (xd + j));
410				needs_coords = 0;
411			}
412			msk = (msk << 24) | fg;
413			NGLEWrite4(fPtr,
414			    VISFX_VRAM_WRITE_DATA_INCRX, msk);
415		}
416		gdata += p;
417	}
418}
419
420static void
421SummitDrawGlyph32(NGLEPtr fPtr, uint32_t fg, PixmapPtr mask, int p,
422    int xm, int ym, int xd, int yd, int w, int h)
423{
424	uint32_t *gdata = mask->devPrivate.ptr;
425	uint32_t msk;
426	int i, j, needs_coords;
427
428	gdata += xm;
429	gdata += (p * ym);
430
431	for (i = 0; i < h; i++) {
432		SummitWaitFifo(fPtr, w * 2);
433		needs_coords = 1;
434		for (j = 0; j < w; j++) {
435			msk = gdata[j] & 0xff000000;
436			if (msk == 0) {
437				needs_coords = 1;
438				continue;
439			}
440			if (needs_coords) {
441				NGLEWrite4(fPtr, VISFX_VRAM_WRITE_DEST,
442				    ((yd + i) << 16) | (xd + j));
443				needs_coords = 0;
444			}
445			msk |= fg;
446			NGLEWrite4(fPtr,
447			    VISFX_VRAM_WRITE_DATA_INCRX, msk);
448		}
449		gdata += p >> 2;
450	}
451}
452
453static void
454SummitGlyphs (CARD8	op,
455	  PicturePtr	pSrc,
456	  PicturePtr	pDst,
457	  PictFormatPtr	maskFormat,
458	  INT16		xSrc,
459	  INT16		ySrc,
460	  int		nlist,
461	  GlyphListPtr	list,
462	  GlyphPtr	*glyphs)
463{
464	ScreenPtr	pScreen = pDst->pDrawable->pScreen;
465	ScrnInfoPtr 	pScrn = xf86Screens[pScreen->myNum];
466	NGLEPtr 	fPtr = NGLEPTR(pScrn);
467	PicturePtr	pPicture;
468	PixmapPtr	mask, dst;
469	GlyphPtr	glyph;
470	int		xDst = list->xOff, yDst = list->yOff;
471	int		x = 0, y = 0, i, n, ofs, p, j, wi, he, xs, ys;
472	int		dw, dh;
473	uint32_t fg = 0xffffffff, msk;
474
475	if (op != PictOpOver) goto fallback;
476
477	if (!exaDrawableIsOffscreen(pDst->pDrawable)) goto fallback;
478
479	dst = SummitGetDrawablePixmap(pDst->pDrawable);
480	ofs = exaGetPixmapOffset(dst);
481	ofs = ofs >> 13;
482	dw = pDst->pDrawable->width;
483	dh = pDst->pDrawable->height;
484
485	if (pDst->pDrawable->type == DRAWABLE_WINDOW) {
486		x += pDst->pDrawable->x;
487		y += pDst->pDrawable->y;
488	}
489
490	if (pSrc->pSourcePict != NULL) {
491		if (pSrc->pSourcePict->type == SourcePictTypeSolidFill) {
492			fg = pSrc->pSourcePict->solidFill.color;
493		}
494	}
495	fg &= 0x00ffffff;
496
497	if (ofs == 0) {
498		/* accessing the visible framebuffer */
499		SUMMIT_WRITE_MODE(OTC01 | BIN8F | BUFFL);
500	} else {
501		SUMMIT_WRITE_MODE(OTC01 | BIN8F | BUFBL);
502	}
503
504	SummitWaitFifo(fPtr, 4);
505	NGLEWrite4(fPtr, VISFX_FOE, FOE_BLEND_ROP);
506	NGLEWrite4(fPtr, VISFX_IBO,
507	    IBO_ADD | SRC(IBO_SRC) | DST(IBO_ONE_MINUS_SRC));
508
509	while (nlist--)     {
510		x += list->xOff;
511		y += list->yOff;
512		n = list->len;
513		while (n--) {
514			glyph = *glyphs++;
515			pPicture = GlyphPicture (glyph)[pScreen->myNum];
516			if (pPicture) {
517				int xd = x - glyph->info.x;
518				int yd = y - glyph->info.y;
519				RegionRec region;
520				BoxPtr pbox;
521				int nbox;
522
523				if (ofs == 0) {
524					/*
525					 * we're drawing to the visible screen,
526					 * so we must take care not to scribble
527					 * over other windows
528					 */
529					if (!miComputeCompositeRegion(&region,
530					  pSrc, pPicture, pDst,
531                        	          0, 0, 0, 0, xd, yd,
532                        	          glyph->info.width,
533                        	          glyph->info.height))
534						goto skip;
535
536					fbGetDrawablePixmap(pPicture->pDrawable,
537					    mask, wi, he);
538					exaPrepareAccess(pPicture->pDrawable,
539					    EXA_PREPARE_SRC);
540					p = exaGetPixmapPitch(mask);
541
542					nbox = RegionNumRects(&region);
543					pbox = RegionRects(&region);
544					while (nbox--) {
545						if (pPicture->format == PICT_a8) {
546							SummitDrawGlyph8(fPtr,
547							    fg, mask, p,
548							    pbox->x1 - xd,
549							    pbox->y1 - yd,
550							    pbox->x1, pbox->y1,
551							    pbox->x2 - pbox->x1,
552							    pbox->y2 - pbox->y1);
553						} else {
554							SummitDrawGlyph32(fPtr,
555							    fg, mask, p,
556							    pbox->x1 - xd,
557							    pbox->y1 - yd,
558							    pbox->x1, pbox->y1,
559							    pbox->x2 - pbox->x1,
560							    pbox->y2 - pbox->y1);
561						}
562        					pbox++;
563    					}
564					RegionUninit(&region);
565					exaFinishAccess(pPicture->pDrawable,
566					    EXA_PREPARE_SRC);
567				} else {
568					/*
569					 * drawing into off-screen memory, we
570					 * only need to clip to the destination
571					 * pixmap's boundaries
572					 */
573
574					fbGetDrawablePixmap(pPicture->pDrawable,
575					    mask, wi, he);
576
577					xs = 0;
578					ys = 0;
579					wi = glyph->info.width;
580					he = glyph->info.height;
581
582					if (xd < 0) {
583						xs -= xd;
584						wi += xd;
585						xd = 0;
586					}
587
588					if (yd < 0) {
589						ys -= yd;
590						he += yd;
591						yd = 0;
592					}
593
594					if ((xd + wi) > dw) {
595						wi -= (xd + wi - dw);
596					}
597
598					if ((yd + he) > dh) {
599						he -= (yd + he - dh);
600					}
601
602					if ((he <= 0) || (wi <= 0))
603						goto skip;
604
605					yd += (ofs - fPtr->fbi.fbi_height);
606
607					exaPrepareAccess(pPicture->pDrawable,
608					    EXA_PREPARE_SRC);
609					p = exaGetPixmapPitch(mask);
610
611					if (pPicture->format == PICT_a8) {
612						SummitDrawGlyph8(fPtr,
613						    fg, mask, p,
614						    xs, ys,
615						    xd, yd,
616						    wi, he);
617					} else {
618						SummitDrawGlyph32(fPtr,
619						    fg, mask, p,
620						    xs, ys,
621						    xd, yd,
622						    wi, he);
623					}
624					exaFinishAccess(pPicture->pDrawable,
625					    EXA_PREPARE_SRC);
626				}
627			}
628skip:
629			x += glyph->info.xOff;
630			y += glyph->info.yOff;
631		}
632		list++;
633	}
634	return;
635fallback:
636	fPtr->glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
637}
638
639Bool
640SummitInitAccel(ScreenPtr pScreen)
641{
642	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
643	PictureScreenPtr ps = GetPictureScreen(pScreen);
644	NGLEPtr fPtr = NGLEPTR(pScrn);
645	ExaDriverPtr pExa;
646	int bpp = pScrn->bitsPerPixel >> 3, ret;
647
648	pExa = exaDriverAlloc();
649	if (!pExa)
650		return FALSE;
651
652	fPtr->pExa = pExa;
653
654	pExa->exa_major = EXA_VERSION_MAJOR;
655	pExa->exa_minor = EXA_VERSION_MINOR;
656
657	pExa->memoryBase = fPtr->fbmem;
658	pExa->memorySize = fPtr->fbi.fbi_stride * (fPtr->fbi.fbi_height * 2);
659	pExa->offScreenBase = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height;
660	pExa->pixmapOffsetAlign = fPtr->fbi.fbi_stride;
661	pExa->pixmapPitchAlign = fPtr->fbi.fbi_stride;
662
663	pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_MIXED_PIXMAPS;
664
665	pExa->maxX = 2048;
666	pExa->maxY = 2048;
667
668	pExa->WaitMarker = SummitWaitMarker;
669	pExa->Solid = SummitSolid;
670	pExa->DoneSolid = SummitDoneCopy;
671	pExa->Copy = SummitCopy;
672	pExa->DoneCopy = SummitDoneCopy;
673	pExa->PrepareCopy = SummitPrepareCopy;
674	pExa->PrepareSolid = SummitPrepareSolid;
675	pExa->UploadToScreen = SummitUploadToScreen;
676	pExa->DownloadFromScreen = SummitDownloadFromScreen;
677	pExa->PrepareAccess = SummitPrepareAccess;
678	pExa->FinishAccess = SummitFinishAccess;
679
680	fPtr->read_mode = -1;
681	fPtr->write_mode = -1;
682	SUMMIT_READ_MODE(OTC01 | BIN8F | BUFFL);
683	SUMMIT_WRITE_MODE(OTC01 | BIN8F | BUFFL);
684	NGLEWrite4(fPtr, VISFX_FOE, FOE_BLEND_ROP);
685	NGLEWrite4(fPtr, VISFX_IBO, GXcopy);
686	NGLEWrite4(fPtr, VISFX_CONTROL, 0);
687
688	ret = exaDriverInit(pScreen, pExa);
689
690	fPtr->glyphs = ps->Glyphs;
691	ps->Glyphs = SummitGlyphs;
692	return ret;
693}
694