pixman-implementation.c revision f4f78bb6
1317c648bSmrg/* 2317c648bSmrg * Copyright © 2009 Red Hat, Inc. 3317c648bSmrg * 4317c648bSmrg * Permission to use, copy, modify, distribute, and sell this software and its 5317c648bSmrg * documentation for any purpose is hereby granted without fee, provided that 6317c648bSmrg * the above copyright notice appear in all copies and that both that 7317c648bSmrg * copyright notice and this permission notice appear in supporting 8317c648bSmrg * documentation, and that the name of Red Hat not be used in advertising or 9317c648bSmrg * publicity pertaining to distribution of the software without specific, 10317c648bSmrg * written prior permission. Red Hat makes no representations about the 11317c648bSmrg * suitability of this software for any purpose. It is provided "as is" 12317c648bSmrg * without express or implied warranty. 13317c648bSmrg * 14317c648bSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 15317c648bSmrg * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 16317c648bSmrg * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 17317c648bSmrg * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18317c648bSmrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 19317c648bSmrg * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 20317c648bSmrg * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 21317c648bSmrg * SOFTWARE. 22317c648bSmrg */ 23317c648bSmrg 24a450e446Smrg#ifdef HAVE_CONFIG_H 25317c648bSmrg#include <config.h> 26a450e446Smrg#endif 27317c648bSmrg#include <stdlib.h> 28317c648bSmrg#include "pixman-private.h" 29317c648bSmrg 309ad247e8Sjmcneillpixman_implementation_t * 319ad247e8Sjmcneill_pixman_implementation_create (pixman_implementation_t *fallback, 329ad247e8Sjmcneill const pixman_fast_path_t *fast_paths) 33317c648bSmrg{ 349ad247e8Sjmcneill pixman_implementation_t *imp; 35317c648bSmrg 369ad247e8Sjmcneill assert (fast_paths); 37317c648bSmrg 389ad247e8Sjmcneill if ((imp = malloc (sizeof (pixman_implementation_t)))) 399ad247e8Sjmcneill { 409ad247e8Sjmcneill pixman_implementation_t *d; 41317c648bSmrg 429ad247e8Sjmcneill memset (imp, 0, sizeof *imp); 43317c648bSmrg 449ad247e8Sjmcneill imp->fallback = fallback; 459ad247e8Sjmcneill imp->fast_paths = fast_paths; 469ad247e8Sjmcneill 479ad247e8Sjmcneill /* Make sure the whole fallback chain has the right toplevel */ 489ad247e8Sjmcneill for (d = imp; d != NULL; d = d->fallback) 499ad247e8Sjmcneill d->toplevel = imp; 509ad247e8Sjmcneill } 51317c648bSmrg 529ad247e8Sjmcneill return imp; 53317c648bSmrg} 54317c648bSmrg 559ad247e8Sjmcneill#define N_CACHED_FAST_PATHS 8 56953d7d37Smrg 579ad247e8Sjmcneilltypedef struct 58953d7d37Smrg{ 599ad247e8Sjmcneill struct 609ad247e8Sjmcneill { 619ad247e8Sjmcneill pixman_implementation_t * imp; 629ad247e8Sjmcneill pixman_fast_path_t fast_path; 639ad247e8Sjmcneill } cache [N_CACHED_FAST_PATHS]; 649ad247e8Sjmcneill} cache_t; 65953d7d37Smrg 669ad247e8SjmcneillPIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache); 679ad247e8Sjmcneill 68f4f78bb6Smrgstatic void 69f4f78bb6Smrgdummy_composite_rect (pixman_implementation_t *imp, 70f4f78bb6Smrg pixman_composite_info_t *info) 71f4f78bb6Smrg{ 72f4f78bb6Smrg} 73f4f78bb6Smrg 74f4f78bb6Smrgvoid 759ad247e8Sjmcneill_pixman_implementation_lookup_composite (pixman_implementation_t *toplevel, 769ad247e8Sjmcneill pixman_op_t op, 779ad247e8Sjmcneill pixman_format_code_t src_format, 789ad247e8Sjmcneill uint32_t src_flags, 799ad247e8Sjmcneill pixman_format_code_t mask_format, 809ad247e8Sjmcneill uint32_t mask_flags, 819ad247e8Sjmcneill pixman_format_code_t dest_format, 829ad247e8Sjmcneill uint32_t dest_flags, 839ad247e8Sjmcneill pixman_implementation_t **out_imp, 849ad247e8Sjmcneill pixman_composite_func_t *out_func) 85317c648bSmrg{ 869ad247e8Sjmcneill pixman_implementation_t *imp; 879ad247e8Sjmcneill cache_t *cache; 88317c648bSmrg int i; 89d0321353Smrg 909ad247e8Sjmcneill /* Check cache for fast paths */ 919ad247e8Sjmcneill cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache); 92317c648bSmrg 939ad247e8Sjmcneill for (i = 0; i < N_CACHED_FAST_PATHS; ++i) 949ad247e8Sjmcneill { 959ad247e8Sjmcneill const pixman_fast_path_t *info = &(cache->cache[i].fast_path); 96952204abSmrg 979ad247e8Sjmcneill /* Note that we check for equality here, not whether 989ad247e8Sjmcneill * the cached fast path matches. This is to prevent 999ad247e8Sjmcneill * us from selecting an overly general fast path 1009ad247e8Sjmcneill * when a more specific one would work. 1019ad247e8Sjmcneill */ 1029ad247e8Sjmcneill if (info->op == op && 1039ad247e8Sjmcneill info->src_format == src_format && 1049ad247e8Sjmcneill info->mask_format == mask_format && 1059ad247e8Sjmcneill info->dest_format == dest_format && 1069ad247e8Sjmcneill info->src_flags == src_flags && 1079ad247e8Sjmcneill info->mask_flags == mask_flags && 1089ad247e8Sjmcneill info->dest_flags == dest_flags && 1099ad247e8Sjmcneill info->func) 1109ad247e8Sjmcneill { 1119ad247e8Sjmcneill *out_imp = cache->cache[i].imp; 1129ad247e8Sjmcneill *out_func = cache->cache[i].fast_path.func; 113317c648bSmrg 1149ad247e8Sjmcneill goto update_cache; 1159ad247e8Sjmcneill } 1169ad247e8Sjmcneill } 117d0321353Smrg 1189ad247e8Sjmcneill for (imp = toplevel; imp != NULL; imp = imp->fallback) 119317c648bSmrg { 1209ad247e8Sjmcneill const pixman_fast_path_t *info = imp->fast_paths; 1219ad247e8Sjmcneill 1229ad247e8Sjmcneill while (info->op != PIXMAN_OP_NONE) 1239ad247e8Sjmcneill { 1249ad247e8Sjmcneill if ((info->op == op || info->op == PIXMAN_OP_any) && 1259ad247e8Sjmcneill /* Formats */ 1269ad247e8Sjmcneill ((info->src_format == src_format) || 1279ad247e8Sjmcneill (info->src_format == PIXMAN_any)) && 1289ad247e8Sjmcneill ((info->mask_format == mask_format) || 1299ad247e8Sjmcneill (info->mask_format == PIXMAN_any)) && 1309ad247e8Sjmcneill ((info->dest_format == dest_format) || 1319ad247e8Sjmcneill (info->dest_format == PIXMAN_any)) && 1329ad247e8Sjmcneill /* Flags */ 1339ad247e8Sjmcneill (info->src_flags & src_flags) == info->src_flags && 1349ad247e8Sjmcneill (info->mask_flags & mask_flags) == info->mask_flags && 1359ad247e8Sjmcneill (info->dest_flags & dest_flags) == info->dest_flags) 1369ad247e8Sjmcneill { 1379ad247e8Sjmcneill *out_imp = imp; 1389ad247e8Sjmcneill *out_func = info->func; 1399ad247e8Sjmcneill 1409ad247e8Sjmcneill /* Set i to the last spot in the cache so that the 1419ad247e8Sjmcneill * move-to-front code below will work 1429ad247e8Sjmcneill */ 1439ad247e8Sjmcneill i = N_CACHED_FAST_PATHS - 1; 1449ad247e8Sjmcneill 1459ad247e8Sjmcneill goto update_cache; 1469ad247e8Sjmcneill } 1479ad247e8Sjmcneill 1489ad247e8Sjmcneill ++info; 1499ad247e8Sjmcneill } 150317c648bSmrg } 151f4f78bb6Smrg 152f4f78bb6Smrg /* We should never reach this point */ 153f4f78bb6Smrg _pixman_log_error ( 154f4f78bb6Smrg FUNC, 155f4f78bb6Smrg "No composite function found\n" 156f4f78bb6Smrg "\n" 157f4f78bb6Smrg "The most likely cause of this is that this system has issues with\n" 158f4f78bb6Smrg "thread local storage\n"); 159f4f78bb6Smrg 160f4f78bb6Smrg *out_imp = NULL; 161f4f78bb6Smrg *out_func = dummy_composite_rect; 162f4f78bb6Smrg return; 163d0321353Smrg 1649ad247e8Sjmcneillupdate_cache: 1659ad247e8Sjmcneill if (i) 1669ad247e8Sjmcneill { 1679ad247e8Sjmcneill while (i--) 1689ad247e8Sjmcneill cache->cache[i + 1] = cache->cache[i]; 169953d7d37Smrg 1709ad247e8Sjmcneill cache->cache[0].imp = *out_imp; 1719ad247e8Sjmcneill cache->cache[0].fast_path.op = op; 1729ad247e8Sjmcneill cache->cache[0].fast_path.src_format = src_format; 1739ad247e8Sjmcneill cache->cache[0].fast_path.src_flags = src_flags; 1749ad247e8Sjmcneill cache->cache[0].fast_path.mask_format = mask_format; 1759ad247e8Sjmcneill cache->cache[0].fast_path.mask_flags = mask_flags; 1769ad247e8Sjmcneill cache->cache[0].fast_path.dest_format = dest_format; 1779ad247e8Sjmcneill cache->cache[0].fast_path.dest_flags = dest_flags; 1789ad247e8Sjmcneill cache->cache[0].fast_path.func = *out_func; 1799ad247e8Sjmcneill } 180f4f78bb6Smrg} 181317c648bSmrg 182f4f78bb6Smrgstatic void 183f4f78bb6Smrgdummy_combine (pixman_implementation_t *imp, 184f4f78bb6Smrg pixman_op_t op, 185f4f78bb6Smrg uint32_t * pd, 186f4f78bb6Smrg const uint32_t * ps, 187f4f78bb6Smrg const uint32_t * pm, 188f4f78bb6Smrg int w) 189f4f78bb6Smrg{ 190317c648bSmrg} 191317c648bSmrg 1929ad247e8Sjmcneillpixman_combine_32_func_t 1939ad247e8Sjmcneill_pixman_implementation_lookup_combiner (pixman_implementation_t *imp, 1949ad247e8Sjmcneill pixman_op_t op, 1959ad247e8Sjmcneill pixman_bool_t component_alpha, 1969ad247e8Sjmcneill pixman_bool_t narrow) 197317c648bSmrg{ 1989ad247e8Sjmcneill while (imp) 1999ad247e8Sjmcneill { 2009ad247e8Sjmcneill pixman_combine_32_func_t f = NULL; 201317c648bSmrg 2029ad247e8Sjmcneill switch ((narrow << 1) | component_alpha) 2039ad247e8Sjmcneill { 2049ad247e8Sjmcneill case 0: /* not narrow, not component alpha */ 2059ad247e8Sjmcneill f = (pixman_combine_32_func_t)imp->combine_float[op]; 2069ad247e8Sjmcneill break; 2079ad247e8Sjmcneill 2089ad247e8Sjmcneill case 1: /* not narrow, component_alpha */ 2099ad247e8Sjmcneill f = (pixman_combine_32_func_t)imp->combine_float_ca[op]; 2109ad247e8Sjmcneill break; 211317c648bSmrg 2129ad247e8Sjmcneill case 2: /* narrow, not component alpha */ 2139ad247e8Sjmcneill f = imp->combine_32[op]; 2149ad247e8Sjmcneill break; 2159ad247e8Sjmcneill 2169ad247e8Sjmcneill case 3: /* narrow, component_alpha */ 2179ad247e8Sjmcneill f = imp->combine_32_ca[op]; 2189ad247e8Sjmcneill break; 2199ad247e8Sjmcneill } 2209ad247e8Sjmcneill 2219ad247e8Sjmcneill if (f) 2229ad247e8Sjmcneill return f; 2239ad247e8Sjmcneill 2249ad247e8Sjmcneill imp = imp->fallback; 2259ad247e8Sjmcneill } 2269ad247e8Sjmcneill 227f4f78bb6Smrg /* We should never reach this point */ 228f4f78bb6Smrg _pixman_log_error (FUNC, "No known combine function\n"); 229f4f78bb6Smrg return dummy_combine; 230317c648bSmrg} 231317c648bSmrg 232317c648bSmrgpixman_bool_t 233d0321353Smrg_pixman_implementation_blt (pixman_implementation_t * imp, 234d0321353Smrg uint32_t * src_bits, 235d0321353Smrg uint32_t * dst_bits, 236d0321353Smrg int src_stride, 237d0321353Smrg int dst_stride, 238d0321353Smrg int src_bpp, 239d0321353Smrg int dst_bpp, 240d0321353Smrg int src_x, 241d0321353Smrg int src_y, 2426ba797d6Smrg int dest_x, 2436ba797d6Smrg int dest_y, 244d0321353Smrg int width, 245d0321353Smrg int height) 246317c648bSmrg{ 2479ad247e8Sjmcneill while (imp) 2489ad247e8Sjmcneill { 2499ad247e8Sjmcneill if (imp->blt && 2509ad247e8Sjmcneill (*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride, 2519ad247e8Sjmcneill src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y, 2529ad247e8Sjmcneill width, height)) 2539ad247e8Sjmcneill { 2549ad247e8Sjmcneill return TRUE; 2559ad247e8Sjmcneill } 2569ad247e8Sjmcneill 2579ad247e8Sjmcneill imp = imp->fallback; 2589ad247e8Sjmcneill } 2599ad247e8Sjmcneill 2609ad247e8Sjmcneill return FALSE; 261317c648bSmrg} 262317c648bSmrg 263317c648bSmrgpixman_bool_t 264317c648bSmrg_pixman_implementation_fill (pixman_implementation_t *imp, 265d0321353Smrg uint32_t * bits, 266d0321353Smrg int stride, 267d0321353Smrg int bpp, 268d0321353Smrg int x, 269d0321353Smrg int y, 270d0321353Smrg int width, 271d0321353Smrg int height, 272f4f78bb6Smrg uint32_t filler) 273317c648bSmrg{ 2749ad247e8Sjmcneill while (imp) 2759ad247e8Sjmcneill { 2769ad247e8Sjmcneill if (imp->fill && 277f4f78bb6Smrg ((*imp->fill) (imp, bits, stride, bpp, x, y, width, height, filler))) 2789ad247e8Sjmcneill { 2799ad247e8Sjmcneill return TRUE; 2809ad247e8Sjmcneill } 2819ad247e8Sjmcneill 2829ad247e8Sjmcneill imp = imp->fallback; 2839ad247e8Sjmcneill } 2849ad247e8Sjmcneill 2859ad247e8Sjmcneill return FALSE; 286317c648bSmrg} 287d0321353Smrg 2889ad247e8Sjmcneillpixman_bool_t 289953d7d37Smrg_pixman_implementation_src_iter_init (pixman_implementation_t *imp, 290953d7d37Smrg pixman_iter_t *iter, 291953d7d37Smrg pixman_image_t *image, 292953d7d37Smrg int x, 293953d7d37Smrg int y, 294953d7d37Smrg int width, 295953d7d37Smrg int height, 296953d7d37Smrg uint8_t *buffer, 2979ad247e8Sjmcneill iter_flags_t iter_flags, 2989ad247e8Sjmcneill uint32_t image_flags) 299953d7d37Smrg{ 3006ba797d6Smrg iter->image = image; 3016ba797d6Smrg iter->buffer = (uint32_t *)buffer; 3026ba797d6Smrg iter->x = x; 3036ba797d6Smrg iter->y = y; 3046ba797d6Smrg iter->width = width; 3056ba797d6Smrg iter->height = height; 3069ad247e8Sjmcneill iter->iter_flags = iter_flags; 3079ad247e8Sjmcneill iter->image_flags = image_flags; 3089ad247e8Sjmcneill 3099ad247e8Sjmcneill while (imp) 3109ad247e8Sjmcneill { 3119ad247e8Sjmcneill if (imp->src_iter_init && (*imp->src_iter_init) (imp, iter)) 3129ad247e8Sjmcneill return TRUE; 3139ad247e8Sjmcneill 3149ad247e8Sjmcneill imp = imp->fallback; 3159ad247e8Sjmcneill } 3166ba797d6Smrg 3179ad247e8Sjmcneill return FALSE; 318953d7d37Smrg} 319953d7d37Smrg 3209ad247e8Sjmcneillpixman_bool_t 321953d7d37Smrg_pixman_implementation_dest_iter_init (pixman_implementation_t *imp, 322953d7d37Smrg pixman_iter_t *iter, 323953d7d37Smrg pixman_image_t *image, 324953d7d37Smrg int x, 325953d7d37Smrg int y, 326953d7d37Smrg int width, 327953d7d37Smrg int height, 328953d7d37Smrg uint8_t *buffer, 3299ad247e8Sjmcneill iter_flags_t iter_flags, 3309ad247e8Sjmcneill uint32_t image_flags) 331953d7d37Smrg{ 3326ba797d6Smrg iter->image = image; 3336ba797d6Smrg iter->buffer = (uint32_t *)buffer; 3346ba797d6Smrg iter->x = x; 3356ba797d6Smrg iter->y = y; 3366ba797d6Smrg iter->width = width; 3376ba797d6Smrg iter->height = height; 3389ad247e8Sjmcneill iter->iter_flags = iter_flags; 3399ad247e8Sjmcneill iter->image_flags = image_flags; 3409ad247e8Sjmcneill 3419ad247e8Sjmcneill while (imp) 3429ad247e8Sjmcneill { 3439ad247e8Sjmcneill if (imp->dest_iter_init && (*imp->dest_iter_init) (imp, iter)) 3449ad247e8Sjmcneill return TRUE; 3459ad247e8Sjmcneill 3469ad247e8Sjmcneill imp = imp->fallback; 3479ad247e8Sjmcneill } 3486ba797d6Smrg 3499ad247e8Sjmcneill return FALSE; 3509ad247e8Sjmcneill} 3519ad247e8Sjmcneill 3529ad247e8Sjmcneillpixman_bool_t 3539ad247e8Sjmcneill_pixman_disabled (const char *name) 3549ad247e8Sjmcneill{ 3559ad247e8Sjmcneill const char *env; 3569ad247e8Sjmcneill 3579ad247e8Sjmcneill if ((env = getenv ("PIXMAN_DISABLE"))) 3589ad247e8Sjmcneill { 3599ad247e8Sjmcneill do 3609ad247e8Sjmcneill { 3619ad247e8Sjmcneill const char *end; 3629ad247e8Sjmcneill int len; 3639ad247e8Sjmcneill 3649ad247e8Sjmcneill if ((end = strchr (env, ' '))) 3659ad247e8Sjmcneill len = end - env; 3669ad247e8Sjmcneill else 3679ad247e8Sjmcneill len = strlen (env); 3689ad247e8Sjmcneill 3699ad247e8Sjmcneill if (strlen (name) == len && strncmp (name, env, len) == 0) 3709ad247e8Sjmcneill { 3719ad247e8Sjmcneill printf ("pixman: Disabled %s implementation\n", name); 3729ad247e8Sjmcneill return TRUE; 3739ad247e8Sjmcneill } 3749ad247e8Sjmcneill 3759ad247e8Sjmcneill env += len; 3769ad247e8Sjmcneill } 3779ad247e8Sjmcneill while (*env++); 3789ad247e8Sjmcneill } 3799ad247e8Sjmcneill 3809ad247e8Sjmcneill return FALSE; 3819ad247e8Sjmcneill} 3829ad247e8Sjmcneill 3839ad247e8Sjmcneillpixman_implementation_t * 3849ad247e8Sjmcneill_pixman_choose_implementation (void) 3859ad247e8Sjmcneill{ 3869ad247e8Sjmcneill pixman_implementation_t *imp; 3879ad247e8Sjmcneill 3889ad247e8Sjmcneill imp = _pixman_implementation_create_general(); 3899ad247e8Sjmcneill 3909ad247e8Sjmcneill if (!_pixman_disabled ("fast")) 3919ad247e8Sjmcneill imp = _pixman_implementation_create_fast_path (imp); 3929ad247e8Sjmcneill 3939ad247e8Sjmcneill imp = _pixman_x86_get_implementations (imp); 3949ad247e8Sjmcneill imp = _pixman_arm_get_implementations (imp); 3959ad247e8Sjmcneill imp = _pixman_ppc_get_implementations (imp); 3969ad247e8Sjmcneill imp = _pixman_mips_get_implementations (imp); 3979ad247e8Sjmcneill 3989ad247e8Sjmcneill imp = _pixman_implementation_create_noop (imp); 3999ad247e8Sjmcneill 4009ad247e8Sjmcneill return imp; 401953d7d37Smrg} 402