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