pixman.c (37021B)
1 /* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */ 2 /* 3 * Copyright © 2000 SuSE, Inc. 4 * Copyright © 2007 Red Hat, Inc. 5 * 6 * Permission to use, copy, modify, distribute, and sell this software and its 7 * documentation for any purpose is hereby granted without fee, provided that 8 * the above copyright notice appear in all copies and that both that 9 * copyright notice and this permission notice appear in supporting 10 * documentation, and that the name of SuSE not be used in advertising or 11 * publicity pertaining to distribution of the software without specific, 12 * written prior permission. SuSE makes no representations about the 13 * suitability of this software for any purpose. It is provided "as is" 14 * without express or implied warranty. 15 * 16 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 * 23 * Author: Keith Packard, SuSE, Inc. 24 */ 25 26 #ifdef HAVE_CONFIG_H 27 #include <pixman-config.h> 28 #endif 29 #include "pixman-private.h" 30 31 #include <stdlib.h> 32 33 pixman_implementation_t *global_implementation; 34 35 #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR 36 static void __attribute__((constructor)) 37 pixman_constructor (void) 38 { 39 global_implementation = _pixman_choose_implementation (); 40 } 41 #endif 42 43 #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_DESTRUCTOR 44 static void __attribute__((destructor)) 45 pixman_destructor (void) 46 { 47 pixman_implementation_t *imp = global_implementation; 48 49 while (imp) 50 { 51 pixman_implementation_t *cur = imp; 52 imp = imp->fallback; 53 free (cur); 54 } 55 } 56 #endif 57 58 typedef struct operator_info_t operator_info_t; 59 60 struct operator_info_t 61 { 62 uint8_t opaque_info[4]; 63 }; 64 65 #define PACK(neither, src, dest, both) \ 66 {{ (uint8_t)PIXMAN_OP_ ## neither, \ 67 (uint8_t)PIXMAN_OP_ ## src, \ 68 (uint8_t)PIXMAN_OP_ ## dest, \ 69 (uint8_t)PIXMAN_OP_ ## both }} 70 71 static const operator_info_t operator_table[] = 72 { 73 /* Neither Opaque Src Opaque Dst Opaque Both Opaque */ 74 PACK (CLEAR, CLEAR, CLEAR, CLEAR), 75 PACK (SRC, SRC, SRC, SRC), 76 PACK (DST, DST, DST, DST), 77 PACK (OVER, SRC, OVER, SRC), 78 PACK (OVER_REVERSE, OVER_REVERSE, DST, DST), 79 PACK (IN, IN, SRC, SRC), 80 PACK (IN_REVERSE, DST, IN_REVERSE, DST), 81 PACK (OUT, OUT, CLEAR, CLEAR), 82 PACK (OUT_REVERSE, CLEAR, OUT_REVERSE, CLEAR), 83 PACK (ATOP, IN, OVER, SRC), 84 PACK (ATOP_REVERSE, OVER_REVERSE, IN_REVERSE, DST), 85 PACK (XOR, OUT, OUT_REVERSE, CLEAR), 86 PACK (ADD, ADD, ADD, ADD), 87 PACK (SATURATE, OVER_REVERSE, DST, DST), 88 89 {{ 0 /* 0x0e */ }}, 90 {{ 0 /* 0x0f */ }}, 91 92 PACK (CLEAR, CLEAR, CLEAR, CLEAR), 93 PACK (SRC, SRC, SRC, SRC), 94 PACK (DST, DST, DST, DST), 95 PACK (DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER), 96 PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE), 97 PACK (DISJOINT_IN, DISJOINT_IN, DISJOINT_IN, DISJOINT_IN), 98 PACK (DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE), 99 PACK (DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT), 100 PACK (DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE), 101 PACK (DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP), 102 PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE), 103 PACK (DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR), 104 105 {{ 0 /* 0x1c */ }}, 106 {{ 0 /* 0x1d */ }}, 107 {{ 0 /* 0x1e */ }}, 108 {{ 0 /* 0x1f */ }}, 109 110 PACK (CLEAR, CLEAR, CLEAR, CLEAR), 111 PACK (SRC, SRC, SRC, SRC), 112 PACK (DST, DST, DST, DST), 113 PACK (CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER), 114 PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE), 115 PACK (CONJOINT_IN, CONJOINT_IN, CONJOINT_IN, CONJOINT_IN), 116 PACK (CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE), 117 PACK (CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT), 118 PACK (CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE), 119 PACK (CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP), 120 PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE), 121 PACK (CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR), 122 123 {{ 0 /* 0x2c */ }}, 124 {{ 0 /* 0x2d */ }}, 125 {{ 0 /* 0x2e */ }}, 126 {{ 0 /* 0x2f */ }}, 127 128 PACK (MULTIPLY, MULTIPLY, MULTIPLY, MULTIPLY), 129 PACK (SCREEN, SCREEN, SCREEN, SCREEN), 130 PACK (OVERLAY, OVERLAY, OVERLAY, OVERLAY), 131 PACK (DARKEN, DARKEN, DARKEN, DARKEN), 132 PACK (LIGHTEN, LIGHTEN, LIGHTEN, LIGHTEN), 133 PACK (COLOR_DODGE, COLOR_DODGE, COLOR_DODGE, COLOR_DODGE), 134 PACK (COLOR_BURN, COLOR_BURN, COLOR_BURN, COLOR_BURN), 135 PACK (HARD_LIGHT, HARD_LIGHT, HARD_LIGHT, HARD_LIGHT), 136 PACK (SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT), 137 PACK (DIFFERENCE, DIFFERENCE, DIFFERENCE, DIFFERENCE), 138 PACK (EXCLUSION, EXCLUSION, EXCLUSION, EXCLUSION), 139 PACK (HSL_HUE, HSL_HUE, HSL_HUE, HSL_HUE), 140 PACK (HSL_SATURATION, HSL_SATURATION, HSL_SATURATION, HSL_SATURATION), 141 PACK (HSL_COLOR, HSL_COLOR, HSL_COLOR, HSL_COLOR), 142 PACK (HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY), 143 }; 144 145 /* 146 * Optimize the current operator based on opacity of source or destination 147 * The output operator should be mathematically equivalent to the source. 148 */ 149 static pixman_op_t 150 optimize_operator (pixman_op_t op, 151 uint32_t src_flags, 152 uint32_t mask_flags, 153 uint32_t dst_flags) 154 { 155 pixman_bool_t is_source_opaque, is_dest_opaque; 156 157 #define OPAQUE_SHIFT 13 158 159 COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT)); 160 161 is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE); 162 is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE); 163 164 is_dest_opaque >>= OPAQUE_SHIFT - 1; 165 is_source_opaque >>= OPAQUE_SHIFT; 166 167 return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque]; 168 } 169 170 /* 171 * Computing composite region 172 */ 173 static inline pixman_bool_t 174 clip_general_image (pixman_region32_t * region, 175 pixman_region32_t * clip, 176 int dx, 177 int dy) 178 { 179 if (pixman_region32_n_rects (region) == 1 && 180 pixman_region32_n_rects (clip) == 1) 181 { 182 pixman_box32_t * rbox = pixman_region32_rectangles (region, NULL); 183 pixman_box32_t * cbox = pixman_region32_rectangles (clip, NULL); 184 int v; 185 186 if (rbox->x1 < (v = cbox->x1 + dx)) 187 rbox->x1 = v; 188 if (rbox->x2 > (v = cbox->x2 + dx)) 189 rbox->x2 = v; 190 if (rbox->y1 < (v = cbox->y1 + dy)) 191 rbox->y1 = v; 192 if (rbox->y2 > (v = cbox->y2 + dy)) 193 rbox->y2 = v; 194 if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2) 195 { 196 pixman_region32_init (region); 197 return FALSE; 198 } 199 } 200 else if (pixman_region32_empty (clip)) 201 { 202 return FALSE; 203 } 204 else 205 { 206 if (dx || dy) 207 pixman_region32_translate (region, -dx, -dy); 208 209 if (!pixman_region32_intersect (region, region, clip)) 210 return FALSE; 211 212 if (dx || dy) 213 pixman_region32_translate (region, dx, dy); 214 } 215 216 return pixman_region32_not_empty (region); 217 } 218 219 static inline pixman_bool_t 220 clip_source_image (pixman_region32_t * region, 221 pixman_image_t * image, 222 int dx, 223 int dy) 224 { 225 /* Source clips are ignored, unless they are explicitly turned on 226 * and the clip in question was set by an X client. (Because if 227 * the clip was not set by a client, then it is a hierarchy 228 * clip and those should always be ignored for sources). 229 */ 230 if (!image->common.clip_sources || !image->common.client_clip) 231 return TRUE; 232 233 return clip_general_image (region, 234 &image->common.clip_region, 235 dx, dy); 236 } 237 238 /* 239 * returns FALSE if the final region is empty. Indistinguishable from 240 * an allocation failure, but rendering ignores those anyways. 241 */ 242 pixman_bool_t 243 _pixman_compute_composite_region32 (pixman_region32_t * region, 244 pixman_image_t * src_image, 245 pixman_image_t * mask_image, 246 pixman_image_t * dest_image, 247 int32_t src_x, 248 int32_t src_y, 249 int32_t mask_x, 250 int32_t mask_y, 251 int32_t dest_x, 252 int32_t dest_y, 253 int32_t width, 254 int32_t height) 255 { 256 region->extents.x1 = dest_x; 257 region->extents.x2 = dest_x + width; 258 region->extents.y1 = dest_y; 259 region->extents.y2 = dest_y + height; 260 261 region->extents.x1 = MAX (region->extents.x1, 0); 262 region->extents.y1 = MAX (region->extents.y1, 0); 263 region->extents.x2 = MIN (region->extents.x2, dest_image->bits.width); 264 region->extents.y2 = MIN (region->extents.y2, dest_image->bits.height); 265 266 region->data = 0; 267 268 /* Check for empty operation */ 269 if (region->extents.x1 >= region->extents.x2 || 270 region->extents.y1 >= region->extents.y2) 271 { 272 region->extents.x1 = 0; 273 region->extents.x2 = 0; 274 region->extents.y1 = 0; 275 region->extents.y2 = 0; 276 return FALSE; 277 } 278 279 if (dest_image->common.have_clip_region) 280 { 281 if (!clip_general_image (region, &dest_image->common.clip_region, 0, 0)) 282 return FALSE; 283 } 284 285 if (dest_image->common.alpha_map) 286 { 287 if (!pixman_region32_intersect_rect (region, region, 288 dest_image->common.alpha_origin_x, 289 dest_image->common.alpha_origin_y, 290 dest_image->common.alpha_map->width, 291 dest_image->common.alpha_map->height)) 292 { 293 return FALSE; 294 } 295 if (pixman_region32_empty (region)) 296 return FALSE; 297 if (dest_image->common.alpha_map->common.have_clip_region) 298 { 299 if (!clip_general_image (region, &dest_image->common.alpha_map->common.clip_region, 300 -dest_image->common.alpha_origin_x, 301 -dest_image->common.alpha_origin_y)) 302 { 303 return FALSE; 304 } 305 } 306 } 307 308 /* clip against src */ 309 if (src_image->common.have_clip_region) 310 { 311 if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y)) 312 return FALSE; 313 } 314 if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region) 315 { 316 if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map, 317 dest_x - (src_x - src_image->common.alpha_origin_x), 318 dest_y - (src_y - src_image->common.alpha_origin_y))) 319 { 320 return FALSE; 321 } 322 } 323 /* clip against mask */ 324 if (mask_image && mask_image->common.have_clip_region) 325 { 326 if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y)) 327 return FALSE; 328 329 if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region) 330 { 331 if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map, 332 dest_x - (mask_x - mask_image->common.alpha_origin_x), 333 dest_y - (mask_y - mask_image->common.alpha_origin_y))) 334 { 335 return FALSE; 336 } 337 } 338 } 339 340 return TRUE; 341 } 342 343 typedef struct box_48_16 box_48_16_t; 344 345 struct box_48_16 346 { 347 pixman_fixed_48_16_t x1; 348 pixman_fixed_48_16_t y1; 349 pixman_fixed_48_16_t x2; 350 pixman_fixed_48_16_t y2; 351 }; 352 353 static pixman_bool_t 354 compute_transformed_extents (pixman_transform_t *transform, 355 const pixman_box32_t *extents, 356 box_48_16_t *transformed) 357 { 358 pixman_fixed_48_16_t tx1, ty1, tx2, ty2; 359 pixman_fixed_t x1, y1, x2, y2; 360 int i; 361 362 x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2; 363 y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2; 364 x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2; 365 y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2; 366 367 if (!transform) 368 { 369 transformed->x1 = x1; 370 transformed->y1 = y1; 371 transformed->x2 = x2; 372 transformed->y2 = y2; 373 374 return TRUE; 375 } 376 377 tx1 = ty1 = INT64_MAX; 378 tx2 = ty2 = INT64_MIN; 379 380 for (i = 0; i < 4; ++i) 381 { 382 pixman_fixed_48_16_t tx, ty; 383 pixman_vector_t v; 384 385 v.vector[0] = (i & 0x01)? x1 : x2; 386 v.vector[1] = (i & 0x02)? y1 : y2; 387 v.vector[2] = pixman_fixed_1; 388 389 if (!pixman_transform_point (transform, &v)) 390 return FALSE; 391 392 tx = (pixman_fixed_48_16_t)v.vector[0]; 393 ty = (pixman_fixed_48_16_t)v.vector[1]; 394 395 if (tx < tx1) 396 tx1 = tx; 397 if (ty < ty1) 398 ty1 = ty; 399 if (tx > tx2) 400 tx2 = tx; 401 if (ty > ty2) 402 ty2 = ty; 403 } 404 405 transformed->x1 = tx1; 406 transformed->y1 = ty1; 407 transformed->x2 = tx2; 408 transformed->y2 = ty2; 409 410 return TRUE; 411 } 412 413 #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX)) 414 #define ABS(f) (((f) < 0)? (-(f)) : (f)) 415 #define IS_16_16(f) (((f) >= pixman_min_fixed_48_16 && ((f) <= pixman_max_fixed_48_16))) 416 417 static pixman_bool_t 418 analyze_extent (pixman_image_t *image, 419 const pixman_box32_t *extents, 420 uint32_t *flags) 421 { 422 pixman_transform_t *transform; 423 pixman_fixed_t x_off, y_off; 424 pixman_fixed_t width, height; 425 pixman_fixed_t *params; 426 box_48_16_t transformed; 427 pixman_box32_t exp_extents; 428 429 if (!image) 430 return TRUE; 431 432 /* Some compositing functions walk one step 433 * outside the destination rectangle, so we 434 * check here that the expanded-by-one source 435 * extents in destination space fits in 16 bits 436 */ 437 if (!IS_16BIT (extents->x1 - 1) || 438 !IS_16BIT (extents->y1 - 1) || 439 !IS_16BIT (extents->x2 + 1) || 440 !IS_16BIT (extents->y2 + 1)) 441 { 442 return FALSE; 443 } 444 445 transform = image->common.transform; 446 if (image->common.type == BITS) 447 { 448 /* During repeat mode calculations we might convert the 449 * width/height of an image to fixed 16.16, so we need 450 * them to be smaller than 16 bits. 451 */ 452 if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff) 453 return FALSE; 454 455 if ((image->common.flags & FAST_PATH_ID_TRANSFORM) == FAST_PATH_ID_TRANSFORM && 456 extents->x1 >= 0 && 457 extents->y1 >= 0 && 458 extents->x2 <= image->bits.width && 459 extents->y2 <= image->bits.height) 460 { 461 *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; 462 return TRUE; 463 } 464 465 switch (image->common.filter) 466 { 467 case PIXMAN_FILTER_CONVOLUTION: 468 params = image->common.filter_params; 469 x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1); 470 y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1); 471 width = params[0]; 472 height = params[1]; 473 break; 474 475 case PIXMAN_FILTER_SEPARABLE_CONVOLUTION: 476 params = image->common.filter_params; 477 x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1); 478 y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1); 479 width = params[0]; 480 height = params[1]; 481 break; 482 483 case PIXMAN_FILTER_GOOD: 484 case PIXMAN_FILTER_BEST: 485 case PIXMAN_FILTER_BILINEAR: 486 x_off = - pixman_fixed_1 / 2; 487 y_off = - pixman_fixed_1 / 2; 488 width = pixman_fixed_1; 489 height = pixman_fixed_1; 490 break; 491 492 case PIXMAN_FILTER_FAST: 493 case PIXMAN_FILTER_NEAREST: 494 x_off = - pixman_fixed_e; 495 y_off = - pixman_fixed_e; 496 width = 0; 497 height = 0; 498 break; 499 500 default: 501 return FALSE; 502 } 503 } 504 else 505 { 506 x_off = 0; 507 y_off = 0; 508 width = 0; 509 height = 0; 510 } 511 512 if (!compute_transformed_extents (transform, extents, &transformed)) 513 return FALSE; 514 515 if (image->common.type == BITS) 516 { 517 if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_e) >= 0 && 518 pixman_fixed_to_int (transformed.y1 - pixman_fixed_e) >= 0 && 519 pixman_fixed_to_int (transformed.x2 - pixman_fixed_e) < image->bits.width && 520 pixman_fixed_to_int (transformed.y2 - pixman_fixed_e) < image->bits.height) 521 { 522 *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; 523 } 524 525 if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_1 / 2) >= 0 && 526 pixman_fixed_to_int (transformed.y1 - pixman_fixed_1 / 2) >= 0 && 527 pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2) < image->bits.width && 528 pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2) < image->bits.height) 529 { 530 *flags |= FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR; 531 } 532 } 533 534 /* Check we don't overflow when the destination extents are expanded by one. 535 * This ensures that compositing functions can simply walk the source space 536 * using 16.16 variables without worrying about overflow. 537 */ 538 exp_extents = *extents; 539 exp_extents.x1 -= 1; 540 exp_extents.y1 -= 1; 541 exp_extents.x2 += 1; 542 exp_extents.y2 += 1; 543 544 if (!compute_transformed_extents (transform, &exp_extents, &transformed)) 545 return FALSE; 546 547 if (!IS_16_16 (transformed.x1 + x_off - 8 * pixman_fixed_e) || 548 !IS_16_16 (transformed.y1 + y_off - 8 * pixman_fixed_e) || 549 !IS_16_16 (transformed.x2 + x_off + 8 * pixman_fixed_e + width) || 550 !IS_16_16 (transformed.y2 + y_off + 8 * pixman_fixed_e + height)) 551 { 552 return FALSE; 553 } 554 555 return TRUE; 556 } 557 558 /* 559 * Work around GCC bug causing crashes in Mozilla with SSE2 560 * 561 * When using -msse, gcc generates movdqa instructions assuming that 562 * the stack is 16 byte aligned. Unfortunately some applications, such 563 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which 564 * causes the movdqa instructions to fail. 565 * 566 * The __force_align_arg_pointer__ makes gcc generate a prologue that 567 * realigns the stack pointer to 16 bytes. 568 * 569 * On x86-64 this is not necessary because the standard ABI already 570 * calls for a 16 byte aligned stack. 571 * 572 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693 573 */ 574 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) 575 __attribute__((__force_align_arg_pointer__)) 576 #endif 577 PIXMAN_EXPORT void 578 pixman_image_composite32 (pixman_op_t op, 579 pixman_image_t * src, 580 pixman_image_t * mask, 581 pixman_image_t * dest, 582 int32_t src_x, 583 int32_t src_y, 584 int32_t mask_x, 585 int32_t mask_y, 586 int32_t dest_x, 587 int32_t dest_y, 588 int32_t width, 589 int32_t height) 590 { 591 pixman_format_code_t src_format, mask_format, dest_format; 592 pixman_region32_t region; 593 pixman_box32_t extents; 594 pixman_implementation_t *imp; 595 pixman_composite_func_t func; 596 pixman_composite_info_t info; 597 const pixman_box32_t *pbox; 598 int n; 599 600 _pixman_image_validate (src); 601 if (mask) 602 _pixman_image_validate (mask); 603 _pixman_image_validate (dest); 604 605 src_format = src->common.extended_format_code; 606 info.src_flags = src->common.flags; 607 608 if (mask && !(mask->common.flags & FAST_PATH_IS_OPAQUE)) 609 { 610 mask_format = mask->common.extended_format_code; 611 info.mask_flags = mask->common.flags; 612 } 613 else 614 { 615 mask_format = PIXMAN_null; 616 info.mask_flags = FAST_PATH_IS_OPAQUE | FAST_PATH_NO_ALPHA_MAP; 617 } 618 619 dest_format = dest->common.extended_format_code; 620 info.dest_flags = dest->common.flags; 621 622 /* Check for pixbufs */ 623 if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) && 624 (src->type == BITS && src->bits.bits == mask->bits.bits) && 625 (src->common.repeat == mask->common.repeat) && 626 (info.src_flags & info.mask_flags & FAST_PATH_ID_TRANSFORM) && 627 (src_x == mask_x && src_y == mask_y)) 628 { 629 if (src_format == PIXMAN_x8b8g8r8) 630 src_format = mask_format = PIXMAN_pixbuf; 631 else if (src_format == PIXMAN_x8r8g8b8) 632 src_format = mask_format = PIXMAN_rpixbuf; 633 } 634 635 pixman_region32_init (®ion); 636 637 if (!_pixman_compute_composite_region32 ( 638 ®ion, src, mask, dest, 639 src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height)) 640 { 641 goto out; 642 } 643 644 extents = *pixman_region32_extents (®ion); 645 646 extents.x1 -= dest_x - src_x; 647 extents.y1 -= dest_y - src_y; 648 extents.x2 -= dest_x - src_x; 649 extents.y2 -= dest_y - src_y; 650 651 if (!analyze_extent (src, &extents, &info.src_flags)) 652 goto out; 653 654 extents.x1 -= src_x - mask_x; 655 extents.y1 -= src_y - mask_y; 656 extents.x2 -= src_x - mask_x; 657 extents.y2 -= src_y - mask_y; 658 659 if (!analyze_extent (mask, &extents, &info.mask_flags)) 660 goto out; 661 662 /* If the clip is within the source samples, and the samples are 663 * opaque, then the source is effectively opaque. 664 */ 665 #define NEAREST_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \ 666 FAST_PATH_NEAREST_FILTER | \ 667 FAST_PATH_SAMPLES_COVER_CLIP_NEAREST) 668 #define BILINEAR_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \ 669 FAST_PATH_BILINEAR_FILTER | \ 670 FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR) 671 672 if ((info.src_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE || 673 (info.src_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE) 674 { 675 info.src_flags |= FAST_PATH_IS_OPAQUE; 676 } 677 678 if ((info.mask_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE || 679 (info.mask_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE) 680 { 681 info.mask_flags |= FAST_PATH_IS_OPAQUE; 682 } 683 684 /* 685 * Check if we can replace our operator by a simpler one 686 * if the src or dest are opaque. The output operator should be 687 * mathematically equivalent to the source. 688 */ 689 info.op = optimize_operator (op, info.src_flags, info.mask_flags, info.dest_flags); 690 691 _pixman_implementation_lookup_composite ( 692 get_implementation (), info.op, 693 src_format, info.src_flags, 694 mask_format, info.mask_flags, 695 dest_format, info.dest_flags, 696 &imp, &func); 697 698 info.src_image = src; 699 info.mask_image = mask; 700 info.dest_image = dest; 701 702 pbox = pixman_region32_rectangles (®ion, &n); 703 704 while (n--) 705 { 706 info.src_x = pbox->x1 + src_x - dest_x; 707 info.src_y = pbox->y1 + src_y - dest_y; 708 info.mask_x = pbox->x1 + mask_x - dest_x; 709 info.mask_y = pbox->y1 + mask_y - dest_y; 710 info.dest_x = pbox->x1; 711 info.dest_y = pbox->y1; 712 info.width = pbox->x2 - pbox->x1; 713 info.height = pbox->y2 - pbox->y1; 714 715 func (imp, &info); 716 717 pbox++; 718 } 719 720 out: 721 pixman_region32_fini (®ion); 722 } 723 724 PIXMAN_EXPORT void 725 pixman_image_composite (pixman_op_t op, 726 pixman_image_t * src, 727 pixman_image_t * mask, 728 pixman_image_t * dest, 729 int16_t src_x, 730 int16_t src_y, 731 int16_t mask_x, 732 int16_t mask_y, 733 int16_t dest_x, 734 int16_t dest_y, 735 uint16_t width, 736 uint16_t height) 737 { 738 pixman_image_composite32 (op, src, mask, dest, src_x, src_y, 739 mask_x, mask_y, dest_x, dest_y, width, height); 740 } 741 742 PIXMAN_EXPORT void 743 pixman_image_composite64f (pixman_op_t op, 744 pixman_image_t * src, 745 pixman_image_t * mask, 746 pixman_image_t * dest, 747 double src_x, 748 double src_y, 749 double mask_x, 750 double mask_y, 751 double dest_x, 752 double dest_y, 753 double width, 754 double height) 755 { 756 pixman_image_composite32 (op, src, mask, dest, src_x, src_y, 757 mask_x, mask_y, dest_x, dest_y, width, height); 758 } 759 760 PIXMAN_EXPORT pixman_bool_t 761 pixman_blt (uint32_t *src_bits, 762 uint32_t *dst_bits, 763 int src_stride, 764 int dst_stride, 765 int src_bpp, 766 int dst_bpp, 767 int src_x, 768 int src_y, 769 int dest_x, 770 int dest_y, 771 int width, 772 int height) 773 { 774 return _pixman_implementation_blt (get_implementation(), 775 src_bits, dst_bits, src_stride, dst_stride, 776 src_bpp, dst_bpp, 777 src_x, src_y, 778 dest_x, dest_y, 779 width, height); 780 } 781 782 PIXMAN_EXPORT pixman_bool_t 783 pixman_fill (uint32_t *bits, 784 int stride, 785 int bpp, 786 int x, 787 int y, 788 int width, 789 int height, 790 uint32_t filler) 791 { 792 return _pixman_implementation_fill ( 793 get_implementation(), bits, stride, bpp, x, y, width, height, filler); 794 } 795 796 static uint32_t 797 color_to_uint32 (const pixman_color_t *color) 798 { 799 return 800 (color->alpha >> 8 << 24) | 801 (color->red >> 8 << 16) | 802 (color->green & 0xff00) | 803 (color->blue >> 8); 804 } 805 806 static pixman_bool_t 807 color_to_pixel (const pixman_color_t *color, 808 uint32_t * pixel, 809 pixman_format_code_t format) 810 { 811 uint32_t c = color_to_uint32 (color); 812 813 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA_FLOAT) 814 { 815 return FALSE; 816 } 817 818 if (!(format == PIXMAN_a8r8g8b8 || 819 format == PIXMAN_x8r8g8b8 || 820 format == PIXMAN_a8b8g8r8 || 821 format == PIXMAN_x8b8g8r8 || 822 format == PIXMAN_b8g8r8a8 || 823 format == PIXMAN_b8g8r8x8 || 824 format == PIXMAN_r8g8b8a8 || 825 format == PIXMAN_r8g8b8x8 || 826 format == PIXMAN_r5g6b5 || 827 format == PIXMAN_b5g6r5 || 828 format == PIXMAN_a8 || 829 format == PIXMAN_a1)) 830 { 831 return FALSE; 832 } 833 834 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR) 835 { 836 c = ((c & 0xff000000) >> 0) | 837 ((c & 0x00ff0000) >> 16) | 838 ((c & 0x0000ff00) >> 0) | 839 ((c & 0x000000ff) << 16); 840 } 841 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA) 842 { 843 c = ((c & 0xff000000) >> 24) | 844 ((c & 0x00ff0000) >> 8) | 845 ((c & 0x0000ff00) << 8) | 846 ((c & 0x000000ff) << 24); 847 } 848 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA) 849 c = ((c & 0xff000000) >> 24) | (c << 8); 850 851 if (format == PIXMAN_a1) 852 c = c >> 31; 853 else if (format == PIXMAN_a8) 854 c = c >> 24; 855 else if (format == PIXMAN_r5g6b5 || 856 format == PIXMAN_b5g6r5) 857 c = convert_8888_to_0565 (c); 858 859 #if 0 860 printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue); 861 printf ("pixel: %x\n", c); 862 #endif 863 864 *pixel = c; 865 return TRUE; 866 } 867 868 PIXMAN_EXPORT pixman_bool_t 869 pixman_image_fill_rectangles (pixman_op_t op, 870 pixman_image_t * dest, 871 const pixman_color_t * color, 872 int n_rects, 873 const pixman_rectangle16_t *rects) 874 { 875 pixman_box32_t stack_boxes[6] = {0}; 876 pixman_box32_t *boxes; 877 pixman_bool_t result; 878 int i; 879 880 if (n_rects > 6) 881 { 882 boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects); 883 if (boxes == NULL) 884 return FALSE; 885 } 886 else 887 { 888 boxes = stack_boxes; 889 } 890 891 for (i = 0; i < n_rects; ++i) 892 { 893 boxes[i].x1 = rects[i].x; 894 boxes[i].y1 = rects[i].y; 895 boxes[i].x2 = boxes[i].x1 + rects[i].width; 896 boxes[i].y2 = boxes[i].y1 + rects[i].height; 897 } 898 899 result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes); 900 901 if (boxes != stack_boxes) 902 free (boxes); 903 904 return result; 905 } 906 907 PIXMAN_EXPORT pixman_bool_t 908 pixman_image_fill_boxes (pixman_op_t op, 909 pixman_image_t * dest, 910 const pixman_color_t *color, 911 int n_boxes, 912 const pixman_box32_t *boxes) 913 { 914 pixman_image_t *solid; 915 pixman_color_t c; 916 int i; 917 918 _pixman_image_validate (dest); 919 920 if (color->alpha == 0xffff) 921 { 922 if (op == PIXMAN_OP_OVER) 923 op = PIXMAN_OP_SRC; 924 } 925 926 if (op == PIXMAN_OP_CLEAR) 927 { 928 c.red = 0; 929 c.green = 0; 930 c.blue = 0; 931 c.alpha = 0; 932 933 color = &c; 934 935 op = PIXMAN_OP_SRC; 936 } 937 938 if (op == PIXMAN_OP_SRC) 939 { 940 uint32_t pixel; 941 942 if (color_to_pixel (color, &pixel, dest->bits.format)) 943 { 944 pixman_region32_t fill_region; 945 int n_rects, j; 946 pixman_box32_t *rects; 947 948 if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes)) 949 return FALSE; 950 951 if (dest->common.have_clip_region) 952 { 953 if (!pixman_region32_intersect (&fill_region, 954 &fill_region, 955 &dest->common.clip_region)) 956 return FALSE; 957 } 958 959 rects = pixman_region32_rectangles (&fill_region, &n_rects); 960 for (j = 0; j < n_rects; ++j) 961 { 962 const pixman_box32_t *rect = &(rects[j]); 963 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format), 964 rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1, 965 pixel); 966 } 967 968 pixman_region32_fini (&fill_region); 969 return TRUE; 970 } 971 } 972 973 solid = pixman_image_create_solid_fill (color); 974 if (!solid) 975 return FALSE; 976 977 for (i = 0; i < n_boxes; ++i) 978 { 979 const pixman_box32_t *box = &(boxes[i]); 980 981 pixman_image_composite32 (op, solid, NULL, dest, 982 0, 0, 0, 0, 983 box->x1, box->y1, 984 box->x2 - box->x1, box->y2 - box->y1); 985 } 986 987 pixman_image_unref (solid); 988 989 return TRUE; 990 } 991 992 /** 993 * pixman_version: 994 * 995 * Returns the version of the pixman library encoded in a single 996 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that 997 * later versions compare greater than earlier versions. 998 * 999 * A run-time comparison to check that pixman's version is greater than 1000 * or equal to version X.Y.Z could be performed as follows: 1001 * 1002 * <informalexample><programlisting> 1003 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...} 1004 * </programlisting></informalexample> 1005 * 1006 * See also pixman_version_string() as well as the compile-time 1007 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING. 1008 * 1009 * Return value: the encoded version. 1010 **/ 1011 PIXMAN_EXPORT int 1012 pixman_version (void) 1013 { 1014 return PIXMAN_VERSION; 1015 } 1016 1017 /** 1018 * pixman_version_string: 1019 * 1020 * Returns the version of the pixman library as a human-readable string 1021 * of the form "X.Y.Z". 1022 * 1023 * See also pixman_version() as well as the compile-time equivalents 1024 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION. 1025 * 1026 * Return value: a string containing the version. 1027 **/ 1028 PIXMAN_EXPORT const char* 1029 pixman_version_string (void) 1030 { 1031 return PIXMAN_VERSION_STRING; 1032 } 1033 1034 /** 1035 * pixman_format_supported_source: 1036 * @format: A pixman_format_code_t format 1037 * 1038 * Return value: whether the provided format code is a supported 1039 * format for a pixman surface used as a source in 1040 * rendering. 1041 * 1042 * Currently, all pixman_format_code_t values are supported. 1043 **/ 1044 PIXMAN_EXPORT pixman_bool_t 1045 pixman_format_supported_source (pixman_format_code_t format) 1046 { 1047 switch (format) 1048 { 1049 /* 32 bpp formats */ 1050 case PIXMAN_a2b10g10r10: 1051 case PIXMAN_x2b10g10r10: 1052 case PIXMAN_a2r10g10b10: 1053 case PIXMAN_x2r10g10b10: 1054 case PIXMAN_a8r8g8b8: 1055 case PIXMAN_a8r8g8b8_sRGB: 1056 case PIXMAN_r8g8b8_sRGB: 1057 case PIXMAN_x8r8g8b8: 1058 case PIXMAN_a8b8g8r8: 1059 case PIXMAN_x8b8g8r8: 1060 case PIXMAN_b8g8r8a8: 1061 case PIXMAN_b8g8r8x8: 1062 case PIXMAN_r8g8b8a8: 1063 case PIXMAN_r8g8b8x8: 1064 case PIXMAN_r8g8b8: 1065 case PIXMAN_b8g8r8: 1066 case PIXMAN_r5g6b5: 1067 case PIXMAN_b5g6r5: 1068 case PIXMAN_x14r6g6b6: 1069 /* 16 bpp formats */ 1070 case PIXMAN_a1r5g5b5: 1071 case PIXMAN_x1r5g5b5: 1072 case PIXMAN_a1b5g5r5: 1073 case PIXMAN_x1b5g5r5: 1074 case PIXMAN_a4r4g4b4: 1075 case PIXMAN_x4r4g4b4: 1076 case PIXMAN_a4b4g4r4: 1077 case PIXMAN_x4b4g4r4: 1078 /* 8bpp formats */ 1079 case PIXMAN_a8: 1080 case PIXMAN_r3g3b2: 1081 case PIXMAN_b2g3r3: 1082 case PIXMAN_a2r2g2b2: 1083 case PIXMAN_a2b2g2r2: 1084 case PIXMAN_c8: 1085 case PIXMAN_g8: 1086 case PIXMAN_x4a4: 1087 /* Collides with PIXMAN_c8 1088 case PIXMAN_x4c4: 1089 */ 1090 /* Collides with PIXMAN_g8 1091 case PIXMAN_x4g4: 1092 */ 1093 /* 4bpp formats */ 1094 case PIXMAN_a4: 1095 case PIXMAN_r1g2b1: 1096 case PIXMAN_b1g2r1: 1097 case PIXMAN_a1r1g1b1: 1098 case PIXMAN_a1b1g1r1: 1099 case PIXMAN_c4: 1100 case PIXMAN_g4: 1101 /* 1bpp formats */ 1102 case PIXMAN_a1: 1103 case PIXMAN_g1: 1104 /* YUV formats */ 1105 case PIXMAN_yuy2: 1106 case PIXMAN_yv12: 1107 return TRUE; 1108 1109 default: 1110 return FALSE; 1111 } 1112 } 1113 1114 /** 1115 * pixman_format_supported_destination: 1116 * @format: A pixman_format_code_t format 1117 * 1118 * Return value: whether the provided format code is a supported 1119 * format for a pixman surface used as a destination in 1120 * rendering. 1121 * 1122 * Currently, all pixman_format_code_t values are supported 1123 * except for the YUV formats. 1124 **/ 1125 PIXMAN_EXPORT pixman_bool_t 1126 pixman_format_supported_destination (pixman_format_code_t format) 1127 { 1128 /* YUV formats cannot be written to at the moment */ 1129 if (format == PIXMAN_yuy2 || format == PIXMAN_yv12) 1130 return FALSE; 1131 1132 return pixman_format_supported_source (format); 1133 } 1134 1135 PIXMAN_EXPORT pixman_bool_t 1136 pixman_compute_composite_region (pixman_region16_t * region, 1137 pixman_image_t * src_image, 1138 pixman_image_t * mask_image, 1139 pixman_image_t * dest_image, 1140 int16_t src_x, 1141 int16_t src_y, 1142 int16_t mask_x, 1143 int16_t mask_y, 1144 int16_t dest_x, 1145 int16_t dest_y, 1146 uint16_t width, 1147 uint16_t height) 1148 { 1149 pixman_region32_t r32; 1150 pixman_bool_t retval; 1151 1152 pixman_region32_init (&r32); 1153 1154 retval = _pixman_compute_composite_region32 ( 1155 &r32, src_image, mask_image, dest_image, 1156 src_x, src_y, mask_x, mask_y, dest_x, dest_y, 1157 width, height); 1158 1159 if (retval) 1160 { 1161 if (!pixman_region16_copy_from_region32 (region, &r32)) 1162 retval = FALSE; 1163 } 1164 1165 pixman_region32_fini (&r32); 1166 return retval; 1167 }