1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/cairo/libpixman/src/pixman-implementation.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,397 @@ 1.4 +/* 1.5 + * Copyright © 2009 Red Hat, Inc. 1.6 + * 1.7 + * Permission to use, copy, modify, distribute, and sell this software and its 1.8 + * documentation for any purpose is hereby granted without fee, provided that 1.9 + * the above copyright notice appear in all copies and that both that 1.10 + * copyright notice and this permission notice appear in supporting 1.11 + * documentation, and that the name of Red Hat not be used in advertising or 1.12 + * publicity pertaining to distribution of the software without specific, 1.13 + * written prior permission. Red Hat makes no representations about the 1.14 + * suitability of this software for any purpose. It is provided "as is" 1.15 + * without express or implied warranty. 1.16 + * 1.17 + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 1.18 + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 1.19 + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 1.20 + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1.21 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 1.22 + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 1.23 + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 1.24 + * SOFTWARE. 1.25 + */ 1.26 + 1.27 +#ifdef HAVE_CONFIG_H 1.28 +#include <config.h> 1.29 +#endif 1.30 +#include <stdlib.h> 1.31 +#include "pixman-private.h" 1.32 + 1.33 +pixman_implementation_t * 1.34 +_pixman_implementation_create (pixman_implementation_t *fallback, 1.35 + const pixman_fast_path_t *fast_paths) 1.36 +{ 1.37 + pixman_implementation_t *imp; 1.38 + 1.39 + assert (fast_paths); 1.40 + 1.41 + if ((imp = malloc (sizeof (pixman_implementation_t)))) 1.42 + { 1.43 + pixman_implementation_t *d; 1.44 + 1.45 + memset (imp, 0, sizeof *imp); 1.46 + 1.47 + imp->fallback = fallback; 1.48 + imp->fast_paths = fast_paths; 1.49 + 1.50 + /* Make sure the whole fallback chain has the right toplevel */ 1.51 + for (d = imp; d != NULL; d = d->fallback) 1.52 + d->toplevel = imp; 1.53 + } 1.54 + 1.55 + return imp; 1.56 +} 1.57 + 1.58 +#define N_CACHED_FAST_PATHS 8 1.59 + 1.60 +typedef struct 1.61 +{ 1.62 + struct 1.63 + { 1.64 + pixman_implementation_t * imp; 1.65 + pixman_fast_path_t fast_path; 1.66 + } cache [N_CACHED_FAST_PATHS]; 1.67 +} cache_t; 1.68 + 1.69 +PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache); 1.70 + 1.71 +static void 1.72 +dummy_composite_rect (pixman_implementation_t *imp, 1.73 + pixman_composite_info_t *info) 1.74 +{ 1.75 +} 1.76 + 1.77 +void 1.78 +_pixman_implementation_lookup_composite (pixman_implementation_t *toplevel, 1.79 + pixman_op_t op, 1.80 + pixman_format_code_t src_format, 1.81 + uint32_t src_flags, 1.82 + pixman_format_code_t mask_format, 1.83 + uint32_t mask_flags, 1.84 + pixman_format_code_t dest_format, 1.85 + uint32_t dest_flags, 1.86 + pixman_implementation_t **out_imp, 1.87 + pixman_composite_func_t *out_func) 1.88 +{ 1.89 + pixman_implementation_t *imp; 1.90 + cache_t *cache; 1.91 + int i; 1.92 + 1.93 + /* Check cache for fast paths */ 1.94 + cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache); 1.95 + 1.96 + for (i = 0; i < N_CACHED_FAST_PATHS; ++i) 1.97 + { 1.98 + const pixman_fast_path_t *info = &(cache->cache[i].fast_path); 1.99 + 1.100 + /* Note that we check for equality here, not whether 1.101 + * the cached fast path matches. This is to prevent 1.102 + * us from selecting an overly general fast path 1.103 + * when a more specific one would work. 1.104 + */ 1.105 + if (info->op == op && 1.106 + info->src_format == src_format && 1.107 + info->mask_format == mask_format && 1.108 + info->dest_format == dest_format && 1.109 + info->src_flags == src_flags && 1.110 + info->mask_flags == mask_flags && 1.111 + info->dest_flags == dest_flags && 1.112 + info->func) 1.113 + { 1.114 + *out_imp = cache->cache[i].imp; 1.115 + *out_func = cache->cache[i].fast_path.func; 1.116 + 1.117 + goto update_cache; 1.118 + } 1.119 + } 1.120 + 1.121 + for (imp = toplevel; imp != NULL; imp = imp->fallback) 1.122 + { 1.123 + const pixman_fast_path_t *info = imp->fast_paths; 1.124 + 1.125 + while (info->op != PIXMAN_OP_NONE) 1.126 + { 1.127 + if ((info->op == op || info->op == PIXMAN_OP_any) && 1.128 + /* Formats */ 1.129 + ((info->src_format == src_format) || 1.130 + (info->src_format == PIXMAN_any)) && 1.131 + ((info->mask_format == mask_format) || 1.132 + (info->mask_format == PIXMAN_any)) && 1.133 + ((info->dest_format == dest_format) || 1.134 + (info->dest_format == PIXMAN_any)) && 1.135 + /* Flags */ 1.136 + (info->src_flags & src_flags) == info->src_flags && 1.137 + (info->mask_flags & mask_flags) == info->mask_flags && 1.138 + (info->dest_flags & dest_flags) == info->dest_flags) 1.139 + { 1.140 + *out_imp = imp; 1.141 + *out_func = info->func; 1.142 + 1.143 + /* Set i to the last spot in the cache so that the 1.144 + * move-to-front code below will work 1.145 + */ 1.146 + i = N_CACHED_FAST_PATHS - 1; 1.147 + 1.148 + goto update_cache; 1.149 + } 1.150 + 1.151 + ++info; 1.152 + } 1.153 + } 1.154 + 1.155 + /* We should never reach this point */ 1.156 + _pixman_log_error (FUNC, "No known composite function\n"); 1.157 + *out_imp = NULL; 1.158 + *out_func = dummy_composite_rect; 1.159 + 1.160 +update_cache: 1.161 + if (i) 1.162 + { 1.163 + while (i--) 1.164 + cache->cache[i + 1] = cache->cache[i]; 1.165 + 1.166 + cache->cache[0].imp = *out_imp; 1.167 + cache->cache[0].fast_path.op = op; 1.168 + cache->cache[0].fast_path.src_format = src_format; 1.169 + cache->cache[0].fast_path.src_flags = src_flags; 1.170 + cache->cache[0].fast_path.mask_format = mask_format; 1.171 + cache->cache[0].fast_path.mask_flags = mask_flags; 1.172 + cache->cache[0].fast_path.dest_format = dest_format; 1.173 + cache->cache[0].fast_path.dest_flags = dest_flags; 1.174 + cache->cache[0].fast_path.func = *out_func; 1.175 + } 1.176 +} 1.177 + 1.178 +static void 1.179 +dummy_combine (pixman_implementation_t *imp, 1.180 + pixman_op_t op, 1.181 + uint32_t * pd, 1.182 + const uint32_t * ps, 1.183 + const uint32_t * pm, 1.184 + int w) 1.185 +{ 1.186 +} 1.187 + 1.188 +pixman_combine_32_func_t 1.189 +_pixman_implementation_lookup_combiner (pixman_implementation_t *imp, 1.190 + pixman_op_t op, 1.191 + pixman_bool_t component_alpha, 1.192 + pixman_bool_t narrow, 1.193 + pixman_bool_t rgb16) 1.194 +{ 1.195 + while (imp) 1.196 + { 1.197 + pixman_combine_32_func_t f = NULL; 1.198 + 1.199 + switch ((narrow << 1) | component_alpha) 1.200 + { 1.201 + case 0: /* not narrow, not component alpha */ 1.202 + f = (pixman_combine_32_func_t)imp->combine_float[op]; 1.203 + break; 1.204 + 1.205 + case 1: /* not narrow, component_alpha */ 1.206 + f = (pixman_combine_32_func_t)imp->combine_float_ca[op]; 1.207 + break; 1.208 + 1.209 + case 2: /* narrow, not component alpha */ 1.210 + f = imp->combine_32[op]; 1.211 + break; 1.212 + 1.213 + case 3: /* narrow, component_alpha */ 1.214 + f = imp->combine_32_ca[op]; 1.215 + break; 1.216 + } 1.217 + if (rgb16) 1.218 + f = (pixman_combine_32_func_t *)imp->combine_16[op]; 1.219 + 1.220 + if (f) 1.221 + return f; 1.222 + 1.223 + imp = imp->fallback; 1.224 + } 1.225 + 1.226 + /* We should never reach this point */ 1.227 + _pixman_log_error (FUNC, "No known combine function\n"); 1.228 + return dummy_combine; 1.229 +} 1.230 + 1.231 +pixman_bool_t 1.232 +_pixman_implementation_blt (pixman_implementation_t * imp, 1.233 + uint32_t * src_bits, 1.234 + uint32_t * dst_bits, 1.235 + int src_stride, 1.236 + int dst_stride, 1.237 + int src_bpp, 1.238 + int dst_bpp, 1.239 + int src_x, 1.240 + int src_y, 1.241 + int dest_x, 1.242 + int dest_y, 1.243 + int width, 1.244 + int height) 1.245 +{ 1.246 + while (imp) 1.247 + { 1.248 + if (imp->blt && 1.249 + (*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride, 1.250 + src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y, 1.251 + width, height)) 1.252 + { 1.253 + return TRUE; 1.254 + } 1.255 + 1.256 + imp = imp->fallback; 1.257 + } 1.258 + 1.259 + return FALSE; 1.260 +} 1.261 + 1.262 +pixman_bool_t 1.263 +_pixman_implementation_fill (pixman_implementation_t *imp, 1.264 + uint32_t * bits, 1.265 + int stride, 1.266 + int bpp, 1.267 + int x, 1.268 + int y, 1.269 + int width, 1.270 + int height, 1.271 + uint32_t filler) 1.272 +{ 1.273 + while (imp) 1.274 + { 1.275 + if (imp->fill && 1.276 + ((*imp->fill) (imp, bits, stride, bpp, x, y, width, height, filler))) 1.277 + { 1.278 + return TRUE; 1.279 + } 1.280 + 1.281 + imp = imp->fallback; 1.282 + } 1.283 + 1.284 + return FALSE; 1.285 +} 1.286 + 1.287 +pixman_bool_t 1.288 +_pixman_implementation_src_iter_init (pixman_implementation_t *imp, 1.289 + pixman_iter_t *iter, 1.290 + pixman_image_t *image, 1.291 + int x, 1.292 + int y, 1.293 + int width, 1.294 + int height, 1.295 + uint8_t *buffer, 1.296 + iter_flags_t iter_flags, 1.297 + uint32_t image_flags) 1.298 +{ 1.299 + iter->image = image; 1.300 + iter->buffer = (uint32_t *)buffer; 1.301 + iter->x = x; 1.302 + iter->y = y; 1.303 + iter->width = width; 1.304 + iter->height = height; 1.305 + iter->iter_flags = iter_flags; 1.306 + iter->image_flags = image_flags; 1.307 + 1.308 + while (imp) 1.309 + { 1.310 + if (imp->src_iter_init && (*imp->src_iter_init) (imp, iter)) 1.311 + return TRUE; 1.312 + 1.313 + imp = imp->fallback; 1.314 + } 1.315 + 1.316 + return FALSE; 1.317 +} 1.318 + 1.319 +pixman_bool_t 1.320 +_pixman_implementation_dest_iter_init (pixman_implementation_t *imp, 1.321 + pixman_iter_t *iter, 1.322 + pixman_image_t *image, 1.323 + int x, 1.324 + int y, 1.325 + int width, 1.326 + int height, 1.327 + uint8_t *buffer, 1.328 + iter_flags_t iter_flags, 1.329 + uint32_t image_flags) 1.330 +{ 1.331 + iter->image = image; 1.332 + iter->buffer = (uint32_t *)buffer; 1.333 + iter->x = x; 1.334 + iter->y = y; 1.335 + iter->width = width; 1.336 + iter->height = height; 1.337 + iter->iter_flags = iter_flags; 1.338 + iter->image_flags = image_flags; 1.339 + 1.340 + while (imp) 1.341 + { 1.342 + if (imp->dest_iter_init && (*imp->dest_iter_init) (imp, iter)) 1.343 + return TRUE; 1.344 + 1.345 + imp = imp->fallback; 1.346 + } 1.347 + 1.348 + return FALSE; 1.349 +} 1.350 + 1.351 +pixman_bool_t 1.352 +_pixman_disabled (const char *name) 1.353 +{ 1.354 + const char *env; 1.355 + 1.356 + if ((env = getenv ("PIXMAN_DISABLE"))) 1.357 + { 1.358 + do 1.359 + { 1.360 + const char *end; 1.361 + int len; 1.362 + 1.363 + if ((end = strchr (env, ' '))) 1.364 + len = end - env; 1.365 + else 1.366 + len = strlen (env); 1.367 + 1.368 + if (strlen (name) == len && strncmp (name, env, len) == 0) 1.369 + { 1.370 + printf ("pixman: Disabled %s implementation\n", name); 1.371 + return TRUE; 1.372 + } 1.373 + 1.374 + env += len; 1.375 + } 1.376 + while (*env++); 1.377 + } 1.378 + 1.379 + return FALSE; 1.380 +} 1.381 + 1.382 +pixman_implementation_t * 1.383 +_pixman_choose_implementation (void) 1.384 +{ 1.385 + pixman_implementation_t *imp; 1.386 + 1.387 + imp = _pixman_implementation_create_general(); 1.388 + 1.389 + if (!_pixman_disabled ("fast")) 1.390 + imp = _pixman_implementation_create_fast_path (imp); 1.391 + 1.392 + imp = _pixman_x86_get_implementations (imp); 1.393 + imp = _pixman_arm_get_implementations (imp); 1.394 + imp = _pixman_ppc_get_implementations (imp); 1.395 + imp = _pixman_mips_get_implementations (imp); 1.396 + 1.397 + imp = _pixman_implementation_create_noop (imp); 1.398 + 1.399 + return imp; 1.400 +}