crime_accel.c revision f282839b
1/* $NetBSD: crime_accel.c,v 1.12 2009/10/06 06:25:47 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	    PIXMAP_IS_SCREEN(pDst->pDrawable)) {
1709		if ((pSrc->pDrawable->type == DRAWABLE_WINDOW) ||
1710		    IS_OFFSCREEN_PIXMAP(pSrc->pDrawable) ||
1711		    PIXMAP_IS_SCREEN(pSrc->pDrawable)) {
1712			/* screen-to-screen */
1713			CrimeDoScreenToScreenComposite(op, pSrc, pMask, pDst,
1714			    xSrc, ySrc, xMask, yMask,
1715			    xDst, yDst, width, height);
1716			return TRUE;
1717		} else {
1718			/* CPU-to-screen composite */
1719			if (op != PictOpOver)
1720				xf86Msg(X_ERROR, "%s: op %d\n", __func__, op);
1721			CrimeDoCPUToScreenComposite(op, pSrc, pMask, pDst,
1722			    xSrc, ySrc, xMask, yMask,
1723			    xDst, yDst, width, height);
1724			return TRUE;
1725		}
1726	} else {
1727		if ((pSrc->pDrawable->type == DRAWABLE_WINDOW) ||
1728		    IS_OFFSCREEN_PIXMAP(pSrc->pDrawable)) {
1729			/* screen-to-RAM */
1730			xf86Msg(X_ERROR, "%s: screen-to-RAM composite\n",
1731			   __func__);
1732			return TRUE;
1733		} else {
1734			/* RAM-to-RAM */
1735			return FALSE;
1736		}
1737	}
1738	xf86Msg(X_ERROR, "composite fucked\n");
1739}
1740
1741static void
1742CrimePolyPoint(
1743    DrawablePtr pDraw,
1744    GCPtr pGC,
1745    int mode,
1746    int npt,
1747    xPoint *pptInit
1748)
1749{
1750	ScreenPtr pScreen = pDraw->pScreen;
1751	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1752	CrimePtr fPtr = CRIMEPTR(pScrn);
1753	BoxPtr pBox;
1754	xPoint *ppt, *pts;
1755	int x1, x2, y1, y2, x, y, i, nBox;
1756
1757	/* make pointlist origin relative */
1758	ppt = pptInit;
1759	if (mode == CoordModePrevious) {
1760		for (i = 0; i < npt; i++) {
1761			ppt++;
1762			ppt->x += (ppt-1)->x;
1763			ppt->y += (ppt-1)->y;
1764		}
1765	}
1766	MAKE_ROOM(6);
1767	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
1768			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1769	WRITE4(CRIME_DE_FG, pGC->fgPixel << 8);
1770	WRITE4(CRIME_DE_ROP, pGC->alu);
1771	WRITE4(CRIME_DE_PLANEMASK, pGC->planemask);
1772	WRITE4(CRIME_DE_DRAWMODE,
1773	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP);
1774	WRITE4(CRIME_DE_PRIMITIVE, DE_PRIM_POINT);
1775	SYNC;
1776	for (nBox = REGION_NUM_RECTS (pGC->pCompositeClip),
1777	    pBox = REGION_RECTS (pGC->pCompositeClip);
1778	    nBox--; pBox++) {
1779
1780		pts = pptInit;
1781		for (i = 0; i < npt; i++) {
1782			x1 = pBox->x1;
1783			y1 = pBox->y1;
1784			x2 = pBox->x2;
1785			y2 = pBox->y2;
1786			x = pts->x + pDraw->x;
1787			y = pts->y + pDraw->y;
1788			if (x1 <= x && x < x2 && y1 <= y && y < y2) {
1789
1790		 		MAKE_ROOM(1);
1791				WRITE4ST(CRIME_DE_X_VERTEX_0,
1792					(x << 16) | y);
1793			}
1794			pts++;
1795		}
1796	}
1797}
1798
1799static void
1800CrimeValidatePolyPoint(
1801   GCPtr         pGC,
1802   unsigned long changes,
1803   DrawablePtr   pDraw )
1804{
1805
1806	if ((pDraw->type == DRAWABLE_WINDOW) ||
1807	    IS_OFFSCREEN_PIXMAP(pDraw)) {
1808		pGC->ops->PolyPoint = CrimePolyPoint;
1809	} else
1810		xf86Msg(X_ERROR, "boo\n");
1811}
1812static void
1813CrimePolyArc(DrawablePtr pDraw,
1814               GCPtr pGC,
1815               int narcs,
1816               xArc *parcs)
1817{
1818    xArc *arc;
1819    BoxRec box;
1820    int i, x2, y2;
1821    RegionPtr cclip;
1822
1823    cclip = pGC->pCompositeClip;
1824
1825    if(!REGION_NUM_RECTS(cclip))
1826	return;
1827
1828    for (arc = parcs, i = narcs; --i >= 0; arc++) {
1829	if (miCanZeroArc(arc)) {
1830	    box.x1 = arc->x + pDraw->x;
1831	    box.y1 = arc->y + pDraw->y;
1832 	    x2 = box.x1 + (int)arc->width + 1;
1833 	    box.x2 = x2;
1834 	    y2 = box.y1 + (int)arc->height + 1;
1835 	    box.y2 = y2;
1836 	    if ( (x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) &&
1837 		    (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) )
1838		miZeroPolyArc(pDraw, pGC, 1, arc);
1839	}
1840	else
1841	    miPolyArc(pDraw, pGC, 1, arc);
1842    }
1843}
1844
1845static void
1846CrimeValidatePolyArc(GCPtr pGC,
1847                       unsigned long changes,
1848                       DrawablePtr pDraw)
1849{
1850	if ((pDraw->type == DRAWABLE_WINDOW) ||
1851	    IS_OFFSCREEN_PIXMAP(pDraw)) {
1852		pGC->ops->PolyPoint = CrimePolyPoint;
1853		/*pGC->ops->PolyArc = miPolyArc;*/
1854		pGC->ops->PolyArc = CrimePolyArc;
1855	} else
1856	{
1857		pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint;
1858		pGC->ops->PolyArc = XAAGetFallbackOps()->PolyArc;
1859	}
1860}
1861
1862static void copyRGBAtoARGB(uint32_t *dest, uint32_t *src, int len)
1863{
1864	while (len > 0) {
1865		*dest = *src >> 8;
1866		dest++;
1867		src++;
1868		len--;
1869	}
1870}
1871
1872static void
1873CrimeReadPixmap(ScrnInfoPtr pScrn,
1874                     int x,
1875		     int y,
1876		     int w,
1877		     int h,
1878		     unsigned char *dst,
1879		     int dstwidth,
1880		     int bpp,
1881		     int depth)
1882{
1883	CrimePtr fPtr = CRIMEPTR(pScrn);
1884	int bufno = 0;
1885	int nextbuf, i, len = w << 2;
1886	int mx = x << 2, offset;
1887
1888	offset = mx & 0x3f;
1889	mx &= ~0x3f;
1890	len = (len + offset + 0x3f) & ~0x3f;
1891
1892	LOG(CRIME_DEBUG_IMAGEREAD);
1893
1894#ifdef CRIME_DEBUG_LOUD
1895	xf86Msg(X_ERROR, "%s: %d %d %d %d\n", __func__, x, y, w, h);
1896#endif
1897
1898	MAKE_ROOM(3);
1899
1900	/*
1901	 * apparently all MTE coordinates are in bytes, not pixels
1902	 * also, the MTE has some crazy alignment requirements - if
1903	 * we don't do as above the thing will deadlock sooner or later
1904	 * We use the MTE here because I couldn't get the rendering engine
1905	 * to actually transfer anything into a linear buffer. The other
1906	 * way around works just fine though. Shouldn't make much of a
1907	 * difference, transfer times should be dominated by copying
1908	 * data in and out of the DMA buffer anyway
1909	 */
1910	WRITE4(CRIME_MTE_MODE, (MTE_TLB_LIN_A << MTE_DST_TLB_SHIFT) |
1911			 (MTE_TLB_A << MTE_SRC_TLB_SHIFT) |
1912			 (MTE_DEPTH_8 << MTE_DEPTH_SHIFT) |
1913			 MTE_MODE_DST_ECC | MTE_MODE_COPY);
1914	WRITE4(CRIME_MTE_SRC_Y_STEP, 1);
1915	WRITE4(CRIME_MTE_DST_Y_STEP, 1);
1916	SYNCMTE;
1917	WRITE4(CRIME_MTE_SRC0, (mx << 16) | y);
1918	WRITE4(CRIME_MTE_SRC1, ((mx + len) << 16) | y);
1919	WRITE4(CRIME_MTE_DST0, (bufno << 13));
1920	WRITE4ST(CRIME_MTE_DST1, (bufno << 13) + len);
1921	for (i = y + 1; i < y + h; i++) {
1922		nextbuf = (bufno + 1) & 7;
1923		SYNCMTE;
1924		WRITE4(CRIME_MTE_SRC0, (mx << 16) | i);
1925		WRITE4(CRIME_MTE_SRC1, ((mx + len) << 16) | i);
1926		WRITE4(CRIME_MTE_DST0, (nextbuf << 13));
1927		WRITE4ST(CRIME_MTE_DST1, (nextbuf << 13) + len);
1928		copyRGBAtoARGB((uint32_t *)dst,
1929			       (uint32_t *)(fPtr->buffers[bufno] + offset), w);
1930		dst += dstwidth;
1931		bufno = nextbuf;
1932	}
1933	SYNCMTE;
1934	copyRGBAtoARGB((uint32_t *)dst,
1935		       (uint32_t *)(fPtr->buffers[bufno] + offset), w);
1936	DONE(CRIME_DEBUG_IMAGEREAD);
1937
1938}
1939int
1940CrimeAccelInit(ScrnInfoPtr pScrn)
1941{
1942	CrimePtr fPtr = CRIMEPTR(pScrn);
1943	XAAInfoRecPtr pXAAInfo = fPtr->pXAA;
1944	int i;
1945
1946	for (i = 0; i < 0x1000; i++) regcache[i] = 0x12345678;
1947	LOG(CRIME_DEBUG_ALL);
1948	SYNC;
1949	WRITE4(CRIME_DE_MODE_DST, DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 |
1950			    DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32);
1951
1952	WRITE4(CRIME_DE_XFER_STEP_Y, 1);
1953	WRITE4(CRIME_DE_XFER_STRD_DST, 4);
1954	WRITE4(CRIME_DE_XFER_STRD_SRC, 1);
1955
1956	WRITE4(CRIME_MTE_BYTEMASK, 0xffffffff);
1957	WRITE4(CRIME_MTE_SRC_Y_STEP, 4);
1958	WRITE4(CRIME_MTE_DST_Y_STEP, 4);
1959	SYNC;
1960
1961	/* blit the screen black */
1962	WRITE4(CRIME_DE_DRAWMODE,
1963	    DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP);
1964	WRITE4(CRIME_DE_ROP, 3);
1965	WRITE4(CRIME_DE_PRIMITIVE, DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB);
1966	WRITE4(CRIME_DE_FG, 0);
1967	WRITE4(CRIME_DE_X_VERTEX_0, 0);
1968	WRITE4ST(CRIME_DE_X_VERTEX_1,
1969	    fPtr->info.width << 16 | fPtr->info.height);
1970	SYNC;
1971
1972	pXAAInfo->Flags = /*LINEAR_FRAMEBUFFER |*/ PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
1973	pXAAInfo->maxOffPixWidth = fPtr->info.width;
1974	pXAAInfo->maxOffPixHeight = 2048;
1975
1976	/* Sync */
1977	pXAAInfo->Sync = CrimeSync;
1978
1979	CrimeDisableClipping(pScrn);
1980
1981	/* Screen-to-screen copy */
1982	pXAAInfo->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
1983	pXAAInfo->SetupForScreenToScreenCopy = CrimeSetupForScreenToScreenCopy;
1984	pXAAInfo->SubsequentScreenToScreenCopy =
1985		CrimeSubsequentScreenToScreenCopy;
1986
1987	/* rectangle fills */
1988	pXAAInfo->SetupForSolidFill = CrimeSetupForSolidFill;
1989	pXAAInfo->SubsequentSolidFillRect = CrimeSubsequentSolidFillRect;
1990
1991	/* image writes */
1992	pXAAInfo->ScanlineImageWriteFlags =
1993	    NO_TRANSPARENCY | LEFT_EDGE_CLIPPING |
1994	    LEFT_EDGE_CLIPPING_NEGATIVE_X |
1995	    CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD;
1996	pXAAInfo->NumScanlineImageWriteBuffers = 8;
1997	for (i = 0; i < 8; i++)
1998		fPtr->buffers[i] = fPtr->linear + (i * 8192);
1999	pXAAInfo->ScanlineImageWriteBuffers = fPtr->buffers;
2000	pXAAInfo->SetupForScanlineImageWrite =
2001		CrimeSetupForScanlineImageWrite;
2002	pXAAInfo->SubsequentScanlineImageWriteRect =
2003		CrimeSubsequentImageWriteRect;
2004	pXAAInfo->SubsequentImageWriteScanline =
2005		CrimeSubsequentImageWriteScanline;
2006
2007	/* read pixmap */
2008	pXAAInfo->ReadPixmapFlags = 0
2009	                             | CPU_TRANSFER_PAD_DWORD
2010				     ;
2011	pXAAInfo->ReadPixmap = CrimeReadPixmap;
2012
2013	/* colour expansion */
2014	pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags =
2015		LEFT_EDGE_CLIPPING;
2016	pXAAInfo->NumScanlineColorExpandBuffers = 1;
2017	fPtr->expandbuffers[0] = (uint8_t *)fPtr->expand;
2018	pXAAInfo->ScanlineColorExpandBuffers = (void *)&fPtr->expandbuffers;
2019	pXAAInfo->SetupForScanlineCPUToScreenColorExpandFill =
2020		CrimeSetupForCPUToScreenColorExpandFill;
2021	pXAAInfo->SubsequentScanlineCPUToScreenColorExpandFill =
2022		CrimeSubsequentScanlineCPUToScreenColorExpandFill;
2023	pXAAInfo->SubsequentColorExpandScanline =
2024		CrimeSubsequentColorExpandScanline;
2025
2026	/* clipping */
2027	pXAAInfo->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
2028		HARDWARE_CLIP_SOLID_FILL |
2029		HARDWARE_CLIP_SOLID_LINE |
2030		HARDWARE_CLIP_MONO_8x8_FILL | HARDWARE_CLIP_DASHED_LINE;
2031	pXAAInfo->SetClippingRectangle = CrimeSetClippingRectangle;
2032	pXAAInfo->DisableClipping = CrimeDisableClipping;
2033
2034	/* solid line drawing */
2035	pXAAInfo->SetupForSolidLine = CrimeSetupForSolidLine;
2036	pXAAInfo->SubsequentSolidTwoPointLine =
2037	    CrimeSubsequentSolidTwoPointLine;
2038	pXAAInfo->SolidLineFlags = 0;
2039
2040	/* dashed line drawing */
2041	pXAAInfo->SetupForDashedLine = CrimeSetupForDashedLine;
2042	pXAAInfo->SubsequentDashedTwoPointLine =
2043	    CrimeSubsequentDashedTwoPointLine;
2044	pXAAInfo->DashedLineFlags = LINE_PATTERN_MSBFIRST_MSBJUSTIFIED;
2045	pXAAInfo->DashPatternMaxLength = 32;
2046
2047	/* mono pattern fills */
2048	pXAAInfo->Mono8x8PatternFillFlags = HARDWARE_PATTERN_PROGRAMMED_BITS |
2049	    HARDWARE_PATTERN_PROGRAMMED_ORIGIN | BIT_ORDER_IN_BYTE_MSBFIRST;
2050	pXAAInfo->SetupForMono8x8PatternFill = CrimeSetupForMono8x8PatternFill;
2051	pXAAInfo->SubsequentMono8x8PatternFillRect =
2052	    CrimeSubsequentMono8x8PatternFillRect;
2053
2054	/* XRender acceleration */
2055#ifdef RENDER
2056	pXAAInfo->CPUToScreenAlphaTextureFlags = 0;
2057	pXAAInfo->SetupForCPUToScreenAlphaTexture =
2058	    CrimeSetupForCPUToScreenAlphaTexture;
2059	pXAAInfo->SubsequentCPUToScreenAlphaTexture =
2060	    CrimeSubsequentCPUToScreenAlphaTexture;
2061	pXAAInfo->CPUToScreenAlphaTextureFormats = CrimeAlphaTextureFormats;
2062
2063	pXAAInfo->SetupForCPUToScreenTexture = CrimeSetupForCPUToScreenTexture;
2064	pXAAInfo->SubsequentCPUToScreenTexture =
2065	    CrimeSubsequentCPUToScreenTexture;
2066	pXAAInfo->CPUToScreenTextureFlags = 0;
2067	pXAAInfo->CPUToScreenTextureFormats = CrimeTextureFormats;
2068	pXAAInfo->Composite = CrimeComposite;
2069#endif
2070	pXAAInfo->ValidatePolyPoint = CrimeValidatePolyPoint;
2071	pXAAInfo->PolyPointMask = GCFunction;
2072	pXAAInfo->ValidatePolyArc = CrimeValidatePolyArc;
2073	pXAAInfo->PolyArcMask = GCFunction | GCLineWidth;
2074
2075	return -1;
2076}
2077