crime_accel.c revision 29406fd8
129406fd8Smacallan/* $NetBSD: crime_accel.c,v 1.13 2009/10/21 03:28:40 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"
3829406fd8Smacallan#include "mipict.h"
39e1ea03a3Smacallan
40e1ea03a3Smacallanuint32_t regcache[0x1000];
41e1ea03a3Smacallan
42e1ea03a3Smacallan#define CRIMEREG(p) (volatile uint32_t *)(fPtr->engine + p)
4329406fd8Smacallan#define WBFLUSH __asm("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)
63e1ea03a3Smacallan#endif
6429406fd8Smacallan#define SYNCMTE do {} while ((*CRIMEREG(0x4000) & CRIME_DE_MTE_IDLE) == 0)
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);
7829406fd8Smacallan#if defined(CRIME_DEBUG_LOUD) && (CRIME_DEBUG_MASK & CRIME_DEBUG_SYNC)
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);
15229406fd8Smacallan#if defined(CRIME_DEBUG_LOUD) && (CRIME_DEBUG_MASK & CRIME_DEBUG_BITBLT)
153e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d, %d; %d x %d -> %d %d\n", __func__,
154e1ea03a3Smacallan	    xSrc, ySrc, w, h, xDst, yDst);
155e1ea03a3Smacallan#endif
15629406fd8Smacallan	if ((fPtr->use_mte) && (w > 64) && (abs(ySrc - yDst) > 4) &&
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	} else {
182e1ea03a3Smacallan		if (fPtr->xdir == -1) {
183e1ea03a3Smacallan			prim |= DE_PRIM_RL;
184e1ea03a3Smacallan			rxe = xDst;
185e1ea03a3Smacallan			rxa = xDst + w - 1;
186e1ea03a3Smacallan			rxs = xSrc + w - 1;
187e1ea03a3Smacallan		} else {
188e1ea03a3Smacallan			prim |= DE_PRIM_LR;
189e1ea03a3Smacallan			rxe = xDst + w - 1;
190e1ea03a3Smacallan			rxa = xDst;
191e1ea03a3Smacallan			rxs = xSrc;
192e1ea03a3Smacallan		}
193e1ea03a3Smacallan		if (fPtr->ydir == -1) {
194e1ea03a3Smacallan			prim |= DE_PRIM_BT;
195e1ea03a3Smacallan			rye = yDst;
196e1ea03a3Smacallan			rya = yDst + h - 1;
197e1ea03a3Smacallan			rys = ySrc + h - 1;
198e1ea03a3Smacallan		} else {
199e1ea03a3Smacallan			prim |= DE_PRIM_TB;
200e1ea03a3Smacallan			rye = yDst + h - 1;
201e1ea03a3Smacallan			rya = yDst;
202e1ea03a3Smacallan			rys = ySrc;
203e1ea03a3Smacallan		}
204e1ea03a3Smacallan
20526dcc2a3Smacallan		MAKE_ROOM(4);
206e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE, prim);
207e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC,(rxs << 16) | (rys & 0xffff));
208e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (rxa << 16) | (rya & 0xffff));
209e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1, (rxe << 16) | (rye & 0xffff));
210e1ea03a3Smacallan	}
211e1ea03a3Smacallan	DONE(CRIME_DEBUG_BITBLT);
212e1ea03a3Smacallan}
213e1ea03a3Smacallan
214e1ea03a3Smacallanstatic void
215e1ea03a3SmacallanCrimeSetupForSolidFill
216e1ea03a3Smacallan(
217e1ea03a3Smacallan    ScrnInfoPtr  pScrn,
218e1ea03a3Smacallan    int          colour,
219e1ea03a3Smacallan    int          rop,
220e1ea03a3Smacallan    unsigned int planemask
221e1ea03a3Smacallan)
222e1ea03a3Smacallan{
223e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
224e1ea03a3Smacallan	int i;
225e1ea03a3Smacallan
226e1ea03a3Smacallan	LOG(CRIME_DEBUG_RECTFILL);
227850ab569Smacallan#ifdef MTE_DRAW_RECT
228231734e4Smacallan	if (rop == GXcopy) {
229231734e4Smacallan		fPtr->use_mte = 1;
230231734e4Smacallan		MAKE_ROOM(3);
231231734e4Smacallan		WRITE4(CRIME_MTE_MODE, MTE_MODE_DST_ECC |
232231734e4Smacallan		    MTE_TLB_A << MTE_DST_TLB_SHIFT |
233231734e4Smacallan		    MTE_TLB_A << MTE_SRC_TLB_SHIFT |
234231734e4Smacallan		    MTE_DEPTH_32 << MTE_DEPTH_SHIFT);
235231734e4Smacallan		WRITE4(CRIME_MTE_DST_Y_STEP, 1);
236231734e4Smacallan		WRITE4(CRIME_MTE_BG, colour << 8);
237231734e4Smacallan		SYNCMTE;
238850ab569Smacallan	} else
239850ab569Smacallan#endif
240850ab569Smacallan	{
241231734e4Smacallan		fPtr->use_mte = 0;
242231734e4Smacallan		MAKE_ROOM(7);
243231734e4Smacallan		WRITE4(CRIME_DE_PLANEMASK, planemask);
244231734e4Smacallan		WRITE4(CRIME_DE_ROP, rop);
245231734e4Smacallan		WRITE4(CRIME_DE_FG, colour << 8);
246231734e4Smacallan		WRITE4(CRIME_DE_DRAWMODE,
247231734e4Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
248231734e4Smacallan		    DE_DRAWMODE_ROP |\
249231734e4Smacallan		    DE_DRAWMODE_SCISSOR_EN);
250231734e4Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
251231734e4Smacallan		    DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
252231734e4Smacallan		WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
253231734e4Smacallan		    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
254231734e4Smacallan		SYNC;
255231734e4Smacallan	}
256e1ea03a3Smacallan	DONE(CRIME_DEBUG_RECTFILL);
257e1ea03a3Smacallan}
258e1ea03a3Smacallan
259e1ea03a3Smacallanstatic void
260e1ea03a3SmacallanCrimeSubsequentSolidFillRect
261e1ea03a3Smacallan(
262e1ea03a3Smacallan    ScrnInfoPtr pScrn,
263e1ea03a3Smacallan    int         x,
264e1ea03a3Smacallan    int         y,
265e1ea03a3Smacallan    int         w,
266e1ea03a3Smacallan    int         h
267e1ea03a3Smacallan)
268e1ea03a3Smacallan{
269e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
2707a6652bbSmacallan	int xa, xe, ya, ye;
271e1ea03a3Smacallan
272e1ea03a3Smacallan	LOG(CRIME_DEBUG_RECTFILL);
273850ab569Smacallan#ifdef MTE_DRAW_RECT
274231734e4Smacallan	if (fPtr->use_mte) {
2757a6652bbSmacallan
2767a6652bbSmacallan		/*
2777a6652bbSmacallan		 * the MTE doesn't support clipping so we have to do it
2787a6652bbSmacallan		 * ourselves - luckily it's trivial with rectangles
2797a6652bbSmacallan		 */
2807a6652bbSmacallan		xa = MAX(fPtr->cxa, x);
2817a6652bbSmacallan		ya = MAX(fPtr->cya, y);
2827a6652bbSmacallan		xe = MIN(fPtr->cxe, x + w);
2837a6652bbSmacallan		ye = MIN(fPtr->cye, y + h);
2847a6652bbSmacallan		if ((xa < xe) && (ya < ye)) {
2857a6652bbSmacallan			MAKE_ROOM(2);
2867a6652bbSmacallan			WRITE4(CRIME_MTE_DST0, (xa << 18) | (ya & 0xffff));
2877a6652bbSmacallan			WRITE4ST(CRIME_MTE_DST1,
2887a6652bbSmacallan		 	   (((xe << 2) - 1 ) << 16) | ((ye - 1) & 0xffff));
2897a6652bbSmacallan		}
290850ab569Smacallan	} else
291850ab569Smacallan#endif
292850ab569Smacallan	{
293231734e4Smacallan		MAKE_ROOM(2);
294231734e4Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (x << 16) | (y & 0xffff));
295231734e4Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
296231734e4Smacallan		    ((x + w - 1) << 16) | ((y + h - 1) & 0xffff));
297231734e4Smacallan	}
298e1ea03a3Smacallan	DONE(CRIME_DEBUG_RECTFILL);
299e1ea03a3Smacallan}
300e1ea03a3Smacallan
3015b2650b9Smacallanstatic void
3025b2650b9SmacallanCrimeSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty,
3035b2650b9Smacallan        int fg, int bg, int rop, unsigned int planemask)
3045b2650b9Smacallan{
3055b2650b9Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
3065b2650b9Smacallan	uint32_t pat;
3075b2650b9Smacallan
3085b2650b9Smacallan	LOG(CRIME_DEBUG_RECTFILL);
3095b2650b9Smacallan	MAKE_ROOM(7);
3105b2650b9Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
3115b2650b9Smacallan	WRITE4(CRIME_DE_ROP, rop);
3125b2650b9Smacallan	WRITE4(CRIME_DE_FG, fg << 8);
3135b2650b9Smacallan	if (bg == -1) {
3145b2650b9Smacallan		WRITE4(CRIME_DE_DRAWMODE,
3155b2650b9Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
3165b2650b9Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_POLY_STIP |
3175b2650b9Smacallan		    DE_DRAWMODE_SCISSOR_EN);
3185b2650b9Smacallan	} else {
3195b2650b9Smacallan		WRITE4(CRIME_DE_BG, bg << 8);
3205b2650b9Smacallan		WRITE4(CRIME_DE_DRAWMODE,
3215b2650b9Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
3225b2650b9Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_POLY_STIP |
3235b2650b9Smacallan		    DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_SCISSOR_EN);
3245b2650b9Smacallan	}
3255b2650b9Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
3265b2650b9Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
3275b2650b9Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
3285b2650b9Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
3295b2650b9Smacallan
3305b2650b9Smacallan	/*
3315b2650b9Smacallan	 * we need to store the pattern so we can just hammer it into the
3325b2650b9Smacallan	 * stipple register later on
3335b2650b9Smacallan	 */
3345b2650b9Smacallan	pat = patx & 0xff000000;
3355b2650b9Smacallan	pat |= pat >> 8;
3365b2650b9Smacallan	fPtr->pattern[0] = pat | (pat >> 16);
3375b2650b9Smacallan	pat = patx & 0x00ff0000;
3385b2650b9Smacallan	pat |= pat << 8;
3395b2650b9Smacallan	fPtr->pattern[1] = pat | (pat >> 16);
3405b2650b9Smacallan	pat = patx & 0x0000ff00;
3415b2650b9Smacallan	pat |= pat >> 8;
3425b2650b9Smacallan	fPtr->pattern[2] = pat | (pat << 16);
3435b2650b9Smacallan	pat = patx & 0x000000ff;
3445b2650b9Smacallan	pat |= pat << 8;
3455b2650b9Smacallan	fPtr->pattern[3] = pat | (pat << 16);
3465b2650b9Smacallan
3475b2650b9Smacallan	pat = paty & 0xff000000;
3485b2650b9Smacallan	pat |= pat >> 8;
3495b2650b9Smacallan	fPtr->pattern[4] = pat | (pat >> 16);
3505b2650b9Smacallan	pat = paty & 0x00ff0000;
3515b2650b9Smacallan	pat |= pat << 8;
3525b2650b9Smacallan	fPtr->pattern[5] = pat | (pat >> 16);
3535b2650b9Smacallan	pat = paty & 0x0000ff00;
3545b2650b9Smacallan	pat |= pat >> 8;
3555b2650b9Smacallan	fPtr->pattern[6] = pat | (pat << 16);
3565b2650b9Smacallan	pat = paty & 0x000000ff;
3575b2650b9Smacallan	pat |= pat << 8;
3585b2650b9Smacallan	fPtr->pattern[7] = pat | (pat << 16);
3595b2650b9Smacallan	SYNC;
3605b2650b9Smacallan	DONE(CRIME_DEBUG_RECTFILL);
3615b2650b9Smacallan}
3625b2650b9Smacallan
3635b2650b9Smacallanstatic void
3645b2650b9SmacallanCrimeSubsequentMono8x8PatternFillRect( ScrnInfoPtr pScrn,
3655b2650b9Smacallan        	int patx, int paty, int x, int y, int w, int h)
3665b2650b9Smacallan{
3675b2650b9Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
3685b2650b9Smacallan	int i, pat;
3695b2650b9Smacallan
3705b2650b9Smacallan	LOG(CRIME_DEBUG_RECTFILL);
3715b2650b9Smacallan
3725b2650b9Smacallan	/* first setup the stipple stuff */
3735b2650b9Smacallan
3745b2650b9Smacallan	MAKE_ROOM(1);
3755b2650b9Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, 0x001f0000 | (patx << 24));
3765b2650b9Smacallan	pat = paty;
3775b2650b9Smacallan
3785b2650b9Smacallan	for (i = 0; i < h; i++) {
3795b2650b9Smacallan		MAKE_ROOM(3);
3805b2650b9Smacallan		WRITE4(CRIME_DE_STIPPLE_PAT, fPtr->pattern[pat]);
3815b2650b9Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (x << 16) | ((y + i) & 0xffff));
3825b2650b9Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
3835b2650b9Smacallan		    ((x + w - 1) << 16) | ((y + i) & 0xffff));
3845b2650b9Smacallan		pat = (pat + 1) & 7;
3855b2650b9Smacallan	}
3865b2650b9Smacallan	DONE(CRIME_DEBUG_RECTFILL);
3875b2650b9Smacallan}
3885b2650b9Smacallan
3895b2650b9Smacallanstatic void
390e1ea03a3SmacallanCrimeSetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
391e1ea03a3Smacallan                                unsigned int planemask, int trans_color,
392e1ea03a3Smacallan                                int bpp, int depth)
393e1ea03a3Smacallan{
394e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
395e1ea03a3Smacallan
396e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
39729406fd8Smacallan#if defined(CRIME_DEBUG_LOUD) && (CRIME_DEBUG_MASK & CRIME_DEBUG_IMAGEWRITE)
398e1ea03a3Smacallan	if ((bpp == 24) || (depth == 24))
399e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d \n", __func__, bpp, depth);
400e1ea03a3Smacallan#endif
40126dcc2a3Smacallan	MAKE_ROOM(7);
402e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
403e1ea03a3Smacallan			    DE_MODE_TYPE_RGB | DE_MODE_PIXDEPTH_32);
40426dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
40526dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
406e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
407e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
408e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
409e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
410e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP |
411e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
412e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
413e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
41426dcc2a3Smacallan	SYNC;
415e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
416e1ea03a3Smacallan}
417e1ea03a3Smacallan
4185b2650b9Smacallanstatic void
419e1ea03a3SmacallanCrimeSubsequentImageWriteRect(ScrnInfoPtr pScrn,
420e1ea03a3Smacallan                                int x, int y, int w, int h, int skipleft)
421e1ea03a3Smacallan{
422e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
423e1ea03a3Smacallan
424e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
425e1ea03a3Smacallan
42629406fd8Smacallan#if defined(CRIME_DEBUG_LOUD) && (CRIME_DEBUG_MASK & CRIME_DEBUG_IMAGEWRITE)
427e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d\n", __func__, x, y, w, h);
428e1ea03a3Smacallan#endif
429e1ea03a3Smacallan
430e1ea03a3Smacallan	fPtr->start = skipleft;
431e1ea03a3Smacallan	x += skipleft;
432e1ea03a3Smacallan	w -= skipleft;
433e1ea03a3Smacallan	if (x < 0) {
434e1ea03a3Smacallan		fPtr->ux = 0;
435e1ea03a3Smacallan		w += x;
436e1ea03a3Smacallan		fPtr->start -= x;
437e1ea03a3Smacallan	} else {
438e1ea03a3Smacallan		fPtr->ux = x;
439e1ea03a3Smacallan	}
440e1ea03a3Smacallan	fPtr->uy = y;
441e1ea03a3Smacallan	fPtr->uw = w;
442e1ea03a3Smacallan	fPtr->uh = h;
443e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
444e1ea03a3Smacallan}
445e1ea03a3Smacallan
4465b2650b9Smacallanstatic void
447e1ea03a3SmacallanCrimeSubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
448e1ea03a3Smacallan{
449e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
450e1ea03a3Smacallan
451e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
45226dcc2a3Smacallan	/*
45326dcc2a3Smacallan	 * we need to sync here, otherwise we might queue up more copy
45426dcc2a3Smacallan	 * commands than we have buffers
45526dcc2a3Smacallan	 */
45634c4e112Smacallan	SYNC;
457e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_ADDR_SRC, (bufno << 13)  + (fPtr->start << 2));
458e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (fPtr->ux << 16) | fPtr->uy);
459e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
460e1ea03a3Smacallan		((fPtr->ux + fPtr->uw - 1) << 16) | (fPtr->uy));
461e1ea03a3Smacallan	fPtr->uy++;
462e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
463e1ea03a3Smacallan}
464e1ea03a3Smacallan
465e1ea03a3Smacallanstatic void
466e1ea03a3SmacallanCrimeSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
467e1ea03a3Smacallan        		int fg, int bg,
468e1ea03a3Smacallan			int rop,
469e1ea03a3Smacallan			unsigned int planemask)
470e1ea03a3Smacallan{
471e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
472e1ea03a3Smacallan
473e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
47426dcc2a3Smacallan	MAKE_ROOM(7);
47526dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
47626dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
477e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
478e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
479e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, fg << 8);
480e1ea03a3Smacallan	if (bg == -1) {
481e1ea03a3Smacallan		/* transparent */
482e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
483e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
484e1ea03a3Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_POLY_STIP);
485e1ea03a3Smacallan	} else {
486e1ea03a3Smacallan		WRITE4(CRIME_DE_BG, bg << 8);
487e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
488e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
489e1ea03a3Smacallan		    DE_DRAWMODE_ROP |
490e1ea03a3Smacallan		    DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_POLY_STIP);
491e1ea03a3Smacallan	}
492e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
493e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
49426dcc2a3Smacallan	SYNC;
495e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
496e1ea03a3Smacallan}
497e1ea03a3Smacallan
498e1ea03a3Smacallanstatic void
499e1ea03a3SmacallanCrimeSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
500e1ea03a3Smacallan			int x, int y, int w, int h,
501e1ea03a3Smacallan			int skipleft )
502e1ea03a3Smacallan{
503e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
504e1ea03a3Smacallan
505e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
506e1ea03a3Smacallan
507e1ea03a3Smacallan	fPtr->start = skipleft;
508e1ea03a3Smacallan	fPtr->ux = x;
509e1ea03a3Smacallan	fPtr->uy = y;
510e1ea03a3Smacallan	fPtr->uw = w;
511e1ea03a3Smacallan	fPtr->uh = h;
512e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
513e1ea03a3Smacallan}
514e1ea03a3Smacallan
515e1ea03a3Smacallanstatic void
516e1ea03a3SmacallanCrimeSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
517e1ea03a3Smacallan{
518e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
519e1ea03a3Smacallan	uint32_t *boo = (uint32_t *)fPtr->expandbuffers[bufno];
520e1ea03a3Smacallan	int idx = fPtr->uw, x = fPtr->ux;
521e1ea03a3Smacallan
522e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
523e1ea03a3Smacallan
52426dcc2a3Smacallan	MAKE_ROOM(5);
525e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, 0x001f0000 | (fPtr->start << 24));
526e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_PAT, *boo);
527e1ea03a3Smacallan	boo++;
528e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x + fPtr->start << 16) | fPtr->uy);
529e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
530e1ea03a3Smacallan		((x + min(idx, 32) - 1) << 16) | (fPtr->uy));
531e1ea03a3Smacallan	idx -= 32;
532e1ea03a3Smacallan	x += 32;
533e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, 0x001f0000);
534e1ea03a3Smacallan
535e1ea03a3Smacallan	while (idx > 0) {
53626dcc2a3Smacallan		MAKE_ROOM(3);
537e1ea03a3Smacallan		WRITE4(CRIME_DE_STIPPLE_PAT, *boo);
538e1ea03a3Smacallan		boo++;
539e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (x << 16) | fPtr->uy);
540e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
541e1ea03a3Smacallan			((x + min(idx, 32) - 1) << 16) | (fPtr->uy));
542e1ea03a3Smacallan		idx -= 32;
543e1ea03a3Smacallan		x += 32;
544e1ea03a3Smacallan	}
545e1ea03a3Smacallan	fPtr->uy++;
546e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
547e1ea03a3Smacallan}
548e1ea03a3Smacallan
549e1ea03a3Smacallanstatic void
550e1ea03a3SmacallanCrimeSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
551e1ea03a3Smacallan    unsigned int planemask)
552e1ea03a3Smacallan{
553e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
554e1ea03a3Smacallan
555e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
556e1ea03a3Smacallan
55726dcc2a3Smacallan	MAKE_ROOM(5);
55826dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
55926dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
560e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
561e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
562e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, color << 8);
563e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
564e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
56593351543Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_SCISSOR_EN);
56626dcc2a3Smacallan	SYNC;
567e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
568e1ea03a3Smacallan}
569e1ea03a3Smacallan
570e1ea03a3Smacallanstatic void
571e1ea03a3SmacallanCrimeSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2,
572e1ea03a3Smacallan    int y2, int flags)
573e1ea03a3Smacallan{
574e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
575e1ea03a3Smacallan
576e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
57726dcc2a3Smacallan	MAKE_ROOM(3);
578e1ea03a3Smacallan	if (flags & OMIT_LAST) {
579e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
580e1ea03a3Smacallan			DE_PRIM_LINE | DE_PRIM_LINE_SKIP_END | 2);
581e1ea03a3Smacallan	} else {
582e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
583e1ea03a3Smacallan			DE_PRIM_LINE | 2);
584e1ea03a3Smacallan	}
585e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x1 << 16) | y1);
586e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1, (x2 << 16) | y2);
587e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
588850ab569Smacallan}
589e1ea03a3Smacallan
590e1ea03a3Smacallanvoid
591e1ea03a3SmacallanCrimeSetupForDashedLine(ScrnInfoPtr pScrn,
592e1ea03a3Smacallan		int fg, int bg, int rop, unsigned int planemask,
593e1ea03a3Smacallan        	int length, unsigned char *pattern)
594e1ea03a3Smacallan{
595e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
596e1ea03a3Smacallan	uint32_t pat;
597e1ea03a3Smacallan
598e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
599e1ea03a3Smacallan
600e1ea03a3Smacallan	fPtr->uw = length;
60126dcc2a3Smacallan	MAKE_ROOM(7);
60226dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
60326dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
604e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
605e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
606e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, fg << 8);
607e1ea03a3Smacallan	if (bg == -1) {
608e1ea03a3Smacallan		/* transparent */
609e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
610e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
61193351543Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_LINE_STIP |
61293351543Smacallan		    DE_DRAWMODE_SCISSOR_EN);
613e1ea03a3Smacallan	} else {
614e1ea03a3Smacallan		WRITE4(CRIME_DE_BG, bg << 8);
615e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
616e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
61793351543Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_SCISSOR_EN |
618e1ea03a3Smacallan		    DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_LINE_STIP);
619e1ea03a3Smacallan	}
620e1ea03a3Smacallan	/*
621e1ea03a3Smacallan	 * can we trust the Xserver to always hand us a 32bit aligned
622e1ea03a3Smacallan	 * pattern buffer?
623e1ea03a3Smacallan	 */
624e1ea03a3Smacallan	memcpy(&pat, pattern, 4);
625e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_PAT, pat);
62626dcc2a3Smacallan	SYNC;
627e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
628e1ea03a3Smacallan}
629e1ea03a3Smacallan
630e1ea03a3Smacallanvoid
631e1ea03a3SmacallanCrimeSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn,
632e1ea03a3Smacallan        int x1, int y1, int x2, int y2, int flags, int phase)
633e1ea03a3Smacallan{
634e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
635e1ea03a3Smacallan	uint32_t stipmode;
636e1ea03a3Smacallan
637e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
63826dcc2a3Smacallan	MAKE_ROOM(4);
639e1ea03a3Smacallan
640e1ea03a3Smacallan	if (flags & OMIT_LAST) {
641e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
642e1ea03a3Smacallan			DE_PRIM_LINE | DE_PRIM_LINE_SKIP_END | 2);
643e1ea03a3Smacallan	} else {
644e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
645e1ea03a3Smacallan			DE_PRIM_LINE | 2);
646e1ea03a3Smacallan	}
647e1ea03a3Smacallan
648e1ea03a3Smacallan	stipmode = ((fPtr->uw - 1) << 16) | (phase << 24);
649e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, stipmode);
650e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x1 << 16) | y1);
651e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1, (x2 << 16) | y2);
652e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
653e1ea03a3Smacallan}
654e1ea03a3Smacallan
655e1ea03a3Smacallanvoid
656e1ea03a3SmacallanCrimeSetClippingRectangle ( ScrnInfoPtr pScrn,
657e1ea03a3Smacallan                        int left, int top, int right, int bottom)
658e1ea03a3Smacallan{
659e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
660e1ea03a3Smacallan
661e1ea03a3Smacallan	LOG(CRIME_DEBUG_CLIPPING);
66226dcc2a3Smacallan	MAKE_ROOM(2);
66393351543Smacallan	WRITE4(CRIME_DE_SCISSOR, (left << 16) | top);
66493351543Smacallan	WRITE4(CRIME_DE_SCISSOR + 4, ((right + 1) << 16) | (bottom + 1));
6657a6652bbSmacallan	fPtr->cxa = left;
6667a6652bbSmacallan	fPtr->cxe = right;
6677a6652bbSmacallan	fPtr->cya = top;
6687a6652bbSmacallan	fPtr->cye = bottom;
66926dcc2a3Smacallan	SYNC;
670e1ea03a3Smacallan	DONE(CRIME_DEBUG_CLIPPING);
671e1ea03a3Smacallan}
672e1ea03a3Smacallan
673e1ea03a3Smacallanvoid
674e1ea03a3SmacallanCrimeDisableClipping (ScrnInfoPtr pScrn)
675e1ea03a3Smacallan{
676e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
677e1ea03a3Smacallan
678e1ea03a3Smacallan	LOG(CRIME_DEBUG_CLIPPING);
67926dcc2a3Smacallan	MAKE_ROOM(2);
68093351543Smacallan	WRITE4(CRIME_DE_SCISSOR, 0);
68193351543Smacallan	WRITE4(CRIME_DE_SCISSOR + 4, 0x3fff3fff);
6827a6652bbSmacallan	fPtr->cxa = 0;
6837a6652bbSmacallan	fPtr->cxe = 2047;
6847a6652bbSmacallan	fPtr->cya = 0;
6857a6652bbSmacallan	fPtr->cye = 2047;
68626dcc2a3Smacallan	SYNC;
687e1ea03a3Smacallan	DONE(CRIME_DEBUG_CLIPPING);
688e1ea03a3Smacallan}
689e1ea03a3Smacallan
690e1ea03a3Smacallanstatic Bool
691e1ea03a3SmacallanCrimeSetupForCPUToScreenAlphaTexture (
692e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
693e1ea03a3Smacallan   int		op,
694e1ea03a3Smacallan   CARD16	red,
695e1ea03a3Smacallan   CARD16	green,
696e1ea03a3Smacallan   CARD16	blue,
697e1ea03a3Smacallan   CARD16	alpha,
698e1ea03a3Smacallan   int		alphaType,
699e1ea03a3Smacallan   CARD8	*alphaPtr,
700e1ea03a3Smacallan   int		alphaPitch,
701e1ea03a3Smacallan   int		width,
702e1ea03a3Smacallan   int		height,
703e1ea03a3Smacallan   int		flags
704e1ea03a3Smacallan)
705e1ea03a3Smacallan{
706e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
707e1ea03a3Smacallan
708e1ea03a3Smacallan	if (op != PictOpOver) {
709e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
710e1ea03a3Smacallan		op = PictOpOver;
711e1ea03a3Smacallan	}
712e1ea03a3Smacallan
713e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
714e1ea03a3Smacallan
715e1ea03a3Smacallan	fPtr->alpha_color = ((red & 0xff00) << 16) |
716e1ea03a3Smacallan			    ((green & 0xff00) << 8) |
71709f0d67cSmacallan			    (blue & 0xff00);
718e1ea03a3Smacallan	fPtr->uw = width;
719e1ea03a3Smacallan	fPtr->uh = height;
720e1ea03a3Smacallan	fPtr->us = alphaPitch;
721e1ea03a3Smacallan	fPtr->alpha_texture = alphaPtr;
72209f0d67cSmacallan	fPtr->format = alphaType;
7235b2650b9Smacallan#ifdef CRIME_DEBUG_LOUD
72409f0d67cSmacallan	if (alphaType != PICT_a8) {
72509f0d67cSmacallan		xf86Msg(X_ERROR, "ARGB mask %08x %d\n", (uint32_t)alphaPtr,
72609f0d67cSmacallan		    alphaPitch);
72709f0d67cSmacallan	}
72829406fd8Smacallan	xf86Msg(X_ERROR, "%s: %x %x %x\n", __func__, red, green, blue);
7295b2650b9Smacallan#endif
73026dcc2a3Smacallan	MAKE_ROOM(7);
73126dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
73226dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
733e1ea03a3Smacallan	/* XXX this register is not where it's supposed to be */
734e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_COLOR, fPtr->alpha_color);
73509f0d67cSmacallan	if (alphaType == PICT_a8) {
73609f0d67cSmacallan		if (fPtr->alpha_color == 0) {
73709f0d67cSmacallan			WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_8 |
738e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
73909f0d67cSmacallan			WRITE4(CRIME_DE_XFER_STEP_X, 1);
74009f0d67cSmacallan			WRITE4(CRIME_DE_ALPHA_FUNC,
74109f0d67cSmacallan			    DE_ALPHA_ADD |
74209f0d67cSmacallan			    (DE_ALPHA_OP_ZERO << DE_ALPHA_OP_SRC_SHIFT) |
74309f0d67cSmacallan			    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
74409f0d67cSmacallan		} else {
74509f0d67cSmacallan			WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
74609f0d67cSmacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
74709f0d67cSmacallan			WRITE4(CRIME_DE_XFER_STEP_X, 4);
74809f0d67cSmacallan			WRITE4(CRIME_DE_ALPHA_FUNC,
74909f0d67cSmacallan			    DE_ALPHA_ADD |
75009f0d67cSmacallan			    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
75109f0d67cSmacallan			    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
75209f0d67cSmacallan		}
753e1ea03a3Smacallan	} else {
754e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
755e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
756e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_STEP_X, 4);
757e1ea03a3Smacallan		WRITE4(CRIME_DE_ALPHA_FUNC,
758e1ea03a3Smacallan		    DE_ALPHA_ADD |
759e1ea03a3Smacallan		    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
760e1ea03a3Smacallan		    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
76109f0d67cSmacallan	}
762e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
763e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
764e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
765e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
766e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
76726dcc2a3Smacallan	SYNC;
768e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
769e1ea03a3Smacallan	return TRUE;
770e1ea03a3Smacallan}
771e1ea03a3Smacallan
772e1ea03a3Smacallanvoid
773e1ea03a3SmacallanCrimeSubsequentCPUToScreenAlphaTexture (
774e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
775e1ea03a3Smacallan    int		dstx,
776e1ea03a3Smacallan    int		dsty,
777e1ea03a3Smacallan    int		srcx,
778e1ea03a3Smacallan    int		srcy,
779e1ea03a3Smacallan    int		width,
780e1ea03a3Smacallan    int		height
781e1ea03a3Smacallan)
782e1ea03a3Smacallan{
783e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
784e1ea03a3Smacallan	unsigned char *aptr;
785e1ea03a3Smacallan	uint32_t *dptr, aval;
786e1ea03a3Smacallan	int i, j;
787e1ea03a3Smacallan	int bufnum = 0;
788e1ea03a3Smacallan
789e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
790e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
791e1ea03a3Smacallan	xf86Msg(X_ERROR, "%d %d %d %d %d %d\n",srcx, srcy, dstx, dsty, width,
792e1ea03a3Smacallan	    height);
793e1ea03a3Smacallan#endif
794e1ea03a3Smacallan	aptr = fPtr->alpha_texture + (fPtr->us * srcy) + srcx;
795e1ea03a3Smacallan	for (i = 0; i < height; i++) {
796e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
797e1ea03a3Smacallan		if (fPtr->alpha_color == 0) {
798e1ea03a3Smacallan			memcpy(dptr, aptr, width);
799e1ea03a3Smacallan		} else {
800e1ea03a3Smacallan			for (j = 0; j < width; j++) {
801e1ea03a3Smacallan				aval = aptr[j];
802e1ea03a3Smacallan				*dptr = aval | fPtr->alpha_color;
803e1ea03a3Smacallan				dptr++;
804e1ea03a3Smacallan			}
805e1ea03a3Smacallan		}
80626dcc2a3Smacallan		MAKE_ROOM(3);
807e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
808e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
809e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
810e1ea03a3Smacallan			((dstx + width - 1) << 16) | (dsty + i));
811e1ea03a3Smacallan		bufnum++;
812e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
813e1ea03a3Smacallan		aptr += fPtr->us;
814e1ea03a3Smacallan	}
815e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
816e1ea03a3Smacallan}
817e1ea03a3Smacallan
81809f0d67cSmacallanvoid
81909f0d67cSmacallanCrimeSubsequentCPUToScreenAlphaTexture32 (
82009f0d67cSmacallan    ScrnInfoPtr	pScrn,
82109f0d67cSmacallan    int		dstx,
82209f0d67cSmacallan    int		dsty,
82309f0d67cSmacallan    int		srcx,
82409f0d67cSmacallan    int		srcy,
82509f0d67cSmacallan    int		width,
82609f0d67cSmacallan    int		height
82709f0d67cSmacallan)
82809f0d67cSmacallan{
82909f0d67cSmacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
83009f0d67cSmacallan	uint8_t *aptr;
83109f0d67cSmacallan	uint32_t *dptr, *sptr;
83209f0d67cSmacallan	int i, j;
83309f0d67cSmacallan	int bufnum = 0;
83409f0d67cSmacallan
83509f0d67cSmacallan	LOG(CRIME_DEBUG_XRENDER);
83629406fd8Smacallan#ifdef CRIME_DEBUG_LOUD_
83709f0d67cSmacallan	xf86Msg(X_ERROR, "%d %d %d %d %d %d\n",srcx, srcy, dstx, dsty, width,
83809f0d67cSmacallan	    height);
83909f0d67cSmacallan#endif
84009f0d67cSmacallan	aptr = fPtr->alpha_texture + (fPtr->us * srcy) + (srcx << 2);
84109f0d67cSmacallan	for (i = 0; i < height; i++) {
84209f0d67cSmacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
84309f0d67cSmacallan		sptr = (uint32_t *)aptr;
84409f0d67cSmacallan		for (j = 0; j < width; j++) {
84509f0d67cSmacallan			*dptr = (*sptr >> 24) | fPtr->alpha_color;
84629406fd8Smacallan#ifdef CRIME_DEBUG_LOUD_
84709f0d67cSmacallan			xf86Msg(X_ERROR, "%08x %08x\n", *sptr, *dptr);
84809f0d67cSmacallan#endif
84909f0d67cSmacallan			sptr++;
85009f0d67cSmacallan			dptr++;
85109f0d67cSmacallan		}
85226dcc2a3Smacallan		MAKE_ROOM(3);
85309f0d67cSmacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
85409f0d67cSmacallan		WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
85509f0d67cSmacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
85609f0d67cSmacallan			((dstx + width - 1) << 16) | (dsty + i));
85709f0d67cSmacallan		bufnum++;
85809f0d67cSmacallan		if (bufnum == 8) bufnum = 0;
85909f0d67cSmacallan		aptr += fPtr->us;
86009f0d67cSmacallan	}
86109f0d67cSmacallan	DONE(CRIME_DEBUG_XRENDER);
86209f0d67cSmacallan}
86309f0d67cSmacallan
864e1ea03a3Smacallanstatic Bool
865e1ea03a3SmacallanCrimeSetupForCPUToScreenTexture (
866e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
867e1ea03a3Smacallan   int		op,
868e1ea03a3Smacallan   int		texType,
869e1ea03a3Smacallan   CARD8	*texPtr,
870e1ea03a3Smacallan   int		texPitch,
871e1ea03a3Smacallan   int		width,
872e1ea03a3Smacallan   int		height,
873e1ea03a3Smacallan   int		flags
874e1ea03a3Smacallan)
875e1ea03a3Smacallan{
876e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
877e1ea03a3Smacallan
878e1ea03a3Smacallan	if (op != PictOpOver) {
879e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
880e1ea03a3Smacallan		op = PictOpOver;
881e1ea03a3Smacallan	}
882e1ea03a3Smacallan
883e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
884e1ea03a3Smacallan
885e1ea03a3Smacallan	fPtr->uw = width;
886e1ea03a3Smacallan	fPtr->uh = height;
887e1ea03a3Smacallan	fPtr->us = texPitch;
888e1ea03a3Smacallan	fPtr->alpha_texture = texPtr;
88926dcc2a3Smacallan	MAKE_ROOM(6);
89026dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
89126dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
892e1ea03a3Smacallan	if (texType == PICT_a8b8g8r8) {
893e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
894e1ea03a3Smacallan				    DE_MODE_TYPE_ABGR | DE_MODE_PIXDEPTH_32);
895e1ea03a3Smacallan	} else {
896e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
897e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
898e1ea03a3Smacallan	}
899e1ea03a3Smacallan	fPtr->format = texType;
900e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
901e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
902e1ea03a3Smacallan	    DE_ALPHA_ADD |
903e1ea03a3Smacallan	    (DE_ALPHA_OP_ONE/*SRC_ALPHA*/ << DE_ALPHA_OP_SRC_SHIFT) |
904e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
905e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
906e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
907e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
908e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
909e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
91026dcc2a3Smacallan	SYNC;
911e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
912e1ea03a3Smacallan	return TRUE;
913e1ea03a3Smacallan}
914e1ea03a3Smacallan
915e1ea03a3Smacallanvoid
916e1ea03a3SmacallanCrimeSubsequentCPUToScreenTexture (
917e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
918e1ea03a3Smacallan    int		dstx,
919e1ea03a3Smacallan    int		dsty,
920e1ea03a3Smacallan    int		srcx,
921e1ea03a3Smacallan    int		srcy,
922e1ea03a3Smacallan    int		width,
923e1ea03a3Smacallan    int		height
924e1ea03a3Smacallan)
925e1ea03a3Smacallan{
926e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
927e1ea03a3Smacallan	unsigned char *aptr, *lptr;
928e1ea03a3Smacallan	uint32_t *dptr, *sptr, aval, pixel;
929e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
930e1ea03a3Smacallan	int bufnum = 0;
931e1ea03a3Smacallan
932e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
933e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
934e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d\n", __func__,
935e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height);
936e1ea03a3Smacallan#endif
937e1ea03a3Smacallan	if ((width == 1) || (fPtr->format != PICT_a8r8g8b8)) {
938e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d %d %d\n", __func__,
939e1ea03a3Smacallan		    srcx, srcy, dstx, dsty, width, height, fPtr->uw, fPtr->us);
940e1ea03a3Smacallan		return;
941e1ea03a3Smacallan	}
942e1ea03a3Smacallan
943e1ea03a3Smacallan	aptr = fPtr->alpha_texture + (srcx << 2);
944e1ea03a3Smacallan	lptr = aptr + (fPtr->us * srcy);
945e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
946e1ea03a3Smacallan		rep = 128 / fPtr->uw;
947e1ea03a3Smacallan		period = rep * fPtr->uw;
948e1ea03a3Smacallan	}
949e1ea03a3Smacallan
950e1ea03a3Smacallan	if (fPtr->format == PICT_a8b8g8r8) {
951e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
952e1ea03a3Smacallan		xf86Msg(X_ERROR, "ABGR\n");
953e1ea03a3Smacallan#endif
954e1ea03a3Smacallan		for (i = 0; i < height; i++) {
955e1ea03a3Smacallan			dptr = (uint32_t *)fPtr->buffers[bufnum];
956e1ea03a3Smacallan			memcpy(dptr, aptr, fPtr->us);
95726dcc2a3Smacallan			MAKE_ROOM(3);
958e1ea03a3Smacallan			WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
959e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
960e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
961e1ea03a3Smacallan				((dstx + width - 1) << 16) | (dsty + i));
962e1ea03a3Smacallan			bufnum++;
963e1ea03a3Smacallan			if (bufnum == 8) bufnum = 0;
964e1ea03a3Smacallan			aptr += fPtr->us;
965e1ea03a3Smacallan		}
966e1ea03a3Smacallan	} else {
967e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
968e1ea03a3Smacallan		xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)aptr, fPtr->uw);
969e1ea03a3Smacallan#endif
970e1ea03a3Smacallan		lcnt = fPtr->uh - srcy;
971e1ea03a3Smacallan		for (i = 0; i < height; i++) {
972e1ea03a3Smacallan			dptr = (uint32_t *)fPtr->buffers[bufnum];
973e1ea03a3Smacallan			for (k = 0; k < rep; k++) {
974e1ea03a3Smacallan				sptr = (uint32_t *)aptr;
975e1ea03a3Smacallan				for (j = 0; j < fPtr->uw; j++) {
976e1ea03a3Smacallan					pixel = *sptr;
977e1ea03a3Smacallan					*dptr = (pixel << 8) | (pixel >> 24);
978e1ea03a3Smacallan					dptr++;
979e1ea03a3Smacallan					sptr++;
980e1ea03a3Smacallan				}
981e1ea03a3Smacallan			}
982e1ea03a3Smacallan			xoff = 0;
98326dcc2a3Smacallan			MAKE_ROOM(1);
984e1ea03a3Smacallan			WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
985e1ea03a3Smacallan			while (xoff < width) {
986e1ea03a3Smacallan				xa = dstx + xoff;
987e1ea03a3Smacallan				xe = dstx + min(xoff + period, width) - 1;
98826dcc2a3Smacallan				MAKE_ROOM(2);
989e1ea03a3Smacallan				WRITE4(CRIME_DE_X_VERTEX_0,
990e1ea03a3Smacallan				    xa << 16 | (dsty + i));
991e1ea03a3Smacallan				WRITE4ST(CRIME_DE_X_VERTEX_1,
992e1ea03a3Smacallan					(xe << 16) | (dsty + i));
993e1ea03a3Smacallan				xoff += period;
994e1ea03a3Smacallan			}
995e1ea03a3Smacallan			bufnum++;
996e1ea03a3Smacallan			if (bufnum == 8) bufnum = 0;
997e1ea03a3Smacallan			lcnt--;
998e1ea03a3Smacallan			if (lcnt == 0) {
999e1ea03a3Smacallan				aptr = lptr;
1000e1ea03a3Smacallan				lcnt = fPtr->uh;
1001e1ea03a3Smacallan			} else
1002e1ea03a3Smacallan				aptr += fPtr->us;
1003e1ea03a3Smacallan		}
1004e1ea03a3Smacallan	}
1005e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1006e1ea03a3Smacallan}
1007e1ea03a3Smacallan
1008e1ea03a3Smacallanstatic Bool
1009e1ea03a3SmacallanCrimeSetupForCPUToScreenTextureMask(
1010e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
1011e1ea03a3Smacallan   int		op,
1012e1ea03a3Smacallan   int		texType,
1013e1ea03a3Smacallan   CARD8	*srcPtr,
1014e1ea03a3Smacallan   int		srcPitch,
1015e1ea03a3Smacallan   CARD8	*mskPtr,
1016e1ea03a3Smacallan   int		mskPitch,
1017e1ea03a3Smacallan   int		width,
1018e1ea03a3Smacallan   int		height,
1019e1ea03a3Smacallan   int		flags
1020e1ea03a3Smacallan)
1021e1ea03a3Smacallan{
1022e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1023e1ea03a3Smacallan
1024e1ea03a3Smacallan	if (op != PictOpOver) {
1025e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
1026e1ea03a3Smacallan		op = PictOpOver;
1027e1ea03a3Smacallan	}
1028e1ea03a3Smacallan
1029e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1030e1ea03a3Smacallan
1031e1ea03a3Smacallan	fPtr->uw = width;
1032e1ea03a3Smacallan	fPtr->uh = height;
1033e1ea03a3Smacallan	fPtr->us = srcPitch >> 2;
1034e1ea03a3Smacallan	if (PICT_FORMAT_BPP(texType) == 32) {
1035e1ea03a3Smacallan		fPtr->um = mskPitch >> 2;
1036e1ea03a3Smacallan	} else
1037e1ea03a3Smacallan		fPtr->um = mskPitch;
1038e1ea03a3Smacallan	fPtr->msk = (uint8_t *)mskPtr;
1039e1ea03a3Smacallan	fPtr->src = (uint8_t *)srcPtr;
1040e1ea03a3Smacallan	fPtr->texture_depth = PICT_FORMAT_BPP(texType);
1041e1ea03a3Smacallan
104226dcc2a3Smacallan	MAKE_ROOM(6);
1043e1ea03a3Smacallan	/* always expect ARGB for now */
1044e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
1045e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
104626dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
104726dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1048e1ea03a3Smacallan	fPtr->format = texType;
1049e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
1050e1ea03a3Smacallan	    DE_ALPHA_ADD |
1051e1ea03a3Smacallan	    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
1052e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
1053e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
1054e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1055e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
1056e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
1057e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
1058e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
105926dcc2a3Smacallan	SYNC;
1060e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1061e1ea03a3Smacallan	return TRUE;
1062e1ea03a3Smacallan}
1063e1ea03a3Smacallan
1064e1ea03a3Smacallanvoid
1065e1ea03a3SmacallanCrimeSubsequentCPUToScreenTextureMask32(
1066e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
1067e1ea03a3Smacallan    int		dstx,
1068e1ea03a3Smacallan    int		dsty,
1069e1ea03a3Smacallan    int		srcx,
1070e1ea03a3Smacallan    int		srcy,
1071e1ea03a3Smacallan    int		maskx,
1072e1ea03a3Smacallan    int		masky,
1073e1ea03a3Smacallan    int		width,
1074e1ea03a3Smacallan    int		height
1075e1ea03a3Smacallan)
1076e1ea03a3Smacallan{
1077e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1078e1ea03a3Smacallan	uint32_t *lsptr, *lmptr, *asptr, *amptr;
1079e1ea03a3Smacallan	uint32_t *dptr, *sptr, *mptr, aval, pixel, mask;
1080e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
1081e1ea03a3Smacallan	int bufnum = 0;
1082e1ea03a3Smacallan	int sr, sg, sb, sa, mr, mg, mb, ma, rr, gg, bb, aa;
1083e1ea03a3Smacallan
1084e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1085e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
1086e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d; %d %d %d\n", __func__,
1087e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height, maskx, masky, fPtr->um);
1088e1ea03a3Smacallan#endif
1089e1ea03a3Smacallan	sptr = fPtr->src + (srcx << 2);
1090e1ea03a3Smacallan	mptr = fPtr->msk + (srcx << 2);
1091e1ea03a3Smacallan	lsptr = sptr + (fPtr->us * srcy);
1092e1ea03a3Smacallan	lmptr = mptr + (fPtr->um * srcy);
1093e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
1094e1ea03a3Smacallan		rep = 128 / fPtr->uw;
1095e1ea03a3Smacallan		period = rep * fPtr->uw;
1096e1ea03a3Smacallan	}
1097e1ea03a3Smacallan
1098e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
109929406fd8Smacallan	xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)asptr, fPtr->uw);
1100e1ea03a3Smacallan#endif
1101e1ea03a3Smacallan	lcnt = fPtr->uh - srcy;
1102e1ea03a3Smacallan	for (i = 0; i < height; i++) {
1103e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
1104e1ea03a3Smacallan		for (k = 0; k < rep; k++) {
1105e1ea03a3Smacallan			asptr = lsptr;
1106e1ea03a3Smacallan			amptr = lmptr;
1107e1ea03a3Smacallan			for (j = 0; j < fPtr->uw; j++) {
1108e1ea03a3Smacallan				pixel = *asptr;
1109e1ea03a3Smacallan				mask = *amptr;
1110e1ea03a3Smacallan				if (mask == 0xffffffff) {
1111e1ea03a3Smacallan					*dptr = (pixel >> 24) | (pixel << 8);
1112e1ea03a3Smacallan				} else if (mask == 0x00000000) {
1113e1ea03a3Smacallan					*dptr = 0;
1114e1ea03a3Smacallan				} else {
1115e1ea03a3Smacallan					/* input is ARGB */
1116e1ea03a3Smacallan					sb = pixel & 0xff;
1117e1ea03a3Smacallan					sg = (pixel >> 8) & 0xff;
1118e1ea03a3Smacallan					sr = (pixel >> 16) & 0xff;
1119e1ea03a3Smacallan					sa = (pixel >> 24) & 0xff;
1120e1ea03a3Smacallan					mb = mask & 0xff;
1121e1ea03a3Smacallan					mg = (mask >> 8) & 0xff;
1122e1ea03a3Smacallan					mr = (mask >> 16) & 0xff;
1123e1ea03a3Smacallan					ma = (mask >> 24) & 0xff;
1124e1ea03a3Smacallan
1125e1ea03a3Smacallan					/* and here we need an RGBA pixel */
1126e1ea03a3Smacallan					bb = (((sb * mb) + 0x80) & 0xff00);
1127e1ea03a3Smacallan					gg = (((sg * mg) + 0x80) & 0xff00) << 8;
1128e1ea03a3Smacallan					rr = (((sr * mr) + 0x80) & 0xff00) << 16;
1129e1ea03a3Smacallan					aa = (((sa * ma) + 0x80) & 0xff00) >> 8;
1130e1ea03a3Smacallan					/*
1131e1ea03a3Smacallan					 * actually we could let the HW do this stuff
1132e1ea03a3Smacallan					 */
1133e1ea03a3Smacallan					*dptr = aa | rr | gg | bb;
1134e1ea03a3Smacallan				}
1135e1ea03a3Smacallan				dptr++;
1136e1ea03a3Smacallan				asptr++;
1137e1ea03a3Smacallan				amptr++;
1138e1ea03a3Smacallan			}
1139e1ea03a3Smacallan		}
1140e1ea03a3Smacallan		xoff = 0;
114126dcc2a3Smacallan		MAKE_ROOM(1);
1142e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
1143e1ea03a3Smacallan		while (xoff < width) {
1144e1ea03a3Smacallan			xa = dstx + xoff;
1145e1ea03a3Smacallan			xe = dstx + min(xoff + period, width) - 1;
114626dcc2a3Smacallan			MAKE_ROOM(2);
1147e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0,
1148e1ea03a3Smacallan			    xa << 16 | (dsty + i));
1149e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
1150e1ea03a3Smacallan				(xe << 16) | (dsty + i));
1151e1ea03a3Smacallan			xoff += period;
1152e1ea03a3Smacallan		}
1153e1ea03a3Smacallan		bufnum++;
1154e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
1155e1ea03a3Smacallan		lcnt--;
1156e1ea03a3Smacallan		if (lcnt == 0) {
1157e1ea03a3Smacallan			/* back to the beginning */
1158e1ea03a3Smacallan			lsptr = sptr;
1159e1ea03a3Smacallan			lmptr = mptr;
1160e1ea03a3Smacallan			lcnt = fPtr->uh;
1161e1ea03a3Smacallan		} else
1162e1ea03a3Smacallan			/* next line */
1163e1ea03a3Smacallan			lsptr += fPtr->us;
1164e1ea03a3Smacallan			lmptr += fPtr->um;
1165e1ea03a3Smacallan	}
1166e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1167e1ea03a3Smacallan}
1168e1ea03a3Smacallan
1169e1ea03a3Smacallanvoid
1170e1ea03a3SmacallanCrimeSubsequentCPUToScreenTextureMask8(
1171e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
1172e1ea03a3Smacallan    int		dstx,
1173e1ea03a3Smacallan    int		dsty,
1174e1ea03a3Smacallan    int		srcx,
1175e1ea03a3Smacallan    int		srcy,
1176e1ea03a3Smacallan    int		maskx,
1177e1ea03a3Smacallan    int		masky,
1178e1ea03a3Smacallan    int		width,
1179e1ea03a3Smacallan    int		height
1180e1ea03a3Smacallan)
1181e1ea03a3Smacallan{
1182e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1183e1ea03a3Smacallan	uint32_t *lsptr, *asptr;
1184e1ea03a3Smacallan	uint32_t *dptr, *sptr, aval, pixel, mask;
1185e1ea03a3Smacallan	uint8_t  *lmptr, *amptr, *mptr;
1186e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
1187e1ea03a3Smacallan	int bufnum = 0;
1188e1ea03a3Smacallan	int sr, sg, sb, sa, rr, gg, bb, aa;
1189e1ea03a3Smacallan
1190e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
11915b2650b9Smacallan#ifdef CRIME_DEBUG_LOUD
1192e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d\n", __func__,
1193e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height);
1194e1ea03a3Smacallan#endif
1195e1ea03a3Smacallan	sptr = (uint32_t *)fPtr->src + (fPtr->us * srcy) + (srcx << 2);
1196e1ea03a3Smacallan	mptr = (uint8_t *)fPtr->msk + (fPtr->um * srcy) + srcx;
1197e1ea03a3Smacallan	lsptr = sptr;
1198e1ea03a3Smacallan	lmptr = mptr;
1199e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
1200e1ea03a3Smacallan		rep = 128 / fPtr->uw;
1201e1ea03a3Smacallan		period = rep * fPtr->uw;
1202e1ea03a3Smacallan	}
1203e1ea03a3Smacallan
1204e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
120529406fd8Smacallan	xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)asptr, fPtr->uw);
1206e1ea03a3Smacallan#endif
1207e1ea03a3Smacallan	lcnt = fPtr->uh;
1208e1ea03a3Smacallan	for (i = 0; i < height; i++) {
1209e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
1210e1ea03a3Smacallan		for (k = 0; k < rep; k++) {
1211e1ea03a3Smacallan			asptr = lsptr;
1212e1ea03a3Smacallan			amptr = lmptr;
1213e1ea03a3Smacallan			for (j = 0; j < fPtr->uw; j++) {
1214e1ea03a3Smacallan				pixel = *asptr;
1215e1ea03a3Smacallan				mask = *amptr;
1216e1ea03a3Smacallan				if (mask == 0xff) {
1217e1ea03a3Smacallan					*dptr = (pixel >> 24) | (pixel << 8);
1218e1ea03a3Smacallan				} else if (mask == 0x00) {
1219e1ea03a3Smacallan					*dptr = 0;
1220e1ea03a3Smacallan				} else {
1221e1ea03a3Smacallan					/* input is ARGB */
1222e1ea03a3Smacallan					sb = pixel & 0xff;
1223e1ea03a3Smacallan					sg = (pixel >> 8) & 0xff;
1224e1ea03a3Smacallan					sr = (pixel >> 16) & 0xff;
1225e1ea03a3Smacallan					sa = (pixel >> 24) & 0xff;
1226e1ea03a3Smacallan
1227e1ea03a3Smacallan					/* and here we need an RGBA pixel */
1228e1ea03a3Smacallan					bb = (((sb * mask) + 0x80) & 0xff00);
1229e1ea03a3Smacallan					gg = (((sg * mask) + 0x80) & 0xff00)
1230e1ea03a3Smacallan					     << 8;
1231e1ea03a3Smacallan					rr = (((sr * mask) + 0x80) & 0xff00)
1232e1ea03a3Smacallan					     << 16;
1233e1ea03a3Smacallan					aa = (((sa * mask) + 0x80) & 0xff00)
1234e1ea03a3Smacallan					     >> 8;
1235e1ea03a3Smacallan					/*
1236e1ea03a3Smacallan					 * actually we could let the HW do this
1237e1ea03a3Smacallan					 * stuff
1238e1ea03a3Smacallan					 */
1239e1ea03a3Smacallan					*dptr = aa | rr | gg | bb;
1240e1ea03a3Smacallan				}
1241e1ea03a3Smacallan				dptr++;
1242e1ea03a3Smacallan				asptr++;
1243e1ea03a3Smacallan				amptr++;
1244e1ea03a3Smacallan			}
1245e1ea03a3Smacallan		}
1246e1ea03a3Smacallan		xoff = 0;
124726dcc2a3Smacallan		MAKE_ROOM(1);
1248e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
1249e1ea03a3Smacallan		while (xoff < width) {
1250e1ea03a3Smacallan			xa = dstx + xoff;
1251e1ea03a3Smacallan			xe = dstx + min(xoff + period, width) - 1;
125226dcc2a3Smacallan			MAKE_ROOM(2);
1253e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0,
1254e1ea03a3Smacallan			    xa << 16 | (dsty + i));
1255e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
1256e1ea03a3Smacallan				(xe << 16) | (dsty + i));
1257e1ea03a3Smacallan			xoff += period;
1258e1ea03a3Smacallan		}
1259e1ea03a3Smacallan		bufnum++;
1260e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
1261e1ea03a3Smacallan		lcnt--;
1262e1ea03a3Smacallan		if (lcnt == 0) {
1263e1ea03a3Smacallan			/* back to the beginning */
1264e1ea03a3Smacallan			lsptr = sptr;
1265e1ea03a3Smacallan			lmptr = mptr;
1266e1ea03a3Smacallan			lcnt = fPtr->uh;
1267e1ea03a3Smacallan		} else
1268e1ea03a3Smacallan			/* next line */
1269e1ea03a3Smacallan			lsptr += fPtr->us;
1270e1ea03a3Smacallan			lmptr += fPtr->um;
1271e1ea03a3Smacallan	}
1272e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1273e1ea03a3Smacallan}
1274e1ea03a3Smacallan
1275e1ea03a3Smacallanstatic void
1276e1ea03a3SmacallanCrimeDoCPUToScreenComposite(
1277e1ea03a3Smacallan   	CARD8      op,
1278e1ea03a3Smacallan        PicturePtr pSrc,
1279e1ea03a3Smacallan        PicturePtr pMask,
1280e1ea03a3Smacallan        PicturePtr pDst,
1281e1ea03a3Smacallan        INT16      xSrc,
1282e1ea03a3Smacallan        INT16      ySrc,
1283e1ea03a3Smacallan        INT16      xMask,
1284e1ea03a3Smacallan        INT16      yMask,
1285e1ea03a3Smacallan        INT16      xDst,
1286e1ea03a3Smacallan        INT16      yDst,
1287e1ea03a3Smacallan        CARD16     width,
1288e1ea03a3Smacallan        CARD16     height
1289e1ea03a3Smacallan)
1290e1ea03a3Smacallan{
1291e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1292e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1293e1ea03a3Smacallan	RegionRec region;
1294e1ea03a3Smacallan	CARD32 *formats;
1295e1ea03a3Smacallan	int flags = 0;
1296e1ea03a3Smacallan	BoxPtr pbox;
1297e1ea03a3Smacallan	int nbox, w, h;
1298e1ea03a3Smacallan
1299e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1300e1ea03a3Smacallan	if (pSrc->transform || (pMask && pMask->transform)) {
1301e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: transform?!\n", __func__);
1302e1ea03a3Smacallan		return;
1303e1ea03a3Smacallan	}
1304e1ea03a3Smacallan
1305e1ea03a3Smacallan	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) {
1306e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: alpha-map?!\n", __func__);
1307e1ea03a3Smacallan		return;
1308e1ea03a3Smacallan	}
1309e1ea03a3Smacallan
1310e1ea03a3Smacallan	xDst += pDst->pDrawable->x;
1311e1ea03a3Smacallan	yDst += pDst->pDrawable->y;
1312e1ea03a3Smacallan	xSrc += pSrc->pDrawable->x;
1313e1ea03a3Smacallan	ySrc += pSrc->pDrawable->y;
1314e1ea03a3Smacallan
1315e1ea03a3Smacallan	if(pMask) {
1316e1ea03a3Smacallan		CARD16 red, green, blue, alpha;
1317e1ea03a3Smacallan		CARD32 pixel =
131829406fd8Smacallan		   *((CARD32*)(((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr));
131909f0d67cSmacallan#ifdef CRIME_DEBUG_LOUD
1320e1ea03a3Smacallan		if(pMask->componentAlpha) {
1321e1ea03a3Smacallan			xf86Msg(X_ERROR, "%s: alpha component mask\n",
1322e1ea03a3Smacallan			    __func__);
132329406fd8Smacallan			xf86Msg(X_ERROR, "src: %d x %d\n",
132429406fd8Smacallan			    pSrc->pDrawable->width,
132509f0d67cSmacallan			    pSrc->pDrawable->height);
1326e1ea03a3Smacallan		}
132709f0d67cSmacallan#endif
1328e1ea03a3Smacallan		if ((pSrc->pDrawable->width == 1) &&
1329e1ea03a3Smacallan		    (pSrc->pDrawable->height == 1)) {
1330e1ea03a3Smacallan
1331e1ea03a3Smacallan			if(!XAAGetRGBAFromPixel(pixel, &red, &green, &blue,
1332e1ea03a3Smacallan			    &alpha, pSrc->format)) {
133329406fd8Smacallan				xf86Msg(X_ERROR, "%s: can't read pixel\n",
133429406fd8Smacallan				    __func__);
1335e1ea03a3Smacallan				return;
1336e1ea03a3Smacallan			}
133729406fd8Smacallan#ifdef CRIME_DEBUG_LOUD
133829406fd8Smacallan			xf86Msg(X_ERROR, "RGBA: %d %d %d %d\n", red, green,
133929406fd8Smacallan			    blue, alpha);
134029406fd8Smacallan#endif
1341e1ea03a3Smacallan			xMask += pMask->pDrawable->x;
1342e1ea03a3Smacallan			yMask += pMask->pDrawable->y;
1343e1ea03a3Smacallan
1344e1ea03a3Smacallan			/* pull out color expandable operations here */
1345e1ea03a3Smacallan			if(pMask->format == PICT_a1) {
1346e1ea03a3Smacallan				PixmapPtr pPix = (PixmapPtr)(pMask->pDrawable);
1347e1ea03a3Smacallan				int skipleft;
1348e1ea03a3Smacallan
1349e1ea03a3Smacallan				if (op != PictOpOver) {
1350e1ea03a3Smacallan					xf86Msg(X_ERROR, "!over\n");
1351e1ea03a3Smacallan					return;
1352e1ea03a3Smacallan				}
1353e1ea03a3Smacallan				if (pMask->repeat) {
1354e1ea03a3Smacallan					xf86Msg(X_ERROR, "mono repeat\n");
1355e1ea03a3Smacallan					return;
1356e1ea03a3Smacallan				}
1357e1ea03a3Smacallan				if (!miComputeCompositeRegion (&region, pSrc,
1358e1ea03a3Smacallan				    pMask, pDst, xSrc, ySrc, xMask, yMask, xDst,
1359e1ea03a3Smacallan				    yDst, width, height)) {
1360e1ea03a3Smacallan					return;
1361e1ea03a3Smacallan				}
1362e1ea03a3Smacallan
1363e1ea03a3Smacallan				nbox = REGION_NUM_RECTS(&region);
1364e1ea03a3Smacallan				pbox = REGION_RECTS(&region);
1365e1ea03a3Smacallan
1366e1ea03a3Smacallan				if(!nbox) {
1367e1ea03a3Smacallan					return;
1368e1ea03a3Smacallan				}
1369e1ea03a3Smacallan
1370e1ea03a3Smacallan				XAAGetPixelFromRGBA(&pixel, red, green, blue, 0,
1371e1ea03a3Smacallan				    pDst->format);
1372e1ea03a3Smacallan
1373e1ea03a3Smacallan				xMask -= xDst;
1374e1ea03a3Smacallan				yMask -= yDst;
1375e1ea03a3Smacallan
1376e1ea03a3Smacallan				while(nbox--) {
1377e1ea03a3Smacallan					skipleft = pbox->x1 + xMask;
1378e1ea03a3Smacallan
137929406fd8Smacallan					(*infoRec->WriteBitmap)(infoRec->pScrn, 					    	    pbox->x1, pbox->y1,
1380e1ea03a3Smacallan					    pbox->x2 - pbox->x1,
1381e1ea03a3Smacallan					    pbox->y2 - pbox->y1,
138229406fd8Smacallan					    (unsigned char*)
138329406fd8Smacallan					        (pPix->devPrivate.ptr) +
138429406fd8Smacallan						(pPix->devKind *
138529406fd8Smacallan					        (pbox->y1 + yMask)) +
138629406fd8Smacallan						((skipleft >> 3) & ~3),
138729406fd8Smacallan					    pPix->devKind, skipleft & 31, pixel,
138829406fd8Smacallan					    -1, GXcopy, ~0);
1389e1ea03a3Smacallan					pbox++;
1390e1ea03a3Smacallan				}
1391e1ea03a3Smacallan
1392e1ea03a3Smacallan				/* WriteBitmap sets the Sync flag */
1393e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1394e1ea03a3Smacallan				DONE(CRIME_DEBUG_XRENDER);
1395e1ea03a3Smacallan				return;
1396e1ea03a3Smacallan			}
139709f0d67cSmacallan			if((pMask->format == PICT_a8) ||
139809f0d67cSmacallan			   (pMask->format == PICT_a8r8g8b8)) {
1399e1ea03a3Smacallan
1400e1ea03a3Smacallan				w = pMask->pDrawable->width;
1401e1ea03a3Smacallan				h = pMask->pDrawable->height;
1402e1ea03a3Smacallan
1403e1ea03a3Smacallan				if(pMask->repeat) {
1404e1ea03a3Smacallan					flags |= XAA_RENDER_REPEAT;
1405e1ea03a3Smacallan				}
1406e1ea03a3Smacallan
1407e1ea03a3Smacallan				if (!miComputeCompositeRegion (&region, pSrc, pMask,
1408e1ea03a3Smacallan				    pDst, xSrc, ySrc, xMask, yMask, xDst, yDst,
1409e1ea03a3Smacallan				    width, height)) {
1410e1ea03a3Smacallan					return;
1411e1ea03a3Smacallan				}
1412e1ea03a3Smacallan
1413e1ea03a3Smacallan				nbox = REGION_NUM_RECTS(&region);
1414e1ea03a3Smacallan				pbox = REGION_RECTS(&region);
1415e1ea03a3Smacallan
1416e1ea03a3Smacallan				if(!nbox) {
1417e1ea03a3Smacallan					REGION_UNINIT(pScreen, &region);
1418e1ea03a3Smacallan					return;
1419e1ea03a3Smacallan				}
1420e1ea03a3Smacallan
142129406fd8Smacallan				CrimeSetupForCPUToScreenAlphaTexture(
142229406fd8Smacallan				    infoRec->pScrn, op, red, green, blue, alpha,
142329406fd8Smacallan				    pMask->format,
1424e1ea03a3Smacallan				    ((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr,
1425e1ea03a3Smacallan				    ((PixmapPtr)(pMask->pDrawable))->devKind,
1426e1ea03a3Smacallan				    w, h, flags);
1427e1ea03a3Smacallan
1428e1ea03a3Smacallan				xMask -= xDst;
1429e1ea03a3Smacallan				yMask -= yDst;
1430e1ea03a3Smacallan
143109f0d67cSmacallan				if (pMask->format != PICT_a8) {
143209f0d67cSmacallan					while(nbox--) {
143309f0d67cSmacallan						CrimeSubsequentCPUToScreenAlphaTexture32(
143409f0d67cSmacallan						    infoRec->pScrn,
143509f0d67cSmacallan						    pbox->x1, pbox->y1, pbox->x1 + xMask,
143609f0d67cSmacallan						    pbox->y1 + yMask, pbox->x2 - pbox->x1,
143709f0d67cSmacallan						    pbox->y2 - pbox->y1);
143809f0d67cSmacallan						pbox++;
143909f0d67cSmacallan					}
144009f0d67cSmacallan				} else {
144109f0d67cSmacallan					while(nbox--) {
144209f0d67cSmacallan						CrimeSubsequentCPUToScreenAlphaTexture(
144309f0d67cSmacallan						    infoRec->pScrn,
144429406fd8Smacallan						    pbox->x1, pbox->y1,
144529406fd8Smacallan						    pbox->x1 + xMask,
144629406fd8Smacallan						    pbox->y1 + yMask,
144729406fd8Smacallan						    pbox->x2 - pbox->x1,
144809f0d67cSmacallan						    pbox->y2 - pbox->y1);
144909f0d67cSmacallan						pbox++;
145009f0d67cSmacallan					}
1451e1ea03a3Smacallan				}
1452e1ea03a3Smacallan				SET_SYNC_FLAG(infoRec);
1453e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1454e1ea03a3Smacallan				DONE(CRIME_DEBUG_XRENDER);
1455e1ea03a3Smacallan				return;
1456e1ea03a3Smacallan			} else {
145729406fd8Smacallan				xf86Msg(X_ERROR, "unknown mask %x\n",
145829406fd8Smacallan				    pMask->format);
1459e1ea03a3Smacallan			}
1460e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1461e1ea03a3Smacallan			DONE(CRIME_DEBUG_XRENDER);
1462e1ea03a3Smacallan			return;
1463e1ea03a3Smacallan		} else {
1464e1ea03a3Smacallan			/* source isn't solid */
1465e1ea03a3Smacallan
1466e1ea03a3Smacallan			w = pSrc->pDrawable->width;
1467e1ea03a3Smacallan			h = pSrc->pDrawable->height;
1468e1ea03a3Smacallan
1469e1ea03a3Smacallan			if(pSrc->repeat)
1470e1ea03a3Smacallan				flags |= XAA_RENDER_REPEAT;
1471e1ea03a3Smacallan
1472e1ea03a3Smacallan			if (!miComputeCompositeRegion (&region, pSrc, pMask,
1473e1ea03a3Smacallan			    pDst, xSrc, ySrc, xMask, yMask, xDst, yDst,
1474e1ea03a3Smacallan			    width, height)) {
1475e1ea03a3Smacallan				return;
1476e1ea03a3Smacallan			}
1477e1ea03a3Smacallan
1478e1ea03a3Smacallan			nbox = REGION_NUM_RECTS(&region);
1479e1ea03a3Smacallan			pbox = REGION_RECTS(&region);
1480e1ea03a3Smacallan
1481e1ea03a3Smacallan			if(!nbox) {
1482e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1483e1ea03a3Smacallan				return;
1484e1ea03a3Smacallan			}
1485e1ea03a3Smacallan			CrimeSetupForCPUToScreenTextureMask(
1486e1ea03a3Smacallan			    infoRec->pScrn, op, pMask->format,
1487e1ea03a3Smacallan			    ((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr,
1488e1ea03a3Smacallan			    ((PixmapPtr)(pSrc->pDrawable))->devKind,
1489e1ea03a3Smacallan			    ((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr,
1490e1ea03a3Smacallan			    ((PixmapPtr)(pMask->pDrawable))->devKind,
1491e1ea03a3Smacallan			    w, h, flags);
1492e1ea03a3Smacallan
1493e1ea03a3Smacallan			xSrc -= xDst;
1494e1ea03a3Smacallan			ySrc -= yDst;
1495e1ea03a3Smacallan
1496e1ea03a3Smacallan			if (PICT_FORMAT_BPP(pMask->format) == 32) {
1497e1ea03a3Smacallan				while(nbox--) {
1498e1ea03a3Smacallan					CrimeSubsequentCPUToScreenTextureMask32(
1499e1ea03a3Smacallan					    infoRec->pScrn,
1500e1ea03a3Smacallan					    pbox->x1, pbox->y1,
1501e1ea03a3Smacallan					    pbox->x1 + xSrc, pbox->y1 + ySrc,
1502e1ea03a3Smacallan					    xMask, yMask,
150329406fd8Smacallan					    pbox->x2 - pbox->x1,
150429406fd8Smacallan					    pbox->y2 - pbox->y1);
1505e1ea03a3Smacallan					pbox++;
1506e1ea03a3Smacallan				}
1507e1ea03a3Smacallan			} else {
1508e1ea03a3Smacallan				while(nbox--) {
1509e1ea03a3Smacallan					CrimeSubsequentCPUToScreenTextureMask8(
1510e1ea03a3Smacallan					    infoRec->pScrn,
1511e1ea03a3Smacallan					    pbox->x1, pbox->y1, pbox->x1 + xSrc,
1512e1ea03a3Smacallan					    pbox->y1 + ySrc,
1513e1ea03a3Smacallan					    xMask, yMask,
1514e1ea03a3Smacallan					    pbox->x2 - pbox->x1,
1515e1ea03a3Smacallan					    pbox->y2 - pbox->y1);
1516e1ea03a3Smacallan					pbox++;
1517e1ea03a3Smacallan				}
1518e1ea03a3Smacallan			}
1519e1ea03a3Smacallan
1520e1ea03a3Smacallan			SET_SYNC_FLAG(infoRec);
1521e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1522e1ea03a3Smacallan			DONE(CRIME_DEBUG_XRENDER);
1523e1ea03a3Smacallan			return;
1524e1ea03a3Smacallan		}
1525e1ea03a3Smacallan	} else {	/* no mask */
1526e1ea03a3Smacallan		formats = infoRec->CPUToScreenTextureFormats;
1527e1ea03a3Smacallan
1528e1ea03a3Smacallan		w = pSrc->pDrawable->width;
1529e1ea03a3Smacallan		h = pSrc->pDrawable->height;
1530e1ea03a3Smacallan
1531e1ea03a3Smacallan		if(pSrc->repeat)
1532e1ea03a3Smacallan			flags |= XAA_RENDER_REPEAT;
1533e1ea03a3Smacallan
1534e1ea03a3Smacallan		while(*formats != pSrc->format) {
1535e1ea03a3Smacallan			if(!(*formats)) {
1536e1ea03a3Smacallan				xf86Msg(X_ERROR,
1537e1ea03a3Smacallan				    "%s: format %x not found\n",
1538e1ea03a3Smacallan				    __func__, pSrc->format);
1539e1ea03a3Smacallan				return;
1540e1ea03a3Smacallan			}
1541e1ea03a3Smacallan			formats++;
1542e1ea03a3Smacallan		}
1543e1ea03a3Smacallan
1544e1ea03a3Smacallan		if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
1545e1ea03a3Smacallan                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
1546e1ea03a3Smacallan                                   width, height)) {
1547e1ea03a3Smacallan			return;
1548e1ea03a3Smacallan		}
1549e1ea03a3Smacallan
1550e1ea03a3Smacallan		nbox = REGION_NUM_RECTS(&region);
1551e1ea03a3Smacallan		pbox = REGION_RECTS(&region);
1552e1ea03a3Smacallan
1553e1ea03a3Smacallan		if(!nbox) {
1554e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1555e1ea03a3Smacallan			return;
1556e1ea03a3Smacallan		}
1557e1ea03a3Smacallan
1558e1ea03a3Smacallan		CrimeSetupForCPUToScreenTexture(infoRec->pScrn,
1559e1ea03a3Smacallan			op, pSrc->format,
1560e1ea03a3Smacallan			((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr,
1561e1ea03a3Smacallan			((PixmapPtr)(pSrc->pDrawable))->devKind,
1562e1ea03a3Smacallan			w, h, flags);
1563e1ea03a3Smacallan
1564e1ea03a3Smacallan		xSrc -= xDst;
1565e1ea03a3Smacallan		ySrc -= yDst;
1566e1ea03a3Smacallan
1567e1ea03a3Smacallan		while(nbox--) {
1568e1ea03a3Smacallan			CrimeSubsequentCPUToScreenTexture(infoRec->pScrn,
1569e1ea03a3Smacallan			    pbox->x1, pbox->y1, pbox->x1 + xSrc,
1570e1ea03a3Smacallan			    pbox->y1 + ySrc, pbox->x2 - pbox->x1,
1571e1ea03a3Smacallan			    pbox->y2 - pbox->y1);
1572e1ea03a3Smacallan			pbox++;
1573e1ea03a3Smacallan		}
1574e1ea03a3Smacallan
1575e1ea03a3Smacallan		SET_SYNC_FLAG(infoRec);
1576e1ea03a3Smacallan		REGION_UNINIT(pScreen, &region);
1577e1ea03a3Smacallan		DONE(CRIME_DEBUG_XRENDER);
1578e1ea03a3Smacallan		return;
1579e1ea03a3Smacallan	}
1580e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: shouldn't be here\n", __func__);
1581e1ea03a3Smacallan}
1582e1ea03a3Smacallan
1583e1ea03a3Smacallanstatic void
1584e1ea03a3SmacallanCrimeDoScreenToScreenComposite(
1585e1ea03a3Smacallan   	CARD8      op,
1586e1ea03a3Smacallan        PicturePtr pSrc,
1587e1ea03a3Smacallan        PicturePtr pMask,
1588e1ea03a3Smacallan        PicturePtr pDst,
1589e1ea03a3Smacallan        INT16      xSrc,
1590e1ea03a3Smacallan        INT16      ySrc,
1591e1ea03a3Smacallan        INT16      xMask,
1592e1ea03a3Smacallan        INT16      yMask,
1593e1ea03a3Smacallan        INT16      xDst,
1594e1ea03a3Smacallan        INT16      yDst,
1595e1ea03a3Smacallan        CARD16     width,
1596e1ea03a3Smacallan        CARD16     height
1597e1ea03a3Smacallan)
1598e1ea03a3Smacallan{
1599e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1600e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1601e1ea03a3Smacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1602e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1603e1ea03a3Smacallan	RegionRec region;
1604e1ea03a3Smacallan	CARD32 *formats;
1605e1ea03a3Smacallan	int flags = 0;
1606e1ea03a3Smacallan	BoxPtr pbox;
1607e1ea03a3Smacallan	int nbox;
1608e1ea03a3Smacallan	int xs, ys, xd, yd, w, h;
160929406fd8Smacallanxf86Msg(X_ERROR, "CRIME screen-to-screen composite\n");
1610e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1611e1ea03a3Smacallan	if (pSrc->transform || (pMask && pMask->transform)) {
1612e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: mask?!\n", __func__);
1613e1ea03a3Smacallan		return;
1614e1ea03a3Smacallan	}
1615e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d\n", __func__, op);
1616e1ea03a3Smacallan	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) {
1617e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: alpha-map\n", __func__);
1618e1ea03a3Smacallan		return;
1619e1ea03a3Smacallan	}
1620e1ea03a3Smacallan
1621e1ea03a3Smacallan	xDst += pDst->pDrawable->x;
1622e1ea03a3Smacallan	yDst += pDst->pDrawable->y;
1623e1ea03a3Smacallan	xSrc += pSrc->pDrawable->x;
1624e1ea03a3Smacallan	ySrc += pSrc->pDrawable->y;
1625e1ea03a3Smacallan
1626e1ea03a3Smacallan	formats = infoRec->CPUToScreenTextureFormats;
1627e1ea03a3Smacallan
1628e1ea03a3Smacallan	w = pSrc->pDrawable->width;
1629e1ea03a3Smacallan	h = pSrc->pDrawable->height;
1630e1ea03a3Smacallan
1631e1ea03a3Smacallan	if(pSrc->repeat)
1632e1ea03a3Smacallan		flags |= XAA_RENDER_REPEAT;
1633e1ea03a3Smacallan
1634e1ea03a3Smacallan	while(*formats != pSrc->format) {
1635e1ea03a3Smacallan		if(!(*formats)) return;
1636e1ea03a3Smacallan		formats++;
1637e1ea03a3Smacallan	}
1638e1ea03a3Smacallan
1639e1ea03a3Smacallan	if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
1640e1ea03a3Smacallan	    xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
1641e1ea03a3Smacallan		return;
1642e1ea03a3Smacallan
1643e1ea03a3Smacallan	nbox = REGION_NUM_RECTS(&region);
1644e1ea03a3Smacallan	pbox = REGION_RECTS(&region);
1645e1ea03a3Smacallan
1646e1ea03a3Smacallan	if(!nbox) {
1647e1ea03a3Smacallan		REGION_UNINIT(pScreen, &region);
1648e1ea03a3Smacallan		return;
1649e1ea03a3Smacallan	}
1650e1ea03a3Smacallan
165126dcc2a3Smacallan	MAKE_ROOM(6);
1652e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
1653e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
165426dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
165526dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1656e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 1);
1657e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
1658e1ea03a3Smacallan	    DE_ALPHA_ADD |
1659e1ea03a3Smacallan	    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
1660e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
1661e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1662e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
1663e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
1664e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
1665e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
166626dcc2a3Smacallan	SYNC;
1667e1ea03a3Smacallan	xSrc -= xDst;
1668e1ea03a3Smacallan	ySrc -= yDst;
1669e1ea03a3Smacallan
1670e1ea03a3Smacallan	/* assume no overlap - might bite us in the arse at some point */
1671e1ea03a3Smacallan	while(nbox--) {
1672e1ea03a3Smacallan		xs = pbox->x1 + xSrc;
1673e1ea03a3Smacallan		ys = pbox->y1 + ySrc;
1674e1ea03a3Smacallan		xd = pbox->x1;
1675e1ea03a3Smacallan		yd = pbox->y1;
1676e1ea03a3Smacallan		w = pbox->x2 - pbox->x1;
1677e1ea03a3Smacallan		h = pbox->y2 - pbox->y1;
167826dcc2a3Smacallan		MAKE_ROOM(3);
1679e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC,(xs << 16) | (ys & 0xffff));
1680e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (xd << 16) | (yd & 0xffff));
1681e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
1682e1ea03a3Smacallan		    ((xd + w - 1) << 16) | ((yd + h - 1) & 0xffff));
1683e1ea03a3Smacallan		pbox++;
1684e1ea03a3Smacallan	}
1685e1ea03a3Smacallan
1686e1ea03a3Smacallan	SET_SYNC_FLAG(infoRec);
1687e1ea03a3Smacallan	REGION_UNINIT(pScreen, &region);
1688e1ea03a3Smacallan	return;
1689e1ea03a3Smacallan}
1690e1ea03a3Smacallan
1691e1ea03a3Smacallanstatic Bool
1692e1ea03a3SmacallanCrimeComposite(
1693e1ea03a3Smacallan   	CARD8      op,
1694e1ea03a3Smacallan        PicturePtr pSrc,
1695e1ea03a3Smacallan        PicturePtr pMask,
1696e1ea03a3Smacallan        PicturePtr pDst,
1697e1ea03a3Smacallan        INT16      xSrc,
1698e1ea03a3Smacallan        INT16      ySrc,
1699e1ea03a3Smacallan        INT16      xMask,
1700e1ea03a3Smacallan        INT16      yMask,
1701e1ea03a3Smacallan        INT16      xDst,
1702e1ea03a3Smacallan        INT16      yDst,
1703e1ea03a3Smacallan        CARD16     width,
1704e1ea03a3Smacallan        CARD16     height
1705e1ea03a3Smacallan)
1706e1ea03a3Smacallan{
1707e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1708e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1709e1ea03a3Smacallan
1710e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1711e1ea03a3Smacallan
171229406fd8Smacallan	if(!REGION_NUM_RECTS(pDst->pCompositeClip)) {
171329406fd8Smacallan#ifdef CRIME_DEBUG_LOUD
171429406fd8Smacallan		xf86Msg(X_ERROR, "%s: empty clip\n", __func__);
171529406fd8Smacallan#endif
1716e1ea03a3Smacallan		return TRUE;
171729406fd8Smacallan	}
1718e1ea03a3Smacallan
171929406fd8Smacallan	if(!infoRec->pScrn->vtSema) {
172029406fd8Smacallan#ifdef CRIME_DEBUG_LOUD
172129406fd8Smacallan		xf86Msg(X_ERROR, "%s: semaphore\n", __func__);
172229406fd8Smacallan#endif
1723e1ea03a3Smacallan		return FALSE;
172429406fd8Smacallan	}
1725e1ea03a3Smacallan
1726e1ea03a3Smacallan	if((pDst->pDrawable->type == DRAWABLE_WINDOW) ||
1727f282839bSmacallan	    IS_OFFSCREEN_PIXMAP(pDst->pDrawable) ||
1728f282839bSmacallan	    PIXMAP_IS_SCREEN(pDst->pDrawable)) {
1729e1ea03a3Smacallan		if ((pSrc->pDrawable->type == DRAWABLE_WINDOW) ||
1730f282839bSmacallan		    IS_OFFSCREEN_PIXMAP(pSrc->pDrawable) ||
1731f282839bSmacallan		    PIXMAP_IS_SCREEN(pSrc->pDrawable)) {
1732e1ea03a3Smacallan			/* screen-to-screen */
1733e1ea03a3Smacallan			CrimeDoScreenToScreenComposite(op, pSrc, pMask, pDst,
1734e1ea03a3Smacallan			    xSrc, ySrc, xMask, yMask,
1735e1ea03a3Smacallan			    xDst, yDst, width, height);
1736e1ea03a3Smacallan			return TRUE;
1737e1ea03a3Smacallan		} else {
1738e1ea03a3Smacallan			/* CPU-to-screen composite */
1739e1ea03a3Smacallan			if (op != PictOpOver)
1740e1ea03a3Smacallan				xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
1741e1ea03a3Smacallan			CrimeDoCPUToScreenComposite(op, pSrc, pMask, pDst,
1742e1ea03a3Smacallan			    xSrc, ySrc, xMask, yMask,
1743e1ea03a3Smacallan			    xDst, yDst, width, height);
1744e1ea03a3Smacallan			return TRUE;
1745e1ea03a3Smacallan		}
1746e1ea03a3Smacallan	} else {
1747e1ea03a3Smacallan		if ((pSrc->pDrawable->type == DRAWABLE_WINDOW) ||
174829406fd8Smacallan		    IS_OFFSCREEN_PIXMAP(pSrc->pDrawable) ||
174929406fd8Smacallan		    PIXMAP_IS_SCREEN(pSrc->pDrawable)) {
175029406fd8Smacallan			/*
175129406fd8Smacallan			 * screen-to-RAM
175229406fd8Smacallan			 * Download from screen, then composite
175329406fd8Smacallan			 */
1754e1ea03a3Smacallan			xf86Msg(X_ERROR, "%s: screen-to-RAM composite\n",
1755e1ea03a3Smacallan			   __func__);
1756e1ea03a3Smacallan			return TRUE;
1757e1ea03a3Smacallan		} else {
1758e1ea03a3Smacallan			/* RAM-to-RAM */
175929406fd8Smacallan#ifdef CRIME_DEBUG_LOUD
176029406fd8Smacallan			xf86Msg(X_ERROR, "%s: fallback %d, %08x %08x %08x\n",
176129406fd8Smacallan			    __func__, op, (uint32_t)pSrc->format,
176229406fd8Smacallan			    (uint32_t)pDst->format,
176329406fd8Smacallan			    pMask == NULL ? 0 : (uint32_t)pMask->format);
176429406fd8Smacallan#endif
176529406fd8Smacallan#if 0
1766e1ea03a3Smacallan			return FALSE;
176729406fd8Smacallan#else
176829406fd8Smacallan			return fbComposite(op, pSrc, pMask, pDst, xSrc, ySrc,
176929406fd8Smacallan			    xMask, yMask, xDst, yDst, width, height);
177029406fd8Smacallan#endif
1771e1ea03a3Smacallan		}
1772e1ea03a3Smacallan	}
1773e1ea03a3Smacallan	xf86Msg(X_ERROR, "composite fucked\n");
1774e1ea03a3Smacallan}
1775e1ea03a3Smacallan
177629406fd8Smacallanstatic Bool
177729406fd8SmacallanCrimeGlyphs (CARD8	op,
177829406fd8Smacallan	  PicturePtr	pSrc,
177929406fd8Smacallan	  PicturePtr	pDst,
178029406fd8Smacallan	  PictFormatPtr	maskFormat,
178129406fd8Smacallan	  INT16		xSrc,
178229406fd8Smacallan	  INT16		ySrc,
178329406fd8Smacallan	  int		nlist,
178429406fd8Smacallan	  GlyphListPtr	list,
178529406fd8Smacallan	  GlyphPtr	*glyphs)
178629406fd8Smacallan{
178729406fd8Smacallan	ScreenPtr	pScreen = pDst->pDrawable->pScreen;
178829406fd8Smacallan	PicturePtr	pPicture;
178929406fd8Smacallan	GlyphPtr	glyph;
179029406fd8Smacallan	int		xDst = list->xOff, yDst = list->yOff;
179129406fd8Smacallan	int		x = 0, y = 0, i, n;
179229406fd8Smacallan
179329406fd8Smacallan	while (nlist--)     {
179429406fd8Smacallan		x += list->xOff;
179529406fd8Smacallan		y += list->yOff;
179629406fd8Smacallan		n = list->len;
179729406fd8Smacallan		while (n--) {
179829406fd8Smacallan			glyph = *glyphs++;
179929406fd8Smacallan			pPicture = GlyphPicture (glyph)[pScreen->myNum];
180029406fd8Smacallan
180129406fd8Smacallan			CrimeComposite (op,
180229406fd8Smacallan				  pSrc,
180329406fd8Smacallan				  pPicture,
180429406fd8Smacallan				  pDst,
180529406fd8Smacallan				  xSrc + (x - glyph->info.x) - xDst,
180629406fd8Smacallan				  ySrc + (y - glyph->info.y) - yDst,
180729406fd8Smacallan				  0, 0,
180829406fd8Smacallan				  x - glyph->info.x,
180929406fd8Smacallan				  y - glyph->info.y,
181029406fd8Smacallan				  glyph->info.width,
181129406fd8Smacallan				  glyph->info.height);
181229406fd8Smacallan
181329406fd8Smacallan			x += glyph->info.xOff;
181429406fd8Smacallan			y += glyph->info.yOff;
181529406fd8Smacallan		}
181629406fd8Smacallan		list++;
181729406fd8Smacallan	}
181829406fd8Smacallan	return TRUE;
181929406fd8Smacallan}
182029406fd8Smacallan
1821e1ea03a3Smacallanstatic void
1822e1ea03a3SmacallanCrimePolyPoint(
1823e1ea03a3Smacallan    DrawablePtr pDraw,
1824e1ea03a3Smacallan    GCPtr pGC,
1825e1ea03a3Smacallan    int mode,
1826e1ea03a3Smacallan    int npt,
1827e1ea03a3Smacallan    xPoint *pptInit
1828e1ea03a3Smacallan)
1829e1ea03a3Smacallan{
1830e1ea03a3Smacallan	ScreenPtr pScreen = pDraw->pScreen;
1831e1ea03a3Smacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1832e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1833e1ea03a3Smacallan	BoxPtr pBox;
1834e1ea03a3Smacallan	xPoint *ppt, *pts;
1835e1ea03a3Smacallan	int x1, x2, y1, y2, x, y, i, nBox;
1836e1ea03a3Smacallan
1837e1ea03a3Smacallan	/* make pointlist origin relative */
1838e1ea03a3Smacallan	ppt = pptInit;
1839e1ea03a3Smacallan	if (mode == CoordModePrevious) {
1840e1ea03a3Smacallan		for (i = 0; i < npt; i++) {
1841e1ea03a3Smacallan			ppt++;
1842e1ea03a3Smacallan			ppt->x += (ppt-1)->x;
1843e1ea03a3Smacallan			ppt->y += (ppt-1)->y;
1844e1ea03a3Smacallan		}
1845e1ea03a3Smacallan	}
184626dcc2a3Smacallan	MAKE_ROOM(6);
184726dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
184826dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1849e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, pGC->fgPixel << 8);
1850e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, pGC->alu);
1851e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, pGC->planemask);
1852e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1853e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP);
1854e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE, DE_PRIM_POINT);
185526dcc2a3Smacallan	SYNC;
1856e1ea03a3Smacallan	for (nBox = REGION_NUM_RECTS (pGC->pCompositeClip),
1857e1ea03a3Smacallan	    pBox = REGION_RECTS (pGC->pCompositeClip);
1858e1ea03a3Smacallan	    nBox--; pBox++) {
1859e1ea03a3Smacallan
1860e1ea03a3Smacallan		pts = pptInit;
1861e1ea03a3Smacallan		for (i = 0; i < npt; i++) {
1862e1ea03a3Smacallan			x1 = pBox->x1;
1863e1ea03a3Smacallan			y1 = pBox->y1;
1864e1ea03a3Smacallan			x2 = pBox->x2;
1865e1ea03a3Smacallan			y2 = pBox->y2;
1866e1ea03a3Smacallan			x = pts->x + pDraw->x;
1867e1ea03a3Smacallan			y = pts->y + pDraw->y;
1868e1ea03a3Smacallan			if (x1 <= x && x < x2 && y1 <= y && y < y2) {
1869e1ea03a3Smacallan
187026dcc2a3Smacallan		 		MAKE_ROOM(1);
1871e1ea03a3Smacallan				WRITE4ST(CRIME_DE_X_VERTEX_0,
1872e1ea03a3Smacallan					(x << 16) | y);
1873e1ea03a3Smacallan			}
1874e1ea03a3Smacallan			pts++;
1875e1ea03a3Smacallan		}
1876e1ea03a3Smacallan	}
1877e1ea03a3Smacallan}
1878e1ea03a3Smacallan
1879e1ea03a3Smacallanstatic void
1880e1ea03a3SmacallanCrimeValidatePolyPoint(
1881e1ea03a3Smacallan   GCPtr         pGC,
1882e1ea03a3Smacallan   unsigned long changes,
1883e1ea03a3Smacallan   DrawablePtr   pDraw )
1884e1ea03a3Smacallan{
1885e1ea03a3Smacallan
1886e1ea03a3Smacallan	if ((pDraw->type == DRAWABLE_WINDOW) ||
1887e1ea03a3Smacallan	    IS_OFFSCREEN_PIXMAP(pDraw)) {
1888e1ea03a3Smacallan		pGC->ops->PolyPoint = CrimePolyPoint;
1889e1ea03a3Smacallan	} else
1890e1ea03a3Smacallan		xf86Msg(X_ERROR, "boo\n");
1891e1ea03a3Smacallan}
189234c4e112Smacallanstatic void
189334c4e112SmacallanCrimePolyArc(DrawablePtr pDraw,
189434c4e112Smacallan               GCPtr pGC,
189534c4e112Smacallan               int narcs,
189634c4e112Smacallan               xArc *parcs)
189734c4e112Smacallan{
189834c4e112Smacallan    xArc *arc;
189934c4e112Smacallan    BoxRec box;
190034c4e112Smacallan    int i, x2, y2;
190134c4e112Smacallan    RegionPtr cclip;
190234c4e112Smacallan
190334c4e112Smacallan    cclip = pGC->pCompositeClip;
190434c4e112Smacallan
190534c4e112Smacallan    if(!REGION_NUM_RECTS(cclip))
190634c4e112Smacallan	return;
190734c4e112Smacallan
190834c4e112Smacallan    for (arc = parcs, i = narcs; --i >= 0; arc++) {
190934c4e112Smacallan	if (miCanZeroArc(arc)) {
191034c4e112Smacallan	    box.x1 = arc->x + pDraw->x;
191134c4e112Smacallan	    box.y1 = arc->y + pDraw->y;
191234c4e112Smacallan 	    x2 = box.x1 + (int)arc->width + 1;
191334c4e112Smacallan 	    box.x2 = x2;
191434c4e112Smacallan 	    y2 = box.y1 + (int)arc->height + 1;
191534c4e112Smacallan 	    box.y2 = y2;
191634c4e112Smacallan 	    if ( (x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) &&
191734c4e112Smacallan 		    (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) )
191834c4e112Smacallan		miZeroPolyArc(pDraw, pGC, 1, arc);
191934c4e112Smacallan	}
192034c4e112Smacallan	else
192134c4e112Smacallan	    miPolyArc(pDraw, pGC, 1, arc);
192234c4e112Smacallan    }
192334c4e112Smacallan}
192434c4e112Smacallan
192534c4e112Smacallanstatic void
192634c4e112SmacallanCrimeValidatePolyArc(GCPtr pGC,
192734c4e112Smacallan                       unsigned long changes,
192834c4e112Smacallan                       DrawablePtr pDraw)
192934c4e112Smacallan{
193034c4e112Smacallan	if ((pDraw->type == DRAWABLE_WINDOW) ||
193134c4e112Smacallan	    IS_OFFSCREEN_PIXMAP(pDraw)) {
193234c4e112Smacallan		pGC->ops->PolyPoint = CrimePolyPoint;
193334c4e112Smacallan		/*pGC->ops->PolyArc = miPolyArc;*/
193434c4e112Smacallan		pGC->ops->PolyArc = CrimePolyArc;
193534c4e112Smacallan	} else
193634c4e112Smacallan	{
193734c4e112Smacallan		pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint;
193834c4e112Smacallan		pGC->ops->PolyArc = XAAGetFallbackOps()->PolyArc;
193934c4e112Smacallan	}
194034c4e112Smacallan}
1941e1ea03a3Smacallan
194226dcc2a3Smacallanstatic void copyRGBAtoARGB(uint32_t *dest, uint32_t *src, int len)
194326dcc2a3Smacallan{
194426dcc2a3Smacallan	while (len > 0) {
194526dcc2a3Smacallan		*dest = *src >> 8;
194626dcc2a3Smacallan		dest++;
194726dcc2a3Smacallan		src++;
194826dcc2a3Smacallan		len--;
194926dcc2a3Smacallan	}
195026dcc2a3Smacallan}
195126dcc2a3Smacallan
195234c4e112Smacallanstatic void
195334c4e112SmacallanCrimeReadPixmap(ScrnInfoPtr pScrn,
195434c4e112Smacallan                     int x,
195534c4e112Smacallan		     int y,
195634c4e112Smacallan		     int w,
195734c4e112Smacallan		     int h,
195834c4e112Smacallan		     unsigned char *dst,
195934c4e112Smacallan		     int dstwidth,
196034c4e112Smacallan		     int bpp,
196134c4e112Smacallan		     int depth)
196234c4e112Smacallan{
196326dcc2a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
196426dcc2a3Smacallan	int bufno = 0;
196526dcc2a3Smacallan	int nextbuf, i, len = w << 2;
196626dcc2a3Smacallan	int mx = x << 2, offset;
196726dcc2a3Smacallan
196826dcc2a3Smacallan	offset = mx & 0x3f;
196926dcc2a3Smacallan	mx &= ~0x3f;
197026dcc2a3Smacallan	len = (len + offset + 0x3f) & ~0x3f;
197126dcc2a3Smacallan
197226dcc2a3Smacallan	LOG(CRIME_DEBUG_IMAGEREAD);
197326dcc2a3Smacallan
197426dcc2a3Smacallan#ifdef CRIME_DEBUG_LOUD
197526dcc2a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d\n", __func__, x, y, w, h);
197626dcc2a3Smacallan#endif
197726dcc2a3Smacallan
197826dcc2a3Smacallan	MAKE_ROOM(3);
197926dcc2a3Smacallan
198026dcc2a3Smacallan	/*
198126dcc2a3Smacallan	 * apparently all MTE coordinates are in bytes, not pixels
198226dcc2a3Smacallan	 * also, the MTE has some crazy alignment requirements - if
198326dcc2a3Smacallan	 * we don't do as above the thing will deadlock sooner or later
198426dcc2a3Smacallan	 * We use the MTE here because I couldn't get the rendering engine
198526dcc2a3Smacallan	 * to actually transfer anything into a linear buffer. The other
198626dcc2a3Smacallan	 * way around works just fine though. Shouldn't make much of a
198726dcc2a3Smacallan	 * difference, transfer times should be dominated by copying
198826dcc2a3Smacallan	 * data in and out of the DMA buffer anyway
198926dcc2a3Smacallan	 */
199026dcc2a3Smacallan	WRITE4(CRIME_MTE_MODE, (MTE_TLB_LIN_A << MTE_DST_TLB_SHIFT) |
199126dcc2a3Smacallan			 (MTE_TLB_A << MTE_SRC_TLB_SHIFT) |
199226dcc2a3Smacallan			 (MTE_DEPTH_8 << MTE_DEPTH_SHIFT) |
199326dcc2a3Smacallan			 MTE_MODE_DST_ECC | MTE_MODE_COPY);
199426dcc2a3Smacallan	WRITE4(CRIME_MTE_SRC_Y_STEP, 1);
199526dcc2a3Smacallan	WRITE4(CRIME_MTE_DST_Y_STEP, 1);
199626dcc2a3Smacallan	SYNCMTE;
199726dcc2a3Smacallan	WRITE4(CRIME_MTE_SRC0, (mx << 16) | y);
199826dcc2a3Smacallan	WRITE4(CRIME_MTE_SRC1, ((mx + len) << 16) | y);
199926dcc2a3Smacallan	WRITE4(CRIME_MTE_DST0, (bufno << 13));
200026dcc2a3Smacallan	WRITE4ST(CRIME_MTE_DST1, (bufno << 13) + len);
200126dcc2a3Smacallan	for (i = y + 1; i < y + h; i++) {
200226dcc2a3Smacallan		nextbuf = (bufno + 1) & 7;
200326dcc2a3Smacallan		SYNCMTE;
200426dcc2a3Smacallan		WRITE4(CRIME_MTE_SRC0, (mx << 16) | i);
200526dcc2a3Smacallan		WRITE4(CRIME_MTE_SRC1, ((mx + len) << 16) | i);
200626dcc2a3Smacallan		WRITE4(CRIME_MTE_DST0, (nextbuf << 13));
200726dcc2a3Smacallan		WRITE4ST(CRIME_MTE_DST1, (nextbuf << 13) + len);
200826dcc2a3Smacallan		copyRGBAtoARGB((uint32_t *)dst,
200926dcc2a3Smacallan			       (uint32_t *)(fPtr->buffers[bufno] + offset), w);
201026dcc2a3Smacallan		dst += dstwidth;
201126dcc2a3Smacallan		bufno = nextbuf;
201226dcc2a3Smacallan	}
201326dcc2a3Smacallan	SYNCMTE;
201426dcc2a3Smacallan	copyRGBAtoARGB((uint32_t *)dst,
201526dcc2a3Smacallan		       (uint32_t *)(fPtr->buffers[bufno] + offset), w);
201626dcc2a3Smacallan	DONE(CRIME_DEBUG_IMAGEREAD);
201726dcc2a3Smacallan
201834c4e112Smacallan}
201929406fd8Smacallan
2020e1ea03a3Smacallanint
2021e1ea03a3SmacallanCrimeAccelInit(ScrnInfoPtr pScrn)
2022e1ea03a3Smacallan{
2023e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
2024e1ea03a3Smacallan	XAAInfoRecPtr pXAAInfo = fPtr->pXAA;
2025e1ea03a3Smacallan	int i;
2026e1ea03a3Smacallan
2027e1ea03a3Smacallan	for (i = 0; i < 0x1000; i++) regcache[i] = 0x12345678;
2028e1ea03a3Smacallan	LOG(CRIME_DEBUG_ALL);
2029e1ea03a3Smacallan	SYNC;
2030e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
2031e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
2032e1ea03a3Smacallan
2033e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_Y, 1);
203426dcc2a3Smacallan	WRITE4(CRIME_DE_XFER_STRD_DST, 4);
2035e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STRD_SRC, 1);
2036e1ea03a3Smacallan
2037e1ea03a3Smacallan	WRITE4(CRIME_MTE_BYTEMASK, 0xffffffff);
2038e1ea03a3Smacallan	WRITE4(CRIME_MTE_SRC_Y_STEP, 4);
2039e1ea03a3Smacallan	WRITE4(CRIME_MTE_DST_Y_STEP, 4);
204026dcc2a3Smacallan	SYNC;
2041e1ea03a3Smacallan
2042e1ea03a3Smacallan	/* blit the screen black */
2043e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
2044e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP);
2045e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, 3);
2046e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE, DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
2047e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, 0);
2048e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, 0);
2049e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
2050e1ea03a3Smacallan	    fPtr->info.width << 16 | fPtr->info.height);
2051e1ea03a3Smacallan	SYNC;
2052e1ea03a3Smacallan
205334c4e112Smacallan	pXAAInfo->Flags = /*LINEAR_FRAMEBUFFER |*/ PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
2054e1ea03a3Smacallan	pXAAInfo->maxOffPixWidth = fPtr->info.width;
2055e1ea03a3Smacallan	pXAAInfo->maxOffPixHeight = 2048;
2056e1ea03a3Smacallan
2057e1ea03a3Smacallan	/* Sync */
2058e1ea03a3Smacallan	pXAAInfo->Sync = CrimeSync;
2059e1ea03a3Smacallan
20608e5567ffSmacallan	CrimeDisableClipping(pScrn);
20618e5567ffSmacallan
2062e1ea03a3Smacallan	/* Screen-to-screen copy */
2063e1ea03a3Smacallan	pXAAInfo->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
2064e1ea03a3Smacallan	pXAAInfo->SetupForScreenToScreenCopy = CrimeSetupForScreenToScreenCopy;
2065e1ea03a3Smacallan	pXAAInfo->SubsequentScreenToScreenCopy =
2066e1ea03a3Smacallan		CrimeSubsequentScreenToScreenCopy;
2067e1ea03a3Smacallan
2068e1ea03a3Smacallan	/* rectangle fills */
2069e1ea03a3Smacallan	pXAAInfo->SetupForSolidFill = CrimeSetupForSolidFill;
2070e1ea03a3Smacallan	pXAAInfo->SubsequentSolidFillRect = CrimeSubsequentSolidFillRect;
2071e1ea03a3Smacallan
2072e1ea03a3Smacallan	/* image writes */
2073e1ea03a3Smacallan	pXAAInfo->ScanlineImageWriteFlags =
2074e1ea03a3Smacallan	    NO_TRANSPARENCY | LEFT_EDGE_CLIPPING |
2075e1ea03a3Smacallan	    LEFT_EDGE_CLIPPING_NEGATIVE_X |
2076e1ea03a3Smacallan	    CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD;
2077e1ea03a3Smacallan	pXAAInfo->NumScanlineImageWriteBuffers = 8;
2078e1ea03a3Smacallan	for (i = 0; i < 8; i++)
2079e1ea03a3Smacallan		fPtr->buffers[i] = fPtr->linear + (i * 8192);
2080e1ea03a3Smacallan	pXAAInfo->ScanlineImageWriteBuffers = fPtr->buffers;
2081e1ea03a3Smacallan	pXAAInfo->SetupForScanlineImageWrite =
2082e1ea03a3Smacallan		CrimeSetupForScanlineImageWrite;
2083e1ea03a3Smacallan	pXAAInfo->SubsequentScanlineImageWriteRect =
2084e1ea03a3Smacallan		CrimeSubsequentImageWriteRect;
2085e1ea03a3Smacallan	pXAAInfo->SubsequentImageWriteScanline =
2086e1ea03a3Smacallan		CrimeSubsequentImageWriteScanline;
2087e1ea03a3Smacallan
208834c4e112Smacallan	/* read pixmap */
208934c4e112Smacallan	pXAAInfo->ReadPixmapFlags = 0
209034c4e112Smacallan	                             | CPU_TRANSFER_PAD_DWORD
209134c4e112Smacallan				     ;
209234c4e112Smacallan	pXAAInfo->ReadPixmap = CrimeReadPixmap;
209334c4e112Smacallan
2094e1ea03a3Smacallan	/* colour expansion */
2095e1ea03a3Smacallan	pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags =
2096e1ea03a3Smacallan		LEFT_EDGE_CLIPPING;
2097e1ea03a3Smacallan	pXAAInfo->NumScanlineColorExpandBuffers = 1;
2098e1ea03a3Smacallan	fPtr->expandbuffers[0] = (uint8_t *)fPtr->expand;
2099e1ea03a3Smacallan	pXAAInfo->ScanlineColorExpandBuffers = (void *)&fPtr->expandbuffers;
2100e1ea03a3Smacallan	pXAAInfo->SetupForScanlineCPUToScreenColorExpandFill =
2101e1ea03a3Smacallan		CrimeSetupForCPUToScreenColorExpandFill;
2102e1ea03a3Smacallan	pXAAInfo->SubsequentScanlineCPUToScreenColorExpandFill =
2103e1ea03a3Smacallan		CrimeSubsequentScanlineCPUToScreenColorExpandFill;
2104e1ea03a3Smacallan	pXAAInfo->SubsequentColorExpandScanline =
2105e1ea03a3Smacallan		CrimeSubsequentColorExpandScanline;
2106e1ea03a3Smacallan
2107e1ea03a3Smacallan	/* clipping */
2108e1ea03a3Smacallan	pXAAInfo->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
21097a6652bbSmacallan		HARDWARE_CLIP_SOLID_FILL |
21107a6652bbSmacallan		HARDWARE_CLIP_SOLID_LINE |
21115b2650b9Smacallan		HARDWARE_CLIP_MONO_8x8_FILL | HARDWARE_CLIP_DASHED_LINE;
2112e1ea03a3Smacallan	pXAAInfo->SetClippingRectangle = CrimeSetClippingRectangle;
2113e1ea03a3Smacallan	pXAAInfo->DisableClipping = CrimeDisableClipping;
2114e1ea03a3Smacallan
2115e1ea03a3Smacallan	/* solid line drawing */
2116e1ea03a3Smacallan	pXAAInfo->SetupForSolidLine = CrimeSetupForSolidLine;
2117e1ea03a3Smacallan	pXAAInfo->SubsequentSolidTwoPointLine =
2118e1ea03a3Smacallan	    CrimeSubsequentSolidTwoPointLine;
21195b2650b9Smacallan	pXAAInfo->SolidLineFlags = 0;
2120e1ea03a3Smacallan
2121e1ea03a3Smacallan	/* dashed line drawing */
2122e1ea03a3Smacallan	pXAAInfo->SetupForDashedLine = CrimeSetupForDashedLine;
2123e1ea03a3Smacallan	pXAAInfo->SubsequentDashedTwoPointLine =
2124e1ea03a3Smacallan	    CrimeSubsequentDashedTwoPointLine;
2125e1ea03a3Smacallan	pXAAInfo->DashedLineFlags = LINE_PATTERN_MSBFIRST_MSBJUSTIFIED;
2126e1ea03a3Smacallan	pXAAInfo->DashPatternMaxLength = 32;
2127e1ea03a3Smacallan
21285b2650b9Smacallan	/* mono pattern fills */
21295b2650b9Smacallan	pXAAInfo->Mono8x8PatternFillFlags = HARDWARE_PATTERN_PROGRAMMED_BITS |
21305b2650b9Smacallan	    HARDWARE_PATTERN_PROGRAMMED_ORIGIN | BIT_ORDER_IN_BYTE_MSBFIRST;
21315b2650b9Smacallan	pXAAInfo->SetupForMono8x8PatternFill = CrimeSetupForMono8x8PatternFill;
21325b2650b9Smacallan	pXAAInfo->SubsequentMono8x8PatternFillRect =
21335b2650b9Smacallan	    CrimeSubsequentMono8x8PatternFillRect;
21345b2650b9Smacallan
2135e1ea03a3Smacallan	/* XRender acceleration */
2136e1ea03a3Smacallan#ifdef RENDER
2137e1ea03a3Smacallan	pXAAInfo->CPUToScreenAlphaTextureFlags = 0;
2138e1ea03a3Smacallan	pXAAInfo->SetupForCPUToScreenAlphaTexture =
2139e1ea03a3Smacallan	    CrimeSetupForCPUToScreenAlphaTexture;
2140e1ea03a3Smacallan	pXAAInfo->SubsequentCPUToScreenAlphaTexture =
2141e1ea03a3Smacallan	    CrimeSubsequentCPUToScreenAlphaTexture;
2142e1ea03a3Smacallan	pXAAInfo->CPUToScreenAlphaTextureFormats = CrimeAlphaTextureFormats;
2143e1ea03a3Smacallan
2144e1ea03a3Smacallan	pXAAInfo->SetupForCPUToScreenTexture = CrimeSetupForCPUToScreenTexture;
2145e1ea03a3Smacallan	pXAAInfo->SubsequentCPUToScreenTexture =
2146e1ea03a3Smacallan	    CrimeSubsequentCPUToScreenTexture;
2147e1ea03a3Smacallan	pXAAInfo->CPUToScreenTextureFlags = 0;
2148e1ea03a3Smacallan	pXAAInfo->CPUToScreenTextureFormats = CrimeTextureFormats;
2149e1ea03a3Smacallan	pXAAInfo->Composite = CrimeComposite;
215029406fd8Smacallan	pXAAInfo->Glyphs = CrimeGlyphs;
2151e1ea03a3Smacallan#endif
2152e1ea03a3Smacallan	pXAAInfo->ValidatePolyPoint = CrimeValidatePolyPoint;
2153e1ea03a3Smacallan	pXAAInfo->PolyPointMask = GCFunction;
215434c4e112Smacallan	pXAAInfo->ValidatePolyArc = CrimeValidatePolyArc;
215534c4e112Smacallan	pXAAInfo->PolyArcMask = GCFunction | GCLineWidth;
2156e1ea03a3Smacallan
2157e1ea03a3Smacallan	return -1;
2158e1ea03a3Smacallan}
2159