picture.c revision 6747b715
1/* 2 * 3 * Copyright © 2000 SuSE, 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 SuSE not be used in advertising or 10 * publicity pertaining to distribution of the software without specific, 11 * written prior permission. SuSE makes no representations about the 12 * suitability of this software for any purpose. It is provided "as is" 13 * without express or implied warranty. 14 * 15 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 17 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 19 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21 * 22 * Author: Keith Packard, SuSE, Inc. 23 */ 24 25#ifdef HAVE_DIX_CONFIG_H 26#include <dix-config.h> 27#endif 28 29#include "misc.h" 30#include "scrnintstr.h" 31#include "os.h" 32#include "regionstr.h" 33#include "validate.h" 34#include "windowstr.h" 35#include "input.h" 36#include "resource.h" 37#include "colormapst.h" 38#include "cursorstr.h" 39#include "dixstruct.h" 40#include "gcstruct.h" 41#include "servermd.h" 42#include "picturestr.h" 43#include "xace.h" 44 45DevPrivateKeyRec PictureScreenPrivateKeyRec; 46DevPrivateKeyRec PictureWindowPrivateKeyRec; 47static int PictureGeneration; 48RESTYPE PictureType; 49RESTYPE PictFormatType; 50RESTYPE GlyphSetType; 51int PictureCmapPolicy = PictureCmapPolicyDefault; 52 53Bool 54PictureDestroyWindow (WindowPtr pWindow) 55{ 56 ScreenPtr pScreen = pWindow->drawable.pScreen; 57 PicturePtr pPicture; 58 PictureScreenPtr ps = GetPictureScreen(pScreen); 59 Bool ret; 60 61 while ((pPicture = GetPictureWindow(pWindow))) 62 { 63 SetPictureWindow(pWindow, pPicture->pNext); 64 if (pPicture->id) 65 FreeResource (pPicture->id, PictureType); 66 FreePicture ((pointer) pPicture, pPicture->id); 67 } 68 pScreen->DestroyWindow = ps->DestroyWindow; 69 ret = (*pScreen->DestroyWindow) (pWindow); 70 ps->DestroyWindow = pScreen->DestroyWindow; 71 pScreen->DestroyWindow = PictureDestroyWindow; 72 return ret; 73} 74 75Bool 76PictureCloseScreen (int index, ScreenPtr pScreen) 77{ 78 PictureScreenPtr ps = GetPictureScreen(pScreen); 79 Bool ret; 80 int n; 81 82 pScreen->CloseScreen = ps->CloseScreen; 83 ret = (*pScreen->CloseScreen) (index, pScreen); 84 PictureResetFilters (pScreen); 85 for (n = 0; n < ps->nformats; n++) 86 if (ps->formats[n].type == PictTypeIndexed) 87 (*ps->CloseIndexed) (pScreen, &ps->formats[n]); 88 GlyphUninit (pScreen); 89 SetPictureScreen(pScreen, 0); 90 free(ps->formats); 91 free(ps); 92 return ret; 93} 94 95void 96PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef) 97{ 98 ScreenPtr pScreen = pColormap->pScreen; 99 PictureScreenPtr ps = GetPictureScreen(pScreen); 100 101 pScreen->StoreColors = ps->StoreColors; 102 (*pScreen->StoreColors) (pColormap, ndef, pdef); 103 ps->StoreColors = pScreen->StoreColors; 104 pScreen->StoreColors = PictureStoreColors; 105 106 if (pColormap->class == PseudoColor || pColormap->class == GrayScale) 107 { 108 PictFormatPtr format = ps->formats; 109 int nformats = ps->nformats; 110 111 while (nformats--) 112 { 113 if (format->type == PictTypeIndexed && 114 format->index.pColormap == pColormap) 115 { 116 (*ps->UpdateIndexed) (pScreen, format, ndef, pdef); 117 break; 118 } 119 format++; 120 } 121 } 122} 123 124static int 125visualDepth (ScreenPtr pScreen, VisualPtr pVisual) 126{ 127 int d, v; 128 DepthPtr pDepth; 129 130 for (d = 0; d < pScreen->numDepths; d++) 131 { 132 pDepth = &pScreen->allowedDepths[d]; 133 for (v = 0; v < pDepth->numVids; v++) 134 if (pDepth->vids[v] == pVisual->vid) 135 return pDepth->depth; 136 } 137 return 0; 138} 139 140typedef struct _formatInit { 141 CARD32 format; 142 CARD8 depth; 143} FormatInitRec, *FormatInitPtr; 144 145static int 146addFormat (FormatInitRec formats[256], 147 int nformat, 148 CARD32 format, 149 CARD8 depth) 150{ 151 int n; 152 153 for (n = 0; n < nformat; n++) 154 if (formats[n].format == format && formats[n].depth == depth) 155 return nformat; 156 formats[nformat].format = format; 157 formats[nformat].depth = depth; 158 return ++nformat; 159} 160 161#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1)) 162 163PictFormatPtr 164PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp) 165{ 166 int nformats, f; 167 PictFormatPtr pFormats; 168 FormatInitRec formats[1024]; 169 CARD32 format; 170 CARD8 depth; 171 VisualPtr pVisual; 172 int v; 173 int bpp; 174 int type; 175 int r, g, b; 176 int d; 177 DepthPtr pDepth; 178 179 nformats = 0; 180 /* formats required by protocol */ 181 formats[nformats].format = PICT_a1; 182 formats[nformats].depth = 1; 183 nformats++; 184 formats[nformats].format = PICT_FORMAT(BitsPerPixel(8), 185 PICT_TYPE_A, 186 8, 0, 0, 0); 187 formats[nformats].depth = 8; 188 nformats++; 189 formats[nformats].format = PICT_FORMAT(BitsPerPixel(4), 190 PICT_TYPE_A, 191 4, 0, 0, 0); 192 formats[nformats].depth = 4; 193 nformats++; 194 formats[nformats].format = PICT_a8r8g8b8; 195 formats[nformats].depth = 32; 196 nformats++; 197 formats[nformats].format = PICT_x8r8g8b8; 198 formats[nformats].depth = 32; 199 nformats++; 200 formats[nformats].format = PICT_b8g8r8a8; 201 formats[nformats].depth = 32; 202 nformats++; 203 formats[nformats].format = PICT_b8g8r8x8; 204 formats[nformats].depth = 32; 205 nformats++; 206 207 /* now look through the depths and visuals adding other formats */ 208 for (v = 0; v < pScreen->numVisuals; v++) 209 { 210 pVisual = &pScreen->visuals[v]; 211 depth = visualDepth (pScreen, pVisual); 212 if (!depth) 213 continue; 214 bpp = BitsPerPixel (depth); 215 switch (pVisual->class) { 216 case DirectColor: 217 case TrueColor: 218 r = Ones (pVisual->redMask); 219 g = Ones (pVisual->greenMask); 220 b = Ones (pVisual->blueMask); 221 type = PICT_TYPE_OTHER; 222 /* 223 * Current rendering code supports only three direct formats, 224 * fields must be packed together at the bottom of the pixel 225 */ 226 if (pVisual->offsetBlue == 0 && 227 pVisual->offsetGreen == b && 228 pVisual->offsetRed == b + g) 229 { 230 type = PICT_TYPE_ARGB; 231 } 232 else if (pVisual->offsetRed == 0 && 233 pVisual->offsetGreen == r && 234 pVisual->offsetBlue == r + g) 235 { 236 type = PICT_TYPE_ABGR; 237 } 238 else if (pVisual->offsetRed == pVisual->offsetGreen - r && 239 pVisual->offsetGreen == pVisual->offsetBlue - g && 240 pVisual->offsetBlue == bpp - b) 241 { 242 type = PICT_TYPE_BGRA; 243 } 244 if (type != PICT_TYPE_OTHER) 245 { 246 format = PICT_FORMAT(bpp, type, 0, r, g, b); 247 nformats = addFormat (formats, nformats, format, depth); 248 } 249 break; 250 case StaticColor: 251 case PseudoColor: 252 format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v); 253 nformats = addFormat (formats, nformats, format, depth); 254 break; 255 case StaticGray: 256 case GrayScale: 257 format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v); 258 nformats = addFormat (formats, nformats, format, depth); 259 break; 260 } 261 } 262 /* 263 * Walk supported depths and add useful Direct formats 264 */ 265 for (d = 0; d < pScreen->numDepths; d++) 266 { 267 pDepth = &pScreen->allowedDepths[d]; 268 bpp = BitsPerPixel (pDepth->depth); 269 format = 0; 270 switch (bpp) { 271 case 16: 272 /* depth 12 formats */ 273 if (pDepth->depth >= 12) 274 { 275 nformats = addFormat (formats, nformats, 276 PICT_x4r4g4b4, pDepth->depth); 277 nformats = addFormat (formats, nformats, 278 PICT_x4b4g4r4, pDepth->depth); 279 } 280 /* depth 15 formats */ 281 if (pDepth->depth >= 15) 282 { 283 nformats = addFormat (formats, nformats, 284 PICT_x1r5g5b5, pDepth->depth); 285 nformats = addFormat (formats, nformats, 286 PICT_x1b5g5r5, pDepth->depth); 287 } 288 /* depth 16 formats */ 289 if (pDepth->depth >= 16) 290 { 291 nformats = addFormat (formats, nformats, 292 PICT_a1r5g5b5, pDepth->depth); 293 nformats = addFormat (formats, nformats, 294 PICT_a1b5g5r5, pDepth->depth); 295 nformats = addFormat (formats, nformats, 296 PICT_r5g6b5, pDepth->depth); 297 nformats = addFormat (formats, nformats, 298 PICT_b5g6r5, pDepth->depth); 299 nformats = addFormat (formats, nformats, 300 PICT_a4r4g4b4, pDepth->depth); 301 nformats = addFormat (formats, nformats, 302 PICT_a4b4g4r4, pDepth->depth); 303 } 304 break; 305 case 24: 306 if (pDepth->depth >= 24) 307 { 308 nformats = addFormat (formats, nformats, 309 PICT_r8g8b8, pDepth->depth); 310 nformats = addFormat (formats, nformats, 311 PICT_b8g8r8, pDepth->depth); 312 } 313 break; 314 case 32: 315 if (pDepth->depth >= 24) 316 { 317 nformats = addFormat (formats, nformats, 318 PICT_x8r8g8b8, pDepth->depth); 319 nformats = addFormat (formats, nformats, 320 PICT_x8b8g8r8, pDepth->depth); 321 } 322 if (pDepth->depth >= 30) 323 { 324 nformats = addFormat (formats, nformats, 325 PICT_a2r10g10b10, pDepth->depth); 326 nformats = addFormat (formats, nformats, 327 PICT_x2r10g10b10, pDepth->depth); 328 nformats = addFormat (formats, nformats, 329 PICT_a2b10g10r10, pDepth->depth); 330 nformats = addFormat (formats, nformats, 331 PICT_x2b10g10r10, pDepth->depth); 332 } 333 break; 334 } 335 } 336 337 338 pFormats = calloc(nformats, sizeof (PictFormatRec)); 339 if (!pFormats) 340 return 0; 341 for (f = 0; f < nformats; f++) 342 { 343 pFormats[f].id = FakeClientID (0); 344 pFormats[f].depth = formats[f].depth; 345 format = formats[f].format; 346 pFormats[f].format = format; 347 switch (PICT_FORMAT_TYPE(format)) { 348 case PICT_TYPE_ARGB: 349 pFormats[f].type = PictTypeDirect; 350 351 pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); 352 if (pFormats[f].direct.alphaMask) 353 pFormats[f].direct.alpha = (PICT_FORMAT_R(format) + 354 PICT_FORMAT_G(format) + 355 PICT_FORMAT_B(format)); 356 357 pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); 358 pFormats[f].direct.red = (PICT_FORMAT_G(format) + 359 PICT_FORMAT_B(format)); 360 361 pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); 362 pFormats[f].direct.green = PICT_FORMAT_B(format); 363 364 pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); 365 pFormats[f].direct.blue = 0; 366 break; 367 368 case PICT_TYPE_ABGR: 369 pFormats[f].type = PictTypeDirect; 370 371 pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); 372 if (pFormats[f].direct.alphaMask) 373 pFormats[f].direct.alpha = (PICT_FORMAT_B(format) + 374 PICT_FORMAT_G(format) + 375 PICT_FORMAT_R(format)); 376 377 pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); 378 pFormats[f].direct.blue = (PICT_FORMAT_G(format) + 379 PICT_FORMAT_R(format)); 380 381 pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); 382 pFormats[f].direct.green = PICT_FORMAT_R(format); 383 384 pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); 385 pFormats[f].direct.red = 0; 386 break; 387 388 case PICT_TYPE_BGRA: 389 pFormats[f].type = PictTypeDirect; 390 391 pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); 392 pFormats[f].direct.blue = (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format)); 393 394 pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); 395 pFormats[f].direct.green = (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format) - 396 PICT_FORMAT_G(format)); 397 398 pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); 399 pFormats[f].direct.red = (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format) - 400 PICT_FORMAT_G(format) - PICT_FORMAT_R(format)); 401 402 pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); 403 pFormats[f].direct.alpha = 0; 404 break; 405 406 case PICT_TYPE_A: 407 pFormats[f].type = PictTypeDirect; 408 409 pFormats[f].direct.alpha = 0; 410 pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); 411 412 /* remaining fields already set to zero */ 413 break; 414 415 case PICT_TYPE_COLOR: 416 case PICT_TYPE_GRAY: 417 pFormats[f].type = PictTypeIndexed; 418 pFormats[f].index.vid = pScreen->visuals[PICT_FORMAT_VIS(format)].vid; 419 break; 420 } 421 } 422 *nformatp = nformats; 423 return pFormats; 424} 425 426static VisualPtr 427PictureFindVisual (ScreenPtr pScreen, VisualID visual) 428{ 429 int i; 430 VisualPtr pVisual; 431 for (i = 0, pVisual = pScreen->visuals; 432 i < pScreen->numVisuals; 433 i++, pVisual++) 434 { 435 if (pVisual->vid == visual) 436 return pVisual; 437 } 438 return 0; 439} 440 441Bool 442PictureInitIndexedFormat(ScreenPtr pScreen, PictFormatPtr format) 443{ 444 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 445 446 if (format->type != PictTypeIndexed || format->index.pColormap) 447 return TRUE; 448 449 if (format->index.vid == pScreen->rootVisual) { 450 dixLookupResourceByType((pointer *)&format->index.pColormap, 451 pScreen->defColormap, RT_COLORMAP, 452 serverClient, DixGetAttrAccess); 453 } else { 454 VisualPtr pVisual = PictureFindVisual(pScreen, format->index.vid); 455 if (CreateColormap(FakeClientID (0), pScreen, pVisual, 456 &format->index.pColormap, AllocNone, 0) 457 != Success) 458 return FALSE; 459 } 460 if (!ps->InitIndexed(pScreen, format)) 461 return FALSE; 462 return TRUE; 463} 464 465static Bool 466PictureInitIndexedFormats (ScreenPtr pScreen) 467{ 468 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 469 PictFormatPtr format; 470 int nformat; 471 472 if (!ps) 473 return FALSE; 474 format = ps->formats; 475 nformat = ps->nformats; 476 while (nformat--) 477 if (!PictureInitIndexedFormat(pScreen, format++)) 478 return FALSE; 479 return TRUE; 480} 481 482Bool 483PictureFinishInit (void) 484{ 485 int s; 486 487 for (s = 0; s < screenInfo.numScreens; s++) 488 { 489 if (!PictureInitIndexedFormats (screenInfo.screens[s])) 490 return FALSE; 491 (void) AnimCurInit (screenInfo.screens[s]); 492 } 493 494 return TRUE; 495} 496 497Bool 498PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel) 499{ 500 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 501 502 if (!ps) 503 return FALSE; 504 ps->subpixel = subpixel; 505 return TRUE; 506 507} 508 509int 510PictureGetSubpixelOrder (ScreenPtr pScreen) 511{ 512 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 513 514 if (!ps) 515 return SubPixelUnknown; 516 return ps->subpixel; 517} 518 519PictFormatPtr 520PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual) 521{ 522 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 523 PictFormatPtr format; 524 int nformat; 525 int type; 526 527 if (!ps) 528 return 0; 529 format = ps->formats; 530 nformat = ps->nformats; 531 switch (pVisual->class) { 532 case StaticGray: 533 case GrayScale: 534 case StaticColor: 535 case PseudoColor: 536 type = PictTypeIndexed; 537 break; 538 case TrueColor: 539 case DirectColor: 540 type = PictTypeDirect; 541 break; 542 default: 543 return 0; 544 } 545 while (nformat--) 546 { 547 if (format->depth == depth && format->type == type) 548 { 549 if (type == PictTypeIndexed) 550 { 551 if (format->index.vid == pVisual->vid) 552 return format; 553 } 554 else 555 { 556 if (format->direct.redMask << format->direct.red == 557 pVisual->redMask && 558 format->direct.greenMask << format->direct.green == 559 pVisual->greenMask && 560 format->direct.blueMask << format->direct.blue == 561 pVisual->blueMask) 562 { 563 return format; 564 } 565 } 566 } 567 format++; 568 } 569 return 0; 570} 571 572PictFormatPtr 573PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f) 574{ 575 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 576 PictFormatPtr format; 577 int nformat; 578 579 if (!ps) 580 return 0; 581 format = ps->formats; 582 nformat = ps->nformats; 583 while (nformat--) 584 { 585 if (format->depth == depth && format->format == (f & 0xffffff)) 586 return format; 587 format++; 588 } 589 return 0; 590} 591 592int 593PictureParseCmapPolicy (const char *name) 594{ 595 if ( strcmp (name, "default" ) == 0) 596 return PictureCmapPolicyDefault; 597 else if ( strcmp (name, "mono" ) == 0) 598 return PictureCmapPolicyMono; 599 else if ( strcmp (name, "gray" ) == 0) 600 return PictureCmapPolicyGray; 601 else if ( strcmp (name, "color" ) == 0) 602 return PictureCmapPolicyColor; 603 else if ( strcmp (name, "all" ) == 0) 604 return PictureCmapPolicyAll; 605 else 606 return PictureCmapPolicyInvalid; 607} 608 609Bool 610PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) 611{ 612 PictureScreenPtr ps; 613 int n; 614 CARD32 type, a, r, g, b; 615 616 if (PictureGeneration != serverGeneration) 617 { 618 PictureType = CreateNewResourceType (FreePicture, "PICTURE"); 619 if (!PictureType) 620 return FALSE; 621 PictFormatType = CreateNewResourceType (FreePictFormat, "PICTFORMAT"); 622 if (!PictFormatType) 623 return FALSE; 624 GlyphSetType = CreateNewResourceType (FreeGlyphSet, "GLYPHSET"); 625 if (!GlyphSetType) 626 return FALSE; 627 PictureGeneration = serverGeneration; 628 } 629 if (!dixRegisterPrivateKey(&PictureScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 630 return FALSE; 631 632 if (!dixRegisterPrivateKey(&PictureWindowPrivateKeyRec, PRIVATE_WINDOW, 0)) 633 return FALSE; 634 635 if (!formats) 636 { 637 formats = PictureCreateDefaultFormats (pScreen, &nformats); 638 if (!formats) 639 return FALSE; 640 } 641 for (n = 0; n < nformats; n++) 642 { 643 if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n))) 644 { 645 free(formats); 646 return FALSE; 647 } 648 if (formats[n].type == PictTypeIndexed) 649 { 650 VisualPtr pVisual = PictureFindVisual (pScreen, formats[n].index.vid); 651 if ((pVisual->class | DynamicClass) == PseudoColor) 652 type = PICT_TYPE_COLOR; 653 else 654 type = PICT_TYPE_GRAY; 655 a = r = g = b = 0; 656 } 657 else 658 { 659 if ((formats[n].direct.redMask| 660 formats[n].direct.blueMask| 661 formats[n].direct.greenMask) == 0) 662 type = PICT_TYPE_A; 663 else if (formats[n].direct.red > formats[n].direct.blue) 664 type = PICT_TYPE_ARGB; 665 else if (formats[n].direct.red == 0) 666 type = PICT_TYPE_ABGR; 667 else 668 type = PICT_TYPE_BGRA; 669 a = Ones (formats[n].direct.alphaMask); 670 r = Ones (formats[n].direct.redMask); 671 g = Ones (formats[n].direct.greenMask); 672 b = Ones (formats[n].direct.blueMask); 673 } 674 formats[n].format = PICT_FORMAT(0,type,a,r,g,b); 675 } 676 ps = (PictureScreenPtr) malloc(sizeof (PictureScreenRec)); 677 if (!ps) 678 { 679 free(formats); 680 return FALSE; 681 } 682 SetPictureScreen(pScreen, ps); 683 684 ps->formats = formats; 685 ps->fallback = formats; 686 ps->nformats = nformats; 687 688 ps->filters = 0; 689 ps->nfilters = 0; 690 ps->filterAliases = 0; 691 ps->nfilterAliases = 0; 692 693 ps->subpixel = SubPixelUnknown; 694 695 ps->CloseScreen = pScreen->CloseScreen; 696 ps->DestroyWindow = pScreen->DestroyWindow; 697 ps->StoreColors = pScreen->StoreColors; 698 pScreen->DestroyWindow = PictureDestroyWindow; 699 pScreen->CloseScreen = PictureCloseScreen; 700 pScreen->StoreColors = PictureStoreColors; 701 702 if (!PictureSetDefaultFilters (pScreen)) 703 { 704 PictureResetFilters (pScreen); 705 SetPictureScreen(pScreen, 0); 706 free(formats); 707 free(ps); 708 return FALSE; 709 } 710 711 return TRUE; 712} 713 714void 715SetPictureToDefaults (PicturePtr pPicture) 716{ 717 pPicture->refcnt = 1; 718 pPicture->repeat = 0; 719 pPicture->graphicsExposures = FALSE; 720 pPicture->subWindowMode = ClipByChildren; 721 pPicture->polyEdge = PolyEdgeSharp; 722 pPicture->polyMode = PolyModePrecise; 723 pPicture->freeCompClip = FALSE; 724 pPicture->clientClipType = CT_NONE; 725 pPicture->componentAlpha = FALSE; 726 pPicture->repeatType = RepeatNone; 727 728 pPicture->alphaMap = 0; 729 pPicture->alphaOrigin.x = 0; 730 pPicture->alphaOrigin.y = 0; 731 732 pPicture->clipOrigin.x = 0; 733 pPicture->clipOrigin.y = 0; 734 pPicture->clientClip = 0; 735 736 pPicture->transform = 0; 737 738 pPicture->dither = None; 739 pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE); 740 pPicture->filter_params = 0; 741 pPicture->filter_nparams = 0; 742 743 pPicture->serialNumber = GC_CHANGE_SERIAL_BIT; 744 pPicture->stateChanges = (1 << (CPLastBit+1)) - 1; 745 pPicture->pSourcePict = 0; 746} 747 748PicturePtr 749CreatePicture (Picture pid, 750 DrawablePtr pDrawable, 751 PictFormatPtr pFormat, 752 Mask vmask, 753 XID *vlist, 754 ClientPtr client, 755 int *error) 756{ 757 PicturePtr pPicture; 758 PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen); 759 760 pPicture = dixAllocateObjectWithPrivates(PictureRec, PRIVATE_PICTURE); 761 if (!pPicture) 762 { 763 *error = BadAlloc; 764 return 0; 765 } 766 767 pPicture->id = pid; 768 pPicture->pDrawable = pDrawable; 769 pPicture->pFormat = pFormat; 770 pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24); 771 772 /* security creation/labeling check */ 773 *error = XaceHook(XACE_RESOURCE_ACCESS, client, pid, PictureType, pPicture, 774 RT_PIXMAP, pDrawable, DixCreateAccess|DixSetAttrAccess); 775 if (*error != Success) 776 goto out; 777 778 if (pDrawable->type == DRAWABLE_PIXMAP) 779 { 780 ++((PixmapPtr)pDrawable)->refcnt; 781 pPicture->pNext = 0; 782 } 783 else 784 { 785 pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable)); 786 SetPictureWindow(((WindowPtr) pDrawable), pPicture); 787 } 788 789 SetPictureToDefaults (pPicture); 790 791 if (vmask) 792 *error = ChangePicture (pPicture, vmask, vlist, 0, client); 793 else 794 *error = Success; 795 if (*error == Success) 796 *error = (*ps->CreatePicture) (pPicture); 797out: 798 if (*error != Success) 799 { 800 FreePicture (pPicture, (XID) 0); 801 pPicture = 0; 802 } 803 return pPicture; 804} 805 806static CARD32 xRenderColorToCard32(xRenderColor c) 807{ 808 return 809 (c.alpha >> 8 << 24) | 810 (c.red >> 8 << 16) | 811 (c.green & 0xff00) | 812 (c.blue >> 8); 813} 814 815static unsigned int premultiply(unsigned int x) 816{ 817 unsigned int a = x >> 24; 818 unsigned int t = (x & 0xff00ff) * a + 0x800080; 819 t = (t + ((t >> 8) & 0xff00ff)) >> 8; 820 t &= 0xff00ff; 821 822 x = ((x >> 8) & 0xff) * a + 0x80; 823 x = (x + ((x >> 8) & 0xff)); 824 x &= 0xff00; 825 x |= t | (a << 24); 826 return x; 827} 828 829static unsigned int INTERPOLATE_PIXEL_256(unsigned int x, unsigned int a, 830 unsigned int y, unsigned int b) 831{ 832 CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; 833 t >>= 8; 834 t &= 0xff00ff; 835 836 x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; 837 x &= 0xff00ff00; 838 x |= t; 839 return x; 840} 841 842CARD32 843PictureGradientColor (PictGradientStopPtr stop1, 844 PictGradientStopPtr stop2, 845 CARD32 x) 846{ 847 CARD32 current_color, next_color; 848 int dist, idist; 849 850 current_color = xRenderColorToCard32 (stop1->color); 851 next_color = xRenderColorToCard32 (stop2->color); 852 853 dist = (int) (256 * (x - stop1->x) / (stop2->x - stop1->x)); 854 idist = 256 - dist; 855 856 return premultiply (INTERPOLATE_PIXEL_256 (current_color, idist, 857 next_color, dist)); 858} 859 860static void initGradient(SourcePictPtr pGradient, int stopCount, 861 xFixed *stopPoints, xRenderColor *stopColors, int *error) 862{ 863 int i; 864 xFixed dpos; 865 866 if (stopCount <= 0) { 867 *error = BadValue; 868 return; 869 } 870 871 dpos = -1; 872 for (i = 0; i < stopCount; ++i) { 873 if (stopPoints[i] < dpos || stopPoints[i] > (1<<16)) { 874 *error = BadValue; 875 return; 876 } 877 dpos = stopPoints[i]; 878 } 879 880 pGradient->gradient.stops = malloc(stopCount*sizeof(PictGradientStop)); 881 if (!pGradient->gradient.stops) { 882 *error = BadAlloc; 883 return; 884 } 885 886 pGradient->gradient.nstops = stopCount; 887 888 for (i = 0; i < stopCount; ++i) { 889 pGradient->gradient.stops[i].x = stopPoints[i]; 890 pGradient->gradient.stops[i].color = stopColors[i]; 891 } 892 893 pGradient->gradient.class = SourcePictClassUnknown; 894 pGradient->gradient.stopRange = 0xffff; 895 pGradient->gradient.colorTable = NULL; 896 pGradient->gradient.colorTableSize = 0; 897} 898 899static PicturePtr createSourcePicture(void) 900{ 901 PicturePtr pPicture; 902 pPicture = dixAllocateObjectWithPrivates(PictureRec, PRIVATE_PICTURE); 903 pPicture->pDrawable = 0; 904 pPicture->pFormat = 0; 905 pPicture->pNext = 0; 906 pPicture->format = PICT_a8r8g8b8; 907 908 SetPictureToDefaults(pPicture); 909 return pPicture; 910} 911 912PicturePtr 913CreateSolidPicture (Picture pid, xRenderColor *color, int *error) 914{ 915 PicturePtr pPicture; 916 pPicture = createSourcePicture(); 917 if (!pPicture) { 918 *error = BadAlloc; 919 return 0; 920 } 921 922 pPicture->id = pid; 923 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictSolidFill)); 924 if (!pPicture->pSourcePict) { 925 *error = BadAlloc; 926 free(pPicture); 927 return 0; 928 } 929 pPicture->pSourcePict->type = SourcePictTypeSolidFill; 930 pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color); 931 return pPicture; 932} 933 934PicturePtr 935CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2, 936 int nStops, xFixed *stops, xRenderColor *colors, int *error) 937{ 938 PicturePtr pPicture; 939 940 if (nStops < 2) { 941 *error = BadValue; 942 return 0; 943 } 944 945 pPicture = createSourcePicture(); 946 if (!pPicture) { 947 *error = BadAlloc; 948 return 0; 949 } 950 951 pPicture->id = pid; 952 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictLinearGradient)); 953 if (!pPicture->pSourcePict) { 954 *error = BadAlloc; 955 free(pPicture); 956 return 0; 957 } 958 959 pPicture->pSourcePict->linear.type = SourcePictTypeLinear; 960 pPicture->pSourcePict->linear.p1 = *p1; 961 pPicture->pSourcePict->linear.p2 = *p2; 962 963 initGradient(pPicture->pSourcePict, nStops, stops, colors, error); 964 if (*error) { 965 free(pPicture); 966 return 0; 967 } 968 return pPicture; 969} 970 971#define FixedToDouble(x) ((x)/65536.) 972 973PicturePtr 974CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer, 975 xFixed innerRadius, xFixed outerRadius, 976 int nStops, xFixed *stops, xRenderColor *colors, int *error) 977{ 978 PicturePtr pPicture; 979 PictRadialGradient *radial; 980 981 if (nStops < 2) { 982 *error = BadValue; 983 return 0; 984 } 985 986 pPicture = createSourcePicture(); 987 if (!pPicture) { 988 *error = BadAlloc; 989 return 0; 990 } 991 992 pPicture->id = pid; 993 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictRadialGradient)); 994 if (!pPicture->pSourcePict) { 995 *error = BadAlloc; 996 free(pPicture); 997 return 0; 998 } 999 radial = &pPicture->pSourcePict->radial; 1000 1001 radial->type = SourcePictTypeRadial; 1002 radial->c1.x = inner->x; 1003 radial->c1.y = inner->y; 1004 radial->c1.radius = innerRadius; 1005 radial->c2.x = outer->x; 1006 radial->c2.y = outer->y; 1007 radial->c2.radius = outerRadius; 1008 radial->cdx = (radial->c2.x - radial->c1.x) / 65536.; 1009 radial->cdy = (radial->c2.y - radial->c1.y) / 65536.; 1010 radial->dr = (radial->c2.radius - radial->c1.radius) / 65536.; 1011 radial->A = ( radial->cdx * radial->cdx 1012 + radial->cdy * radial->cdy 1013 - radial->dr * radial->dr); 1014 1015 initGradient(pPicture->pSourcePict, nStops, stops, colors, error); 1016 if (*error) { 1017 free(pPicture); 1018 return 0; 1019 } 1020 return pPicture; 1021} 1022 1023PicturePtr 1024CreateConicalGradientPicture (Picture pid, xPointFixed *center, xFixed angle, 1025 int nStops, xFixed *stops, xRenderColor *colors, int *error) 1026{ 1027 PicturePtr pPicture; 1028 1029 if (nStops < 2) { 1030 *error = BadValue; 1031 return 0; 1032 } 1033 1034 pPicture = createSourcePicture(); 1035 if (!pPicture) { 1036 *error = BadAlloc; 1037 return 0; 1038 } 1039 1040 pPicture->id = pid; 1041 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictConicalGradient)); 1042 if (!pPicture->pSourcePict) { 1043 *error = BadAlloc; 1044 free(pPicture); 1045 return 0; 1046 } 1047 1048 pPicture->pSourcePict->conical.type = SourcePictTypeConical; 1049 pPicture->pSourcePict->conical.center = *center; 1050 pPicture->pSourcePict->conical.angle = angle; 1051 1052 initGradient(pPicture->pSourcePict, nStops, stops, colors, error); 1053 if (*error) { 1054 free(pPicture); 1055 return 0; 1056 } 1057 return pPicture; 1058} 1059 1060#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val) 1061 1062#define NEXT_PTR(_type) ((_type) ulist++->ptr) 1063 1064int 1065ChangePicture (PicturePtr pPicture, 1066 Mask vmask, 1067 XID *vlist, 1068 DevUnion *ulist, 1069 ClientPtr client) 1070{ 1071 ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0; 1072 PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0; 1073 BITS32 index2; 1074 int error = 0; 1075 BITS32 maskQ; 1076 1077 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; 1078 maskQ = vmask; 1079 while (vmask && !error) 1080 { 1081 index2 = (BITS32) lowbit (vmask); 1082 vmask &= ~index2; 1083 pPicture->stateChanges |= index2; 1084 switch (index2) 1085 { 1086 case CPRepeat: 1087 { 1088 unsigned int newr; 1089 newr = NEXT_VAL(unsigned int); 1090 if (newr <= RepeatReflect) 1091 { 1092 pPicture->repeat = (newr != RepeatNone); 1093 pPicture->repeatType = newr; 1094 } 1095 else 1096 { 1097 client->errorValue = newr; 1098 error = BadValue; 1099 } 1100 } 1101 break; 1102 case CPAlphaMap: 1103 { 1104 PicturePtr pAlpha; 1105 1106 if (vlist) 1107 { 1108 Picture pid = NEXT_VAL(Picture); 1109 1110 if (pid == None) 1111 pAlpha = 0; 1112 else 1113 { 1114 error = dixLookupResourceByType((pointer *)&pAlpha, pid, 1115 PictureType, client, 1116 DixReadAccess); 1117 if (error != Success) 1118 { 1119 client->errorValue = pid; 1120 break; 1121 } 1122 if (pAlpha->pDrawable == NULL || 1123 pAlpha->pDrawable->type != DRAWABLE_PIXMAP) 1124 { 1125 client->errorValue = pid; 1126 error = BadMatch; 1127 break; 1128 } 1129 } 1130 } 1131 else 1132 pAlpha = NEXT_PTR(PicturePtr); 1133 if (!error) 1134 { 1135 if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP) 1136 pAlpha->refcnt++; 1137 if (pPicture->alphaMap) 1138 FreePicture ((pointer) pPicture->alphaMap, (XID) 0); 1139 pPicture->alphaMap = pAlpha; 1140 } 1141 } 1142 break; 1143 case CPAlphaXOrigin: 1144 pPicture->alphaOrigin.x = NEXT_VAL(INT16); 1145 break; 1146 case CPAlphaYOrigin: 1147 pPicture->alphaOrigin.y = NEXT_VAL(INT16); 1148 break; 1149 case CPClipXOrigin: 1150 pPicture->clipOrigin.x = NEXT_VAL(INT16); 1151 break; 1152 case CPClipYOrigin: 1153 pPicture->clipOrigin.y = NEXT_VAL(INT16); 1154 break; 1155 case CPClipMask: 1156 { 1157 Pixmap pid; 1158 PixmapPtr pPixmap; 1159 int clipType; 1160 if (!pScreen) 1161 return BadDrawable; 1162 1163 if (vlist) 1164 { 1165 pid = NEXT_VAL(Pixmap); 1166 if (pid == None) 1167 { 1168 clipType = CT_NONE; 1169 pPixmap = NullPixmap; 1170 } 1171 else 1172 { 1173 clipType = CT_PIXMAP; 1174 error = dixLookupResourceByType((pointer *)&pPixmap, pid, 1175 RT_PIXMAP, client, 1176 DixReadAccess); 1177 if (error != Success) 1178 { 1179 client->errorValue = pid; 1180 break; 1181 } 1182 } 1183 } 1184 else 1185 { 1186 pPixmap = NEXT_PTR(PixmapPtr); 1187 if (pPixmap) 1188 clipType = CT_PIXMAP; 1189 else 1190 clipType = CT_NONE; 1191 } 1192 1193 if (pPixmap) 1194 { 1195 if ((pPixmap->drawable.depth != 1) || 1196 (pPixmap->drawable.pScreen != pScreen)) 1197 { 1198 error = BadMatch; 1199 break; 1200 } 1201 else 1202 { 1203 clipType = CT_PIXMAP; 1204 pPixmap->refcnt++; 1205 } 1206 } 1207 error = (*ps->ChangePictureClip)(pPicture, clipType, 1208 (pointer)pPixmap, 0); 1209 break; 1210 } 1211 case CPGraphicsExposure: 1212 { 1213 unsigned int newe; 1214 newe = NEXT_VAL(unsigned int); 1215 if (newe <= xTrue) 1216 pPicture->graphicsExposures = newe; 1217 else 1218 { 1219 client->errorValue = newe; 1220 error = BadValue; 1221 } 1222 } 1223 break; 1224 case CPSubwindowMode: 1225 { 1226 unsigned int news; 1227 news = NEXT_VAL(unsigned int); 1228 if (news == ClipByChildren || news == IncludeInferiors) 1229 pPicture->subWindowMode = news; 1230 else 1231 { 1232 client->errorValue = news; 1233 error = BadValue; 1234 } 1235 } 1236 break; 1237 case CPPolyEdge: 1238 { 1239 unsigned int newe; 1240 newe = NEXT_VAL(unsigned int); 1241 if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth) 1242 pPicture->polyEdge = newe; 1243 else 1244 { 1245 client->errorValue = newe; 1246 error = BadValue; 1247 } 1248 } 1249 break; 1250 case CPPolyMode: 1251 { 1252 unsigned int newm; 1253 newm = NEXT_VAL(unsigned int); 1254 if (newm == PolyModePrecise || newm == PolyModeImprecise) 1255 pPicture->polyMode = newm; 1256 else 1257 { 1258 client->errorValue = newm; 1259 error = BadValue; 1260 } 1261 } 1262 break; 1263 case CPDither: 1264 pPicture->dither = NEXT_VAL(Atom); 1265 break; 1266 case CPComponentAlpha: 1267 { 1268 unsigned int newca; 1269 1270 newca = NEXT_VAL (unsigned int); 1271 if (newca <= xTrue) 1272 pPicture->componentAlpha = newca; 1273 else 1274 { 1275 client->errorValue = newca; 1276 error = BadValue; 1277 } 1278 } 1279 break; 1280 default: 1281 client->errorValue = maskQ; 1282 error = BadValue; 1283 break; 1284 } 1285 } 1286 if (ps) 1287 (*ps->ChangePicture) (pPicture, maskQ); 1288 return error; 1289} 1290 1291int 1292SetPictureClipRects (PicturePtr pPicture, 1293 int xOrigin, 1294 int yOrigin, 1295 int nRect, 1296 xRectangle *rects) 1297{ 1298 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 1299 PictureScreenPtr ps = GetPictureScreen(pScreen); 1300 RegionPtr clientClip; 1301 int result; 1302 1303 clientClip = RegionFromRects(nRect, rects, CT_UNSORTED); 1304 if (!clientClip) 1305 return BadAlloc; 1306 result =(*ps->ChangePictureClip) (pPicture, CT_REGION, 1307 (pointer) clientClip, 0); 1308 if (result == Success) 1309 { 1310 pPicture->clipOrigin.x = xOrigin; 1311 pPicture->clipOrigin.y = yOrigin; 1312 pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; 1313 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; 1314 } 1315 return result; 1316} 1317 1318int 1319SetPictureClipRegion (PicturePtr pPicture, 1320 int xOrigin, 1321 int yOrigin, 1322 RegionPtr pRegion) 1323{ 1324 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 1325 PictureScreenPtr ps = GetPictureScreen(pScreen); 1326 RegionPtr clientClip; 1327 int result; 1328 int type; 1329 1330 if (pRegion) 1331 { 1332 type = CT_REGION; 1333 clientClip = RegionCreate(RegionExtents(pRegion), 1334 RegionNumRects(pRegion)); 1335 if (!clientClip) 1336 return BadAlloc; 1337 if (!RegionCopy(clientClip, pRegion)) 1338 { 1339 RegionDestroy(clientClip); 1340 return BadAlloc; 1341 } 1342 } 1343 else 1344 { 1345 type = CT_NONE; 1346 clientClip = 0; 1347 } 1348 1349 result =(*ps->ChangePictureClip) (pPicture, type, 1350 (pointer) clientClip, 0); 1351 if (result == Success) 1352 { 1353 pPicture->clipOrigin.x = xOrigin; 1354 pPicture->clipOrigin.y = yOrigin; 1355 pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; 1356 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; 1357 } 1358 return result; 1359} 1360 1361static Bool 1362transformIsIdentity(PictTransform *t) 1363{ 1364 return ((t->matrix[0][0] == t->matrix[1][1]) && 1365 (t->matrix[0][0] == t->matrix[2][2]) && 1366 (t->matrix[0][0] != 0) && 1367 (t->matrix[0][1] == 0) && 1368 (t->matrix[0][2] == 0) && 1369 (t->matrix[1][0] == 0) && 1370 (t->matrix[1][2] == 0) && 1371 (t->matrix[2][0] == 0) && 1372 (t->matrix[2][1] == 0)); 1373} 1374 1375int 1376SetPictureTransform (PicturePtr pPicture, 1377 PictTransform *transform) 1378{ 1379 if (transform && transformIsIdentity (transform)) 1380 transform = 0; 1381 1382 if (transform) 1383 { 1384 if (!pPicture->transform) 1385 { 1386 pPicture->transform = (PictTransform *) malloc(sizeof (PictTransform)); 1387 if (!pPicture->transform) 1388 return BadAlloc; 1389 } 1390 *pPicture->transform = *transform; 1391 } 1392 else 1393 { 1394 if (pPicture->transform) 1395 { 1396 free(pPicture->transform); 1397 pPicture->transform = 0; 1398 } 1399 } 1400 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; 1401 1402 if (pPicture->pDrawable != NULL) { 1403 int result; 1404 PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); 1405 1406 result = (*ps->ChangePictureTransform) (pPicture, transform); 1407 1408 return result; 1409 } 1410 1411 return Success; 1412} 1413 1414void 1415CopyPicture (PicturePtr pSrc, 1416 Mask mask, 1417 PicturePtr pDst) 1418{ 1419 PictureScreenPtr ps = GetPictureScreen(pSrc->pDrawable->pScreen); 1420 Mask origMask = mask; 1421 1422 pDst->serialNumber |= GC_CHANGE_SERIAL_BIT; 1423 pDst->stateChanges |= mask; 1424 1425 while (mask) { 1426 Mask bit = lowbit(mask); 1427 1428 switch (bit) 1429 { 1430 case CPRepeat: 1431 pDst->repeat = pSrc->repeat; 1432 pDst->repeatType = pSrc->repeatType; 1433 break; 1434 case CPAlphaMap: 1435 if (pSrc->alphaMap && pSrc->alphaMap->pDrawable->type == DRAWABLE_PIXMAP) 1436 pSrc->alphaMap->refcnt++; 1437 if (pDst->alphaMap) 1438 FreePicture ((pointer) pDst->alphaMap, (XID) 0); 1439 pDst->alphaMap = pSrc->alphaMap; 1440 break; 1441 case CPAlphaXOrigin: 1442 pDst->alphaOrigin.x = pSrc->alphaOrigin.x; 1443 break; 1444 case CPAlphaYOrigin: 1445 pDst->alphaOrigin.y = pSrc->alphaOrigin.y; 1446 break; 1447 case CPClipXOrigin: 1448 pDst->clipOrigin.x = pSrc->clipOrigin.x; 1449 break; 1450 case CPClipYOrigin: 1451 pDst->clipOrigin.y = pSrc->clipOrigin.y; 1452 break; 1453 case CPClipMask: 1454 switch (pSrc->clientClipType) { 1455 case CT_NONE: 1456 (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0); 1457 break; 1458 case CT_REGION: 1459 if (!pSrc->clientClip) { 1460 (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0); 1461 } else { 1462 RegionPtr clientClip; 1463 RegionPtr srcClientClip = (RegionPtr)pSrc->clientClip; 1464 1465 clientClip = RegionCreate( 1466 RegionExtents(srcClientClip), 1467 RegionNumRects(srcClientClip)); 1468 (*ps->ChangePictureClip)(pDst, CT_REGION, clientClip, 0); 1469 } 1470 break; 1471 default: 1472 /* XXX: CT_PIXMAP unimplemented */ 1473 break; 1474 } 1475 break; 1476 case CPGraphicsExposure: 1477 pDst->graphicsExposures = pSrc->graphicsExposures; 1478 break; 1479 case CPPolyEdge: 1480 pDst->polyEdge = pSrc->polyEdge; 1481 break; 1482 case CPPolyMode: 1483 pDst->polyMode = pSrc->polyMode; 1484 break; 1485 case CPDither: 1486 pDst->dither = pSrc->dither; 1487 break; 1488 case CPComponentAlpha: 1489 pDst->componentAlpha = pSrc->componentAlpha; 1490 break; 1491 } 1492 mask &= ~bit; 1493 } 1494 1495 (*ps->ChangePicture)(pDst, origMask); 1496} 1497 1498static void 1499ValidateOnePicture (PicturePtr pPicture) 1500{ 1501 if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber) 1502 { 1503 PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); 1504 1505 (*ps->ValidatePicture) (pPicture, pPicture->stateChanges); 1506 pPicture->stateChanges = 0; 1507 pPicture->serialNumber = pPicture->pDrawable->serialNumber; 1508 } 1509} 1510 1511void 1512ValidatePicture(PicturePtr pPicture) 1513{ 1514 ValidateOnePicture (pPicture); 1515 if (pPicture->alphaMap) 1516 ValidateOnePicture (pPicture->alphaMap); 1517} 1518 1519int 1520FreePicture (pointer value, 1521 XID pid) 1522{ 1523 PicturePtr pPicture = (PicturePtr) value; 1524 1525 if (--pPicture->refcnt == 0) 1526 { 1527 free(pPicture->transform); 1528 1529 if (pPicture->pSourcePict) 1530 { 1531 if (pPicture->pSourcePict->type != SourcePictTypeSolidFill) 1532 free(pPicture->pSourcePict->linear.stops); 1533 1534 free(pPicture->pSourcePict); 1535 } 1536 1537 if (pPicture->pDrawable) 1538 { 1539 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 1540 PictureScreenPtr ps = GetPictureScreen(pScreen); 1541 1542 if (pPicture->alphaMap) 1543 FreePicture ((pointer) pPicture->alphaMap, (XID) 0); 1544 (*ps->DestroyPicture) (pPicture); 1545 (*ps->DestroyPictureClip) (pPicture); 1546 if (pPicture->pDrawable->type == DRAWABLE_WINDOW) 1547 { 1548 WindowPtr pWindow = (WindowPtr) pPicture->pDrawable; 1549 PicturePtr *pPrev; 1550 1551 for (pPrev = (PicturePtr *)dixLookupPrivateAddr 1552 (&pWindow->devPrivates, PictureWindowPrivateKey); 1553 *pPrev; 1554 pPrev = &(*pPrev)->pNext) 1555 { 1556 if (*pPrev == pPicture) 1557 { 1558 *pPrev = pPicture->pNext; 1559 break; 1560 } 1561 } 1562 } 1563 else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP) 1564 { 1565 (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable); 1566 } 1567 } 1568 dixFreeObjectWithPrivates(pPicture, PRIVATE_PICTURE); 1569 } 1570 return Success; 1571} 1572 1573int 1574FreePictFormat (pointer pPictFormat, 1575 XID pid) 1576{ 1577 return Success; 1578} 1579 1580/** 1581 * ReduceCompositeOp is used to choose simpler ops for cases where alpha 1582 * channels are always one and so math on the alpha channel per pixel becomes 1583 * unnecessary. It may also avoid destination reads sometimes if apps aren't 1584 * being careful to avoid these cases. 1585 */ 1586static CARD8 1587ReduceCompositeOp (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, 1588 INT16 xSrc, INT16 ySrc, CARD16 width, CARD16 height) 1589{ 1590 Bool no_src_alpha, no_dst_alpha; 1591 1592 /* Sampling off the edge of a RepeatNone picture introduces alpha 1593 * even if the picture itself doesn't have alpha. We don't try to 1594 * detect every case where we don't sample off the edge, just the 1595 * simplest case where there is no transform on the source 1596 * picture. 1597 */ 1598 no_src_alpha = PICT_FORMAT_COLOR(pSrc->format) && 1599 PICT_FORMAT_A(pSrc->format) == 0 && 1600 (pSrc->repeatType != RepeatNone || 1601 (!pSrc->transform && 1602 xSrc >= 0 && ySrc >= 0 && 1603 xSrc + width <= pSrc->pDrawable->width && 1604 ySrc + height <= pSrc->pDrawable->height)) && 1605 pSrc->alphaMap == NULL && 1606 pMask == NULL; 1607 no_dst_alpha = PICT_FORMAT_COLOR(pDst->format) && 1608 PICT_FORMAT_A(pDst->format) == 0 && 1609 pDst->alphaMap == NULL; 1610 1611 /* TODO, maybe: Conjoint and Disjoint op reductions? */ 1612 1613 /* Deal with simplifications where the source alpha is always 1. */ 1614 if (no_src_alpha) 1615 { 1616 switch (op) { 1617 case PictOpOver: 1618 op = PictOpSrc; 1619 break; 1620 case PictOpInReverse: 1621 op = PictOpDst; 1622 break; 1623 case PictOpOutReverse: 1624 op = PictOpClear; 1625 break; 1626 case PictOpAtop: 1627 op = PictOpIn; 1628 break; 1629 case PictOpAtopReverse: 1630 op = PictOpOverReverse; 1631 break; 1632 case PictOpXor: 1633 op = PictOpOut; 1634 break; 1635 default: 1636 break; 1637 } 1638 } 1639 1640 /* Deal with simplifications when the destination alpha is always 1 */ 1641 if (no_dst_alpha) 1642 { 1643 switch (op) { 1644 case PictOpOverReverse: 1645 op = PictOpDst; 1646 break; 1647 case PictOpIn: 1648 op = PictOpSrc; 1649 break; 1650 case PictOpOut: 1651 op = PictOpClear; 1652 break; 1653 case PictOpAtop: 1654 op = PictOpOver; 1655 break; 1656 case PictOpXor: 1657 op = PictOpOutReverse; 1658 break; 1659 default: 1660 break; 1661 } 1662 } 1663 1664 /* Reduce some con/disjoint ops to the basic names. */ 1665 switch (op) { 1666 case PictOpDisjointClear: 1667 case PictOpConjointClear: 1668 op = PictOpClear; 1669 break; 1670 case PictOpDisjointSrc: 1671 case PictOpConjointSrc: 1672 op = PictOpSrc; 1673 break; 1674 case PictOpDisjointDst: 1675 case PictOpConjointDst: 1676 op = PictOpDst; 1677 break; 1678 default: 1679 break; 1680 } 1681 1682 return op; 1683} 1684 1685void 1686CompositePicture (CARD8 op, 1687 PicturePtr pSrc, 1688 PicturePtr pMask, 1689 PicturePtr pDst, 1690 INT16 xSrc, 1691 INT16 ySrc, 1692 INT16 xMask, 1693 INT16 yMask, 1694 INT16 xDst, 1695 INT16 yDst, 1696 CARD16 width, 1697 CARD16 height) 1698{ 1699 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 1700 1701 ValidatePicture (pSrc); 1702 if (pMask) 1703 ValidatePicture (pMask); 1704 ValidatePicture (pDst); 1705 1706 op = ReduceCompositeOp (op, pSrc, pMask, pDst, xSrc, ySrc, width, height); 1707 if (op == PictOpDst) 1708 return; 1709 1710 (*ps->Composite) (op, 1711 pSrc, 1712 pMask, 1713 pDst, 1714 xSrc, 1715 ySrc, 1716 xMask, 1717 yMask, 1718 xDst, 1719 yDst, 1720 width, 1721 height); 1722} 1723 1724void 1725CompositeRects (CARD8 op, 1726 PicturePtr pDst, 1727 xRenderColor *color, 1728 int nRect, 1729 xRectangle *rects) 1730{ 1731 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 1732 1733 ValidatePicture (pDst); 1734 (*ps->CompositeRects) (op, pDst, color, nRect, rects); 1735} 1736 1737void 1738CompositeTrapezoids (CARD8 op, 1739 PicturePtr pSrc, 1740 PicturePtr pDst, 1741 PictFormatPtr maskFormat, 1742 INT16 xSrc, 1743 INT16 ySrc, 1744 int ntrap, 1745 xTrapezoid *traps) 1746{ 1747 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 1748 1749 ValidatePicture (pSrc); 1750 ValidatePicture (pDst); 1751 (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); 1752} 1753 1754void 1755CompositeTriangles (CARD8 op, 1756 PicturePtr pSrc, 1757 PicturePtr pDst, 1758 PictFormatPtr maskFormat, 1759 INT16 xSrc, 1760 INT16 ySrc, 1761 int ntriangles, 1762 xTriangle *triangles) 1763{ 1764 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 1765 1766 ValidatePicture (pSrc); 1767 ValidatePicture (pDst); 1768 (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles); 1769} 1770 1771void 1772CompositeTriStrip (CARD8 op, 1773 PicturePtr pSrc, 1774 PicturePtr pDst, 1775 PictFormatPtr maskFormat, 1776 INT16 xSrc, 1777 INT16 ySrc, 1778 int npoints, 1779 xPointFixed *points) 1780{ 1781 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 1782 1783 ValidatePicture (pSrc); 1784 ValidatePicture (pDst); 1785 (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); 1786} 1787 1788void 1789CompositeTriFan (CARD8 op, 1790 PicturePtr pSrc, 1791 PicturePtr pDst, 1792 PictFormatPtr maskFormat, 1793 INT16 xSrc, 1794 INT16 ySrc, 1795 int npoints, 1796 xPointFixed *points) 1797{ 1798 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 1799 1800 ValidatePicture (pSrc); 1801 ValidatePicture (pDst); 1802 (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); 1803} 1804 1805void 1806AddTraps (PicturePtr pPicture, 1807 INT16 xOff, 1808 INT16 yOff, 1809 int ntrap, 1810 xTrap *traps) 1811{ 1812 PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); 1813 1814 ValidatePicture (pPicture); 1815 (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps); 1816} 1817 1818