home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / ddx / mfb / mfbblt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-01-27  |  13.5 KB  |  600 lines

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