Initial commit
[xorg_rtime.git] / xorg-server-1.4 / afb / afbblt.c
blob9eb4e4732c8534d92b4e6af48932d8507f1e58cb
1 /*
2 * afb copy area
3 */
5 /*
7 Copyright (c) 1989 X Consortium
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 Except as contained in this notice, the name of the X Consortium shall not be
27 used in advertising or otherwise to promote the sale, use or other dealings
28 in this Software without prior written authorization from the X Consortium.
30 Author: Keith Packard
34 #ifdef HAVE_DIX_CONFIG_H
35 #include <dix-config.h>
36 #endif
38 #include <stdlib.h>
40 #include <X11/X.h>
41 #include <X11/Xmd.h>
42 #include <X11/Xproto.h>
43 #include "afb.h"
44 #include "gcstruct.h"
45 #include "windowstr.h"
46 #include "scrnintstr.h"
47 #include "pixmapstr.h"
48 #include "regionstr.h"
49 #include "maskbits.h"
50 #include "fastblt.h"
51 #include "mergerop.h"
53 void
54 MROP_NAME(afbDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc, planemask)
55 DrawablePtr pSrc, pDst;
56 int alu;
57 RegionPtr prgnDst;
58 DDXPointPtr pptSrc;
59 unsigned long planemask;
61 PixelType *psrcBase, *pdstBase; /* start of src and dst bitmaps */
62 int widthSrc, widthDst; /* add to get to same position in next line */
63 int sizeSrc, sizeDst;
65 BoxPtr pbox;
66 int nbox;
68 BoxPtr pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
69 /* temporaries for shuffling rectangles */
70 DDXPointPtr pptTmp, pptNew1, pptNew2;
71 /* shuffling boxes entails shuffling the
72 source points too */
73 int w, h;
74 int xdir; /* 1 = left right, -1 = right left/ */
75 int ydir; /* 1 = top down, -1 = bottom up */
77 PixelType *psrcLine, *pdstLine;
78 /* pointers to line with current src and dst */
79 register PixelType *psrc; /* pointer to current src longword */
80 register PixelType *pdst; /* pointer to current dst longword */
82 MROP_DECLARE_REG()
84 /* following used for looping through a line */
85 PixelType startmask, endmask; /* masks for writing ends of dst */
86 int nlMiddle; /* whole longwords in dst */
87 int xoffSrc, xoffDst;
88 register int leftShift, rightShift;
89 register PixelType bits;
90 register PixelType bits1;
91 register int nl; /* temp copy of nlMiddle */
93 int careful;
94 int depthSrc;
95 int depthDst;
97 MROP_INITIALIZE(alu,0);
99 afbGetPixelWidthSizeDepthAndPointer(pSrc, widthSrc, sizeSrc, depthSrc,
100 psrcBase);
101 afbGetPixelWidthSizeDepthAndPointer(pDst, widthDst, sizeDst, depthDst,
102 pdstBase);
104 /* Special case where depth of dest pixmap is 1 but source pixmap isn't
105 * Used for GetImage to copy a plane from a source pixmap to a particular
106 * dest pixmap plane.
107 * Note: planemask should have only one bit set or several planes from
108 * the source will be copied to the same dest plane.
110 if (depthDst == 1 && depthDst != depthSrc)
111 sizeDst = 0;
113 /* XXX we have to err on the side of safety when both are windows,
114 * because we don't know if IncludeInferiors is being used.
116 careful = ((pSrc == pDst) ||
117 ((pSrc->type == DRAWABLE_WINDOW) &&
118 (pDst->type == DRAWABLE_WINDOW)));
120 pbox = REGION_RECTS(prgnDst);
121 nbox = REGION_NUM_RECTS(prgnDst);
123 pboxNew1 = NULL;
124 pptNew1 = NULL;
125 pboxNew2 = NULL;
126 pptNew2 = NULL;
127 if (careful && (pptSrc->y < pbox->y1)) {
128 /* walk source botttom to top */
129 ydir = -1;
130 widthSrc = -widthSrc;
131 widthDst = -widthDst;
133 if (nbox > 1) {
134 /* keep ordering in each band, reverse order of bands */
135 pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox);
136 if(!pboxNew1)
137 return;
138 pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox);
139 if(!pptNew1) {
140 DEALLOCATE_LOCAL(pboxNew1);
141 return;
143 pboxBase = pboxNext = pbox+nbox-1;
144 while (pboxBase >= pbox) {
145 while ((pboxNext >= pbox) &&
146 (pboxBase->y1 == pboxNext->y1))
147 pboxNext--;
148 pboxTmp = pboxNext+1;
149 pptTmp = pptSrc + (pboxTmp - pbox);
150 while (pboxTmp <= pboxBase) {
151 *pboxNew1++ = *pboxTmp++;
152 *pptNew1++ = *pptTmp++;
154 pboxBase = pboxNext;
156 pboxNew1 -= nbox;
157 pbox = pboxNew1;
158 pptNew1 -= nbox;
159 pptSrc = pptNew1;
161 } else {
162 /* walk source top to bottom */
163 ydir = 1;
166 if (careful && (pptSrc->x < pbox->x1)) {
167 /* walk source right to left */
168 xdir = -1;
170 if (nbox > 1) {
171 /* reverse order of rects in each band */
172 pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
173 pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
174 if(!pboxNew2 || !pptNew2) {
175 if (pptNew2)
176 DEALLOCATE_LOCAL(pptNew2);
177 if (pboxNew2)
178 DEALLOCATE_LOCAL(pboxNew2);
179 if (pboxNew1) {
180 DEALLOCATE_LOCAL(pptNew1);
181 DEALLOCATE_LOCAL(pboxNew1);
183 return;
185 pboxBase = pboxNext = pbox;
186 while (pboxBase < pbox+nbox) {
187 while ((pboxNext < pbox+nbox) && (pboxNext->y1 == pboxBase->y1))
188 pboxNext++;
189 pboxTmp = pboxNext;
190 pptTmp = pptSrc + (pboxTmp - pbox);
191 while (pboxTmp != pboxBase) {
192 *pboxNew2++ = *--pboxTmp;
193 *pptNew2++ = *--pptTmp;
195 pboxBase = pboxNext;
197 pboxNew2 -= nbox;
198 pbox = pboxNew2;
199 pptNew2 -= nbox;
200 pptSrc = pptNew2;
202 } else {
203 /* walk source left to right */
204 xdir = 1;
207 while(nbox--) {
208 int d;
209 for (d = 0; d < depthSrc; d++) {
210 PixelType *psrcB;
211 PixelType *pdstB;
213 if (!(planemask & (1 << d)))
214 continue;
216 psrcB = psrcBase + sizeSrc * d; /* @@@ NEXT PLANE @@@ */
217 pdstB = pdstBase + sizeDst * d; /* @@@ NEXT PLANE @@@ */
219 w = pbox->x2 - pbox->x1;
220 h = pbox->y2 - pbox->y1;
222 if (ydir == -1) { /* start at last scanline of rectangle */
223 psrcLine = afbScanlineDeltaSrc(psrcB, -(pptSrc->y+h-1), widthSrc);
224 pdstLine = afbScanlineDeltaDst(pdstB, -(pbox->y2-1), widthDst);
225 } else { /* start at first scanline */
226 psrcLine = afbScanlineDeltaSrc(psrcB, pptSrc->y, widthSrc);
227 pdstLine = afbScanlineDeltaDst(pdstB, pbox->y1, widthDst);
229 if ((pbox->x1 & PIM) + w <= PPW) {
230 maskpartialbits (pbox->x1, w, startmask);
231 endmask = 0;
232 nlMiddle = 0;
233 } else {
234 maskbits(pbox->x1, w, startmask, endmask, nlMiddle);
236 if (xdir == 1) {
237 xoffSrc = pptSrc->x & PIM;
238 xoffDst = pbox->x1 & PIM;
239 pdstLine += (pbox->x1 >> PWSH);
240 psrcLine += (pptSrc->x >> PWSH);
241 #ifdef DO_UNALIGNED_BITBLT
242 nl = xoffSrc - xoffDst;
243 psrcLine = (PixelType *)(((unsigned char *) psrcLine) + nl);
244 #else
245 if (xoffSrc == xoffDst)
246 #endif
248 while (h--) {
249 psrc = psrcLine;
250 pdst = pdstLine;
251 if (startmask) {
252 *pdst = MROP_MASK(*psrc, *pdst, startmask);
253 psrc++;
254 pdst++;
256 nl = nlMiddle;
258 #ifdef LARGE_INSTRUCTION_CACHE
259 #ifdef FAST_CONSTANT_OFFSET_MODE
261 psrc += nl & (UNROLL-1);
262 pdst += nl & (UNROLL-1);
264 #define BodyOdd(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]);
265 #define BodyEven(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]);
267 #define LoopReset \
268 pdst += UNROLL; \
269 psrc += UNROLL;
271 #else
273 #define BodyOdd(n) *pdst = MROP_SOLID (*psrc, *pdst); pdst++; psrc++;
274 #define BodyEven(n) BodyOdd(n)
276 #define LoopReset ;
278 #endif
279 PackedLoop
281 #undef BodyOdd
282 #undef BodyEven
283 #undef LoopReset
285 #else
286 #ifdef NOTDEF
287 /* you'd think this would be faster --
288 * a single instruction instead of 6
289 * but measurements show it to be ~15% slower
291 while ((nl -= 6) >= 0) {
292 asm ("moveml %1+,#0x0c0f;moveml#0x0c0f,%0"
293 : "=m" (*(char *)pdst)
294 : "m" (*(char *)psrc)
295 : "d0", "d1", "d2", "d3",
296 "a2", "a3");
297 pdst += 6;
299 nl += 6;
300 while (nl--)
301 *pdst++ = *psrc++;
302 #endif
303 DuffL(nl, label1,
304 *pdst = MROP_SOLID (*psrc, *pdst);
305 pdst++; psrc++;)
306 #endif
308 if (endmask)
309 *pdst = MROP_MASK(*psrc, *pdst, endmask);
310 afbScanlineIncDst(pdstLine, widthDst);
311 afbScanlineIncSrc(psrcLine, widthSrc);
314 #ifndef DO_UNALIGNED_BITBLT
315 else {
316 if (xoffSrc > xoffDst) {
317 leftShift = (xoffSrc - xoffDst);
318 rightShift = PPW - leftShift;
319 } else {
320 rightShift = (xoffDst - xoffSrc);
321 leftShift = PPW - rightShift;
323 while (h--) {
324 psrc = psrcLine;
325 pdst = pdstLine;
326 bits = 0;
327 if (xoffSrc > xoffDst)
328 bits = *psrc++;
329 if (startmask) {
330 bits1 = BitLeft(bits,leftShift);
331 bits = *psrc++;
332 bits1 |= BitRight(bits,rightShift);
333 *pdst = MROP_MASK(bits1, *pdst, startmask);
334 pdst++;
336 nl = nlMiddle;
338 #ifdef LARGE_INSTRUCTION_CACHE
339 bits1 = bits;
341 #ifdef FAST_CONSTANT_OFFSET_MODE
343 psrc += nl & (UNROLL-1);
344 pdst += nl & (UNROLL-1);
346 #define BodyOdd(n) \
347 bits = psrc[-n]; \
348 pdst[-n] = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), pdst[-n]);
350 #define BodyEven(n) \
351 bits1 = psrc[-n]; \
352 pdst[-n] = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), pdst[-n]);
354 #define LoopReset \
355 pdst += UNROLL; \
356 psrc += UNROLL;
358 #else
360 #define BodyOdd(n) \
361 bits = *psrc++; \
362 *pdst = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), *pdst); \
363 pdst++;
365 #define BodyEven(n) \
366 bits1 = *psrc++; \
367 *pdst = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), *pdst); \
368 pdst++;
370 #define LoopReset ;
372 #endif /* !FAST_CONSTANT_OFFSET_MODE */
374 PackedLoop
376 #undef BodyOdd
377 #undef BodyEven
378 #undef LoopReset
380 #else
381 DuffL(nl,label2,
382 bits1 = BitLeft(bits, leftShift);
383 bits = *psrc++;
384 *pdst = MROP_SOLID (bits1 | BitRight(bits, rightShift), *pdst);
385 pdst++;
387 #endif
389 if (endmask) {
390 bits1 = BitLeft(bits, leftShift);
391 if (BitLeft(endmask, rightShift)) {
392 bits = *psrc;
393 bits1 |= BitRight(bits, rightShift);
395 *pdst = MROP_MASK (bits1, *pdst, endmask);
397 afbScanlineIncDst(pdstLine, widthDst);
398 afbScanlineIncSrc(psrcLine, widthSrc);
401 #endif /* DO_UNALIGNED_BITBLT */
402 } else { /* xdir == -1 */
403 xoffSrc = (pptSrc->x + w - 1) & PIM;
404 xoffDst = (pbox->x2 - 1) & PIM;
405 pdstLine += ((pbox->x2-1) >> PWSH) + 1;
406 psrcLine += ((pptSrc->x+w - 1) >> PWSH) + 1;
407 #ifdef DO_UNALIGNED_BITBLT
408 nl = xoffSrc - xoffDst;
409 psrcLine = (PixelType *)
410 (((unsigned char *) psrcLine) + nl);
411 #else
412 if (xoffSrc == xoffDst)
413 #endif
415 while (h--) {
416 psrc = psrcLine;
417 pdst = pdstLine;
418 if (endmask) {
419 pdst--;
420 psrc--;
421 *pdst = MROP_MASK (*psrc, *pdst, endmask);
423 nl = nlMiddle;
425 #ifdef LARGE_INSTRUCTION_CACHE
426 #ifdef FAST_CONSTANT_OFFSET_MODE
427 psrc -= nl & (UNROLL - 1);
428 pdst -= nl & (UNROLL - 1);
430 #define BodyOdd(n) pdst[n-1] = MROP_SOLID (psrc[n-1], pdst[n-1]);
432 #define BodyEven(n) BodyOdd(n)
434 #define LoopReset \
435 pdst -= UNROLL;\
436 psrc -= UNROLL;
438 #else
440 #define BodyOdd(n) --pdst; --psrc; *pdst = MROP_SOLID(*psrc, *pdst);
441 #define BodyEven(n) BodyOdd(n)
442 #define LoopReset ;
444 #endif
445 PackedLoop
447 #undef BodyOdd
448 #undef BodyEven
449 #undef LoopReset
451 #else
452 DuffL(nl,label3,
453 --pdst; --psrc; *pdst = MROP_SOLID (*psrc, *pdst);)
454 #endif
456 if (startmask) {
457 --pdst;
458 --psrc;
459 *pdst = MROP_MASK(*psrc, *pdst, startmask);
461 afbScanlineIncDst(pdstLine, widthDst);
462 afbScanlineIncSrc(psrcLine, widthSrc);
465 #ifndef DO_UNALIGNED_BITBLT
466 else {
467 if (xoffDst > xoffSrc) {
468 rightShift = (xoffDst - xoffSrc);
469 leftShift = PPW - rightShift;
470 } else {
471 leftShift = (xoffSrc - xoffDst);
472 rightShift = PPW - leftShift;
474 while (h--) {
475 psrc = psrcLine;
476 pdst = pdstLine;
477 bits = 0;
478 if (xoffDst > xoffSrc)
479 bits = *--psrc;
480 if (endmask) {
481 bits1 = BitRight(bits, rightShift);
482 bits = *--psrc;
483 bits1 |= BitLeft(bits, leftShift);
484 pdst--;
485 *pdst = MROP_MASK(bits1, *pdst, endmask);
487 nl = nlMiddle;
489 #ifdef LARGE_INSTRUCTION_CACHE
490 bits1 = bits;
491 #ifdef FAST_CONSTANT_OFFSET_MODE
492 psrc -= nl & (UNROLL - 1);
493 pdst -= nl & (UNROLL - 1);
495 #define BodyOdd(n) \
496 bits = psrc[n-1]; \
497 pdst[n-1] = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),pdst[n-1]);
499 #define BodyEven(n) \
500 bits1 = psrc[n-1]; \
501 pdst[n-1] = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),pdst[n-1]);
503 #define LoopReset \
504 pdst -= UNROLL; \
505 psrc -= UNROLL;
507 #else
509 #define BodyOdd(n) \
510 bits = *--psrc; --pdst; \
511 *pdst = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),*pdst);
513 #define BodyEven(n) \
514 bits1 = *--psrc; --pdst; \
515 *pdst = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),*pdst);
517 #define LoopReset ;
519 #endif
521 PackedLoop
523 #undef BodyOdd
524 #undef BodyEven
525 #undef LoopReset
527 #else
528 DuffL(nl, label4,
529 bits1 = BitRight(bits, rightShift);
530 bits = *--psrc;
531 --pdst;
532 *pdst = MROP_SOLID(bits1 | BitLeft(bits, leftShift),*pdst);
534 #endif
536 if (startmask) {
537 bits1 = BitRight(bits, rightShift);
538 if (BitRight (startmask, leftShift)) {
539 bits = *--psrc;
540 bits1 |= BitLeft(bits, leftShift);
542 --pdst;
543 *pdst = MROP_MASK(bits1, *pdst, startmask);
545 afbScanlineIncDst(pdstLine, widthDst);
546 afbScanlineIncSrc(psrcLine, widthSrc);
549 #endif
552 pbox++;
553 pptSrc++;
555 if (pboxNew2) {
556 DEALLOCATE_LOCAL(pptNew2);
557 DEALLOCATE_LOCAL(pboxNew2);
559 if (pboxNew1) {
560 DEALLOCATE_LOCAL(pptNew1);
561 DEALLOCATE_LOCAL(pboxNew1);