1 2#ifdef HAVE_XORG_CONFIG_H 3#include <xorg-config.h> 4#endif 5 6#include "misc.h" 7#include "xf86.h" 8#include "xf86_OSproc.h" 9 10#include <X11/X.h> 11#include "scrnintstr.h" 12#include "xf86str.h" 13#include "xaa.h" 14#include "xaalocal.h" 15#include "migc.h" 16#include "gcstruct.h" 17#include "pixmapstr.h" 18 19/* 20 Written mostly by Harm Hanemaayer (H.Hanemaayer@inter.nl.net). 21 */ 22 23 24RegionPtr 25XAACopyArea( 26 DrawablePtr pSrcDrawable, 27 DrawablePtr pDstDrawable, 28 GC *pGC, 29 int srcx, int srcy, 30 int width, int height, 31 int dstx, int dsty ) 32{ 33 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 34 35 if(pDstDrawable->type == DRAWABLE_WINDOW) { 36 if((pSrcDrawable->type == DRAWABLE_WINDOW) || 37 IS_OFFSCREEN_PIXMAP(pSrcDrawable)){ 38 if(infoRec->ScreenToScreenBitBlt && 39 CHECK_ROP(pGC,infoRec->ScreenToScreenBitBltFlags) && 40 CHECK_ROPSRC(pGC,infoRec->ScreenToScreenBitBltFlags) && 41 CHECK_PLANEMASK(pGC,infoRec->ScreenToScreenBitBltFlags)) 42 return (XAABitBlt( pSrcDrawable, pDstDrawable, 43 pGC, srcx, srcy, width, height, dstx, dsty, 44 XAADoBitBlt, 0L)); 45 } else { 46 if(infoRec->WritePixmap && 47 ((pDstDrawable->bitsPerPixel == pSrcDrawable->bitsPerPixel) || 48 ((pDstDrawable->bitsPerPixel == 24) && 49 (pSrcDrawable->bitsPerPixel == 32) && 50 (infoRec->WritePixmapFlags & CONVERT_32BPP_TO_24BPP))) && 51 CHECK_ROP(pGC,infoRec->WritePixmapFlags) && 52 CHECK_ROPSRC(pGC,infoRec->WritePixmapFlags) && 53 CHECK_PLANEMASK(pGC,infoRec->WritePixmapFlags) && 54 CHECK_NO_GXCOPY(pGC,infoRec->WritePixmapFlags)) 55 return (XAABitBlt( pSrcDrawable, pDstDrawable, 56 pGC, srcx, srcy, width, height, dstx, dsty, 57 XAADoImageWrite, 0L)); 58 } 59 } else if(IS_OFFSCREEN_PIXMAP(pDstDrawable)){ 60 if((pSrcDrawable->type == DRAWABLE_WINDOW) || 61 IS_OFFSCREEN_PIXMAP(pSrcDrawable)){ 62 if(infoRec->ScreenToScreenBitBlt && 63 CHECK_ROP(pGC,infoRec->ScreenToScreenBitBltFlags) && 64 CHECK_ROPSRC(pGC,infoRec->ScreenToScreenBitBltFlags) && 65 CHECK_PLANEMASK(pGC,infoRec->ScreenToScreenBitBltFlags)) 66 return (XAABitBlt( pSrcDrawable, pDstDrawable, 67 pGC, srcx, srcy, width, height, dstx, dsty, 68 XAADoBitBlt, 0L)); 69 } 70 } 71 72 return (XAAFallbackOps.CopyArea(pSrcDrawable, pDstDrawable, pGC, 73 srcx, srcy, width, height, dstx, dsty)); 74} 75 76 77void 78XAADoBitBlt( 79 DrawablePtr pSrc, 80 DrawablePtr pDst, 81 GC *pGC, 82 RegionPtr prgnDst, 83 DDXPointPtr pptSrc ) 84{ 85 int nbox, careful; 86 BoxPtr pbox, pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2; 87 DDXPointPtr pptTmp, pptNew1, pptNew2; 88 int xdir, ydir; 89 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 90 91 /* XXX we have to err on the side of safety when both are windows, 92 * because we don't know if IncludeInferiors is being used. 93 */ 94 careful = ((pSrc == pDst) || 95 ((pSrc->type == DRAWABLE_WINDOW) && 96 (pDst->type == DRAWABLE_WINDOW))); 97 98 pbox = RegionRects(prgnDst); 99 nbox = RegionNumRects(prgnDst); 100 101 pboxNew1 = NULL; 102 pptNew1 = NULL; 103 pboxNew2 = NULL; 104 pptNew2 = NULL; 105 if (careful && (pptSrc->y < pbox->y1)) { 106 /* walk source botttom to top */ 107 ydir = -1; 108 109 if (nbox > 1) { 110 /* keep ordering in each band, reverse order of bands */ 111 pboxNew1 = (BoxPtr)malloc(sizeof(BoxRec) * nbox); 112 if(!pboxNew1) 113 return; 114 pptNew1 = (DDXPointPtr)malloc(sizeof(DDXPointRec) * nbox); 115 if(!pptNew1) { 116 free(pboxNew1); 117 return; 118 } 119 pboxBase = pboxNext = pbox+nbox-1; 120 while (pboxBase >= pbox) { 121 while ((pboxNext >= pbox) && 122 (pboxBase->y1 == pboxNext->y1)) 123 pboxNext--; 124 pboxTmp = pboxNext+1; 125 pptTmp = pptSrc + (pboxTmp - pbox); 126 while (pboxTmp <= pboxBase) { 127 *pboxNew1++ = *pboxTmp++; 128 *pptNew1++ = *pptTmp++; 129 } 130 pboxBase = pboxNext; 131 } 132 pboxNew1 -= nbox; 133 pbox = pboxNew1; 134 pptNew1 -= nbox; 135 pptSrc = pptNew1; 136 } 137 } else { 138 /* walk source top to bottom */ 139 ydir = 1; 140 } 141 142 if (careful && (pptSrc->x < pbox->x1)) { 143 /* walk source right to left */ 144 xdir = -1; 145 146 if (nbox > 1) { 147 /* reverse order of rects in each band */ 148 pboxNew2 = (BoxPtr)malloc(sizeof(BoxRec) * nbox); 149 pptNew2 = (DDXPointPtr)malloc(sizeof(DDXPointRec) * nbox); 150 if(!pboxNew2 || !pptNew2) { 151 free(pptNew2); 152 free(pboxNew2); 153 if (pboxNew1) { 154 free(pptNew1); 155 free(pboxNew1); 156 } 157 return; 158 } 159 pboxBase = pboxNext = pbox; 160 while (pboxBase < pbox+nbox) { 161 while ((pboxNext < pbox+nbox) && 162 (pboxNext->y1 == pboxBase->y1)) 163 pboxNext++; 164 pboxTmp = pboxNext; 165 pptTmp = pptSrc + (pboxTmp - pbox); 166 while (pboxTmp != pboxBase) { 167 *pboxNew2++ = *--pboxTmp; 168 *pptNew2++ = *--pptTmp; 169 } 170 pboxBase = pboxNext; 171 } 172 pboxNew2 -= nbox; 173 pbox = pboxNew2; 174 pptNew2 -= nbox; 175 pptSrc = pptNew2; 176 } 177 } else { 178 /* walk source left to right */ 179 xdir = 1; 180 } 181 182 (*infoRec->ScreenToScreenBitBlt)(infoRec->pScrn, nbox, pptSrc, pbox, 183 xdir, ydir, pGC->alu, pGC->planemask); 184 185 if (pboxNew2) { 186 free(pptNew2); 187 free(pboxNew2); 188 } 189 if (pboxNew1) { 190 free(pptNew1); 191 free(pboxNew1); 192 } 193 194} 195 196void 197XAADoImageWrite( 198 DrawablePtr pSrc, 199 DrawablePtr pDst, 200 GC *pGC, 201 RegionPtr prgnDst, 202 DDXPointPtr pptSrc ) 203{ 204 int srcwidth; 205 unsigned char* psrcBase; /* start of image */ 206 unsigned char* srcPntr; /* index into the image */ 207 BoxPtr pbox = RegionRects(prgnDst); 208 int nbox = RegionNumRects(prgnDst); 209 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 210 int Bpp = pSrc->bitsPerPixel >> 3; 211 212 psrcBase = (unsigned char *)((PixmapPtr)pSrc)->devPrivate.ptr; 213 srcwidth = (int)((PixmapPtr)pSrc)->devKind; 214 215 for(; nbox; pbox++, pptSrc++, nbox--) { 216 srcPntr = psrcBase + (pptSrc->y * srcwidth) + (pptSrc->x * Bpp); 217 218 (*infoRec->WritePixmap)(infoRec->pScrn, pbox->x1, pbox->y1, 219 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, srcPntr, srcwidth, 220 pGC->alu, pGC->planemask, -1, pSrc->bitsPerPixel, pSrc->depth); 221 } 222} 223 224 225void 226XAADoImageRead( 227 DrawablePtr pSrc, 228 DrawablePtr pDst, 229 GC *pGC, 230 RegionPtr prgnDst, 231 DDXPointPtr pptSrc ) 232{ 233 int dstwidth; 234 unsigned char* pdstBase; /* start of image */ 235 unsigned char* dstPntr; /* index into the image */ 236 BoxPtr pbox = RegionRects(prgnDst); 237 int nbox = RegionNumRects(prgnDst); 238 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 239 int Bpp = pSrc->bitsPerPixel >> 3; /* wouldn't get here unless both 240 src and dst have same bpp */ 241 242 pdstBase = (unsigned char *)((PixmapPtr)pDst)->devPrivate.ptr; 243 dstwidth = (int)((PixmapPtr)pDst)->devKind; 244 245 for(; nbox; pbox++, pptSrc++, nbox--) { 246 dstPntr = pdstBase + (pbox->y1 * dstwidth) + (pbox->x1 * Bpp); 247 248 (*infoRec->ReadPixmap)(infoRec->pScrn, pptSrc->x, pptSrc->y, 249 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, dstPntr, dstwidth, 250 pSrc->bitsPerPixel, pSrc->depth); 251 } 252} 253 254 255void 256XAAScreenToScreenBitBlt( 257 ScrnInfoPtr pScrn, 258 int nbox, 259 DDXPointPtr pptSrc, 260 BoxPtr pbox, 261 int xdir, int ydir, 262 int alu, 263 unsigned int planemask ) 264{ 265 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 266 int dirsetup; 267 268 if ((!(infoRec->CopyAreaFlags & ONLY_TWO_BITBLT_DIRECTIONS) 269 || (xdir == ydir)) && 270 (!(infoRec->CopyAreaFlags & ONLY_LEFT_TO_RIGHT_BITBLT) 271 || (xdir == 1))) { 272 (*infoRec->SetupForScreenToScreenCopy)(pScrn, 273 xdir, ydir, alu, planemask, -1); 274 for (; nbox; pbox++, pptSrc++, nbox--) 275 (*infoRec->SubsequentScreenToScreenCopy)(pScrn,pptSrc->x, pptSrc->y, 276 pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 277 SET_SYNC_FLAG(infoRec); 278 return; 279 } 280 281 if (infoRec->CopyAreaFlags & ONLY_LEFT_TO_RIGHT_BITBLT) { 282 /* 283 * This is the case of a chip that only supports xdir = 1, 284 * with ydir = 1 or ydir = -1, but we have xdir = -1. 285 */ 286 (*infoRec->SetupForScreenToScreenCopy)(pScrn, 287 1, ydir, alu, planemask, -1); 288 for (; nbox; pbox++, pptSrc++, nbox--) 289 if (pptSrc->y != pbox->y1 || pptSrc->x >= pbox->x1) 290 /* No problem. Do a xdir = 1 blit instead. */ 291 (*infoRec->SubsequentScreenToScreenCopy)(pScrn, 292 pptSrc->x, pptSrc->y, pbox->x1, pbox->y1, 293 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 294 else 295 { 296 /* 297 * This is the difficult case. Needs striping into 298 * non-overlapping horizontal chunks. 299 */ 300 int stripeWidth, w, fullStripes, extra, i; 301 stripeWidth = 16; 302 w = pbox->x2 - pbox->x1; 303 if (pbox->x1 - pptSrc->x < stripeWidth) 304 stripeWidth = pbox->x1 - pptSrc->x; 305 fullStripes = w / stripeWidth; 306 extra = w % stripeWidth; 307 308 /* First, take care of the little bit on the far right */ 309 if (extra) 310 (*infoRec->SubsequentScreenToScreenCopy)(pScrn, 311 pptSrc->x + fullStripes * stripeWidth, pptSrc->y, 312 pbox->x1 + fullStripes * stripeWidth, pbox->y1, 313 extra, pbox->y2 - pbox->y1); 314 315 /* Now, take care of the rest of the blit */ 316 for (i = fullStripes - 1; i >= 0; i--) 317 (*infoRec->SubsequentScreenToScreenCopy)(pScrn, 318 pptSrc->x + i * stripeWidth, pptSrc->y, 319 pbox->x1 + i * stripeWidth, pbox->y1, 320 stripeWidth, pbox->y2 - pbox->y1); 321 } 322 SET_SYNC_FLAG(infoRec); 323 return; 324 } 325 326 /* 327 * Now the case of a chip that only supports xdir = ydir = 1 or 328 * xdir = ydir = -1, but we have xdir != ydir. 329 */ 330 dirsetup = 0; /* No direction set up yet. */ 331 for (; nbox; pbox++, pptSrc++, nbox--) { 332 if (xdir == 1 && pptSrc->y != pbox->y1) { 333 /* Do a xdir = ydir = -1 blit instead. */ 334 if (dirsetup != -1) { 335 (*infoRec->SetupForScreenToScreenCopy)(pScrn, 336 -1, -1, alu, planemask, -1); 337 dirsetup = -1; 338 } 339 (*infoRec->SubsequentScreenToScreenCopy)(pScrn,pptSrc->x, pptSrc->y, 340 pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 341 } 342 else if (xdir == -1 && pptSrc->y != pbox->y1) { 343 /* Do a xdir = ydir = 1 blit instead. */ 344 if (dirsetup != 1) { 345 (*infoRec->SetupForScreenToScreenCopy)(pScrn, 346 1, 1, alu, planemask, -1); 347 dirsetup = 1; 348 } 349 (*infoRec->SubsequentScreenToScreenCopy)(pScrn,pptSrc->x, pptSrc->y, 350 pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 351 } 352 else 353 if (xdir == 1) { 354 /* 355 * xdir = 1, ydir = -1. 356 * Perform line-by-line xdir = ydir = 1 blits, going up. 357 */ 358 int i; 359 if (dirsetup != 1) { 360 (*infoRec->SetupForScreenToScreenCopy)(pScrn, 361 1, 1, alu, planemask, -1); 362 dirsetup = 1; 363 } 364 for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--) 365 (*infoRec->SubsequentScreenToScreenCopy)(pScrn, 366 pptSrc->x, pptSrc->y + i, pbox->x1, pbox->y1 + i, 367 pbox->x2 - pbox->x1, 1); 368 } 369 else { 370 /* 371 * xdir = -1, ydir = 1. 372 * Perform line-by-line xdir = ydir = -1 blits, going down. 373 */ 374 int i; 375 if (dirsetup != -1) { 376 (*infoRec->SetupForScreenToScreenCopy)(pScrn, 377 -1, -1, alu, planemask, -1); 378 dirsetup = -1; 379 } 380 for (i = 0; i < pbox->y2 - pbox->y1; i++) 381 (*infoRec->SubsequentScreenToScreenCopy)(pScrn, 382 pptSrc->x, pptSrc->y + i, pbox->x1, pbox->y1 + i, 383 pbox->x2 - pbox->x1, 1); 384 } 385 } /* next box */ 386 SET_SYNC_FLAG(infoRec); 387} 388