]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/mfb/mfbblt.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / programs / Xserver / mfb / mfbblt.c
1 /*
2  * mfb copy area
3  */
4
5 /*
6
7 Copyright (c) 1989  X Consortium
8
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:
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
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.
25
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.
29
30 Author: Keith Packard
31
32 */
33 /* $XConsortium: mfbblt.c,v 1.11 94/04/17 20:28:16 dpw Exp $ */
34 /* $XFree86: xc/programs/Xserver/mfb/mfbblt.c,v 3.0 1994/08/12 14:03:38 dawes Exp $ */
35
36 #include        "X.h"
37 #include        "Xmd.h"
38 #include        "Xproto.h"
39 #include        "mfb.h"
40 #include        "gcstruct.h"
41 #include        "windowstr.h"
42 #include        "scrnintstr.h"
43 #include        "pixmapstr.h"
44 #include        "regionstr.h"
45 #include        "maskbits.h"
46 #include        "fastblt.h"
47 #include        "mergerop.h"
48
49 void
50 MROP_NAME(mfbDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc)
51     DrawablePtr     pSrc, pDst;
52     int             alu;
53     RegionPtr       prgnDst;
54     DDXPointPtr     pptSrc;
55 {
56     PixelType *psrcBase, *pdstBase;     
57                                 /* start of src and dst bitmaps */
58     int widthSrc, widthDst;     /* add to get to same position in next line */
59
60     BoxPtr pbox;
61     int nbox;
62
63     BoxPtr pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
64                                 /* temporaries for shuffling rectangles */
65     DDXPointPtr pptTmp, pptNew1, pptNew2;
66                                 /* shuffling boxes entails shuffling the
67                                    source points too */
68     int w, h;
69     int xdir;                   /* 1 = left right, -1 = right left/ */
70     int ydir;                   /* 1 = top down, -1 = bottom up */
71
72     PixelType *psrcLine, *pdstLine;     
73                                 /* pointers to line with current src and dst */
74     register PixelType *psrc;/* pointer to current src longword */
75     register PixelType *pdst;/* pointer to current dst longword */
76
77     MROP_DECLARE_REG()
78
79                                 /* following used for looping through a line */
80     PixelType startmask, endmask;       /* masks for writing ends of dst */
81     int nlMiddle;               /* whole longwords in dst */
82     int xoffSrc, xoffDst;
83     register int leftShift, rightShift;
84     register PixelType bits;
85     register PixelType bits1;
86     register int nl;            /* temp copy of nlMiddle */
87
88                                 /* place to store full source word */
89     int nstart;                 /* number of ragged bits at start of dst */
90     int nend;                   /* number of ragged bits at end of dst */
91     int srcStartOver;           /* pulling nstart bits from src
92                                    overflows into the next word? */
93     int careful;
94     int tmpSrc;
95
96     MROP_INITIALIZE(alu,0);
97
98     mfbGetPixelWidthAndPointer(pSrc, widthSrc, psrcBase);
99
100     mfbGetPixelWidthAndPointer(pDst, widthDst, pdstBase);
101
102     /* XXX we have to err on the side of safety when both are windows,
103      * because we don't know if IncludeInferiors is being used.
104      */
105     careful = ((pSrc == pDst) ||
106                ((pSrc->type == DRAWABLE_WINDOW) &&
107                 (pDst->type == DRAWABLE_WINDOW)));
108
109     pbox = REGION_RECTS(prgnDst);
110     nbox = REGION_NUM_RECTS(prgnDst);
111
112     pboxNew1 = NULL;
113     pptNew1 = NULL;
114     pboxNew2 = NULL;
115     pptNew2 = NULL;
116     if (careful && (pptSrc->y < pbox->y1))
117     {
118         /* walk source botttom to top */
119         ydir = -1;
120         widthSrc = -widthSrc;
121         widthDst = -widthDst;
122
123         if (nbox > 1)
124         {
125             /* keep ordering in each band, reverse order of bands */
126             pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
127             if(!pboxNew1)
128                 return;
129             pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
130             if(!pptNew1)
131             {
132                 DEALLOCATE_LOCAL(pboxNew1);
133                 return;
134             }
135             pboxBase = pboxNext = pbox+nbox-1;
136             while (pboxBase >= pbox)
137             {
138                 while ((pboxNext >= pbox) &&
139                        (pboxBase->y1 == pboxNext->y1))
140                     pboxNext--;
141                 pboxTmp = pboxNext+1;
142                 pptTmp = pptSrc + (pboxTmp - pbox);
143                 while (pboxTmp <= pboxBase)
144                 {
145                     *pboxNew1++ = *pboxTmp++;
146                     *pptNew1++ = *pptTmp++;
147                 }
148                 pboxBase = pboxNext;
149             }
150             pboxNew1 -= nbox;
151             pbox = pboxNew1;
152             pptNew1 -= nbox;
153             pptSrc = pptNew1;
154         }
155     }
156     else
157     {
158         /* walk source top to bottom */
159         ydir = 1;
160     }
161
162     if (careful && (pptSrc->x < pbox->x1))
163     {
164         /* walk source right to left */
165         xdir = -1;
166
167         if (nbox > 1)
168         {
169             /* reverse order of rects in each band */
170             pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
171             pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
172             if(!pboxNew2 || !pptNew2)
173             {
174                 if (pptNew2) DEALLOCATE_LOCAL(pptNew2);
175                 if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2);
176                 if (pboxNew1)
177                 {
178                     DEALLOCATE_LOCAL(pptNew1);
179                     DEALLOCATE_LOCAL(pboxNew1);
180                 }
181                 return;
182             }
183             pboxBase = pboxNext = pbox;
184             while (pboxBase < pbox+nbox)
185             {
186                 while ((pboxNext < pbox+nbox) &&
187                        (pboxNext->y1 == pboxBase->y1))
188                     pboxNext++;
189                 pboxTmp = pboxNext;
190                 pptTmp = pptSrc + (pboxTmp - pbox);
191                 while (pboxTmp != pboxBase)
192                 {
193                     *pboxNew2++ = *--pboxTmp;
194                     *pptNew2++ = *--pptTmp;
195                 }
196                 pboxBase = pboxNext;
197             }
198             pboxNew2 -= nbox;
199             pbox = pboxNew2;
200             pptNew2 -= nbox;
201             pptSrc = pptNew2;
202         }
203     }
204     else
205     {
206         /* walk source left to right */
207         xdir = 1;
208     }
209
210     while(nbox--)
211     {
212         w = pbox->x2 - pbox->x1;
213         h = pbox->y2 - pbox->y1;
214
215         if (ydir == -1) /* start at last scanline of rectangle */
216         {
217             psrcLine = mfbScanlineDeltaSrc(psrcBase, -(pptSrc->y+h-1), widthSrc);
218             pdstLine = mfbScanlineDeltaDst(pdstBase, -(pbox->y2-1), widthDst);
219         }
220         else /* start at first scanline */
221         {
222             psrcLine = mfbScanlineDeltaSrc(psrcBase, pptSrc->y, widthSrc);
223             pdstLine = mfbScanlineDeltaDst(pdstBase, pbox->y1, widthDst);
224         }
225         if ((pbox->x1 & PIM) + w <= PPW)
226         {
227             maskpartialbits (pbox->x1, w, startmask);
228             endmask = 0;
229             nlMiddle = 0;
230         }
231         else
232         {
233             maskbits(pbox->x1, w, startmask, endmask, nlMiddle);
234         }
235         if (xdir == 1)
236         {
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 *)
244                         (((unsigned char *) psrcLine) + nl);
245 #else
246             if (xoffSrc == xoffDst)
247 #endif
248             {
249                 while (h--)
250                 {
251                     psrc = psrcLine;
252                     pdst = pdstLine;
253                     if (startmask)
254                     {
255                         *pdst = MROP_MASK(*psrc, *pdst, startmask);
256                         psrc++;
257                         pdst++;
258                     }
259                     nl = nlMiddle;
260
261 #ifdef LARGE_INSTRUCTION_CACHE
262 #ifdef FAST_CONSTANT_OFFSET_MODE
263
264                     psrc += nl & (UNROLL-1);
265                     pdst += nl & (UNROLL-1);
266
267 #define BodyOdd(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]);
268 #define BodyEven(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]);
269
270 #define LoopReset \
271 pdst += UNROLL; \
272 psrc += UNROLL;
273
274 #else
275
276 #define BodyOdd(n)  *pdst = MROP_SOLID (*psrc, *pdst); pdst++; psrc++;
277 #define BodyEven(n) BodyOdd(n)
278
279 #define LoopReset   ;
280
281 #endif
282                     PackedLoop
283
284 #undef BodyOdd
285 #undef BodyEven
286 #undef LoopReset
287
288 #else
289 #ifdef NOTDEF
290                     /* you'd think this would be faster --
291                      * a single instruction instead of 6
292                      * but measurements show it to be ~15% slower
293                      */
294                     while ((nl -= 6) >= 0)
295                     {
296                         asm ("moveml %1+,#0x0c0f;moveml#0x0c0f,%0"
297                              : "=m" (*(char *)pdst)
298                              : "m" (*(char *)psrc)
299                              : "d0", "d1", "d2", "d3",
300                                "a2", "a3");
301                         pdst += 6;
302                     }
303                     nl += 6;
304                     while (nl--)
305                         *pdst++ = *psrc++;
306 #endif
307                     DuffL(nl, label1,
308                             *pdst = MROP_SOLID (*psrc, *pdst);
309                             pdst++; psrc++;)
310 #endif
311
312                     if (endmask)
313                         *pdst = MROP_MASK(*psrc, *pdst, endmask);
314                     mfbScanlineIncDst(pdstLine, widthDst);
315                     mfbScanlineIncSrc(psrcLine, widthSrc);
316                 }
317             }
318 #ifndef DO_UNALIGNED_BITBLT
319             else
320             {
321                 if (xoffSrc > xoffDst)
322                 {
323                     leftShift = (xoffSrc - xoffDst);
324                     rightShift = PPW - leftShift;
325                 }
326                 else
327                 {
328                     rightShift = (xoffDst - xoffSrc);
329                     leftShift = PPW - rightShift;
330                 }
331                 while (h--)
332                 {
333                     psrc = psrcLine;
334                     pdst = pdstLine;
335                     bits = 0;
336                     if (xoffSrc > xoffDst)
337                         bits = *psrc++;
338                     if (startmask)
339                     {
340                         bits1 = BitLeft(bits,leftShift);
341                         if (BitLeft(startmask, rightShift)) {
342                                 bits = *psrc++;
343                                 bits1 |= BitRight(bits,rightShift);
344                         }
345                         *pdst = MROP_MASK(bits1, *pdst, startmask);
346                         pdst++;
347                     }
348                     nl = nlMiddle;
349
350 #ifdef LARGE_INSTRUCTION_CACHE
351                     bits1 = bits;
352
353 #ifdef FAST_CONSTANT_OFFSET_MODE
354
355                     psrc += nl & (UNROLL-1);
356                     pdst += nl & (UNROLL-1);
357
358 #define BodyOdd(n) \
359 bits = psrc[-n]; \
360 pdst[-n] = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), pdst[-n]);
361
362 #define BodyEven(n) \
363 bits1 = psrc[-n]; \
364 pdst[-n] = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), pdst[-n]);
365
366 #define LoopReset \
367 pdst += UNROLL; \
368 psrc += UNROLL;
369
370 #else
371
372 #define BodyOdd(n) \
373 bits = *psrc++; \
374 *pdst = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), *pdst); \
375 pdst++;
376                    
377 #define BodyEven(n) \
378 bits1 = *psrc++; \
379 *pdst = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), *pdst); \
380 pdst++;
381
382 #define LoopReset   ;
383
384 #endif  /* !FAST_CONSTANT_OFFSET_MODE */
385
386                     PackedLoop
387
388 #undef BodyOdd
389 #undef BodyEven
390 #undef LoopReset
391
392 #else
393                     DuffL (nl,label2,
394                         bits1 = BitLeft(bits, leftShift);
395                         bits = *psrc++;
396                         *pdst = MROP_SOLID (bits1 | BitRight(bits, rightShift), *pdst);
397                         pdst++;
398                     )
399 #endif
400
401                     if (endmask)
402                     {
403                         bits1 = BitLeft(bits, leftShift);
404                         if (BitLeft(endmask, rightShift))
405                         {
406                             bits = *psrc;
407                             bits1 |= BitRight(bits, rightShift);
408                         }
409                         *pdst = MROP_MASK (bits1, *pdst, endmask);
410                     }
411                     mfbScanlineIncDst(pdstLine, widthDst);
412                     mfbScanlineIncSrc(psrcLine, widthSrc);
413                 }
414             }
415 #endif /* DO_UNALIGNED_BITBLT */
416         }
417         else    /* xdir == -1 */
418         {
419             xoffSrc = (pptSrc->x + w - 1) & PIM;
420             xoffDst = (pbox->x2 - 1) & PIM;
421             pdstLine += ((pbox->x2-1) >> PWSH) + 1;
422             psrcLine += ((pptSrc->x+w - 1) >> PWSH) + 1;
423 #ifdef DO_UNALIGNED_BITBLT
424             nl = xoffSrc - xoffDst;
425             psrcLine = (PixelType *)
426                         (((unsigned char *) psrcLine) + nl);
427 #else
428             if (xoffSrc == xoffDst)
429 #endif
430             {
431                 while (h--)
432                 {
433                     psrc = psrcLine;
434                     pdst = pdstLine;
435                     if (endmask)
436                     {
437                         pdst--;
438                         psrc--;
439                         *pdst = MROP_MASK (*psrc, *pdst, endmask);
440                     }
441                     nl = nlMiddle;
442
443 #ifdef LARGE_INSTRUCTION_CACHE
444 #ifdef FAST_CONSTANT_OFFSET_MODE
445                     psrc -= nl & (UNROLL - 1);
446                     pdst -= nl & (UNROLL - 1);
447
448 #define BodyOdd(n) pdst[n-1] = MROP_SOLID (psrc[n-1], pdst[n-1]);
449
450 #define BodyEven(n) BodyOdd(n)
451
452 #define LoopReset \
453 pdst -= UNROLL;\
454 psrc -= UNROLL;
455
456 #else
457
458 #define BodyOdd(n)  --pdst; --psrc; *pdst = MROP_SOLID(*psrc, *pdst);
459 #define BodyEven(n) BodyOdd(n)
460 #define LoopReset   ;
461
462 #endif
463                     PackedLoop
464
465 #undef BodyOdd
466 #undef BodyEven
467 #undef LoopReset
468
469 #else
470                     DuffL(nl,label3,
471                          --pdst; --psrc; *pdst = MROP_SOLID (*psrc, *pdst);)
472 #endif
473
474                     if (startmask)
475                     {
476                         --pdst;
477                         --psrc;
478                         *pdst = MROP_MASK(*psrc, *pdst, startmask);
479                     }
480                     mfbScanlineIncDst(pdstLine, widthDst);
481                     mfbScanlineIncSrc(psrcLine, widthSrc);
482                 }
483             }
484 #ifndef DO_UNALIGNED_BITBLT
485             else
486             {
487                 if (xoffDst > xoffSrc)
488                 {
489                     rightShift = (xoffDst - xoffSrc);
490                     leftShift = PPW - rightShift;
491                 }
492                 else
493                 {
494                     leftShift = (xoffSrc - xoffDst);
495                     rightShift = PPW - leftShift;
496                 }
497                 while (h--)
498                 {
499                     psrc = psrcLine;
500                     pdst = pdstLine;
501                     bits = 0;
502                     if (xoffDst > xoffSrc)
503                         bits = *--psrc;
504                     if (endmask)
505                     {
506                         bits1 = BitRight(bits, rightShift);
507                         if (BitRight(endmask, leftShift)) {
508                                 bits = *--psrc;
509                                 bits1 |= BitLeft(bits, leftShift);
510                         }
511                         pdst--;
512                         *pdst = MROP_MASK(bits1, *pdst, endmask);
513                     }
514                     nl = nlMiddle;
515
516 #ifdef LARGE_INSTRUCTION_CACHE
517                     bits1 = bits;
518 #ifdef FAST_CONSTANT_OFFSET_MODE
519                     psrc -= nl & (UNROLL - 1);
520                     pdst -= nl & (UNROLL - 1);
521
522 #define BodyOdd(n) \
523 bits = psrc[n-1]; \
524 pdst[n-1] = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),pdst[n-1]);
525
526 #define BodyEven(n) \
527 bits1 = psrc[n-1]; \
528 pdst[n-1] = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),pdst[n-1]);
529
530 #define LoopReset \
531 pdst -= UNROLL; \
532 psrc -= UNROLL;
533
534 #else
535
536 #define BodyOdd(n) \
537 bits = *--psrc; --pdst; \
538 *pdst = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),*pdst);
539
540 #define BodyEven(n) \
541 bits1 = *--psrc; --pdst; \
542 *pdst = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),*pdst);
543
544 #define LoopReset   ;
545
546 #endif
547
548                     PackedLoop
549
550 #undef BodyOdd
551 #undef BodyEven
552 #undef LoopReset
553
554 #else
555                     DuffL (nl, label4,
556                         bits1 = BitRight(bits, rightShift);
557                         bits = *--psrc;
558                         --pdst;
559                         *pdst = MROP_SOLID(bits1 | BitLeft(bits, leftShift),*pdst);
560                     )
561 #endif
562
563                     if (startmask)
564                     {
565                         bits1 = BitRight(bits, rightShift);
566                         if (BitRight (startmask, leftShift))
567                         {
568                             bits = *--psrc;
569                             bits1 |= BitLeft(bits, leftShift);
570                         }
571                         --pdst;
572                         *pdst = MROP_MASK(bits1, *pdst, startmask);
573                     }
574                     mfbScanlineIncDst(pdstLine, widthDst);
575                     mfbScanlineIncSrc(psrcLine, widthSrc);
576                 }
577             }
578 #endif
579         }
580         pbox++;
581         pptSrc++;
582     }
583     if (pboxNew2)
584     {
585         DEALLOCATE_LOCAL(pptNew2);
586         DEALLOCATE_LOCAL(pboxNew2);
587     }
588     if (pboxNew1)
589     {
590         DEALLOCATE_LOCAL(pptNew1);
591         DEALLOCATE_LOCAL(pboxNew1);
592     }
593 }