aboutsummaryrefslogtreecommitdiff
path: root/pixman/pixman/pixman-implementation.c
diff options
context:
space:
mode:
Diffstat (limited to 'pixman/pixman/pixman-implementation.c')
-rw-r--r--pixman/pixman/pixman-implementation.c276
1 files changed, 187 insertions, 89 deletions
diff --git a/pixman/pixman/pixman-implementation.c b/pixman/pixman/pixman-implementation.c
index 77d0906c8..5dd050199 100644
--- a/pixman/pixman/pixman-implementation.c
+++ b/pixman/pixman/pixman-implementation.c
@@ -27,92 +27,141 @@
#include <stdlib.h>
#include "pixman-private.h"
-static pixman_bool_t
-delegate_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)
+pixman_implementation_t *
+_pixman_implementation_create (pixman_implementation_t *fallback,
+ const pixman_fast_path_t *fast_paths)
{
- return _pixman_implementation_blt (
- imp->delegate, src_bits, dst_bits, src_stride, dst_stride,
- src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y,
- width, height);
-}
+ pixman_implementation_t *imp;
-static pixman_bool_t
-delegate_fill (pixman_implementation_t *imp,
- uint32_t * bits,
- int stride,
- int bpp,
- int x,
- int y,
- int width,
- int height,
- uint32_t xor)
-{
- return _pixman_implementation_fill (
- imp->delegate, bits, stride, bpp, x, y, width, height, xor);
-}
+ assert (fast_paths);
-static void
-delegate_src_iter_init (pixman_implementation_t *imp,
- pixman_iter_t * iter)
-{
- imp->delegate->src_iter_init (imp->delegate, iter);
+ 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;
}
-static void
-delegate_dest_iter_init (pixman_implementation_t *imp,
- pixman_iter_t * iter)
+#define N_CACHED_FAST_PATHS 8
+
+typedef struct
{
- imp->delegate->dest_iter_init (imp->delegate, iter);
-}
+ struct
+ {
+ pixman_implementation_t * imp;
+ pixman_fast_path_t fast_path;
+ } cache [N_CACHED_FAST_PATHS];
+} cache_t;
-pixman_implementation_t *
-_pixman_implementation_create (pixman_implementation_t *delegate,
- const pixman_fast_path_t *fast_paths)
+PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
+
+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)
{
- pixman_implementation_t *imp = malloc (sizeof (pixman_implementation_t));
- pixman_implementation_t *d;
+ pixman_implementation_t *imp;
+ cache_t *cache;
int i;
- if (!imp)
- return NULL;
+ /* Check cache for fast paths */
+ cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
- assert (fast_paths);
+ 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;
- /* Make sure the whole delegate chain has the right toplevel */
- imp->delegate = delegate;
- for (d = imp; d != NULL; d = d->delegate)
- d->toplevel = imp;
+ 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;
- /* Fill out function pointers with ones that just delegate
- */
- imp->blt = delegate_blt;
- imp->fill = delegate_fill;
- imp->src_iter_init = delegate_src_iter_init;
- imp->dest_iter_init = delegate_dest_iter_init;
+ /* 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;
- imp->fast_paths = fast_paths;
+ goto update_cache;
+ }
- for (i = 0; i < PIXMAN_N_OPERATORS; ++i)
+ ++info;
+ }
+ }
+ return FALSE;
+
+update_cache:
+ if (i)
{
- imp->combine_32[i] = NULL;
- imp->combine_64[i] = NULL;
- imp->combine_32_ca[i] = NULL;
- imp->combine_64_ca[i] = NULL;
+ 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 imp;
+ return TRUE;
}
pixman_combine_32_func_t
@@ -121,25 +170,36 @@ _pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
pixman_bool_t component_alpha,
pixman_bool_t narrow)
{
- pixman_combine_32_func_t f;
-
- do
+ while (imp)
{
- pixman_combine_32_func_t (*combiners[]) =
+ pixman_combine_32_func_t f = NULL;
+
+ switch ((narrow << 1) | component_alpha)
{
- (pixman_combine_32_func_t *)imp->combine_64,
- (pixman_combine_32_func_t *)imp->combine_64_ca,
- imp->combine_32,
- imp->combine_32_ca,
- };
+ case 0: /* not narrow, not component alpha */
+ f = (pixman_combine_32_func_t)imp->combine_64[op];
+ break;
+
+ case 1: /* not narrow, component_alpha */
+ f = (pixman_combine_32_func_t)imp->combine_64_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;
+ }
- f = combiners[component_alpha | (narrow << 1)][op];
+ if (f)
+ return f;
- imp = imp->delegate;
+ imp = imp->fallback;
}
- while (!f);
- return f;
+ return NULL;
}
pixman_bool_t
@@ -157,9 +217,20 @@ _pixman_implementation_blt (pixman_implementation_t * imp,
int width,
int height)
{
- return (*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);
+ 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
@@ -173,10 +244,21 @@ _pixman_implementation_fill (pixman_implementation_t *imp,
int height,
uint32_t xor)
{
- return (*imp->fill) (imp, bits, stride, bpp, x, y, width, height, xor);
+ while (imp)
+ {
+ if (imp->fill &&
+ ((*imp->fill) (imp, bits, stride, bpp, x, y, width, height, xor)))
+ {
+ return TRUE;
+ }
+
+ imp = imp->fallback;
+ }
+
+ return FALSE;
}
-void
+pixman_bool_t
_pixman_implementation_src_iter_init (pixman_implementation_t *imp,
pixman_iter_t *iter,
pixman_image_t *image,
@@ -197,10 +279,18 @@ _pixman_implementation_src_iter_init (pixman_implementation_t *imp,
iter->iter_flags = iter_flags;
iter->image_flags = image_flags;
- (*imp->src_iter_init) (imp, iter);
+ while (imp)
+ {
+ if (imp->src_iter_init && (*imp->src_iter_init) (imp, iter))
+ return TRUE;
+
+ imp = imp->fallback;
+ }
+
+ return FALSE;
}
-void
+pixman_bool_t
_pixman_implementation_dest_iter_init (pixman_implementation_t *imp,
pixman_iter_t *iter,
pixman_image_t *image,
@@ -221,7 +311,15 @@ _pixman_implementation_dest_iter_init (pixman_implementation_t *imp,
iter->iter_flags = iter_flags;
iter->image_flags = image_flags;
- (*imp->dest_iter_init) (imp, iter);
+ while (imp)
+ {
+ if (imp->dest_iter_init && (*imp->dest_iter_init) (imp, iter))
+ return TRUE;
+
+ imp = imp->fallback;
+ }
+
+ return FALSE;
}
pixman_bool_t