1706f2543Smrg
2706f2543Smrg/*
3706f2543Smrg   This is a lighter version of cfbBitBlt.  We calculate the boxes
4706f2543Smrg   when accelerating pixmap->screen and screen->screen copies.
5706f2543Smrg   We also pass the GC to the doBitBlt function so that it has access
6706f2543Smrg   to the fg and bg so CopyPlane can use this.
7706f2543Smrg*/
8706f2543Smrg
9706f2543Smrg#ifdef HAVE_XORG_CONFIG_H
10706f2543Smrg#include <xorg-config.h>
11706f2543Smrg#endif
12706f2543Smrg
13706f2543Smrg#include "misc.h"
14706f2543Smrg#include "xf86.h"
15706f2543Smrg#include "xf86_OSproc.h"
16706f2543Smrg
17706f2543Smrg#include <X11/X.h>
18706f2543Smrg#include "mi.h"
19706f2543Smrg#include "pixmapstr.h"
20706f2543Smrg#include "gcstruct.h"
21706f2543Smrg#include "windowstr.h"
22706f2543Smrg#include "xaalocal.h"
23706f2543Smrg
24706f2543Smrg
25706f2543SmrgRegionPtr
26706f2543SmrgXAABitBlt(
27706f2543Smrg    DrawablePtr pSrcDrawable,
28706f2543Smrg    DrawablePtr pDstDrawable,
29706f2543Smrg    GC *pGC,
30706f2543Smrg    int srcx, int srcy,
31706f2543Smrg    int width, int height,
32706f2543Smrg    int dstx, int dsty,
33706f2543Smrg    void (*doBitBlt)(DrawablePtr, DrawablePtr, GCPtr, RegionPtr, DDXPointPtr),
34706f2543Smrg    unsigned long bitPlane )
35706f2543Smrg{
36706f2543Smrg
37706f2543Smrg    RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */
38706f2543Smrg    RegionPtr prgnExposed;
39706f2543Smrg    Bool freeSrcClip = FALSE;
40706f2543Smrg    RegionRec rgnDst;
41706f2543Smrg    DDXPointPtr pptSrc, ppt;
42706f2543Smrg    DDXPointRec origDest;
43706f2543Smrg    BoxPtr pbox;
44706f2543Smrg    BoxRec fastBox;
45706f2543Smrg    int i, dx, dy, numRects;
46706f2543Smrg    xRectangle origSource;
47706f2543Smrg    int fastClip = 0;		/* for fast clipping with pixmap source */
48706f2543Smrg    int fastExpose = 0;		/* for fast exposures with pixmap source */
49706f2543Smrg
50706f2543Smrg    origSource.x = srcx;
51706f2543Smrg    origSource.y = srcy;
52706f2543Smrg    origSource.width = width;
53706f2543Smrg    origSource.height = height;
54706f2543Smrg    origDest.x = dstx;
55706f2543Smrg    origDest.y = dsty;
56706f2543Smrg
57706f2543Smrg    if (pSrcDrawable->pScreen->SourceValidate) {
58706f2543Smrg	(*pSrcDrawable->pScreen->SourceValidate) (
59706f2543Smrg			pSrcDrawable, srcx, srcy, width, height,
60706f2543Smrg			pGC->subWindowMode);
61706f2543Smrg    }
62706f2543Smrg
63706f2543Smrg    srcx += pSrcDrawable->x;
64706f2543Smrg    srcy += pSrcDrawable->y;
65706f2543Smrg
66706f2543Smrg    /* clip the source */
67706f2543Smrg    if (pSrcDrawable->type == DRAWABLE_PIXMAP) {
68706f2543Smrg	if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE))
69706f2543Smrg	    prgnSrcClip = pGC->pCompositeClip;
70706f2543Smrg	else
71706f2543Smrg	    fastClip = 1;
72706f2543Smrg    } else {	/* Window */
73706f2543Smrg	if (pGC->subWindowMode == IncludeInferiors) {
74706f2543Smrg	    if (!((WindowPtr) pSrcDrawable)->parent) {
75706f2543Smrg		/*
76706f2543Smrg		 * special case bitblt from root window in
77706f2543Smrg		 * IncludeInferiors mode; just like from a pixmap
78706f2543Smrg		 */
79706f2543Smrg		fastClip = 1;
80706f2543Smrg	    } else if ((pSrcDrawable == pDstDrawable) &&
81706f2543Smrg		(pGC->clientClipType == CT_NONE)) {
82706f2543Smrg		prgnSrcClip = pGC->pCompositeClip;
83706f2543Smrg	    } else {
84706f2543Smrg		prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable);
85706f2543Smrg		freeSrcClip = TRUE;
86706f2543Smrg	    }
87706f2543Smrg	} else {
88706f2543Smrg	    prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
89706f2543Smrg	}
90706f2543Smrg    }
91706f2543Smrg
92706f2543Smrg    fastBox.x1 = srcx;
93706f2543Smrg    fastBox.y1 = srcy;
94706f2543Smrg    fastBox.x2 = srcx + width;
95706f2543Smrg    fastBox.y2 = srcy + height;
96706f2543Smrg
97706f2543Smrg    /* Don't create a source region if we are doing a fast clip */
98706f2543Smrg    if (fastClip) {
99706f2543Smrg	fastExpose = 1;
100706f2543Smrg	/*
101706f2543Smrg	 * clip the source; if regions extend beyond the source size,
102706f2543Smrg 	 * make sure exposure events get sent
103706f2543Smrg	 */
104706f2543Smrg	if (fastBox.x1 < pSrcDrawable->x) {
105706f2543Smrg	    fastBox.x1 = pSrcDrawable->x;
106706f2543Smrg	    fastExpose = 0;
107706f2543Smrg	}
108706f2543Smrg	if (fastBox.y1 < pSrcDrawable->y) {
109706f2543Smrg	    fastBox.y1 = pSrcDrawable->y;
110706f2543Smrg	    fastExpose = 0;
111706f2543Smrg	}
112706f2543Smrg	if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width) {
113706f2543Smrg	    fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
114706f2543Smrg	    fastExpose = 0;
115706f2543Smrg	}
116706f2543Smrg	if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height) {
117706f2543Smrg	    fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
118706f2543Smrg	    fastExpose = 0;
119706f2543Smrg	}
120706f2543Smrg    } else {
121706f2543Smrg	RegionInit(&rgnDst, &fastBox, 1);
122706f2543Smrg	RegionIntersect(&rgnDst, &rgnDst, prgnSrcClip);
123706f2543Smrg    }
124706f2543Smrg
125706f2543Smrg    dstx += pDstDrawable->x;
126706f2543Smrg    dsty += pDstDrawable->y;
127706f2543Smrg
128706f2543Smrg    if (pDstDrawable->type == DRAWABLE_WINDOW) {
129706f2543Smrg	if (!((WindowPtr)pDstDrawable)->realized) {
130706f2543Smrg	    if (!fastClip)
131706f2543Smrg		RegionUninit(&rgnDst);
132706f2543Smrg	    if (freeSrcClip)
133706f2543Smrg		RegionDestroy(prgnSrcClip);
134706f2543Smrg	    return NULL;
135706f2543Smrg	}
136706f2543Smrg    }
137706f2543Smrg
138706f2543Smrg    dx = srcx - dstx;
139706f2543Smrg    dy = srcy - dsty;
140706f2543Smrg
141706f2543Smrg    /* Translate and clip the dst to the destination composite clip */
142706f2543Smrg    if (fastClip) {
143706f2543Smrg	RegionPtr cclip;
144706f2543Smrg
145706f2543Smrg        /* Translate the region directly */
146706f2543Smrg        fastBox.x1 -= dx;
147706f2543Smrg        fastBox.x2 -= dx;
148706f2543Smrg        fastBox.y1 -= dy;
149706f2543Smrg        fastBox.y2 -= dy;
150706f2543Smrg
151706f2543Smrg	/* If the destination composite clip is one rectangle we can
152706f2543Smrg	   do the clip directly.  Otherwise we have to create a full
153706f2543Smrg	   blown region and call intersect */
154706f2543Smrg
155706f2543Smrg	cclip = pGC->pCompositeClip;
156706f2543Smrg        if (RegionNumRects(cclip) == 1) {
157706f2543Smrg	    BoxPtr pBox = RegionRects(cclip);
158706f2543Smrg
159706f2543Smrg	    if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1;
160706f2543Smrg	    if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2;
161706f2543Smrg	    if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1;
162706f2543Smrg	    if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2;
163706f2543Smrg
164706f2543Smrg	    /* Check to see if the region is empty */
165706f2543Smrg	    if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2) {
166706f2543Smrg		RegionNull(&rgnDst);
167706f2543Smrg	    } else {
168706f2543Smrg		RegionInit(&rgnDst, &fastBox, 1);
169706f2543Smrg	    }
170706f2543Smrg	} else {
171706f2543Smrg	    /* We must turn off fastClip now, since we must create
172706f2543Smrg	       a full blown region.  It is intersected with the
173706f2543Smrg	       composite clip below. */
174706f2543Smrg	    fastClip = 0;
175706f2543Smrg	    RegionInit(&rgnDst, &fastBox,1);
176706f2543Smrg	}
177706f2543Smrg    } else {
178706f2543Smrg        RegionTranslate(&rgnDst, -dx, -dy);
179706f2543Smrg    }
180706f2543Smrg
181706f2543Smrg    if (!fastClip) {
182706f2543Smrg	RegionIntersect(&rgnDst, &rgnDst,
183706f2543Smrg				 pGC->pCompositeClip);
184706f2543Smrg    }
185706f2543Smrg
186706f2543Smrg    /* Do bit blitting */
187706f2543Smrg    numRects = RegionNumRects(&rgnDst);
188706f2543Smrg    if (numRects && width && height) {
189706f2543Smrg	if(!(pptSrc = (DDXPointPtr)malloc(numRects *
190706f2543Smrg						  sizeof(DDXPointRec)))) {
191706f2543Smrg	    RegionUninit(&rgnDst);
192706f2543Smrg	    if (freeSrcClip)
193706f2543Smrg		RegionDestroy(prgnSrcClip);
194706f2543Smrg	    return NULL;
195706f2543Smrg	}
196706f2543Smrg	pbox = RegionRects(&rgnDst);
197706f2543Smrg	ppt = pptSrc;
198706f2543Smrg	for (i = numRects; --i >= 0; pbox++, ppt++) {
199706f2543Smrg	    ppt->x = pbox->x1 + dx;
200706f2543Smrg	    ppt->y = pbox->y1 + dy;
201706f2543Smrg	}
202706f2543Smrg
203706f2543Smrg	(*doBitBlt) (pSrcDrawable, pDstDrawable, pGC, &rgnDst, pptSrc);
204706f2543Smrg	free(pptSrc);
205706f2543Smrg    }
206706f2543Smrg
207706f2543Smrg    prgnExposed = NULL;
208706f2543Smrg    if (pGC->fExpose) {
209706f2543Smrg        /* Pixmap sources generate a NoExposed (we return NULL to do this) */
210706f2543Smrg        if (!fastExpose)
211706f2543Smrg	    prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
212706f2543Smrg				  origSource.x, origSource.y,
213706f2543Smrg				  (int)origSource.width,
214706f2543Smrg				  (int)origSource.height,
215706f2543Smrg				  origDest.x, origDest.y, bitPlane);
216706f2543Smrg    }
217706f2543Smrg    RegionUninit(&rgnDst);
218706f2543Smrg    if (freeSrcClip)
219706f2543Smrg	RegionDestroy(prgnSrcClip);
220706f2543Smrg    return prgnExposed;
221706f2543Smrg}
222