gfx/cairo/libpixman/src/pixman-implementation.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

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 }

mercurial