230 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			230 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
 | 
						|
/* 
 | 
						|
   This is a lighter version of cfbBitBlt.  We calculate the boxes
 | 
						|
   when accelerating pixmap->screen and screen->screen copies. 
 | 
						|
   We also pass the GC to the doBitBlt function so that it has access
 | 
						|
   to the fg and bg so CopyPlane can use this. 
 | 
						|
*/
 | 
						|
 | 
						|
#ifdef HAVE_XORG_CONFIG_H
 | 
						|
#include <xorg-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include "misc.h"
 | 
						|
#include "xf86.h"
 | 
						|
#include "xf86_OSproc.h"
 | 
						|
 | 
						|
#include <X11/X.h>
 | 
						|
#include "mi.h"
 | 
						|
#include "pixmapstr.h"
 | 
						|
#include "gcstruct.h"
 | 
						|
#include "windowstr.h"
 | 
						|
#include "xaalocal.h"
 | 
						|
 | 
						|
RegionPtr
 | 
						|
XAABitBlt(DrawablePtr pSrcDrawable,
 | 
						|
          DrawablePtr pDstDrawable,
 | 
						|
          GC * pGC,
 | 
						|
          int srcx, int srcy,
 | 
						|
          int width, int height,
 | 
						|
          int dstx, int dsty,
 | 
						|
          void (*doBitBlt) (DrawablePtr, DrawablePtr, GCPtr, RegionPtr,
 | 
						|
                            DDXPointPtr), unsigned long bitPlane)
 | 
						|
{
 | 
						|
 | 
						|
    RegionPtr prgnSrcClip = NULL;       /* may be a new region, or just a copy */
 | 
						|
    RegionPtr prgnExposed;
 | 
						|
    Bool freeSrcClip = FALSE;
 | 
						|
    RegionRec rgnDst;
 | 
						|
    DDXPointPtr pptSrc, ppt;
 | 
						|
    DDXPointRec origDest;
 | 
						|
    BoxPtr pbox;
 | 
						|
    BoxRec fastBox;
 | 
						|
    int i, dx, dy, numRects;
 | 
						|
    xRectangle origSource;
 | 
						|
    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->pScreen->SourceValidate) {
 | 
						|
        (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, srcx, srcy,
 | 
						|
                                                  width, height,
 | 
						|
                                                  pGC->subWindowMode);
 | 
						|
    }
 | 
						|
 | 
						|
    srcx += pSrcDrawable->x;
 | 
						|
    srcy += pSrcDrawable->y;
 | 
						|
 | 
						|
    /* clip the source */
 | 
						|
    if (pSrcDrawable->type == DRAWABLE_PIXMAP) {
 | 
						|
        if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE))
 | 
						|
            prgnSrcClip = pGC->pCompositeClip;
 | 
						|
        else
 | 
						|
            fastClip = 1;
 | 
						|
    }
 | 
						|
    else {                      /* Window */
 | 
						|
        if (pGC->subWindowMode == IncludeInferiors) {
 | 
						|
            if (!((WindowPtr) pSrcDrawable)->parent) {
 | 
						|
                /*
 | 
						|
                 * 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 = pGC->pCompositeClip;
 | 
						|
            }
 | 
						|
            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 {
 | 
						|
        RegionInit(&rgnDst, &fastBox, 1);
 | 
						|
        RegionIntersect(&rgnDst, &rgnDst, prgnSrcClip);
 | 
						|
    }
 | 
						|
 | 
						|
    dstx += pDstDrawable->x;
 | 
						|
    dsty += pDstDrawable->y;
 | 
						|
 | 
						|
    if (pDstDrawable->type == DRAWABLE_WINDOW) {
 | 
						|
        if (!((WindowPtr) pDstDrawable)->realized) {
 | 
						|
            if (!fastClip)
 | 
						|
                RegionUninit(&rgnDst);
 | 
						|
            if (freeSrcClip)
 | 
						|
                RegionDestroy(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 */
 | 
						|
 | 
						|
        cclip = pGC->pCompositeClip;
 | 
						|
        if (RegionNumRects(cclip) == 1) {
 | 
						|
            BoxPtr pBox = RegionRects(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) {
 | 
						|
                RegionNull(&rgnDst);
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                RegionInit(&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;
 | 
						|
            RegionInit(&rgnDst, &fastBox, 1);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        RegionTranslate(&rgnDst, -dx, -dy);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!fastClip) {
 | 
						|
        RegionIntersect(&rgnDst, &rgnDst, pGC->pCompositeClip);
 | 
						|
    }
 | 
						|
 | 
						|
    /* Do bit blitting */
 | 
						|
    numRects = RegionNumRects(&rgnDst);
 | 
						|
    if (numRects && width && height) {
 | 
						|
        if (!(pptSrc = (DDXPointPtr) malloc(numRects * sizeof(DDXPointRec)))) {
 | 
						|
            RegionUninit(&rgnDst);
 | 
						|
            if (freeSrcClip)
 | 
						|
                RegionDestroy(prgnSrcClip);
 | 
						|
            return NULL;
 | 
						|
        }
 | 
						|
        pbox = RegionRects(&rgnDst);
 | 
						|
        ppt = pptSrc;
 | 
						|
        for (i = numRects; --i >= 0; pbox++, ppt++) {
 | 
						|
            ppt->x = pbox->x1 + dx;
 | 
						|
            ppt->y = pbox->y1 + dy;
 | 
						|
        }
 | 
						|
 | 
						|
        (*doBitBlt) (pSrcDrawable, pDstDrawable, pGC, &rgnDst, pptSrc);
 | 
						|
        free(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);
 | 
						|
    }
 | 
						|
    RegionUninit(&rgnDst);
 | 
						|
    if (freeSrcClip)
 | 
						|
        RegionDestroy(prgnSrcClip);
 | 
						|
    return prgnExposed;
 | 
						|
}
 |