crime_accel.c revision 09f0d67c
109f0d67cSmacallan/* $NetBSD: crime_accel.c,v 1.3 2009/02/25 00:25:02 macallan Exp $ */
2e1ea03a3Smacallan/*
3e1ea03a3Smacallan * Copyright (c) 2008 Michael Lorenz
4e1ea03a3Smacallan * All rights reserved.
5e1ea03a3Smacallan *
6e1ea03a3Smacallan * Redistribution and use in source and binary forms, with or without
7e1ea03a3Smacallan * modification, are permitted provided that the following conditions
8e1ea03a3Smacallan * are met:
9e1ea03a3Smacallan *
10e1ea03a3Smacallan *    - Redistributions of source code must retain the above copyright
11e1ea03a3Smacallan *      notice, this list of conditions and the following disclaimer.
12e1ea03a3Smacallan *    - Redistributions in binary form must reproduce the above
13e1ea03a3Smacallan *      copyright notice, this list of conditions and the following
14e1ea03a3Smacallan *      disclaimer in the documentation and/or other materials provided
15e1ea03a3Smacallan *      with the distribution.
16e1ea03a3Smacallan *
17e1ea03a3Smacallan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18e1ea03a3Smacallan * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19e1ea03a3Smacallan * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20e1ea03a3Smacallan * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21e1ea03a3Smacallan * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22e1ea03a3Smacallan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23e1ea03a3Smacallan * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24e1ea03a3Smacallan * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25e1ea03a3Smacallan * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26e1ea03a3Smacallan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27e1ea03a3Smacallan * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28e1ea03a3Smacallan * POSSIBILITY OF SUCH DAMAGE.
29e1ea03a3Smacallan *
30e1ea03a3Smacallan */
31e1ea03a3Smacallan
32e1ea03a3Smacallan/* a driver for the CRIME rendering engine foundin SGI O2 workstations */
33e1ea03a3Smacallan
34e1ea03a3Smacallan#include "crime.h"
35e1ea03a3Smacallan#include "picturestr.h"
36e1ea03a3Smacallan#include "xaalocal.h"
37e1ea03a3Smacallan
38e1ea03a3Smacallanuint32_t regcache[0x1000];
39e1ea03a3Smacallan
40e1ea03a3Smacallan#define CRIMEREG(p) (volatile uint32_t *)(fPtr->engine + p)
41e1ea03a3Smacallan/*#define WBFLUSH { volatile uint32_t boo = *CRIMEREG(0x4000); }*/
42e1ea03a3Smacallan#define WBFLUSH __asm__ ("nop; sync;")
43e1ea03a3Smacallan#if 0
44e1ea03a3Smacallan#define WRITE4(r, v) {if (regcache[r >> 2] != v) { \
45e1ea03a3Smacallan			*CRIMEREG(r) = v; \
46e1ea03a3Smacallan			regcache[r >> 2] = v; } }
47e1ea03a3Smacallan#else
48e1ea03a3Smacallan#define WRITE4(r, v) { *CRIMEREG(r) = v; }
49e1ea03a3Smacallan#endif
50e1ea03a3Smacallan#define WRITE4ST(r, v) {WBFLUSH; *CRIMEREG(r + CRIME_DE_START) = v; WBFLUSH;}
51e1ea03a3Smacallan#ifdef DEBUG
52e1ea03a3Smacallan#define SYNC { int bail = 0; do {bail++; } \
53e1ea03a3Smacallan          while(((*CRIMEREG(0x4000) & CRIME_DE_IDLE) == 0) && (bail < 10000000)); \
54e1ea03a3Smacallan          if (bail == 10000000) { \
55e1ea03a3Smacallan          	xf86Msg(X_ERROR, "sync timeout\n"); \
56e1ea03a3Smacallan          	WRITE4ST(CRIME_MTE_FLUSH, 0); \
57e1ea03a3Smacallan          	WRITE4ST(CRIME_DE_FLUSH, 0); \
58e1ea03a3Smacallan          } \
59e1ea03a3Smacallan        }
60e1ea03a3Smacallan#else
61e1ea03a3Smacallan#define SYNC do {} while ((*CRIMEREG(0x4000) & CRIME_DE_IDLE) == 0)
62e1ea03a3Smacallan#endif
63e1ea03a3Smacallan#define READY do {} while ((*CRIMEREG(0x4000) & 0x0e000000) != 0x0e000000)
64e1ea03a3Smacallan
65e1ea03a3SmacallanCARD32 CrimeAlphaTextureFormats[] = {PICT_a8, 0};
66e1ea03a3SmacallanCARD32 CrimeTextureFormats[] = {PICT_a8b8g8r8, PICT_a8r8g8b8, 0};
67e1ea03a3Smacallan
68e1ea03a3Smacallanvoid
69e1ea03a3SmacallanCrimeSync(ScrnInfoPtr pScrn)
70e1ea03a3Smacallan{
71e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
72e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
73e1ea03a3Smacallan	volatile uint32_t *status = CRIMEREG(CRIME_DE_STATUS);
74e1ea03a3Smacallan
75e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %08x\n", __func__, *status);
76e1ea03a3Smacallan#endif
77e1ea03a3Smacallan	LOG(CRIME_DEBUG_SYNC);
78e1ea03a3Smacallan	SYNC;
79e1ea03a3Smacallan}
80e1ea03a3Smacallan
81e1ea03a3Smacallanstatic void
82e1ea03a3SmacallanCrimeSetupForScreenToScreenCopy(
83e1ea03a3Smacallan	ScrnInfoPtr  pScrn,
84e1ea03a3Smacallan	int          xdir,
85e1ea03a3Smacallan	int          ydir,
86e1ea03a3Smacallan	int          rop,
87e1ea03a3Smacallan	unsigned int planemask,
88e1ea03a3Smacallan	int          TransparencyColour
89e1ea03a3Smacallan)
90e1ea03a3Smacallan{
91e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
92e1ea03a3Smacallan
93e1ea03a3Smacallan	LOG(CRIME_DEBUG_BITBLT);
94e1ea03a3Smacallan	SYNC;
95e1ea03a3Smacallan#if 0
96e1ea03a3Smacallan	if ((rop == GXcopy) && (planemask == 0xffffffff) && (xdir > 0)) {
97e1ea03a3Smacallan		/* use the MTE */
98e1ea03a3Smacallan		WRITE4(CRIME_MTE_MODE, MTE_MODE_DST_ECC |
99e1ea03a3Smacallan		    MTE_TLB_A << MTE_DST_TLB_SHIFT |
100e1ea03a3Smacallan		    MTE_TLB_A << MTE_SRC_TLB_SHIFT |
101e1ea03a3Smacallan		    MTE_DEPTH_32 << MTE_DEPTH_SHIFT |
102e1ea03a3Smacallan		    MTE_MODE_COPY);
103e1ea03a3Smacallan		fPtr->use_mte = 1;
104e1ea03a3Smacallan		if (ydir > 0) {
105e1ea03a3Smacallan			WRITE4(CRIME_MTE_DST_Y_STEP, 1);
106e1ea03a3Smacallan			WRITE4(CRIME_MTE_SRC_Y_STEP, 1);
107e1ea03a3Smacallan		} else {
108e1ea03a3Smacallan			WRITE4(CRIME_MTE_DST_Y_STEP, -1);
109e1ea03a3Smacallan			WRITE4(CRIME_MTE_SRC_Y_STEP, -1);
110e1ea03a3Smacallan		}
111e1ea03a3Smacallan	} else
112e1ea03a3Smacallan#endif
113e1ea03a3Smacallan		fPtr->use_mte = 0;
114e1ea03a3Smacallan
115e1ea03a3Smacallan	SYNC;
116e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 1);
117e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
118e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
119e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
120e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
121e1ea03a3Smacallan	    DE_DRAWMODE_ROP | DE_DRAWMODE_XFER_EN);
122e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
123e1ea03a3Smacallan		    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
124e1ea03a3Smacallan	fPtr->xdir = xdir;
125e1ea03a3Smacallan	fPtr->ydir = ydir;
126e1ea03a3Smacallan	DONE(CRIME_DEBUG_BITBLT);
127e1ea03a3Smacallan}
128e1ea03a3Smacallan
129e1ea03a3Smacallanstatic void
130e1ea03a3SmacallanCrimeSubsequentScreenToScreenCopy
131e1ea03a3Smacallan(
132e1ea03a3Smacallan	ScrnInfoPtr pScrn,
133e1ea03a3Smacallan	int         xSrc,
134e1ea03a3Smacallan	int         ySrc,
135e1ea03a3Smacallan	int         xDst,
136e1ea03a3Smacallan	int         yDst,
137e1ea03a3Smacallan	int         w,
138e1ea03a3Smacallan	int         h
139e1ea03a3Smacallan)
140e1ea03a3Smacallan{
141e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
142e1ea03a3Smacallan	uint32_t prim = DE_PRIM_RECTANGLE;
143e1ea03a3Smacallan	volatile uint32_t reg, oreg;
144e1ea03a3Smacallan	uint32_t rxa, rya, rxe, rye, rxs, rys, rxd, ryd, rxde, ryde;
145e1ea03a3Smacallan
146e1ea03a3Smacallan	LOG(CRIME_DEBUG_BITBLT);
147e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
148e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d, %d; %d x %d -> %d %d\n", __func__,
149e1ea03a3Smacallan	    xSrc, ySrc, w, h, xDst, yDst);
150e1ea03a3Smacallan#endif
151e1ea03a3Smacallan
152e1ea03a3Smacallan	if ((fPtr->use_mte) && (w > 64) && ((w & 3) == 0) && ((xSrc & 3) == 0) && ((xDst & 3) == 0)) {
153e1ea03a3Smacallan		if (fPtr->ydir == -1) {
154e1ea03a3Smacallan			/* bottom to top */
155e1ea03a3Smacallan			rye = ySrc;
156e1ea03a3Smacallan			rya = ySrc + h - 1;
157e1ea03a3Smacallan			ryd = yDst + h - 1;
158e1ea03a3Smacallan			ryde = yDst;
159e1ea03a3Smacallan		} else {
160e1ea03a3Smacallan			/* top to bottom */
161e1ea03a3Smacallan			rye = ySrc + h - 1;
162e1ea03a3Smacallan			rya = ySrc;
163e1ea03a3Smacallan			ryd = yDst;
164e1ea03a3Smacallan			ryde = yDst + h - 1;
165e1ea03a3Smacallan		}
166e1ea03a3Smacallan		rxa = xSrc << 2;
167e1ea03a3Smacallan		rxe = ((xSrc + w) << 2) - 1;
168e1ea03a3Smacallan		rxd = xDst << 2;
169e1ea03a3Smacallan		rxde = ((xDst + w) << 2) - 1;
170e1ea03a3Smacallan		oreg = *CRIMEREG(0x4000);
171e1ea03a3Smacallan		READY;
172e1ea03a3Smacallan		WRITE4(CRIME_MTE_SRC0, (rxa << 16) | rya);
173e1ea03a3Smacallan		WRITE4(CRIME_MTE_SRC1, (rxe << 16) | rye);
174e1ea03a3Smacallan		WRITE4(CRIME_MTE_DST0, (rxd << 16) | ryd);
175e1ea03a3Smacallan		WBFLUSH;
176e1ea03a3Smacallan		WRITE4ST(CRIME_MTE_DST1, (rxde << 16) | ryde);
177e1ea03a3Smacallan		reg = *CRIMEREG(0x4000);
178e1ea03a3Smacallan
179e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
180e1ea03a3Smacallan		xf86Msg(X_ERROR, "reg: %08x %08x\n", oreg, reg);
181e1ea03a3Smacallan#endif
182e1ea03a3Smacallan	} else {
183e1ea03a3Smacallan		if (fPtr->xdir == -1) {
184e1ea03a3Smacallan			prim |= DE_PRIM_RL;
185e1ea03a3Smacallan			rxe = xDst;
186e1ea03a3Smacallan			rxa = xDst + w - 1;
187e1ea03a3Smacallan			rxs = xSrc + w - 1;
188e1ea03a3Smacallan		} else {
189e1ea03a3Smacallan			prim |= DE_PRIM_LR;
190e1ea03a3Smacallan			rxe = xDst + w - 1;
191e1ea03a3Smacallan			rxa = xDst;
192e1ea03a3Smacallan			rxs = xSrc;
193e1ea03a3Smacallan		}
194e1ea03a3Smacallan		if (fPtr->ydir == -1) {
195e1ea03a3Smacallan			prim |= DE_PRIM_BT;
196e1ea03a3Smacallan			rye = yDst;
197e1ea03a3Smacallan			rya = yDst + h - 1;
198e1ea03a3Smacallan			rys = ySrc + h - 1;
199e1ea03a3Smacallan		} else {
200e1ea03a3Smacallan			prim |= DE_PRIM_TB;
201e1ea03a3Smacallan			rye = yDst + h - 1;
202e1ea03a3Smacallan			rya = yDst;
203e1ea03a3Smacallan			rys = ySrc;
204e1ea03a3Smacallan		}
205e1ea03a3Smacallan
206e1ea03a3Smacallan		READY;
207e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE, prim);
208e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC,(rxs << 16) | (rys & 0xffff));
209e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (rxa << 16) | (rya & 0xffff));
210e1ea03a3Smacallan		WBFLUSH;
211e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1, (rxe << 16) | (rye & 0xffff));
212e1ea03a3Smacallan	}
213e1ea03a3Smacallan	DONE(CRIME_DEBUG_BITBLT);
214e1ea03a3Smacallan}
215e1ea03a3Smacallan
216e1ea03a3Smacallanstatic void
217e1ea03a3SmacallanCrimeSetupForSolidFill
218e1ea03a3Smacallan(
219e1ea03a3Smacallan    ScrnInfoPtr  pScrn,
220e1ea03a3Smacallan    int          colour,
221e1ea03a3Smacallan    int          rop,
222e1ea03a3Smacallan    unsigned int planemask
223e1ea03a3Smacallan)
224e1ea03a3Smacallan{
225e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
226e1ea03a3Smacallan	int i;
227e1ea03a3Smacallan
228e1ea03a3Smacallan	SYNC;
229e1ea03a3Smacallan	LOG(CRIME_DEBUG_RECTFILL);
230e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
231e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
232e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, colour << 8);
233e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
234e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP);
235e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
236e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
237e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
238e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
239e1ea03a3Smacallan	DONE(CRIME_DEBUG_RECTFILL);
240e1ea03a3Smacallan}
241e1ea03a3Smacallan
242e1ea03a3Smacallanstatic void
243e1ea03a3SmacallanCrimeSubsequentSolidFillRect
244e1ea03a3Smacallan(
245e1ea03a3Smacallan    ScrnInfoPtr pScrn,
246e1ea03a3Smacallan    int         x,
247e1ea03a3Smacallan    int         y,
248e1ea03a3Smacallan    int         w,
249e1ea03a3Smacallan    int         h
250e1ea03a3Smacallan)
251e1ea03a3Smacallan{
252e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
253e1ea03a3Smacallan
254e1ea03a3Smacallan	LOG(CRIME_DEBUG_RECTFILL);
255e1ea03a3Smacallan	READY;
256e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x << 16) | (y & 0xffff));
257e1ea03a3Smacallan	WBFLUSH;
258e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
259e1ea03a3Smacallan	    ((x + w - 1) << 16) | ((y + h - 1) & 0xffff));
260e1ea03a3Smacallan	DONE(CRIME_DEBUG_RECTFILL);
261e1ea03a3Smacallan}
262e1ea03a3Smacallan
263e1ea03a3Smacallanvoid
264e1ea03a3SmacallanCrimeSetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
265e1ea03a3Smacallan                                unsigned int planemask, int trans_color,
266e1ea03a3Smacallan                                int bpp, int depth)
267e1ea03a3Smacallan{
268e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
269e1ea03a3Smacallan
270e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
271e1ea03a3Smacallan	SYNC;
272e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
273e1ea03a3Smacallan	if ((bpp == 24) || (depth == 24))
274e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d \n", __func__, bpp, depth);
275e1ea03a3Smacallan#endif
276e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
277e1ea03a3Smacallan			    DE_MODE_TYPE_RGB | DE_MODE_PIXDEPTH_32);
278e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
279e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
280e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
281e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
282e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP |
283e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
284e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
285e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
286e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
287e1ea03a3Smacallan}
288e1ea03a3Smacallan
289e1ea03a3Smacallanvoid
290e1ea03a3SmacallanCrimeSubsequentImageWriteRect(ScrnInfoPtr pScrn,
291e1ea03a3Smacallan                                int x, int y, int w, int h, int skipleft)
292e1ea03a3Smacallan{
293e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
294e1ea03a3Smacallan
295e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
296e1ea03a3Smacallan
297e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
298e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d\n", __func__, x, y, w, h);
299e1ea03a3Smacallan#endif
300e1ea03a3Smacallan
301e1ea03a3Smacallan	fPtr->start = skipleft;
302e1ea03a3Smacallan	x += skipleft;
303e1ea03a3Smacallan	w -= skipleft;
304e1ea03a3Smacallan	if (x < 0) {
305e1ea03a3Smacallan		fPtr->ux = 0;
306e1ea03a3Smacallan		w += x;
307e1ea03a3Smacallan		fPtr->start -= x;
308e1ea03a3Smacallan	} else {
309e1ea03a3Smacallan		fPtr->ux = x;
310e1ea03a3Smacallan	}
311e1ea03a3Smacallan	fPtr->uy = y;
312e1ea03a3Smacallan	fPtr->uw = w;
313e1ea03a3Smacallan	fPtr->uh = h;
314e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
315e1ea03a3Smacallan}
316e1ea03a3Smacallan
317e1ea03a3Smacallanvoid
318e1ea03a3SmacallanCrimeSubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
319e1ea03a3Smacallan{
320e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
321e1ea03a3Smacallan
322e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
32334c4e112Smacallan	SYNC;
324e1ea03a3Smacallan
325e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_ADDR_SRC, (bufno << 13)  + (fPtr->start << 2));
326e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (fPtr->ux << 16) | fPtr->uy);
327e1ea03a3Smacallan	WBFLUSH;
328e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
329e1ea03a3Smacallan		((fPtr->ux + fPtr->uw - 1) << 16) | (fPtr->uy));
330e1ea03a3Smacallan	fPtr->uy++;
331e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
332e1ea03a3Smacallan}
333e1ea03a3Smacallan
334e1ea03a3Smacallanstatic void
335e1ea03a3SmacallanCrimeSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
336e1ea03a3Smacallan        		int fg, int bg,
337e1ea03a3Smacallan			int rop,
338e1ea03a3Smacallan			unsigned int planemask)
339e1ea03a3Smacallan{
340e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
341e1ea03a3Smacallan
342e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
343e1ea03a3Smacallan	SYNC;
344e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
345e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
346e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, fg << 8);
347e1ea03a3Smacallan	if (bg == -1) {
348e1ea03a3Smacallan		/* transparent */
349e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
350e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
351e1ea03a3Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_POLY_STIP);
352e1ea03a3Smacallan	} else {
353e1ea03a3Smacallan		WRITE4(CRIME_DE_BG, bg << 8);
354e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
355e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
356e1ea03a3Smacallan		    DE_DRAWMODE_ROP |
357e1ea03a3Smacallan		    DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_POLY_STIP);
358e1ea03a3Smacallan	}
359e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
360e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
361e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
362e1ea03a3Smacallan}
363e1ea03a3Smacallan
364e1ea03a3Smacallanstatic void
365e1ea03a3SmacallanCrimeSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
366e1ea03a3Smacallan			int x, int y, int w, int h,
367e1ea03a3Smacallan			int skipleft )
368e1ea03a3Smacallan{
369e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
370e1ea03a3Smacallan
371e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
372e1ea03a3Smacallan
373e1ea03a3Smacallan	fPtr->start = skipleft;
374e1ea03a3Smacallan	fPtr->ux = x;
375e1ea03a3Smacallan	fPtr->uy = y;
376e1ea03a3Smacallan	fPtr->uw = w;
377e1ea03a3Smacallan	fPtr->uh = h;
378e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
379e1ea03a3Smacallan}
380e1ea03a3Smacallan
381e1ea03a3Smacallanstatic void
382e1ea03a3SmacallanCrimeSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
383e1ea03a3Smacallan{
384e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
385e1ea03a3Smacallan	uint32_t *boo = (uint32_t *)fPtr->expandbuffers[bufno];
386e1ea03a3Smacallan	int idx = fPtr->uw, x = fPtr->ux;
387e1ea03a3Smacallan
388e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
389e1ea03a3Smacallan	READY;
390e1ea03a3Smacallan
391e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, 0x001f0000 | (fPtr->start << 24));
392e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_PAT, *boo);
393e1ea03a3Smacallan	boo++;
394e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x + fPtr->start << 16) | fPtr->uy);
395e1ea03a3Smacallan	WBFLUSH;
396e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
397e1ea03a3Smacallan		((x + min(idx, 32) - 1) << 16) | (fPtr->uy));
398e1ea03a3Smacallan	idx -= 32;
399e1ea03a3Smacallan	x += 32;
400e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, 0x001f0000);
401e1ea03a3Smacallan
402e1ea03a3Smacallan	while (idx > 0) {
403e1ea03a3Smacallan		WRITE4(CRIME_DE_STIPPLE_PAT, *boo);
404e1ea03a3Smacallan		boo++;
405e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (x << 16) | fPtr->uy);
406e1ea03a3Smacallan		WBFLUSH;
407e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
408e1ea03a3Smacallan			((x + min(idx, 32) - 1) << 16) | (fPtr->uy));
409e1ea03a3Smacallan		idx -= 32;
410e1ea03a3Smacallan		x += 32;
411e1ea03a3Smacallan	}
412e1ea03a3Smacallan	fPtr->uy++;
413e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
414e1ea03a3Smacallan}
415e1ea03a3Smacallan
416e1ea03a3Smacallanstatic void
417e1ea03a3SmacallanCrimeSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
418e1ea03a3Smacallan    unsigned int planemask)
419e1ea03a3Smacallan{
420e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
421e1ea03a3Smacallan
422e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
423e1ea03a3Smacallan
424e1ea03a3Smacallan	SYNC;
425e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
426e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
427e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, color << 8);
428e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
429e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
430e1ea03a3Smacallan		    DE_DRAWMODE_ROP);
431e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
432e1ea03a3Smacallan}
433e1ea03a3Smacallan
434e1ea03a3Smacallanstatic void
435e1ea03a3SmacallanCrimeSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2,
436e1ea03a3Smacallan    int y2, int flags)
437e1ea03a3Smacallan{
438e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
439e1ea03a3Smacallan
440e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
441e1ea03a3Smacallan	READY;
442e1ea03a3Smacallan	if (flags & OMIT_LAST) {
443e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
444e1ea03a3Smacallan			DE_PRIM_LINE | DE_PRIM_LINE_SKIP_END | 2);
445e1ea03a3Smacallan	} else {
446e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
447e1ea03a3Smacallan			DE_PRIM_LINE | 2);
448e1ea03a3Smacallan	}
449e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x1 << 16) | y1);
450e1ea03a3Smacallan	WBFLUSH;
451e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1, (x2 << 16) | y2);
452e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
453e1ea03a3Smacallan}
454e1ea03a3Smacallan
455e1ea03a3Smacallanvoid
456e1ea03a3SmacallanCrimeSetupForDashedLine(ScrnInfoPtr pScrn,
457e1ea03a3Smacallan		int fg, int bg, int rop, unsigned int planemask,
458e1ea03a3Smacallan        	int length, unsigned char *pattern)
459e1ea03a3Smacallan{
460e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
461e1ea03a3Smacallan	uint32_t pat;
462e1ea03a3Smacallan
463e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
464e1ea03a3Smacallan	SYNC;
465e1ea03a3Smacallan
466e1ea03a3Smacallan	fPtr->uw = length;
467e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
468e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
469e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, fg << 8);
470e1ea03a3Smacallan	if (bg == -1) {
471e1ea03a3Smacallan		/* transparent */
472e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
473e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
474e1ea03a3Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_LINE_STIP);
475e1ea03a3Smacallan	} else {
476e1ea03a3Smacallan		WRITE4(CRIME_DE_BG, bg << 8);
477e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
478e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
479e1ea03a3Smacallan		    DE_DRAWMODE_ROP |
480e1ea03a3Smacallan		    DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_LINE_STIP);
481e1ea03a3Smacallan	}
482e1ea03a3Smacallan	/*
483e1ea03a3Smacallan	 * can we trust the Xserver to always hand us a 32bit aligned
484e1ea03a3Smacallan	 * pattern buffer?
485e1ea03a3Smacallan	 */
486e1ea03a3Smacallan	memcpy(&pat, pattern, 4);
487e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_PAT, pat);
488e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
489e1ea03a3Smacallan}
490e1ea03a3Smacallan
491e1ea03a3Smacallanvoid
492e1ea03a3SmacallanCrimeSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn,
493e1ea03a3Smacallan        int x1, int y1, int x2, int y2, int flags, int phase)
494e1ea03a3Smacallan{
495e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
496e1ea03a3Smacallan	uint32_t stipmode;
497e1ea03a3Smacallan
498e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
499e1ea03a3Smacallan	READY;
500e1ea03a3Smacallan
501e1ea03a3Smacallan	if (flags & OMIT_LAST) {
502e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
503e1ea03a3Smacallan			DE_PRIM_LINE | DE_PRIM_LINE_SKIP_END | 2);
504e1ea03a3Smacallan	} else {
505e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
506e1ea03a3Smacallan			DE_PRIM_LINE | 2);
507e1ea03a3Smacallan	}
508e1ea03a3Smacallan
509e1ea03a3Smacallan	stipmode = ((fPtr->uw - 1) << 16) | (phase << 24);
510e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, stipmode);
511e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x1 << 16) | y1);
512e1ea03a3Smacallan	WBFLUSH;
513e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1, (x2 << 16) | y2);
514e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
515e1ea03a3Smacallan}
516e1ea03a3Smacallan
517e1ea03a3Smacallanvoid
518e1ea03a3SmacallanCrimeSetClippingRectangle ( ScrnInfoPtr pScrn,
519e1ea03a3Smacallan                        int left, int top, int right, int bottom)
520e1ea03a3Smacallan{
521e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
522e1ea03a3Smacallan
523e1ea03a3Smacallan	LOG(CRIME_DEBUG_CLIPPING);
524e1ea03a3Smacallan	/* nothing so far */
525e1ea03a3Smacallan	DONE(CRIME_DEBUG_CLIPPING);
526e1ea03a3Smacallan}
527e1ea03a3Smacallan
528e1ea03a3Smacallanvoid
529e1ea03a3SmacallanCrimeDisableClipping (ScrnInfoPtr pScrn)
530e1ea03a3Smacallan{
531e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
532e1ea03a3Smacallan
533e1ea03a3Smacallan	LOG(CRIME_DEBUG_CLIPPING);
534e1ea03a3Smacallan	SYNC;
535e1ea03a3Smacallan
536e1ea03a3Smacallan	WRITE4(CRIME_DE_CLIPMODE, 0);
537e1ea03a3Smacallan	DONE(CRIME_DEBUG_CLIPPING);
538e1ea03a3Smacallan}
539e1ea03a3Smacallan
540e1ea03a3Smacallanstatic Bool
541e1ea03a3SmacallanCrimeSetupForCPUToScreenAlphaTexture (
542e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
543e1ea03a3Smacallan   int		op,
544e1ea03a3Smacallan   CARD16	red,
545e1ea03a3Smacallan   CARD16	green,
546e1ea03a3Smacallan   CARD16	blue,
547e1ea03a3Smacallan   CARD16	alpha,
548e1ea03a3Smacallan   int		alphaType,
549e1ea03a3Smacallan   CARD8	*alphaPtr,
550e1ea03a3Smacallan   int		alphaPitch,
551e1ea03a3Smacallan   int		width,
552e1ea03a3Smacallan   int		height,
553e1ea03a3Smacallan   int		flags
554e1ea03a3Smacallan)
555e1ea03a3Smacallan{
556e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
557e1ea03a3Smacallan
558e1ea03a3Smacallan	if (op != PictOpOver) {
559e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
560e1ea03a3Smacallan		op = PictOpOver;
561e1ea03a3Smacallan	}
562e1ea03a3Smacallan
563e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
564e1ea03a3Smacallan
565e1ea03a3Smacallan	fPtr->alpha_color = ((red & 0xff00) << 16) |
566e1ea03a3Smacallan			    ((green & 0xff00) << 8) |
56709f0d67cSmacallan			    (blue & 0xff00);
568e1ea03a3Smacallan	fPtr->uw = width;
569e1ea03a3Smacallan	fPtr->uh = height;
570e1ea03a3Smacallan	fPtr->us = alphaPitch;
571e1ea03a3Smacallan	fPtr->alpha_texture = alphaPtr;
57209f0d67cSmacallan	fPtr->format = alphaType;
57309f0d67cSmacallan	if (alphaType != PICT_a8) {
57409f0d67cSmacallan		xf86Msg(X_ERROR, "ARGB mask %08x %d\n", (uint32_t)alphaPtr,
57509f0d67cSmacallan		    alphaPitch);
57609f0d67cSmacallan
57709f0d67cSmacallan	}
578e1ea03a3Smacallan	SYNC;
579e1ea03a3Smacallan	/* XXX this register is not where it's supposed to be */
580e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_COLOR, fPtr->alpha_color);
58109f0d67cSmacallan	if (alphaType == PICT_a8) {
58209f0d67cSmacallan		if (fPtr->alpha_color == 0) {
58309f0d67cSmacallan			WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_8 |
584e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
58509f0d67cSmacallan			WRITE4(CRIME_DE_XFER_STEP_X, 1);
58609f0d67cSmacallan			WRITE4(CRIME_DE_ALPHA_FUNC,
58709f0d67cSmacallan			    DE_ALPHA_ADD |
58809f0d67cSmacallan			    (DE_ALPHA_OP_ZERO << DE_ALPHA_OP_SRC_SHIFT) |
58909f0d67cSmacallan			    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
59009f0d67cSmacallan		} else {
59109f0d67cSmacallan			WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
59209f0d67cSmacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
59309f0d67cSmacallan			WRITE4(CRIME_DE_XFER_STEP_X, 4);
59409f0d67cSmacallan			WRITE4(CRIME_DE_ALPHA_FUNC,
59509f0d67cSmacallan			    DE_ALPHA_ADD |
59609f0d67cSmacallan			    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
59709f0d67cSmacallan			    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
59809f0d67cSmacallan		}
599e1ea03a3Smacallan	} else {
600e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
601e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
602e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_STEP_X, 4);
603e1ea03a3Smacallan		WRITE4(CRIME_DE_ALPHA_FUNC,
604e1ea03a3Smacallan		    DE_ALPHA_ADD |
605e1ea03a3Smacallan		    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
606e1ea03a3Smacallan		    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
60709f0d67cSmacallan	}
608e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
609e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
610e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
611e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
612e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
613e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
614e1ea03a3Smacallan	return TRUE;
615e1ea03a3Smacallan}
616e1ea03a3Smacallan
617e1ea03a3Smacallanvoid
618e1ea03a3SmacallanCrimeSubsequentCPUToScreenAlphaTexture (
619e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
620e1ea03a3Smacallan    int		dstx,
621e1ea03a3Smacallan    int		dsty,
622e1ea03a3Smacallan    int		srcx,
623e1ea03a3Smacallan    int		srcy,
624e1ea03a3Smacallan    int		width,
625e1ea03a3Smacallan    int		height
626e1ea03a3Smacallan)
627e1ea03a3Smacallan{
628e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
629e1ea03a3Smacallan	unsigned char *aptr;
630e1ea03a3Smacallan	uint32_t *dptr, aval;
631e1ea03a3Smacallan	int i, j;
632e1ea03a3Smacallan	int bufnum = 0;
633e1ea03a3Smacallan
634e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
635e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
636e1ea03a3Smacallan	xf86Msg(X_ERROR, "%d %d %d %d %d %d\n",srcx, srcy, dstx, dsty, width,
637e1ea03a3Smacallan	    height);
638e1ea03a3Smacallan#endif
639e1ea03a3Smacallan	aptr = fPtr->alpha_texture + (fPtr->us * srcy) + srcx;
640e1ea03a3Smacallan	for (i = 0; i < height; i++) {
641e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
642e1ea03a3Smacallan		if (fPtr->alpha_color == 0) {
643e1ea03a3Smacallan			memcpy(dptr, aptr, width);
644e1ea03a3Smacallan		} else {
645e1ea03a3Smacallan			for (j = 0; j < width; j++) {
646e1ea03a3Smacallan				aval = aptr[j];
647e1ea03a3Smacallan				*dptr = aval | fPtr->alpha_color;
648e1ea03a3Smacallan				dptr++;
649e1ea03a3Smacallan			}
650e1ea03a3Smacallan		}
651e1ea03a3Smacallan		READY;
652e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
653e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
654e1ea03a3Smacallan		WBFLUSH;
655e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
656e1ea03a3Smacallan			((dstx + width - 1) << 16) | (dsty + i));
657e1ea03a3Smacallan		bufnum++;
658e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
659e1ea03a3Smacallan		aptr += fPtr->us;
660e1ea03a3Smacallan	}
661e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
662e1ea03a3Smacallan}
663e1ea03a3Smacallan
66409f0d67cSmacallanvoid
66509f0d67cSmacallanCrimeSubsequentCPUToScreenAlphaTexture32 (
66609f0d67cSmacallan    ScrnInfoPtr	pScrn,
66709f0d67cSmacallan    int		dstx,
66809f0d67cSmacallan    int		dsty,
66909f0d67cSmacallan    int		srcx,
67009f0d67cSmacallan    int		srcy,
67109f0d67cSmacallan    int		width,
67209f0d67cSmacallan    int		height
67309f0d67cSmacallan)
67409f0d67cSmacallan{
67509f0d67cSmacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
67609f0d67cSmacallan	uint8_t *aptr;
67709f0d67cSmacallan	uint32_t *dptr, *sptr;
67809f0d67cSmacallan	int i, j;
67909f0d67cSmacallan	int bufnum = 0;
68009f0d67cSmacallan
68109f0d67cSmacallan	LOG(CRIME_DEBUG_XRENDER);
68209f0d67cSmacallan#ifndef CRIME_DEBUG_LOUD
68309f0d67cSmacallan	xf86Msg(X_ERROR, "%d %d %d %d %d %d\n",srcx, srcy, dstx, dsty, width,
68409f0d67cSmacallan	    height);
68509f0d67cSmacallan#endif
68609f0d67cSmacallan	aptr = fPtr->alpha_texture + (fPtr->us * srcy) + (srcx << 2);
68709f0d67cSmacallan	for (i = 0; i < height; i++) {
68809f0d67cSmacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
68909f0d67cSmacallan		sptr = (uint32_t *)aptr;
69009f0d67cSmacallan		for (j = 0; j < width; j++) {
69109f0d67cSmacallan			*dptr = (*sptr >> 24) | fPtr->alpha_color;
69209f0d67cSmacallan#ifdef CRIME_DEBUG_LOUD
69309f0d67cSmacallan			xf86Msg(X_ERROR, "%08x %08x\n", *sptr, *dptr);
69409f0d67cSmacallan#endif
69509f0d67cSmacallan			sptr++;
69609f0d67cSmacallan			dptr++;
69709f0d67cSmacallan		}
69809f0d67cSmacallan		READY;
69909f0d67cSmacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
70009f0d67cSmacallan		WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
70109f0d67cSmacallan		WBFLUSH;
70209f0d67cSmacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
70309f0d67cSmacallan			((dstx + width - 1) << 16) | (dsty + i));
70409f0d67cSmacallan		bufnum++;
70509f0d67cSmacallan		if (bufnum == 8) bufnum = 0;
70609f0d67cSmacallan		aptr += fPtr->us;
70709f0d67cSmacallan	}
70809f0d67cSmacallan	DONE(CRIME_DEBUG_XRENDER);
70909f0d67cSmacallan}
71009f0d67cSmacallan
711e1ea03a3Smacallanstatic Bool
712e1ea03a3SmacallanCrimeSetupForCPUToScreenTexture (
713e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
714e1ea03a3Smacallan   int		op,
715e1ea03a3Smacallan   int		texType,
716e1ea03a3Smacallan   CARD8	*texPtr,
717e1ea03a3Smacallan   int		texPitch,
718e1ea03a3Smacallan   int		width,
719e1ea03a3Smacallan   int		height,
720e1ea03a3Smacallan   int		flags
721e1ea03a3Smacallan)
722e1ea03a3Smacallan{
723e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
724e1ea03a3Smacallan
725e1ea03a3Smacallan	if (op != PictOpOver) {
726e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
727e1ea03a3Smacallan		op = PictOpOver;
728e1ea03a3Smacallan	}
729e1ea03a3Smacallan
730e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
731e1ea03a3Smacallan
732e1ea03a3Smacallan	fPtr->uw = width;
733e1ea03a3Smacallan	fPtr->uh = height;
734e1ea03a3Smacallan	fPtr->us = texPitch;
735e1ea03a3Smacallan	fPtr->alpha_texture = texPtr;
736e1ea03a3Smacallan	SYNC;
737e1ea03a3Smacallan	if (texType == PICT_a8b8g8r8) {
738e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
739e1ea03a3Smacallan				    DE_MODE_TYPE_ABGR | DE_MODE_PIXDEPTH_32);
740e1ea03a3Smacallan	} else {
741e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
742e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
743e1ea03a3Smacallan	}
744e1ea03a3Smacallan	fPtr->format = texType;
745e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
746e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
747e1ea03a3Smacallan	    DE_ALPHA_ADD |
748e1ea03a3Smacallan	    (DE_ALPHA_OP_ONE/*SRC_ALPHA*/ << DE_ALPHA_OP_SRC_SHIFT) |
749e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
750e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
751e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
752e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
753e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
754e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
755e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
756e1ea03a3Smacallan	return TRUE;
757e1ea03a3Smacallan}
758e1ea03a3Smacallan
759e1ea03a3Smacallanvoid
760e1ea03a3SmacallanCrimeSubsequentCPUToScreenTexture (
761e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
762e1ea03a3Smacallan    int		dstx,
763e1ea03a3Smacallan    int		dsty,
764e1ea03a3Smacallan    int		srcx,
765e1ea03a3Smacallan    int		srcy,
766e1ea03a3Smacallan    int		width,
767e1ea03a3Smacallan    int		height
768e1ea03a3Smacallan)
769e1ea03a3Smacallan{
770e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
771e1ea03a3Smacallan	unsigned char *aptr, *lptr;
772e1ea03a3Smacallan	uint32_t *dptr, *sptr, aval, pixel;
773e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
774e1ea03a3Smacallan	int bufnum = 0;
775e1ea03a3Smacallan
776e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
777e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
778e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d\n", __func__,
779e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height);
780e1ea03a3Smacallan#endif
781e1ea03a3Smacallan	if ((width == 1) || (fPtr->format != PICT_a8r8g8b8)) {
782e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d %d %d\n", __func__,
783e1ea03a3Smacallan		    srcx, srcy, dstx, dsty, width, height, fPtr->uw, fPtr->us);
784e1ea03a3Smacallan		return;
785e1ea03a3Smacallan	}
786e1ea03a3Smacallan
787e1ea03a3Smacallan	aptr = fPtr->alpha_texture + (srcx << 2);
788e1ea03a3Smacallan	lptr = aptr + (fPtr->us * srcy);
789e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
790e1ea03a3Smacallan		rep = 128 / fPtr->uw;
791e1ea03a3Smacallan		period = rep * fPtr->uw;
792e1ea03a3Smacallan	}
793e1ea03a3Smacallan
794e1ea03a3Smacallan	if (fPtr->format == PICT_a8b8g8r8) {
795e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
796e1ea03a3Smacallan		xf86Msg(X_ERROR, "ABGR\n");
797e1ea03a3Smacallan#endif
798e1ea03a3Smacallan		for (i = 0; i < height; i++) {
799e1ea03a3Smacallan			dptr = (uint32_t *)fPtr->buffers[bufnum];
800e1ea03a3Smacallan			memcpy(dptr, aptr, fPtr->us);
801e1ea03a3Smacallan			READY;
802e1ea03a3Smacallan			WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
803e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
804e1ea03a3Smacallan			WBFLUSH;
805e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
806e1ea03a3Smacallan				((dstx + width - 1) << 16) | (dsty + i));
807e1ea03a3Smacallan			bufnum++;
808e1ea03a3Smacallan			if (bufnum == 8) bufnum = 0;
809e1ea03a3Smacallan			aptr += fPtr->us;
810e1ea03a3Smacallan		}
811e1ea03a3Smacallan	} else {
812e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
813e1ea03a3Smacallan		xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)aptr, fPtr->uw);
814e1ea03a3Smacallan#endif
815e1ea03a3Smacallan		lcnt = fPtr->uh - srcy;
816e1ea03a3Smacallan		for (i = 0; i < height; i++) {
817e1ea03a3Smacallan			dptr = (uint32_t *)fPtr->buffers[bufnum];
818e1ea03a3Smacallan			for (k = 0; k < rep; k++) {
819e1ea03a3Smacallan				sptr = (uint32_t *)aptr;
820e1ea03a3Smacallan				for (j = 0; j < fPtr->uw; j++) {
821e1ea03a3Smacallan					pixel = *sptr;
822e1ea03a3Smacallan					*dptr = (pixel << 8) | (pixel >> 24);
823e1ea03a3Smacallan					dptr++;
824e1ea03a3Smacallan					sptr++;
825e1ea03a3Smacallan				}
826e1ea03a3Smacallan			}
827e1ea03a3Smacallan			xoff = 0;
828e1ea03a3Smacallan			READY;
829e1ea03a3Smacallan			WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
830e1ea03a3Smacallan			while (xoff < width) {
831e1ea03a3Smacallan				xa = dstx + xoff;
832e1ea03a3Smacallan				xe = dstx + min(xoff + period, width) - 1;
833e1ea03a3Smacallan				READY;
834e1ea03a3Smacallan				WRITE4(CRIME_DE_X_VERTEX_0,
835e1ea03a3Smacallan				    xa << 16 | (dsty + i));
836e1ea03a3Smacallan				WBFLUSH;
837e1ea03a3Smacallan				WRITE4ST(CRIME_DE_X_VERTEX_1,
838e1ea03a3Smacallan					(xe << 16) | (dsty + i));
839e1ea03a3Smacallan				xoff += period;
840e1ea03a3Smacallan			}
841e1ea03a3Smacallan			bufnum++;
842e1ea03a3Smacallan			if (bufnum == 8) bufnum = 0;
843e1ea03a3Smacallan			lcnt--;
844e1ea03a3Smacallan			if (lcnt == 0) {
845e1ea03a3Smacallan				aptr = lptr;
846e1ea03a3Smacallan				lcnt = fPtr->uh;
847e1ea03a3Smacallan			} else
848e1ea03a3Smacallan				aptr += fPtr->us;
849e1ea03a3Smacallan		}
850e1ea03a3Smacallan	}
851e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
852e1ea03a3Smacallan}
853e1ea03a3Smacallan
854e1ea03a3Smacallanstatic Bool
855e1ea03a3SmacallanCrimeSetupForCPUToScreenTextureMask(
856e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
857e1ea03a3Smacallan   int		op,
858e1ea03a3Smacallan   int		texType,
859e1ea03a3Smacallan   CARD8	*srcPtr,
860e1ea03a3Smacallan   int		srcPitch,
861e1ea03a3Smacallan   CARD8	*mskPtr,
862e1ea03a3Smacallan   int		mskPitch,
863e1ea03a3Smacallan   int		width,
864e1ea03a3Smacallan   int		height,
865e1ea03a3Smacallan   int		flags
866e1ea03a3Smacallan)
867e1ea03a3Smacallan{
868e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
869e1ea03a3Smacallan
870e1ea03a3Smacallan	if (op != PictOpOver) {
871e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
872e1ea03a3Smacallan		op = PictOpOver;
873e1ea03a3Smacallan	}
874e1ea03a3Smacallan
875e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
876e1ea03a3Smacallan
877e1ea03a3Smacallan	fPtr->uw = width;
878e1ea03a3Smacallan	fPtr->uh = height;
879e1ea03a3Smacallan	fPtr->us = srcPitch >> 2;
880e1ea03a3Smacallan	if (PICT_FORMAT_BPP(texType) == 32) {
881e1ea03a3Smacallan		fPtr->um = mskPitch >> 2;
882e1ea03a3Smacallan	} else
883e1ea03a3Smacallan		fPtr->um = mskPitch;
884e1ea03a3Smacallan	fPtr->msk = (uint8_t *)mskPtr;
885e1ea03a3Smacallan	fPtr->src = (uint8_t *)srcPtr;
886e1ea03a3Smacallan	fPtr->texture_depth = PICT_FORMAT_BPP(texType);
887e1ea03a3Smacallan
888e1ea03a3Smacallan	SYNC;
889e1ea03a3Smacallan	/* always expect ARGB for now */
890e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
891e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
892e1ea03a3Smacallan	fPtr->format = texType;
893e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
894e1ea03a3Smacallan	    DE_ALPHA_ADD |
895e1ea03a3Smacallan	    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
896e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
897e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
898e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
899e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
900e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
901e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
902e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
903e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
904e1ea03a3Smacallan	return TRUE;
905e1ea03a3Smacallan}
906e1ea03a3Smacallan
907e1ea03a3Smacallanvoid
908e1ea03a3SmacallanCrimeSubsequentCPUToScreenTextureMask32(
909e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
910e1ea03a3Smacallan    int		dstx,
911e1ea03a3Smacallan    int		dsty,
912e1ea03a3Smacallan    int		srcx,
913e1ea03a3Smacallan    int		srcy,
914e1ea03a3Smacallan    int		maskx,
915e1ea03a3Smacallan    int		masky,
916e1ea03a3Smacallan    int		width,
917e1ea03a3Smacallan    int		height
918e1ea03a3Smacallan)
919e1ea03a3Smacallan{
920e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
921e1ea03a3Smacallan	uint32_t *lsptr, *lmptr, *asptr, *amptr;
922e1ea03a3Smacallan	uint32_t *dptr, *sptr, *mptr, aval, pixel, mask;
923e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
924e1ea03a3Smacallan	int bufnum = 0;
925e1ea03a3Smacallan	int sr, sg, sb, sa, mr, mg, mb, ma, rr, gg, bb, aa;
926e1ea03a3Smacallan
927e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
928e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
929e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d; %d %d %d\n", __func__,
930e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height, maskx, masky, fPtr->um);
931e1ea03a3Smacallan#endif
932e1ea03a3Smacallan	sptr = fPtr->src + (srcx << 2);
933e1ea03a3Smacallan	mptr = fPtr->msk + (srcx << 2);
934e1ea03a3Smacallan	lsptr = sptr + (fPtr->us * srcy);
935e1ea03a3Smacallan	lmptr = mptr + (fPtr->um * srcy);
936e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
937e1ea03a3Smacallan		rep = 128 / fPtr->uw;
938e1ea03a3Smacallan		period = rep * fPtr->uw;
939e1ea03a3Smacallan	}
940e1ea03a3Smacallan
941e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
942e1ea03a3Smacallan	xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)aptr, fPtr->uw);
943e1ea03a3Smacallan#endif
944e1ea03a3Smacallan	lcnt = fPtr->uh - srcy;
945e1ea03a3Smacallan	for (i = 0; i < height; i++) {
946e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
947e1ea03a3Smacallan		for (k = 0; k < rep; k++) {
948e1ea03a3Smacallan			asptr = lsptr;
949e1ea03a3Smacallan			amptr = lmptr;
950e1ea03a3Smacallan			for (j = 0; j < fPtr->uw; j++) {
951e1ea03a3Smacallan				pixel = *asptr;
952e1ea03a3Smacallan				mask = *amptr;
953e1ea03a3Smacallan				if (mask == 0xffffffff) {
954e1ea03a3Smacallan					*dptr = (pixel >> 24) | (pixel << 8);
955e1ea03a3Smacallan				} else if (mask == 0x00000000) {
956e1ea03a3Smacallan					*dptr = 0;
957e1ea03a3Smacallan				} else {
958e1ea03a3Smacallan					/* input is ARGB */
959e1ea03a3Smacallan					sb = pixel & 0xff;
960e1ea03a3Smacallan					sg = (pixel >> 8) & 0xff;
961e1ea03a3Smacallan					sr = (pixel >> 16) & 0xff;
962e1ea03a3Smacallan					sa = (pixel >> 24) & 0xff;
963e1ea03a3Smacallan					mb = mask & 0xff;
964e1ea03a3Smacallan					mg = (mask >> 8) & 0xff;
965e1ea03a3Smacallan					mr = (mask >> 16) & 0xff;
966e1ea03a3Smacallan					ma = (mask >> 24) & 0xff;
967e1ea03a3Smacallan
968e1ea03a3Smacallan					/* and here we need an RGBA pixel */
969e1ea03a3Smacallan					bb = (((sb * mb) + 0x80) & 0xff00);
970e1ea03a3Smacallan					gg = (((sg * mg) + 0x80) & 0xff00) << 8;
971e1ea03a3Smacallan					rr = (((sr * mr) + 0x80) & 0xff00) << 16;
972e1ea03a3Smacallan					aa = (((sa * ma) + 0x80) & 0xff00) >> 8;
973e1ea03a3Smacallan					/*
974e1ea03a3Smacallan					 * actually we could let the HW do this stuff
975e1ea03a3Smacallan					 */
976e1ea03a3Smacallan					*dptr = aa | rr | gg | bb;
977e1ea03a3Smacallan				}
978e1ea03a3Smacallan				dptr++;
979e1ea03a3Smacallan				asptr++;
980e1ea03a3Smacallan				amptr++;
981e1ea03a3Smacallan			}
982e1ea03a3Smacallan		}
983e1ea03a3Smacallan		xoff = 0;
984e1ea03a3Smacallan		READY;
985e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
986e1ea03a3Smacallan		while (xoff < width) {
987e1ea03a3Smacallan			xa = dstx + xoff;
988e1ea03a3Smacallan			xe = dstx + min(xoff + period, width) - 1;
989e1ea03a3Smacallan			READY;
990e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0,
991e1ea03a3Smacallan			    xa << 16 | (dsty + i));
992e1ea03a3Smacallan			WBFLUSH;
993e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
994e1ea03a3Smacallan				(xe << 16) | (dsty + i));
995e1ea03a3Smacallan			xoff += period;
996e1ea03a3Smacallan		}
997e1ea03a3Smacallan		bufnum++;
998e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
999e1ea03a3Smacallan		lcnt--;
1000e1ea03a3Smacallan		if (lcnt == 0) {
1001e1ea03a3Smacallan			/* back to the beginning */
1002e1ea03a3Smacallan			lsptr = sptr;
1003e1ea03a3Smacallan			lmptr = mptr;
1004e1ea03a3Smacallan			lcnt = fPtr->uh;
1005e1ea03a3Smacallan		} else
1006e1ea03a3Smacallan			/* next line */
1007e1ea03a3Smacallan			lsptr += fPtr->us;
1008e1ea03a3Smacallan			lmptr += fPtr->um;
1009e1ea03a3Smacallan	}
1010e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1011e1ea03a3Smacallan}
1012e1ea03a3Smacallan
1013e1ea03a3Smacallanvoid
1014e1ea03a3SmacallanCrimeSubsequentCPUToScreenTextureMask8(
1015e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
1016e1ea03a3Smacallan    int		dstx,
1017e1ea03a3Smacallan    int		dsty,
1018e1ea03a3Smacallan    int		srcx,
1019e1ea03a3Smacallan    int		srcy,
1020e1ea03a3Smacallan    int		maskx,
1021e1ea03a3Smacallan    int		masky,
1022e1ea03a3Smacallan    int		width,
1023e1ea03a3Smacallan    int		height
1024e1ea03a3Smacallan)
1025e1ea03a3Smacallan{
1026e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1027e1ea03a3Smacallan	uint32_t *lsptr, *asptr;
1028e1ea03a3Smacallan	uint32_t *dptr, *sptr, aval, pixel, mask;
1029e1ea03a3Smacallan	uint8_t  *lmptr, *amptr, *mptr;
1030e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
1031e1ea03a3Smacallan	int bufnum = 0;
1032e1ea03a3Smacallan	int sr, sg, sb, sa, rr, gg, bb, aa;
1033e1ea03a3Smacallan
1034e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1035e1ea03a3Smacallan#ifndef CRIME_DEBUG_LOUD
1036e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d\n", __func__,
1037e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height);
1038e1ea03a3Smacallan#endif
1039e1ea03a3Smacallan	sptr = (uint32_t *)fPtr->src + (fPtr->us * srcy) + (srcx << 2);
1040e1ea03a3Smacallan	mptr = (uint8_t *)fPtr->msk + (fPtr->um * srcy) + srcx;
1041e1ea03a3Smacallan	lsptr = sptr;
1042e1ea03a3Smacallan	lmptr = mptr;
1043e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
1044e1ea03a3Smacallan		rep = 128 / fPtr->uw;
1045e1ea03a3Smacallan		period = rep * fPtr->uw;
1046e1ea03a3Smacallan	}
1047e1ea03a3Smacallan
1048e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
1049e1ea03a3Smacallan	xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)aptr, fPtr->uw);
1050e1ea03a3Smacallan#endif
1051e1ea03a3Smacallan	lcnt = fPtr->uh;
1052e1ea03a3Smacallan	for (i = 0; i < height; i++) {
1053e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
1054e1ea03a3Smacallan		for (k = 0; k < rep; k++) {
1055e1ea03a3Smacallan			asptr = lsptr;
1056e1ea03a3Smacallan			amptr = lmptr;
1057e1ea03a3Smacallan			for (j = 0; j < fPtr->uw; j++) {
1058e1ea03a3Smacallan				pixel = *asptr;
1059e1ea03a3Smacallan				mask = *amptr;
1060e1ea03a3Smacallan				if (mask == 0xff) {
1061e1ea03a3Smacallan					*dptr = (pixel >> 24) | (pixel << 8);
1062e1ea03a3Smacallan				} else if (mask == 0x00) {
1063e1ea03a3Smacallan					*dptr = 0;
1064e1ea03a3Smacallan				} else {
1065e1ea03a3Smacallan					/* input is ARGB */
1066e1ea03a3Smacallan					sb = pixel & 0xff;
1067e1ea03a3Smacallan					sg = (pixel >> 8) & 0xff;
1068e1ea03a3Smacallan					sr = (pixel >> 16) & 0xff;
1069e1ea03a3Smacallan					sa = (pixel >> 24) & 0xff;
1070e1ea03a3Smacallan
1071e1ea03a3Smacallan					/* and here we need an RGBA pixel */
1072e1ea03a3Smacallan					bb = (((sb * mask) + 0x80) & 0xff00);
1073e1ea03a3Smacallan					gg = (((sg * mask) + 0x80) & 0xff00)
1074e1ea03a3Smacallan					     << 8;
1075e1ea03a3Smacallan					rr = (((sr * mask) + 0x80) & 0xff00)
1076e1ea03a3Smacallan					     << 16;
1077e1ea03a3Smacallan					aa = (((sa * mask) + 0x80) & 0xff00)
1078e1ea03a3Smacallan					     >> 8;
1079e1ea03a3Smacallan					/*
1080e1ea03a3Smacallan					 * actually we could let the HW do this
1081e1ea03a3Smacallan					 * stuff
1082e1ea03a3Smacallan					 */
1083e1ea03a3Smacallan					*dptr = aa | rr | gg | bb;
1084e1ea03a3Smacallan				}
1085e1ea03a3Smacallan				dptr++;
1086e1ea03a3Smacallan				asptr++;
1087e1ea03a3Smacallan				amptr++;
1088e1ea03a3Smacallan			}
1089e1ea03a3Smacallan		}
1090e1ea03a3Smacallan		xoff = 0;
1091e1ea03a3Smacallan		SYNC;
1092e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
1093e1ea03a3Smacallan		while (xoff < width) {
1094e1ea03a3Smacallan			xa = dstx + xoff;
1095e1ea03a3Smacallan			xe = dstx + min(xoff + period, width) - 1;
1096e1ea03a3Smacallan			READY;
1097e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0,
1098e1ea03a3Smacallan			    xa << 16 | (dsty + i));
1099e1ea03a3Smacallan			WBFLUSH;
1100e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
1101e1ea03a3Smacallan				(xe << 16) | (dsty + i));
1102e1ea03a3Smacallan			xoff += period;
1103e1ea03a3Smacallan		}
1104e1ea03a3Smacallan		bufnum++;
1105e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
1106e1ea03a3Smacallan		lcnt--;
1107e1ea03a3Smacallan		if (lcnt == 0) {
1108e1ea03a3Smacallan			/* back to the beginning */
1109e1ea03a3Smacallan			lsptr = sptr;
1110e1ea03a3Smacallan			lmptr = mptr;
1111e1ea03a3Smacallan			lcnt = fPtr->uh;
1112e1ea03a3Smacallan		} else
1113e1ea03a3Smacallan			/* next line */
1114e1ea03a3Smacallan			lsptr += fPtr->us;
1115e1ea03a3Smacallan			lmptr += fPtr->um;
1116e1ea03a3Smacallan	}
1117e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1118e1ea03a3Smacallan}
1119e1ea03a3Smacallan
1120e1ea03a3Smacallanstatic void
1121e1ea03a3SmacallanCrimeDoCPUToScreenComposite(
1122e1ea03a3Smacallan   	CARD8      op,
1123e1ea03a3Smacallan        PicturePtr pSrc,
1124e1ea03a3Smacallan        PicturePtr pMask,
1125e1ea03a3Smacallan        PicturePtr pDst,
1126e1ea03a3Smacallan        INT16      xSrc,
1127e1ea03a3Smacallan        INT16      ySrc,
1128e1ea03a3Smacallan        INT16      xMask,
1129e1ea03a3Smacallan        INT16      yMask,
1130e1ea03a3Smacallan        INT16      xDst,
1131e1ea03a3Smacallan        INT16      yDst,
1132e1ea03a3Smacallan        CARD16     width,
1133e1ea03a3Smacallan        CARD16     height
1134e1ea03a3Smacallan)
1135e1ea03a3Smacallan{
1136e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1137e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1138e1ea03a3Smacallan	RegionRec region;
1139e1ea03a3Smacallan	CARD32 *formats;
1140e1ea03a3Smacallan	int flags = 0;
1141e1ea03a3Smacallan	BoxPtr pbox;
1142e1ea03a3Smacallan	int nbox, w, h;
1143e1ea03a3Smacallan
1144e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1145e1ea03a3Smacallan	if (pSrc->transform || (pMask && pMask->transform)) {
1146e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: transform?!\n", __func__);
1147e1ea03a3Smacallan		return;
1148e1ea03a3Smacallan	}
1149e1ea03a3Smacallan
1150e1ea03a3Smacallan	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) {
1151e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: alpha-map?!\n", __func__);
1152e1ea03a3Smacallan		return;
1153e1ea03a3Smacallan	}
1154e1ea03a3Smacallan
1155e1ea03a3Smacallan	xDst += pDst->pDrawable->x;
1156e1ea03a3Smacallan	yDst += pDst->pDrawable->y;
1157e1ea03a3Smacallan	xSrc += pSrc->pDrawable->x;
1158e1ea03a3Smacallan	ySrc += pSrc->pDrawable->y;
1159e1ea03a3Smacallan
1160e1ea03a3Smacallan	if(pMask) {
1161e1ea03a3Smacallan		CARD16 red, green, blue, alpha;
1162e1ea03a3Smacallan		CARD32 pixel =
1163e1ea03a3Smacallan		    *((CARD32*)(((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr));
116409f0d67cSmacallan#ifdef CRIME_DEBUG_LOUD
1165e1ea03a3Smacallan		if(pMask->componentAlpha) {
1166e1ea03a3Smacallan			xf86Msg(X_ERROR, "%s: alpha component mask\n",
1167e1ea03a3Smacallan			    __func__);
116809f0d67cSmacallan			xf86Msg(X_ERROR, "src: %d x %d\n", pSrc->pDrawable->width,
116909f0d67cSmacallan			    pSrc->pDrawable->height);
1170e1ea03a3Smacallan		}
117109f0d67cSmacallan#endif
1172e1ea03a3Smacallan		if ((pSrc->pDrawable->width == 1) &&
1173e1ea03a3Smacallan		    (pSrc->pDrawable->height == 1)) {
1174e1ea03a3Smacallan
1175e1ea03a3Smacallan			if(!XAAGetRGBAFromPixel(pixel, &red, &green, &blue,
1176e1ea03a3Smacallan			    &alpha, pSrc->format)) {
1177e1ea03a3Smacallan				xf86Msg(X_ERROR, "%s: can't read pixel\n", __func__);
1178e1ea03a3Smacallan				return;
1179e1ea03a3Smacallan			}
1180e1ea03a3Smacallan			xMask += pMask->pDrawable->x;
1181e1ea03a3Smacallan			yMask += pMask->pDrawable->y;
1182e1ea03a3Smacallan
1183e1ea03a3Smacallan			/* pull out color expandable operations here */
1184e1ea03a3Smacallan			if(pMask->format == PICT_a1) {
1185e1ea03a3Smacallan				PixmapPtr pPix = (PixmapPtr)(pMask->pDrawable);
1186e1ea03a3Smacallan				int skipleft;
1187e1ea03a3Smacallan
1188e1ea03a3Smacallan				if (alpha == 0xffff) {
1189e1ea03a3Smacallan					/* actually we can but for now we don't care */
1190e1ea03a3Smacallan					xf86Msg(X_ERROR,
1191e1ea03a3Smacallan					   "can't colour expand with alpha\n");
1192e1ea03a3Smacallan					return;
1193e1ea03a3Smacallan				}
1194e1ea03a3Smacallan				if (op != PictOpOver) {
1195e1ea03a3Smacallan					xf86Msg(X_ERROR, "!over\n");
1196e1ea03a3Smacallan					return;
1197e1ea03a3Smacallan				}
1198e1ea03a3Smacallan				if (pMask->repeat) {
1199e1ea03a3Smacallan					xf86Msg(X_ERROR, "mono repeat\n");
1200e1ea03a3Smacallan					return;
1201e1ea03a3Smacallan				}
1202e1ea03a3Smacallan				if (!miComputeCompositeRegion (&region, pSrc,
1203e1ea03a3Smacallan				    pMask, pDst, xSrc, ySrc, xMask, yMask, xDst,
1204e1ea03a3Smacallan				    yDst, width, height)) {
1205e1ea03a3Smacallan					return;
1206e1ea03a3Smacallan				}
1207e1ea03a3Smacallan
1208e1ea03a3Smacallan				nbox = REGION_NUM_RECTS(&region);
1209e1ea03a3Smacallan				pbox = REGION_RECTS(&region);
1210e1ea03a3Smacallan
1211e1ea03a3Smacallan				if(!nbox) {
1212e1ea03a3Smacallan					return;
1213e1ea03a3Smacallan				}
1214e1ea03a3Smacallan
1215e1ea03a3Smacallan				XAAGetPixelFromRGBA(&pixel, red, green, blue, 0,
1216e1ea03a3Smacallan				    pDst->format);
1217e1ea03a3Smacallan
1218e1ea03a3Smacallan				xMask -= xDst;
1219e1ea03a3Smacallan				yMask -= yDst;
1220e1ea03a3Smacallan
1221e1ea03a3Smacallan				while(nbox--) {
1222e1ea03a3Smacallan					skipleft = pbox->x1 + xMask;
1223e1ea03a3Smacallan
1224e1ea03a3Smacallan					(*infoRec->WriteBitmap)(infoRec->pScrn, 					    pbox->x1, pbox->y1,
1225e1ea03a3Smacallan					    pbox->x2 - pbox->x1,
1226e1ea03a3Smacallan					    pbox->y2 - pbox->y1,
1227e1ea03a3Smacallan					    (unsigned char*)(pPix->devPrivate.ptr) + 					    (pPix->devKind *
1228e1ea03a3Smacallan					    (pbox->y1 + yMask)) + ((skipleft >> 3) & ~3),
1229e1ea03a3Smacallan					    pPix->devKind, skipleft & 31, pixel, -1,
1230e1ea03a3Smacallan					    GXcopy, ~0);
1231e1ea03a3Smacallan					pbox++;
1232e1ea03a3Smacallan				}
1233e1ea03a3Smacallan
1234e1ea03a3Smacallan				/* WriteBitmap sets the Sync flag */
1235e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1236e1ea03a3Smacallan				DONE(CRIME_DEBUG_XRENDER);
1237e1ea03a3Smacallan				return;
1238e1ea03a3Smacallan			}
123909f0d67cSmacallan			if((pMask->format == PICT_a8) ||
124009f0d67cSmacallan			   (pMask->format == PICT_a8r8g8b8)) {
1241e1ea03a3Smacallan
1242e1ea03a3Smacallan				w = pMask->pDrawable->width;
1243e1ea03a3Smacallan				h = pMask->pDrawable->height;
1244e1ea03a3Smacallan
1245e1ea03a3Smacallan				if(pMask->repeat) {
1246e1ea03a3Smacallan					flags |= XAA_RENDER_REPEAT;
1247e1ea03a3Smacallan				}
1248e1ea03a3Smacallan
1249e1ea03a3Smacallan				if (!miComputeCompositeRegion (&region, pSrc, pMask,
1250e1ea03a3Smacallan				    pDst, xSrc, ySrc, xMask, yMask, xDst, yDst,
1251e1ea03a3Smacallan				    width, height)) {
1252e1ea03a3Smacallan					return;
1253e1ea03a3Smacallan				}
1254e1ea03a3Smacallan
1255e1ea03a3Smacallan				nbox = REGION_NUM_RECTS(&region);
1256e1ea03a3Smacallan				pbox = REGION_RECTS(&region);
1257e1ea03a3Smacallan
1258e1ea03a3Smacallan				if(!nbox) {
1259e1ea03a3Smacallan					REGION_UNINIT(pScreen, &region);
1260e1ea03a3Smacallan					return;
1261e1ea03a3Smacallan				}
1262e1ea03a3Smacallan
1263e1ea03a3Smacallan				CrimeSetupForCPUToScreenAlphaTexture(infoRec->pScrn,
1264e1ea03a3Smacallan				    op, red, green, blue, alpha, pMask->format,
1265e1ea03a3Smacallan				    ((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr,
1266e1ea03a3Smacallan				    ((PixmapPtr)(pMask->pDrawable))->devKind,
1267e1ea03a3Smacallan				    w, h, flags);
1268e1ea03a3Smacallan
1269e1ea03a3Smacallan				xMask -= xDst;
1270e1ea03a3Smacallan				yMask -= yDst;
1271e1ea03a3Smacallan
127209f0d67cSmacallan				if (pMask->format != PICT_a8) {
127309f0d67cSmacallan					while(nbox--) {
127409f0d67cSmacallan						CrimeSubsequentCPUToScreenAlphaTexture32(
127509f0d67cSmacallan						    infoRec->pScrn,
127609f0d67cSmacallan						    pbox->x1, pbox->y1, pbox->x1 + xMask,
127709f0d67cSmacallan						    pbox->y1 + yMask, pbox->x2 - pbox->x1,
127809f0d67cSmacallan						    pbox->y2 - pbox->y1);
127909f0d67cSmacallan						pbox++;
128009f0d67cSmacallan					}
128109f0d67cSmacallan				} else {
128209f0d67cSmacallan					while(nbox--) {
128309f0d67cSmacallan						CrimeSubsequentCPUToScreenAlphaTexture(
128409f0d67cSmacallan						    infoRec->pScrn,
128509f0d67cSmacallan						    pbox->x1, pbox->y1, pbox->x1 + xMask,
128609f0d67cSmacallan						    pbox->y1 + yMask, pbox->x2 - pbox->x1,
128709f0d67cSmacallan						    pbox->y2 - pbox->y1);
128809f0d67cSmacallan						pbox++;
128909f0d67cSmacallan					}
1290e1ea03a3Smacallan				}
1291e1ea03a3Smacallan				SET_SYNC_FLAG(infoRec);
1292e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1293e1ea03a3Smacallan				DONE(CRIME_DEBUG_XRENDER);
1294e1ea03a3Smacallan				return;
1295e1ea03a3Smacallan			} else {
1296e1ea03a3Smacallan				xf86Msg(X_ERROR, "unknown mask %x\n", pMask->format);
1297e1ea03a3Smacallan			}
1298e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1299e1ea03a3Smacallan			DONE(CRIME_DEBUG_XRENDER);
1300e1ea03a3Smacallan			return;
1301e1ea03a3Smacallan		} else {
1302e1ea03a3Smacallan			/* source isn't solid */
1303e1ea03a3Smacallan
1304e1ea03a3Smacallan			w = pSrc->pDrawable->width;
1305e1ea03a3Smacallan			h = pSrc->pDrawable->height;
1306e1ea03a3Smacallan
1307e1ea03a3Smacallan			if(pSrc->repeat)
1308e1ea03a3Smacallan				flags |= XAA_RENDER_REPEAT;
1309e1ea03a3Smacallan
1310e1ea03a3Smacallan			if (!miComputeCompositeRegion (&region, pSrc, pMask,
1311e1ea03a3Smacallan			    pDst, xSrc, ySrc, xMask, yMask, xDst, yDst,
1312e1ea03a3Smacallan			    width, height)) {
1313e1ea03a3Smacallan				return;
1314e1ea03a3Smacallan			}
1315e1ea03a3Smacallan
1316e1ea03a3Smacallan			nbox = REGION_NUM_RECTS(&region);
1317e1ea03a3Smacallan			pbox = REGION_RECTS(&region);
1318e1ea03a3Smacallan
1319e1ea03a3Smacallan			if(!nbox) {
1320e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1321e1ea03a3Smacallan				return;
1322e1ea03a3Smacallan			}
1323e1ea03a3Smacallan			CrimeSetupForCPUToScreenTextureMask(
1324e1ea03a3Smacallan			    infoRec->pScrn, op, pMask->format,
1325e1ea03a3Smacallan			    ((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr,
1326e1ea03a3Smacallan			    ((PixmapPtr)(pSrc->pDrawable))->devKind,
1327e1ea03a3Smacallan			    ((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr,
1328e1ea03a3Smacallan			    ((PixmapPtr)(pMask->pDrawable))->devKind,
1329e1ea03a3Smacallan			    w, h, flags);
1330e1ea03a3Smacallan
1331e1ea03a3Smacallan			xSrc -= xDst;
1332e1ea03a3Smacallan			ySrc -= yDst;
1333e1ea03a3Smacallan
1334e1ea03a3Smacallan			if (PICT_FORMAT_BPP(pMask->format) == 32) {
1335e1ea03a3Smacallan				while(nbox--) {
1336e1ea03a3Smacallan					CrimeSubsequentCPUToScreenTextureMask32(
1337e1ea03a3Smacallan					    infoRec->pScrn,
1338e1ea03a3Smacallan					    pbox->x1, pbox->y1,
1339e1ea03a3Smacallan					    pbox->x1 + xSrc, pbox->y1 + ySrc,
1340e1ea03a3Smacallan					    xMask, yMask,
1341e1ea03a3Smacallan					    pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
1342e1ea03a3Smacallan					pbox++;
1343e1ea03a3Smacallan				}
1344e1ea03a3Smacallan			} else {
1345e1ea03a3Smacallan				while(nbox--) {
1346e1ea03a3Smacallan					CrimeSubsequentCPUToScreenTextureMask8(
1347e1ea03a3Smacallan					    infoRec->pScrn,
1348e1ea03a3Smacallan					    pbox->x1, pbox->y1, pbox->x1 + xSrc,
1349e1ea03a3Smacallan					    pbox->y1 + ySrc,
1350e1ea03a3Smacallan					    xMask, yMask,
1351e1ea03a3Smacallan					    pbox->x2 - pbox->x1,
1352e1ea03a3Smacallan					    pbox->y2 - pbox->y1);
1353e1ea03a3Smacallan					pbox++;
1354e1ea03a3Smacallan				}
1355e1ea03a3Smacallan			}
1356e1ea03a3Smacallan
1357e1ea03a3Smacallan			SET_SYNC_FLAG(infoRec);
1358e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1359e1ea03a3Smacallan			DONE(CRIME_DEBUG_XRENDER);
1360e1ea03a3Smacallan			return;
1361e1ea03a3Smacallan		}
1362e1ea03a3Smacallan	} else {	/* no mask */
1363e1ea03a3Smacallan		formats = infoRec->CPUToScreenTextureFormats;
1364e1ea03a3Smacallan
1365e1ea03a3Smacallan		w = pSrc->pDrawable->width;
1366e1ea03a3Smacallan		h = pSrc->pDrawable->height;
1367e1ea03a3Smacallan
1368e1ea03a3Smacallan		if(pSrc->repeat)
1369e1ea03a3Smacallan			flags |= XAA_RENDER_REPEAT;
1370e1ea03a3Smacallan
1371e1ea03a3Smacallan		while(*formats != pSrc->format) {
1372e1ea03a3Smacallan			if(!(*formats)) {
1373e1ea03a3Smacallan				xf86Msg(X_ERROR,
1374e1ea03a3Smacallan				    "%s: format %x not found\n",
1375e1ea03a3Smacallan				    __func__, pSrc->format);
1376e1ea03a3Smacallan				return;
1377e1ea03a3Smacallan			}
1378e1ea03a3Smacallan			formats++;
1379e1ea03a3Smacallan		}
1380e1ea03a3Smacallan
1381e1ea03a3Smacallan		if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
1382e1ea03a3Smacallan                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
1383e1ea03a3Smacallan                                   width, height)) {
1384e1ea03a3Smacallan			return;
1385e1ea03a3Smacallan		}
1386e1ea03a3Smacallan
1387e1ea03a3Smacallan		nbox = REGION_NUM_RECTS(&region);
1388e1ea03a3Smacallan		pbox = REGION_RECTS(&region);
1389e1ea03a3Smacallan
1390e1ea03a3Smacallan		if(!nbox) {
1391e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1392e1ea03a3Smacallan			return;
1393e1ea03a3Smacallan		}
1394e1ea03a3Smacallan
1395e1ea03a3Smacallan		CrimeSetupForCPUToScreenTexture(infoRec->pScrn,
1396e1ea03a3Smacallan			op, pSrc->format,
1397e1ea03a3Smacallan			((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr,
1398e1ea03a3Smacallan			((PixmapPtr)(pSrc->pDrawable))->devKind,
1399e1ea03a3Smacallan			w, h, flags);
1400e1ea03a3Smacallan
1401e1ea03a3Smacallan		xSrc -= xDst;
1402e1ea03a3Smacallan		ySrc -= yDst;
1403e1ea03a3Smacallan
1404e1ea03a3Smacallan		while(nbox--) {
1405e1ea03a3Smacallan			CrimeSubsequentCPUToScreenTexture(infoRec->pScrn,
1406e1ea03a3Smacallan			    pbox->x1, pbox->y1, pbox->x1 + xSrc,
1407e1ea03a3Smacallan			    pbox->y1 + ySrc, pbox->x2 - pbox->x1,
1408e1ea03a3Smacallan			    pbox->y2 - pbox->y1);
1409e1ea03a3Smacallan			pbox++;
1410e1ea03a3Smacallan		}
1411e1ea03a3Smacallan
1412e1ea03a3Smacallan		SET_SYNC_FLAG(infoRec);
1413e1ea03a3Smacallan		REGION_UNINIT(pScreen, &region);
1414e1ea03a3Smacallan		DONE(CRIME_DEBUG_XRENDER);
1415e1ea03a3Smacallan		return;
1416e1ea03a3Smacallan	}
1417e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: shouldn't be here\n", __func__);
1418e1ea03a3Smacallan}
1419e1ea03a3Smacallan
1420e1ea03a3Smacallanstatic void
1421e1ea03a3SmacallanCrimeDoScreenToScreenComposite(
1422e1ea03a3Smacallan   	CARD8      op,
1423e1ea03a3Smacallan        PicturePtr pSrc,
1424e1ea03a3Smacallan        PicturePtr pMask,
1425e1ea03a3Smacallan        PicturePtr pDst,
1426e1ea03a3Smacallan        INT16      xSrc,
1427e1ea03a3Smacallan        INT16      ySrc,
1428e1ea03a3Smacallan        INT16      xMask,
1429e1ea03a3Smacallan        INT16      yMask,
1430e1ea03a3Smacallan        INT16      xDst,
1431e1ea03a3Smacallan        INT16      yDst,
1432e1ea03a3Smacallan        CARD16     width,
1433e1ea03a3Smacallan        CARD16     height
1434e1ea03a3Smacallan)
1435e1ea03a3Smacallan{
1436e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1437e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1438e1ea03a3Smacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1439e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1440e1ea03a3Smacallan	RegionRec region;
1441e1ea03a3Smacallan	CARD32 *formats;
1442e1ea03a3Smacallan	int flags = 0;
1443e1ea03a3Smacallan	BoxPtr pbox;
1444e1ea03a3Smacallan	int nbox;
1445e1ea03a3Smacallan	int xs, ys, xd, yd, w, h;
1446e1ea03a3Smacallan
1447e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1448e1ea03a3Smacallan	if (pSrc->transform || (pMask && pMask->transform)) {
1449e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: mask?!\n", __func__);
1450e1ea03a3Smacallan		return;
1451e1ea03a3Smacallan	}
1452e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d\n", __func__, op);
1453e1ea03a3Smacallan	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) {
1454e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: alpha-map\n", __func__);
1455e1ea03a3Smacallan		return;
1456e1ea03a3Smacallan	}
1457e1ea03a3Smacallan
1458e1ea03a3Smacallan	xDst += pDst->pDrawable->x;
1459e1ea03a3Smacallan	yDst += pDst->pDrawable->y;
1460e1ea03a3Smacallan	xSrc += pSrc->pDrawable->x;
1461e1ea03a3Smacallan	ySrc += pSrc->pDrawable->y;
1462e1ea03a3Smacallan
1463e1ea03a3Smacallan	formats = infoRec->CPUToScreenTextureFormats;
1464e1ea03a3Smacallan
1465e1ea03a3Smacallan	w = pSrc->pDrawable->width;
1466e1ea03a3Smacallan	h = pSrc->pDrawable->height;
1467e1ea03a3Smacallan
1468e1ea03a3Smacallan	if(pSrc->repeat)
1469e1ea03a3Smacallan		flags |= XAA_RENDER_REPEAT;
1470e1ea03a3Smacallan
1471e1ea03a3Smacallan	while(*formats != pSrc->format) {
1472e1ea03a3Smacallan		if(!(*formats)) return;
1473e1ea03a3Smacallan		formats++;
1474e1ea03a3Smacallan	}
1475e1ea03a3Smacallan
1476e1ea03a3Smacallan	if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
1477e1ea03a3Smacallan	    xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
1478e1ea03a3Smacallan		return;
1479e1ea03a3Smacallan
1480e1ea03a3Smacallan	nbox = REGION_NUM_RECTS(&region);
1481e1ea03a3Smacallan	pbox = REGION_RECTS(&region);
1482e1ea03a3Smacallan
1483e1ea03a3Smacallan	if(!nbox) {
1484e1ea03a3Smacallan		REGION_UNINIT(pScreen, &region);
1485e1ea03a3Smacallan		return;
1486e1ea03a3Smacallan	}
1487e1ea03a3Smacallan
1488e1ea03a3Smacallan	SYNC;
1489e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
1490e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1491e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 1);
1492e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
1493e1ea03a3Smacallan	    DE_ALPHA_ADD |
1494e1ea03a3Smacallan	    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
1495e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
1496e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1497e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
1498e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
1499e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
1500e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
1501e1ea03a3Smacallan
1502e1ea03a3Smacallan	xSrc -= xDst;
1503e1ea03a3Smacallan	ySrc -= yDst;
1504e1ea03a3Smacallan
1505e1ea03a3Smacallan	/* assume no overlap - might bite us in the arse at some point */
1506e1ea03a3Smacallan	while(nbox--) {
1507e1ea03a3Smacallan		xs = pbox->x1 + xSrc;
1508e1ea03a3Smacallan		ys = pbox->y1 + ySrc;
1509e1ea03a3Smacallan		xd = pbox->x1;
1510e1ea03a3Smacallan		yd = pbox->y1;
1511e1ea03a3Smacallan		w = pbox->x2 - pbox->x1;
1512e1ea03a3Smacallan		h = pbox->y2 - pbox->y1;
1513e1ea03a3Smacallan		READY;
1514e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC,(xs << 16) | (ys & 0xffff));
1515e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (xd << 16) | (yd & 0xffff));
1516e1ea03a3Smacallan		WBFLUSH;
1517e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
1518e1ea03a3Smacallan		    ((xd + w - 1) << 16) | ((yd + h - 1) & 0xffff));
1519e1ea03a3Smacallan		pbox++;
1520e1ea03a3Smacallan	}
1521e1ea03a3Smacallan
1522e1ea03a3Smacallan	SET_SYNC_FLAG(infoRec);
1523e1ea03a3Smacallan	REGION_UNINIT(pScreen, &region);
1524e1ea03a3Smacallan	return;
1525e1ea03a3Smacallan}
1526e1ea03a3Smacallan
1527e1ea03a3Smacallanstatic Bool
1528e1ea03a3SmacallanCrimeComposite(
1529e1ea03a3Smacallan   	CARD8      op,
1530e1ea03a3Smacallan        PicturePtr pSrc,
1531e1ea03a3Smacallan        PicturePtr pMask,
1532e1ea03a3Smacallan        PicturePtr pDst,
1533e1ea03a3Smacallan        INT16      xSrc,
1534e1ea03a3Smacallan        INT16      ySrc,
1535e1ea03a3Smacallan        INT16      xMask,
1536e1ea03a3Smacallan        INT16      yMask,
1537e1ea03a3Smacallan        INT16      xDst,
1538e1ea03a3Smacallan        INT16      yDst,
1539e1ea03a3Smacallan        CARD16     width,
1540e1ea03a3Smacallan        CARD16     height
1541e1ea03a3Smacallan)
1542e1ea03a3Smacallan{
1543e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1544e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1545e1ea03a3Smacallan
1546e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1547e1ea03a3Smacallan
1548e1ea03a3Smacallan	if(!REGION_NUM_RECTS(pDst->pCompositeClip))
1549e1ea03a3Smacallan		return TRUE;
1550e1ea03a3Smacallan
1551e1ea03a3Smacallan	if(!infoRec->pScrn->vtSema)
1552e1ea03a3Smacallan		return FALSE;
1553e1ea03a3Smacallan
1554e1ea03a3Smacallan	if((pDst->pDrawable->type == DRAWABLE_WINDOW) ||
1555e1ea03a3Smacallan	    IS_OFFSCREEN_PIXMAP(pDst->pDrawable)) {
1556e1ea03a3Smacallan		if ((pSrc->pDrawable->type == DRAWABLE_WINDOW) ||
1557e1ea03a3Smacallan		    IS_OFFSCREEN_PIXMAP(pSrc->pDrawable)) {
1558e1ea03a3Smacallan			/* screen-to-screen */
1559e1ea03a3Smacallan			CrimeDoScreenToScreenComposite(op, pSrc, pMask, pDst,
1560e1ea03a3Smacallan			    xSrc, ySrc, xMask, yMask,
1561e1ea03a3Smacallan			    xDst, yDst, width, height);
1562e1ea03a3Smacallan			return TRUE;
1563e1ea03a3Smacallan		} else {
1564e1ea03a3Smacallan			/* CPU-to-screen composite */
1565e1ea03a3Smacallan			if (op != PictOpOver)
1566e1ea03a3Smacallan				xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
1567e1ea03a3Smacallan			CrimeDoCPUToScreenComposite(op, pSrc, pMask, pDst,
1568e1ea03a3Smacallan			    xSrc, ySrc, xMask, yMask,
1569e1ea03a3Smacallan			    xDst, yDst, width, height);
1570e1ea03a3Smacallan			return TRUE;
1571e1ea03a3Smacallan		}
1572e1ea03a3Smacallan	} else {
1573e1ea03a3Smacallan		if ((pSrc->pDrawable->type == DRAWABLE_WINDOW) ||
1574e1ea03a3Smacallan		    IS_OFFSCREEN_PIXMAP(pSrc->pDrawable)) {
1575e1ea03a3Smacallan			/* screen-to-RAM */
1576e1ea03a3Smacallan			xf86Msg(X_ERROR, "%s: screen-to-RAM composite\n",
1577e1ea03a3Smacallan			   __func__);
1578e1ea03a3Smacallan			return TRUE;
1579e1ea03a3Smacallan		} else {
1580e1ea03a3Smacallan			/* RAM-to-RAM */
1581e1ea03a3Smacallan			return FALSE;
1582e1ea03a3Smacallan		}
1583e1ea03a3Smacallan	}
1584e1ea03a3Smacallan	xf86Msg(X_ERROR, "composite fucked\n");
1585e1ea03a3Smacallan}
1586e1ea03a3Smacallan
1587e1ea03a3Smacallanstatic void
1588e1ea03a3SmacallanCrimePolyPoint(
1589e1ea03a3Smacallan    DrawablePtr pDraw,
1590e1ea03a3Smacallan    GCPtr pGC,
1591e1ea03a3Smacallan    int mode,
1592e1ea03a3Smacallan    int npt,
1593e1ea03a3Smacallan    xPoint *pptInit
1594e1ea03a3Smacallan)
1595e1ea03a3Smacallan{
1596e1ea03a3Smacallan	ScreenPtr pScreen = pDraw->pScreen;
1597e1ea03a3Smacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1598e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1599e1ea03a3Smacallan	BoxPtr pBox;
1600e1ea03a3Smacallan	xPoint *ppt, *pts;
1601e1ea03a3Smacallan	int x1, x2, y1, y2, x, y, i, nBox;
1602e1ea03a3Smacallan
1603e1ea03a3Smacallan	/* make pointlist origin relative */
1604e1ea03a3Smacallan	ppt = pptInit;
1605e1ea03a3Smacallan	if (mode == CoordModePrevious) {
1606e1ea03a3Smacallan		for (i = 0; i < npt; i++) {
1607e1ea03a3Smacallan			ppt++;
1608e1ea03a3Smacallan			ppt->x += (ppt-1)->x;
1609e1ea03a3Smacallan			ppt->y += (ppt-1)->y;
1610e1ea03a3Smacallan		}
1611e1ea03a3Smacallan	}
1612e1ea03a3Smacallan	SYNC;
1613e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, pGC->fgPixel << 8);
1614e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, pGC->alu);
1615e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, pGC->planemask);
1616e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1617e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP);
1618e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE, DE_PRIM_POINT);
1619e1ea03a3Smacallan	for (nBox = REGION_NUM_RECTS (pGC->pCompositeClip),
1620e1ea03a3Smacallan	    pBox = REGION_RECTS (pGC->pCompositeClip);
1621e1ea03a3Smacallan	    nBox--; pBox++) {
1622e1ea03a3Smacallan
1623e1ea03a3Smacallan		pts = pptInit;
1624e1ea03a3Smacallan		for (i = 0; i < npt; i++) {
1625e1ea03a3Smacallan			x1 = pBox->x1;
1626e1ea03a3Smacallan			y1 = pBox->y1;
1627e1ea03a3Smacallan			x2 = pBox->x2;
1628e1ea03a3Smacallan			y2 = pBox->y2;
1629e1ea03a3Smacallan			x = pts->x + pDraw->x;
1630e1ea03a3Smacallan			y = pts->y + pDraw->y;
1631e1ea03a3Smacallan			if (x1 <= x && x < x2 && y1 <= y && y < y2) {
1632e1ea03a3Smacallan
1633e1ea03a3Smacallan		 		READY;
1634e1ea03a3Smacallan				WRITE4ST(CRIME_DE_X_VERTEX_0,
1635e1ea03a3Smacallan					(x << 16) | y);
1636e1ea03a3Smacallan			}
1637e1ea03a3Smacallan			pts++;
1638e1ea03a3Smacallan		}
1639e1ea03a3Smacallan	}
1640e1ea03a3Smacallan}
1641e1ea03a3Smacallan
1642e1ea03a3Smacallanstatic void
1643e1ea03a3SmacallanCrimeValidatePolyPoint(
1644e1ea03a3Smacallan   GCPtr         pGC,
1645e1ea03a3Smacallan   unsigned long changes,
1646e1ea03a3Smacallan   DrawablePtr   pDraw )
1647e1ea03a3Smacallan{
1648e1ea03a3Smacallan
1649e1ea03a3Smacallan	if ((pDraw->type == DRAWABLE_WINDOW) ||
1650e1ea03a3Smacallan	    IS_OFFSCREEN_PIXMAP(pDraw)) {
1651e1ea03a3Smacallan		pGC->ops->PolyPoint = CrimePolyPoint;
1652e1ea03a3Smacallan	} else
1653e1ea03a3Smacallan		xf86Msg(X_ERROR, "boo\n");
1654e1ea03a3Smacallan}
165534c4e112Smacallanstatic void
165634c4e112SmacallanCrimePolyArc(DrawablePtr pDraw,
165734c4e112Smacallan               GCPtr pGC,
165834c4e112Smacallan               int narcs,
165934c4e112Smacallan               xArc *parcs)
166034c4e112Smacallan{
166134c4e112Smacallan    xArc *arc;
166234c4e112Smacallan    BoxRec box;
166334c4e112Smacallan    int i, x2, y2;
166434c4e112Smacallan    RegionPtr cclip;
166534c4e112Smacallan
166634c4e112Smacallan    cclip = pGC->pCompositeClip;
166734c4e112Smacallan
166834c4e112Smacallan    if(!REGION_NUM_RECTS(cclip))
166934c4e112Smacallan	return;
167034c4e112Smacallan
167134c4e112Smacallan    for (arc = parcs, i = narcs; --i >= 0; arc++) {
167234c4e112Smacallan	if (miCanZeroArc(arc)) {
167334c4e112Smacallan	    box.x1 = arc->x + pDraw->x;
167434c4e112Smacallan	    box.y1 = arc->y + pDraw->y;
167534c4e112Smacallan 	    x2 = box.x1 + (int)arc->width + 1;
167634c4e112Smacallan 	    box.x2 = x2;
167734c4e112Smacallan 	    y2 = box.y1 + (int)arc->height + 1;
167834c4e112Smacallan 	    box.y2 = y2;
167934c4e112Smacallan 	    if ( (x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) &&
168034c4e112Smacallan 		    (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) )
168134c4e112Smacallan		miZeroPolyArc(pDraw, pGC, 1, arc);
168234c4e112Smacallan	}
168334c4e112Smacallan	else
168434c4e112Smacallan	    miPolyArc(pDraw, pGC, 1, arc);
168534c4e112Smacallan    }
168634c4e112Smacallan}
168734c4e112Smacallan
168834c4e112Smacallanstatic void
168934c4e112SmacallanCrimeValidatePolyArc(GCPtr pGC,
169034c4e112Smacallan                       unsigned long changes,
169134c4e112Smacallan                       DrawablePtr pDraw)
169234c4e112Smacallan{
169334c4e112Smacallan	if ((pDraw->type == DRAWABLE_WINDOW) ||
169434c4e112Smacallan	    IS_OFFSCREEN_PIXMAP(pDraw)) {
169534c4e112Smacallan		pGC->ops->PolyPoint = CrimePolyPoint;
169634c4e112Smacallan		/*pGC->ops->PolyArc = miPolyArc;*/
169734c4e112Smacallan		pGC->ops->PolyArc = CrimePolyArc;
169834c4e112Smacallan	} else
169934c4e112Smacallan	{
170034c4e112Smacallan		pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint;
170134c4e112Smacallan		pGC->ops->PolyArc = XAAGetFallbackOps()->PolyArc;
170234c4e112Smacallan	}
170334c4e112Smacallan}
1704e1ea03a3Smacallan
170534c4e112Smacallanstatic void
170634c4e112SmacallanCrimeReadPixmap(ScrnInfoPtr pScrn,
170734c4e112Smacallan                     int x,
170834c4e112Smacallan		     int y,
170934c4e112Smacallan		     int w,
171034c4e112Smacallan		     int h,
171134c4e112Smacallan		     unsigned char *dst,
171234c4e112Smacallan		     int dstwidth,
171334c4e112Smacallan		     int bpp,
171434c4e112Smacallan		     int depth)
171534c4e112Smacallan{
171634c4e112Smacallan	/* dummy for now */
171734c4e112Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
171834c4e112Smacallan}
1719e1ea03a3Smacallanint
1720e1ea03a3SmacallanCrimeAccelInit(ScrnInfoPtr pScrn)
1721e1ea03a3Smacallan{
1722e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1723e1ea03a3Smacallan	XAAInfoRecPtr pXAAInfo = fPtr->pXAA;
1724e1ea03a3Smacallan	int i;
1725e1ea03a3Smacallan
1726e1ea03a3Smacallan	for (i = 0; i < 0x1000; i++) regcache[i] = 0x12345678;
1727e1ea03a3Smacallan	LOG(CRIME_DEBUG_ALL);
1728e1ea03a3Smacallan	SYNC;
1729e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
1730e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1731e1ea03a3Smacallan
1732e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_Y, 1);
1733e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STRD_DST, 0);
1734e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STRD_SRC, 1);
1735e1ea03a3Smacallan
1736e1ea03a3Smacallan	WRITE4(CRIME_MTE_BYTEMASK, 0xffffffff);
1737e1ea03a3Smacallan	WRITE4(CRIME_MTE_SRC_Y_STEP, 4);
1738e1ea03a3Smacallan	WRITE4(CRIME_MTE_DST_Y_STEP, 4);
1739e1ea03a3Smacallan
1740e1ea03a3Smacallan	/* blit the screen black */
1741e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1742e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP);
1743e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, 3);
1744e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE, DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
1745e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, 0);
1746e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, 0);
1747e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
1748e1ea03a3Smacallan	    fPtr->info.width << 16 | fPtr->info.height);
1749e1ea03a3Smacallan	SYNC;
1750e1ea03a3Smacallan
175134c4e112Smacallan	pXAAInfo->Flags = /*LINEAR_FRAMEBUFFER |*/ PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
1752e1ea03a3Smacallan	pXAAInfo->maxOffPixWidth = fPtr->info.width;
1753e1ea03a3Smacallan	pXAAInfo->maxOffPixHeight = 2048;
1754e1ea03a3Smacallan
1755e1ea03a3Smacallan	/* Sync */
1756e1ea03a3Smacallan	pXAAInfo->Sync = CrimeSync;
1757e1ea03a3Smacallan
1758e1ea03a3Smacallan	/* Screen-to-screen copy */
1759e1ea03a3Smacallan	pXAAInfo->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
1760e1ea03a3Smacallan	pXAAInfo->SetupForScreenToScreenCopy = CrimeSetupForScreenToScreenCopy;
1761e1ea03a3Smacallan	pXAAInfo->SubsequentScreenToScreenCopy =
1762e1ea03a3Smacallan		CrimeSubsequentScreenToScreenCopy;
1763e1ea03a3Smacallan
1764e1ea03a3Smacallan	/* rectangle fills */
1765e1ea03a3Smacallan	pXAAInfo->SetupForSolidFill = CrimeSetupForSolidFill;
1766e1ea03a3Smacallan	pXAAInfo->SubsequentSolidFillRect = CrimeSubsequentSolidFillRect;
1767e1ea03a3Smacallan
1768e1ea03a3Smacallan	/* image writes */
1769e1ea03a3Smacallan	pXAAInfo->ScanlineImageWriteFlags =
1770e1ea03a3Smacallan	    NO_TRANSPARENCY | LEFT_EDGE_CLIPPING |
1771e1ea03a3Smacallan	    LEFT_EDGE_CLIPPING_NEGATIVE_X |
1772e1ea03a3Smacallan	    CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD;
1773e1ea03a3Smacallan	pXAAInfo->NumScanlineImageWriteBuffers = 8;
1774e1ea03a3Smacallan	for (i = 0; i < 8; i++)
1775e1ea03a3Smacallan		fPtr->buffers[i] = fPtr->linear + (i * 8192);
1776e1ea03a3Smacallan	pXAAInfo->ScanlineImageWriteBuffers = fPtr->buffers;
1777e1ea03a3Smacallan	pXAAInfo->SetupForScanlineImageWrite =
1778e1ea03a3Smacallan		CrimeSetupForScanlineImageWrite;
1779e1ea03a3Smacallan	pXAAInfo->SubsequentScanlineImageWriteRect =
1780e1ea03a3Smacallan		CrimeSubsequentImageWriteRect;
1781e1ea03a3Smacallan	pXAAInfo->SubsequentImageWriteScanline =
1782e1ea03a3Smacallan		CrimeSubsequentImageWriteScanline;
1783e1ea03a3Smacallan
178434c4e112Smacallan	/* read pixmap */
178534c4e112Smacallan	pXAAInfo->ReadPixmapFlags = 0
178634c4e112Smacallan	                             | CPU_TRANSFER_PAD_DWORD
178734c4e112Smacallan				     ;
178834c4e112Smacallan	pXAAInfo->ReadPixmap = CrimeReadPixmap;
178934c4e112Smacallan
1790e1ea03a3Smacallan	/* colour expansion */
1791e1ea03a3Smacallan	pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags =
1792e1ea03a3Smacallan		LEFT_EDGE_CLIPPING;
1793e1ea03a3Smacallan	pXAAInfo->NumScanlineColorExpandBuffers = 1;
1794e1ea03a3Smacallan	fPtr->expandbuffers[0] = (uint8_t *)fPtr->expand;
1795e1ea03a3Smacallan	pXAAInfo->ScanlineColorExpandBuffers = (void *)&fPtr->expandbuffers;
1796e1ea03a3Smacallan	pXAAInfo->SetupForScanlineCPUToScreenColorExpandFill =
1797e1ea03a3Smacallan		CrimeSetupForCPUToScreenColorExpandFill;
1798e1ea03a3Smacallan	pXAAInfo->SubsequentScanlineCPUToScreenColorExpandFill =
1799e1ea03a3Smacallan		CrimeSubsequentScanlineCPUToScreenColorExpandFill;
1800e1ea03a3Smacallan	pXAAInfo->SubsequentColorExpandScanline =
1801e1ea03a3Smacallan		CrimeSubsequentColorExpandScanline;
1802e1ea03a3Smacallan
1803e1ea03a3Smacallan	/* clipping */
1804e1ea03a3Smacallan	pXAAInfo->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
1805e1ea03a3Smacallan		HARDWARE_CLIP_SOLID_FILL | HARDWARE_CLIP_SOLID_LINE;
1806e1ea03a3Smacallan	pXAAInfo->SetClippingRectangle = CrimeSetClippingRectangle;
1807e1ea03a3Smacallan	pXAAInfo->DisableClipping = CrimeDisableClipping;
1808e1ea03a3Smacallan
1809e1ea03a3Smacallan	/* solid line drawing */
1810e1ea03a3Smacallan	pXAAInfo->SetupForSolidLine = CrimeSetupForSolidLine;
1811e1ea03a3Smacallan	pXAAInfo->SubsequentSolidTwoPointLine =
1812e1ea03a3Smacallan	    CrimeSubsequentSolidTwoPointLine;
1813e1ea03a3Smacallan	pXAAInfo->SolidLineFlags = BIT_ORDER_IN_BYTE_MSBFIRST;
1814e1ea03a3Smacallan
1815e1ea03a3Smacallan	/* dashed line drawing */
1816e1ea03a3Smacallan	pXAAInfo->SetupForDashedLine = CrimeSetupForDashedLine;
1817e1ea03a3Smacallan	pXAAInfo->SubsequentDashedTwoPointLine =
1818e1ea03a3Smacallan	    CrimeSubsequentDashedTwoPointLine;
1819e1ea03a3Smacallan	pXAAInfo->DashedLineFlags = LINE_PATTERN_MSBFIRST_MSBJUSTIFIED;
1820e1ea03a3Smacallan	pXAAInfo->DashPatternMaxLength = 32;
1821e1ea03a3Smacallan
1822e1ea03a3Smacallan	/* XRender acceleration */
1823e1ea03a3Smacallan#ifdef RENDER
1824e1ea03a3Smacallan	pXAAInfo->CPUToScreenAlphaTextureFlags = 0;
1825e1ea03a3Smacallan	pXAAInfo->SetupForCPUToScreenAlphaTexture =
1826e1ea03a3Smacallan	    CrimeSetupForCPUToScreenAlphaTexture;
1827e1ea03a3Smacallan	pXAAInfo->SubsequentCPUToScreenAlphaTexture =
1828e1ea03a3Smacallan	    CrimeSubsequentCPUToScreenAlphaTexture;
1829e1ea03a3Smacallan	pXAAInfo->CPUToScreenAlphaTextureFormats = CrimeAlphaTextureFormats;
1830e1ea03a3Smacallan
1831e1ea03a3Smacallan	pXAAInfo->SetupForCPUToScreenTexture = CrimeSetupForCPUToScreenTexture;
1832e1ea03a3Smacallan	pXAAInfo->SubsequentCPUToScreenTexture =
1833e1ea03a3Smacallan	    CrimeSubsequentCPUToScreenTexture;
1834e1ea03a3Smacallan	pXAAInfo->CPUToScreenTextureFlags = 0;
1835e1ea03a3Smacallan	pXAAInfo->CPUToScreenTextureFormats = CrimeTextureFormats;
1836e1ea03a3Smacallan	pXAAInfo->Composite = CrimeComposite;
1837e1ea03a3Smacallan#endif
1838e1ea03a3Smacallan	pXAAInfo->ValidatePolyPoint = CrimeValidatePolyPoint;
1839e1ea03a3Smacallan	pXAAInfo->PolyPointMask = GCFunction;
184034c4e112Smacallan	pXAAInfo->ValidatePolyArc = CrimeValidatePolyArc;
184134c4e112Smacallan	pXAAInfo->PolyArcMask = GCFunction | GCLineWidth;
1842e1ea03a3Smacallan
1843e1ea03a3Smacallan	return -1;
1844e1ea03a3Smacallan}
1845