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