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