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