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