home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / ddx / mfb / mfbbitblt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-02  |  12.5 KB  |  452 lines

  1. /* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */
  2. /***********************************************************
  3. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
  4. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  5.  
  6.                         All Rights Reserved
  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 names of Digital or MIT not be
  13. used in advertising or publicity pertaining to distribution of the
  14. software without specific, written prior permission.  
  15.  
  16. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  17. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  18. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  19. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  20. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  21. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  22. SOFTWARE.
  23.  
  24. ******************************************************************/
  25. /* $XConsortium: mfbbitblt.c,v 5.21 91/07/02 19:54:31 keith Exp $ */
  26. #include "X.h"
  27. #include "Xprotostr.h"
  28.  
  29. #include "miscstruct.h"
  30. #include "regionstr.h"
  31. #include "gcstruct.h"
  32. #include "windowstr.h"
  33. #include "pixmapstr.h"
  34. #include "scrnintstr.h"
  35.  
  36. #include "mi.h"
  37.  
  38. #include "mfb.h"
  39. #include "maskbits.h"
  40.  
  41.  
  42. /* CopyArea and CopyPlane for a monchrome frame buffer
  43.  
  44.  
  45.     clip the source rectangle to the source's available bits.  (this
  46. avoids copying unnecessary pieces that will just get exposed anyway.)
  47. this becomes the new shape of the destination.
  48.     clip the destination region to the composite clip in the
  49. GC.  this requires translating the destination region to (dstx, dsty).
  50.     build a list of source points, one for each rectangle in the
  51. destination.  this is a simple translation.
  52.     go do the multiple rectangle copies
  53.     do graphics exposures
  54. */
  55. /** Optimized for drawing pixmaps into windows, especially when drawing into
  56.  ** unobscured windows.  Calls to the general-purpose region code were
  57.  ** replaced with rectangle-to-rectangle clipping comparisions.  This is
  58.  ** possible, since the pixmap is a single rectangle.  In an unobscured
  59.  ** window, the destination clip is also a single rectangle, and region
  60.  ** code can be avoided entirely.  This is a big savings, since the region
  61.  ** code uses XAlloc() and makes many function calls.
  62.  **
  63.  ** In addition, if source is a pixmap, there is no need to call the
  64.  ** expensive miHandleExposures() routine.  Instead, we simply return NULL.
  65.  **
  66.  ** Previously, drawing a pixmap into an unobscured window executed at least
  67.  ** 8 XAlloc()'s, 30 function calls, and hundreds of lines of code.
  68.  **
  69.  ** Now, the same operation requires no XAlloc()'s, no region function calls,
  70.  ** and much less overhead.  Nice for drawing lots of small pixmaps.
  71.  */
  72.  
  73. extern int  mfbDoBitbltCopy();
  74. extern int  mfbDoBitbltXor();
  75. extern int  mfbDoBitbltCopyInverted();
  76. extern int  mfbDoBitbltOr();
  77. extern int  mfbDoBitbltGeneral();
  78.  
  79. mfbDoBitblt (pSrc, pDst, alu, prgnDst, pptSrc)
  80.     DrawablePtr        pSrc, pDst;
  81.     int            alu;
  82.     RegionPtr        prgnDst;
  83.     DDXPointPtr        pptSrc;
  84. {
  85.     switch (alu)
  86.     {
  87.     case GXcopy:
  88.     return mfbDoBitbltCopy (pSrc, pDst, alu, prgnDst, pptSrc);
  89.     case GXxor:
  90.     return mfbDoBitbltXor (pSrc, pDst, alu, prgnDst, pptSrc);
  91.     case GXcopyInverted:
  92.     return mfbDoBitbltCopyInverted (pSrc, pDst, alu, prgnDst, pptSrc);
  93.     case GXor:
  94.     return mfbDoBitbltOr (pSrc, pDst, alu, prgnDst, pptSrc);
  95.     default:
  96.     return mfbDoBitbltGeneral (pSrc, pDst, alu, prgnDst, pptSrc);
  97.     }
  98. }
  99.  
  100. RegionPtr
  101. mfbCopyArea(pSrcDrawable, pDstDrawable,
  102.         pGC, srcx, srcy, width, height, dstx, dsty)
  103. register DrawablePtr pSrcDrawable;
  104. register DrawablePtr pDstDrawable;
  105. register GC *pGC;
  106. int srcx, srcy;
  107. int width, height;
  108. int dstx, dsty;
  109. {
  110.     RegionPtr prgnSrcClip;    /* may be a new region, or just a copy */
  111.     Bool freeSrcClip = FALSE;
  112.  
  113.     RegionPtr prgnExposed;
  114.     RegionRec rgnDst;
  115.     DDXPointPtr pptSrc;
  116.     register DDXPointPtr ppt;
  117.     register BoxPtr pbox;
  118.     int i;
  119.     register int dx;
  120.     register int dy;
  121.     xRectangle origSource;
  122.     DDXPointRec origDest;
  123.     int numRects;
  124.     BoxRec fastBox;
  125.     int fastClip = 0;        /* for fast clipping with pixmap source */
  126.     int fastExpose = 0;        /* for fast exposures with pixmap source */
  127.     int (*localDoBitBlt)();
  128.  
  129.     origSource.x = srcx;
  130.     origSource.y = srcy;
  131.     origSource.width = width;
  132.     origSource.height = height;
  133.     origDest.x = dstx;
  134.     origDest.y = dsty;
  135.  
  136.     if ((pSrcDrawable != pDstDrawable) &&
  137.     pSrcDrawable->pScreen->SourceValidate)
  138.     {
  139.     (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, srcx, srcy, width, height);
  140.     }
  141.  
  142.     switch (pGC->alu) {
  143.     case GXcopy:
  144.     localDoBitBlt = mfbDoBitbltCopy;
  145.     break;
  146.     case GXcopyInverted:
  147.     localDoBitBlt = mfbDoBitbltCopyInverted;
  148.     break;
  149.     case GXxor:
  150.     localDoBitBlt = mfbDoBitbltXor;
  151.     break;
  152.     case GXor:
  153.     localDoBitBlt = mfbDoBitbltOr;
  154.     break;
  155.     default:
  156.     localDoBitBlt = mfbDoBitbltGeneral;
  157.     break;
  158.     }
  159.  
  160.     srcx += pSrcDrawable->x;
  161.     srcy += pSrcDrawable->y;
  162.  
  163.     /* clip the source */
  164.  
  165.     if (pSrcDrawable->type == DRAWABLE_PIXMAP)
  166.     {
  167.     if ((pSrcDrawable == pDstDrawable) &&
  168.         (pGC->clientClipType == CT_NONE))
  169.     {
  170.         prgnSrcClip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip;
  171.     }
  172.     else
  173.     {
  174.         fastClip = 1;
  175.     }
  176.     }
  177.     else
  178.     {
  179.     if (pGC->subWindowMode == IncludeInferiors)
  180.     {
  181.         if (!((WindowPtr) pSrcDrawable)->parent)
  182.         {
  183.         /*
  184.          * special case bitblt from root window in
  185.          * IncludeInferiors mode; just like from a pixmap
  186.          */
  187.         fastClip = 1;
  188.         }
  189.         else if ((pSrcDrawable == pDstDrawable) &&
  190.         (pGC->clientClipType == CT_NONE))
  191.         {
  192.         prgnSrcClip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip;
  193.         }
  194.         else
  195.         {
  196.         prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable);
  197.         freeSrcClip = TRUE;
  198.         }
  199.     }
  200.     else
  201.     {
  202.         prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
  203.     }
  204.     }
  205.  
  206.     fastBox.x1 = srcx;
  207.     fastBox.y1 = srcy;
  208.     fastBox.x2 = srcx + width;
  209.     fastBox.y2 = srcy + height;
  210.  
  211.     /* Don't create a source region if we are doing a fast clip */
  212.     if (fastClip)
  213.     {
  214.     fastExpose = 1;
  215.     /*
  216.      * clip the source; if regions extend beyond the source size,
  217.       * make sure exposure events get sent
  218.      */
  219.     if (fastBox.x1 < pSrcDrawable->x)
  220.     {
  221.         fastBox.x1 = pSrcDrawable->x;
  222.         fastExpose = 0;
  223.     }
  224.     if (fastBox.y1 < pSrcDrawable->y)
  225.     {
  226.         fastBox.y1 = pSrcDrawable->y;
  227.         fastExpose = 0;
  228.     }
  229.     if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
  230.     {
  231.         fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
  232.         fastExpose = 0;
  233.     }
  234.     if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
  235.     {
  236.         fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
  237.         fastExpose = 0;
  238.     }
  239.     }
  240.     else
  241.     {
  242.     (*pGC->pScreen->RegionInit)(&rgnDst, &fastBox, 1);
  243.     (*pGC->pScreen->Intersect)(&rgnDst, &rgnDst, prgnSrcClip);
  244.     }
  245.  
  246.     dstx += pDstDrawable->x;
  247.     dsty += pDstDrawable->y;
  248.  
  249.     if (pDstDrawable->type == DRAWABLE_WINDOW)
  250.     {
  251.     if (!((WindowPtr)pDstDrawable)->realized)
  252.     {
  253.         if (!fastClip)
  254.         (*pGC->pScreen->RegionUninit)(&rgnDst);
  255.         if (freeSrcClip)
  256.         (*pGC->pScreen->RegionDestroy)(prgnSrcClip);
  257.         return NULL;
  258.     }
  259.     }
  260.  
  261.     dx = srcx - dstx;
  262.     dy = srcy - dsty;
  263.  
  264.     /* Translate and clip the dst to the destination composite clip */
  265.     if (fastClip)
  266.     {
  267.     RegionPtr cclip;
  268.  
  269.         /* Translate the region directly */
  270.         fastBox.x1 -= dx;
  271.         fastBox.x2 -= dx;
  272.         fastBox.y1 -= dy;
  273.         fastBox.y2 -= dy;
  274.  
  275.     /* If the destination composite clip is one rectangle we can
  276.        do the clip directly.  Otherwise we have to create a full
  277.        blown region and call intersect */
  278.     cclip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip;
  279.         if (REGION_NUM_RECTS(cclip) == 1)
  280.         {
  281.         BoxPtr pBox = REGION_RECTS(cclip);
  282.  
  283.         if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1;
  284.         if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2;
  285.         if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1;
  286.         if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2;
  287.  
  288.         /* Check to see if the region is empty */
  289.         if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2)
  290.         (*pGC->pScreen->RegionInit)(&rgnDst, NullBox, 0);
  291.         else
  292.         (*pGC->pScreen->RegionInit)(&rgnDst, &fastBox, 1);
  293.     }
  294.         else
  295.     {
  296.         /* We must turn off fastClip now, since we must create
  297.            a full blown region.  It is intersected with the
  298.            composite clip below. */
  299.         fastClip = 0;
  300.         (*pGC->pScreen->RegionInit)(&rgnDst, &fastBox,1);
  301.     }
  302.     }
  303.     else
  304.     {
  305.         (*pGC->pScreen->TranslateRegion)(&rgnDst, -dx, -dy);
  306.     }
  307.  
  308.     if (!fastClip)
  309.     {
  310.     (*pGC->pScreen->Intersect)(&rgnDst,
  311.                    &rgnDst,
  312.                  ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip);
  313.     }
  314.  
  315.     /* Do bit blitting */
  316.     numRects = REGION_NUM_RECTS(&rgnDst);
  317.     if (numRects && width && height)
  318.     {
  319.     if(!(pptSrc = (DDXPointPtr)ALLOCATE_LOCAL(numRects *
  320.                           sizeof(DDXPointRec))))
  321.     {
  322.         (*pGC->pScreen->RegionUninit)(&rgnDst);
  323.         if (freeSrcClip)
  324.         (*pGC->pScreen->RegionDestroy)(prgnSrcClip);
  325.         return NULL;
  326.     }
  327.     pbox = REGION_RECTS(&rgnDst);
  328.     ppt = pptSrc;
  329.     for (i = numRects; --i >= 0; pbox++, ppt++)
  330.     {
  331.         ppt->x = pbox->x1 + dx;
  332.         ppt->y = pbox->y1 + dy;
  333.     }
  334.     
  335.     if (pGC->planemask & 1)
  336.         (*localDoBitBlt) (pSrcDrawable, pDstDrawable, pGC->alu, &rgnDst, pptSrc);
  337.  
  338.     DEALLOCATE_LOCAL(pptSrc);
  339.     }
  340.  
  341.     prgnExposed = NULL;
  342.     if (((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->fExpose) 
  343.     {
  344.         /* Pixmap sources generate a NoExposed (we return NULL to do this) */
  345.         if (!fastExpose)
  346.         prgnExposed =
  347.         miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
  348.                   origSource.x, origSource.y,
  349.                   (int)origSource.width,
  350.                   (int)origSource.height,
  351.                   origDest.x, origDest.y, (unsigned long)0);
  352.     }
  353.     (*pGC->pScreen->RegionUninit)(&rgnDst);
  354.     if (freeSrcClip)
  355.     (*pGC->pScreen->RegionDestroy)(prgnSrcClip);
  356.     return prgnExposed;
  357. }
  358.  
  359. /*
  360.  * Devices which use mfb for 1-bit pixmap support
  361.  * must register a function for n-to-1 copy operations
  362.  */
  363.  
  364. static unsigned long    copyPlaneGeneration;
  365. static int        copyPlaneScreenIndex = -1;
  366.  
  367. Bool
  368. mfbRegisterCopyPlaneProc (pScreen, proc)
  369.     ScreenPtr    pScreen;
  370.     RegionPtr    (*proc)();
  371. {
  372.     if (copyPlaneGeneration != serverGeneration)
  373.     {
  374.     copyPlaneScreenIndex = AllocateScreenPrivateIndex();
  375.     if (copyPlaneScreenIndex < 0)
  376.         return FALSE;
  377.     copyPlaneGeneration = serverGeneration;
  378.     }
  379.     pScreen->devPrivates[copyPlaneScreenIndex].ptr = (pointer) proc;
  380.     return TRUE;
  381. }
  382.  
  383. /*
  384.     if fg == 1 and bg ==0, we can do an ordinary CopyArea.
  385.     if fg == bg, we can do a CopyArea with alu = mfbReduceRop(alu, fg)
  386.     if fg == 0 and bg == 1, we use the same rasterop, with
  387.     source operand inverted.
  388.  
  389.     CopyArea deals with all of the graphics exposure events.
  390.     This code depends on knowing that we can change the
  391. alu in the GC without having to call ValidateGC() before calling
  392. CopyArea().
  393.  
  394. */
  395.  
  396. RegionPtr
  397. mfbCopyPlane(pSrcDrawable, pDstDrawable,
  398.         pGC, srcx, srcy, width, height, dstx, dsty, plane)
  399. DrawablePtr pSrcDrawable, pDstDrawable;
  400. register GC *pGC;
  401. int srcx, srcy;
  402. int width, height;
  403. int dstx, dsty;
  404. unsigned long plane;
  405. {
  406.     int alu;
  407.     RegionPtr    prgnExposed;
  408.     RegionPtr    (*copyPlane)();
  409.  
  410.     if (pSrcDrawable->depth != 1)
  411.     {
  412.     if (copyPlaneScreenIndex >= 0 &&
  413.         (copyPlane = (RegionPtr (*)()) 
  414.         pSrcDrawable->pScreen->devPrivates[copyPlaneScreenIndex].ptr)
  415.         )
  416.     {
  417.         return (*copyPlane) (pSrcDrawable, pDstDrawable,
  418.                pGC, srcx, srcy, width, height, dstx, dsty, plane);
  419.     }  
  420.     else
  421.     {
  422.         FatalError ("No copyPlane proc registered for depth %d\n",
  423.             pSrcDrawable->depth);
  424.     }
  425.     }
  426.     if (plane != 1)
  427.     return NULL;
  428.  
  429.     if ((pGC->fgPixel & 1) == 1 && (pGC->bgPixel & 1) == 0)
  430.     {
  431.     prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable,
  432.              pGC, srcx, srcy, width, height, dstx, dsty);
  433.     }
  434.     else if ((pGC->fgPixel & 1) == (pGC->bgPixel & 1))
  435.     {
  436.     alu = pGC->alu;
  437.     pGC->alu = mfbReduceRop(pGC->alu, pGC->fgPixel);
  438.     prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable,
  439.              pGC, srcx, srcy, width, height, dstx, dsty);
  440.     pGC->alu = alu;
  441.     }
  442.     else /* need to invert the src */
  443.     {
  444.     alu = pGC->alu;
  445.     pGC->alu = InverseAlu[alu];
  446.     prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable,
  447.              pGC, srcx, srcy, width, height, dstx, dsty);
  448.     pGC->alu = alu;
  449.     }
  450.     return prgnExposed;
  451. }
  452.