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