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