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