1706f2543Smrg
2706f2543Smrg#ifdef HAVE_XORG_CONFIG_H
3706f2543Smrg#include <xorg-config.h>
4706f2543Smrg#endif
5706f2543Smrg
6706f2543Smrg#include "misc.h"
7706f2543Smrg#include "xf86.h"
8706f2543Smrg#include "xf86_OSproc.h"
9706f2543Smrg#include "servermd.h"
10706f2543Smrg
11706f2543Smrg#include <X11/X.h>
12706f2543Smrg#include "scrnintstr.h"
13706f2543Smrg#include "mi.h"
14706f2543Smrg#include "pixmapstr.h"
15706f2543Smrg#include "xf86str.h"
16706f2543Smrg#include "xaa.h"
17706f2543Smrg#include "xaalocal.h"
18706f2543Smrg
19706f2543Smrgvoid XAAMoveDWORDS_FixedBase(
20706f2543Smrg   register CARD32* dest,
21706f2543Smrg   register CARD32* src,
22706f2543Smrg   register int dwords )
23706f2543Smrg{
24706f2543Smrg     while(dwords & ~0x03) {
25706f2543Smrg	 *dest = *src;
26706f2543Smrg	 *dest = *(src + 1);
27706f2543Smrg	 *dest = *(src + 2);
28706f2543Smrg	 *dest = *(src + 3);
29706f2543Smrg	 dwords -= 4;
30706f2543Smrg	 src += 4;
31706f2543Smrg     }
32706f2543Smrg
33706f2543Smrg     if(!dwords) return;
34706f2543Smrg     *dest = *src;
35706f2543Smrg     if(dwords == 1) return;
36706f2543Smrg     *dest = *(src + 1);
37706f2543Smrg     if(dwords == 2) return;
38706f2543Smrg     *dest = *(src + 2);
39706f2543Smrg}
40706f2543Smrg
41706f2543Smrgvoid XAAMoveDWORDS(
42706f2543Smrg   register CARD32* dest,
43706f2543Smrg   register CARD32* src,
44706f2543Smrg   register int dwords )
45706f2543Smrg{
46706f2543Smrg     while(dwords & ~0x03) {
47706f2543Smrg	*dest = *src;
48706f2543Smrg	*(dest + 1) = *(src + 1);
49706f2543Smrg	*(dest + 2) = *(src + 2);
50706f2543Smrg	*(dest + 3) = *(src + 3);
51706f2543Smrg	src += 4;
52706f2543Smrg	dest += 4;
53706f2543Smrg	dwords -= 4;
54706f2543Smrg     }
55706f2543Smrg     if(!dwords) return;
56706f2543Smrg     *dest = *src;
57706f2543Smrg     if(dwords == 1) return;
58706f2543Smrg     *(dest + 1) = *(src + 1);
59706f2543Smrg     if(dwords == 2) return;
60706f2543Smrg     *(dest + 2) = *(src + 2);
61706f2543Smrg}
62706f2543Smrg
63706f2543Smrgvoid XAAMoveDWORDS_FixedSrc(
64706f2543Smrg   register CARD32* dest,
65706f2543Smrg   register CARD32* src,
66706f2543Smrg   register int dwords )
67706f2543Smrg{
68706f2543Smrg     while(dwords & ~0x03) {
69706f2543Smrg	*dest = *src;
70706f2543Smrg	*(dest + 1) = *src;
71706f2543Smrg	*(dest + 2) = *src;
72706f2543Smrg	*(dest + 3) = *src;
73706f2543Smrg	dest += 4;
74706f2543Smrg	dwords -= 4;
75706f2543Smrg     }
76706f2543Smrg     if(!dwords) return;
77706f2543Smrg     *dest = *src;
78706f2543Smrg     if(dwords == 1) return;
79706f2543Smrg     *(dest + 1) = *src;
80706f2543Smrg     if(dwords == 2) return;
81706f2543Smrg     *(dest + 2) = *src;
82706f2543Smrg}
83706f2543Smrg
84706f2543Smrgstatic void
85706f2543SmrgXAAWritePixmap32To24(
86706f2543Smrg   ScrnInfoPtr pScrn,
87706f2543Smrg   int x, int y, int w, int h,
88706f2543Smrg   unsigned char *srcInit,
89706f2543Smrg   int srcwidth,	/* bytes */
90706f2543Smrg   int rop,
91706f2543Smrg   unsigned int planemask,
92706f2543Smrg   int trans
93706f2543Smrg){
94706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
95706f2543Smrg    int count, dwords = bytes_to_int32(w * 3);
96706f2543Smrg    CARD32 *src, *dst;
97706f2543Smrg    Bool PlusOne = FALSE;
98706f2543Smrg
99706f2543Smrg    if((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) &&
100706f2543Smrg					((dwords * h) & 0x01)) {
101706f2543Smrg	PlusOne = TRUE;
102706f2543Smrg    }
103706f2543Smrg
104706f2543Smrg    (*infoRec->SetupForImageWrite)(pScrn, rop, planemask, trans, 24, 24);
105706f2543Smrg    (*infoRec->SubsequentImageWriteRect)(pScrn, x, y, w, h, 0);
106706f2543Smrg
107706f2543Smrg    if(dwords > infoRec->ImageWriteRange) {
108706f2543Smrg	dst = (CARD32*)infoRec->ImageWriteBase;
109706f2543Smrg	while(h--) {
110706f2543Smrg	    src = (CARD32*)srcInit;
111706f2543Smrg  	    count = w;
112706f2543Smrg
113706f2543Smrg	    while(count >= 4) {
114706f2543Smrg		*dst = (src[0] & 0x00ffffff) | (src[1] << 24);
115706f2543Smrg		*dst = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16);
116706f2543Smrg		*dst = ((src[2] >> 16) & 0x000000ff) | (src[3] << 8);
117706f2543Smrg		src += 4;
118706f2543Smrg		count -= 4;
119706f2543Smrg	    }
120706f2543Smrg	    switch(count) {
121706f2543Smrg	    case 0:	break;
122706f2543Smrg	    case 1:	*dst = src[0];
123706f2543Smrg			break;
124706f2543Smrg	    case 2:	*dst = (src[0] & 0x00ffffff) | (src[1] << 24);
125706f2543Smrg			*dst = src[1] >> 8;
126706f2543Smrg			break;
127706f2543Smrg	    default:	*dst = (src[0] & 0x00ffffff) | (src[1] << 24);
128706f2543Smrg			*dst = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16);
129706f2543Smrg			*dst = src[2] >> 16;
130706f2543Smrg			break;
131706f2543Smrg	    }
132706f2543Smrg	    srcInit += srcwidth;
133706f2543Smrg	}
134706f2543Smrg    } else {
135706f2543Smrg	while(h--) {
136706f2543Smrg	    dst = (CARD32*)infoRec->ImageWriteBase;
137706f2543Smrg	    src = (CARD32*)srcInit;
138706f2543Smrg  	    count = w;
139706f2543Smrg
140706f2543Smrg	    while(count >= 4) {
141706f2543Smrg		dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24);
142706f2543Smrg		dst[1] = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16);
143706f2543Smrg		dst[2] = ((src[2] >> 16) & 0x000000ff) | (src[3] << 8);
144706f2543Smrg		dst += 3;
145706f2543Smrg		src += 4;
146706f2543Smrg		count -= 4;
147706f2543Smrg	    }
148706f2543Smrg	    switch(count) {
149706f2543Smrg	    case 0:	break;
150706f2543Smrg	    case 1:	dst[0] = src[0];
151706f2543Smrg			break;
152706f2543Smrg	    case 2:	dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24);
153706f2543Smrg			dst[1] = src[1] >> 8;
154706f2543Smrg			break;
155706f2543Smrg	    default:	dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24);
156706f2543Smrg			dst[1] = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16);
157706f2543Smrg			dst[2] = src[2] >> 16;
158706f2543Smrg			break;
159706f2543Smrg	    }
160706f2543Smrg	    srcInit += srcwidth;
161706f2543Smrg	}
162706f2543Smrg    }
163706f2543Smrg
164706f2543Smrg    if(PlusOne) {
165706f2543Smrg	CARD32* base = (CARD32*)infoRec->ImageWriteBase;
166706f2543Smrg	*base = 0x00000000;
167706f2543Smrg    }
168706f2543Smrg
169706f2543Smrg    if(infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE)
170706f2543Smrg	(*infoRec->Sync)(pScrn);
171706f2543Smrg    else SET_SYNC_FLAG(infoRec);
172706f2543Smrg
173706f2543Smrg}
174706f2543Smrg
175706f2543Smrgvoid
176706f2543SmrgXAAWritePixmap (
177706f2543Smrg   ScrnInfoPtr pScrn,
178706f2543Smrg   int x, int y, int w, int h,
179706f2543Smrg   unsigned char *src,
180706f2543Smrg   int srcwidth,	/* bytes */
181706f2543Smrg   int rop,
182706f2543Smrg   unsigned int planemask,
183706f2543Smrg   int trans,
184706f2543Smrg   int bpp, int depth
185706f2543Smrg){
186706f2543Smrg    XAAInfoRecPtr infoRec;
187706f2543Smrg    int dwords, skipleft, Bpp;
188706f2543Smrg    Bool beCareful, PlusOne;
189706f2543Smrg
190706f2543Smrg    if((bpp == 32) && (pScrn->bitsPerPixel == 24)) {
191706f2543Smrg	XAAWritePixmap32To24(pScrn, x, y, w, h, src, srcwidth,
192706f2543Smrg						rop, planemask, trans);
193706f2543Smrg	return;
194706f2543Smrg    }
195706f2543Smrg
196706f2543Smrg    infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
197706f2543Smrg    beCareful = PlusOne = FALSE;
198706f2543Smrg    Bpp = bpp >> 3;
199706f2543Smrg
200706f2543Smrg    if((skipleft = (long)src & 0x03L)) {
201706f2543Smrg	if(!(infoRec->ImageWriteFlags & LEFT_EDGE_CLIPPING)) {
202706f2543Smrg	   skipleft = 0;
203706f2543Smrg	   beCareful = TRUE;
204706f2543Smrg	   goto BAD_ALIGNMENT;
205706f2543Smrg	}
206706f2543Smrg
207706f2543Smrg	if(Bpp == 3)
208706f2543Smrg	   skipleft = 4 - skipleft;
209706f2543Smrg	else
210706f2543Smrg	   skipleft /= Bpp;
211706f2543Smrg
212706f2543Smrg	if((x < skipleft) && !(infoRec->ImageWriteFlags &
213706f2543Smrg				 LEFT_EDGE_CLIPPING_NEGATIVE_X)) {
214706f2543Smrg	   skipleft = 0;
215706f2543Smrg	   beCareful = TRUE;
216706f2543Smrg	   goto BAD_ALIGNMENT;
217706f2543Smrg	}
218706f2543Smrg
219706f2543Smrg	x -= skipleft;
220706f2543Smrg	w += skipleft;
221706f2543Smrg
222706f2543Smrg	if(Bpp == 3)
223706f2543Smrg	   src -= 3 * skipleft;
224706f2543Smrg	else   /* is this Alpha friendly ? */
225706f2543Smrg	   src = (unsigned char*)((long)src & ~0x03L);
226706f2543Smrg    }
227706f2543Smrg
228706f2543SmrgBAD_ALIGNMENT:
229706f2543Smrg
230706f2543Smrg    dwords = bytes_to_int32(w * Bpp);
231706f2543Smrg
232706f2543Smrg    if((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) &&
233706f2543Smrg						((dwords * h) & 0x01)) {
234706f2543Smrg	PlusOne = TRUE;
235706f2543Smrg    }
236706f2543Smrg
237706f2543Smrg
238706f2543Smrg    (*infoRec->SetupForImageWrite)(pScrn, rop, planemask, trans, bpp, depth);
239706f2543Smrg    (*infoRec->SubsequentImageWriteRect)(pScrn, x, y, w, h, skipleft);
240706f2543Smrg
241706f2543Smrg    if(beCareful) {
242706f2543Smrg	/* in cases with bad alignment we have to be careful not
243706f2543Smrg	   to read beyond the end of the source */
244706f2543Smrg	if(((x * Bpp) + (dwords << 2)) > srcwidth) h--;
245706f2543Smrg	else beCareful = FALSE;
246706f2543Smrg    }
247706f2543Smrg
248706f2543Smrg    if(dwords > infoRec->ImageWriteRange) {
249706f2543Smrg	while(h--) {
250706f2543Smrg	    XAAMoveDWORDS_FixedBase((CARD32*)infoRec->ImageWriteBase,
251706f2543Smrg		(CARD32*)src, dwords);
252706f2543Smrg	    src += srcwidth;
253706f2543Smrg	}
254706f2543Smrg	if(beCareful) {
255706f2543Smrg	   int shift = ((long)src & 0x03L) << 3;
256706f2543Smrg	   if(--dwords)
257706f2543Smrg		XAAMoveDWORDS_FixedBase((CARD32*)infoRec->ImageWriteBase,
258706f2543Smrg			(CARD32*)src, dwords);
259706f2543Smrg	   src = (unsigned char*)((long)(src + (dwords << 2)) & ~0x03L);
260706f2543Smrg	   *((CARD32*)infoRec->ImageWriteBase) = *((CARD32*)src) >> shift;
261706f2543Smrg	}
262706f2543Smrg    } else {
263706f2543Smrg	if(srcwidth == (dwords << 2)) {
264706f2543Smrg	   int decrement = infoRec->ImageWriteRange/dwords;
265706f2543Smrg
266706f2543Smrg	   while(h > decrement) {
267706f2543Smrg		XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase,
268706f2543Smrg	 		(CARD32*)src, dwords * decrement);
269706f2543Smrg		src += (srcwidth * decrement);
270706f2543Smrg		h -= decrement;
271706f2543Smrg	   }
272706f2543Smrg	   if(h) {
273706f2543Smrg		XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase,
274706f2543Smrg	 		(CARD32*)src, dwords * h);
275706f2543Smrg		if(beCareful) src += (srcwidth * h);
276706f2543Smrg	   }
277706f2543Smrg	} else {
278706f2543Smrg	    while(h--) {
279706f2543Smrg		XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase,
280706f2543Smrg	 		(CARD32*)src, dwords);
281706f2543Smrg		src += srcwidth;
282706f2543Smrg	    }
283706f2543Smrg	}
284706f2543Smrg
285706f2543Smrg	if(beCareful) {
286706f2543Smrg	    int shift = ((long)src & 0x03L) << 3;
287706f2543Smrg	    if(--dwords)
288706f2543Smrg		XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase,
289706f2543Smrg					(CARD32*)src, dwords);
290706f2543Smrg	    src = (unsigned char*)((long)(src + (dwords << 2)) & ~0x03L);
291706f2543Smrg
292706f2543Smrg	    ((CARD32*)infoRec->ImageWriteBase)[dwords] =
293706f2543Smrg			*((CARD32*)src) >> shift;
294706f2543Smrg	}
295706f2543Smrg    }
296706f2543Smrg
297706f2543Smrg    if(PlusOne) {
298706f2543Smrg	CARD32* base = (CARD32*)infoRec->ImageWriteBase;
299706f2543Smrg	*base = 0x00000000;
300706f2543Smrg    }
301706f2543Smrg
302706f2543Smrg    if(infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE)
303706f2543Smrg	(*infoRec->Sync)(pScrn);
304706f2543Smrg    else SET_SYNC_FLAG(infoRec);
305706f2543Smrg}
306706f2543Smrg
307706f2543Smrg
308706f2543Smrgvoid
309706f2543SmrgXAAWritePixmapScanline (
310706f2543Smrg   ScrnInfoPtr pScrn,
311706f2543Smrg   int x, int y, int w, int h,
312706f2543Smrg   unsigned char *src,
313706f2543Smrg   int srcwidth,	/* bytes */
314706f2543Smrg   int rop,
315706f2543Smrg   unsigned int planemask,
316706f2543Smrg   int trans,
317706f2543Smrg   int bpp, int depth
318706f2543Smrg){
319706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
320706f2543Smrg    int dwords, skipleft, bufferNo = 0, Bpp = bpp >> 3;
321706f2543Smrg    Bool beCareful = FALSE;
322706f2543Smrg    CARD32* base;
323706f2543Smrg
324706f2543Smrg    if((skipleft = (long)src & 0x03L)) {
325706f2543Smrg	if(!(infoRec->ScanlineImageWriteFlags & LEFT_EDGE_CLIPPING)) {
326706f2543Smrg	   skipleft = 0;
327706f2543Smrg	   beCareful = TRUE;
328706f2543Smrg	   goto BAD_ALIGNMENT;
329706f2543Smrg	}
330706f2543Smrg
331706f2543Smrg	if(Bpp == 3)
332706f2543Smrg	   skipleft = 4 - skipleft;
333706f2543Smrg	else
334706f2543Smrg	   skipleft /= Bpp;
335706f2543Smrg
336706f2543Smrg	if((x < skipleft) && !(infoRec->ScanlineImageWriteFlags &
337706f2543Smrg				 LEFT_EDGE_CLIPPING_NEGATIVE_X)) {
338706f2543Smrg	   skipleft = 0;
339706f2543Smrg	   beCareful = TRUE;
340706f2543Smrg	   goto BAD_ALIGNMENT;
341706f2543Smrg	}
342706f2543Smrg
343706f2543Smrg	x -= skipleft;
344706f2543Smrg	w += skipleft;
345706f2543Smrg
346706f2543Smrg	if(Bpp == 3)
347706f2543Smrg	   src -= 3 * skipleft;
348706f2543Smrg	else
349706f2543Smrg	   src = (unsigned char*)((long)src & ~0x03L);
350706f2543Smrg    }
351706f2543Smrg
352706f2543SmrgBAD_ALIGNMENT:
353706f2543Smrg
354706f2543Smrg    dwords = bytes_to_int32(w * Bpp);
355706f2543Smrg
356706f2543Smrg    (*infoRec->SetupForScanlineImageWrite)(
357706f2543Smrg				pScrn, rop, planemask, trans, bpp, depth);
358706f2543Smrg    (*infoRec->SubsequentScanlineImageWriteRect)(pScrn, x, y, w, h, skipleft);
359706f2543Smrg
360706f2543Smrg    if(beCareful) {
361706f2543Smrg	/* in cases with bad alignment we have to be careful not
362706f2543Smrg	   to read beyond the end of the source */
363706f2543Smrg	if(((x * Bpp) + (dwords << 2)) > srcwidth) h--;
364706f2543Smrg	else beCareful = FALSE;
365706f2543Smrg    }
366706f2543Smrg
367706f2543Smrg    while(h--) {
368706f2543Smrg	base = (CARD32*)infoRec->ScanlineImageWriteBuffers[bufferNo];
369706f2543Smrg	XAAMoveDWORDS(base, (CARD32*)src, dwords);
370706f2543Smrg	(*infoRec->SubsequentImageWriteScanline)(pScrn, bufferNo++);
371706f2543Smrg	src += srcwidth;
372706f2543Smrg	if(bufferNo >= infoRec->NumScanlineImageWriteBuffers)
373706f2543Smrg	    bufferNo = 0;
374706f2543Smrg    }
375706f2543Smrg
376706f2543Smrg    if(beCareful) {
377706f2543Smrg	int shift = ((long)src & 0x03L) << 3;
378706f2543Smrg	base = (CARD32*)infoRec->ScanlineImageWriteBuffers[bufferNo];
379706f2543Smrg	if(--dwords)
380706f2543Smrg	    XAAMoveDWORDS(base,(CARD32*)src, dwords);
381706f2543Smrg	src = (unsigned char*)((long)(src + (dwords << 2)) & ~0x03L);
382706f2543Smrg
383706f2543Smrg	base[dwords] = *((CARD32*)src) >> shift;
384706f2543Smrg	(*infoRec->SubsequentImageWriteScanline)(pScrn, bufferNo);
385706f2543Smrg    }
386706f2543Smrg
387706f2543Smrg    SET_SYNC_FLAG(infoRec);
388706f2543Smrg}
389706f2543Smrg
390706f2543Smrg
391706f2543Smrgvoid
392706f2543SmrgXAAPutImage(
393706f2543Smrg    DrawablePtr pDraw,
394706f2543Smrg    GCPtr       pGC,
395706f2543Smrg    int         depth,
396706f2543Smrg    int 	x,
397706f2543Smrg    int		y,
398706f2543Smrg    int		w,
399706f2543Smrg    int		h,
400706f2543Smrg    int         leftPad,
401706f2543Smrg    int         format,
402706f2543Smrg    char        *pImage
403706f2543Smrg){
404706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
405706f2543Smrg    int bpp = BitsPerPixel(depth);
406706f2543Smrg    Bool depthBug = FALSE;
407706f2543Smrg    if(!w || !h) return;
408706f2543Smrg
409706f2543Smrg    if(!RegionNumRects(pGC->pCompositeClip))
410706f2543Smrg	return;
411706f2543Smrg
412706f2543Smrg    depthBug = XAA_DEPTH_BUG(pGC);
413706f2543Smrg
414706f2543Smrg    if(((format == ZPixmap) && infoRec->WritePixmap &&
415706f2543Smrg	     ((pDraw->bitsPerPixel == bpp) ||
416706f2543Smrg		((pDraw->bitsPerPixel == 24) &&  (bpp == 32) &&
417706f2543Smrg		(infoRec->WritePixmapFlags & CONVERT_32BPP_TO_24BPP))) &&
418706f2543Smrg	     CHECK_ROP(pGC,infoRec->WritePixmapFlags) &&
419706f2543Smrg	     CHECK_ROPSRC(pGC,infoRec->WritePixmapFlags) &&
420706f2543Smrg	     CHECK_PLANEMASK(pGC,infoRec->WritePixmapFlags) &&
421706f2543Smrg	     CHECK_NO_GXCOPY(pGC,infoRec->WritePixmapFlags)) ||
422706f2543Smrg       ((format == XYBitmap) && !depthBug && infoRec->WriteBitmap &&
423706f2543Smrg	     CHECK_ROP(pGC,infoRec->WriteBitmapFlags) &&
424706f2543Smrg	     CHECK_ROPSRC(pGC,infoRec->WriteBitmapFlags) &&
425706f2543Smrg	     CHECK_PLANEMASK(pGC,infoRec->WriteBitmapFlags) &&
426706f2543Smrg	     CHECK_COLORS(pGC,infoRec->WriteBitmapFlags) &&
427706f2543Smrg	     !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)) ||
428706f2543Smrg       ((format == XYPixmap) && !depthBug && infoRec->WriteBitmap &&
429706f2543Smrg	     CHECK_ROP(pGC,infoRec->WriteBitmapFlags) &&
430706f2543Smrg	     CHECK_ROPSRC(pGC,infoRec->WriteBitmapFlags) &&
431706f2543Smrg	     !(infoRec->WriteBitmapFlags & NO_PLANEMASK) &&
432706f2543Smrg	     !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY))){
433706f2543Smrg
434706f2543Smrg	int MaxBoxes = RegionNumRects(pGC->pCompositeClip);
435706f2543Smrg	BoxPtr pbox, pClipBoxes;
436706f2543Smrg	int nboxes, srcx, srcy, srcwidth;
437706f2543Smrg	xRectangle TheRect;
438706f2543Smrg
439706f2543Smrg	TheRect.x = pDraw->x + x;
440706f2543Smrg	TheRect.y = pDraw->y + y;
441706f2543Smrg	TheRect.width = w;
442706f2543Smrg	TheRect.height = h;
443706f2543Smrg
444706f2543Smrg	if(MaxBoxes > (infoRec->PreAllocSize/sizeof(BoxRec))) {
445706f2543Smrg	    pClipBoxes = malloc(MaxBoxes * sizeof(BoxRec));
446706f2543Smrg	    if(!pClipBoxes) return;
447706f2543Smrg	} else pClipBoxes = (BoxPtr)infoRec->PreAllocMem;
448706f2543Smrg
449706f2543Smrg	nboxes = XAAGetRectClipBoxes(pGC, pClipBoxes, 1, &TheRect);
450706f2543Smrg	pbox = pClipBoxes;
451706f2543Smrg
452706f2543Smrg	if(format == XYBitmap) {
453706f2543Smrg	    srcwidth = BitmapBytePad(leftPad + w);
454706f2543Smrg	    while(nboxes--) {
455706f2543Smrg		srcx = pbox->x1 - TheRect.x + leftPad;
456706f2543Smrg		srcy = pbox->y1 - TheRect.y;
457706f2543Smrg		(*infoRec->WriteBitmap)(infoRec->pScrn, pbox->x1, pbox->y1,
458706f2543Smrg			pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
459706f2543Smrg			(unsigned char*)pImage +
460706f2543Smrg				(srcwidth * srcy) + ((srcx >> 5) << 2),
461706f2543Smrg			srcwidth, srcx & 31, pGC->fgPixel, pGC->bgPixel,
462706f2543Smrg	 		pGC->alu, pGC->planemask);
463706f2543Smrg		pbox++;
464706f2543Smrg	    }
465706f2543Smrg        } else if(format == ZPixmap) {
466706f2543Smrg	    int Bpp = bpp >> 3;
467706f2543Smrg	    srcwidth = PixmapBytePad(leftPad + w, depth);
468706f2543Smrg	    while(nboxes--) {
469706f2543Smrg		srcx = pbox->x1 - TheRect.x + leftPad;
470706f2543Smrg		srcy = pbox->y1 - TheRect.y;
471706f2543Smrg		(*infoRec->WritePixmap)(infoRec->pScrn, pbox->x1, pbox->y1,
472706f2543Smrg			pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
473706f2543Smrg			(unsigned char*)pImage +
474706f2543Smrg				(srcwidth * srcy) + (srcx * Bpp),
475706f2543Smrg			srcwidth, pGC->alu, pGC->planemask, -1,
476706f2543Smrg			Bpp << 3, depth);
477706f2543Smrg		pbox++;
478706f2543Smrg	    }
479706f2543Smrg	} else { /* XYPixmap */
480706f2543Smrg	    int depth = pGC->depth;
481706f2543Smrg	    int numBox, increment;
482706f2543Smrg	    unsigned long i, mask;
483706f2543Smrg	    BoxPtr pntBox;
484706f2543Smrg
485706f2543Smrg	    srcwidth = BitmapBytePad(w + leftPad);
486706f2543Smrg	    increment = h * srcwidth;
487706f2543Smrg 	    i = 1 << (depth - 1);
488706f2543Smrg	    mask = ~0;
489706f2543Smrg
490706f2543Smrg	    if((infoRec->pScrn->overlayFlags & OVERLAY_8_32_PLANAR) &&
491706f2543Smrg							 (pGC->depth == 8)){
492706f2543Smrg		i = 0x80000000;  mask = 0xff000000;
493706f2543Smrg	    }
494706f2543Smrg
495706f2543Smrg	    for(; i & mask; i >>= 1, pImage += increment) {
496706f2543Smrg		if(i & pGC->planemask) {
497706f2543Smrg		    pntBox = pbox;
498706f2543Smrg		    numBox = nboxes;
499706f2543Smrg		    while(numBox--) {
500706f2543Smrg			srcx = pntBox->x1 - TheRect.x + leftPad;
501706f2543Smrg			srcy = pntBox->y1 - TheRect.y;
502706f2543Smrg			(*infoRec->WriteBitmap)(infoRec->pScrn,
503706f2543Smrg				pntBox->x1, pntBox->y1,
504706f2543Smrg				pntBox->x2 - pntBox->x1,
505706f2543Smrg				pntBox->y2 - pntBox->y1,
506706f2543Smrg				(unsigned char*)pImage +
507706f2543Smrg				(srcwidth * srcy) + ((srcx >> 5) << 2),
508706f2543Smrg				srcwidth, srcx & 31, ~0, 0, pGC->alu, i);
509706f2543Smrg			pntBox++;
510706f2543Smrg	    	    }
511706f2543Smrg		}
512706f2543Smrg	    }
513706f2543Smrg
514706f2543Smrg	}
515706f2543Smrg
516706f2543Smrg	if(pClipBoxes != (BoxPtr)infoRec->PreAllocMem)
517706f2543Smrg	    free(pClipBoxes);
518706f2543Smrg    } else
519706f2543Smrg	XAAFallbackOps.PutImage(pDraw, pGC, depth, x, y, w, h, leftPad,
520706f2543Smrg				format, pImage);
521706f2543Smrg}
522