Add qemu 2.4.0
[kvmfornfv.git] / qemu / pixman / pixman / pixman-implementation.c
diff --git a/qemu/pixman/pixman/pixman-implementation.c b/qemu/pixman/pixman/pixman-implementation.c
new file mode 100644 (file)
index 0000000..5884054
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  Red Hat makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include "pixman-private.h"
+
+pixman_implementation_t *
+_pixman_implementation_create (pixman_implementation_t *fallback,
+                              const pixman_fast_path_t *fast_paths)
+{
+    pixman_implementation_t *imp;
+
+    assert (fast_paths);
+
+    if ((imp = malloc (sizeof (pixman_implementation_t))))
+    {
+       pixman_implementation_t *d;
+
+       memset (imp, 0, sizeof *imp);
+
+       imp->fallback = fallback;
+       imp->fast_paths = fast_paths;
+       
+       /* Make sure the whole fallback chain has the right toplevel */
+       for (d = imp; d != NULL; d = d->fallback)
+           d->toplevel = imp;
+    }
+
+    return imp;
+}
+
+#define N_CACHED_FAST_PATHS 8
+
+typedef struct
+{
+    struct
+    {
+       pixman_implementation_t *       imp;
+       pixman_fast_path_t              fast_path;
+    } cache [N_CACHED_FAST_PATHS];
+} cache_t;
+
+PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
+
+static void
+dummy_composite_rect (pixman_implementation_t *imp,
+                     pixman_composite_info_t *info)
+{
+}
+
+void
+_pixman_implementation_lookup_composite (pixman_implementation_t  *toplevel,
+                                        pixman_op_t               op,
+                                        pixman_format_code_t      src_format,
+                                        uint32_t                  src_flags,
+                                        pixman_format_code_t      mask_format,
+                                        uint32_t                  mask_flags,
+                                        pixman_format_code_t      dest_format,
+                                        uint32_t                  dest_flags,
+                                        pixman_implementation_t **out_imp,
+                                        pixman_composite_func_t  *out_func)
+{
+    pixman_implementation_t *imp;
+    cache_t *cache;
+    int i;
+
+    /* Check cache for fast paths */
+    cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
+
+    for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
+    {
+       const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
+
+       /* Note that we check for equality here, not whether
+        * the cached fast path matches. This is to prevent
+        * us from selecting an overly general fast path
+        * when a more specific one would work.
+        */
+       if (info->op == op                      &&
+           info->src_format == src_format      &&
+           info->mask_format == mask_format    &&
+           info->dest_format == dest_format    &&
+           info->src_flags == src_flags        &&
+           info->mask_flags == mask_flags      &&
+           info->dest_flags == dest_flags      &&
+           info->func)
+       {
+           *out_imp = cache->cache[i].imp;
+           *out_func = cache->cache[i].fast_path.func;
+
+           goto update_cache;
+       }
+    }
+
+    for (imp = toplevel; imp != NULL; imp = imp->fallback)
+    {
+       const pixman_fast_path_t *info = imp->fast_paths;
+
+       while (info->op != PIXMAN_OP_NONE)
+       {
+           if ((info->op == op || info->op == PIXMAN_OP_any)           &&
+               /* Formats */
+               ((info->src_format == src_format) ||
+                (info->src_format == PIXMAN_any))                      &&
+               ((info->mask_format == mask_format) ||
+                (info->mask_format == PIXMAN_any))                     &&
+               ((info->dest_format == dest_format) ||
+                (info->dest_format == PIXMAN_any))                     &&
+               /* Flags */
+               (info->src_flags & src_flags) == info->src_flags        &&
+               (info->mask_flags & mask_flags) == info->mask_flags     &&
+               (info->dest_flags & dest_flags) == info->dest_flags)
+           {
+               *out_imp = imp;
+               *out_func = info->func;
+
+               /* Set i to the last spot in the cache so that the
+                * move-to-front code below will work
+                */
+               i = N_CACHED_FAST_PATHS - 1;
+
+               goto update_cache;
+           }
+
+           ++info;
+       }
+    }
+
+    /* We should never reach this point */
+    _pixman_log_error (
+        FUNC,
+        "No composite function found\n"
+        "\n"
+        "The most likely cause of this is that this system has issues with\n"
+        "thread local storage\n");
+
+    *out_imp = NULL;
+    *out_func = dummy_composite_rect;
+    return;
+
+update_cache:
+    if (i)
+    {
+       while (i--)
+           cache->cache[i + 1] = cache->cache[i];
+
+       cache->cache[0].imp = *out_imp;
+       cache->cache[0].fast_path.op = op;
+       cache->cache[0].fast_path.src_format = src_format;
+       cache->cache[0].fast_path.src_flags = src_flags;
+       cache->cache[0].fast_path.mask_format = mask_format;
+       cache->cache[0].fast_path.mask_flags = mask_flags;
+       cache->cache[0].fast_path.dest_format = dest_format;
+       cache->cache[0].fast_path.dest_flags = dest_flags;
+       cache->cache[0].fast_path.func = *out_func;
+    }
+}
+
+static void
+dummy_combine (pixman_implementation_t *imp,
+              pixman_op_t              op,
+              uint32_t *               pd,
+              const uint32_t *         ps,
+              const uint32_t *         pm,
+              int                      w)
+{
+}
+
+pixman_combine_32_func_t
+_pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
+                                       pixman_op_t              op,
+                                       pixman_bool_t            component_alpha,
+                                       pixman_bool_t            narrow)
+{
+    while (imp)
+    {
+       pixman_combine_32_func_t f = NULL;
+
+       switch ((narrow << 1) | component_alpha)
+       {
+       case 0: /* not narrow, not component alpha */
+           f = (pixman_combine_32_func_t)imp->combine_float[op];
+           break;
+           
+       case 1: /* not narrow, component_alpha */
+           f = (pixman_combine_32_func_t)imp->combine_float_ca[op];
+           break;
+
+       case 2: /* narrow, not component alpha */
+           f = imp->combine_32[op];
+           break;
+
+       case 3: /* narrow, component_alpha */
+           f = imp->combine_32_ca[op];
+           break;
+       }
+
+       if (f)
+           return f;
+
+       imp = imp->fallback;
+    }
+
+    /* We should never reach this point */
+    _pixman_log_error (FUNC, "No known combine function\n");
+    return dummy_combine;
+}
+
+pixman_bool_t
+_pixman_implementation_blt (pixman_implementation_t * imp,
+                            uint32_t *                src_bits,
+                            uint32_t *                dst_bits,
+                            int                       src_stride,
+                            int                       dst_stride,
+                            int                       src_bpp,
+                            int                       dst_bpp,
+                            int                       src_x,
+                            int                       src_y,
+                            int                       dest_x,
+                            int                       dest_y,
+                            int                       width,
+                            int                       height)
+{
+    while (imp)
+    {
+       if (imp->blt &&
+           (*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride,
+                        src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y,
+                        width, height))
+       {
+           return TRUE;
+       }
+
+       imp = imp->fallback;
+    }
+
+    return FALSE;
+}
+
+pixman_bool_t
+_pixman_implementation_fill (pixman_implementation_t *imp,
+                             uint32_t *               bits,
+                             int                      stride,
+                             int                      bpp,
+                             int                      x,
+                             int                      y,
+                             int                      width,
+                             int                      height,
+                             uint32_t                 filler)
+{
+    while (imp)
+    {
+       if (imp->fill &&
+           ((*imp->fill) (imp, bits, stride, bpp, x, y, width, height, filler)))
+       {
+           return TRUE;
+       }
+
+       imp = imp->fallback;
+    }
+
+    return FALSE;
+}
+
+static uint32_t *
+get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
+{
+    return NULL;
+}
+
+void
+_pixman_implementation_iter_init (pixman_implementation_t *imp,
+                                  pixman_iter_t           *iter,
+                                  pixman_image_t          *image,
+                                  int                      x,
+                                  int                      y,
+                                  int                      width,
+                                  int                      height,
+                                  uint8_t                 *buffer,
+                                  iter_flags_t             iter_flags,
+                                  uint32_t                 image_flags)
+{
+    pixman_format_code_t format;
+
+    iter->image = image;
+    iter->buffer = (uint32_t *)buffer;
+    iter->x = x;
+    iter->y = y;
+    iter->width = width;
+    iter->height = height;
+    iter->iter_flags = iter_flags;
+    iter->image_flags = image_flags;
+    iter->fini = NULL;
+
+    if (!iter->image)
+    {
+       iter->get_scanline = get_scanline_null;
+       return;
+    }
+
+    format = iter->image->common.extended_format_code;
+
+    while (imp)
+    {
+        if (imp->iter_info)
+        {
+            const pixman_iter_info_t *info;
+
+            for (info = imp->iter_info; info->format != PIXMAN_null; ++info)
+            {
+                if ((info->format == PIXMAN_any || info->format == format) &&
+                    (info->image_flags & image_flags) == info->image_flags &&
+                    (info->iter_flags & iter_flags) == info->iter_flags)
+                {
+                    iter->get_scanline = info->get_scanline;
+                    iter->write_back = info->write_back;
+
+                    if (info->initializer)
+                        info->initializer (iter, info);
+                    return;
+                }
+            }
+        }
+
+        imp = imp->fallback;
+    }
+}
+
+pixman_bool_t
+_pixman_disabled (const char *name)
+{
+    const char *env;
+
+    if ((env = getenv ("PIXMAN_DISABLE")))
+    {
+       do
+       {
+           const char *end;
+           int len;
+
+           if ((end = strchr (env, ' ')))
+               len = end - env;
+           else
+               len = strlen (env);
+
+           if (strlen (name) == len && strncmp (name, env, len) == 0)
+           {
+               printf ("pixman: Disabled %s implementation\n", name);
+               return TRUE;
+           }
+
+           env += len;
+       }
+       while (*env++);
+    }
+
+    return FALSE;
+}
+
+pixman_implementation_t *
+_pixman_choose_implementation (void)
+{
+    pixman_implementation_t *imp;
+
+    imp = _pixman_implementation_create_general();
+
+    if (!_pixman_disabled ("fast"))
+       imp = _pixman_implementation_create_fast_path (imp);
+
+    imp = _pixman_x86_get_implementations (imp);
+    imp = _pixman_arm_get_implementations (imp);
+    imp = _pixman_ppc_get_implementations (imp);
+    imp = _pixman_mips_get_implementations (imp);
+
+    imp = _pixman_implementation_create_noop (imp);
+
+    return imp;
+}