xaaBitBlt.c revision 706f2543
1 2/* 3 This is a lighter version of cfbBitBlt. We calculate the boxes 4 when accelerating pixmap->screen and screen->screen copies. 5 We also pass the GC to the doBitBlt function so that it has access 6 to the fg and bg so CopyPlane can use this. 7*/ 8 9#ifdef HAVE_XORG_CONFIG_H 10#include <xorg-config.h> 11#endif 12 13#include "misc.h" 14#include "xf86.h" 15#include "xf86_OSproc.h" 16 17#include <X11/X.h> 18#include "mi.h" 19#include "pixmapstr.h" 20#include "gcstruct.h" 21#include "windowstr.h" 22#include "xaalocal.h" 23 24 25RegionPtr 26XAABitBlt( 27 DrawablePtr pSrcDrawable, 28 DrawablePtr pDstDrawable, 29 GC *pGC, 30 int srcx, int srcy, 31 int width, int height, 32 int dstx, int dsty, 33 void (*doBitBlt)(DrawablePtr, DrawablePtr, GCPtr, RegionPtr, DDXPointPtr), 34 unsigned long bitPlane ) 35{ 36 37 RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */ 38 RegionPtr prgnExposed; 39 Bool freeSrcClip = FALSE; 40 RegionRec rgnDst; 41 DDXPointPtr pptSrc, ppt; 42 DDXPointRec origDest; 43 BoxPtr pbox; 44 BoxRec fastBox; 45 int i, dx, dy, numRects; 46 xRectangle origSource; 47 int fastClip = 0; /* for fast clipping with pixmap source */ 48 int fastExpose = 0; /* for fast exposures with pixmap source */ 49 50 origSource.x = srcx; 51 origSource.y = srcy; 52 origSource.width = width; 53 origSource.height = height; 54 origDest.x = dstx; 55 origDest.y = dsty; 56 57 if (pSrcDrawable->pScreen->SourceValidate) { 58 (*pSrcDrawable->pScreen->SourceValidate) ( 59 pSrcDrawable, srcx, srcy, width, height, 60 pGC->subWindowMode); 61 } 62 63 srcx += pSrcDrawable->x; 64 srcy += pSrcDrawable->y; 65 66 /* clip the source */ 67 if (pSrcDrawable->type == DRAWABLE_PIXMAP) { 68 if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE)) 69 prgnSrcClip = pGC->pCompositeClip; 70 else 71 fastClip = 1; 72 } else { /* Window */ 73 if (pGC->subWindowMode == IncludeInferiors) { 74 if (!((WindowPtr) pSrcDrawable)->parent) { 75 /* 76 * special case bitblt from root window in 77 * IncludeInferiors mode; just like from a pixmap 78 */ 79 fastClip = 1; 80 } else if ((pSrcDrawable == pDstDrawable) && 81 (pGC->clientClipType == CT_NONE)) { 82 prgnSrcClip = pGC->pCompositeClip; 83 } else { 84 prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable); 85 freeSrcClip = TRUE; 86 } 87 } else { 88 prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList; 89 } 90 } 91 92 fastBox.x1 = srcx; 93 fastBox.y1 = srcy; 94 fastBox.x2 = srcx + width; 95 fastBox.y2 = srcy + height; 96 97 /* Don't create a source region if we are doing a fast clip */ 98 if (fastClip) { 99 fastExpose = 1; 100 /* 101 * clip the source; if regions extend beyond the source size, 102 * make sure exposure events get sent 103 */ 104 if (fastBox.x1 < pSrcDrawable->x) { 105 fastBox.x1 = pSrcDrawable->x; 106 fastExpose = 0; 107 } 108 if (fastBox.y1 < pSrcDrawable->y) { 109 fastBox.y1 = pSrcDrawable->y; 110 fastExpose = 0; 111 } 112 if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width) { 113 fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; 114 fastExpose = 0; 115 } 116 if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height) { 117 fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; 118 fastExpose = 0; 119 } 120 } else { 121 RegionInit(&rgnDst, &fastBox, 1); 122 RegionIntersect(&rgnDst, &rgnDst, prgnSrcClip); 123 } 124 125 dstx += pDstDrawable->x; 126 dsty += pDstDrawable->y; 127 128 if (pDstDrawable->type == DRAWABLE_WINDOW) { 129 if (!((WindowPtr)pDstDrawable)->realized) { 130 if (!fastClip) 131 RegionUninit(&rgnDst); 132 if (freeSrcClip) 133 RegionDestroy(prgnSrcClip); 134 return NULL; 135 } 136 } 137 138 dx = srcx - dstx; 139 dy = srcy - dsty; 140 141 /* Translate and clip the dst to the destination composite clip */ 142 if (fastClip) { 143 RegionPtr cclip; 144 145 /* Translate the region directly */ 146 fastBox.x1 -= dx; 147 fastBox.x2 -= dx; 148 fastBox.y1 -= dy; 149 fastBox.y2 -= dy; 150 151 /* If the destination composite clip is one rectangle we can 152 do the clip directly. Otherwise we have to create a full 153 blown region and call intersect */ 154 155 cclip = pGC->pCompositeClip; 156 if (RegionNumRects(cclip) == 1) { 157 BoxPtr pBox = RegionRects(cclip); 158 159 if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1; 160 if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2; 161 if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1; 162 if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2; 163 164 /* Check to see if the region is empty */ 165 if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2) { 166 RegionNull(&rgnDst); 167 } else { 168 RegionInit(&rgnDst, &fastBox, 1); 169 } 170 } else { 171 /* We must turn off fastClip now, since we must create 172 a full blown region. It is intersected with the 173 composite clip below. */ 174 fastClip = 0; 175 RegionInit(&rgnDst, &fastBox,1); 176 } 177 } else { 178 RegionTranslate(&rgnDst, -dx, -dy); 179 } 180 181 if (!fastClip) { 182 RegionIntersect(&rgnDst, &rgnDst, 183 pGC->pCompositeClip); 184 } 185 186 /* Do bit blitting */ 187 numRects = RegionNumRects(&rgnDst); 188 if (numRects && width && height) { 189 if(!(pptSrc = (DDXPointPtr)malloc(numRects * 190 sizeof(DDXPointRec)))) { 191 RegionUninit(&rgnDst); 192 if (freeSrcClip) 193 RegionDestroy(prgnSrcClip); 194 return NULL; 195 } 196 pbox = RegionRects(&rgnDst); 197 ppt = pptSrc; 198 for (i = numRects; --i >= 0; pbox++, ppt++) { 199 ppt->x = pbox->x1 + dx; 200 ppt->y = pbox->y1 + dy; 201 } 202 203 (*doBitBlt) (pSrcDrawable, pDstDrawable, pGC, &rgnDst, pptSrc); 204 free(pptSrc); 205 } 206 207 prgnExposed = NULL; 208 if (pGC->fExpose) { 209 /* Pixmap sources generate a NoExposed (we return NULL to do this) */ 210 if (!fastExpose) 211 prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, 212 origSource.x, origSource.y, 213 (int)origSource.width, 214 (int)origSource.height, 215 origDest.x, origDest.y, bitPlane); 216 } 217 RegionUninit(&rgnDst); 218 if (freeSrcClip) 219 RegionDestroy(prgnSrcClip); 220 return prgnExposed; 221} 222