aboutsummaryrefslogtreecommitdiff
path: root/pixman
diff options
context:
space:
mode:
Diffstat (limited to 'pixman')
-rw-r--r--pixman/pixman/Makefile.win32290
-rw-r--r--pixman/pixman/pixman-arm-neon-asm.S197
-rw-r--r--pixman/pixman/pixman-arm-neon.c45
-rw-r--r--pixman/pixman/pixman-fast-path.h432
-rw-r--r--pixman/pixman/pixman-general.c2
-rw-r--r--pixman/pixman/pixman-image.c1563
-rw-r--r--pixman/pixman/pixman-sse2.c112
-rw-r--r--pixman/test/Makefile.am94
-rw-r--r--pixman/test/Makefile.win3273
-rw-r--r--pixman/test/composite.c1814
-rw-r--r--pixman/test/fetch-test.c53
-rw-r--r--pixman/test/scaling-helpers-test.c93
-rw-r--r--pixman/test/stress-test.c1710
-rw-r--r--pixman/test/trap-crasher.c20
14 files changed, 3723 insertions, 2775 deletions
diff --git a/pixman/pixman/Makefile.win32 b/pixman/pixman/Makefile.win32
index a61f33f94..b5f9397a0 100644
--- a/pixman/pixman/Makefile.win32
+++ b/pixman/pixman/Makefile.win32
@@ -1,144 +1,146 @@
-LIBRARY = pixman-1
-
-CC = cl
-LINK = link
-
-CFG_VAR = $(CFG)
-ifeq ($(CFG_VAR),)
-CFG_VAR=release
-endif
-
-MMX_VAR = $(MMX)
-ifeq ($(MMX_VAR),)
-MMX_VAR=on
-endif
-
-SSE2_VAR = $(SSE2)
-ifeq ($(SSE2_VAR),)
-SSE2_VAR=on
-endif
-
-CFLAGS = -MD -nologo -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -I../pixman/src -I. -DPACKAGE=$(LIBRARY) -DPACKAGE_VERSION="" -DPACKAGE_BUGREPORT=""
-MMX_CFLAGS = -DUSE_MMX -w14710 -w14714
-SSE2_CFLAGS = -DUSE_SSE2
-
-# optimization flags
-ifeq ($(CFG_VAR),debug)
-CFLAGS += -Od -Zi
-else
-CFLAGS += -O2
-endif
-
-SOURCES = \
- pixman-image.c \
- pixman-access.c \
- pixman-access-accessors.c \
- pixman-region16.c \
- pixman-region32.c \
- pixman-combine32.c \
- pixman-combine64.c \
- pixman-utils.c \
- pixman-edge.c \
- pixman-edge-accessors.c \
- pixman-trap.c \
- pixman-timer.c \
- pixman-matrix.c \
- pixman-gradient-walker.c \
- pixman-conical-gradient.c \
- pixman-linear-gradient.c \
- pixman-radial-gradient.c \
- pixman-bits-image.c \
- pixman.c \
- pixman-cpu.c \
- pixman-fast-path.c \
- pixman-implementation.c \
- pixman-solid-fill.c \
- pixman-general.c \
- $(NULL)
-
-# MMX compilation flags
-ifeq ($(MMX_VAR),on)
-CFLAGS += $(MMX_CFLAGS)
-SOURCES += pixman-mmx.c
-endif
-
-# SSE2 compilation flags
-ifeq ($(SSE2_VAR),on)
-CFLAGS += $(SSE2_CFLAGS)
-SOURCES += pixman-sse2.c
-endif
-
-OBJECTS = $(patsubst %.c, $(CFG_VAR)/%.obj, $(SOURCES))
-
-# targets
-all: inform informMMX informSSE2 $(CFG_VAR)/$(LIBRARY).lib
- @exit 0
-clean: inform clean_r
- @exit 0
-pixman: inform informMMX informSSE2 $(CFG_VAR)/$(LIBRARY).lib
- @exit 0
-
-inform:
-ifneq ($(CFG),release)
-ifneq ($(CFG),debug)
-ifneq ($(CFG),)
- @echo "Invalid specified configuration option : "$(CFG)"."
- @echo
- @echo -n "Possible choices for configuration are "
- @echo "'release' and 'debug'"
- @echo ""
- @exit 1
-endif
- @echo "Using default RELEASE configuration... (use CFG=release or CFG=debug)"
-endif
-endif
-
-informMMX:
-ifneq ($(MMX),off)
-ifneq ($(MMX),on)
-ifneq ($(MMX),)
- @echo "Invalid specified MMX option : "$(MMX_VAR)"."
- @echo
- @echo -n "Possible choices for MMX are 'on' or 'off'"
- @echo ""
- @exit 1
-endif
- @echo "Setting MMX flag to default value 'on'... (use MMX=on or MMX=off)"
-endif
-endif
-
-informSSE2:
-ifneq ($(SSE2),off)
-ifneq ($(SSE2),on)
-ifneq ($(SSE2),)
- @echo "Invalid specified SSE option : "$(SSE2)"."
- @echo
- @echo -n "Possible choices for SSE2 are 'on' or 'off'"
- @echo ""
- @exit 1
-endif
- @echo "Setting SSE2 flag to default value 'on'... (use SSE2=on or SSE2=off)"
-endif
-endif
-
-# pixman compilation and linking
-$(CFG_VAR)/%.obj: %.c
- @mkdir -p $(CFG_VAR)
- @$(CC) -c $(CFLAGS) -Fo"$@" $<
-
-$(CFG_VAR)/$(LIBRARY).lib: $(OBJECTS)
- lib -NOLOGO -OUT:$@ $(OBJECTS) || exit 0
-
-pixman-combine32.c: pixman-combine.c.template pixman-combine32.h make-combine.pl
- perl ./make-combine.pl 8 < $< > $@ || ($(RM) $@; exit 1)
-pixman-combine32.h: pixman-combine.h.template make-combine.pl
- perl ./make-combine.pl 8 < $< > $@ || ($(RM) $@; exit 1)
-
-pixman-combine64.c: pixman-combine.c.template pixman-combine64.h make-combine.pl
- perl ./make-combine.pl 16 < $< > $@ || ($(RM) $@; exit 1)
-pixman-combine64.h: pixman-combine.h.template make-combine.pl
- perl ./make-combine.pl 16 < $< > $@ || ($(RM) $@; exit 1)
-
-clean_r:
- @rm -f $(CFG_VAR)/*.obj $(CFG_VAR)/*.lib $(CFG_VAR)/*.pdb $(CFG)/*.ilk || exit 0
- @rm -f $(CFG)/*.obj $(CFG)/*.lib $(CFG)/*.pdb $(CFG)/*.ilk pixman-combine32.c pixman-combine64.c pixman-combine64.c pixman-combine64.h || exit 0
+LIBRARY = pixman-1
+
+CC = cl
+LINK = link
+
+CFG_VAR = $(CFG)
+ifeq ($(CFG_VAR),)
+CFG_VAR=release
+endif
+
+MMX_VAR = $(MMX)
+ifeq ($(MMX_VAR),)
+MMX_VAR=on
+endif
+
+SSE2_VAR = $(SSE2)
+ifeq ($(SSE2_VAR),)
+SSE2_VAR=on
+endif
+
+CFLAGS = -MD -nologo -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -I../pixman/src -I. -DPACKAGE=$(LIBRARY) -DPACKAGE_VERSION="" -DPACKAGE_BUGREPORT=""
+MMX_CFLAGS = -DUSE_MMX -w14710 -w14714
+SSE2_CFLAGS = -DUSE_SSE2
+
+# optimization flags
+ifeq ($(CFG_VAR),debug)
+CFLAGS += -Od -Zi
+else
+CFLAGS += -O2
+endif
+
+SOURCES = \
+ pixman-image.c \
+ pixman-access.c \
+ pixman-access-accessors.c \
+ pixman-region16.c \
+ pixman-region32.c \
+ pixman-combine32.c \
+ pixman-combine64.c \
+ pixman-utils.c \
+ pixman-edge.c \
+ pixman-edge-accessors.c \
+ pixman-trap.c \
+ pixman-timer.c \
+ pixman-matrix.c \
+ pixman-gradient-walker.c \
+ pixman-conical-gradient.c \
+ pixman-linear-gradient.c \
+ pixman-radial-gradient.c \
+ pixman-bits-image.c \
+ pixman.c \
+ pixman-cpu.c \
+ pixman-fast-path.c \
+ pixman-implementation.c \
+ pixman-solid-fill.c \
+ pixman-general.c \
+ $(NULL)
+
+BUILT_SOURCES = pixman-combine32.h pixman-combine32.c pixman-combine64.h pixman-combine64.c
+
+# MMX compilation flags
+ifeq ($(MMX_VAR),on)
+CFLAGS += $(MMX_CFLAGS)
+SOURCES += pixman-mmx.c
+endif
+
+# SSE2 compilation flags
+ifeq ($(SSE2_VAR),on)
+CFLAGS += $(SSE2_CFLAGS)
+SOURCES += pixman-sse2.c
+endif
+
+OBJECTS = $(patsubst %.c, $(CFG_VAR)/%.obj, $(SOURCES))
+
+# targets
+all: inform informMMX informSSE2 $(CFG_VAR)/$(LIBRARY).lib
+ @exit 0
+clean: inform clean_r
+ @exit 0
+pixman: inform informMMX informSSE2 $(CFG_VAR)/$(LIBRARY).lib
+ @exit 0
+
+inform:
+ifneq ($(CFG),release)
+ifneq ($(CFG),debug)
+ifneq ($(CFG),)
+ @echo "Invalid specified configuration option : "$(CFG)"."
+ @echo
+ @echo -n "Possible choices for configuration are "
+ @echo "'release' and 'debug'"
+ @echo ""
+ @exit 1
+endif
+ @echo "Using default RELEASE configuration... (use CFG=release or CFG=debug)"
+endif
+endif
+
+informMMX:
+ifneq ($(MMX),off)
+ifneq ($(MMX),on)
+ifneq ($(MMX),)
+ @echo "Invalid specified MMX option : "$(MMX_VAR)"."
+ @echo
+ @echo -n "Possible choices for MMX are 'on' or 'off'"
+ @echo ""
+ @exit 1
+endif
+ @echo "Setting MMX flag to default value 'on'... (use MMX=on or MMX=off)"
+endif
+endif
+
+informSSE2:
+ifneq ($(SSE2),off)
+ifneq ($(SSE2),on)
+ifneq ($(SSE2),)
+ @echo "Invalid specified SSE option : "$(SSE2)"."
+ @echo
+ @echo -n "Possible choices for SSE2 are 'on' or 'off'"
+ @echo ""
+ @exit 1
+endif
+ @echo "Setting SSE2 flag to default value 'on'... (use SSE2=on or SSE2=off)"
+endif
+endif
+
+# pixman compilation and linking
+$(CFG_VAR)/%.obj: %.c $(BUILT_SOURCES)
+ @mkdir -p $(CFG_VAR)
+ @$(CC) -c $(CFLAGS) -Fo"$@" $<
+
+$(CFG_VAR)/$(LIBRARY).lib: $(OBJECTS)
+ lib -NOLOGO -OUT:$@ $(OBJECTS) || exit 0
+
+pixman-combine32.c: pixman-combine.c.template pixman-combine32.h make-combine.pl
+ perl ./make-combine.pl 8 < $< > $@ || ($(RM) $@; exit 1)
+pixman-combine32.h: pixman-combine.h.template make-combine.pl
+ perl ./make-combine.pl 8 < $< > $@ || ($(RM) $@; exit 1)
+
+pixman-combine64.c: pixman-combine.c.template pixman-combine64.h make-combine.pl
+ perl ./make-combine.pl 16 < $< > $@ || ($(RM) $@; exit 1)
+pixman-combine64.h: pixman-combine.h.template make-combine.pl
+ perl ./make-combine.pl 16 < $< > $@ || ($(RM) $@; exit 1)
+
+clean_r:
+ @rm -f $(CFG_VAR)/*.obj $(CFG_VAR)/*.lib $(CFG_VAR)/*.pdb $(CFG)/*.ilk || exit 0
+ @rm -f $(CFG)/*.obj $(CFG)/*.lib $(CFG)/*.pdb $(CFG)/*.ilk $(BUILT_SOURCES) || exit 0
diff --git a/pixman/pixman/pixman-arm-neon-asm.S b/pixman/pixman/pixman-arm-neon-asm.S
index 47daf457c..c168e10c2 100644
--- a/pixman/pixman/pixman-arm-neon-asm.S
+++ b/pixman/pixman/pixman-arm-neon-asm.S
@@ -2391,3 +2391,200 @@ generate_composite_function_nearest_scanline \
10, /* dst_r_basereg */ \
8, /* src_basereg */ \
15 /* mask_basereg */
+
+/******************************************************************************/
+
+/* Supplementary macro for setting function attributes */
+.macro pixman_asm_function fname
+ .func fname
+ .global fname
+#ifdef __ELF__
+ .hidden fname
+ .type fname, %function
+#endif
+fname:
+.endm
+
+.macro bilinear_interpolate_last_pixel
+ mov TMP1, X, asr #16
+ mov TMP2, X, asr #16
+ add TMP1, TOP, TMP1, asl #2
+ add TMP2, BOTTOM, TMP2, asl #2
+ vld1.32 {d0}, [TMP1]
+ vshr.u16 d30, d24, #8
+ vld1.32 {d1}, [TMP2]
+ vmull.u8 q1, d0, d28
+ vmlal.u8 q1, d1, d29
+ /* 5 cycles bubble */
+ vshll.u16 q0, d2, #8
+ vmlsl.u16 q0, d2, d30
+ vmlal.u16 q0, d3, d30
+ /* 5 cycles bubble */
+ vshrn.u32 d0, q0, #16
+ /* 3 cycles bubble */
+ vmovn.u16 d0, q0
+ /* 1 cycle bubble */
+ vst1.32 {d0[0]}, [OUT, :32]!
+.endm
+
+.macro bilinear_interpolate_two_pixels
+ mov TMP1, X, asr #16
+ mov TMP2, X, asr #16
+ add X, X, UX
+ add TMP1, TOP, TMP1, asl #2
+ add TMP2, BOTTOM, TMP2, asl #2
+ vld1.32 {d0}, [TMP1]
+ vld1.32 {d1}, [TMP2]
+ vmull.u8 q1, d0, d28
+ vmlal.u8 q1, d1, d29
+ mov TMP1, X, asr #16
+ mov TMP2, X, asr #16
+ add X, X, UX
+ add TMP1, TOP, TMP1, asl #2
+ add TMP2, BOTTOM, TMP2, asl #2
+ vld1.32 {d20}, [TMP1]
+ vld1.32 {d21}, [TMP2]
+ vmull.u8 q11, d20, d28
+ vmlal.u8 q11, d21, d29
+ vshr.u16 q15, q12, #8
+ vadd.u16 q12, q12, q13
+ vshll.u16 q0, d2, #8
+ vmlsl.u16 q0, d2, d30
+ vmlal.u16 q0, d3, d30
+ vshll.u16 q10, d22, #8
+ vmlsl.u16 q10, d22, d31
+ vmlal.u16 q10, d23, d31
+ vshrn.u32 d30, q0, #16
+ vshrn.u32 d31, q10, #16
+ vmovn.u16 d0, q15
+ vst1.32 {d0}, [OUT]!
+.endm
+
+.macro bilinear_interpolate_four_pixels
+ mov TMP1, X, asr #16
+ mov TMP2, X, asr #16
+ add X, X, UX
+ add TMP1, TOP, TMP1, asl #2
+ add TMP2, BOTTOM, TMP2, asl #2
+ vld1.32 {d0}, [TMP1]
+ vld1.32 {d1}, [TMP2]
+ vmull.u8 q1, d0, d28
+ vmlal.u8 q1, d1, d29
+ mov TMP1, X, asr #16
+ mov TMP2, X, asr #16
+ add X, X, UX
+ add TMP1, TOP, TMP1, asl #2
+ add TMP2, BOTTOM, TMP2, asl #2
+ vld1.32 {d20}, [TMP1]
+ vld1.32 {d21}, [TMP2]
+ vmull.u8 q11, d20, d28
+ vmlal.u8 q11, d21, d29
+ vshr.u16 q15, q12, #8
+ vadd.u16 q12, q12, q13
+ vshll.u16 q0, d2, #8
+ vmlsl.u16 q0, d2, d30
+ vmlal.u16 q0, d3, d30
+ vshll.u16 q10, d22, #8
+ vmlsl.u16 q10, d22, d31
+ vmlal.u16 q10, d23, d31
+ mov TMP1, X, asr #16
+ mov TMP2, X, asr #16
+ add X, X, UX
+ add TMP1, TOP, TMP1, asl #2
+ add TMP2, BOTTOM, TMP2, asl #2
+ vld1.32 {d4}, [TMP1]
+ vld1.32 {d5}, [TMP2]
+ vmull.u8 q3, d4, d28
+ vmlal.u8 q3, d5, d29
+ mov TMP1, X, asr #16
+ mov TMP2, X, asr #16
+ add X, X, UX
+ add TMP1, TOP, TMP1, asl #2
+ add TMP2, BOTTOM, TMP2, asl #2
+ vld1.32 {d16}, [TMP1]
+ vld1.32 {d17}, [TMP2]
+ vmull.u8 q9, d16, d28
+ vmlal.u8 q9, d17, d29
+ vshr.u16 q15, q12, #8
+ vadd.u16 q12, q12, q13
+ vshll.u16 q2, d6, #8
+ vmlsl.u16 q2, d6, d30
+ vmlal.u16 q2, d7, d30
+ vshll.u16 q8, d18, #8
+ vmlsl.u16 q8, d18, d31
+ vmlal.u16 q8, d19, d31
+ vshrn.u32 d0, q0, #16
+ vshrn.u32 d1, q10, #16
+ vshrn.u32 d4, q2, #16
+ vshrn.u32 d5, q8, #16
+ vmovn.u16 d0, q0
+ vmovn.u16 d1, q2
+ vst1.32 {d0, d1}, [OUT]!
+.endm
+
+
+/*
+ * pixman_scaled_bilinear_scanline_8888_8888_SRC (uint32_t * out,
+ * const uint32_t * top,
+ * const uint32_t * bottom,
+ * int wt,
+ * int wb,
+ * pixman_fixed_t x,
+ * pixman_fixed_t ux,
+ * int width)
+ */
+
+pixman_asm_function pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon
+ OUT .req r0
+ TOP .req r1
+ BOTTOM .req r2
+ WT .req r3
+ WB .req r4
+ X .req r5
+ UX .req r6
+ WIDTH .req ip
+ TMP1 .req r3
+ TMP2 .req r4
+
+ mov ip, sp
+ push {r4, r5, r6, r7}
+ ldmia ip, {WB, X, UX, WIDTH}
+
+ cmp WIDTH, #0
+ ble 3f
+ vdup.u16 q12, X
+ vdup.u16 q13, UX
+ vdup.u8 d28, WT
+ vdup.u8 d29, WB
+ vadd.u16 d25, d25, d26
+ vadd.u16 q13, q13, q13
+
+ subs WIDTH, WIDTH, #4
+ blt 1f
+0:
+ bilinear_interpolate_four_pixels
+ subs WIDTH, WIDTH, #4
+ bge 0b
+1:
+ tst WIDTH, #2
+ beq 2f
+ bilinear_interpolate_two_pixels
+2:
+ tst WIDTH, #1
+ beq 3f
+ bilinear_interpolate_last_pixel
+3:
+ pop {r4, r5, r6, r7}
+ bx lr
+
+ .unreq OUT
+ .unreq TOP
+ .unreq BOTTOM
+ .unreq WT
+ .unreq WB
+ .unreq X
+ .unreq UX
+ .unreq WIDTH
+ .unreq TMP1
+ .unreq TMP2
+.endfunc
diff --git a/pixman/pixman/pixman-arm-neon.c b/pixman/pixman/pixman-arm-neon.c
index 3e0c0d1c2..c7c025418 100644
--- a/pixman/pixman/pixman-arm-neon.c
+++ b/pixman/pixman/pixman-arm-neon.c
@@ -232,6 +232,47 @@ pixman_blt_neon (uint32_t *src_bits,
}
}
+void
+pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon (uint32_t * out,
+ const uint32_t * top,
+ const uint32_t * bottom,
+ int wt,
+ int wb,
+ pixman_fixed_t x,
+ pixman_fixed_t ux,
+ int width);
+
+static force_inline void
+scaled_bilinear_scanline_neon_8888_8888_SRC (uint32_t * dst,
+ const uint32_t * mask,
+ const uint32_t * src_top,
+ const uint32_t * src_bottom,
+ int32_t w,
+ int wt,
+ int wb,
+ pixman_fixed_t vx,
+ pixman_fixed_t unit_x,
+ pixman_fixed_t max_vx,
+ pixman_bool_t zero_src)
+{
+ pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon (dst, src_top,
+ src_bottom, wt, wb,
+ vx, unit_x, w);
+}
+
+FAST_BILINEAR_MAINLOOP_COMMON (neon_8888_8888_cover_SRC,
+ scaled_bilinear_scanline_neon_8888_8888_SRC,
+ uint32_t, uint32_t, uint32_t,
+ COVER, FALSE, FALSE)
+FAST_BILINEAR_MAINLOOP_COMMON (neon_8888_8888_pad_SRC,
+ scaled_bilinear_scanline_neon_8888_8888_SRC,
+ uint32_t, uint32_t, uint32_t,
+ PAD, FALSE, FALSE)
+FAST_BILINEAR_MAINLOOP_COMMON (neon_8888_8888_none_SRC,
+ scaled_bilinear_scanline_neon_8888_8888_SRC,
+ uint32_t, uint32_t, uint32_t,
+ NONE, FALSE, FALSE)
+
static const pixman_fast_path_t arm_neon_fast_paths[] =
{
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, neon_composite_src_0565_0565),
@@ -343,6 +384,10 @@ static const pixman_fast_path_t arm_neon_fast_paths[] =
PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, r5g6b5, r5g6b5, neon_0565_8_0565),
PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, b5g6r5, b5g6r5, neon_0565_8_0565),
+ SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, neon_8888_8888),
+ SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, neon_8888_8888),
+ SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, neon_8888_8888),
+
{ PIXMAN_OP_NONE },
};
diff --git a/pixman/pixman/pixman-fast-path.h b/pixman/pixman/pixman-fast-path.h
index d08122293..1885d47e7 100644
--- a/pixman/pixman/pixman-fast-path.h
+++ b/pixman/pixman/pixman-fast-path.h
@@ -587,4 +587,436 @@ fast_composite_scaled_nearest ## scale_func_name (pixman_implementation_t *imp,
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NONE (op,s,d,func), \
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_PAD (op,s,d,func)
+/*****************************************************************************/
+
+/*
+ * Identify 5 zones in each scanline for bilinear scaling. Depending on
+ * whether 2 pixels to be interpolated are fetched from the image itself,
+ * from the padding area around it or from both image and padding area.
+ */
+static force_inline void
+bilinear_pad_repeat_get_scanline_bounds (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 width1 = *width, left_pad1, right_pad1;
+ int width2 = *width, left_pad2, right_pad2;
+
+ pad_repeat_get_scanline_bounds (source_image_width, vx, unit_x,
+ &width1, &left_pad1, &right_pad1);
+ pad_repeat_get_scanline_bounds (source_image_width, vx + pixman_fixed_1,
+ unit_x, &width2, &left_pad2, &right_pad2);
+
+ *left_pad = left_pad2;
+ *left_tz = left_pad1 - left_pad2;
+ *right_tz = right_pad2 - right_pad1;
+ *right_pad = right_pad1;
+ *width -= *left_pad + *left_tz + *right_tz + *right_pad;
+}
+
+/*
+ * Main loop template for single pass bilinear scaling. It needs to be
+ * provided with 'scanline_func' which should do the compositing operation.
+ * The needed function has the following prototype:
+ *
+ * scanline_func (dst_type_t * dst,
+ * const mask_type_ * mask,
+ * const src_type_t * src_top,
+ * const src_type_t * src_bottom,
+ * int32_t width,
+ * int weight_top,
+ * int weight_bottom,
+ * pixman_fixed_t vx,
+ * pixman_fixed_t unit_x,
+ * pixman_fixed_t max_vx,
+ * pixman_bool_t zero_src)
+ *
+ * Where:
+ * dst - destination scanline buffer for storing results
+ * mask - mask buffer (or single value for solid mask)
+ * src_top, src_bottom - two source scanlines
+ * width - number of pixels to process
+ * weight_top - weight of the top row for interpolation
+ * weight_bottom - weight of the bottom row for interpolation
+ * vx - initial position for fetching the first pair of
+ * pixels from the source buffer
+ * unit_x - position increment needed to move to the next pair
+ * of pixels
+ * max_vx - image size as a fixed point value, can be used for
+ * implementing NORMAL repeat (when it is supported)
+ * zero_src - boolean hint variable, which is set to TRUE when
+ * all source pixels are fetched from zero padding
+ * zone for NONE repeat
+ *
+ * Note: normally the sum of 'weight_top' and 'weight_bottom' is equal to 256,
+ * but sometimes it may be less than that for NONE repeat when handling
+ * fuzzy antialiased top or bottom image edges. Also both top and
+ * bottom weight variables are guaranteed to have value in 0-255
+ * range and can fit into unsigned byte or be used with 8-bit SIMD
+ * multiplication instructions.
+ */
+#define FAST_BILINEAR_MAINLOOP_INT(scale_func_name, scanline_func, src_type_t, mask_type_t, \
+ dst_type_t, repeat_mode, have_mask, mask_is_solid) \
+static void \
+fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp, \
+ pixman_op_t op, \
+ pixman_image_t * src_image, \
+ pixman_image_t * mask_image, \
+ pixman_image_t * dst_image, \
+ int32_t src_x, \
+ int32_t src_y, \
+ int32_t mask_x, \
+ int32_t mask_y, \
+ int32_t dst_x, \
+ int32_t dst_y, \
+ int32_t width, \
+ int32_t height) \
+{ \
+ dst_type_t *dst_line; \
+ mask_type_t *mask_line; \
+ src_type_t *src_first_line; \
+ int y1, y2; \
+ pixman_fixed_t max_vx = INT32_MAX; /* suppress uninitialized variable warning */ \
+ pixman_vector_t v; \
+ pixman_fixed_t vx, vy; \
+ pixman_fixed_t unit_x, unit_y; \
+ int32_t left_pad, left_tz, right_tz, right_pad; \
+ \
+ dst_type_t *dst; \
+ mask_type_t solid_mask; \
+ const mask_type_t *mask = &solid_mask; \
+ int src_stride, mask_stride, dst_stride; \
+ \
+ PIXMAN_IMAGE_GET_LINE (dst_image, dst_x, dst_y, dst_type_t, dst_stride, dst_line, 1); \
+ if (have_mask) \
+ { \
+ if (mask_is_solid) \
+ { \
+ solid_mask = _pixman_image_get_solid (imp, mask_image, dst_image->bits.format); \
+ mask_stride = 0; \
+ } \
+ else \
+ { \
+ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type_t, \
+ mask_stride, mask_line, 1); \
+ } \
+ } \
+ /* pass in 0 instead of src_x and src_y because src_x and src_y need to be \
+ * transformed from destination space to source space */ \
+ PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, src_type_t, src_stride, src_first_line, 1); \
+ \
+ /* reference point is the center of the pixel */ \
+ v.vector[0] = pixman_int_to_fixed (src_x) + pixman_fixed_1 / 2; \
+ v.vector[1] = pixman_int_to_fixed (src_y) + pixman_fixed_1 / 2; \
+ v.vector[2] = pixman_fixed_1; \
+ \
+ if (!pixman_transform_point_3d (src_image->common.transform, &v)) \
+ return; \
+ \
+ unit_x = src_image->common.transform->matrix[0][0]; \
+ unit_y = src_image->common.transform->matrix[1][1]; \
+ \
+ v.vector[0] -= pixman_fixed_1 / 2; \
+ v.vector[1] -= pixman_fixed_1 / 2; \
+ \
+ vy = v.vector[1]; \
+ \
+ if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD || \
+ PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \
+ { \
+ bilinear_pad_repeat_get_scanline_bounds (src_image->bits.width, v.vector[0], unit_x, \
+ &left_pad, &left_tz, &width, &right_tz, &right_pad); \
+ if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \
+ { \
+ /* PAD repeat does not need special handling for 'transition zones' and */ \
+ /* they can be combined with 'padding zones' safely */ \
+ left_pad += left_tz; \
+ right_pad += right_tz; \
+ left_tz = right_tz = 0; \
+ } \
+ v.vector[0] += left_pad * unit_x; \
+ } \
+ \
+ while (--height >= 0) \
+ { \
+ int weight1, weight2; \
+ dst = dst_line; \
+ dst_line += dst_stride; \
+ vx = v.vector[0]; \
+ if (have_mask && !mask_is_solid) \
+ { \
+ mask = mask_line; \
+ mask_line += mask_stride; \
+ } \
+ \
+ y1 = pixman_fixed_to_int (vy); \
+ weight2 = (vy >> 8) & 0xff; \
+ if (weight2) \
+ { \
+ /* normal case, both row weights are in 0-255 range and fit unsigned byte */ \
+ y2 = y1 + 1; \
+ weight1 = 256 - weight2; \
+ } \
+ else \
+ { \
+ /* set both top and bottom row to the same scanline, and weights to 128+128 */ \
+ y2 = y1; \
+ weight1 = weight2 = 128; \
+ } \
+ vy += unit_y; \
+ if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \
+ { \
+ src_type_t *src1, *src2; \
+ src_type_t buf1[2]; \
+ src_type_t buf2[2]; \
+ repeat (PIXMAN_REPEAT_PAD, &y1, src_image->bits.height); \
+ repeat (PIXMAN_REPEAT_PAD, &y2, src_image->bits.height); \
+ src1 = src_first_line + src_stride * y1; \
+ src2 = src_first_line + src_stride * y2; \
+ \
+ if (left_pad > 0) \
+ { \
+ buf1[0] = buf1[1] = src1[0]; \
+ buf2[0] = buf2[1] = src2[0]; \
+ scanline_func (dst, mask, \
+ buf1, buf2, left_pad, weight1, weight2, 0, 0, 0, FALSE); \
+ dst += left_pad; \
+ if (have_mask && !mask_is_solid) \
+ mask += left_pad; \
+ } \
+ if (width > 0) \
+ { \
+ scanline_func (dst, mask, \
+ src1, src2, width, weight1, weight2, vx, unit_x, 0, FALSE); \
+ dst += width; \
+ if (have_mask && !mask_is_solid) \
+ mask += width; \
+ } \
+ if (right_pad > 0) \
+ { \
+ buf1[0] = buf1[1] = src1[src_image->bits.width - 1]; \
+ buf2[0] = buf2[1] = src2[src_image->bits.width - 1]; \
+ scanline_func (dst, mask, \
+ buf1, buf2, right_pad, weight1, weight2, 0, 0, 0, FALSE); \
+ } \
+ } \
+ else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \
+ { \
+ src_type_t *src1, *src2; \
+ src_type_t buf1[2]; \
+ src_type_t buf2[2]; \
+ /* handle top/bottom zero padding by just setting weights to 0 if needed */ \
+ if (y1 < 0) \
+ { \
+ weight1 = 0; \
+ y1 = 0; \
+ } \
+ if (y1 >= src_image->bits.height) \
+ { \
+ weight1 = 0; \
+ y1 = src_image->bits.height - 1; \
+ } \
+ if (y2 < 0) \
+ { \
+ weight2 = 0; \
+ y2 = 0; \
+ } \
+ if (y2 >= src_image->bits.height) \
+ { \
+ weight2 = 0; \
+ y2 = src_image->bits.height - 1; \
+ } \
+ src1 = src_first_line + src_stride * y1; \
+ src2 = src_first_line + src_stride * y2; \
+ \
+ if (left_pad > 0) \
+ { \
+ buf1[0] = buf1[1] = 0; \
+ buf2[0] = buf2[1] = 0; \
+ scanline_func (dst, mask, \
+ buf1, buf2, left_pad, weight1, weight2, 0, 0, 0, TRUE); \
+ dst += left_pad; \
+ if (have_mask && !mask_is_solid) \
+ mask += left_pad; \
+ } \
+ if (left_tz > 0) \
+ { \
+ buf1[0] = 0; \
+ buf1[1] = src1[0]; \
+ buf2[0] = 0; \
+ buf2[1] = src2[0]; \
+ scanline_func (dst, mask, \
+ buf1, buf2, left_tz, weight1, weight2, \
+ pixman_fixed_frac (vx), unit_x, 0, FALSE); \
+ dst += left_tz; \
+ if (have_mask && !mask_is_solid) \
+ mask += left_tz; \
+ vx += left_tz * unit_x; \
+ } \
+ if (width > 0) \
+ { \
+ scanline_func (dst, mask, \
+ src1, src2, width, weight1, weight2, vx, unit_x, 0, FALSE); \
+ dst += width; \
+ if (have_mask && !mask_is_solid) \
+ mask += width; \
+ vx += width * unit_x; \
+ } \
+ if (right_tz > 0) \
+ { \
+ buf1[0] = src1[src_image->bits.width - 1]; \
+ buf1[1] = 0; \
+ buf2[0] = src2[src_image->bits.width - 1]; \
+ buf2[1] = 0; \
+ scanline_func (dst, mask, \
+ buf1, buf2, right_tz, weight1, weight2, \
+ pixman_fixed_frac (vx), unit_x, 0, FALSE); \
+ dst += right_tz; \
+ if (have_mask && !mask_is_solid) \
+ mask += right_tz; \
+ } \
+ if (right_pad > 0) \
+ { \
+ buf1[0] = buf1[1] = 0; \
+ buf2[0] = buf2[1] = 0; \
+ scanline_func (dst, mask, \
+ buf1, buf2, right_pad, weight1, weight2, 0, 0, 0, TRUE); \
+ } \
+ } \
+ else \
+ { \
+ scanline_func (dst, mask, src_first_line + src_stride * y1, \
+ src_first_line + src_stride * y2, width, \
+ weight1, weight2, vx, unit_x, max_vx, FALSE); \
+ } \
+ } \
+}
+
+/* A workaround for old sun studio, see: https://bugs.freedesktop.org/show_bug.cgi?id=32764 */
+#define FAST_BILINEAR_MAINLOOP_COMMON(scale_func_name, scanline_func, src_type_t, mask_type_t, \
+ dst_type_t, repeat_mode, have_mask, mask_is_solid) \
+ FAST_BILINEAR_MAINLOOP_INT(_ ## scale_func_name, scanline_func, src_type_t, mask_type_t,\
+ dst_type_t, repeat_mode, have_mask, mask_is_solid)
+
+#define SCALED_BILINEAR_FLAGS \
+ (FAST_PATH_SCALE_TRANSFORM | \
+ FAST_PATH_NO_ALPHA_MAP | \
+ FAST_PATH_BILINEAR_FILTER | \
+ FAST_PATH_NO_ACCESSORS | \
+ FAST_PATH_NARROW_FORMAT)
+
+#define SIMPLE_BILINEAR_FAST_PATH_PAD(op,s,d,func) \
+ { PIXMAN_OP_ ## op, \
+ PIXMAN_ ## s, \
+ (SCALED_BILINEAR_FLAGS | \
+ FAST_PATH_PAD_REPEAT | \
+ FAST_PATH_X_UNIT_POSITIVE), \
+ PIXMAN_null, 0, \
+ PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
+ fast_composite_scaled_bilinear_ ## func ## _pad ## _ ## op, \
+ }
+
+#define SIMPLE_BILINEAR_FAST_PATH_NONE(op,s,d,func) \
+ { PIXMAN_OP_ ## op, \
+ PIXMAN_ ## s, \
+ (SCALED_BILINEAR_FLAGS | \
+ FAST_PATH_NONE_REPEAT | \
+ FAST_PATH_X_UNIT_POSITIVE), \
+ PIXMAN_null, 0, \
+ PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
+ fast_composite_scaled_bilinear_ ## func ## _none ## _ ## op, \
+ }
+
+#define SIMPLE_BILINEAR_FAST_PATH_COVER(op,s,d,func) \
+ { PIXMAN_OP_ ## op, \
+ PIXMAN_ ## s, \
+ SCALED_BILINEAR_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \
+ PIXMAN_null, 0, \
+ PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
+ fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op, \
+ }
+
+#define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_PAD(op,s,d,func) \
+ { PIXMAN_OP_ ## op, \
+ PIXMAN_ ## s, \
+ (SCALED_BILINEAR_FLAGS | \
+ FAST_PATH_PAD_REPEAT | \
+ FAST_PATH_X_UNIT_POSITIVE), \
+ PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \
+ PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
+ fast_composite_scaled_bilinear_ ## func ## _pad ## _ ## op, \
+ }
+
+#define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_NONE(op,s,d,func) \
+ { PIXMAN_OP_ ## op, \
+ PIXMAN_ ## s, \
+ (SCALED_BILINEAR_FLAGS | \
+ FAST_PATH_NONE_REPEAT | \
+ FAST_PATH_X_UNIT_POSITIVE), \
+ PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \
+ PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
+ fast_composite_scaled_bilinear_ ## func ## _none ## _ ## op, \
+ }
+
+#define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_COVER(op,s,d,func) \
+ { PIXMAN_OP_ ## op, \
+ PIXMAN_ ## s, \
+ SCALED_BILINEAR_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \
+ PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \
+ PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
+ fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op, \
+ }
+
+#define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_PAD(op,s,d,func) \
+ { PIXMAN_OP_ ## op, \
+ PIXMAN_ ## s, \
+ (SCALED_BILINEAR_FLAGS | \
+ FAST_PATH_PAD_REPEAT | \
+ FAST_PATH_X_UNIT_POSITIVE), \
+ PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \
+ PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
+ fast_composite_scaled_bilinear_ ## func ## _pad ## _ ## op, \
+ }
+
+#define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_NONE(op,s,d,func) \
+ { PIXMAN_OP_ ## op, \
+ PIXMAN_ ## s, \
+ (SCALED_BILINEAR_FLAGS | \
+ FAST_PATH_NONE_REPEAT | \
+ FAST_PATH_X_UNIT_POSITIVE), \
+ PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \
+ PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
+ fast_composite_scaled_bilinear_ ## func ## _none ## _ ## op, \
+ }
+
+#define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_COVER(op,s,d,func) \
+ { PIXMAN_OP_ ## op, \
+ PIXMAN_ ## s, \
+ SCALED_BILINEAR_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \
+ PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \
+ PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
+ fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op, \
+ }
+
+/* Prefer the use of 'cover' variant, because it is faster */
+#define SIMPLE_BILINEAR_FAST_PATH(op,s,d,func) \
+ SIMPLE_BILINEAR_FAST_PATH_COVER (op,s,d,func), \
+ SIMPLE_BILINEAR_FAST_PATH_NONE (op,s,d,func), \
+ SIMPLE_BILINEAR_FAST_PATH_PAD (op,s,d,func)
+
+#define SIMPLE_BILINEAR_A8_MASK_FAST_PATH(op,s,d,func) \
+ SIMPLE_BILINEAR_A8_MASK_FAST_PATH_COVER (op,s,d,func), \
+ SIMPLE_BILINEAR_A8_MASK_FAST_PATH_NONE (op,s,d,func), \
+ SIMPLE_BILINEAR_A8_MASK_FAST_PATH_PAD (op,s,d,func)
+
+#define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH(op,s,d,func) \
+ SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_COVER (op,s,d,func), \
+ SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_NONE (op,s,d,func), \
+ SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_PAD (op,s,d,func)
+
#endif
diff --git a/pixman/pixman/pixman-general.c b/pixman/pixman/pixman-general.c
index 16ea3a457..872fb7e9f 100644
--- a/pixman/pixman/pixman-general.c
+++ b/pixman/pixman/pixman-general.c
@@ -36,8 +36,6 @@
#include <stdlib.h>
#include <string.h>
#include "pixman-private.h"
-#include "pixman-combine32.h"
-#include "pixman-private.h"
static void
general_src_iter_init (pixman_implementation_t *imp,
diff --git a/pixman/pixman/pixman-image.c b/pixman/pixman/pixman-image.c
index 306692fe0..84bacf87e 100644
--- a/pixman/pixman/pixman-image.c
+++ b/pixman/pixman/pixman-image.c
@@ -1,782 +1,781 @@
-/*
- * Copyright © 2000 SuSE, Inc.
- * Copyright © 2007 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 SuSE not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. SuSE makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include "pixman-private.h"
-#include "pixman-combine32.h"
-
-pixman_bool_t
-_pixman_init_gradient (gradient_t * gradient,
- const pixman_gradient_stop_t *stops,
- int n_stops)
-{
- return_val_if_fail (n_stops > 0, FALSE);
-
- gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t));
- if (!gradient->stops)
- return FALSE;
-
- memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
-
- gradient->n_stops = n_stops;
-
- return TRUE;
-}
-
-pixman_image_t *
-_pixman_image_allocate (void)
-{
- pixman_image_t *image = malloc (sizeof (pixman_image_t));
-
- if (image)
- {
- image_common_t *common = &image->common;
-
- pixman_region32_init (&common->clip_region);
-
- common->alpha_count = 0;
- common->have_clip_region = FALSE;
- common->clip_sources = FALSE;
- common->transform = NULL;
- common->repeat = PIXMAN_REPEAT_NONE;
- common->filter = PIXMAN_FILTER_NEAREST;
- common->filter_params = NULL;
- common->n_filter_params = 0;
- common->alpha_map = NULL;
- common->component_alpha = FALSE;
- common->ref_count = 1;
- common->property_changed = NULL;
- common->client_clip = FALSE;
- common->destroy_func = NULL;
- common->destroy_data = NULL;
- common->dirty = TRUE;
- }
-
- return image;
-}
-
-static void
-image_property_changed (pixman_image_t *image)
-{
- image->common.dirty = TRUE;
-}
-
-/* Ref Counting */
-PIXMAN_EXPORT pixman_image_t *
-pixman_image_ref (pixman_image_t *image)
-{
- image->common.ref_count++;
-
- return image;
-}
-
-/* returns TRUE when the image is freed */
-PIXMAN_EXPORT pixman_bool_t
-pixman_image_unref (pixman_image_t *image)
-{
- image_common_t *common = (image_common_t *)image;
-
- common->ref_count--;
-
- if (common->ref_count == 0)
- {
- if (image->common.destroy_func)
- image->common.destroy_func (image, image->common.destroy_data);
-
- pixman_region32_fini (&common->clip_region);
-
- if (common->transform)
- free (common->transform);
-
- if (common->filter_params)
- free (common->filter_params);
-
- if (common->alpha_map)
- pixman_image_unref ((pixman_image_t *)common->alpha_map);
-
- if (image->type == LINEAR ||
- image->type == RADIAL ||
- image->type == CONICAL)
- {
- if (image->gradient.stops)
- free (image->gradient.stops);
- }
-
- if (image->type == BITS && image->bits.free_me)
- free (image->bits.free_me);
-
- free (image);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-PIXMAN_EXPORT void
-pixman_image_set_destroy_function (pixman_image_t * image,
- pixman_image_destroy_func_t func,
- void * data)
-{
- image->common.destroy_func = func;
- image->common.destroy_data = data;
-}
-
-PIXMAN_EXPORT void *
-pixman_image_get_destroy_data (pixman_image_t *image)
-{
- return image->common.destroy_data;
-}
-
-void
-_pixman_image_reset_clip_region (pixman_image_t *image)
-{
- image->common.have_clip_region = FALSE;
-}
-
-/* Executive Summary: This function is a no-op that only exists
- * for historical reasons.
- *
- * There used to be a bug in the X server where it would rely on
- * out-of-bounds accesses when it was asked to composite with a
- * window as the source. It would create a pixman image pointing
- * to some bogus position in memory, but then set a clip region
- * to the position where the actual bits were.
- *
- * Due to a bug in old versions of pixman, where it would not clip
- * against the image bounds when a clip region was set, this would
- * actually work. So when the pixman bug was fixed, a workaround was
- * added to allow certain out-of-bound accesses. This function disabled
- * those workarounds.
- *
- * Since 0.21.2, pixman doesn't do these workarounds anymore, so now
- * this function is a no-op.
- */
-PIXMAN_EXPORT void
-pixman_disable_out_of_bounds_workaround (void)
-{
-}
-
-static void
-compute_image_info (pixman_image_t *image)
-{
- pixman_format_code_t code;
- uint32_t flags = 0;
-
- /* Transform */
- if (!image->common.transform)
- {
- flags |= (FAST_PATH_ID_TRANSFORM |
- FAST_PATH_X_UNIT_POSITIVE |
- FAST_PATH_Y_UNIT_ZERO |
- FAST_PATH_AFFINE_TRANSFORM);
- }
- else
- {
- flags |= FAST_PATH_HAS_TRANSFORM;
-
- if (image->common.transform->matrix[2][0] == 0 &&
- image->common.transform->matrix[2][1] == 0 &&
- image->common.transform->matrix[2][2] == pixman_fixed_1)
- {
- flags |= FAST_PATH_AFFINE_TRANSFORM;
-
- if (image->common.transform->matrix[0][1] == 0 &&
- image->common.transform->matrix[1][0] == 0)
- {
- if (image->common.transform->matrix[0][0] == -pixman_fixed_1 &&
- image->common.transform->matrix[1][1] == -pixman_fixed_1)
- {
- flags |= FAST_PATH_ROTATE_180_TRANSFORM;
- }
- flags |= FAST_PATH_SCALE_TRANSFORM;
- }
- else if (image->common.transform->matrix[0][0] == 0 &&
- image->common.transform->matrix[1][1] == 0)
- {
- pixman_fixed_t m01 = image->common.transform->matrix[0][1];
- if (m01 == -image->common.transform->matrix[1][0])
- {
- if (m01 == -pixman_fixed_1)
- flags |= FAST_PATH_ROTATE_90_TRANSFORM;
- else if (m01 == pixman_fixed_1)
- flags |= FAST_PATH_ROTATE_270_TRANSFORM;
- }
- }
- }
-
- if (image->common.transform->matrix[0][0] > 0)
- flags |= FAST_PATH_X_UNIT_POSITIVE;
-
- if (image->common.transform->matrix[1][0] == 0)
- flags |= FAST_PATH_Y_UNIT_ZERO;
- }
-
- /* Filter */
- switch (image->common.filter)
- {
- case PIXMAN_FILTER_NEAREST:
- case PIXMAN_FILTER_FAST:
- flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
- break;
-
- case PIXMAN_FILTER_BILINEAR:
- case PIXMAN_FILTER_GOOD:
- case PIXMAN_FILTER_BEST:
- flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
- break;
-
- case PIXMAN_FILTER_CONVOLUTION:
- break;
-
- default:
- flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
- break;
- }
-
- /* Repeat mode */
- switch (image->common.repeat)
- {
- case PIXMAN_REPEAT_NONE:
- flags |=
- FAST_PATH_NO_REFLECT_REPEAT |
- FAST_PATH_NO_PAD_REPEAT |
- FAST_PATH_NO_NORMAL_REPEAT;
- break;
-
- case PIXMAN_REPEAT_REFLECT:
- flags |=
- FAST_PATH_NO_PAD_REPEAT |
- FAST_PATH_NO_NONE_REPEAT |
- FAST_PATH_NO_NORMAL_REPEAT;
- break;
-
- case PIXMAN_REPEAT_PAD:
- flags |=
- FAST_PATH_NO_REFLECT_REPEAT |
- FAST_PATH_NO_NONE_REPEAT |
- FAST_PATH_NO_NORMAL_REPEAT;
- break;
-
- default:
- flags |=
- FAST_PATH_NO_REFLECT_REPEAT |
- FAST_PATH_NO_PAD_REPEAT |
- FAST_PATH_NO_NONE_REPEAT;
- break;
- }
-
- /* Component alpha */
- if (image->common.component_alpha)
- flags |= FAST_PATH_COMPONENT_ALPHA;
- else
- flags |= FAST_PATH_UNIFIED_ALPHA;
-
- flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);
-
- /* Type specific checks */
- switch (image->type)
- {
- case SOLID:
- code = PIXMAN_solid;
-
- if (image->solid.color.alpha == 0xffff)
- flags |= FAST_PATH_IS_OPAQUE;
- break;
-
- case BITS:
- if (image->bits.width == 1 &&
- image->bits.height == 1 &&
- image->common.repeat != PIXMAN_REPEAT_NONE)
- {
- code = PIXMAN_solid;
- }
- else
- {
- code = image->bits.format;
- }
-
- if (!PIXMAN_FORMAT_A (image->bits.format) &&
- PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY &&
- PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR)
- {
- flags |= FAST_PATH_SAMPLES_OPAQUE;
-
- if (image->common.repeat != PIXMAN_REPEAT_NONE)
- flags |= FAST_PATH_IS_OPAQUE;
- }
-
- if (image->bits.read_func || image->bits.write_func)
- flags &= ~FAST_PATH_NO_ACCESSORS;
-
- if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
- flags &= ~FAST_PATH_NARROW_FORMAT;
- break;
-
- case RADIAL:
- code = PIXMAN_unknown;
-
- /*
- * As explained in pixman-radial-gradient.c, every point of
- * the plane has a valid associated radius (and thus will be
- * colored) if and only if a is negative (i.e. one of the two
- * circles contains the other one).
- */
-
- if (image->radial.a >= 0)
- break;
-
- /* Fall through */
-
- case CONICAL:
- case LINEAR:
- code = PIXMAN_unknown;
-
- if (image->common.repeat != PIXMAN_REPEAT_NONE)
- {
- int i;
-
- flags |= FAST_PATH_IS_OPAQUE;
- for (i = 0; i < image->gradient.n_stops; ++i)
- {
- if (image->gradient.stops[i].color.alpha != 0xffff)
- {
- flags &= ~FAST_PATH_IS_OPAQUE;
- break;
- }
- }
- }
- break;
-
- default:
- code = PIXMAN_unknown;
- break;
- }
-
- /* Alpha map */
- if (!image->common.alpha_map)
- {
- flags |= FAST_PATH_NO_ALPHA_MAP;
- }
- else
- {
- if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
- flags &= ~FAST_PATH_NARROW_FORMAT;
- }
-
- /* Both alpha maps and convolution filters can introduce
- * non-opaqueness in otherwise opaque images. Also
- * an image with component alpha turned on is only opaque
- * if all channels are opaque, so we simply turn it off
- * unconditionally for those images.
- */
- if (image->common.alpha_map ||
- image->common.filter == PIXMAN_FILTER_CONVOLUTION ||
- image->common.component_alpha)
- {
- flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
- }
-
- image->common.flags = flags;
- image->common.extended_format_code = code;
-}
-
-void
-_pixman_image_validate (pixman_image_t *image)
-{
- if (image->common.dirty)
- {
- compute_image_info (image);
-
- /* It is important that property_changed is
- * called *after* compute_image_info() because
- * property_changed() can make use of the flags
- * to set up accessors etc.
- */
- if (image->common.property_changed)
- image->common.property_changed (image);
-
- image->common.dirty = FALSE;
- }
-
- if (image->common.alpha_map)
- _pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
-}
-
-PIXMAN_EXPORT pixman_bool_t
-pixman_image_set_clip_region32 (pixman_image_t * image,
- pixman_region32_t *region)
-{
- image_common_t *common = (image_common_t *)image;
- pixman_bool_t result;
-
- if (region)
- {
- if ((result = pixman_region32_copy (&common->clip_region, region)))
- image->common.have_clip_region = TRUE;
- }
- else
- {
- _pixman_image_reset_clip_region (image);
-
- result = TRUE;
- }
-
- image_property_changed (image);
-
- return result;
-}
-
-PIXMAN_EXPORT pixman_bool_t
-pixman_image_set_clip_region (pixman_image_t * image,
- pixman_region16_t *region)
-{
- image_common_t *common = (image_common_t *)image;
- pixman_bool_t result;
-
- if (region)
- {
- if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
- image->common.have_clip_region = TRUE;
- }
- else
- {
- _pixman_image_reset_clip_region (image);
-
- result = TRUE;
- }
-
- image_property_changed (image);
-
- return result;
-}
-
-PIXMAN_EXPORT void
-pixman_image_set_has_client_clip (pixman_image_t *image,
- pixman_bool_t client_clip)
-{
- image->common.client_clip = client_clip;
-}
-
-PIXMAN_EXPORT pixman_bool_t
-pixman_image_set_transform (pixman_image_t * image,
- const pixman_transform_t *transform)
-{
- static const pixman_transform_t id =
- {
- { { pixman_fixed_1, 0, 0 },
- { 0, pixman_fixed_1, 0 },
- { 0, 0, pixman_fixed_1 } }
- };
-
- image_common_t *common = (image_common_t *)image;
- pixman_bool_t result;
-
- if (common->transform == transform)
- return TRUE;
-
- if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
- {
- free (common->transform);
- common->transform = NULL;
- result = TRUE;
-
- goto out;
- }
-
- if (common->transform &&
- memcmp (common->transform, transform, sizeof (pixman_transform_t) == 0))
- {
- return TRUE;
- }
-
- if (common->transform == NULL)
- common->transform = malloc (sizeof (pixman_transform_t));
-
- if (common->transform == NULL)
- {
- result = FALSE;
-
- goto out;
- }
-
- memcpy (common->transform, transform, sizeof(pixman_transform_t));
-
- result = TRUE;
-
-out:
- image_property_changed (image);
-
- return result;
-}
-
-PIXMAN_EXPORT void
-pixman_image_set_repeat (pixman_image_t *image,
- pixman_repeat_t repeat)
-{
- if (image->common.repeat == repeat)
- return;
-
- image->common.repeat = repeat;
-
- image_property_changed (image);
-}
-
-PIXMAN_EXPORT pixman_bool_t
-pixman_image_set_filter (pixman_image_t * image,
- pixman_filter_t filter,
- const pixman_fixed_t *params,
- int n_params)
-{
- image_common_t *common = (image_common_t *)image;
- pixman_fixed_t *new_params;
-
- if (params == common->filter_params && filter == common->filter)
- return TRUE;
-
- new_params = NULL;
- if (params)
- {
- new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
- if (!new_params)
- return FALSE;
-
- memcpy (new_params,
- params, n_params * sizeof (pixman_fixed_t));
- }
-
- common->filter = filter;
-
- if (common->filter_params)
- free (common->filter_params);
-
- common->filter_params = new_params;
- common->n_filter_params = n_params;
-
- image_property_changed (image);
- return TRUE;
-}
-
-PIXMAN_EXPORT void
-pixman_image_set_source_clipping (pixman_image_t *image,
- pixman_bool_t clip_sources)
-{
- if (image->common.clip_sources == clip_sources)
- return;
-
- image->common.clip_sources = clip_sources;
-
- image_property_changed (image);
-}
-
-/* Unlike all the other property setters, this function does not
- * copy the content of indexed. Doing this copying is simply
- * way, way too expensive.
- */
-PIXMAN_EXPORT void
-pixman_image_set_indexed (pixman_image_t * image,
- const pixman_indexed_t *indexed)
-{
- bits_image_t *bits = (bits_image_t *)image;
-
- if (bits->indexed == indexed)
- return;
-
- bits->indexed = indexed;
-
- image_property_changed (image);
-}
-
-PIXMAN_EXPORT void
-pixman_image_set_alpha_map (pixman_image_t *image,
- pixman_image_t *alpha_map,
- int16_t x,
- int16_t y)
-{
- image_common_t *common = (image_common_t *)image;
-
- return_if_fail (!alpha_map || alpha_map->type == BITS);
-
- if (alpha_map && common->alpha_count > 0)
- {
- /* If this image is being used as an alpha map itself,
- * then you can't give it an alpha map of its own.
- */
- return;
- }
-
- if (alpha_map && alpha_map->common.alpha_map)
- {
- /* If the image has an alpha map of its own,
- * then it can't be used as an alpha map itself
- */
- return;
- }
-
- if (common->alpha_map != (bits_image_t *)alpha_map)
- {
- if (common->alpha_map)
- {
- common->alpha_map->common.alpha_count--;
-
- pixman_image_unref ((pixman_image_t *)common->alpha_map);
- }
-
- if (alpha_map)
- {
- common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
-
- common->alpha_map->common.alpha_count++;
- }
- else
- {
- common->alpha_map = NULL;
- }
- }
-
- common->alpha_origin_x = x;
- common->alpha_origin_y = y;
-
- image_property_changed (image);
-}
-
-PIXMAN_EXPORT void
-pixman_image_set_component_alpha (pixman_image_t *image,
- pixman_bool_t component_alpha)
-{
- if (image->common.component_alpha == component_alpha)
- return;
-
- image->common.component_alpha = component_alpha;
-
- image_property_changed (image);
-}
-
-PIXMAN_EXPORT pixman_bool_t
-pixman_image_get_component_alpha (pixman_image_t *image)
-{
- return image->common.component_alpha;
-}
-
-PIXMAN_EXPORT void
-pixman_image_set_accessors (pixman_image_t * image,
- pixman_read_memory_func_t read_func,
- pixman_write_memory_func_t write_func)
-{
- return_if_fail (image != NULL);
-
- if (image->type == BITS)
- {
- image->bits.read_func = read_func;
- image->bits.write_func = write_func;
-
- image_property_changed (image);
- }
-}
-
-PIXMAN_EXPORT uint32_t *
-pixman_image_get_data (pixman_image_t *image)
-{
- if (image->type == BITS)
- return image->bits.bits;
-
- return NULL;
-}
-
-PIXMAN_EXPORT int
-pixman_image_get_width (pixman_image_t *image)
-{
- if (image->type == BITS)
- return image->bits.width;
-
- return 0;
-}
-
-PIXMAN_EXPORT int
-pixman_image_get_height (pixman_image_t *image)
-{
- if (image->type == BITS)
- return image->bits.height;
-
- return 0;
-}
-
-PIXMAN_EXPORT int
-pixman_image_get_stride (pixman_image_t *image)
-{
- if (image->type == BITS)
- return image->bits.rowstride * (int) sizeof (uint32_t);
-
- return 0;
-}
-
-PIXMAN_EXPORT int
-pixman_image_get_depth (pixman_image_t *image)
-{
- if (image->type == BITS)
- return PIXMAN_FORMAT_DEPTH (image->bits.format);
-
- return 0;
-}
-
-PIXMAN_EXPORT pixman_format_code_t
-pixman_image_get_format (pixman_image_t *image)
-{
- if (image->type == BITS)
- return image->bits.format;
-
- return 0;
-}
-
-uint32_t
-_pixman_image_get_solid (pixman_implementation_t *imp,
- pixman_image_t * image,
- pixman_format_code_t format)
-{
- uint32_t result;
- pixman_iter_t iter;
-
- _pixman_implementation_src_iter_init (
- imp, &iter, image, 0, 0, 1, 1,
- (uint8_t *)&result, ITER_NARROW);
-
- result = *iter.get_scanline (&iter, NULL);
-
- /* If necessary, convert RGB <--> BGR. */
- if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB)
- {
- result = (((result & 0xff000000) >> 0) |
- ((result & 0x00ff0000) >> 16) |
- ((result & 0x0000ff00) >> 0) |
- ((result & 0x000000ff) << 16));
- }
-
- return result;
-}
+/*
+ * Copyright © 2000 SuSE, Inc.
+ * Copyright © 2007 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "pixman-private.h"
+
+pixman_bool_t
+_pixman_init_gradient (gradient_t * gradient,
+ const pixman_gradient_stop_t *stops,
+ int n_stops)
+{
+ return_val_if_fail (n_stops > 0, FALSE);
+
+ gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t));
+ if (!gradient->stops)
+ return FALSE;
+
+ memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
+
+ gradient->n_stops = n_stops;
+
+ return TRUE;
+}
+
+pixman_image_t *
+_pixman_image_allocate (void)
+{
+ pixman_image_t *image = malloc (sizeof (pixman_image_t));
+
+ if (image)
+ {
+ image_common_t *common = &image->common;
+
+ pixman_region32_init (&common->clip_region);
+
+ common->alpha_count = 0;
+ common->have_clip_region = FALSE;
+ common->clip_sources = FALSE;
+ common->transform = NULL;
+ common->repeat = PIXMAN_REPEAT_NONE;
+ common->filter = PIXMAN_FILTER_NEAREST;
+ common->filter_params = NULL;
+ common->n_filter_params = 0;
+ common->alpha_map = NULL;
+ common->component_alpha = FALSE;
+ common->ref_count = 1;
+ common->property_changed = NULL;
+ common->client_clip = FALSE;
+ common->destroy_func = NULL;
+ common->destroy_data = NULL;
+ common->dirty = TRUE;
+ }
+
+ return image;
+}
+
+static void
+image_property_changed (pixman_image_t *image)
+{
+ image->common.dirty = TRUE;
+}
+
+/* Ref Counting */
+PIXMAN_EXPORT pixman_image_t *
+pixman_image_ref (pixman_image_t *image)
+{
+ image->common.ref_count++;
+
+ return image;
+}
+
+/* returns TRUE when the image is freed */
+PIXMAN_EXPORT pixman_bool_t
+pixman_image_unref (pixman_image_t *image)
+{
+ image_common_t *common = (image_common_t *)image;
+
+ common->ref_count--;
+
+ if (common->ref_count == 0)
+ {
+ if (image->common.destroy_func)
+ image->common.destroy_func (image, image->common.destroy_data);
+
+ pixman_region32_fini (&common->clip_region);
+
+ if (common->transform)
+ free (common->transform);
+
+ if (common->filter_params)
+ free (common->filter_params);
+
+ if (common->alpha_map)
+ pixman_image_unref ((pixman_image_t *)common->alpha_map);
+
+ if (image->type == LINEAR ||
+ image->type == RADIAL ||
+ image->type == CONICAL)
+ {
+ if (image->gradient.stops)
+ free (image->gradient.stops);
+ }
+
+ if (image->type == BITS && image->bits.free_me)
+ free (image->bits.free_me);
+
+ free (image);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+PIXMAN_EXPORT void
+pixman_image_set_destroy_function (pixman_image_t * image,
+ pixman_image_destroy_func_t func,
+ void * data)
+{
+ image->common.destroy_func = func;
+ image->common.destroy_data = data;
+}
+
+PIXMAN_EXPORT void *
+pixman_image_get_destroy_data (pixman_image_t *image)
+{
+ return image->common.destroy_data;
+}
+
+void
+_pixman_image_reset_clip_region (pixman_image_t *image)
+{
+ image->common.have_clip_region = FALSE;
+}
+
+/* Executive Summary: This function is a no-op that only exists
+ * for historical reasons.
+ *
+ * There used to be a bug in the X server where it would rely on
+ * out-of-bounds accesses when it was asked to composite with a
+ * window as the source. It would create a pixman image pointing
+ * to some bogus position in memory, but then set a clip region
+ * to the position where the actual bits were.
+ *
+ * Due to a bug in old versions of pixman, where it would not clip
+ * against the image bounds when a clip region was set, this would
+ * actually work. So when the pixman bug was fixed, a workaround was
+ * added to allow certain out-of-bound accesses. This function disabled
+ * those workarounds.
+ *
+ * Since 0.21.2, pixman doesn't do these workarounds anymore, so now
+ * this function is a no-op.
+ */
+PIXMAN_EXPORT void
+pixman_disable_out_of_bounds_workaround (void)
+{
+}
+
+static void
+compute_image_info (pixman_image_t *image)
+{
+ pixman_format_code_t code;
+ uint32_t flags = 0;
+
+ /* Transform */
+ if (!image->common.transform)
+ {
+ flags |= (FAST_PATH_ID_TRANSFORM |
+ FAST_PATH_X_UNIT_POSITIVE |
+ FAST_PATH_Y_UNIT_ZERO |
+ FAST_PATH_AFFINE_TRANSFORM);
+ }
+ else
+ {
+ flags |= FAST_PATH_HAS_TRANSFORM;
+
+ if (image->common.transform->matrix[2][0] == 0 &&
+ image->common.transform->matrix[2][1] == 0 &&
+ image->common.transform->matrix[2][2] == pixman_fixed_1)
+ {
+ flags |= FAST_PATH_AFFINE_TRANSFORM;
+
+ if (image->common.transform->matrix[0][1] == 0 &&
+ image->common.transform->matrix[1][0] == 0)
+ {
+ if (image->common.transform->matrix[0][0] == -pixman_fixed_1 &&
+ image->common.transform->matrix[1][1] == -pixman_fixed_1)
+ {
+ flags |= FAST_PATH_ROTATE_180_TRANSFORM;
+ }
+ flags |= FAST_PATH_SCALE_TRANSFORM;
+ }
+ else if (image->common.transform->matrix[0][0] == 0 &&
+ image->common.transform->matrix[1][1] == 0)
+ {
+ pixman_fixed_t m01 = image->common.transform->matrix[0][1];
+ if (m01 == -image->common.transform->matrix[1][0])
+ {
+ if (m01 == -pixman_fixed_1)
+ flags |= FAST_PATH_ROTATE_90_TRANSFORM;
+ else if (m01 == pixman_fixed_1)
+ flags |= FAST_PATH_ROTATE_270_TRANSFORM;
+ }
+ }
+ }
+
+ if (image->common.transform->matrix[0][0] > 0)
+ flags |= FAST_PATH_X_UNIT_POSITIVE;
+
+ if (image->common.transform->matrix[1][0] == 0)
+ flags |= FAST_PATH_Y_UNIT_ZERO;
+ }
+
+ /* Filter */
+ switch (image->common.filter)
+ {
+ case PIXMAN_FILTER_NEAREST:
+ case PIXMAN_FILTER_FAST:
+ flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
+ break;
+
+ case PIXMAN_FILTER_BILINEAR:
+ case PIXMAN_FILTER_GOOD:
+ case PIXMAN_FILTER_BEST:
+ flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
+ break;
+
+ case PIXMAN_FILTER_CONVOLUTION:
+ break;
+
+ default:
+ flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
+ break;
+ }
+
+ /* Repeat mode */
+ switch (image->common.repeat)
+ {
+ case PIXMAN_REPEAT_NONE:
+ flags |=
+ FAST_PATH_NO_REFLECT_REPEAT |
+ FAST_PATH_NO_PAD_REPEAT |
+ FAST_PATH_NO_NORMAL_REPEAT;
+ break;
+
+ case PIXMAN_REPEAT_REFLECT:
+ flags |=
+ FAST_PATH_NO_PAD_REPEAT |
+ FAST_PATH_NO_NONE_REPEAT |
+ FAST_PATH_NO_NORMAL_REPEAT;
+ break;
+
+ case PIXMAN_REPEAT_PAD:
+ flags |=
+ FAST_PATH_NO_REFLECT_REPEAT |
+ FAST_PATH_NO_NONE_REPEAT |
+ FAST_PATH_NO_NORMAL_REPEAT;
+ break;
+
+ default:
+ flags |=
+ FAST_PATH_NO_REFLECT_REPEAT |
+ FAST_PATH_NO_PAD_REPEAT |
+ FAST_PATH_NO_NONE_REPEAT;
+ break;
+ }
+
+ /* Component alpha */
+ if (image->common.component_alpha)
+ flags |= FAST_PATH_COMPONENT_ALPHA;
+ else
+ flags |= FAST_PATH_UNIFIED_ALPHA;
+
+ flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);
+
+ /* Type specific checks */
+ switch (image->type)
+ {
+ case SOLID:
+ code = PIXMAN_solid;
+
+ if (image->solid.color.alpha == 0xffff)
+ flags |= FAST_PATH_IS_OPAQUE;
+ break;
+
+ case BITS:
+ if (image->bits.width == 1 &&
+ image->bits.height == 1 &&
+ image->common.repeat != PIXMAN_REPEAT_NONE)
+ {
+ code = PIXMAN_solid;
+ }
+ else
+ {
+ code = image->bits.format;
+ }
+
+ if (!PIXMAN_FORMAT_A (image->bits.format) &&
+ PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY &&
+ PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR)
+ {
+ flags |= FAST_PATH_SAMPLES_OPAQUE;
+
+ if (image->common.repeat != PIXMAN_REPEAT_NONE)
+ flags |= FAST_PATH_IS_OPAQUE;
+ }
+
+ if (image->bits.read_func || image->bits.write_func)
+ flags &= ~FAST_PATH_NO_ACCESSORS;
+
+ if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
+ flags &= ~FAST_PATH_NARROW_FORMAT;
+ break;
+
+ case RADIAL:
+ code = PIXMAN_unknown;
+
+ /*
+ * As explained in pixman-radial-gradient.c, every point of
+ * the plane has a valid associated radius (and thus will be
+ * colored) if and only if a is negative (i.e. one of the two
+ * circles contains the other one).
+ */
+
+ if (image->radial.a >= 0)
+ break;
+
+ /* Fall through */
+
+ case CONICAL:
+ case LINEAR:
+ code = PIXMAN_unknown;
+
+ if (image->common.repeat != PIXMAN_REPEAT_NONE)
+ {
+ int i;
+
+ flags |= FAST_PATH_IS_OPAQUE;
+ for (i = 0; i < image->gradient.n_stops; ++i)
+ {
+ if (image->gradient.stops[i].color.alpha != 0xffff)
+ {
+ flags &= ~FAST_PATH_IS_OPAQUE;
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ code = PIXMAN_unknown;
+ break;
+ }
+
+ /* Alpha map */
+ if (!image->common.alpha_map)
+ {
+ flags |= FAST_PATH_NO_ALPHA_MAP;
+ }
+ else
+ {
+ if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
+ flags &= ~FAST_PATH_NARROW_FORMAT;
+ }
+
+ /* Both alpha maps and convolution filters can introduce
+ * non-opaqueness in otherwise opaque images. Also
+ * an image with component alpha turned on is only opaque
+ * if all channels are opaque, so we simply turn it off
+ * unconditionally for those images.
+ */
+ if (image->common.alpha_map ||
+ image->common.filter == PIXMAN_FILTER_CONVOLUTION ||
+ image->common.component_alpha)
+ {
+ flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
+ }
+
+ image->common.flags = flags;
+ image->common.extended_format_code = code;
+}
+
+void
+_pixman_image_validate (pixman_image_t *image)
+{
+ if (image->common.dirty)
+ {
+ compute_image_info (image);
+
+ /* It is important that property_changed is
+ * called *after* compute_image_info() because
+ * property_changed() can make use of the flags
+ * to set up accessors etc.
+ */
+ if (image->common.property_changed)
+ image->common.property_changed (image);
+
+ image->common.dirty = FALSE;
+ }
+
+ if (image->common.alpha_map)
+ _pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
+}
+
+PIXMAN_EXPORT pixman_bool_t
+pixman_image_set_clip_region32 (pixman_image_t * image,
+ pixman_region32_t *region)
+{
+ image_common_t *common = (image_common_t *)image;
+ pixman_bool_t result;
+
+ if (region)
+ {
+ if ((result = pixman_region32_copy (&common->clip_region, region)))
+ image->common.have_clip_region = TRUE;
+ }
+ else
+ {
+ _pixman_image_reset_clip_region (image);
+
+ result = TRUE;
+ }
+
+ image_property_changed (image);
+
+ return result;
+}
+
+PIXMAN_EXPORT pixman_bool_t
+pixman_image_set_clip_region (pixman_image_t * image,
+ pixman_region16_t *region)
+{
+ image_common_t *common = (image_common_t *)image;
+ pixman_bool_t result;
+
+ if (region)
+ {
+ if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
+ image->common.have_clip_region = TRUE;
+ }
+ else
+ {
+ _pixman_image_reset_clip_region (image);
+
+ result = TRUE;
+ }
+
+ image_property_changed (image);
+
+ return result;
+}
+
+PIXMAN_EXPORT void
+pixman_image_set_has_client_clip (pixman_image_t *image,
+ pixman_bool_t client_clip)
+{
+ image->common.client_clip = client_clip;
+}
+
+PIXMAN_EXPORT pixman_bool_t
+pixman_image_set_transform (pixman_image_t * image,
+ const pixman_transform_t *transform)
+{
+ static const pixman_transform_t id =
+ {
+ { { pixman_fixed_1, 0, 0 },
+ { 0, pixman_fixed_1, 0 },
+ { 0, 0, pixman_fixed_1 } }
+ };
+
+ image_common_t *common = (image_common_t *)image;
+ pixman_bool_t result;
+
+ if (common->transform == transform)
+ return TRUE;
+
+ if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
+ {
+ free (common->transform);
+ common->transform = NULL;
+ result = TRUE;
+
+ goto out;
+ }
+
+ if (common->transform &&
+ memcmp (common->transform, transform, sizeof (pixman_transform_t) == 0))
+ {
+ return TRUE;
+ }
+
+ if (common->transform == NULL)
+ common->transform = malloc (sizeof (pixman_transform_t));
+
+ if (common->transform == NULL)
+ {
+ result = FALSE;
+
+ goto out;
+ }
+
+ memcpy (common->transform, transform, sizeof(pixman_transform_t));
+
+ result = TRUE;
+
+out:
+ image_property_changed (image);
+
+ return result;
+}
+
+PIXMAN_EXPORT void
+pixman_image_set_repeat (pixman_image_t *image,
+ pixman_repeat_t repeat)
+{
+ if (image->common.repeat == repeat)
+ return;
+
+ image->common.repeat = repeat;
+
+ image_property_changed (image);
+}
+
+PIXMAN_EXPORT pixman_bool_t
+pixman_image_set_filter (pixman_image_t * image,
+ pixman_filter_t filter,
+ const pixman_fixed_t *params,
+ int n_params)
+{
+ image_common_t *common = (image_common_t *)image;
+ pixman_fixed_t *new_params;
+
+ if (params == common->filter_params && filter == common->filter)
+ return TRUE;
+
+ new_params = NULL;
+ if (params)
+ {
+ new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
+ if (!new_params)
+ return FALSE;
+
+ memcpy (new_params,
+ params, n_params * sizeof (pixman_fixed_t));
+ }
+
+ common->filter = filter;
+
+ if (common->filter_params)
+ free (common->filter_params);
+
+ common->filter_params = new_params;
+ common->n_filter_params = n_params;
+
+ image_property_changed (image);
+ return TRUE;
+}
+
+PIXMAN_EXPORT void
+pixman_image_set_source_clipping (pixman_image_t *image,
+ pixman_bool_t clip_sources)
+{
+ if (image->common.clip_sources == clip_sources)
+ return;
+
+ image->common.clip_sources = clip_sources;
+
+ image_property_changed (image);
+}
+
+/* Unlike all the other property setters, this function does not
+ * copy the content of indexed. Doing this copying is simply
+ * way, way too expensive.
+ */
+PIXMAN_EXPORT void
+pixman_image_set_indexed (pixman_image_t * image,
+ const pixman_indexed_t *indexed)
+{
+ bits_image_t *bits = (bits_image_t *)image;
+
+ if (bits->indexed == indexed)
+ return;
+
+ bits->indexed = indexed;
+
+ image_property_changed (image);
+}
+
+PIXMAN_EXPORT void
+pixman_image_set_alpha_map (pixman_image_t *image,
+ pixman_image_t *alpha_map,
+ int16_t x,
+ int16_t y)
+{
+ image_common_t *common = (image_common_t *)image;
+
+ return_if_fail (!alpha_map || alpha_map->type == BITS);
+
+ if (alpha_map && common->alpha_count > 0)
+ {
+ /* If this image is being used as an alpha map itself,
+ * then you can't give it an alpha map of its own.
+ */
+ return;
+ }
+
+ if (alpha_map && alpha_map->common.alpha_map)
+ {
+ /* If the image has an alpha map of its own,
+ * then it can't be used as an alpha map itself
+ */
+ return;
+ }
+
+ if (common->alpha_map != (bits_image_t *)alpha_map)
+ {
+ if (common->alpha_map)
+ {
+ common->alpha_map->common.alpha_count--;
+
+ pixman_image_unref ((pixman_image_t *)common->alpha_map);
+ }
+
+ if (alpha_map)
+ {
+ common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
+
+ common->alpha_map->common.alpha_count++;
+ }
+ else
+ {
+ common->alpha_map = NULL;
+ }
+ }
+
+ common->alpha_origin_x = x;
+ common->alpha_origin_y = y;
+
+ image_property_changed (image);
+}
+
+PIXMAN_EXPORT void
+pixman_image_set_component_alpha (pixman_image_t *image,
+ pixman_bool_t component_alpha)
+{
+ if (image->common.component_alpha == component_alpha)
+ return;
+
+ image->common.component_alpha = component_alpha;
+
+ image_property_changed (image);
+}
+
+PIXMAN_EXPORT pixman_bool_t
+pixman_image_get_component_alpha (pixman_image_t *image)
+{
+ return image->common.component_alpha;
+}
+
+PIXMAN_EXPORT void
+pixman_image_set_accessors (pixman_image_t * image,
+ pixman_read_memory_func_t read_func,
+ pixman_write_memory_func_t write_func)
+{
+ return_if_fail (image != NULL);
+
+ if (image->type == BITS)
+ {
+ image->bits.read_func = read_func;
+ image->bits.write_func = write_func;
+
+ image_property_changed (image);
+ }
+}
+
+PIXMAN_EXPORT uint32_t *
+pixman_image_get_data (pixman_image_t *image)
+{
+ if (image->type == BITS)
+ return image->bits.bits;
+
+ return NULL;
+}
+
+PIXMAN_EXPORT int
+pixman_image_get_width (pixman_image_t *image)
+{
+ if (image->type == BITS)
+ return image->bits.width;
+
+ return 0;
+}
+
+PIXMAN_EXPORT int
+pixman_image_get_height (pixman_image_t *image)
+{
+ if (image->type == BITS)
+ return image->bits.height;
+
+ return 0;
+}
+
+PIXMAN_EXPORT int
+pixman_image_get_stride (pixman_image_t *image)
+{
+ if (image->type == BITS)
+ return image->bits.rowstride * (int) sizeof (uint32_t);
+
+ return 0;
+}
+
+PIXMAN_EXPORT int
+pixman_image_get_depth (pixman_image_t *image)
+{
+ if (image->type == BITS)
+ return PIXMAN_FORMAT_DEPTH (image->bits.format);
+
+ return 0;
+}
+
+PIXMAN_EXPORT pixman_format_code_t
+pixman_image_get_format (pixman_image_t *image)
+{
+ if (image->type == BITS)
+ return image->bits.format;
+
+ return 0;
+}
+
+uint32_t
+_pixman_image_get_solid (pixman_implementation_t *imp,
+ pixman_image_t * image,
+ pixman_format_code_t format)
+{
+ uint32_t result;
+ pixman_iter_t iter;
+
+ _pixman_implementation_src_iter_init (
+ imp, &iter, image, 0, 0, 1, 1,
+ (uint8_t *)&result, ITER_NARROW);
+
+ result = *iter.get_scanline (&iter, NULL);
+
+ /* If necessary, convert RGB <--> BGR. */
+ if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB)
+ {
+ result = (((result & 0xff000000) >> 0) |
+ ((result & 0x00ff0000) >> 16) |
+ ((result & 0x0000ff00) >> 0) |
+ ((result & 0x000000ff) << 16));
+ }
+
+ return result;
+}
diff --git a/pixman/pixman/pixman-sse2.c b/pixman/pixman/pixman-sse2.c
index 88287b453..696005f75 100644
--- a/pixman/pixman/pixman-sse2.c
+++ b/pixman/pixman/pixman-sse2.c
@@ -5567,6 +5567,114 @@ FAST_NEAREST_MAINLOOP_COMMON (sse2_8888_n_8888_none_OVER,
scaled_nearest_scanline_sse2_8888_n_8888_OVER,
uint32_t, uint32_t, uint32_t, NONE, TRUE, TRUE)
+static void
+bilinear_interpolate_line_sse2 (uint32_t * out,
+ const uint32_t * top,
+ const uint32_t * bottom,
+ int wt,
+ int wb,
+ pixman_fixed_t x,
+ pixman_fixed_t ux,
+ int width)
+{
+ const __m128i xmm_wt = _mm_set_epi16 (wt, wt, wt, wt, wt, wt, wt, wt);
+ const __m128i xmm_wb = _mm_set_epi16 (wb, wb, wb, wb, wb, wb, wb, wb);
+ const __m128i xmm_xorc = _mm_set_epi16 (0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff);
+ const __m128i xmm_addc = _mm_set_epi16 (0, 0, 0, 0, 1, 1, 1, 1);
+ const __m128i xmm_ux = _mm_set_epi16 (ux, ux, ux, ux, ux, ux, ux, ux);
+ const __m128i xmm_zero = _mm_setzero_si128 ();
+ __m128i xmm_x = _mm_set_epi16 (x, x, x, x, x, x, x, x);
+ uint32_t pix1, pix2, pix3, pix4;
+
+ #define INTERPOLATE_ONE_PIXEL(pix) \
+ do { \
+ __m128i xmm_wh, xmm_lo, xmm_hi, a; \
+ /* fetch 2x2 pixel block into sse2 register */ \
+ uint32_t tl = top [pixman_fixed_to_int (x)]; \
+ uint32_t tr = top [pixman_fixed_to_int (x) + 1]; \
+ uint32_t bl = bottom [pixman_fixed_to_int (x)]; \
+ uint32_t br = bottom [pixman_fixed_to_int (x) + 1]; \
+ a = _mm_set_epi32 (tr, tl, br, bl); \
+ x += ux; \
+ /* vertical interpolation */ \
+ a = _mm_add_epi16 (_mm_mullo_epi16 (_mm_unpackhi_epi8 (a, xmm_zero), \
+ xmm_wt), \
+ _mm_mullo_epi16 (_mm_unpacklo_epi8 (a, xmm_zero), \
+ xmm_wb)); \
+ /* calculate horizontal weights */ \
+ xmm_wh = _mm_add_epi16 (xmm_addc, \
+ _mm_xor_si128 (xmm_xorc, \
+ _mm_srli_epi16 (xmm_x, 8))); \
+ xmm_x = _mm_add_epi16 (xmm_x, xmm_ux); \
+ /* horizontal interpolation */ \
+ xmm_lo = _mm_mullo_epi16 (a, xmm_wh); \
+ xmm_hi = _mm_mulhi_epu16 (a, xmm_wh); \
+ a = _mm_add_epi32 (_mm_unpacklo_epi16 (xmm_lo, xmm_hi), \
+ _mm_unpackhi_epi16 (xmm_lo, xmm_hi)); \
+ /* shift and pack the result */ \
+ a = _mm_srli_epi32 (a, 16); \
+ a = _mm_packs_epi32 (a, a); \
+ a = _mm_packus_epi16 (a, a); \
+ pix = _mm_cvtsi128_si32 (a); \
+ } while (0)
+
+ while ((width -= 4) >= 0)
+ {
+ INTERPOLATE_ONE_PIXEL (pix1);
+ INTERPOLATE_ONE_PIXEL (pix2);
+ INTERPOLATE_ONE_PIXEL (pix3);
+ INTERPOLATE_ONE_PIXEL (pix4);
+ *out++ = pix1;
+ *out++ = pix2;
+ *out++ = pix3;
+ *out++ = pix4;
+ }
+ if (width & 2)
+ {
+ INTERPOLATE_ONE_PIXEL (pix1);
+ INTERPOLATE_ONE_PIXEL (pix2);
+ *out++ = pix1;
+ *out++ = pix2;
+ }
+ if (width & 1)
+ {
+ INTERPOLATE_ONE_PIXEL (pix1);
+ *out = pix1;
+ }
+
+ #undef INTERPOLATE_ONE_PIXEL
+}
+
+static force_inline void
+scaled_bilinear_scanline_sse2_8888_8888_SRC (uint32_t * dst,
+ const uint32_t * mask,
+ const uint32_t * src_top,
+ const uint32_t * src_bottom,
+ int32_t w,
+ int wt,
+ int wb,
+ pixman_fixed_t vx,
+ pixman_fixed_t unit_x,
+ pixman_fixed_t max_vx,
+ pixman_bool_t zero_src)
+{
+ bilinear_interpolate_line_sse2 (dst, src_top, src_bottom,
+ wt, wb, vx, unit_x, w);
+}
+
+FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_cover_SRC,
+ scaled_bilinear_scanline_sse2_8888_8888_SRC,
+ uint32_t, uint32_t, uint32_t,
+ COVER, FALSE, FALSE)
+FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_pad_SRC,
+ scaled_bilinear_scanline_sse2_8888_8888_SRC,
+ uint32_t, uint32_t, uint32_t,
+ PAD, FALSE, FALSE)
+FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_none_SRC,
+ scaled_bilinear_scanline_sse2_8888_8888_SRC,
+ uint32_t, uint32_t, uint32_t,
+ NONE, FALSE, FALSE)
+
static const pixman_fast_path_t sse2_fast_paths[] =
{
/* PIXMAN_OP_OVER */
@@ -5668,6 +5776,10 @@ static const pixman_fast_path_t sse2_fast_paths[] =
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_n_8888),
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_n_8888),
+ SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, sse2_8888_8888),
+ SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, sse2_8888_8888),
+ SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, sse2_8888_8888),
+
{ PIXMAN_OP_NONE },
};
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 <pixman.h>
-#include <stdio.h>
-#include <stdlib.h> /* abort() */
-#include <math.h>
-#include <config.h>
-#include <time.h>
-#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 <number>\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 <pixman.h>
+#include <stdio.h>
+#include <stdlib.h> /* abort() */
+#include <math.h>
+#include <config.h>
+#include <time.h>
+#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 <number>\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 <config.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#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 (&region);
-
- 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 (
- &region, &region, x, y, width, height);
- }
-
- pixman_image_set_clip_region32 (image, &region);
-
- pixman_region32_fini (&region);
- }
-
- /* 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> Number of tests to run\n"
- "-s <seed> Seed of first test\n"
- "-v Print out seeds\n"
- "-v <n> 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 (&region);
+
+ 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 (
+ &region, &region, x, y, width, height);
+ }
+
+ pixman_image_set_clip_region32 (image, &region);
+
+ pixman_region32_fini (&region);
+ }
+
+ /* 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> Number of tests to run\n"
+ "-s <seed> Seed of first test\n"
+ "-v Print out seeds\n"
+ "-v <n> 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);
}