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 known composite function\n"); *out_imp = NULL; *out_func = dummy_composite_rect; 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; } }
pixman_bool_t _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) { static cache_t fast_path_cache; static DWORD thread_id; pixman_implementation_t *imp; cache_t *cache; int i; /* tomnotcat: FIXME: use thread local storage to support multi thread access. */ if (thread_id) { assert (GetCurrentThreadId () == thread_id); } else { thread_id = GetCurrentThreadId (); } /* 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; } } return FALSE; 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; } return TRUE; }