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