pixman-utils.c revision 317c648b
1/* 2 * Copyright © 2000 SuSE, Inc. 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of SuSE not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. SuSE makes no representations about the 11 * suitability of this software for any purpose. It is provided "as is" 12 * without express or implied warranty. 13 * 14 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 16 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 18 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 19 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 * 21 * Author: Keith Packard, SuSE, Inc. 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include <config.h> 26#endif 27 28#include <stdlib.h> 29 30#include "pixman-private.h" 31 32/* 33 * Compute the smallest value no less than y which is on a 34 * grid row 35 */ 36 37PIXMAN_EXPORT pixman_fixed_t 38pixman_sample_ceil_y (pixman_fixed_t y, int n) 39{ 40 pixman_fixed_t f = pixman_fixed_frac(y); 41 pixman_fixed_t i = pixman_fixed_floor(y); 42 43 f = ((f + Y_FRAC_FIRST(n)) / STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n); 44 if (f > Y_FRAC_LAST(n)) 45 { 46 if (pixman_fixed_to_int(i) == 0x7fff) 47 { 48 f = 0xffff; /* saturate */ 49 } else { 50 f = Y_FRAC_FIRST(n); 51 i += pixman_fixed_1; 52 } 53 } 54 return (i | f); 55} 56 57#define _div(a,b) ((a) >= 0 ? (a) / (b) : -((-(a) + (b) - 1) / (b))) 58 59/* 60 * Compute the largest value no greater than y which is on a 61 * grid row 62 */ 63PIXMAN_EXPORT pixman_fixed_t 64pixman_sample_floor_y (pixman_fixed_t y, int n) 65{ 66 pixman_fixed_t f = pixman_fixed_frac(y); 67 pixman_fixed_t i = pixman_fixed_floor (y); 68 69 f = _div(f - Y_FRAC_FIRST(n), STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n); 70 if (f < Y_FRAC_FIRST(n)) 71 { 72 if (pixman_fixed_to_int(i) == 0x8000) 73 { 74 f = 0; /* saturate */ 75 } else { 76 f = Y_FRAC_LAST(n); 77 i -= pixman_fixed_1; 78 } 79 } 80 return (i | f); 81} 82 83/* 84 * Step an edge by any amount (including negative values) 85 */ 86PIXMAN_EXPORT void 87pixman_edge_step (pixman_edge_t *e, int n) 88{ 89 pixman_fixed_48_16_t ne; 90 91 e->x += n * e->stepx; 92 93 ne = e->e + n * (pixman_fixed_48_16_t) e->dx; 94 95 if (n >= 0) 96 { 97 if (ne > 0) 98 { 99 int nx = (ne + e->dy - 1) / e->dy; 100 e->e = ne - nx * (pixman_fixed_48_16_t) e->dy; 101 e->x += nx * e->signdx; 102 } 103 } 104 else 105 { 106 if (ne <= -e->dy) 107 { 108 int nx = (-ne) / e->dy; 109 e->e = ne + nx * (pixman_fixed_48_16_t) e->dy; 110 e->x -= nx * e->signdx; 111 } 112 } 113} 114 115/* 116 * A private routine to initialize the multi-step 117 * elements of an edge structure 118 */ 119static void 120_pixman_edge_multi_init (pixman_edge_t *e, int n, pixman_fixed_t *stepx_p, pixman_fixed_t *dx_p) 121{ 122 pixman_fixed_t stepx; 123 pixman_fixed_48_16_t ne; 124 125 ne = n * (pixman_fixed_48_16_t) e->dx; 126 stepx = n * e->stepx; 127 if (ne > 0) 128 { 129 int nx = ne / e->dy; 130 ne -= nx * e->dy; 131 stepx += nx * e->signdx; 132 } 133 *dx_p = ne; 134 *stepx_p = stepx; 135} 136 137/* 138 * Initialize one edge structure given the line endpoints and a 139 * starting y value 140 */ 141PIXMAN_EXPORT void 142pixman_edge_init (pixman_edge_t *e, 143 int n, 144 pixman_fixed_t y_start, 145 pixman_fixed_t x_top, 146 pixman_fixed_t y_top, 147 pixman_fixed_t x_bot, 148 pixman_fixed_t y_bot) 149{ 150 pixman_fixed_t dx, dy; 151 152 e->x = x_top; 153 e->e = 0; 154 dx = x_bot - x_top; 155 dy = y_bot - y_top; 156 e->dy = dy; 157 e->dx = 0; 158 if (dy) 159 { 160 if (dx >= 0) 161 { 162 e->signdx = 1; 163 e->stepx = dx / dy; 164 e->dx = dx % dy; 165 e->e = -dy; 166 } 167 else 168 { 169 e->signdx = -1; 170 e->stepx = -(-dx / dy); 171 e->dx = -dx % dy; 172 e->e = 0; 173 } 174 175 _pixman_edge_multi_init (e, STEP_Y_SMALL(n), &e->stepx_small, &e->dx_small); 176 _pixman_edge_multi_init (e, STEP_Y_BIG(n), &e->stepx_big, &e->dx_big); 177 } 178 pixman_edge_step (e, y_start - y_top); 179} 180 181/* 182 * Initialize one edge structure given a line, starting y value 183 * and a pixel offset for the line 184 */ 185PIXMAN_EXPORT void 186pixman_line_fixed_edge_init (pixman_edge_t *e, 187 int n, 188 pixman_fixed_t y, 189 const pixman_line_fixed_t *line, 190 int x_off, 191 int y_off) 192{ 193 pixman_fixed_t x_off_fixed = pixman_int_to_fixed(x_off); 194 pixman_fixed_t y_off_fixed = pixman_int_to_fixed(y_off); 195 const pixman_point_fixed_t *top, *bot; 196 197 if (line->p1.y <= line->p2.y) 198 { 199 top = &line->p1; 200 bot = &line->p2; 201 } 202 else 203 { 204 top = &line->p2; 205 bot = &line->p1; 206 } 207 pixman_edge_init (e, n, y, 208 top->x + x_off_fixed, 209 top->y + y_off_fixed, 210 bot->x + x_off_fixed, 211 bot->y + y_off_fixed); 212} 213 214pixman_bool_t 215pixman_multiply_overflows_int (unsigned int a, 216 unsigned int b) 217{ 218 return a >= INT32_MAX / b; 219} 220 221pixman_bool_t 222pixman_addition_overflows_int (unsigned int a, 223 unsigned int b) 224{ 225 return a > INT32_MAX - b; 226} 227 228void * 229pixman_malloc_ab(unsigned int a, 230 unsigned int b) 231{ 232 if (a >= INT32_MAX / b) 233 return NULL; 234 235 return malloc (a * b); 236} 237 238void * 239pixman_malloc_abc (unsigned int a, 240 unsigned int b, 241 unsigned int c) 242{ 243 if (a >= INT32_MAX / b) 244 return NULL; 245 else if (a * b >= INT32_MAX / c) 246 return NULL; 247 else 248 return malloc (a * b * c); 249} 250 251 252/** 253 * pixman_version: 254 * 255 * Returns the version of the pixman library encoded in a single 256 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that 257 * later versions compare greater than earlier versions. 258 * 259 * A run-time comparison to check that pixman's version is greater than 260 * or equal to version X.Y.Z could be performed as follows: 261 * 262 * <informalexample><programlisting> 263 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...} 264 * </programlisting></informalexample> 265 * 266 * See also pixman_version_string() as well as the compile-time 267 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING. 268 * 269 * Return value: the encoded version. 270 **/ 271PIXMAN_EXPORT int 272pixman_version (void) 273{ 274 return PIXMAN_VERSION; 275} 276 277/* 278 * Helper routine to expand a color component from 0 < n <= 8 bits to 16 bits by 279 * replication. 280 */ 281static inline uint64_t 282expand16(const uint8_t val, int nbits) 283{ 284 // Start out with the high bit of val in the high bit of result. 285 uint16_t result = (uint16_t)val << (16 - nbits); 286 287 if (nbits == 0) 288 return 0; 289 290 // Copy the bits in result, doubling the number of bits each time, until we 291 // fill all 16 bits. 292 while (nbits < 16) { 293 result |= result >> nbits; 294 nbits *= 2; 295 } 296 297 return result; 298} 299 300/* 301 * This function expands images from ARGB8 format to ARGB16. To preserve 302 * precision, it needs to know the original source format. For example, if the 303 * source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then 304 * the expanded value is 12345123. To correctly expand this to 16 bits, it 305 * should be 1234512345123451 and not 1234512312345123. 306 */ 307void 308pixman_expand(uint64_t *dst, const uint32_t *src, 309 pixman_format_code_t format, int width) 310{ 311 /* 312 * Determine the sizes of each component and the masks and shifts required 313 * to extract them from the source pixel. 314 */ 315 const int a_size = PIXMAN_FORMAT_A(format), 316 r_size = PIXMAN_FORMAT_R(format), 317 g_size = PIXMAN_FORMAT_G(format), 318 b_size = PIXMAN_FORMAT_B(format); 319 const int a_shift = 32 - a_size, 320 r_shift = 24 - r_size, 321 g_shift = 16 - g_size, 322 b_shift = 8 - b_size; 323 const uint8_t a_mask = ~(~0 << a_size), 324 r_mask = ~(~0 << r_size), 325 g_mask = ~(~0 << g_size), 326 b_mask = ~(~0 << b_size); 327 int i; 328 329 /* Start at the end so that we can do the expansion in place when src == dst */ 330 for (i = width - 1; i >= 0; i--) 331 { 332 const uint32_t pixel = src[i]; 333 // Extract the components. 334 const uint8_t a = (pixel >> a_shift) & a_mask, 335 r = (pixel >> r_shift) & r_mask, 336 g = (pixel >> g_shift) & g_mask, 337 b = (pixel >> b_shift) & b_mask; 338 const uint64_t a16 = a_size ? expand16(a, a_size) : 0xffff, 339 r16 = expand16(r, r_size), 340 g16 = expand16(g, g_size), 341 b16 = expand16(b, b_size); 342 343 dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16; 344 } 345} 346 347/* 348 * Contracting is easier than expanding. We just need to truncate the 349 * components. 350 */ 351void 352pixman_contract(uint32_t *dst, const uint64_t *src, int width) 353{ 354 int i; 355 356 /* Start at the beginning so that we can do the contraction in place when 357 * src == dst */ 358 for (i = 0; i < width; i++) 359 { 360 const uint8_t a = src[i] >> 56, 361 r = src[i] >> 40, 362 g = src[i] >> 24, 363 b = src[i] >> 8; 364 dst[i] = a << 24 | r << 16 | g << 8 | b; 365 } 366} 367 368/** 369 * pixman_version_string: 370 * 371 * Returns the version of the pixman library as a human-readable string 372 * of the form "X.Y.Z". 373 * 374 * See also pixman_version() as well as the compile-time equivalents 375 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION. 376 * 377 * Return value: a string containing the version. 378 **/ 379PIXMAN_EXPORT const char* 380pixman_version_string (void) 381{ 382 return PIXMAN_VERSION_STRING; 383} 384 385/** 386 * pixman_format_supported_destination: 387 * @format: A pixman_format_code_t format 388 * 389 * Return value: whether the provided format code is a supported 390 * format for a pixman surface used as a destination in 391 * rendering. 392 * 393 * Currently, all pixman_format_code_t values are supported 394 * except for the YUV formats. 395 **/ 396PIXMAN_EXPORT pixman_bool_t 397pixman_format_supported_destination (pixman_format_code_t format) 398{ 399 switch (format) { 400 /* 32 bpp formats */ 401 case PIXMAN_a2b10g10r10: 402 case PIXMAN_x2b10g10r10: 403 case PIXMAN_a8r8g8b8: 404 case PIXMAN_x8r8g8b8: 405 case PIXMAN_a8b8g8r8: 406 case PIXMAN_x8b8g8r8: 407 case PIXMAN_b8g8r8a8: 408 case PIXMAN_b8g8r8x8: 409 case PIXMAN_r8g8b8: 410 case PIXMAN_b8g8r8: 411 case PIXMAN_r5g6b5: 412 case PIXMAN_b5g6r5: 413 /* 16 bpp formats */ 414 case PIXMAN_a1r5g5b5: 415 case PIXMAN_x1r5g5b5: 416 case PIXMAN_a1b5g5r5: 417 case PIXMAN_x1b5g5r5: 418 case PIXMAN_a4r4g4b4: 419 case PIXMAN_x4r4g4b4: 420 case PIXMAN_a4b4g4r4: 421 case PIXMAN_x4b4g4r4: 422 /* 8bpp formats */ 423 case PIXMAN_a8: 424 case PIXMAN_r3g3b2: 425 case PIXMAN_b2g3r3: 426 case PIXMAN_a2r2g2b2: 427 case PIXMAN_a2b2g2r2: 428 case PIXMAN_c8: 429 case PIXMAN_g8: 430 case PIXMAN_x4a4: 431 /* Collides with PIXMAN_c8 432 case PIXMAN_x4c4: 433 */ 434 /* Collides with PIXMAN_g8 435 case PIXMAN_x4g4: 436 */ 437 /* 4bpp formats */ 438 case PIXMAN_a4: 439 case PIXMAN_r1g2b1: 440 case PIXMAN_b1g2r1: 441 case PIXMAN_a1r1g1b1: 442 case PIXMAN_a1b1g1r1: 443 case PIXMAN_c4: 444 case PIXMAN_g4: 445 /* 1bpp formats */ 446 case PIXMAN_a1: 447 case PIXMAN_g1: 448 return TRUE; 449 450 /* YUV formats */ 451 case PIXMAN_yuy2: 452 case PIXMAN_yv12: 453 default: 454 return FALSE; 455 } 456} 457 458/** 459 * pixman_format_supported_source: 460 * @format: A pixman_format_code_t format 461 * 462 * Return value: whether the provided format code is a supported 463 * format for a pixman surface used as a source in 464 * rendering. 465 * 466 * Currently, all pixman_format_code_t values are supported. 467 **/ 468PIXMAN_EXPORT pixman_bool_t 469pixman_format_supported_source (pixman_format_code_t format) 470{ 471 switch (format) { 472 /* 32 bpp formats */ 473 case PIXMAN_a2b10g10r10: 474 case PIXMAN_x2b10g10r10: 475 case PIXMAN_a8r8g8b8: 476 case PIXMAN_x8r8g8b8: 477 case PIXMAN_a8b8g8r8: 478 case PIXMAN_x8b8g8r8: 479 case PIXMAN_b8g8r8a8: 480 case PIXMAN_b8g8r8x8: 481 case PIXMAN_r8g8b8: 482 case PIXMAN_b8g8r8: 483 case PIXMAN_r5g6b5: 484 case PIXMAN_b5g6r5: 485 /* 16 bpp formats */ 486 case PIXMAN_a1r5g5b5: 487 case PIXMAN_x1r5g5b5: 488 case PIXMAN_a1b5g5r5: 489 case PIXMAN_x1b5g5r5: 490 case PIXMAN_a4r4g4b4: 491 case PIXMAN_x4r4g4b4: 492 case PIXMAN_a4b4g4r4: 493 case PIXMAN_x4b4g4r4: 494 /* 8bpp formats */ 495 case PIXMAN_a8: 496 case PIXMAN_r3g3b2: 497 case PIXMAN_b2g3r3: 498 case PIXMAN_a2r2g2b2: 499 case PIXMAN_a2b2g2r2: 500 case PIXMAN_c8: 501 case PIXMAN_g8: 502 case PIXMAN_x4a4: 503 /* Collides with PIXMAN_c8 504 case PIXMAN_x4c4: 505 */ 506 /* Collides with PIXMAN_g8 507 case PIXMAN_x4g4: 508 */ 509 /* 4bpp formats */ 510 case PIXMAN_a4: 511 case PIXMAN_r1g2b1: 512 case PIXMAN_b1g2r1: 513 case PIXMAN_a1r1g1b1: 514 case PIXMAN_a1b1g1r1: 515 case PIXMAN_c4: 516 case PIXMAN_g4: 517 /* 1bpp formats */ 518 case PIXMAN_a1: 519 case PIXMAN_g1: 520 /* YUV formats */ 521 case PIXMAN_yuy2: 522 case PIXMAN_yv12: 523 return TRUE; 524 525 default: 526 return FALSE; 527 } 528} 529 530void 531_pixman_walk_composite_region (pixman_implementation_t *imp, 532 pixman_op_t op, 533 pixman_image_t * pSrc, 534 pixman_image_t * pMask, 535 pixman_image_t * pDst, 536 int16_t xSrc, 537 int16_t ySrc, 538 int16_t xMask, 539 int16_t yMask, 540 int16_t xDst, 541 int16_t yDst, 542 uint16_t width, 543 uint16_t height, 544 pixman_bool_t srcRepeat, 545 pixman_bool_t maskRepeat, 546 pixman_composite_func_t compositeRect) 547{ 548 int n; 549 const pixman_box32_t *pbox; 550 int w, h, w_this, h_this; 551 int x_msk, y_msk, x_src, y_src, x_dst, y_dst; 552 pixman_region32_t reg; 553 pixman_region32_t *region; 554 555 pixman_region32_init (®); 556 if (!pixman_compute_composite_region32 (®, pSrc, pMask, pDst, 557 xSrc, ySrc, xMask, yMask, xDst, yDst, width, height)) 558 { 559 return; 560 } 561 562 region = ® 563 564 pbox = pixman_region32_rectangles (region, &n); 565 while (n--) 566 { 567 h = pbox->y2 - pbox->y1; 568 y_src = pbox->y1 - yDst + ySrc; 569 y_msk = pbox->y1 - yDst + yMask; 570 y_dst = pbox->y1; 571 while (h) 572 { 573 h_this = h; 574 w = pbox->x2 - pbox->x1; 575 x_src = pbox->x1 - xDst + xSrc; 576 x_msk = pbox->x1 - xDst + xMask; 577 x_dst = pbox->x1; 578 if (maskRepeat) 579 { 580 y_msk = MOD (y_msk, pMask->bits.height); 581 if (h_this > pMask->bits.height - y_msk) 582 h_this = pMask->bits.height - y_msk; 583 } 584 if (srcRepeat) 585 { 586 y_src = MOD (y_src, pSrc->bits.height); 587 if (h_this > pSrc->bits.height - y_src) 588 h_this = pSrc->bits.height - y_src; 589 } 590 while (w) 591 { 592 w_this = w; 593 if (maskRepeat) 594 { 595 x_msk = MOD (x_msk, pMask->bits.width); 596 if (w_this > pMask->bits.width - x_msk) 597 w_this = pMask->bits.width - x_msk; 598 } 599 if (srcRepeat) 600 { 601 x_src = MOD (x_src, pSrc->bits.width); 602 if (w_this > pSrc->bits.width - x_src) 603 w_this = pSrc->bits.width - x_src; 604 } 605 (*compositeRect) (imp, 606 op, pSrc, pMask, pDst, 607 x_src, y_src, x_msk, y_msk, x_dst, y_dst, 608 w_this, h_this); 609 w -= w_this; 610 x_src += w_this; 611 x_msk += w_this; 612 x_dst += w_this; 613 } 614 h -= h_this; 615 y_src += h_this; 616 y_msk += h_this; 617 y_dst += h_this; 618 } 619 pbox++; 620 } 621 pixman_region32_fini (®); 622} 623 624static pixman_bool_t 625mask_is_solid (pixman_image_t *mask) 626{ 627 if (mask->type == SOLID) 628 return TRUE; 629 630 if (mask->type == BITS && 631 mask->common.repeat == PIXMAN_REPEAT_NORMAL && 632 mask->bits.width == 1 && 633 mask->bits.height == 1) 634 { 635 return TRUE; 636 } 637 638 return FALSE; 639} 640 641static const FastPathInfo * 642get_fast_path (const FastPathInfo *fast_paths, 643 pixman_op_t op, 644 pixman_image_t *pSrc, 645 pixman_image_t *pMask, 646 pixman_image_t *pDst, 647 pixman_bool_t is_pixbuf) 648{ 649 const FastPathInfo *info; 650 651 for (info = fast_paths; info->op != PIXMAN_OP_NONE; info++) 652 { 653 pixman_bool_t valid_src = FALSE; 654 pixman_bool_t valid_mask = FALSE; 655 656 if (info->op != op) 657 continue; 658 659 if ((info->src_format == PIXMAN_solid && pixman_image_can_get_solid (pSrc)) || 660 (pSrc->type == BITS && info->src_format == pSrc->bits.format)) 661 { 662 valid_src = TRUE; 663 } 664 665 if (!valid_src) 666 continue; 667 668 if ((info->mask_format == PIXMAN_null && !pMask) || 669 (pMask && pMask->type == BITS && info->mask_format == pMask->bits.format)) 670 { 671 valid_mask = TRUE; 672 673 if (info->flags & NEED_SOLID_MASK) 674 { 675 if (!pMask || !mask_is_solid (pMask)) 676 valid_mask = FALSE; 677 } 678 679 if (info->flags & NEED_COMPONENT_ALPHA) 680 { 681 if (!pMask || !pMask->common.component_alpha) 682 valid_mask = FALSE; 683 } 684 } 685 686 if (!valid_mask) 687 continue; 688 689 if (info->dest_format != pDst->bits.format) 690 continue; 691 692 if ((info->flags & NEED_PIXBUF) && !is_pixbuf) 693 continue; 694 695 return info; 696 } 697 698 return NULL; 699} 700 701pixman_bool_t 702_pixman_run_fast_path (const FastPathInfo *paths, 703 pixman_implementation_t *imp, 704 pixman_op_t op, 705 pixman_image_t *src, 706 pixman_image_t *mask, 707 pixman_image_t *dest, 708 int32_t src_x, 709 int32_t src_y, 710 int32_t mask_x, 711 int32_t mask_y, 712 int32_t dest_x, 713 int32_t dest_y, 714 int32_t width, 715 int32_t height) 716{ 717 pixman_composite_func_t func = NULL; 718 pixman_bool_t src_repeat = src->common.repeat == PIXMAN_REPEAT_NORMAL; 719 pixman_bool_t mask_repeat = mask && mask->common.repeat == PIXMAN_REPEAT_NORMAL; 720 721 if ((src->type == BITS || pixman_image_can_get_solid (src)) && 722 (!mask || mask->type == BITS) 723 && !src->common.transform && !(mask && mask->common.transform) 724 && !(mask && mask->common.alpha_map) && !src->common.alpha_map && !dest->common.alpha_map 725 && (src->common.filter != PIXMAN_FILTER_CONVOLUTION) 726 && (src->common.repeat != PIXMAN_REPEAT_PAD) 727 && (src->common.repeat != PIXMAN_REPEAT_REFLECT) 728 && (!mask || (mask->common.filter != PIXMAN_FILTER_CONVOLUTION && 729 mask->common.repeat != PIXMAN_REPEAT_PAD && 730 mask->common.repeat != PIXMAN_REPEAT_REFLECT)) 731 && !src->common.read_func && !src->common.write_func 732 && !(mask && mask->common.read_func) 733 && !(mask && mask->common.write_func) 734 && !dest->common.read_func 735 && !dest->common.write_func) 736 { 737 const FastPathInfo *info; 738 pixman_bool_t pixbuf; 739 740 pixbuf = 741 src && src->type == BITS && 742 mask && mask->type == BITS && 743 src->bits.bits == mask->bits.bits && 744 src_x == mask_x && 745 src_y == mask_y && 746 !mask->common.component_alpha && 747 !mask_repeat; 748 749 info = get_fast_path (paths, op, src, mask, dest, pixbuf); 750 751 if (info) 752 { 753 func = info->func; 754 755 if (info->src_format == PIXMAN_solid) 756 src_repeat = FALSE; 757 758 if (info->mask_format == PIXMAN_solid || info->flags & NEED_SOLID_MASK) 759 mask_repeat = FALSE; 760 761 if ((src_repeat && 762 src->bits.width == 1 && 763 src->bits.height == 1) || 764 (mask_repeat && 765 mask->bits.width == 1 && 766 mask->bits.height == 1)) 767 { 768 /* If src or mask are repeating 1x1 images and src_repeat or 769 * mask_repeat are still TRUE, it means the fast path we 770 * selected does not actually handle repeating images. 771 * 772 * So rather than call the "fast path" with a zillion 773 * 1x1 requests, we just fall back to the general code (which 774 * does do something sensible with 1x1 repeating images). 775 */ 776 func = NULL; 777 } 778 } 779 } 780 781 if (func) 782 { 783 _pixman_walk_composite_region (imp, op, 784 src, mask, dest, 785 src_x, src_y, mask_x, mask_y, 786 dest_x, dest_y, 787 width, height, 788 src_repeat, mask_repeat, 789 func); 790 return TRUE; 791 } 792 793 return FALSE; 794} 795