1
2#ifdef HAVE_XORG_CONFIG_H
3#include <xorg-config.h>
4#endif
5
6#include "misc.h"
7#include "xf86.h"
8#include "xf86_OSproc.h"
9#include "servermd.h"
10
11#include <X11/X.h>
12#include "scrnintstr.h"
13#include "mi.h"
14#include "pixmapstr.h"
15#include "xf86str.h"
16#include "xaa.h"
17#include "xaalocal.h"
18
19void XAAMoveDWORDS_FixedBase(
20   register CARD32* dest,
21   register CARD32* src,
22   register int dwords )
23{
24     while(dwords & ~0x03) {
25	 *dest = *src;
26	 *dest = *(src + 1);
27	 *dest = *(src + 2);
28	 *dest = *(src + 3);
29	 dwords -= 4;
30	 src += 4;
31     }
32
33     if(!dwords) return;
34     *dest = *src;
35     if(dwords == 1) return;
36     *dest = *(src + 1);
37     if(dwords == 2) return;
38     *dest = *(src + 2);
39}
40
41void XAAMoveDWORDS(
42   register CARD32* dest,
43   register CARD32* src,
44   register int dwords )
45{
46     while(dwords & ~0x03) {
47	*dest = *src;
48	*(dest + 1) = *(src + 1);
49	*(dest + 2) = *(src + 2);
50	*(dest + 3) = *(src + 3);
51	src += 4;
52	dest += 4;
53	dwords -= 4;
54     }
55     if(!dwords) return;
56     *dest = *src;
57     if(dwords == 1) return;
58     *(dest + 1) = *(src + 1);
59     if(dwords == 2) return;
60     *(dest + 2) = *(src + 2);
61}
62
63void XAAMoveDWORDS_FixedSrc(
64   register CARD32* dest,
65   register CARD32* src,
66   register int dwords )
67{
68     while(dwords & ~0x03) {
69	*dest = *src;
70	*(dest + 1) = *src;
71	*(dest + 2) = *src;
72	*(dest + 3) = *src;
73	dest += 4;
74	dwords -= 4;
75     }
76     if(!dwords) return;
77     *dest = *src;
78     if(dwords == 1) return;
79     *(dest + 1) = *src;
80     if(dwords == 2) return;
81     *(dest + 2) = *src;
82}
83
84static void
85XAAWritePixmap32To24(
86   ScrnInfoPtr pScrn,
87   int x, int y, int w, int h,
88   unsigned char *srcInit,
89   int srcwidth,	/* bytes */
90   int rop,
91   unsigned int planemask,
92   int trans
93){
94    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
95    int count, dwords = bytes_to_int32(w * 3);
96    CARD32 *src, *dst;
97    Bool PlusOne = FALSE;
98
99    if((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) &&
100					((dwords * h) & 0x01)) {
101	PlusOne = TRUE;
102    }
103
104    (*infoRec->SetupForImageWrite)(pScrn, rop, planemask, trans, 24, 24);
105    (*infoRec->SubsequentImageWriteRect)(pScrn, x, y, w, h, 0);
106
107    if(dwords > infoRec->ImageWriteRange) {
108	dst = (CARD32*)infoRec->ImageWriteBase;
109	while(h--) {
110	    src = (CARD32*)srcInit;
111  	    count = w;
112
113	    while(count >= 4) {
114		*dst = (src[0] & 0x00ffffff) | (src[1] << 24);
115		*dst = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16);
116		*dst = ((src[2] >> 16) & 0x000000ff) | (src[3] << 8);
117		src += 4;
118		count -= 4;
119	    }
120	    switch(count) {
121	    case 0:	break;
122	    case 1:	*dst = src[0];
123			break;
124	    case 2:	*dst = (src[0] & 0x00ffffff) | (src[1] << 24);
125			*dst = src[1] >> 8;
126			break;
127	    default:	*dst = (src[0] & 0x00ffffff) | (src[1] << 24);
128			*dst = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16);
129			*dst = src[2] >> 16;
130			break;
131	    }
132	    srcInit += srcwidth;
133	}
134    } else {
135	while(h--) {
136	    dst = (CARD32*)infoRec->ImageWriteBase;
137	    src = (CARD32*)srcInit;
138  	    count = w;
139
140	    while(count >= 4) {
141		dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24);
142		dst[1] = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16);
143		dst[2] = ((src[2] >> 16) & 0x000000ff) | (src[3] << 8);
144		dst += 3;
145		src += 4;
146		count -= 4;
147	    }
148	    switch(count) {
149	    case 0:	break;
150	    case 1:	dst[0] = src[0];
151			break;
152	    case 2:	dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24);
153			dst[1] = src[1] >> 8;
154			break;
155	    default:	dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24);
156			dst[1] = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16);
157			dst[2] = src[2] >> 16;
158			break;
159	    }
160	    srcInit += srcwidth;
161	}
162    }
163
164    if(PlusOne) {
165	CARD32* base = (CARD32*)infoRec->ImageWriteBase;
166	*base = 0x00000000;
167    }
168
169    if(infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE)
170	(*infoRec->Sync)(pScrn);
171    else SET_SYNC_FLAG(infoRec);
172
173}
174
175void
176XAAWritePixmap (
177   ScrnInfoPtr pScrn,
178   int x, int y, int w, int h,
179   unsigned char *src,
180   int srcwidth,	/* bytes */
181   int rop,
182   unsigned int planemask,
183   int trans,
184   int bpp, int depth
185){
186    XAAInfoRecPtr infoRec;
187    int dwords, skipleft, Bpp;
188    Bool beCareful, PlusOne;
189
190    if((bpp == 32) && (pScrn->bitsPerPixel == 24)) {
191	XAAWritePixmap32To24(pScrn, x, y, w, h, src, srcwidth,
192						rop, planemask, trans);
193	return;
194    }
195
196    infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
197    beCareful = PlusOne = FALSE;
198    Bpp = bpp >> 3;
199
200    if((skipleft = (long)src & 0x03L)) {
201	if(!(infoRec->ImageWriteFlags & LEFT_EDGE_CLIPPING)) {
202	   skipleft = 0;
203	   beCareful = TRUE;
204	   goto BAD_ALIGNMENT;
205	}
206
207	if(Bpp == 3)
208	   skipleft = 4 - skipleft;
209	else
210	   skipleft /= Bpp;
211
212	if((x < skipleft) && !(infoRec->ImageWriteFlags &
213				 LEFT_EDGE_CLIPPING_NEGATIVE_X)) {
214	   skipleft = 0;
215	   beCareful = TRUE;
216	   goto BAD_ALIGNMENT;
217	}
218
219	x -= skipleft;
220	w += skipleft;
221
222	if(Bpp == 3)
223	   src -= 3 * skipleft;
224	else   /* is this Alpha friendly ? */
225	   src = (unsigned char*)((long)src & ~0x03L);
226    }
227
228BAD_ALIGNMENT:
229
230    dwords = bytes_to_int32(w * Bpp);
231
232    if((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) &&
233						((dwords * h) & 0x01)) {
234	PlusOne = TRUE;
235    }
236
237
238    (*infoRec->SetupForImageWrite)(pScrn, rop, planemask, trans, bpp, depth);
239    (*infoRec->SubsequentImageWriteRect)(pScrn, x, y, w, h, skipleft);
240
241    if(beCareful) {
242	/* in cases with bad alignment we have to be careful not
243	   to read beyond the end of the source */
244	if(((x * Bpp) + (dwords << 2)) > srcwidth) h--;
245	else beCareful = FALSE;
246    }
247
248    if(dwords > infoRec->ImageWriteRange) {
249	while(h--) {
250	    XAAMoveDWORDS_FixedBase((CARD32*)infoRec->ImageWriteBase,
251		(CARD32*)src, dwords);
252	    src += srcwidth;
253	}
254	if(beCareful) {
255	   int shift = ((long)src & 0x03L) << 3;
256	   if(--dwords)
257		XAAMoveDWORDS_FixedBase((CARD32*)infoRec->ImageWriteBase,
258			(CARD32*)src, dwords);
259	   src = (unsigned char*)((long)(src + (dwords << 2)) & ~0x03L);
260	   *((CARD32*)infoRec->ImageWriteBase) = *((CARD32*)src) >> shift;
261	}
262    } else {
263	if(srcwidth == (dwords << 2)) {
264	   int decrement = infoRec->ImageWriteRange/dwords;
265
266	   while(h > decrement) {
267		XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase,
268	 		(CARD32*)src, dwords * decrement);
269		src += (srcwidth * decrement);
270		h -= decrement;
271	   }
272	   if(h) {
273		XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase,
274	 		(CARD32*)src, dwords * h);
275		if(beCareful) src += (srcwidth * h);
276	   }
277	} else {
278	    while(h--) {
279		XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase,
280	 		(CARD32*)src, dwords);
281		src += srcwidth;
282	    }
283	}
284
285	if(beCareful) {
286	    int shift = ((long)src & 0x03L) << 3;
287	    if(--dwords)
288		XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase,
289					(CARD32*)src, dwords);
290	    src = (unsigned char*)((long)(src + (dwords << 2)) & ~0x03L);
291
292	    ((CARD32*)infoRec->ImageWriteBase)[dwords] =
293			*((CARD32*)src) >> shift;
294	}
295    }
296
297    if(PlusOne) {
298	CARD32* base = (CARD32*)infoRec->ImageWriteBase;
299	*base = 0x00000000;
300    }
301
302    if(infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE)
303	(*infoRec->Sync)(pScrn);
304    else SET_SYNC_FLAG(infoRec);
305}
306
307
308void
309XAAWritePixmapScanline (
310   ScrnInfoPtr pScrn,
311   int x, int y, int w, int h,
312   unsigned char *src,
313   int srcwidth,	/* bytes */
314   int rop,
315   unsigned int planemask,
316   int trans,
317   int bpp, int depth
318){
319    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
320    int dwords, skipleft, bufferNo = 0, Bpp = bpp >> 3;
321    Bool beCareful = FALSE;
322    CARD32* base;
323
324    if((skipleft = (long)src & 0x03L)) {
325	if(!(infoRec->ScanlineImageWriteFlags & LEFT_EDGE_CLIPPING)) {
326	   skipleft = 0;
327	   beCareful = TRUE;
328	   goto BAD_ALIGNMENT;
329	}
330
331	if(Bpp == 3)
332	   skipleft = 4 - skipleft;
333	else
334	   skipleft /= Bpp;
335
336	if((x < skipleft) && !(infoRec->ScanlineImageWriteFlags &
337				 LEFT_EDGE_CLIPPING_NEGATIVE_X)) {
338	   skipleft = 0;
339	   beCareful = TRUE;
340	   goto BAD_ALIGNMENT;
341	}
342
343	x -= skipleft;
344	w += skipleft;
345
346	if(Bpp == 3)
347	   src -= 3 * skipleft;
348	else
349	   src = (unsigned char*)((long)src & ~0x03L);
350    }
351
352BAD_ALIGNMENT:
353
354    dwords = bytes_to_int32(w * Bpp);
355
356    (*infoRec->SetupForScanlineImageWrite)(
357				pScrn, rop, planemask, trans, bpp, depth);
358    (*infoRec->SubsequentScanlineImageWriteRect)(pScrn, x, y, w, h, skipleft);
359
360    if(beCareful) {
361	/* in cases with bad alignment we have to be careful not
362	   to read beyond the end of the source */
363	if(((x * Bpp) + (dwords << 2)) > srcwidth) h--;
364	else beCareful = FALSE;
365    }
366
367    while(h--) {
368	base = (CARD32*)infoRec->ScanlineImageWriteBuffers[bufferNo];
369	XAAMoveDWORDS(base, (CARD32*)src, dwords);
370	(*infoRec->SubsequentImageWriteScanline)(pScrn, bufferNo++);
371	src += srcwidth;
372	if(bufferNo >= infoRec->NumScanlineImageWriteBuffers)
373	    bufferNo = 0;
374    }
375
376    if(beCareful) {
377	int shift = ((long)src & 0x03L) << 3;
378	base = (CARD32*)infoRec->ScanlineImageWriteBuffers[bufferNo];
379	if(--dwords)
380	    XAAMoveDWORDS(base,(CARD32*)src, dwords);
381	src = (unsigned char*)((long)(src + (dwords << 2)) & ~0x03L);
382
383	base[dwords] = *((CARD32*)src) >> shift;
384	(*infoRec->SubsequentImageWriteScanline)(pScrn, bufferNo);
385    }
386
387    SET_SYNC_FLAG(infoRec);
388}
389
390
391void
392XAAPutImage(
393    DrawablePtr pDraw,
394    GCPtr       pGC,
395    int         depth,
396    int 	x,
397    int		y,
398    int		w,
399    int		h,
400    int         leftPad,
401    int         format,
402    char        *pImage
403){
404    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
405    int bpp = BitsPerPixel(depth);
406    Bool depthBug = FALSE;
407    if(!w || !h) return;
408
409    if(!RegionNumRects(pGC->pCompositeClip))
410	return;
411
412    depthBug = XAA_DEPTH_BUG(pGC);
413
414    if(((format == ZPixmap) && infoRec->WritePixmap &&
415	     ((pDraw->bitsPerPixel == bpp) ||
416		((pDraw->bitsPerPixel == 24) &&  (bpp == 32) &&
417		(infoRec->WritePixmapFlags & CONVERT_32BPP_TO_24BPP))) &&
418	     CHECK_ROP(pGC,infoRec->WritePixmapFlags) &&
419	     CHECK_ROPSRC(pGC,infoRec->WritePixmapFlags) &&
420	     CHECK_PLANEMASK(pGC,infoRec->WritePixmapFlags) &&
421	     CHECK_NO_GXCOPY(pGC,infoRec->WritePixmapFlags)) ||
422       ((format == XYBitmap) && !depthBug && infoRec->WriteBitmap &&
423	     CHECK_ROP(pGC,infoRec->WriteBitmapFlags) &&
424	     CHECK_ROPSRC(pGC,infoRec->WriteBitmapFlags) &&
425	     CHECK_PLANEMASK(pGC,infoRec->WriteBitmapFlags) &&
426	     CHECK_COLORS(pGC,infoRec->WriteBitmapFlags) &&
427	     !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)) ||
428       ((format == XYPixmap) && !depthBug && infoRec->WriteBitmap &&
429	     CHECK_ROP(pGC,infoRec->WriteBitmapFlags) &&
430	     CHECK_ROPSRC(pGC,infoRec->WriteBitmapFlags) &&
431	     !(infoRec->WriteBitmapFlags & NO_PLANEMASK) &&
432	     !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY))){
433
434	int MaxBoxes = RegionNumRects(pGC->pCompositeClip);
435	BoxPtr pbox, pClipBoxes;
436	int nboxes, srcx, srcy, srcwidth;
437	xRectangle TheRect;
438
439	TheRect.x = pDraw->x + x;
440	TheRect.y = pDraw->y + y;
441	TheRect.width = w;
442	TheRect.height = h;
443
444	if(MaxBoxes > (infoRec->PreAllocSize/sizeof(BoxRec))) {
445	    pClipBoxes = malloc(MaxBoxes * sizeof(BoxRec));
446	    if(!pClipBoxes) return;
447	} else pClipBoxes = (BoxPtr)infoRec->PreAllocMem;
448
449	nboxes = XAAGetRectClipBoxes(pGC, pClipBoxes, 1, &TheRect);
450	pbox = pClipBoxes;
451
452	if(format == XYBitmap) {
453	    srcwidth = BitmapBytePad(leftPad + w);
454	    while(nboxes--) {
455		srcx = pbox->x1 - TheRect.x + leftPad;
456		srcy = pbox->y1 - TheRect.y;
457		(*infoRec->WriteBitmap)(infoRec->pScrn, pbox->x1, pbox->y1,
458			pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
459			(unsigned char*)pImage +
460				(srcwidth * srcy) + ((srcx >> 5) << 2),
461			srcwidth, srcx & 31, pGC->fgPixel, pGC->bgPixel,
462	 		pGC->alu, pGC->planemask);
463		pbox++;
464	    }
465        } else if(format == ZPixmap) {
466	    int Bpp = bpp >> 3;
467	    srcwidth = PixmapBytePad(leftPad + w, depth);
468	    while(nboxes--) {
469		srcx = pbox->x1 - TheRect.x + leftPad;
470		srcy = pbox->y1 - TheRect.y;
471		(*infoRec->WritePixmap)(infoRec->pScrn, pbox->x1, pbox->y1,
472			pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
473			(unsigned char*)pImage +
474				(srcwidth * srcy) + (srcx * Bpp),
475			srcwidth, pGC->alu, pGC->planemask, -1,
476			Bpp << 3, depth);
477		pbox++;
478	    }
479	} else { /* XYPixmap */
480	    int depth = pGC->depth;
481	    int numBox, increment;
482	    unsigned long i, mask;
483	    BoxPtr pntBox;
484
485	    srcwidth = BitmapBytePad(w + leftPad);
486	    increment = h * srcwidth;
487 	    i = 1 << (depth - 1);
488	    mask = ~0;
489
490	    if((infoRec->pScrn->overlayFlags & OVERLAY_8_32_PLANAR) &&
491							 (pGC->depth == 8)){
492		i = 0x80000000;  mask = 0xff000000;
493	    }
494
495	    for(; i & mask; i >>= 1, pImage += increment) {
496		if(i & pGC->planemask) {
497		    pntBox = pbox;
498		    numBox = nboxes;
499		    while(numBox--) {
500			srcx = pntBox->x1 - TheRect.x + leftPad;
501			srcy = pntBox->y1 - TheRect.y;
502			(*infoRec->WriteBitmap)(infoRec->pScrn,
503				pntBox->x1, pntBox->y1,
504				pntBox->x2 - pntBox->x1,
505				pntBox->y2 - pntBox->y1,
506				(unsigned char*)pImage +
507				(srcwidth * srcy) + ((srcx >> 5) << 2),
508				srcwidth, srcx & 31, ~0, 0, pGC->alu, i);
509			pntBox++;
510	    	    }
511		}
512	    }
513
514	}
515
516	if(pClipBoxes != (BoxPtr)infoRec->PreAllocMem)
517	    free(pClipBoxes);
518    } else
519	XAAFallbackOps.PutImage(pDraw, pGC, depth, x, y, w, h, leftPad,
520				format, pImage);
521}
522