1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/cairo/libpixman/src/pixman-general.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,243 @@ 1.4 +/* 1.5 + * Copyright © 2009 Red Hat, Inc. 1.6 + * Copyright © 2000 SuSE, Inc. 1.7 + * Copyright © 2007 Red Hat, Inc. 1.8 + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. 1.9 + * 2005 Lars Knoll & Zack Rusin, Trolltech 1.10 + * 2008 Aaron Plattner, NVIDIA Corporation 1.11 + * 1.12 + * Permission to use, copy, modify, distribute, and sell this software and its 1.13 + * documentation for any purpose is hereby granted without fee, provided that 1.14 + * the above copyright notice appear in all copies and that both that 1.15 + * copyright notice and this permission notice appear in supporting 1.16 + * documentation, and that the name of Red Hat not be used in advertising or 1.17 + * publicity pertaining to distribution of the software without specific, 1.18 + * written prior permission. Red Hat makes no representations about the 1.19 + * suitability of this software for any purpose. It is provided "as is" 1.20 + * without express or implied warranty. 1.21 + * 1.22 + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 1.23 + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 1.24 + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 1.25 + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1.26 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 1.27 + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 1.28 + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 1.29 + * SOFTWARE. 1.30 + */ 1.31 +#ifdef HAVE_CONFIG_H 1.32 +#include <config.h> 1.33 +#endif 1.34 +#include <stdlib.h> 1.35 +#include <string.h> 1.36 +#include <math.h> 1.37 +#include <limits.h> 1.38 +#include <stdio.h> 1.39 +#include <stdlib.h> 1.40 +#include <string.h> 1.41 +#include "pixman-private.h" 1.42 + 1.43 +static pixman_bool_t 1.44 +general_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) 1.45 +{ 1.46 + pixman_image_t *image = iter->image; 1.47 + 1.48 + if (image->type == LINEAR) 1.49 + _pixman_linear_gradient_iter_init (image, iter); 1.50 + else if (image->type == RADIAL) 1.51 + _pixman_radial_gradient_iter_init (image, iter); 1.52 + else if (image->type == CONICAL) 1.53 + _pixman_conical_gradient_iter_init (image, iter); 1.54 + else if (image->type == BITS) 1.55 + _pixman_bits_image_src_iter_init (image, iter); 1.56 + else if (image->type == SOLID) 1.57 + _pixman_log_error (FUNC, "Solid image not handled by noop"); 1.58 + else 1.59 + _pixman_log_error (FUNC, "Pixman bug: unknown image type\n"); 1.60 + 1.61 + return TRUE; 1.62 +} 1.63 + 1.64 +static pixman_bool_t 1.65 +general_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) 1.66 +{ 1.67 + if (iter->image->type == BITS) 1.68 + { 1.69 + _pixman_bits_image_dest_iter_init (iter->image, iter); 1.70 + 1.71 + return TRUE; 1.72 + } 1.73 + else 1.74 + { 1.75 + _pixman_log_error (FUNC, "Trying to write to a non-writable image"); 1.76 + 1.77 + return FALSE; 1.78 + } 1.79 +} 1.80 + 1.81 +typedef struct op_info_t op_info_t; 1.82 +struct op_info_t 1.83 +{ 1.84 + uint8_t src, dst; 1.85 +}; 1.86 + 1.87 +#define ITER_IGNORE_BOTH \ 1.88 + (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_LOCALIZED_ALPHA) 1.89 + 1.90 +static const op_info_t op_flags[PIXMAN_N_OPERATORS] = 1.91 +{ 1.92 + /* Src Dst */ 1.93 + { ITER_IGNORE_BOTH, ITER_IGNORE_BOTH }, /* CLEAR */ 1.94 + { ITER_LOCALIZED_ALPHA, ITER_IGNORE_BOTH }, /* SRC */ 1.95 + { ITER_IGNORE_BOTH, ITER_LOCALIZED_ALPHA }, /* DST */ 1.96 + { 0, ITER_LOCALIZED_ALPHA }, /* OVER */ 1.97 + { ITER_LOCALIZED_ALPHA, 0 }, /* OVER_REVERSE */ 1.98 + { ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* IN */ 1.99 + { ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* IN_REVERSE */ 1.100 + { ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* OUT */ 1.101 + { ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* OUT_REVERSE */ 1.102 + { 0, 0 }, /* ATOP */ 1.103 + { 0, 0 }, /* ATOP_REVERSE */ 1.104 + { 0, 0 }, /* XOR */ 1.105 + { ITER_LOCALIZED_ALPHA, ITER_LOCALIZED_ALPHA }, /* ADD */ 1.106 + { 0, 0 }, /* SATURATE */ 1.107 +}; 1.108 + 1.109 +#define SCANLINE_BUFFER_LENGTH 8192 1.110 + 1.111 +static void 1.112 +general_composite_rect (pixman_implementation_t *imp, 1.113 + pixman_composite_info_t *info) 1.114 +{ 1.115 + PIXMAN_COMPOSITE_ARGS (info); 1.116 + uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8]; 1.117 + uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer; 1.118 + uint8_t *src_buffer, *mask_buffer, *dest_buffer; 1.119 + pixman_iter_t src_iter, mask_iter, dest_iter; 1.120 + pixman_combine_32_func_t compose; 1.121 + pixman_bool_t component_alpha; 1.122 + iter_flags_t narrow, src_iter_flags; 1.123 + iter_flags_t rgb16; 1.124 + int Bpp; 1.125 + int i; 1.126 + 1.127 + if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT) && 1.128 + (!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT) && 1.129 + (dest_image->common.flags & FAST_PATH_NARROW_FORMAT)) 1.130 + { 1.131 + narrow = ITER_NARROW; 1.132 + Bpp = 4; 1.133 + } 1.134 + else 1.135 + { 1.136 + narrow = 0; 1.137 + Bpp = 16; 1.138 + } 1.139 + 1.140 + // XXX: This special casing is bad. Ideally, we'd keep the general code general perhaps 1.141 + // by having it deal more specifically with different intermediate formats 1.142 + if ( 1.143 + (dest_image->common.flags & FAST_PATH_16_FORMAT && (src_image->type == LINEAR || src_image->type == RADIAL)) && 1.144 + ( op == PIXMAN_OP_SRC || 1.145 + (op == PIXMAN_OP_OVER && (src_image->common.flags & FAST_PATH_IS_OPAQUE)) 1.146 + ) 1.147 + ) { 1.148 + rgb16 = ITER_16; 1.149 + } else { 1.150 + rgb16 = 0; 1.151 + } 1.152 + 1.153 + 1.154 + if (width * Bpp > SCANLINE_BUFFER_LENGTH) 1.155 + { 1.156 + scanline_buffer = pixman_malloc_abc (width, 3, Bpp); 1.157 + 1.158 + if (!scanline_buffer) 1.159 + return; 1.160 + } 1.161 + 1.162 + src_buffer = scanline_buffer; 1.163 + mask_buffer = src_buffer + width * Bpp; 1.164 + dest_buffer = mask_buffer + width * Bpp; 1.165 + 1.166 + if (!narrow) 1.167 + { 1.168 + /* To make sure there aren't any NANs in the buffers */ 1.169 + memset (src_buffer, 0, width * Bpp); 1.170 + memset (mask_buffer, 0, width * Bpp); 1.171 + memset (dest_buffer, 0, width * Bpp); 1.172 + } 1.173 + 1.174 + /* src iter */ 1.175 + src_iter_flags = narrow | op_flags[op].src | rgb16; 1.176 + 1.177 + _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src_image, 1.178 + src_x, src_y, width, height, 1.179 + src_buffer, src_iter_flags, info->src_flags); 1.180 + 1.181 + /* mask iter */ 1.182 + if ((src_iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) == 1.183 + (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) 1.184 + { 1.185 + /* If it doesn't matter what the source is, then it doesn't matter 1.186 + * what the mask is 1.187 + */ 1.188 + mask_image = NULL; 1.189 + } 1.190 + 1.191 + component_alpha = 1.192 + mask_image && 1.193 + mask_image->common.type == BITS && 1.194 + mask_image->common.component_alpha && 1.195 + PIXMAN_FORMAT_RGB (mask_image->bits.format); 1.196 + 1.197 + _pixman_implementation_src_iter_init ( 1.198 + imp->toplevel, &mask_iter, mask_image, mask_x, mask_y, width, height, 1.199 + mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB), info->mask_flags); 1.200 + 1.201 + /* dest iter */ 1.202 + _pixman_implementation_dest_iter_init ( 1.203 + imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height, 1.204 + dest_buffer, narrow | op_flags[op].dst | rgb16, info->dest_flags); 1.205 + 1.206 + compose = _pixman_implementation_lookup_combiner ( 1.207 + imp->toplevel, op, component_alpha, narrow, !!rgb16); 1.208 + 1.209 + for (i = 0; i < height; ++i) 1.210 + { 1.211 + uint32_t *s, *m, *d; 1.212 + 1.213 + m = mask_iter.get_scanline (&mask_iter, NULL); 1.214 + s = src_iter.get_scanline (&src_iter, m); 1.215 + d = dest_iter.get_scanline (&dest_iter, NULL); 1.216 + 1.217 + compose (imp->toplevel, op, d, s, m, width); 1.218 + 1.219 + dest_iter.write_back (&dest_iter); 1.220 + } 1.221 + 1.222 + if (scanline_buffer != (uint8_t *) stack_scanline_buffer) 1.223 + free (scanline_buffer); 1.224 +} 1.225 + 1.226 +static const pixman_fast_path_t general_fast_path[] = 1.227 +{ 1.228 + { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect }, 1.229 + { PIXMAN_OP_NONE } 1.230 +}; 1.231 + 1.232 +pixman_implementation_t * 1.233 +_pixman_implementation_create_general (void) 1.234 +{ 1.235 + pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path); 1.236 + 1.237 + _pixman_setup_combiner_functions_16 (imp); 1.238 + _pixman_setup_combiner_functions_32 (imp); 1.239 + _pixman_setup_combiner_functions_float (imp); 1.240 + 1.241 + imp->src_iter_init = general_src_iter_init; 1.242 + imp->dest_iter_init = general_dest_iter_init; 1.243 + 1.244 + return imp; 1.245 +} 1.246 +