crime_accel.c revision f282839b
1f282839bSmacallan/* $NetBSD: crime_accel.c,v 1.12 2009/10/06 06:25:47 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"
37850ab569Smacallan#include "xaa.h"
38e1ea03a3Smacallan
39e1ea03a3Smacallanuint32_t regcache[0x1000];
40e1ea03a3Smacallan
41e1ea03a3Smacallan#define CRIMEREG(p) (volatile uint32_t *)(fPtr->engine + p)
42e1ea03a3Smacallan/*#define WBFLUSH { volatile uint32_t boo = *CRIMEREG(0x4000); }*/
43e1ea03a3Smacallan#define WBFLUSH __asm__ ("nop; sync;")
44e1ea03a3Smacallan#if 0
45e1ea03a3Smacallan#define WRITE4(r, v) {if (regcache[r >> 2] != v) { \
46e1ea03a3Smacallan			*CRIMEREG(r) = v; \
47e1ea03a3Smacallan			regcache[r >> 2] = v; } }
48e1ea03a3Smacallan#else
49e1ea03a3Smacallan#define WRITE4(r, v) { *CRIMEREG(r) = v; }
50e1ea03a3Smacallan#endif
51e1ea03a3Smacallan#define WRITE4ST(r, v) {WBFLUSH; *CRIMEREG(r + CRIME_DE_START) = v; WBFLUSH;}
52850ab569Smacallan#ifdef CRIME_DEBUG
53e1ea03a3Smacallan#define SYNC { int bail = 0; do {bail++; } \
54e1ea03a3Smacallan          while(((*CRIMEREG(0x4000) & CRIME_DE_IDLE) == 0) && (bail < 10000000)); \
55e1ea03a3Smacallan          if (bail == 10000000) { \
56e1ea03a3Smacallan          	xf86Msg(X_ERROR, "sync timeout\n"); \
57e1ea03a3Smacallan          	WRITE4ST(CRIME_MTE_FLUSH, 0); \
58e1ea03a3Smacallan          	WRITE4ST(CRIME_DE_FLUSH, 0); \
59e1ea03a3Smacallan          } \
60e1ea03a3Smacallan        }
61e1ea03a3Smacallan#else
62e1ea03a3Smacallan#define SYNC do {} while ((*CRIMEREG(0x4000) & CRIME_DE_IDLE) == 0)
6326dcc2a3Smacallan#define SYNCMTE do {} while ((*CRIMEREG(0x4000) & CRIME_DE_MTE_IDLE) == 0)
64e1ea03a3Smacallan#endif
6526dcc2a3Smacallan#define MAKE_ROOM(x) do {} while ((16 - \
6626dcc2a3Smacallan				   CRIME_PIPE_LEVEL(*CRIMEREG(0x4000))) < x);
67e1ea03a3Smacallan
687a6652bbSmacallan#define MAX(a, b) (a > b ? a : b)
697a6652bbSmacallan#define MIN(a, b) (a < b ? a : b)
707a6652bbSmacallan
71e1ea03a3SmacallanCARD32 CrimeAlphaTextureFormats[] = {PICT_a8, 0};
72e1ea03a3SmacallanCARD32 CrimeTextureFormats[] = {PICT_a8b8g8r8, PICT_a8r8g8b8, 0};
73e1ea03a3Smacallan
74e1ea03a3Smacallanvoid
75e1ea03a3SmacallanCrimeSync(ScrnInfoPtr pScrn)
76e1ea03a3Smacallan{
77e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
78e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
79e1ea03a3Smacallan	volatile uint32_t *status = CRIMEREG(CRIME_DE_STATUS);
80e1ea03a3Smacallan
81e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %08x\n", __func__, *status);
82e1ea03a3Smacallan#endif
83e1ea03a3Smacallan	LOG(CRIME_DEBUG_SYNC);
84e1ea03a3Smacallan	SYNC;
85e1ea03a3Smacallan}
86e1ea03a3Smacallan
87e1ea03a3Smacallanstatic void
88e1ea03a3SmacallanCrimeSetupForScreenToScreenCopy(
89e1ea03a3Smacallan	ScrnInfoPtr  pScrn,
90e1ea03a3Smacallan	int          xdir,
91e1ea03a3Smacallan	int          ydir,
92e1ea03a3Smacallan	int          rop,
93e1ea03a3Smacallan	unsigned int planemask,
94e1ea03a3Smacallan	int          TransparencyColour
95e1ea03a3Smacallan)
96e1ea03a3Smacallan{
97e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
98e1ea03a3Smacallan
99e1ea03a3Smacallan	LOG(CRIME_DEBUG_BITBLT);
10026dcc2a3Smacallan	MAKE_ROOM(9);
101e1ea03a3Smacallan	if ((rop == GXcopy) && (planemask == 0xffffffff) && (xdir > 0)) {
102e1ea03a3Smacallan		/* use the MTE */
103e1ea03a3Smacallan		WRITE4(CRIME_MTE_MODE, MTE_MODE_DST_ECC |
104e1ea03a3Smacallan		    MTE_TLB_A << MTE_DST_TLB_SHIFT |
105e1ea03a3Smacallan		    MTE_TLB_A << MTE_SRC_TLB_SHIFT |
106e1ea03a3Smacallan		    MTE_DEPTH_32 << MTE_DEPTH_SHIFT |
107e1ea03a3Smacallan		    MTE_MODE_COPY);
108e1ea03a3Smacallan		fPtr->use_mte = 1;
109e1ea03a3Smacallan		if (ydir > 0) {
110e1ea03a3Smacallan			WRITE4(CRIME_MTE_DST_Y_STEP, 1);
111e1ea03a3Smacallan			WRITE4(CRIME_MTE_SRC_Y_STEP, 1);
112e1ea03a3Smacallan		} else {
113e1ea03a3Smacallan			WRITE4(CRIME_MTE_DST_Y_STEP, -1);
114e1ea03a3Smacallan			WRITE4(CRIME_MTE_SRC_Y_STEP, -1);
115e1ea03a3Smacallan		}
116e1ea03a3Smacallan	} else
117e1ea03a3Smacallan		fPtr->use_mte = 0;
118e1ea03a3Smacallan
119e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 1);
120e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
121e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
122e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
123e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
124e1ea03a3Smacallan	    DE_DRAWMODE_ROP | DE_DRAWMODE_XFER_EN);
125e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
126e1ea03a3Smacallan		    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
12726dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
12826dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
129e1ea03a3Smacallan	fPtr->xdir = xdir;
130e1ea03a3Smacallan	fPtr->ydir = ydir;
13126dcc2a3Smacallan	SYNC;
132e1ea03a3Smacallan	DONE(CRIME_DEBUG_BITBLT);
133e1ea03a3Smacallan}
134e1ea03a3Smacallan
135e1ea03a3Smacallanstatic void
136e1ea03a3SmacallanCrimeSubsequentScreenToScreenCopy
137e1ea03a3Smacallan(
138e1ea03a3Smacallan	ScrnInfoPtr pScrn,
139e1ea03a3Smacallan	int         xSrc,
140e1ea03a3Smacallan	int         ySrc,
141e1ea03a3Smacallan	int         xDst,
142e1ea03a3Smacallan	int         yDst,
143e1ea03a3Smacallan	int         w,
144e1ea03a3Smacallan	int         h
145e1ea03a3Smacallan)
146e1ea03a3Smacallan{
147e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
148e1ea03a3Smacallan	uint32_t prim = DE_PRIM_RECTANGLE;
149e1ea03a3Smacallan	uint32_t rxa, rya, rxe, rye, rxs, rys, rxd, ryd, rxde, ryde;
150e1ea03a3Smacallan
151e1ea03a3Smacallan	LOG(CRIME_DEBUG_BITBLT);
152e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
153e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d, %d; %d x %d -> %d %d\n", __func__,
154e1ea03a3Smacallan	    xSrc, ySrc, w, h, xDst, yDst);
155e1ea03a3Smacallan#endif
156231734e4Smacallan	if ((fPtr->use_mte) && (w > 64) && /*((w & 3) == 0) &&*/
157231734e4Smacallan	   ((xSrc & 15) == (xDst & 15))) {
158e1ea03a3Smacallan		if (fPtr->ydir == -1) {
159e1ea03a3Smacallan			/* bottom to top */
160e1ea03a3Smacallan			rye = ySrc;
161e1ea03a3Smacallan			rya = ySrc + h - 1;
162e1ea03a3Smacallan			ryd = yDst + h - 1;
163e1ea03a3Smacallan			ryde = yDst;
164e1ea03a3Smacallan		} else {
165e1ea03a3Smacallan			/* top to bottom */
166e1ea03a3Smacallan			rye = ySrc + h - 1;
167e1ea03a3Smacallan			rya = ySrc;
168e1ea03a3Smacallan			ryd = yDst;
169e1ea03a3Smacallan			ryde = yDst + h - 1;
170e1ea03a3Smacallan		}
171e1ea03a3Smacallan		rxa = xSrc << 2;
172e1ea03a3Smacallan		rxe = ((xSrc + w) << 2) - 1;
173e1ea03a3Smacallan		rxd = xDst << 2;
174e1ea03a3Smacallan		rxde = ((xDst + w) << 2) - 1;
17526dcc2a3Smacallan		MAKE_ROOM(4);
176e1ea03a3Smacallan		WRITE4(CRIME_MTE_SRC0, (rxa << 16) | rya);
177e1ea03a3Smacallan		WRITE4(CRIME_MTE_SRC1, (rxe << 16) | rye);
178e1ea03a3Smacallan		WRITE4(CRIME_MTE_DST0, (rxd << 16) | ryd);
179e1ea03a3Smacallan		WRITE4ST(CRIME_MTE_DST1, (rxde << 16) | ryde);
180e1ea03a3Smacallan
181e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
182e1ea03a3Smacallan		xf86Msg(X_ERROR, "reg: %08x %08x\n", oreg, reg);
183e1ea03a3Smacallan#endif
184e1ea03a3Smacallan	} else {
185e1ea03a3Smacallan		if (fPtr->xdir == -1) {
186e1ea03a3Smacallan			prim |= DE_PRIM_RL;
187e1ea03a3Smacallan			rxe = xDst;
188e1ea03a3Smacallan			rxa = xDst + w - 1;
189e1ea03a3Smacallan			rxs = xSrc + w - 1;
190e1ea03a3Smacallan		} else {
191e1ea03a3Smacallan			prim |= DE_PRIM_LR;
192e1ea03a3Smacallan			rxe = xDst + w - 1;
193e1ea03a3Smacallan			rxa = xDst;
194e1ea03a3Smacallan			rxs = xSrc;
195e1ea03a3Smacallan		}
196e1ea03a3Smacallan		if (fPtr->ydir == -1) {
197e1ea03a3Smacallan			prim |= DE_PRIM_BT;
198e1ea03a3Smacallan			rye = yDst;
199e1ea03a3Smacallan			rya = yDst + h - 1;
200e1ea03a3Smacallan			rys = ySrc + h - 1;
201e1ea03a3Smacallan		} else {
202e1ea03a3Smacallan			prim |= DE_PRIM_TB;
203e1ea03a3Smacallan			rye = yDst + h - 1;
204e1ea03a3Smacallan			rya = yDst;
205e1ea03a3Smacallan			rys = ySrc;
206e1ea03a3Smacallan		}
207e1ea03a3Smacallan
20826dcc2a3Smacallan		MAKE_ROOM(4);
209e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE, prim);
210e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC,(rxs << 16) | (rys & 0xffff));
211e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (rxa << 16) | (rya & 0xffff));
212e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1, (rxe << 16) | (rye & 0xffff));
213e1ea03a3Smacallan	}
214e1ea03a3Smacallan	DONE(CRIME_DEBUG_BITBLT);
215e1ea03a3Smacallan}
216e1ea03a3Smacallan
217e1ea03a3Smacallanstatic void
218e1ea03a3SmacallanCrimeSetupForSolidFill
219e1ea03a3Smacallan(
220e1ea03a3Smacallan    ScrnInfoPtr  pScrn,
221e1ea03a3Smacallan    int          colour,
222e1ea03a3Smacallan    int          rop,
223e1ea03a3Smacallan    unsigned int planemask
224e1ea03a3Smacallan)
225e1ea03a3Smacallan{
226e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
227e1ea03a3Smacallan	int i;
228e1ea03a3Smacallan
229e1ea03a3Smacallan	LOG(CRIME_DEBUG_RECTFILL);
230850ab569Smacallan#ifdef MTE_DRAW_RECT
231231734e4Smacallan	if (rop == GXcopy) {
232231734e4Smacallan		fPtr->use_mte = 1;
233231734e4Smacallan		MAKE_ROOM(3);
234231734e4Smacallan		WRITE4(CRIME_MTE_MODE, MTE_MODE_DST_ECC |
235231734e4Smacallan		    MTE_TLB_A << MTE_DST_TLB_SHIFT |
236231734e4Smacallan		    MTE_TLB_A << MTE_SRC_TLB_SHIFT |
237231734e4Smacallan		    MTE_DEPTH_32 << MTE_DEPTH_SHIFT);
238231734e4Smacallan		WRITE4(CRIME_MTE_DST_Y_STEP, 1);
239231734e4Smacallan		WRITE4(CRIME_MTE_BG, colour << 8);
240231734e4Smacallan		SYNCMTE;
241850ab569Smacallan	} else
242850ab569Smacallan#endif
243850ab569Smacallan	{
244231734e4Smacallan		fPtr->use_mte = 0;
245231734e4Smacallan		MAKE_ROOM(7);
246231734e4Smacallan		WRITE4(CRIME_DE_PLANEMASK, planemask);
247231734e4Smacallan		WRITE4(CRIME_DE_ROP, rop);
248231734e4Smacallan		WRITE4(CRIME_DE_FG, colour << 8);
249231734e4Smacallan		WRITE4(CRIME_DE_DRAWMODE,
250231734e4Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
251231734e4Smacallan		    DE_DRAWMODE_ROP |\
252231734e4Smacallan		    DE_DRAWMODE_SCISSOR_EN);
253231734e4Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
254231734e4Smacallan		    DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
255231734e4Smacallan		WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
256231734e4Smacallan		    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
257231734e4Smacallan		SYNC;
258231734e4Smacallan	}
259e1ea03a3Smacallan	DONE(CRIME_DEBUG_RECTFILL);
260e1ea03a3Smacallan}
261e1ea03a3Smacallan
262e1ea03a3Smacallanstatic void
263e1ea03a3SmacallanCrimeSubsequentSolidFillRect
264e1ea03a3Smacallan(
265e1ea03a3Smacallan    ScrnInfoPtr pScrn,
266e1ea03a3Smacallan    int         x,
267e1ea03a3Smacallan    int         y,
268e1ea03a3Smacallan    int         w,
269e1ea03a3Smacallan    int         h
270e1ea03a3Smacallan)
271e1ea03a3Smacallan{
272e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
2737a6652bbSmacallan	int xa, xe, ya, ye;
274e1ea03a3Smacallan
275e1ea03a3Smacallan	LOG(CRIME_DEBUG_RECTFILL);
276850ab569Smacallan#ifdef MTE_DRAW_RECT
277231734e4Smacallan	if (fPtr->use_mte) {
2787a6652bbSmacallan
2797a6652bbSmacallan		/*
2807a6652bbSmacallan		 * the MTE doesn't support clipping so we have to do it
2817a6652bbSmacallan		 * ourselves - luckily it's trivial with rectangles
2827a6652bbSmacallan		 */
2837a6652bbSmacallan		xa = MAX(fPtr->cxa, x);
2847a6652bbSmacallan		ya = MAX(fPtr->cya, y);
2857a6652bbSmacallan		xe = MIN(fPtr->cxe, x + w);
2867a6652bbSmacallan		ye = MIN(fPtr->cye, y + h);
2877a6652bbSmacallan		if ((xa < xe) && (ya < ye)) {
2887a6652bbSmacallan			MAKE_ROOM(2);
2897a6652bbSmacallan			WRITE4(CRIME_MTE_DST0, (xa << 18) | (ya & 0xffff));
2907a6652bbSmacallan			WRITE4ST(CRIME_MTE_DST1,
2917a6652bbSmacallan		 	   (((xe << 2) - 1 ) << 16) | ((ye - 1) & 0xffff));
2927a6652bbSmacallan		}
293850ab569Smacallan	} else
294850ab569Smacallan#endif
295850ab569Smacallan	{
296231734e4Smacallan		MAKE_ROOM(2);
297231734e4Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (x << 16) | (y & 0xffff));
298231734e4Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
299231734e4Smacallan		    ((x + w - 1) << 16) | ((y + h - 1) & 0xffff));
300231734e4Smacallan	}
301e1ea03a3Smacallan	DONE(CRIME_DEBUG_RECTFILL);
302e1ea03a3Smacallan}
303e1ea03a3Smacallan
3045b2650b9Smacallanstatic void
3055b2650b9SmacallanCrimeSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty,
3065b2650b9Smacallan        int fg, int bg, int rop, unsigned int planemask)
3075b2650b9Smacallan{
3085b2650b9Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
3095b2650b9Smacallan	uint32_t pat;
3105b2650b9Smacallan
3115b2650b9Smacallan	LOG(CRIME_DEBUG_RECTFILL);
3125b2650b9Smacallan	MAKE_ROOM(7);
3135b2650b9Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
3145b2650b9Smacallan	WRITE4(CRIME_DE_ROP, rop);
3155b2650b9Smacallan	WRITE4(CRIME_DE_FG, fg << 8);
3165b2650b9Smacallan	if (bg == -1) {
3175b2650b9Smacallan		WRITE4(CRIME_DE_DRAWMODE,
3185b2650b9Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
3195b2650b9Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_POLY_STIP |
3205b2650b9Smacallan		    DE_DRAWMODE_SCISSOR_EN);
3215b2650b9Smacallan	} else {
3225b2650b9Smacallan		WRITE4(CRIME_DE_BG, bg << 8);
3235b2650b9Smacallan		WRITE4(CRIME_DE_DRAWMODE,
3245b2650b9Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
3255b2650b9Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_POLY_STIP |
3265b2650b9Smacallan		    DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_SCISSOR_EN);
3275b2650b9Smacallan	}
3285b2650b9Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
3295b2650b9Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
3305b2650b9Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
3315b2650b9Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
3325b2650b9Smacallan
3335b2650b9Smacallan	/*
3345b2650b9Smacallan	 * we need to store the pattern so we can just hammer it into the
3355b2650b9Smacallan	 * stipple register later on
3365b2650b9Smacallan	 */
3375b2650b9Smacallan	pat = patx & 0xff000000;
3385b2650b9Smacallan	pat |= pat >> 8;
3395b2650b9Smacallan	fPtr->pattern[0] = pat | (pat >> 16);
3405b2650b9Smacallan	pat = patx & 0x00ff0000;
3415b2650b9Smacallan	pat |= pat << 8;
3425b2650b9Smacallan	fPtr->pattern[1] = pat | (pat >> 16);
3435b2650b9Smacallan	pat = patx & 0x0000ff00;
3445b2650b9Smacallan	pat |= pat >> 8;
3455b2650b9Smacallan	fPtr->pattern[2] = pat | (pat << 16);
3465b2650b9Smacallan	pat = patx & 0x000000ff;
3475b2650b9Smacallan	pat |= pat << 8;
3485b2650b9Smacallan	fPtr->pattern[3] = pat | (pat << 16);
3495b2650b9Smacallan
3505b2650b9Smacallan	pat = paty & 0xff000000;
3515b2650b9Smacallan	pat |= pat >> 8;
3525b2650b9Smacallan	fPtr->pattern[4] = pat | (pat >> 16);
3535b2650b9Smacallan	pat = paty & 0x00ff0000;
3545b2650b9Smacallan	pat |= pat << 8;
3555b2650b9Smacallan	fPtr->pattern[5] = pat | (pat >> 16);
3565b2650b9Smacallan	pat = paty & 0x0000ff00;
3575b2650b9Smacallan	pat |= pat >> 8;
3585b2650b9Smacallan	fPtr->pattern[6] = pat | (pat << 16);
3595b2650b9Smacallan	pat = paty & 0x000000ff;
3605b2650b9Smacallan	pat |= pat << 8;
3615b2650b9Smacallan	fPtr->pattern[7] = pat | (pat << 16);
3625b2650b9Smacallan	SYNC;
3635b2650b9Smacallan	DONE(CRIME_DEBUG_RECTFILL);
3645b2650b9Smacallan}
3655b2650b9Smacallan
3665b2650b9Smacallanstatic void
3675b2650b9SmacallanCrimeSubsequentMono8x8PatternFillRect( ScrnInfoPtr pScrn,
3685b2650b9Smacallan        	int patx, int paty, int x, int y, int w, int h)
3695b2650b9Smacallan{
3705b2650b9Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
3715b2650b9Smacallan	int i, pat;
3725b2650b9Smacallan
3735b2650b9Smacallan	LOG(CRIME_DEBUG_RECTFILL);
3745b2650b9Smacallan
3755b2650b9Smacallan	/* first setup the stipple stuff */
3765b2650b9Smacallan
3775b2650b9Smacallan	MAKE_ROOM(1);
3785b2650b9Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, 0x001f0000 | (patx << 24));
3795b2650b9Smacallan	pat = paty;
3805b2650b9Smacallan
3815b2650b9Smacallan	for (i = 0; i < h; i++) {
3825b2650b9Smacallan		MAKE_ROOM(3);
3835b2650b9Smacallan		WRITE4(CRIME_DE_STIPPLE_PAT, fPtr->pattern[pat]);
3845b2650b9Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (x << 16) | ((y + i) & 0xffff));
3855b2650b9Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
3865b2650b9Smacallan		    ((x + w - 1) << 16) | ((y + i) & 0xffff));
3875b2650b9Smacallan		pat = (pat + 1) & 7;
3885b2650b9Smacallan	}
3895b2650b9Smacallan	DONE(CRIME_DEBUG_RECTFILL);
3905b2650b9Smacallan}
3915b2650b9Smacallan
3925b2650b9Smacallanstatic void
393e1ea03a3SmacallanCrimeSetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
394e1ea03a3Smacallan                                unsigned int planemask, int trans_color,
395e1ea03a3Smacallan                                int bpp, int depth)
396e1ea03a3Smacallan{
397e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
398e1ea03a3Smacallan
399e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
400e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
401e1ea03a3Smacallan	if ((bpp == 24) || (depth == 24))
402e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d \n", __func__, bpp, depth);
403e1ea03a3Smacallan#endif
40426dcc2a3Smacallan	MAKE_ROOM(7);
405e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
406e1ea03a3Smacallan			    DE_MODE_TYPE_RGB | DE_MODE_PIXDEPTH_32);
40726dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
40826dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
409e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
410e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
411e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
412e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
413e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP |
414e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
415e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
416e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
41726dcc2a3Smacallan	SYNC;
418e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
419e1ea03a3Smacallan}
420e1ea03a3Smacallan
4215b2650b9Smacallanstatic void
422e1ea03a3SmacallanCrimeSubsequentImageWriteRect(ScrnInfoPtr pScrn,
423e1ea03a3Smacallan                                int x, int y, int w, int h, int skipleft)
424e1ea03a3Smacallan{
425e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
426e1ea03a3Smacallan
427e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
428e1ea03a3Smacallan
429e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
430e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d\n", __func__, x, y, w, h);
431e1ea03a3Smacallan#endif
432e1ea03a3Smacallan
433e1ea03a3Smacallan	fPtr->start = skipleft;
434e1ea03a3Smacallan	x += skipleft;
435e1ea03a3Smacallan	w -= skipleft;
436e1ea03a3Smacallan	if (x < 0) {
437e1ea03a3Smacallan		fPtr->ux = 0;
438e1ea03a3Smacallan		w += x;
439e1ea03a3Smacallan		fPtr->start -= x;
440e1ea03a3Smacallan	} else {
441e1ea03a3Smacallan		fPtr->ux = x;
442e1ea03a3Smacallan	}
443e1ea03a3Smacallan	fPtr->uy = y;
444e1ea03a3Smacallan	fPtr->uw = w;
445e1ea03a3Smacallan	fPtr->uh = h;
446e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
447e1ea03a3Smacallan}
448e1ea03a3Smacallan
4495b2650b9Smacallanstatic void
450e1ea03a3SmacallanCrimeSubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
451e1ea03a3Smacallan{
452e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
453e1ea03a3Smacallan
454e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
45526dcc2a3Smacallan	/*
45626dcc2a3Smacallan	 * we need to sync here, otherwise we might queue up more copy
45726dcc2a3Smacallan	 * commands than we have buffers
45826dcc2a3Smacallan	 */
45934c4e112Smacallan	SYNC;
460e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_ADDR_SRC, (bufno << 13)  + (fPtr->start << 2));
461e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (fPtr->ux << 16) | fPtr->uy);
462e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
463e1ea03a3Smacallan		((fPtr->ux + fPtr->uw - 1) << 16) | (fPtr->uy));
464e1ea03a3Smacallan	fPtr->uy++;
465e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
466e1ea03a3Smacallan}
467e1ea03a3Smacallan
468e1ea03a3Smacallanstatic void
469e1ea03a3SmacallanCrimeSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
470e1ea03a3Smacallan        		int fg, int bg,
471e1ea03a3Smacallan			int rop,
472e1ea03a3Smacallan			unsigned int planemask)
473e1ea03a3Smacallan{
474e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
475e1ea03a3Smacallan
476e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
47726dcc2a3Smacallan	MAKE_ROOM(7);
47826dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
47926dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
480e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
481e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
482e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, fg << 8);
483e1ea03a3Smacallan	if (bg == -1) {
484e1ea03a3Smacallan		/* transparent */
485e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
486e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
487e1ea03a3Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_POLY_STIP);
488e1ea03a3Smacallan	} else {
489e1ea03a3Smacallan		WRITE4(CRIME_DE_BG, bg << 8);
490e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
491e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
492e1ea03a3Smacallan		    DE_DRAWMODE_ROP |
493e1ea03a3Smacallan		    DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_POLY_STIP);
494e1ea03a3Smacallan	}
495e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
496e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
49726dcc2a3Smacallan	SYNC;
498e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
499e1ea03a3Smacallan}
500e1ea03a3Smacallan
501e1ea03a3Smacallanstatic void
502e1ea03a3SmacallanCrimeSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
503e1ea03a3Smacallan			int x, int y, int w, int h,
504e1ea03a3Smacallan			int skipleft )
505e1ea03a3Smacallan{
506e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
507e1ea03a3Smacallan
508e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
509e1ea03a3Smacallan
510e1ea03a3Smacallan	fPtr->start = skipleft;
511e1ea03a3Smacallan	fPtr->ux = x;
512e1ea03a3Smacallan	fPtr->uy = y;
513e1ea03a3Smacallan	fPtr->uw = w;
514e1ea03a3Smacallan	fPtr->uh = h;
515e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
516e1ea03a3Smacallan}
517e1ea03a3Smacallan
518e1ea03a3Smacallanstatic void
519e1ea03a3SmacallanCrimeSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
520e1ea03a3Smacallan{
521e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
522e1ea03a3Smacallan	uint32_t *boo = (uint32_t *)fPtr->expandbuffers[bufno];
523e1ea03a3Smacallan	int idx = fPtr->uw, x = fPtr->ux;
524e1ea03a3Smacallan
525e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
526e1ea03a3Smacallan
52726dcc2a3Smacallan	MAKE_ROOM(5);
528e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, 0x001f0000 | (fPtr->start << 24));
529e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_PAT, *boo);
530e1ea03a3Smacallan	boo++;
531e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x + fPtr->start << 16) | fPtr->uy);
532e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
533e1ea03a3Smacallan		((x + min(idx, 32) - 1) << 16) | (fPtr->uy));
534e1ea03a3Smacallan	idx -= 32;
535e1ea03a3Smacallan	x += 32;
536e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, 0x001f0000);
537e1ea03a3Smacallan
538e1ea03a3Smacallan	while (idx > 0) {
53926dcc2a3Smacallan		MAKE_ROOM(3);
540e1ea03a3Smacallan		WRITE4(CRIME_DE_STIPPLE_PAT, *boo);
541e1ea03a3Smacallan		boo++;
542e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (x << 16) | fPtr->uy);
543e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
544e1ea03a3Smacallan			((x + min(idx, 32) - 1) << 16) | (fPtr->uy));
545e1ea03a3Smacallan		idx -= 32;
546e1ea03a3Smacallan		x += 32;
547e1ea03a3Smacallan	}
548e1ea03a3Smacallan	fPtr->uy++;
549e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
550e1ea03a3Smacallan}
551e1ea03a3Smacallan
552e1ea03a3Smacallanstatic void
553e1ea03a3SmacallanCrimeSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
554e1ea03a3Smacallan    unsigned int planemask)
555e1ea03a3Smacallan{
556e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
557e1ea03a3Smacallan
558e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
559e1ea03a3Smacallan
56026dcc2a3Smacallan	MAKE_ROOM(5);
56126dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
56226dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
563e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
564e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
565e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, color << 8);
566e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
567e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
56893351543Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_SCISSOR_EN);
56926dcc2a3Smacallan	SYNC;
570e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
571e1ea03a3Smacallan}
572e1ea03a3Smacallan
573e1ea03a3Smacallanstatic void
574e1ea03a3SmacallanCrimeSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2,
575e1ea03a3Smacallan    int y2, int flags)
576e1ea03a3Smacallan{
577e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
578e1ea03a3Smacallan
579e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
58026dcc2a3Smacallan	MAKE_ROOM(3);
581e1ea03a3Smacallan	if (flags & OMIT_LAST) {
582e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
583e1ea03a3Smacallan			DE_PRIM_LINE | DE_PRIM_LINE_SKIP_END | 2);
584e1ea03a3Smacallan	} else {
585e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
586e1ea03a3Smacallan			DE_PRIM_LINE | 2);
587e1ea03a3Smacallan	}
588e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x1 << 16) | y1);
589e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1, (x2 << 16) | y2);
590e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
591850ab569Smacallan}
592e1ea03a3Smacallan
593e1ea03a3Smacallanvoid
594e1ea03a3SmacallanCrimeSetupForDashedLine(ScrnInfoPtr pScrn,
595e1ea03a3Smacallan		int fg, int bg, int rop, unsigned int planemask,
596e1ea03a3Smacallan        	int length, unsigned char *pattern)
597e1ea03a3Smacallan{
598e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
599e1ea03a3Smacallan	uint32_t pat;
600e1ea03a3Smacallan
601e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
602e1ea03a3Smacallan
603e1ea03a3Smacallan	fPtr->uw = length;
60426dcc2a3Smacallan	MAKE_ROOM(7);
60526dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
60626dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
607e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
608e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
609e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, fg << 8);
610e1ea03a3Smacallan	if (bg == -1) {
611e1ea03a3Smacallan		/* transparent */
612e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
613e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
61493351543Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_LINE_STIP |
61593351543Smacallan		    DE_DRAWMODE_SCISSOR_EN);
616e1ea03a3Smacallan	} else {
617e1ea03a3Smacallan		WRITE4(CRIME_DE_BG, bg << 8);
618e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
619e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
62093351543Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_SCISSOR_EN |
621e1ea03a3Smacallan		    DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_LINE_STIP);
622e1ea03a3Smacallan	}
623e1ea03a3Smacallan	/*
624e1ea03a3Smacallan	 * can we trust the Xserver to always hand us a 32bit aligned
625e1ea03a3Smacallan	 * pattern buffer?
626e1ea03a3Smacallan	 */
627e1ea03a3Smacallan	memcpy(&pat, pattern, 4);
628e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_PAT, pat);
62926dcc2a3Smacallan	SYNC;
630e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
631e1ea03a3Smacallan}
632e1ea03a3Smacallan
633e1ea03a3Smacallanvoid
634e1ea03a3SmacallanCrimeSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn,
635e1ea03a3Smacallan        int x1, int y1, int x2, int y2, int flags, int phase)
636e1ea03a3Smacallan{
637e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
638e1ea03a3Smacallan	uint32_t stipmode;
639e1ea03a3Smacallan
640e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
64126dcc2a3Smacallan	MAKE_ROOM(4);
642e1ea03a3Smacallan
643e1ea03a3Smacallan	if (flags & OMIT_LAST) {
644e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
645e1ea03a3Smacallan			DE_PRIM_LINE | DE_PRIM_LINE_SKIP_END | 2);
646e1ea03a3Smacallan	} else {
647e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
648e1ea03a3Smacallan			DE_PRIM_LINE | 2);
649e1ea03a3Smacallan	}
650e1ea03a3Smacallan
651e1ea03a3Smacallan	stipmode = ((fPtr->uw - 1) << 16) | (phase << 24);
652e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, stipmode);
653e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x1 << 16) | y1);
654e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1, (x2 << 16) | y2);
655e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
656e1ea03a3Smacallan}
657e1ea03a3Smacallan
658e1ea03a3Smacallanvoid
659e1ea03a3SmacallanCrimeSetClippingRectangle ( ScrnInfoPtr pScrn,
660e1ea03a3Smacallan                        int left, int top, int right, int bottom)
661e1ea03a3Smacallan{
662e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
663e1ea03a3Smacallan
664e1ea03a3Smacallan	LOG(CRIME_DEBUG_CLIPPING);
66526dcc2a3Smacallan	MAKE_ROOM(2);
66693351543Smacallan	WRITE4(CRIME_DE_SCISSOR, (left << 16) | top);
66793351543Smacallan	WRITE4(CRIME_DE_SCISSOR + 4, ((right + 1) << 16) | (bottom + 1));
6687a6652bbSmacallan	fPtr->cxa = left;
6697a6652bbSmacallan	fPtr->cxe = right;
6707a6652bbSmacallan	fPtr->cya = top;
6717a6652bbSmacallan	fPtr->cye = bottom;
67226dcc2a3Smacallan	SYNC;
673e1ea03a3Smacallan	DONE(CRIME_DEBUG_CLIPPING);
674e1ea03a3Smacallan}
675e1ea03a3Smacallan
676e1ea03a3Smacallanvoid
677e1ea03a3SmacallanCrimeDisableClipping (ScrnInfoPtr pScrn)
678e1ea03a3Smacallan{
679e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
680e1ea03a3Smacallan
681e1ea03a3Smacallan	LOG(CRIME_DEBUG_CLIPPING);
68226dcc2a3Smacallan	MAKE_ROOM(2);
68393351543Smacallan	WRITE4(CRIME_DE_SCISSOR, 0);
68493351543Smacallan	WRITE4(CRIME_DE_SCISSOR + 4, 0x3fff3fff);
6857a6652bbSmacallan	fPtr->cxa = 0;
6867a6652bbSmacallan	fPtr->cxe = 2047;
6877a6652bbSmacallan	fPtr->cya = 0;
6887a6652bbSmacallan	fPtr->cye = 2047;
68926dcc2a3Smacallan	SYNC;
690e1ea03a3Smacallan	DONE(CRIME_DEBUG_CLIPPING);
691e1ea03a3Smacallan}
692e1ea03a3Smacallan
693e1ea03a3Smacallanstatic Bool
694e1ea03a3SmacallanCrimeSetupForCPUToScreenAlphaTexture (
695e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
696e1ea03a3Smacallan   int		op,
697e1ea03a3Smacallan   CARD16	red,
698e1ea03a3Smacallan   CARD16	green,
699e1ea03a3Smacallan   CARD16	blue,
700e1ea03a3Smacallan   CARD16	alpha,
701e1ea03a3Smacallan   int		alphaType,
702e1ea03a3Smacallan   CARD8	*alphaPtr,
703e1ea03a3Smacallan   int		alphaPitch,
704e1ea03a3Smacallan   int		width,
705e1ea03a3Smacallan   int		height,
706e1ea03a3Smacallan   int		flags
707e1ea03a3Smacallan)
708e1ea03a3Smacallan{
709e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
710e1ea03a3Smacallan
711e1ea03a3Smacallan	if (op != PictOpOver) {
712e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
713e1ea03a3Smacallan		op = PictOpOver;
714e1ea03a3Smacallan	}
715e1ea03a3Smacallan
716e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
717e1ea03a3Smacallan
718e1ea03a3Smacallan	fPtr->alpha_color = ((red & 0xff00) << 16) |
719e1ea03a3Smacallan			    ((green & 0xff00) << 8) |
72009f0d67cSmacallan			    (blue & 0xff00);
721e1ea03a3Smacallan	fPtr->uw = width;
722e1ea03a3Smacallan	fPtr->uh = height;
723e1ea03a3Smacallan	fPtr->us = alphaPitch;
724e1ea03a3Smacallan	fPtr->alpha_texture = alphaPtr;
72509f0d67cSmacallan	fPtr->format = alphaType;
7265b2650b9Smacallan#ifdef CRIME_DEBUG_LOUD
72709f0d67cSmacallan	if (alphaType != PICT_a8) {
72809f0d67cSmacallan		xf86Msg(X_ERROR, "ARGB mask %08x %d\n", (uint32_t)alphaPtr,
72909f0d67cSmacallan		    alphaPitch);
73009f0d67cSmacallan	}
7315b2650b9Smacallan#endif
73226dcc2a3Smacallan	MAKE_ROOM(7);
73326dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
73426dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
735e1ea03a3Smacallan	/* XXX this register is not where it's supposed to be */
736e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_COLOR, fPtr->alpha_color);
73709f0d67cSmacallan	if (alphaType == PICT_a8) {
73809f0d67cSmacallan		if (fPtr->alpha_color == 0) {
73909f0d67cSmacallan			WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_8 |
740e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
74109f0d67cSmacallan			WRITE4(CRIME_DE_XFER_STEP_X, 1);
74209f0d67cSmacallan			WRITE4(CRIME_DE_ALPHA_FUNC,
74309f0d67cSmacallan			    DE_ALPHA_ADD |
74409f0d67cSmacallan			    (DE_ALPHA_OP_ZERO << DE_ALPHA_OP_SRC_SHIFT) |
74509f0d67cSmacallan			    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
74609f0d67cSmacallan		} else {
74709f0d67cSmacallan			WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
74809f0d67cSmacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
74909f0d67cSmacallan			WRITE4(CRIME_DE_XFER_STEP_X, 4);
75009f0d67cSmacallan			WRITE4(CRIME_DE_ALPHA_FUNC,
75109f0d67cSmacallan			    DE_ALPHA_ADD |
75209f0d67cSmacallan			    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
75309f0d67cSmacallan			    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
75409f0d67cSmacallan		}
755e1ea03a3Smacallan	} else {
756e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
757e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
758e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_STEP_X, 4);
759e1ea03a3Smacallan		WRITE4(CRIME_DE_ALPHA_FUNC,
760e1ea03a3Smacallan		    DE_ALPHA_ADD |
761e1ea03a3Smacallan		    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
762e1ea03a3Smacallan		    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
76309f0d67cSmacallan	}
764e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
765e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
766e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
767e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
768e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
76926dcc2a3Smacallan	SYNC;
770e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
771e1ea03a3Smacallan	return TRUE;
772e1ea03a3Smacallan}
773e1ea03a3Smacallan
774e1ea03a3Smacallanvoid
775e1ea03a3SmacallanCrimeSubsequentCPUToScreenAlphaTexture (
776e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
777e1ea03a3Smacallan    int		dstx,
778e1ea03a3Smacallan    int		dsty,
779e1ea03a3Smacallan    int		srcx,
780e1ea03a3Smacallan    int		srcy,
781e1ea03a3Smacallan    int		width,
782e1ea03a3Smacallan    int		height
783e1ea03a3Smacallan)
784e1ea03a3Smacallan{
785e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
786e1ea03a3Smacallan	unsigned char *aptr;
787e1ea03a3Smacallan	uint32_t *dptr, aval;
788e1ea03a3Smacallan	int i, j;
789e1ea03a3Smacallan	int bufnum = 0;
790e1ea03a3Smacallan
791e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
792e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
793e1ea03a3Smacallan	xf86Msg(X_ERROR, "%d %d %d %d %d %d\n",srcx, srcy, dstx, dsty, width,
794e1ea03a3Smacallan	    height);
795e1ea03a3Smacallan#endif
796e1ea03a3Smacallan	aptr = fPtr->alpha_texture + (fPtr->us * srcy) + srcx;
797e1ea03a3Smacallan	for (i = 0; i < height; i++) {
798e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
799e1ea03a3Smacallan		if (fPtr->alpha_color == 0) {
800e1ea03a3Smacallan			memcpy(dptr, aptr, width);
801e1ea03a3Smacallan		} else {
802e1ea03a3Smacallan			for (j = 0; j < width; j++) {
803e1ea03a3Smacallan				aval = aptr[j];
804e1ea03a3Smacallan				*dptr = aval | fPtr->alpha_color;
805e1ea03a3Smacallan				dptr++;
806e1ea03a3Smacallan			}
807e1ea03a3Smacallan		}
80826dcc2a3Smacallan		MAKE_ROOM(3);
809e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
810e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
811e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
812e1ea03a3Smacallan			((dstx + width - 1) << 16) | (dsty + i));
813e1ea03a3Smacallan		bufnum++;
814e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
815e1ea03a3Smacallan		aptr += fPtr->us;
816e1ea03a3Smacallan	}
817e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
818e1ea03a3Smacallan}
819e1ea03a3Smacallan
82009f0d67cSmacallanvoid
82109f0d67cSmacallanCrimeSubsequentCPUToScreenAlphaTexture32 (
82209f0d67cSmacallan    ScrnInfoPtr	pScrn,
82309f0d67cSmacallan    int		dstx,
82409f0d67cSmacallan    int		dsty,
82509f0d67cSmacallan    int		srcx,
82609f0d67cSmacallan    int		srcy,
82709f0d67cSmacallan    int		width,
82809f0d67cSmacallan    int		height
82909f0d67cSmacallan)
83009f0d67cSmacallan{
83109f0d67cSmacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
83209f0d67cSmacallan	uint8_t *aptr;
83309f0d67cSmacallan	uint32_t *dptr, *sptr;
83409f0d67cSmacallan	int i, j;
83509f0d67cSmacallan	int bufnum = 0;
83609f0d67cSmacallan
83709f0d67cSmacallan	LOG(CRIME_DEBUG_XRENDER);
83826dcc2a3Smacallan#ifdef CRIME_DEBUG_LOUD
83909f0d67cSmacallan	xf86Msg(X_ERROR, "%d %d %d %d %d %d\n",srcx, srcy, dstx, dsty, width,
84009f0d67cSmacallan	    height);
84109f0d67cSmacallan#endif
84209f0d67cSmacallan	aptr = fPtr->alpha_texture + (fPtr->us * srcy) + (srcx << 2);
84309f0d67cSmacallan	for (i = 0; i < height; i++) {
84409f0d67cSmacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
84509f0d67cSmacallan		sptr = (uint32_t *)aptr;
84609f0d67cSmacallan		for (j = 0; j < width; j++) {
84709f0d67cSmacallan			*dptr = (*sptr >> 24) | fPtr->alpha_color;
84809f0d67cSmacallan#ifdef CRIME_DEBUG_LOUD
84909f0d67cSmacallan			xf86Msg(X_ERROR, "%08x %08x\n", *sptr, *dptr);
85009f0d67cSmacallan#endif
85109f0d67cSmacallan			sptr++;
85209f0d67cSmacallan			dptr++;
85309f0d67cSmacallan		}
85426dcc2a3Smacallan		MAKE_ROOM(3);
85509f0d67cSmacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
85609f0d67cSmacallan		WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
85709f0d67cSmacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
85809f0d67cSmacallan			((dstx + width - 1) << 16) | (dsty + i));
85909f0d67cSmacallan		bufnum++;
86009f0d67cSmacallan		if (bufnum == 8) bufnum = 0;
86109f0d67cSmacallan		aptr += fPtr->us;
86209f0d67cSmacallan	}
86309f0d67cSmacallan	DONE(CRIME_DEBUG_XRENDER);
86409f0d67cSmacallan}
86509f0d67cSmacallan
866e1ea03a3Smacallanstatic Bool
867e1ea03a3SmacallanCrimeSetupForCPUToScreenTexture (
868e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
869e1ea03a3Smacallan   int		op,
870e1ea03a3Smacallan   int		texType,
871e1ea03a3Smacallan   CARD8	*texPtr,
872e1ea03a3Smacallan   int		texPitch,
873e1ea03a3Smacallan   int		width,
874e1ea03a3Smacallan   int		height,
875e1ea03a3Smacallan   int		flags
876e1ea03a3Smacallan)
877e1ea03a3Smacallan{
878e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
879e1ea03a3Smacallan
880e1ea03a3Smacallan	if (op != PictOpOver) {
881e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
882e1ea03a3Smacallan		op = PictOpOver;
883e1ea03a3Smacallan	}
884e1ea03a3Smacallan
885e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
886e1ea03a3Smacallan
887e1ea03a3Smacallan	fPtr->uw = width;
888e1ea03a3Smacallan	fPtr->uh = height;
889e1ea03a3Smacallan	fPtr->us = texPitch;
890e1ea03a3Smacallan	fPtr->alpha_texture = texPtr;
89126dcc2a3Smacallan	MAKE_ROOM(6);
89226dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
89326dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
894e1ea03a3Smacallan	if (texType == PICT_a8b8g8r8) {
895e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
896e1ea03a3Smacallan				    DE_MODE_TYPE_ABGR | DE_MODE_PIXDEPTH_32);
897e1ea03a3Smacallan	} else {
898e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
899e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
900e1ea03a3Smacallan	}
901e1ea03a3Smacallan	fPtr->format = texType;
902e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
903e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
904e1ea03a3Smacallan	    DE_ALPHA_ADD |
905e1ea03a3Smacallan	    (DE_ALPHA_OP_ONE/*SRC_ALPHA*/ << DE_ALPHA_OP_SRC_SHIFT) |
906e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
907e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
908e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
909e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
910e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
911e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
91226dcc2a3Smacallan	SYNC;
913e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
914e1ea03a3Smacallan	return TRUE;
915e1ea03a3Smacallan}
916e1ea03a3Smacallan
917e1ea03a3Smacallanvoid
918e1ea03a3SmacallanCrimeSubsequentCPUToScreenTexture (
919e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
920e1ea03a3Smacallan    int		dstx,
921e1ea03a3Smacallan    int		dsty,
922e1ea03a3Smacallan    int		srcx,
923e1ea03a3Smacallan    int		srcy,
924e1ea03a3Smacallan    int		width,
925e1ea03a3Smacallan    int		height
926e1ea03a3Smacallan)
927e1ea03a3Smacallan{
928e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
929e1ea03a3Smacallan	unsigned char *aptr, *lptr;
930e1ea03a3Smacallan	uint32_t *dptr, *sptr, aval, pixel;
931e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
932e1ea03a3Smacallan	int bufnum = 0;
933e1ea03a3Smacallan
934e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
935e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
936e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d\n", __func__,
937e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height);
938e1ea03a3Smacallan#endif
939e1ea03a3Smacallan	if ((width == 1) || (fPtr->format != PICT_a8r8g8b8)) {
940e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d %d %d\n", __func__,
941e1ea03a3Smacallan		    srcx, srcy, dstx, dsty, width, height, fPtr->uw, fPtr->us);
942e1ea03a3Smacallan		return;
943e1ea03a3Smacallan	}
944e1ea03a3Smacallan
945e1ea03a3Smacallan	aptr = fPtr->alpha_texture + (srcx << 2);
946e1ea03a3Smacallan	lptr = aptr + (fPtr->us * srcy);
947e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
948e1ea03a3Smacallan		rep = 128 / fPtr->uw;
949e1ea03a3Smacallan		period = rep * fPtr->uw;
950e1ea03a3Smacallan	}
951e1ea03a3Smacallan
952e1ea03a3Smacallan	if (fPtr->format == PICT_a8b8g8r8) {
953e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
954e1ea03a3Smacallan		xf86Msg(X_ERROR, "ABGR\n");
955e1ea03a3Smacallan#endif
956e1ea03a3Smacallan		for (i = 0; i < height; i++) {
957e1ea03a3Smacallan			dptr = (uint32_t *)fPtr->buffers[bufnum];
958e1ea03a3Smacallan			memcpy(dptr, aptr, fPtr->us);
95926dcc2a3Smacallan			MAKE_ROOM(3);
960e1ea03a3Smacallan			WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
961e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
962e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
963e1ea03a3Smacallan				((dstx + width - 1) << 16) | (dsty + i));
964e1ea03a3Smacallan			bufnum++;
965e1ea03a3Smacallan			if (bufnum == 8) bufnum = 0;
966e1ea03a3Smacallan			aptr += fPtr->us;
967e1ea03a3Smacallan		}
968e1ea03a3Smacallan	} else {
969e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
970e1ea03a3Smacallan		xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)aptr, fPtr->uw);
971e1ea03a3Smacallan#endif
972e1ea03a3Smacallan		lcnt = fPtr->uh - srcy;
973e1ea03a3Smacallan		for (i = 0; i < height; i++) {
974e1ea03a3Smacallan			dptr = (uint32_t *)fPtr->buffers[bufnum];
975e1ea03a3Smacallan			for (k = 0; k < rep; k++) {
976e1ea03a3Smacallan				sptr = (uint32_t *)aptr;
977e1ea03a3Smacallan				for (j = 0; j < fPtr->uw; j++) {
978e1ea03a3Smacallan					pixel = *sptr;
979e1ea03a3Smacallan					*dptr = (pixel << 8) | (pixel >> 24);
980e1ea03a3Smacallan					dptr++;
981e1ea03a3Smacallan					sptr++;
982e1ea03a3Smacallan				}
983e1ea03a3Smacallan			}
984e1ea03a3Smacallan			xoff = 0;
98526dcc2a3Smacallan			MAKE_ROOM(1);
986e1ea03a3Smacallan			WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
987e1ea03a3Smacallan			while (xoff < width) {
988e1ea03a3Smacallan				xa = dstx + xoff;
989e1ea03a3Smacallan				xe = dstx + min(xoff + period, width) - 1;
99026dcc2a3Smacallan				MAKE_ROOM(2);
991e1ea03a3Smacallan				WRITE4(CRIME_DE_X_VERTEX_0,
992e1ea03a3Smacallan				    xa << 16 | (dsty + i));
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				aptr = lptr;
1002e1ea03a3Smacallan				lcnt = fPtr->uh;
1003e1ea03a3Smacallan			} else
1004e1ea03a3Smacallan				aptr += fPtr->us;
1005e1ea03a3Smacallan		}
1006e1ea03a3Smacallan	}
1007e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1008e1ea03a3Smacallan}
1009e1ea03a3Smacallan
1010e1ea03a3Smacallanstatic Bool
1011e1ea03a3SmacallanCrimeSetupForCPUToScreenTextureMask(
1012e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
1013e1ea03a3Smacallan   int		op,
1014e1ea03a3Smacallan   int		texType,
1015e1ea03a3Smacallan   CARD8	*srcPtr,
1016e1ea03a3Smacallan   int		srcPitch,
1017e1ea03a3Smacallan   CARD8	*mskPtr,
1018e1ea03a3Smacallan   int		mskPitch,
1019e1ea03a3Smacallan   int		width,
1020e1ea03a3Smacallan   int		height,
1021e1ea03a3Smacallan   int		flags
1022e1ea03a3Smacallan)
1023e1ea03a3Smacallan{
1024e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1025e1ea03a3Smacallan
1026e1ea03a3Smacallan	if (op != PictOpOver) {
1027e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
1028e1ea03a3Smacallan		op = PictOpOver;
1029e1ea03a3Smacallan	}
1030e1ea03a3Smacallan
1031e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1032e1ea03a3Smacallan
1033e1ea03a3Smacallan	fPtr->uw = width;
1034e1ea03a3Smacallan	fPtr->uh = height;
1035e1ea03a3Smacallan	fPtr->us = srcPitch >> 2;
1036e1ea03a3Smacallan	if (PICT_FORMAT_BPP(texType) == 32) {
1037e1ea03a3Smacallan		fPtr->um = mskPitch >> 2;
1038e1ea03a3Smacallan	} else
1039e1ea03a3Smacallan		fPtr->um = mskPitch;
1040e1ea03a3Smacallan	fPtr->msk = (uint8_t *)mskPtr;
1041e1ea03a3Smacallan	fPtr->src = (uint8_t *)srcPtr;
1042e1ea03a3Smacallan	fPtr->texture_depth = PICT_FORMAT_BPP(texType);
1043e1ea03a3Smacallan
104426dcc2a3Smacallan	MAKE_ROOM(6);
1045e1ea03a3Smacallan	/* always expect ARGB for now */
1046e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
1047e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
104826dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
104926dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1050e1ea03a3Smacallan	fPtr->format = texType;
1051e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
1052e1ea03a3Smacallan	    DE_ALPHA_ADD |
1053e1ea03a3Smacallan	    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
1054e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
1055e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
1056e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1057e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
1058e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
1059e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
1060e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
106126dcc2a3Smacallan	SYNC;
1062e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1063e1ea03a3Smacallan	return TRUE;
1064e1ea03a3Smacallan}
1065e1ea03a3Smacallan
1066e1ea03a3Smacallanvoid
1067e1ea03a3SmacallanCrimeSubsequentCPUToScreenTextureMask32(
1068e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
1069e1ea03a3Smacallan    int		dstx,
1070e1ea03a3Smacallan    int		dsty,
1071e1ea03a3Smacallan    int		srcx,
1072e1ea03a3Smacallan    int		srcy,
1073e1ea03a3Smacallan    int		maskx,
1074e1ea03a3Smacallan    int		masky,
1075e1ea03a3Smacallan    int		width,
1076e1ea03a3Smacallan    int		height
1077e1ea03a3Smacallan)
1078e1ea03a3Smacallan{
1079e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1080e1ea03a3Smacallan	uint32_t *lsptr, *lmptr, *asptr, *amptr;
1081e1ea03a3Smacallan	uint32_t *dptr, *sptr, *mptr, aval, pixel, mask;
1082e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
1083e1ea03a3Smacallan	int bufnum = 0;
1084e1ea03a3Smacallan	int sr, sg, sb, sa, mr, mg, mb, ma, rr, gg, bb, aa;
1085e1ea03a3Smacallan
1086e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1087e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
1088e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d; %d %d %d\n", __func__,
1089e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height, maskx, masky, fPtr->um);
1090e1ea03a3Smacallan#endif
1091e1ea03a3Smacallan	sptr = fPtr->src + (srcx << 2);
1092e1ea03a3Smacallan	mptr = fPtr->msk + (srcx << 2);
1093e1ea03a3Smacallan	lsptr = sptr + (fPtr->us * srcy);
1094e1ea03a3Smacallan	lmptr = mptr + (fPtr->um * srcy);
1095e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
1096e1ea03a3Smacallan		rep = 128 / fPtr->uw;
1097e1ea03a3Smacallan		period = rep * fPtr->uw;
1098e1ea03a3Smacallan	}
1099e1ea03a3Smacallan
1100e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
1101e1ea03a3Smacallan	xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)aptr, fPtr->uw);
1102e1ea03a3Smacallan#endif
1103e1ea03a3Smacallan	lcnt = fPtr->uh - srcy;
1104e1ea03a3Smacallan	for (i = 0; i < height; i++) {
1105e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
1106e1ea03a3Smacallan		for (k = 0; k < rep; k++) {
1107e1ea03a3Smacallan			asptr = lsptr;
1108e1ea03a3Smacallan			amptr = lmptr;
1109e1ea03a3Smacallan			for (j = 0; j < fPtr->uw; j++) {
1110e1ea03a3Smacallan				pixel = *asptr;
1111e1ea03a3Smacallan				mask = *amptr;
1112e1ea03a3Smacallan				if (mask == 0xffffffff) {
1113e1ea03a3Smacallan					*dptr = (pixel >> 24) | (pixel << 8);
1114e1ea03a3Smacallan				} else if (mask == 0x00000000) {
1115e1ea03a3Smacallan					*dptr = 0;
1116e1ea03a3Smacallan				} else {
1117e1ea03a3Smacallan					/* input is ARGB */
1118e1ea03a3Smacallan					sb = pixel & 0xff;
1119e1ea03a3Smacallan					sg = (pixel >> 8) & 0xff;
1120e1ea03a3Smacallan					sr = (pixel >> 16) & 0xff;
1121e1ea03a3Smacallan					sa = (pixel >> 24) & 0xff;
1122e1ea03a3Smacallan					mb = mask & 0xff;
1123e1ea03a3Smacallan					mg = (mask >> 8) & 0xff;
1124e1ea03a3Smacallan					mr = (mask >> 16) & 0xff;
1125e1ea03a3Smacallan					ma = (mask >> 24) & 0xff;
1126e1ea03a3Smacallan
1127e1ea03a3Smacallan					/* and here we need an RGBA pixel */
1128e1ea03a3Smacallan					bb = (((sb * mb) + 0x80) & 0xff00);
1129e1ea03a3Smacallan					gg = (((sg * mg) + 0x80) & 0xff00) << 8;
1130e1ea03a3Smacallan					rr = (((sr * mr) + 0x80) & 0xff00) << 16;
1131e1ea03a3Smacallan					aa = (((sa * ma) + 0x80) & 0xff00) >> 8;
1132e1ea03a3Smacallan					/*
1133e1ea03a3Smacallan					 * actually we could let the HW do this stuff
1134e1ea03a3Smacallan					 */
1135e1ea03a3Smacallan					*dptr = aa | rr | gg | bb;
1136e1ea03a3Smacallan				}
1137e1ea03a3Smacallan				dptr++;
1138e1ea03a3Smacallan				asptr++;
1139e1ea03a3Smacallan				amptr++;
1140e1ea03a3Smacallan			}
1141e1ea03a3Smacallan		}
1142e1ea03a3Smacallan		xoff = 0;
114326dcc2a3Smacallan		MAKE_ROOM(1);
1144e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
1145e1ea03a3Smacallan		while (xoff < width) {
1146e1ea03a3Smacallan			xa = dstx + xoff;
1147e1ea03a3Smacallan			xe = dstx + min(xoff + period, width) - 1;
114826dcc2a3Smacallan			MAKE_ROOM(2);
1149e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0,
1150e1ea03a3Smacallan			    xa << 16 | (dsty + i));
1151e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
1152e1ea03a3Smacallan				(xe << 16) | (dsty + i));
1153e1ea03a3Smacallan			xoff += period;
1154e1ea03a3Smacallan		}
1155e1ea03a3Smacallan		bufnum++;
1156e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
1157e1ea03a3Smacallan		lcnt--;
1158e1ea03a3Smacallan		if (lcnt == 0) {
1159e1ea03a3Smacallan			/* back to the beginning */
1160e1ea03a3Smacallan			lsptr = sptr;
1161e1ea03a3Smacallan			lmptr = mptr;
1162e1ea03a3Smacallan			lcnt = fPtr->uh;
1163e1ea03a3Smacallan		} else
1164e1ea03a3Smacallan			/* next line */
1165e1ea03a3Smacallan			lsptr += fPtr->us;
1166e1ea03a3Smacallan			lmptr += fPtr->um;
1167e1ea03a3Smacallan	}
1168e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1169e1ea03a3Smacallan}
1170e1ea03a3Smacallan
1171e1ea03a3Smacallanvoid
1172e1ea03a3SmacallanCrimeSubsequentCPUToScreenTextureMask8(
1173e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
1174e1ea03a3Smacallan    int		dstx,
1175e1ea03a3Smacallan    int		dsty,
1176e1ea03a3Smacallan    int		srcx,
1177e1ea03a3Smacallan    int		srcy,
1178e1ea03a3Smacallan    int		maskx,
1179e1ea03a3Smacallan    int		masky,
1180e1ea03a3Smacallan    int		width,
1181e1ea03a3Smacallan    int		height
1182e1ea03a3Smacallan)
1183e1ea03a3Smacallan{
1184e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1185e1ea03a3Smacallan	uint32_t *lsptr, *asptr;
1186e1ea03a3Smacallan	uint32_t *dptr, *sptr, aval, pixel, mask;
1187e1ea03a3Smacallan	uint8_t  *lmptr, *amptr, *mptr;
1188e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
1189e1ea03a3Smacallan	int bufnum = 0;
1190e1ea03a3Smacallan	int sr, sg, sb, sa, rr, gg, bb, aa;
1191e1ea03a3Smacallan
1192e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
11935b2650b9Smacallan#ifdef CRIME_DEBUG_LOUD
1194e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d\n", __func__,
1195e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height);
1196e1ea03a3Smacallan#endif
1197e1ea03a3Smacallan	sptr = (uint32_t *)fPtr->src + (fPtr->us * srcy) + (srcx << 2);
1198e1ea03a3Smacallan	mptr = (uint8_t *)fPtr->msk + (fPtr->um * srcy) + srcx;
1199e1ea03a3Smacallan	lsptr = sptr;
1200e1ea03a3Smacallan	lmptr = mptr;
1201e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
1202e1ea03a3Smacallan		rep = 128 / fPtr->uw;
1203e1ea03a3Smacallan		period = rep * fPtr->uw;
1204e1ea03a3Smacallan	}
1205e1ea03a3Smacallan
1206e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
1207e1ea03a3Smacallan	xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)aptr, fPtr->uw);
1208e1ea03a3Smacallan#endif
1209e1ea03a3Smacallan	lcnt = fPtr->uh;
1210e1ea03a3Smacallan	for (i = 0; i < height; i++) {
1211e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
1212e1ea03a3Smacallan		for (k = 0; k < rep; k++) {
1213e1ea03a3Smacallan			asptr = lsptr;
1214e1ea03a3Smacallan			amptr = lmptr;
1215e1ea03a3Smacallan			for (j = 0; j < fPtr->uw; j++) {
1216e1ea03a3Smacallan				pixel = *asptr;
1217e1ea03a3Smacallan				mask = *amptr;
1218e1ea03a3Smacallan				if (mask == 0xff) {
1219e1ea03a3Smacallan					*dptr = (pixel >> 24) | (pixel << 8);
1220e1ea03a3Smacallan				} else if (mask == 0x00) {
1221e1ea03a3Smacallan					*dptr = 0;
1222e1ea03a3Smacallan				} else {
1223e1ea03a3Smacallan					/* input is ARGB */
1224e1ea03a3Smacallan					sb = pixel & 0xff;
1225e1ea03a3Smacallan					sg = (pixel >> 8) & 0xff;
1226e1ea03a3Smacallan					sr = (pixel >> 16) & 0xff;
1227e1ea03a3Smacallan					sa = (pixel >> 24) & 0xff;
1228e1ea03a3Smacallan
1229e1ea03a3Smacallan					/* and here we need an RGBA pixel */
1230e1ea03a3Smacallan					bb = (((sb * mask) + 0x80) & 0xff00);
1231e1ea03a3Smacallan					gg = (((sg * mask) + 0x80) & 0xff00)
1232e1ea03a3Smacallan					     << 8;
1233e1ea03a3Smacallan					rr = (((sr * mask) + 0x80) & 0xff00)
1234e1ea03a3Smacallan					     << 16;
1235e1ea03a3Smacallan					aa = (((sa * mask) + 0x80) & 0xff00)
1236e1ea03a3Smacallan					     >> 8;
1237e1ea03a3Smacallan					/*
1238e1ea03a3Smacallan					 * actually we could let the HW do this
1239e1ea03a3Smacallan					 * stuff
1240e1ea03a3Smacallan					 */
1241e1ea03a3Smacallan					*dptr = aa | rr | gg | bb;
1242e1ea03a3Smacallan				}
1243e1ea03a3Smacallan				dptr++;
1244e1ea03a3Smacallan				asptr++;
1245e1ea03a3Smacallan				amptr++;
1246e1ea03a3Smacallan			}
1247e1ea03a3Smacallan		}
1248e1ea03a3Smacallan		xoff = 0;
124926dcc2a3Smacallan		MAKE_ROOM(1);
1250e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
1251e1ea03a3Smacallan		while (xoff < width) {
1252e1ea03a3Smacallan			xa = dstx + xoff;
1253e1ea03a3Smacallan			xe = dstx + min(xoff + period, width) - 1;
125426dcc2a3Smacallan			MAKE_ROOM(2);
1255e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0,
1256e1ea03a3Smacallan			    xa << 16 | (dsty + i));
1257e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
1258e1ea03a3Smacallan				(xe << 16) | (dsty + i));
1259e1ea03a3Smacallan			xoff += period;
1260e1ea03a3Smacallan		}
1261e1ea03a3Smacallan		bufnum++;
1262e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
1263e1ea03a3Smacallan		lcnt--;
1264e1ea03a3Smacallan		if (lcnt == 0) {
1265e1ea03a3Smacallan			/* back to the beginning */
1266e1ea03a3Smacallan			lsptr = sptr;
1267e1ea03a3Smacallan			lmptr = mptr;
1268e1ea03a3Smacallan			lcnt = fPtr->uh;
1269e1ea03a3Smacallan		} else
1270e1ea03a3Smacallan			/* next line */
1271e1ea03a3Smacallan			lsptr += fPtr->us;
1272e1ea03a3Smacallan			lmptr += fPtr->um;
1273e1ea03a3Smacallan	}
1274e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1275e1ea03a3Smacallan}
1276e1ea03a3Smacallan
1277e1ea03a3Smacallanstatic void
1278e1ea03a3SmacallanCrimeDoCPUToScreenComposite(
1279e1ea03a3Smacallan   	CARD8      op,
1280e1ea03a3Smacallan        PicturePtr pSrc,
1281e1ea03a3Smacallan        PicturePtr pMask,
1282e1ea03a3Smacallan        PicturePtr pDst,
1283e1ea03a3Smacallan        INT16      xSrc,
1284e1ea03a3Smacallan        INT16      ySrc,
1285e1ea03a3Smacallan        INT16      xMask,
1286e1ea03a3Smacallan        INT16      yMask,
1287e1ea03a3Smacallan        INT16      xDst,
1288e1ea03a3Smacallan        INT16      yDst,
1289e1ea03a3Smacallan        CARD16     width,
1290e1ea03a3Smacallan        CARD16     height
1291e1ea03a3Smacallan)
1292e1ea03a3Smacallan{
1293e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1294e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1295e1ea03a3Smacallan	RegionRec region;
1296e1ea03a3Smacallan	CARD32 *formats;
1297e1ea03a3Smacallan	int flags = 0;
1298e1ea03a3Smacallan	BoxPtr pbox;
1299e1ea03a3Smacallan	int nbox, w, h;
1300e1ea03a3Smacallan
1301e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1302e1ea03a3Smacallan	if (pSrc->transform || (pMask && pMask->transform)) {
1303e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: transform?!\n", __func__);
1304e1ea03a3Smacallan		return;
1305e1ea03a3Smacallan	}
1306e1ea03a3Smacallan
1307e1ea03a3Smacallan	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) {
1308e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: alpha-map?!\n", __func__);
1309e1ea03a3Smacallan		return;
1310e1ea03a3Smacallan	}
1311e1ea03a3Smacallan
1312e1ea03a3Smacallan	xDst += pDst->pDrawable->x;
1313e1ea03a3Smacallan	yDst += pDst->pDrawable->y;
1314e1ea03a3Smacallan	xSrc += pSrc->pDrawable->x;
1315e1ea03a3Smacallan	ySrc += pSrc->pDrawable->y;
1316e1ea03a3Smacallan
1317e1ea03a3Smacallan	if(pMask) {
1318e1ea03a3Smacallan		CARD16 red, green, blue, alpha;
1319e1ea03a3Smacallan		CARD32 pixel =
1320e1ea03a3Smacallan		    *((CARD32*)(((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr));
132109f0d67cSmacallan#ifdef CRIME_DEBUG_LOUD
1322e1ea03a3Smacallan		if(pMask->componentAlpha) {
1323e1ea03a3Smacallan			xf86Msg(X_ERROR, "%s: alpha component mask\n",
1324e1ea03a3Smacallan			    __func__);
132509f0d67cSmacallan			xf86Msg(X_ERROR, "src: %d x %d\n", pSrc->pDrawable->width,
132609f0d67cSmacallan			    pSrc->pDrawable->height);
1327e1ea03a3Smacallan		}
132809f0d67cSmacallan#endif
1329e1ea03a3Smacallan		if ((pSrc->pDrawable->width == 1) &&
1330e1ea03a3Smacallan		    (pSrc->pDrawable->height == 1)) {
1331e1ea03a3Smacallan
1332e1ea03a3Smacallan			if(!XAAGetRGBAFromPixel(pixel, &red, &green, &blue,
1333e1ea03a3Smacallan			    &alpha, pSrc->format)) {
1334e1ea03a3Smacallan				xf86Msg(X_ERROR, "%s: can't read pixel\n", __func__);
1335e1ea03a3Smacallan				return;
1336e1ea03a3Smacallan			}
1337e1ea03a3Smacallan			xMask += pMask->pDrawable->x;
1338e1ea03a3Smacallan			yMask += pMask->pDrawable->y;
1339e1ea03a3Smacallan
1340e1ea03a3Smacallan			/* pull out color expandable operations here */
1341e1ea03a3Smacallan			if(pMask->format == PICT_a1) {
1342e1ea03a3Smacallan				PixmapPtr pPix = (PixmapPtr)(pMask->pDrawable);
1343e1ea03a3Smacallan				int skipleft;
1344e1ea03a3Smacallan
1345e1ea03a3Smacallan				if (op != PictOpOver) {
1346e1ea03a3Smacallan					xf86Msg(X_ERROR, "!over\n");
1347e1ea03a3Smacallan					return;
1348e1ea03a3Smacallan				}
1349e1ea03a3Smacallan				if (pMask->repeat) {
1350e1ea03a3Smacallan					xf86Msg(X_ERROR, "mono repeat\n");
1351e1ea03a3Smacallan					return;
1352e1ea03a3Smacallan				}
1353e1ea03a3Smacallan				if (!miComputeCompositeRegion (&region, pSrc,
1354e1ea03a3Smacallan				    pMask, pDst, xSrc, ySrc, xMask, yMask, xDst,
1355e1ea03a3Smacallan				    yDst, width, height)) {
1356e1ea03a3Smacallan					return;
1357e1ea03a3Smacallan				}
1358e1ea03a3Smacallan
1359e1ea03a3Smacallan				nbox = REGION_NUM_RECTS(&region);
1360e1ea03a3Smacallan				pbox = REGION_RECTS(&region);
1361e1ea03a3Smacallan
1362e1ea03a3Smacallan				if(!nbox) {
1363e1ea03a3Smacallan					return;
1364e1ea03a3Smacallan				}
1365e1ea03a3Smacallan
1366e1ea03a3Smacallan				XAAGetPixelFromRGBA(&pixel, red, green, blue, 0,
1367e1ea03a3Smacallan				    pDst->format);
1368e1ea03a3Smacallan
1369e1ea03a3Smacallan				xMask -= xDst;
1370e1ea03a3Smacallan				yMask -= yDst;
1371e1ea03a3Smacallan
1372e1ea03a3Smacallan				while(nbox--) {
1373e1ea03a3Smacallan					skipleft = pbox->x1 + xMask;
1374e1ea03a3Smacallan
1375e1ea03a3Smacallan					(*infoRec->WriteBitmap)(infoRec->pScrn, 					    pbox->x1, pbox->y1,
1376e1ea03a3Smacallan					    pbox->x2 - pbox->x1,
1377e1ea03a3Smacallan					    pbox->y2 - pbox->y1,
1378e1ea03a3Smacallan					    (unsigned char*)(pPix->devPrivate.ptr) + 					    (pPix->devKind *
1379e1ea03a3Smacallan					    (pbox->y1 + yMask)) + ((skipleft >> 3) & ~3),
1380e1ea03a3Smacallan					    pPix->devKind, skipleft & 31, pixel, -1,
1381e1ea03a3Smacallan					    GXcopy, ~0);
1382e1ea03a3Smacallan					pbox++;
1383e1ea03a3Smacallan				}
1384e1ea03a3Smacallan
1385e1ea03a3Smacallan				/* WriteBitmap sets the Sync flag */
1386e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1387e1ea03a3Smacallan				DONE(CRIME_DEBUG_XRENDER);
1388e1ea03a3Smacallan				return;
1389e1ea03a3Smacallan			}
139009f0d67cSmacallan			if((pMask->format == PICT_a8) ||
139109f0d67cSmacallan			   (pMask->format == PICT_a8r8g8b8)) {
1392e1ea03a3Smacallan
1393e1ea03a3Smacallan				w = pMask->pDrawable->width;
1394e1ea03a3Smacallan				h = pMask->pDrawable->height;
1395e1ea03a3Smacallan
1396e1ea03a3Smacallan				if(pMask->repeat) {
1397e1ea03a3Smacallan					flags |= XAA_RENDER_REPEAT;
1398e1ea03a3Smacallan				}
1399e1ea03a3Smacallan
1400e1ea03a3Smacallan				if (!miComputeCompositeRegion (&region, pSrc, pMask,
1401e1ea03a3Smacallan				    pDst, xSrc, ySrc, xMask, yMask, xDst, yDst,
1402e1ea03a3Smacallan				    width, height)) {
1403e1ea03a3Smacallan					return;
1404e1ea03a3Smacallan				}
1405e1ea03a3Smacallan
1406e1ea03a3Smacallan				nbox = REGION_NUM_RECTS(&region);
1407e1ea03a3Smacallan				pbox = REGION_RECTS(&region);
1408e1ea03a3Smacallan
1409e1ea03a3Smacallan				if(!nbox) {
1410e1ea03a3Smacallan					REGION_UNINIT(pScreen, &region);
1411e1ea03a3Smacallan					return;
1412e1ea03a3Smacallan				}
1413e1ea03a3Smacallan
1414e1ea03a3Smacallan				CrimeSetupForCPUToScreenAlphaTexture(infoRec->pScrn,
1415e1ea03a3Smacallan				    op, red, green, blue, alpha, pMask->format,
1416e1ea03a3Smacallan				    ((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr,
1417e1ea03a3Smacallan				    ((PixmapPtr)(pMask->pDrawable))->devKind,
1418e1ea03a3Smacallan				    w, h, flags);
1419e1ea03a3Smacallan
1420e1ea03a3Smacallan				xMask -= xDst;
1421e1ea03a3Smacallan				yMask -= yDst;
1422e1ea03a3Smacallan
142309f0d67cSmacallan				if (pMask->format != PICT_a8) {
142409f0d67cSmacallan					while(nbox--) {
142509f0d67cSmacallan						CrimeSubsequentCPUToScreenAlphaTexture32(
142609f0d67cSmacallan						    infoRec->pScrn,
142709f0d67cSmacallan						    pbox->x1, pbox->y1, pbox->x1 + xMask,
142809f0d67cSmacallan						    pbox->y1 + yMask, pbox->x2 - pbox->x1,
142909f0d67cSmacallan						    pbox->y2 - pbox->y1);
143009f0d67cSmacallan						pbox++;
143109f0d67cSmacallan					}
143209f0d67cSmacallan				} else {
143309f0d67cSmacallan					while(nbox--) {
143409f0d67cSmacallan						CrimeSubsequentCPUToScreenAlphaTexture(
143509f0d67cSmacallan						    infoRec->pScrn,
143609f0d67cSmacallan						    pbox->x1, pbox->y1, pbox->x1 + xMask,
143709f0d67cSmacallan						    pbox->y1 + yMask, pbox->x2 - pbox->x1,
143809f0d67cSmacallan						    pbox->y2 - pbox->y1);
143909f0d67cSmacallan						pbox++;
144009f0d67cSmacallan					}
1441e1ea03a3Smacallan				}
1442e1ea03a3Smacallan				SET_SYNC_FLAG(infoRec);
1443e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1444e1ea03a3Smacallan				DONE(CRIME_DEBUG_XRENDER);
1445e1ea03a3Smacallan				return;
1446e1ea03a3Smacallan			} else {
1447e1ea03a3Smacallan				xf86Msg(X_ERROR, "unknown mask %x\n", pMask->format);
1448e1ea03a3Smacallan			}
1449e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1450e1ea03a3Smacallan			DONE(CRIME_DEBUG_XRENDER);
1451e1ea03a3Smacallan			return;
1452e1ea03a3Smacallan		} else {
1453e1ea03a3Smacallan			/* source isn't solid */
1454e1ea03a3Smacallan
1455e1ea03a3Smacallan			w = pSrc->pDrawable->width;
1456e1ea03a3Smacallan			h = pSrc->pDrawable->height;
1457e1ea03a3Smacallan
1458e1ea03a3Smacallan			if(pSrc->repeat)
1459e1ea03a3Smacallan				flags |= XAA_RENDER_REPEAT;
1460e1ea03a3Smacallan
1461e1ea03a3Smacallan			if (!miComputeCompositeRegion (&region, pSrc, pMask,
1462e1ea03a3Smacallan			    pDst, xSrc, ySrc, xMask, yMask, xDst, yDst,
1463e1ea03a3Smacallan			    width, height)) {
1464e1ea03a3Smacallan				return;
1465e1ea03a3Smacallan			}
1466e1ea03a3Smacallan
1467e1ea03a3Smacallan			nbox = REGION_NUM_RECTS(&region);
1468e1ea03a3Smacallan			pbox = REGION_RECTS(&region);
1469e1ea03a3Smacallan
1470e1ea03a3Smacallan			if(!nbox) {
1471e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1472e1ea03a3Smacallan				return;
1473e1ea03a3Smacallan			}
1474e1ea03a3Smacallan			CrimeSetupForCPUToScreenTextureMask(
1475e1ea03a3Smacallan			    infoRec->pScrn, op, pMask->format,
1476e1ea03a3Smacallan			    ((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr,
1477e1ea03a3Smacallan			    ((PixmapPtr)(pSrc->pDrawable))->devKind,
1478e1ea03a3Smacallan			    ((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr,
1479e1ea03a3Smacallan			    ((PixmapPtr)(pMask->pDrawable))->devKind,
1480e1ea03a3Smacallan			    w, h, flags);
1481e1ea03a3Smacallan
1482e1ea03a3Smacallan			xSrc -= xDst;
1483e1ea03a3Smacallan			ySrc -= yDst;
1484e1ea03a3Smacallan
1485e1ea03a3Smacallan			if (PICT_FORMAT_BPP(pMask->format) == 32) {
1486e1ea03a3Smacallan				while(nbox--) {
1487e1ea03a3Smacallan					CrimeSubsequentCPUToScreenTextureMask32(
1488e1ea03a3Smacallan					    infoRec->pScrn,
1489e1ea03a3Smacallan					    pbox->x1, pbox->y1,
1490e1ea03a3Smacallan					    pbox->x1 + xSrc, pbox->y1 + ySrc,
1491e1ea03a3Smacallan					    xMask, yMask,
1492e1ea03a3Smacallan					    pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
1493e1ea03a3Smacallan					pbox++;
1494e1ea03a3Smacallan				}
1495e1ea03a3Smacallan			} else {
1496e1ea03a3Smacallan				while(nbox--) {
1497e1ea03a3Smacallan					CrimeSubsequentCPUToScreenTextureMask8(
1498e1ea03a3Smacallan					    infoRec->pScrn,
1499e1ea03a3Smacallan					    pbox->x1, pbox->y1, pbox->x1 + xSrc,
1500e1ea03a3Smacallan					    pbox->y1 + ySrc,
1501e1ea03a3Smacallan					    xMask, yMask,
1502e1ea03a3Smacallan					    pbox->x2 - pbox->x1,
1503e1ea03a3Smacallan					    pbox->y2 - pbox->y1);
1504e1ea03a3Smacallan					pbox++;
1505e1ea03a3Smacallan				}
1506e1ea03a3Smacallan			}
1507e1ea03a3Smacallan
1508e1ea03a3Smacallan			SET_SYNC_FLAG(infoRec);
1509e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1510e1ea03a3Smacallan			DONE(CRIME_DEBUG_XRENDER);
1511e1ea03a3Smacallan			return;
1512e1ea03a3Smacallan		}
1513e1ea03a3Smacallan	} else {	/* no mask */
1514e1ea03a3Smacallan		formats = infoRec->CPUToScreenTextureFormats;
1515e1ea03a3Smacallan
1516e1ea03a3Smacallan		w = pSrc->pDrawable->width;
1517e1ea03a3Smacallan		h = pSrc->pDrawable->height;
1518e1ea03a3Smacallan
1519e1ea03a3Smacallan		if(pSrc->repeat)
1520e1ea03a3Smacallan			flags |= XAA_RENDER_REPEAT;
1521e1ea03a3Smacallan
1522e1ea03a3Smacallan		while(*formats != pSrc->format) {
1523e1ea03a3Smacallan			if(!(*formats)) {
1524e1ea03a3Smacallan				xf86Msg(X_ERROR,
1525e1ea03a3Smacallan				    "%s: format %x not found\n",
1526e1ea03a3Smacallan				    __func__, pSrc->format);
1527e1ea03a3Smacallan				return;
1528e1ea03a3Smacallan			}
1529e1ea03a3Smacallan			formats++;
1530e1ea03a3Smacallan		}
1531e1ea03a3Smacallan
1532e1ea03a3Smacallan		if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
1533e1ea03a3Smacallan                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
1534e1ea03a3Smacallan                                   width, height)) {
1535e1ea03a3Smacallan			return;
1536e1ea03a3Smacallan		}
1537e1ea03a3Smacallan
1538e1ea03a3Smacallan		nbox = REGION_NUM_RECTS(&region);
1539e1ea03a3Smacallan		pbox = REGION_RECTS(&region);
1540e1ea03a3Smacallan
1541e1ea03a3Smacallan		if(!nbox) {
1542e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1543e1ea03a3Smacallan			return;
1544e1ea03a3Smacallan		}
1545e1ea03a3Smacallan
1546e1ea03a3Smacallan		CrimeSetupForCPUToScreenTexture(infoRec->pScrn,
1547e1ea03a3Smacallan			op, pSrc->format,
1548e1ea03a3Smacallan			((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr,
1549e1ea03a3Smacallan			((PixmapPtr)(pSrc->pDrawable))->devKind,
1550e1ea03a3Smacallan			w, h, flags);
1551e1ea03a3Smacallan
1552e1ea03a3Smacallan		xSrc -= xDst;
1553e1ea03a3Smacallan		ySrc -= yDst;
1554e1ea03a3Smacallan
1555e1ea03a3Smacallan		while(nbox--) {
1556e1ea03a3Smacallan			CrimeSubsequentCPUToScreenTexture(infoRec->pScrn,
1557e1ea03a3Smacallan			    pbox->x1, pbox->y1, pbox->x1 + xSrc,
1558e1ea03a3Smacallan			    pbox->y1 + ySrc, pbox->x2 - pbox->x1,
1559e1ea03a3Smacallan			    pbox->y2 - pbox->y1);
1560e1ea03a3Smacallan			pbox++;
1561e1ea03a3Smacallan		}
1562e1ea03a3Smacallan
1563e1ea03a3Smacallan		SET_SYNC_FLAG(infoRec);
1564e1ea03a3Smacallan		REGION_UNINIT(pScreen, &region);
1565e1ea03a3Smacallan		DONE(CRIME_DEBUG_XRENDER);
1566e1ea03a3Smacallan		return;
1567e1ea03a3Smacallan	}
1568e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: shouldn't be here\n", __func__);
1569e1ea03a3Smacallan}
1570e1ea03a3Smacallan
1571e1ea03a3Smacallanstatic void
1572e1ea03a3SmacallanCrimeDoScreenToScreenComposite(
1573e1ea03a3Smacallan   	CARD8      op,
1574e1ea03a3Smacallan        PicturePtr pSrc,
1575e1ea03a3Smacallan        PicturePtr pMask,
1576e1ea03a3Smacallan        PicturePtr pDst,
1577e1ea03a3Smacallan        INT16      xSrc,
1578e1ea03a3Smacallan        INT16      ySrc,
1579e1ea03a3Smacallan        INT16      xMask,
1580e1ea03a3Smacallan        INT16      yMask,
1581e1ea03a3Smacallan        INT16      xDst,
1582e1ea03a3Smacallan        INT16      yDst,
1583e1ea03a3Smacallan        CARD16     width,
1584e1ea03a3Smacallan        CARD16     height
1585e1ea03a3Smacallan)
1586e1ea03a3Smacallan{
1587e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1588e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1589e1ea03a3Smacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1590e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1591e1ea03a3Smacallan	RegionRec region;
1592e1ea03a3Smacallan	CARD32 *formats;
1593e1ea03a3Smacallan	int flags = 0;
1594e1ea03a3Smacallan	BoxPtr pbox;
1595e1ea03a3Smacallan	int nbox;
1596e1ea03a3Smacallan	int xs, ys, xd, yd, w, h;
1597e1ea03a3Smacallan
1598e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1599e1ea03a3Smacallan	if (pSrc->transform || (pMask && pMask->transform)) {
1600e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: mask?!\n", __func__);
1601e1ea03a3Smacallan		return;
1602e1ea03a3Smacallan	}
1603e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d\n", __func__, op);
1604e1ea03a3Smacallan	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) {
1605e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: alpha-map\n", __func__);
1606e1ea03a3Smacallan		return;
1607e1ea03a3Smacallan	}
1608e1ea03a3Smacallan
1609e1ea03a3Smacallan	xDst += pDst->pDrawable->x;
1610e1ea03a3Smacallan	yDst += pDst->pDrawable->y;
1611e1ea03a3Smacallan	xSrc += pSrc->pDrawable->x;
1612e1ea03a3Smacallan	ySrc += pSrc->pDrawable->y;
1613e1ea03a3Smacallan
1614e1ea03a3Smacallan	formats = infoRec->CPUToScreenTextureFormats;
1615e1ea03a3Smacallan
1616e1ea03a3Smacallan	w = pSrc->pDrawable->width;
1617e1ea03a3Smacallan	h = pSrc->pDrawable->height;
1618e1ea03a3Smacallan
1619e1ea03a3Smacallan	if(pSrc->repeat)
1620e1ea03a3Smacallan		flags |= XAA_RENDER_REPEAT;
1621e1ea03a3Smacallan
1622e1ea03a3Smacallan	while(*formats != pSrc->format) {
1623e1ea03a3Smacallan		if(!(*formats)) return;
1624e1ea03a3Smacallan		formats++;
1625e1ea03a3Smacallan	}
1626e1ea03a3Smacallan
1627e1ea03a3Smacallan	if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
1628e1ea03a3Smacallan	    xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
1629e1ea03a3Smacallan		return;
1630e1ea03a3Smacallan
1631e1ea03a3Smacallan	nbox = REGION_NUM_RECTS(&region);
1632e1ea03a3Smacallan	pbox = REGION_RECTS(&region);
1633e1ea03a3Smacallan
1634e1ea03a3Smacallan	if(!nbox) {
1635e1ea03a3Smacallan		REGION_UNINIT(pScreen, &region);
1636e1ea03a3Smacallan		return;
1637e1ea03a3Smacallan	}
1638e1ea03a3Smacallan
163926dcc2a3Smacallan	MAKE_ROOM(6);
1640e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
1641e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
164226dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
164326dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1644e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 1);
1645e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
1646e1ea03a3Smacallan	    DE_ALPHA_ADD |
1647e1ea03a3Smacallan	    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
1648e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
1649e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1650e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
1651e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
1652e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
1653e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
165426dcc2a3Smacallan	SYNC;
1655e1ea03a3Smacallan	xSrc -= xDst;
1656e1ea03a3Smacallan	ySrc -= yDst;
1657e1ea03a3Smacallan
1658e1ea03a3Smacallan	/* assume no overlap - might bite us in the arse at some point */
1659e1ea03a3Smacallan	while(nbox--) {
1660e1ea03a3Smacallan		xs = pbox->x1 + xSrc;
1661e1ea03a3Smacallan		ys = pbox->y1 + ySrc;
1662e1ea03a3Smacallan		xd = pbox->x1;
1663e1ea03a3Smacallan		yd = pbox->y1;
1664e1ea03a3Smacallan		w = pbox->x2 - pbox->x1;
1665e1ea03a3Smacallan		h = pbox->y2 - pbox->y1;
166626dcc2a3Smacallan		MAKE_ROOM(3);
1667e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC,(xs << 16) | (ys & 0xffff));
1668e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (xd << 16) | (yd & 0xffff));
1669e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
1670e1ea03a3Smacallan		    ((xd + w - 1) << 16) | ((yd + h - 1) & 0xffff));
1671e1ea03a3Smacallan		pbox++;
1672e1ea03a3Smacallan	}
1673e1ea03a3Smacallan
1674e1ea03a3Smacallan	SET_SYNC_FLAG(infoRec);
1675e1ea03a3Smacallan	REGION_UNINIT(pScreen, &region);
1676e1ea03a3Smacallan	return;
1677e1ea03a3Smacallan}
1678e1ea03a3Smacallan
1679e1ea03a3Smacallanstatic Bool
1680e1ea03a3SmacallanCrimeComposite(
1681e1ea03a3Smacallan   	CARD8      op,
1682e1ea03a3Smacallan        PicturePtr pSrc,
1683e1ea03a3Smacallan        PicturePtr pMask,
1684e1ea03a3Smacallan        PicturePtr pDst,
1685e1ea03a3Smacallan        INT16      xSrc,
1686e1ea03a3Smacallan        INT16      ySrc,
1687e1ea03a3Smacallan        INT16      xMask,
1688e1ea03a3Smacallan        INT16      yMask,
1689e1ea03a3Smacallan        INT16      xDst,
1690e1ea03a3Smacallan        INT16      yDst,
1691e1ea03a3Smacallan        CARD16     width,
1692e1ea03a3Smacallan        CARD16     height
1693e1ea03a3Smacallan)
1694e1ea03a3Smacallan{
1695e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1696e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1697e1ea03a3Smacallan
1698e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1699e1ea03a3Smacallan
1700e1ea03a3Smacallan	if(!REGION_NUM_RECTS(pDst->pCompositeClip))
1701e1ea03a3Smacallan		return TRUE;
1702e1ea03a3Smacallan
1703e1ea03a3Smacallan	if(!infoRec->pScrn->vtSema)
1704e1ea03a3Smacallan		return FALSE;
1705e1ea03a3Smacallan
1706e1ea03a3Smacallan	if((pDst->pDrawable->type == DRAWABLE_WINDOW) ||
1707f282839bSmacallan	    IS_OFFSCREEN_PIXMAP(pDst->pDrawable) ||
1708f282839bSmacallan	    PIXMAP_IS_SCREEN(pDst->pDrawable)) {
1709e1ea03a3Smacallan		if ((pSrc->pDrawable->type == DRAWABLE_WINDOW) ||
1710f282839bSmacallan		    IS_OFFSCREEN_PIXMAP(pSrc->pDrawable) ||
1711f282839bSmacallan		    PIXMAP_IS_SCREEN(pSrc->pDrawable)) {
1712e1ea03a3Smacallan			/* screen-to-screen */
1713e1ea03a3Smacallan			CrimeDoScreenToScreenComposite(op, pSrc, pMask, pDst,
1714e1ea03a3Smacallan			    xSrc, ySrc, xMask, yMask,
1715e1ea03a3Smacallan			    xDst, yDst, width, height);
1716e1ea03a3Smacallan			return TRUE;
1717e1ea03a3Smacallan		} else {
1718e1ea03a3Smacallan			/* CPU-to-screen composite */
1719e1ea03a3Smacallan			if (op != PictOpOver)
1720e1ea03a3Smacallan				xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
1721e1ea03a3Smacallan			CrimeDoCPUToScreenComposite(op, pSrc, pMask, pDst,
1722e1ea03a3Smacallan			    xSrc, ySrc, xMask, yMask,
1723e1ea03a3Smacallan			    xDst, yDst, width, height);
1724e1ea03a3Smacallan			return TRUE;
1725e1ea03a3Smacallan		}
1726e1ea03a3Smacallan	} else {
1727e1ea03a3Smacallan		if ((pSrc->pDrawable->type == DRAWABLE_WINDOW) ||
1728e1ea03a3Smacallan		    IS_OFFSCREEN_PIXMAP(pSrc->pDrawable)) {
1729e1ea03a3Smacallan			/* screen-to-RAM */
1730e1ea03a3Smacallan			xf86Msg(X_ERROR, "%s: screen-to-RAM composite\n",
1731e1ea03a3Smacallan			   __func__);
1732e1ea03a3Smacallan			return TRUE;
1733e1ea03a3Smacallan		} else {
1734e1ea03a3Smacallan			/* RAM-to-RAM */
1735e1ea03a3Smacallan			return FALSE;
1736e1ea03a3Smacallan		}
1737e1ea03a3Smacallan	}
1738e1ea03a3Smacallan	xf86Msg(X_ERROR, "composite fucked\n");
1739e1ea03a3Smacallan}
1740e1ea03a3Smacallan
1741e1ea03a3Smacallanstatic void
1742e1ea03a3SmacallanCrimePolyPoint(
1743e1ea03a3Smacallan    DrawablePtr pDraw,
1744e1ea03a3Smacallan    GCPtr pGC,
1745e1ea03a3Smacallan    int mode,
1746e1ea03a3Smacallan    int npt,
1747e1ea03a3Smacallan    xPoint *pptInit
1748e1ea03a3Smacallan)
1749e1ea03a3Smacallan{
1750e1ea03a3Smacallan	ScreenPtr pScreen = pDraw->pScreen;
1751e1ea03a3Smacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1752e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1753e1ea03a3Smacallan	BoxPtr pBox;
1754e1ea03a3Smacallan	xPoint *ppt, *pts;
1755e1ea03a3Smacallan	int x1, x2, y1, y2, x, y, i, nBox;
1756e1ea03a3Smacallan
1757e1ea03a3Smacallan	/* make pointlist origin relative */
1758e1ea03a3Smacallan	ppt = pptInit;
1759e1ea03a3Smacallan	if (mode == CoordModePrevious) {
1760e1ea03a3Smacallan		for (i = 0; i < npt; i++) {
1761e1ea03a3Smacallan			ppt++;
1762e1ea03a3Smacallan			ppt->x += (ppt-1)->x;
1763e1ea03a3Smacallan			ppt->y += (ppt-1)->y;
1764e1ea03a3Smacallan		}
1765e1ea03a3Smacallan	}
176626dcc2a3Smacallan	MAKE_ROOM(6);
176726dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
176826dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1769e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, pGC->fgPixel << 8);
1770e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, pGC->alu);
1771e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, pGC->planemask);
1772e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1773e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP);
1774e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE, DE_PRIM_POINT);
177526dcc2a3Smacallan	SYNC;
1776e1ea03a3Smacallan	for (nBox = REGION_NUM_RECTS (pGC->pCompositeClip),
1777e1ea03a3Smacallan	    pBox = REGION_RECTS (pGC->pCompositeClip);
1778e1ea03a3Smacallan	    nBox--; pBox++) {
1779e1ea03a3Smacallan
1780e1ea03a3Smacallan		pts = pptInit;
1781e1ea03a3Smacallan		for (i = 0; i < npt; i++) {
1782e1ea03a3Smacallan			x1 = pBox->x1;
1783e1ea03a3Smacallan			y1 = pBox->y1;
1784e1ea03a3Smacallan			x2 = pBox->x2;
1785e1ea03a3Smacallan			y2 = pBox->y2;
1786e1ea03a3Smacallan			x = pts->x + pDraw->x;
1787e1ea03a3Smacallan			y = pts->y + pDraw->y;
1788e1ea03a3Smacallan			if (x1 <= x && x < x2 && y1 <= y && y < y2) {
1789e1ea03a3Smacallan
179026dcc2a3Smacallan		 		MAKE_ROOM(1);
1791e1ea03a3Smacallan				WRITE4ST(CRIME_DE_X_VERTEX_0,
1792e1ea03a3Smacallan					(x << 16) | y);
1793e1ea03a3Smacallan			}
1794e1ea03a3Smacallan			pts++;
1795e1ea03a3Smacallan		}
1796e1ea03a3Smacallan	}
1797e1ea03a3Smacallan}
1798e1ea03a3Smacallan
1799e1ea03a3Smacallanstatic void
1800e1ea03a3SmacallanCrimeValidatePolyPoint(
1801e1ea03a3Smacallan   GCPtr         pGC,
1802e1ea03a3Smacallan   unsigned long changes,
1803e1ea03a3Smacallan   DrawablePtr   pDraw )
1804e1ea03a3Smacallan{
1805e1ea03a3Smacallan
1806e1ea03a3Smacallan	if ((pDraw->type == DRAWABLE_WINDOW) ||
1807e1ea03a3Smacallan	    IS_OFFSCREEN_PIXMAP(pDraw)) {
1808e1ea03a3Smacallan		pGC->ops->PolyPoint = CrimePolyPoint;
1809e1ea03a3Smacallan	} else
1810e1ea03a3Smacallan		xf86Msg(X_ERROR, "boo\n");
1811e1ea03a3Smacallan}
181234c4e112Smacallanstatic void
181334c4e112SmacallanCrimePolyArc(DrawablePtr pDraw,
181434c4e112Smacallan               GCPtr pGC,
181534c4e112Smacallan               int narcs,
181634c4e112Smacallan               xArc *parcs)
181734c4e112Smacallan{
181834c4e112Smacallan    xArc *arc;
181934c4e112Smacallan    BoxRec box;
182034c4e112Smacallan    int i, x2, y2;
182134c4e112Smacallan    RegionPtr cclip;
182234c4e112Smacallan
182334c4e112Smacallan    cclip = pGC->pCompositeClip;
182434c4e112Smacallan
182534c4e112Smacallan    if(!REGION_NUM_RECTS(cclip))
182634c4e112Smacallan	return;
182734c4e112Smacallan
182834c4e112Smacallan    for (arc = parcs, i = narcs; --i >= 0; arc++) {
182934c4e112Smacallan	if (miCanZeroArc(arc)) {
183034c4e112Smacallan	    box.x1 = arc->x + pDraw->x;
183134c4e112Smacallan	    box.y1 = arc->y + pDraw->y;
183234c4e112Smacallan 	    x2 = box.x1 + (int)arc->width + 1;
183334c4e112Smacallan 	    box.x2 = x2;
183434c4e112Smacallan 	    y2 = box.y1 + (int)arc->height + 1;
183534c4e112Smacallan 	    box.y2 = y2;
183634c4e112Smacallan 	    if ( (x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) &&
183734c4e112Smacallan 		    (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) )
183834c4e112Smacallan		miZeroPolyArc(pDraw, pGC, 1, arc);
183934c4e112Smacallan	}
184034c4e112Smacallan	else
184134c4e112Smacallan	    miPolyArc(pDraw, pGC, 1, arc);
184234c4e112Smacallan    }
184334c4e112Smacallan}
184434c4e112Smacallan
184534c4e112Smacallanstatic void
184634c4e112SmacallanCrimeValidatePolyArc(GCPtr pGC,
184734c4e112Smacallan                       unsigned long changes,
184834c4e112Smacallan                       DrawablePtr pDraw)
184934c4e112Smacallan{
185034c4e112Smacallan	if ((pDraw->type == DRAWABLE_WINDOW) ||
185134c4e112Smacallan	    IS_OFFSCREEN_PIXMAP(pDraw)) {
185234c4e112Smacallan		pGC->ops->PolyPoint = CrimePolyPoint;
185334c4e112Smacallan		/*pGC->ops->PolyArc = miPolyArc;*/
185434c4e112Smacallan		pGC->ops->PolyArc = CrimePolyArc;
185534c4e112Smacallan	} else
185634c4e112Smacallan	{
185734c4e112Smacallan		pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint;
185834c4e112Smacallan		pGC->ops->PolyArc = XAAGetFallbackOps()->PolyArc;
185934c4e112Smacallan	}
186034c4e112Smacallan}
1861e1ea03a3Smacallan
186226dcc2a3Smacallanstatic void copyRGBAtoARGB(uint32_t *dest, uint32_t *src, int len)
186326dcc2a3Smacallan{
186426dcc2a3Smacallan	while (len > 0) {
186526dcc2a3Smacallan		*dest = *src >> 8;
186626dcc2a3Smacallan		dest++;
186726dcc2a3Smacallan		src++;
186826dcc2a3Smacallan		len--;
186926dcc2a3Smacallan	}
187026dcc2a3Smacallan}
187126dcc2a3Smacallan
187234c4e112Smacallanstatic void
187334c4e112SmacallanCrimeReadPixmap(ScrnInfoPtr pScrn,
187434c4e112Smacallan                     int x,
187534c4e112Smacallan		     int y,
187634c4e112Smacallan		     int w,
187734c4e112Smacallan		     int h,
187834c4e112Smacallan		     unsigned char *dst,
187934c4e112Smacallan		     int dstwidth,
188034c4e112Smacallan		     int bpp,
188134c4e112Smacallan		     int depth)
188234c4e112Smacallan{
188326dcc2a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
188426dcc2a3Smacallan	int bufno = 0;
188526dcc2a3Smacallan	int nextbuf, i, len = w << 2;
188626dcc2a3Smacallan	int mx = x << 2, offset;
188726dcc2a3Smacallan
188826dcc2a3Smacallan	offset = mx & 0x3f;
188926dcc2a3Smacallan	mx &= ~0x3f;
189026dcc2a3Smacallan	len = (len + offset + 0x3f) & ~0x3f;
189126dcc2a3Smacallan
189226dcc2a3Smacallan	LOG(CRIME_DEBUG_IMAGEREAD);
189326dcc2a3Smacallan
189426dcc2a3Smacallan#ifdef CRIME_DEBUG_LOUD
189526dcc2a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d\n", __func__, x, y, w, h);
189626dcc2a3Smacallan#endif
189726dcc2a3Smacallan
189826dcc2a3Smacallan	MAKE_ROOM(3);
189926dcc2a3Smacallan
190026dcc2a3Smacallan	/*
190126dcc2a3Smacallan	 * apparently all MTE coordinates are in bytes, not pixels
190226dcc2a3Smacallan	 * also, the MTE has some crazy alignment requirements - if
190326dcc2a3Smacallan	 * we don't do as above the thing will deadlock sooner or later
190426dcc2a3Smacallan	 * We use the MTE here because I couldn't get the rendering engine
190526dcc2a3Smacallan	 * to actually transfer anything into a linear buffer. The other
190626dcc2a3Smacallan	 * way around works just fine though. Shouldn't make much of a
190726dcc2a3Smacallan	 * difference, transfer times should be dominated by copying
190826dcc2a3Smacallan	 * data in and out of the DMA buffer anyway
190926dcc2a3Smacallan	 */
191026dcc2a3Smacallan	WRITE4(CRIME_MTE_MODE, (MTE_TLB_LIN_A << MTE_DST_TLB_SHIFT) |
191126dcc2a3Smacallan			 (MTE_TLB_A << MTE_SRC_TLB_SHIFT) |
191226dcc2a3Smacallan			 (MTE_DEPTH_8 << MTE_DEPTH_SHIFT) |
191326dcc2a3Smacallan			 MTE_MODE_DST_ECC | MTE_MODE_COPY);
191426dcc2a3Smacallan	WRITE4(CRIME_MTE_SRC_Y_STEP, 1);
191526dcc2a3Smacallan	WRITE4(CRIME_MTE_DST_Y_STEP, 1);
191626dcc2a3Smacallan	SYNCMTE;
191726dcc2a3Smacallan	WRITE4(CRIME_MTE_SRC0, (mx << 16) | y);
191826dcc2a3Smacallan	WRITE4(CRIME_MTE_SRC1, ((mx + len) << 16) | y);
191926dcc2a3Smacallan	WRITE4(CRIME_MTE_DST0, (bufno << 13));
192026dcc2a3Smacallan	WRITE4ST(CRIME_MTE_DST1, (bufno << 13) + len);
192126dcc2a3Smacallan	for (i = y + 1; i < y + h; i++) {
192226dcc2a3Smacallan		nextbuf = (bufno + 1) & 7;
192326dcc2a3Smacallan		SYNCMTE;
192426dcc2a3Smacallan		WRITE4(CRIME_MTE_SRC0, (mx << 16) | i);
192526dcc2a3Smacallan		WRITE4(CRIME_MTE_SRC1, ((mx + len) << 16) | i);
192626dcc2a3Smacallan		WRITE4(CRIME_MTE_DST0, (nextbuf << 13));
192726dcc2a3Smacallan		WRITE4ST(CRIME_MTE_DST1, (nextbuf << 13) + len);
192826dcc2a3Smacallan		copyRGBAtoARGB((uint32_t *)dst,
192926dcc2a3Smacallan			       (uint32_t *)(fPtr->buffers[bufno] + offset), w);
193026dcc2a3Smacallan		dst += dstwidth;
193126dcc2a3Smacallan		bufno = nextbuf;
193226dcc2a3Smacallan	}
193326dcc2a3Smacallan	SYNCMTE;
193426dcc2a3Smacallan	copyRGBAtoARGB((uint32_t *)dst,
193526dcc2a3Smacallan		       (uint32_t *)(fPtr->buffers[bufno] + offset), w);
193626dcc2a3Smacallan	DONE(CRIME_DEBUG_IMAGEREAD);
193726dcc2a3Smacallan
193834c4e112Smacallan}
1939e1ea03a3Smacallanint
1940e1ea03a3SmacallanCrimeAccelInit(ScrnInfoPtr pScrn)
1941e1ea03a3Smacallan{
1942e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1943e1ea03a3Smacallan	XAAInfoRecPtr pXAAInfo = fPtr->pXAA;
1944e1ea03a3Smacallan	int i;
1945e1ea03a3Smacallan
1946e1ea03a3Smacallan	for (i = 0; i < 0x1000; i++) regcache[i] = 0x12345678;
1947e1ea03a3Smacallan	LOG(CRIME_DEBUG_ALL);
1948e1ea03a3Smacallan	SYNC;
1949e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
1950e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1951e1ea03a3Smacallan
1952e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_Y, 1);
195326dcc2a3Smacallan	WRITE4(CRIME_DE_XFER_STRD_DST, 4);
1954e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STRD_SRC, 1);
1955e1ea03a3Smacallan
1956e1ea03a3Smacallan	WRITE4(CRIME_MTE_BYTEMASK, 0xffffffff);
1957e1ea03a3Smacallan	WRITE4(CRIME_MTE_SRC_Y_STEP, 4);
1958e1ea03a3Smacallan	WRITE4(CRIME_MTE_DST_Y_STEP, 4);
195926dcc2a3Smacallan	SYNC;
1960e1ea03a3Smacallan
1961e1ea03a3Smacallan	/* blit the screen black */
1962e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1963e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP);
1964e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, 3);
1965e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE, DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
1966e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, 0);
1967e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, 0);
1968e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
1969e1ea03a3Smacallan	    fPtr->info.width << 16 | fPtr->info.height);
1970e1ea03a3Smacallan	SYNC;
1971e1ea03a3Smacallan
197234c4e112Smacallan	pXAAInfo->Flags = /*LINEAR_FRAMEBUFFER |*/ PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
1973e1ea03a3Smacallan	pXAAInfo->maxOffPixWidth = fPtr->info.width;
1974e1ea03a3Smacallan	pXAAInfo->maxOffPixHeight = 2048;
1975e1ea03a3Smacallan
1976e1ea03a3Smacallan	/* Sync */
1977e1ea03a3Smacallan	pXAAInfo->Sync = CrimeSync;
1978e1ea03a3Smacallan
19798e5567ffSmacallan	CrimeDisableClipping(pScrn);
19808e5567ffSmacallan
1981e1ea03a3Smacallan	/* Screen-to-screen copy */
1982e1ea03a3Smacallan	pXAAInfo->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
1983e1ea03a3Smacallan	pXAAInfo->SetupForScreenToScreenCopy = CrimeSetupForScreenToScreenCopy;
1984e1ea03a3Smacallan	pXAAInfo->SubsequentScreenToScreenCopy =
1985e1ea03a3Smacallan		CrimeSubsequentScreenToScreenCopy;
1986e1ea03a3Smacallan
1987e1ea03a3Smacallan	/* rectangle fills */
1988e1ea03a3Smacallan	pXAAInfo->SetupForSolidFill = CrimeSetupForSolidFill;
1989e1ea03a3Smacallan	pXAAInfo->SubsequentSolidFillRect = CrimeSubsequentSolidFillRect;
1990e1ea03a3Smacallan
1991e1ea03a3Smacallan	/* image writes */
1992e1ea03a3Smacallan	pXAAInfo->ScanlineImageWriteFlags =
1993e1ea03a3Smacallan	    NO_TRANSPARENCY | LEFT_EDGE_CLIPPING |
1994e1ea03a3Smacallan	    LEFT_EDGE_CLIPPING_NEGATIVE_X |
1995e1ea03a3Smacallan	    CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD;
1996e1ea03a3Smacallan	pXAAInfo->NumScanlineImageWriteBuffers = 8;
1997e1ea03a3Smacallan	for (i = 0; i < 8; i++)
1998e1ea03a3Smacallan		fPtr->buffers[i] = fPtr->linear + (i * 8192);
1999e1ea03a3Smacallan	pXAAInfo->ScanlineImageWriteBuffers = fPtr->buffers;
2000e1ea03a3Smacallan	pXAAInfo->SetupForScanlineImageWrite =
2001e1ea03a3Smacallan		CrimeSetupForScanlineImageWrite;
2002e1ea03a3Smacallan	pXAAInfo->SubsequentScanlineImageWriteRect =
2003e1ea03a3Smacallan		CrimeSubsequentImageWriteRect;
2004e1ea03a3Smacallan	pXAAInfo->SubsequentImageWriteScanline =
2005e1ea03a3Smacallan		CrimeSubsequentImageWriteScanline;
2006e1ea03a3Smacallan
200734c4e112Smacallan	/* read pixmap */
200834c4e112Smacallan	pXAAInfo->ReadPixmapFlags = 0
200934c4e112Smacallan	                             | CPU_TRANSFER_PAD_DWORD
201034c4e112Smacallan				     ;
201134c4e112Smacallan	pXAAInfo->ReadPixmap = CrimeReadPixmap;
201234c4e112Smacallan
2013e1ea03a3Smacallan	/* colour expansion */
2014e1ea03a3Smacallan	pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags =
2015e1ea03a3Smacallan		LEFT_EDGE_CLIPPING;
2016e1ea03a3Smacallan	pXAAInfo->NumScanlineColorExpandBuffers = 1;
2017e1ea03a3Smacallan	fPtr->expandbuffers[0] = (uint8_t *)fPtr->expand;
2018e1ea03a3Smacallan	pXAAInfo->ScanlineColorExpandBuffers = (void *)&fPtr->expandbuffers;
2019e1ea03a3Smacallan	pXAAInfo->SetupForScanlineCPUToScreenColorExpandFill =
2020e1ea03a3Smacallan		CrimeSetupForCPUToScreenColorExpandFill;
2021e1ea03a3Smacallan	pXAAInfo->SubsequentScanlineCPUToScreenColorExpandFill =
2022e1ea03a3Smacallan		CrimeSubsequentScanlineCPUToScreenColorExpandFill;
2023e1ea03a3Smacallan	pXAAInfo->SubsequentColorExpandScanline =
2024e1ea03a3Smacallan		CrimeSubsequentColorExpandScanline;
2025e1ea03a3Smacallan
2026e1ea03a3Smacallan	/* clipping */
2027e1ea03a3Smacallan	pXAAInfo->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
20287a6652bbSmacallan		HARDWARE_CLIP_SOLID_FILL |
20297a6652bbSmacallan		HARDWARE_CLIP_SOLID_LINE |
20305b2650b9Smacallan		HARDWARE_CLIP_MONO_8x8_FILL | HARDWARE_CLIP_DASHED_LINE;
2031e1ea03a3Smacallan	pXAAInfo->SetClippingRectangle = CrimeSetClippingRectangle;
2032e1ea03a3Smacallan	pXAAInfo->DisableClipping = CrimeDisableClipping;
2033e1ea03a3Smacallan
2034e1ea03a3Smacallan	/* solid line drawing */
2035e1ea03a3Smacallan	pXAAInfo->SetupForSolidLine = CrimeSetupForSolidLine;
2036e1ea03a3Smacallan	pXAAInfo->SubsequentSolidTwoPointLine =
2037e1ea03a3Smacallan	    CrimeSubsequentSolidTwoPointLine;
20385b2650b9Smacallan	pXAAInfo->SolidLineFlags = 0;
2039e1ea03a3Smacallan
2040e1ea03a3Smacallan	/* dashed line drawing */
2041e1ea03a3Smacallan	pXAAInfo->SetupForDashedLine = CrimeSetupForDashedLine;
2042e1ea03a3Smacallan	pXAAInfo->SubsequentDashedTwoPointLine =
2043e1ea03a3Smacallan	    CrimeSubsequentDashedTwoPointLine;
2044e1ea03a3Smacallan	pXAAInfo->DashedLineFlags = LINE_PATTERN_MSBFIRST_MSBJUSTIFIED;
2045e1ea03a3Smacallan	pXAAInfo->DashPatternMaxLength = 32;
2046e1ea03a3Smacallan
20475b2650b9Smacallan	/* mono pattern fills */
20485b2650b9Smacallan	pXAAInfo->Mono8x8PatternFillFlags = HARDWARE_PATTERN_PROGRAMMED_BITS |
20495b2650b9Smacallan	    HARDWARE_PATTERN_PROGRAMMED_ORIGIN | BIT_ORDER_IN_BYTE_MSBFIRST;
20505b2650b9Smacallan	pXAAInfo->SetupForMono8x8PatternFill = CrimeSetupForMono8x8PatternFill;
20515b2650b9Smacallan	pXAAInfo->SubsequentMono8x8PatternFillRect =
20525b2650b9Smacallan	    CrimeSubsequentMono8x8PatternFillRect;
20535b2650b9Smacallan
2054e1ea03a3Smacallan	/* XRender acceleration */
2055e1ea03a3Smacallan#ifdef RENDER
2056e1ea03a3Smacallan	pXAAInfo->CPUToScreenAlphaTextureFlags = 0;
2057e1ea03a3Smacallan	pXAAInfo->SetupForCPUToScreenAlphaTexture =
2058e1ea03a3Smacallan	    CrimeSetupForCPUToScreenAlphaTexture;
2059e1ea03a3Smacallan	pXAAInfo->SubsequentCPUToScreenAlphaTexture =
2060e1ea03a3Smacallan	    CrimeSubsequentCPUToScreenAlphaTexture;
2061e1ea03a3Smacallan	pXAAInfo->CPUToScreenAlphaTextureFormats = CrimeAlphaTextureFormats;
2062e1ea03a3Smacallan
2063e1ea03a3Smacallan	pXAAInfo->SetupForCPUToScreenTexture = CrimeSetupForCPUToScreenTexture;
2064e1ea03a3Smacallan	pXAAInfo->SubsequentCPUToScreenTexture =
2065e1ea03a3Smacallan	    CrimeSubsequentCPUToScreenTexture;
2066e1ea03a3Smacallan	pXAAInfo->CPUToScreenTextureFlags = 0;
2067e1ea03a3Smacallan	pXAAInfo->CPUToScreenTextureFormats = CrimeTextureFormats;
2068e1ea03a3Smacallan	pXAAInfo->Composite = CrimeComposite;
2069e1ea03a3Smacallan#endif
2070e1ea03a3Smacallan	pXAAInfo->ValidatePolyPoint = CrimeValidatePolyPoint;
2071e1ea03a3Smacallan	pXAAInfo->PolyPointMask = GCFunction;
207234c4e112Smacallan	pXAAInfo->ValidatePolyArc = CrimeValidatePolyArc;
207334c4e112Smacallan	pXAAInfo->PolyArcMask = GCFunction | GCLineWidth;
2074e1ea03a3Smacallan
2075e1ea03a3Smacallan	return -1;
2076e1ea03a3Smacallan}
2077