From a18769801e521ccb5a409c377ac0a6a1141f5776 Mon Sep 17 00:00:00 2001 From: marha Date: Tue, 1 Mar 2011 07:17:23 +0000 Subject: pixman mesa git update 1 Mar 2011 --- pixman/test/Makefile.am | 94 +- pixman/test/Makefile.win32 | 73 ++ pixman/test/composite.c | 1814 ++++++++++++++++++------------------ pixman/test/fetch-test.c | 53 +- pixman/test/scaling-helpers-test.c | 93 ++ pixman/test/stress-test.c | 1710 ++++++++++++++++----------------- pixman/test/trap-crasher.c | 20 +- 7 files changed, 2010 insertions(+), 1847 deletions(-) create mode 100644 pixman/test/Makefile.win32 create mode 100644 pixman/test/scaling-helpers-test.c (limited to 'pixman/test') diff --git a/pixman/test/Makefile.am b/pixman/test/Makefile.am index f05b99918..9dc72199e 100644 --- a/pixman/test/Makefile.am +++ b/pixman/test/Makefile.am @@ -1,46 +1,48 @@ -AM_CFLAGS = @OPENMP_CFLAGS@ -AM_LDFLAGS = @OPENMP_CFLAGS@ @TESTPROGS_EXTRA_LDFLAGS@ -LDADD = $(top_builddir)/pixman/libpixman-1.la -lm -INCLUDES = -I$(top_srcdir)/pixman -I$(top_builddir)/pixman - -TESTPROGRAMS = \ - a1-trap-test \ - pdf-op-test \ - region-test \ - region-translate-test \ - fetch-test \ - oob-test \ - trap-crasher \ - alpha-loop \ - scaling-crash-test \ - gradient-crash-test \ - alphamap \ - stress-test \ - composite-traps-test \ - blitters-test \ - scaling-test \ - affine-test \ - composite - -pdf_op_test_SOURCES = pdf-op-test.c utils.c utils.h -region_test_SOURCES = region-test.c utils.c utils.h -blitters_test_SOURCES = blitters-test.c utils.c utils.h -composite_traps_test_SOURCES = composite-traps-test.c utils.c utils.h -scaling_test_SOURCES = scaling-test.c utils.c utils.h -affine_test_SOURCES = affine-test.c utils.c utils.h -alphamap_SOURCES = alphamap.c utils.c utils.h -alpha_loop_SOURCES = alpha-loop.c utils.c utils.h -composite_SOURCES = composite.c utils.c utils.h -gradient_crash_test_SOURCES = gradient-crash-test.c utils.c utils.h -stress_test_SOURCES = stress-test.c utils.c utils.h - -# Benchmarks - -BENCHMARKS = \ - lowlevel-blt-bench - -lowlevel_blt_bench_SOURCES = lowlevel-blt-bench.c utils.c utils.h - -noinst_PROGRAMS = $(TESTPROGRAMS) $(BENCHMARKS) - -TESTS = $(TESTPROGRAMS) +AM_CFLAGS = @OPENMP_CFLAGS@ +AM_LDFLAGS = @OPENMP_CFLAGS@ @TESTPROGS_EXTRA_LDFLAGS@ +LDADD = $(top_builddir)/pixman/libpixman-1.la -lm +INCLUDES = -I$(top_srcdir)/pixman -I$(top_builddir)/pixman + +TESTPROGRAMS = \ + a1-trap-test \ + pdf-op-test \ + region-test \ + region-translate-test \ + fetch-test \ + oob-test \ + trap-crasher \ + alpha-loop \ + scaling-crash-test \ + scaling-helpers-test \ + gradient-crash-test \ + alphamap \ + stress-test \ + composite-traps-test \ + blitters-test \ + scaling-test \ + affine-test \ + composite + +pdf_op_test_SOURCES = pdf-op-test.c utils.c utils.h +region_test_SOURCES = region-test.c utils.c utils.h +blitters_test_SOURCES = blitters-test.c utils.c utils.h +composite_traps_test_SOURCES = composite-traps-test.c utils.c utils.h +scaling_test_SOURCES = scaling-test.c utils.c utils.h +affine_test_SOURCES = affine-test.c utils.c utils.h +alphamap_SOURCES = alphamap.c utils.c utils.h +alpha_loop_SOURCES = alpha-loop.c utils.c utils.h +composite_SOURCES = composite.c utils.c utils.h +gradient_crash_test_SOURCES = gradient-crash-test.c utils.c utils.h +stress_test_SOURCES = stress-test.c utils.c utils.h +scaling_helpers_test_SOURCES = scaling-helpers-test.c utils.c utils.h + +# Benchmarks + +BENCHMARKS = \ + lowlevel-blt-bench + +lowlevel_blt_bench_SOURCES = lowlevel-blt-bench.c utils.c utils.h + +noinst_PROGRAMS = $(TESTPROGRAMS) $(BENCHMARKS) + +TESTS = $(TESTPROGRAMS) diff --git a/pixman/test/Makefile.win32 b/pixman/test/Makefile.win32 new file mode 100644 index 000000000..c71afe187 --- /dev/null +++ b/pixman/test/Makefile.win32 @@ -0,0 +1,73 @@ +CC = cl +LINK = link + +CFG_VAR = $(CFG) +ifeq ($(CFG_VAR),) +CFG_VAR=release +endif + +CFLAGS = -MD -nologo -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -D_BIND_TO_CURRENT_VCLIBS_VERSION -D_MT -I../pixman -I. -I../ +TEST_LDADD = ../pixman/$(CFG_VAR)/pixman-1.lib +INCLUDES = -I../pixman -I$(top_builddir)/pixman + +# optimization flags +ifeq ($(CFG_VAR),debug) +CFLAGS += -Od -Zi +else +CFLAGS += -O2 +endif + +SOURCES = \ + a1-trap-test.c \ + pdf-op-test.c \ + region-test.c \ + region-translate-test.c \ + fetch-test.c \ + oob-test.c \ + trap-crasher.c \ + alpha-loop.c \ + scaling-crash-test.c \ + gradient-crash-test.c \ + alphamap.c \ + stress-test.c \ + composite-traps-test.c \ + blitters-test.c \ + scaling-test.c \ + affine-test.c \ + composite.c \ + utils.c + +TESTS = \ + $(CFG_VAR)/a1-trap-test.exe \ + $(CFG_VAR)/pdf-op-test.exe \ + $(CFG_VAR)/region-test.exe \ + $(CFG_VAR)/region-translate-test.exe \ + $(CFG_VAR)/fetch-test.exe \ + $(CFG_VAR)/oob-test.exe \ + $(CFG_VAR)/trap-crasher.exe \ + $(CFG_VAR)/alpha-loop.exe \ + $(CFG_VAR)/scaling-crash-test.exe \ + $(CFG_VAR)/gradient-crash-test.exe \ + $(CFG_VAR)/alphamap.exe \ + $(CFG_VAR)/stress-test.exe \ + $(CFG_VAR)/composite-traps-test.exe \ + $(CFG_VAR)/blitters-test.exe \ + $(CFG_VAR)/scaling-test.exe \ + $(CFG_VAR)/affine-test.exe \ + $(CFG_VAR)/composite.exe + + +OBJECTS = $(patsubst %.c, $(CFG_VAR)/%.obj, $(SOURCES)) + +$(CFG_VAR)/%.obj: %.c + @mkdir -p $(CFG_VAR) + @$(CC) -c $(CFLAGS) -Fo"$@" $< + +$(CFG_VAR)/%.exe: $(CFG_VAR)/%.obj + $(LINK) /NOLOGO /OUT:$@ $< $(CFG_VAR)/utils.obj $(TEST_LDADD) + +all: $(OBJECTS) $(TESTS) + @exit 0 + +clean: + @rm -f $(CFG_VAR)/*.obj $(CFG_VAR)/*.pdb || exit 0 diff --git a/pixman/test/composite.c b/pixman/test/composite.c index 8b8a8f540..a86e5ed68 100644 --- a/pixman/test/composite.c +++ b/pixman/test/composite.c @@ -1,907 +1,907 @@ -/* - * Copyright © 2005 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2010 Soeren Sandmann - * Copyright © 2010 Red Hat, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Eric Anholt not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Eric Anholt makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -#define PIXMAN_USE_INTERNAL_API -#include -#include -#include /* abort() */ -#include -#include -#include -#include "utils.h" - -typedef struct color_t color_t; -typedef struct format_t format_t; -typedef struct image_t image_t; -typedef struct operator_t operator_t; - -struct color_t -{ - double r, g, b, a; -}; - -struct format_t -{ - pixman_format_code_t format; - const char *name; -}; - -static const color_t colors[] = -{ - { 1.0, 1.0, 1.0, 1.0 }, - { 1.0, 1.0, 1.0, 0.0 }, - { 0.0, 0.0, 0.0, 1.0 }, - { 0.0, 0.0, 0.0, 0.0 }, - { 1.0, 0.0, 0.0, 1.0 }, - { 0.0, 1.0, 0.0, 1.0 }, - { 0.0, 0.0, 1.0, 1.0 }, - { 0.5, 0.0, 0.0, 0.5 }, -}; - -static uint16_t -_color_double_to_short (double d) -{ - uint32_t i; - - i = (uint32_t) (d * 65536); - i -= (i >> 16); - - return i; -} - -static void -compute_pixman_color (const color_t *color, - pixman_color_t *out) -{ - out->red = _color_double_to_short (color->r); - out->green = _color_double_to_short (color->g); - out->blue = _color_double_to_short (color->b); - out->alpha = _color_double_to_short (color->a); -} - -#define REPEAT 0x01000000 -#define FLAGS 0xff000000 - -static const int sizes[] = -{ - 0, - 1, - 1 | REPEAT, - 10 -}; - -static const format_t formats[] = -{ -#define P(x) { PIXMAN_##x, #x } - - /* 32 bpp formats */ - P(a8r8g8b8), - P(x8r8g8b8), - P(a8b8g8r8), - P(x8b8g8r8), - P(b8g8r8a8), - P(b8g8r8x8), - P(x2r10g10b10), - P(x2b10g10r10), - P(a2r10g10b10), - P(a2b10g10r10), - - /* 24 bpp formats */ - P(r8g8b8), - P(b8g8r8), - P(r5g6b5), - P(b5g6r5), - - /* 16 bpp formats */ - P(x1r5g5b5), - P(x1b5g5r5), - P(a1r5g5b5), - P(a1b5g5r5), - P(a4b4g4r4), - P(x4b4g4r4), - P(a4r4g4b4), - P(x4r4g4b4), - - /* 8 bpp formats */ - P(a8), - P(r3g3b2), - P(b2g3r3), - P(a2r2g2b2), - P(a2b2g2r2), - P(x4a4), - - /* 4 bpp formats */ - P(a4), - P(r1g2b1), - P(b1g2r1), - P(a1r1g1b1), - P(a1b1g1r1), - - /* 1 bpp formats */ - P(a1) -#undef P -}; - -struct image_t -{ - pixman_image_t *image; - const format_t *format; - const color_t *color; - pixman_repeat_t repeat; - int size; -}; - -struct operator_t -{ - pixman_op_t op; - const char *name; -}; - -static const operator_t operators[] = -{ -#define P(x) { PIXMAN_OP_##x, #x } - P(CLEAR), - P(SRC), - P(DST), - P(OVER), - P(OVER_REVERSE), - P(IN), - P(IN_REVERSE), - P(OUT), - P(OUT_REVERSE), - P(ATOP), - P(ATOP_REVERSE), - P(XOR), - P(ADD), - P(SATURATE), - - P(DISJOINT_CLEAR), - P(DISJOINT_SRC), - P(DISJOINT_DST), - P(DISJOINT_OVER), - P(DISJOINT_OVER_REVERSE), - P(DISJOINT_IN), - P(DISJOINT_IN_REVERSE), - P(DISJOINT_OUT), - P(DISJOINT_OUT_REVERSE), - P(DISJOINT_ATOP), - P(DISJOINT_ATOP_REVERSE), - P(DISJOINT_XOR), - - P(CONJOINT_CLEAR), - P(CONJOINT_SRC), - P(CONJOINT_DST), - P(CONJOINT_OVER), - P(CONJOINT_OVER_REVERSE), - P(CONJOINT_IN), - P(CONJOINT_IN_REVERSE), - P(CONJOINT_OUT), - P(CONJOINT_OUT_REVERSE), - P(CONJOINT_ATOP), - P(CONJOINT_ATOP_REVERSE), - P(CONJOINT_XOR), -#undef P -}; - -static double -calc_op (pixman_op_t op, double src, double dst, double srca, double dsta) -{ -#define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0) - - double Fa, Fb; - - switch (op) - { - case PIXMAN_OP_CLEAR: - case PIXMAN_OP_DISJOINT_CLEAR: - case PIXMAN_OP_CONJOINT_CLEAR: - return mult_chan (src, dst, 0.0, 0.0); - - case PIXMAN_OP_SRC: - case PIXMAN_OP_DISJOINT_SRC: - case PIXMAN_OP_CONJOINT_SRC: - return mult_chan (src, dst, 1.0, 0.0); - - case PIXMAN_OP_DST: - case PIXMAN_OP_DISJOINT_DST: - case PIXMAN_OP_CONJOINT_DST: - return mult_chan (src, dst, 0.0, 1.0); - - case PIXMAN_OP_OVER: - return mult_chan (src, dst, 1.0, 1.0 - srca); - - case PIXMAN_OP_OVER_REVERSE: - return mult_chan (src, dst, 1.0 - dsta, 1.0); - - case PIXMAN_OP_IN: - return mult_chan (src, dst, dsta, 0.0); - - case PIXMAN_OP_IN_REVERSE: - return mult_chan (src, dst, 0.0, srca); - - case PIXMAN_OP_OUT: - return mult_chan (src, dst, 1.0 - dsta, 0.0); - - case PIXMAN_OP_OUT_REVERSE: - return mult_chan (src, dst, 0.0, 1.0 - srca); - - case PIXMAN_OP_ATOP: - return mult_chan (src, dst, dsta, 1.0 - srca); - - case PIXMAN_OP_ATOP_REVERSE: - return mult_chan (src, dst, 1.0 - dsta, srca); - - case PIXMAN_OP_XOR: - return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca); - - case PIXMAN_OP_ADD: - return mult_chan (src, dst, 1.0, 1.0); - - case PIXMAN_OP_SATURATE: - case PIXMAN_OP_DISJOINT_OVER_REVERSE: - if (srca == 0.0) - Fa = 1.0; - else - Fa = MIN (1.0, (1.0 - dsta) / srca); - return mult_chan (src, dst, Fa, 1.0); - - case PIXMAN_OP_DISJOINT_OVER: - if (dsta == 0.0) - Fb = 1.0; - else - Fb = MIN (1.0, (1.0 - srca) / dsta); - return mult_chan (src, dst, 1.0, Fb); - - case PIXMAN_OP_DISJOINT_IN: - if (srca == 0.0) - Fa = 0.0; - else - Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca); - return mult_chan (src, dst, Fa, 0.0); - - case PIXMAN_OP_DISJOINT_IN_REVERSE: - if (dsta == 0.0) - Fb = 0.0; - else - Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta); - return mult_chan (src, dst, 0.0, Fb); - - case PIXMAN_OP_DISJOINT_OUT: - if (srca == 0.0) - Fa = 1.0; - else - Fa = MIN (1.0, (1.0 - dsta) / srca); - return mult_chan (src, dst, Fa, 0.0); - - case PIXMAN_OP_DISJOINT_OUT_REVERSE: - if (dsta == 0.0) - Fb = 1.0; - else - Fb = MIN (1.0, (1.0 - srca) / dsta); - return mult_chan (src, dst, 0.0, Fb); - - case PIXMAN_OP_DISJOINT_ATOP: - if (srca == 0.0) - Fa = 0.0; - else - Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca); - if (dsta == 0.0) - Fb = 1.0; - else - Fb = MIN (1.0, (1.0 - srca) / dsta); - return mult_chan (src, dst, Fa, Fb); - - case PIXMAN_OP_DISJOINT_ATOP_REVERSE: - if (srca == 0.0) - Fa = 1.0; - else - Fa = MIN (1.0, (1.0 - dsta) / srca); - if (dsta == 0.0) - Fb = 0.0; - else - Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta); - return mult_chan (src, dst, Fa, Fb); - - case PIXMAN_OP_DISJOINT_XOR: - if (srca == 0.0) - Fa = 1.0; - else - Fa = MIN (1.0, (1.0 - dsta) / srca); - if (dsta == 0.0) - Fb = 1.0; - else - Fb = MIN (1.0, (1.0 - srca) / dsta); - return mult_chan (src, dst, Fa, Fb); - - case PIXMAN_OP_CONJOINT_OVER: - if (dsta == 0.0) - Fb = 0.0; - else - Fb = MAX (0.0, 1.0 - srca / dsta); - return mult_chan (src, dst, 1.0, Fb); - - case PIXMAN_OP_CONJOINT_OVER_REVERSE: - if (srca == 0.0) - Fa = 0.0; - else - Fa = MAX (0.0, 1.0 - dsta / srca); - return mult_chan (src, dst, Fa, 1.0); - - case PIXMAN_OP_CONJOINT_IN: - if (srca == 0.0) - Fa = 1.0; - else - Fa = MIN (1.0, dsta / srca); - return mult_chan (src, dst, Fa, 0.0); - - case PIXMAN_OP_CONJOINT_IN_REVERSE: - if (dsta == 0.0) - Fb = 1.0; - else - Fb = MIN (1.0, srca / dsta); - return mult_chan (src, dst, 0.0, Fb); - - case PIXMAN_OP_CONJOINT_OUT: - if (srca == 0.0) - Fa = 0.0; - else - Fa = MAX (0.0, 1.0 - dsta / srca); - return mult_chan (src, dst, Fa, 0.0); - - case PIXMAN_OP_CONJOINT_OUT_REVERSE: - if (dsta == 0.0) - Fb = 0.0; - else - Fb = MAX (0.0, 1.0 - srca / dsta); - return mult_chan (src, dst, 0.0, Fb); - - case PIXMAN_OP_CONJOINT_ATOP: - if (srca == 0.0) - Fa = 1.0; - else - Fa = MIN (1.0, dsta / srca); - if (dsta == 0.0) - Fb = 0.0; - else - Fb = MAX (0.0, 1.0 - srca / dsta); - return mult_chan (src, dst, Fa, Fb); - - case PIXMAN_OP_CONJOINT_ATOP_REVERSE: - if (srca == 0.0) - Fa = 0.0; - else - Fa = MAX (0.0, 1.0 - dsta / srca); - if (dsta == 0.0) - Fb = 1.0; - else - Fb = MIN (1.0, srca / dsta); - return mult_chan (src, dst, Fa, Fb); - - case PIXMAN_OP_CONJOINT_XOR: - if (srca == 0.0) - Fa = 0.0; - else - Fa = MAX (0.0, 1.0 - dsta / srca); - if (dsta == 0.0) - Fb = 0.0; - else - Fb = MAX (0.0, 1.0 - srca / dsta); - return mult_chan (src, dst, Fa, Fb); - - case PIXMAN_OP_MULTIPLY: - case PIXMAN_OP_SCREEN: - case PIXMAN_OP_OVERLAY: - case PIXMAN_OP_DARKEN: - case PIXMAN_OP_LIGHTEN: - case PIXMAN_OP_COLOR_DODGE: - case PIXMAN_OP_COLOR_BURN: - case PIXMAN_OP_HARD_LIGHT: - case PIXMAN_OP_SOFT_LIGHT: - case PIXMAN_OP_DIFFERENCE: - case PIXMAN_OP_EXCLUSION: - case PIXMAN_OP_HSL_HUE: - case PIXMAN_OP_HSL_SATURATION: - case PIXMAN_OP_HSL_COLOR: - case PIXMAN_OP_HSL_LUMINOSITY: - default: - abort(); - } -#undef mult_chan -} - -static void -do_composite (pixman_op_t op, - const color_t *src, - const color_t *mask, - const color_t *dst, - color_t *result, - pixman_bool_t component_alpha) -{ - color_t srcval, srcalpha; - - if (mask == NULL) - { - srcval = *src; - - srcalpha.r = src->a; - srcalpha.g = src->a; - srcalpha.b = src->a; - srcalpha.a = src->a; - } - else if (component_alpha) - { - srcval.r = src->r * mask->r; - srcval.g = src->g * mask->g; - srcval.b = src->b * mask->b; - srcval.a = src->a * mask->a; - - srcalpha.r = src->a * mask->r; - srcalpha.g = src->a * mask->g; - srcalpha.b = src->a * mask->b; - srcalpha.a = src->a * mask->a; - } - else - { - srcval.r = src->r * mask->a; - srcval.g = src->g * mask->a; - srcval.b = src->b * mask->a; - srcval.a = src->a * mask->a; - - srcalpha.r = src->a * mask->a; - srcalpha.g = src->a * mask->a; - srcalpha.b = src->a * mask->a; - srcalpha.a = src->a * mask->a; - } - - result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a); - result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a); - result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a); - result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a); -} - -static void -color_correct (pixman_format_code_t format, - color_t *color) -{ -#define MASK(x) ((1 << (x)) - 1) -#define round_pix(pix, m) \ - ((int)((pix) * (MASK(m)) + .5) / (double) (MASK(m))) - - if (PIXMAN_FORMAT_R (format) == 0) - { - color->r = 0.0; - color->g = 0.0; - color->b = 0.0; - } - else - { - color->r = round_pix (color->r, PIXMAN_FORMAT_R (format)); - color->g = round_pix (color->g, PIXMAN_FORMAT_G (format)); - color->b = round_pix (color->b, PIXMAN_FORMAT_B (format)); - } - - if (PIXMAN_FORMAT_A (format) == 0) - color->a = 1.0; - else - color->a = round_pix (color->a, PIXMAN_FORMAT_A (format)); - -#undef round_pix -#undef MASK -} - -static void -get_pixel (pixman_image_t *image, - pixman_format_code_t format, - color_t *color) -{ -#define MASK(N) ((1UL << (N))-1) - - unsigned long rs, gs, bs, as; - int a, r, g, b; - unsigned long val; - - val = *(unsigned long *) pixman_image_get_data (image); -#ifdef WORDS_BIGENDIAN - val >>= 8 * sizeof(val) - PIXMAN_FORMAT_BPP (format); -#endif - - /* Number of bits in each channel */ - a = PIXMAN_FORMAT_A (format); - r = PIXMAN_FORMAT_R (format); - g = PIXMAN_FORMAT_G (format); - b = PIXMAN_FORMAT_B (format); - - switch (PIXMAN_FORMAT_TYPE (format)) - { - case PIXMAN_TYPE_ARGB: - bs = 0; - gs = b + bs; - rs = g + gs; - as = r + rs; - break; - - case PIXMAN_TYPE_ABGR: - rs = 0; - gs = r + rs; - bs = g + gs; - as = b + bs; - break; - - case PIXMAN_TYPE_BGRA: - as = 0; - rs = PIXMAN_FORMAT_BPP (format) - (b + g + r); - gs = r + rs; - bs = g + gs; - break; - - case PIXMAN_TYPE_A: - as = 0; - rs = 0; - gs = 0; - bs = 0; - break; - - case PIXMAN_TYPE_OTHER: - case PIXMAN_TYPE_COLOR: - case PIXMAN_TYPE_GRAY: - case PIXMAN_TYPE_YUY2: - case PIXMAN_TYPE_YV12: - default: - abort (); - as = 0; - rs = 0; - gs = 0; - bs = 0; - break; - } - - if (MASK (a) != 0) - color->a = ((val >> as) & MASK (a)) / (double) MASK (a); - else - color->a = 1.0; - - if (MASK (r) != 0) - { - color->r = ((val >> rs) & MASK (r)) / (double) MASK (r); - color->g = ((val >> gs) & MASK (g)) / (double) MASK (g); - color->b = ((val >> bs) & MASK (b)) / (double) MASK (b); - } - else - { - color->r = 0.0; - color->g = 0.0; - color->b = 0.0; - } - -#undef MASK -} - -static double -eval_diff (color_t *expected, color_t *test, pixman_format_code_t format) -{ - double rscale, gscale, bscale, ascale; - double rdiff, gdiff, bdiff, adiff; - - rscale = 1.0 * ((1 << PIXMAN_FORMAT_R (format)) - 1); - gscale = 1.0 * ((1 << PIXMAN_FORMAT_G (format)) - 1); - bscale = 1.0 * ((1 << PIXMAN_FORMAT_B (format)) - 1); - ascale = 1.0 * ((1 << PIXMAN_FORMAT_A (format)) - 1); - - rdiff = fabs (test->r - expected->r) * rscale; - bdiff = fabs (test->g - expected->g) * gscale; - gdiff = fabs (test->b - expected->b) * bscale; - adiff = fabs (test->a - expected->a) * ascale; - - return MAX (MAX (MAX (rdiff, gdiff), bdiff), adiff); -} - -static char * -describe_image (image_t *info, char *buf, int buflen) -{ - if (info->size) - { - snprintf (buf, buflen, "%s %dx%d%s", - info->format->name, - info->size, info->size, - info->repeat ? "R" :""); - } - else - { - snprintf (buf, buflen, "solid"); - } - - return buf; -} - -/* Test a composite of a given operation, source, mask, and destination - * picture. - * Fills the window, and samples from the 0,0 pixel corner. - */ -static pixman_bool_t -composite_test (image_t *dst, - const operator_t *op, - image_t *src, - image_t *mask, - pixman_bool_t component_alpha) -{ - pixman_color_t fill; - pixman_rectangle16_t rect; - color_t expected, result, tdst, tsrc, tmsk; - double diff; - pixman_bool_t success = TRUE; - - compute_pixman_color (dst->color, &fill); - rect.x = rect.y = 0; - rect.width = rect.height = dst->size; - pixman_image_fill_rectangles (PIXMAN_OP_SRC, dst->image, - &fill, 1, &rect); - - if (mask != NULL) - { - pixman_image_set_component_alpha (mask->image, component_alpha); - pixman_image_composite (op->op, src->image, mask->image, dst->image, - 0, 0, - 0, 0, - 0, 0, - dst->size, dst->size); - - tmsk = *mask->color; - if (mask->size) - { - color_correct (mask->format->format, &tmsk); - - if (component_alpha && - PIXMAN_FORMAT_R (mask->format->format) == 0) - { - /* Ax component-alpha masks expand alpha into - * all color channels. - */ - tmsk.r = tmsk.g = tmsk.b = tmsk.a; - } - } - } - else - { - pixman_image_composite (op->op, src->image, NULL, dst->image, - 0, 0, - 0, 0, - 0, 0, - dst->size, dst->size); - } - get_pixel (dst->image, dst->format->format, &result); - - tdst = *dst->color; - color_correct (dst->format->format, &tdst); - tsrc = *src->color; - if (src->size) - color_correct (src->format->format, &tsrc); - do_composite (op->op, &tsrc, mask ? &tmsk : NULL, &tdst, - &expected, component_alpha); - color_correct (dst->format->format, &expected); - - diff = eval_diff (&expected, &result, dst->format->format); - - /* FIXME: We should find out what deviation is acceptable. 3.0 - * is clearly absurd for 2 bit formats for example. On the other - * hand currently 1.0 does not work. - */ - if (diff > 3.0) - { - char buf[40]; - - snprintf (buf, sizeof (buf), - "%s %scomposite", - op->name, - component_alpha ? "CA " : ""); - - printf ("%s test error of %.4f --\n" - " R G B A\n" - "got: %.2f %.2f %.2f %.2f [%08lx]\n" - "expected: %.2f %.2f %.2f %.2f\n", - buf, diff, - result.r, result.g, result.b, result.a, - *(unsigned long *) pixman_image_get_data (dst->image), - expected.r, expected.g, expected.b, expected.a); - - if (mask != NULL) - { - printf ("src color: %.2f %.2f %.2f %.2f\n" - "msk color: %.2f %.2f %.2f %.2f\n" - "dst color: %.2f %.2f %.2f %.2f\n", - src->color->r, src->color->g, - src->color->b, src->color->a, - mask->color->r, mask->color->g, - mask->color->b, mask->color->a, - dst->color->r, dst->color->g, - dst->color->b, dst->color->a); - printf ("src: %s, ", describe_image (src, buf, sizeof (buf))); - printf ("mask: %s, ", describe_image (mask, buf, sizeof (buf))); - printf ("dst: %s\n\n", describe_image (dst, buf, sizeof (buf))); - } - else - { - printf ("src color: %.2f %.2f %.2f %.2f\n" - "dst color: %.2f %.2f %.2f %.2f\n", - src->color->r, src->color->g, - src->color->b, src->color->a, - dst->color->r, dst->color->g, - dst->color->b, dst->color->a); - printf ("src: %s, ", describe_image (src, buf, sizeof (buf))); - printf ("dst: %s\n\n", describe_image (dst, buf, sizeof (buf))); - } - - success = FALSE; - } - - return success; -} - -static void -image_init (image_t *info, - int color, - int format, - int size) -{ - pixman_color_t fill; - - info->color = &colors[color]; - compute_pixman_color (info->color, &fill); - - info->format = &formats[format]; - info->size = sizes[size] & ~FLAGS; - info->repeat = PIXMAN_REPEAT_NONE; - - if (info->size) - { - pixman_rectangle16_t rect; - - info->image = pixman_image_create_bits (info->format->format, - info->size, info->size, - NULL, 0); - - rect.x = rect.y = 0; - rect.width = rect.height = info->size; - pixman_image_fill_rectangles (PIXMAN_OP_SRC, info->image, &fill, - 1, &rect); - - if (size & REPEAT) - { - pixman_image_set_repeat (info->image, PIXMAN_REPEAT_NORMAL); - info->repeat = PIXMAN_REPEAT_NORMAL; - } - } - else - { - info->image = pixman_image_create_solid_fill (&fill); - } -} - -static void -image_fini (image_t *info) -{ - pixman_image_unref (info->image); -} - -static int -random_size (void) -{ - return lcg_rand_n (ARRAY_LENGTH (sizes)); -} - -static int -random_color (void) -{ - return lcg_rand_n (ARRAY_LENGTH (colors)); -} - -static int -random_format (void) -{ - return lcg_rand_n (ARRAY_LENGTH (formats)); -} - -static pixman_bool_t -run_test (uint32_t seed) -{ - image_t src, mask, dst; - const operator_t *op; - int ca; - int ok; - - lcg_srand (seed); - - image_init (&dst, random_color(), random_format(), 1); - image_init (&src, random_color(), random_format(), random_size()); - image_init (&mask, random_color(), random_format(), random_size()); - - op = &(operators [lcg_rand_n (ARRAY_LENGTH (operators))]); - - ca = lcg_rand_n (3); - - switch (ca) - { - case 0: - ok = composite_test (&dst, op, &src, NULL, FALSE); - break; - case 1: - ok = composite_test (&dst, op, &src, &mask, FALSE); - break; - case 2: - ok = composite_test (&dst, op, &src, &mask, - mask.size? TRUE : FALSE); - break; - default: - ok = FALSE; - break; - } - - image_fini (&src); - image_fini (&mask); - image_fini (&dst); - - return ok; -} - -int -main (int argc, char **argv) -{ -#define N_TESTS (8 * 1024 * 1024) - int result = 0; - int i; - - if (argc > 1) - { - char *end; - - i = strtol (argv[1], &end, 0); - - if (end != argv[1]) - { - if (!run_test (i)) - return 1; - else - return 0; - } - else - { - printf ("Usage:\n\n %s \n\n", argv[0]); - return -1; - } - } - -#ifdef USE_OPENMP -# pragma omp parallel for default(none) shared(result) shared(argv) -#endif - for (i = 1; i <= N_TESTS; ++i) - { - if (!result && !run_test (i)) - { - printf ("Test %d failed.\n", i); - - result = i; - } - } - - return result; -} +/* + * Copyright © 2005 Eric Anholt + * Copyright © 2009 Chris Wilson + * Copyright © 2010 Soeren Sandmann + * Copyright © 2010 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Eric Anholt not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Eric Anholt makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +#define PIXMAN_USE_INTERNAL_API +#include +#include +#include /* abort() */ +#include +#include +#include +#include "utils.h" + +typedef struct color_t color_t; +typedef struct format_t format_t; +typedef struct image_t image_t; +typedef struct operator_t operator_t; + +struct color_t +{ + double r, g, b, a; +}; + +struct format_t +{ + pixman_format_code_t format; + const char *name; +}; + +static const color_t colors[] = +{ + { 1.0, 1.0, 1.0, 1.0 }, + { 1.0, 1.0, 1.0, 0.0 }, + { 0.0, 0.0, 0.0, 1.0 }, + { 0.0, 0.0, 0.0, 0.0 }, + { 1.0, 0.0, 0.0, 1.0 }, + { 0.0, 1.0, 0.0, 1.0 }, + { 0.0, 0.0, 1.0, 1.0 }, + { 0.5, 0.0, 0.0, 0.5 }, +}; + +static uint16_t +_color_double_to_short (double d) +{ + uint32_t i; + + i = (uint32_t) (d * 65536); + i -= (i >> 16); + + return i; +} + +static void +compute_pixman_color (const color_t *color, + pixman_color_t *out) +{ + out->red = _color_double_to_short (color->r); + out->green = _color_double_to_short (color->g); + out->blue = _color_double_to_short (color->b); + out->alpha = _color_double_to_short (color->a); +} + +#define REPEAT 0x01000000 +#define FLAGS 0xff000000 + +static const int sizes[] = +{ + 0, + 1, + 1 | REPEAT, + 10 +}; + +static const format_t formats[] = +{ +#define P(x) { PIXMAN_##x, #x } + + /* 32 bpp formats */ + P(a8r8g8b8), + P(x8r8g8b8), + P(a8b8g8r8), + P(x8b8g8r8), + P(b8g8r8a8), + P(b8g8r8x8), + P(x2r10g10b10), + P(x2b10g10r10), + P(a2r10g10b10), + P(a2b10g10r10), + + /* 24 bpp formats */ + P(r8g8b8), + P(b8g8r8), + P(r5g6b5), + P(b5g6r5), + + /* 16 bpp formats */ + P(x1r5g5b5), + P(x1b5g5r5), + P(a1r5g5b5), + P(a1b5g5r5), + P(a4b4g4r4), + P(x4b4g4r4), + P(a4r4g4b4), + P(x4r4g4b4), + + /* 8 bpp formats */ + P(a8), + P(r3g3b2), + P(b2g3r3), + P(a2r2g2b2), + P(a2b2g2r2), + P(x4a4), + + /* 4 bpp formats */ + P(a4), + P(r1g2b1), + P(b1g2r1), + P(a1r1g1b1), + P(a1b1g1r1), + + /* 1 bpp formats */ + P(a1) +#undef P +}; + +struct image_t +{ + pixman_image_t *image; + const format_t *format; + const color_t *color; + pixman_repeat_t repeat; + int size; +}; + +struct operator_t +{ + pixman_op_t op; + const char *name; +}; + +static const operator_t operators[] = +{ +#define P(x) { PIXMAN_OP_##x, #x } + P(CLEAR), + P(SRC), + P(DST), + P(OVER), + P(OVER_REVERSE), + P(IN), + P(IN_REVERSE), + P(OUT), + P(OUT_REVERSE), + P(ATOP), + P(ATOP_REVERSE), + P(XOR), + P(ADD), + P(SATURATE), + + P(DISJOINT_CLEAR), + P(DISJOINT_SRC), + P(DISJOINT_DST), + P(DISJOINT_OVER), + P(DISJOINT_OVER_REVERSE), + P(DISJOINT_IN), + P(DISJOINT_IN_REVERSE), + P(DISJOINT_OUT), + P(DISJOINT_OUT_REVERSE), + P(DISJOINT_ATOP), + P(DISJOINT_ATOP_REVERSE), + P(DISJOINT_XOR), + + P(CONJOINT_CLEAR), + P(CONJOINT_SRC), + P(CONJOINT_DST), + P(CONJOINT_OVER), + P(CONJOINT_OVER_REVERSE), + P(CONJOINT_IN), + P(CONJOINT_IN_REVERSE), + P(CONJOINT_OUT), + P(CONJOINT_OUT_REVERSE), + P(CONJOINT_ATOP), + P(CONJOINT_ATOP_REVERSE), + P(CONJOINT_XOR), +#undef P +}; + +static double +calc_op (pixman_op_t op, double src, double dst, double srca, double dsta) +{ +#define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0) + + double Fa, Fb; + + switch (op) + { + case PIXMAN_OP_CLEAR: + case PIXMAN_OP_DISJOINT_CLEAR: + case PIXMAN_OP_CONJOINT_CLEAR: + return mult_chan (src, dst, 0.0, 0.0); + + case PIXMAN_OP_SRC: + case PIXMAN_OP_DISJOINT_SRC: + case PIXMAN_OP_CONJOINT_SRC: + return mult_chan (src, dst, 1.0, 0.0); + + case PIXMAN_OP_DST: + case PIXMAN_OP_DISJOINT_DST: + case PIXMAN_OP_CONJOINT_DST: + return mult_chan (src, dst, 0.0, 1.0); + + case PIXMAN_OP_OVER: + return mult_chan (src, dst, 1.0, 1.0 - srca); + + case PIXMAN_OP_OVER_REVERSE: + return mult_chan (src, dst, 1.0 - dsta, 1.0); + + case PIXMAN_OP_IN: + return mult_chan (src, dst, dsta, 0.0); + + case PIXMAN_OP_IN_REVERSE: + return mult_chan (src, dst, 0.0, srca); + + case PIXMAN_OP_OUT: + return mult_chan (src, dst, 1.0 - dsta, 0.0); + + case PIXMAN_OP_OUT_REVERSE: + return mult_chan (src, dst, 0.0, 1.0 - srca); + + case PIXMAN_OP_ATOP: + return mult_chan (src, dst, dsta, 1.0 - srca); + + case PIXMAN_OP_ATOP_REVERSE: + return mult_chan (src, dst, 1.0 - dsta, srca); + + case PIXMAN_OP_XOR: + return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca); + + case PIXMAN_OP_ADD: + return mult_chan (src, dst, 1.0, 1.0); + + case PIXMAN_OP_SATURATE: + case PIXMAN_OP_DISJOINT_OVER_REVERSE: + if (srca == 0.0) + Fa = 1.0; + else + Fa = MIN (1.0, (1.0 - dsta) / srca); + return mult_chan (src, dst, Fa, 1.0); + + case PIXMAN_OP_DISJOINT_OVER: + if (dsta == 0.0) + Fb = 1.0; + else + Fb = MIN (1.0, (1.0 - srca) / dsta); + return mult_chan (src, dst, 1.0, Fb); + + case PIXMAN_OP_DISJOINT_IN: + if (srca == 0.0) + Fa = 0.0; + else + Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca); + return mult_chan (src, dst, Fa, 0.0); + + case PIXMAN_OP_DISJOINT_IN_REVERSE: + if (dsta == 0.0) + Fb = 0.0; + else + Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta); + return mult_chan (src, dst, 0.0, Fb); + + case PIXMAN_OP_DISJOINT_OUT: + if (srca == 0.0) + Fa = 1.0; + else + Fa = MIN (1.0, (1.0 - dsta) / srca); + return mult_chan (src, dst, Fa, 0.0); + + case PIXMAN_OP_DISJOINT_OUT_REVERSE: + if (dsta == 0.0) + Fb = 1.0; + else + Fb = MIN (1.0, (1.0 - srca) / dsta); + return mult_chan (src, dst, 0.0, Fb); + + case PIXMAN_OP_DISJOINT_ATOP: + if (srca == 0.0) + Fa = 0.0; + else + Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca); + if (dsta == 0.0) + Fb = 1.0; + else + Fb = MIN (1.0, (1.0 - srca) / dsta); + return mult_chan (src, dst, Fa, Fb); + + case PIXMAN_OP_DISJOINT_ATOP_REVERSE: + if (srca == 0.0) + Fa = 1.0; + else + Fa = MIN (1.0, (1.0 - dsta) / srca); + if (dsta == 0.0) + Fb = 0.0; + else + Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta); + return mult_chan (src, dst, Fa, Fb); + + case PIXMAN_OP_DISJOINT_XOR: + if (srca == 0.0) + Fa = 1.0; + else + Fa = MIN (1.0, (1.0 - dsta) / srca); + if (dsta == 0.0) + Fb = 1.0; + else + Fb = MIN (1.0, (1.0 - srca) / dsta); + return mult_chan (src, dst, Fa, Fb); + + case PIXMAN_OP_CONJOINT_OVER: + if (dsta == 0.0) + Fb = 0.0; + else + Fb = MAX (0.0, 1.0 - srca / dsta); + return mult_chan (src, dst, 1.0, Fb); + + case PIXMAN_OP_CONJOINT_OVER_REVERSE: + if (srca == 0.0) + Fa = 0.0; + else + Fa = MAX (0.0, 1.0 - dsta / srca); + return mult_chan (src, dst, Fa, 1.0); + + case PIXMAN_OP_CONJOINT_IN: + if (srca == 0.0) + Fa = 1.0; + else + Fa = MIN (1.0, dsta / srca); + return mult_chan (src, dst, Fa, 0.0); + + case PIXMAN_OP_CONJOINT_IN_REVERSE: + if (dsta == 0.0) + Fb = 1.0; + else + Fb = MIN (1.0, srca / dsta); + return mult_chan (src, dst, 0.0, Fb); + + case PIXMAN_OP_CONJOINT_OUT: + if (srca == 0.0) + Fa = 0.0; + else + Fa = MAX (0.0, 1.0 - dsta / srca); + return mult_chan (src, dst, Fa, 0.0); + + case PIXMAN_OP_CONJOINT_OUT_REVERSE: + if (dsta == 0.0) + Fb = 0.0; + else + Fb = MAX (0.0, 1.0 - srca / dsta); + return mult_chan (src, dst, 0.0, Fb); + + case PIXMAN_OP_CONJOINT_ATOP: + if (srca == 0.0) + Fa = 1.0; + else + Fa = MIN (1.0, dsta / srca); + if (dsta == 0.0) + Fb = 0.0; + else + Fb = MAX (0.0, 1.0 - srca / dsta); + return mult_chan (src, dst, Fa, Fb); + + case PIXMAN_OP_CONJOINT_ATOP_REVERSE: + if (srca == 0.0) + Fa = 0.0; + else + Fa = MAX (0.0, 1.0 - dsta / srca); + if (dsta == 0.0) + Fb = 1.0; + else + Fb = MIN (1.0, srca / dsta); + return mult_chan (src, dst, Fa, Fb); + + case PIXMAN_OP_CONJOINT_XOR: + if (srca == 0.0) + Fa = 0.0; + else + Fa = MAX (0.0, 1.0 - dsta / srca); + if (dsta == 0.0) + Fb = 0.0; + else + Fb = MAX (0.0, 1.0 - srca / dsta); + return mult_chan (src, dst, Fa, Fb); + + case PIXMAN_OP_MULTIPLY: + case PIXMAN_OP_SCREEN: + case PIXMAN_OP_OVERLAY: + case PIXMAN_OP_DARKEN: + case PIXMAN_OP_LIGHTEN: + case PIXMAN_OP_COLOR_DODGE: + case PIXMAN_OP_COLOR_BURN: + case PIXMAN_OP_HARD_LIGHT: + case PIXMAN_OP_SOFT_LIGHT: + case PIXMAN_OP_DIFFERENCE: + case PIXMAN_OP_EXCLUSION: + case PIXMAN_OP_HSL_HUE: + case PIXMAN_OP_HSL_SATURATION: + case PIXMAN_OP_HSL_COLOR: + case PIXMAN_OP_HSL_LUMINOSITY: + default: + abort(); + return 0; /* silence MSVC */ + } +#undef mult_chan +} + +static void +do_composite (pixman_op_t op, + const color_t *src, + const color_t *mask, + const color_t *dst, + color_t *result, + pixman_bool_t component_alpha) +{ + color_t srcval, srcalpha; + + if (mask == NULL) + { + srcval = *src; + + srcalpha.r = src->a; + srcalpha.g = src->a; + srcalpha.b = src->a; + srcalpha.a = src->a; + } + else if (component_alpha) + { + srcval.r = src->r * mask->r; + srcval.g = src->g * mask->g; + srcval.b = src->b * mask->b; + srcval.a = src->a * mask->a; + + srcalpha.r = src->a * mask->r; + srcalpha.g = src->a * mask->g; + srcalpha.b = src->a * mask->b; + srcalpha.a = src->a * mask->a; + } + else + { + srcval.r = src->r * mask->a; + srcval.g = src->g * mask->a; + srcval.b = src->b * mask->a; + srcval.a = src->a * mask->a; + + srcalpha.r = src->a * mask->a; + srcalpha.g = src->a * mask->a; + srcalpha.b = src->a * mask->a; + srcalpha.a = src->a * mask->a; + } + + result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a); + result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a); + result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a); + result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a); +} + +static void +color_correct (pixman_format_code_t format, + color_t *color) +{ +#define MASK(x) ((1 << (x)) - 1) +#define round_pix(pix, m) \ + ((int)((pix) * (MASK(m)) + .5) / (double) (MASK(m))) + + if (PIXMAN_FORMAT_R (format) == 0) + { + color->r = 0.0; + color->g = 0.0; + color->b = 0.0; + } + else + { + color->r = round_pix (color->r, PIXMAN_FORMAT_R (format)); + color->g = round_pix (color->g, PIXMAN_FORMAT_G (format)); + color->b = round_pix (color->b, PIXMAN_FORMAT_B (format)); + } + + if (PIXMAN_FORMAT_A (format) == 0) + color->a = 1.0; + else + color->a = round_pix (color->a, PIXMAN_FORMAT_A (format)); + +#undef round_pix +#undef MASK +} + +static void +get_pixel (pixman_image_t *image, + pixman_format_code_t format, + color_t *color) +{ +#define MASK(N) ((1UL << (N))-1) + + unsigned long rs, gs, bs, as; + int a, r, g, b; + unsigned long val; + + val = *(unsigned long *) pixman_image_get_data (image); +#ifdef WORDS_BIGENDIAN + val >>= 8 * sizeof(val) - PIXMAN_FORMAT_BPP (format); +#endif + + /* Number of bits in each channel */ + a = PIXMAN_FORMAT_A (format); + r = PIXMAN_FORMAT_R (format); + g = PIXMAN_FORMAT_G (format); + b = PIXMAN_FORMAT_B (format); + + switch (PIXMAN_FORMAT_TYPE (format)) + { + case PIXMAN_TYPE_ARGB: + bs = 0; + gs = b + bs; + rs = g + gs; + as = r + rs; + break; + + case PIXMAN_TYPE_ABGR: + rs = 0; + gs = r + rs; + bs = g + gs; + as = b + bs; + break; + + case PIXMAN_TYPE_BGRA: + as = 0; + rs = PIXMAN_FORMAT_BPP (format) - (b + g + r); + gs = r + rs; + bs = g + gs; + break; + + case PIXMAN_TYPE_A: + as = 0; + rs = 0; + gs = 0; + bs = 0; + break; + + case PIXMAN_TYPE_OTHER: + case PIXMAN_TYPE_COLOR: + case PIXMAN_TYPE_GRAY: + case PIXMAN_TYPE_YUY2: + case PIXMAN_TYPE_YV12: + default: + abort (); + as = 0; + rs = 0; + gs = 0; + bs = 0; + break; + } + + if (MASK (a) != 0) + color->a = ((val >> as) & MASK (a)) / (double) MASK (a); + else + color->a = 1.0; + + if (MASK (r) != 0) + { + color->r = ((val >> rs) & MASK (r)) / (double) MASK (r); + color->g = ((val >> gs) & MASK (g)) / (double) MASK (g); + color->b = ((val >> bs) & MASK (b)) / (double) MASK (b); + } + else + { + color->r = 0.0; + color->g = 0.0; + color->b = 0.0; + } + +#undef MASK +} + +static double +eval_diff (color_t *expected, color_t *test, pixman_format_code_t format) +{ + double rscale, gscale, bscale, ascale; + double rdiff, gdiff, bdiff, adiff; + + rscale = 1.0 * ((1 << PIXMAN_FORMAT_R (format)) - 1); + gscale = 1.0 * ((1 << PIXMAN_FORMAT_G (format)) - 1); + bscale = 1.0 * ((1 << PIXMAN_FORMAT_B (format)) - 1); + ascale = 1.0 * ((1 << PIXMAN_FORMAT_A (format)) - 1); + + rdiff = fabs (test->r - expected->r) * rscale; + bdiff = fabs (test->g - expected->g) * gscale; + gdiff = fabs (test->b - expected->b) * bscale; + adiff = fabs (test->a - expected->a) * ascale; + + return MAX (MAX (MAX (rdiff, gdiff), bdiff), adiff); +} + +static char * +describe_image (image_t *info, char *buf) +{ + if (info->size) + { + sprintf (buf, "%s %dx%d%s", + info->format->name, + info->size, info->size, + info->repeat ? "R" :""); + } + else + { + sprintf (buf, "solid"); + } + + return buf; +} + +/* Test a composite of a given operation, source, mask, and destination + * picture. + * Fills the window, and samples from the 0,0 pixel corner. + */ +static pixman_bool_t +composite_test (image_t *dst, + const operator_t *op, + image_t *src, + image_t *mask, + pixman_bool_t component_alpha) +{ + pixman_color_t fill; + pixman_rectangle16_t rect; + color_t expected, result, tdst, tsrc, tmsk; + double diff; + pixman_bool_t success = TRUE; + + compute_pixman_color (dst->color, &fill); + rect.x = rect.y = 0; + rect.width = rect.height = dst->size; + pixman_image_fill_rectangles (PIXMAN_OP_SRC, dst->image, + &fill, 1, &rect); + + if (mask != NULL) + { + pixman_image_set_component_alpha (mask->image, component_alpha); + pixman_image_composite (op->op, src->image, mask->image, dst->image, + 0, 0, + 0, 0, + 0, 0, + dst->size, dst->size); + + tmsk = *mask->color; + if (mask->size) + { + color_correct (mask->format->format, &tmsk); + + if (component_alpha && + PIXMAN_FORMAT_R (mask->format->format) == 0) + { + /* Ax component-alpha masks expand alpha into + * all color channels. + */ + tmsk.r = tmsk.g = tmsk.b = tmsk.a; + } + } + } + else + { + pixman_image_composite (op->op, src->image, NULL, dst->image, + 0, 0, + 0, 0, + 0, 0, + dst->size, dst->size); + } + get_pixel (dst->image, dst->format->format, &result); + + tdst = *dst->color; + color_correct (dst->format->format, &tdst); + tsrc = *src->color; + if (src->size) + color_correct (src->format->format, &tsrc); + do_composite (op->op, &tsrc, mask ? &tmsk : NULL, &tdst, + &expected, component_alpha); + color_correct (dst->format->format, &expected); + + diff = eval_diff (&expected, &result, dst->format->format); + + /* FIXME: We should find out what deviation is acceptable. 3.0 + * is clearly absurd for 2 bit formats for example. On the other + * hand currently 1.0 does not work. + */ + if (diff > 3.0) + { + char buf[40]; + + sprintf (buf, "%s %scomposite", + op->name, + component_alpha ? "CA " : ""); + + printf ("%s test error of %.4f --\n" + " R G B A\n" + "got: %.2f %.2f %.2f %.2f [%08lx]\n" + "expected: %.2f %.2f %.2f %.2f\n", + buf, diff, + result.r, result.g, result.b, result.a, + *(unsigned long *) pixman_image_get_data (dst->image), + expected.r, expected.g, expected.b, expected.a); + + if (mask != NULL) + { + printf ("src color: %.2f %.2f %.2f %.2f\n" + "msk color: %.2f %.2f %.2f %.2f\n" + "dst color: %.2f %.2f %.2f %.2f\n", + src->color->r, src->color->g, + src->color->b, src->color->a, + mask->color->r, mask->color->g, + mask->color->b, mask->color->a, + dst->color->r, dst->color->g, + dst->color->b, dst->color->a); + printf ("src: %s, ", describe_image (src, buf)); + printf ("mask: %s, ", describe_image (mask, buf)); + printf ("dst: %s\n\n", describe_image (dst, buf)); + } + else + { + printf ("src color: %.2f %.2f %.2f %.2f\n" + "dst color: %.2f %.2f %.2f %.2f\n", + src->color->r, src->color->g, + src->color->b, src->color->a, + dst->color->r, dst->color->g, + dst->color->b, dst->color->a); + printf ("src: %s, ", describe_image (src, buf)); + printf ("dst: %s\n\n", describe_image (dst, buf)); + } + + success = FALSE; + } + + return success; +} + +static void +image_init (image_t *info, + int color, + int format, + int size) +{ + pixman_color_t fill; + + info->color = &colors[color]; + compute_pixman_color (info->color, &fill); + + info->format = &formats[format]; + info->size = sizes[size] & ~FLAGS; + info->repeat = PIXMAN_REPEAT_NONE; + + if (info->size) + { + pixman_rectangle16_t rect; + + info->image = pixman_image_create_bits (info->format->format, + info->size, info->size, + NULL, 0); + + rect.x = rect.y = 0; + rect.width = rect.height = info->size; + pixman_image_fill_rectangles (PIXMAN_OP_SRC, info->image, &fill, + 1, &rect); + + if (size & REPEAT) + { + pixman_image_set_repeat (info->image, PIXMAN_REPEAT_NORMAL); + info->repeat = PIXMAN_REPEAT_NORMAL; + } + } + else + { + info->image = pixman_image_create_solid_fill (&fill); + } +} + +static void +image_fini (image_t *info) +{ + pixman_image_unref (info->image); +} + +static int +random_size (void) +{ + return lcg_rand_n (ARRAY_LENGTH (sizes)); +} + +static int +random_color (void) +{ + return lcg_rand_n (ARRAY_LENGTH (colors)); +} + +static int +random_format (void) +{ + return lcg_rand_n (ARRAY_LENGTH (formats)); +} + +static pixman_bool_t +run_test (uint32_t seed) +{ + image_t src, mask, dst; + const operator_t *op; + int ca; + int ok; + + lcg_srand (seed); + + image_init (&dst, random_color(), random_format(), 1); + image_init (&src, random_color(), random_format(), random_size()); + image_init (&mask, random_color(), random_format(), random_size()); + + op = &(operators [lcg_rand_n (ARRAY_LENGTH (operators))]); + + ca = lcg_rand_n (3); + + switch (ca) + { + case 0: + ok = composite_test (&dst, op, &src, NULL, FALSE); + break; + case 1: + ok = composite_test (&dst, op, &src, &mask, FALSE); + break; + case 2: + ok = composite_test (&dst, op, &src, &mask, + mask.size? TRUE : FALSE); + break; + default: + ok = FALSE; + break; + } + + image_fini (&src); + image_fini (&mask); + image_fini (&dst); + + return ok; +} + +int +main (int argc, char **argv) +{ +#define N_TESTS (8 * 1024 * 1024) + int result = 0; + int i; + + if (argc > 1) + { + char *end; + + i = strtol (argv[1], &end, 0); + + if (end != argv[1]) + { + if (!run_test (i)) + return 1; + else + return 0; + } + else + { + printf ("Usage:\n\n %s \n\n", argv[0]); + return -1; + } + } + +#ifdef USE_OPENMP +# pragma omp parallel for default(none) shared(result) shared(argv) +#endif + for (i = 1; i <= N_TESTS; ++i) + { + if (!result && !run_test (i)) + { + printf ("Test %d failed.\n", i); + + result = i; + } + } + + return result; +} diff --git a/pixman/test/fetch-test.c b/pixman/test/fetch-test.c index 2ca16ddbf..60bc765f6 100644 --- a/pixman/test/fetch-test.c +++ b/pixman/test/fetch-test.c @@ -8,7 +8,7 @@ static pixman_indexed_t mono_palette = { - .rgba = { 0x00000000, 0x00ffffff }, + 0, { 0x00000000, 0x00ffffff }, }; @@ -24,57 +24,53 @@ typedef struct { static testcase_t testcases[] = { { - .format = PIXMAN_a8r8g8b8, - .width = 2, .height = 2, - .stride = 8, - .src = { 0x00112233, 0x44556677, - 0x8899aabb, 0xccddeeff }, - .dst = { 0x00112233, 0x44556677, - 0x8899aabb, 0xccddeeff }, - .indexed = NULL, + PIXMAN_a8r8g8b8, + 2, 2, + 8, + { 0x00112233, 0x44556677, + 0x8899aabb, 0xccddeeff }, + { 0x00112233, 0x44556677, + 0x8899aabb, 0xccddeeff }, + NULL, }, { - .format = PIXMAN_g1, - .width = 8, .height = 2, - .stride = 4, + PIXMAN_g1, + 8, 2, + 4, #ifdef WORDS_BIGENDIAN - .src = { 0xaa000000, 0x55000000 }, #else - .src = { 0x00000055, 0x000000aa }, #endif - .dst = { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff }, - .indexed = &mono_palette, + &mono_palette, }, #if 0 { - .format = PIXMAN_g8, - .width = 4, .height = 2, - .stride = 4, - .src = { 0x01234567, - 0x89abcdef }, - .dst = { 0x00010101, 0x00232323, 0x00454545, 0x00676767, - 0x00898989, 0x00ababab, 0x00cdcdcd, 0x00efefef, }, + PIXMAN_g8, + 4, 2, + 4, + { 0x01234567, + 0x89abcdef }, + { 0x00010101, 0x00232323, 0x00454545, 0x00676767, + 0x00898989, 0x00ababab, 0x00cdcdcd, 0x00efefef, }, }, #endif /* FIXME: make this work on big endian */ { - .format = PIXMAN_yv12, - .width = 8, .height = 2, - .stride = 8, + PIXMAN_yv12, + 8, 2, + 8, #ifdef WORDS_BIGENDIAN - .src = { 0x00ff00ff, 0x00ff00ff, 0xff00ff00, 0xff00ff00, @@ -82,7 +78,6 @@ static testcase_t testcases[] = 0x800080ff }, #else - .src = { 0xff00ff00, 0xff00ff00, 0x00ff00ff, 0x00ff00ff, @@ -90,7 +85,6 @@ static testcase_t testcases[] = 0xff800080 }, #endif - .dst = { 0xff000000, 0xffffffff, 0xffb80000, 0xffffe113, 0xff000000, 0xffffffff, 0xff0023ee, 0xff4affff, @@ -116,6 +110,7 @@ reader (const void *src, int size) return *(uint32_t *)src; default: assert(0); + return 0; /* silence MSVC */ } } diff --git a/pixman/test/scaling-helpers-test.c b/pixman/test/scaling-helpers-test.c new file mode 100644 index 000000000..c1861389b --- /dev/null +++ b/pixman/test/scaling-helpers-test.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include "utils.h" +#include "pixman-fast-path.h" + +/* A trivial reference implementation for + * 'bilinear_pad_repeat_get_scanline_bounds' + */ +static void +bilinear_pad_repeat_get_scanline_bounds_ref (int32_t source_image_width, + pixman_fixed_t vx_, + pixman_fixed_t unit_x, + int32_t * left_pad, + int32_t * left_tz, + int32_t * width, + int32_t * right_tz, + int32_t * right_pad) +{ + int w = *width; + *left_pad = 0; + *left_tz = 0; + *width = 0; + *right_tz = 0; + *right_pad = 0; + int64_t vx = vx_; + while (--w >= 0) + { + if (vx < 0) + { + if (vx + pixman_fixed_1 < 0) + *left_pad += 1; + else + *left_tz += 1; + } + else if (vx + pixman_fixed_1 >= pixman_int_to_fixed (source_image_width)) + { + if (vx >= pixman_int_to_fixed (source_image_width)) + *right_pad += 1; + else + *right_tz += 1; + } + else + { + *width += 1; + } + vx += unit_x; + } +} + +int +main (void) +{ + int i; + for (i = 0; i < 10000; i++) + { + int32_t left_pad1, left_tz1, width1, right_tz1, right_pad1; + int32_t left_pad2, left_tz2, width2, right_tz2, right_pad2; + pixman_fixed_t vx = lcg_rand_N(10000 << 16) - (3000 << 16); + int32_t width = lcg_rand_N(10000); + int32_t source_image_width = lcg_rand_N(10000) + 1; + pixman_fixed_t unit_x = lcg_rand_N(10 << 16) + 1; + width1 = width2 = width; + + bilinear_pad_repeat_get_scanline_bounds_ref (source_image_width, + vx, + unit_x, + &left_pad1, + &left_tz1, + &width1, + &right_tz1, + &right_pad1); + + bilinear_pad_repeat_get_scanline_bounds (source_image_width, + vx, + unit_x, + &left_pad2, + &left_tz2, + &width2, + &right_tz2, + &right_pad2); + + assert (left_pad1 == left_pad2); + assert (left_tz1 == left_tz2); + assert (width1 == width2); + assert (right_tz1 == right_tz2); + assert (right_pad1 == right_pad2); + } + + return 0; +} diff --git a/pixman/test/stress-test.c b/pixman/test/stress-test.c index 0a89a52e9..166dc6d2c 100644 --- a/pixman/test/stress-test.c +++ b/pixman/test/stress-test.c @@ -1,855 +1,855 @@ -#include "utils.h" - -#if 0 -#define fence_malloc malloc -#define fence_free free -#define make_random_bytes malloc -#endif - -static const pixman_format_code_t image_formats[] = -{ - PIXMAN_a8r8g8b8, - PIXMAN_x8r8g8b8, - PIXMAN_r5g6b5, - PIXMAN_r3g3b2, - PIXMAN_a8, - PIXMAN_a8b8g8r8, - PIXMAN_x8b8g8r8, - PIXMAN_b8g8r8a8, - PIXMAN_b8g8r8x8, - PIXMAN_x14r6g6b6, - PIXMAN_r8g8b8, - PIXMAN_b8g8r8, - PIXMAN_r5g6b5, - PIXMAN_b5g6r5, - PIXMAN_x2r10g10b10, - PIXMAN_a2r10g10b10, - PIXMAN_x2b10g10r10, - PIXMAN_a2b10g10r10, - PIXMAN_a1r5g5b5, - PIXMAN_x1r5g5b5, - PIXMAN_a1b5g5r5, - PIXMAN_x1b5g5r5, - PIXMAN_a4r4g4b4, - PIXMAN_x4r4g4b4, - PIXMAN_a4b4g4r4, - PIXMAN_x4b4g4r4, - PIXMAN_a8, - PIXMAN_r3g3b2, - PIXMAN_b2g3r3, - PIXMAN_a2r2g2b2, - PIXMAN_a2b2g2r2, - PIXMAN_c8, - PIXMAN_g8, - PIXMAN_x4c4, - PIXMAN_x4g4, - PIXMAN_c4, - PIXMAN_g4, - PIXMAN_g1, - PIXMAN_x4a4, - PIXMAN_a4, - PIXMAN_r1g2b1, - PIXMAN_b1g2r1, - PIXMAN_a1r1g1b1, - PIXMAN_a1b1g1r1, - PIXMAN_a1 -}; - -static pixman_filter_t filters[] = -{ - PIXMAN_FILTER_NEAREST, - PIXMAN_FILTER_BILINEAR, - PIXMAN_FILTER_FAST, - PIXMAN_FILTER_GOOD, - PIXMAN_FILTER_BEST, - PIXMAN_FILTER_CONVOLUTION -}; - -static int -get_size (void) -{ - switch (lcg_rand_n (28)) - { - case 0: - return 1; - - case 1: - return 2; - - default: - case 2: - return lcg_rand_n (200); - - case 4: - return lcg_rand_n (2000) + 1000; - - case 5: - return 65535; - - case 6: - return 65536; - - case 7: - return lcg_rand_N (64000) + 63000; - } -} - -static void -destroy (pixman_image_t *image, void *data) -{ - if (image->type == BITS && image->bits.free_me != image->bits.bits) - { - uint32_t *bits; - - if (image->bits.bits != (void *)0x01) - { - bits = image->bits.bits; - - if (image->bits.rowstride < 0) - bits -= (- image->bits.rowstride * (image->bits.height - 1)); - - fence_free (bits); - } - } - - free (data); -} - -static uint32_t -real_reader (const void *src, int size) -{ - switch (size) - { - case 1: - return *(uint8_t *)src; - case 2: - return *(uint16_t *)src; - case 4: - return *(uint32_t *)src; - default: - assert (0); - break; - } -} - -static void -real_writer (void *src, uint32_t value, int size) -{ - switch (size) - { - case 1: - *(uint8_t *)src = value; - break; - - case 2: - *(uint16_t *)src = value; - break; - - case 4: - *(uint32_t *)src = value; - break; - - default: - assert (0); - break; - } -} - -static uint32_t -fake_reader (const void *src, int size) -{ - uint32_t r = lcg_rand_u32 (); - - assert (size == 1 || size == 2 || size == 4); - return r & ((1 << (size * 8)) - 1); -} - -static void -fake_writer (void *src, uint32_t value, int size) -{ - assert (size == 1 || size == 2 || size == 4); -} - -static int32_t -log_rand (void) -{ - uint32_t mask; - - mask = (1 << lcg_rand_n (31)) - 1; - - return (lcg_rand () & mask) - (mask >> 1); -} - -static pixman_image_t * -create_random_bits_image (void) -{ - pixman_format_code_t format; - pixman_indexed_t *indexed; - pixman_image_t *image; - int width, height, stride; - uint32_t *bits; - pixman_read_memory_func_t read_func = NULL; - pixman_write_memory_func_t write_func = NULL; - pixman_filter_t filter; - pixman_fixed_t *coefficients = NULL; - int n_coefficients = 0; - - /* format */ - format = image_formats[lcg_rand_n (ARRAY_LENGTH (image_formats))]; - - indexed = NULL; - if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR) - { - indexed = malloc (sizeof (pixman_indexed_t)); - - initialize_palette (indexed, PIXMAN_FORMAT_BPP (format), TRUE); - } - else if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY) - { - indexed = malloc (sizeof (pixman_indexed_t)); - - initialize_palette (indexed, PIXMAN_FORMAT_BPP (format), FALSE); - } - else - { - indexed = NULL; - } - - /* size */ - width = get_size (); - height = get_size (); - - if ((uint64_t)width * height > 200000) - { - if (lcg_rand_n(2) == 0) - height = 200000 / width; - else - width = 200000 / height; - } - - if (height == 0) - height = 1; - if (width == 0) - width = 1; - - /* bits */ - switch (lcg_rand_n (7)) - { - default: - case 0: - stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17); - stride = (stride + 3) & (~3); - bits = (uint32_t *)make_random_bytes (height * stride); - break; - - case 1: - stride = 0; - bits = NULL; - break; - - case 2: /* Zero-filled */ - stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17); - stride = (stride + 3) & (~3); - bits = fence_malloc (height * stride); - if (!bits) - return NULL; - memset (bits, 0, height * stride); - break; - - case 3: /* Filled with 0xFF */ - stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17); - stride = (stride + 3) & (~3); - bits = fence_malloc (height * stride); - if (!bits) - return NULL; - memset (bits, 0xff, height * stride); - break; - - case 4: /* bits is a bad pointer, has read/write functions */ - stride = 232; - bits = (void *)0x01; - read_func = fake_reader; - write_func = fake_writer; - break; - - case 5: /* bits is a real pointer, has read/write functions */ - stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17); - stride = (stride + 3) & (~3); - bits = fence_malloc (height * stride); - if (!bits) - return NULL; - memset (bits, 0xff, height * stride); - read_func = real_reader; - write_func = real_writer; - break; - - case 6: /* bits is a real pointer, stride is negative */ - stride = (width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17)); - stride = (stride + 3) & (~3); - bits = (uint32_t *)make_random_bytes (height * stride); - if (!bits) - return NULL; - bits += ((height - 1) * stride) / 4; - stride = - stride; - break; - } - - /* Filter */ - filter = filters[lcg_rand_n (ARRAY_LENGTH (filters))]; - if (filter == PIXMAN_FILTER_CONVOLUTION) - { - int width = lcg_rand_n (17); - int height = lcg_rand_n (19); - - n_coefficients = width * height + 2; - coefficients = malloc (n_coefficients * sizeof (pixman_fixed_t)); - - if (coefficients) - { - int i; - - for (i = 0; i < width * height; ++i) - coefficients[i + 2] = lcg_rand_u32(); - - coefficients[0] = width << 16; - coefficients[1] = height << 16; - } - else - { - filter = PIXMAN_FILTER_BEST; - } - } - - /* Finally create the image */ - image = pixman_image_create_bits (format, width, height, bits, stride); - if (!image) - return NULL; - - pixman_image_set_indexed (image, indexed); - pixman_image_set_destroy_function (image, destroy, indexed); - pixman_image_set_accessors (image, read_func, write_func); - pixman_image_set_filter (image, filter, coefficients, n_coefficients); - - return image; -} - -static pixman_repeat_t repeats[] = -{ - PIXMAN_REPEAT_NONE, - PIXMAN_REPEAT_NORMAL, - PIXMAN_REPEAT_REFLECT, - PIXMAN_REPEAT_PAD -}; - -static uint32_t -absolute (int32_t i) -{ - return i < 0? -i : i; -} - -static void -set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map) -{ - pixman_repeat_t repeat; - - /* Set properties that are generic to all images */ - - /* Repeat */ - repeat = repeats[lcg_rand_n (ARRAY_LENGTH (repeats))]; - pixman_image_set_repeat (image, repeat); - - /* Alpha map */ - if (allow_alpha_map && lcg_rand_n (3) == 0) - { - pixman_image_t *alpha_map; - int16_t x, y; - - alpha_map = create_random_bits_image (); - - if (alpha_map) - { - set_general_properties (alpha_map, FALSE); - - x = lcg_rand_N (100000) - 65536; - y = lcg_rand_N (100000) - 65536; - - pixman_image_set_alpha_map (image, alpha_map, x, y); - - pixman_image_unref (alpha_map); - } - } - - /* Component alpha */ - pixman_image_set_component_alpha (image, lcg_rand_n (3) == 0); - - /* Clip region */ - if (lcg_rand_n (8) != 0) - { - pixman_region32_t region; - int i, n_rects; - - pixman_region32_init (®ion); - - switch (lcg_rand_n (10)) - { - case 0: - n_rects = 0; - break; - - case 1: case 2: case 3: - n_rects = 1; - break; - - case 4: case 5: - n_rects = 2; - break; - - case 6: case 7: - n_rects = 3; - - default: - n_rects = lcg_rand_n (100); - break; - } - - for (i = 0; i < n_rects; ++i) - { - uint32_t width, height; - int x, y; - - x = log_rand(); - y = log_rand(); - width = absolute (log_rand ()) + 1; - height = absolute (log_rand ()) + 1; - - pixman_region32_union_rect ( - ®ion, ®ion, x, y, width, height); - } - - pixman_image_set_clip_region32 (image, ®ion); - - pixman_region32_fini (®ion); - } - - /* Whether source clipping is enabled */ - pixman_image_set_source_clipping (image, !!lcg_rand_n (2)); - - /* Client clip */ - pixman_image_set_has_client_clip (image, !!lcg_rand_n (2)); - - /* Transform */ - if (lcg_rand_n (5) < 2) - { - pixman_transform_t xform; - int i, j, k; - uint32_t tx, ty, sx, sy; - uint32_t c, s; - - memset (&xform, 0, sizeof xform); - xform.matrix[0][0] = pixman_fixed_1; - xform.matrix[1][1] = pixman_fixed_1; - xform.matrix[2][2] = pixman_fixed_1; - - for (k = 0; k < 3; ++k) - { - switch (lcg_rand_n (4)) - { - case 0: - /* rotation */ - c = lcg_rand_N (2 * 65536) - 65536; - s = lcg_rand_N (2 * 65536) - 65536; - pixman_transform_rotate (&xform, NULL, c, s); - break; - - case 1: - /* translation */ - tx = lcg_rand_u32(); - ty = lcg_rand_u32(); - pixman_transform_translate (&xform, NULL, tx, ty); - break; - - case 2: - /* scale */ - sx = lcg_rand_u32(); - sy = lcg_rand_u32(); - pixman_transform_scale (&xform, NULL, sx, sy); - break; - - case 3: - if (lcg_rand_n (16) == 0) - { - /* random */ - for (i = 0; i < 3; ++i) - for (j = 0; j < 3; ++j) - xform.matrix[i][j] = lcg_rand_u32(); - break; - } - else if (lcg_rand_n (16) == 0) - { - /* zero */ - memset (&xform, 0, sizeof xform); - } - break; - } - } - - pixman_image_set_transform (image, &xform); - } -} - -static pixman_color_t -random_color (void) -{ - pixman_color_t color = - { - lcg_rand() & 0xffff, - lcg_rand() & 0xffff, - lcg_rand() & 0xffff, - lcg_rand() & 0xffff, - }; - - return color; -} - - -static pixman_image_t * -create_random_solid_image (void) -{ - pixman_color_t color = random_color(); - pixman_image_t *image = pixman_image_create_solid_fill (&color); - - return image; -} - -static pixman_gradient_stop_t * -create_random_stops (int *n_stops) -{ - pixman_fixed_t step; - pixman_fixed_t s; - int i; - pixman_gradient_stop_t *stops; - - *n_stops = lcg_rand_n (50) + 1; - - step = pixman_fixed_1 / *n_stops; - - stops = malloc (*n_stops * sizeof (pixman_gradient_stop_t)); - - s = 0; - for (i = 0; i < (*n_stops) - 1; ++i) - { - stops[i].x = s; - stops[i].color = random_color(); - - s += step; - } - - stops[*n_stops - 1].x = pixman_fixed_1; - stops[*n_stops - 1].color = random_color(); - - return stops; -} - -static pixman_point_fixed_t -create_random_point (void) -{ - pixman_point_fixed_t p; - - p.x = log_rand (); - p.y = log_rand (); - - return p; -} - -static pixman_image_t * -create_random_linear_image (void) -{ - int n_stops; - pixman_gradient_stop_t *stops; - pixman_point_fixed_t p1, p2; - pixman_image_t *result; - - stops = create_random_stops (&n_stops); - if (!stops) - return NULL; - - p1 = create_random_point (); - p2 = create_random_point (); - - result = pixman_image_create_linear_gradient (&p1, &p2, stops, n_stops); - - free (stops); - - return result; -} - -static pixman_image_t * -create_random_radial_image (void) -{ - int n_stops; - pixman_gradient_stop_t *stops; - pixman_point_fixed_t inner_c, outer_c; - pixman_fixed_t inner_r, outer_r; - pixman_image_t *result; - - inner_c = create_random_point(); - outer_c = create_random_point(); - inner_r = lcg_rand(); - outer_r = lcg_rand(); - - stops = create_random_stops (&n_stops); - - if (!stops) - return NULL; - - result = pixman_image_create_radial_gradient ( - &inner_c, &outer_c, inner_r, outer_r, stops, n_stops); - - free (stops); - - return result; -} - -static pixman_image_t * -create_random_conical_image (void) -{ - pixman_gradient_stop_t *stops; - int n_stops; - pixman_point_fixed_t c; - pixman_fixed_t angle; - pixman_image_t *result; - - c = create_random_point(); - angle = lcg_rand(); - - stops = create_random_stops (&n_stops); - - if (!stops) - return NULL; - - result = pixman_image_create_conical_gradient (&c, angle, stops, n_stops); - - free (stops); - - return result; -} - -static pixman_image_t * -create_random_image (void) -{ - pixman_image_t *result; - - switch (lcg_rand_n (5)) - { - default: - case 0: - result = create_random_bits_image (); - break; - - case 1: - result = create_random_solid_image (); - break; - - case 2: - result = create_random_linear_image (); - break; - - case 3: - result = create_random_radial_image (); - break; - - case 4: - result = create_random_conical_image (); - break; - } - - if (result) - set_general_properties (result, TRUE); - - return result; -} - -static const pixman_op_t op_list[] = -{ - PIXMAN_OP_SRC, - PIXMAN_OP_OVER, - PIXMAN_OP_ADD, - PIXMAN_OP_CLEAR, - PIXMAN_OP_SRC, - PIXMAN_OP_DST, - PIXMAN_OP_OVER, - PIXMAN_OP_OVER_REVERSE, - PIXMAN_OP_IN, - PIXMAN_OP_IN_REVERSE, - PIXMAN_OP_OUT, - PIXMAN_OP_OUT_REVERSE, - PIXMAN_OP_ATOP, - PIXMAN_OP_ATOP_REVERSE, - PIXMAN_OP_XOR, - PIXMAN_OP_ADD, - PIXMAN_OP_SATURATE, - PIXMAN_OP_DISJOINT_CLEAR, - PIXMAN_OP_DISJOINT_SRC, - PIXMAN_OP_DISJOINT_DST, - PIXMAN_OP_DISJOINT_OVER, - PIXMAN_OP_DISJOINT_OVER_REVERSE, - PIXMAN_OP_DISJOINT_IN, - PIXMAN_OP_DISJOINT_IN_REVERSE, - PIXMAN_OP_DISJOINT_OUT, - PIXMAN_OP_DISJOINT_OUT_REVERSE, - PIXMAN_OP_DISJOINT_ATOP, - PIXMAN_OP_DISJOINT_ATOP_REVERSE, - PIXMAN_OP_DISJOINT_XOR, - PIXMAN_OP_CONJOINT_CLEAR, - PIXMAN_OP_CONJOINT_SRC, - PIXMAN_OP_CONJOINT_DST, - PIXMAN_OP_CONJOINT_OVER, - PIXMAN_OP_CONJOINT_OVER_REVERSE, - PIXMAN_OP_CONJOINT_IN, - PIXMAN_OP_CONJOINT_IN_REVERSE, - PIXMAN_OP_CONJOINT_OUT, - PIXMAN_OP_CONJOINT_OUT_REVERSE, - PIXMAN_OP_CONJOINT_ATOP, - PIXMAN_OP_CONJOINT_ATOP_REVERSE, - PIXMAN_OP_CONJOINT_XOR, - PIXMAN_OP_MULTIPLY, - PIXMAN_OP_SCREEN, - PIXMAN_OP_OVERLAY, - PIXMAN_OP_DARKEN, - PIXMAN_OP_LIGHTEN, - PIXMAN_OP_COLOR_DODGE, - PIXMAN_OP_COLOR_BURN, - PIXMAN_OP_HARD_LIGHT, - PIXMAN_OP_DIFFERENCE, - PIXMAN_OP_EXCLUSION, - PIXMAN_OP_SOFT_LIGHT, - PIXMAN_OP_HSL_HUE, - PIXMAN_OP_HSL_SATURATION, - PIXMAN_OP_HSL_COLOR, - PIXMAN_OP_HSL_LUMINOSITY, -}; - -static void -run_test (uint32_t seed) -{ - pixman_image_t *source, *mask, *dest; - pixman_op_t op; - - lcg_srand (seed); - - source = create_random_image (); - mask = create_random_image (); - dest = create_random_bits_image (); - - if (source && mask && dest) - { - set_general_properties (dest, TRUE); - - op = op_list [lcg_rand_n (ARRAY_LENGTH (op_list))]; - - pixman_image_composite32 (op, - source, mask, dest, - log_rand(), log_rand(), - log_rand(), log_rand(), - log_rand(), log_rand(), - absolute (log_rand()), - absolute (log_rand())); - } - if (source) - pixman_image_unref (source); - if (mask) - pixman_image_unref (mask); - if (dest) - pixman_image_unref (dest); -} - -static pixman_bool_t -get_int (char *s, uint32_t *i) -{ - char *end; - int p; - - p = strtol (s, &end, 0); - - if (end != s && *end == 0) - { - *i = p; - return TRUE; - } - - return FALSE; -} - -int -main (int argc, char **argv) -{ - int verbose = FALSE; - uint32_t seed = 1; - uint32_t n_tests = 0xffffffff; - uint32_t mod = 0; - uint32_t i; - - pixman_disable_out_of_bounds_workaround (); - - enable_fp_exceptions(); - - if (getenv ("VERBOSE") != NULL) - verbose = TRUE; - - for (i = 1; i < argc; ++i) - { - if (strcmp (argv[i], "-v") == 0) - { - verbose = TRUE; - - if (i + 1 < argc) - { - get_int (argv[i + 1], &mod); - i++; - } - } - else if (strcmp (argv[i], "-s") == 0 && i + 1 < argc) - { - get_int (argv[i + 1], &seed); - i++; - } - else if (strcmp (argv[i], "-n") == 0 && i + 1 < argc) - { - get_int (argv[i + 1], &n_tests); - i++; - } - else - { - if (strcmp (argv[i], "-h") != 0) - printf ("Unknown option '%s'\n\n", argv[i]); - - printf ("Options:\n\n" - "-n Number of tests to run\n" - "-s Seed of first test\n" - "-v Print out seeds\n" - "-v Print out every n'th seed\n\n"); - - exit (-1); - } - } - - if (n_tests == 0xffffffff) - n_tests = 8000; - - /* FIXME: seed 2005763 fails in set_lum() with divide by zero */ -#ifdef USE_OPENMP -# pragma omp parallel for default(none) shared(verbose, n_tests, mod, seed) -#endif - for (i = seed; i < seed + n_tests; ++i) - { - if (verbose) - { - if (mod == 0 || (i % mod) == 0) - printf ("Seed %d\n", i); - } - - run_test (i); - } - - return 0; -} +#include "utils.h" + +#if 0 +#define fence_malloc malloc +#define fence_free free +#define make_random_bytes malloc +#endif + +static const pixman_format_code_t image_formats[] = +{ + PIXMAN_a8r8g8b8, + PIXMAN_x8r8g8b8, + PIXMAN_r5g6b5, + PIXMAN_r3g3b2, + PIXMAN_a8, + PIXMAN_a8b8g8r8, + PIXMAN_x8b8g8r8, + PIXMAN_b8g8r8a8, + PIXMAN_b8g8r8x8, + PIXMAN_x14r6g6b6, + PIXMAN_r8g8b8, + PIXMAN_b8g8r8, + PIXMAN_r5g6b5, + PIXMAN_b5g6r5, + PIXMAN_x2r10g10b10, + PIXMAN_a2r10g10b10, + PIXMAN_x2b10g10r10, + PIXMAN_a2b10g10r10, + PIXMAN_a1r5g5b5, + PIXMAN_x1r5g5b5, + PIXMAN_a1b5g5r5, + PIXMAN_x1b5g5r5, + PIXMAN_a4r4g4b4, + PIXMAN_x4r4g4b4, + PIXMAN_a4b4g4r4, + PIXMAN_x4b4g4r4, + PIXMAN_a8, + PIXMAN_r3g3b2, + PIXMAN_b2g3r3, + PIXMAN_a2r2g2b2, + PIXMAN_a2b2g2r2, + PIXMAN_c8, + PIXMAN_g8, + PIXMAN_x4c4, + PIXMAN_x4g4, + PIXMAN_c4, + PIXMAN_g4, + PIXMAN_g1, + PIXMAN_x4a4, + PIXMAN_a4, + PIXMAN_r1g2b1, + PIXMAN_b1g2r1, + PIXMAN_a1r1g1b1, + PIXMAN_a1b1g1r1, + PIXMAN_a1 +}; + +static pixman_filter_t filters[] = +{ + PIXMAN_FILTER_NEAREST, + PIXMAN_FILTER_BILINEAR, + PIXMAN_FILTER_FAST, + PIXMAN_FILTER_GOOD, + PIXMAN_FILTER_BEST, + PIXMAN_FILTER_CONVOLUTION +}; + +static int +get_size (void) +{ + switch (lcg_rand_n (28)) + { + case 0: + return 1; + + case 1: + return 2; + + default: + case 2: + return lcg_rand_n (200); + + case 4: + return lcg_rand_n (2000) + 1000; + + case 5: + return 65535; + + case 6: + return 65536; + + case 7: + return lcg_rand_N (64000) + 63000; + } +} + +static void +destroy (pixman_image_t *image, void *data) +{ + if (image->type == BITS && image->bits.free_me != image->bits.bits) + { + uint32_t *bits; + + if (image->bits.bits != (void *)0x01) + { + bits = image->bits.bits; + + if (image->bits.rowstride < 0) + bits -= (- image->bits.rowstride * (image->bits.height - 1)); + + fence_free (bits); + } + } + + free (data); +} + +static uint32_t +real_reader (const void *src, int size) +{ + switch (size) + { + case 1: + return *(uint8_t *)src; + case 2: + return *(uint16_t *)src; + case 4: + return *(uint32_t *)src; + default: + assert (0); + return 0; /* silence MSVC */ + } +} + +static void +real_writer (void *src, uint32_t value, int size) +{ + switch (size) + { + case 1: + *(uint8_t *)src = value; + break; + + case 2: + *(uint16_t *)src = value; + break; + + case 4: + *(uint32_t *)src = value; + break; + + default: + assert (0); + break; + } +} + +static uint32_t +fake_reader (const void *src, int size) +{ + uint32_t r = lcg_rand_u32 (); + + assert (size == 1 || size == 2 || size == 4); + return r & ((1 << (size * 8)) - 1); +} + +static void +fake_writer (void *src, uint32_t value, int size) +{ + assert (size == 1 || size == 2 || size == 4); +} + +static int32_t +log_rand (void) +{ + uint32_t mask; + + mask = (1 << lcg_rand_n (31)) - 1; + + return (lcg_rand () & mask) - (mask >> 1); +} + +static pixman_image_t * +create_random_bits_image (void) +{ + pixman_format_code_t format; + pixman_indexed_t *indexed; + pixman_image_t *image; + int width, height, stride; + uint32_t *bits; + pixman_read_memory_func_t read_func = NULL; + pixman_write_memory_func_t write_func = NULL; + pixman_filter_t filter; + pixman_fixed_t *coefficients = NULL; + int n_coefficients = 0; + + /* format */ + format = image_formats[lcg_rand_n (ARRAY_LENGTH (image_formats))]; + + indexed = NULL; + if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR) + { + indexed = malloc (sizeof (pixman_indexed_t)); + + initialize_palette (indexed, PIXMAN_FORMAT_BPP (format), TRUE); + } + else if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY) + { + indexed = malloc (sizeof (pixman_indexed_t)); + + initialize_palette (indexed, PIXMAN_FORMAT_BPP (format), FALSE); + } + else + { + indexed = NULL; + } + + /* size */ + width = get_size (); + height = get_size (); + + if ((uint64_t)width * height > 200000) + { + if (lcg_rand_n(2) == 0) + height = 200000 / width; + else + width = 200000 / height; + } + + if (height == 0) + height = 1; + if (width == 0) + width = 1; + + /* bits */ + switch (lcg_rand_n (7)) + { + default: + case 0: + stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17); + stride = (stride + 3) & (~3); + bits = (uint32_t *)make_random_bytes (height * stride); + break; + + case 1: + stride = 0; + bits = NULL; + break; + + case 2: /* Zero-filled */ + stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17); + stride = (stride + 3) & (~3); + bits = fence_malloc (height * stride); + if (!bits) + return NULL; + memset (bits, 0, height * stride); + break; + + case 3: /* Filled with 0xFF */ + stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17); + stride = (stride + 3) & (~3); + bits = fence_malloc (height * stride); + if (!bits) + return NULL; + memset (bits, 0xff, height * stride); + break; + + case 4: /* bits is a bad pointer, has read/write functions */ + stride = 232; + bits = (void *)0x01; + read_func = fake_reader; + write_func = fake_writer; + break; + + case 5: /* bits is a real pointer, has read/write functions */ + stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17); + stride = (stride + 3) & (~3); + bits = fence_malloc (height * stride); + if (!bits) + return NULL; + memset (bits, 0xff, height * stride); + read_func = real_reader; + write_func = real_writer; + break; + + case 6: /* bits is a real pointer, stride is negative */ + stride = (width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17)); + stride = (stride + 3) & (~3); + bits = (uint32_t *)make_random_bytes (height * stride); + if (!bits) + return NULL; + bits += ((height - 1) * stride) / 4; + stride = - stride; + break; + } + + /* Filter */ + filter = filters[lcg_rand_n (ARRAY_LENGTH (filters))]; + if (filter == PIXMAN_FILTER_CONVOLUTION) + { + int width = lcg_rand_n (17); + int height = lcg_rand_n (19); + + n_coefficients = width * height + 2; + coefficients = malloc (n_coefficients * sizeof (pixman_fixed_t)); + + if (coefficients) + { + int i; + + for (i = 0; i < width * height; ++i) + coefficients[i + 2] = lcg_rand_u32(); + + coefficients[0] = width << 16; + coefficients[1] = height << 16; + } + else + { + filter = PIXMAN_FILTER_BEST; + } + } + + /* Finally create the image */ + image = pixman_image_create_bits (format, width, height, bits, stride); + if (!image) + return NULL; + + pixman_image_set_indexed (image, indexed); + pixman_image_set_destroy_function (image, destroy, indexed); + pixman_image_set_accessors (image, read_func, write_func); + pixman_image_set_filter (image, filter, coefficients, n_coefficients); + + return image; +} + +static pixman_repeat_t repeats[] = +{ + PIXMAN_REPEAT_NONE, + PIXMAN_REPEAT_NORMAL, + PIXMAN_REPEAT_REFLECT, + PIXMAN_REPEAT_PAD +}; + +static uint32_t +absolute (int32_t i) +{ + return i < 0? -i : i; +} + +static void +set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map) +{ + pixman_repeat_t repeat; + + /* Set properties that are generic to all images */ + + /* Repeat */ + repeat = repeats[lcg_rand_n (ARRAY_LENGTH (repeats))]; + pixman_image_set_repeat (image, repeat); + + /* Alpha map */ + if (allow_alpha_map && lcg_rand_n (3) == 0) + { + pixman_image_t *alpha_map; + int16_t x, y; + + alpha_map = create_random_bits_image (); + + if (alpha_map) + { + set_general_properties (alpha_map, FALSE); + + x = lcg_rand_N (100000) - 65536; + y = lcg_rand_N (100000) - 65536; + + pixman_image_set_alpha_map (image, alpha_map, x, y); + + pixman_image_unref (alpha_map); + } + } + + /* Component alpha */ + pixman_image_set_component_alpha (image, lcg_rand_n (3) == 0); + + /* Clip region */ + if (lcg_rand_n (8) != 0) + { + pixman_region32_t region; + int i, n_rects; + + pixman_region32_init (®ion); + + switch (lcg_rand_n (10)) + { + case 0: + n_rects = 0; + break; + + case 1: case 2: case 3: + n_rects = 1; + break; + + case 4: case 5: + n_rects = 2; + break; + + case 6: case 7: + n_rects = 3; + + default: + n_rects = lcg_rand_n (100); + break; + } + + for (i = 0; i < n_rects; ++i) + { + uint32_t width, height; + int x, y; + + x = log_rand(); + y = log_rand(); + width = absolute (log_rand ()) + 1; + height = absolute (log_rand ()) + 1; + + pixman_region32_union_rect ( + ®ion, ®ion, x, y, width, height); + } + + pixman_image_set_clip_region32 (image, ®ion); + + pixman_region32_fini (®ion); + } + + /* Whether source clipping is enabled */ + pixman_image_set_source_clipping (image, !!lcg_rand_n (2)); + + /* Client clip */ + pixman_image_set_has_client_clip (image, !!lcg_rand_n (2)); + + /* Transform */ + if (lcg_rand_n (5) < 2) + { + pixman_transform_t xform; + int i, j, k; + uint32_t tx, ty, sx, sy; + uint32_t c, s; + + memset (&xform, 0, sizeof xform); + xform.matrix[0][0] = pixman_fixed_1; + xform.matrix[1][1] = pixman_fixed_1; + xform.matrix[2][2] = pixman_fixed_1; + + for (k = 0; k < 3; ++k) + { + switch (lcg_rand_n (4)) + { + case 0: + /* rotation */ + c = lcg_rand_N (2 * 65536) - 65536; + s = lcg_rand_N (2 * 65536) - 65536; + pixman_transform_rotate (&xform, NULL, c, s); + break; + + case 1: + /* translation */ + tx = lcg_rand_u32(); + ty = lcg_rand_u32(); + pixman_transform_translate (&xform, NULL, tx, ty); + break; + + case 2: + /* scale */ + sx = lcg_rand_u32(); + sy = lcg_rand_u32(); + pixman_transform_scale (&xform, NULL, sx, sy); + break; + + case 3: + if (lcg_rand_n (16) == 0) + { + /* random */ + for (i = 0; i < 3; ++i) + for (j = 0; j < 3; ++j) + xform.matrix[i][j] = lcg_rand_u32(); + break; + } + else if (lcg_rand_n (16) == 0) + { + /* zero */ + memset (&xform, 0, sizeof xform); + } + break; + } + } + + pixman_image_set_transform (image, &xform); + } +} + +static pixman_color_t +random_color (void) +{ + pixman_color_t color = + { + lcg_rand() & 0xffff, + lcg_rand() & 0xffff, + lcg_rand() & 0xffff, + lcg_rand() & 0xffff, + }; + + return color; +} + + +static pixman_image_t * +create_random_solid_image (void) +{ + pixman_color_t color = random_color(); + pixman_image_t *image = pixman_image_create_solid_fill (&color); + + return image; +} + +static pixman_gradient_stop_t * +create_random_stops (int *n_stops) +{ + pixman_fixed_t step; + pixman_fixed_t s; + int i; + pixman_gradient_stop_t *stops; + + *n_stops = lcg_rand_n (50) + 1; + + step = pixman_fixed_1 / *n_stops; + + stops = malloc (*n_stops * sizeof (pixman_gradient_stop_t)); + + s = 0; + for (i = 0; i < (*n_stops) - 1; ++i) + { + stops[i].x = s; + stops[i].color = random_color(); + + s += step; + } + + stops[*n_stops - 1].x = pixman_fixed_1; + stops[*n_stops - 1].color = random_color(); + + return stops; +} + +static pixman_point_fixed_t +create_random_point (void) +{ + pixman_point_fixed_t p; + + p.x = log_rand (); + p.y = log_rand (); + + return p; +} + +static pixman_image_t * +create_random_linear_image (void) +{ + int n_stops; + pixman_gradient_stop_t *stops; + pixman_point_fixed_t p1, p2; + pixman_image_t *result; + + stops = create_random_stops (&n_stops); + if (!stops) + return NULL; + + p1 = create_random_point (); + p2 = create_random_point (); + + result = pixman_image_create_linear_gradient (&p1, &p2, stops, n_stops); + + free (stops); + + return result; +} + +static pixman_image_t * +create_random_radial_image (void) +{ + int n_stops; + pixman_gradient_stop_t *stops; + pixman_point_fixed_t inner_c, outer_c; + pixman_fixed_t inner_r, outer_r; + pixman_image_t *result; + + inner_c = create_random_point(); + outer_c = create_random_point(); + inner_r = lcg_rand(); + outer_r = lcg_rand(); + + stops = create_random_stops (&n_stops); + + if (!stops) + return NULL; + + result = pixman_image_create_radial_gradient ( + &inner_c, &outer_c, inner_r, outer_r, stops, n_stops); + + free (stops); + + return result; +} + +static pixman_image_t * +create_random_conical_image (void) +{ + pixman_gradient_stop_t *stops; + int n_stops; + pixman_point_fixed_t c; + pixman_fixed_t angle; + pixman_image_t *result; + + c = create_random_point(); + angle = lcg_rand(); + + stops = create_random_stops (&n_stops); + + if (!stops) + return NULL; + + result = pixman_image_create_conical_gradient (&c, angle, stops, n_stops); + + free (stops); + + return result; +} + +static pixman_image_t * +create_random_image (void) +{ + pixman_image_t *result; + + switch (lcg_rand_n (5)) + { + default: + case 0: + result = create_random_bits_image (); + break; + + case 1: + result = create_random_solid_image (); + break; + + case 2: + result = create_random_linear_image (); + break; + + case 3: + result = create_random_radial_image (); + break; + + case 4: + result = create_random_conical_image (); + break; + } + + if (result) + set_general_properties (result, TRUE); + + return result; +} + +static const pixman_op_t op_list[] = +{ + PIXMAN_OP_SRC, + PIXMAN_OP_OVER, + PIXMAN_OP_ADD, + PIXMAN_OP_CLEAR, + PIXMAN_OP_SRC, + PIXMAN_OP_DST, + PIXMAN_OP_OVER, + PIXMAN_OP_OVER_REVERSE, + PIXMAN_OP_IN, + PIXMAN_OP_IN_REVERSE, + PIXMAN_OP_OUT, + PIXMAN_OP_OUT_REVERSE, + PIXMAN_OP_ATOP, + PIXMAN_OP_ATOP_REVERSE, + PIXMAN_OP_XOR, + PIXMAN_OP_ADD, + PIXMAN_OP_SATURATE, + PIXMAN_OP_DISJOINT_CLEAR, + PIXMAN_OP_DISJOINT_SRC, + PIXMAN_OP_DISJOINT_DST, + PIXMAN_OP_DISJOINT_OVER, + PIXMAN_OP_DISJOINT_OVER_REVERSE, + PIXMAN_OP_DISJOINT_IN, + PIXMAN_OP_DISJOINT_IN_REVERSE, + PIXMAN_OP_DISJOINT_OUT, + PIXMAN_OP_DISJOINT_OUT_REVERSE, + PIXMAN_OP_DISJOINT_ATOP, + PIXMAN_OP_DISJOINT_ATOP_REVERSE, + PIXMAN_OP_DISJOINT_XOR, + PIXMAN_OP_CONJOINT_CLEAR, + PIXMAN_OP_CONJOINT_SRC, + PIXMAN_OP_CONJOINT_DST, + PIXMAN_OP_CONJOINT_OVER, + PIXMAN_OP_CONJOINT_OVER_REVERSE, + PIXMAN_OP_CONJOINT_IN, + PIXMAN_OP_CONJOINT_IN_REVERSE, + PIXMAN_OP_CONJOINT_OUT, + PIXMAN_OP_CONJOINT_OUT_REVERSE, + PIXMAN_OP_CONJOINT_ATOP, + PIXMAN_OP_CONJOINT_ATOP_REVERSE, + PIXMAN_OP_CONJOINT_XOR, + PIXMAN_OP_MULTIPLY, + PIXMAN_OP_SCREEN, + PIXMAN_OP_OVERLAY, + PIXMAN_OP_DARKEN, + PIXMAN_OP_LIGHTEN, + PIXMAN_OP_COLOR_DODGE, + PIXMAN_OP_COLOR_BURN, + PIXMAN_OP_HARD_LIGHT, + PIXMAN_OP_DIFFERENCE, + PIXMAN_OP_EXCLUSION, + PIXMAN_OP_SOFT_LIGHT, + PIXMAN_OP_HSL_HUE, + PIXMAN_OP_HSL_SATURATION, + PIXMAN_OP_HSL_COLOR, + PIXMAN_OP_HSL_LUMINOSITY, +}; + +static void +run_test (uint32_t seed) +{ + pixman_image_t *source, *mask, *dest; + pixman_op_t op; + + lcg_srand (seed); + + source = create_random_image (); + mask = create_random_image (); + dest = create_random_bits_image (); + + if (source && mask && dest) + { + set_general_properties (dest, TRUE); + + op = op_list [lcg_rand_n (ARRAY_LENGTH (op_list))]; + + pixman_image_composite32 (op, + source, mask, dest, + log_rand(), log_rand(), + log_rand(), log_rand(), + log_rand(), log_rand(), + absolute (log_rand()), + absolute (log_rand())); + } + if (source) + pixman_image_unref (source); + if (mask) + pixman_image_unref (mask); + if (dest) + pixman_image_unref (dest); +} + +static pixman_bool_t +get_int (char *s, uint32_t *i) +{ + char *end; + int p; + + p = strtol (s, &end, 0); + + if (end != s && *end == 0) + { + *i = p; + return TRUE; + } + + return FALSE; +} + +int +main (int argc, char **argv) +{ + int verbose = FALSE; + uint32_t seed = 1; + uint32_t n_tests = 0xffffffff; + uint32_t mod = 0; + uint32_t i; + + pixman_disable_out_of_bounds_workaround (); + + enable_fp_exceptions(); + + if (getenv ("VERBOSE") != NULL) + verbose = TRUE; + + for (i = 1; i < argc; ++i) + { + if (strcmp (argv[i], "-v") == 0) + { + verbose = TRUE; + + if (i + 1 < argc) + { + get_int (argv[i + 1], &mod); + i++; + } + } + else if (strcmp (argv[i], "-s") == 0 && i + 1 < argc) + { + get_int (argv[i + 1], &seed); + i++; + } + else if (strcmp (argv[i], "-n") == 0 && i + 1 < argc) + { + get_int (argv[i + 1], &n_tests); + i++; + } + else + { + if (strcmp (argv[i], "-h") != 0) + printf ("Unknown option '%s'\n\n", argv[i]); + + printf ("Options:\n\n" + "-n Number of tests to run\n" + "-s Seed of first test\n" + "-v Print out seeds\n" + "-v Print out every n'th seed\n\n"); + + exit (-1); + } + } + + if (n_tests == 0xffffffff) + n_tests = 8000; + + /* FIXME: seed 2005763 fails in set_lum() with divide by zero */ +#ifdef USE_OPENMP +# pragma omp parallel for default(none) shared(verbose, n_tests, mod, seed) +#endif + for (i = seed; i < seed + n_tests; ++i) + { + if (verbose) + { + if (mod == 0 || (i % mod) == 0) + printf ("Seed %d\n", i); + } + + run_test (i); + } + + return 0; +} diff --git a/pixman/test/trap-crasher.c b/pixman/test/trap-crasher.c index 42b82f674..7485e62fd 100644 --- a/pixman/test/trap-crasher.c +++ b/pixman/test/trap-crasher.c @@ -7,21 +7,21 @@ main() pixman_image_t *dst; pixman_trapezoid_t traps[1] = { { - .top = 2147483646, - .bottom = 2147483647, - .left = { - .p1 = { .x = 0, .y = 0 }, - .p2 = { .x = 0, .y = 2147483647 } + 2147483646, + 2147483647, + { + { 0, 0 }, + { 0, 2147483647 } }, - .right = { - .p1 = { .x = 65536, .y = 0 }, - .p2 = { .x = 0, .y = 2147483647 } + { + { 65536, 0 }, + { 0, 2147483647 } } }, }; - + dst = pixman_image_create_bits (PIXMAN_a8, 1, 1, NULL, -1); - + pixman_add_trapezoids (dst, 0, 0, sizeof (traps)/sizeof (traps[0]), traps); return (0); } -- cgit v1.2.3