1/* 2 * 3 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of Keith Packard not be used in 10 * advertising or publicity pertaining to distribution of the software without 11 * specific, written prior permission. Keith Packard makes no 12 * representations about the suitability of this software for any purpose. It 13 * is provided "as is" without express or implied warranty. 14 * 15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 * PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24#ifdef HAVE_XORG_CONFIG_H 25#include <xorg-config.h> 26#endif 27 28#include <string.h> 29 30#include "misc.h" 31#include "xf86.h" 32#include "xf86_OSproc.h" 33 34#include <X11/X.h> 35#include "scrnintstr.h" 36#include "pixmapstr.h" 37#include "windowstr.h" 38#include "xf86str.h" 39#include "mi.h" 40#include "picturestr.h" 41#include "glyphstr.h" 42#include "picture.h" 43#include "mipict.h" 44#include "xaa.h" 45#include "xaalocal.h" 46#include "xaawrap.h" 47#include "xaacexp.h" 48#include "xf86fbman.h" 49#include "servermd.h" 50 51Bool 52XAAGetPixelFromRGBA ( 53 CARD32 *pixel, 54 CARD16 red, 55 CARD16 green, 56 CARD16 blue, 57 CARD16 alpha, 58 CARD32 format 59){ 60 int rbits, bbits, gbits, abits; 61 int rshift, bshift, gshift, ashift; 62 63 *pixel = 0; 64 65 if(!PICT_FORMAT_COLOR(format)) 66 return FALSE; 67 68 rbits = PICT_FORMAT_R(format); 69 gbits = PICT_FORMAT_G(format); 70 bbits = PICT_FORMAT_B(format); 71 abits = PICT_FORMAT_A(format); 72 73 if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 74 bshift = 0; 75 gshift = bbits; 76 rshift = gshift + gbits; 77 ashift = rshift + rbits; 78 } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { 79 rshift = 0; 80 gshift = rbits; 81 bshift = gshift + gbits; 82 ashift = bshift + bbits; 83 } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { 84 bshift = PICT_FORMAT_BPP(format) - bbits; 85 gshift = bshift - gbits; 86 rshift = gshift - rbits; 87 ashift = 0; 88 } else 89 return FALSE; 90 91 *pixel |= ( blue >> (16 - bbits)) << bshift; 92 *pixel |= ( red >> (16 - rbits)) << rshift; 93 *pixel |= (green >> (16 - gbits)) << gshift; 94 *pixel |= (alpha >> (16 - abits)) << ashift; 95 96 return TRUE; 97} 98 99 100Bool 101XAAGetRGBAFromPixel( 102 CARD32 pixel, 103 CARD16 *red, 104 CARD16 *green, 105 CARD16 *blue, 106 CARD16 *alpha, 107 CARD32 format 108){ 109 int rbits, bbits, gbits, abits; 110 int rshift, bshift, gshift, ashift; 111 112 if(!PICT_FORMAT_COLOR(format)) 113 return FALSE; 114 115 rbits = PICT_FORMAT_R(format); 116 gbits = PICT_FORMAT_G(format); 117 bbits = PICT_FORMAT_B(format); 118 abits = PICT_FORMAT_A(format); 119 120 if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 121 bshift = 0; 122 gshift = bbits; 123 rshift = gshift + gbits; 124 ashift = rshift + rbits; 125 } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { 126 rshift = 0; 127 gshift = rbits; 128 bshift = gshift + gbits; 129 ashift = bshift + bbits; 130 } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { 131 bshift = PICT_FORMAT_BPP(format) - bbits; 132 gshift = bshift - gbits; 133 rshift = gshift - rbits; 134 ashift = 0; 135 } else 136 return FALSE; 137 138 *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits); 139 while(rbits < 16) { 140 *red |= *red >> rbits; 141 rbits <<= 1; 142 } 143 144 *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits); 145 while(gbits < 16) { 146 *green |= *green >> gbits; 147 gbits <<= 1; 148 } 149 150 *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits); 151 while(bbits < 16) { 152 *blue |= *blue >> bbits; 153 bbits <<= 1; 154 } 155 156 if(abits) { 157 *alpha = ((pixel >> ashift ) & ((1 << abits) - 1)) << (16 - abits); 158 while(abits < 16) { 159 *alpha |= *alpha >> abits; 160 abits <<= 1; 161 } 162 } else *alpha = 0xffff; 163 164 return TRUE; 165} 166 167/* 8:8:8 + PICT_a8 -> 8:8:8:8 texture */ 168 169void 170XAA_888_plus_PICT_a8_to_8888 ( 171 CARD32 color, 172 CARD8 *alphaPtr, /* in bytes */ 173 int alphaPitch, 174 CARD32 *dstPtr, 175 int dstPitch, /* in dwords */ 176 int width, 177 int height 178){ 179 int x; 180 181 color &= 0x00ffffff; 182 183 while(height--) { 184 for(x = 0; x < width; x++) 185 dstPtr[x] = color | (alphaPtr[x] << 24); 186 dstPtr += dstPitch; 187 alphaPtr += alphaPitch; 188 } 189} 190 191#define DRAWABLE_IS_ON_CARD(pDraw) \ 192 (pDraw->type == DRAWABLE_WINDOW || \ 193 (pDraw->type == DRAWABLE_PIXMAP && IS_OFFSCREEN_PIXMAP(pDraw))) 194 195Bool 196XAADoComposite ( 197 CARD8 op, 198 PicturePtr pSrc, 199 PicturePtr pMask, 200 PicturePtr pDst, 201 INT16 xSrc, 202 INT16 ySrc, 203 INT16 xMask, 204 INT16 yMask, 205 INT16 xDst, 206 INT16 yDst, 207 CARD16 width, 208 CARD16 height 209){ 210 ScreenPtr pScreen = pDst->pDrawable->pScreen; 211 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); 212 RegionRec region; 213 CARD32 *formats, *dstformats; 214 int flags = 0; 215 BoxPtr pbox; 216 int nbox, w, h; 217 218 if(!RegionNumRects(pDst->pCompositeClip)) 219 return TRUE; 220 221 if(!infoRec->pScrn->vtSema || !DRAWABLE_IS_ON_CARD(pDst->pDrawable)) 222 return FALSE; 223 224 if(DRAWABLE_IS_ON_CARD(pSrc->pDrawable)) 225 return FALSE; 226 227 if (pSrc->transform || (pMask && pMask->transform)) 228 return FALSE; 229 230 if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) 231 return FALSE; 232 233 if ((pSrc->repeat && pSrc->repeatType != RepeatNormal) || 234 (pMask && pMask->repeat && pMask->repeatType != RepeatNormal)) 235 { 236 return FALSE; 237 } 238 239 xDst += pDst->pDrawable->x; 240 yDst += pDst->pDrawable->y; 241 xSrc += pSrc->pDrawable->x; 242 ySrc += pSrc->pDrawable->y; 243 244 if(pMask) { 245 if(pMask->componentAlpha) 246 return FALSE; 247 248 /* for now we only do it if there is a 1x1 (solid) source */ 249 250 if((pSrc->pDrawable->width == 1) && (pSrc->pDrawable->height == 1)) { 251 CARD16 red, green, blue, alpha; 252 CARD32 pixel = 253 *((CARD32*)(((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr)); 254 255 if(!XAAGetRGBAFromPixel(pixel,&red,&green,&blue,&alpha,pSrc->format)) 256 return FALSE; 257 258 xMask += pMask->pDrawable->x; 259 yMask += pMask->pDrawable->y; 260 261 /* pull out color expandable operations here */ 262 if((pMask->format == PICT_a1) && (alpha == 0xffff) && 263 (op == PictOpOver) && infoRec->WriteBitmap && !pMask->repeat && 264 !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY) && 265 (!(infoRec->WriteBitmapFlags & RGB_EQUAL) || 266 ((red == green) && (green == blue)))) 267 { 268 PixmapPtr pPix = (PixmapPtr)(pMask->pDrawable); 269 int skipleft; 270 271 if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, 272 xSrc, ySrc, xMask, yMask, xDst, yDst, 273 width, height)) 274 return TRUE; 275 276 nbox = RegionNumRects(®ion); 277 pbox = RegionRects(®ion); 278 279 if(!nbox) 280 return TRUE; 281 282 XAAGetPixelFromRGBA(&pixel, red, green, blue, 0, pDst->format); 283 284 xMask -= xDst; 285 yMask -= yDst; 286 287 while(nbox--) { 288 skipleft = pbox->x1 + xMask; 289 290 (*infoRec->WriteBitmap)(infoRec->pScrn, 291 pbox->x1, pbox->y1, 292 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, 293 (unsigned char*)(pPix->devPrivate.ptr) + 294 (pPix->devKind * (pbox->y1 + yMask)) + 295 ((skipleft >> 3) & ~3), pPix->devKind, 296 skipleft & 31, pixel, -1, GXcopy, ~0); 297 pbox++; 298 } 299 300 /* WriteBitmap sets the Sync flag */ 301 RegionUninit(®ion); 302 return TRUE; 303 } 304 305 formats = infoRec->CPUToScreenAlphaTextureFormats; 306 dstformats = infoRec->CPUToScreenAlphaTextureDstFormats; 307 if(!formats || !dstformats) 308 return FALSE; 309 310 w = pMask->pDrawable->width; 311 h = pMask->pDrawable->height; 312 313 if(pMask->repeat) { 314 if((infoRec->CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_TILE) || 315 ((infoRec->CPUToScreenAlphaTextureFlags & 316 XAA_RENDER_POWER_OF_2_TILE_ONLY) && 317 ((h & (h - 1)) || (w & (w - 1))))) 318 { 319 return FALSE; 320 } 321 flags |= XAA_RENDER_REPEAT; 322 } 323 324 if((alpha != 0xffff) && 325 (infoRec->CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_SRC_ALPHA)) 326 return FALSE; 327 328 while(*formats != pMask->format) { 329 if(!(*formats)) return FALSE; 330 formats++; 331 } 332 while(*dstformats != pDst->format) { 333 if(!(*dstformats)) 334 return FALSE; 335 dstformats++; 336 } 337 338 if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, 339 xSrc, ySrc, xMask, yMask, xDst, yDst, 340 width, height)) 341 return TRUE; 342 343 nbox = RegionNumRects(®ion); 344 pbox = RegionRects(®ion); 345 346 if(!nbox) { 347 RegionUninit(®ion); 348 return TRUE; 349 } 350 351 if(!(infoRec->SetupForCPUToScreenAlphaTexture2)(infoRec->pScrn, 352 op, red, green, blue, alpha, pMask->format, 353 pDst->format, 354 ((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr, 355 ((PixmapPtr)(pMask->pDrawable))->devKind, 356 w, h, flags)) 357 { 358 RegionUninit(®ion); 359 return FALSE; 360 } 361 362 xMask -= xDst; 363 yMask -= yDst; 364 365 while(nbox--) { 366 (*infoRec->SubsequentCPUToScreenAlphaTexture)(infoRec->pScrn, 367 pbox->x1, pbox->y1, 368 pbox->x1 + xMask, pbox->y1 + yMask, 369 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 370 pbox++; 371 } 372 373 SET_SYNC_FLAG(infoRec); 374 RegionUninit(®ion); 375 return TRUE; 376 } 377 } else { 378 formats = infoRec->CPUToScreenTextureFormats; 379 dstformats = infoRec->CPUToScreenTextureDstFormats; 380 if(!formats || !dstformats) 381 return FALSE; 382 383 w = pSrc->pDrawable->width; 384 h = pSrc->pDrawable->height; 385 386 if(pSrc->repeat) { 387 if((infoRec->CPUToScreenTextureFlags & XAA_RENDER_NO_TILE) || 388 ((infoRec->CPUToScreenTextureFlags & 389 XAA_RENDER_POWER_OF_2_TILE_ONLY) && 390 ((h & (h - 1)) || (w & (w - 1))))) 391 { 392 return FALSE; 393 } 394 flags |= XAA_RENDER_REPEAT; 395 } 396 397 while(*formats != pSrc->format) { 398 if(!(*formats)) return FALSE; 399 formats++; 400 } 401 while(*dstformats != pDst->format) { 402 if(!(*dstformats)) 403 return FALSE; 404 dstformats++; 405 } 406 407 if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, 408 xSrc, ySrc, xMask, yMask, xDst, yDst, 409 width, height)) 410 return TRUE; 411 412 nbox = RegionNumRects(®ion); 413 pbox = RegionRects(®ion); 414 415 if(!nbox) { 416 RegionUninit(®ion); 417 return TRUE; 418 } 419 420 if(!(infoRec->SetupForCPUToScreenTexture2)(infoRec->pScrn, 421 op, pSrc->format, pDst->format, 422 ((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr, 423 ((PixmapPtr)(pSrc->pDrawable))->devKind, 424 w, h, flags)) 425 { 426 RegionUninit(®ion); 427 return FALSE; 428 } 429 430 431 xSrc -= xDst; 432 ySrc -= yDst; 433 434 while(nbox--) { 435 (*infoRec->SubsequentCPUToScreenTexture)(infoRec->pScrn, 436 pbox->x1, pbox->y1, 437 pbox->x1 + xSrc, pbox->y1 + ySrc, 438 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 439 pbox++; 440 } 441 442 SET_SYNC_FLAG(infoRec); 443 RegionUninit(®ion); 444 return TRUE; 445 } 446 447 448 return FALSE; 449} 450 451static void 452XAACompositeSrcCopy (PicturePtr pSrc, 453 PicturePtr pDst, 454 INT16 xSrc, 455 INT16 ySrc, 456 INT16 xDst, 457 INT16 yDst, 458 CARD16 width, 459 CARD16 height) 460{ 461 ScreenPtr pScreen = pDst->pDrawable->pScreen; 462 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); 463 int i, nbox; 464 int xoff, yoff; 465 BoxPtr pbox; 466 DDXPointPtr pptSrc; 467 RegionRec region; 468 469 xDst += pDst->pDrawable->x; 470 yDst += pDst->pDrawable->y; 471 xSrc += pSrc->pDrawable->x; 472 ySrc += pSrc->pDrawable->y; 473 474 if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst, 475 xSrc, ySrc, 0, 0, xDst, yDst, 476 width, height)) 477 return; 478 479 nbox = RegionNumRects(®ion); 480 pbox = RegionRects(®ion); 481 482 if(!nbox) { 483 RegionUninit(®ion); 484 return; 485 } 486 pptSrc = malloc(sizeof(DDXPointRec) * nbox); 487 if (!pptSrc) { 488 RegionUninit(®ion); 489 return; 490 } 491 xoff = xSrc - xDst; 492 yoff = ySrc - yDst; 493 for (i = 0; i < nbox; i++) { 494 pptSrc[i].x = pbox[i].x1 + xoff; 495 pptSrc[i].y = pbox[i].y1 + yoff; 496 } 497 498 infoRec->ScratchGC.planemask = ~0L; 499 infoRec->ScratchGC.alu = GXcopy; 500 501 XAADoBitBlt(pSrc->pDrawable, pDst->pDrawable, &infoRec->ScratchGC, ®ion, 502 pptSrc); 503 504 free(pptSrc); 505 RegionUninit(®ion); 506 return; 507} 508 509void 510XAAComposite (CARD8 op, 511 PicturePtr pSrc, 512 PicturePtr pMask, 513 PicturePtr pDst, 514 INT16 xSrc, 515 INT16 ySrc, 516 INT16 xMask, 517 INT16 yMask, 518 INT16 xDst, 519 INT16 yDst, 520 CARD16 width, 521 CARD16 height) 522{ 523 ScreenPtr pScreen = pDst->pDrawable->pScreen; 524 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); 525 XAA_RENDER_PROLOGUE(pScreen, Composite); 526 527 if(!pMask && infoRec->pScrn->vtSema && 528 infoRec->ScreenToScreenBitBlt && 529 pSrc->pDrawable && 530 DRAWABLE_IS_ON_CARD(pSrc->pDrawable) && 531 DRAWABLE_IS_ON_CARD(pDst->pDrawable) && 532 !pSrc->transform && 533 (!pSrc->repeat || (xSrc >= 0 && ySrc >= 0 && 534 xSrc+width<=pSrc->pDrawable->width && 535 ySrc+height<=pSrc->pDrawable->height)) && 536 ((op == PictOpSrc && 537 ((pSrc->format==pDst->format) || 538 (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) || 539 (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) || 540 (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap && 541 pSrc->format==pDst->format && 542 (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8)))) 543 { 544 XAACompositeSrcCopy(pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height); 545 } else if(!pSrc->pDrawable || (pMask && !pMask->pDrawable) || 546 !infoRec->Composite || 547 !(*infoRec->Composite)(op, pSrc, pMask, pDst, 548 xSrc, ySrc, xMask, yMask, xDst, yDst, 549 width, height)) 550 { 551 if(infoRec->pScrn->vtSema && 552 ((pSrc->pDrawable && 553 (pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) || 554 pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) { 555 SYNC_CHECK(pDst->pDrawable); 556 } 557 (*GetPictureScreen(pScreen)->Composite) (op, 558 pSrc, 559 pMask, 560 pDst, 561 xSrc, 562 ySrc, 563 xMask, 564 yMask, 565 xDst, 566 yDst, 567 width, 568 height); 569 } 570 571 if(pDst->pDrawable->type == DRAWABLE_PIXMAP) 572 (XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst->pDrawable)))->flags |= DIRTY; 573 574 XAA_RENDER_EPILOGUE(pScreen, Composite, XAAComposite); 575} 576 577Bool 578XAADoGlyphs (CARD8 op, 579 PicturePtr pSrc, 580 PicturePtr pDst, 581 PictFormatPtr maskFormat, 582 INT16 xSrc, 583 INT16 ySrc, 584 int nlist, 585 GlyphListPtr list, 586 GlyphPtr *glyphs) 587{ 588 ScreenPtr pScreen = pDst->pDrawable->pScreen; 589 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); 590 591 if(!RegionNumRects(pDst->pCompositeClip)) 592 return TRUE; 593 594 if(!infoRec->pScrn->vtSema || 595 ((pDst->pDrawable->type != DRAWABLE_WINDOW) && 596 !IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) 597 return FALSE; 598 599 if((pSrc->pDrawable->type != DRAWABLE_PIXMAP) || 600 IS_OFFSCREEN_PIXMAP(pSrc->pDrawable)) 601 return FALSE; 602 603 /* 604 * If it looks like we have a chance of being able to draw these 605 * glyphs with an accelerated Composite, do that now to avoid 606 * unneeded and costly syncs. 607 */ 608 if(maskFormat) { 609 if(!infoRec->CPUToScreenAlphaTextureFormats) 610 return FALSE; 611 } else { 612 if(!infoRec->CPUToScreenTextureFormats) 613 return FALSE; 614 } 615 616 miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); 617 618 return TRUE; 619} 620 621 622void 623XAAGlyphs (CARD8 op, 624 PicturePtr pSrc, 625 PicturePtr pDst, 626 PictFormatPtr maskFormat, 627 INT16 xSrc, 628 INT16 ySrc, 629 int nlist, 630 GlyphListPtr list, 631 GlyphPtr *glyphs) 632{ 633 ScreenPtr pScreen = pDst->pDrawable->pScreen; 634 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); 635 XAA_RENDER_PROLOGUE(pScreen, Glyphs); 636 637 if(!pSrc->pDrawable || !infoRec->Glyphs || 638 !(*infoRec->Glyphs)(op, pSrc, pDst, maskFormat, 639 xSrc, ySrc, nlist, list, glyphs)) 640 { 641 if(infoRec->pScrn->vtSema && 642 ((pSrc->pDrawable && 643 (pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) || 644 pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) { 645 SYNC_CHECK(pDst->pDrawable); 646 } 647 (*GetPictureScreen(pScreen)->Glyphs) (op, pSrc, pDst, maskFormat, 648 xSrc, ySrc, nlist, list, glyphs); 649 } 650 651 if(pDst->pDrawable->type == DRAWABLE_PIXMAP) 652 (XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst->pDrawable)))->flags |= DIRTY; 653 654 XAA_RENDER_EPILOGUE(pScreen, Glyphs, XAAGlyphs); 655} 656