tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pixman-implementation.c (11640B)


      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 <pixman-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 static const pixman_fast_path_t empty_fast_path[] =
    384 {
    385    { PIXMAN_OP_NONE }
    386 };
    387 
    388 pixman_implementation_t *
    389 _pixman_choose_implementation (void)
    390 {
    391    pixman_implementation_t *imp;
    392 
    393    imp = _pixman_implementation_create_general();
    394 
    395    if (!_pixman_disabled ("fast"))
    396 imp = _pixman_implementation_create_fast_path (imp);
    397 
    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);
    402    imp = _pixman_riscv_get_implementations (imp);
    403 
    404    imp = _pixman_implementation_create_noop (imp);
    405 
    406    if (_pixman_disabled ("wholeops"))
    407    {
    408        pixman_implementation_t *cur;
    409 
    410        /* Disable all whole-operation paths except the general one,
    411         * so that optimized iterators are used as much as possible.
    412         */
    413        for (cur = imp; cur->fallback; cur = cur->fallback)
    414            cur->fast_paths = empty_fast_path;
    415    }
    416 
    417    return imp;
    418 }