crime_accel.c revision 93351543
193351543Smacallan/* $NetBSD: crime_accel.c,v 1.4 2009/03/18 23:24:51 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,
23493351543Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP |
23593351543Smacallan	    DE_DRAWMODE_SCISSOR_EN);
236e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
237e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
238e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
239e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
240e1ea03a3Smacallan	DONE(CRIME_DEBUG_RECTFILL);
241e1ea03a3Smacallan}
242e1ea03a3Smacallan
243e1ea03a3Smacallanstatic void
244e1ea03a3SmacallanCrimeSubsequentSolidFillRect
245e1ea03a3Smacallan(
246e1ea03a3Smacallan    ScrnInfoPtr pScrn,
247e1ea03a3Smacallan    int         x,
248e1ea03a3Smacallan    int         y,
249e1ea03a3Smacallan    int         w,
250e1ea03a3Smacallan    int         h
251e1ea03a3Smacallan)
252e1ea03a3Smacallan{
253e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
254e1ea03a3Smacallan
255e1ea03a3Smacallan	LOG(CRIME_DEBUG_RECTFILL);
256e1ea03a3Smacallan	READY;
257e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x << 16) | (y & 0xffff));
258e1ea03a3Smacallan	WBFLUSH;
259e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
260e1ea03a3Smacallan	    ((x + w - 1) << 16) | ((y + h - 1) & 0xffff));
261e1ea03a3Smacallan	DONE(CRIME_DEBUG_RECTFILL);
262e1ea03a3Smacallan}
263e1ea03a3Smacallan
264e1ea03a3Smacallanvoid
265e1ea03a3SmacallanCrimeSetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
266e1ea03a3Smacallan                                unsigned int planemask, int trans_color,
267e1ea03a3Smacallan                                int bpp, int depth)
268e1ea03a3Smacallan{
269e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
270e1ea03a3Smacallan
271e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
272e1ea03a3Smacallan	SYNC;
273e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
274e1ea03a3Smacallan	if ((bpp == 24) || (depth == 24))
275e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d \n", __func__, bpp, depth);
276e1ea03a3Smacallan#endif
277e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
278e1ea03a3Smacallan			    DE_MODE_TYPE_RGB | DE_MODE_PIXDEPTH_32);
279e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
280e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
281e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
282e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
283e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP |
284e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
285e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
286e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
287e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
288e1ea03a3Smacallan}
289e1ea03a3Smacallan
290e1ea03a3Smacallanvoid
291e1ea03a3SmacallanCrimeSubsequentImageWriteRect(ScrnInfoPtr pScrn,
292e1ea03a3Smacallan                                int x, int y, int w, int h, int skipleft)
293e1ea03a3Smacallan{
294e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
295e1ea03a3Smacallan
296e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
297e1ea03a3Smacallan
298e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
299e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d\n", __func__, x, y, w, h);
300e1ea03a3Smacallan#endif
301e1ea03a3Smacallan
302e1ea03a3Smacallan	fPtr->start = skipleft;
303e1ea03a3Smacallan	x += skipleft;
304e1ea03a3Smacallan	w -= skipleft;
305e1ea03a3Smacallan	if (x < 0) {
306e1ea03a3Smacallan		fPtr->ux = 0;
307e1ea03a3Smacallan		w += x;
308e1ea03a3Smacallan		fPtr->start -= x;
309e1ea03a3Smacallan	} else {
310e1ea03a3Smacallan		fPtr->ux = x;
311e1ea03a3Smacallan	}
312e1ea03a3Smacallan	fPtr->uy = y;
313e1ea03a3Smacallan	fPtr->uw = w;
314e1ea03a3Smacallan	fPtr->uh = h;
315e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
316e1ea03a3Smacallan}
317e1ea03a3Smacallan
318e1ea03a3Smacallanvoid
319e1ea03a3SmacallanCrimeSubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
320e1ea03a3Smacallan{
321e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
322e1ea03a3Smacallan
323e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
32434c4e112Smacallan	SYNC;
325e1ea03a3Smacallan
326e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_ADDR_SRC, (bufno << 13)  + (fPtr->start << 2));
327e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (fPtr->ux << 16) | fPtr->uy);
328e1ea03a3Smacallan	WBFLUSH;
329e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
330e1ea03a3Smacallan		((fPtr->ux + fPtr->uw - 1) << 16) | (fPtr->uy));
331e1ea03a3Smacallan	fPtr->uy++;
332e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
333e1ea03a3Smacallan}
334e1ea03a3Smacallan
335e1ea03a3Smacallanstatic void
336e1ea03a3SmacallanCrimeSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
337e1ea03a3Smacallan        		int fg, int bg,
338e1ea03a3Smacallan			int rop,
339e1ea03a3Smacallan			unsigned int planemask)
340e1ea03a3Smacallan{
341e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
342e1ea03a3Smacallan
343e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
344e1ea03a3Smacallan	SYNC;
345e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
346e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
347e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, fg << 8);
348e1ea03a3Smacallan	if (bg == -1) {
349e1ea03a3Smacallan		/* transparent */
350e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
351e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
352e1ea03a3Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_POLY_STIP);
353e1ea03a3Smacallan	} else {
354e1ea03a3Smacallan		WRITE4(CRIME_DE_BG, bg << 8);
355e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
356e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
357e1ea03a3Smacallan		    DE_DRAWMODE_ROP |
358e1ea03a3Smacallan		    DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_POLY_STIP);
359e1ea03a3Smacallan	}
360e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
361e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
362e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
363e1ea03a3Smacallan}
364e1ea03a3Smacallan
365e1ea03a3Smacallanstatic void
366e1ea03a3SmacallanCrimeSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
367e1ea03a3Smacallan			int x, int y, int w, int h,
368e1ea03a3Smacallan			int skipleft )
369e1ea03a3Smacallan{
370e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
371e1ea03a3Smacallan
372e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
373e1ea03a3Smacallan
374e1ea03a3Smacallan	fPtr->start = skipleft;
375e1ea03a3Smacallan	fPtr->ux = x;
376e1ea03a3Smacallan	fPtr->uy = y;
377e1ea03a3Smacallan	fPtr->uw = w;
378e1ea03a3Smacallan	fPtr->uh = h;
379e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
380e1ea03a3Smacallan}
381e1ea03a3Smacallan
382e1ea03a3Smacallanstatic void
383e1ea03a3SmacallanCrimeSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
384e1ea03a3Smacallan{
385e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
386e1ea03a3Smacallan	uint32_t *boo = (uint32_t *)fPtr->expandbuffers[bufno];
387e1ea03a3Smacallan	int idx = fPtr->uw, x = fPtr->ux;
388e1ea03a3Smacallan
389e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
390e1ea03a3Smacallan	READY;
391e1ea03a3Smacallan
392e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, 0x001f0000 | (fPtr->start << 24));
393e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_PAT, *boo);
394e1ea03a3Smacallan	boo++;
395e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x + fPtr->start << 16) | fPtr->uy);
396e1ea03a3Smacallan	WBFLUSH;
397e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
398e1ea03a3Smacallan		((x + min(idx, 32) - 1) << 16) | (fPtr->uy));
399e1ea03a3Smacallan	idx -= 32;
400e1ea03a3Smacallan	x += 32;
401e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, 0x001f0000);
402e1ea03a3Smacallan
403e1ea03a3Smacallan	while (idx > 0) {
404e1ea03a3Smacallan		WRITE4(CRIME_DE_STIPPLE_PAT, *boo);
405e1ea03a3Smacallan		boo++;
406e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (x << 16) | fPtr->uy);
407e1ea03a3Smacallan		WBFLUSH;
408e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
409e1ea03a3Smacallan			((x + min(idx, 32) - 1) << 16) | (fPtr->uy));
410e1ea03a3Smacallan		idx -= 32;
411e1ea03a3Smacallan		x += 32;
412e1ea03a3Smacallan	}
413e1ea03a3Smacallan	fPtr->uy++;
414e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
415e1ea03a3Smacallan}
416e1ea03a3Smacallan
417e1ea03a3Smacallanstatic void
418e1ea03a3SmacallanCrimeSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
419e1ea03a3Smacallan    unsigned int planemask)
420e1ea03a3Smacallan{
421e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
422e1ea03a3Smacallan
423e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
424e1ea03a3Smacallan
425e1ea03a3Smacallan	SYNC;
426e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
427e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
428e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, color << 8);
429e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
430e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
43193351543Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_SCISSOR_EN);
432e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
433e1ea03a3Smacallan}
434e1ea03a3Smacallan
435e1ea03a3Smacallanstatic void
436e1ea03a3SmacallanCrimeSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2,
437e1ea03a3Smacallan    int y2, int flags)
438e1ea03a3Smacallan{
439e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
440e1ea03a3Smacallan
441e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
442e1ea03a3Smacallan	READY;
443e1ea03a3Smacallan	if (flags & OMIT_LAST) {
444e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
445e1ea03a3Smacallan			DE_PRIM_LINE | DE_PRIM_LINE_SKIP_END | 2);
446e1ea03a3Smacallan	} else {
447e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
448e1ea03a3Smacallan			DE_PRIM_LINE | 2);
449e1ea03a3Smacallan	}
450e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x1 << 16) | y1);
451e1ea03a3Smacallan	WBFLUSH;
452e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1, (x2 << 16) | y2);
453e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
454e1ea03a3Smacallan}
455e1ea03a3Smacallan
456e1ea03a3Smacallanvoid
457e1ea03a3SmacallanCrimeSetupForDashedLine(ScrnInfoPtr pScrn,
458e1ea03a3Smacallan		int fg, int bg, int rop, unsigned int planemask,
459e1ea03a3Smacallan        	int length, unsigned char *pattern)
460e1ea03a3Smacallan{
461e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
462e1ea03a3Smacallan	uint32_t pat;
463e1ea03a3Smacallan
464e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
465e1ea03a3Smacallan	SYNC;
466e1ea03a3Smacallan
467e1ea03a3Smacallan	fPtr->uw = length;
468e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
469e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
470e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, fg << 8);
471e1ea03a3Smacallan	if (bg == -1) {
472e1ea03a3Smacallan		/* transparent */
473e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
474e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
47593351543Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_LINE_STIP |
47693351543Smacallan		    DE_DRAWMODE_SCISSOR_EN);
477e1ea03a3Smacallan	} else {
478e1ea03a3Smacallan		WRITE4(CRIME_DE_BG, bg << 8);
479e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
480e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
48193351543Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_SCISSOR_EN |
482e1ea03a3Smacallan		    DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_LINE_STIP);
483e1ea03a3Smacallan	}
484e1ea03a3Smacallan	/*
485e1ea03a3Smacallan	 * can we trust the Xserver to always hand us a 32bit aligned
486e1ea03a3Smacallan	 * pattern buffer?
487e1ea03a3Smacallan	 */
488e1ea03a3Smacallan	memcpy(&pat, pattern, 4);
489e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_PAT, pat);
490e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
491e1ea03a3Smacallan}
492e1ea03a3Smacallan
493e1ea03a3Smacallanvoid
494e1ea03a3SmacallanCrimeSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn,
495e1ea03a3Smacallan        int x1, int y1, int x2, int y2, int flags, int phase)
496e1ea03a3Smacallan{
497e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
498e1ea03a3Smacallan	uint32_t stipmode;
499e1ea03a3Smacallan
500e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
501e1ea03a3Smacallan	READY;
502e1ea03a3Smacallan
503e1ea03a3Smacallan	if (flags & OMIT_LAST) {
504e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
505e1ea03a3Smacallan			DE_PRIM_LINE | DE_PRIM_LINE_SKIP_END | 2);
506e1ea03a3Smacallan	} else {
507e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
508e1ea03a3Smacallan			DE_PRIM_LINE | 2);
509e1ea03a3Smacallan	}
510e1ea03a3Smacallan
511e1ea03a3Smacallan	stipmode = ((fPtr->uw - 1) << 16) | (phase << 24);
512e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, stipmode);
513e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x1 << 16) | y1);
514e1ea03a3Smacallan	WBFLUSH;
515e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1, (x2 << 16) | y2);
516e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
517e1ea03a3Smacallan}
518e1ea03a3Smacallan
519e1ea03a3Smacallanvoid
520e1ea03a3SmacallanCrimeSetClippingRectangle ( ScrnInfoPtr pScrn,
521e1ea03a3Smacallan                        int left, int top, int right, int bottom)
522e1ea03a3Smacallan{
523e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
524e1ea03a3Smacallan
525e1ea03a3Smacallan	LOG(CRIME_DEBUG_CLIPPING);
52693351543Smacallan	WRITE4(CRIME_DE_SCISSOR, (left << 16) | top);
52793351543Smacallan	WRITE4(CRIME_DE_SCISSOR + 4, ((right + 1) << 16) | (bottom + 1));
52893351543Smacallan
529e1ea03a3Smacallan	DONE(CRIME_DEBUG_CLIPPING);
530e1ea03a3Smacallan}
531e1ea03a3Smacallan
532e1ea03a3Smacallanvoid
533e1ea03a3SmacallanCrimeDisableClipping (ScrnInfoPtr pScrn)
534e1ea03a3Smacallan{
535e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
536e1ea03a3Smacallan
537e1ea03a3Smacallan	LOG(CRIME_DEBUG_CLIPPING);
538e1ea03a3Smacallan	SYNC;
539e1ea03a3Smacallan
54093351543Smacallan	WRITE4(CRIME_DE_SCISSOR, 0);
54193351543Smacallan	WRITE4(CRIME_DE_SCISSOR + 4, 0x3fff3fff);
542e1ea03a3Smacallan	DONE(CRIME_DEBUG_CLIPPING);
543e1ea03a3Smacallan}
544e1ea03a3Smacallan
545e1ea03a3Smacallanstatic Bool
546e1ea03a3SmacallanCrimeSetupForCPUToScreenAlphaTexture (
547e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
548e1ea03a3Smacallan   int		op,
549e1ea03a3Smacallan   CARD16	red,
550e1ea03a3Smacallan   CARD16	green,
551e1ea03a3Smacallan   CARD16	blue,
552e1ea03a3Smacallan   CARD16	alpha,
553e1ea03a3Smacallan   int		alphaType,
554e1ea03a3Smacallan   CARD8	*alphaPtr,
555e1ea03a3Smacallan   int		alphaPitch,
556e1ea03a3Smacallan   int		width,
557e1ea03a3Smacallan   int		height,
558e1ea03a3Smacallan   int		flags
559e1ea03a3Smacallan)
560e1ea03a3Smacallan{
561e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
562e1ea03a3Smacallan
563e1ea03a3Smacallan	if (op != PictOpOver) {
564e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
565e1ea03a3Smacallan		op = PictOpOver;
566e1ea03a3Smacallan	}
567e1ea03a3Smacallan
568e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
569e1ea03a3Smacallan
570e1ea03a3Smacallan	fPtr->alpha_color = ((red & 0xff00) << 16) |
571e1ea03a3Smacallan			    ((green & 0xff00) << 8) |
57209f0d67cSmacallan			    (blue & 0xff00);
573e1ea03a3Smacallan	fPtr->uw = width;
574e1ea03a3Smacallan	fPtr->uh = height;
575e1ea03a3Smacallan	fPtr->us = alphaPitch;
576e1ea03a3Smacallan	fPtr->alpha_texture = alphaPtr;
57709f0d67cSmacallan	fPtr->format = alphaType;
57809f0d67cSmacallan	if (alphaType != PICT_a8) {
57909f0d67cSmacallan		xf86Msg(X_ERROR, "ARGB mask %08x %d\n", (uint32_t)alphaPtr,
58009f0d67cSmacallan		    alphaPitch);
58109f0d67cSmacallan
58209f0d67cSmacallan	}
583e1ea03a3Smacallan	SYNC;
584e1ea03a3Smacallan	/* XXX this register is not where it's supposed to be */
585e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_COLOR, fPtr->alpha_color);
58609f0d67cSmacallan	if (alphaType == PICT_a8) {
58709f0d67cSmacallan		if (fPtr->alpha_color == 0) {
58809f0d67cSmacallan			WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_8 |
589e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
59009f0d67cSmacallan			WRITE4(CRIME_DE_XFER_STEP_X, 1);
59109f0d67cSmacallan			WRITE4(CRIME_DE_ALPHA_FUNC,
59209f0d67cSmacallan			    DE_ALPHA_ADD |
59309f0d67cSmacallan			    (DE_ALPHA_OP_ZERO << DE_ALPHA_OP_SRC_SHIFT) |
59409f0d67cSmacallan			    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
59509f0d67cSmacallan		} else {
59609f0d67cSmacallan			WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
59709f0d67cSmacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
59809f0d67cSmacallan			WRITE4(CRIME_DE_XFER_STEP_X, 4);
59909f0d67cSmacallan			WRITE4(CRIME_DE_ALPHA_FUNC,
60009f0d67cSmacallan			    DE_ALPHA_ADD |
60109f0d67cSmacallan			    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
60209f0d67cSmacallan			    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
60309f0d67cSmacallan		}
604e1ea03a3Smacallan	} else {
605e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
606e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
607e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_STEP_X, 4);
608e1ea03a3Smacallan		WRITE4(CRIME_DE_ALPHA_FUNC,
609e1ea03a3Smacallan		    DE_ALPHA_ADD |
610e1ea03a3Smacallan		    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
611e1ea03a3Smacallan		    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
61209f0d67cSmacallan	}
613e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
614e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
615e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
616e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
617e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
618e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
619e1ea03a3Smacallan	return TRUE;
620e1ea03a3Smacallan}
621e1ea03a3Smacallan
622e1ea03a3Smacallanvoid
623e1ea03a3SmacallanCrimeSubsequentCPUToScreenAlphaTexture (
624e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
625e1ea03a3Smacallan    int		dstx,
626e1ea03a3Smacallan    int		dsty,
627e1ea03a3Smacallan    int		srcx,
628e1ea03a3Smacallan    int		srcy,
629e1ea03a3Smacallan    int		width,
630e1ea03a3Smacallan    int		height
631e1ea03a3Smacallan)
632e1ea03a3Smacallan{
633e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
634e1ea03a3Smacallan	unsigned char *aptr;
635e1ea03a3Smacallan	uint32_t *dptr, aval;
636e1ea03a3Smacallan	int i, j;
637e1ea03a3Smacallan	int bufnum = 0;
638e1ea03a3Smacallan
639e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
640e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
641e1ea03a3Smacallan	xf86Msg(X_ERROR, "%d %d %d %d %d %d\n",srcx, srcy, dstx, dsty, width,
642e1ea03a3Smacallan	    height);
643e1ea03a3Smacallan#endif
644e1ea03a3Smacallan	aptr = fPtr->alpha_texture + (fPtr->us * srcy) + srcx;
645e1ea03a3Smacallan	for (i = 0; i < height; i++) {
646e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
647e1ea03a3Smacallan		if (fPtr->alpha_color == 0) {
648e1ea03a3Smacallan			memcpy(dptr, aptr, width);
649e1ea03a3Smacallan		} else {
650e1ea03a3Smacallan			for (j = 0; j < width; j++) {
651e1ea03a3Smacallan				aval = aptr[j];
652e1ea03a3Smacallan				*dptr = aval | fPtr->alpha_color;
653e1ea03a3Smacallan				dptr++;
654e1ea03a3Smacallan			}
655e1ea03a3Smacallan		}
656e1ea03a3Smacallan		READY;
657e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
658e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
659e1ea03a3Smacallan		WBFLUSH;
660e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
661e1ea03a3Smacallan			((dstx + width - 1) << 16) | (dsty + i));
662e1ea03a3Smacallan		bufnum++;
663e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
664e1ea03a3Smacallan		aptr += fPtr->us;
665e1ea03a3Smacallan	}
666e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
667e1ea03a3Smacallan}
668e1ea03a3Smacallan
66909f0d67cSmacallanvoid
67009f0d67cSmacallanCrimeSubsequentCPUToScreenAlphaTexture32 (
67109f0d67cSmacallan    ScrnInfoPtr	pScrn,
67209f0d67cSmacallan    int		dstx,
67309f0d67cSmacallan    int		dsty,
67409f0d67cSmacallan    int		srcx,
67509f0d67cSmacallan    int		srcy,
67609f0d67cSmacallan    int		width,
67709f0d67cSmacallan    int		height
67809f0d67cSmacallan)
67909f0d67cSmacallan{
68009f0d67cSmacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
68109f0d67cSmacallan	uint8_t *aptr;
68209f0d67cSmacallan	uint32_t *dptr, *sptr;
68309f0d67cSmacallan	int i, j;
68409f0d67cSmacallan	int bufnum = 0;
68509f0d67cSmacallan
68609f0d67cSmacallan	LOG(CRIME_DEBUG_XRENDER);
68709f0d67cSmacallan#ifndef CRIME_DEBUG_LOUD
68809f0d67cSmacallan	xf86Msg(X_ERROR, "%d %d %d %d %d %d\n",srcx, srcy, dstx, dsty, width,
68909f0d67cSmacallan	    height);
69009f0d67cSmacallan#endif
69109f0d67cSmacallan	aptr = fPtr->alpha_texture + (fPtr->us * srcy) + (srcx << 2);
69209f0d67cSmacallan	for (i = 0; i < height; i++) {
69309f0d67cSmacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
69409f0d67cSmacallan		sptr = (uint32_t *)aptr;
69509f0d67cSmacallan		for (j = 0; j < width; j++) {
69609f0d67cSmacallan			*dptr = (*sptr >> 24) | fPtr->alpha_color;
69709f0d67cSmacallan#ifdef CRIME_DEBUG_LOUD
69809f0d67cSmacallan			xf86Msg(X_ERROR, "%08x %08x\n", *sptr, *dptr);
69909f0d67cSmacallan#endif
70009f0d67cSmacallan			sptr++;
70109f0d67cSmacallan			dptr++;
70209f0d67cSmacallan		}
70309f0d67cSmacallan		READY;
70409f0d67cSmacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
70509f0d67cSmacallan		WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
70609f0d67cSmacallan		WBFLUSH;
70709f0d67cSmacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
70809f0d67cSmacallan			((dstx + width - 1) << 16) | (dsty + i));
70909f0d67cSmacallan		bufnum++;
71009f0d67cSmacallan		if (bufnum == 8) bufnum = 0;
71109f0d67cSmacallan		aptr += fPtr->us;
71209f0d67cSmacallan	}
71309f0d67cSmacallan	DONE(CRIME_DEBUG_XRENDER);
71409f0d67cSmacallan}
71509f0d67cSmacallan
716e1ea03a3Smacallanstatic Bool
717e1ea03a3SmacallanCrimeSetupForCPUToScreenTexture (
718e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
719e1ea03a3Smacallan   int		op,
720e1ea03a3Smacallan   int		texType,
721e1ea03a3Smacallan   CARD8	*texPtr,
722e1ea03a3Smacallan   int		texPitch,
723e1ea03a3Smacallan   int		width,
724e1ea03a3Smacallan   int		height,
725e1ea03a3Smacallan   int		flags
726e1ea03a3Smacallan)
727e1ea03a3Smacallan{
728e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
729e1ea03a3Smacallan
730e1ea03a3Smacallan	if (op != PictOpOver) {
731e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
732e1ea03a3Smacallan		op = PictOpOver;
733e1ea03a3Smacallan	}
734e1ea03a3Smacallan
735e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
736e1ea03a3Smacallan
737e1ea03a3Smacallan	fPtr->uw = width;
738e1ea03a3Smacallan	fPtr->uh = height;
739e1ea03a3Smacallan	fPtr->us = texPitch;
740e1ea03a3Smacallan	fPtr->alpha_texture = texPtr;
741e1ea03a3Smacallan	SYNC;
742e1ea03a3Smacallan	if (texType == PICT_a8b8g8r8) {
743e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
744e1ea03a3Smacallan				    DE_MODE_TYPE_ABGR | DE_MODE_PIXDEPTH_32);
745e1ea03a3Smacallan	} else {
746e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
747e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
748e1ea03a3Smacallan	}
749e1ea03a3Smacallan	fPtr->format = texType;
750e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
751e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
752e1ea03a3Smacallan	    DE_ALPHA_ADD |
753e1ea03a3Smacallan	    (DE_ALPHA_OP_ONE/*SRC_ALPHA*/ << DE_ALPHA_OP_SRC_SHIFT) |
754e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
755e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
756e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
757e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
758e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
759e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
760e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
761e1ea03a3Smacallan	return TRUE;
762e1ea03a3Smacallan}
763e1ea03a3Smacallan
764e1ea03a3Smacallanvoid
765e1ea03a3SmacallanCrimeSubsequentCPUToScreenTexture (
766e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
767e1ea03a3Smacallan    int		dstx,
768e1ea03a3Smacallan    int		dsty,
769e1ea03a3Smacallan    int		srcx,
770e1ea03a3Smacallan    int		srcy,
771e1ea03a3Smacallan    int		width,
772e1ea03a3Smacallan    int		height
773e1ea03a3Smacallan)
774e1ea03a3Smacallan{
775e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
776e1ea03a3Smacallan	unsigned char *aptr, *lptr;
777e1ea03a3Smacallan	uint32_t *dptr, *sptr, aval, pixel;
778e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
779e1ea03a3Smacallan	int bufnum = 0;
780e1ea03a3Smacallan
781e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
782e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
783e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d\n", __func__,
784e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height);
785e1ea03a3Smacallan#endif
786e1ea03a3Smacallan	if ((width == 1) || (fPtr->format != PICT_a8r8g8b8)) {
787e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d %d %d\n", __func__,
788e1ea03a3Smacallan		    srcx, srcy, dstx, dsty, width, height, fPtr->uw, fPtr->us);
789e1ea03a3Smacallan		return;
790e1ea03a3Smacallan	}
791e1ea03a3Smacallan
792e1ea03a3Smacallan	aptr = fPtr->alpha_texture + (srcx << 2);
793e1ea03a3Smacallan	lptr = aptr + (fPtr->us * srcy);
794e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
795e1ea03a3Smacallan		rep = 128 / fPtr->uw;
796e1ea03a3Smacallan		period = rep * fPtr->uw;
797e1ea03a3Smacallan	}
798e1ea03a3Smacallan
799e1ea03a3Smacallan	if (fPtr->format == PICT_a8b8g8r8) {
800e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
801e1ea03a3Smacallan		xf86Msg(X_ERROR, "ABGR\n");
802e1ea03a3Smacallan#endif
803e1ea03a3Smacallan		for (i = 0; i < height; i++) {
804e1ea03a3Smacallan			dptr = (uint32_t *)fPtr->buffers[bufnum];
805e1ea03a3Smacallan			memcpy(dptr, aptr, fPtr->us);
806e1ea03a3Smacallan			READY;
807e1ea03a3Smacallan			WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
808e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
809e1ea03a3Smacallan			WBFLUSH;
810e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
811e1ea03a3Smacallan				((dstx + width - 1) << 16) | (dsty + i));
812e1ea03a3Smacallan			bufnum++;
813e1ea03a3Smacallan			if (bufnum == 8) bufnum = 0;
814e1ea03a3Smacallan			aptr += fPtr->us;
815e1ea03a3Smacallan		}
816e1ea03a3Smacallan	} else {
817e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
818e1ea03a3Smacallan		xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)aptr, fPtr->uw);
819e1ea03a3Smacallan#endif
820e1ea03a3Smacallan		lcnt = fPtr->uh - srcy;
821e1ea03a3Smacallan		for (i = 0; i < height; i++) {
822e1ea03a3Smacallan			dptr = (uint32_t *)fPtr->buffers[bufnum];
823e1ea03a3Smacallan			for (k = 0; k < rep; k++) {
824e1ea03a3Smacallan				sptr = (uint32_t *)aptr;
825e1ea03a3Smacallan				for (j = 0; j < fPtr->uw; j++) {
826e1ea03a3Smacallan					pixel = *sptr;
827e1ea03a3Smacallan					*dptr = (pixel << 8) | (pixel >> 24);
828e1ea03a3Smacallan					dptr++;
829e1ea03a3Smacallan					sptr++;
830e1ea03a3Smacallan				}
831e1ea03a3Smacallan			}
832e1ea03a3Smacallan			xoff = 0;
833e1ea03a3Smacallan			READY;
834e1ea03a3Smacallan			WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
835e1ea03a3Smacallan			while (xoff < width) {
836e1ea03a3Smacallan				xa = dstx + xoff;
837e1ea03a3Smacallan				xe = dstx + min(xoff + period, width) - 1;
838e1ea03a3Smacallan				READY;
839e1ea03a3Smacallan				WRITE4(CRIME_DE_X_VERTEX_0,
840e1ea03a3Smacallan				    xa << 16 | (dsty + i));
841e1ea03a3Smacallan				WBFLUSH;
842e1ea03a3Smacallan				WRITE4ST(CRIME_DE_X_VERTEX_1,
843e1ea03a3Smacallan					(xe << 16) | (dsty + i));
844e1ea03a3Smacallan				xoff += period;
845e1ea03a3Smacallan			}
846e1ea03a3Smacallan			bufnum++;
847e1ea03a3Smacallan			if (bufnum == 8) bufnum = 0;
848e1ea03a3Smacallan			lcnt--;
849e1ea03a3Smacallan			if (lcnt == 0) {
850e1ea03a3Smacallan				aptr = lptr;
851e1ea03a3Smacallan				lcnt = fPtr->uh;
852e1ea03a3Smacallan			} else
853e1ea03a3Smacallan				aptr += fPtr->us;
854e1ea03a3Smacallan		}
855e1ea03a3Smacallan	}
856e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
857e1ea03a3Smacallan}
858e1ea03a3Smacallan
859e1ea03a3Smacallanstatic Bool
860e1ea03a3SmacallanCrimeSetupForCPUToScreenTextureMask(
861e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
862e1ea03a3Smacallan   int		op,
863e1ea03a3Smacallan   int		texType,
864e1ea03a3Smacallan   CARD8	*srcPtr,
865e1ea03a3Smacallan   int		srcPitch,
866e1ea03a3Smacallan   CARD8	*mskPtr,
867e1ea03a3Smacallan   int		mskPitch,
868e1ea03a3Smacallan   int		width,
869e1ea03a3Smacallan   int		height,
870e1ea03a3Smacallan   int		flags
871e1ea03a3Smacallan)
872e1ea03a3Smacallan{
873e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
874e1ea03a3Smacallan
875e1ea03a3Smacallan	if (op != PictOpOver) {
876e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
877e1ea03a3Smacallan		op = PictOpOver;
878e1ea03a3Smacallan	}
879e1ea03a3Smacallan
880e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
881e1ea03a3Smacallan
882e1ea03a3Smacallan	fPtr->uw = width;
883e1ea03a3Smacallan	fPtr->uh = height;
884e1ea03a3Smacallan	fPtr->us = srcPitch >> 2;
885e1ea03a3Smacallan	if (PICT_FORMAT_BPP(texType) == 32) {
886e1ea03a3Smacallan		fPtr->um = mskPitch >> 2;
887e1ea03a3Smacallan	} else
888e1ea03a3Smacallan		fPtr->um = mskPitch;
889e1ea03a3Smacallan	fPtr->msk = (uint8_t *)mskPtr;
890e1ea03a3Smacallan	fPtr->src = (uint8_t *)srcPtr;
891e1ea03a3Smacallan	fPtr->texture_depth = PICT_FORMAT_BPP(texType);
892e1ea03a3Smacallan
893e1ea03a3Smacallan	SYNC;
894e1ea03a3Smacallan	/* always expect ARGB for now */
895e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
896e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
897e1ea03a3Smacallan	fPtr->format = texType;
898e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
899e1ea03a3Smacallan	    DE_ALPHA_ADD |
900e1ea03a3Smacallan	    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
901e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
902e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
903e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
904e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
905e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
906e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
907e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
908e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
909e1ea03a3Smacallan	return TRUE;
910e1ea03a3Smacallan}
911e1ea03a3Smacallan
912e1ea03a3Smacallanvoid
913e1ea03a3SmacallanCrimeSubsequentCPUToScreenTextureMask32(
914e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
915e1ea03a3Smacallan    int		dstx,
916e1ea03a3Smacallan    int		dsty,
917e1ea03a3Smacallan    int		srcx,
918e1ea03a3Smacallan    int		srcy,
919e1ea03a3Smacallan    int		maskx,
920e1ea03a3Smacallan    int		masky,
921e1ea03a3Smacallan    int		width,
922e1ea03a3Smacallan    int		height
923e1ea03a3Smacallan)
924e1ea03a3Smacallan{
925e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
926e1ea03a3Smacallan	uint32_t *lsptr, *lmptr, *asptr, *amptr;
927e1ea03a3Smacallan	uint32_t *dptr, *sptr, *mptr, aval, pixel, mask;
928e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
929e1ea03a3Smacallan	int bufnum = 0;
930e1ea03a3Smacallan	int sr, sg, sb, sa, mr, mg, mb, ma, rr, gg, bb, aa;
931e1ea03a3Smacallan
932e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
933e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
934e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d; %d %d %d\n", __func__,
935e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height, maskx, masky, fPtr->um);
936e1ea03a3Smacallan#endif
937e1ea03a3Smacallan	sptr = fPtr->src + (srcx << 2);
938e1ea03a3Smacallan	mptr = fPtr->msk + (srcx << 2);
939e1ea03a3Smacallan	lsptr = sptr + (fPtr->us * srcy);
940e1ea03a3Smacallan	lmptr = mptr + (fPtr->um * srcy);
941e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
942e1ea03a3Smacallan		rep = 128 / fPtr->uw;
943e1ea03a3Smacallan		period = rep * fPtr->uw;
944e1ea03a3Smacallan	}
945e1ea03a3Smacallan
946e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
947e1ea03a3Smacallan	xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)aptr, fPtr->uw);
948e1ea03a3Smacallan#endif
949e1ea03a3Smacallan	lcnt = fPtr->uh - srcy;
950e1ea03a3Smacallan	for (i = 0; i < height; i++) {
951e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
952e1ea03a3Smacallan		for (k = 0; k < rep; k++) {
953e1ea03a3Smacallan			asptr = lsptr;
954e1ea03a3Smacallan			amptr = lmptr;
955e1ea03a3Smacallan			for (j = 0; j < fPtr->uw; j++) {
956e1ea03a3Smacallan				pixel = *asptr;
957e1ea03a3Smacallan				mask = *amptr;
958e1ea03a3Smacallan				if (mask == 0xffffffff) {
959e1ea03a3Smacallan					*dptr = (pixel >> 24) | (pixel << 8);
960e1ea03a3Smacallan				} else if (mask == 0x00000000) {
961e1ea03a3Smacallan					*dptr = 0;
962e1ea03a3Smacallan				} else {
963e1ea03a3Smacallan					/* input is ARGB */
964e1ea03a3Smacallan					sb = pixel & 0xff;
965e1ea03a3Smacallan					sg = (pixel >> 8) & 0xff;
966e1ea03a3Smacallan					sr = (pixel >> 16) & 0xff;
967e1ea03a3Smacallan					sa = (pixel >> 24) & 0xff;
968e1ea03a3Smacallan					mb = mask & 0xff;
969e1ea03a3Smacallan					mg = (mask >> 8) & 0xff;
970e1ea03a3Smacallan					mr = (mask >> 16) & 0xff;
971e1ea03a3Smacallan					ma = (mask >> 24) & 0xff;
972e1ea03a3Smacallan
973e1ea03a3Smacallan					/* and here we need an RGBA pixel */
974e1ea03a3Smacallan					bb = (((sb * mb) + 0x80) & 0xff00);
975e1ea03a3Smacallan					gg = (((sg * mg) + 0x80) & 0xff00) << 8;
976e1ea03a3Smacallan					rr = (((sr * mr) + 0x80) & 0xff00) << 16;
977e1ea03a3Smacallan					aa = (((sa * ma) + 0x80) & 0xff00) >> 8;
978e1ea03a3Smacallan					/*
979e1ea03a3Smacallan					 * actually we could let the HW do this stuff
980e1ea03a3Smacallan					 */
981e1ea03a3Smacallan					*dptr = aa | rr | gg | bb;
982e1ea03a3Smacallan				}
983e1ea03a3Smacallan				dptr++;
984e1ea03a3Smacallan				asptr++;
985e1ea03a3Smacallan				amptr++;
986e1ea03a3Smacallan			}
987e1ea03a3Smacallan		}
988e1ea03a3Smacallan		xoff = 0;
989e1ea03a3Smacallan		READY;
990e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
991e1ea03a3Smacallan		while (xoff < width) {
992e1ea03a3Smacallan			xa = dstx + xoff;
993e1ea03a3Smacallan			xe = dstx + min(xoff + period, width) - 1;
994e1ea03a3Smacallan			READY;
995e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0,
996e1ea03a3Smacallan			    xa << 16 | (dsty + i));
997e1ea03a3Smacallan			WBFLUSH;
998e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
999e1ea03a3Smacallan				(xe << 16) | (dsty + i));
1000e1ea03a3Smacallan			xoff += period;
1001e1ea03a3Smacallan		}
1002e1ea03a3Smacallan		bufnum++;
1003e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
1004e1ea03a3Smacallan		lcnt--;
1005e1ea03a3Smacallan		if (lcnt == 0) {
1006e1ea03a3Smacallan			/* back to the beginning */
1007e1ea03a3Smacallan			lsptr = sptr;
1008e1ea03a3Smacallan			lmptr = mptr;
1009e1ea03a3Smacallan			lcnt = fPtr->uh;
1010e1ea03a3Smacallan		} else
1011e1ea03a3Smacallan			/* next line */
1012e1ea03a3Smacallan			lsptr += fPtr->us;
1013e1ea03a3Smacallan			lmptr += fPtr->um;
1014e1ea03a3Smacallan	}
1015e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1016e1ea03a3Smacallan}
1017e1ea03a3Smacallan
1018e1ea03a3Smacallanvoid
1019e1ea03a3SmacallanCrimeSubsequentCPUToScreenTextureMask8(
1020e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
1021e1ea03a3Smacallan    int		dstx,
1022e1ea03a3Smacallan    int		dsty,
1023e1ea03a3Smacallan    int		srcx,
1024e1ea03a3Smacallan    int		srcy,
1025e1ea03a3Smacallan    int		maskx,
1026e1ea03a3Smacallan    int		masky,
1027e1ea03a3Smacallan    int		width,
1028e1ea03a3Smacallan    int		height
1029e1ea03a3Smacallan)
1030e1ea03a3Smacallan{
1031e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1032e1ea03a3Smacallan	uint32_t *lsptr, *asptr;
1033e1ea03a3Smacallan	uint32_t *dptr, *sptr, aval, pixel, mask;
1034e1ea03a3Smacallan	uint8_t  *lmptr, *amptr, *mptr;
1035e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
1036e1ea03a3Smacallan	int bufnum = 0;
1037e1ea03a3Smacallan	int sr, sg, sb, sa, rr, gg, bb, aa;
1038e1ea03a3Smacallan
1039e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1040e1ea03a3Smacallan#ifndef CRIME_DEBUG_LOUD
1041e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d\n", __func__,
1042e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height);
1043e1ea03a3Smacallan#endif
1044e1ea03a3Smacallan	sptr = (uint32_t *)fPtr->src + (fPtr->us * srcy) + (srcx << 2);
1045e1ea03a3Smacallan	mptr = (uint8_t *)fPtr->msk + (fPtr->um * srcy) + srcx;
1046e1ea03a3Smacallan	lsptr = sptr;
1047e1ea03a3Smacallan	lmptr = mptr;
1048e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
1049e1ea03a3Smacallan		rep = 128 / fPtr->uw;
1050e1ea03a3Smacallan		period = rep * fPtr->uw;
1051e1ea03a3Smacallan	}
1052e1ea03a3Smacallan
1053e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
1054e1ea03a3Smacallan	xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)aptr, fPtr->uw);
1055e1ea03a3Smacallan#endif
1056e1ea03a3Smacallan	lcnt = fPtr->uh;
1057e1ea03a3Smacallan	for (i = 0; i < height; i++) {
1058e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
1059e1ea03a3Smacallan		for (k = 0; k < rep; k++) {
1060e1ea03a3Smacallan			asptr = lsptr;
1061e1ea03a3Smacallan			amptr = lmptr;
1062e1ea03a3Smacallan			for (j = 0; j < fPtr->uw; j++) {
1063e1ea03a3Smacallan				pixel = *asptr;
1064e1ea03a3Smacallan				mask = *amptr;
1065e1ea03a3Smacallan				if (mask == 0xff) {
1066e1ea03a3Smacallan					*dptr = (pixel >> 24) | (pixel << 8);
1067e1ea03a3Smacallan				} else if (mask == 0x00) {
1068e1ea03a3Smacallan					*dptr = 0;
1069e1ea03a3Smacallan				} else {
1070e1ea03a3Smacallan					/* input is ARGB */
1071e1ea03a3Smacallan					sb = pixel & 0xff;
1072e1ea03a3Smacallan					sg = (pixel >> 8) & 0xff;
1073e1ea03a3Smacallan					sr = (pixel >> 16) & 0xff;
1074e1ea03a3Smacallan					sa = (pixel >> 24) & 0xff;
1075e1ea03a3Smacallan
1076e1ea03a3Smacallan					/* and here we need an RGBA pixel */
1077e1ea03a3Smacallan					bb = (((sb * mask) + 0x80) & 0xff00);
1078e1ea03a3Smacallan					gg = (((sg * mask) + 0x80) & 0xff00)
1079e1ea03a3Smacallan					     << 8;
1080e1ea03a3Smacallan					rr = (((sr * mask) + 0x80) & 0xff00)
1081e1ea03a3Smacallan					     << 16;
1082e1ea03a3Smacallan					aa = (((sa * mask) + 0x80) & 0xff00)
1083e1ea03a3Smacallan					     >> 8;
1084e1ea03a3Smacallan					/*
1085e1ea03a3Smacallan					 * actually we could let the HW do this
1086e1ea03a3Smacallan					 * stuff
1087e1ea03a3Smacallan					 */
1088e1ea03a3Smacallan					*dptr = aa | rr | gg | bb;
1089e1ea03a3Smacallan				}
1090e1ea03a3Smacallan				dptr++;
1091e1ea03a3Smacallan				asptr++;
1092e1ea03a3Smacallan				amptr++;
1093e1ea03a3Smacallan			}
1094e1ea03a3Smacallan		}
1095e1ea03a3Smacallan		xoff = 0;
1096e1ea03a3Smacallan		SYNC;
1097e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
1098e1ea03a3Smacallan		while (xoff < width) {
1099e1ea03a3Smacallan			xa = dstx + xoff;
1100e1ea03a3Smacallan			xe = dstx + min(xoff + period, width) - 1;
1101e1ea03a3Smacallan			READY;
1102e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0,
1103e1ea03a3Smacallan			    xa << 16 | (dsty + i));
1104e1ea03a3Smacallan			WBFLUSH;
1105e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
1106e1ea03a3Smacallan				(xe << 16) | (dsty + i));
1107e1ea03a3Smacallan			xoff += period;
1108e1ea03a3Smacallan		}
1109e1ea03a3Smacallan		bufnum++;
1110e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
1111e1ea03a3Smacallan		lcnt--;
1112e1ea03a3Smacallan		if (lcnt == 0) {
1113e1ea03a3Smacallan			/* back to the beginning */
1114e1ea03a3Smacallan			lsptr = sptr;
1115e1ea03a3Smacallan			lmptr = mptr;
1116e1ea03a3Smacallan			lcnt = fPtr->uh;
1117e1ea03a3Smacallan		} else
1118e1ea03a3Smacallan			/* next line */
1119e1ea03a3Smacallan			lsptr += fPtr->us;
1120e1ea03a3Smacallan			lmptr += fPtr->um;
1121e1ea03a3Smacallan	}
1122e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1123e1ea03a3Smacallan}
1124e1ea03a3Smacallan
1125e1ea03a3Smacallanstatic void
1126e1ea03a3SmacallanCrimeDoCPUToScreenComposite(
1127e1ea03a3Smacallan   	CARD8      op,
1128e1ea03a3Smacallan        PicturePtr pSrc,
1129e1ea03a3Smacallan        PicturePtr pMask,
1130e1ea03a3Smacallan        PicturePtr pDst,
1131e1ea03a3Smacallan        INT16      xSrc,
1132e1ea03a3Smacallan        INT16      ySrc,
1133e1ea03a3Smacallan        INT16      xMask,
1134e1ea03a3Smacallan        INT16      yMask,
1135e1ea03a3Smacallan        INT16      xDst,
1136e1ea03a3Smacallan        INT16      yDst,
1137e1ea03a3Smacallan        CARD16     width,
1138e1ea03a3Smacallan        CARD16     height
1139e1ea03a3Smacallan)
1140e1ea03a3Smacallan{
1141e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1142e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1143e1ea03a3Smacallan	RegionRec region;
1144e1ea03a3Smacallan	CARD32 *formats;
1145e1ea03a3Smacallan	int flags = 0;
1146e1ea03a3Smacallan	BoxPtr pbox;
1147e1ea03a3Smacallan	int nbox, w, h;
1148e1ea03a3Smacallan
1149e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1150e1ea03a3Smacallan	if (pSrc->transform || (pMask && pMask->transform)) {
1151e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: transform?!\n", __func__);
1152e1ea03a3Smacallan		return;
1153e1ea03a3Smacallan	}
1154e1ea03a3Smacallan
1155e1ea03a3Smacallan	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) {
1156e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: alpha-map?!\n", __func__);
1157e1ea03a3Smacallan		return;
1158e1ea03a3Smacallan	}
1159e1ea03a3Smacallan
1160e1ea03a3Smacallan	xDst += pDst->pDrawable->x;
1161e1ea03a3Smacallan	yDst += pDst->pDrawable->y;
1162e1ea03a3Smacallan	xSrc += pSrc->pDrawable->x;
1163e1ea03a3Smacallan	ySrc += pSrc->pDrawable->y;
1164e1ea03a3Smacallan
1165e1ea03a3Smacallan	if(pMask) {
1166e1ea03a3Smacallan		CARD16 red, green, blue, alpha;
1167e1ea03a3Smacallan		CARD32 pixel =
1168e1ea03a3Smacallan		    *((CARD32*)(((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr));
116909f0d67cSmacallan#ifdef CRIME_DEBUG_LOUD
1170e1ea03a3Smacallan		if(pMask->componentAlpha) {
1171e1ea03a3Smacallan			xf86Msg(X_ERROR, "%s: alpha component mask\n",
1172e1ea03a3Smacallan			    __func__);
117309f0d67cSmacallan			xf86Msg(X_ERROR, "src: %d x %d\n", pSrc->pDrawable->width,
117409f0d67cSmacallan			    pSrc->pDrawable->height);
1175e1ea03a3Smacallan		}
117609f0d67cSmacallan#endif
1177e1ea03a3Smacallan		if ((pSrc->pDrawable->width == 1) &&
1178e1ea03a3Smacallan		    (pSrc->pDrawable->height == 1)) {
1179e1ea03a3Smacallan
1180e1ea03a3Smacallan			if(!XAAGetRGBAFromPixel(pixel, &red, &green, &blue,
1181e1ea03a3Smacallan			    &alpha, pSrc->format)) {
1182e1ea03a3Smacallan				xf86Msg(X_ERROR, "%s: can't read pixel\n", __func__);
1183e1ea03a3Smacallan				return;
1184e1ea03a3Smacallan			}
1185e1ea03a3Smacallan			xMask += pMask->pDrawable->x;
1186e1ea03a3Smacallan			yMask += pMask->pDrawable->y;
1187e1ea03a3Smacallan
1188e1ea03a3Smacallan			/* pull out color expandable operations here */
1189e1ea03a3Smacallan			if(pMask->format == PICT_a1) {
1190e1ea03a3Smacallan				PixmapPtr pPix = (PixmapPtr)(pMask->pDrawable);
1191e1ea03a3Smacallan				int skipleft;
1192e1ea03a3Smacallan
1193e1ea03a3Smacallan				if (alpha == 0xffff) {
1194e1ea03a3Smacallan					/* actually we can but for now we don't care */
1195e1ea03a3Smacallan					xf86Msg(X_ERROR,
1196e1ea03a3Smacallan					   "can't colour expand with alpha\n");
1197e1ea03a3Smacallan					return;
1198e1ea03a3Smacallan				}
1199e1ea03a3Smacallan				if (op != PictOpOver) {
1200e1ea03a3Smacallan					xf86Msg(X_ERROR, "!over\n");
1201e1ea03a3Smacallan					return;
1202e1ea03a3Smacallan				}
1203e1ea03a3Smacallan				if (pMask->repeat) {
1204e1ea03a3Smacallan					xf86Msg(X_ERROR, "mono repeat\n");
1205e1ea03a3Smacallan					return;
1206e1ea03a3Smacallan				}
1207e1ea03a3Smacallan				if (!miComputeCompositeRegion (&region, pSrc,
1208e1ea03a3Smacallan				    pMask, pDst, xSrc, ySrc, xMask, yMask, xDst,
1209e1ea03a3Smacallan				    yDst, width, height)) {
1210e1ea03a3Smacallan					return;
1211e1ea03a3Smacallan				}
1212e1ea03a3Smacallan
1213e1ea03a3Smacallan				nbox = REGION_NUM_RECTS(&region);
1214e1ea03a3Smacallan				pbox = REGION_RECTS(&region);
1215e1ea03a3Smacallan
1216e1ea03a3Smacallan				if(!nbox) {
1217e1ea03a3Smacallan					return;
1218e1ea03a3Smacallan				}
1219e1ea03a3Smacallan
1220e1ea03a3Smacallan				XAAGetPixelFromRGBA(&pixel, red, green, blue, 0,
1221e1ea03a3Smacallan				    pDst->format);
1222e1ea03a3Smacallan
1223e1ea03a3Smacallan				xMask -= xDst;
1224e1ea03a3Smacallan				yMask -= yDst;
1225e1ea03a3Smacallan
1226e1ea03a3Smacallan				while(nbox--) {
1227e1ea03a3Smacallan					skipleft = pbox->x1 + xMask;
1228e1ea03a3Smacallan
1229e1ea03a3Smacallan					(*infoRec->WriteBitmap)(infoRec->pScrn, 					    pbox->x1, pbox->y1,
1230e1ea03a3Smacallan					    pbox->x2 - pbox->x1,
1231e1ea03a3Smacallan					    pbox->y2 - pbox->y1,
1232e1ea03a3Smacallan					    (unsigned char*)(pPix->devPrivate.ptr) + 					    (pPix->devKind *
1233e1ea03a3Smacallan					    (pbox->y1 + yMask)) + ((skipleft >> 3) & ~3),
1234e1ea03a3Smacallan					    pPix->devKind, skipleft & 31, pixel, -1,
1235e1ea03a3Smacallan					    GXcopy, ~0);
1236e1ea03a3Smacallan					pbox++;
1237e1ea03a3Smacallan				}
1238e1ea03a3Smacallan
1239e1ea03a3Smacallan				/* WriteBitmap sets the Sync flag */
1240e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1241e1ea03a3Smacallan				DONE(CRIME_DEBUG_XRENDER);
1242e1ea03a3Smacallan				return;
1243e1ea03a3Smacallan			}
124409f0d67cSmacallan			if((pMask->format == PICT_a8) ||
124509f0d67cSmacallan			   (pMask->format == PICT_a8r8g8b8)) {
1246e1ea03a3Smacallan
1247e1ea03a3Smacallan				w = pMask->pDrawable->width;
1248e1ea03a3Smacallan				h = pMask->pDrawable->height;
1249e1ea03a3Smacallan
1250e1ea03a3Smacallan				if(pMask->repeat) {
1251e1ea03a3Smacallan					flags |= XAA_RENDER_REPEAT;
1252e1ea03a3Smacallan				}
1253e1ea03a3Smacallan
1254e1ea03a3Smacallan				if (!miComputeCompositeRegion (&region, pSrc, pMask,
1255e1ea03a3Smacallan				    pDst, xSrc, ySrc, xMask, yMask, xDst, yDst,
1256e1ea03a3Smacallan				    width, height)) {
1257e1ea03a3Smacallan					return;
1258e1ea03a3Smacallan				}
1259e1ea03a3Smacallan
1260e1ea03a3Smacallan				nbox = REGION_NUM_RECTS(&region);
1261e1ea03a3Smacallan				pbox = REGION_RECTS(&region);
1262e1ea03a3Smacallan
1263e1ea03a3Smacallan				if(!nbox) {
1264e1ea03a3Smacallan					REGION_UNINIT(pScreen, &region);
1265e1ea03a3Smacallan					return;
1266e1ea03a3Smacallan				}
1267e1ea03a3Smacallan
1268e1ea03a3Smacallan				CrimeSetupForCPUToScreenAlphaTexture(infoRec->pScrn,
1269e1ea03a3Smacallan				    op, red, green, blue, alpha, pMask->format,
1270e1ea03a3Smacallan				    ((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr,
1271e1ea03a3Smacallan				    ((PixmapPtr)(pMask->pDrawable))->devKind,
1272e1ea03a3Smacallan				    w, h, flags);
1273e1ea03a3Smacallan
1274e1ea03a3Smacallan				xMask -= xDst;
1275e1ea03a3Smacallan				yMask -= yDst;
1276e1ea03a3Smacallan
127709f0d67cSmacallan				if (pMask->format != PICT_a8) {
127809f0d67cSmacallan					while(nbox--) {
127909f0d67cSmacallan						CrimeSubsequentCPUToScreenAlphaTexture32(
128009f0d67cSmacallan						    infoRec->pScrn,
128109f0d67cSmacallan						    pbox->x1, pbox->y1, pbox->x1 + xMask,
128209f0d67cSmacallan						    pbox->y1 + yMask, pbox->x2 - pbox->x1,
128309f0d67cSmacallan						    pbox->y2 - pbox->y1);
128409f0d67cSmacallan						pbox++;
128509f0d67cSmacallan					}
128609f0d67cSmacallan				} else {
128709f0d67cSmacallan					while(nbox--) {
128809f0d67cSmacallan						CrimeSubsequentCPUToScreenAlphaTexture(
128909f0d67cSmacallan						    infoRec->pScrn,
129009f0d67cSmacallan						    pbox->x1, pbox->y1, pbox->x1 + xMask,
129109f0d67cSmacallan						    pbox->y1 + yMask, pbox->x2 - pbox->x1,
129209f0d67cSmacallan						    pbox->y2 - pbox->y1);
129309f0d67cSmacallan						pbox++;
129409f0d67cSmacallan					}
1295e1ea03a3Smacallan				}
1296e1ea03a3Smacallan				SET_SYNC_FLAG(infoRec);
1297e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1298e1ea03a3Smacallan				DONE(CRIME_DEBUG_XRENDER);
1299e1ea03a3Smacallan				return;
1300e1ea03a3Smacallan			} else {
1301e1ea03a3Smacallan				xf86Msg(X_ERROR, "unknown mask %x\n", pMask->format);
1302e1ea03a3Smacallan			}
1303e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1304e1ea03a3Smacallan			DONE(CRIME_DEBUG_XRENDER);
1305e1ea03a3Smacallan			return;
1306e1ea03a3Smacallan		} else {
1307e1ea03a3Smacallan			/* source isn't solid */
1308e1ea03a3Smacallan
1309e1ea03a3Smacallan			w = pSrc->pDrawable->width;
1310e1ea03a3Smacallan			h = pSrc->pDrawable->height;
1311e1ea03a3Smacallan
1312e1ea03a3Smacallan			if(pSrc->repeat)
1313e1ea03a3Smacallan				flags |= XAA_RENDER_REPEAT;
1314e1ea03a3Smacallan
1315e1ea03a3Smacallan			if (!miComputeCompositeRegion (&region, pSrc, pMask,
1316e1ea03a3Smacallan			    pDst, xSrc, ySrc, xMask, yMask, xDst, yDst,
1317e1ea03a3Smacallan			    width, height)) {
1318e1ea03a3Smacallan				return;
1319e1ea03a3Smacallan			}
1320e1ea03a3Smacallan
1321e1ea03a3Smacallan			nbox = REGION_NUM_RECTS(&region);
1322e1ea03a3Smacallan			pbox = REGION_RECTS(&region);
1323e1ea03a3Smacallan
1324e1ea03a3Smacallan			if(!nbox) {
1325e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1326e1ea03a3Smacallan				return;
1327e1ea03a3Smacallan			}
1328e1ea03a3Smacallan			CrimeSetupForCPUToScreenTextureMask(
1329e1ea03a3Smacallan			    infoRec->pScrn, op, pMask->format,
1330e1ea03a3Smacallan			    ((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr,
1331e1ea03a3Smacallan			    ((PixmapPtr)(pSrc->pDrawable))->devKind,
1332e1ea03a3Smacallan			    ((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr,
1333e1ea03a3Smacallan			    ((PixmapPtr)(pMask->pDrawable))->devKind,
1334e1ea03a3Smacallan			    w, h, flags);
1335e1ea03a3Smacallan
1336e1ea03a3Smacallan			xSrc -= xDst;
1337e1ea03a3Smacallan			ySrc -= yDst;
1338e1ea03a3Smacallan
1339e1ea03a3Smacallan			if (PICT_FORMAT_BPP(pMask->format) == 32) {
1340e1ea03a3Smacallan				while(nbox--) {
1341e1ea03a3Smacallan					CrimeSubsequentCPUToScreenTextureMask32(
1342e1ea03a3Smacallan					    infoRec->pScrn,
1343e1ea03a3Smacallan					    pbox->x1, pbox->y1,
1344e1ea03a3Smacallan					    pbox->x1 + xSrc, pbox->y1 + ySrc,
1345e1ea03a3Smacallan					    xMask, yMask,
1346e1ea03a3Smacallan					    pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
1347e1ea03a3Smacallan					pbox++;
1348e1ea03a3Smacallan				}
1349e1ea03a3Smacallan			} else {
1350e1ea03a3Smacallan				while(nbox--) {
1351e1ea03a3Smacallan					CrimeSubsequentCPUToScreenTextureMask8(
1352e1ea03a3Smacallan					    infoRec->pScrn,
1353e1ea03a3Smacallan					    pbox->x1, pbox->y1, pbox->x1 + xSrc,
1354e1ea03a3Smacallan					    pbox->y1 + ySrc,
1355e1ea03a3Smacallan					    xMask, yMask,
1356e1ea03a3Smacallan					    pbox->x2 - pbox->x1,
1357e1ea03a3Smacallan					    pbox->y2 - pbox->y1);
1358e1ea03a3Smacallan					pbox++;
1359e1ea03a3Smacallan				}
1360e1ea03a3Smacallan			}
1361e1ea03a3Smacallan
1362e1ea03a3Smacallan			SET_SYNC_FLAG(infoRec);
1363e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1364e1ea03a3Smacallan			DONE(CRIME_DEBUG_XRENDER);
1365e1ea03a3Smacallan			return;
1366e1ea03a3Smacallan		}
1367e1ea03a3Smacallan	} else {	/* no mask */
1368e1ea03a3Smacallan		formats = infoRec->CPUToScreenTextureFormats;
1369e1ea03a3Smacallan
1370e1ea03a3Smacallan		w = pSrc->pDrawable->width;
1371e1ea03a3Smacallan		h = pSrc->pDrawable->height;
1372e1ea03a3Smacallan
1373e1ea03a3Smacallan		if(pSrc->repeat)
1374e1ea03a3Smacallan			flags |= XAA_RENDER_REPEAT;
1375e1ea03a3Smacallan
1376e1ea03a3Smacallan		while(*formats != pSrc->format) {
1377e1ea03a3Smacallan			if(!(*formats)) {
1378e1ea03a3Smacallan				xf86Msg(X_ERROR,
1379e1ea03a3Smacallan				    "%s: format %x not found\n",
1380e1ea03a3Smacallan				    __func__, pSrc->format);
1381e1ea03a3Smacallan				return;
1382e1ea03a3Smacallan			}
1383e1ea03a3Smacallan			formats++;
1384e1ea03a3Smacallan		}
1385e1ea03a3Smacallan
1386e1ea03a3Smacallan		if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
1387e1ea03a3Smacallan                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
1388e1ea03a3Smacallan                                   width, height)) {
1389e1ea03a3Smacallan			return;
1390e1ea03a3Smacallan		}
1391e1ea03a3Smacallan
1392e1ea03a3Smacallan		nbox = REGION_NUM_RECTS(&region);
1393e1ea03a3Smacallan		pbox = REGION_RECTS(&region);
1394e1ea03a3Smacallan
1395e1ea03a3Smacallan		if(!nbox) {
1396e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1397e1ea03a3Smacallan			return;
1398e1ea03a3Smacallan		}
1399e1ea03a3Smacallan
1400e1ea03a3Smacallan		CrimeSetupForCPUToScreenTexture(infoRec->pScrn,
1401e1ea03a3Smacallan			op, pSrc->format,
1402e1ea03a3Smacallan			((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr,
1403e1ea03a3Smacallan			((PixmapPtr)(pSrc->pDrawable))->devKind,
1404e1ea03a3Smacallan			w, h, flags);
1405e1ea03a3Smacallan
1406e1ea03a3Smacallan		xSrc -= xDst;
1407e1ea03a3Smacallan		ySrc -= yDst;
1408e1ea03a3Smacallan
1409e1ea03a3Smacallan		while(nbox--) {
1410e1ea03a3Smacallan			CrimeSubsequentCPUToScreenTexture(infoRec->pScrn,
1411e1ea03a3Smacallan			    pbox->x1, pbox->y1, pbox->x1 + xSrc,
1412e1ea03a3Smacallan			    pbox->y1 + ySrc, pbox->x2 - pbox->x1,
1413e1ea03a3Smacallan			    pbox->y2 - pbox->y1);
1414e1ea03a3Smacallan			pbox++;
1415e1ea03a3Smacallan		}
1416e1ea03a3Smacallan
1417e1ea03a3Smacallan		SET_SYNC_FLAG(infoRec);
1418e1ea03a3Smacallan		REGION_UNINIT(pScreen, &region);
1419e1ea03a3Smacallan		DONE(CRIME_DEBUG_XRENDER);
1420e1ea03a3Smacallan		return;
1421e1ea03a3Smacallan	}
1422e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: shouldn't be here\n", __func__);
1423e1ea03a3Smacallan}
1424e1ea03a3Smacallan
1425e1ea03a3Smacallanstatic void
1426e1ea03a3SmacallanCrimeDoScreenToScreenComposite(
1427e1ea03a3Smacallan   	CARD8      op,
1428e1ea03a3Smacallan        PicturePtr pSrc,
1429e1ea03a3Smacallan        PicturePtr pMask,
1430e1ea03a3Smacallan        PicturePtr pDst,
1431e1ea03a3Smacallan        INT16      xSrc,
1432e1ea03a3Smacallan        INT16      ySrc,
1433e1ea03a3Smacallan        INT16      xMask,
1434e1ea03a3Smacallan        INT16      yMask,
1435e1ea03a3Smacallan        INT16      xDst,
1436e1ea03a3Smacallan        INT16      yDst,
1437e1ea03a3Smacallan        CARD16     width,
1438e1ea03a3Smacallan        CARD16     height
1439e1ea03a3Smacallan)
1440e1ea03a3Smacallan{
1441e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1442e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1443e1ea03a3Smacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1444e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1445e1ea03a3Smacallan	RegionRec region;
1446e1ea03a3Smacallan	CARD32 *formats;
1447e1ea03a3Smacallan	int flags = 0;
1448e1ea03a3Smacallan	BoxPtr pbox;
1449e1ea03a3Smacallan	int nbox;
1450e1ea03a3Smacallan	int xs, ys, xd, yd, w, h;
1451e1ea03a3Smacallan
1452e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1453e1ea03a3Smacallan	if (pSrc->transform || (pMask && pMask->transform)) {
1454e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: mask?!\n", __func__);
1455e1ea03a3Smacallan		return;
1456e1ea03a3Smacallan	}
1457e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d\n", __func__, op);
1458e1ea03a3Smacallan	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) {
1459e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: alpha-map\n", __func__);
1460e1ea03a3Smacallan		return;
1461e1ea03a3Smacallan	}
1462e1ea03a3Smacallan
1463e1ea03a3Smacallan	xDst += pDst->pDrawable->x;
1464e1ea03a3Smacallan	yDst += pDst->pDrawable->y;
1465e1ea03a3Smacallan	xSrc += pSrc->pDrawable->x;
1466e1ea03a3Smacallan	ySrc += pSrc->pDrawable->y;
1467e1ea03a3Smacallan
1468e1ea03a3Smacallan	formats = infoRec->CPUToScreenTextureFormats;
1469e1ea03a3Smacallan
1470e1ea03a3Smacallan	w = pSrc->pDrawable->width;
1471e1ea03a3Smacallan	h = pSrc->pDrawable->height;
1472e1ea03a3Smacallan
1473e1ea03a3Smacallan	if(pSrc->repeat)
1474e1ea03a3Smacallan		flags |= XAA_RENDER_REPEAT;
1475e1ea03a3Smacallan
1476e1ea03a3Smacallan	while(*formats != pSrc->format) {
1477e1ea03a3Smacallan		if(!(*formats)) return;
1478e1ea03a3Smacallan		formats++;
1479e1ea03a3Smacallan	}
1480e1ea03a3Smacallan
1481e1ea03a3Smacallan	if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
1482e1ea03a3Smacallan	    xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
1483e1ea03a3Smacallan		return;
1484e1ea03a3Smacallan
1485e1ea03a3Smacallan	nbox = REGION_NUM_RECTS(&region);
1486e1ea03a3Smacallan	pbox = REGION_RECTS(&region);
1487e1ea03a3Smacallan
1488e1ea03a3Smacallan	if(!nbox) {
1489e1ea03a3Smacallan		REGION_UNINIT(pScreen, &region);
1490e1ea03a3Smacallan		return;
1491e1ea03a3Smacallan	}
1492e1ea03a3Smacallan
1493e1ea03a3Smacallan	SYNC;
1494e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
1495e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1496e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 1);
1497e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
1498e1ea03a3Smacallan	    DE_ALPHA_ADD |
1499e1ea03a3Smacallan	    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
1500e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
1501e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1502e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
1503e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
1504e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
1505e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
1506e1ea03a3Smacallan
1507e1ea03a3Smacallan	xSrc -= xDst;
1508e1ea03a3Smacallan	ySrc -= yDst;
1509e1ea03a3Smacallan
1510e1ea03a3Smacallan	/* assume no overlap - might bite us in the arse at some point */
1511e1ea03a3Smacallan	while(nbox--) {
1512e1ea03a3Smacallan		xs = pbox->x1 + xSrc;
1513e1ea03a3Smacallan		ys = pbox->y1 + ySrc;
1514e1ea03a3Smacallan		xd = pbox->x1;
1515e1ea03a3Smacallan		yd = pbox->y1;
1516e1ea03a3Smacallan		w = pbox->x2 - pbox->x1;
1517e1ea03a3Smacallan		h = pbox->y2 - pbox->y1;
1518e1ea03a3Smacallan		READY;
1519e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC,(xs << 16) | (ys & 0xffff));
1520e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (xd << 16) | (yd & 0xffff));
1521e1ea03a3Smacallan		WBFLUSH;
1522e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
1523e1ea03a3Smacallan		    ((xd + w - 1) << 16) | ((yd + h - 1) & 0xffff));
1524e1ea03a3Smacallan		pbox++;
1525e1ea03a3Smacallan	}
1526e1ea03a3Smacallan
1527e1ea03a3Smacallan	SET_SYNC_FLAG(infoRec);
1528e1ea03a3Smacallan	REGION_UNINIT(pScreen, &region);
1529e1ea03a3Smacallan	return;
1530e1ea03a3Smacallan}
1531e1ea03a3Smacallan
1532e1ea03a3Smacallanstatic Bool
1533e1ea03a3SmacallanCrimeComposite(
1534e1ea03a3Smacallan   	CARD8      op,
1535e1ea03a3Smacallan        PicturePtr pSrc,
1536e1ea03a3Smacallan        PicturePtr pMask,
1537e1ea03a3Smacallan        PicturePtr pDst,
1538e1ea03a3Smacallan        INT16      xSrc,
1539e1ea03a3Smacallan        INT16      ySrc,
1540e1ea03a3Smacallan        INT16      xMask,
1541e1ea03a3Smacallan        INT16      yMask,
1542e1ea03a3Smacallan        INT16      xDst,
1543e1ea03a3Smacallan        INT16      yDst,
1544e1ea03a3Smacallan        CARD16     width,
1545e1ea03a3Smacallan        CARD16     height
1546e1ea03a3Smacallan)
1547e1ea03a3Smacallan{
1548e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1549e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1550e1ea03a3Smacallan
1551e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1552e1ea03a3Smacallan
1553e1ea03a3Smacallan	if(!REGION_NUM_RECTS(pDst->pCompositeClip))
1554e1ea03a3Smacallan		return TRUE;
1555e1ea03a3Smacallan
1556e1ea03a3Smacallan	if(!infoRec->pScrn->vtSema)
1557e1ea03a3Smacallan		return FALSE;
1558e1ea03a3Smacallan
1559e1ea03a3Smacallan	if((pDst->pDrawable->type == DRAWABLE_WINDOW) ||
1560e1ea03a3Smacallan	    IS_OFFSCREEN_PIXMAP(pDst->pDrawable)) {
1561e1ea03a3Smacallan		if ((pSrc->pDrawable->type == DRAWABLE_WINDOW) ||
1562e1ea03a3Smacallan		    IS_OFFSCREEN_PIXMAP(pSrc->pDrawable)) {
1563e1ea03a3Smacallan			/* screen-to-screen */
1564e1ea03a3Smacallan			CrimeDoScreenToScreenComposite(op, pSrc, pMask, pDst,
1565e1ea03a3Smacallan			    xSrc, ySrc, xMask, yMask,
1566e1ea03a3Smacallan			    xDst, yDst, width, height);
1567e1ea03a3Smacallan			return TRUE;
1568e1ea03a3Smacallan		} else {
1569e1ea03a3Smacallan			/* CPU-to-screen composite */
1570e1ea03a3Smacallan			if (op != PictOpOver)
1571e1ea03a3Smacallan				xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
1572e1ea03a3Smacallan			CrimeDoCPUToScreenComposite(op, pSrc, pMask, pDst,
1573e1ea03a3Smacallan			    xSrc, ySrc, xMask, yMask,
1574e1ea03a3Smacallan			    xDst, yDst, width, height);
1575e1ea03a3Smacallan			return TRUE;
1576e1ea03a3Smacallan		}
1577e1ea03a3Smacallan	} else {
1578e1ea03a3Smacallan		if ((pSrc->pDrawable->type == DRAWABLE_WINDOW) ||
1579e1ea03a3Smacallan		    IS_OFFSCREEN_PIXMAP(pSrc->pDrawable)) {
1580e1ea03a3Smacallan			/* screen-to-RAM */
1581e1ea03a3Smacallan			xf86Msg(X_ERROR, "%s: screen-to-RAM composite\n",
1582e1ea03a3Smacallan			   __func__);
1583e1ea03a3Smacallan			return TRUE;
1584e1ea03a3Smacallan		} else {
1585e1ea03a3Smacallan			/* RAM-to-RAM */
1586e1ea03a3Smacallan			return FALSE;
1587e1ea03a3Smacallan		}
1588e1ea03a3Smacallan	}
1589e1ea03a3Smacallan	xf86Msg(X_ERROR, "composite fucked\n");
1590e1ea03a3Smacallan}
1591e1ea03a3Smacallan
1592e1ea03a3Smacallanstatic void
1593e1ea03a3SmacallanCrimePolyPoint(
1594e1ea03a3Smacallan    DrawablePtr pDraw,
1595e1ea03a3Smacallan    GCPtr pGC,
1596e1ea03a3Smacallan    int mode,
1597e1ea03a3Smacallan    int npt,
1598e1ea03a3Smacallan    xPoint *pptInit
1599e1ea03a3Smacallan)
1600e1ea03a3Smacallan{
1601e1ea03a3Smacallan	ScreenPtr pScreen = pDraw->pScreen;
1602e1ea03a3Smacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1603e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1604e1ea03a3Smacallan	BoxPtr pBox;
1605e1ea03a3Smacallan	xPoint *ppt, *pts;
1606e1ea03a3Smacallan	int x1, x2, y1, y2, x, y, i, nBox;
1607e1ea03a3Smacallan
1608e1ea03a3Smacallan	/* make pointlist origin relative */
1609e1ea03a3Smacallan	ppt = pptInit;
1610e1ea03a3Smacallan	if (mode == CoordModePrevious) {
1611e1ea03a3Smacallan		for (i = 0; i < npt; i++) {
1612e1ea03a3Smacallan			ppt++;
1613e1ea03a3Smacallan			ppt->x += (ppt-1)->x;
1614e1ea03a3Smacallan			ppt->y += (ppt-1)->y;
1615e1ea03a3Smacallan		}
1616e1ea03a3Smacallan	}
1617e1ea03a3Smacallan	SYNC;
1618e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, pGC->fgPixel << 8);
1619e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, pGC->alu);
1620e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, pGC->planemask);
1621e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1622e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP);
1623e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE, DE_PRIM_POINT);
1624e1ea03a3Smacallan	for (nBox = REGION_NUM_RECTS (pGC->pCompositeClip),
1625e1ea03a3Smacallan	    pBox = REGION_RECTS (pGC->pCompositeClip);
1626e1ea03a3Smacallan	    nBox--; pBox++) {
1627e1ea03a3Smacallan
1628e1ea03a3Smacallan		pts = pptInit;
1629e1ea03a3Smacallan		for (i = 0; i < npt; i++) {
1630e1ea03a3Smacallan			x1 = pBox->x1;
1631e1ea03a3Smacallan			y1 = pBox->y1;
1632e1ea03a3Smacallan			x2 = pBox->x2;
1633e1ea03a3Smacallan			y2 = pBox->y2;
1634e1ea03a3Smacallan			x = pts->x + pDraw->x;
1635e1ea03a3Smacallan			y = pts->y + pDraw->y;
1636e1ea03a3Smacallan			if (x1 <= x && x < x2 && y1 <= y && y < y2) {
1637e1ea03a3Smacallan
1638e1ea03a3Smacallan		 		READY;
1639e1ea03a3Smacallan				WRITE4ST(CRIME_DE_X_VERTEX_0,
1640e1ea03a3Smacallan					(x << 16) | y);
1641e1ea03a3Smacallan			}
1642e1ea03a3Smacallan			pts++;
1643e1ea03a3Smacallan		}
1644e1ea03a3Smacallan	}
1645e1ea03a3Smacallan}
1646e1ea03a3Smacallan
1647e1ea03a3Smacallanstatic void
1648e1ea03a3SmacallanCrimeValidatePolyPoint(
1649e1ea03a3Smacallan   GCPtr         pGC,
1650e1ea03a3Smacallan   unsigned long changes,
1651e1ea03a3Smacallan   DrawablePtr   pDraw )
1652e1ea03a3Smacallan{
1653e1ea03a3Smacallan
1654e1ea03a3Smacallan	if ((pDraw->type == DRAWABLE_WINDOW) ||
1655e1ea03a3Smacallan	    IS_OFFSCREEN_PIXMAP(pDraw)) {
1656e1ea03a3Smacallan		pGC->ops->PolyPoint = CrimePolyPoint;
1657e1ea03a3Smacallan	} else
1658e1ea03a3Smacallan		xf86Msg(X_ERROR, "boo\n");
1659e1ea03a3Smacallan}
166034c4e112Smacallanstatic void
166134c4e112SmacallanCrimePolyArc(DrawablePtr pDraw,
166234c4e112Smacallan               GCPtr pGC,
166334c4e112Smacallan               int narcs,
166434c4e112Smacallan               xArc *parcs)
166534c4e112Smacallan{
166634c4e112Smacallan    xArc *arc;
166734c4e112Smacallan    BoxRec box;
166834c4e112Smacallan    int i, x2, y2;
166934c4e112Smacallan    RegionPtr cclip;
167034c4e112Smacallan
167134c4e112Smacallan    cclip = pGC->pCompositeClip;
167234c4e112Smacallan
167334c4e112Smacallan    if(!REGION_NUM_RECTS(cclip))
167434c4e112Smacallan	return;
167534c4e112Smacallan
167634c4e112Smacallan    for (arc = parcs, i = narcs; --i >= 0; arc++) {
167734c4e112Smacallan	if (miCanZeroArc(arc)) {
167834c4e112Smacallan	    box.x1 = arc->x + pDraw->x;
167934c4e112Smacallan	    box.y1 = arc->y + pDraw->y;
168034c4e112Smacallan 	    x2 = box.x1 + (int)arc->width + 1;
168134c4e112Smacallan 	    box.x2 = x2;
168234c4e112Smacallan 	    y2 = box.y1 + (int)arc->height + 1;
168334c4e112Smacallan 	    box.y2 = y2;
168434c4e112Smacallan 	    if ( (x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) &&
168534c4e112Smacallan 		    (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) )
168634c4e112Smacallan		miZeroPolyArc(pDraw, pGC, 1, arc);
168734c4e112Smacallan	}
168834c4e112Smacallan	else
168934c4e112Smacallan	    miPolyArc(pDraw, pGC, 1, arc);
169034c4e112Smacallan    }
169134c4e112Smacallan}
169234c4e112Smacallan
169334c4e112Smacallanstatic void
169434c4e112SmacallanCrimeValidatePolyArc(GCPtr pGC,
169534c4e112Smacallan                       unsigned long changes,
169634c4e112Smacallan                       DrawablePtr pDraw)
169734c4e112Smacallan{
169834c4e112Smacallan	if ((pDraw->type == DRAWABLE_WINDOW) ||
169934c4e112Smacallan	    IS_OFFSCREEN_PIXMAP(pDraw)) {
170034c4e112Smacallan		pGC->ops->PolyPoint = CrimePolyPoint;
170134c4e112Smacallan		/*pGC->ops->PolyArc = miPolyArc;*/
170234c4e112Smacallan		pGC->ops->PolyArc = CrimePolyArc;
170334c4e112Smacallan	} else
170434c4e112Smacallan	{
170534c4e112Smacallan		pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint;
170634c4e112Smacallan		pGC->ops->PolyArc = XAAGetFallbackOps()->PolyArc;
170734c4e112Smacallan	}
170834c4e112Smacallan}
1709e1ea03a3Smacallan
171034c4e112Smacallanstatic void
171134c4e112SmacallanCrimeReadPixmap(ScrnInfoPtr pScrn,
171234c4e112Smacallan                     int x,
171334c4e112Smacallan		     int y,
171434c4e112Smacallan		     int w,
171534c4e112Smacallan		     int h,
171634c4e112Smacallan		     unsigned char *dst,
171734c4e112Smacallan		     int dstwidth,
171834c4e112Smacallan		     int bpp,
171934c4e112Smacallan		     int depth)
172034c4e112Smacallan{
172134c4e112Smacallan	/* dummy for now */
172234c4e112Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
172334c4e112Smacallan}
1724e1ea03a3Smacallanint
1725e1ea03a3SmacallanCrimeAccelInit(ScrnInfoPtr pScrn)
1726e1ea03a3Smacallan{
1727e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1728e1ea03a3Smacallan	XAAInfoRecPtr pXAAInfo = fPtr->pXAA;
1729e1ea03a3Smacallan	int i;
1730e1ea03a3Smacallan
1731e1ea03a3Smacallan	for (i = 0; i < 0x1000; i++) regcache[i] = 0x12345678;
1732e1ea03a3Smacallan	LOG(CRIME_DEBUG_ALL);
1733e1ea03a3Smacallan	SYNC;
1734e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
1735e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1736e1ea03a3Smacallan
1737e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_Y, 1);
1738e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STRD_DST, 0);
1739e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STRD_SRC, 1);
1740e1ea03a3Smacallan
1741e1ea03a3Smacallan	WRITE4(CRIME_MTE_BYTEMASK, 0xffffffff);
1742e1ea03a3Smacallan	WRITE4(CRIME_MTE_SRC_Y_STEP, 4);
1743e1ea03a3Smacallan	WRITE4(CRIME_MTE_DST_Y_STEP, 4);
1744e1ea03a3Smacallan
1745e1ea03a3Smacallan	/* blit the screen black */
1746e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1747e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP);
1748e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, 3);
1749e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE, DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
1750e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, 0);
1751e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, 0);
1752e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
1753e1ea03a3Smacallan	    fPtr->info.width << 16 | fPtr->info.height);
1754e1ea03a3Smacallan	SYNC;
1755e1ea03a3Smacallan
175634c4e112Smacallan	pXAAInfo->Flags = /*LINEAR_FRAMEBUFFER |*/ PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
1757e1ea03a3Smacallan	pXAAInfo->maxOffPixWidth = fPtr->info.width;
1758e1ea03a3Smacallan	pXAAInfo->maxOffPixHeight = 2048;
1759e1ea03a3Smacallan
1760e1ea03a3Smacallan	/* Sync */
1761e1ea03a3Smacallan	pXAAInfo->Sync = CrimeSync;
1762e1ea03a3Smacallan
1763e1ea03a3Smacallan	/* Screen-to-screen copy */
1764e1ea03a3Smacallan	pXAAInfo->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
1765e1ea03a3Smacallan	pXAAInfo->SetupForScreenToScreenCopy = CrimeSetupForScreenToScreenCopy;
1766e1ea03a3Smacallan	pXAAInfo->SubsequentScreenToScreenCopy =
1767e1ea03a3Smacallan		CrimeSubsequentScreenToScreenCopy;
1768e1ea03a3Smacallan
1769e1ea03a3Smacallan	/* rectangle fills */
1770e1ea03a3Smacallan	pXAAInfo->SetupForSolidFill = CrimeSetupForSolidFill;
1771e1ea03a3Smacallan	pXAAInfo->SubsequentSolidFillRect = CrimeSubsequentSolidFillRect;
1772e1ea03a3Smacallan
1773e1ea03a3Smacallan	/* image writes */
1774e1ea03a3Smacallan	pXAAInfo->ScanlineImageWriteFlags =
1775e1ea03a3Smacallan	    NO_TRANSPARENCY | LEFT_EDGE_CLIPPING |
1776e1ea03a3Smacallan	    LEFT_EDGE_CLIPPING_NEGATIVE_X |
1777e1ea03a3Smacallan	    CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD;
1778e1ea03a3Smacallan	pXAAInfo->NumScanlineImageWriteBuffers = 8;
1779e1ea03a3Smacallan	for (i = 0; i < 8; i++)
1780e1ea03a3Smacallan		fPtr->buffers[i] = fPtr->linear + (i * 8192);
1781e1ea03a3Smacallan	pXAAInfo->ScanlineImageWriteBuffers = fPtr->buffers;
1782e1ea03a3Smacallan	pXAAInfo->SetupForScanlineImageWrite =
1783e1ea03a3Smacallan		CrimeSetupForScanlineImageWrite;
1784e1ea03a3Smacallan	pXAAInfo->SubsequentScanlineImageWriteRect =
1785e1ea03a3Smacallan		CrimeSubsequentImageWriteRect;
1786e1ea03a3Smacallan	pXAAInfo->SubsequentImageWriteScanline =
1787e1ea03a3Smacallan		CrimeSubsequentImageWriteScanline;
1788e1ea03a3Smacallan
178934c4e112Smacallan	/* read pixmap */
179034c4e112Smacallan	pXAAInfo->ReadPixmapFlags = 0
179134c4e112Smacallan	                             | CPU_TRANSFER_PAD_DWORD
179234c4e112Smacallan				     ;
179334c4e112Smacallan	pXAAInfo->ReadPixmap = CrimeReadPixmap;
179434c4e112Smacallan
1795e1ea03a3Smacallan	/* colour expansion */
1796e1ea03a3Smacallan	pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags =
1797e1ea03a3Smacallan		LEFT_EDGE_CLIPPING;
1798e1ea03a3Smacallan	pXAAInfo->NumScanlineColorExpandBuffers = 1;
1799e1ea03a3Smacallan	fPtr->expandbuffers[0] = (uint8_t *)fPtr->expand;
1800e1ea03a3Smacallan	pXAAInfo->ScanlineColorExpandBuffers = (void *)&fPtr->expandbuffers;
1801e1ea03a3Smacallan	pXAAInfo->SetupForScanlineCPUToScreenColorExpandFill =
1802e1ea03a3Smacallan		CrimeSetupForCPUToScreenColorExpandFill;
1803e1ea03a3Smacallan	pXAAInfo->SubsequentScanlineCPUToScreenColorExpandFill =
1804e1ea03a3Smacallan		CrimeSubsequentScanlineCPUToScreenColorExpandFill;
1805e1ea03a3Smacallan	pXAAInfo->SubsequentColorExpandScanline =
1806e1ea03a3Smacallan		CrimeSubsequentColorExpandScanline;
1807e1ea03a3Smacallan
1808e1ea03a3Smacallan	/* clipping */
1809e1ea03a3Smacallan	pXAAInfo->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
1810e1ea03a3Smacallan		HARDWARE_CLIP_SOLID_FILL | HARDWARE_CLIP_SOLID_LINE;
1811e1ea03a3Smacallan	pXAAInfo->SetClippingRectangle = CrimeSetClippingRectangle;
1812e1ea03a3Smacallan	pXAAInfo->DisableClipping = CrimeDisableClipping;
1813e1ea03a3Smacallan
1814e1ea03a3Smacallan	/* solid line drawing */
1815e1ea03a3Smacallan	pXAAInfo->SetupForSolidLine = CrimeSetupForSolidLine;
1816e1ea03a3Smacallan	pXAAInfo->SubsequentSolidTwoPointLine =
1817e1ea03a3Smacallan	    CrimeSubsequentSolidTwoPointLine;
1818e1ea03a3Smacallan	pXAAInfo->SolidLineFlags = BIT_ORDER_IN_BYTE_MSBFIRST;
1819e1ea03a3Smacallan
1820e1ea03a3Smacallan	/* dashed line drawing */
1821e1ea03a3Smacallan	pXAAInfo->SetupForDashedLine = CrimeSetupForDashedLine;
1822e1ea03a3Smacallan	pXAAInfo->SubsequentDashedTwoPointLine =
1823e1ea03a3Smacallan	    CrimeSubsequentDashedTwoPointLine;
1824e1ea03a3Smacallan	pXAAInfo->DashedLineFlags = LINE_PATTERN_MSBFIRST_MSBJUSTIFIED;
1825e1ea03a3Smacallan	pXAAInfo->DashPatternMaxLength = 32;
1826e1ea03a3Smacallan
1827e1ea03a3Smacallan	/* XRender acceleration */
1828e1ea03a3Smacallan#ifdef RENDER
1829e1ea03a3Smacallan	pXAAInfo->CPUToScreenAlphaTextureFlags = 0;
1830e1ea03a3Smacallan	pXAAInfo->SetupForCPUToScreenAlphaTexture =
1831e1ea03a3Smacallan	    CrimeSetupForCPUToScreenAlphaTexture;
1832e1ea03a3Smacallan	pXAAInfo->SubsequentCPUToScreenAlphaTexture =
1833e1ea03a3Smacallan	    CrimeSubsequentCPUToScreenAlphaTexture;
1834e1ea03a3Smacallan	pXAAInfo->CPUToScreenAlphaTextureFormats = CrimeAlphaTextureFormats;
1835e1ea03a3Smacallan
1836e1ea03a3Smacallan	pXAAInfo->SetupForCPUToScreenTexture = CrimeSetupForCPUToScreenTexture;
1837e1ea03a3Smacallan	pXAAInfo->SubsequentCPUToScreenTexture =
1838e1ea03a3Smacallan	    CrimeSubsequentCPUToScreenTexture;
1839e1ea03a3Smacallan	pXAAInfo->CPUToScreenTextureFlags = 0;
1840e1ea03a3Smacallan	pXAAInfo->CPUToScreenTextureFormats = CrimeTextureFormats;
1841e1ea03a3Smacallan	pXAAInfo->Composite = CrimeComposite;
1842e1ea03a3Smacallan#endif
1843e1ea03a3Smacallan	pXAAInfo->ValidatePolyPoint = CrimeValidatePolyPoint;
1844e1ea03a3Smacallan	pXAAInfo->PolyPointMask = GCFunction;
184534c4e112Smacallan	pXAAInfo->ValidatePolyArc = CrimeValidatePolyArc;
184634c4e112Smacallan	pXAAInfo->PolyArcMask = GCFunction | GCLineWidth;
1847e1ea03a3Smacallan
1848e1ea03a3Smacallan	return -1;
1849e1ea03a3Smacallan}
1850