Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* |
michael@0 | 2 | * Copyright © 2009 Red Hat, Inc. |
michael@0 | 3 | * |
michael@0 | 4 | * Permission to use, copy, modify, distribute, and sell this software and its |
michael@0 | 5 | * documentation for any purpose is hereby granted without fee, provided that |
michael@0 | 6 | * the above copyright notice appear in all copies and that both that |
michael@0 | 7 | * copyright notice and this permission notice appear in supporting |
michael@0 | 8 | * documentation, and that the name of Red Hat not be used in advertising or |
michael@0 | 9 | * publicity pertaining to distribution of the software without specific, |
michael@0 | 10 | * written prior permission. Red Hat makes no representations about the |
michael@0 | 11 | * suitability of this software for any purpose. It is provided "as is" |
michael@0 | 12 | * without express or implied warranty. |
michael@0 | 13 | * |
michael@0 | 14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS |
michael@0 | 15 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
michael@0 | 16 | * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY |
michael@0 | 17 | * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
michael@0 | 18 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN |
michael@0 | 19 | * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING |
michael@0 | 20 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
michael@0 | 21 | * SOFTWARE. |
michael@0 | 22 | */ |
michael@0 | 23 | |
michael@0 | 24 | #ifdef HAVE_CONFIG_H |
michael@0 | 25 | #include <config.h> |
michael@0 | 26 | #endif |
michael@0 | 27 | #include <stdlib.h> |
michael@0 | 28 | #include "pixman-private.h" |
michael@0 | 29 | |
michael@0 | 30 | pixman_implementation_t * |
michael@0 | 31 | _pixman_implementation_create (pixman_implementation_t *fallback, |
michael@0 | 32 | const pixman_fast_path_t *fast_paths) |
michael@0 | 33 | { |
michael@0 | 34 | pixman_implementation_t *imp; |
michael@0 | 35 | |
michael@0 | 36 | assert (fast_paths); |
michael@0 | 37 | |
michael@0 | 38 | if ((imp = malloc (sizeof (pixman_implementation_t)))) |
michael@0 | 39 | { |
michael@0 | 40 | pixman_implementation_t *d; |
michael@0 | 41 | |
michael@0 | 42 | memset (imp, 0, sizeof *imp); |
michael@0 | 43 | |
michael@0 | 44 | imp->fallback = fallback; |
michael@0 | 45 | imp->fast_paths = fast_paths; |
michael@0 | 46 | |
michael@0 | 47 | /* Make sure the whole fallback chain has the right toplevel */ |
michael@0 | 48 | for (d = imp; d != NULL; d = d->fallback) |
michael@0 | 49 | d->toplevel = imp; |
michael@0 | 50 | } |
michael@0 | 51 | |
michael@0 | 52 | return imp; |
michael@0 | 53 | } |
michael@0 | 54 | |
michael@0 | 55 | #define N_CACHED_FAST_PATHS 8 |
michael@0 | 56 | |
michael@0 | 57 | typedef struct |
michael@0 | 58 | { |
michael@0 | 59 | struct |
michael@0 | 60 | { |
michael@0 | 61 | pixman_implementation_t * imp; |
michael@0 | 62 | pixman_fast_path_t fast_path; |
michael@0 | 63 | } cache [N_CACHED_FAST_PATHS]; |
michael@0 | 64 | } cache_t; |
michael@0 | 65 | |
michael@0 | 66 | PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache); |
michael@0 | 67 | |
michael@0 | 68 | static void |
michael@0 | 69 | dummy_composite_rect (pixman_implementation_t *imp, |
michael@0 | 70 | pixman_composite_info_t *info) |
michael@0 | 71 | { |
michael@0 | 72 | } |
michael@0 | 73 | |
michael@0 | 74 | void |
michael@0 | 75 | _pixman_implementation_lookup_composite (pixman_implementation_t *toplevel, |
michael@0 | 76 | pixman_op_t op, |
michael@0 | 77 | pixman_format_code_t src_format, |
michael@0 | 78 | uint32_t src_flags, |
michael@0 | 79 | pixman_format_code_t mask_format, |
michael@0 | 80 | uint32_t mask_flags, |
michael@0 | 81 | pixman_format_code_t dest_format, |
michael@0 | 82 | uint32_t dest_flags, |
michael@0 | 83 | pixman_implementation_t **out_imp, |
michael@0 | 84 | pixman_composite_func_t *out_func) |
michael@0 | 85 | { |
michael@0 | 86 | pixman_implementation_t *imp; |
michael@0 | 87 | cache_t *cache; |
michael@0 | 88 | int i; |
michael@0 | 89 | |
michael@0 | 90 | /* Check cache for fast paths */ |
michael@0 | 91 | cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache); |
michael@0 | 92 | |
michael@0 | 93 | for (i = 0; i < N_CACHED_FAST_PATHS; ++i) |
michael@0 | 94 | { |
michael@0 | 95 | const pixman_fast_path_t *info = &(cache->cache[i].fast_path); |
michael@0 | 96 | |
michael@0 | 97 | /* Note that we check for equality here, not whether |
michael@0 | 98 | * the cached fast path matches. This is to prevent |
michael@0 | 99 | * us from selecting an overly general fast path |
michael@0 | 100 | * when a more specific one would work. |
michael@0 | 101 | */ |
michael@0 | 102 | if (info->op == op && |
michael@0 | 103 | info->src_format == src_format && |
michael@0 | 104 | info->mask_format == mask_format && |
michael@0 | 105 | info->dest_format == dest_format && |
michael@0 | 106 | info->src_flags == src_flags && |
michael@0 | 107 | info->mask_flags == mask_flags && |
michael@0 | 108 | info->dest_flags == dest_flags && |
michael@0 | 109 | info->func) |
michael@0 | 110 | { |
michael@0 | 111 | *out_imp = cache->cache[i].imp; |
michael@0 | 112 | *out_func = cache->cache[i].fast_path.func; |
michael@0 | 113 | |
michael@0 | 114 | goto update_cache; |
michael@0 | 115 | } |
michael@0 | 116 | } |
michael@0 | 117 | |
michael@0 | 118 | for (imp = toplevel; imp != NULL; imp = imp->fallback) |
michael@0 | 119 | { |
michael@0 | 120 | const pixman_fast_path_t *info = imp->fast_paths; |
michael@0 | 121 | |
michael@0 | 122 | while (info->op != PIXMAN_OP_NONE) |
michael@0 | 123 | { |
michael@0 | 124 | if ((info->op == op || info->op == PIXMAN_OP_any) && |
michael@0 | 125 | /* Formats */ |
michael@0 | 126 | ((info->src_format == src_format) || |
michael@0 | 127 | (info->src_format == PIXMAN_any)) && |
michael@0 | 128 | ((info->mask_format == mask_format) || |
michael@0 | 129 | (info->mask_format == PIXMAN_any)) && |
michael@0 | 130 | ((info->dest_format == dest_format) || |
michael@0 | 131 | (info->dest_format == PIXMAN_any)) && |
michael@0 | 132 | /* Flags */ |
michael@0 | 133 | (info->src_flags & src_flags) == info->src_flags && |
michael@0 | 134 | (info->mask_flags & mask_flags) == info->mask_flags && |
michael@0 | 135 | (info->dest_flags & dest_flags) == info->dest_flags) |
michael@0 | 136 | { |
michael@0 | 137 | *out_imp = imp; |
michael@0 | 138 | *out_func = info->func; |
michael@0 | 139 | |
michael@0 | 140 | /* Set i to the last spot in the cache so that the |
michael@0 | 141 | * move-to-front code below will work |
michael@0 | 142 | */ |
michael@0 | 143 | i = N_CACHED_FAST_PATHS - 1; |
michael@0 | 144 | |
michael@0 | 145 | goto update_cache; |
michael@0 | 146 | } |
michael@0 | 147 | |
michael@0 | 148 | ++info; |
michael@0 | 149 | } |
michael@0 | 150 | } |
michael@0 | 151 | |
michael@0 | 152 | /* We should never reach this point */ |
michael@0 | 153 | _pixman_log_error (FUNC, "No known composite function\n"); |
michael@0 | 154 | *out_imp = NULL; |
michael@0 | 155 | *out_func = dummy_composite_rect; |
michael@0 | 156 | |
michael@0 | 157 | update_cache: |
michael@0 | 158 | if (i) |
michael@0 | 159 | { |
michael@0 | 160 | while (i--) |
michael@0 | 161 | cache->cache[i + 1] = cache->cache[i]; |
michael@0 | 162 | |
michael@0 | 163 | cache->cache[0].imp = *out_imp; |
michael@0 | 164 | cache->cache[0].fast_path.op = op; |
michael@0 | 165 | cache->cache[0].fast_path.src_format = src_format; |
michael@0 | 166 | cache->cache[0].fast_path.src_flags = src_flags; |
michael@0 | 167 | cache->cache[0].fast_path.mask_format = mask_format; |
michael@0 | 168 | cache->cache[0].fast_path.mask_flags = mask_flags; |
michael@0 | 169 | cache->cache[0].fast_path.dest_format = dest_format; |
michael@0 | 170 | cache->cache[0].fast_path.dest_flags = dest_flags; |
michael@0 | 171 | cache->cache[0].fast_path.func = *out_func; |
michael@0 | 172 | } |
michael@0 | 173 | } |
michael@0 | 174 | |
michael@0 | 175 | static void |
michael@0 | 176 | dummy_combine (pixman_implementation_t *imp, |
michael@0 | 177 | pixman_op_t op, |
michael@0 | 178 | uint32_t * pd, |
michael@0 | 179 | const uint32_t * ps, |
michael@0 | 180 | const uint32_t * pm, |
michael@0 | 181 | int w) |
michael@0 | 182 | { |
michael@0 | 183 | } |
michael@0 | 184 | |
michael@0 | 185 | pixman_combine_32_func_t |
michael@0 | 186 | _pixman_implementation_lookup_combiner (pixman_implementation_t *imp, |
michael@0 | 187 | pixman_op_t op, |
michael@0 | 188 | pixman_bool_t component_alpha, |
michael@0 | 189 | pixman_bool_t narrow, |
michael@0 | 190 | pixman_bool_t rgb16) |
michael@0 | 191 | { |
michael@0 | 192 | while (imp) |
michael@0 | 193 | { |
michael@0 | 194 | pixman_combine_32_func_t f = NULL; |
michael@0 | 195 | |
michael@0 | 196 | switch ((narrow << 1) | component_alpha) |
michael@0 | 197 | { |
michael@0 | 198 | case 0: /* not narrow, not component alpha */ |
michael@0 | 199 | f = (pixman_combine_32_func_t)imp->combine_float[op]; |
michael@0 | 200 | break; |
michael@0 | 201 | |
michael@0 | 202 | case 1: /* not narrow, component_alpha */ |
michael@0 | 203 | f = (pixman_combine_32_func_t)imp->combine_float_ca[op]; |
michael@0 | 204 | break; |
michael@0 | 205 | |
michael@0 | 206 | case 2: /* narrow, not component alpha */ |
michael@0 | 207 | f = imp->combine_32[op]; |
michael@0 | 208 | break; |
michael@0 | 209 | |
michael@0 | 210 | case 3: /* narrow, component_alpha */ |
michael@0 | 211 | f = imp->combine_32_ca[op]; |
michael@0 | 212 | break; |
michael@0 | 213 | } |
michael@0 | 214 | if (rgb16) |
michael@0 | 215 | f = (pixman_combine_32_func_t *)imp->combine_16[op]; |
michael@0 | 216 | |
michael@0 | 217 | if (f) |
michael@0 | 218 | return f; |
michael@0 | 219 | |
michael@0 | 220 | imp = imp->fallback; |
michael@0 | 221 | } |
michael@0 | 222 | |
michael@0 | 223 | /* We should never reach this point */ |
michael@0 | 224 | _pixman_log_error (FUNC, "No known combine function\n"); |
michael@0 | 225 | return dummy_combine; |
michael@0 | 226 | } |
michael@0 | 227 | |
michael@0 | 228 | pixman_bool_t |
michael@0 | 229 | _pixman_implementation_blt (pixman_implementation_t * imp, |
michael@0 | 230 | uint32_t * src_bits, |
michael@0 | 231 | uint32_t * dst_bits, |
michael@0 | 232 | int src_stride, |
michael@0 | 233 | int dst_stride, |
michael@0 | 234 | int src_bpp, |
michael@0 | 235 | int dst_bpp, |
michael@0 | 236 | int src_x, |
michael@0 | 237 | int src_y, |
michael@0 | 238 | int dest_x, |
michael@0 | 239 | int dest_y, |
michael@0 | 240 | int width, |
michael@0 | 241 | int height) |
michael@0 | 242 | { |
michael@0 | 243 | while (imp) |
michael@0 | 244 | { |
michael@0 | 245 | if (imp->blt && |
michael@0 | 246 | (*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride, |
michael@0 | 247 | src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y, |
michael@0 | 248 | width, height)) |
michael@0 | 249 | { |
michael@0 | 250 | return TRUE; |
michael@0 | 251 | } |
michael@0 | 252 | |
michael@0 | 253 | imp = imp->fallback; |
michael@0 | 254 | } |
michael@0 | 255 | |
michael@0 | 256 | return FALSE; |
michael@0 | 257 | } |
michael@0 | 258 | |
michael@0 | 259 | pixman_bool_t |
michael@0 | 260 | _pixman_implementation_fill (pixman_implementation_t *imp, |
michael@0 | 261 | uint32_t * bits, |
michael@0 | 262 | int stride, |
michael@0 | 263 | int bpp, |
michael@0 | 264 | int x, |
michael@0 | 265 | int y, |
michael@0 | 266 | int width, |
michael@0 | 267 | int height, |
michael@0 | 268 | uint32_t filler) |
michael@0 | 269 | { |
michael@0 | 270 | while (imp) |
michael@0 | 271 | { |
michael@0 | 272 | if (imp->fill && |
michael@0 | 273 | ((*imp->fill) (imp, bits, stride, bpp, x, y, width, height, filler))) |
michael@0 | 274 | { |
michael@0 | 275 | return TRUE; |
michael@0 | 276 | } |
michael@0 | 277 | |
michael@0 | 278 | imp = imp->fallback; |
michael@0 | 279 | } |
michael@0 | 280 | |
michael@0 | 281 | return FALSE; |
michael@0 | 282 | } |
michael@0 | 283 | |
michael@0 | 284 | pixman_bool_t |
michael@0 | 285 | _pixman_implementation_src_iter_init (pixman_implementation_t *imp, |
michael@0 | 286 | pixman_iter_t *iter, |
michael@0 | 287 | pixman_image_t *image, |
michael@0 | 288 | int x, |
michael@0 | 289 | int y, |
michael@0 | 290 | int width, |
michael@0 | 291 | int height, |
michael@0 | 292 | uint8_t *buffer, |
michael@0 | 293 | iter_flags_t iter_flags, |
michael@0 | 294 | uint32_t image_flags) |
michael@0 | 295 | { |
michael@0 | 296 | iter->image = image; |
michael@0 | 297 | iter->buffer = (uint32_t *)buffer; |
michael@0 | 298 | iter->x = x; |
michael@0 | 299 | iter->y = y; |
michael@0 | 300 | iter->width = width; |
michael@0 | 301 | iter->height = height; |
michael@0 | 302 | iter->iter_flags = iter_flags; |
michael@0 | 303 | iter->image_flags = image_flags; |
michael@0 | 304 | |
michael@0 | 305 | while (imp) |
michael@0 | 306 | { |
michael@0 | 307 | if (imp->src_iter_init && (*imp->src_iter_init) (imp, iter)) |
michael@0 | 308 | return TRUE; |
michael@0 | 309 | |
michael@0 | 310 | imp = imp->fallback; |
michael@0 | 311 | } |
michael@0 | 312 | |
michael@0 | 313 | return FALSE; |
michael@0 | 314 | } |
michael@0 | 315 | |
michael@0 | 316 | pixman_bool_t |
michael@0 | 317 | _pixman_implementation_dest_iter_init (pixman_implementation_t *imp, |
michael@0 | 318 | pixman_iter_t *iter, |
michael@0 | 319 | pixman_image_t *image, |
michael@0 | 320 | int x, |
michael@0 | 321 | int y, |
michael@0 | 322 | int width, |
michael@0 | 323 | int height, |
michael@0 | 324 | uint8_t *buffer, |
michael@0 | 325 | iter_flags_t iter_flags, |
michael@0 | 326 | uint32_t image_flags) |
michael@0 | 327 | { |
michael@0 | 328 | iter->image = image; |
michael@0 | 329 | iter->buffer = (uint32_t *)buffer; |
michael@0 | 330 | iter->x = x; |
michael@0 | 331 | iter->y = y; |
michael@0 | 332 | iter->width = width; |
michael@0 | 333 | iter->height = height; |
michael@0 | 334 | iter->iter_flags = iter_flags; |
michael@0 | 335 | iter->image_flags = image_flags; |
michael@0 | 336 | |
michael@0 | 337 | while (imp) |
michael@0 | 338 | { |
michael@0 | 339 | if (imp->dest_iter_init && (*imp->dest_iter_init) (imp, iter)) |
michael@0 | 340 | return TRUE; |
michael@0 | 341 | |
michael@0 | 342 | imp = imp->fallback; |
michael@0 | 343 | } |
michael@0 | 344 | |
michael@0 | 345 | return FALSE; |
michael@0 | 346 | } |
michael@0 | 347 | |
michael@0 | 348 | pixman_bool_t |
michael@0 | 349 | _pixman_disabled (const char *name) |
michael@0 | 350 | { |
michael@0 | 351 | const char *env; |
michael@0 | 352 | |
michael@0 | 353 | if ((env = getenv ("PIXMAN_DISABLE"))) |
michael@0 | 354 | { |
michael@0 | 355 | do |
michael@0 | 356 | { |
michael@0 | 357 | const char *end; |
michael@0 | 358 | int len; |
michael@0 | 359 | |
michael@0 | 360 | if ((end = strchr (env, ' '))) |
michael@0 | 361 | len = end - env; |
michael@0 | 362 | else |
michael@0 | 363 | len = strlen (env); |
michael@0 | 364 | |
michael@0 | 365 | if (strlen (name) == len && strncmp (name, env, len) == 0) |
michael@0 | 366 | { |
michael@0 | 367 | printf ("pixman: Disabled %s implementation\n", name); |
michael@0 | 368 | return TRUE; |
michael@0 | 369 | } |
michael@0 | 370 | |
michael@0 | 371 | env += len; |
michael@0 | 372 | } |
michael@0 | 373 | while (*env++); |
michael@0 | 374 | } |
michael@0 | 375 | |
michael@0 | 376 | return FALSE; |
michael@0 | 377 | } |
michael@0 | 378 | |
michael@0 | 379 | pixman_implementation_t * |
michael@0 | 380 | _pixman_choose_implementation (void) |
michael@0 | 381 | { |
michael@0 | 382 | pixman_implementation_t *imp; |
michael@0 | 383 | |
michael@0 | 384 | imp = _pixman_implementation_create_general(); |
michael@0 | 385 | |
michael@0 | 386 | if (!_pixman_disabled ("fast")) |
michael@0 | 387 | imp = _pixman_implementation_create_fast_path (imp); |
michael@0 | 388 | |
michael@0 | 389 | imp = _pixman_x86_get_implementations (imp); |
michael@0 | 390 | imp = _pixman_arm_get_implementations (imp); |
michael@0 | 391 | imp = _pixman_ppc_get_implementations (imp); |
michael@0 | 392 | imp = _pixman_mips_get_implementations (imp); |
michael@0 | 393 | |
michael@0 | 394 | imp = _pixman_implementation_create_noop (imp); |
michael@0 | 395 | |
michael@0 | 396 | return imp; |
michael@0 | 397 | } |