1 /* 2 * Copyright 2000 Keith Packard, member of The XFree86 Project, Inc. 3 * 2005 Lars Knoll & Zack Rusin, Trolltech 4 * 2008 Aaron Plattner, NVIDIA Corporation 5 * Copyright 2000 SuSE, Inc. 6 * Copyright 2007, 2009 Red Hat, Inc. 7 * Copyright 2008 Andr Tupinamb <andrelrt (at) gmail.com> 8 * 9 * Permission to use, copy, modify, distribute, and sell this software and its 10 * documentation for any purpose is hereby granted without fee, provided that 11 * the above copyright notice appear in all copies and that both that 12 * copyright notice and this permission notice appear in supporting 13 * documentation, and that the name of Keith Packard not be used in 14 * advertising or publicity pertaining to distribution of the software without 15 * specific, written prior permission. Keith Packard makes no 16 * representations about the suitability of this software for any purpose. It 17 * is provided "as is" without express or implied warranty. 18 * 19 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 20 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 24 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 25 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 26 * SOFTWARE. 27 */ 28 29 #ifdef HAVE_CONFIG_H 30 #include <config.h> 31 #endif 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include "pixman-private.h" 36 #include "pixman-combine32.h" 37 #include "pixman-inlines.h" 38 39 static uint32_t * 40 _pixman_image_get_scanline_generic_float (pixman_iter_t * iter, 41 const uint32_t *mask) 42 { 43 pixman_iter_get_scanline_t fetch_32 = iter->data; 44 uint32_t *buffer = iter->buffer; 45 46 fetch_32 (iter, NULL); 47 48 pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); 49 50 return iter->buffer; 51 } 52 53 /* Fetch functions */ 54 55 static force_inline uint32_t 56 fetch_pixel_no_alpha (bits_image_t *image, 57 int x, int y, pixman_bool_t check_bounds) 58 { 59 if (check_bounds && 60 (x < 0 || x >= image->width || y < 0 || y >= image->height)) 61 { 62 return 0; 63 } 64 65 return image->fetch_pixel_32 (image, x, y); 66 } 67 68 typedef uint32_t (* get_pixel_t) (bits_image_t *image, 69 int x, int y, pixman_bool_t check_bounds); 70 71 static force_inline uint32_t 72 bits_image_fetch_pixel_nearest (bits_image_t *image, 73 pixman_fixed_t x, 74 pixman_fixed_t y, 75 get_pixel_t get_pixel) 76 { 77 int x0 = pixman_fixed_to_int (x - pixman_fixed_e); 78 int y0 = pixman_fixed_to_int (y - pixman_fixed_e); 79 80 if (image->common.repeat != PIXMAN_REPEAT_NONE) 81 { 82 repeat (image->common.repeat, &x0, image->width); 83 repeat (image->common.repeat, &y0, image->height); 84 85 return get_pixel (image, x0, y0, FALSE); 86 } 87 else 88 { 89 return get_pixel (image, x0, y0, TRUE); 90 } 91 } 92 93 static force_inline uint32_t 94 bits_image_fetch_pixel_bilinear (bits_image_t *image, 95 pixman_fixed_t x, 96 pixman_fixed_t y, 97 get_pixel_t get_pixel) 98 { 99 pixman_repeat_t repeat_mode = image->common.repeat; 100 int width = image->width; 101 int height = image->height; 102 int x1, y1, x2, y2; 103 uint32_t tl, tr, bl, br; 104 int32_t distx, disty; 105 106 x1 = x - pixman_fixed_1 / 2; 107 y1 = y - pixman_fixed_1 / 2; 108 109 distx = pixman_fixed_to_bilinear_weight (x1); 110 disty = pixman_fixed_to_bilinear_weight (y1); 111 112 x1 = pixman_fixed_to_int (x1); 113 y1 = pixman_fixed_to_int (y1); 114 x2 = x1 + 1; 115 y2 = y1 + 1; 116 117 if (repeat_mode != PIXMAN_REPEAT_NONE) 118 { 119 repeat (repeat_mode, &x1, width); 120 repeat (repeat_mode, &y1, height); 121 repeat (repeat_mode, &x2, width); 122 repeat (repeat_mode, &y2, height); 123 124 tl = get_pixel (image, x1, y1, FALSE); 125 bl = get_pixel (image, x1, y2, FALSE); 126 tr = get_pixel (image, x2, y1, FALSE); 127 br = get_pixel (image, x2, y2, FALSE); 128 } 129 else 130 { 131 tl = get_pixel (image, x1, y1, TRUE); 132 tr = get_pixel (image, x2, y1, TRUE); 133 bl = get_pixel (image, x1, y2, TRUE); 134 br = get_pixel (image, x2, y2, TRUE); 135 } 136 137 return bilinear_interpolation (tl, tr, bl, br, distx, disty); 138 } 139 140 static uint32_t * 141 bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter, 142 const uint32_t *mask) 143 { 144 145 pixman_image_t * ima = iter->image; 146 int offset = iter->x; 147 int line = iter->y++; 148 int width = iter->width; 149 uint32_t * buffer = iter->buffer; 150 151 bits_image_t *bits = &ima->bits; 152 pixman_fixed_t x_top, x_bottom, x; 153 pixman_fixed_t ux_top, ux_bottom, ux; 154 pixman_vector_t v; 155 uint32_t top_mask, bottom_mask; 156 uint32_t *top_row; 157 uint32_t *bottom_row; 158 uint32_t *end; 159 uint32_t zero[2] = { 0, 0 }; 160 uint32_t one = 1; 161 int y, y1, y2; 162 int disty; 163 int mask_inc; 164 int w; 165 166 /* reference point is the center of the pixel */ 167 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; 168 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; 169 v.vector[2] = pixman_fixed_1; 170 171 if (!pixman_transform_point_3d (bits->common.transform, &v)) 172 return iter->buffer; 173 174 ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0]; 175 x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2; 176 177 y = v.vector[1] - pixman_fixed_1/2; 178 disty = pixman_fixed_to_bilinear_weight (y); 179 180 /* Load the pointers to the first and second lines from the source 181 * image that bilinear code must read. 182 * 183 * The main trick in this code is about the check if any line are 184 * outside of the image; 185 * 186 * When I realize that a line (any one) is outside, I change 187 * the pointer to a dummy area with zeros. Once I change this, I 188 * must be sure the pointer will not change, so I set the 189 * variables to each pointer increments inside the loop. 190 */ 191 y1 = pixman_fixed_to_int (y); 192 y2 = y1 + 1; 193 194 if (y1 < 0 || y1 >= bits->height) 195 { 196 top_row = zero; 197 x_top = 0; 198 ux_top = 0; 199 } 200 else 201 { 202 top_row = bits->bits + y1 * bits->rowstride; 203 x_top = x; 204 ux_top = ux; 205 } 206 207 if (y2 < 0 || y2 >= bits->height) 208 { 209 bottom_row = zero; 210 x_bottom = 0; 211 ux_bottom = 0; 212 } 213 else 214 { 215 bottom_row = bits->bits + y2 * bits->rowstride; 216 x_bottom = x; 217 ux_bottom = ux; 218 } 219 220 /* Instead of checking whether the operation uses the mast in 221 * each loop iteration, verify this only once and prepare the 222 * variables to make the code smaller inside the loop. 223 */ 224 if (!mask) 225 { 226 mask_inc = 0; 227 mask = &one; 228 } 229 else 230 { 231 /* If have a mask, prepare the variables to check it */ 232 mask_inc = 1; 233 } 234 235 /* If both are zero, then the whole thing is zero */ 236 if (top_row == zero && bottom_row == zero) 237 { 238 memset (buffer, 0, width * sizeof (uint32_t)); 239 return iter->buffer; 240 } 241 else if (bits->format == PIXMAN_x8r8g8b8) 242 { 243 if (top_row == zero) 244 { 245 top_mask = 0; 246 bottom_mask = 0xff000000; 247 } 248 else if (bottom_row == zero) 249 { 250 top_mask = 0xff000000; 251 bottom_mask = 0; 252 } 253 else 254 { 255 top_mask = 0xff000000; 256 bottom_mask = 0xff000000; 257 } 258 } 259 else 260 { 261 top_mask = 0; 262 bottom_mask = 0; 263 } 264 265 end = buffer + width; 266 267 /* Zero fill to the left of the image */ 268 while (buffer < end && x < pixman_fixed_minus_1) 269 { 270 *buffer++ = 0; 271 x += ux; 272 x_top += ux_top; 273 x_bottom += ux_bottom; 274 mask += mask_inc; 275 } 276 277 /* Left edge 278 */ 279 while (buffer < end && x < 0) 280 { 281 uint32_t tr, br; 282 int32_t distx; 283 284 tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask; 285 br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask; 286 287 distx = pixman_fixed_to_bilinear_weight (x); 288 289 *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty); 290 291 x += ux; 292 x_top += ux_top; 293 x_bottom += ux_bottom; 294 mask += mask_inc; 295 } 296 297 /* Main part */ 298 w = pixman_int_to_fixed (bits->width - 1); 299 300 while (buffer < end && x < w) 301 { 302 if (*mask) 303 { 304 uint32_t tl, tr, bl, br; 305 int32_t distx; 306 307 tl = top_row [pixman_fixed_to_int (x_top)] | top_mask; 308 tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask; 309 bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask; 310 br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask; 311 312 distx = pixman_fixed_to_bilinear_weight (x); 313 314 *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty); 315 } 316 317 buffer++; 318 x += ux; 319 x_top += ux_top; 320 x_bottom += ux_bottom; 321 mask += mask_inc; 322 } 323 324 /* Right Edge */ 325 w = pixman_int_to_fixed (bits->width); 326 while (buffer < end && x < w) 327 { 328 if (*mask) 329 { 330 uint32_t tl, bl; 331 int32_t distx; 332 333 tl = top_row [pixman_fixed_to_int (x_top)] | top_mask; 334 bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask; 335 336 distx = pixman_fixed_to_bilinear_weight (x); 337 338 *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty); 339 } 340 341 buffer++; 342 x += ux; 343 x_top += ux_top; 344 x_bottom += ux_bottom; 345 mask += mask_inc; 346 } 347 348 /* Zero fill to the left of the image */ 349 while (buffer < end) 350 *buffer++ = 0; 351 352 return iter->buffer; 353 } 354 355 static force_inline uint32_t 356 bits_image_fetch_pixel_convolution (bits_image_t *image, 357 pixman_fixed_t x, 358 pixman_fixed_t y, 359 get_pixel_t get_pixel) 360 { 361 pixman_fixed_t *params = image->common.filter_params; 362 int x_off = (params[0] - pixman_fixed_1) >> 1; 363 int y_off = (params[1] - pixman_fixed_1) >> 1; 364 int32_t cwidth = pixman_fixed_to_int (params[0]); 365 int32_t cheight = pixman_fixed_to_int (params[1]); 366 int32_t i, j, x1, x2, y1, y2; 367 pixman_repeat_t repeat_mode = image->common.repeat; 368 int width = image->width; 369 int height = image->height; 370 int srtot, sgtot, sbtot, satot; 371 372 params += 2; 373 374 x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); 375 y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); 376 x2 = x1 + cwidth; 377 y2 = y1 + cheight; 378 379 srtot = sgtot = sbtot = satot = 0; 380 381 for (i = y1; i < y2; ++i) 382 { 383 for (j = x1; j < x2; ++j) 384 { 385 int rx = j; 386 int ry = i; 387 388 pixman_fixed_t f = *params; 389 390 if (f) 391 { 392 uint32_t pixel; 393 394 if (repeat_mode != PIXMAN_REPEAT_NONE) 395 { 396 repeat (repeat_mode, &rx, width); 397 repeat (repeat_mode, &ry, height); 398 399 pixel = get_pixel (image, rx, ry, FALSE); 400 } 401 else 402 { 403 pixel = get_pixel (image, rx, ry, TRUE); 404 } 405 406 srtot += (int)RED_8 (pixel) * f; 407 sgtot += (int)GREEN_8 (pixel) * f; 408 sbtot += (int)BLUE_8 (pixel) * f; 409 satot += (int)ALPHA_8 (pixel) * f; 410 } 411 412 params++; 413 } 414 } 415 416 satot = (satot + 0x8000) >> 16; 417 srtot = (srtot + 0x8000) >> 16; 418 sgtot = (sgtot + 0x8000) >> 16; 419 sbtot = (sbtot + 0x8000) >> 16; 420 421 satot = CLIP (satot, 0, 0xff); 422 srtot = CLIP (srtot, 0, 0xff); 423 sgtot = CLIP (sgtot, 0, 0xff); 424 sbtot = CLIP (sbtot, 0, 0xff); 425 426 return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot)); 427 } 428 429 static uint32_t 430 bits_image_fetch_pixel_separable_convolution (bits_image_t *image, 431 pixman_fixed_t x, 432 pixman_fixed_t y, 433 get_pixel_t get_pixel) 434 { 435 pixman_fixed_t *params = image->common.filter_params; 436 pixman_repeat_t repeat_mode = image->common.repeat; 437 int width = image->width; 438 int height = image->height; 439 int cwidth = pixman_fixed_to_int (params[0]); 440 int cheight = pixman_fixed_to_int (params[1]); 441 int x_phase_bits = pixman_fixed_to_int (params[2]); 442 int y_phase_bits = pixman_fixed_to_int (params[3]); 443 int x_phase_shift = 16 - x_phase_bits; 444 int y_phase_shift = 16 - y_phase_bits; 445 int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1; 446 int y_off = ((cheight << 16) - pixman_fixed_1) >> 1; 447 pixman_fixed_t *y_params; 448 int srtot, sgtot, sbtot, satot; 449 int32_t x1, x2, y1, y2; 450 int32_t px, py; 451 int i, j; 452 453 /* Round x and y to the middle of the closest phase before continuing. This 454 * ensures that the convolution matrix is aligned right, since it was 455 * positioned relative to a particular phase (and not relative to whatever 456 * exact fraction we happen to get here). 457 */ 458 x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1); 459 y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1); 460 461 px = (x & 0xffff) >> x_phase_shift; 462 py = (y & 0xffff) >> y_phase_shift; 463 464 y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight; 465 466 x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); 467 y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); 468 x2 = x1 + cwidth; 469 y2 = y1 + cheight; 470 471 srtot = sgtot = sbtot = satot = 0; 472 473 for (i = y1; i < y2; ++i) 474 { 475 pixman_fixed_48_16_t fy = *y_params++; 476 pixman_fixed_t *x_params = params + 4 + px * cwidth; 477 478 if (fy) 479 { 480 for (j = x1; j < x2; ++j) 481 { 482 pixman_fixed_t fx = *x_params++; 483 int rx = j; 484 int ry = i; 485 486 if (fx) 487 { 488 pixman_fixed_t f; 489 uint32_t pixel; 490 491 if (repeat_mode != PIXMAN_REPEAT_NONE) 492 { 493 repeat (repeat_mode, &rx, width); 494 repeat (repeat_mode, &ry, height); 495 496 pixel = get_pixel (image, rx, ry, FALSE); 497 } 498 else 499 { 500 pixel = get_pixel (image, rx, ry, TRUE); 501 } 502 503 f = (fy * fx + 0x8000) >> 16; 504 505 srtot += (int)RED_8 (pixel) * f; 506 sgtot += (int)GREEN_8 (pixel) * f; 507 sbtot += (int)BLUE_8 (pixel) * f; 508 satot += (int)ALPHA_8 (pixel) * f; 509 } 510 } 511 } 512 } 513 514 satot = (satot + 0x8000) >> 16; 515 srtot = (srtot + 0x8000) >> 16; 516 sgtot = (sgtot + 0x8000) >> 16; 517 sbtot = (sbtot + 0x8000) >> 16; 518 519 satot = CLIP (satot, 0, 0xff); 520 srtot = CLIP (srtot, 0, 0xff); 521 sgtot = CLIP (sgtot, 0, 0xff); 522 sbtot = CLIP (sbtot, 0, 0xff); 523 524 return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot)); 525 } 526 527 static force_inline uint32_t 528 bits_image_fetch_pixel_filtered (bits_image_t *image, 529 pixman_fixed_t x, 530 pixman_fixed_t y, 531 get_pixel_t get_pixel) 532 { 533 switch (image->common.filter) 534 { 535 case PIXMAN_FILTER_NEAREST: 536 case PIXMAN_FILTER_FAST: 537 return bits_image_fetch_pixel_nearest (image, x, y, get_pixel); 538 break; 539 540 case PIXMAN_FILTER_BILINEAR: 541 case PIXMAN_FILTER_GOOD: 542 case PIXMAN_FILTER_BEST: 543 return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel); 544 break; 545 546 case PIXMAN_FILTER_CONVOLUTION: 547 return bits_image_fetch_pixel_convolution (image, x, y, get_pixel); 548 break; 549 550 case PIXMAN_FILTER_SEPARABLE_CONVOLUTION: 551 return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel); 552 break; 553 554 default: 555 break; 556 } 557 558 return 0; 559 } 560 561 static uint32_t * 562 bits_image_fetch_affine_no_alpha (pixman_iter_t * iter, 563 const uint32_t * mask) 564 { 565 pixman_image_t *image = iter->image; 566 int offset = iter->x; 567 int line = iter->y++; 568 int width = iter->width; 569 uint32_t * buffer = iter->buffer; 570 571 pixman_fixed_t x, y; 572 pixman_fixed_t ux, uy; 573 pixman_vector_t v; 574 int i; 575 576 /* reference point is the center of the pixel */ 577 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; 578 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; 579 v.vector[2] = pixman_fixed_1; 580 581 if (image->common.transform) 582 { 583 if (!pixman_transform_point_3d (image->common.transform, &v)) 584 return iter->buffer; 585 586 ux = image->common.transform->matrix[0][0]; 587 uy = image->common.transform->matrix[1][0]; 588 } 589 else 590 { 591 ux = pixman_fixed_1; 592 uy = 0; 593 } 594 595 x = v.vector[0]; 596 y = v.vector[1]; 597 598 for (i = 0; i < width; ++i) 599 { 600 if (!mask || mask[i]) 601 { 602 buffer[i] = bits_image_fetch_pixel_filtered ( 603 &image->bits, x, y, fetch_pixel_no_alpha); 604 } 605 606 x += ux; 607 y += uy; 608 } 609 610 return buffer; 611 } 612 613 /* General fetcher */ 614 static force_inline uint32_t 615 fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds) 616 { 617 uint32_t pixel; 618 619 if (check_bounds && 620 (x < 0 || x >= image->width || y < 0 || y >= image->height)) 621 { 622 return 0; 623 } 624 625 pixel = image->fetch_pixel_32 (image, x, y); 626 627 if (image->common.alpha_map) 628 { 629 uint32_t pixel_a; 630 631 x -= image->common.alpha_origin_x; 632 y -= image->common.alpha_origin_y; 633 634 if (x < 0 || x >= image->common.alpha_map->width || 635 y < 0 || y >= image->common.alpha_map->height) 636 { 637 pixel_a = 0; 638 } 639 else 640 { 641 pixel_a = image->common.alpha_map->fetch_pixel_32 ( 642 image->common.alpha_map, x, y); 643 644 pixel_a = ALPHA_8 (pixel_a); 645 } 646 647 pixel &= 0x00ffffff; 648 pixel |= (pixel_a << 24); 649 } 650 651 return pixel; 652 } 653 654 static uint32_t * 655 bits_image_fetch_general (pixman_iter_t *iter, 656 const uint32_t *mask) 657 { 658 pixman_image_t *image = iter->image; 659 int offset = iter->x; 660 int line = iter->y++; 661 int width = iter->width; 662 uint32_t * buffer = iter->buffer; 663 664 pixman_fixed_t x, y, w; 665 pixman_fixed_t ux, uy, uw; 666 pixman_vector_t v; 667 int i; 668 669 /* reference point is the center of the pixel */ 670 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; 671 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; 672 v.vector[2] = pixman_fixed_1; 673 674 if (image->common.transform) 675 { 676 if (!pixman_transform_point_3d (image->common.transform, &v)) 677 return buffer; 678 679 ux = image->common.transform->matrix[0][0]; 680 uy = image->common.transform->matrix[1][0]; 681 uw = image->common.transform->matrix[2][0]; 682 } 683 else 684 { 685 ux = pixman_fixed_1; 686 uy = 0; 687 uw = 0; 688 } 689 690 x = v.vector[0]; 691 y = v.vector[1]; 692 w = v.vector[2]; 693 694 for (i = 0; i < width; ++i) 695 { 696 pixman_fixed_t x0, y0; 697 698 if (!mask || mask[i]) 699 { 700 if (w != 0) 701 { 702 x0 = ((pixman_fixed_48_16_t)x << 16) / w; 703 y0 = ((pixman_fixed_48_16_t)y << 16) / w; 704 } 705 else 706 { 707 x0 = 0; 708 y0 = 0; 709 } 710 711 buffer[i] = bits_image_fetch_pixel_filtered ( 712 &image->bits, x0, y0, fetch_pixel_general); 713 } 714 715 x += ux; 716 y += uy; 717 w += uw; 718 } 719 720 return buffer; 721 } 722 723 typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x); 724 725 static force_inline void 726 bits_image_fetch_separable_convolution_affine (pixman_image_t * image, 727 int offset, 728 int line, 729 int width, 730 uint32_t * buffer, 731 const uint32_t * mask, 732 733 convert_pixel_t convert_pixel, 734 pixman_format_code_t format, 735 pixman_repeat_t repeat_mode) 736 { 737 bits_image_t *bits = &image->bits; 738 pixman_fixed_t *params = image->common.filter_params; 739 int cwidth = pixman_fixed_to_int (params[0]); 740 int cheight = pixman_fixed_to_int (params[1]); 741 int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1; 742 int y_off = ((cheight << 16) - pixman_fixed_1) >> 1; 743 int x_phase_bits = pixman_fixed_to_int (params[2]); 744 int y_phase_bits = pixman_fixed_to_int (params[3]); 745 int x_phase_shift = 16 - x_phase_bits; 746 int y_phase_shift = 16 - y_phase_bits; 747 pixman_fixed_t vx, vy; 748 pixman_fixed_t ux, uy; 749 pixman_vector_t v; 750 int k; 751 752 /* reference point is the center of the pixel */ 753 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; 754 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; 755 v.vector[2] = pixman_fixed_1; 756 757 if (!pixman_transform_point_3d (image->common.transform, &v)) 758 return; 759 760 ux = image->common.transform->matrix[0][0]; 761 uy = image->common.transform->matrix[1][0]; 762 763 vx = v.vector[0]; 764 vy = v.vector[1]; 765 766 for (k = 0; k < width; ++k) 767 { 768 pixman_fixed_t *y_params; 769 int satot, srtot, sgtot, sbtot; 770 pixman_fixed_t x, y; 771 int32_t x1, x2, y1, y2; 772 int32_t px, py; 773 int i, j; 774 775 if (mask && !mask[k]) 776 goto next; 777 778 /* Round x and y to the middle of the closest phase before continuing. This 779 * ensures that the convolution matrix is aligned right, since it was 780 * positioned relative to a particular phase (and not relative to whatever 781 * exact fraction we happen to get here). 782 */ 783 x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1); 784 y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1); 785 786 px = (x & 0xffff) >> x_phase_shift; 787 py = (y & 0xffff) >> y_phase_shift; 788 789 x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); 790 y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); 791 x2 = x1 + cwidth; 792 y2 = y1 + cheight; 793 794 satot = srtot = sgtot = sbtot = 0; 795 796 y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight; 797 798 for (i = y1; i < y2; ++i) 799 { 800 pixman_fixed_t fy = *y_params++; 801 802 if (fy) 803 { 804 pixman_fixed_t *x_params = params + 4 + px * cwidth; 805 806 for (j = x1; j < x2; ++j) 807 { 808 pixman_fixed_t fx = *x_params++; 809 int rx = j; 810 int ry = i; 811 812 if (fx) 813 { 814 pixman_fixed_t f; 815 uint32_t pixel, mask; 816 uint8_t *row; 817 818 mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; 819 820 if (repeat_mode != PIXMAN_REPEAT_NONE) 821 { 822 repeat (repeat_mode, &rx, bits->width); 823 repeat (repeat_mode, &ry, bits->height); 824 825 row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry; 826 pixel = convert_pixel (row, rx) | mask; 827 } 828 else 829 { 830 if (rx < 0 || ry < 0 || rx >= bits->width || ry >= bits->height) 831 { 832 pixel = 0; 833 } 834 else 835 { 836 row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry; 837 pixel = convert_pixel (row, rx) | mask; 838 } 839 } 840 841 f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16; 842 srtot += (int)RED_8 (pixel) * f; 843 sgtot += (int)GREEN_8 (pixel) * f; 844 sbtot += (int)BLUE_8 (pixel) * f; 845 satot += (int)ALPHA_8 (pixel) * f; 846 } 847 } 848 } 849 } 850 851 satot = (satot + 0x8000) >> 16; 852 srtot = (srtot + 0x8000) >> 16; 853 sgtot = (sgtot + 0x8000) >> 16; 854 sbtot = (sbtot + 0x8000) >> 16; 855 856 satot = CLIP (satot, 0, 0xff); 857 srtot = CLIP (srtot, 0, 0xff); 858 sgtot = CLIP (sgtot, 0, 0xff); 859 sbtot = CLIP (sbtot, 0, 0xff); 860 861 buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0); 862 863 next: 864 vx += ux; 865 vy += uy; 866 } 867 } 868 869 static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 870 871 static force_inline void 872 bits_image_fetch_bilinear_affine (pixman_image_t * image, 873 int offset, 874 int line, 875 int width, 876 uint32_t * buffer, 877 const uint32_t * mask, 878 879 convert_pixel_t convert_pixel, 880 pixman_format_code_t format, 881 pixman_repeat_t repeat_mode) 882 { 883 pixman_fixed_t x, y; 884 pixman_fixed_t ux, uy; 885 pixman_vector_t v; 886 bits_image_t *bits = &image->bits; 887 int i; 888 889 /* reference point is the center of the pixel */ 890 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; 891 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; 892 v.vector[2] = pixman_fixed_1; 893 894 if (!pixman_transform_point_3d (image->common.transform, &v)) 895 return; 896 897 ux = image->common.transform->matrix[0][0]; 898 uy = image->common.transform->matrix[1][0]; 899 900 x = v.vector[0]; 901 y = v.vector[1]; 902 903 for (i = 0; i < width; ++i) 904 { 905 int x1, y1, x2, y2; 906 uint32_t tl, tr, bl, br; 907 int32_t distx, disty; 908 int width = image->bits.width; 909 int height = image->bits.height; 910 const uint8_t *row1; 911 const uint8_t *row2; 912 913 if (mask && !mask[i]) 914 goto next; 915 916 x1 = x - pixman_fixed_1 / 2; 917 y1 = y - pixman_fixed_1 / 2; 918 919 distx = pixman_fixed_to_bilinear_weight (x1); 920 disty = pixman_fixed_to_bilinear_weight (y1); 921 922 y1 = pixman_fixed_to_int (y1); 923 y2 = y1 + 1; 924 x1 = pixman_fixed_to_int (x1); 925 x2 = x1 + 1; 926 927 if (repeat_mode != PIXMAN_REPEAT_NONE) 928 { 929 uint32_t mask; 930 931 mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; 932 933 repeat (repeat_mode, &x1, width); 934 repeat (repeat_mode, &y1, height); 935 repeat (repeat_mode, &x2, width); 936 repeat (repeat_mode, &y2, height); 937 938 row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1; 939 row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2; 940 941 tl = convert_pixel (row1, x1) | mask; 942 tr = convert_pixel (row1, x2) | mask; 943 bl = convert_pixel (row2, x1) | mask; 944 br = convert_pixel (row2, x2) | mask; 945 } 946 else 947 { 948 uint32_t mask1, mask2; 949 int bpp; 950 951 /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value, 952 * which means if you use it in expressions, those 953 * expressions become unsigned themselves. Since 954 * the variables below can be negative in some cases, 955 * that will lead to crashes on 64 bit architectures. 956 * 957 * So this line makes sure bpp is signed 958 */ 959 bpp = PIXMAN_FORMAT_BPP (format); 960 961 if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0) 962 { 963 buffer[i] = 0; 964 goto next; 965 } 966 967 if (y2 == 0) 968 { 969 row1 = zero; 970 mask1 = 0; 971 } 972 else 973 { 974 row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1; 975 row1 += bpp / 8 * x1; 976 977 mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; 978 } 979 980 if (y1 == height - 1) 981 { 982 row2 = zero; 983 mask2 = 0; 984 } 985 else 986 { 987 row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2; 988 row2 += bpp / 8 * x1; 989 990 mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; 991 } 992 993 if (x2 == 0) 994 { 995 tl = 0; 996 bl = 0; 997 } 998 else 999 { 1000 tl = convert_pixel (row1, 0) | mask1; 1001 bl = convert_pixel (row2, 0) | mask2; 1002 } 1003 1004 if (x1 == width - 1) 1005 { 1006 tr = 0; 1007 br = 0; 1008 } 1009 else 1010 { 1011 tr = convert_pixel (row1, 1) | mask1; 1012 br = convert_pixel (row2, 1) | mask2; 1013 } 1014 } 1015 1016 buffer[i] = bilinear_interpolation ( 1017 tl, tr, bl, br, distx, disty); 1018 1019 next: 1020 x += ux; 1021 y += uy; 1022 } 1023 } 1024 1025 static force_inline void 1026 bits_image_fetch_nearest_affine (pixman_image_t * image, 1027 int offset, 1028 int line, 1029 int width, 1030 uint32_t * buffer, 1031 const uint32_t * mask, 1032 1033 convert_pixel_t convert_pixel, 1034 pixman_format_code_t format, 1035 pixman_repeat_t repeat_mode) 1036 { 1037 pixman_fixed_t x, y; 1038 pixman_fixed_t ux, uy; 1039 pixman_vector_t v; 1040 bits_image_t *bits = &image->bits; 1041 int i; 1042 1043 /* reference point is the center of the pixel */ 1044 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; 1045 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; 1046 v.vector[2] = pixman_fixed_1; 1047 1048 if (!pixman_transform_point_3d (image->common.transform, &v)) 1049 return; 1050 1051 ux = image->common.transform->matrix[0][0]; 1052 uy = image->common.transform->matrix[1][0]; 1053 1054 x = v.vector[0]; 1055 y = v.vector[1]; 1056 1057 for (i = 0; i < width; ++i) 1058 { 1059 int width, height, x0, y0; 1060 const uint8_t *row; 1061 1062 if (mask && !mask[i]) 1063 goto next; 1064 1065 width = image->bits.width; 1066 height = image->bits.height; 1067 x0 = pixman_fixed_to_int (x - pixman_fixed_e); 1068 y0 = pixman_fixed_to_int (y - pixman_fixed_e); 1069 1070 if (repeat_mode == PIXMAN_REPEAT_NONE && 1071 (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width)) 1072 { 1073 buffer[i] = 0; 1074 } 1075 else 1076 { 1077 uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; 1078 1079 if (repeat_mode != PIXMAN_REPEAT_NONE) 1080 { 1081 repeat (repeat_mode, &x0, width); 1082 repeat (repeat_mode, &y0, height); 1083 } 1084 1085 row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0; 1086 1087 buffer[i] = convert_pixel (row, x0) | mask; 1088 } 1089 1090 next: 1091 x += ux; 1092 y += uy; 1093 } 1094 } 1095 1096 static force_inline uint32_t 1097 convert_a8r8g8b8 (const uint8_t *row, int x) 1098 { 1099 return *(((uint32_t *)row) + x); 1100 } 1101 1102 static force_inline uint32_t 1103 convert_x8r8g8b8 (const uint8_t *row, int x) 1104 { 1105 return *(((uint32_t *)row) + x); 1106 } 1107 1108 static force_inline uint32_t 1109 convert_a8 (const uint8_t *row, int x) 1110 { 1111 return *(row + x) << 24; 1112 } 1113 1114 static force_inline uint32_t 1115 convert_r5g6b5 (const uint8_t *row, int x) 1116 { 1117 return convert_0565_to_0888 (*((uint16_t *)row + x)); 1118 } 1119 1120 #define MAKE_SEPARABLE_CONVOLUTION_FETCHER(name, format, repeat_mode) \ 1121 static uint32_t * \ 1122 bits_image_fetch_separable_convolution_affine_ ## name (pixman_iter_t *iter, \ 1123 const uint32_t * mask) \ 1124 { \ 1125 bits_image_fetch_separable_convolution_affine ( \ 1126 iter->image, \ 1127 iter->x, iter->y++, \ 1128 iter->width, \ 1129 iter->buffer, mask, \ 1130 convert_ ## format, \ 1131 PIXMAN_ ## format, \ 1132 repeat_mode); \ 1133 \ 1134 return iter->buffer; \ 1135 } 1136 1137 #define MAKE_BILINEAR_FETCHER(name, format, repeat_mode) \ 1138 static uint32_t * \ 1139 bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t *iter, \ 1140 const uint32_t * mask) \ 1141 { \ 1142 bits_image_fetch_bilinear_affine (iter->image, \ 1143 iter->x, iter->y++, \ 1144 iter->width, \ 1145 iter->buffer, mask, \ 1146 convert_ ## format, \ 1147 PIXMAN_ ## format, \ 1148 repeat_mode); \ 1149 return iter->buffer; \ 1150 } 1151 1152 #define MAKE_NEAREST_FETCHER(name, format, repeat_mode) \ 1153 static uint32_t * \ 1154 bits_image_fetch_nearest_affine_ ## name (pixman_iter_t *iter, \ 1155 const uint32_t * mask) \ 1156 { \ 1157 bits_image_fetch_nearest_affine (iter->image, \ 1158 iter->x, iter->y++, \ 1159 iter->width, \ 1160 iter->buffer, mask, \ 1161 convert_ ## format, \ 1162 PIXMAN_ ## format, \ 1163 repeat_mode); \ 1164 return iter->buffer; \ 1165 } 1166 1167 #define MAKE_FETCHERS(name, format, repeat_mode) \ 1168 MAKE_NEAREST_FETCHER (name, format, repeat_mode) \ 1169 MAKE_BILINEAR_FETCHER (name, format, repeat_mode) \ 1170 MAKE_SEPARABLE_CONVOLUTION_FETCHER (name, format, repeat_mode) 1171 1172 MAKE_FETCHERS (pad_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_PAD) 1173 MAKE_FETCHERS (none_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NONE) 1174 MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT) 1175 MAKE_FETCHERS (normal_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NORMAL) 1176 MAKE_FETCHERS (pad_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_PAD) 1177 MAKE_FETCHERS (none_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NONE) 1178 MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT) 1179 MAKE_FETCHERS (normal_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NORMAL) 1180 MAKE_FETCHERS (pad_a8, a8, PIXMAN_REPEAT_PAD) 1181 MAKE_FETCHERS (none_a8, a8, PIXMAN_REPEAT_NONE) 1182 MAKE_FETCHERS (reflect_a8, a8, PIXMAN_REPEAT_REFLECT) 1183 MAKE_FETCHERS (normal_a8, a8, PIXMAN_REPEAT_NORMAL) 1184 MAKE_FETCHERS (pad_r5g6b5, r5g6b5, PIXMAN_REPEAT_PAD) 1185 MAKE_FETCHERS (none_r5g6b5, r5g6b5, PIXMAN_REPEAT_NONE) 1186 MAKE_FETCHERS (reflect_r5g6b5, r5g6b5, PIXMAN_REPEAT_REFLECT) 1187 MAKE_FETCHERS (normal_r5g6b5, r5g6b5, PIXMAN_REPEAT_NORMAL) 1188 1189 static void 1190 replicate_pixel_32 (bits_image_t * bits, 1191 int x, 1192 int y, 1193 int width, 1194 uint32_t * buffer) 1195 { 1196 uint32_t color; 1197 uint32_t *end; 1198 1199 color = bits->fetch_pixel_32 (bits, x, y); 1200 1201 end = buffer + width; 1202 while (buffer < end) 1203 *(buffer++) = color; 1204 } 1205 1206 static void 1207 replicate_pixel_float (bits_image_t * bits, 1208 int x, 1209 int y, 1210 int width, 1211 uint32_t * b) 1212 { 1213 argb_t color; 1214 argb_t *buffer = (argb_t *)b; 1215 argb_t *end; 1216 1217 color = bits->fetch_pixel_float (bits, x, y); 1218 1219 end = buffer + width; 1220 while (buffer < end) 1221 *(buffer++) = color; 1222 } 1223 1224 static void 1225 bits_image_fetch_untransformed_repeat_none (bits_image_t *image, 1226 pixman_bool_t wide, 1227 int x, 1228 int y, 1229 int width, 1230 uint32_t * buffer) 1231 { 1232 uint32_t w; 1233 1234 if (y < 0 || y >= image->height) 1235 { 1236 memset (buffer, 0, width * (wide? sizeof (argb_t) : 4)); 1237 return; 1238 } 1239 1240 if (x < 0) 1241 { 1242 w = MIN (width, -x); 1243 1244 memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4)); 1245 1246 width -= w; 1247 buffer += w * (wide? 4 : 1); 1248 x += w; 1249 } 1250 1251 if (x < image->width) 1252 { 1253 w = MIN (width, image->width - x); 1254 1255 if (wide) 1256 image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL); 1257 else 1258 image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL); 1259 1260 width -= w; 1261 buffer += w * (wide? 4 : 1); 1262 x += w; 1263 } 1264 1265 memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4)); 1266 } 1267 1268 static void 1269 bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, 1270 pixman_bool_t wide, 1271 int x, 1272 int y, 1273 int width, 1274 uint32_t * buffer) 1275 { 1276 uint32_t w; 1277 1278 while (y < 0) 1279 y += image->height; 1280 1281 while (y >= image->height) 1282 y -= image->height; 1283 1284 if (image->width == 1) 1285 { 1286 if (wide) 1287 replicate_pixel_float (image, 0, y, width, buffer); 1288 else 1289 replicate_pixel_32 (image, 0, y, width, buffer); 1290 1291 return; 1292 } 1293 1294 while (width) 1295 { 1296 while (x < 0) 1297 x += image->width; 1298 while (x >= image->width) 1299 x -= image->width; 1300 1301 w = MIN (width, image->width - x); 1302 1303 if (wide) 1304 image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL); 1305 else 1306 image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL); 1307 1308 buffer += w * (wide? 4 : 1); 1309 x += w; 1310 width -= w; 1311 } 1312 } 1313 1314 static uint32_t * 1315 bits_image_fetch_untransformed_32 (pixman_iter_t * iter, 1316 const uint32_t *mask) 1317 { 1318 pixman_image_t *image = iter->image; 1319 int x = iter->x; 1320 int y = iter->y; 1321 int width = iter->width; 1322 uint32_t * buffer = iter->buffer; 1323 1324 if (image->common.repeat == PIXMAN_REPEAT_NONE) 1325 { 1326 bits_image_fetch_untransformed_repeat_none ( 1327 &image->bits, FALSE, x, y, width, buffer); 1328 } 1329 else 1330 { 1331 bits_image_fetch_untransformed_repeat_normal ( 1332 &image->bits, FALSE, x, y, width, buffer); 1333 } 1334 1335 iter->y++; 1336 return buffer; 1337 } 1338 1339 static uint32_t * 1340 bits_image_fetch_untransformed_float (pixman_iter_t * iter, 1341 const uint32_t *mask) 1342 { 1343 pixman_image_t *image = iter->image; 1344 int x = iter->x; 1345 int y = iter->y; 1346 int width = iter->width; 1347 uint32_t * buffer = iter->buffer; 1348 1349 if (image->common.repeat == PIXMAN_REPEAT_NONE) 1350 { 1351 bits_image_fetch_untransformed_repeat_none ( 1352 &image->bits, TRUE, x, y, width, buffer); 1353 } 1354 else 1355 { 1356 bits_image_fetch_untransformed_repeat_normal ( 1357 &image->bits, TRUE, x, y, width, buffer); 1358 } 1359 1360 iter->y++; 1361 return buffer; 1362 } 1363 1364 typedef struct 1365 { 1366 pixman_format_code_t format; 1367 uint32_t flags; 1368 pixman_iter_get_scanline_t get_scanline_32; 1369 pixman_iter_get_scanline_t get_scanline_float; 1370 } fetcher_info_t; 1371 1372 static const fetcher_info_t fetcher_info[] = 1373 { 1374 { PIXMAN_any, 1375 (FAST_PATH_NO_ALPHA_MAP | 1376 FAST_PATH_ID_TRANSFORM | 1377 FAST_PATH_NO_CONVOLUTION_FILTER | 1378 FAST_PATH_NO_PAD_REPEAT | 1379 FAST_PATH_NO_REFLECT_REPEAT), 1380 bits_image_fetch_untransformed_32, 1381 bits_image_fetch_untransformed_float 1382 }, 1383 1384 #define FAST_BILINEAR_FLAGS \ 1385 (FAST_PATH_NO_ALPHA_MAP | \ 1386 FAST_PATH_NO_ACCESSORS | \ 1387 FAST_PATH_HAS_TRANSFORM | \ 1388 FAST_PATH_AFFINE_TRANSFORM | \ 1389 FAST_PATH_X_UNIT_POSITIVE | \ 1390 FAST_PATH_Y_UNIT_ZERO | \ 1391 FAST_PATH_NONE_REPEAT | \ 1392 FAST_PATH_BILINEAR_FILTER) 1393 1394 { PIXMAN_a8r8g8b8, 1395 FAST_BILINEAR_FLAGS, 1396 bits_image_fetch_bilinear_no_repeat_8888, 1397 _pixman_image_get_scanline_generic_float 1398 }, 1399 1400 { PIXMAN_x8r8g8b8, 1401 FAST_BILINEAR_FLAGS, 1402 bits_image_fetch_bilinear_no_repeat_8888, 1403 _pixman_image_get_scanline_generic_float 1404 }, 1405 1406 #define GENERAL_BILINEAR_FLAGS \ 1407 (FAST_PATH_NO_ALPHA_MAP | \ 1408 FAST_PATH_NO_ACCESSORS | \ 1409 FAST_PATH_HAS_TRANSFORM | \ 1410 FAST_PATH_AFFINE_TRANSFORM | \ 1411 FAST_PATH_BILINEAR_FILTER) 1412 1413 #define GENERAL_NEAREST_FLAGS \ 1414 (FAST_PATH_NO_ALPHA_MAP | \ 1415 FAST_PATH_NO_ACCESSORS | \ 1416 FAST_PATH_HAS_TRANSFORM | \ 1417 FAST_PATH_AFFINE_TRANSFORM | \ 1418 FAST_PATH_NEAREST_FILTER) 1419 1420 #define GENERAL_SEPARABLE_CONVOLUTION_FLAGS \ 1421 (FAST_PATH_NO_ALPHA_MAP | \ 1422 FAST_PATH_NO_ACCESSORS | \ 1423 FAST_PATH_HAS_TRANSFORM | \ 1424 FAST_PATH_AFFINE_TRANSFORM | \ 1425 FAST_PATH_SEPARABLE_CONVOLUTION_FILTER) 1426 1427 #define SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \ 1428 { PIXMAN_ ## format, \ 1429 GENERAL_SEPARABLE_CONVOLUTION_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ 1430 bits_image_fetch_separable_convolution_affine_ ## name, \ 1431 _pixman_image_get_scanline_generic_float \ 1432 }, 1433 1434 #define BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \ 1435 { PIXMAN_ ## format, \ 1436 GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ 1437 bits_image_fetch_bilinear_affine_ ## name, \ 1438 _pixman_image_get_scanline_generic_float \ 1439 }, 1440 1441 #define NEAREST_AFFINE_FAST_PATH(name, format, repeat) \ 1442 { PIXMAN_ ## format, \ 1443 GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ 1444 bits_image_fetch_nearest_affine_ ## name, \ 1445 _pixman_image_get_scanline_generic_float \ 1446 }, 1447 1448 #define AFFINE_FAST_PATHS(name, format, repeat) \ 1449 SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \ 1450 BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \ 1451 NEAREST_AFFINE_FAST_PATH(name, format, repeat) 1452 1453 AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD) 1454 AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE) 1455 AFFINE_FAST_PATHS (reflect_a8r8g8b8, a8r8g8b8, REFLECT) 1456 AFFINE_FAST_PATHS (normal_a8r8g8b8, a8r8g8b8, NORMAL) 1457 AFFINE_FAST_PATHS (pad_x8r8g8b8, x8r8g8b8, PAD) 1458 AFFINE_FAST_PATHS (none_x8r8g8b8, x8r8g8b8, NONE) 1459 AFFINE_FAST_PATHS (reflect_x8r8g8b8, x8r8g8b8, REFLECT) 1460 AFFINE_FAST_PATHS (normal_x8r8g8b8, x8r8g8b8, NORMAL) 1461 AFFINE_FAST_PATHS (pad_a8, a8, PAD) 1462 AFFINE_FAST_PATHS (none_a8, a8, NONE) 1463 AFFINE_FAST_PATHS (reflect_a8, a8, REFLECT) 1464 AFFINE_FAST_PATHS (normal_a8, a8, NORMAL) 1465 AFFINE_FAST_PATHS (pad_r5g6b5, r5g6b5, PAD) 1466 AFFINE_FAST_PATHS (none_r5g6b5, r5g6b5, NONE) 1467 AFFINE_FAST_PATHS (reflect_r5g6b5, r5g6b5, REFLECT) 1468 AFFINE_FAST_PATHS (normal_r5g6b5, r5g6b5, NORMAL) 1469 1470 /* Affine, no alpha */ 1471 { PIXMAN_any, 1472 (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM), 1473 bits_image_fetch_affine_no_alpha, 1474 _pixman_image_get_scanline_generic_float 1475 }, 1476 1477 /* General */ 1478 { PIXMAN_any, 1479 0, 1480 bits_image_fetch_general, 1481 _pixman_image_get_scanline_generic_float 1482 }, 1483 1484 { PIXMAN_null }, 1485 }; 1486 1487 static void 1488 bits_image_property_changed (pixman_image_t *image) 1489 { 1490 _pixman_bits_image_setup_accessors (&image->bits); 1491 } 1492 1493 void 1494 _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter) 1495 { 1496 pixman_format_code_t format = image->common.extended_format_code; 1497 uint32_t flags = image->common.flags; 1498 const fetcher_info_t *info; 1499 1500 for (info = fetcher_info; info->format != PIXMAN_null; ++info) 1501 { 1502 if ((info->format == format || info->format == PIXMAN_any) && 1503 (info->flags & flags) == info->flags) 1504 { 1505 if (iter->iter_flags & ITER_NARROW) 1506 { 1507 iter->get_scanline = info->get_scanline_32; 1508 } 1509 else 1510 { 1511 iter->data = info->get_scanline_32; 1512 iter->get_scanline = info->get_scanline_float; 1513 } 1514 return; 1515 } 1516 } 1517 1518 /* Just in case we somehow didn't find a scanline function */ 1519 iter->get_scanline = _pixman_iter_get_scanline_noop; 1520 } 1521 1522 static uint32_t * 1523 dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask) 1524 { 1525 pixman_image_t *image = iter->image; 1526 int x = iter->x; 1527 int y = iter->y; 1528 int width = iter->width; 1529 uint32_t * buffer = iter->buffer; 1530 1531 image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask); 1532 if (image->common.alpha_map) 1533 { 1534 uint32_t *alpha; 1535 1536 if ((alpha = malloc (width * sizeof (uint32_t)))) 1537 { 1538 int i; 1539 1540 x -= image->common.alpha_origin_x; 1541 y -= image->common.alpha_origin_y; 1542 1543 image->common.alpha_map->fetch_scanline_32 ( 1544 (pixman_image_t *)image->common.alpha_map, 1545 x, y, width, alpha, mask); 1546 1547 for (i = 0; i < width; ++i) 1548 { 1549 buffer[i] &= ~0xff000000; 1550 buffer[i] |= (alpha[i] & 0xff000000); 1551 } 1552 1553 free (alpha); 1554 } 1555 } 1556 1557 return iter->buffer; 1558 } 1559 1560 static uint32_t * 1561 dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) 1562 { 1563 bits_image_t * image = &iter->image->bits; 1564 int x = iter->x; 1565 int y = iter->y; 1566 int width = iter->width; 1567 argb_t * buffer = (argb_t *)iter->buffer; 1568 1569 image->fetch_scanline_float ( 1570 (pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask); 1571 if (image->common.alpha_map) 1572 { 1573 argb_t *alpha; 1574 1575 if ((alpha = malloc (width * sizeof (argb_t)))) 1576 { 1577 int i; 1578 1579 x -= image->common.alpha_origin_x; 1580 y -= image->common.alpha_origin_y; 1581 1582 image->common.alpha_map->fetch_scanline_float ( 1583 (pixman_image_t *)image->common.alpha_map, 1584 x, y, width, (uint32_t *)alpha, mask); 1585 1586 for (i = 0; i < width; ++i) 1587 buffer[i].a = alpha[i].a; 1588 1589 free (alpha); 1590 } 1591 } 1592 1593 return iter->buffer; 1594 } 1595 1596 static void 1597 dest_write_back_narrow (pixman_iter_t *iter) 1598 { 1599 bits_image_t * image = &iter->image->bits; 1600 int x = iter->x; 1601 int y = iter->y; 1602 int width = iter->width; 1603 const uint32_t *buffer = iter->buffer; 1604 1605 image->store_scanline_32 (image, x, y, width, buffer); 1606 1607 if (image->common.alpha_map) 1608 { 1609 x -= image->common.alpha_origin_x; 1610 y -= image->common.alpha_origin_y; 1611 1612 image->common.alpha_map->store_scanline_32 ( 1613 image->common.alpha_map, x, y, width, buffer); 1614 } 1615 1616 iter->y++; 1617 } 1618 1619 static void 1620 dest_write_back_wide (pixman_iter_t *iter) 1621 { 1622 bits_image_t * image = &iter->image->bits; 1623 int x = iter->x; 1624 int y = iter->y; 1625 int width = iter->width; 1626 const uint32_t *buffer = iter->buffer; 1627 1628 image->store_scanline_float (image, x, y, width, buffer); 1629 1630 if (image->common.alpha_map) 1631 { 1632 x -= image->common.alpha_origin_x; 1633 y -= image->common.alpha_origin_y; 1634 1635 image->common.alpha_map->store_scanline_float ( 1636 image->common.alpha_map, x, y, width, buffer); 1637 } 1638 1639 iter->y++; 1640 } 1641 1642 void 1643 _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter) 1644 { 1645 if (iter->iter_flags & ITER_NARROW) 1646 { 1647 if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == 1648 (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) 1649 { 1650 iter->get_scanline = _pixman_iter_get_scanline_noop; 1651 } 1652 else 1653 { 1654 iter->get_scanline = dest_get_scanline_narrow; 1655 } 1656 1657 iter->write_back = dest_write_back_narrow; 1658 } 1659 else 1660 { 1661 iter->get_scanline = dest_get_scanline_wide; 1662 iter->write_back = dest_write_back_wide; 1663 } 1664 } 1665 1666 static uint32_t * 1667 create_bits (pixman_format_code_t format, 1668 int width, 1669 int height, 1670 int * rowstride_bytes, 1671 pixman_bool_t clear) 1672 { 1673 int stride; 1674 size_t buf_size; 1675 int bpp; 1676 1677 /* what follows is a long-winded way, avoiding any possibility of integer 1678 * overflows, of saying: 1679 * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t); 1680 */ 1681 1682 bpp = PIXMAN_FORMAT_BPP (format); 1683 if (_pixman_multiply_overflows_int (width, bpp)) 1684 return NULL; 1685 1686 stride = width * bpp; 1687 if (_pixman_addition_overflows_int (stride, 0x1f)) 1688 return NULL; 1689 1690 stride += 0x1f; 1691 stride >>= 5; 1692 1693 stride *= sizeof (uint32_t); 1694 1695 if (_pixman_multiply_overflows_size (height, stride)) 1696 return NULL; 1697 1698 buf_size = height * stride; 1699 1700 if (rowstride_bytes) 1701 *rowstride_bytes = stride; 1702 1703 if (clear) 1704 return calloc (buf_size, 1); 1705 else 1706 return malloc (buf_size); 1707 } 1708 1709 pixman_bool_t 1710 _pixman_bits_image_init (pixman_image_t * image, 1711 pixman_format_code_t format, 1712 int width, 1713 int height, 1714 uint32_t * bits, 1715 int rowstride, 1716 pixman_bool_t clear) 1717 { 1718 uint32_t *free_me = NULL; 1719 1720 if (!bits && width && height) 1721 { 1722 int rowstride_bytes; 1723 1724 free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear); 1725 1726 if (!bits) 1727 return FALSE; 1728 1729 rowstride = rowstride_bytes / (int) sizeof (uint32_t); 1730 } 1731 1732 _pixman_image_init (image); 1733 1734 image->type = BITS; 1735 image->bits.format = format; 1736 image->bits.width = width; 1737 image->bits.height = height; 1738 image->bits.bits = bits; 1739 image->bits.free_me = free_me; 1740 image->bits.read_func = NULL; 1741 image->bits.write_func = NULL; 1742 image->bits.rowstride = rowstride; 1743 image->bits.indexed = NULL; 1744 1745 image->common.property_changed = bits_image_property_changed; 1746 1747 _pixman_image_reset_clip_region (image); 1748 1749 return TRUE; 1750 } 1751 1752 static pixman_image_t * 1753 create_bits_image_internal (pixman_format_code_t format, 1754 int width, 1755 int height, 1756 uint32_t * bits, 1757 int rowstride_bytes, 1758 pixman_bool_t clear) 1759 { 1760 pixman_image_t *image; 1761 1762 /* must be a whole number of uint32_t's 1763 */ 1764 return_val_if_fail ( 1765 bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL); 1766 1767 return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL); 1768 1769 image = _pixman_image_allocate (); 1770 1771 if (!image) 1772 return NULL; 1773 1774 if (!_pixman_bits_image_init (image, format, width, height, bits, 1775 rowstride_bytes / (int) sizeof (uint32_t), 1776 clear)) 1777 { 1778 free (image); 1779 return NULL; 1780 } 1781 1782 return image; 1783 } 1784 1785 /* If bits is NULL, a buffer will be allocated and initialized to 0 */ 1786 PIXMAN_EXPORT pixman_image_t * 1787 pixman_image_create_bits (pixman_format_code_t format, 1788 int width, 1789 int height, 1790 uint32_t * bits, 1791 int rowstride_bytes) 1792 { 1793 return create_bits_image_internal ( 1794 format, width, height, bits, rowstride_bytes, TRUE); 1795 } 1796 1797 1798 /* If bits is NULL, a buffer will be allocated and _not_ initialized */ 1799 PIXMAN_EXPORT pixman_image_t * 1800 pixman_image_create_bits_no_clear (pixman_format_code_t format, 1801 int width, 1802 int height, 1803 uint32_t * bits, 1804 int rowstride_bytes) 1805 { 1806 return create_bits_image_internal ( 1807 format, width, height, bits, rowstride_bytes, FALSE); 1808 } 1809