pm2_exa.c revision a3890ad9
1/*
2 * Copyright 1997-2001 by Alan Hourihane, Wigan, England.
3 * Copyright 2016 by Michael Lorenz
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Alan Hourihane not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission.  Alan Hourihane makes no representations
12 * about the suitability of this software for any purpose.  It is provided
13 * "as is" without express or implied warranty.
14 *
15 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
24 *           Dirk Hohndel, <hohndel@suse.de>
25 *           Stefan Dirsch, <sndirsch@suse.de>
26 *           Mark Vojkovich, <mvojkovi@ucsd.edu>
27 *           Michel Dänzer, <michdaen@iiic.ethz.ch>
28 *
29 * this work is sponsored by S.u.S.E. GmbH, Fuerth, Elsa GmbH, Aachen and
30 * Siemens Nixdorf Informationssysteme
31 *
32 * Permedia 2 accelerated options, EXA style.
33 */
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
39#include <X11/Xarch.h>
40#include "xf86.h"
41#include "xf86_OSproc.h"
42
43#include "xf86Pci.h"
44
45#include "glint_regs.h"
46#include "glint.h"
47
48/*#define PM2_DEBUG*/
49
50#ifdef PM2_DEBUG
51#define STATIC static
52#define ENTER xf86Msg(X_ERROR, "%s>\n", __func__);
53#define DPRINTF xf86Msg
54#else
55#define ENTER
56#define STATIC
57#define DPRINTF while (0) xf86Msg
58#endif
59
60int src_formats[] = {PICT_a8r8g8b8, PICT_x8r8g8b8,
61		     PICT_a8b8g8r8, PICT_x8b8g8r8};
62int tex_formats[] = {PICT_a8r8g8b8, PICT_a8b8g8r8};
63
64static uint32_t Pm2BlendOps[] = {
65    /* Clear */
66    ABM_SrcZERO			| ABM_DstZERO,
67    /* Src */
68    ABM_SrcONE			| ABM_DstZERO,
69    /* Dst */
70    ABM_SrcZERO			| ABM_DstONE,
71    /* Over */
72    ABM_SrcONE			| ABM_DstONE_MINUS_SRC_ALPHA,
73    /* OverReverse */
74    ABM_SrcONE_MINUS_DST_ALPHA	| ABM_DstONE,
75    /* In */
76    ABM_SrcDST_ALPHA		| ABM_DstZERO,
77    /* InReverse */
78    ABM_SrcZERO			| ABM_DstSRC_ALPHA,
79    /* Out */
80    ABM_SrcONE_MINUS_DST_ALPHA	| ABM_DstZERO,
81    /* OutReverse */
82    ABM_SrcZERO			| ABM_DstONE_MINUS_SRC_ALPHA,
83    /* Atop */
84    ABM_SrcDST_ALPHA		| ABM_DstONE_MINUS_SRC_ALPHA,
85    /* AtopReverse */
86    ABM_SrcONE_MINUS_DST_ALPHA	| ABM_DstSRC_ALPHA,
87    /* Xor */
88    ABM_SrcONE_MINUS_DST_ALPHA	| ABM_DstONE_MINUS_SRC_ALPHA,
89    /* Add */
90    ABM_SrcONE			| ABM_DstONE
91};
92
93#define arraysize(ary)        (sizeof(ary) / sizeof(ary[0]))
94
95STATIC void
96Pm2WaitMarker(ScreenPtr pScreen, int Marker)
97{
98	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
99
100	Permedia2Sync(pScrn);
101}
102
103STATIC Bool
104Pm2PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
105		int xdir, int ydir, int rop, Pixel planemask)
106{
107	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
108	GLINTPtr pGlint = GLINTPTR(pScrn);
109
110	ENTER;
111
112	pGlint->BltScanDirection = 0;
113	if (xdir == 1) pGlint->BltScanDirection |= XPositive;
114	if (ydir == 1) pGlint->BltScanDirection |= YPositive;
115
116	GLINT_WAIT(6);
117	DO_PLANEMASK(planemask);
118	GLINT_WRITE_REG(UNIT_DISABLE, AlphaBlendMode);
119	GLINT_WRITE_REG(UNIT_DISABLE, DitherMode);
120	GLINT_WRITE_REG(UNIT_DISABLE, TextureAddressMode);
121
122	GLINT_WRITE_REG(UNIT_DISABLE, ColorDDAMode);
123	if ((rop == GXset) || (rop == GXclear)) {
124		pGlint->FrameBufferReadMode = pGlint->pprod;
125	} else
126	if ((rop == GXcopy) || (rop == GXcopyInverted)) {
127		pGlint->FrameBufferReadMode = pGlint->pprod |FBRM_SrcEnable;
128	} else {
129		pGlint->FrameBufferReadMode = pGlint->pprod | FBRM_SrcEnable |
130							FBRM_DstEnable;
131	}
132	LOADROP(rop);
133	pGlint->srcoff = exaGetPixmapOffset(pSrcPixmap);
134	return TRUE;
135}
136
137STATIC void
138Pm2Copy(PixmapPtr pDstPixmap,
139         int srcX, int srcY, int dstX, int dstY, int w, int h)
140{
141	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
142	GLINTPtr pGlint = GLINTPTR(pScrn);
143	int align;
144	int dstoff = exaGetPixmapOffset(pDstPixmap);
145	int pitch = exaGetPixmapPitch(pDstPixmap);
146
147	ENTER;
148
149	/* assuming constant pitch for now */
150	srcY += pGlint->srcoff / pitch;
151	dstY += dstoff / pitch;
152
153	/* We can only use GXcopy for Packed modes */
154	if ((pGlint->ROP != GXcopy) || (pScrn->bitsPerPixel != 8)) {
155		GLINT_WAIT(5);
156		GLINT_WRITE_REG(pGlint->FrameBufferReadMode, FBReadMode);
157        	Permedia2LoadCoord(pScrn, dstX, dstY, w, h);
158        	GLINT_WRITE_REG(((srcY - dstY) & 0x0FFF) << 16 |
159        			((srcX - dstX) & 0x0FFF), FBSourceDelta);
160	} else {
161  		align = (dstX & pGlint->bppalign) - (srcX & pGlint->bppalign);
162		GLINT_WAIT(6);
163		GLINT_WRITE_REG(pGlint->FrameBufferReadMode|FBRM_Packed, FBReadMode);
164        	Permedia2LoadCoord(pScrn, dstX >> pGlint->BppShift, dstY,
165					(w + 7) >> pGlint->BppShift, h);
166  		GLINT_WRITE_REG(align << 29 | dstX << 16 | (dstX + w), PackedDataLimits);
167        	GLINT_WRITE_REG(((srcX - dstX) & 0x0FFF) << 16 |
168        		       (((srcX & ~pGlint->bppalign) - (dstX & ~pGlint->bppalign)) & 0x0FFF),
169        		       FBSourceDelta);
170	}
171	GLINT_WRITE_REG(PrimitiveRectangle | pGlint->BltScanDirection, Render);
172}
173
174STATIC void
175Pm2DoneCopy(PixmapPtr pPixmap)
176{
177	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
178	GLINTPtr pGlint = GLINTPTR(pScrn);
179
180}
181
182STATIC Bool
183Pm2PrepareSolid(PixmapPtr pPixmap, int rop, Pixel planemask, Pixel color)
184{
185	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
186	GLINTPtr pGlint = GLINTPTR(pScrn);
187
188	ENTER;
189
190	REPLICATE(color);
191
192	GLINT_WAIT(8);
193	GLINT_WRITE_REG(UNIT_DISABLE, AlphaBlendMode);
194	GLINT_WRITE_REG(UNIT_DISABLE, DitherMode);
195	GLINT_WRITE_REG(UNIT_DISABLE, TextureAddressMode);
196	DO_PLANEMASK(planemask);
197	if (rop == GXcopy) {
198		GLINT_WRITE_REG(UNIT_DISABLE, ColorDDAMode);
199		GLINT_WRITE_REG(pGlint->pprod, FBReadMode);
200		GLINT_WRITE_REG(color, FBBlockColor);
201	} else {
202		GLINT_WRITE_REG(UNIT_ENABLE, ColorDDAMode);
203      		GLINT_WRITE_REG(color, ConstantColor);
204		/* We can use Packed mode for filling solid non-GXcopy rasters */
205		GLINT_WRITE_REG(pGlint->pprod|FBRM_DstEnable|FBRM_Packed, FBReadMode);
206	}
207	LOADROP(rop);
208
209	return TRUE;
210}
211
212STATIC void
213Pm2Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
214{
215	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
216	GLINTPtr pGlint = GLINTPTR(pScrn);
217	int offset = exaGetPixmapOffset(pPixmap);
218	int pitch = exaGetPixmapPitch(pPixmap);
219	int w = x2 - x1, h = y2 - y1;
220	int speed = 0;
221
222	ENTER;
223
224	y1 += offset / pitch;
225	if (pGlint->ROP == GXcopy) {
226		GLINT_WAIT(3);
227        	Permedia2LoadCoord(pScrn, x1, y1, w, h);
228		speed = FastFillEnable;
229	} else {
230		GLINT_WAIT(4);
231		Permedia2LoadCoord(pScrn, x1 >> pGlint->BppShift, y1,
232					(w + 7) >> pGlint->BppShift, h);
233  		GLINT_WRITE_REG(x1 << 16 | (x1 + w), PackedDataLimits);
234  		speed = 0;
235	}
236	GLINT_WRITE_REG(PrimitiveRectangle | XPositive | YPositive | speed, Render);
237}
238
239/*
240 * Memcpy-based UTS.
241 */
242STATIC Bool
243Pm2UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
244    char *src, int src_pitch)
245{
246	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
247	GLINTPtr pGlint = GLINTPTR(pScrn);
248	int    offset	   = exaGetPixmapOffset(pDst);
249	unsigned char *dst = pGlint->FbBase + offset;
250	CARD32 *s;
251	int    dst_pitch   = exaGetPixmapPitch(pDst);
252
253	int bpp    = pDst->drawable.bitsPerPixel;
254	int cpp    = (bpp + 7) >> 3;
255	int wBytes = w * cpp;
256	int xx, i, fs = pGlint->FIFOSize, chunk, adr;
257
258	ENTER;
259
260	if (bpp < 24) {
261		/* for now */
262		dst += (x * cpp) + (y * dst_pitch);
263
264		Permedia2Sync(pScrn);
265
266		while (h--) {
267			memcpy(dst, src, wBytes);
268			src += src_pitch;
269			dst += dst_pitch;
270		}
271	} else {
272		/* use host blit */
273		y += offset / dst_pitch;
274		adr = y * (dst_pitch >> 2) + x;
275		DPRINTF(X_ERROR, "%d %d\n", x, y);
276        	while (h--) {
277        		s = (CARD32 *)src;
278        		xx = w;
279        		GLINT_WAIT(2);
280        		DO_PLANEMASK(0xffffffff);
281        		GLINT_WRITE_REG(adr, TextureDownloadOffset);
282			while (xx > 0) {
283				chunk = min(fs - 1, xx);
284	        		GLINT_WAIT(chunk);
285	        	      	GLINT_WRITE_REG(((chunk - 1) << 16) | (0x11 << 4) |
286					0x0d, OutputFIFO);
287				GLINT_MoveDWORDS(
288					(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
289	 				s, chunk);
290	 			xx -= chunk;
291	 			s += chunk;
292			}
293			adr += (dst_pitch >> 2);
294			src += src_pitch;
295		}
296		exaMarkSync(pDst->drawable.pScreen);
297	}
298	return TRUE;
299}
300
301/*
302 * Memcpy-based DFS.
303 */
304STATIC Bool
305Pm2DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
306    char *dst, int dst_pitch)
307{
308 	ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
309	GLINTPtr pGlint    = GLINTPTR(pScrn);
310	unsigned char *src = pGlint->FbBase + exaGetPixmapOffset(pSrc);
311	int    src_pitch   = exaGetPixmapPitch(pSrc);
312
313	ENTER;
314	int bpp    = pSrc->drawable.bitsPerPixel;
315	int cpp    = (bpp + 7) >> 3;
316	int wBytes = w * cpp;
317
318	src += (x * cpp) + (y * src_pitch);
319
320	Permedia2Sync(pScrn);
321
322	while (h--) {
323		memcpy(dst, src, wBytes);
324		src += src_pitch;
325		dst += dst_pitch;
326	}
327
328	return TRUE;
329}
330
331Bool
332Pm2CheckComposite(int op, PicturePtr pSrcPicture,
333                           PicturePtr pMaskPicture,
334                           PicturePtr pDstPicture)
335{
336	int i, ok = FALSE;
337
338	ENTER;
339
340	i = 0;
341	while ((i < arraysize(src_formats)) && (!ok)) {
342		ok =  (pSrcPicture->format == src_formats[i]);
343		i++;
344	}
345
346	if (!ok) {
347		DPRINTF(X_ERROR, "%s: unsupported src format %x\n",
348		    __func__, pSrcPicture->format);
349		return FALSE;
350	}
351
352	if (pDstPicture != NULL) {
353		i = 0;
354		while ((i < arraysize(src_formats)) && (!ok)) {
355			ok =  (pDstPicture->format == src_formats[i]);
356			i++;
357		}
358
359		if (!ok) {
360			DPRINTF(X_ERROR, "%s: unsupported dst format %x\n",
361			    __func__, pDstPicture->format);
362			return FALSE;
363		}
364	}
365
366	DPRINTF(X_ERROR, "src is %x, %d\n", pSrcPicture->format, op);
367
368	if (pMaskPicture != NULL) {
369		i = 0;
370		ok = FALSE;
371		while ((i < arraysize(tex_formats)) && (!ok)) {
372			ok =  (pMaskPicture->format == tex_formats[i]);
373			i++;
374		}
375		if (!ok) {
376			DPRINTF(X_ERROR, "%s: unsupported mask format %x\n",
377			    __func__, pMaskPicture->format);
378			return FALSE;
379		}
380		DPRINTF(X_ERROR, "mask is %x %d %d\n", pMaskPicture->format,
381		    pMaskPicture->pDrawable->width,
382		    pMaskPicture->pDrawable->height);
383		if (op != PictOpOver)
384			return FALSE;
385	}
386	DPRINTF(X_ERROR, "true\n");
387	return TRUE;
388}
389
390Bool
391Pm2PrepareComposite(int op, PicturePtr pSrcPicture,
392                             PicturePtr pMaskPicture,
393                             PicturePtr pDstPicture,
394                             PixmapPtr  pSrc,
395                             PixmapPtr  pMask,
396                             PixmapPtr  pDst)
397{
398	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
399	GLINTPtr pGlint   = GLINTPTR(pScrn);
400
401	ENTER;
402
403	pGlint->no_source_pixmap = FALSE;
404	pGlint->source_is_solid = FALSE;
405
406	if (pSrcPicture->pSourcePict != NULL) {
407		if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) {
408			pGlint->fillcolour =
409			    pSrcPicture->pSourcePict->solidFill.color;
410			DPRINTF(X_ERROR, "%s: solid src %08x\n",
411			    __func__, pGlint->fillcolour);
412			pGlint->no_source_pixmap = TRUE;
413			pGlint->source_is_solid = TRUE;
414		}
415	}
416	if ((pMaskPicture != NULL) && (pMaskPicture->pSourcePict != NULL)) {
417		if (pMaskPicture->pSourcePict->type ==
418		    SourcePictTypeSolidFill) {
419			pGlint->fillcolour =
420			   pMaskPicture->pSourcePict->solidFill.color;
421			DPRINTF(X_ERROR, "%s: solid mask %08x\n",
422			    __func__, pGlint->fillcolour);
423		}
424	}
425	if (pMaskPicture != NULL) {
426		pGlint->mskoff = exaGetPixmapOffset(pMask);
427		pGlint->mskpitch = exaGetPixmapPitch(pMask);
428		pGlint->mskformat = pMaskPicture->format;
429	} else {
430		pGlint->mskoff = 0;
431		pGlint->mskpitch = 0;
432		pGlint->mskformat = 0;
433	}
434	if (pSrc != NULL) {
435		pGlint->source_is_solid =
436		   ((pSrc->drawable.width == 1) && (pSrc->drawable.height == 1));
437		pGlint->srcoff = exaGetPixmapOffset(pSrc);
438		pGlint->srcpitch = exaGetPixmapPitch(pSrc);
439		if (pGlint->source_is_solid) {
440			pGlint->fillcolour = exaGetPixmapFirstPixel(pSrc);
441		}
442	}
443	pGlint->srcformat = pSrcPicture->format;
444	pGlint->dstformat = pDstPicture->format;
445
446
447	pGlint->op = op;
448	/* first things first */
449	if (pGlint->source_is_solid)
450		goto ok;
451	if (pGlint->mskpitch == 0)
452		goto ok;
453	DPRINTF(X_ERROR, "nope\n");
454	return FALSE;
455ok:
456	GLINT_WAIT(10);
457	GLINT_WRITE_REG(UNIT_DISABLE, ColorDDAMode);
458	LOADROP(GXcopy);
459	GLINT_WRITE_REG(0, QStart);
460	GLINT_WRITE_REG(0, dQdx);
461	GLINT_WRITE_REG(0, dQdyDom);
462	GLINT_WRITE_REG(0x20, PMTextureDataFormat);
463	GLINT_WRITE_REG(1 << 20, dSdx);
464	GLINT_WRITE_REG(0, dSdyDom);
465	GLINT_WRITE_REG(0, dTdx);
466	GLINT_WRITE_REG(1 << 20, dTdyDom);
467	return TRUE;
468}
469
470void
471Pm2Comp_Over32Solid(ScrnInfoPtr pScrn, int maskX, int maskY,
472				     int dstX, int dstY,
473				     int width, int height)
474{
475	GLINTPtr pGlint = GLINTPTR(pScrn);
476	unsigned long pp;
477	uint32_t *m;
478	int i, j;
479
480	ENTER;
481
482	/* first blit the source colour into the mask */
483	GLINT_WAIT(8);
484	GLINT_WRITE_REG(UNIT_DISABLE, AlphaBlendMode);
485	GLINT_WRITE_REG(UNIT_DISABLE, DitherMode);
486	GLINT_WRITE_REG(CFBRM_Packed| CWM_Enable, Config);
487	GLINT_WRITE_REG(pGlint->fillcolour, FBBlockColor);
488	DO_PLANEMASK(0x00ffffff);	/* preserve alpha */
489       	Permedia2LoadCoord(pScrn, maskX, maskY + pGlint->mskoff / pGlint->mskpitch, width, height);
490	GLINT_WRITE_REG(
491	    PrimitiveRectangle | XPositive | YPositive | FastFillEnable,
492	    Render);
493
494	/* now do the actual rendering */
495	GLINT_WAIT(15);
496
497	/* enable alpha blending */
498	GLINT_WRITE_REG(
499	    ABM_SrcSRC_ALPHA | ABM_DstONE_MINUS_SRC_ALPHA |
500	    ABM_ColorOrderRGB | UNIT_ENABLE, AlphaBlendMode);
501
502	/* not sure if we need this, everything is in ARGB anyway */
503	GLINT_WRITE_REG(UNIT_ENABLE | DTM_ColorOrderRGB, DitherMode);
504
505	/* setup for drawing the dst rectangle... */
506	GLINT_WRITE_REG(CFBRM_DstEnable | /*CFBRM_Packed|*/ CWM_Enable, Config);
507       	Permedia2LoadCoord(pScrn, dstX, dstY, width, height);
508       	/* point at the texture, 1:1 mapping etc. */
509	GLINT_WRITE_REG(pGlint->mskoff >> 2, PMTextureBaseAddress);
510	GLINT_WRITE_REG(1 | 0xb << 9 | 0xb << 13 | 1 << 1 | 1 << 3, PMTextureReadMode);
511	GLINT_WRITE_REG(1 | TextureModeCopy, TextureColorMode);
512	GLINT_WRITE_REG(1, TextureAddressMode);
513	GLINT_WRITE_REG(maskX << 20, SStart);
514	GLINT_WRITE_REG(maskY << 20, TStart);
515	GLINT_WRITE_REG(PrimitiveRectangle | XPositive | YPositive | TextureEnable,
516	    Render);
517}
518
519void
520Pm2Comp_Op32(ScrnInfoPtr pScrn, int op, int srcX, int srcY,
521				     int dstX, int dstY,
522				     int width, int height)
523{
524	GLINTPtr pGlint = GLINTPTR(pScrn);
525
526	ENTER;
527
528	GLINT_WAIT(8);
529	DO_PLANEMASK(0xffffffff);
530
531	GLINT_WRITE_REG(
532	    Pm2BlendOps[op] |
533	    ABM_ColorOrderRGB | UNIT_ENABLE, AlphaBlendMode);
534	GLINT_WRITE_REG(UNIT_ENABLE | DTM_ColorOrderRGB, DitherMode);
535	GLINT_WRITE_REG(CFBRM_DstEnable | /*CFBRM_Packed|*/ CWM_Enable, Config);
536       	Permedia2LoadCoord(pScrn, dstX, dstY, width, height);
537	GLINT_WRITE_REG(pGlint->srcoff >> 2, PMTextureBaseAddress);
538	GLINT_WRITE_REG(1 | 0xb << 9 | 0xb << 13 | 1 << 1 | 1 << 3, PMTextureReadMode);
539	GLINT_WRITE_REG(1 | TextureModeCopy, TextureColorMode);
540	GLINT_WRITE_REG(1, TextureAddressMode);
541	GLINT_WRITE_REG(srcX << 20, SStart);
542	GLINT_WRITE_REG(srcY << 20, TStart);
543	GLINT_WRITE_REG(PrimitiveRectangle | XPositive | YPositive | TextureEnable,
544	    Render);
545}
546
547void
548Pm2Composite(PixmapPtr pDst, int srcX, int srcY,
549                              int maskX, int maskY,
550                              int dstX, int dstY,
551                              int width, int height)
552{
553	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
554	GLINTPtr pGlint   = GLINTPTR(pScrn);
555	uint32_t dstoff, dstpitch;
556
557	ENTER;
558	dstoff = exaGetPixmapOffset(pDst);
559	dstpitch = exaGetPixmapPitch(pDst);
560	dstY += dstoff / dstpitch;
561	if (pGlint->source_is_solid) {
562		switch (pGlint->op) {
563			case PictOpOver:
564				DPRINTF(X_ERROR, "Over %08x %08x, %d %d\n",
565				    pGlint->mskformat, pGlint->dstformat, dstX, dstY);
566				switch (pGlint->mskformat) {
567					case PICT_a8r8g8b8:
568					case PICT_a8b8g8r8:
569						Pm2Comp_Over32Solid(pScrn,
570						    maskX, maskY,
571						    dstX, dstY,
572						    width, height);
573						break;
574					default:
575						xf86Msg(X_ERROR,
576						  "unsupported mask format\n");
577				}
578				break;
579			default:
580				xf86Msg(X_ERROR, "unsupported op %d\n", pGlint->op);
581		}
582	} else {
583		Pm2Comp_Op32(pScrn, pGlint->op, srcX, srcY, dstX, dstY, width, height);
584	}
585}
586
587Bool
588Pm2InitEXA(ScreenPtr pScreen)
589{
590	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
591	GLINTPtr pGlint = GLINTPTR(pScrn);
592	ExaDriverPtr pExa;
593	int stride, lines;
594
595	ENTER;
596
597	pExa = exaDriverAlloc();
598	if (!pExa)
599		return FALSE;
600
601	pGlint->pExa = pExa;
602
603	pExa->exa_major = EXA_VERSION_MAJOR;
604	pExa->exa_minor = EXA_VERSION_MINOR;
605
606	pExa->memoryBase = pGlint->FbBase;
607	stride = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3);
608	lines = min(pGlint->FbMapSize / stride, 2047);
609	pExa->memorySize = lines * stride;
610	pExa->offScreenBase = stride * pScrn->virtualY;
611	DPRINTF(X_ERROR, "stride: %d\n", stride);
612	DPRINTF(X_ERROR, "pprod: %08x\n", pGlint->pprod);
613	pExa->offScreenBase = stride * pScrn->virtualY;
614
615	/* for now, until I figure out how to do variable stride */
616	pExa->pixmapOffsetAlign = stride;
617	pExa->pixmapPitchAlign = stride;
618
619	pExa->flags = EXA_OFFSCREEN_PIXMAPS;
620
621	pExa->maxX = 2047;
622	pExa->maxY = 2047;
623
624	pExa->WaitMarker = Pm2WaitMarker;
625
626	pExa->PrepareSolid = Pm2PrepareSolid;
627	pExa->Solid = Pm2Solid;
628	pExa->DoneSolid = Pm2DoneCopy;
629	pExa->PrepareCopy = Pm2PrepareCopy;
630	pExa->Copy = Pm2Copy;
631	pExa->DoneCopy = Pm2DoneCopy;
632
633	if (pGlint->render) {
634		pExa->CheckComposite = Pm2CheckComposite;
635		pExa->PrepareComposite = Pm2PrepareComposite;
636		pExa->Composite = Pm2Composite;
637		pExa->DoneComposite = Pm2DoneCopy;
638	}
639
640if (0) {
641	pExa->UploadToScreen = Pm2UploadToScreen;
642	pExa->DownloadFromScreen = Pm2DownloadFromScreen;
643}
644	Permedia2InitializeEngine(pScrn);
645
646	return exaDriverInit(pScreen, pExa);
647}
648