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