Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  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. pixman_bool_t
  289. _pixman_implementation_src_iter_init (pixman_implementation_t   *imp,
  290.                                       pixman_iter_t             *iter,
  291.                                       pixman_image_t            *image,
  292.                                       int                        x,
  293.                                       int                        y,
  294.                                       int                        width,
  295.                                       int                        height,
  296.                                       uint8_t                   *buffer,
  297.                                       iter_flags_t               iter_flags,
  298.                                       uint32_t                   image_flags)
  299. {
  300.     iter->image = image;
  301.     iter->buffer = (uint32_t *)buffer;
  302.     iter->x = x;
  303.     iter->y = y;
  304.     iter->width = width;
  305.     iter->height = height;
  306.     iter->iter_flags = iter_flags;
  307.     iter->image_flags = image_flags;
  308.  
  309.     while (imp)
  310.     {
  311.         if (imp->src_iter_init && (*imp->src_iter_init) (imp, iter))
  312.             return TRUE;
  313.  
  314.         imp = imp->fallback;
  315.     }
  316.  
  317.     return FALSE;
  318. }
  319.  
  320. pixman_bool_t
  321. _pixman_implementation_dest_iter_init (pixman_implementation_t  *imp,
  322.                                        pixman_iter_t            *iter,
  323.                                        pixman_image_t           *image,
  324.                                        int                       x,
  325.                                        int                       y,
  326.                                        int                       width,
  327.                                        int                       height,
  328.                                        uint8_t                  *buffer,
  329.                                        iter_flags_t              iter_flags,
  330.                                        uint32_t                  image_flags)
  331. {
  332.     iter->image = image;
  333.     iter->buffer = (uint32_t *)buffer;
  334.     iter->x = x;
  335.     iter->y = y;
  336.     iter->width = width;
  337.     iter->height = height;
  338.     iter->iter_flags = iter_flags;
  339.     iter->image_flags = image_flags;
  340.  
  341.     while (imp)
  342.     {
  343.         if (imp->dest_iter_init && (*imp->dest_iter_init) (imp, iter))
  344.             return TRUE;
  345.  
  346.         imp = imp->fallback;
  347.     }
  348.  
  349.     return FALSE;
  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.  
  395.     imp = _pixman_implementation_create_noop (imp);
  396.  
  397.     return imp;
  398. }
  399.