crime_accel.c revision 5b2650b9
15b2650b9Smacallan/* $NetBSD: crime_accel.c,v 1.6 2009/03/31 15:57:35 macallan Exp $ */
2e1ea03a3Smacallan/*
3e1ea03a3Smacallan * Copyright (c) 2008 Michael Lorenz
4e1ea03a3Smacallan * All rights reserved.
5e1ea03a3Smacallan *
6e1ea03a3Smacallan * Redistribution and use in source and binary forms, with or without
7e1ea03a3Smacallan * modification, are permitted provided that the following conditions
8e1ea03a3Smacallan * are met:
9e1ea03a3Smacallan *
10e1ea03a3Smacallan *    - Redistributions of source code must retain the above copyright
11e1ea03a3Smacallan *      notice, this list of conditions and the following disclaimer.
12e1ea03a3Smacallan *    - Redistributions in binary form must reproduce the above
13e1ea03a3Smacallan *      copyright notice, this list of conditions and the following
14e1ea03a3Smacallan *      disclaimer in the documentation and/or other materials provided
15e1ea03a3Smacallan *      with the distribution.
16e1ea03a3Smacallan *
17e1ea03a3Smacallan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18e1ea03a3Smacallan * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19e1ea03a3Smacallan * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20e1ea03a3Smacallan * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21e1ea03a3Smacallan * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22e1ea03a3Smacallan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23e1ea03a3Smacallan * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24e1ea03a3Smacallan * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25e1ea03a3Smacallan * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26e1ea03a3Smacallan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27e1ea03a3Smacallan * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28e1ea03a3Smacallan * POSSIBILITY OF SUCH DAMAGE.
29e1ea03a3Smacallan *
30e1ea03a3Smacallan */
31e1ea03a3Smacallan
32e1ea03a3Smacallan/* a driver for the CRIME rendering engine foundin SGI O2 workstations */
33e1ea03a3Smacallan
34e1ea03a3Smacallan#include "crime.h"
35e1ea03a3Smacallan#include "picturestr.h"
36e1ea03a3Smacallan#include "xaalocal.h"
37e1ea03a3Smacallan
38e1ea03a3Smacallanuint32_t regcache[0x1000];
39e1ea03a3Smacallan
40e1ea03a3Smacallan#define CRIMEREG(p) (volatile uint32_t *)(fPtr->engine + p)
41e1ea03a3Smacallan/*#define WBFLUSH { volatile uint32_t boo = *CRIMEREG(0x4000); }*/
42e1ea03a3Smacallan#define WBFLUSH __asm__ ("nop; sync;")
43e1ea03a3Smacallan#if 0
44e1ea03a3Smacallan#define WRITE4(r, v) {if (regcache[r >> 2] != v) { \
45e1ea03a3Smacallan			*CRIMEREG(r) = v; \
46e1ea03a3Smacallan			regcache[r >> 2] = v; } }
47e1ea03a3Smacallan#else
48e1ea03a3Smacallan#define WRITE4(r, v) { *CRIMEREG(r) = v; }
49e1ea03a3Smacallan#endif
50e1ea03a3Smacallan#define WRITE4ST(r, v) {WBFLUSH; *CRIMEREG(r + CRIME_DE_START) = v; WBFLUSH;}
51e1ea03a3Smacallan#ifdef DEBUG
52e1ea03a3Smacallan#define SYNC { int bail = 0; do {bail++; } \
53e1ea03a3Smacallan          while(((*CRIMEREG(0x4000) & CRIME_DE_IDLE) == 0) && (bail < 10000000)); \
54e1ea03a3Smacallan          if (bail == 10000000) { \
55e1ea03a3Smacallan          	xf86Msg(X_ERROR, "sync timeout\n"); \
56e1ea03a3Smacallan          	WRITE4ST(CRIME_MTE_FLUSH, 0); \
57e1ea03a3Smacallan          	WRITE4ST(CRIME_DE_FLUSH, 0); \
58e1ea03a3Smacallan          } \
59e1ea03a3Smacallan        }
60e1ea03a3Smacallan#else
61e1ea03a3Smacallan#define SYNC do {} while ((*CRIMEREG(0x4000) & CRIME_DE_IDLE) == 0)
6226dcc2a3Smacallan#define SYNCMTE do {} while ((*CRIMEREG(0x4000) & CRIME_DE_MTE_IDLE) == 0)
63e1ea03a3Smacallan#endif
6426dcc2a3Smacallan#define MAKE_ROOM(x) do {} while ((16 - \
6526dcc2a3Smacallan				   CRIME_PIPE_LEVEL(*CRIMEREG(0x4000))) < x);
66e1ea03a3Smacallan
67e1ea03a3SmacallanCARD32 CrimeAlphaTextureFormats[] = {PICT_a8, 0};
68e1ea03a3SmacallanCARD32 CrimeTextureFormats[] = {PICT_a8b8g8r8, PICT_a8r8g8b8, 0};
69e1ea03a3Smacallan
70e1ea03a3Smacallanvoid
71e1ea03a3SmacallanCrimeSync(ScrnInfoPtr pScrn)
72e1ea03a3Smacallan{
73e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
74e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
75e1ea03a3Smacallan	volatile uint32_t *status = CRIMEREG(CRIME_DE_STATUS);
76e1ea03a3Smacallan
77e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %08x\n", __func__, *status);
78e1ea03a3Smacallan#endif
79e1ea03a3Smacallan	LOG(CRIME_DEBUG_SYNC);
80e1ea03a3Smacallan	SYNC;
81e1ea03a3Smacallan}
82e1ea03a3Smacallan
83e1ea03a3Smacallanstatic void
84e1ea03a3SmacallanCrimeSetupForScreenToScreenCopy(
85e1ea03a3Smacallan	ScrnInfoPtr  pScrn,
86e1ea03a3Smacallan	int          xdir,
87e1ea03a3Smacallan	int          ydir,
88e1ea03a3Smacallan	int          rop,
89e1ea03a3Smacallan	unsigned int planemask,
90e1ea03a3Smacallan	int          TransparencyColour
91e1ea03a3Smacallan)
92e1ea03a3Smacallan{
93e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
94e1ea03a3Smacallan
95e1ea03a3Smacallan	LOG(CRIME_DEBUG_BITBLT);
9626dcc2a3Smacallan	MAKE_ROOM(9);
97e1ea03a3Smacallan#if 0
98e1ea03a3Smacallan	if ((rop == GXcopy) && (planemask == 0xffffffff) && (xdir > 0)) {
99e1ea03a3Smacallan		/* use the MTE */
100e1ea03a3Smacallan		WRITE4(CRIME_MTE_MODE, MTE_MODE_DST_ECC |
101e1ea03a3Smacallan		    MTE_TLB_A << MTE_DST_TLB_SHIFT |
102e1ea03a3Smacallan		    MTE_TLB_A << MTE_SRC_TLB_SHIFT |
103e1ea03a3Smacallan		    MTE_DEPTH_32 << MTE_DEPTH_SHIFT |
104e1ea03a3Smacallan		    MTE_MODE_COPY);
105e1ea03a3Smacallan		fPtr->use_mte = 1;
106e1ea03a3Smacallan		if (ydir > 0) {
107e1ea03a3Smacallan			WRITE4(CRIME_MTE_DST_Y_STEP, 1);
108e1ea03a3Smacallan			WRITE4(CRIME_MTE_SRC_Y_STEP, 1);
109e1ea03a3Smacallan		} else {
110e1ea03a3Smacallan			WRITE4(CRIME_MTE_DST_Y_STEP, -1);
111e1ea03a3Smacallan			WRITE4(CRIME_MTE_SRC_Y_STEP, -1);
112e1ea03a3Smacallan		}
113e1ea03a3Smacallan	} else
114e1ea03a3Smacallan#endif
115e1ea03a3Smacallan		fPtr->use_mte = 0;
116e1ea03a3Smacallan
117e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 1);
118e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
119e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
120e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
121e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
122e1ea03a3Smacallan	    DE_DRAWMODE_ROP | DE_DRAWMODE_XFER_EN);
123e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
124e1ea03a3Smacallan		    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
12526dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
12626dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
127e1ea03a3Smacallan	fPtr->xdir = xdir;
128e1ea03a3Smacallan	fPtr->ydir = ydir;
12926dcc2a3Smacallan	SYNC;
130e1ea03a3Smacallan	DONE(CRIME_DEBUG_BITBLT);
131e1ea03a3Smacallan}
132e1ea03a3Smacallan
133e1ea03a3Smacallanstatic void
134e1ea03a3SmacallanCrimeSubsequentScreenToScreenCopy
135e1ea03a3Smacallan(
136e1ea03a3Smacallan	ScrnInfoPtr pScrn,
137e1ea03a3Smacallan	int         xSrc,
138e1ea03a3Smacallan	int         ySrc,
139e1ea03a3Smacallan	int         xDst,
140e1ea03a3Smacallan	int         yDst,
141e1ea03a3Smacallan	int         w,
142e1ea03a3Smacallan	int         h
143e1ea03a3Smacallan)
144e1ea03a3Smacallan{
145e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
146e1ea03a3Smacallan	uint32_t prim = DE_PRIM_RECTANGLE;
147e1ea03a3Smacallan	volatile uint32_t reg, oreg;
148e1ea03a3Smacallan	uint32_t rxa, rya, rxe, rye, rxs, rys, rxd, ryd, rxde, ryde;
149e1ea03a3Smacallan
150e1ea03a3Smacallan	LOG(CRIME_DEBUG_BITBLT);
151e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
152e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d, %d; %d x %d -> %d %d\n", __func__,
153e1ea03a3Smacallan	    xSrc, ySrc, w, h, xDst, yDst);
154e1ea03a3Smacallan#endif
155e1ea03a3Smacallan
156e1ea03a3Smacallan	if ((fPtr->use_mte) && (w > 64) && ((w & 3) == 0) && ((xSrc & 3) == 0) && ((xDst & 3) == 0)) {
157e1ea03a3Smacallan		if (fPtr->ydir == -1) {
158e1ea03a3Smacallan			/* bottom to top */
159e1ea03a3Smacallan			rye = ySrc;
160e1ea03a3Smacallan			rya = ySrc + h - 1;
161e1ea03a3Smacallan			ryd = yDst + h - 1;
162e1ea03a3Smacallan			ryde = yDst;
163e1ea03a3Smacallan		} else {
164e1ea03a3Smacallan			/* top to bottom */
165e1ea03a3Smacallan			rye = ySrc + h - 1;
166e1ea03a3Smacallan			rya = ySrc;
167e1ea03a3Smacallan			ryd = yDst;
168e1ea03a3Smacallan			ryde = yDst + h - 1;
169e1ea03a3Smacallan		}
170e1ea03a3Smacallan		rxa = xSrc << 2;
171e1ea03a3Smacallan		rxe = ((xSrc + w) << 2) - 1;
172e1ea03a3Smacallan		rxd = xDst << 2;
173e1ea03a3Smacallan		rxde = ((xDst + w) << 2) - 1;
174e1ea03a3Smacallan		oreg = *CRIMEREG(0x4000);
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		reg = *CRIMEREG(0x4000);
181e1ea03a3Smacallan
182e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
183e1ea03a3Smacallan		xf86Msg(X_ERROR, "reg: %08x %08x\n", oreg, reg);
184e1ea03a3Smacallan#endif
185e1ea03a3Smacallan	} else {
186e1ea03a3Smacallan		if (fPtr->xdir == -1) {
187e1ea03a3Smacallan			prim |= DE_PRIM_RL;
188e1ea03a3Smacallan			rxe = xDst;
189e1ea03a3Smacallan			rxa = xDst + w - 1;
190e1ea03a3Smacallan			rxs = xSrc + w - 1;
191e1ea03a3Smacallan		} else {
192e1ea03a3Smacallan			prim |= DE_PRIM_LR;
193e1ea03a3Smacallan			rxe = xDst + w - 1;
194e1ea03a3Smacallan			rxa = xDst;
195e1ea03a3Smacallan			rxs = xSrc;
196e1ea03a3Smacallan		}
197e1ea03a3Smacallan		if (fPtr->ydir == -1) {
198e1ea03a3Smacallan			prim |= DE_PRIM_BT;
199e1ea03a3Smacallan			rye = yDst;
200e1ea03a3Smacallan			rya = yDst + h - 1;
201e1ea03a3Smacallan			rys = ySrc + h - 1;
202e1ea03a3Smacallan		} else {
203e1ea03a3Smacallan			prim |= DE_PRIM_TB;
204e1ea03a3Smacallan			rye = yDst + h - 1;
205e1ea03a3Smacallan			rya = yDst;
206e1ea03a3Smacallan			rys = ySrc;
207e1ea03a3Smacallan		}
208e1ea03a3Smacallan
20926dcc2a3Smacallan		MAKE_ROOM(4);
210e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE, prim);
211e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC,(rxs << 16) | (rys & 0xffff));
212e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (rxa << 16) | (rya & 0xffff));
213e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1, (rxe << 16) | (rye & 0xffff));
214e1ea03a3Smacallan	}
215e1ea03a3Smacallan	DONE(CRIME_DEBUG_BITBLT);
216e1ea03a3Smacallan}
217e1ea03a3Smacallan
218e1ea03a3Smacallanstatic void
219e1ea03a3SmacallanCrimeSetupForSolidFill
220e1ea03a3Smacallan(
221e1ea03a3Smacallan    ScrnInfoPtr  pScrn,
222e1ea03a3Smacallan    int          colour,
223e1ea03a3Smacallan    int          rop,
224e1ea03a3Smacallan    unsigned int planemask
225e1ea03a3Smacallan)
226e1ea03a3Smacallan{
227e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
228e1ea03a3Smacallan	int i;
229e1ea03a3Smacallan
230e1ea03a3Smacallan	LOG(CRIME_DEBUG_RECTFILL);
23126dcc2a3Smacallan	MAKE_ROOM(7);
232e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
233e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
234e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, colour << 8);
235e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
23693351543Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP |
23793351543Smacallan	    DE_DRAWMODE_SCISSOR_EN);
238e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
239e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
24026dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
24126dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
24226dcc2a3Smacallan	SYNC;
243e1ea03a3Smacallan	DONE(CRIME_DEBUG_RECTFILL);
244e1ea03a3Smacallan}
245e1ea03a3Smacallan
246e1ea03a3Smacallanstatic void
247e1ea03a3SmacallanCrimeSubsequentSolidFillRect
248e1ea03a3Smacallan(
249e1ea03a3Smacallan    ScrnInfoPtr pScrn,
250e1ea03a3Smacallan    int         x,
251e1ea03a3Smacallan    int         y,
252e1ea03a3Smacallan    int         w,
253e1ea03a3Smacallan    int         h
254e1ea03a3Smacallan)
255e1ea03a3Smacallan{
256e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
257e1ea03a3Smacallan
258e1ea03a3Smacallan	LOG(CRIME_DEBUG_RECTFILL);
25926dcc2a3Smacallan	MAKE_ROOM(2);
260e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x << 16) | (y & 0xffff));
261e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
262e1ea03a3Smacallan	    ((x + w - 1) << 16) | ((y + h - 1) & 0xffff));
263e1ea03a3Smacallan	DONE(CRIME_DEBUG_RECTFILL);
264e1ea03a3Smacallan}
265e1ea03a3Smacallan
2665b2650b9Smacallanstatic void
2675b2650b9SmacallanCrimeSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty,
2685b2650b9Smacallan        int fg, int bg, int rop, unsigned int planemask)
2695b2650b9Smacallan{
2705b2650b9Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
2715b2650b9Smacallan	uint32_t pat;
2725b2650b9Smacallan
2735b2650b9Smacallan	LOG(CRIME_DEBUG_RECTFILL);
2745b2650b9Smacallan	MAKE_ROOM(7);
2755b2650b9Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
2765b2650b9Smacallan	WRITE4(CRIME_DE_ROP, rop);
2775b2650b9Smacallan	WRITE4(CRIME_DE_FG, fg << 8);
2785b2650b9Smacallan	if (bg == -1) {
2795b2650b9Smacallan		WRITE4(CRIME_DE_DRAWMODE,
2805b2650b9Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
2815b2650b9Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_POLY_STIP |
2825b2650b9Smacallan		    DE_DRAWMODE_SCISSOR_EN);
2835b2650b9Smacallan	} else {
2845b2650b9Smacallan		WRITE4(CRIME_DE_BG, bg << 8);
2855b2650b9Smacallan		WRITE4(CRIME_DE_DRAWMODE,
2865b2650b9Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
2875b2650b9Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_POLY_STIP |
2885b2650b9Smacallan		    DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_SCISSOR_EN);
2895b2650b9Smacallan	}
2905b2650b9Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
2915b2650b9Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
2925b2650b9Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
2935b2650b9Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
2945b2650b9Smacallan
2955b2650b9Smacallan	/*
2965b2650b9Smacallan	 * we need to store the pattern so we can just hammer it into the
2975b2650b9Smacallan	 * stipple register later on
2985b2650b9Smacallan	 */
2995b2650b9Smacallan	pat = patx & 0xff000000;
3005b2650b9Smacallan	pat |= pat >> 8;
3015b2650b9Smacallan	fPtr->pattern[0] = pat | (pat >> 16);
3025b2650b9Smacallan	pat = patx & 0x00ff0000;
3035b2650b9Smacallan	pat |= pat << 8;
3045b2650b9Smacallan	fPtr->pattern[1] = pat | (pat >> 16);
3055b2650b9Smacallan	pat = patx & 0x0000ff00;
3065b2650b9Smacallan	pat |= pat >> 8;
3075b2650b9Smacallan	fPtr->pattern[2] = pat | (pat << 16);
3085b2650b9Smacallan	pat = patx & 0x000000ff;
3095b2650b9Smacallan	pat |= pat << 8;
3105b2650b9Smacallan	fPtr->pattern[3] = pat | (pat << 16);
3115b2650b9Smacallan
3125b2650b9Smacallan	pat = paty & 0xff000000;
3135b2650b9Smacallan	pat |= pat >> 8;
3145b2650b9Smacallan	fPtr->pattern[4] = pat | (pat >> 16);
3155b2650b9Smacallan	pat = paty & 0x00ff0000;
3165b2650b9Smacallan	pat |= pat << 8;
3175b2650b9Smacallan	fPtr->pattern[5] = pat | (pat >> 16);
3185b2650b9Smacallan	pat = paty & 0x0000ff00;
3195b2650b9Smacallan	pat |= pat >> 8;
3205b2650b9Smacallan	fPtr->pattern[6] = pat | (pat << 16);
3215b2650b9Smacallan	pat = paty & 0x000000ff;
3225b2650b9Smacallan	pat |= pat << 8;
3235b2650b9Smacallan	fPtr->pattern[7] = pat | (pat << 16);
3245b2650b9Smacallan	SYNC;
3255b2650b9Smacallan	DONE(CRIME_DEBUG_RECTFILL);
3265b2650b9Smacallan}
3275b2650b9Smacallan
3285b2650b9Smacallanstatic void
3295b2650b9SmacallanCrimeSubsequentMono8x8PatternFillRect( ScrnInfoPtr pScrn,
3305b2650b9Smacallan        	int patx, int paty, int x, int y, int w, int h)
3315b2650b9Smacallan{
3325b2650b9Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
3335b2650b9Smacallan	int i, pat;
3345b2650b9Smacallan
3355b2650b9Smacallan	LOG(CRIME_DEBUG_RECTFILL);
3365b2650b9Smacallan
3375b2650b9Smacallan	/* first setup the stipple stuff */
3385b2650b9Smacallan
3395b2650b9Smacallan	MAKE_ROOM(1);
3405b2650b9Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, 0x001f0000 | (patx << 24));
3415b2650b9Smacallan	pat = paty;
3425b2650b9Smacallan
3435b2650b9Smacallan	for (i = 0; i < h; i++) {
3445b2650b9Smacallan		MAKE_ROOM(3);
3455b2650b9Smacallan		WRITE4(CRIME_DE_STIPPLE_PAT, fPtr->pattern[pat]);
3465b2650b9Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (x << 16) | ((y + i) & 0xffff));
3475b2650b9Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
3485b2650b9Smacallan		    ((x + w - 1) << 16) | ((y + i) & 0xffff));
3495b2650b9Smacallan		pat = (pat + 1) & 7;
3505b2650b9Smacallan	}
3515b2650b9Smacallan	DONE(CRIME_DEBUG_RECTFILL);
3525b2650b9Smacallan}
3535b2650b9Smacallan
3545b2650b9Smacallanstatic void
355e1ea03a3SmacallanCrimeSetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
356e1ea03a3Smacallan                                unsigned int planemask, int trans_color,
357e1ea03a3Smacallan                                int bpp, int depth)
358e1ea03a3Smacallan{
359e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
360e1ea03a3Smacallan
361e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
362e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
363e1ea03a3Smacallan	if ((bpp == 24) || (depth == 24))
364e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d \n", __func__, bpp, depth);
365e1ea03a3Smacallan#endif
36626dcc2a3Smacallan	MAKE_ROOM(7);
367e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
368e1ea03a3Smacallan			    DE_MODE_TYPE_RGB | DE_MODE_PIXDEPTH_32);
36926dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
37026dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
371e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
372e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
373e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
374e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
375e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP |
376e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
377e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
378e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
37926dcc2a3Smacallan	SYNC;
380e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
381e1ea03a3Smacallan}
382e1ea03a3Smacallan
3835b2650b9Smacallanstatic void
384e1ea03a3SmacallanCrimeSubsequentImageWriteRect(ScrnInfoPtr pScrn,
385e1ea03a3Smacallan                                int x, int y, int w, int h, int skipleft)
386e1ea03a3Smacallan{
387e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
388e1ea03a3Smacallan
389e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
390e1ea03a3Smacallan
391e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
392e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d\n", __func__, x, y, w, h);
393e1ea03a3Smacallan#endif
394e1ea03a3Smacallan
395e1ea03a3Smacallan	fPtr->start = skipleft;
396e1ea03a3Smacallan	x += skipleft;
397e1ea03a3Smacallan	w -= skipleft;
398e1ea03a3Smacallan	if (x < 0) {
399e1ea03a3Smacallan		fPtr->ux = 0;
400e1ea03a3Smacallan		w += x;
401e1ea03a3Smacallan		fPtr->start -= x;
402e1ea03a3Smacallan	} else {
403e1ea03a3Smacallan		fPtr->ux = x;
404e1ea03a3Smacallan	}
405e1ea03a3Smacallan	fPtr->uy = y;
406e1ea03a3Smacallan	fPtr->uw = w;
407e1ea03a3Smacallan	fPtr->uh = h;
408e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
409e1ea03a3Smacallan}
410e1ea03a3Smacallan
4115b2650b9Smacallanstatic void
412e1ea03a3SmacallanCrimeSubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
413e1ea03a3Smacallan{
414e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
415e1ea03a3Smacallan
416e1ea03a3Smacallan	LOG(CRIME_DEBUG_IMAGEWRITE);
41726dcc2a3Smacallan	/*
41826dcc2a3Smacallan	 * we need to sync here, otherwise we might queue up more copy
41926dcc2a3Smacallan	 * commands than we have buffers
42026dcc2a3Smacallan	 */
42134c4e112Smacallan	SYNC;
422e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_ADDR_SRC, (bufno << 13)  + (fPtr->start << 2));
423e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (fPtr->ux << 16) | fPtr->uy);
424e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
425e1ea03a3Smacallan		((fPtr->ux + fPtr->uw - 1) << 16) | (fPtr->uy));
426e1ea03a3Smacallan	fPtr->uy++;
427e1ea03a3Smacallan	DONE(CRIME_DEBUG_IMAGEWRITE);
428e1ea03a3Smacallan}
429e1ea03a3Smacallan
430e1ea03a3Smacallanstatic void
431e1ea03a3SmacallanCrimeSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
432e1ea03a3Smacallan        		int fg, int bg,
433e1ea03a3Smacallan			int rop,
434e1ea03a3Smacallan			unsigned int planemask)
435e1ea03a3Smacallan{
436e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
437e1ea03a3Smacallan
438e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
43926dcc2a3Smacallan	MAKE_ROOM(7);
44026dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
44126dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
442e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
443e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
444e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, fg << 8);
445e1ea03a3Smacallan	if (bg == -1) {
446e1ea03a3Smacallan		/* transparent */
447e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
448e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
449e1ea03a3Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_POLY_STIP);
450e1ea03a3Smacallan	} else {
451e1ea03a3Smacallan		WRITE4(CRIME_DE_BG, bg << 8);
452e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
453e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
454e1ea03a3Smacallan		    DE_DRAWMODE_ROP |
455e1ea03a3Smacallan		    DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_POLY_STIP);
456e1ea03a3Smacallan	}
457e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
458e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
45926dcc2a3Smacallan	SYNC;
460e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
461e1ea03a3Smacallan}
462e1ea03a3Smacallan
463e1ea03a3Smacallanstatic void
464e1ea03a3SmacallanCrimeSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
465e1ea03a3Smacallan			int x, int y, int w, int h,
466e1ea03a3Smacallan			int skipleft )
467e1ea03a3Smacallan{
468e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
469e1ea03a3Smacallan
470e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
471e1ea03a3Smacallan
472e1ea03a3Smacallan	fPtr->start = skipleft;
473e1ea03a3Smacallan	fPtr->ux = x;
474e1ea03a3Smacallan	fPtr->uy = y;
475e1ea03a3Smacallan	fPtr->uw = w;
476e1ea03a3Smacallan	fPtr->uh = h;
477e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
478e1ea03a3Smacallan}
479e1ea03a3Smacallan
480e1ea03a3Smacallanstatic void
481e1ea03a3SmacallanCrimeSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
482e1ea03a3Smacallan{
483e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
484e1ea03a3Smacallan	uint32_t *boo = (uint32_t *)fPtr->expandbuffers[bufno];
485e1ea03a3Smacallan	int idx = fPtr->uw, x = fPtr->ux;
486e1ea03a3Smacallan
487e1ea03a3Smacallan	LOG(CRIME_DEBUG_COLOUREXPAND);
488e1ea03a3Smacallan
48926dcc2a3Smacallan	MAKE_ROOM(5);
490e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, 0x001f0000 | (fPtr->start << 24));
491e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_PAT, *boo);
492e1ea03a3Smacallan	boo++;
493e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x + fPtr->start << 16) | fPtr->uy);
494e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
495e1ea03a3Smacallan		((x + min(idx, 32) - 1) << 16) | (fPtr->uy));
496e1ea03a3Smacallan	idx -= 32;
497e1ea03a3Smacallan	x += 32;
498e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, 0x001f0000);
499e1ea03a3Smacallan
500e1ea03a3Smacallan	while (idx > 0) {
50126dcc2a3Smacallan		MAKE_ROOM(3);
502e1ea03a3Smacallan		WRITE4(CRIME_DE_STIPPLE_PAT, *boo);
503e1ea03a3Smacallan		boo++;
504e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (x << 16) | fPtr->uy);
505e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
506e1ea03a3Smacallan			((x + min(idx, 32) - 1) << 16) | (fPtr->uy));
507e1ea03a3Smacallan		idx -= 32;
508e1ea03a3Smacallan		x += 32;
509e1ea03a3Smacallan	}
510e1ea03a3Smacallan	fPtr->uy++;
511e1ea03a3Smacallan	DONE(CRIME_DEBUG_COLOUREXPAND);
512e1ea03a3Smacallan}
513e1ea03a3Smacallan
514e1ea03a3Smacallanstatic void
515e1ea03a3SmacallanCrimeSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
516e1ea03a3Smacallan    unsigned int planemask)
517e1ea03a3Smacallan{
518e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
519e1ea03a3Smacallan
520e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
521e1ea03a3Smacallan
52226dcc2a3Smacallan	MAKE_ROOM(5);
52326dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
52426dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
525e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
526e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
527e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, color << 8);
528e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
529e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
53093351543Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_SCISSOR_EN);
53126dcc2a3Smacallan	SYNC;
532e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
533e1ea03a3Smacallan}
534e1ea03a3Smacallan
535e1ea03a3Smacallanstatic void
536e1ea03a3SmacallanCrimeSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2,
537e1ea03a3Smacallan    int y2, int flags)
538e1ea03a3Smacallan{
539e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
540e1ea03a3Smacallan
541e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
54226dcc2a3Smacallan	MAKE_ROOM(3);
543e1ea03a3Smacallan	if (flags & OMIT_LAST) {
544e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
545e1ea03a3Smacallan			DE_PRIM_LINE | DE_PRIM_LINE_SKIP_END | 2);
546e1ea03a3Smacallan	} else {
547e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
548e1ea03a3Smacallan			DE_PRIM_LINE | 2);
549e1ea03a3Smacallan	}
550e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x1 << 16) | y1);
551e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1, (x2 << 16) | y2);
552e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
553e1ea03a3Smacallan}
554e1ea03a3Smacallan
555e1ea03a3Smacallanvoid
556e1ea03a3SmacallanCrimeSetupForDashedLine(ScrnInfoPtr pScrn,
557e1ea03a3Smacallan		int fg, int bg, int rop, unsigned int planemask,
558e1ea03a3Smacallan        	int length, unsigned char *pattern)
559e1ea03a3Smacallan{
560e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
561e1ea03a3Smacallan	uint32_t pat;
562e1ea03a3Smacallan
563e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
564e1ea03a3Smacallan
565e1ea03a3Smacallan	fPtr->uw = length;
56626dcc2a3Smacallan	MAKE_ROOM(7);
56726dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
56826dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
569e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, planemask);
570e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, rop);
571e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, fg << 8);
572e1ea03a3Smacallan	if (bg == -1) {
573e1ea03a3Smacallan		/* transparent */
574e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
575e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
57693351543Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_LINE_STIP |
57793351543Smacallan		    DE_DRAWMODE_SCISSOR_EN);
578e1ea03a3Smacallan	} else {
579e1ea03a3Smacallan		WRITE4(CRIME_DE_BG, bg << 8);
580e1ea03a3Smacallan		WRITE4(CRIME_DE_DRAWMODE,
581e1ea03a3Smacallan		    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK |
58293351543Smacallan		    DE_DRAWMODE_ROP | DE_DRAWMODE_SCISSOR_EN |
583e1ea03a3Smacallan		    DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_LINE_STIP);
584e1ea03a3Smacallan	}
585e1ea03a3Smacallan	/*
586e1ea03a3Smacallan	 * can we trust the Xserver to always hand us a 32bit aligned
587e1ea03a3Smacallan	 * pattern buffer?
588e1ea03a3Smacallan	 */
589e1ea03a3Smacallan	memcpy(&pat, pattern, 4);
590e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_PAT, pat);
59126dcc2a3Smacallan	SYNC;
592e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
593e1ea03a3Smacallan}
594e1ea03a3Smacallan
595e1ea03a3Smacallanvoid
596e1ea03a3SmacallanCrimeSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn,
597e1ea03a3Smacallan        int x1, int y1, int x2, int y2, int flags, int phase)
598e1ea03a3Smacallan{
599e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
600e1ea03a3Smacallan	uint32_t stipmode;
601e1ea03a3Smacallan
602e1ea03a3Smacallan	LOG(CRIME_DEBUG_LINES);
60326dcc2a3Smacallan	MAKE_ROOM(4);
604e1ea03a3Smacallan
605e1ea03a3Smacallan	if (flags & OMIT_LAST) {
606e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
607e1ea03a3Smacallan			DE_PRIM_LINE | DE_PRIM_LINE_SKIP_END | 2);
608e1ea03a3Smacallan	} else {
609e1ea03a3Smacallan		WRITE4(CRIME_DE_PRIMITIVE,
610e1ea03a3Smacallan			DE_PRIM_LINE | 2);
611e1ea03a3Smacallan	}
612e1ea03a3Smacallan
613e1ea03a3Smacallan	stipmode = ((fPtr->uw - 1) << 16) | (phase << 24);
614e1ea03a3Smacallan	WRITE4(CRIME_DE_STIPPLE_MODE, stipmode);
615e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, (x1 << 16) | y1);
616e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1, (x2 << 16) | y2);
617e1ea03a3Smacallan	DONE(CRIME_DEBUG_LINES);
618e1ea03a3Smacallan}
619e1ea03a3Smacallan
620e1ea03a3Smacallanvoid
621e1ea03a3SmacallanCrimeSetClippingRectangle ( ScrnInfoPtr pScrn,
622e1ea03a3Smacallan                        int left, int top, int right, int bottom)
623e1ea03a3Smacallan{
624e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
625e1ea03a3Smacallan
626e1ea03a3Smacallan	LOG(CRIME_DEBUG_CLIPPING);
62726dcc2a3Smacallan	MAKE_ROOM(2);
62893351543Smacallan	WRITE4(CRIME_DE_SCISSOR, (left << 16) | top);
62993351543Smacallan	WRITE4(CRIME_DE_SCISSOR + 4, ((right + 1) << 16) | (bottom + 1));
63026dcc2a3Smacallan	SYNC;
631e1ea03a3Smacallan	DONE(CRIME_DEBUG_CLIPPING);
632e1ea03a3Smacallan}
633e1ea03a3Smacallan
634e1ea03a3Smacallanvoid
635e1ea03a3SmacallanCrimeDisableClipping (ScrnInfoPtr pScrn)
636e1ea03a3Smacallan{
637e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
638e1ea03a3Smacallan
639e1ea03a3Smacallan	LOG(CRIME_DEBUG_CLIPPING);
64026dcc2a3Smacallan	MAKE_ROOM(2);
64193351543Smacallan	WRITE4(CRIME_DE_SCISSOR, 0);
64293351543Smacallan	WRITE4(CRIME_DE_SCISSOR + 4, 0x3fff3fff);
64326dcc2a3Smacallan	SYNC;
644e1ea03a3Smacallan	DONE(CRIME_DEBUG_CLIPPING);
645e1ea03a3Smacallan}
646e1ea03a3Smacallan
647e1ea03a3Smacallanstatic Bool
648e1ea03a3SmacallanCrimeSetupForCPUToScreenAlphaTexture (
649e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
650e1ea03a3Smacallan   int		op,
651e1ea03a3Smacallan   CARD16	red,
652e1ea03a3Smacallan   CARD16	green,
653e1ea03a3Smacallan   CARD16	blue,
654e1ea03a3Smacallan   CARD16	alpha,
655e1ea03a3Smacallan   int		alphaType,
656e1ea03a3Smacallan   CARD8	*alphaPtr,
657e1ea03a3Smacallan   int		alphaPitch,
658e1ea03a3Smacallan   int		width,
659e1ea03a3Smacallan   int		height,
660e1ea03a3Smacallan   int		flags
661e1ea03a3Smacallan)
662e1ea03a3Smacallan{
663e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
664e1ea03a3Smacallan
665e1ea03a3Smacallan	if (op != PictOpOver) {
666e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
667e1ea03a3Smacallan		op = PictOpOver;
668e1ea03a3Smacallan	}
669e1ea03a3Smacallan
670e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
671e1ea03a3Smacallan
672e1ea03a3Smacallan	fPtr->alpha_color = ((red & 0xff00) << 16) |
673e1ea03a3Smacallan			    ((green & 0xff00) << 8) |
67409f0d67cSmacallan			    (blue & 0xff00);
675e1ea03a3Smacallan	fPtr->uw = width;
676e1ea03a3Smacallan	fPtr->uh = height;
677e1ea03a3Smacallan	fPtr->us = alphaPitch;
678e1ea03a3Smacallan	fPtr->alpha_texture = alphaPtr;
67909f0d67cSmacallan	fPtr->format = alphaType;
6805b2650b9Smacallan#ifdef CRIME_DEBUG_LOUD
68109f0d67cSmacallan	if (alphaType != PICT_a8) {
68209f0d67cSmacallan		xf86Msg(X_ERROR, "ARGB mask %08x %d\n", (uint32_t)alphaPtr,
68309f0d67cSmacallan		    alphaPitch);
68409f0d67cSmacallan	}
6855b2650b9Smacallan#endif
68626dcc2a3Smacallan	MAKE_ROOM(7);
68726dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
68826dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
689e1ea03a3Smacallan	/* XXX this register is not where it's supposed to be */
690e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_COLOR, fPtr->alpha_color);
69109f0d67cSmacallan	if (alphaType == PICT_a8) {
69209f0d67cSmacallan		if (fPtr->alpha_color == 0) {
69309f0d67cSmacallan			WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_8 |
694e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
69509f0d67cSmacallan			WRITE4(CRIME_DE_XFER_STEP_X, 1);
69609f0d67cSmacallan			WRITE4(CRIME_DE_ALPHA_FUNC,
69709f0d67cSmacallan			    DE_ALPHA_ADD |
69809f0d67cSmacallan			    (DE_ALPHA_OP_ZERO << DE_ALPHA_OP_SRC_SHIFT) |
69909f0d67cSmacallan			    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
70009f0d67cSmacallan		} else {
70109f0d67cSmacallan			WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
70209f0d67cSmacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
70309f0d67cSmacallan			WRITE4(CRIME_DE_XFER_STEP_X, 4);
70409f0d67cSmacallan			WRITE4(CRIME_DE_ALPHA_FUNC,
70509f0d67cSmacallan			    DE_ALPHA_ADD |
70609f0d67cSmacallan			    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
70709f0d67cSmacallan			    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
70809f0d67cSmacallan		}
709e1ea03a3Smacallan	} else {
710e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
711e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
712e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_STEP_X, 4);
713e1ea03a3Smacallan		WRITE4(CRIME_DE_ALPHA_FUNC,
714e1ea03a3Smacallan		    DE_ALPHA_ADD |
715e1ea03a3Smacallan		    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
716e1ea03a3Smacallan		    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
71709f0d67cSmacallan	}
718e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
719e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
720e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
721e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
722e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
72326dcc2a3Smacallan	SYNC;
724e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
725e1ea03a3Smacallan	return TRUE;
726e1ea03a3Smacallan}
727e1ea03a3Smacallan
728e1ea03a3Smacallanvoid
729e1ea03a3SmacallanCrimeSubsequentCPUToScreenAlphaTexture (
730e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
731e1ea03a3Smacallan    int		dstx,
732e1ea03a3Smacallan    int		dsty,
733e1ea03a3Smacallan    int		srcx,
734e1ea03a3Smacallan    int		srcy,
735e1ea03a3Smacallan    int		width,
736e1ea03a3Smacallan    int		height
737e1ea03a3Smacallan)
738e1ea03a3Smacallan{
739e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
740e1ea03a3Smacallan	unsigned char *aptr;
741e1ea03a3Smacallan	uint32_t *dptr, aval;
742e1ea03a3Smacallan	int i, j;
743e1ea03a3Smacallan	int bufnum = 0;
744e1ea03a3Smacallan
745e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
746e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
747e1ea03a3Smacallan	xf86Msg(X_ERROR, "%d %d %d %d %d %d\n",srcx, srcy, dstx, dsty, width,
748e1ea03a3Smacallan	    height);
749e1ea03a3Smacallan#endif
750e1ea03a3Smacallan	aptr = fPtr->alpha_texture + (fPtr->us * srcy) + srcx;
751e1ea03a3Smacallan	for (i = 0; i < height; i++) {
752e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
753e1ea03a3Smacallan		if (fPtr->alpha_color == 0) {
754e1ea03a3Smacallan			memcpy(dptr, aptr, width);
755e1ea03a3Smacallan		} else {
756e1ea03a3Smacallan			for (j = 0; j < width; j++) {
757e1ea03a3Smacallan				aval = aptr[j];
758e1ea03a3Smacallan				*dptr = aval | fPtr->alpha_color;
759e1ea03a3Smacallan				dptr++;
760e1ea03a3Smacallan			}
761e1ea03a3Smacallan		}
76226dcc2a3Smacallan		MAKE_ROOM(3);
763e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
764e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
765e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
766e1ea03a3Smacallan			((dstx + width - 1) << 16) | (dsty + i));
767e1ea03a3Smacallan		bufnum++;
768e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
769e1ea03a3Smacallan		aptr += fPtr->us;
770e1ea03a3Smacallan	}
771e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
772e1ea03a3Smacallan}
773e1ea03a3Smacallan
77409f0d67cSmacallanvoid
77509f0d67cSmacallanCrimeSubsequentCPUToScreenAlphaTexture32 (
77609f0d67cSmacallan    ScrnInfoPtr	pScrn,
77709f0d67cSmacallan    int		dstx,
77809f0d67cSmacallan    int		dsty,
77909f0d67cSmacallan    int		srcx,
78009f0d67cSmacallan    int		srcy,
78109f0d67cSmacallan    int		width,
78209f0d67cSmacallan    int		height
78309f0d67cSmacallan)
78409f0d67cSmacallan{
78509f0d67cSmacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
78609f0d67cSmacallan	uint8_t *aptr;
78709f0d67cSmacallan	uint32_t *dptr, *sptr;
78809f0d67cSmacallan	int i, j;
78909f0d67cSmacallan	int bufnum = 0;
79009f0d67cSmacallan
79109f0d67cSmacallan	LOG(CRIME_DEBUG_XRENDER);
79226dcc2a3Smacallan#ifdef CRIME_DEBUG_LOUD
79309f0d67cSmacallan	xf86Msg(X_ERROR, "%d %d %d %d %d %d\n",srcx, srcy, dstx, dsty, width,
79409f0d67cSmacallan	    height);
79509f0d67cSmacallan#endif
79609f0d67cSmacallan	aptr = fPtr->alpha_texture + (fPtr->us * srcy) + (srcx << 2);
79709f0d67cSmacallan	for (i = 0; i < height; i++) {
79809f0d67cSmacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
79909f0d67cSmacallan		sptr = (uint32_t *)aptr;
80009f0d67cSmacallan		for (j = 0; j < width; j++) {
80109f0d67cSmacallan			*dptr = (*sptr >> 24) | fPtr->alpha_color;
80209f0d67cSmacallan#ifdef CRIME_DEBUG_LOUD
80309f0d67cSmacallan			xf86Msg(X_ERROR, "%08x %08x\n", *sptr, *dptr);
80409f0d67cSmacallan#endif
80509f0d67cSmacallan			sptr++;
80609f0d67cSmacallan			dptr++;
80709f0d67cSmacallan		}
80826dcc2a3Smacallan		MAKE_ROOM(3);
80909f0d67cSmacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
81009f0d67cSmacallan		WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
81109f0d67cSmacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
81209f0d67cSmacallan			((dstx + width - 1) << 16) | (dsty + i));
81309f0d67cSmacallan		bufnum++;
81409f0d67cSmacallan		if (bufnum == 8) bufnum = 0;
81509f0d67cSmacallan		aptr += fPtr->us;
81609f0d67cSmacallan	}
81709f0d67cSmacallan	DONE(CRIME_DEBUG_XRENDER);
81809f0d67cSmacallan}
81909f0d67cSmacallan
820e1ea03a3Smacallanstatic Bool
821e1ea03a3SmacallanCrimeSetupForCPUToScreenTexture (
822e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
823e1ea03a3Smacallan   int		op,
824e1ea03a3Smacallan   int		texType,
825e1ea03a3Smacallan   CARD8	*texPtr,
826e1ea03a3Smacallan   int		texPitch,
827e1ea03a3Smacallan   int		width,
828e1ea03a3Smacallan   int		height,
829e1ea03a3Smacallan   int		flags
830e1ea03a3Smacallan)
831e1ea03a3Smacallan{
832e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
833e1ea03a3Smacallan
834e1ea03a3Smacallan	if (op != PictOpOver) {
835e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
836e1ea03a3Smacallan		op = PictOpOver;
837e1ea03a3Smacallan	}
838e1ea03a3Smacallan
839e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
840e1ea03a3Smacallan
841e1ea03a3Smacallan	fPtr->uw = width;
842e1ea03a3Smacallan	fPtr->uh = height;
843e1ea03a3Smacallan	fPtr->us = texPitch;
844e1ea03a3Smacallan	fPtr->alpha_texture = texPtr;
84526dcc2a3Smacallan	MAKE_ROOM(6);
84626dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
84726dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
848e1ea03a3Smacallan	if (texType == PICT_a8b8g8r8) {
849e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
850e1ea03a3Smacallan				    DE_MODE_TYPE_ABGR | DE_MODE_PIXDEPTH_32);
851e1ea03a3Smacallan	} else {
852e1ea03a3Smacallan		WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
853e1ea03a3Smacallan				    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
854e1ea03a3Smacallan	}
855e1ea03a3Smacallan	fPtr->format = texType;
856e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
857e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
858e1ea03a3Smacallan	    DE_ALPHA_ADD |
859e1ea03a3Smacallan	    (DE_ALPHA_OP_ONE/*SRC_ALPHA*/ << DE_ALPHA_OP_SRC_SHIFT) |
860e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
861e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
862e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
863e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
864e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
865e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
86626dcc2a3Smacallan	SYNC;
867e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
868e1ea03a3Smacallan	return TRUE;
869e1ea03a3Smacallan}
870e1ea03a3Smacallan
871e1ea03a3Smacallanvoid
872e1ea03a3SmacallanCrimeSubsequentCPUToScreenTexture (
873e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
874e1ea03a3Smacallan    int		dstx,
875e1ea03a3Smacallan    int		dsty,
876e1ea03a3Smacallan    int		srcx,
877e1ea03a3Smacallan    int		srcy,
878e1ea03a3Smacallan    int		width,
879e1ea03a3Smacallan    int		height
880e1ea03a3Smacallan)
881e1ea03a3Smacallan{
882e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
883e1ea03a3Smacallan	unsigned char *aptr, *lptr;
884e1ea03a3Smacallan	uint32_t *dptr, *sptr, aval, pixel;
885e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
886e1ea03a3Smacallan	int bufnum = 0;
887e1ea03a3Smacallan
888e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
889e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
890e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d\n", __func__,
891e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height);
892e1ea03a3Smacallan#endif
893e1ea03a3Smacallan	if ((width == 1) || (fPtr->format != PICT_a8r8g8b8)) {
894e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d %d %d\n", __func__,
895e1ea03a3Smacallan		    srcx, srcy, dstx, dsty, width, height, fPtr->uw, fPtr->us);
896e1ea03a3Smacallan		return;
897e1ea03a3Smacallan	}
898e1ea03a3Smacallan
899e1ea03a3Smacallan	aptr = fPtr->alpha_texture + (srcx << 2);
900e1ea03a3Smacallan	lptr = aptr + (fPtr->us * srcy);
901e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
902e1ea03a3Smacallan		rep = 128 / fPtr->uw;
903e1ea03a3Smacallan		period = rep * fPtr->uw;
904e1ea03a3Smacallan	}
905e1ea03a3Smacallan
906e1ea03a3Smacallan	if (fPtr->format == PICT_a8b8g8r8) {
907e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
908e1ea03a3Smacallan		xf86Msg(X_ERROR, "ABGR\n");
909e1ea03a3Smacallan#endif
910e1ea03a3Smacallan		for (i = 0; i < height; i++) {
911e1ea03a3Smacallan			dptr = (uint32_t *)fPtr->buffers[bufnum];
912e1ea03a3Smacallan			memcpy(dptr, aptr, fPtr->us);
91326dcc2a3Smacallan			MAKE_ROOM(3);
914e1ea03a3Smacallan			WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
915e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0, dstx << 16 | (dsty + i));
916e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
917e1ea03a3Smacallan				((dstx + width - 1) << 16) | (dsty + i));
918e1ea03a3Smacallan			bufnum++;
919e1ea03a3Smacallan			if (bufnum == 8) bufnum = 0;
920e1ea03a3Smacallan			aptr += fPtr->us;
921e1ea03a3Smacallan		}
922e1ea03a3Smacallan	} else {
923e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
924e1ea03a3Smacallan		xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)aptr, fPtr->uw);
925e1ea03a3Smacallan#endif
926e1ea03a3Smacallan		lcnt = fPtr->uh - srcy;
927e1ea03a3Smacallan		for (i = 0; i < height; i++) {
928e1ea03a3Smacallan			dptr = (uint32_t *)fPtr->buffers[bufnum];
929e1ea03a3Smacallan			for (k = 0; k < rep; k++) {
930e1ea03a3Smacallan				sptr = (uint32_t *)aptr;
931e1ea03a3Smacallan				for (j = 0; j < fPtr->uw; j++) {
932e1ea03a3Smacallan					pixel = *sptr;
933e1ea03a3Smacallan					*dptr = (pixel << 8) | (pixel >> 24);
934e1ea03a3Smacallan					dptr++;
935e1ea03a3Smacallan					sptr++;
936e1ea03a3Smacallan				}
937e1ea03a3Smacallan			}
938e1ea03a3Smacallan			xoff = 0;
93926dcc2a3Smacallan			MAKE_ROOM(1);
940e1ea03a3Smacallan			WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
941e1ea03a3Smacallan			while (xoff < width) {
942e1ea03a3Smacallan				xa = dstx + xoff;
943e1ea03a3Smacallan				xe = dstx + min(xoff + period, width) - 1;
94426dcc2a3Smacallan				MAKE_ROOM(2);
945e1ea03a3Smacallan				WRITE4(CRIME_DE_X_VERTEX_0,
946e1ea03a3Smacallan				    xa << 16 | (dsty + i));
947e1ea03a3Smacallan				WRITE4ST(CRIME_DE_X_VERTEX_1,
948e1ea03a3Smacallan					(xe << 16) | (dsty + i));
949e1ea03a3Smacallan				xoff += period;
950e1ea03a3Smacallan			}
951e1ea03a3Smacallan			bufnum++;
952e1ea03a3Smacallan			if (bufnum == 8) bufnum = 0;
953e1ea03a3Smacallan			lcnt--;
954e1ea03a3Smacallan			if (lcnt == 0) {
955e1ea03a3Smacallan				aptr = lptr;
956e1ea03a3Smacallan				lcnt = fPtr->uh;
957e1ea03a3Smacallan			} else
958e1ea03a3Smacallan				aptr += fPtr->us;
959e1ea03a3Smacallan		}
960e1ea03a3Smacallan	}
961e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
962e1ea03a3Smacallan}
963e1ea03a3Smacallan
964e1ea03a3Smacallanstatic Bool
965e1ea03a3SmacallanCrimeSetupForCPUToScreenTextureMask(
966e1ea03a3Smacallan   ScrnInfoPtr	pScrn,
967e1ea03a3Smacallan   int		op,
968e1ea03a3Smacallan   int		texType,
969e1ea03a3Smacallan   CARD8	*srcPtr,
970e1ea03a3Smacallan   int		srcPitch,
971e1ea03a3Smacallan   CARD8	*mskPtr,
972e1ea03a3Smacallan   int		mskPitch,
973e1ea03a3Smacallan   int		width,
974e1ea03a3Smacallan   int		height,
975e1ea03a3Smacallan   int		flags
976e1ea03a3Smacallan)
977e1ea03a3Smacallan{
978e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
979e1ea03a3Smacallan
980e1ea03a3Smacallan	if (op != PictOpOver) {
981e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
982e1ea03a3Smacallan		op = PictOpOver;
983e1ea03a3Smacallan	}
984e1ea03a3Smacallan
985e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
986e1ea03a3Smacallan
987e1ea03a3Smacallan	fPtr->uw = width;
988e1ea03a3Smacallan	fPtr->uh = height;
989e1ea03a3Smacallan	fPtr->us = srcPitch >> 2;
990e1ea03a3Smacallan	if (PICT_FORMAT_BPP(texType) == 32) {
991e1ea03a3Smacallan		fPtr->um = mskPitch >> 2;
992e1ea03a3Smacallan	} else
993e1ea03a3Smacallan		fPtr->um = mskPitch;
994e1ea03a3Smacallan	fPtr->msk = (uint8_t *)mskPtr;
995e1ea03a3Smacallan	fPtr->src = (uint8_t *)srcPtr;
996e1ea03a3Smacallan	fPtr->texture_depth = PICT_FORMAT_BPP(texType);
997e1ea03a3Smacallan
99826dcc2a3Smacallan	MAKE_ROOM(6);
999e1ea03a3Smacallan	/* always expect ARGB for now */
1000e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_LIN_A | DE_MODE_BUFDEPTH_32 |
1001e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
100226dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
100326dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1004e1ea03a3Smacallan	fPtr->format = texType;
1005e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
1006e1ea03a3Smacallan	    DE_ALPHA_ADD |
1007e1ea03a3Smacallan	    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
1008e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
1009e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 4);
1010e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1011e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
1012e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
1013e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
1014e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
101526dcc2a3Smacallan	SYNC;
1016e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1017e1ea03a3Smacallan	return TRUE;
1018e1ea03a3Smacallan}
1019e1ea03a3Smacallan
1020e1ea03a3Smacallanvoid
1021e1ea03a3SmacallanCrimeSubsequentCPUToScreenTextureMask32(
1022e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
1023e1ea03a3Smacallan    int		dstx,
1024e1ea03a3Smacallan    int		dsty,
1025e1ea03a3Smacallan    int		srcx,
1026e1ea03a3Smacallan    int		srcy,
1027e1ea03a3Smacallan    int		maskx,
1028e1ea03a3Smacallan    int		masky,
1029e1ea03a3Smacallan    int		width,
1030e1ea03a3Smacallan    int		height
1031e1ea03a3Smacallan)
1032e1ea03a3Smacallan{
1033e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1034e1ea03a3Smacallan	uint32_t *lsptr, *lmptr, *asptr, *amptr;
1035e1ea03a3Smacallan	uint32_t *dptr, *sptr, *mptr, aval, pixel, mask;
1036e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
1037e1ea03a3Smacallan	int bufnum = 0;
1038e1ea03a3Smacallan	int sr, sg, sb, sa, mr, mg, mb, ma, rr, gg, bb, aa;
1039e1ea03a3Smacallan
1040e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1041e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
1042e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d; %d %d %d\n", __func__,
1043e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height, maskx, masky, fPtr->um);
1044e1ea03a3Smacallan#endif
1045e1ea03a3Smacallan	sptr = fPtr->src + (srcx << 2);
1046e1ea03a3Smacallan	mptr = fPtr->msk + (srcx << 2);
1047e1ea03a3Smacallan	lsptr = sptr + (fPtr->us * srcy);
1048e1ea03a3Smacallan	lmptr = mptr + (fPtr->um * srcy);
1049e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
1050e1ea03a3Smacallan		rep = 128 / fPtr->uw;
1051e1ea03a3Smacallan		period = rep * fPtr->uw;
1052e1ea03a3Smacallan	}
1053e1ea03a3Smacallan
1054e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
1055e1ea03a3Smacallan	xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)aptr, fPtr->uw);
1056e1ea03a3Smacallan#endif
1057e1ea03a3Smacallan	lcnt = fPtr->uh - srcy;
1058e1ea03a3Smacallan	for (i = 0; i < height; i++) {
1059e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
1060e1ea03a3Smacallan		for (k = 0; k < rep; k++) {
1061e1ea03a3Smacallan			asptr = lsptr;
1062e1ea03a3Smacallan			amptr = lmptr;
1063e1ea03a3Smacallan			for (j = 0; j < fPtr->uw; j++) {
1064e1ea03a3Smacallan				pixel = *asptr;
1065e1ea03a3Smacallan				mask = *amptr;
1066e1ea03a3Smacallan				if (mask == 0xffffffff) {
1067e1ea03a3Smacallan					*dptr = (pixel >> 24) | (pixel << 8);
1068e1ea03a3Smacallan				} else if (mask == 0x00000000) {
1069e1ea03a3Smacallan					*dptr = 0;
1070e1ea03a3Smacallan				} else {
1071e1ea03a3Smacallan					/* input is ARGB */
1072e1ea03a3Smacallan					sb = pixel & 0xff;
1073e1ea03a3Smacallan					sg = (pixel >> 8) & 0xff;
1074e1ea03a3Smacallan					sr = (pixel >> 16) & 0xff;
1075e1ea03a3Smacallan					sa = (pixel >> 24) & 0xff;
1076e1ea03a3Smacallan					mb = mask & 0xff;
1077e1ea03a3Smacallan					mg = (mask >> 8) & 0xff;
1078e1ea03a3Smacallan					mr = (mask >> 16) & 0xff;
1079e1ea03a3Smacallan					ma = (mask >> 24) & 0xff;
1080e1ea03a3Smacallan
1081e1ea03a3Smacallan					/* and here we need an RGBA pixel */
1082e1ea03a3Smacallan					bb = (((sb * mb) + 0x80) & 0xff00);
1083e1ea03a3Smacallan					gg = (((sg * mg) + 0x80) & 0xff00) << 8;
1084e1ea03a3Smacallan					rr = (((sr * mr) + 0x80) & 0xff00) << 16;
1085e1ea03a3Smacallan					aa = (((sa * ma) + 0x80) & 0xff00) >> 8;
1086e1ea03a3Smacallan					/*
1087e1ea03a3Smacallan					 * actually we could let the HW do this stuff
1088e1ea03a3Smacallan					 */
1089e1ea03a3Smacallan					*dptr = aa | rr | gg | bb;
1090e1ea03a3Smacallan				}
1091e1ea03a3Smacallan				dptr++;
1092e1ea03a3Smacallan				asptr++;
1093e1ea03a3Smacallan				amptr++;
1094e1ea03a3Smacallan			}
1095e1ea03a3Smacallan		}
1096e1ea03a3Smacallan		xoff = 0;
109726dcc2a3Smacallan		MAKE_ROOM(1);
1098e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
1099e1ea03a3Smacallan		while (xoff < width) {
1100e1ea03a3Smacallan			xa = dstx + xoff;
1101e1ea03a3Smacallan			xe = dstx + min(xoff + period, width) - 1;
110226dcc2a3Smacallan			MAKE_ROOM(2);
1103e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0,
1104e1ea03a3Smacallan			    xa << 16 | (dsty + i));
1105e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
1106e1ea03a3Smacallan				(xe << 16) | (dsty + i));
1107e1ea03a3Smacallan			xoff += period;
1108e1ea03a3Smacallan		}
1109e1ea03a3Smacallan		bufnum++;
1110e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
1111e1ea03a3Smacallan		lcnt--;
1112e1ea03a3Smacallan		if (lcnt == 0) {
1113e1ea03a3Smacallan			/* back to the beginning */
1114e1ea03a3Smacallan			lsptr = sptr;
1115e1ea03a3Smacallan			lmptr = mptr;
1116e1ea03a3Smacallan			lcnt = fPtr->uh;
1117e1ea03a3Smacallan		} else
1118e1ea03a3Smacallan			/* next line */
1119e1ea03a3Smacallan			lsptr += fPtr->us;
1120e1ea03a3Smacallan			lmptr += fPtr->um;
1121e1ea03a3Smacallan	}
1122e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1123e1ea03a3Smacallan}
1124e1ea03a3Smacallan
1125e1ea03a3Smacallanvoid
1126e1ea03a3SmacallanCrimeSubsequentCPUToScreenTextureMask8(
1127e1ea03a3Smacallan    ScrnInfoPtr	pScrn,
1128e1ea03a3Smacallan    int		dstx,
1129e1ea03a3Smacallan    int		dsty,
1130e1ea03a3Smacallan    int		srcx,
1131e1ea03a3Smacallan    int		srcy,
1132e1ea03a3Smacallan    int		maskx,
1133e1ea03a3Smacallan    int		masky,
1134e1ea03a3Smacallan    int		width,
1135e1ea03a3Smacallan    int		height
1136e1ea03a3Smacallan)
1137e1ea03a3Smacallan{
1138e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1139e1ea03a3Smacallan	uint32_t *lsptr, *asptr;
1140e1ea03a3Smacallan	uint32_t *dptr, *sptr, aval, pixel, mask;
1141e1ea03a3Smacallan	uint8_t  *lmptr, *amptr, *mptr;
1142e1ea03a3Smacallan	int i, j, k, l, rep = 1, period = fPtr->uw, xoff, lcnt, xa, xe;
1143e1ea03a3Smacallan	int bufnum = 0;
1144e1ea03a3Smacallan	int sr, sg, sb, sa, rr, gg, bb, aa;
1145e1ea03a3Smacallan
1146e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
11475b2650b9Smacallan#ifdef CRIME_DEBUG_LOUD
1148e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d %d %d\n", __func__,
1149e1ea03a3Smacallan	    srcx, srcy, dstx, dsty, width, height);
1150e1ea03a3Smacallan#endif
1151e1ea03a3Smacallan	sptr = (uint32_t *)fPtr->src + (fPtr->us * srcy) + (srcx << 2);
1152e1ea03a3Smacallan	mptr = (uint8_t *)fPtr->msk + (fPtr->um * srcy) + srcx;
1153e1ea03a3Smacallan	lsptr = sptr;
1154e1ea03a3Smacallan	lmptr = mptr;
1155e1ea03a3Smacallan	if ((fPtr->uw < 128) && (fPtr->uw < width)) {
1156e1ea03a3Smacallan		rep = 128 / fPtr->uw;
1157e1ea03a3Smacallan		period = rep * fPtr->uw;
1158e1ea03a3Smacallan	}
1159e1ea03a3Smacallan
1160e1ea03a3Smacallan#ifdef CRIME_DEBUG_LOUD
1161e1ea03a3Smacallan	xf86Msg(X_ERROR, "ARGB %08x %d\n", (uint32_t)aptr, fPtr->uw);
1162e1ea03a3Smacallan#endif
1163e1ea03a3Smacallan	lcnt = fPtr->uh;
1164e1ea03a3Smacallan	for (i = 0; i < height; i++) {
1165e1ea03a3Smacallan		dptr = (uint32_t *)fPtr->buffers[bufnum];
1166e1ea03a3Smacallan		for (k = 0; k < rep; k++) {
1167e1ea03a3Smacallan			asptr = lsptr;
1168e1ea03a3Smacallan			amptr = lmptr;
1169e1ea03a3Smacallan			for (j = 0; j < fPtr->uw; j++) {
1170e1ea03a3Smacallan				pixel = *asptr;
1171e1ea03a3Smacallan				mask = *amptr;
1172e1ea03a3Smacallan				if (mask == 0xff) {
1173e1ea03a3Smacallan					*dptr = (pixel >> 24) | (pixel << 8);
1174e1ea03a3Smacallan				} else if (mask == 0x00) {
1175e1ea03a3Smacallan					*dptr = 0;
1176e1ea03a3Smacallan				} else {
1177e1ea03a3Smacallan					/* input is ARGB */
1178e1ea03a3Smacallan					sb = pixel & 0xff;
1179e1ea03a3Smacallan					sg = (pixel >> 8) & 0xff;
1180e1ea03a3Smacallan					sr = (pixel >> 16) & 0xff;
1181e1ea03a3Smacallan					sa = (pixel >> 24) & 0xff;
1182e1ea03a3Smacallan
1183e1ea03a3Smacallan					/* and here we need an RGBA pixel */
1184e1ea03a3Smacallan					bb = (((sb * mask) + 0x80) & 0xff00);
1185e1ea03a3Smacallan					gg = (((sg * mask) + 0x80) & 0xff00)
1186e1ea03a3Smacallan					     << 8;
1187e1ea03a3Smacallan					rr = (((sr * mask) + 0x80) & 0xff00)
1188e1ea03a3Smacallan					     << 16;
1189e1ea03a3Smacallan					aa = (((sa * mask) + 0x80) & 0xff00)
1190e1ea03a3Smacallan					     >> 8;
1191e1ea03a3Smacallan					/*
1192e1ea03a3Smacallan					 * actually we could let the HW do this
1193e1ea03a3Smacallan					 * stuff
1194e1ea03a3Smacallan					 */
1195e1ea03a3Smacallan					*dptr = aa | rr | gg | bb;
1196e1ea03a3Smacallan				}
1197e1ea03a3Smacallan				dptr++;
1198e1ea03a3Smacallan				asptr++;
1199e1ea03a3Smacallan				amptr++;
1200e1ea03a3Smacallan			}
1201e1ea03a3Smacallan		}
1202e1ea03a3Smacallan		xoff = 0;
120326dcc2a3Smacallan		MAKE_ROOM(1);
1204e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC, bufnum * 8192);
1205e1ea03a3Smacallan		while (xoff < width) {
1206e1ea03a3Smacallan			xa = dstx + xoff;
1207e1ea03a3Smacallan			xe = dstx + min(xoff + period, width) - 1;
120826dcc2a3Smacallan			MAKE_ROOM(2);
1209e1ea03a3Smacallan			WRITE4(CRIME_DE_X_VERTEX_0,
1210e1ea03a3Smacallan			    xa << 16 | (dsty + i));
1211e1ea03a3Smacallan			WRITE4ST(CRIME_DE_X_VERTEX_1,
1212e1ea03a3Smacallan				(xe << 16) | (dsty + i));
1213e1ea03a3Smacallan			xoff += period;
1214e1ea03a3Smacallan		}
1215e1ea03a3Smacallan		bufnum++;
1216e1ea03a3Smacallan		if (bufnum == 8) bufnum = 0;
1217e1ea03a3Smacallan		lcnt--;
1218e1ea03a3Smacallan		if (lcnt == 0) {
1219e1ea03a3Smacallan			/* back to the beginning */
1220e1ea03a3Smacallan			lsptr = sptr;
1221e1ea03a3Smacallan			lmptr = mptr;
1222e1ea03a3Smacallan			lcnt = fPtr->uh;
1223e1ea03a3Smacallan		} else
1224e1ea03a3Smacallan			/* next line */
1225e1ea03a3Smacallan			lsptr += fPtr->us;
1226e1ea03a3Smacallan			lmptr += fPtr->um;
1227e1ea03a3Smacallan	}
1228e1ea03a3Smacallan	DONE(CRIME_DEBUG_XRENDER);
1229e1ea03a3Smacallan}
1230e1ea03a3Smacallan
1231e1ea03a3Smacallanstatic void
1232e1ea03a3SmacallanCrimeDoCPUToScreenComposite(
1233e1ea03a3Smacallan   	CARD8      op,
1234e1ea03a3Smacallan        PicturePtr pSrc,
1235e1ea03a3Smacallan        PicturePtr pMask,
1236e1ea03a3Smacallan        PicturePtr pDst,
1237e1ea03a3Smacallan        INT16      xSrc,
1238e1ea03a3Smacallan        INT16      ySrc,
1239e1ea03a3Smacallan        INT16      xMask,
1240e1ea03a3Smacallan        INT16      yMask,
1241e1ea03a3Smacallan        INT16      xDst,
1242e1ea03a3Smacallan        INT16      yDst,
1243e1ea03a3Smacallan        CARD16     width,
1244e1ea03a3Smacallan        CARD16     height
1245e1ea03a3Smacallan)
1246e1ea03a3Smacallan{
1247e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1248e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1249e1ea03a3Smacallan	RegionRec region;
1250e1ea03a3Smacallan	CARD32 *formats;
1251e1ea03a3Smacallan	int flags = 0;
1252e1ea03a3Smacallan	BoxPtr pbox;
1253e1ea03a3Smacallan	int nbox, w, h;
1254e1ea03a3Smacallan
1255e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1256e1ea03a3Smacallan	if (pSrc->transform || (pMask && pMask->transform)) {
1257e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: transform?!\n", __func__);
1258e1ea03a3Smacallan		return;
1259e1ea03a3Smacallan	}
1260e1ea03a3Smacallan
1261e1ea03a3Smacallan	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) {
1262e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: alpha-map?!\n", __func__);
1263e1ea03a3Smacallan		return;
1264e1ea03a3Smacallan	}
1265e1ea03a3Smacallan
1266e1ea03a3Smacallan	xDst += pDst->pDrawable->x;
1267e1ea03a3Smacallan	yDst += pDst->pDrawable->y;
1268e1ea03a3Smacallan	xSrc += pSrc->pDrawable->x;
1269e1ea03a3Smacallan	ySrc += pSrc->pDrawable->y;
1270e1ea03a3Smacallan
1271e1ea03a3Smacallan	if(pMask) {
1272e1ea03a3Smacallan		CARD16 red, green, blue, alpha;
1273e1ea03a3Smacallan		CARD32 pixel =
1274e1ea03a3Smacallan		    *((CARD32*)(((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr));
127509f0d67cSmacallan#ifdef CRIME_DEBUG_LOUD
1276e1ea03a3Smacallan		if(pMask->componentAlpha) {
1277e1ea03a3Smacallan			xf86Msg(X_ERROR, "%s: alpha component mask\n",
1278e1ea03a3Smacallan			    __func__);
127909f0d67cSmacallan			xf86Msg(X_ERROR, "src: %d x %d\n", pSrc->pDrawable->width,
128009f0d67cSmacallan			    pSrc->pDrawable->height);
1281e1ea03a3Smacallan		}
128209f0d67cSmacallan#endif
1283e1ea03a3Smacallan		if ((pSrc->pDrawable->width == 1) &&
1284e1ea03a3Smacallan		    (pSrc->pDrawable->height == 1)) {
1285e1ea03a3Smacallan
1286e1ea03a3Smacallan			if(!XAAGetRGBAFromPixel(pixel, &red, &green, &blue,
1287e1ea03a3Smacallan			    &alpha, pSrc->format)) {
1288e1ea03a3Smacallan				xf86Msg(X_ERROR, "%s: can't read pixel\n", __func__);
1289e1ea03a3Smacallan				return;
1290e1ea03a3Smacallan			}
1291e1ea03a3Smacallan			xMask += pMask->pDrawable->x;
1292e1ea03a3Smacallan			yMask += pMask->pDrawable->y;
1293e1ea03a3Smacallan
1294e1ea03a3Smacallan			/* pull out color expandable operations here */
1295e1ea03a3Smacallan			if(pMask->format == PICT_a1) {
1296e1ea03a3Smacallan				PixmapPtr pPix = (PixmapPtr)(pMask->pDrawable);
1297e1ea03a3Smacallan				int skipleft;
1298e1ea03a3Smacallan
1299e1ea03a3Smacallan				if (alpha == 0xffff) {
1300e1ea03a3Smacallan					/* actually we can but for now we don't care */
1301e1ea03a3Smacallan					xf86Msg(X_ERROR,
1302e1ea03a3Smacallan					   "can't colour expand with alpha\n");
1303e1ea03a3Smacallan					return;
1304e1ea03a3Smacallan				}
1305e1ea03a3Smacallan				if (op != PictOpOver) {
1306e1ea03a3Smacallan					xf86Msg(X_ERROR, "!over\n");
1307e1ea03a3Smacallan					return;
1308e1ea03a3Smacallan				}
1309e1ea03a3Smacallan				if (pMask->repeat) {
1310e1ea03a3Smacallan					xf86Msg(X_ERROR, "mono repeat\n");
1311e1ea03a3Smacallan					return;
1312e1ea03a3Smacallan				}
1313e1ea03a3Smacallan				if (!miComputeCompositeRegion (&region, pSrc,
1314e1ea03a3Smacallan				    pMask, pDst, xSrc, ySrc, xMask, yMask, xDst,
1315e1ea03a3Smacallan				    yDst, width, height)) {
1316e1ea03a3Smacallan					return;
1317e1ea03a3Smacallan				}
1318e1ea03a3Smacallan
1319e1ea03a3Smacallan				nbox = REGION_NUM_RECTS(&region);
1320e1ea03a3Smacallan				pbox = REGION_RECTS(&region);
1321e1ea03a3Smacallan
1322e1ea03a3Smacallan				if(!nbox) {
1323e1ea03a3Smacallan					return;
1324e1ea03a3Smacallan				}
1325e1ea03a3Smacallan
1326e1ea03a3Smacallan				XAAGetPixelFromRGBA(&pixel, red, green, blue, 0,
1327e1ea03a3Smacallan				    pDst->format);
1328e1ea03a3Smacallan
1329e1ea03a3Smacallan				xMask -= xDst;
1330e1ea03a3Smacallan				yMask -= yDst;
1331e1ea03a3Smacallan
1332e1ea03a3Smacallan				while(nbox--) {
1333e1ea03a3Smacallan					skipleft = pbox->x1 + xMask;
1334e1ea03a3Smacallan
1335e1ea03a3Smacallan					(*infoRec->WriteBitmap)(infoRec->pScrn, 					    pbox->x1, pbox->y1,
1336e1ea03a3Smacallan					    pbox->x2 - pbox->x1,
1337e1ea03a3Smacallan					    pbox->y2 - pbox->y1,
1338e1ea03a3Smacallan					    (unsigned char*)(pPix->devPrivate.ptr) + 					    (pPix->devKind *
1339e1ea03a3Smacallan					    (pbox->y1 + yMask)) + ((skipleft >> 3) & ~3),
1340e1ea03a3Smacallan					    pPix->devKind, skipleft & 31, pixel, -1,
1341e1ea03a3Smacallan					    GXcopy, ~0);
1342e1ea03a3Smacallan					pbox++;
1343e1ea03a3Smacallan				}
1344e1ea03a3Smacallan
1345e1ea03a3Smacallan				/* WriteBitmap sets the Sync flag */
1346e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1347e1ea03a3Smacallan				DONE(CRIME_DEBUG_XRENDER);
1348e1ea03a3Smacallan				return;
1349e1ea03a3Smacallan			}
135009f0d67cSmacallan			if((pMask->format == PICT_a8) ||
135109f0d67cSmacallan			   (pMask->format == PICT_a8r8g8b8)) {
1352e1ea03a3Smacallan
1353e1ea03a3Smacallan				w = pMask->pDrawable->width;
1354e1ea03a3Smacallan				h = pMask->pDrawable->height;
1355e1ea03a3Smacallan
1356e1ea03a3Smacallan				if(pMask->repeat) {
1357e1ea03a3Smacallan					flags |= XAA_RENDER_REPEAT;
1358e1ea03a3Smacallan				}
1359e1ea03a3Smacallan
1360e1ea03a3Smacallan				if (!miComputeCompositeRegion (&region, pSrc, pMask,
1361e1ea03a3Smacallan				    pDst, xSrc, ySrc, xMask, yMask, xDst, yDst,
1362e1ea03a3Smacallan				    width, height)) {
1363e1ea03a3Smacallan					return;
1364e1ea03a3Smacallan				}
1365e1ea03a3Smacallan
1366e1ea03a3Smacallan				nbox = REGION_NUM_RECTS(&region);
1367e1ea03a3Smacallan				pbox = REGION_RECTS(&region);
1368e1ea03a3Smacallan
1369e1ea03a3Smacallan				if(!nbox) {
1370e1ea03a3Smacallan					REGION_UNINIT(pScreen, &region);
1371e1ea03a3Smacallan					return;
1372e1ea03a3Smacallan				}
1373e1ea03a3Smacallan
1374e1ea03a3Smacallan				CrimeSetupForCPUToScreenAlphaTexture(infoRec->pScrn,
1375e1ea03a3Smacallan				    op, red, green, blue, alpha, pMask->format,
1376e1ea03a3Smacallan				    ((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr,
1377e1ea03a3Smacallan				    ((PixmapPtr)(pMask->pDrawable))->devKind,
1378e1ea03a3Smacallan				    w, h, flags);
1379e1ea03a3Smacallan
1380e1ea03a3Smacallan				xMask -= xDst;
1381e1ea03a3Smacallan				yMask -= yDst;
1382e1ea03a3Smacallan
138309f0d67cSmacallan				if (pMask->format != PICT_a8) {
138409f0d67cSmacallan					while(nbox--) {
138509f0d67cSmacallan						CrimeSubsequentCPUToScreenAlphaTexture32(
138609f0d67cSmacallan						    infoRec->pScrn,
138709f0d67cSmacallan						    pbox->x1, pbox->y1, pbox->x1 + xMask,
138809f0d67cSmacallan						    pbox->y1 + yMask, pbox->x2 - pbox->x1,
138909f0d67cSmacallan						    pbox->y2 - pbox->y1);
139009f0d67cSmacallan						pbox++;
139109f0d67cSmacallan					}
139209f0d67cSmacallan				} else {
139309f0d67cSmacallan					while(nbox--) {
139409f0d67cSmacallan						CrimeSubsequentCPUToScreenAlphaTexture(
139509f0d67cSmacallan						    infoRec->pScrn,
139609f0d67cSmacallan						    pbox->x1, pbox->y1, pbox->x1 + xMask,
139709f0d67cSmacallan						    pbox->y1 + yMask, pbox->x2 - pbox->x1,
139809f0d67cSmacallan						    pbox->y2 - pbox->y1);
139909f0d67cSmacallan						pbox++;
140009f0d67cSmacallan					}
1401e1ea03a3Smacallan				}
1402e1ea03a3Smacallan				SET_SYNC_FLAG(infoRec);
1403e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1404e1ea03a3Smacallan				DONE(CRIME_DEBUG_XRENDER);
1405e1ea03a3Smacallan				return;
1406e1ea03a3Smacallan			} else {
1407e1ea03a3Smacallan				xf86Msg(X_ERROR, "unknown mask %x\n", pMask->format);
1408e1ea03a3Smacallan			}
1409e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1410e1ea03a3Smacallan			DONE(CRIME_DEBUG_XRENDER);
1411e1ea03a3Smacallan			return;
1412e1ea03a3Smacallan		} else {
1413e1ea03a3Smacallan			/* source isn't solid */
1414e1ea03a3Smacallan
1415e1ea03a3Smacallan			w = pSrc->pDrawable->width;
1416e1ea03a3Smacallan			h = pSrc->pDrawable->height;
1417e1ea03a3Smacallan
1418e1ea03a3Smacallan			if(pSrc->repeat)
1419e1ea03a3Smacallan				flags |= XAA_RENDER_REPEAT;
1420e1ea03a3Smacallan
1421e1ea03a3Smacallan			if (!miComputeCompositeRegion (&region, pSrc, pMask,
1422e1ea03a3Smacallan			    pDst, xSrc, ySrc, xMask, yMask, xDst, yDst,
1423e1ea03a3Smacallan			    width, height)) {
1424e1ea03a3Smacallan				return;
1425e1ea03a3Smacallan			}
1426e1ea03a3Smacallan
1427e1ea03a3Smacallan			nbox = REGION_NUM_RECTS(&region);
1428e1ea03a3Smacallan			pbox = REGION_RECTS(&region);
1429e1ea03a3Smacallan
1430e1ea03a3Smacallan			if(!nbox) {
1431e1ea03a3Smacallan				REGION_UNINIT(pScreen, &region);
1432e1ea03a3Smacallan				return;
1433e1ea03a3Smacallan			}
1434e1ea03a3Smacallan			CrimeSetupForCPUToScreenTextureMask(
1435e1ea03a3Smacallan			    infoRec->pScrn, op, pMask->format,
1436e1ea03a3Smacallan			    ((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr,
1437e1ea03a3Smacallan			    ((PixmapPtr)(pSrc->pDrawable))->devKind,
1438e1ea03a3Smacallan			    ((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr,
1439e1ea03a3Smacallan			    ((PixmapPtr)(pMask->pDrawable))->devKind,
1440e1ea03a3Smacallan			    w, h, flags);
1441e1ea03a3Smacallan
1442e1ea03a3Smacallan			xSrc -= xDst;
1443e1ea03a3Smacallan			ySrc -= yDst;
1444e1ea03a3Smacallan
1445e1ea03a3Smacallan			if (PICT_FORMAT_BPP(pMask->format) == 32) {
1446e1ea03a3Smacallan				while(nbox--) {
1447e1ea03a3Smacallan					CrimeSubsequentCPUToScreenTextureMask32(
1448e1ea03a3Smacallan					    infoRec->pScrn,
1449e1ea03a3Smacallan					    pbox->x1, pbox->y1,
1450e1ea03a3Smacallan					    pbox->x1 + xSrc, pbox->y1 + ySrc,
1451e1ea03a3Smacallan					    xMask, yMask,
1452e1ea03a3Smacallan					    pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
1453e1ea03a3Smacallan					pbox++;
1454e1ea03a3Smacallan				}
1455e1ea03a3Smacallan			} else {
1456e1ea03a3Smacallan				while(nbox--) {
1457e1ea03a3Smacallan					CrimeSubsequentCPUToScreenTextureMask8(
1458e1ea03a3Smacallan					    infoRec->pScrn,
1459e1ea03a3Smacallan					    pbox->x1, pbox->y1, pbox->x1 + xSrc,
1460e1ea03a3Smacallan					    pbox->y1 + ySrc,
1461e1ea03a3Smacallan					    xMask, yMask,
1462e1ea03a3Smacallan					    pbox->x2 - pbox->x1,
1463e1ea03a3Smacallan					    pbox->y2 - pbox->y1);
1464e1ea03a3Smacallan					pbox++;
1465e1ea03a3Smacallan				}
1466e1ea03a3Smacallan			}
1467e1ea03a3Smacallan
1468e1ea03a3Smacallan			SET_SYNC_FLAG(infoRec);
1469e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1470e1ea03a3Smacallan			DONE(CRIME_DEBUG_XRENDER);
1471e1ea03a3Smacallan			return;
1472e1ea03a3Smacallan		}
1473e1ea03a3Smacallan	} else {	/* no mask */
1474e1ea03a3Smacallan		formats = infoRec->CPUToScreenTextureFormats;
1475e1ea03a3Smacallan
1476e1ea03a3Smacallan		w = pSrc->pDrawable->width;
1477e1ea03a3Smacallan		h = pSrc->pDrawable->height;
1478e1ea03a3Smacallan
1479e1ea03a3Smacallan		if(pSrc->repeat)
1480e1ea03a3Smacallan			flags |= XAA_RENDER_REPEAT;
1481e1ea03a3Smacallan
1482e1ea03a3Smacallan		while(*formats != pSrc->format) {
1483e1ea03a3Smacallan			if(!(*formats)) {
1484e1ea03a3Smacallan				xf86Msg(X_ERROR,
1485e1ea03a3Smacallan				    "%s: format %x not found\n",
1486e1ea03a3Smacallan				    __func__, pSrc->format);
1487e1ea03a3Smacallan				return;
1488e1ea03a3Smacallan			}
1489e1ea03a3Smacallan			formats++;
1490e1ea03a3Smacallan		}
1491e1ea03a3Smacallan
1492e1ea03a3Smacallan		if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
1493e1ea03a3Smacallan                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
1494e1ea03a3Smacallan                                   width, height)) {
1495e1ea03a3Smacallan			return;
1496e1ea03a3Smacallan		}
1497e1ea03a3Smacallan
1498e1ea03a3Smacallan		nbox = REGION_NUM_RECTS(&region);
1499e1ea03a3Smacallan		pbox = REGION_RECTS(&region);
1500e1ea03a3Smacallan
1501e1ea03a3Smacallan		if(!nbox) {
1502e1ea03a3Smacallan			REGION_UNINIT(pScreen, &region);
1503e1ea03a3Smacallan			return;
1504e1ea03a3Smacallan		}
1505e1ea03a3Smacallan
1506e1ea03a3Smacallan		CrimeSetupForCPUToScreenTexture(infoRec->pScrn,
1507e1ea03a3Smacallan			op, pSrc->format,
1508e1ea03a3Smacallan			((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr,
1509e1ea03a3Smacallan			((PixmapPtr)(pSrc->pDrawable))->devKind,
1510e1ea03a3Smacallan			w, h, flags);
1511e1ea03a3Smacallan
1512e1ea03a3Smacallan		xSrc -= xDst;
1513e1ea03a3Smacallan		ySrc -= yDst;
1514e1ea03a3Smacallan
1515e1ea03a3Smacallan		while(nbox--) {
1516e1ea03a3Smacallan			CrimeSubsequentCPUToScreenTexture(infoRec->pScrn,
1517e1ea03a3Smacallan			    pbox->x1, pbox->y1, pbox->x1 + xSrc,
1518e1ea03a3Smacallan			    pbox->y1 + ySrc, pbox->x2 - pbox->x1,
1519e1ea03a3Smacallan			    pbox->y2 - pbox->y1);
1520e1ea03a3Smacallan			pbox++;
1521e1ea03a3Smacallan		}
1522e1ea03a3Smacallan
1523e1ea03a3Smacallan		SET_SYNC_FLAG(infoRec);
1524e1ea03a3Smacallan		REGION_UNINIT(pScreen, &region);
1525e1ea03a3Smacallan		DONE(CRIME_DEBUG_XRENDER);
1526e1ea03a3Smacallan		return;
1527e1ea03a3Smacallan	}
1528e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: shouldn't be here\n", __func__);
1529e1ea03a3Smacallan}
1530e1ea03a3Smacallan
1531e1ea03a3Smacallanstatic void
1532e1ea03a3SmacallanCrimeDoScreenToScreenComposite(
1533e1ea03a3Smacallan   	CARD8      op,
1534e1ea03a3Smacallan        PicturePtr pSrc,
1535e1ea03a3Smacallan        PicturePtr pMask,
1536e1ea03a3Smacallan        PicturePtr pDst,
1537e1ea03a3Smacallan        INT16      xSrc,
1538e1ea03a3Smacallan        INT16      ySrc,
1539e1ea03a3Smacallan        INT16      xMask,
1540e1ea03a3Smacallan        INT16      yMask,
1541e1ea03a3Smacallan        INT16      xDst,
1542e1ea03a3Smacallan        INT16      yDst,
1543e1ea03a3Smacallan        CARD16     width,
1544e1ea03a3Smacallan        CARD16     height
1545e1ea03a3Smacallan)
1546e1ea03a3Smacallan{
1547e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1548e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1549e1ea03a3Smacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1550e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1551e1ea03a3Smacallan	RegionRec region;
1552e1ea03a3Smacallan	CARD32 *formats;
1553e1ea03a3Smacallan	int flags = 0;
1554e1ea03a3Smacallan	BoxPtr pbox;
1555e1ea03a3Smacallan	int nbox;
1556e1ea03a3Smacallan	int xs, ys, xd, yd, w, h;
1557e1ea03a3Smacallan
1558e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1559e1ea03a3Smacallan	if (pSrc->transform || (pMask && pMask->transform)) {
1560e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: mask?!\n", __func__);
1561e1ea03a3Smacallan		return;
1562e1ea03a3Smacallan	}
1563e1ea03a3Smacallan	xf86Msg(X_ERROR, "%s: %d\n", __func__, op);
1564e1ea03a3Smacallan	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) {
1565e1ea03a3Smacallan		xf86Msg(X_ERROR, "%s: alpha-map\n", __func__);
1566e1ea03a3Smacallan		return;
1567e1ea03a3Smacallan	}
1568e1ea03a3Smacallan
1569e1ea03a3Smacallan	xDst += pDst->pDrawable->x;
1570e1ea03a3Smacallan	yDst += pDst->pDrawable->y;
1571e1ea03a3Smacallan	xSrc += pSrc->pDrawable->x;
1572e1ea03a3Smacallan	ySrc += pSrc->pDrawable->y;
1573e1ea03a3Smacallan
1574e1ea03a3Smacallan	formats = infoRec->CPUToScreenTextureFormats;
1575e1ea03a3Smacallan
1576e1ea03a3Smacallan	w = pSrc->pDrawable->width;
1577e1ea03a3Smacallan	h = pSrc->pDrawable->height;
1578e1ea03a3Smacallan
1579e1ea03a3Smacallan	if(pSrc->repeat)
1580e1ea03a3Smacallan		flags |= XAA_RENDER_REPEAT;
1581e1ea03a3Smacallan
1582e1ea03a3Smacallan	while(*formats != pSrc->format) {
1583e1ea03a3Smacallan		if(!(*formats)) return;
1584e1ea03a3Smacallan		formats++;
1585e1ea03a3Smacallan	}
1586e1ea03a3Smacallan
1587e1ea03a3Smacallan	if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
1588e1ea03a3Smacallan	    xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
1589e1ea03a3Smacallan		return;
1590e1ea03a3Smacallan
1591e1ea03a3Smacallan	nbox = REGION_NUM_RECTS(&region);
1592e1ea03a3Smacallan	pbox = REGION_RECTS(&region);
1593e1ea03a3Smacallan
1594e1ea03a3Smacallan	if(!nbox) {
1595e1ea03a3Smacallan		REGION_UNINIT(pScreen, &region);
1596e1ea03a3Smacallan		return;
1597e1ea03a3Smacallan	}
1598e1ea03a3Smacallan
159926dcc2a3Smacallan	MAKE_ROOM(6);
1600e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_SRC, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
1601e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
160226dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
160326dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1604e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_X, 1);
1605e1ea03a3Smacallan	WRITE4(CRIME_DE_ALPHA_FUNC,
1606e1ea03a3Smacallan	    DE_ALPHA_ADD |
1607e1ea03a3Smacallan	    (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) |
1608e1ea03a3Smacallan	    (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT));
1609e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1610e1ea03a3Smacallan	    DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ALPHA_BLEND |
1611e1ea03a3Smacallan	    DE_DRAWMODE_XFER_EN);
1612e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE,
1613e1ea03a3Smacallan		DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
161426dcc2a3Smacallan	SYNC;
1615e1ea03a3Smacallan	xSrc -= xDst;
1616e1ea03a3Smacallan	ySrc -= yDst;
1617e1ea03a3Smacallan
1618e1ea03a3Smacallan	/* assume no overlap - might bite us in the arse at some point */
1619e1ea03a3Smacallan	while(nbox--) {
1620e1ea03a3Smacallan		xs = pbox->x1 + xSrc;
1621e1ea03a3Smacallan		ys = pbox->y1 + ySrc;
1622e1ea03a3Smacallan		xd = pbox->x1;
1623e1ea03a3Smacallan		yd = pbox->y1;
1624e1ea03a3Smacallan		w = pbox->x2 - pbox->x1;
1625e1ea03a3Smacallan		h = pbox->y2 - pbox->y1;
162626dcc2a3Smacallan		MAKE_ROOM(3);
1627e1ea03a3Smacallan		WRITE4(CRIME_DE_XFER_ADDR_SRC,(xs << 16) | (ys & 0xffff));
1628e1ea03a3Smacallan		WRITE4(CRIME_DE_X_VERTEX_0, (xd << 16) | (yd & 0xffff));
1629e1ea03a3Smacallan		WRITE4ST(CRIME_DE_X_VERTEX_1,
1630e1ea03a3Smacallan		    ((xd + w - 1) << 16) | ((yd + h - 1) & 0xffff));
1631e1ea03a3Smacallan		pbox++;
1632e1ea03a3Smacallan	}
1633e1ea03a3Smacallan
1634e1ea03a3Smacallan	SET_SYNC_FLAG(infoRec);
1635e1ea03a3Smacallan	REGION_UNINIT(pScreen, &region);
1636e1ea03a3Smacallan	return;
1637e1ea03a3Smacallan}
1638e1ea03a3Smacallan
1639e1ea03a3Smacallanstatic Bool
1640e1ea03a3SmacallanCrimeComposite(
1641e1ea03a3Smacallan   	CARD8      op,
1642e1ea03a3Smacallan        PicturePtr pSrc,
1643e1ea03a3Smacallan        PicturePtr pMask,
1644e1ea03a3Smacallan        PicturePtr pDst,
1645e1ea03a3Smacallan        INT16      xSrc,
1646e1ea03a3Smacallan        INT16      ySrc,
1647e1ea03a3Smacallan        INT16      xMask,
1648e1ea03a3Smacallan        INT16      yMask,
1649e1ea03a3Smacallan        INT16      xDst,
1650e1ea03a3Smacallan        INT16      yDst,
1651e1ea03a3Smacallan        CARD16     width,
1652e1ea03a3Smacallan        CARD16     height
1653e1ea03a3Smacallan)
1654e1ea03a3Smacallan{
1655e1ea03a3Smacallan	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1656e1ea03a3Smacallan	XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
1657e1ea03a3Smacallan
1658e1ea03a3Smacallan	LOG(CRIME_DEBUG_XRENDER);
1659e1ea03a3Smacallan
1660e1ea03a3Smacallan	if(!REGION_NUM_RECTS(pDst->pCompositeClip))
1661e1ea03a3Smacallan		return TRUE;
1662e1ea03a3Smacallan
1663e1ea03a3Smacallan	if(!infoRec->pScrn->vtSema)
1664e1ea03a3Smacallan		return FALSE;
1665e1ea03a3Smacallan
1666e1ea03a3Smacallan	if((pDst->pDrawable->type == DRAWABLE_WINDOW) ||
1667e1ea03a3Smacallan	    IS_OFFSCREEN_PIXMAP(pDst->pDrawable)) {
1668e1ea03a3Smacallan		if ((pSrc->pDrawable->type == DRAWABLE_WINDOW) ||
1669e1ea03a3Smacallan		    IS_OFFSCREEN_PIXMAP(pSrc->pDrawable)) {
1670e1ea03a3Smacallan			/* screen-to-screen */
1671e1ea03a3Smacallan			CrimeDoScreenToScreenComposite(op, pSrc, pMask, pDst,
1672e1ea03a3Smacallan			    xSrc, ySrc, xMask, yMask,
1673e1ea03a3Smacallan			    xDst, yDst, width, height);
1674e1ea03a3Smacallan			return TRUE;
1675e1ea03a3Smacallan		} else {
1676e1ea03a3Smacallan			/* CPU-to-screen composite */
1677e1ea03a3Smacallan			if (op != PictOpOver)
1678e1ea03a3Smacallan				xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
1679e1ea03a3Smacallan			CrimeDoCPUToScreenComposite(op, pSrc, pMask, pDst,
1680e1ea03a3Smacallan			    xSrc, ySrc, xMask, yMask,
1681e1ea03a3Smacallan			    xDst, yDst, width, height);
1682e1ea03a3Smacallan			return TRUE;
1683e1ea03a3Smacallan		}
1684e1ea03a3Smacallan	} else {
1685e1ea03a3Smacallan		if ((pSrc->pDrawable->type == DRAWABLE_WINDOW) ||
1686e1ea03a3Smacallan		    IS_OFFSCREEN_PIXMAP(pSrc->pDrawable)) {
1687e1ea03a3Smacallan			/* screen-to-RAM */
1688e1ea03a3Smacallan			xf86Msg(X_ERROR, "%s: screen-to-RAM composite\n",
1689e1ea03a3Smacallan			   __func__);
1690e1ea03a3Smacallan			return TRUE;
1691e1ea03a3Smacallan		} else {
1692e1ea03a3Smacallan			/* RAM-to-RAM */
1693e1ea03a3Smacallan			return FALSE;
1694e1ea03a3Smacallan		}
1695e1ea03a3Smacallan	}
1696e1ea03a3Smacallan	xf86Msg(X_ERROR, "composite fucked\n");
1697e1ea03a3Smacallan}
1698e1ea03a3Smacallan
1699e1ea03a3Smacallanstatic void
1700e1ea03a3SmacallanCrimePolyPoint(
1701e1ea03a3Smacallan    DrawablePtr pDraw,
1702e1ea03a3Smacallan    GCPtr pGC,
1703e1ea03a3Smacallan    int mode,
1704e1ea03a3Smacallan    int npt,
1705e1ea03a3Smacallan    xPoint *pptInit
1706e1ea03a3Smacallan)
1707e1ea03a3Smacallan{
1708e1ea03a3Smacallan	ScreenPtr pScreen = pDraw->pScreen;
1709e1ea03a3Smacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1710e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1711e1ea03a3Smacallan	BoxPtr pBox;
1712e1ea03a3Smacallan	xPoint *ppt, *pts;
1713e1ea03a3Smacallan	int x1, x2, y1, y2, x, y, i, nBox;
1714e1ea03a3Smacallan
1715e1ea03a3Smacallan	/* make pointlist origin relative */
1716e1ea03a3Smacallan	ppt = pptInit;
1717e1ea03a3Smacallan	if (mode == CoordModePrevious) {
1718e1ea03a3Smacallan		for (i = 0; i < npt; i++) {
1719e1ea03a3Smacallan			ppt++;
1720e1ea03a3Smacallan			ppt->x += (ppt-1)->x;
1721e1ea03a3Smacallan			ppt->y += (ppt-1)->y;
1722e1ea03a3Smacallan		}
1723e1ea03a3Smacallan	}
172426dcc2a3Smacallan	MAKE_ROOM(6);
172526dcc2a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
172626dcc2a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1727e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, pGC->fgPixel << 8);
1728e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, pGC->alu);
1729e1ea03a3Smacallan	WRITE4(CRIME_DE_PLANEMASK, pGC->planemask);
1730e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1731e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP);
1732e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE, DE_PRIM_POINT);
173326dcc2a3Smacallan	SYNC;
1734e1ea03a3Smacallan	for (nBox = REGION_NUM_RECTS (pGC->pCompositeClip),
1735e1ea03a3Smacallan	    pBox = REGION_RECTS (pGC->pCompositeClip);
1736e1ea03a3Smacallan	    nBox--; pBox++) {
1737e1ea03a3Smacallan
1738e1ea03a3Smacallan		pts = pptInit;
1739e1ea03a3Smacallan		for (i = 0; i < npt; i++) {
1740e1ea03a3Smacallan			x1 = pBox->x1;
1741e1ea03a3Smacallan			y1 = pBox->y1;
1742e1ea03a3Smacallan			x2 = pBox->x2;
1743e1ea03a3Smacallan			y2 = pBox->y2;
1744e1ea03a3Smacallan			x = pts->x + pDraw->x;
1745e1ea03a3Smacallan			y = pts->y + pDraw->y;
1746e1ea03a3Smacallan			if (x1 <= x && x < x2 && y1 <= y && y < y2) {
1747e1ea03a3Smacallan
174826dcc2a3Smacallan		 		MAKE_ROOM(1);
1749e1ea03a3Smacallan				WRITE4ST(CRIME_DE_X_VERTEX_0,
1750e1ea03a3Smacallan					(x << 16) | y);
1751e1ea03a3Smacallan			}
1752e1ea03a3Smacallan			pts++;
1753e1ea03a3Smacallan		}
1754e1ea03a3Smacallan	}
1755e1ea03a3Smacallan}
1756e1ea03a3Smacallan
1757e1ea03a3Smacallanstatic void
1758e1ea03a3SmacallanCrimeValidatePolyPoint(
1759e1ea03a3Smacallan   GCPtr         pGC,
1760e1ea03a3Smacallan   unsigned long changes,
1761e1ea03a3Smacallan   DrawablePtr   pDraw )
1762e1ea03a3Smacallan{
1763e1ea03a3Smacallan
1764e1ea03a3Smacallan	if ((pDraw->type == DRAWABLE_WINDOW) ||
1765e1ea03a3Smacallan	    IS_OFFSCREEN_PIXMAP(pDraw)) {
1766e1ea03a3Smacallan		pGC->ops->PolyPoint = CrimePolyPoint;
1767e1ea03a3Smacallan	} else
1768e1ea03a3Smacallan		xf86Msg(X_ERROR, "boo\n");
1769e1ea03a3Smacallan}
177034c4e112Smacallanstatic void
177134c4e112SmacallanCrimePolyArc(DrawablePtr pDraw,
177234c4e112Smacallan               GCPtr pGC,
177334c4e112Smacallan               int narcs,
177434c4e112Smacallan               xArc *parcs)
177534c4e112Smacallan{
177634c4e112Smacallan    xArc *arc;
177734c4e112Smacallan    BoxRec box;
177834c4e112Smacallan    int i, x2, y2;
177934c4e112Smacallan    RegionPtr cclip;
178034c4e112Smacallan
178134c4e112Smacallan    cclip = pGC->pCompositeClip;
178234c4e112Smacallan
178334c4e112Smacallan    if(!REGION_NUM_RECTS(cclip))
178434c4e112Smacallan	return;
178534c4e112Smacallan
178634c4e112Smacallan    for (arc = parcs, i = narcs; --i >= 0; arc++) {
178734c4e112Smacallan	if (miCanZeroArc(arc)) {
178834c4e112Smacallan	    box.x1 = arc->x + pDraw->x;
178934c4e112Smacallan	    box.y1 = arc->y + pDraw->y;
179034c4e112Smacallan 	    x2 = box.x1 + (int)arc->width + 1;
179134c4e112Smacallan 	    box.x2 = x2;
179234c4e112Smacallan 	    y2 = box.y1 + (int)arc->height + 1;
179334c4e112Smacallan 	    box.y2 = y2;
179434c4e112Smacallan 	    if ( (x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) &&
179534c4e112Smacallan 		    (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) )
179634c4e112Smacallan		miZeroPolyArc(pDraw, pGC, 1, arc);
179734c4e112Smacallan	}
179834c4e112Smacallan	else
179934c4e112Smacallan	    miPolyArc(pDraw, pGC, 1, arc);
180034c4e112Smacallan    }
180134c4e112Smacallan}
180234c4e112Smacallan
180334c4e112Smacallanstatic void
180434c4e112SmacallanCrimeValidatePolyArc(GCPtr pGC,
180534c4e112Smacallan                       unsigned long changes,
180634c4e112Smacallan                       DrawablePtr pDraw)
180734c4e112Smacallan{
180834c4e112Smacallan	if ((pDraw->type == DRAWABLE_WINDOW) ||
180934c4e112Smacallan	    IS_OFFSCREEN_PIXMAP(pDraw)) {
181034c4e112Smacallan		pGC->ops->PolyPoint = CrimePolyPoint;
181134c4e112Smacallan		/*pGC->ops->PolyArc = miPolyArc;*/
181234c4e112Smacallan		pGC->ops->PolyArc = CrimePolyArc;
181334c4e112Smacallan	} else
181434c4e112Smacallan	{
181534c4e112Smacallan		pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint;
181634c4e112Smacallan		pGC->ops->PolyArc = XAAGetFallbackOps()->PolyArc;
181734c4e112Smacallan	}
181834c4e112Smacallan}
1819e1ea03a3Smacallan
182026dcc2a3Smacallanstatic void copyRGBAtoARGB(uint32_t *dest, uint32_t *src, int len)
182126dcc2a3Smacallan{
182226dcc2a3Smacallan	while (len > 0) {
182326dcc2a3Smacallan		*dest = *src >> 8;
182426dcc2a3Smacallan		dest++;
182526dcc2a3Smacallan		src++;
182626dcc2a3Smacallan		len--;
182726dcc2a3Smacallan	}
182826dcc2a3Smacallan}
182926dcc2a3Smacallan
183034c4e112Smacallanstatic void
183134c4e112SmacallanCrimeReadPixmap(ScrnInfoPtr pScrn,
183234c4e112Smacallan                     int x,
183334c4e112Smacallan		     int y,
183434c4e112Smacallan		     int w,
183534c4e112Smacallan		     int h,
183634c4e112Smacallan		     unsigned char *dst,
183734c4e112Smacallan		     int dstwidth,
183834c4e112Smacallan		     int bpp,
183934c4e112Smacallan		     int depth)
184034c4e112Smacallan{
184126dcc2a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
184226dcc2a3Smacallan	int bufno = 0;
184326dcc2a3Smacallan	int nextbuf, i, len = w << 2;
184426dcc2a3Smacallan	int mx = x << 2, offset;
184526dcc2a3Smacallan
184626dcc2a3Smacallan	offset = mx & 0x3f;
184726dcc2a3Smacallan	mx &= ~0x3f;
184826dcc2a3Smacallan	len = (len + offset + 0x3f) & ~0x3f;
184926dcc2a3Smacallan
185026dcc2a3Smacallan	LOG(CRIME_DEBUG_IMAGEREAD);
185126dcc2a3Smacallan
185226dcc2a3Smacallan#ifdef CRIME_DEBUG_LOUD
185326dcc2a3Smacallan	xf86Msg(X_ERROR, "%s: %d %d %d %d\n", __func__, x, y, w, h);
185426dcc2a3Smacallan#endif
185526dcc2a3Smacallan
185626dcc2a3Smacallan	MAKE_ROOM(3);
185726dcc2a3Smacallan
185826dcc2a3Smacallan	/*
185926dcc2a3Smacallan	 * apparently all MTE coordinates are in bytes, not pixels
186026dcc2a3Smacallan	 * also, the MTE has some crazy alignment requirements - if
186126dcc2a3Smacallan	 * we don't do as above the thing will deadlock sooner or later
186226dcc2a3Smacallan	 * We use the MTE here because I couldn't get the rendering engine
186326dcc2a3Smacallan	 * to actually transfer anything into a linear buffer. The other
186426dcc2a3Smacallan	 * way around works just fine though. Shouldn't make much of a
186526dcc2a3Smacallan	 * difference, transfer times should be dominated by copying
186626dcc2a3Smacallan	 * data in and out of the DMA buffer anyway
186726dcc2a3Smacallan	 */
186826dcc2a3Smacallan	WRITE4(CRIME_MTE_MODE, (MTE_TLB_LIN_A << MTE_DST_TLB_SHIFT) |
186926dcc2a3Smacallan			 (MTE_TLB_A << MTE_SRC_TLB_SHIFT) |
187026dcc2a3Smacallan			 (MTE_DEPTH_8 << MTE_DEPTH_SHIFT) |
187126dcc2a3Smacallan			 MTE_MODE_DST_ECC | MTE_MODE_COPY);
187226dcc2a3Smacallan	WRITE4(CRIME_MTE_SRC_Y_STEP, 1);
187326dcc2a3Smacallan	WRITE4(CRIME_MTE_DST_Y_STEP, 1);
187426dcc2a3Smacallan	SYNCMTE;
187526dcc2a3Smacallan	WRITE4(CRIME_MTE_SRC0, (mx << 16) | y);
187626dcc2a3Smacallan	WRITE4(CRIME_MTE_SRC1, ((mx + len) << 16) | y);
187726dcc2a3Smacallan	WRITE4(CRIME_MTE_DST0, (bufno << 13));
187826dcc2a3Smacallan	WRITE4ST(CRIME_MTE_DST1, (bufno << 13) + len);
187926dcc2a3Smacallan	for (i = y + 1; i < y + h; i++) {
188026dcc2a3Smacallan		nextbuf = (bufno + 1) & 7;
188126dcc2a3Smacallan		SYNCMTE;
188226dcc2a3Smacallan		WRITE4(CRIME_MTE_SRC0, (mx << 16) | i);
188326dcc2a3Smacallan		WRITE4(CRIME_MTE_SRC1, ((mx + len) << 16) | i);
188426dcc2a3Smacallan		WRITE4(CRIME_MTE_DST0, (nextbuf << 13));
188526dcc2a3Smacallan		WRITE4ST(CRIME_MTE_DST1, (nextbuf << 13) + len);
188626dcc2a3Smacallan		copyRGBAtoARGB((uint32_t *)dst,
188726dcc2a3Smacallan			       (uint32_t *)(fPtr->buffers[bufno] + offset), w);
188826dcc2a3Smacallan		dst += dstwidth;
188926dcc2a3Smacallan		bufno = nextbuf;
189026dcc2a3Smacallan	}
189126dcc2a3Smacallan	SYNCMTE;
189226dcc2a3Smacallan	copyRGBAtoARGB((uint32_t *)dst,
189326dcc2a3Smacallan		       (uint32_t *)(fPtr->buffers[bufno] + offset), w);
189426dcc2a3Smacallan	DONE(CRIME_DEBUG_IMAGEREAD);
189526dcc2a3Smacallan
189634c4e112Smacallan}
1897e1ea03a3Smacallanint
1898e1ea03a3SmacallanCrimeAccelInit(ScrnInfoPtr pScrn)
1899e1ea03a3Smacallan{
1900e1ea03a3Smacallan	CrimePtr fPtr = CRIMEPTR(pScrn);
1901e1ea03a3Smacallan	XAAInfoRecPtr pXAAInfo = fPtr->pXAA;
1902e1ea03a3Smacallan	int i;
1903e1ea03a3Smacallan
1904e1ea03a3Smacallan	for (i = 0; i < 0x1000; i++) regcache[i] = 0x12345678;
1905e1ea03a3Smacallan	LOG(CRIME_DEBUG_ALL);
1906e1ea03a3Smacallan	SYNC;
1907e1ea03a3Smacallan	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
1908e1ea03a3Smacallan			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1909e1ea03a3Smacallan
1910e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STEP_Y, 1);
191126dcc2a3Smacallan	WRITE4(CRIME_DE_XFER_STRD_DST, 4);
1912e1ea03a3Smacallan	WRITE4(CRIME_DE_XFER_STRD_SRC, 1);
1913e1ea03a3Smacallan
1914e1ea03a3Smacallan	WRITE4(CRIME_MTE_BYTEMASK, 0xffffffff);
1915e1ea03a3Smacallan	WRITE4(CRIME_MTE_SRC_Y_STEP, 4);
1916e1ea03a3Smacallan	WRITE4(CRIME_MTE_DST_Y_STEP, 4);
191726dcc2a3Smacallan	SYNC;
1918e1ea03a3Smacallan
1919e1ea03a3Smacallan	/* blit the screen black */
1920e1ea03a3Smacallan	WRITE4(CRIME_DE_DRAWMODE,
1921e1ea03a3Smacallan	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP);
1922e1ea03a3Smacallan	WRITE4(CRIME_DE_ROP, 3);
1923e1ea03a3Smacallan	WRITE4(CRIME_DE_PRIMITIVE, DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
1924e1ea03a3Smacallan	WRITE4(CRIME_DE_FG, 0);
1925e1ea03a3Smacallan	WRITE4(CRIME_DE_X_VERTEX_0, 0);
1926e1ea03a3Smacallan	WRITE4ST(CRIME_DE_X_VERTEX_1,
1927e1ea03a3Smacallan	    fPtr->info.width << 16 | fPtr->info.height);
1928e1ea03a3Smacallan	SYNC;
1929e1ea03a3Smacallan
193034c4e112Smacallan	pXAAInfo->Flags = /*LINEAR_FRAMEBUFFER |*/ PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
1931e1ea03a3Smacallan	pXAAInfo->maxOffPixWidth = fPtr->info.width;
1932e1ea03a3Smacallan	pXAAInfo->maxOffPixHeight = 2048;
1933e1ea03a3Smacallan
1934e1ea03a3Smacallan	/* Sync */
1935e1ea03a3Smacallan	pXAAInfo->Sync = CrimeSync;
1936e1ea03a3Smacallan
1937e1ea03a3Smacallan	/* Screen-to-screen copy */
1938e1ea03a3Smacallan	pXAAInfo->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
1939e1ea03a3Smacallan	pXAAInfo->SetupForScreenToScreenCopy = CrimeSetupForScreenToScreenCopy;
1940e1ea03a3Smacallan	pXAAInfo->SubsequentScreenToScreenCopy =
1941e1ea03a3Smacallan		CrimeSubsequentScreenToScreenCopy;
1942e1ea03a3Smacallan
1943e1ea03a3Smacallan	/* rectangle fills */
1944e1ea03a3Smacallan	pXAAInfo->SetupForSolidFill = CrimeSetupForSolidFill;
1945e1ea03a3Smacallan	pXAAInfo->SubsequentSolidFillRect = CrimeSubsequentSolidFillRect;
1946e1ea03a3Smacallan
1947e1ea03a3Smacallan	/* image writes */
1948e1ea03a3Smacallan	pXAAInfo->ScanlineImageWriteFlags =
1949e1ea03a3Smacallan	    NO_TRANSPARENCY | LEFT_EDGE_CLIPPING |
1950e1ea03a3Smacallan	    LEFT_EDGE_CLIPPING_NEGATIVE_X |
1951e1ea03a3Smacallan	    CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD;
1952e1ea03a3Smacallan	pXAAInfo->NumScanlineImageWriteBuffers = 8;
1953e1ea03a3Smacallan	for (i = 0; i < 8; i++)
1954e1ea03a3Smacallan		fPtr->buffers[i] = fPtr->linear + (i * 8192);
1955e1ea03a3Smacallan	pXAAInfo->ScanlineImageWriteBuffers = fPtr->buffers;
1956e1ea03a3Smacallan	pXAAInfo->SetupForScanlineImageWrite =
1957e1ea03a3Smacallan		CrimeSetupForScanlineImageWrite;
1958e1ea03a3Smacallan	pXAAInfo->SubsequentScanlineImageWriteRect =
1959e1ea03a3Smacallan		CrimeSubsequentImageWriteRect;
1960e1ea03a3Smacallan	pXAAInfo->SubsequentImageWriteScanline =
1961e1ea03a3Smacallan		CrimeSubsequentImageWriteScanline;
1962e1ea03a3Smacallan
196334c4e112Smacallan	/* read pixmap */
196434c4e112Smacallan	pXAAInfo->ReadPixmapFlags = 0
196534c4e112Smacallan	                             | CPU_TRANSFER_PAD_DWORD
196634c4e112Smacallan				     ;
196734c4e112Smacallan	pXAAInfo->ReadPixmap = CrimeReadPixmap;
196834c4e112Smacallan
1969e1ea03a3Smacallan	/* colour expansion */
1970e1ea03a3Smacallan	pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags =
1971e1ea03a3Smacallan		LEFT_EDGE_CLIPPING;
1972e1ea03a3Smacallan	pXAAInfo->NumScanlineColorExpandBuffers = 1;
1973e1ea03a3Smacallan	fPtr->expandbuffers[0] = (uint8_t *)fPtr->expand;
1974e1ea03a3Smacallan	pXAAInfo->ScanlineColorExpandBuffers = (void *)&fPtr->expandbuffers;
1975e1ea03a3Smacallan	pXAAInfo->SetupForScanlineCPUToScreenColorExpandFill =
1976e1ea03a3Smacallan		CrimeSetupForCPUToScreenColorExpandFill;
1977e1ea03a3Smacallan	pXAAInfo->SubsequentScanlineCPUToScreenColorExpandFill =
1978e1ea03a3Smacallan		CrimeSubsequentScanlineCPUToScreenColorExpandFill;
1979e1ea03a3Smacallan	pXAAInfo->SubsequentColorExpandScanline =
1980e1ea03a3Smacallan		CrimeSubsequentColorExpandScanline;
1981e1ea03a3Smacallan
1982e1ea03a3Smacallan	/* clipping */
1983e1ea03a3Smacallan	pXAAInfo->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
19845b2650b9Smacallan		HARDWARE_CLIP_SOLID_FILL | HARDWARE_CLIP_SOLID_LINE |
19855b2650b9Smacallan		HARDWARE_CLIP_MONO_8x8_FILL | HARDWARE_CLIP_DASHED_LINE;
1986e1ea03a3Smacallan	pXAAInfo->SetClippingRectangle = CrimeSetClippingRectangle;
1987e1ea03a3Smacallan	pXAAInfo->DisableClipping = CrimeDisableClipping;
1988e1ea03a3Smacallan
1989e1ea03a3Smacallan	/* solid line drawing */
1990e1ea03a3Smacallan	pXAAInfo->SetupForSolidLine = CrimeSetupForSolidLine;
1991e1ea03a3Smacallan	pXAAInfo->SubsequentSolidTwoPointLine =
1992e1ea03a3Smacallan	    CrimeSubsequentSolidTwoPointLine;
19935b2650b9Smacallan	pXAAInfo->SolidLineFlags = 0;
1994e1ea03a3Smacallan
1995e1ea03a3Smacallan	/* dashed line drawing */
1996e1ea03a3Smacallan	pXAAInfo->SetupForDashedLine = CrimeSetupForDashedLine;
1997e1ea03a3Smacallan	pXAAInfo->SubsequentDashedTwoPointLine =
1998e1ea03a3Smacallan	    CrimeSubsequentDashedTwoPointLine;
1999e1ea03a3Smacallan	pXAAInfo->DashedLineFlags = LINE_PATTERN_MSBFIRST_MSBJUSTIFIED;
2000e1ea03a3Smacallan	pXAAInfo->DashPatternMaxLength = 32;
2001e1ea03a3Smacallan
20025b2650b9Smacallan	/* mono pattern fills */
20035b2650b9Smacallan	pXAAInfo->Mono8x8PatternFillFlags = HARDWARE_PATTERN_PROGRAMMED_BITS |
20045b2650b9Smacallan	    HARDWARE_PATTERN_PROGRAMMED_ORIGIN | BIT_ORDER_IN_BYTE_MSBFIRST;
20055b2650b9Smacallan	pXAAInfo->SetupForMono8x8PatternFill = CrimeSetupForMono8x8PatternFill;
20065b2650b9Smacallan	pXAAInfo->SubsequentMono8x8PatternFillRect =
20075b2650b9Smacallan	    CrimeSubsequentMono8x8PatternFillRect;
20085b2650b9Smacallan
2009e1ea03a3Smacallan	/* XRender acceleration */
2010e1ea03a3Smacallan#ifdef RENDER
2011e1ea03a3Smacallan	pXAAInfo->CPUToScreenAlphaTextureFlags = 0;
2012e1ea03a3Smacallan	pXAAInfo->SetupForCPUToScreenAlphaTexture =
2013e1ea03a3Smacallan	    CrimeSetupForCPUToScreenAlphaTexture;
2014e1ea03a3Smacallan	pXAAInfo->SubsequentCPUToScreenAlphaTexture =
2015e1ea03a3Smacallan	    CrimeSubsequentCPUToScreenAlphaTexture;
2016e1ea03a3Smacallan	pXAAInfo->CPUToScreenAlphaTextureFormats = CrimeAlphaTextureFormats;
2017e1ea03a3Smacallan
2018e1ea03a3Smacallan	pXAAInfo->SetupForCPUToScreenTexture = CrimeSetupForCPUToScreenTexture;
2019e1ea03a3Smacallan	pXAAInfo->SubsequentCPUToScreenTexture =
2020e1ea03a3Smacallan	    CrimeSubsequentCPUToScreenTexture;
2021e1ea03a3Smacallan	pXAAInfo->CPUToScreenTextureFlags = 0;
2022e1ea03a3Smacallan	pXAAInfo->CPUToScreenTextureFormats = CrimeTextureFormats;
2023e1ea03a3Smacallan	pXAAInfo->Composite = CrimeComposite;
2024e1ea03a3Smacallan#endif
2025e1ea03a3Smacallan	pXAAInfo->ValidatePolyPoint = CrimeValidatePolyPoint;
2026e1ea03a3Smacallan	pXAAInfo->PolyPointMask = GCFunction;
202734c4e112Smacallan	pXAAInfo->ValidatePolyArc = CrimeValidatePolyArc;
202834c4e112Smacallan	pXAAInfo->PolyArcMask = GCFunction | GCLineWidth;
2029e1ea03a3Smacallan
2030e1ea03a3Smacallan	return -1;
2031e1ea03a3Smacallan}
2032