Add qemu 2.4.0
[kvmfornfv.git] / qemu / pixman / pixman / pixman-implementation.c
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 _pixman_implementation_create (pixman_implementation_t *fallback,
32                                const pixman_fast_path_t *fast_paths)
33 {
34     pixman_implementation_t *imp;
35
36     assert (fast_paths);
37
38     if ((imp = malloc (sizeof (pixman_implementation_t))))
39     {
40         pixman_implementation_t *d;
41
42         memset (imp, 0, sizeof *imp);
43
44         imp->fallback = fallback;
45         imp->fast_paths = fast_paths;
46         
47         /* Make sure the whole fallback chain has the right toplevel */
48         for (d = imp; d != NULL; d = d->fallback)
49             d->toplevel = imp;
50     }
51
52     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 PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
67
68 static void
69 dummy_composite_rect (pixman_implementation_t *imp,
70                       pixman_composite_info_t *info)
71 {
72 }
73
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)
85 {
86     pixman_implementation_t *imp;
87     cache_t *cache;
88     int i;
89
90     /* Check cache for fast paths */
91     cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
92
93     for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
94     {
95         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         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)
110         {
111             *out_imp = cache->cache[i].imp;
112             *out_func = cache->cache[i].fast_path.func;
113
114             goto update_cache;
115         }
116     }
117
118     for (imp = toplevel; imp != NULL; imp = imp->fallback)
119     {
120         const pixman_fast_path_t *info = imp->fast_paths;
121
122         while (info->op != PIXMAN_OP_NONE)
123         {
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)
136             {
137                 *out_imp = imp;
138                 *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                 i = N_CACHED_FAST_PATHS - 1;
144
145                 goto update_cache;
146             }
147
148             ++info;
149         }
150     }
151
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");
159
160     *out_imp = NULL;
161     *out_func = dummy_composite_rect;
162     return;
163
164 update_cache:
165     if (i)
166     {
167         while (i--)
168             cache->cache[i + 1] = cache->cache[i];
169
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;
179     }
180 }
181
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)
189 {
190 }
191
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)
197 {
198     while (imp)
199     {
200         pixman_combine_32_func_t f = NULL;
201
202         switch ((narrow << 1) | component_alpha)
203         {
204         case 0: /* not narrow, not component alpha */
205             f = (pixman_combine_32_func_t)imp->combine_float[op];
206             break;
207             
208         case 1: /* not narrow, component_alpha */
209             f = (pixman_combine_32_func_t)imp->combine_float_ca[op];
210             break;
211
212         case 2: /* narrow, not component alpha */
213             f = imp->combine_32[op];
214             break;
215
216         case 3: /* narrow, component_alpha */
217             f = imp->combine_32_ca[op];
218             break;
219         }
220
221         if (f)
222             return f;
223
224         imp = imp->fallback;
225     }
226
227     /* We should never reach this point */
228     _pixman_log_error (FUNC, "No known combine function\n");
229     return dummy_combine;
230 }
231
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)
246 {
247     while (imp)
248     {
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))
253         {
254             return TRUE;
255         }
256
257         imp = imp->fallback;
258     }
259
260     return FALSE;
261 }
262
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)
273 {
274     while (imp)
275     {
276         if (imp->fill &&
277             ((*imp->fill) (imp, bits, stride, bpp, x, y, width, height, filler)))
278         {
279             return TRUE;
280         }
281
282         imp = imp->fallback;
283     }
284
285     return FALSE;
286 }
287
288 static uint32_t *
289 get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
290 {
291     return NULL;
292 }
293
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)
305 {
306     pixman_format_code_t format;
307
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;
317
318     if (!iter->image)
319     {
320         iter->get_scanline = get_scanline_null;
321         return;
322     }
323
324     format = iter->image->common.extended_format_code;
325
326     while (imp)
327     {
328         if (imp->iter_info)
329         {
330             const pixman_iter_info_t *info;
331
332             for (info = imp->iter_info; info->format != PIXMAN_null; ++info)
333             {
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)
337                 {
338                     iter->get_scanline = info->get_scanline;
339                     iter->write_back = info->write_back;
340
341                     if (info->initializer)
342                         info->initializer (iter, info);
343                     return;
344                 }
345             }
346         }
347
348         imp = imp->fallback;
349     }
350 }
351
352 pixman_bool_t
353 _pixman_disabled (const char *name)
354 {
355     const char *env;
356
357     if ((env = getenv ("PIXMAN_DISABLE")))
358     {
359         do
360         {
361             const char *end;
362             int len;
363
364             if ((end = strchr (env, ' ')))
365                 len = end - env;
366             else
367                 len = strlen (env);
368
369             if (strlen (name) == len && strncmp (name, env, len) == 0)
370             {
371                 printf ("pixman: Disabled %s implementation\n", name);
372                 return TRUE;
373             }
374
375             env += len;
376         }
377         while (*env++);
378     }
379
380     return FALSE;
381 }
382
383 pixman_implementation_t *
384 _pixman_choose_implementation (void)
385 {
386     pixman_implementation_t *imp;
387
388     imp = _pixman_implementation_create_general();
389
390     if (!_pixman_disabled ("fast"))
391         imp = _pixman_implementation_create_fast_path (imp);
392
393     imp = _pixman_x86_get_implementations (imp);
394     imp = _pixman_arm_get_implementations (imp);
395     imp = _pixman_ppc_get_implementations (imp);
396     imp = _pixman_mips_get_implementations (imp);
397
398     imp = _pixman_implementation_create_noop (imp);
399
400     return imp;
401 }