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