beta-0.89.2
[luatex.git] / source / libs / pixman / pixman-src / pixman / pixman-implementation.c
blob2c7de4c68797c90a872c283cf35b4b70978cdc49
1 /*
2 * Copyright © 2009 Red Hat, Inc.
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Red Hat not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. Red Hat makes no representations about the
11 * suitability of this software for any purpose. It is provided "as is"
12 * without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
19 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
20 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 * SOFTWARE.
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 #include <stdlib.h>
28 #include "pixman-private.h"
30 pixman_implementation_t *
31 _pixman_implementation_create (pixman_implementation_t *fallback,
32 const pixman_fast_path_t *fast_paths)
34 pixman_implementation_t *imp;
36 assert (fast_paths);
38 if ((imp = malloc (sizeof (pixman_implementation_t))))
40 pixman_implementation_t *d;
42 memset (imp, 0, sizeof *imp);
44 imp->fallback = fallback;
45 imp->fast_paths = fast_paths;
47 /* Make sure the whole fallback chain has the right toplevel */
48 for (d = imp; d != NULL; d = d->fallback)
49 d->toplevel = imp;
52 return imp;
55 #define N_CACHED_FAST_PATHS 8
57 typedef struct
59 struct
61 pixman_implementation_t * imp;
62 pixman_fast_path_t fast_path;
63 } cache [N_CACHED_FAST_PATHS];
64 } cache_t;
66 PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
68 static void
69 dummy_composite_rect (pixman_implementation_t *imp,
70 pixman_composite_info_t *info)
74 void
75 _pixman_implementation_lookup_composite (pixman_implementation_t *toplevel,
76 pixman_op_t op,
77 pixman_format_code_t src_format,
78 uint32_t src_flags,
79 pixman_format_code_t mask_format,
80 uint32_t mask_flags,
81 pixman_format_code_t dest_format,
82 uint32_t dest_flags,
83 pixman_implementation_t **out_imp,
84 pixman_composite_func_t *out_func)
86 pixman_implementation_t *imp;
87 cache_t *cache;
88 int i;
90 /* Check cache for fast paths */
91 cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
93 for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
95 const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
97 /* Note that we check for equality here, not whether
98 * the cached fast path matches. This is to prevent
99 * us from selecting an overly general fast path
100 * when a more specific one would work.
102 if (info->op == op &&
103 info->src_format == src_format &&
104 info->mask_format == mask_format &&
105 info->dest_format == dest_format &&
106 info->src_flags == src_flags &&
107 info->mask_flags == mask_flags &&
108 info->dest_flags == dest_flags &&
109 info->func)
111 *out_imp = cache->cache[i].imp;
112 *out_func = cache->cache[i].fast_path.func;
114 goto update_cache;
118 for (imp = toplevel; imp != NULL; imp = imp->fallback)
120 const pixman_fast_path_t *info = imp->fast_paths;
122 while (info->op != PIXMAN_OP_NONE)
124 if ((info->op == op || info->op == PIXMAN_OP_any) &&
125 /* Formats */
126 ((info->src_format == src_format) ||
127 (info->src_format == PIXMAN_any)) &&
128 ((info->mask_format == mask_format) ||
129 (info->mask_format == PIXMAN_any)) &&
130 ((info->dest_format == dest_format) ||
131 (info->dest_format == PIXMAN_any)) &&
132 /* Flags */
133 (info->src_flags & src_flags) == info->src_flags &&
134 (info->mask_flags & mask_flags) == info->mask_flags &&
135 (info->dest_flags & dest_flags) == info->dest_flags)
137 *out_imp = imp;
138 *out_func = info->func;
140 /* Set i to the last spot in the cache so that the
141 * move-to-front code below will work
143 i = N_CACHED_FAST_PATHS - 1;
145 goto update_cache;
148 ++info;
152 /* We should never reach this point */
153 _pixman_log_error (
154 FUNC,
155 "No composite function found\n"
156 "\n"
157 "The most likely cause of this is that this system has issues with\n"
158 "thread local storage\n");
160 *out_imp = NULL;
161 *out_func = dummy_composite_rect;
162 return;
164 update_cache:
165 if (i)
167 while (i--)
168 cache->cache[i + 1] = cache->cache[i];
170 cache->cache[0].imp = *out_imp;
171 cache->cache[0].fast_path.op = op;
172 cache->cache[0].fast_path.src_format = src_format;
173 cache->cache[0].fast_path.src_flags = src_flags;
174 cache->cache[0].fast_path.mask_format = mask_format;
175 cache->cache[0].fast_path.mask_flags = mask_flags;
176 cache->cache[0].fast_path.dest_format = dest_format;
177 cache->cache[0].fast_path.dest_flags = dest_flags;
178 cache->cache[0].fast_path.func = *out_func;
182 static void
183 dummy_combine (pixman_implementation_t *imp,
184 pixman_op_t op,
185 uint32_t * pd,
186 const uint32_t * ps,
187 const uint32_t * pm,
188 int w)
192 pixman_combine_32_func_t
193 _pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
194 pixman_op_t op,
195 pixman_bool_t component_alpha,
196 pixman_bool_t narrow)
198 while (imp)
200 pixman_combine_32_func_t f = NULL;
202 switch ((narrow << 1) | component_alpha)
204 case 0: /* not narrow, not component alpha */
205 f = (pixman_combine_32_func_t)imp->combine_float[op];
206 break;
208 case 1: /* not narrow, component_alpha */
209 f = (pixman_combine_32_func_t)imp->combine_float_ca[op];
210 break;
212 case 2: /* narrow, not component alpha */
213 f = imp->combine_32[op];
214 break;
216 case 3: /* narrow, component_alpha */
217 f = imp->combine_32_ca[op];
218 break;
221 if (f)
222 return f;
224 imp = imp->fallback;
227 /* We should never reach this point */
228 _pixman_log_error (FUNC, "No known combine function\n");
229 return dummy_combine;
232 pixman_bool_t
233 _pixman_implementation_blt (pixman_implementation_t * imp,
234 uint32_t * src_bits,
235 uint32_t * dst_bits,
236 int src_stride,
237 int dst_stride,
238 int src_bpp,
239 int dst_bpp,
240 int src_x,
241 int src_y,
242 int dest_x,
243 int dest_y,
244 int width,
245 int height)
247 while (imp)
249 if (imp->blt &&
250 (*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride,
251 src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y,
252 width, height))
254 return TRUE;
257 imp = imp->fallback;
260 return FALSE;
263 pixman_bool_t
264 _pixman_implementation_fill (pixman_implementation_t *imp,
265 uint32_t * bits,
266 int stride,
267 int bpp,
268 int x,
269 int y,
270 int width,
271 int height,
272 uint32_t filler)
274 while (imp)
276 if (imp->fill &&
277 ((*imp->fill) (imp, bits, stride, bpp, x, y, width, height, filler)))
279 return TRUE;
282 imp = imp->fallback;
285 return FALSE;
288 static uint32_t *
289 get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
291 return NULL;
294 void
295 _pixman_implementation_iter_init (pixman_implementation_t *imp,
296 pixman_iter_t *iter,
297 pixman_image_t *image,
298 int x,
299 int y,
300 int width,
301 int height,
302 uint8_t *buffer,
303 iter_flags_t iter_flags,
304 uint32_t image_flags)
306 pixman_format_code_t format;
308 iter->image = image;
309 iter->buffer = (uint32_t *)buffer;
310 iter->x = x;
311 iter->y = y;
312 iter->width = width;
313 iter->height = height;
314 iter->iter_flags = iter_flags;
315 iter->image_flags = image_flags;
316 iter->fini = NULL;
318 if (!iter->image)
320 iter->get_scanline = get_scanline_null;
321 return;
324 format = iter->image->common.extended_format_code;
326 while (imp)
328 if (imp->iter_info)
330 const pixman_iter_info_t *info;
332 for (info = imp->iter_info; info->format != PIXMAN_null; ++info)
334 if ((info->format == PIXMAN_any || info->format == format) &&
335 (info->image_flags & image_flags) == info->image_flags &&
336 (info->iter_flags & iter_flags) == info->iter_flags)
338 iter->get_scanline = info->get_scanline;
339 iter->write_back = info->write_back;
341 if (info->initializer)
342 info->initializer (iter, info);
343 return;
348 imp = imp->fallback;
352 pixman_bool_t
353 _pixman_disabled (const char *name)
355 const char *env;
357 if ((env = getenv ("PIXMAN_DISABLE")))
361 const char *end;
362 int len;
364 if ((end = strchr (env, ' ')))
365 len = end - env;
366 else
367 len = strlen (env);
369 if (strlen (name) == len && strncmp (name, env, len) == 0)
371 printf ("pixman: Disabled %s implementation\n", name);
372 return TRUE;
375 env += len;
377 while (*env++);
380 return FALSE;
383 static const pixman_fast_path_t empty_fast_path[] =
385 { PIXMAN_OP_NONE }
388 pixman_implementation_t *
389 _pixman_choose_implementation (void)
391 pixman_implementation_t *imp;
393 imp = _pixman_implementation_create_general();
395 if (!_pixman_disabled ("fast"))
396 imp = _pixman_implementation_create_fast_path (imp);
398 imp = _pixman_x86_get_implementations (imp);
399 imp = _pixman_arm_get_implementations (imp);
400 imp = _pixman_ppc_get_implementations (imp);
401 imp = _pixman_mips_get_implementations (imp);
403 imp = _pixman_implementation_create_noop (imp);
405 if (_pixman_disabled ("wholeops"))
407 pixman_implementation_t *cur;
409 /* Disable all whole-operation paths except the general one,
410 * so that optimized iterators are used as much as possible.
412 for (cur = imp; cur->fallback; cur = cur->fallback)
413 cur->fast_paths = empty_fast_path;
416 return imp;