aboutsummaryrefslogtreecommitdiff
path: root/pixman
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2012-09-24 08:28:39 +0200
committermarha <marha@users.sourceforge.net>2012-09-24 08:28:39 +0200
commit0ebcd32e91486caccc041c8ca23e39e160b24702 (patch)
tree50cd0bc17e8a587fdbecdf52be48fe8c59e222b9 /pixman
parent06d4ea68085558b94d8e9c937091e7b7fcc5d95a (diff)
downloadvcxsrv-0ebcd32e91486caccc041c8ca23e39e160b24702.tar.gz
vcxsrv-0ebcd32e91486caccc041c8ca23e39e160b24702.tar.bz2
vcxsrv-0ebcd32e91486caccc041c8ca23e39e160b24702.zip
mesa pixman xserver git update 24 sep 2012
xserver: 7722bcbab2507d263c7685b15cccbfdd52fc3a24 pixman: c4b69e706e63e01fbc70e0026c2079007c89de14 mesa: c432c86e6aeebeb46c028af940224c59faa16e88
Diffstat (limited to 'pixman')
-rw-r--r--pixman/pixman/pixman-arm-neon.c89
-rw-r--r--pixman/pixman/pixman-fast-path.c8
-rw-r--r--pixman/pixman/pixman-general.c46
-rw-r--r--pixman/pixman/pixman-glyph.c4
-rw-r--r--pixman/pixman/pixman-implementation.c276
-rw-r--r--pixman/pixman/pixman-mips-dspr2.c89
-rw-r--r--pixman/pixman/pixman-mmx.c119
-rw-r--r--pixman/pixman/pixman-noop.c14
-rw-r--r--pixman/pixman/pixman-private.h36
-rw-r--r--pixman/pixman/pixman-sse2.c146
-rw-r--r--pixman/pixman/pixman-utils.c112
-rw-r--r--pixman/pixman/pixman.c2
-rw-r--r--pixman/test/scaling-test.c40
13 files changed, 388 insertions, 593 deletions
diff --git a/pixman/pixman/pixman-arm-neon.c b/pixman/pixman/pixman-arm-neon.c
index ca139de0b..60e9c78d2 100644
--- a/pixman/pixman/pixman-arm-neon.c
+++ b/pixman/pixman/pixman-arm-neon.c
@@ -183,14 +183,15 @@ pixman_composite_src_n_8888_asm_neon (int32_t w,
uint32_t src);
static pixman_bool_t
-pixman_fill_neon (uint32_t *bits,
- int stride,
- int bpp,
- int x,
- int y,
- int width,
- int height,
- uint32_t _xor)
+arm_neon_fill (pixman_implementation_t *imp,
+ uint32_t * bits,
+ int stride,
+ int bpp,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint32_t _xor)
{
/* stride is always multiple of 32bit units in pixman */
uint32_t byte_stride = stride * sizeof(uint32_t);
@@ -227,18 +228,19 @@ pixman_fill_neon (uint32_t *bits,
}
static pixman_bool_t
-pixman_blt_neon (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)
+arm_neon_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)
{
if (src_bpp != dst_bpp)
return FALSE;
@@ -422,53 +424,6 @@ static const pixman_fast_path_t arm_neon_fast_paths[] =
{ PIXMAN_OP_NONE },
};
-static pixman_bool_t
-arm_neon_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)
-{
- if (!pixman_blt_neon (
- src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
- src_x, src_y, dest_x, dest_y, width, height))
-
- {
- 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);
- }
-
- return TRUE;
-}
-
-static pixman_bool_t
-arm_neon_fill (pixman_implementation_t *imp,
- uint32_t * bits,
- int stride,
- int bpp,
- int x,
- int y,
- int width,
- int height,
- uint32_t xor)
-{
- if (pixman_fill_neon (bits, stride, bpp, x, y, width, height, xor))
- return TRUE;
-
- return _pixman_implementation_fill (
- imp->delegate, bits, stride, bpp, x, y, width, height, xor);
-}
-
#define BIND_COMBINE_U(name) \
void \
pixman_composite_scanline_##name##_mask_asm_neon (int32_t w, \
diff --git a/pixman/pixman/pixman-fast-path.c b/pixman/pixman/pixman-fast-path.c
index 9778b0cbe..86ed821d6 100644
--- a/pixman/pixman/pixman-fast-path.c
+++ b/pixman/pixman/pixman-fast-path.c
@@ -1258,7 +1258,7 @@ fast_composite_tiled_repeat (pixman_implementation_t *imp,
mask_flags = FAST_PATH_IS_OPAQUE;
}
- if (_pixman_lookup_composite_function (
+ if (_pixman_implementation_lookup_composite (
imp->toplevel, info->op,
src_image->common.extended_format_code, src_flags,
mask_format, mask_flags,
@@ -1458,7 +1458,7 @@ fetch_nearest (pixman_repeat_t src_repeat,
{
if (repeat (src_repeat, &x, src_width))
{
- if (format == PIXMAN_x8r8g8b8)
+ if (format == PIXMAN_x8r8g8b8 || format == PIXMAN_x8b8g8r8)
return *(src + x) | 0xff000000;
else
return *(src + x);
@@ -2192,9 +2192,7 @@ fast_path_fill (pixman_implementation_t *imp,
break;
default:
- return _pixman_implementation_fill (
- imp->delegate, bits, stride, bpp, x, y, width, height, xor);
- break;
+ return FALSE;
}
return TRUE;
diff --git a/pixman/pixman/pixman-general.c b/pixman/pixman/pixman-general.c
index d4b2daa37..42a84a0b4 100644
--- a/pixman/pixman/pixman-general.c
+++ b/pixman/pixman/pixman-general.c
@@ -37,7 +37,7 @@
#include <string.h>
#include "pixman-private.h"
-static void
+static pixman_bool_t
general_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
{
pixman_image_t *image = iter->image;
@@ -54,18 +54,24 @@ general_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
_pixman_bits_image_src_iter_init (image, iter);
else
_pixman_log_error (FUNC, "Pixman bug: unknown image type\n");
+
+ return TRUE;
}
-static void
+static pixman_bool_t
general_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
{
if (iter->image->type == BITS)
{
_pixman_bits_image_dest_iter_init (iter->image, iter);
+
+ return TRUE;
}
else
{
_pixman_log_error (FUNC, "Trying to write to a non-writable image");
+
+ return FALSE;
}
}
@@ -200,40 +206,6 @@ static const pixman_fast_path_t general_fast_path[] =
{ PIXMAN_OP_NONE }
};
-static pixman_bool_t
-general_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)
-{
- /* We can't blit unless we have sse2 or mmx */
-
- return FALSE;
-}
-
-static pixman_bool_t
-general_fill (pixman_implementation_t *imp,
- uint32_t * bits,
- int stride,
- int bpp,
- int x,
- int y,
- int width,
- int height,
- uint32_t xor)
-{
- return FALSE;
-}
-
pixman_implementation_t *
_pixman_implementation_create_general (void)
{
@@ -242,8 +214,6 @@ _pixman_implementation_create_general (void)
_pixman_setup_combiner_functions_32 (imp);
_pixman_setup_combiner_functions_64 (imp);
- imp->blt = general_blt;
- imp->fill = general_fill;
imp->src_iter_init = general_src_iter_init;
imp->dest_iter_init = general_dest_iter_init;
diff --git a/pixman/pixman/pixman-glyph.c b/pixman/pixman/pixman-glyph.c
index cbc3637fa..30a409908 100644
--- a/pixman/pixman/pixman-glyph.c
+++ b/pixman/pixman/pixman-glyph.c
@@ -464,7 +464,7 @@ pixman_composite_glyphs_no_mask (pixman_op_t op,
glyph_format = glyph_img->common.extended_format_code;
glyph_flags = glyph_img->common.flags;
- _pixman_lookup_composite_function (
+ _pixman_implementation_lookup_composite (
get_implementation(), op,
src->common.extended_format_code, src->common.flags,
glyph_format, glyph_flags | extra,
@@ -576,7 +576,7 @@ add_glyphs (pixman_glyph_cache_t *cache,
white_src = TRUE;
}
- _pixman_lookup_composite_function (
+ _pixman_implementation_lookup_composite (
get_implementation(), PIXMAN_OP_ADD,
src_format, info.src_flags,
mask_format, info.mask_flags,
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
diff --git a/pixman/pixman/pixman-mips-dspr2.c b/pixman/pixman/pixman-mips-dspr2.c
index 63a0225a2..1a9e6103a 100644
--- a/pixman/pixman/pixman-mips-dspr2.c
+++ b/pixman/pixman/pixman-mips-dspr2.c
@@ -85,14 +85,15 @@ PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, 8888_8_8888, ADD,
uint32_t, uint32_t)
static pixman_bool_t
-pixman_fill_mips (uint32_t *bits,
- int stride,
- int bpp,
- int x,
- int y,
- int width,
- int height,
- uint32_t _xor)
+mips_dspr2_fill (pixman_implementation_t *imp,
+ uint32_t * bits,
+ int stride,
+ int bpp,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint32_t _xor)
{
uint8_t *byte_line;
uint32_t byte_width;
@@ -130,18 +131,19 @@ pixman_fill_mips (uint32_t *bits,
}
static pixman_bool_t
-pixman_blt_mips (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)
+mips_dspr2_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)
{
if (src_bpp != dst_bpp)
return FALSE;
@@ -266,53 +268,6 @@ static const pixman_fast_path_t mips_dspr2_fast_paths[] =
{ PIXMAN_OP_NONE },
};
-static pixman_bool_t
-mips_dspr2_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)
-{
- if (!pixman_blt_mips (
- src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
- src_x, src_y, dest_x, dest_y, width, height))
-
- {
- 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);
- }
-
- return TRUE;
-}
-
-static pixman_bool_t
-mips_dspr2_fill (pixman_implementation_t *imp,
- uint32_t * bits,
- int stride,
- int bpp,
- int x,
- int y,
- int width,
- int height,
- uint32_t xor)
-{
- if (pixman_fill_mips (bits, stride, bpp, x, y, width, height, xor))
- return TRUE;
-
- return _pixman_implementation_fill (
- imp->delegate, bits, stride, bpp, x, y, width, height, xor);
-}
-
pixman_implementation_t *
_pixman_implementation_create_mips_dspr2 (pixman_implementation_t *fallback)
{
diff --git a/pixman/pixman/pixman-mmx.c b/pixman/pixman/pixman-mmx.c
index b3a4c5f75..fccba9d63 100644
--- a/pixman/pixman/pixman-mmx.c
+++ b/pixman/pixman/pixman-mmx.c
@@ -2055,15 +2055,16 @@ mmx_composite_over_n_8_8888 (pixman_implementation_t *imp,
_mm_empty ();
}
-pixman_bool_t
-pixman_fill_mmx (uint32_t *bits,
- int stride,
- int bpp,
- int x,
- int y,
- int width,
- int height,
- uint32_t xor)
+static pixman_bool_t
+mmx_fill (pixman_implementation_t *imp,
+ uint32_t * bits,
+ int stride,
+ int bpp,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint32_t xor)
{
uint64_t fill;
__m64 vfill;
@@ -2281,9 +2282,9 @@ mmx_composite_src_n_8_8888 (pixman_implementation_t *imp,
srca = src >> 24;
if (src == 0)
{
- pixman_fill_mmx (dest_image->bits.bits, dest_image->bits.rowstride,
- PIXMAN_FORMAT_BPP (dest_image->bits.format),
- dest_x, dest_y, width, height, 0);
+ mmx_fill (imp, dest_image->bits.bits, dest_image->bits.rowstride,
+ PIXMAN_FORMAT_BPP (dest_image->bits.format),
+ dest_x, dest_y, width, height, 0);
return;
}
@@ -3240,18 +3241,19 @@ mmx_composite_add_8888_8888 (pixman_implementation_t *imp,
}
static pixman_bool_t
-pixman_blt_mmx (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)
+mmx_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)
{
uint8_t * src_bytes;
uint8_t * dst_bytes;
@@ -3396,13 +3398,13 @@ mmx_composite_copy_area (pixman_implementation_t *imp,
{
PIXMAN_COMPOSITE_ARGS (info);
- pixman_blt_mmx (src_image->bits.bits,
- dest_image->bits.bits,
- src_image->bits.rowstride,
- dest_image->bits.rowstride,
- PIXMAN_FORMAT_BPP (src_image->bits.format),
- PIXMAN_FORMAT_BPP (dest_image->bits.format),
- src_x, src_y, dest_x, dest_y, width, height);
+ mmx_blt (imp, src_image->bits.bits,
+ dest_image->bits.bits,
+ src_image->bits.rowstride,
+ dest_image->bits.rowstride,
+ PIXMAN_FORMAT_BPP (src_image->bits.format),
+ PIXMAN_FORMAT_BPP (dest_image->bits.format),
+ src_x, src_y, dest_x, dest_y, width, height);
}
static void
@@ -3913,7 +3915,7 @@ static const fetcher_info_t fetchers[] =
{ PIXMAN_null }
};
-static void
+static pixman_bool_t
mmx_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
{
pixman_image_t *image = iter->image;
@@ -3938,12 +3940,12 @@ mmx_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
iter->stride = s;
iter->get_scanline = f->get_scanline;
- return;
+ return TRUE;
}
}
}
- imp->delegate->src_iter_init (imp->delegate, iter);
+ return FALSE;
}
static const pixman_fast_path_t mmx_fast_paths[] =
@@ -4042,55 +4044,6 @@ static const pixman_fast_path_t mmx_fast_paths[] =
{ PIXMAN_OP_NONE },
};
-static pixman_bool_t
-mmx_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)
-{
- if (!pixman_blt_mmx (
- src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
- src_x, src_y, dest_x, dest_y, width, height))
-
- {
- 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);
- }
-
- return TRUE;
-}
-
-static pixman_bool_t
-mmx_fill (pixman_implementation_t *imp,
- uint32_t * bits,
- int stride,
- int bpp,
- int x,
- int y,
- int width,
- int height,
- uint32_t xor)
-{
- if (!pixman_fill_mmx (bits, stride, bpp, x, y, width, height, xor))
- {
- return _pixman_implementation_fill (
- imp->delegate, bits, stride, bpp, x, y, width, height, xor);
- }
-
- return TRUE;
-}
-
pixman_implementation_t *
_pixman_implementation_create_mmx (pixman_implementation_t *fallback)
{
diff --git a/pixman/pixman/pixman-noop.c b/pixman/pixman/pixman-noop.c
index 7b017e8ec..7b9759ffb 100644
--- a/pixman/pixman/pixman-noop.c
+++ b/pixman/pixman/pixman-noop.c
@@ -59,7 +59,7 @@ get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
return NULL;
}
-static void
+static pixman_bool_t
noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
{
pixman_image_t *image = iter->image;
@@ -117,11 +117,13 @@ noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
}
else
{
- (* imp->delegate->src_iter_init) (imp->delegate, iter);
+ return FALSE;
}
+
+ return TRUE;
}
-static void
+static pixman_bool_t
noop_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
{
pixman_image_t *image = iter->image;
@@ -138,10 +140,12 @@ noop_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
iter->get_scanline = _pixman_iter_get_scanline_noop;
iter->write_back = dest_write_back_direct;
+
+ return TRUE;
}
else
{
- (* imp->delegate->dest_iter_init) (imp->delegate, iter);
+ return FALSE;
}
}
@@ -156,7 +160,7 @@ _pixman_implementation_create_noop (pixman_implementation_t *fallback)
{
pixman_implementation_t *imp =
_pixman_implementation_create (fallback, noop_fast_paths);
-
+
imp->src_iter_init = noop_src_iter_init;
imp->dest_iter_init = noop_dest_iter_init;
diff --git a/pixman/pixman/pixman-private.h b/pixman/pixman/pixman-private.h
index dbfa82952..b9c8319df 100644
--- a/pixman/pixman/pixman-private.h
+++ b/pixman/pixman/pixman-private.h
@@ -445,8 +445,8 @@ typedef pixman_bool_t (*pixman_fill_func_t) (pixman_implementation_t *imp,
int width,
int height,
uint32_t xor);
-typedef void (*pixman_iter_init_func_t) (pixman_implementation_t *imp,
- pixman_iter_t *iter);
+typedef pixman_bool_t (*pixman_iter_init_func_t) (pixman_implementation_t *imp,
+ pixman_iter_t *iter);
void _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp);
void _pixman_setup_combiner_functions_64 (pixman_implementation_t *imp);
@@ -466,7 +466,7 @@ typedef struct
struct pixman_implementation_t
{
pixman_implementation_t * toplevel;
- pixman_implementation_t * delegate;
+ pixman_implementation_t * fallback;
const pixman_fast_path_t * fast_paths;
pixman_blt_func_t blt;
@@ -486,9 +486,21 @@ _pixman_image_get_solid (pixman_implementation_t *imp,
pixman_format_code_t format);
pixman_implementation_t *
-_pixman_implementation_create (pixman_implementation_t *delegate,
+_pixman_implementation_create (pixman_implementation_t *fallback,
const pixman_fast_path_t *fast_paths);
+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_combine_32_func_t
_pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
pixman_op_t op,
@@ -521,7 +533,7 @@ _pixman_implementation_fill (pixman_implementation_t *imp,
int height,
uint32_t xor);
-void
+pixman_bool_t
_pixman_implementation_src_iter_init (pixman_implementation_t *imp,
pixman_iter_t *iter,
pixman_image_t *image,
@@ -533,7 +545,7 @@ _pixman_implementation_src_iter_init (pixman_implementation_t *imp,
iter_flags_t flags,
uint32_t image_flags);
-void
+pixman_bool_t
_pixman_implementation_dest_iter_init (pixman_implementation_t *imp,
pixman_iter_t *iter,
pixman_image_t *image,
@@ -770,18 +782,6 @@ pixman_contract (uint32_t * dst,
const uint64_t *src,
int width);
-pixman_bool_t
-_pixman_lookup_composite_function (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);
-
/* Region Helpers */
pixman_bool_t
pixman_region32_copy_from_region16 (pixman_region32_t *dst,
diff --git a/pixman/pixman/pixman-sse2.c b/pixman/pixman/pixman-sse2.c
index 665eeadbe..e273a951e 100644
--- a/pixman/pixman/pixman-sse2.c
+++ b/pixman/pixman/pixman-sse2.c
@@ -3309,18 +3309,22 @@ sse2_composite_over_n_8_8888 (pixman_implementation_t *imp,
}
+#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
+__attribute__((__force_align_arg_pointer__))
+#endif
static pixman_bool_t
-pixman_fill_sse2 (uint32_t *bits,
- int stride,
- int bpp,
- int x,
- int y,
- int width,
- int height,
- uint32_t data)
+sse2_fill (pixman_implementation_t *imp,
+ uint32_t * bits,
+ int stride,
+ int bpp,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint32_t xor)
{
uint32_t byte_width;
- uint8_t *byte_line;
+ uint8_t *byte_line;
__m128i xmm_def;
@@ -3334,9 +3338,9 @@ pixman_fill_sse2 (uint32_t *bits,
byte_width = width;
stride *= 1;
- b = data & 0xff;
+ b = xor & 0xff;
w = (b << 8) | b;
- data = (w << 16) | w;
+ xor = (w << 16) | w;
}
else if (bpp == 16)
{
@@ -3345,7 +3349,7 @@ pixman_fill_sse2 (uint32_t *bits,
byte_width = 2 * width;
stride *= 2;
- data = (data & 0xffff) * 0x00010001;
+ xor = (xor & 0xffff) * 0x00010001;
}
else if (bpp == 32)
{
@@ -3359,7 +3363,7 @@ pixman_fill_sse2 (uint32_t *bits,
return FALSE;
}
- xmm_def = create_mask_2x32_128 (data, data);
+ xmm_def = create_mask_2x32_128 (xor, xor);
while (height--)
{
@@ -3370,21 +3374,21 @@ pixman_fill_sse2 (uint32_t *bits,
if (w >= 1 && ((unsigned long)d & 1))
{
- *(uint8_t *)d = data;
+ *(uint8_t *)d = xor;
w -= 1;
d += 1;
}
while (w >= 2 && ((unsigned long)d & 3))
{
- *(uint16_t *)d = data;
+ *(uint16_t *)d = xor;
w -= 2;
d += 2;
}
while (w >= 4 && ((unsigned long)d & 15))
{
- *(uint32_t *)d = data;
+ *(uint32_t *)d = xor;
w -= 4;
d += 4;
@@ -3435,7 +3439,7 @@ pixman_fill_sse2 (uint32_t *bits,
while (w >= 4)
{
- *(uint32_t *)d = data;
+ *(uint32_t *)d = xor;
w -= 4;
d += 4;
@@ -3443,14 +3447,14 @@ pixman_fill_sse2 (uint32_t *bits,
if (w >= 2)
{
- *(uint16_t *)d = data;
+ *(uint16_t *)d = xor;
w -= 2;
d += 2;
}
if (w >= 1)
{
- *(uint8_t *)d = data;
+ *(uint8_t *)d = xor;
w -= 1;
d += 1;
}
@@ -3479,9 +3483,9 @@ sse2_composite_src_n_8_8888 (pixman_implementation_t *imp,
srca = src >> 24;
if (src == 0)
{
- pixman_fill_sse2 (dest_image->bits.bits, dest_image->bits.rowstride,
- PIXMAN_FORMAT_BPP (dest_image->bits.format),
- dest_x, dest_y, width, height, 0);
+ sse2_fill (imp, dest_image->bits.bits, dest_image->bits.rowstride,
+ PIXMAN_FORMAT_BPP (dest_image->bits.format),
+ dest_x, dest_y, width, height, 0);
return;
}
@@ -4523,18 +4527,19 @@ sse2_composite_add_8888_8888 (pixman_implementation_t *imp,
}
static pixman_bool_t
-pixman_blt_sse2 (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)
+sse2_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)
{
uint8_t * src_bytes;
uint8_t * dst_bytes;
@@ -4640,7 +4645,6 @@ pixman_blt_sse2 (uint32_t *src_bits,
}
}
-
return TRUE;
}
@@ -4649,13 +4653,13 @@ sse2_composite_copy_area (pixman_implementation_t *imp,
pixman_composite_info_t *info)
{
PIXMAN_COMPOSITE_ARGS (info);
- pixman_blt_sse2 (src_image->bits.bits,
- dest_image->bits.bits,
- src_image->bits.rowstride,
- dest_image->bits.rowstride,
- PIXMAN_FORMAT_BPP (src_image->bits.format),
- PIXMAN_FORMAT_BPP (dest_image->bits.format),
- src_x, src_y, dest_x, dest_y, width, height);
+ sse2_blt (imp, src_image->bits.bits,
+ dest_image->bits.bits,
+ src_image->bits.rowstride,
+ dest_image->bits.rowstride,
+ PIXMAN_FORMAT_BPP (src_image->bits.format),
+ PIXMAN_FORMAT_BPP (dest_image->bits.format),
+ src_x, src_y, dest_x, dest_y, width, height);
}
static void
@@ -5878,58 +5882,6 @@ static const pixman_fast_path_t sse2_fast_paths[] =
{ PIXMAN_OP_NONE },
};
-static pixman_bool_t
-sse2_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)
-{
- if (!pixman_blt_sse2 (
- src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
- src_x, src_y, dest_x, dest_y, width, height))
-
- {
- 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);
- }
-
- return TRUE;
-}
-
-#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
-__attribute__((__force_align_arg_pointer__))
-#endif
-static pixman_bool_t
-sse2_fill (pixman_implementation_t *imp,
- uint32_t * bits,
- int stride,
- int bpp,
- int x,
- int y,
- int width,
- int height,
- uint32_t xor)
-{
- if (!pixman_fill_sse2 (bits, stride, bpp, x, y, width, height, xor))
- {
- return _pixman_implementation_fill (
- imp->delegate, bits, stride, bpp, x, y, width, height, xor);
- }
-
- return TRUE;
-}
-
static uint32_t *
sse2_fetch_x8r8g8b8 (pixman_iter_t *iter, const uint32_t *mask)
{
@@ -6072,7 +6024,7 @@ static const fetcher_info_t fetchers[] =
{ PIXMAN_null }
};
-static void
+static pixman_bool_t
sse2_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
{
pixman_image_t *image = iter->image;
@@ -6097,12 +6049,12 @@ sse2_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
iter->stride = s;
iter->get_scanline = f->get_scanline;
- return;
+ return TRUE;
}
}
}
- imp->delegate->src_iter_init (imp->delegate, iter);
+ return FALSE;
}
#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
diff --git a/pixman/pixman/pixman-utils.c b/pixman/pixman/pixman-utils.c
index 93c061ad2..5633f8f79 100644
--- a/pixman/pixman/pixman-utils.c
+++ b/pixman/pixman/pixman-utils.c
@@ -30,118 +30,6 @@
#include "pixman-private.h"
-#define N_CACHED_FAST_PATHS 8
-
-typedef struct
-{
- struct
- {
- pixman_implementation_t * imp;
- pixman_fast_path_t fast_path;
- } cache [N_CACHED_FAST_PATHS];
-} cache_t;
-
-PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
-
-pixman_bool_t
-_pixman_lookup_composite_function (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->delegate)
- {
- 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;
-}
-
pixman_bool_t
_pixman_multiply_overflows_size (size_t a, size_t b)
{
diff --git a/pixman/pixman/pixman.c b/pixman/pixman/pixman.c
index 994ef388c..739cc7994 100644
--- a/pixman/pixman/pixman.c
+++ b/pixman/pixman/pixman.c
@@ -669,7 +669,7 @@ pixman_image_composite32 (pixman_op_t op,
*/
op = optimize_operator (op, src_flags, mask_flags, dest_flags);
- if (_pixman_lookup_composite_function (
+ if (_pixman_implementation_lookup_composite (
get_implementation (), op,
src_format, src_flags, mask_format, mask_flags, dest_format, dest_flags,
&imp, &func))
diff --git a/pixman/test/scaling-test.c b/pixman/test/scaling-test.c
index 44c4f3de4..273612395 100644
--- a/pixman/test/scaling-test.c
+++ b/pixman/test/scaling-test.c
@@ -20,6 +20,31 @@
/*
* Composite operation with pseudorandom images
*/
+
+static pixman_format_code_t
+get_format (int bpp)
+{
+ if (bpp == 4)
+ {
+ switch (lcg_rand_n (4))
+ {
+ default:
+ case 0:
+ return PIXMAN_a8r8g8b8;
+ case 1:
+ return PIXMAN_x8r8g8b8;
+ case 2:
+ return PIXMAN_a8b8g8r8;
+ case 3:
+ return PIXMAN_x8b8g8r8;
+ }
+ }
+ else
+ {
+ return PIXMAN_r5g6b5;
+ }
+}
+
uint32_t
test_composite (int testnum,
int verbose)
@@ -124,11 +149,8 @@ test_composite (int testnum,
for (i = 0; i < dst_stride * dst_height; i++)
*((uint8_t *)dstbuf + i) = lcg_rand_n (256);
- src_fmt = src_bpp == 4 ? (lcg_rand_n (2) == 0 ?
- PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5;
-
- dst_fmt = dst_bpp == 4 ? (lcg_rand_n (2) == 0 ?
- PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5;
+ src_fmt = get_format (src_bpp);
+ dst_fmt = get_format (dst_bpp);
src_img = pixman_image_create_bits (
src_fmt, src_width, src_height, srcbuf, src_stride);
@@ -322,7 +344,7 @@ test_composite (int testnum,
pixman_image_composite (op, src_img, mask_img, dst_img,
src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h);
- if (dst_fmt == PIXMAN_x8r8g8b8)
+ if (dst_fmt == PIXMAN_x8r8g8b8 || dst_fmt == PIXMAN_x8b8g8r8)
{
/* ignore unused part */
for (i = 0; i < dst_stride * dst_height / 4; i++)
@@ -358,11 +380,11 @@ test_composite (int testnum,
}
#if BILINEAR_INTERPOLATION_BITS == 8
-#define CHECKSUM 0x80DF1CB2
+#define CHECKSUM 0x8D3A7539
#elif BILINEAR_INTERPOLATION_BITS == 7
-#define CHECKSUM 0x2818D5FB
+#define CHECKSUM 0x03A23E0C
#elif BILINEAR_INTERPOLATION_BITS == 4
-#define CHECKSUM 0x387540A5
+#define CHECKSUM 0xE96D1A5E
#else
#define CHECKSUM 0x00000000
#endif