1455 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1455 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * cfb copy area
 | |
|  */
 | |
| 
 | |
| 
 | |
| /*
 | |
| 
 | |
| Copyright 1989, 1998  The Open Group
 | |
| 
 | |
| Permission to use, copy, modify, distribute, and sell this software and its
 | |
| documentation for any purpose is hereby granted without fee, provided that
 | |
| the above copyright notice appear in all copies and that both that
 | |
| copyright notice and this permission notice appear in supporting
 | |
| documentation.
 | |
| 
 | |
| The above copyright notice and this permission notice shall be included in
 | |
| all copies or substantial portions of the Software.
 | |
| 
 | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | |
| OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | |
| AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | |
| CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | |
| 
 | |
| Except as contained in this notice, the name of The Open Group shall not be
 | |
| used in advertising or otherwise to promote the sale, use or other dealings
 | |
| in this Software without prior written authorization from The Open Group.
 | |
| 
 | |
| Author: Keith Packard
 | |
| 
 | |
| */
 | |
| 
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #include	<X11/X.h>
 | |
| #include	<X11/Xmd.h>
 | |
| #include	<X11/Xproto.h>
 | |
| #include	"gcstruct.h"
 | |
| #include	"windowstr.h"
 | |
| #include	"scrnintstr.h"
 | |
| #include	"pixmapstr.h"
 | |
| #include	"regionstr.h"
 | |
| #include	"mi.h"
 | |
| #include	"cfb.h"
 | |
| #include	"cfbmskbits.h"
 | |
| #include	"cfb8bit.h"
 | |
| #include	"fastblt.h"
 | |
| #define MFB_CONSTS_ONLY
 | |
| #include	"maskbits.h"
 | |
| 
 | |
| #if PSZ == 8
 | |
| #define cfbCopyPlane1toN cfbCopyPlane1to8
 | |
| #define cfbCopyPlaneNto1 cfbCopyPlane8to1
 | |
| #else
 | |
| static unsigned int FgPixel, BgPixel;
 | |
| # if PSZ == 16
 | |
| #define cfbCopyPlane1toN cfbCopyPlane1to16
 | |
| #define cfbCopyPlaneNto1 cfbCopyPlane16to1
 | |
| # endif
 | |
| # if PSZ == 24
 | |
| #define cfbCopyPlane1toN cfbCopyPlane1to24
 | |
| #define cfbCopyPlaneNto1 cfbCopyPlane24to1
 | |
| # endif
 | |
| # if PSZ == 32
 | |
| #define cfbCopyPlane1toN cfbCopyPlane1to32
 | |
| #define cfbCopyPlaneNto1 cfbCopyPlane32to1
 | |
| # endif
 | |
| #endif
 | |
| 
 | |
| /* cfbBitBltcfb == cfbCopyPlaneExpand */
 | |
| RegionPtr
 | |
| cfbBitBlt (
 | |
|     register DrawablePtr pSrcDrawable,
 | |
|     register DrawablePtr pDstDrawable,
 | |
|     GC *pGC,
 | |
|     int srcx, int srcy,
 | |
|     int width, int height,
 | |
|     int dstx, int dsty,
 | |
|     void (*doBitBlt)(
 | |
|         DrawablePtr /*pSrc*/,
 | |
|         DrawablePtr /*pDst*/,
 | |
|         int /*alu*/,
 | |
|         RegionPtr /*prgnDst*/,
 | |
|         DDXPointPtr /*pptSrc*/,
 | |
|         unsigned long /*planemask*/),
 | |
|     unsigned long bitPlane)
 | |
