picture.c revision 9ace9065
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->filter = PictureGetFilterId (FilterNearest, -1, TRUE); 739 pPicture->filter_params = 0; 740 pPicture->filter_nparams = 0; 741 742 pPicture->serialNumber = GC_CHANGE_SERIAL_BIT; 743 pPicture->stateChanges = -1; 744 pPicture->pSourcePict = 0; 745} 746 747PicturePtr 748CreatePicture (Picture pid, 749 DrawablePtr pDrawable, 750 PictFormatPtr pFormat, 751 Mask vmask, 752 XID *vlist, 753 ClientPtr client, 754 int *error) 755{ 756 PicturePtr pPicture; 757 PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen); 758 759 pPicture = dixAllocateObjectWithPrivates(PictureRec, PRIVATE_PICTURE); 760 if (!pPicture) 761 { 762 *error = BadAlloc; 763 return 0; 764 } 765 766 pPicture->id = pid; 767 pPicture->pDrawable = pDrawable; 768 pPicture->pFormat = pFormat; 769 pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24); 770 771 /* security creation/labeling check */ 772 *error = XaceHook(XACE_RESOURCE_ACCESS, client, pid, PictureType, pPicture, 773 RT_PIXMAP, pDrawable, DixCreateAccess|DixSetAttrAccess); 774 if (*error != Success) 775 goto out; 776 777 if (pDrawable->type == DRAWABLE_PIXMAP) 778 { 779 ++((PixmapPtr)pDrawable)->refcnt; 780 pPicture->pNext = 0; 781 } 782 else 783 { 784 pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable)); 785 SetPictureWindow(((WindowPtr) pDrawable), pPicture); 786 } 787 788 SetPictureToDefaults (pPicture); 789 790 if (vmask) 791 *error = ChangePicture (pPicture, vmask, vlist, 0, client); 792 else 793 *error = Success; 794 if (*error == Success) 795 *error = (*ps->CreatePicture) (pPicture); 796out: 797 if (*error != Success) 798 { 799 FreePicture (pPicture, (XID) 0); 800 pPicture = 0; 801 } 802 return pPicture; 803} 804 805static CARD32 xRenderColorToCard32(xRenderColor c) 806{ 807 return 808 (c.alpha >> 8 << 24) | 809 (c.red >> 8 << 16) | 810 (c.green & 0xff00) | 811 (c.blue >> 8); 812} 813 814static unsigned int premultiply(unsigned int x) 815{ 816 unsigned int a = x >> 24; 817 unsigned int t = (x & 0xff00ff) * a + 0x800080; 818 t = (t + ((t >> 8) & 0xff00ff)) >> 8; 819 t &= 0xff00ff; 820 821 x = ((x >> 8) & 0xff) * a + 0x80; 822 x = (x + ((x >> 8) & 0xff)); 823 x &= 0xff00; 824 x |= t | (a << 24); 825 return x; 826} 827 828static unsigned int INTERPOLATE_PIXEL_256(unsigned int x, unsigned int a, 829 unsigned int y, unsigned int b) 830{ 831 CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; 832 t >>= 8; 833 t &= 0xff00ff; 834 835 x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; 836 x &= 0xff00ff00; 837 x |= t; 838 return x; 839} 840 841CARD32 842PictureGradientColor (PictGradientStopPtr stop1, 843 PictGradientStopPtr stop2, 844 CARD32 x) 845{ 846 CARD32 current_color, next_color; 847 int dist, idist; 848 849 current_color = xRenderColorToCard32 (stop1->color); 850 next_color = xRenderColorToCard32 (stop2->color); 851 852 dist = (int) (256 * (x - stop1->x) / (stop2->x - stop1->x)); 853 idist = 256 - dist; 854 855 return premultiply (INTERPOLATE_PIXEL_256 (current_color, idist, 856 next_color, dist)); 857} 858 859static void initGradient(SourcePictPtr pGradient, int stopCount, 860 xFixed *stopPoints, xRenderColor *stopColors, int *error) 861{ 862 int i; 863 xFixed dpos; 864 865 if (stopCount <= 0) { 866 *error = BadValue; 867 return; 868 } 869 870 dpos = -1; 871 for (i = 0; i < stopCount; ++i) { 872 if (stopPoints[i] < dpos || stopPoints[i] > (1<<16)) { 873 *error = BadValue; 874 return; 875 } 876 dpos = stopPoints[i]; 877 } 878 879 pGradient->gradient.stops = malloc(stopCount*sizeof(PictGradientStop)); 880 if (!pGradient->gradient.stops) { 881 *error = BadAlloc; 882 return; 883 } 884 885 pGradient->gradient.nstops = stopCount; 886 887 for (i = 0; i < stopCount; ++i) { 888 pGradient->gradient.stops[i].x = stopPoints[i]; 889 pGradient->gradient.stops[i].color = stopColors[i]; 890 } 891 892 pGradient->gradient.class = SourcePictClassUnknown; 893 pGradient->gradient.stopRange = 0xffff; 894 pGradient->gradient.colorTable = NULL; 895 pGradient->gradient.colorTableSize = 0; 896} 897 898static PicturePtr createSourcePicture(void) 899{ 900 PicturePtr pPicture; 901 pPicture = dixAllocateObjectWithPrivates(PictureRec, PRIVATE_PICTURE); 902 pPicture->pDrawable = 0; 903 pPicture->pFormat = 0; 904 pPicture->pNext = 0; 905 pPicture->format = PICT_a8r8g8b8; 906 907 SetPictureToDefaults(pPicture); 908 return pPicture; 909} 910 911PicturePtr 912CreateSolidPicture (Picture pid, xRenderColor *color, int *error) 913{ 914 PicturePtr pPicture; 915 pPicture = createSourcePicture(); 916 if (!pPicture) { 917 *error = BadAlloc; 918 return 0; 919 } 920 921 pPicture->id = pid; 922 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictSolidFill)); 923 if (!pPicture->pSourcePict) { 924 *error = BadAlloc; 925 free(pPicture); 926 return 0; 927 } 928 pPicture->pSourcePict->type = SourcePictTypeSolidFill; 929 pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color); 930 return pPicture; 931} 932 933PicturePtr 934CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2, 935 int nStops, xFixed *stops, xRenderColor *colors, int *error) 936{ 937 PicturePtr pPicture; 938 939 if (nStops < 2) { 940 *error = BadValue; 941 return 0; 942 } 943 944 pPicture = createSourcePicture(); 945 if (!pPicture) { 946 *error = BadAlloc; 947 return 0; 948 } 949 950 pPicture->id = pid; 951 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictLinearGradient)); 952 if (!pPicture->pSourcePict) { 953 *error = BadAlloc; 954 free(pPicture); 955 return 0; 956 } 957 958 pPicture->pSourcePict->linear.type = SourcePictTypeLinear; 959 pPicture->pSourcePict->linear.p1 = *p1; 960 pPicture->pSourcePict->linear.p2 = *p2; 961 962 initGradient(pPicture->pSourcePict, nStops, stops, colors, error); 963 if (*error) { 964 free(pPicture); 965 return 0; 966 } 967 return pPicture; 968} 969 970#define FixedToDouble(x) ((x)/65536.) 971 972PicturePtr 973CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer, 974 xFixed innerRadius, xFixed outerRadius, 975 int nStops, xFixed *stops, xRenderColor *colors, int *error) 976{ 977 PicturePtr pPicture; 978 PictRadialGradient *radial; 979 980 if (nStops < 2) { 981 *error = BadValue; 982 return 0; 983 } 984 985 pPicture = createSourcePicture(); 986 if (!pPicture) { 987 *error = BadAlloc; 988 return 0; 989 } 990 991 pPicture->id = pid; 992 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictRadialGradient)); 993 if (!pPicture->pSourcePict) { 994 *error = BadAlloc; 995 free(pPicture); 996 return 0; 997 } 998 radial = &pPicture->pSourcePict->radial; 999 1000 radial->type = SourcePictTypeRadial; 1001 radial->c1.x = inner->x; 1002 radial->c1.y = inner->y; 1003 radial->c1.radius = innerRadius; 1004 radial->c2.x = outer->x; 1005 radial->c2.y = outer->y; 1006 radial->c2.radius = outerRadius; 1007 radial->cdx = (radial->c2.x - radial->c1.x) / 65536.; 1008 radial->cdy = (radial->c2.y - radial->c1.y) / 65536.; 1009 radial->dr = (radial->c2.radius - radial->c1.radius) / 65536.; 1010 radial->A = ( radial->cdx * radial->cdx 1011 + radial->cdy * radial->cdy 1012 - radial->dr * radial->dr); 1013 1014 initGradient(pPicture->pSourcePict, nStops, stops, colors, error); 1015 if (*error) { 1016 free(pPicture); 1017 return 0; 1018 } 1019 return pPicture; 1020} 1021 1022PicturePtr 1023CreateConicalGradientPicture (Picture pid, xPointFixed *center, xFixed angle, 1024 int nStops, xFixed *stops, xRenderColor *colors, int *error) 1025{ 1026 PicturePtr pPicture; 1027 1028 if (nStops < 2) { 1029 *error = BadValue; 1030 return 0; 1031 } 1032 1033 pPicture = createSourcePicture(); 1034 if (!pPicture) { 1035 *error = BadAlloc; 1036 return 0; 1037 } 1038 1039 pPicture->id = pid; 1040 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictConicalGradient)); 1041 if (!pPicture->pSourcePict) { 1042 *error = BadAlloc; 1043 free(pPicture); 1044 return 0; 1045 } 1046 1047 pPicture->pSourcePict->conical.type = SourcePictTypeConical; 1048 pPicture->pSourcePict->conical.center = *center; 1049 pPicture->pSourcePict->conical.angle = angle; 1050 1051 initGradient(pPicture->pSourcePict, nStops, stops, colors, error); 1052 if (*error) { 1053 free(pPicture); 1054 return 0; 1055 } 1056 return pPicture; 1057} 1058 1059#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val) 1060 1061#define NEXT_PTR(_type) ((_type) ulist++->ptr) 1062 1063int 1064ChangePicture (PicturePtr pPicture, 1065 Mask vmask, 1066 XID *vlist, 1067 DevUnion *ulist, 1068 ClientPtr client) 1069{ 1070 ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0; 1071 PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0; 1072 BITS32 index2; 1073 int error = 0; 1074 BITS32 maskQ; 1075 1076 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; 1077 maskQ = vmask; 1078 while (vmask && !error) 1079 { 1080 index2 = (BITS32) lowbit (vmask); 1081 vmask &= ~index2; 1082 pPicture->stateChanges |= index2; 1083 switch (index2) 1084 { 1085 case CPRepeat: 1086 { 1087 unsigned int newr; 1088 newr = NEXT_VAL(unsigned int); 1089 if (newr <= RepeatReflect) 1090 { 1091 pPicture->repeat = (newr != RepeatNone); 1092 pPicture->repeatType = newr; 1093 } 1094 else 1095 { 1096 client->errorValue = newr; 1097 error = BadValue; 1098 } 1099 } 1100 break; 1101 case CPAlphaMap: 1102 { 1103 PicturePtr pAlpha; 1104 1105 if (vlist) 1106 { 1107 Picture pid = NEXT_VAL(Picture); 1108 1109 if (pid == None) 1110 pAlpha = 0; 1111 else 1112 { 1113 error = dixLookupResourceByType((pointer *)&pAlpha, pid, 1114 PictureType, client, 1115 DixReadAccess); 1116 if (error != Success) 1117 { 1118 client->errorValue = pid; 1119 break; 1120 } 1121 if (pAlpha->pDrawable == NULL || 1122 pAlpha->pDrawable->type != DRAWABLE_PIXMAP) 1123 { 1124 client->errorValue = pid; 1125 error = BadMatch; 1126 break; 1127 } 1128 } 1129 } 1130 else 1131 pAlpha = NEXT_PTR(PicturePtr); 1132 if (!error) 1133 { 1134 if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP) 1135 pAlpha->refcnt++; 1136 if (pPicture->alphaMap) 1137 FreePicture ((pointer) pPicture->alphaMap, (XID) 0); 1138 pPicture->alphaMap = pAlpha; 1139 } 1140 } 1141 break; 1142 case CPAlphaXOrigin: 1143 pPicture->alphaOrigin.x = NEXT_VAL(INT16); 1144 break; 1145 case CPAlphaYOrigin: 1146 pPicture->alphaOrigin.y = NEXT_VAL(INT16); 1147 break; 1148 case CPClipXOrigin: 1149 pPicture->clipOrigin.x = NEXT_VAL(INT16); 1150 break; 1151 case CPClipYOrigin: 1152 pPicture->clipOrigin.y = NEXT_VAL(INT16); 1153 break; 1154 case CPClipMask: 1155 { 1156 Pixmap pid; 1157 PixmapPtr pPixmap; 1158 int clipType; 1159 if (!pScreen) 1160 return BadDrawable; 1161 1162 if (vlist) 1163 { 1164 pid = NEXT_VAL(Pixmap); 1165 if (pid == None) 1166 { 1167 clipType = CT_NONE; 1168 pPixmap = NullPixmap; 1169 } 1170 else 1171 { 1172 clipType = CT_PIXMAP; 1173 error = dixLookupResourceByType((pointer *)&pPixmap, pid, 1174 RT_PIXMAP, client, 1175 DixReadAccess); 1176 if (error != Success) 1177 { 1178 client->errorValue = pid; 1179 break; 1180 } 1181 } 1182 } 1183 else 1184 { 1185 pPixmap = NEXT_PTR(PixmapPtr); 1186 if (pPixmap) 1187 clipType = CT_PIXMAP; 1188 else 1189 clipType = CT_NONE; 1190 } 1191 1192 if (pPixmap) 1193 { 1194 if ((pPixmap->drawable.depth != 1) || 1195 (pPixmap->drawable.pScreen != pScreen)) 1196 { 1197 error = BadMatch; 1198 break; 1199 } 1200 else 1201 { 1202 clipType = CT_PIXMAP; 1203 pPixmap->refcnt++; 1204 } 1205 } 1206 error = (*ps->ChangePictureClip)(pPicture, clipType, 1207 (pointer)pPixmap, 0); 1208 break; 1209 } 1210 case CPGraphicsExposure: 1211 { 1212 unsigned int newe; 1213 newe = NEXT_VAL(unsigned int); 1214 if (newe <= xTrue) 1215 pPicture->graphicsExposures = newe; 1216 else 1217 { 1218 client->errorValue = newe; 1219 error = BadValue; 1220 } 1221 } 1222 break; 1223 case CPSubwindowMode: 1224 { 1225 unsigned int news; 1226 news = NEXT_VAL(unsigned int); 1227 if (news == ClipByChildren || news == IncludeInferiors) 1228 pPicture->subWindowMode = news; 1229 else 1230 { 1231 client->errorValue = news; 1232 error = BadValue; 1233 } 1234 } 1235 break; 1236 case CPPolyEdge: 1237 { 1238 unsigned int newe; 1239 newe = NEXT_VAL(unsigned int); 1240 if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth) 1241 pPicture->polyEdge = newe; 1242 else 1243 { 1244 client->errorValue = newe; 1245 error = BadValue; 1246 } 1247 } 1248 break; 1249 case CPPolyMode: 1250 { 1251 unsigned int newm; 1252 newm = NEXT_VAL(unsigned int); 1253 if (newm == PolyModePrecise || newm == PolyModeImprecise) 1254 pPicture->polyMode = newm; 1255 else 1256 { 1257 client->errorValue = newm; 1258 error = BadValue; 1259 } 1260 } 1261 break; 1262 case CPDither: 1263 (void) NEXT_VAL(Atom); /* unimplemented */ 1264 break; 1265 case CPComponentAlpha: 1266 { 1267 unsigned int newca; 1268 1269 newca = NEXT_VAL (unsigned int); 1270 if (newca <= xTrue) 1271 pPicture->componentAlpha = newca; 1272 else 1273 { 1274 client->errorValue = newca; 1275 error = BadValue; 1276 } 1277 } 1278 break; 1279 default: 1280 client->errorValue = maskQ; 1281 error = BadValue; 1282 break; 1283 } 1284 } 1285 if (ps) 1286 (*ps->ChangePicture) (pPicture, maskQ); 1287 return error; 1288} 1289 1290int 1291SetPictureClipRects (PicturePtr pPicture, 1292 int xOrigin, 1293 int yOrigin, 1294 int nRect, 1295 xRectangle *rects) 1296{ 1297 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 1298 PictureScreenPtr ps = GetPictureScreen(pScreen); 1299 RegionPtr clientClip; 1300 int result; 1301 1302 clientClip = RegionFromRects(nRect, rects, CT_UNSORTED); 1303 if (!clientClip) 1304 return BadAlloc; 1305 result =(*ps->ChangePictureClip) (pPicture, CT_REGION, 1306 (pointer) clientClip, 0); 1307 if (result == Success) 1308 { 1309 pPicture->clipOrigin.x = xOrigin; 1310 pPicture->clipOrigin.y = yOrigin; 1311 pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; 1312 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; 1313 } 1314 return result; 1315} 1316 1317int 1318SetPictureClipRegion (PicturePtr pPicture, 1319 int xOrigin, 1320 int yOrigin, 1321 RegionPtr pRegion) 1322{ 1323 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 1324 PictureScreenPtr ps = GetPictureScreen(pScreen); 1325 RegionPtr clientClip; 1326 int result; 1327 int type; 1328 1329 if (pRegion) 1330 { 1331 type = CT_REGION; 1332 clientClip = RegionCreate(RegionExtents(pRegion), 1333 RegionNumRects(pRegion)); 1334 if (!clientClip) 1335 return BadAlloc; 1336 if (!RegionCopy(clientClip, pRegion)) 1337 { 1338 RegionDestroy(clientClip); 1339 return BadAlloc; 1340 } 1341 } 1342 else 1343 { 1344 type = CT_NONE; 1345 clientClip = 0; 1346 } 1347 1348 result =(*ps->ChangePictureClip) (pPicture, type, 1349 (pointer) clientClip, 0); 1350 if (result == Success) 1351 { 1352 pPicture->clipOrigin.x = xOrigin; 1353 pPicture->clipOrigin.y = yOrigin; 1354 pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; 1355 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; 1356 } 1357 return result; 1358} 1359 1360static Bool 1361transformIsIdentity(PictTransform *t) 1362{ 1363 return ((t->matrix[0][0] == t->matrix[1][1]) && 1364 (t->matrix[0][0] == t->matrix[2][2]) && 1365 (t->matrix[0][0] != 0) && 1366 (t->matrix[0][1] == 0) && 1367 (t->matrix[0][2] == 0) && 1368 (t->matrix[1][0] == 0) && 1369 (t->matrix[1][2] == 0) && 1370 (t->matrix[2][0] == 0) && 1371 (t->matrix[2][1] == 0)); 1372} 1373 1374int 1375SetPictureTransform (PicturePtr pPicture, 1376 PictTransform *transform) 1377{ 1378 if (transform && transformIsIdentity (transform)) 1379 transform = 0; 1380 1381 if (transform) 1382 { 1383 if (!pPicture->transform) 1384 { 1385 pPicture->transform = (PictTransform *) malloc(sizeof (PictTransform)); 1386 if (!pPicture->transform) 1387 return BadAlloc; 1388 } 1389 *pPicture->transform = *transform; 1390 } 1391 else 1392 { 1393 free(pPicture->transform); 1394 pPicture->transform = NULL; 1395 } 1396 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; 1397 1398 if (pPicture->pDrawable != NULL) { 1399 int result; 1400 PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); 1401 1402 result = (*ps->ChangePictureTransform) (pPicture, transform); 1403 1404 return result; 1405 } 1406 1407 return Success; 1408} 1409 1410void 1411CopyPicture (PicturePtr pSrc, 1412 Mask mask, 1413 PicturePtr pDst) 1414{ 1415 PictureScreenPtr ps = GetPictureScreen(pSrc->pDrawable->pScreen); 1416 Mask origMask = mask; 1417 1418 pDst->serialNumber |= GC_CHANGE_SERIAL_BIT; 1419 pDst->stateChanges |= mask; 1420 1421 while (mask) { 1422 Mask bit = lowbit(mask); 1423 1424 switch (bit) 1425 { 1426 case CPRepeat: 1427 pDst->repeat = pSrc->repeat; 1428 pDst->repeatType = pSrc->repeatType; 1429 break; 1430 case CPAlphaMap: 1431 if (pSrc->alphaMap && pSrc->alphaMap->pDrawable->type == DRAWABLE_PIXMAP) 1432 pSrc->alphaMap->refcnt++; 1433 if (pDst->alphaMap) 1434 FreePicture ((pointer) pDst->alphaMap, (XID) 0); 1435 pDst->alphaMap = pSrc->alphaMap; 1436 break; 1437 case CPAlphaXOrigin: 1438 pDst->alphaOrigin.x = pSrc->alphaOrigin.x; 1439 break; 1440 case CPAlphaYOrigin: 1441 pDst->alphaOrigin.y = pSrc->alphaOrigin.y; 1442 break; 1443 case CPClipXOrigin: 1444 pDst->clipOrigin.x = pSrc->clipOrigin.x; 1445 break; 1446 case CPClipYOrigin: 1447 pDst->clipOrigin.y = pSrc->clipOrigin.y; 1448 break; 1449 case CPClipMask: 1450 switch (pSrc->clientClipType) { 1451 case CT_NONE: 1452 (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0); 1453 break; 1454 case CT_REGION: 1455 if (!pSrc->clientClip) { 1456 (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0); 1457 } else { 1458 RegionPtr clientClip; 1459 RegionPtr srcClientClip = (RegionPtr)pSrc->clientClip; 1460 1461 clientClip = RegionCreate( 1462 RegionExtents(srcClientClip), 1463 RegionNumRects(srcClientClip)); 1464 (*ps->ChangePictureClip)(pDst, CT_REGION, clientClip, 0); 1465 } 1466 break; 1467 default: 1468 /* XXX: CT_PIXMAP unimplemented */ 1469 break; 1470 } 1471 break; 1472 case CPGraphicsExposure: 1473 pDst->graphicsExposures = pSrc->graphicsExposures; 1474 break; 1475 case CPPolyEdge: 1476 pDst->polyEdge = pSrc->polyEdge; 1477 break; 1478 case CPPolyMode: 1479 pDst->polyMode = pSrc->polyMode; 1480 break; 1481 case CPDither: 1482 break; 1483 case CPComponentAlpha: 1484 pDst->componentAlpha = pSrc->componentAlpha; 1485 break; 1486 } 1487 mask &= ~bit; 1488 } 1489 1490 (*ps->ChangePicture)(pDst, origMask); 1491} 1492 1493static void 1494ValidateOnePicture (PicturePtr pPicture) 1495{ 1496 if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber) 1497 { 1498 PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); 1499 1500 (*ps->ValidatePicture) (pPicture, pPicture->stateChanges); 1501 pPicture->stateChanges = 0; 1502 pPicture->serialNumber = pPicture->pDrawable->serialNumber; 1503 } 1504} 1505 1506void 1507ValidatePicture(PicturePtr pPicture) 1508{ 1509 ValidateOnePicture (pPicture); 1510 if (pPicture->alphaMap) 1511 ValidateOnePicture (pPicture->alphaMap); 1512} 1513 1514int 1515FreePicture (pointer value, 1516 XID pid) 1517{ 1518 PicturePtr pPicture = (PicturePtr) value; 1519 1520 if (--pPicture->refcnt == 0) 1521 { 1522 free(pPicture->transform); 1523 1524 if (pPicture->pSourcePict) 1525 { 1526 if (pPicture->pSourcePict->type != SourcePictTypeSolidFill) 1527 free(pPicture->pSourcePict->linear.stops); 1528 1529 free(pPicture->pSourcePict); 1530 } 1531 1532 if (pPicture->pDrawable) 1533 { 1534 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 1535 PictureScreenPtr ps = GetPictureScreen(pScreen); 1536 1537 if (pPicture->alphaMap) 1538 FreePicture ((pointer) pPicture->alphaMap, (XID) 0); 1539 (*ps->DestroyPicture) (pPicture); 1540 (*ps->DestroyPictureClip) (pPicture); 1541 if (pPicture->pDrawable->type == DRAWABLE_WINDOW) 1542 { 1543 WindowPtr pWindow = (WindowPtr) pPicture->pDrawable; 1544 PicturePtr *pPrev; 1545 1546 for (pPrev = (PicturePtr *)dixLookupPrivateAddr 1547 (&pWindow->devPrivates, PictureWindowPrivateKey); 1548 *pPrev; 1549 pPrev = &(*pPrev)->pNext) 1550 { 1551 if (*pPrev == pPicture) 1552 { 1553 *pPrev = pPicture->pNext; 1554 break; 1555 } 1556 } 1557 } 1558 else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP) 1559 { 1560 (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable); 1561 } 1562 } 1563 dixFreeObjectWithPrivates(pPicture, PRIVATE_PICTURE); 1564 } 1565 return Success; 1566} 1567 1568int 1569FreePictFormat (pointer pPictFormat, 1570 XID pid) 1571{ 1572 return Success; 1573} 1574 1575/** 1576 * ReduceCompositeOp is used to choose simpler ops for cases where alpha 1577 * channels are always one and so math on the alpha channel per pixel becomes 1578 * unnecessary. It may also avoid destination reads sometimes if apps aren't 1579 * being careful to avoid these cases. 1580 */ 1581static CARD8 1582ReduceCompositeOp (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, 1583 INT16 xSrc, INT16 ySrc, CARD16 width, CARD16 height) 1584{ 1585 Bool no_src_alpha, no_dst_alpha; 1586 1587 /* Sampling off the edge of a RepeatNone picture introduces alpha 1588 * even if the picture itself doesn't have alpha. We don't try to 1589 * detect every case where we don't sample off the edge, just the 1590 * simplest case where there is no transform on the source 1591 * picture. 1592 */ 1593 no_src_alpha = PICT_FORMAT_COLOR(pSrc->format) && 1594 PICT_FORMAT_A(pSrc->format) == 0 && 1595 (pSrc->repeatType != RepeatNone || 1596 (!pSrc->transform && 1597 xSrc >= 0 && ySrc >= 0 && 1598 xSrc + width <= pSrc->pDrawable->width && 1599 ySrc + height <= pSrc->pDrawable->height)) && 1600 pSrc->alphaMap == NULL && 1601 pMask == NULL; 1602 no_dst_alpha = PICT_FORMAT_COLOR(pDst->format) && 1603 PICT_FORMAT_A(pDst->format) == 0 && 1604 pDst->alphaMap == NULL; 1605 1606 /* TODO, maybe: Conjoint and Disjoint op reductions? */ 1607 1608 /* Deal with simplifications where the source alpha is always 1. */ 1609 if (no_src_alpha) 1610 { 1611 switch (op) { 1612 case PictOpOver: 1613 op = PictOpSrc; 1614 break; 1615 case PictOpInReverse: 1616 op = PictOpDst; 1617 break; 1618 case PictOpOutReverse: 1619 op = PictOpClear; 1620 break; 1621 case PictOpAtop: 1622 op = PictOpIn; 1623 break; 1624 case PictOpAtopReverse: 1625 op = PictOpOverReverse; 1626 break; 1627 case PictOpXor: 1628 op = PictOpOut; 1629 break; 1630 default: 1631 break; 1632 } 1633 } 1634 1635 /* Deal with simplifications when the destination alpha is always 1 */ 1636 if (no_dst_alpha) 1637 { 1638 switch (op) { 1639 case PictOpOverReverse: 1640 op = PictOpDst; 1641 break; 1642 case PictOpIn: 1643 op = PictOpSrc; 1644 break; 1645 case PictOpOut: 1646 op = PictOpClear; 1647 break; 1648 case PictOpAtop: 1649 op = PictOpOver; 1650 break; 1651 case PictOpXor: 1652 op = PictOpOutReverse; 1653 break; 1654 default: 1655 break; 1656 } 1657 } 1658 1659 /* Reduce some con/disjoint ops to the basic names. */ 1660 switch (op) { 1661 case PictOpDisjointClear: 1662 case PictOpConjointClear: 1663 op = PictOpClear; 1664 break; 1665 case PictOpDisjointSrc: 1666 case PictOpConjointSrc: 1667 op = PictOpSrc; 1668 break; 1669 case PictOpDisjointDst: 1670 case PictOpConjointDst: 1671 op = PictOpDst; 1672 break; 1673 default: 1674 break; 1675 } 1676 1677 return op; 1678} 1679 1680void 1681CompositePicture (CARD8 op, 1682 PicturePtr pSrc, 1683 PicturePtr pMask, 1684 PicturePtr pDst, 1685 INT16 xSrc, 1686 INT16 ySrc, 1687 INT16 xMask, 1688 INT16 yMask, 1689 INT16 xDst, 1690 INT16 yDst, 1691 CARD16 width, 1692 CARD16 height) 1693{ 1694 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 1695 1696 ValidatePicture (pSrc); 1697 if (pMask) 1698 ValidatePicture (pMask); 1699 ValidatePicture (pDst); 1700 1701 op = ReduceCompositeOp (op, pSrc, pMask, pDst, xSrc, ySrc, width, height); 1702 if (op == PictOpDst) 1703 return; 1704 1705 (*ps->Composite) (op, 1706 pSrc, 1707 pMask, 1708 pDst, 1709 xSrc, 1710 ySrc, 1711 xMask, 1712 yMask, 1713 xDst, 1714 yDst, 1715 width, 1716 height); 1717} 1718 1719void 1720CompositeRects (CARD8 op, 1721 PicturePtr pDst, 1722 xRenderColor *color, 1723 int nRect, 1724 xRectangle *rects) 1725{ 1726 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 1727 1728 ValidatePicture (pDst); 1729 (*ps->CompositeRects) (op, pDst, color, nRect, rects); 1730} 1731 1732void 1733CompositeTrapezoids (CARD8 op, 1734 PicturePtr pSrc, 1735 PicturePtr pDst, 1736 PictFormatPtr maskFormat, 1737 INT16 xSrc, 1738 INT16 ySrc, 1739 int ntrap, 1740 xTrapezoid *traps) 1741{ 1742 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 1743 1744 ValidatePicture (pSrc); 1745 ValidatePicture (pDst); 1746 (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); 1747} 1748 1749void 1750CompositeTriangles (CARD8 op, 1751 PicturePtr pSrc, 1752 PicturePtr pDst, 1753 PictFormatPtr maskFormat, 1754 INT16 xSrc, 1755 INT16 ySrc, 1756 int ntriangles, 1757 xTriangle *triangles) 1758{ 1759 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 1760 1761 ValidatePicture (pSrc); 1762 ValidatePicture (pDst); 1763 (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles); 1764} 1765 1766void 1767CompositeTriStrip (CARD8 op, 1768 PicturePtr pSrc, 1769 PicturePtr pDst, 1770 PictFormatPtr maskFormat, 1771 INT16 xSrc, 1772 INT16 ySrc, 1773 int npoints, 1774 xPointFixed *points) 1775{ 1776 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 1777 1778 ValidatePicture (pSrc); 1779 ValidatePicture (pDst); 1780 (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); 1781} 1782 1783void 1784CompositeTriFan (CARD8 op, 1785 PicturePtr pSrc, 1786 PicturePtr pDst, 1787 PictFormatPtr maskFormat, 1788 INT16 xSrc, 1789 INT16 ySrc, 1790 int npoints, 1791 xPointFixed *points) 1792{ 1793 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 1794 1795 ValidatePicture (pSrc); 1796 ValidatePicture (pDst); 1797 (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); 1798} 1799 1800void 1801AddTraps (PicturePtr pPicture, 1802 INT16 xOff, 1803 INT16 yOff, 1804 int ntrap, 1805 xTrap *traps) 1806{ 1807 PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); 1808 1809 ValidatePicture (pPicture); 1810 (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps); 1811} 1812 1813