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.
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that
11 * copyright notice and this permission notice appear in supporting
12 * documentation, and that the name of Keith Packard not be used in
13 * advertising or publicity pertaining to distribution of the software without
14 * specific, written prior permission. Keith Packard makes no
15 * representations about the suitability of this software for any purpose. It
16 * is provided "as is" without express or implied warranty.
18 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
19 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
23 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
24 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
31 #include "pixman-private.h"
32 #include "pixman-combine32.h"
34 #define Red(x) (((x) >> 16) & 0xff)
35 #define Green(x) (((x) >> 8) & 0xff)
36 #define Blue(x) ((x) & 0xff)
41 bits_image_store_scanline_32 (bits_image_t *image,
44 const uint32_t *buffer)
46 image->store_scanline_raw_32 (image, x, y, width, buffer);
48 if (image->common.alpha_map)
50 x -= image->common.alpha_origin_x;
51 y -= image->common.alpha_origin_y;
53 bits_image_store_scanline_32 (image->common.alpha_map, x, y, width, buffer);
58 bits_image_store_scanline_64 (bits_image_t *image,
61 const uint32_t *buffer)
63 image->store_scanline_raw_64 (image, x, y, width, buffer);
65 if (image->common.alpha_map)
67 x -= image->common.alpha_origin_x;
68 y -= image->common.alpha_origin_y;
70 bits_image_store_scanline_64 (image->common.alpha_map, x, y, width, buffer);
75 _pixman_image_store_scanline_32 (bits_image_t *image, int x, int y, int width,
76 const uint32_t *buffer)
78 image->store_scanline_32 (image, x, y, width, buffer);
82 _pixman_image_store_scanline_64 (bits_image_t *image, int x, int y, int width,
83 const uint32_t *buffer)
85 image->store_scanline_64 (image, x, y, width, buffer);
90 /* On entry, @buffer should contain @n_pixels (x, y) coordinate pairs, where
91 * x and y are both uint32_ts. On exit, buffer will contain the corresponding
94 * The coordinates must be within the sample grid. If either x or y is 0xffffffff,
95 * the pixel returned will be 0.
98 bits_image_fetch_raw_pixels (bits_image_t *image, uint32_t *buffer, int n_pixels)
100 image->fetch_pixels_raw_32 (image, buffer, n_pixels);
104 bits_image_fetch_alpha_pixels (bits_image_t *image, uint32_t *buffer, int n_pixels)
106 #define N_ALPHA_PIXELS 256
108 uint32_t alpha_pixels[N_ALPHA_PIXELS * 2];
111 if (!image->common.alpha_map)
113 bits_image_fetch_raw_pixels (image, buffer, n_pixels);
121 int tmp_n_pixels = MIN (N_ALPHA_PIXELS, n_pixels - i);
125 memcpy (alpha_pixels, buffer + 2 * i, tmp_n_pixels * 2 * sizeof (int32_t));
126 coords = (int32_t *)alpha_pixels;
127 for (j = 0; j < tmp_n_pixels; ++j)
129 int32_t x = coords[0];
130 int32_t y = coords[1];
134 x -= image->common.alpha_origin_x;
136 if (x < 0 || x >= image->common.alpha_map->width)
142 y -= image->common.alpha_origin_y;
144 if (y < 0 || y >= image->common.alpha_map->height)
154 bits_image_fetch_raw_pixels (image->common.alpha_map, alpha_pixels,
156 bits_image_fetch_raw_pixels (image, buffer + 2 * i, tmp_n_pixels);
158 for (j = 0; j < tmp_n_pixels; ++j)
160 int a = alpha_pixels[j] >> 24;
161 uint32_t p = buffer[2 * i - j] | 0xff000000;
171 bits_image_fetch_pixels_src_clip (bits_image_t *image, uint32_t *buffer, int n_pixels)
173 bits_image_fetch_alpha_pixels (image, buffer, n_pixels);
176 static force_inline void
177 repeat (pixman_repeat_t repeat, int width, int height, int *x, int *y)
181 case PIXMAN_REPEAT_NORMAL:
182 *x = MOD (*x, width);
183 *y = MOD (*y, height);
186 case PIXMAN_REPEAT_PAD:
187 *x = CLIP (*x, 0, width - 1);
188 *y = CLIP (*y, 0, height - 1);
191 case PIXMAN_REPEAT_REFLECT:
192 *x = MOD (*x, width * 2);
193 *y = MOD (*y, height * 2);
196 *x = width * 2 - *x - 1;
199 *y = height * 2 - *y - 1;
202 case PIXMAN_REPEAT_NONE:
203 if (*x < 0 || *x >= width)
206 if (*y < 0 || *y >= height)
212 /* Buffer contains list of fixed-point coordinates on input,
213 * a list of pixels on output
216 bits_image_fetch_nearest_pixels (bits_image_t *image, uint32_t *buffer, int n_pixels)
218 pixman_repeat_t repeat_mode = image->common.repeat;
219 int width = image->width;
220 int height = image->height;
223 for (i = 0; i < 2 * n_pixels; i += 2)
225 int32_t *coords = (int32_t *)buffer;
228 /* Subtract pixman_fixed_e to ensure that 0.5 rounds to 0, not 1 */
229 x = pixman_fixed_to_int (coords[i] - pixman_fixed_e);
230 y = pixman_fixed_to_int (coords[i + 1] - pixman_fixed_e);
232 repeat (repeat_mode, width, height, &x, &y);
238 bits_image_fetch_pixels_src_clip (image, buffer, n_pixels);
241 #define N_TMP_PIXELS (256)
243 /* Buffer contains list of fixed-point coordinates on input,
244 * a list of pixels on output
247 bits_image_fetch_bilinear_pixels (bits_image_t *image, uint32_t *buffer, int n_pixels)
249 /* (Four pixels * two coordinates) per pixel */
250 #define N_TEMPS (N_TMP_PIXELS * 8)
251 #define N_DISTS (N_TMP_PIXELS * 2)
253 uint32_t temps[N_TEMPS];
254 int32_t dists[N_DISTS];
255 pixman_repeat_t repeat_mode = image->common.repeat;
256 int width = image->width;
257 int height = image->height;
262 coords = (int32_t *)buffer;
265 int tmp_n_pixels = MIN(N_TMP_PIXELS, n_pixels - i);
266 int32_t distx, disty;
271 t = (int32_t *)temps;
273 for (j = 0; j < tmp_n_pixels; ++j)
275 int32_t x1, y1, x2, y2;
277 x1 = coords[0] - pixman_fixed_1 / 2;
278 y1 = coords[1] - pixman_fixed_1 / 2;
280 distx = (x1 >> 8) & 0xff;
281 disty = (y1 >> 8) & 0xff;
288 repeat (repeat_mode, width, height, &x1, &y1);
289 repeat (repeat_mode, width, height, &x2, &y2);
306 bits_image_fetch_pixels_src_clip (image, temps, tmp_n_pixels * 4);
308 u = (uint32_t *)temps;
310 for (j = 0; j < tmp_n_pixels; ++j)
312 uint32_t tl, tr, bl, br, r;
313 int32_t idistx, idisty;
324 idistx = 256 - distx;
325 idisty = 256 - disty;
327 #define FbGet8(v,i) ((uint16_t) (uint8_t) ((v) >> i))
329 ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
330 fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
331 r = (((ft * idisty + fb * disty) >> 16) & 0xff);
332 ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
333 fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
334 r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
335 ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
336 fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
337 r |= (((ft * idisty + fb * disty)) & 0xff0000);
338 ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
339 fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
340 r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
347 /* Buffer contains list of fixed-point coordinates on input,
348 * a list of pixels on output
351 bits_image_fetch_convolution_pixels (bits_image_t *image,
352 uint32_t *buffer, int n_pixels)
354 uint32_t tmp_pixels_stack[N_TMP_PIXELS * 2]; /* Two coordinates per pixel */
355 uint32_t *tmp_pixels = tmp_pixels_stack;
356 pixman_fixed_t *params = image->common.filter_params;
357 int x_off = (params[0] - pixman_fixed_1) >> 1;
358 int y_off = (params[1] - pixman_fixed_1) >> 1;
366 int32_t cwidth = pixman_fixed_to_int (params[0]);
367 int32_t cheight = pixman_fixed_to_int (params[1]);
368 int kernel_size = cwidth * cheight;
372 n_tmp_pixels = N_TMP_PIXELS;
373 if (kernel_size > n_tmp_pixels)
375 /* Two coordinates per pixel */
376 tmp_pixels = malloc (kernel_size * 2 * sizeof (uint32_t));
377 n_tmp_pixels = kernel_size;
381 /* We ignore out-of-memory during rendering */
386 max_n_kernels = n_tmp_pixels / kernel_size;
389 coords = (int32_t *)buffer;
392 int n_kernels = MIN (max_n_kernels, (n_pixels - i));
393 pixman_repeat_t repeat_mode = image->common.repeat;
394 int width = image->width;
395 int height = image->height;
398 t = (int32_t *)tmp_pixels;
399 for (j = 0; j < n_kernels; ++j)
401 int32_t x, y, x1, x2, y1, y2;
403 /* Subtract pixman_fixed_e to ensure that 0.5 rounds to 0, not 1 */
404 x1 = pixman_fixed_to_int (coords[0] - pixman_fixed_e - x_off);
405 y1 = pixman_fixed_to_int (coords[1] - pixman_fixed_e - y_off);
409 for (y = y1; y < y2; ++y)
411 for (x = x1; x < x2; ++x)
416 repeat (repeat_mode, width, height, &rx, &ry);
426 bits_image_fetch_pixels_src_clip (image, tmp_pixels, n_kernels * kernel_size);
429 for (j = 0; j < n_kernels; ++j)
431 int32_t srtot, sgtot, sbtot, satot;
432 pixman_fixed_t *p = params;
435 srtot = sgtot = sbtot = satot = 0;
437 for (k = 0; k < kernel_size; ++k)
439 pixman_fixed_t f = *p++;
445 sgtot += Green(c) * f;
446 sbtot += Blue(c) * f;
447 satot += Alpha(c) * f;
456 if (satot < 0) satot = 0; else if (satot > 0xff) satot = 0xff;
457 if (srtot < 0) srtot = 0; else if (srtot > 0xff) srtot = 0xff;
458 if (sgtot < 0) sgtot = 0; else if (sgtot > 0xff) sgtot = 0xff;
459 if (sbtot < 0) sbtot = 0; else if (sbtot > 0xff) sbtot = 0xff;
461 buffer[i++] = ((satot << 24) |
468 if (tmp_pixels != tmp_pixels_stack)
473 bits_image_fetch_filtered (bits_image_t *pict, uint32_t *buffer, int n_pixels)
475 switch (pict->common.filter)
477 case PIXMAN_FILTER_NEAREST:
478 case PIXMAN_FILTER_FAST:
479 bits_image_fetch_nearest_pixels (pict, buffer, n_pixels);
482 case PIXMAN_FILTER_BILINEAR:
483 case PIXMAN_FILTER_GOOD:
484 case PIXMAN_FILTER_BEST:
485 bits_image_fetch_bilinear_pixels (pict, buffer, n_pixels);
488 case PIXMAN_FILTER_CONVOLUTION:
489 bits_image_fetch_convolution_pixels (pict, buffer, n_pixels);
495 bits_image_fetch_transformed (pixman_image_t * pict, int x, int y, int width,
496 uint32_t *buffer, uint32_t *mask,
502 pixman_vector_t unit;
503 pixman_bool_t affine = TRUE;
504 uint32_t tmp_buffer[2 * N_TMP_PIXELS];
508 bits = pict->bits.bits;
509 stride = pict->bits.rowstride;
511 /* reference point is the center of the pixel */
512 v.vector[0] = pixman_int_to_fixed(x) + pixman_fixed_1 / 2;
513 v.vector[1] = pixman_int_to_fixed(y) + pixman_fixed_1 / 2;
514 v.vector[2] = pixman_fixed_1;
516 /* when using convolution filters or PIXMAN_REPEAT_PAD one
517 * might get here without a transform */
518 if (pict->common.transform)
520 if (!pixman_transform_point_3d (pict->common.transform, &v))
523 unit.vector[0] = pict->common.transform->matrix[0][0];
524 unit.vector[1] = pict->common.transform->matrix[1][0];
525 unit.vector[2] = pict->common.transform->matrix[2][0];
527 affine = (v.vector[2] == pixman_fixed_1 && unit.vector[2] == 0);
531 unit.vector[0] = pixman_fixed_1;
539 int n_pixels = MIN (N_TMP_PIXELS, width - i);
542 coords = (int32_t *)tmp_buffer;
544 for (j = 0; j < n_pixels; ++j)
548 coords[0] = v.vector[0];
549 coords[1] = v.vector[1];
553 pixman_fixed_48_16_t div;
555 div = ((pixman_fixed_48_16_t)v.vector[0] << 16) / v.vector[2];
557 if ((div >> 16) > 0x7fff)
558 coords[0] = 0x7fffffff;
559 else if ((div >> 16) < 0x8000)
560 coords[0] = 0x80000000;
564 div = ((pixman_fixed_48_16_t)v.vector[1] << 16) / v.vector[2];
566 if ((div >> 16) > 0x7fff)
567 coords[1] = 0x7fffffff;
568 else if ((div >> 16) < 0x8000)
569 coords[1] = 0x8000000;
573 v.vector[2] += unit.vector[2];
578 v.vector[0] += unit.vector[0];
579 v.vector[1] += unit.vector[1];
582 bits_image_fetch_filtered (&pict->bits, tmp_buffer, n_pixels);
584 for (j = 0; j < n_pixels; ++j)
585 buffer[i++] = tmp_buffer[j];
590 bits_image_fetch_solid_32 (pixman_image_t * image,
591 int x, int y, int width,
593 uint32_t *mask, uint32_t maskBits)
601 image->bits.fetch_pixels_raw_32 (&image->bits, color, 1);
603 end = buffer + width;
605 *(buffer++) = color[0];
609 bits_image_fetch_solid_64 (pixman_image_t * image,
610 int x, int y, int width,
616 uint32_t *coords = (uint32_t *)color;
617 uint64_t *buffer = (uint64_t *)b;
623 image->bits.fetch_pixels_raw_64 (&image->bits, color, 1);
625 end = buffer + width;
627 *(buffer++) = color[0];
631 bits_image_fetch_untransformed_repeat_none (bits_image_t *image, pixman_bool_t wide,
632 int x, int y, int width,
637 if (y < 0 || y >= image->height)
639 memset (buffer, 0, width * sizeof (uint32_t));
647 memset (buffer, 0, w * (wide? 8 : 4));
654 if (x < image->width)
656 w = MIN (width, image->width - x);
659 image->fetch_scanline_raw_64 (image, x, y, w, buffer, NULL, 0);
661 image->fetch_scanline_raw_32 (image, x, y, w, buffer, NULL, 0);
668 memset (buffer, 0, width * (wide? 8 : 4));
672 bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, pixman_bool_t wide,
673 int x, int y, int width,
680 while (y >= image->height)
687 while (x >= image->width)
690 w = MIN (width, image->width - x);
693 image->fetch_scanline_raw_64 (image, x, y, w, buffer, NULL, 0);
695 image->fetch_scanline_raw_32 (image, x, y, w, buffer, NULL, 0);
704 bits_image_fetch_untransformed_32 (pixman_image_t * image,
705 int x, int y, int width,
707 uint32_t *mask, uint32_t maskBits)
709 if (image->common.repeat == PIXMAN_REPEAT_NONE)
711 bits_image_fetch_untransformed_repeat_none (
712 &image->bits, FALSE, x, y, width, buffer);
716 bits_image_fetch_untransformed_repeat_normal (
717 &image->bits, FALSE, x, y, width, buffer);
722 bits_image_fetch_untransformed_64 (pixman_image_t * image,
723 int x, int y, int width,
725 uint32_t *unused, uint32_t unused2)
727 if (image->common.repeat == PIXMAN_REPEAT_NONE)
729 bits_image_fetch_untransformed_repeat_none (
730 &image->bits, TRUE, x, y, width, buffer);
734 bits_image_fetch_untransformed_repeat_normal (
735 &image->bits, TRUE, x, y, width, buffer);
740 bits_image_property_changed (pixman_image_t *image)
742 bits_image_t *bits = (bits_image_t *)image;
744 _pixman_bits_image_setup_raw_accessors (bits);
746 if (bits->common.alpha_map)
748 image->common.get_scanline_64 =
749 _pixman_image_get_scanline_64_generic;
750 image->common.get_scanline_32 =
751 bits_image_fetch_transformed;
753 else if ((bits->common.repeat != PIXMAN_REPEAT_NONE) &&
757 image->common.get_scanline_64 = bits_image_fetch_solid_64;
758 image->common.get_scanline_32 = bits_image_fetch_solid_32;
760 else if (!bits->common.transform &&
761 bits->common.filter != PIXMAN_FILTER_CONVOLUTION &&
762 (bits->common.repeat == PIXMAN_REPEAT_NONE ||
763 bits->common.repeat == PIXMAN_REPEAT_NORMAL))
765 image->common.get_scanline_64 =
766 bits_image_fetch_untransformed_64;
767 image->common.get_scanline_32 =
768 bits_image_fetch_untransformed_32;
772 image->common.get_scanline_64 =
773 _pixman_image_get_scanline_64_generic;
774 image->common.get_scanline_32 =
775 bits_image_fetch_transformed;
778 bits->store_scanline_64 = bits_image_store_scanline_64;
779 bits->store_scanline_32 = bits_image_store_scanline_32;
783 create_bits (pixman_format_code_t format,
786 int *rowstride_bytes)
792 /* what follows is a long-winded way, avoiding any possibility of integer
793 * overflows, of saying:
794 * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t);
797 bpp = PIXMAN_FORMAT_BPP (format);
798 if (pixman_multiply_overflows_int (width, bpp))
801 stride = width * bpp;
802 if (pixman_addition_overflows_int (stride, 0x1f))
808 stride *= sizeof (uint32_t);
810 if (pixman_multiply_overflows_int (height, stride))
813 buf_size = height * stride;
816 *rowstride_bytes = stride;
818 return calloc (buf_size, 1);
821 PIXMAN_EXPORT pixman_image_t *
822 pixman_image_create_bits (pixman_format_code_t format,
828 pixman_image_t *image;
829 uint32_t *free_me = NULL;
831 /* must be a whole number of uint32_t's
833 return_val_if_fail (bits == NULL ||
834 (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
836 if (!bits && width && height)
838 free_me = bits = create_bits (format, width, height, &rowstride_bytes);
843 image = _pixman_image_allocate();
852 image->bits.format = format;
853 image->bits.width = width;
854 image->bits.height = height;
855 image->bits.bits = bits;
856 image->bits.free_me = free_me;
858 /* The rowstride is stored in number of uint32_t */
859 image->bits.rowstride = rowstride_bytes / (int) sizeof (uint32_t);
861 image->bits.indexed = NULL;
863 image->common.property_changed = bits_image_property_changed;
865 bits_image_property_changed (image);
867 _pixman_image_reset_clip_region (image);