| {
 | |
|     RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */
 | |
|     Bool freeSrcClip = FALSE;
 | |
| 
 | |
|     RegionPtr prgnExposed;
 | |
|     RegionRec rgnDst;
 | |
|     DDXPointPtr pptSrc;
 | |
|     register DDXPointPtr ppt;
 | |
|     register BoxPtr pbox;
 | |
|     int i;
 | |
|     register int dx;
 | |
|     register int dy;
 | |
|     xRectangle origSource;
 | |
|     DDXPointRec origDest;
 | |
|     int numRects;
 | |
|     BoxRec fastBox;
 | |
|     int fastClip = 0;		/* for fast clipping with pixmap source */
 | |
|     int fastExpose = 0;		/* for fast exposures with pixmap source */
 | |
| 
 | |
|     origSource.x = srcx;
 | |
|     origSource.y = srcy;
 | |
|     origSource.width = width;
 | |
|     origSource.height = height;
 | |
|     origDest.x = dstx;
 | |
|     origDest.y = dsty;
 | |
| 
 | |
|     if ((pSrcDrawable != pDstDrawable) &&
 | |
| 	pSrcDrawable->pScreen->SourceValidate)
 | |
|     {
 | |
| 	(*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, srcx, srcy, width, height);
 | |
|     }
 | |
| 
 | |
|     srcx += pSrcDrawable->x;
 | |
|     srcy += pSrcDrawable->y;
 | |
| 
 | |
|     /* clip the source */
 | |
| 
 | |
|     if (pSrcDrawable->type == DRAWABLE_PIXMAP)
 | |
|     {
 | |
| 	if ((pSrcDrawable == pDstDrawable) &&
 | |
| 	    (pGC->clientClipType == CT_NONE))
 | |
| 	{
 | |
| 	    prgnSrcClip = cfbGetCompositeClip(pGC);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    fastClip = 1;
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	if (pGC->subWindowMode == IncludeInferiors)
 | |
| 	{
 | |
| 	    /*
 | |
| 	     * XFree86 DDX empties the border clip when the
 | |
| 	     * VT is inactive
 | |
| 	     */
 | |
| 	    if (!((WindowPtr) pSrcDrawable)->parent &&
 | |
| 		REGION_NOTEMPTY (pSrcDrawable->pScreen,
 | |
| 				 &((WindowPtr) pSrcDrawable)->borderClip))
 | |
| 	    {
 | |
| 		/*
 | |
| 		 * special case bitblt from root window in
 | |
| 		 * IncludeInferiors mode; just like from a pixmap
 | |
| 		 */
 | |
| 		fastClip = 1;
 | |
| 	    }
 | |
| 	    else if ((pSrcDrawable == pDstDrawable) &&
 | |
| 		(pGC->clientClipType == CT_NONE))
 | |
| 	    {
 | |
| 		prgnSrcClip = cfbGetCompositeClip(pGC);
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable);
 | |
| 		freeSrcClip = TRUE;
 | |
| 	    }
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     fastBox.x1 = srcx;
 | |
|     fastBox.y1 = srcy;
 | |
|     fastBox.x2 = srcx + width;
 | |
|     fastBox.y2 = srcy + height;
 | |
| 
 | |
|     /* Don't create a source region if we are doing a fast clip */
 | |
|     if (fastClip)
 | |
|     {
 | |
| 	fastExpose = 1;
 | |
| 	/*
 | |
| 	 * clip the source; if regions extend beyond the source size,
 | |
|  	 * make sure exposure events get sent
 | |
| 	 */
 | |
| 	if (fastBox.x1 < pSrcDrawable->x)
 | |
| 	{
 | |
| 	    fastBox.x1 = pSrcDrawable->x;
 | |
| 	    fastExpose = 0;
 | |
| 	}
 | |
| 	if (fastBox.y1 < pSrcDrawable->y)
 | |
| 	{
 | |
| 	    fastBox.y1 = pSrcDrawable->y;
 | |
| 	    fastExpose = 0;
 | |
| 	}
 | |
| 	if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
 | |
| 	{
 | |
| 	    fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
 | |
| 	    fastExpose = 0;
 | |
| 	}
 | |
| 	if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
 | |
| 	{
 | |
| 	    fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
 | |
| 	    fastExpose = 0;
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
 | |
| 	REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip);
 | |
|     }
 | |
| 
 | |
|     dstx += pDstDrawable->x;
 | |
|     dsty += pDstDrawable->y;
 | |
| 
 | |
|     if (pDstDrawable->type == DRAWABLE_WINDOW)
 | |
|     {
 | |
| 	if (!((WindowPtr)pDstDrawable)->realized)
 | |
| 	{
 | |
| 	    if (!fastClip)
 | |
| 		REGION_UNINIT(pGC->pScreen, &rgnDst);
 | |
| 	    if (freeSrcClip)
 | |
| 		REGION_DESTROY(pGC->pScreen, prgnSrcClip);
 | |
| 	    return NULL;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     dx = srcx - dstx;
 | |
|     dy = srcy - dsty;
 | |
| 
 | |
|     /* Translate and clip the dst to the destination composite clip */
 | |
|     if (fastClip)
 | |
|     {
 | |
| 	RegionPtr cclip;
 | |
| 
 | |
|         /* Translate the region directly */
 | |
|         fastBox.x1 -= dx;
 | |
|         fastBox.x2 -= dx;
 | |
|         fastBox.y1 -= dy;
 | |
|         fastBox.y2 -= dy;
 | |
| 
 | |
| 	/* If the destination composite clip is one rectangle we can
 | |
| 	   do the clip directly.  Otherwise we have to create a full
 | |
| 	   blown region and call intersect */
 | |
| 
 | |
| 	/* XXX because CopyPlane uses this routine for 8-to-1 bit
 | |
| 	 * copies, this next line *must* also correctly fetch the
 | |
| 	 * composite clip from an mfb gc
 | |
| 	 */
 | |
| 
 | |
| 	cclip = cfbGetCompositeClip(pGC);
 | |
|         if (REGION_NUM_RECTS(cclip) == 1)
 | |
|         {
 | |
| 	    BoxPtr pBox = REGION_RECTS(cclip);
 | |
| 
 | |
| 	    if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1;
 | |
| 	    if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2;
 | |
| 	    if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1;
 | |
| 	    if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2;
 | |
| 
 | |
| 	    /* Check to see if the region is empty */
 | |
| 	    if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2)
 | |
| 	    {
 | |
| 		REGION_NULL(pGC->pScreen, &rgnDst);
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
 | |
| 	    }
 | |
| 	}
 | |
|         else
 | |
| 	{
 | |
| 	    /* We must turn off fastClip now, since we must create
 | |
| 	       a full blown region.  It is intersected with the
 | |
| 	       composite clip below. */
 | |
| 	    fastClip = 0;
 | |
| 	    REGION_INIT(pGC->pScreen, &rgnDst, &fastBox,1);
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy);
 | |
|     }
 | |
| 
 | |
|     if (!fastClip)
 | |
|     {
 | |
| 	REGION_INTERSECT(pGC->pScreen, &rgnDst,
 | |
| 				   &rgnDst,
 | |
| 				   cfbGetCompositeClip(pGC));
 | |
|     }
 | |
| 
 | |
|     /* Do bit blitting */
 | |
|     numRects = REGION_NUM_RECTS(&rgnDst);
 | |
|     if (numRects && width && height)
 | |
|     {
 | |
| 	if(!(pptSrc = (DDXPointPtr)ALLOCATE_LOCAL(numRects *
 | |
| 						  sizeof(DDXPointRec))))
 | |
| 	{
 | |
| 	    REGION_UNINIT(pGC->pScreen, &rgnDst);
 | |
| 	    if (freeSrcClip)
 | |
| 		REGION_DESTROY(pGC->pScreen, prgnSrcClip);
 | |
| 	    return NULL;
 | |
| 	}
 | |
| 	pbox = REGION_RECTS(&rgnDst);
 | |
| 	ppt = pptSrc;
 | |
| 	for (i = numRects; --i >= 0; pbox++, ppt++)
 | |
| 	{
 | |
| 	    ppt->x = pbox->x1 + dx;
 | |
| 	    ppt->y = pbox->y1 + dy;
 | |
| 	}
 | |
| 
 | |
| 	(*doBitBlt) (pSrcDrawable, pDstDrawable, pGC->alu, &rgnDst, pptSrc, pGC->planemask);
 | |
| 	DEALLOCATE_LOCAL(pptSrc);
 | |
|     }
 | |
| 
 | |
|     prgnExposed = NULL;
 | |
|     if (pGC->fExpose)
 | |
|     {
 | |
|         /* Pixmap sources generate a NoExposed (we return NULL to do this) */
 | |
|         if (!fastExpose)
 | |
| 	    prgnExposed =
 | |
| 		miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
 | |
| 				  origSource.x, origSource.y,
 | |
| 				  (int)origSource.width,
 | |
| 				  (int)origSource.height,
 | |
| 				  origDest.x, origDest.y, bitPlane);
 | |
|     }
 | |
|     REGION_UNINIT(pGC->pScreen, &rgnDst);
 | |
|     if (freeSrcClip)
 | |
| 	REGION_DESTROY(pGC->pScreen, prgnSrcClip);
 | |
|     return prgnExposed;
 | |
| }
 | |
| 
 | |
| 
 | |
| RegionPtr
 | |
| cfbCopyPlaneReduce (
 | |
|     register DrawablePtr pSrcDrawable,
 | |
|     register DrawablePtr pDstDrawable,
 | |
|     GC *pGC,
 | |
|     int srcx, int srcy,
 | |
|     int width, int height,
 | |
|     int dstx, int dsty,
 | |
|     void (*doCopyPlane)(
 | |
|         DrawablePtr /*pSrc*/,
 | |
|         DrawablePtr /*pDst*/,
 | |
|         int /*alu*/,
 | |
|         RegionPtr /*prgnDst*/,
 | |
|         DDXPointPtr /*pptSrc*/,
 | |
|         unsigned long /*planemask*/,
 | |
|         unsigned long /*bitPlane*/),
 | |
|     unsigned long bitPlane)
 | |
| {
 | |
|     RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */
 | |
|     Bool freeSrcClip = FALSE;
 | |
| 
 | |
|     RegionPtr prgnExposed;
 | |
|     RegionRec rgnDst;
 | |
|     DDXPointPtr pptSrc;
 | |
|     register DDXPointPtr ppt;
 | |
|     register BoxPtr pbox;
 | |
|     int i;
 | |
|     register int dx;
 | |
|     register int dy;
 | |
|     xRectangle origSource;
 | |
|     DDXPointRec origDest;
 | |
|     int numRects;
 | |
|     BoxRec fastBox;
 | |
|     int fastClip = 0;		/* for fast clipping with pixmap source */
 | |
|     int fastExpose = 0;		/* for fast exposures with pixmap source */
 | |
| 
 | |
|     origSource.x = srcx;
 | |
|     origSource.y = srcy;
 | |
|     origSource.width = width;
 | |
|     origSource.height = height;
 | |
|     origDest.x = dstx;
 | |
|     origDest.y = dsty;
 | |
| 
 | |
|     if ((pSrcDrawable != pDstDrawable) &&
 | |
| 	pSrcDrawable->pScreen->SourceValidate)
 | |
|     {
 | |
| 	(*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, srcx, srcy, width, height);
 | |
|     }
 | |
| 
 | |
|     srcx += pSrcDrawable->x;
 | |
|     srcy += pSrcDrawable->y;
 | |
| 
 | |
|     /* clip the source */
 | |
| 
 | |
|     if (pSrcDrawable->type == DRAWABLE_PIXMAP)
 | |
|     {
 | |
| 	if ((pSrcDrawable == pDstDrawable) &&
 | |
| 	    (pGC->clientClipType == CT_NONE))
 | |
| 	{
 | |
| 	    prgnSrcClip = cfbGetCompositeClip(pGC);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    fastClip = 1;
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	if (pGC->subWindowMode == IncludeInferiors)
 | |
| 	{
 | |
| 	    /*
 | |
| 	     * XFree86 DDX empties the border clip when the
 | |
| 	     * VT is inactive
 | |
| 	     */
 | |
| 	    if (!((WindowPtr) pSrcDrawable)->parent &&
 | |
| 		REGION_NOTEMPTY (pSrcDrawable->pScreen,
 | |
| 				 &((WindowPtr) pSrcDrawable)->borderClip))
 | |
| 	    {
 | |
| 		/*
 | |
| 		 * special case bitblt from root window in
 | |
| 		 * IncludeInferiors mode; just like from a pixmap
 | |
| 		 */
 | |
| 		fastClip = 1;
 | |
| 	    }
 | |
| 	    else if ((pSrcDrawable == pDstDrawable) &&
 | |
| 		(pGC->clientClipType == CT_NONE))
 | |
| 	    {
 | |
| 		prgnSrcClip = cfbGetCompositeClip(pGC);
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable);
 | |
| 		freeSrcClip = TRUE;
 | |
| 	    }
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     fastBox.x1 = srcx;
 | |
|     fastBox.y1 = srcy;
 | |
|     fastBox.x2 = srcx + width;
 | |
|     fastBox.y2 = srcy + height;
 | |
| 
 | |
|     /* Don't create a source region if we are doing a fast clip */
 | |
|     if (fastClip)
 | |
|     {
 | |
| 	fastExpose = 1;
 | |
| 	/*
 | |
| 	 * clip the source; if regions extend beyond the source size,
 | |
|  	 * make sure exposure events get sent
 | |
| 	 */
 | |
| 	if (fastBox.x1 < pSrcDrawable->x)
 | |
| 	{
 | |
| 	    fastBox.x1 = pSrcDrawable->x;
 | |
| 	    fastExpose = 0;
 | |
| 	}
 | |
| 	if (fastBox.y1 < pSrcDrawable->y)
 | |
| 	{
 | |
| 	    fastBox.y1 = pSrcDrawable->y;
 | |
| 	    fastExpose = 0;
 | |
| 	}
 | |
| 	if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
 | |
| 	{
 | |
| 	    fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
 | |
| 	    fastExpose = 0;
 | |
| 	}
 | |
| 	if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
 | |
| 	{
 | |
| 	    fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
 | |
| 	    fastExpose = 0;
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
 | |
| 	REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip);
 | |
|     }
 | |
| 
 | |
|     dstx += pDstDrawable->x;
 | |
|     dsty += pDstDrawable->y;
 | |
| 
 | |
|     if (pDstDrawable->type == DRAWABLE_WINDOW)
 | |
|     {
 | |
| 	if (!((WindowPtr)pDstDrawable)->realized)
 | |
| 	{
 | |
| 	    if (!fastClip)
 | |
| 		REGION_UNINIT(pGC->pScreen, &rgnDst);
 | |
| 	    if (freeSrcClip)
 | |
| 		REGION_DESTROY(pGC->pScreen, prgnSrcClip);
 | |
| 	    return NULL;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     dx = srcx - dstx;
 | |
|     dy = srcy - dsty;
 | |
| 
 | |
|     /* Translate and clip the dst to the destination composite clip */
 | |
|     if (fastClip)
 | |
|     {
 | |
| 	RegionPtr cclip;
 | |
| 
 | |
|         /* Translate the region directly */
 | |
|         fastBox.x1 -= dx;
 | |
|         fastBox.x2 -= dx;
 | |
|         fastBox.y1 -= dy;
 | |
|         fastBox.y2 -= dy;
 | |
| 
 | |
| 	/* If the destination composite clip is one rectangle we can
 | |
| 	   do the clip directly.  Otherwise we have to create a full
 | |
| 	   blown region and call intersect */
 | |
| 
 | |
| 	/* XXX because CopyPlane uses this routine for 8-to-1 bit
 | |
| 	 * copies, this next line *must* also correctly fetch the
 | |
| 	 * composite clip from an mfb gc
 | |
| 	 */
 | |
| 
 | |
| 	cclip = cfbGetCompositeClip(pGC);
 | |
|         if (REGION_NUM_RECTS(cclip) == 1)
 | |
|         {
 | |
| 	    BoxPtr pBox = REGION_RECTS(cclip);
 | |
| 
 | |
| 	    if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1;
 | |
| 	    if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2;
 | |
| 	    if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1;
 | |
| 	    if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2;
 | |
| 
 | |
| 	    /* Check to see if the region is empty */
 | |
| 	    if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2)
 | |
| 	    {
 | |
| 		REGION_NULL(pGC->pScreen, &rgnDst);
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
 | |
| 	    }
 | |
| 	}
 | |
|         else
 | |
| 	{
 | |
| 	    /* We must turn off fastClip now, since we must create
 | |
| 	       a full blown region.  It is intersected with the
 | |
| 	       composite clip below. */
 | |
| 	    fastClip = 0;
 | |
| 	    REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy);
 | |
|     }
 | |
| 
 | |
|     if (!fastClip)
 | |
|     {
 | |
| 	REGION_INTERSECT(pGC->pScreen, &rgnDst,
 | |
| 				   &rgnDst,
 | |
| 				   cfbGetCompositeClip(pGC));
 | |
|     }
 | |
| 
 | |
|     /* Do bit blitting */
 | |
|     numRects = REGION_NUM_RECTS(&rgnDst);
 | |
|     if (numRects && width && height)
 | |
|     {
 | |
| 	if(!(pptSrc = (DDXPointPtr)ALLOCATE_LOCAL(numRects *
 | |
| 						  sizeof(DDXPointRec))))
 | |
| 	{
 | |
| 	    REGION_UNINIT(pGC->pScreen, &rgnDst);
 | |
| 	    if (freeSrcClip)
 | |
| 		REGION_DESTROY(pGC->pScreen, prgnSrcClip);
 | |
| 	    return NULL;
 | |
| 	}
 | |
| 	pbox = REGION_RECTS(&rgnDst);
 | |
| 	ppt = pptSrc;
 | |
| 	for (i = numRects; --i >= 0; pbox++, ppt++)
 | |
| 	{
 | |
| 	    ppt->x = pbox->x1 + dx;
 | |
| 	    ppt->y = pbox->y1 + dy;
 | |
| 	}
 | |
| 
 | |
| 	(*doCopyPlane) (pSrcDrawable, pDstDrawable, pGC->alu, &rgnDst, pptSrc, pGC->planemask, bitPlane);
 | |
| 	DEALLOCATE_LOCAL(pptSrc);
 | |
|     }
 | |
| 
 | |
|     prgnExposed = NULL;
 | |
|     if (pGC->fExpose)
 | |
|     {
 | |
|         /* Pixmap sources generate a NoExposed (we return NULL to do this) */
 | |
|         if (!fastExpose)
 | |
| 	    prgnExposed =
 | |
| 		miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
 | |
| 				  origSource.x, origSource.y,
 | |
| 				  (int)origSource.width,
 | |
| 				  (int)origSource.height,
 | |
| 				  origDest.x, origDest.y, bitPlane);
 | |
|     }
 | |
|     REGION_UNINIT(pGC->pScreen, &rgnDst);
 | |
|     if (freeSrcClip)
 | |
| 	REGION_DESTROY(pGC->pScreen, prgnSrcClip);
 | |
|     return prgnExposed;
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| cfbDoBitblt (pSrc, pDst, alu, prgnDst, pptSrc, planemask)
 | |
|     DrawablePtr	    pSrc, pDst;
 | |
|     int		    alu;
 | |
|     RegionPtr	    prgnDst;
 | |
|     DDXPointPtr	    pptSrc;
 | |
|     unsigned long   planemask;
 | |
| {
 | |
|     void (*doBitBlt)(
 | |
|         DrawablePtr /*pSrc*/,
 | |
|         DrawablePtr /*pDst*/,
 | |
|         int /*alu*/,
 | |
|         RegionPtr /*prgnDst*/,
 | |
|         DDXPointPtr /*pptSrc*/,
 | |
|         unsigned long /*planemask*/)
 | |
|         = cfbDoBitbltGeneral;
 | |
| 
 | |
|     if ((planemask & PMSK) == PMSK) {
 | |
| 	switch (alu) {
 | |
| 	case GXcopy:
 | |
| 	    doBitBlt = cfbDoBitbltCopy;
 | |
| 	    break;
 | |
| 	case GXxor:
 | |
| 	    doBitBlt = cfbDoBitbltXor;
 | |
| 	    break;
 | |
| 	case GXor:
 | |
| 	    doBitBlt = cfbDoBitbltOr;
 | |
| 	    break;
 | |
| 	}
 | |
|     }
 | |
|     (*doBitBlt) (pSrc, pDst, alu, prgnDst, pptSrc, planemask);
 | |
| }
 | |
| 
 | |
| RegionPtr
 | |
| cfbCopyArea(pSrcDrawable, pDstDrawable,
 | |
|             pGC, srcx, srcy, width, height, dstx, dsty)
 | |
|     register DrawablePtr pSrcDrawable;
 | |
|     register DrawablePtr pDstDrawable;
 | |
|     GC *pGC;
 | |
|     int srcx, srcy;
 | |
|     int width, height;
 | |
|     int dstx, dsty;
 | |
| {
 | |
|     void (*doBitBlt) (
 | |
|         DrawablePtr /*pSrc*/,
 | |
|         DrawablePtr /*pDst*/,
 | |
|         int /*alu*/,
 | |
|         RegionPtr /*prgnDst*/,
 | |
|         DDXPointPtr /*pptSrc*/,
 | |
|         unsigned long /*planemask*/);
 | |
|     
 | |
|     doBitBlt = cfbDoBitbltCopy;
 | |
|     if (pGC->alu != GXcopy || (pGC->planemask & PMSK) != PMSK)
 | |
|     {
 | |
| 	doBitBlt = cfbDoBitbltGeneral;
 | |
| 	if ((pGC->planemask & PMSK) == PMSK)
 | |
| 	{
 | |
| 	    switch (pGC->alu) {
 | |
| 	    case GXxor:
 | |
| 		doBitBlt = cfbDoBitbltXor;
 | |
| 		break;
 | |
| 	    case GXor:
 | |
| 		doBitBlt = cfbDoBitbltOr;
 | |
| 		break;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     return cfbBitBlt (pSrcDrawable, pDstDrawable,
 | |
|             pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, 0L);
 | |
| }
 | |
| 
 | |
| #if PSZ == 8
 | |
| void
 | |
| cfbCopyPlane1to8 (pSrcDrawable, pDstDrawable, rop, prgnDst, pptSrc, planemask)
 | |
|     DrawablePtr pSrcDrawable;	/* must be a bitmap */
 | |
|     DrawablePtr pDstDrawable;	/* must be depth 8 drawable */
 | |
|     int	rop;		/* not used; caller must call cfb8CheckOpaqueStipple
 | |
| 			 * beforehand to get cfb8StippleRRop set correctly */
 | |
|     RegionPtr prgnDst;		/* region in destination to draw to;
 | |
| 				 * screen relative coords. if dest is a window;
 | |
| 				 * drawable relative if dest is a pixmap */
 | |
|     DDXPointPtr pptSrc;		/* drawable relative src coords to copy from;
 | |
| 				 * must be one point for each box in prgnDst */
 | |
|     unsigned long planemask;	/* to apply to destination writes */
 | |
| {
 | |
|     int	srcx, srcy;	/* upper left corner of box being copied in source */
 | |
|     int dstx, dsty;	/* upper left corner of box being copied in dest */
 | |
|     int width, height;	/* in pixels, unpadded, of box being copied */
 | |
|     int xoffSrc; /* bit # in leftmost word of row from which copying starts */
 | |
|     int xoffDst; /* byte # in leftmost word of row from which copying starts */
 | |
|     CfbBits *psrcBase, *pdstBase; /* start of drawable's pixel data */
 | |
|     int	widthSrc;    /* # of groups of 32 pixels (1 bit/pixel) in src bitmap*/
 | |
|     int widthDst;    /* # of groups of 4 pixels (8 bits/pixel) in dst */
 | |
|     CfbBits *psrcLine, *pdstLine; /* steps a row at a time thru src/dst; 
 | |
| 					 * may point into middle of row */
 | |
|     register CfbBits *psrc, *pdst; /* steps within the row */
 | |
|     register CfbBits bits, tmp;	 /* bits from source */
 | |
|     register int leftShift;
 | |
|     register int rightShift;
 | |
|     CfbBits startmask;		/* left edge pixel mask */
 | |
|     CfbBits endmask;		/* right edge pixel mask */
 | |
|     register int nlMiddle;   /* number of words in middle of the row to draw */
 | |
|     register int nl;
 | |
|     int firstoff = 0;
 | |
|     int secondoff = 0;
 | |
|     CfbBits src;
 | |
|     int nbox;		/* number of boxes in region to copy */
 | |
|     BoxPtr  pbox;	/* steps thru boxes in region */
 | |
|     int pixelsRemainingOnRightEdge; /* # pixels to be drawn on a row after
 | |
| 				     * the main "middle" loop */
 | |
| 
 | |
|     cfbGetLongWidthAndPointer (pSrcDrawable, widthSrc, psrcBase)
 | |
|     cfbGetLongWidthAndPointer (pDstDrawable, widthDst, pdstBase)
 | |
| 
 | |
|     nbox = REGION_NUM_RECTS(prgnDst);
 | |
|     pbox = REGION_RECTS(prgnDst);
 | |
|     while (nbox--)
 | |
|     {
 | |
| 	dstx = pbox->x1;
 | |
| 	dsty = pbox->y1;
 | |
| 	srcx = pptSrc->x;
 | |
| 	srcy = pptSrc->y;
 | |
| 	width = pbox->x2 - pbox->x1;
 | |
| 	height = pbox->y2 - pbox->y1;
 | |
| 	pbox++;
 | |
| 	pptSrc++;
 | |
| 
 | |
| 	psrcLine = psrcBase + srcy * widthSrc + (srcx >> MFB_PWSH);
 | |
| 	pdstLine = pdstBase + dsty * widthDst + (dstx >> PWSH);
 | |
| 	xoffSrc = srcx & MFB_PIM; /* finds starting bit in src */
 | |
| 	xoffDst = dstx & PIM;  /* finds starting byte in dst */
 | |
| 
 | |
| 	/* compute startmask, endmask, nlMiddle */
 | |
| 
 | |
| 	if (xoffDst + width < PPW) /* XXX should this be '<= PPW' ? */
 | |
| 	{ /* the copy only affects one word per row in destination */
 | |
| 	    maskpartialbits(dstx, width, startmask);
 | |
| 	    endmask = 0;  /* nothing on right edge */
 | |
| 	    nlMiddle = 0; /* nothing in middle */
 | |
| 	}
 | |
| 	else
 | |
| 	{ /* the copy will affect multiple words per row in destination */
 | |
| 	    maskbits(dstx, width, startmask, endmask, nlMiddle);
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * compute constants for the first four bits to be
 | |
| 	 * copied.  This avoids troubles with partial first
 | |
| 	 * writes, and difficult shift computation
 | |
| 	 */
 | |
| 	if (startmask)
 | |
| 	{
 | |
| 	    firstoff = xoffSrc - xoffDst;
 | |
| 	    if (firstoff > (MFB_PPW-PPW))
 | |
| 		secondoff = MFB_PPW - firstoff;
 | |
| 	    if (xoffDst)
 | |
| 	    {
 | |
| 	    	srcx += (PPW-xoffDst);
 | |
| 	    	xoffSrc = srcx & MFB_PIM;
 | |
| 	    }
 | |
| 	}
 | |
| 	leftShift = xoffSrc;
 | |
| 	rightShift = MFB_PPW - leftShift;
 | |
| 
 | |
| 	pixelsRemainingOnRightEdge = (nlMiddle & 7) * PPW +
 | |
| 	    				((dstx + width) & PIM);
 | |
| 
 | |
| 	/* setup is done; now let's move some bits */
 | |
| 
 | |
| 	/* caller must call cfb8CheckOpaqueStipple before this function
 | |
| 	 * to set cfb8StippleRRop!
 | |
| 	 */
 | |
| 
 | |
| 	if (cfb8StippleRRop == GXcopy)
 | |
| 	{
 | |
| 	    while (height--)
 | |
| 	    { /* one iteration of this loop copies one row */
 | |
| 	    	psrc = psrcLine;
 | |
| 	    	pdst = pdstLine;
 | |
| 	    	psrcLine += widthSrc;
 | |
| 	    	pdstLine += widthDst;
 | |
| 	    	bits = *psrc++;
 | |
| 	    	if (startmask)
 | |
| 	    	{
 | |
| 		    if (firstoff < 0)
 | |
| 		    	tmp = BitRight (bits, -firstoff);
 | |
| 		    else
 | |
| 		    {
 | |
| 		    	tmp = BitLeft (bits, firstoff);
 | |
| 			/*
 | |
| 			 * need a more cautious test for partialmask
 | |
| 			 * case...
 | |
| 			 */
 | |
| 		    	if (firstoff >= (MFB_PPW-PPW))
 | |
| 		    	{
 | |
| 			    bits = *psrc++;
 | |
| 			    if (firstoff != (MFB_PPW-PPW))
 | |
| 				tmp |= BitRight (bits, secondoff);
 | |
| 		    	}
 | |
| 		    }
 | |
| 		    *pdst = (*pdst & ~startmask) | (GetPixelGroup(tmp) & startmask);
 | |
| 		    pdst++;
 | |
| 	    	}
 | |
| 	    	nl = nlMiddle;
 | |
| 	    	while (nl >= 8)
 | |
| 	    	{
 | |
| 		    nl -= 8;
 | |
| 		    tmp = BitLeft(bits, leftShift);
 | |
| 		    bits = *psrc++;
 | |
| 		    if (rightShift != MFB_PPW)
 | |
| 		    	tmp |= BitRight(bits, rightShift);
 | |
| 
 | |
| #ifdef FAST_CONSTANT_OFFSET_MODE
 | |
| # define StorePixels(pdst,o,pixels)	(pdst)[o] = (pixels)
 | |
| # define EndStep(pdst,o)		(pdst) += (o)
 | |
| # define StoreRopPixels(pdst,o,and,xor)	(pdst)[o] = DoRRop((pdst)[o],and,xor);
 | |
| #else
 | |
| # define StorePixels(pdst,o,pixels)	*(pdst)++ = (pixels)
 | |
| # define EndStep(pdst,o)
 | |
| # define StoreRopPixels(pdst,o,and,xor)	*(pdst) = DoRRop(*(pdst),and,xor); (pdst)++;
 | |
| #endif
 | |
| 
 | |
| #define Step(c)			NextBitGroup(c);
 | |
| #define StoreBitsPlain(o,c)	StorePixels(pdst,o,GetPixelGroup(c))
 | |
| #define StoreRopBitsPlain(o,c)	StoreRopPixels(pdst,o,\
 | |
| 					cfb8StippleAnd[GetBitGroup(c)], \
 | |
| 					cfb8StippleXor[GetBitGroup(c)])
 | |
| #define StoreBits0(c)		StoreBitsPlain(0,c)
 | |
| #define StoreRopBits0(c)	StoreRopBitsPlain(0,c)
 | |
| 
 | |
| #if (BITMAP_BIT_ORDER == MSBFirst)
 | |
| # define StoreBits(o,c)	StoreBitsPlain(o,c)
 | |
| # define StoreRopBits(o,c)  StoreRopBitsPlain(o,c)
 | |
| # define FirstStep(c)	Step(c)
 | |
| #else /* BITMAP_BIT_ORDER == LSBFirst */
 | |
| #if PGSZ == 64
 | |
| # define StoreBits(o,c)	StorePixels(pdst,o, (cfb8Pixels[c & 0xff]))
 | |
| # define StoreRopBits(o,c)  StoreRopPixels(pdst,o, \
 | |
|     (cfb8StippleAnd[c & 0xff]), \
 | |
|     (cfb8StippleXor[c & 0xff]))
 | |
| # define FirstStep(c)	c = BitLeft (c, 8);
 | |
| #else
 | |
| /* 0x3c is 0xf << 2 (4 bits, long word) */
 | |
| # define StoreBits(o,c)	StorePixels(pdst,o,*((CfbBits *)\
 | |
| 			    (((char *) cfb8Pixels) + (c & 0x3c))))
 | |
| # define StoreRopBits(o,c)  StoreRopPixels(pdst,o, \
 | |
|     *((CfbBits *) (((char *) cfb8StippleAnd) + (c & 0x3c))), \
 | |
|     *((CfbBits *) (((char *) cfb8StippleXor) + (c & 0x3c))))
 | |
| # define FirstStep(c)	c = BitLeft (c, 2);
 | |
| #endif /* PGSZ */
 | |
| #endif /* BITMAP_BIT_ORDER */
 | |
| 
 | |
| 		    StoreBits0(tmp);	FirstStep(tmp);
 | |
| 		    StoreBits(1,tmp);	Step(tmp);
 | |
| 		    StoreBits(2,tmp);	Step(tmp);
 | |
| 		    StoreBits(3,tmp);	Step(tmp);
 | |
| 		    StoreBits(4,tmp);	Step(tmp);
 | |
| 		    StoreBits(5,tmp);	Step(tmp);
 | |
| 		    StoreBits(6,tmp);	Step(tmp);
 | |
| 		    StoreBits(7,tmp);   EndStep (pdst,8);
 | |
| 	    	}
 | |
| 
 | |
| 		/* do rest of middle and partial word on right edge */
 | |
| 
 | |
| 	    	if (pixelsRemainingOnRightEdge)
 | |
| 	    	{
 | |
| 		    tmp = BitLeft(bits, leftShift);
 | |
| 
 | |
| 		    if (pixelsRemainingOnRightEdge > rightShift)
 | |
| 		    {
 | |
| 		    	bits = *psrc++;
 | |
| 		    	tmp |= BitRight (bits, rightShift);
 | |
| 		    }
 | |
| 		    EndStep (pdst, nl);
 | |
| 		    switch (nl)
 | |
| 		    {
 | |
| 		    case 7:
 | |
| 			StoreBitsPlain(-7,tmp);	Step(tmp);
 | |
| 		    case 6:
 | |
| 			StoreBitsPlain(-6,tmp);	Step(tmp);
 | |
| 		    case 5:
 | |
| 			StoreBitsPlain(-5,tmp);	Step(tmp);
 | |
| 		    case 4:
 | |
| 			StoreBitsPlain(-4,tmp);	Step(tmp);
 | |
| 		    case 3:
 | |
| 			StoreBitsPlain(-3,tmp);	Step(tmp);
 | |
| 		    case 2:
 | |
| 			StoreBitsPlain(-2,tmp);	Step(tmp);
 | |
| 		    case 1:
 | |
| 			StoreBitsPlain(-1,tmp);	Step(tmp);
 | |
| 		    }
 | |
| 		    if (endmask)
 | |
| 		    	*pdst = (*pdst & ~endmask) | (GetPixelGroup(tmp) & endmask);
 | |
| 	    	}
 | |
| 	    }
 | |
| 	}
 | |
| 	else /* cfb8StippleRRop != GXcopy */
 | |
| 	{
 | |
| 	    while (height--)
 | |
| 	    { /* one iteration of this loop copies one row */
 | |
| 	    	psrc = psrcLine;
 | |
| 	    	pdst = pdstLine;
 | |
| 	    	psrcLine += widthSrc;
 | |
| 	    	pdstLine += widthDst;
 | |
| 	    	bits = *psrc++;
 | |
| 
 | |
| 		/* do partial word on left edge */
 | |
| 
 | |
| 	    	if (startmask)
 | |
| 	    	{
 | |
| 		    if (firstoff < 0)
 | |
| 		    	tmp = BitRight (bits, -firstoff);
 | |
| 		    else
 | |
| 		    {
 | |
| 		    	tmp = BitLeft (bits, firstoff);
 | |
| 		    	if (firstoff >= (MFB_PPW-PPW))
 | |
| 		    	{
 | |
| 			    bits = *psrc++;
 | |
| 			    if (firstoff != (MFB_PPW-PPW))
 | |
| 				tmp |= BitRight (bits, secondoff);
 | |
| 		    	}
 | |
| 		    }
 | |
| 		    src = GetBitGroup(tmp);
 | |
| 		    *pdst = MaskRRopPixels (*pdst, src, startmask);
 | |
| 		    pdst++;
 | |
| 	    	}
 | |
| 
 | |
| 		/* do middle of row */
 | |
| 
 | |
| 	    	nl = nlMiddle;
 | |
| 		while (nl >= 8)
 | |
| 		{
 | |
| 		    nl -= 8;
 | |
| 		    tmp = BitLeft(bits, leftShift);
 | |
| 		    bits = *psrc++;
 | |
| 		    if (rightShift != MFB_PPW)
 | |
| 			tmp |= BitRight(bits, rightShift);
 | |
| 		    StoreRopBits0(tmp);		FirstStep(tmp);
 | |
| 		    StoreRopBits(1,tmp);	Step(tmp);
 | |
| 		    StoreRopBits(2,tmp);	Step(tmp);
 | |
| 		    StoreRopBits(3,tmp);	Step(tmp);
 | |
| 		    StoreRopBits(4,tmp);	Step(tmp);
 | |
| 		    StoreRopBits(5,tmp);	Step(tmp);
 | |
| 		    StoreRopBits(6,tmp);	Step(tmp);
 | |
| 		    StoreRopBits(7,tmp);	EndStep(pdst,8);
 | |
| 		}
 | |
| 
 | |
| 		/* do rest of middle and partial word on right edge */
 | |
| 
 | |
| 	    	if (pixelsRemainingOnRightEdge)
 | |
| 	    	{
 | |
| 		    tmp = BitLeft(bits, leftShift);
 | |
| 
 | |
| 		    if (pixelsRemainingOnRightEdge > rightShift)
 | |
| 		    {
 | |
| 		    	bits = *psrc++; /* XXX purify abr here */
 | |
| 		    	tmp |= BitRight (bits, rightShift);
 | |
| 		    }
 | |
| 		    while (nl--)
 | |
| 		    {
 | |
| 			src = GetBitGroup (tmp);
 | |
| 			*pdst = RRopPixels (*pdst, src);
 | |
| 		    	pdst++;
 | |
| 			NextBitGroup(tmp);
 | |
| 		    }
 | |
| 		    if (endmask)
 | |
| 		    {
 | |
| 			src = GetBitGroup (tmp);
 | |
| 			*pdst = MaskRRopPixels (*pdst, src, endmask);
 | |
| 		    }
 | |
| 	    	}
 | |
| 	    } /* end copy one row */
 | |
| 	} /* end alu is non-copy-mode case */
 | |
|     } /* end iteration over region boxes */
 | |
| }
 | |
| 
 | |
| #else /* PSZ == 8 */
 | |
| 
 | |
| #define mfbmaskbits(x, w, startmask, endmask, nlw) \
 | |
|     startmask = mfbGetstarttab((x)&0x1f); \
 | |
|     endmask = mfbGetendtab(((x)+(w)) & 0x1f); \
 | |
|     if (startmask) \
 | |
| 	nlw = (((w) - (32 - ((x)&0x1f))) >> 5); \
 | |
|     else \
 | |
| 	nlw = (w) >> 5;
 | |
| 
 | |
| #define mfbmaskpartialbits(x, w, mask) \
 | |
|     mask = mfbGetpartmasks((x)&0x1f,(w)&0x1f);
 | |
| 
 | |
| #define LeftMost    0
 | |
| #define StepBit(bit, inc)  ((bit) += (inc))
 | |
| 
 | |
| 
 | |
| #define GetBits(psrc, nBits, curBit, bitPos, bits) {\
 | |
|     bits = 0; \
 | |
|     while (nBits--) \
 | |
|     { \
 | |
| 	bits |= ((*psrc++ >> bitPos) & 1) << curBit; \
 | |
| 	StepBit (curBit, 1); \
 | |
|     } \
 | |
| }
 | |
| 
 | |
| /******************************************************************/
 | |
| 
 | |
| static void
 | |
| #if PSZ == 16
 | |
| cfbCopyPlane1to16
 | |
| #endif
 | |
| #if PSZ == 24
 | |
| cfbCopyPlane1to24
 | |
| #endif
 | |
| #if PSZ == 32
 | |
| cfbCopyPlane1to32
 | |
| #endif
 | |
| (
 | |
|     DrawablePtr pSrcDrawable,
 | |
|     DrawablePtr pDstDrawable,
 | |
|     int	rop,
 | |
|     RegionPtr prgnDst,
 | |
|     DDXPointPtr pptSrc,
 | |
|     unsigned long planemask)
 | |
| {
 | |
|     int	srcx, srcy, dstx, dsty;
 | |
|     int width, height;
 | |
|     int xoffSrc;
 | |
|     CfbBits *psrcBase, *pdstBase;
 | |
|     int	widthSrc, widthDst;
 | |
|     unsigned int *psrcLine;
 | |
|     register unsigned int *psrc;
 | |
| #if PSZ == 16
 | |
|     unsigned short *pdstLine;
 | |
|     register unsigned short *pdst;
 | |
| #endif
 | |
| #if PSZ == 32
 | |
|     unsigned int *pdstLine;
 | |
|     register unsigned int *pdst;
 | |
| #endif
 | |
| #if PSZ == 24
 | |
|     unsigned char *pdstLine;
 | |
|     register unsigned char *pdst;
 | |
| #endif
 | |
|     register unsigned int  bits, tmp;
 | |
|     register unsigned int  fgpixel, bgpixel;
 | |
|     register unsigned int  src;
 | |
| #if PSZ == 24
 | |
|     register unsigned int  dst;
 | |
| #endif
 | |
|     register int  leftShift, rightShift;
 | |
|     register int  i, nl;
 | |
|     int nbox;
 | |
|     BoxPtr pbox;
 | |
|     int  result;
 | |
| 
 | |
| #if PSZ == 16
 | |
|     unsigned int doublet[4];	/* Pixel values for 16bpp expansion. */
 | |
| #endif
 | |
| #if PSZ == 32
 | |
|     unsigned int doublet[8];	/* Pixel values for 32bpp expansion */
 | |
| #endif
 | |
| 
 | |
|     fgpixel = FgPixel & planemask;
 | |
|     bgpixel = BgPixel & planemask;    
 | |
| 
 | |
| #if PSZ == 16
 | |
|     if (rop == GXcopy && (planemask & PMSK) == PMSK) {
 | |
|         doublet[0] = bgpixel | (bgpixel << 16);
 | |
|         doublet[1] = fgpixel | (bgpixel << 16);
 | |
|         doublet[2] = bgpixel | (fgpixel << 16);
 | |
|         doublet[3] = fgpixel | (fgpixel << 16);
 | |
|     }
 | |
| #endif
 | |
| #if PSZ == 32
 | |
|     if (rop == GXcopy && (planemask & PMSK) == PMSK) {
 | |
|         doublet[0] = bgpixel; doublet[1] = bgpixel;
 | |
|         doublet[2] = fgpixel; doublet[3] = bgpixel;
 | |
|         doublet[4] = bgpixel; doublet[5] = fgpixel;
 | |
|         doublet[6] = fgpixel; doublet[7] = fgpixel;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     /* must explicitly ask for "int" widths, as code below expects it */
 | |
|     /* on some machines (Alpha), "long" and "int" are not the same size */
 | |
|     cfbGetTypedWidthAndPointer (pSrcDrawable, widthSrc, psrcBase, int, CfbBits)
 | |
|     cfbGetTypedWidthAndPointer (pDstDrawable, widthDst, pdstBase, int, CfbBits)
 | |
| 
 | |
| #if PSZ == 16
 | |
|     widthDst <<= 1;
 | |
| #endif
 | |
| #if PSZ == 24
 | |
|     widthDst <<= 2;
 | |
| #endif
 | |
| 
 | |
|     nbox = REGION_NUM_RECTS(prgnDst);
 | |
|     pbox = REGION_RECTS(prgnDst);
 | |
| 
 | |
|     while (nbox--)
 | |
|     {
 | |
| 	dstx = pbox->x1;
 | |
| 	dsty = pbox->y1;
 | |
| 	srcx = pptSrc->x;
 | |
| 	srcy = pptSrc->y;
 | |
| 	width = pbox->x2 - pbox->x1;
 | |
| 	height = pbox->y2 - pbox->y1;
 | |
| 	pbox++;
 | |
| 	pptSrc++;
 | |
| 	psrcLine = (unsigned int *)psrcBase + srcy * widthSrc + (srcx >> 5);
 | |
| #if PSZ == 16
 | |
| 	pdstLine = (unsigned short *)pdstBase + dsty * widthDst + dstx;
 | |
| #endif
 | |
| #if PSZ == 24
 | |
| 	pdstLine = (unsigned char *)pdstBase + dsty * widthDst + dstx * 3;
 | |
| #endif
 | |
| #if PSZ == 32
 | |
| 	pdstLine = (unsigned int *)pdstBase + dsty * widthDst + dstx;
 | |
| #endif
 | |
| 	xoffSrc = srcx & 0x1f;
 | |
| 
 | |
| 	/*
 | |
| 	 * compute constants for the first four bits to be
 | |
| 	 * copied.  This avoids troubles with partial first
 | |
| 	 * writes, and difficult shift computation
 | |
| 	 */
 | |
| 	leftShift = xoffSrc;
 | |
| 	rightShift = 32 - leftShift;
 | |
| 
 | |
| 	if (rop == GXcopy && (planemask & PMSK) == PMSK)
 | |
| 	{
 | |
| 	    while (height--)
 | |
| 	    {
 | |
| 	        psrc = psrcLine;
 | |
| 	        pdst = pdstLine;
 | |
| 	        psrcLine += widthSrc;
 | |
| 	        pdstLine += widthDst;
 | |
| 	        bits = *psrc++;
 | |
| 	        nl = width;
 | |
|    	        while (nl >= 32)
 | |
| 	        {
 | |
| 		    tmp = BitLeft(bits, leftShift);
 | |
| 		    bits = *psrc++;
 | |
| 		    if (rightShift != 32)
 | |
| 		        tmp |= BitRight(bits, rightShift);
 | |
| 		    i = 0;
 | |
| #if PSZ == 16
 | |
| 		    /*
 | |
| 		     * I've thrown in some optimization to at least write
 | |
| 		     * some aligned 32-bit words instead of 16-bit shorts.
 | |
| 		     */
 | |
| 		    if ((unsigned long)psrc & 2) {
 | |
| 		        /* Write unaligned 16-bit word at left edge. */
 | |
| 		        if (tmp & 0x01)
 | |
| 		            *pdst = fgpixel;
 | |
| 		        else
 | |
| 		            *pdst = bgpixel;
 | |
| 		        pdst++;
 | |
| 		        i++;
 | |
| 		    }
 | |
| 		    while (i <= 24)
 | |
| 		    {
 | |
| 		        unsigned tmpbits = tmp >> i;
 | |
| 		        *(unsigned int *)pdst = doublet[tmpbits & 0x03];
 | |
| 	        	*(unsigned int *)(pdst + 2) =
 | |
| 		            doublet[(tmpbits >> 2) & 0x03];
 | |
| 	        	*(unsigned int *)(pdst + 4) =
 | |
| 		            doublet[(tmpbits >> 4) & 0x03];
 | |
| 	        	*(unsigned int *)(pdst + 6) =
 | |
| 		            doublet[(tmpbits >> 6) & 0x03];
 | |
| 		        pdst += 8;	/* Advance four 32-bit words. */
 | |
| 		        i += 8;
 | |
| 		    }
 | |
| 		    while (i <= 30)
 | |
| 		    {
 | |
| 		        *(unsigned int *)pdst =
 | |
| 		            doublet[(tmp >> i) & 0x03];
 | |
| 		        pdst += 2;	/* Advance one 32-bit word. */
 | |
| 		        i += 2;
 | |
| 		    }
 | |
| 		    if (i == 31) {
 | |
| 		        if ((tmp >> 31) & 0x01)
 | |
| 		            *pdst = fgpixel;
 | |
| 		        else
 | |
| 		            *pdst = bgpixel;
 | |
| 		        pdst++;
 | |
| 		    }
 | |
| #endif		    
 | |
| #if PSZ == 24
 | |
| 		    while (i < 32) {
 | |
| 		        if ((tmp >> i) & 0x01) {
 | |
| 		            *pdst = fgpixel;
 | |
| 		            *(pdst + 1) = fgpixel >> 8;
 | |
| 		            *(pdst + 2) = fgpixel >> 16;
 | |
| 		        }
 | |
| 		        else {
 | |
| 		            *pdst = bgpixel;
 | |
| 		            *(pdst + 1) = bgpixel >> 8;
 | |
| 		            *(pdst + 2) = bgpixel >> 16;
 | |
| 		        }
 | |
| 		        pdst += 3;
 | |
| 		        i++;
 | |
| 		    }
 | |
| #endif
 | |
| #if PSZ == 32
 | |
| 		    while (i <= 28) {
 | |
| 		        int pair;
 | |
| 		        pair = (tmp >> i) & 0x03;
 | |
| 		        *pdst = doublet[pair * 2];
 | |
| 		        *(pdst + 1) = doublet[pair * 2 + 1];
 | |
| 		        pair = (tmp >> (i + 2)) & 0x03;
 | |
| 		        *(pdst + 2) = doublet[pair * 2];
 | |
| 		        *(pdst + 3) = doublet[pair * 2 + 1];
 | |
| 		        pdst += 4;
 | |
| 		        i += 4;
 | |
| 		    }
 | |
| 		    while (i < 32) {
 | |
| 		        *pdst = ((tmp >> i) & 0x01) ? fgpixel : bgpixel;
 | |
| 		        pdst++;
 | |
| 		        i++;
 | |
| 		    }
 | |
| #endif
 | |
| 		    nl -= 32;
 | |
| 	        }
 | |
| 
 | |
| 	        if (nl)
 | |
| 	        {
 | |
| 		    tmp = BitLeft(bits, leftShift);
 | |
| 		    /*
 | |
| 		     * better condition needed -- mustn't run
 | |
| 		     * off the end of the source...
 | |
| 		     */
 | |
| 		    if (rightShift != 32)
 | |
| 		    {
 | |
| 		        bits = *psrc++;
 | |
| 		        tmp |= BitRight (bits, rightShift);
 | |
| 		    }
 | |
| 		    i = 32;
 | |
| 		    while (nl--)
 | |
| 		    {
 | |
| 		        --i;
 | |
| #if PSZ == 24
 | |
| 		        if ((tmp >> (31 - i)) & 0x01) {
 | |
| 		            *pdst = fgpixel;
 | |
| 		            *(pdst + 1) = fgpixel >> 8;
 | |
| 		            *(pdst + 2) = fgpixel >> 16;
 | |
| 		        }
 | |
| 		        else {
 | |
| 		            *pdst = bgpixel;
 | |
| 		            *(pdst + 1) = bgpixel >> 8;
 | |
| 		            *(pdst + 2) = bgpixel >> 16;
 | |
| 		        }
 | |
| 		        pdst += 3;
 | |
| #else
 | |
| 		        *pdst = ((tmp >> (31 - i)) & 0x01) ? fgpixel : bgpixel;
 | |
| 		        pdst++;
 | |
| #endif
 | |
| 		    }
 | |
| 	        }
 | |
|             }
 | |
|         }
 | |
| 	else
 | |
| 	{
 | |
| 	    while (height--)
 | |
| 	    {
 | |
| 	        psrc = psrcLine;
 | |
| 	        pdst = pdstLine;
 | |
| 	        psrcLine += widthSrc;
 | |
| 	        pdstLine += widthDst;
 | |
| 	        bits = *psrc++;
 | |
| 	        nl = width;
 | |
|    	        while (nl >= 32)
 | |
| 	        {
 | |
| 		    tmp = BitLeft(bits, leftShift);
 | |
| 		    bits = *psrc++;
 | |
| 		    if (rightShift != 32)
 | |
| 		        tmp |= BitRight(bits, rightShift);
 | |
| 		    i = 32;
 | |
| 		    while (i--)
 | |
| 		    {
 | |
| 		        src = ((tmp >> (31 - i)) & 0x01) ? fgpixel : bgpixel;
 | |
| #if PSZ == 24
 | |
| 		        dst = *pdst;
 | |
| 			dst |= (*(pdst + 1)) << 8;
 | |
| 			dst |= (*(pdst + 2)) << 16;
 | |
|                         DoRop (result, rop, src, dst);
 | |
| 			*pdst = (dst & ~planemask) |
 | |
| 		  	        (result & planemask);
 | |
| 			*(pdst+1) = ((dst & ~planemask) >> 8) |
 | |
| 		  	        ((result & planemask) >> 8);
 | |
| 			*(pdst+2) = ((dst & ~planemask) >> 16) |
 | |
| 		  	        ((result & planemask) >> 16);
 | |
| 			pdst += 3;
 | |
| #else
 | |
|                         DoRop (result, rop, src, *pdst);
 | |
| 
 | |
| 		        *pdst = (*pdst & ~planemask) |
 | |
| 		  	        (result & planemask);
 | |
| 		        pdst++;
 | |
| #endif
 | |
| 		    }
 | |
| 		    nl -= 32;
 | |
| 	        }
 | |
| 
 | |
| 	        if (nl)
 | |
| 	        {
 | |
| 		    tmp = BitLeft(bits, leftShift);
 | |
| 		    /*
 | |
| 		     * better condition needed -- mustn't run
 | |
| 		     * off the end of the source...
 | |
| 		     */
 | |
| 		    if (rightShift != 32)
 | |
| 		    {
 | |
| 		        bits = *psrc++;
 | |
| 		        tmp |= BitRight (bits, rightShift);
 | |
| 		    }
 | |
| 		    i = 32;
 | |
| 		    while (nl--)
 | |
| 		    {
 | |
| 		        --i;
 | |
| 		        src = ((tmp >> (31 - i)) & 0x01) ? fgpixel : bgpixel;
 | |
| #if PSZ == 24
 | |
| 		        dst = *pdst;
 | |
| 			dst |= (*(pdst + 1)) << 8;
 | |
| 			dst |= (*(pdst + 2)) << 16;
 | |
|                         DoRop (result, rop, src, dst);
 | |
| 			*pdst = (dst & ~planemask) |
 | |
| 		  	        (result & planemask);
 | |
| 			*(pdst+1) = ((dst & ~planemask) >> 8) |
 | |
| 		  	        ((result & planemask) >> 8);
 | |
| 			*(pdst+2) = ((dst & ~planemask) >> 16) |
 | |
| 		  	        ((result & planemask) >> 16);
 | |
| 			pdst += 3;
 | |
| #else
 | |
|                         DoRop (result, rop, src, *pdst);
 | |
| 
 | |
| 		        *pdst = (*pdst & ~planemask) |
 | |
| 		  	        (result & planemask);
 | |
| 		        pdst++;
 | |
| #endif
 | |
| 		    }
 | |
| 	        }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| #endif  /* PSZ == 8 */
 | |
| 
 | |
| /* shared among all different cfb depths through linker magic */
 | |
| 
 | |
| RegionPtr cfbCopyPlane(pSrcDrawable, pDstDrawable,
 | |
| 	    pGC, srcx, srcy, width, height, dstx, dsty, bitPlane)
 | |
|     DrawablePtr 	pSrcDrawable;
 | |
|     DrawablePtr		pDstDrawable;
 | |
|     GCPtr		pGC;
 | |
|     int 		srcx, srcy;
 | |
|     int 		width, height;
 | |
|     int 		dstx, dsty;
 | |
|     unsigned long	bitPlane;
 | |
| {
 | |
|     RegionPtr	ret;
 | |
| 
 | |
| #if IMAGE_BYTE_ORDER == LSBFirst
 | |
| 
 | |
|     void (*doCopyPlaneExpand)(
 | |
|         DrawablePtr /*pSrc*/,
 | |
|         DrawablePtr /*pDst*/,
 | |
|         int /*alu*/,
 | |
|         RegionPtr /*prgnDst*/,
 | |
|         DDXPointPtr /*pptSrc*/,
 | |
|         unsigned long /*planemask*/);
 | |
| 
 | |
|     if (pSrcDrawable->bitsPerPixel == 1 && pDstDrawable->bitsPerPixel == PSZ)
 | |
|     {
 | |
|     	if (bitPlane == 1)
 | |
| 	{
 | |
|        	    doCopyPlaneExpand = cfbCopyPlane1toN;
 | |
| #if PSZ == 8
 | |
| 	    cfb8CheckOpaqueStipple (pGC->alu,
 | |
| 				    pGC->fgPixel, pGC->bgPixel,
 | |
| 				    pGC->planemask);
 | |
| #else
 | |
| 	    FgPixel = pGC->fgPixel;
 | |
| 	    BgPixel = pGC->bgPixel;
 | |
| #endif
 | |
|     	    ret = cfbCopyPlaneExpand (pSrcDrawable, pDstDrawable,
 | |
| 	    	    pGC, srcx, srcy, width, height, dstx, dsty, doCopyPlaneExpand, bitPlane);
 | |
| 	}
 | |
| 	else
 | |
| 	    ret = miHandleExposures (pSrcDrawable, pDstDrawable,
 | |
| 	    	pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
 | |
|     }
 | |
|     else if (pSrcDrawable->bitsPerPixel == PSZ && pDstDrawable->bitsPerPixel == 1)
 | |
|     {
 | |
| 	int oldalu;
 | |
| 
 | |
| 	oldalu = pGC->alu;
 | |
|     	if ((pGC->fgPixel & 1) == 0 && (pGC->bgPixel&1) == 1)
 | |
| 	    pGC->alu = mfbGetInverseAlu(pGC->alu);
 | |
|     	else if ((pGC->fgPixel & 1) == (pGC->bgPixel & 1))
 | |
| 	    pGC->alu = mfbReduceRop(pGC->alu, pGC->fgPixel);
 | |
| 	ret = cfbCopyPlaneReduce(pSrcDrawable, pDstDrawable,
 | |
| 			 pGC, srcx, srcy, width, height, dstx, dsty, 
 | |
| 			 cfbCopyPlaneNto1, bitPlane);
 | |
| 	pGC->alu = oldalu;
 | |
|     }
 | |
|     else if (pSrcDrawable->bitsPerPixel == PSZ && pDstDrawable->bitsPerPixel == PSZ)
 | |
|     {
 | |
| 	PixmapPtr	pBitmap;
 | |
| 	ScreenPtr	pScreen = pSrcDrawable->pScreen;
 | |
| 	GCPtr		pGC1;
 | |
| 
 | |
| 	pBitmap = (*pScreen->CreatePixmap) (pScreen, width, height, 1);
 | |
| 	if (!pBitmap)
 | |
| 	    return NULL;
 | |
| 	pGC1 = GetScratchGC (1, pScreen);
 | |
| 	if (!pGC1)
 | |
| 	{
 | |
| 	    (*pScreen->DestroyPixmap) (pBitmap);
 | |
| 	    return NULL;
 | |
| 	}
 | |
| 	/*
 | |
| 	 * don't need to set pGC->fgPixel,bgPixel as copyPlaneNto1
 | |
| 	 * ignores pixel values, expecting the rop to "do the
 | |
| 	 * right thing", which GXcopy will.
 | |
| 	 */
 | |
| 	ValidateGC ((DrawablePtr) pBitmap, pGC1);
 | |
| 	/* no exposures here, scratch GC's don't get graphics expose */
 | |
| 	cfbCopyPlaneReduce(pSrcDrawable, (DrawablePtr) pBitmap,
 | |
| 			  pGC1, srcx, srcy, width, height, 0, 0, 
 | |
| 			  cfbCopyPlaneNto1, bitPlane);
 | |
| #if PSZ == 8
 | |
| 	cfb8CheckOpaqueStipple (pGC->alu,
 | |
| 				pGC->fgPixel, pGC->bgPixel,
 | |
| 				pGC->planemask);
 | |
| #else
 | |
| 	    FgPixel = pGC->fgPixel;
 | |
| 	    BgPixel = pGC->bgPixel;
 | |
| #endif
 | |
| 	/* no exposures here, copy bits from inside a pixmap */
 | |
| 	cfbCopyPlaneExpand((DrawablePtr) pBitmap, pDstDrawable, pGC,
 | |
| 			    0, 0, width, height, dstx, dsty, cfbCopyPlane1toN, 1);
 | |
| 	FreeScratchGC (pGC1);
 | |
| 	(*pScreen->DestroyPixmap) (pBitmap);
 | |
| 	/* compute resultant exposures */
 | |
| 	ret = miHandleExposures (pSrcDrawable, pDstDrawable, pGC,
 | |
| 				 srcx, srcy, width, height,
 | |
| 				 dstx, dsty, bitPlane);
 | |
|     }
 | |
|     else
 | |
| #endif
 | |
| 	ret = miCopyPlane (pSrcDrawable, pDstDrawable,
 | |
| 	    pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| 
 |