Line data Source code
1 : /*
2 : * Copyright © 2009 Red Hat, Inc.
3 : *
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.
13 : *
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.
22 : */
23 :
24 : #ifdef HAVE_CONFIG_H
25 : #include <config.h>
26 : #endif
27 : #include <stdlib.h>
28 : #include "pixman-private.h"
29 :
30 : pixman_implementation_t *
31 4 : _pixman_implementation_create (pixman_implementation_t *fallback,
32 : const pixman_fast_path_t *fast_paths)
33 : {
34 : pixman_implementation_t *imp;
35 :
36 4 : assert (fast_paths);
37 :
38 4 : if ((imp = malloc (sizeof (pixman_implementation_t))))
39 : {
40 : pixman_implementation_t *d;
41 :
42 4 : memset (imp, 0, sizeof *imp);
43 :
44 4 : imp->fallback = fallback;
45 4 : imp->fast_paths = fast_paths;
46 :
47 : /* Make sure the whole fallback chain has the right toplevel */
48 14 : for (d = imp; d != NULL; d = d->fallback)
49 10 : d->toplevel = imp;
50 : }
51 :
52 4 : return imp;
53 : }
54 :
55 : #define N_CACHED_FAST_PATHS 8
56 :
57 : typedef struct
58 : {
59 : struct
60 : {
61 : pixman_implementation_t * imp;
62 : pixman_fast_path_t fast_path;
63 : } cache [N_CACHED_FAST_PATHS];
64 : } cache_t;
65 :
66 24 : PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
67 :
68 : static void
69 0 : dummy_composite_rect (pixman_implementation_t *imp,
70 : pixman_composite_info_t *info)
71 : {
72 0 : }
73 :
74 : void
75 22 : _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)
85 : {
86 : pixman_implementation_t *imp;
87 : cache_t *cache;
88 : int i;
89 :
90 : /* Check cache for fast paths */
91 22 : cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
92 :
93 30 : for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
94 : {
95 29 : const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
96 :
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.
101 : */
102 50 : if (info->op == op &&
103 42 : info->src_format == src_format &&
104 42 : info->mask_format == mask_format &&
105 42 : info->dest_format == dest_format &&
106 42 : info->src_flags == src_flags &&
107 42 : info->mask_flags == mask_flags &&
108 42 : info->dest_flags == dest_flags &&
109 21 : info->func)
110 : {
111 21 : *out_imp = cache->cache[i].imp;
112 21 : *out_func = cache->cache[i].fast_path.func;
113 :
114 21 : goto update_cache;
115 : }
116 : }
117 :
118 2 : for (imp = toplevel; imp != NULL; imp = imp->fallback)
119 : {
120 2 : const pixman_fast_path_t *info = imp->fast_paths;
121 :
122 78 : while (info->op != PIXMAN_OP_NONE)
123 : {
124 86 : if ((info->op == op || info->op == PIXMAN_OP_any) &&
125 : /* Formats */
126 20 : ((info->src_format == src_format) ||
127 11 : (info->src_format == PIXMAN_any)) &&
128 2 : ((info->mask_format == mask_format) ||
129 2 : (info->mask_format == PIXMAN_any)) &&
130 3 : ((info->dest_format == dest_format) ||
131 2 : (info->dest_format == PIXMAN_any)) &&
132 : /* Flags */
133 2 : (info->src_flags & src_flags) == info->src_flags &&
134 2 : (info->mask_flags & mask_flags) == info->mask_flags &&
135 1 : (info->dest_flags & dest_flags) == info->dest_flags)
136 : {
137 1 : *out_imp = imp;
138 1 : *out_func = info->func;
139 :
140 : /* Set i to the last spot in the cache so that the
141 : * move-to-front code below will work
142 : */
143 1 : i = N_CACHED_FAST_PATHS - 1;
144 :
145 1 : goto update_cache;
146 : }
147 :
148 74 : ++info;
149 : }
150 : }
151 :
152 : /* We should never reach this point */
153 : _pixman_log_error (FUNC, "No known composite function\n");
154 0 : *out_imp = NULL;
155 0 : *out_func = dummy_composite_rect;
156 :
157 : update_cache:
158 22 : if (i)
159 : {
160 9 : while (i--)
161 7 : cache->cache[i + 1] = cache->cache[i];
162 :
163 1 : cache->cache[0].imp = *out_imp;
164 1 : cache->cache[0].fast_path.op = op;
165 1 : cache->cache[0].fast_path.src_format = src_format;
166 1 : cache->cache[0].fast_path.src_flags = src_flags;
167 1 : cache->cache[0].fast_path.mask_format = mask_format;
168 1 : cache->cache[0].fast_path.mask_flags = mask_flags;
169 1 : cache->cache[0].fast_path.dest_format = dest_format;
170 1 : cache->cache[0].fast_path.dest_flags = dest_flags;
171 1 : cache->cache[0].fast_path.func = *out_func;
172 : }
173 22 : }
174 :
175 : static void
176 0 : dummy_combine (pixman_implementation_t *imp,
177 : pixman_op_t op,
178 : uint32_t * pd,
179 : const uint32_t * ps,
180 : const uint32_t * pm,
181 : int w)
182 : {
183 0 : }
184 :
185 : pixman_combine_32_func_t
186 0 : _pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
187 : pixman_op_t op,
188 : pixman_bool_t component_alpha,
189 : pixman_bool_t narrow,
190 : pixman_bool_t rgb16)
191 : {
192 0 : while (imp)
193 : {
194 0 : pixman_combine_32_func_t f = NULL;
195 :
196 0 : switch ((narrow << 1) | component_alpha)
197 : {
198 : case 0: /* not narrow, not component alpha */
199 0 : f = (pixman_combine_32_func_t)imp->combine_float[op];
200 0 : break;
201 :
202 : case 1: /* not narrow, component_alpha */
203 0 : f = (pixman_combine_32_func_t)imp->combine_float_ca[op];
204 0 : break;
205 :
206 : case 2: /* narrow, not component alpha */
207 0 : f = imp->combine_32[op];
208 0 : break;
209 :
210 : case 3: /* narrow, component_alpha */
211 0 : f = imp->combine_32_ca[op];
212 0 : break;
213 : }
214 0 : if (rgb16)
215 0 : f = (pixman_combine_32_func_t *)imp->combine_16[op];
216 :
217 0 : if (f)
218 0 : return f;
219 :
220 0 : imp = imp->fallback;
221 : }
222 :
223 : /* We should never reach this point */
224 : _pixman_log_error (FUNC, "No known combine function\n");
225 0 : return dummy_combine;
226 : }
227 :
228 : pixman_bool_t
229 0 : _pixman_implementation_blt (pixman_implementation_t * imp,
230 : uint32_t * src_bits,
231 : uint32_t * dst_bits,
232 : int src_stride,
233 : int dst_stride,
234 : int src_bpp,
235 : int dst_bpp,
236 : int src_x,
237 : int src_y,
238 : int dest_x,
239 : int dest_y,
240 : int width,
241 : int height)
242 : {
243 0 : while (imp)
244 : {
245 0 : if (imp->blt &&
246 0 : (*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride,
247 : src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y,
248 : width, height))
249 : {
250 0 : return TRUE;
251 : }
252 :
253 0 : imp = imp->fallback;
254 : }
255 :
256 0 : return FALSE;
257 : }
258 :
259 : pixman_bool_t
260 0 : _pixman_implementation_fill (pixman_implementation_t *imp,
261 : uint32_t * bits,
262 : int stride,
263 : int bpp,
264 : int x,
265 : int y,
266 : int width,
267 : int height,
268 : uint32_t filler)
269 : {
270 0 : while (imp)
271 : {
272 0 : if (imp->fill &&
273 0 : ((*imp->fill) (imp, bits, stride, bpp, x, y, width, height, filler)))
274 : {
275 0 : return TRUE;
276 : }
277 :
278 0 : imp = imp->fallback;
279 : }
280 :
281 0 : return FALSE;
282 : }
283 :
284 : pixman_bool_t
285 0 : _pixman_implementation_src_iter_init (pixman_implementation_t *imp,
286 : pixman_iter_t *iter,
287 : pixman_image_t *image,
288 : int x,
289 : int y,
290 : int width,
291 : int height,
292 : uint8_t *buffer,
293 : iter_flags_t iter_flags,
294 : uint32_t image_flags)
295 : {
296 0 : iter->image = image;
297 0 : iter->buffer = (uint32_t *)buffer;
298 0 : iter->x = x;
299 0 : iter->y = y;
300 0 : iter->width = width;
301 0 : iter->height = height;
302 0 : iter->iter_flags = iter_flags;
303 0 : iter->image_flags = image_flags;
304 :
305 0 : while (imp)
306 : {
307 0 : if (imp->src_iter_init && (*imp->src_iter_init) (imp, iter))
308 0 : return TRUE;
309 :
310 0 : imp = imp->fallback;
311 : }
312 :
313 0 : return FALSE;
314 : }
315 :
316 : pixman_bool_t
317 0 : _pixman_implementation_dest_iter_init (pixman_implementation_t *imp,
318 : pixman_iter_t *iter,
319 : pixman_image_t *image,
320 : int x,
321 : int y,
322 : int width,
323 : int height,
324 : uint8_t *buffer,
325 : iter_flags_t iter_flags,
326 : uint32_t image_flags)
327 : {
328 0 : iter->image = image;
329 0 : iter->buffer = (uint32_t *)buffer;
330 0 : iter->x = x;
331 0 : iter->y = y;
332 0 : iter->width = width;
333 0 : iter->height = height;
334 0 : iter->iter_flags = iter_flags;
335 0 : iter->image_flags = image_flags;
336 :
337 0 : while (imp)
338 : {
339 0 : if (imp->dest_iter_init && (*imp->dest_iter_init) (imp, iter))
340 0 : return TRUE;
341 :
342 0 : imp = imp->fallback;
343 : }
344 :
345 0 : return FALSE;
346 : }
347 :
348 : pixman_bool_t
349 2 : _pixman_disabled (const char *name)
350 : {
351 : const char *env;
352 :
353 2 : if ((env = getenv ("PIXMAN_DISABLE")))
354 : {
355 : do
356 : {
357 : const char *end;
358 : int len;
359 :
360 0 : if ((end = strchr (env, ' ')))
361 0 : len = end - env;
362 : else
363 0 : len = strlen (env);
364 :
365 0 : if (strlen (name) == len && strncmp (name, env, len) == 0)
366 : {
367 0 : printf ("pixman: Disabled %s implementation\n", name);
368 0 : return TRUE;
369 : }
370 :
371 0 : env += len;
372 : }
373 0 : while (*env++);
374 : }
375 :
376 2 : return FALSE;
377 : }
378 :
379 : pixman_implementation_t *
380 1 : _pixman_choose_implementation (void)
381 : {
382 : pixman_implementation_t *imp;
383 :
384 1 : imp = _pixman_implementation_create_general();
385 :
386 1 : if (!_pixman_disabled ("fast"))
387 1 : imp = _pixman_implementation_create_fast_path (imp);
388 :
389 1 : imp = _pixman_x86_get_implementations (imp);
390 1 : imp = _pixman_arm_get_implementations (imp);
391 1 : imp = _pixman_ppc_get_implementations (imp);
392 1 : imp = _pixman_mips_get_implementations (imp);
393 :
394 1 : imp = _pixman_implementation_create_noop (imp);
395 :
396 1 : return imp;
397 : }
|