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