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
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
;
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
)
55 #define N_CACHED_FAST_PATHS 8
61 pixman_implementation_t
* imp
;
62 pixman_fast_path_t fast_path
;
63 } cache
[N_CACHED_FAST_PATHS
];
66 PIXMAN_DEFINE_THREAD_LOCAL (cache_t
, fast_path_cache
);
69 dummy_composite_rect (pixman_implementation_t
*imp
,
70 pixman_composite_info_t
*info
)
75 _pixman_implementation_lookup_composite (pixman_implementation_t
*toplevel
,
77 pixman_format_code_t src_format
,
79 pixman_format_code_t mask_format
,
81 pixman_format_code_t dest_format
,
83 pixman_implementation_t
**out_imp
,
84 pixman_composite_func_t
*out_func
)
86 pixman_implementation_t
*imp
;
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
&&
111 *out_imp
= cache
->cache
[i
].imp
;
112 *out_func
= cache
->cache
[i
].fast_path
.func
;
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
) &&
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
)) &&
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
)
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;
152 /* We should never reach this point */
155 "No composite function found\n"
157 "The most likely cause of this is that this system has issues with\n"
158 "thread local storage\n");
161 *out_func
= dummy_composite_rect
;
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
;
183 dummy_combine (pixman_implementation_t
*imp
,
192 pixman_combine_32_func_t
193 _pixman_implementation_lookup_combiner (pixman_implementation_t
*imp
,
195 pixman_bool_t component_alpha
,
196 pixman_bool_t narrow
)
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
];
208 case 1: /* not narrow, component_alpha */
209 f
= (pixman_combine_32_func_t
)imp
->combine_float_ca
[op
];
212 case 2: /* narrow, not component alpha */
213 f
= imp
->combine_32
[op
];
216 case 3: /* narrow, component_alpha */
217 f
= imp
->combine_32_ca
[op
];
227 /* We should never reach this point */
228 _pixman_log_error (FUNC
, "No known combine function\n");
229 return dummy_combine
;
233 _pixman_implementation_blt (pixman_implementation_t
* imp
,
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
,
264 _pixman_implementation_fill (pixman_implementation_t
*imp
,
277 ((*imp
->fill
) (imp
, bits
, stride
, bpp
, x
, y
, width
, height
, filler
)))
289 get_scanline_null (pixman_iter_t
*iter
, const uint32_t *mask
)
295 _pixman_implementation_iter_init (pixman_implementation_t
*imp
,
297 pixman_image_t
*image
,
303 iter_flags_t iter_flags
,
304 uint32_t image_flags
)
306 pixman_format_code_t format
;
309 iter
->buffer
= (uint32_t *)buffer
;
313 iter
->height
= height
;
314 iter
->iter_flags
= iter_flags
;
315 iter
->image_flags
= image_flags
;
320 iter
->get_scanline
= get_scanline_null
;
324 format
= iter
->image
->common
.extended_format_code
;
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
);
353 _pixman_disabled (const char *name
)
357 if ((env
= getenv ("PIXMAN_DISABLE")))
364 if ((end
= strchr (env
, ' ')))
369 if (strlen (name
) == len
&& strncmp (name
, env
, len
) == 0)
371 printf ("pixman: Disabled %s implementation\n", name
);
383 static const pixman_fast_path_t empty_fast_path
[] =
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
;