aboutsummaryrefslogtreecommitdiff
path: root/pixman
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2012-09-27 15:15:06 +0200
committermarha <marha@users.sourceforge.net>2012-09-27 15:15:06 +0200
commit24703f26d8ed55b1971aa2e94d33636e871bff0b (patch)
tree3e57b600f4446a1db1d8e73cb8a83519570eb678 /pixman
parent94ef26cb962261d0b47daf7ef3c856510999bd4c (diff)
parent2cf1e3de4759264eac2fa8ac758ea750636542f8 (diff)
downloadvcxsrv-24703f26d8ed55b1971aa2e94d33636e871bff0b.tar.gz
vcxsrv-24703f26d8ed55b1971aa2e94d33636e871bff0b.tar.bz2
vcxsrv-24703f26d8ed55b1971aa2e94d33636e871bff0b.zip
Merge remote-tracking branch 'origin/released'
* origin/released: mesa xserver pixman xkeyboard-config git update 27 sep 2012
Diffstat (limited to 'pixman')
-rw-r--r--pixman/pixman/pixman-arm-common.h24
-rw-r--r--pixman/pixman/pixman-arm-neon-asm.h45
-rw-r--r--pixman/pixman/pixman-arm-simd-asm.S47
-rw-r--r--pixman/pixman/pixman-combine.c.template42
-rw-r--r--pixman/pixman/pixman-fast-path.c14
-rw-r--r--pixman/pixman/pixman-image.c4
-rw-r--r--pixman/pixman/pixman-inlines.h61
-rw-r--r--pixman/pixman/pixman-mips-dspr2-asm.S460
-rw-r--r--pixman/pixman/pixman-mips-dspr2.c56
-rw-r--r--pixman/pixman/pixman-mips-dspr2.h83
-rw-r--r--pixman/pixman/pixman-sse2.c68
-rw-r--r--pixman/test/Makefile.sources2
-rw-r--r--pixman/test/affine-test.c16
-rw-r--r--pixman/test/blitters-test.c2
-rw-r--r--pixman/test/infinite-loop.c39
-rw-r--r--pixman/test/rotate-test.c111
16 files changed, 947 insertions, 127 deletions
diff --git a/pixman/pixman/pixman-arm-common.h b/pixman/pixman/pixman-arm-common.h
index f56264e8c..3a7cb2bef 100644
--- a/pixman/pixman/pixman-arm-common.h
+++ b/pixman/pixman/pixman-arm-common.h
@@ -236,7 +236,8 @@ pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype ( \
dst_type * dst, \
const src_type * src, \
pixman_fixed_t vx, \
- pixman_fixed_t unit_x); \
+ pixman_fixed_t unit_x, \
+ pixman_fixed_t max_vx); \
\
static force_inline void \
scaled_nearest_scanline_##cputype##_##name##_##op (dst_type * pd, \
@@ -248,7 +249,8 @@ scaled_nearest_scanline_##cputype##_##name##_##op (dst_type * pd, \
pixman_bool_t zero_src) \
{ \
pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype (w, pd, ps, \
- vx, unit_x);\
+ vx, unit_x, \
+ max_vx); \
} \
\
FAST_NEAREST_MAINLOOP (cputype##_##name##_cover_##op, \
@@ -259,13 +261,17 @@ FAST_NEAREST_MAINLOOP (cputype##_##name##_none_##op, \
src_type, dst_type, NONE) \
FAST_NEAREST_MAINLOOP (cputype##_##name##_pad_##op, \
scaled_nearest_scanline_##cputype##_##name##_##op, \
- src_type, dst_type, PAD)
+ src_type, dst_type, PAD) \
+FAST_NEAREST_MAINLOOP (cputype##_##name##_normal_##op, \
+ scaled_nearest_scanline_##cputype##_##name##_##op, \
+ src_type, dst_type, NORMAL)
/* Provide entries for the fast path table */
#define PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH(op,s,d,func) \
SIMPLE_NEAREST_FAST_PATH_COVER (op,s,d,func), \
SIMPLE_NEAREST_FAST_PATH_NONE (op,s,d,func), \
- SIMPLE_NEAREST_FAST_PATH_PAD (op,s,d,func)
+ SIMPLE_NEAREST_FAST_PATH_PAD (op,s,d,func), \
+ SIMPLE_NEAREST_FAST_PATH_NORMAL (op,s,d,func)
#define PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_A8_DST(flags, cputype, name, op, \
src_type, dst_type) \
@@ -276,6 +282,7 @@ pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype ( \
const src_type * src, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x, \
+ pixman_fixed_t max_vx, \
const uint8_t * mask); \
\
static force_inline void \
@@ -292,6 +299,7 @@ scaled_nearest_scanline_##cputype##_##name##_##op (const uint8_t * mask, \
return; \
pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype (w, pd, ps, \
vx, unit_x, \
+ max_vx, \
mask); \
} \
\
@@ -303,13 +311,17 @@ FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_none_##op, \
src_type, uint8_t, dst_type, NONE, TRUE, FALSE) \
FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_pad_##op, \
scaled_nearest_scanline_##cputype##_##name##_##op,\
- src_type, uint8_t, dst_type, PAD, TRUE, FALSE)
+ src_type, uint8_t, dst_type, PAD, TRUE, FALSE) \
+FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_normal_##op, \
+ scaled_nearest_scanline_##cputype##_##name##_##op,\
+ src_type, uint8_t, dst_type, NORMAL, TRUE, FALSE)
/* Provide entries for the fast path table */
#define PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH(op,s,d,func) \
SIMPLE_NEAREST_A8_MASK_FAST_PATH_COVER (op,s,d,func), \
SIMPLE_NEAREST_A8_MASK_FAST_PATH_NONE (op,s,d,func), \
- SIMPLE_NEAREST_A8_MASK_FAST_PATH_PAD (op,s,d,func)
+ SIMPLE_NEAREST_A8_MASK_FAST_PATH_PAD (op,s,d,func), \
+ SIMPLE_NEAREST_A8_MASK_FAST_PATH_NORMAL (op,s,d,func)
/*****************************************************************************/
diff --git a/pixman/pixman/pixman-arm-neon-asm.h b/pixman/pixman/pixman-arm-neon-asm.h
index 97adc6a87..1673b080f 100644
--- a/pixman/pixman/pixman-arm-neon-asm.h
+++ b/pixman/pixman/pixman-arm-neon-asm.h
@@ -212,27 +212,39 @@
.macro pixld1_s elem_size, reg1, mem_operand
.if elem_size == 16
mov TMP1, VX, asr #16
- add VX, VX, UNIT_X
+ adds VX, VX, UNIT_X
+5: subpls VX, VX, SRC_WIDTH_FIXED
+ bpl 5b
add TMP1, mem_operand, TMP1, asl #1
mov TMP2, VX, asr #16
- add VX, VX, UNIT_X
+ adds VX, VX, UNIT_X
+5: subpls VX, VX, SRC_WIDTH_FIXED
+ bpl 5b
add TMP2, mem_operand, TMP2, asl #1
vld1.16 {d&reg1&[0]}, [TMP1, :16]
mov TMP1, VX, asr #16
- add VX, VX, UNIT_X
+ adds VX, VX, UNIT_X
+5: subpls VX, VX, SRC_WIDTH_FIXED
+ bpl 5b
add TMP1, mem_operand, TMP1, asl #1
vld1.16 {d&reg1&[1]}, [TMP2, :16]
mov TMP2, VX, asr #16
- add VX, VX, UNIT_X
+ adds VX, VX, UNIT_X
+5: subpls VX, VX, SRC_WIDTH_FIXED
+ bpl 5b
add TMP2, mem_operand, TMP2, asl #1
vld1.16 {d&reg1&[2]}, [TMP1, :16]
vld1.16 {d&reg1&[3]}, [TMP2, :16]
.elseif elem_size == 32
mov TMP1, VX, asr #16
- add VX, VX, UNIT_X
+ adds VX, VX, UNIT_X
+5: subpls VX, VX, SRC_WIDTH_FIXED
+ bpl 5b
add TMP1, mem_operand, TMP1, asl #2
mov TMP2, VX, asr #16
- add VX, VX, UNIT_X
+ adds VX, VX, UNIT_X
+5: subpls VX, VX, SRC_WIDTH_FIXED
+ bpl 5b
add TMP2, mem_operand, TMP2, asl #2
vld1.32 {d&reg1&[0]}, [TMP1, :32]
vld1.32 {d&reg1&[1]}, [TMP2, :32]
@@ -242,7 +254,7 @@
.endm
.macro pixld2_s elem_size, reg1, reg2, mem_operand
-.if elem_size == 32
+.if 0 /* elem_size == 32 */
mov TMP1, VX, asr #16
add VX, VX, UNIT_X, asl #1
add TMP1, mem_operand, TMP1, asl #2
@@ -268,12 +280,16 @@
.macro pixld0_s elem_size, reg1, idx, mem_operand
.if elem_size == 16
mov TMP1, VX, asr #16
- add VX, VX, UNIT_X
+ adds VX, VX, UNIT_X
+5: subpls VX, VX, SRC_WIDTH_FIXED
+ bpl 5b
add TMP1, mem_operand, TMP1, asl #1
vld1.16 {d&reg1&[idx]}, [TMP1, :16]
.elseif elem_size == 32
mov TMP1, VX, asr #16
- add VX, VX, UNIT_X
+ adds VX, VX, UNIT_X
+5: subpls VX, VX, SRC_WIDTH_FIXED
+ bpl 5b
add TMP1, mem_operand, TMP1, asl #2
vld1.32 {d&reg1&[idx]}, [TMP1, :32]
.endif
@@ -964,15 +980,17 @@ fname:
TMP1 .req r4
TMP2 .req r5
DST_R .req r6
+ SRC_WIDTH_FIXED .req r7
.macro pixld_src x:vararg
pixld_s x
.endm
ldr UNIT_X, [sp]
- push {r4-r6, lr}
+ push {r4-r8, lr}
+ ldr SRC_WIDTH_FIXED, [sp, #(24 + 4)]
.if mask_bpp != 0
- ldr MASK, [sp, #(16 + 4)]
+ ldr MASK, [sp, #(24 + 8)]
.endif
.else
/*
@@ -1044,7 +1062,7 @@ fname:
cleanup
.if use_nearest_scaling != 0
- pop {r4-r6, pc} /* exit */
+ pop {r4-r8, pc} /* exit */
.else
bx lr /* exit */
.endif
@@ -1058,7 +1076,7 @@ fname:
cleanup
.if use_nearest_scaling != 0
- pop {r4-r6, pc} /* exit */
+ pop {r4-r8, pc} /* exit */
.unreq DST_R
.unreq SRC
@@ -1069,6 +1087,7 @@ fname:
.unreq TMP2
.unreq DST_W
.unreq MASK
+ .unreq SRC_WIDTH_FIXED
.else
bx lr /* exit */
diff --git a/pixman/pixman/pixman-arm-simd-asm.S b/pixman/pixman/pixman-arm-simd-asm.S
index 8fe1b5038..b438001d3 100644
--- a/pixman/pixman/pixman-arm-simd-asm.S
+++ b/pixman/pixman/pixman-arm-simd-asm.S
@@ -355,49 +355,57 @@ pixman_asm_function pixman_composite_over_n_8_8888_asm_armv6
prefetch_braking_distance
pixman_asm_function fname
- W .req r0
- DST .req r1
- SRC .req r2
- VX .req r3
- UNIT_X .req ip
- TMP1 .req r4
- TMP2 .req r5
- VXMASK .req r6
- PF_OFFS .req r7
+ W .req r0
+ DST .req r1
+ SRC .req r2
+ VX .req r3
+ UNIT_X .req ip
+ TMP1 .req r4
+ TMP2 .req r5
+ VXMASK .req r6
+ PF_OFFS .req r7
+ SRC_WIDTH_FIXED .req r8
ldr UNIT_X, [sp]
- push {r4, r5, r6, r7}
+ push {r4, r5, r6, r7, r8, r10}
mvn VXMASK, #((1 << bpp_shift) - 1)
+ ldr SRC_WIDTH_FIXED, [sp, #28]
/* define helper macro */
.macro scale_2_pixels
ldr&t TMP1, [SRC, TMP1]
- and TMP2, VXMASK, VX, lsr #(16 - bpp_shift)
- add VX, VX, UNIT_X
+ and TMP2, VXMASK, VX, asr #(16 - bpp_shift)
+ adds VX, VX, UNIT_X
str&t TMP1, [DST], #(1 << bpp_shift)
+9: subpls VX, VX, SRC_WIDTH_FIXED
+ bpl 9b
ldr&t TMP2, [SRC, TMP2]
- and TMP1, VXMASK, VX, lsr #(16 - bpp_shift)
- add VX, VX, UNIT_X
+ and TMP1, VXMASK, VX, asr #(16 - bpp_shift)
+ adds VX, VX, UNIT_X
str&t TMP2, [DST], #(1 << bpp_shift)
+9: subpls VX, VX, SRC_WIDTH_FIXED
+ bpl 9b
.endm
/* now do the scaling */
- and TMP1, VXMASK, VX, lsr #(16 - bpp_shift)
- add VX, VX, UNIT_X
+ and TMP1, VXMASK, VX, asr #(16 - bpp_shift)
+ adds VX, VX, UNIT_X
+9: subpls VX, VX, SRC_WIDTH_FIXED
+ bpl 9b
subs W, W, #(8 + prefetch_braking_distance)
blt 2f
/* calculate prefetch offset */
mov PF_OFFS, #prefetch_distance
mla PF_OFFS, UNIT_X, PF_OFFS, VX
1: /* main loop, process 8 pixels per iteration with prefetch */
- subs W, W, #8
+ pld [SRC, PF_OFFS, asr #(16 - bpp_shift)]
add PF_OFFS, UNIT_X, lsl #3
scale_2_pixels
scale_2_pixels
scale_2_pixels
scale_2_pixels
- pld [SRC, PF_OFFS, lsr #(16 - bpp_shift)]
+ subs W, W, #8
bge 1b
2:
subs W, W, #(4 - 8 - prefetch_braking_distance)
@@ -426,8 +434,9 @@ pixman_asm_function fname
.unreq TMP2
.unreq VXMASK
.unreq PF_OFFS
+ .unreq SRC_WIDTH_FIXED
/* return */
- pop {r4, r5, r6, r7}
+ pop {r4, r5, r6, r7, r8, r10}
bx lr
.endfunc
.endm
diff --git a/pixman/pixman/pixman-combine.c.template b/pixman/pixman/pixman-combine.c.template
index cd008d967..f405312d4 100644
--- a/pixman/pixman/pixman-combine.c.template
+++ b/pixman/pixman/pixman-combine.c.template
@@ -6,10 +6,9 @@
#include <string.h>
#include "pixman-private.h"
-
#include "pixman-combine.h"
-/*** per channel helper functions ***/
+/* component alpha helper functions */
static void
combine_mask_ca (comp4_t *src, comp4_t *mask)
@@ -91,15 +90,11 @@ combine_mask_alpha_ca (const comp4_t *src, comp4_t *mask)
/*
* There are two ways of handling alpha -- either as a single unified value or
* a separate value for each component, hence each macro must have two
- * versions. The unified alpha version has a 'U' at the end of the name,
- * the component version has a 'C'. Similarly, functions which deal with
+ * versions. The unified alpha version has a 'u' at the end of the name,
+ * the component version has a 'ca'. Similarly, functions which deal with
* this difference will have two versions using the same convention.
*/
-/*
- * All of the composing functions
- */
-
static force_inline comp4_t
combine_mask (const comp4_t *src, const comp4_t *mask, int i)
{
@@ -154,7 +149,9 @@ combine_src_u (pixman_implementation_t *imp,
int i;
if (!mask)
+ {
memcpy (dest, src, width * sizeof (comp4_t));
+ }
else
{
for (i = 0; i < width; ++i)
@@ -166,7 +163,6 @@ combine_src_u (pixman_implementation_t *imp,
}
}
-/* if the Src is opaque, call combine_src_u */
static void
combine_over_u (pixman_implementation_t *imp,
pixman_op_t op,
@@ -188,7 +184,6 @@ combine_over_u (pixman_implementation_t *imp,
}
}
-/* if the Dst is opaque, this is a noop */
static void
combine_over_reverse_u (pixman_implementation_t *imp,
pixman_op_t op,
@@ -209,7 +204,6 @@ combine_over_reverse_u (pixman_implementation_t *imp,
}
}
-/* if the Dst is opaque, call combine_src_u */
static void
combine_in_u (pixman_implementation_t *imp,
pixman_op_t op,
@@ -229,7 +223,6 @@ combine_in_u (pixman_implementation_t *imp,
}
}
-/* if the Src is opaque, this is a noop */
static void
combine_in_reverse_u (pixman_implementation_t *imp,
pixman_op_t op,
@@ -250,7 +243,6 @@ combine_in_reverse_u (pixman_implementation_t *imp,
}
}
-/* if the Dst is opaque, call combine_clear */
static void
combine_out_u (pixman_implementation_t *imp,
pixman_op_t op,
@@ -270,7 +262,6 @@ combine_out_u (pixman_implementation_t *imp,
}
}
-/* if the Src is opaque, call combine_clear */
static void
combine_out_reverse_u (pixman_implementation_t *imp,
pixman_op_t op,
@@ -291,9 +282,6 @@ combine_out_reverse_u (pixman_implementation_t *imp,
}
}
-/* if the Src is opaque, call combine_in_u */
-/* if the Dst is opaque, call combine_over_u */
-/* if both the Src and Dst are opaque, call combine_src_u */
static void
combine_atop_u (pixman_implementation_t *imp,
pixman_op_t op,
@@ -316,9 +304,6 @@ combine_atop_u (pixman_implementation_t *imp,
}
}
-/* if the Src is opaque, call combine_over_reverse_u */
-/* if the Dst is opaque, call combine_in_reverse_u */
-/* if both the Src and Dst are opaque, call combine_dst_u */
static void
combine_atop_reverse_u (pixman_implementation_t *imp,
pixman_op_t op,
@@ -341,9 +326,6 @@ combine_atop_reverse_u (pixman_implementation_t *imp,
}
}
-/* if the Src is opaque, call combine_over_u */
-/* if the Dst is opaque, call combine_over_reverse_u */
-/* if both the Src and Dst are opaque, call combine_clear */
static void
combine_xor_u (pixman_implementation_t *imp,
pixman_op_t op,
@@ -385,9 +367,6 @@ combine_add_u (pixman_implementation_t *imp,
}
}
-/* if the Src is opaque, call combine_add_u */
-/* if the Dst is opaque, call combine_add_u */
-/* if both the Src and Dst are opaque, call combine_add_u */
static void
combine_saturate_u (pixman_implementation_t *imp,
pixman_op_t op,
@@ -444,7 +423,6 @@ combine_saturate_u (pixman_implementation_t *imp,
* Multiply
* B(Dca, ad, Sca, as) = Dca.Sca
*/
-
static void
combine_multiply_u (pixman_implementation_t *imp,
pixman_op_t op,
@@ -489,7 +467,7 @@ combine_multiply_ca (pixman_implementation_t *imp,
comp4_t r = d;
comp4_t dest_ia = ALPHA_c (~d);
- combine_mask_value_ca (&s, &m);
+ combine_mask_ca (&s, &m);
UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (r, ~m, s, dest_ia);
UNcx4_MUL_UNcx4 (d, s);
@@ -546,7 +524,7 @@ combine_multiply_ca (pixman_implementation_t *imp,
comp1_t ida = ~da; \
comp4_t result; \
\
- combine_mask_value_ca (&s, &m); \
+ combine_mask_ca (&s, &m); \
\
result = d; \
UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (result, ~m, s, ida); \
@@ -1579,9 +1557,8 @@ combine_conjoint_xor_u (pixman_implementation_t *imp,
combine_conjoint_general_u (dest, src, mask, width, COMBINE_XOR);
}
-/************************************************************************/
-/*********************** Per Channel functions **************************/
-/************************************************************************/
+
+/* Component alpha combiners */
static void
combine_clear_ca (pixman_implementation_t *imp,
@@ -2458,4 +2435,3 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
imp->combine_width_ca[PIXMAN_OP_HSL_COLOR] = combine_dst;
imp->combine_width_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst;
}
-
diff --git a/pixman/pixman/pixman-fast-path.c b/pixman/pixman/pixman-fast-path.c
index 86ed821d6..22bfd301c 100644
--- a/pixman/pixman/pixman-fast-path.c
+++ b/pixman/pixman/pixman-fast-path.c
@@ -1415,13 +1415,13 @@ scaled_nearest_scanline_565_565_SRC (uint16_t * dst,
uint16_t tmp1, tmp2, tmp3, tmp4;
while ((w -= 4) >= 0)
{
- tmp1 = src[pixman_fixed_to_int (vx)];
+ tmp1 = *(src + pixman_fixed_to_int (vx));
vx += unit_x;
- tmp2 = src[pixman_fixed_to_int (vx)];
+ tmp2 = *(src + pixman_fixed_to_int (vx));
vx += unit_x;
- tmp3 = src[pixman_fixed_to_int (vx)];
+ tmp3 = *(src + pixman_fixed_to_int (vx));
vx += unit_x;
- tmp4 = src[pixman_fixed_to_int (vx)];
+ tmp4 = *(src + pixman_fixed_to_int (vx));
vx += unit_x;
*dst++ = tmp1;
*dst++ = tmp2;
@@ -1430,15 +1430,15 @@ scaled_nearest_scanline_565_565_SRC (uint16_t * dst,
}
if (w & 2)
{
- tmp1 = src[pixman_fixed_to_int (vx)];
+ tmp1 = *(src + pixman_fixed_to_int (vx));
vx += unit_x;
- tmp2 = src[pixman_fixed_to_int (vx)];
+ tmp2 = *(src + pixman_fixed_to_int (vx));
vx += unit_x;
*dst++ = tmp1;
*dst++ = tmp2;
}
if (w & 1)
- *dst++ = src[pixman_fixed_to_int (vx)];
+ *dst = *(src + pixman_fixed_to_int (vx));
}
FAST_NEAREST_MAINLOOP (565_565_cover_SRC,
diff --git a/pixman/pixman/pixman-image.c b/pixman/pixman/pixman-image.c
index 15597bd61..d9c303441 100644
--- a/pixman/pixman/pixman-image.c
+++ b/pixman/pixman/pixman-image.c
@@ -301,9 +301,9 @@ compute_image_info (pixman_image_t *image)
pixman_fixed_t m01 = image->common.transform->matrix[0][1];
pixman_fixed_t m10 = image->common.transform->matrix[1][0];
- if (m01 == -1 && m10 == 1)
+ if (m01 == -pixman_fixed_1 && m10 == pixman_fixed_1)
flags |= FAST_PATH_ROTATE_90_TRANSFORM;
- else if (m01 == 1 && m10 == -1)
+ else if (m01 == pixman_fixed_1 && m10 == -pixman_fixed_1)
flags |= FAST_PATH_ROTATE_270_TRANSFORM;
}
}
diff --git a/pixman/pixman/pixman-inlines.h b/pixman/pixman/pixman-inlines.h
index f78bc212f..13f901485 100644
--- a/pixman/pixman/pixman-inlines.h
+++ b/pixman/pixman/pixman-inlines.h
@@ -271,7 +271,7 @@ scanline_func_name (dst_type_t *dst, \
int32_t w, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x, \
- pixman_fixed_t max_vx, \
+ pixman_fixed_t src_width_fixed, \
pixman_bool_t fully_transparent_src) \
{ \
uint32_t d; \
@@ -287,25 +287,25 @@ scanline_func_name (dst_type_t *dst, \
\
while ((w -= 2) >= 0) \
{ \
- x1 = vx >> 16; \
+ x1 = pixman_fixed_to_int (vx); \
vx += unit_x; \
if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \
{ \
/* This works because we know that unit_x is positive */ \
- while (vx >= max_vx) \
- vx -= max_vx; \
+ while (vx >= 0) \
+ vx -= src_width_fixed; \
} \
- s1 = src[x1]; \
+ s1 = *(src + x1); \
\
- x2 = vx >> 16; \
+ x2 = pixman_fixed_to_int (vx); \
vx += unit_x; \
if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \
{ \
/* This works because we know that unit_x is positive */ \
- while (vx >= max_vx) \
- vx -= max_vx; \
+ while (vx >= 0) \
+ vx -= src_width_fixed; \
} \
- s2 = src[x2]; \
+ s2 = *(src + x2); \
\
if (PIXMAN_OP_ ## OP == PIXMAN_OP_OVER) \
{ \
@@ -349,8 +349,8 @@ scanline_func_name (dst_type_t *dst, \
\
if (w & 1) \
{ \
- x1 = vx >> 16; \
- s1 = src[x1]; \
+ x1 = pixman_fixed_to_int (vx); \
+ s1 = *(src + x1); \
\
if (PIXMAN_OP_ ## OP == PIXMAN_OP_OVER) \
{ \
@@ -388,7 +388,7 @@ fast_composite_scaled_nearest ## scale_func_name (pixman_implementation_t *imp,
mask_type_t *mask_line; \
src_type_t *src_first_line; \
int y; \
- pixman_fixed_t max_vx = INT32_MAX; /* suppress uninitialized variable warning */ \
+ pixman_fixed_t src_width_fixed = pixman_int_to_fixed (src_image->bits.width); \
pixman_fixed_t max_vy; \
pixman_vector_t v; \
pixman_fixed_t vx, vy; \
@@ -434,11 +434,10 @@ fast_composite_scaled_nearest ## scale_func_name (pixman_implementation_t *imp,
\
if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \
{ \
- /* Clamp repeating positions inside the actual samples */ \
- max_vx = src_image->bits.width << 16; \
- max_vy = src_image->bits.height << 16; \
+ max_vy = pixman_int_to_fixed (src_image->bits.height); \
\
- repeat (PIXMAN_REPEAT_NORMAL, &vx, max_vx); \
+ /* Clamp repeating positions inside the actual samples */ \
+ repeat (PIXMAN_REPEAT_NORMAL, &vx, src_width_fixed); \
repeat (PIXMAN_REPEAT_NORMAL, &vy, max_vy); \
} \
\
@@ -460,7 +459,7 @@ fast_composite_scaled_nearest ## scale_func_name (pixman_implementation_t *imp,
mask_line += mask_stride; \
} \
\
- y = vy >> 16; \
+ y = pixman_fixed_to_int (vy); \
vy += unit_y; \
if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \
repeat (PIXMAN_REPEAT_NORMAL, &vy, max_vy); \
@@ -470,18 +469,21 @@ fast_composite_scaled_nearest ## scale_func_name (pixman_implementation_t *imp,
src = src_first_line + src_stride * y; \
if (left_pad > 0) \
{ \
- scanline_func (mask, dst, src, left_pad, 0, 0, 0, FALSE); \
+ scanline_func (mask, dst, \
+ src + src_image->bits.width - src_image->bits.width + 1, \
+ left_pad, -pixman_fixed_e, 0, src_width_fixed, FALSE); \
} \
if (width > 0) \
{ \
scanline_func (mask + (mask_is_solid ? 0 : left_pad), \
- dst + left_pad, src, width, vx, unit_x, 0, FALSE); \
+ dst + left_pad, src + src_image->bits.width, width, \
+ vx - src_width_fixed, unit_x, src_width_fixed, FALSE); \
} \
if (right_pad > 0) \
{ \
scanline_func (mask + (mask_is_solid ? 0 : left_pad + width), \
- dst + left_pad + width, src + src_image->bits.width - 1, \
- right_pad, 0, 0, 0, FALSE); \
+ dst + left_pad + width, src + src_image->bits.width, \
+ right_pad, -pixman_fixed_e, 0, src_width_fixed, FALSE); \
} \
} \
else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \
@@ -489,29 +491,34 @@ fast_composite_scaled_nearest ## scale_func_name (pixman_implementation_t *imp,
static const src_type_t zero[1] = { 0 }; \
if (y < 0 || y >= src_image->bits.height) \
{ \
- scanline_func (mask, dst, zero, left_pad + width + right_pad, 0, 0, 0, TRUE); \
+ scanline_func (mask, dst, zero + 1, left_pad + width + right_pad, \
+ -pixman_fixed_e, 0, src_width_fixed, TRUE); \
continue; \
} \
src = src_first_line + src_stride * y; \
if (left_pad > 0) \
{ \
- scanline_func (mask, dst, zero, left_pad, 0, 0, 0, TRUE); \
+ scanline_func (mask, dst, zero + 1, left_pad, \
+ -pixman_fixed_e, 0, src_width_fixed, TRUE); \
} \
if (width > 0) \
{ \
scanline_func (mask + (mask_is_solid ? 0 : left_pad), \
- dst + left_pad, src, width, vx, unit_x, 0, FALSE); \
+ dst + left_pad, src + src_image->bits.width, width, \
+ vx - src_width_fixed, unit_x, src_width_fixed, FALSE); \
} \
if (right_pad > 0) \
{ \
scanline_func (mask + (mask_is_solid ? 0 : left_pad + width), \
- dst + left_pad + width, zero, right_pad, 0, 0, 0, TRUE); \
+ dst + left_pad + width, zero + 1, right_pad, \
+ -pixman_fixed_e, 0, src_width_fixed, TRUE); \
} \
} \
else \
{ \
src = src_first_line + src_stride * y; \
- scanline_func (mask, dst, src, width, vx, unit_x, max_vx, FALSE); \
+ scanline_func (mask, dst, src + src_image->bits.width, width, vx - src_width_fixed, \
+ unit_x, src_width_fixed, FALSE); \
} \
} \
}
@@ -859,7 +866,7 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
{ \
vx = v.vector[0]; \
repeat (PIXMAN_REPEAT_NORMAL, &vx, pixman_int_to_fixed(src_image->bits.width)); \
- max_x = pixman_fixed_to_int (vx + (width - 1) * unit_x) + 1; \
+ max_x = pixman_fixed_to_int (vx + (width - 1) * (int64_t)unit_x) + 1; \
\
if (src_image->bits.width < REPEAT_NORMAL_MIN_WIDTH) \
{ \
diff --git a/pixman/pixman/pixman-mips-dspr2-asm.S b/pixman/pixman/pixman-mips-dspr2-asm.S
index a8fccd5ad..3a6b26a30 100644
--- a/pixman/pixman/pixman-mips-dspr2-asm.S
+++ b/pixman/pixman/pixman-mips-dspr2-asm.S
@@ -749,6 +749,466 @@ LEAF_MIPS_DSPR2(pixman_composite_over_n_8_0565_asm_mips)
END(pixman_composite_over_n_8_0565_asm_mips)
+LEAF_MIPS_DSPR2(pixman_composite_over_8888_n_8888_asm_mips)
+/*
+ * a0 - dst (a8r8g8b8)
+ * a1 - src (a8r8g8b8)
+ * a2 - mask (32bit constant)
+ * a3 - w
+ */
+
+ SAVE_REGS_ON_STACK 0, s0
+ li t4, 0x00ff00ff
+ beqz a3, 3f
+ nop
+ addiu t1, a3, -1
+ srl a2, a2, 24
+ beqz t1, 2f
+ nop
+
+1:
+ lw t0, 0(a1) /* t0 = source (a8r8g8b8) */
+ lw t1, 4(a1) /* t1 = source (a8r8g8b8) */
+ /* a2 = mask (32bit constant) */
+ lw t2, 0(a0) /* t2 = destination (a8r8g8b8) */
+ lw t3, 4(a0) /* t3 = destination (a8r8g8b8) */
+ addiu a1, a1, 8
+
+ OVER_2x8888_2x8_2x8888 t0, t1, a2, a2, t2, t3, \
+ t5, t6, t4, t7, t8, t9, t0, t1, s0
+
+ sw t5, 0(a0)
+ sw t6, 4(a0)
+ addiu a3, a3, -2
+ addiu t1, a3, -1
+ bgtz t1, 1b
+ addiu a0, a0, 8
+2:
+ beqz a3, 3f
+ nop
+ lw t0, 0(a1) /* t0 = source (a8r8g8b8) */
+ /* a2 = mask (32bit constant) */
+ lw t1, 0(a0) /* t1 = destination (a8r8g8b8) */
+
+ OVER_8888_8_8888 t0, a2, t1, t3, t4, t5, t6, t7, t8
+
+ sw t3, 0(a0)
+3:
+ RESTORE_REGS_FROM_STACK 0, s0
+ j ra
+ nop
+
+END(pixman_composite_over_8888_n_8888_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_8888_n_0565_asm_mips)
+/*
+ * a0 - dst (r5g6b5)
+ * a1 - src (a8r8g8b8)
+ * a2 - mask (32bit constant)
+ * a3 - w
+ */
+
+ SAVE_REGS_ON_STACK 0, s0, s1, s2, s3
+ li t6, 0x00ff00ff
+ li t7, 0xf800f800
+ li t8, 0x07e007e0
+ li t9, 0x001F001F
+ beqz a3, 3f
+ nop
+ srl a2, a2, 24
+ addiu t1, a3, -1
+ beqz t1, 2f
+ nop
+1:
+ lw t0, 0(a1) /* t0 = source (a8r8g8b8) */
+ lw t1, 4(a1) /* t1 = source (a8r8g8b8) */
+ /* a2 = mask (32bit constant) */
+ lhu t2, 0(a0) /* t2 = destination (r5g6b5) */
+ lhu t3, 2(a0) /* t2 = destination (r5g6b5) */
+ addiu a1, a1, 8
+
+ CONVERT_2x0565_TO_2x8888 t2, t3, t4, t5, t8, t9, s0, s1, t2, t3
+ OVER_2x8888_2x8_2x8888 t0, t1, a2, a2, t4, t5, \
+ t2, t3, t6, t0, t1, s0, s1, s2, s3
+ CONVERT_2x8888_TO_2x0565 t2, t3, t4, t5, t7, t8, t9, s0, s1
+
+ sh t4, 0(a0)
+ sh t5, 2(a0)
+ addiu a3, a3, -2
+ addiu t1, a3, -1
+ bgtz t1, 1b
+ addiu a0, a0, 4
+2:
+ beqz a3, 3f
+ nop
+ lw t0, 0(a1) /* t0 = source (a8r8g8b8) */
+ /* a2 = mask (32bit constant) */
+ lhu t1, 0(a0) /* t1 = destination (r5g6b5) */
+
+ CONVERT_1x0565_TO_1x8888 t1, t2, t4, t5
+ OVER_8888_8_8888 t0, a2, t2, t1, t6, t3, t4, t5, t7
+ CONVERT_1x8888_TO_1x0565 t1, t3, t4, t5
+
+ sh t3, 0(a0)
+3:
+ RESTORE_REGS_FROM_STACK 0, s0, s1, s2, s3
+ j ra
+ nop
+
+END(pixman_composite_over_8888_n_0565_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_0565_n_0565_asm_mips)
+/*
+ * a0 - dst (r5g6b5)
+ * a1 - src (r5g6b5)
+ * a2 - mask (32bit constant)
+ * a3 - w
+ */
+
+ SAVE_REGS_ON_STACK 20, s0, s1, s2, s3, s4, s5
+ li t6, 0x00ff00ff
+ li t7, 0xf800f800
+ li t8, 0x07e007e0
+ li t9, 0x001F001F
+ beqz a3, 3f
+ nop
+ srl a2, a2, 24
+ addiu t1, a3, -1
+ beqz t1, 2f
+ nop
+1:
+ lhu t0, 0(a1) /* t0 = source (r5g6b5) */
+ lhu t1, 2(a1) /* t1 = source (r5g6b5) */
+ /* a2 = mask (32bit constant) */
+ lhu t2, 0(a0) /* t2 = destination (r5g6b5) */
+ lhu t3, 2(a0) /* t3 = destination (r5g6b5) */
+ addiu a1, a1, 4
+
+ CONVERT_2x0565_TO_2x8888 t0, t1, t4, t5, t8, t9, s0, s1, s2, s3
+ CONVERT_2x0565_TO_2x8888 t2, t3, s0, s1, t8, t9, s2, s3, s4, s5
+ OVER_2x8888_2x8_2x8888 t4, t5, a2, a2, s0, s1, \
+ t0, t1, t6, s2, s3, s4, s5, t4, t5
+ CONVERT_2x8888_TO_2x0565 t0, t1, s0, s1, t7, t8, t9, s2, s3
+
+ sh s0, 0(a0)
+ sh s1, 2(a0)
+ addiu a3, a3, -2
+ addiu t1, a3, -1
+ bgtz t1, 1b
+ addiu a0, a0, 4
+2:
+ beqz a3, 3f
+ nop
+ lhu t0, 0(a1) /* t0 = source (r5g6b5) */
+ /* a2 = mask (32bit constant) */
+ lhu t1, 0(a0) /* t1 = destination (r5g6b5) */
+
+ CONVERT_1x0565_TO_1x8888 t0, t2, t4, t5
+ CONVERT_1x0565_TO_1x8888 t1, t3, t4, t5
+ OVER_8888_8_8888 t2, a2, t3, t0, t6, t1, t4, t5, t7
+ CONVERT_1x8888_TO_1x0565 t0, t3, t4, t5
+
+ sh t3, 0(a0)
+3:
+ RESTORE_REGS_FROM_STACK 20, s0, s1, s2, s3, s4, s5
+ j ra
+ nop
+
+END(pixman_composite_over_0565_n_0565_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_8888_8_8888_asm_mips)
+/*
+ * a0 - dst (a8r8g8b8)
+ * a1 - src (a8r8g8b8)
+ * a2 - mask (a8)
+ * a3 - w
+ */
+
+ SAVE_REGS_ON_STACK 0, s0, s1
+ li t4, 0x00ff00ff
+ beqz a3, 3f
+ nop
+ addiu t1, a3, -1
+ beqz t1, 2f
+ nop
+1:
+ lw t0, 0(a1) /* t0 = source (a8r8g8b8) */
+ lw t1, 4(a1) /* t1 = source (a8r8g8b8) */
+ lbu t2, 0(a2) /* t2 = mask (a8) */
+ lbu t3, 1(a2) /* t3 = mask (a8) */
+ lw t5, 0(a0) /* t5 = destination (a8r8g8b8) */
+ lw t6, 4(a0) /* t6 = destination (a8r8g8b8) */
+ addiu a1, a1, 8
+ addiu a2, a2, 2
+
+ OVER_2x8888_2x8_2x8888 t0, t1, t2, t3, t5, t6, \
+ t7, t8, t4, t9, s0, s1, t0, t1, t2
+
+ sw t7, 0(a0)
+ sw t8, 4(a0)
+ addiu a3, a3, -2
+ addiu t1, a3, -1
+ bgtz t1, 1b
+ addiu a0, a0, 8
+2:
+ beqz a3, 3f
+ nop
+ lw t0, 0(a1) /* t0 = source (a8r8g8b8) */
+ lbu t1, 0(a2) /* t1 = mask (a8) */
+ lw t2, 0(a0) /* t2 = destination (a8r8g8b8) */
+
+ OVER_8888_8_8888 t0, t1, t2, t3, t4, t5, t6, t7, t8
+
+ sw t3, 0(a0)
+3:
+ RESTORE_REGS_FROM_STACK 0, s0, s1
+ j ra
+ nop
+
+END(pixman_composite_over_8888_8_8888_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_8888_8_0565_asm_mips)
+/*
+ * a0 - dst (r5g6b5)
+ * a1 - src (a8r8g8b8)
+ * a2 - mask (a8)
+ * a3 - w
+ */
+
+ SAVE_REGS_ON_STACK 20, s0, s1, s2, s3, s4, s5
+ li t6, 0x00ff00ff
+ li t7, 0xf800f800
+ li t8, 0x07e007e0
+ li t9, 0x001F001F
+ beqz a3, 3f
+ nop
+ addiu t1, a3, -1
+ beqz t1, 2f
+ nop
+1:
+ lw t0, 0(a1) /* t0 = source (a8r8g8b8) */
+ lw t1, 4(a1) /* t1 = source (a8r8g8b8) */
+ lbu t2, 0(a2) /* t2 = mask (a8) */
+ lbu t3, 1(a2) /* t3 = mask (a8) */
+ lhu t4, 0(a0) /* t4 = destination (r5g6b5) */
+ lhu t5, 2(a0) /* t5 = destination (r5g6b5) */
+ addiu a1, a1, 8
+ addiu a2, a2, 2
+
+ CONVERT_2x0565_TO_2x8888 t4, t5, s0, s1, t8, t9, s2, s3, s4, s5
+ OVER_2x8888_2x8_2x8888 t0, t1, t2, t3, s0, s1, \
+ t4, t5, t6, s2, s3, s4, s5, t0, t1
+ CONVERT_2x8888_TO_2x0565 t4, t5, s0, s1, t7, t8, t9, s2, s3
+
+ sh s0, 0(a0)
+ sh s1, 2(a0)
+ addiu a3, a3, -2
+ addiu t1, a3, -1
+ bgtz t1, 1b
+ addiu a0, a0, 4
+2:
+ beqz a3, 3f
+ nop
+ lw t0, 0(a1) /* t0 = source (a8r8g8b8) */
+ lbu t1, 0(a2) /* t1 = mask (a8) */
+ lhu t2, 0(a0) /* t2 = destination (r5g6b5) */
+
+ CONVERT_1x0565_TO_1x8888 t2, t3, t4, t5
+ OVER_8888_8_8888 t0, t1, t3, t2, t6, t4, t5, t7, t8
+ CONVERT_1x8888_TO_1x0565 t2, t3, t4, t5
+
+ sh t3, 0(a0)
+3:
+ RESTORE_REGS_FROM_STACK 20, s0, s1, s2, s3, s4, s5
+ j ra
+ nop
+
+END(pixman_composite_over_8888_8_0565_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_0565_8_0565_asm_mips)
+/*
+ * a0 - dst (r5g6b5)
+ * a1 - src (r5g6b5)
+ * a2 - mask (a8)
+ * a3 - w
+ */
+
+ SAVE_REGS_ON_STACK 20, s0, s1, s2, s3, s4, s5
+ li t4, 0xf800f800
+ li t5, 0x07e007e0
+ li t6, 0x001F001F
+ li t7, 0x00ff00ff
+ beqz a3, 3f
+ nop
+ addiu t1, a3, -1
+ beqz t1, 2f
+ nop
+1:
+ lhu t0, 0(a1) /* t0 = source (r5g6b5) */
+ lhu t1, 2(a1) /* t1 = source (r5g6b5) */
+ lbu t2, 0(a2) /* t2 = mask (a8) */
+ lbu t3, 1(a2) /* t3 = mask (a8) */
+ lhu t8, 0(a0) /* t8 = destination (r5g6b5) */
+ lhu t9, 2(a0) /* t9 = destination (r5g6b5) */
+ addiu a1, a1, 4
+ addiu a2, a2, 2
+
+ CONVERT_2x0565_TO_2x8888 t0, t1, s0, s1, t5, t6, s2, s3, s4, s5
+ CONVERT_2x0565_TO_2x8888 t8, t9, s2, s3, t5, t6, s4, s5, t0, t1
+ OVER_2x8888_2x8_2x8888 s0, s1, t2, t3, s2, s3, \
+ t0, t1, t7, s4, s5, t8, t9, s0, s1
+ CONVERT_2x8888_TO_2x0565 t0, t1, s0, s1, t4, t5, t6, s2, s3
+
+ sh s0, 0(a0)
+ sh s1, 2(a0)
+ addiu a3, a3, -2
+ addiu t1, a3, -1
+ bgtz t1, 1b
+ addiu a0, a0, 4
+2:
+ beqz a3, 3f
+ nop
+ lhu t0, 0(a1) /* t0 = source (r5g6b5) */
+ lbu t1, 0(a2) /* t1 = mask (a8) */
+ lhu t2, 0(a0) /* t2 = destination (r5g6b5) */
+
+ CONVERT_1x0565_TO_1x8888 t0, t3, t4, t5
+ CONVERT_1x0565_TO_1x8888 t2, t4, t5, t6
+ OVER_8888_8_8888 t3, t1, t4, t0, t7, t2, t5, t6, t8
+ CONVERT_1x8888_TO_1x0565 t0, t3, t4, t5
+
+ sh t3, 0(a0)
+3:
+ RESTORE_REGS_FROM_STACK 20, s0, s1, s2, s3, s4, s5
+ j ra
+ nop
+
+END(pixman_composite_over_0565_8_0565_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_8888_8888_8888_asm_mips)
+/*
+ * a0 - dst (a8r8g8b8)
+ * a1 - src (a8r8g8b8)
+ * a2 - mask (a8r8g8b8)
+ * a3 - w
+ */
+
+ SAVE_REGS_ON_STACK 0, s0, s1, s2
+ li t4, 0x00ff00ff
+ beqz a3, 3f
+ nop
+ addiu t1, a3, -1
+ beqz t1, 2f
+ nop
+1:
+ lw t0, 0(a1) /* t0 = source (a8r8g8b8) */
+ lw t1, 4(a1) /* t1 = source (a8r8g8b8) */
+ lw t2, 0(a2) /* t2 = mask (a8r8g8b8) */
+ lw t3, 4(a2) /* t3 = mask (a8r8g8b8) */
+ lw t5, 0(a0) /* t5 = destination (a8r8g8b8) */
+ lw t6, 4(a0) /* t6 = destination (a8r8g8b8) */
+ addiu a1, a1, 8
+ addiu a2, a2, 8
+ srl t2, t2, 24
+ srl t3, t3, 24
+
+ OVER_2x8888_2x8_2x8888 t0, t1, t2, t3, t5, t6, t7, t8, t4, t9, s0, s1, s2, t0, t1
+
+ sw t7, 0(a0)
+ sw t8, 4(a0)
+ addiu a3, a3, -2
+ addiu t1, a3, -1
+ bgtz t1, 1b
+ addiu a0, a0, 8
+2:
+ beqz a3, 3f
+ nop
+ lw t0, 0(a1) /* t0 = source (a8r8g8b8) */
+ lw t1, 0(a2) /* t1 = mask (a8r8g8b8) */
+ lw t2, 0(a0) /* t2 = destination (a8r8g8b8) */
+ srl t1, t1, 24
+
+ OVER_8888_8_8888 t0, t1, t2, t3, t4, t5, t6, t7, t8
+
+ sw t3, 0(a0)
+3:
+ RESTORE_REGS_FROM_STACK 0, s0, s1, s2
+ j ra
+ nop
+
+END(pixman_composite_over_8888_8888_8888_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_8888_8888_asm_mips)
+/*
+ * a0 - dst (a8r8g8b8)
+ * a1 - src (a8r8g8b8)
+ * a2 - w
+ */
+
+ SAVE_REGS_ON_STACK 0, s0, s1, s2
+ li t4, 0x00ff00ff
+ beqz a2, 3f
+ nop
+ addiu t1, a2, -1
+ beqz t1, 2f
+ nop
+1:
+ lw t0, 0(a1) /* t0 = source (a8r8g8b8) */
+ lw t1, 4(a1) /* t1 = source (a8r8g8b8) */
+ lw t2, 0(a0) /* t2 = destination (a8r8g8b8) */
+ lw t3, 4(a0) /* t3 = destination (a8r8g8b8) */
+ addiu a1, a1, 8
+
+ not t5, t0
+ srl t5, t5, 24
+ not t6, t1
+ srl t6, t6, 24
+
+ or t7, t5, t6
+ beqz t7, 11f
+ or t8, t0, t1
+ beqz t8, 12f
+
+ MIPS_2xUN8x4_MUL_2xUN8 t2, t3, t5, t6, t7, t8, t4, t9, s0, s1, s2, t2, t3
+
+ addu_s.qb t0, t7, t0
+ addu_s.qb t1, t8, t1
+11:
+ sw t0, 0(a0)
+ sw t1, 4(a0)
+12:
+ addiu a2, a2, -2
+ addiu t1, a2, -1
+ bgtz t1, 1b
+ addiu a0, a0, 8
+2:
+ beqz a2, 3f
+ nop
+
+ lw t0, 0(a1) /* t0 = source (a8r8g8b8) */
+ lw t1, 0(a0) /* t1 = destination (a8r8g8b8) */
+ addiu a1, a1, 4
+
+ not t2, t0
+ srl t2, t2, 24
+
+ beqz t2, 21f
+ nop
+ beqz t0, 3f
+
+ MIPS_UN8x4_MUL_UN8 t1, t2, t3, t4, t5, t6, t7
+
+ addu_s.qb t0, t3, t0
+21:
+ sw t0, 0(a0)
+
+3:
+ RESTORE_REGS_FROM_STACK 0, s0, s1, s2
+ j ra
+ nop
+
+END(pixman_composite_over_8888_8888_asm_mips)
+
LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_mips)
/*
* a0 - *dst
diff --git a/pixman/pixman/pixman-mips-dspr2.c b/pixman/pixman/pixman-mips-dspr2.c
index 1a9e6103a..e80bbb661 100644
--- a/pixman/pixman/pixman-mips-dspr2.c
+++ b/pixman/pixman/pixman-mips-dspr2.c
@@ -48,6 +48,8 @@ PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_8888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_0888_0888,
uint8_t, 3, uint8_t, 3)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, over_8888_8888,
+ uint32_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8888_8888_ca,
uint32_t, 1, uint32_t, 1)
@@ -58,6 +60,22 @@ PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_8888,
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_0565,
uint8_t, 1, uint16_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, over_8888_n_8888,
+ uint32_t, 1, uint32_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, over_8888_n_0565,
+ uint32_t, 1, uint16_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, over_0565_n_0565,
+ uint16_t, 1, uint16_t, 1)
+
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_8888_8_8888, uint32_t, 1,
+ uint8_t, 1, uint32_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_8888_8_0565, uint32_t, 1,
+ uint8_t, 1, uint16_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_0565_8_0565, uint16_t, 1,
+ uint8_t, 1, uint16_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_8888_8888_8888, uint32_t, 1,
+ uint32_t, 1, uint32_t, 1)
+
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_8888, SRC,
uint32_t, uint32_t)
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_0565, SRC,
@@ -234,6 +252,26 @@ static const pixman_fast_path_t mips_dspr2_fast_paths[] =
PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, mips_composite_over_n_8_0565),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, mips_composite_over_n_8_0565),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, mips_composite_over_8888_n_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, mips_composite_over_8888_n_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, r5g6b5, mips_composite_over_8888_n_0565),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, b5g6r5, mips_composite_over_8888_n_0565),
+ PIXMAN_STD_FAST_PATH (OVER, r5g6b5, solid, r5g6b5, mips_composite_over_0565_n_0565),
+ PIXMAN_STD_FAST_PATH (OVER, b5g6r5, solid, b5g6r5, mips_composite_over_0565_n_0565),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, a8r8g8b8, mips_composite_over_8888_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, x8r8g8b8, mips_composite_over_8888_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, a8b8g8r8, mips_composite_over_8888_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, x8b8g8r8, mips_composite_over_8888_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, r5g6b5, mips_composite_over_8888_8_0565),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, b5g6r5, mips_composite_over_8888_8_0565),
+ PIXMAN_STD_FAST_PATH (OVER, r5g6b5, a8, r5g6b5, mips_composite_over_0565_8_0565),
+ PIXMAN_STD_FAST_PATH (OVER, b5g6r5, a8, b5g6r5, mips_composite_over_0565_8_0565),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, a8r8g8b8, mips_composite_over_8888_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, mips_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, mips_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, mips_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, mips_composite_over_8888_8888),
+
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mips_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mips_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mips_8888_8888),
@@ -268,12 +306,30 @@ static const pixman_fast_path_t mips_dspr2_fast_paths[] =
{ PIXMAN_OP_NONE },
};
+static void
+mips_dspr2_combine_over_u (pixman_implementation_t *imp,
+ pixman_op_t op,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
+ int width)
+{
+ if (mask)
+ pixman_composite_over_8888_8888_8888_asm_mips (
+ dest, (uint32_t *)src, (uint32_t *)mask, width);
+ else
+ pixman_composite_over_8888_8888_asm_mips (
+ dest, (uint32_t *)src, width);
+}
+
pixman_implementation_t *
_pixman_implementation_create_mips_dspr2 (pixman_implementation_t *fallback)
{
pixman_implementation_t *imp =
_pixman_implementation_create (fallback, mips_dspr2_fast_paths);
+ imp->combine_32[PIXMAN_OP_OVER] = mips_dspr2_combine_over_u;
+
imp->blt = mips_dspr2_blt;
imp->fill = mips_dspr2_fill;
diff --git a/pixman/pixman/pixman-mips-dspr2.h b/pixman/pixman/pixman-mips-dspr2.h
index a3d774fcb..bddcfd827 100644
--- a/pixman/pixman/pixman-mips-dspr2.h
+++ b/pixman/pixman/pixman-mips-dspr2.h
@@ -127,6 +127,89 @@ mips_composite_##name (pixman_implementation_t *imp, \
} \
}
+/*******************************************************************/
+
+#define PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST(flags, name, \
+ src_type, src_cnt, \
+ dst_type, dst_cnt) \
+void \
+pixman_composite_##name##_asm_mips (dst_type *dst, \
+ src_type *src, \
+ uint32_t mask, \
+ int32_t w); \
+ \
+static void \
+mips_composite_##name (pixman_implementation_t *imp, \
+ pixman_composite_info_t *info) \
+{ \
+ PIXMAN_COMPOSITE_ARGS (info); \
+ dst_type *dst_line, *dst; \
+ src_type *src_line, *src; \
+ int32_t dst_stride, src_stride; \
+ uint32_t mask; \
+ \
+ mask = _pixman_image_get_solid ( \
+ imp, mask_image, dest_image->bits.format); \
+ \
+ if ((flags & SKIP_ZERO_MASK) && mask == 0) \
+ return; \
+ \
+ PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
+ dst_stride, dst_line, dst_cnt); \
+ PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
+ src_stride, src_line, src_cnt); \
+ \
+ while (height--) \
+ { \
+ dst = dst_line; \
+ dst_line += dst_stride; \
+ src = src_line; \
+ src_line += src_stride; \
+ \
+ pixman_composite_##name##_asm_mips (dst, src, mask, width); \
+ } \
+}
+
+/************************************************************************/
+
+#define PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST(name, src_type, src_cnt, \
+ mask_type, mask_cnt, \
+ dst_type, dst_cnt) \
+void \
+pixman_composite_##name##_asm_mips (dst_type *dst, \
+ src_type *src, \
+ mask_type *mask, \
+ int32_t w); \
+ \
+static void \
+mips_composite_##name (pixman_implementation_t *imp, \
+ pixman_composite_info_t *info) \
+{ \
+ PIXMAN_COMPOSITE_ARGS (info); \
+ dst_type *dst_line, *dst; \
+ src_type *src_line, *src; \
+ mask_type *mask_line, *mask; \
+ int32_t dst_stride, src_stride, mask_stride; \
+ \
+ PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
+ dst_stride, dst_line, dst_cnt); \
+ PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
+ src_stride, src_line, src_cnt); \
+ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \
+ mask_stride, mask_line, mask_cnt); \
+ \
+ while (height--) \
+ { \
+ dst = dst_line; \
+ dst_line += dst_stride; \
+ mask = mask_line; \
+ mask_line += mask_stride; \
+ src = src_line; \
+ src_line += src_stride; \
+ pixman_composite_##name##_asm_mips (dst, src, mask, width); \
+ } \
+}
+
/****************************************************************************/
#define PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST(flags, name, op, \
diff --git a/pixman/pixman/pixman-sse2.c b/pixman/pixman/pixman-sse2.c
index d9d96d672..29e3c2e7c 100644
--- a/pixman/pixman/pixman-sse2.c
+++ b/pixman/pixman/pixman-sse2.c
@@ -146,7 +146,7 @@ pack_565_2packedx128_128 (__m128i lo, __m128i hi)
return _mm_packs_epi32 (t0, t1);
}
-__m128i
+static force_inline __m128i
pack_565_2x128_128 (__m128i lo, __m128i hi)
{
__m128i data;
@@ -5159,7 +5159,7 @@ scaled_nearest_scanline_sse2_8888_8888_OVER (uint32_t* pd,
int32_t w,
pixman_fixed_t vx,
pixman_fixed_t unit_x,
- pixman_fixed_t max_vx,
+ pixman_fixed_t src_width_fixed,
pixman_bool_t fully_transparent_src)
{
uint32_t s, d;
@@ -5176,8 +5176,10 @@ scaled_nearest_scanline_sse2_8888_8888_OVER (uint32_t* pd,
while (w && ((unsigned long)pd & 15))
{
d = *pd;
- s = combine1 (ps + (vx >> 16), pm);
+ s = combine1 (ps + pixman_fixed_to_int (vx), pm);
vx += unit_x;
+ while (vx >= 0)
+ vx -= src_width_fixed;
*pd++ = core_combine_over_u_pixel_sse2 (s, d);
if (pm)
@@ -5190,14 +5192,22 @@ scaled_nearest_scanline_sse2_8888_8888_OVER (uint32_t* pd,
__m128i tmp;
uint32_t tmp1, tmp2, tmp3, tmp4;
- tmp1 = ps[vx >> 16];
+ tmp1 = *(ps + pixman_fixed_to_int (vx));
vx += unit_x;
- tmp2 = ps[vx >> 16];
+ while (vx >= 0)
+ vx -= src_width_fixed;
+ tmp2 = *(ps + pixman_fixed_to_int (vx));
vx += unit_x;
- tmp3 = ps[vx >> 16];
+ while (vx >= 0)
+ vx -= src_width_fixed;
+ tmp3 = *(ps + pixman_fixed_to_int (vx));
vx += unit_x;
- tmp4 = ps[vx >> 16];
+ while (vx >= 0)
+ vx -= src_width_fixed;
+ tmp4 = *(ps + pixman_fixed_to_int (vx));
vx += unit_x;
+ while (vx >= 0)
+ vx -= src_width_fixed;
tmp = _mm_set_epi32 (tmp4, tmp3, tmp2, tmp1);
@@ -5235,8 +5245,10 @@ scaled_nearest_scanline_sse2_8888_8888_OVER (uint32_t* pd,
while (w)
{
d = *pd;
- s = combine1 (ps + (vx >> 16), pm);
+ s = combine1 (ps + pixman_fixed_to_int (vx), pm);
vx += unit_x;
+ while (vx >= 0)
+ vx -= src_width_fixed;
*pd++ = core_combine_over_u_pixel_sse2 (s, d);
if (pm)
@@ -5255,6 +5267,9 @@ FAST_NEAREST_MAINLOOP (sse2_8888_8888_none_OVER,
FAST_NEAREST_MAINLOOP (sse2_8888_8888_pad_OVER,
scaled_nearest_scanline_sse2_8888_8888_OVER,
uint32_t, uint32_t, PAD)
+FAST_NEAREST_MAINLOOP (sse2_8888_8888_normal_OVER,
+ scaled_nearest_scanline_sse2_8888_8888_OVER,
+ uint32_t, uint32_t, NORMAL)
static force_inline void
scaled_nearest_scanline_sse2_8888_n_8888_OVER (const uint32_t * mask,
@@ -5263,7 +5278,7 @@ scaled_nearest_scanline_sse2_8888_n_8888_OVER (const uint32_t * mask,
int32_t w,
pixman_fixed_t vx,
pixman_fixed_t unit_x,
- pixman_fixed_t max_vx,
+ pixman_fixed_t src_width_fixed,
pixman_bool_t zero_src)
{
__m128i xmm_mask;
@@ -5278,8 +5293,10 @@ scaled_nearest_scanline_sse2_8888_n_8888_OVER (const uint32_t * mask,
while (w && (unsigned long)dst & 15)
{
- uint32_t s = src[pixman_fixed_to_int (vx)];
+ uint32_t s = *(src + pixman_fixed_to_int (vx));
vx += unit_x;
+ while (vx >= 0)
+ vx -= src_width_fixed;
if (s)
{
@@ -5301,14 +5318,22 @@ scaled_nearest_scanline_sse2_8888_n_8888_OVER (const uint32_t * mask,
{
uint32_t tmp1, tmp2, tmp3, tmp4;
- tmp1 = src[pixman_fixed_to_int (vx)];
+ tmp1 = *(src + pixman_fixed_to_int (vx));
vx += unit_x;
- tmp2 = src[pixman_fixed_to_int (vx)];
+ while (vx >= 0)
+ vx -= src_width_fixed;
+ tmp2 = *(src + pixman_fixed_to_int (vx));
vx += unit_x;
- tmp3 = src[pixman_fixed_to_int (vx)];
+ while (vx >= 0)
+ vx -= src_width_fixed;
+ tmp3 = *(src + pixman_fixed_to_int (vx));
vx += unit_x;
- tmp4 = src[pixman_fixed_to_int (vx)];
+ while (vx >= 0)
+ vx -= src_width_fixed;
+ tmp4 = *(src + pixman_fixed_to_int (vx));
vx += unit_x;
+ while (vx >= 0)
+ vx -= src_width_fixed;
xmm_src = _mm_set_epi32 (tmp4, tmp3, tmp2, tmp1);
@@ -5336,8 +5361,10 @@ scaled_nearest_scanline_sse2_8888_n_8888_OVER (const uint32_t * mask,
while (w)
{
- uint32_t s = src[pixman_fixed_to_int (vx)];
+ uint32_t s = *(src + pixman_fixed_to_int (vx));
vx += unit_x;
+ while (vx >= 0)
+ vx -= src_width_fixed;
if (s)
{
@@ -5367,6 +5394,9 @@ FAST_NEAREST_MAINLOOP_COMMON (sse2_8888_n_8888_pad_OVER,
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)
+FAST_NEAREST_MAINLOOP_COMMON (sse2_8888_n_8888_normal_OVER,
+ scaled_nearest_scanline_sse2_8888_n_8888_OVER,
+ uint32_t, uint32_t, uint32_t, NORMAL, TRUE, TRUE)
#define BMSK ((1 << BILINEAR_INTERPOLATION_BITS) - 1)
@@ -5856,11 +5886,19 @@ static const pixman_fast_path_t sse2_fast_paths[] =
SIMPLE_NEAREST_FAST_PATH_PAD (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_8888),
SIMPLE_NEAREST_FAST_PATH_PAD (OVER, a8r8g8b8, a8r8g8b8, sse2_8888_8888),
SIMPLE_NEAREST_FAST_PATH_PAD (OVER, a8b8g8r8, a8b8g8r8, sse2_8888_8888),
+ SIMPLE_NEAREST_FAST_PATH_NORMAL (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_8888),
+ SIMPLE_NEAREST_FAST_PATH_NORMAL (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_8888),
+ SIMPLE_NEAREST_FAST_PATH_NORMAL (OVER, a8r8g8b8, a8r8g8b8, sse2_8888_8888),
+ SIMPLE_NEAREST_FAST_PATH_NORMAL (OVER, a8b8g8r8, a8b8g8r8, sse2_8888_8888),
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, sse2_8888_n_8888),
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, sse2_8888_n_8888),
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_NEAREST_SOLID_MASK_FAST_PATH_NORMAL (OVER, a8r8g8b8, a8r8g8b8, sse2_8888_n_8888),
+ SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NORMAL (OVER, a8b8g8r8, a8b8g8r8, sse2_8888_n_8888),
+ SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NORMAL (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_n_8888),
+ SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NORMAL (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),
diff --git a/pixman/test/Makefile.sources b/pixman/test/Makefile.sources
index fad8c6f69..0f344116d 100644
--- a/pixman/test/Makefile.sources
+++ b/pixman/test/Makefile.sources
@@ -5,7 +5,9 @@ TESTPROGRAMS = \
region-test \
region-translate-test \
fetch-test \
+ rotate-test \
oob-test \
+ infinite-loop \
trap-crasher \
alpha-loop \
scaling-crash-test \
diff --git a/pixman/test/affine-test.c b/pixman/test/affine-test.c
index 6827cc3a8..7bc28b4cd 100644
--- a/pixman/test/affine-test.c
+++ b/pixman/test/affine-test.c
@@ -200,11 +200,19 @@ test_composite (int testnum,
if (verbose)
{
+#define M(r,c) \
+ transform.matrix[r][c]
+
printf ("src_fmt=%08X, dst_fmt=%08X\n", src_fmt, dst_fmt);
- printf ("op=%d, scale_x=%d, scale_y=%d, repeat=%d\n",
- op, scale_x, scale_y, repeat);
- printf ("translate_x=%d, translate_y=%d\n",
- translate_x, translate_y);
+ printf ("op=%d, repeat=%d, transform=\n",
+ op, repeat);
+ printf (" { { { 0x%08x, 0x%08x, 0x%08x },\n"
+ " { 0x%08x, 0x%08x, 0x%08x },\n"
+ " { 0x%08x, 0x%08x, 0x%08x },\n"
+ " } };\n",
+ M(0,0), M(0,1), M(0,2),
+ M(1,0), M(1,1), M(1,2),
+ M(2,0), M(2,1), M(2,2));
printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n",
src_width, src_height, dst_width, dst_height);
printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n",
diff --git a/pixman/test/blitters-test.c b/pixman/test/blitters-test.c
index 6a3cc8649..8c46cef97 100644
--- a/pixman/test/blitters-test.c
+++ b/pixman/test/blitters-test.c
@@ -395,6 +395,6 @@ main (int argc, const char *argv[])
}
return fuzzer_test_main("blitters", 2000000,
- 0xA364B5BF,
+ 0x3E1DD2E8,
test_composite, argc, argv);
}
diff --git a/pixman/test/infinite-loop.c b/pixman/test/infinite-loop.c
new file mode 100644
index 000000000..02addaab2
--- /dev/null
+++ b/pixman/test/infinite-loop.c
@@ -0,0 +1,39 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "utils.h"
+
+int
+main (int argc, char **argv)
+{
+#define SRC_WIDTH 16
+#define SRC_HEIGHT 12
+#define DST_WIDTH 7
+#define DST_HEIGHT 2
+
+ static const pixman_transform_t transform = {
+ { { 0x200017bd, 0x00000000, 0x000e6465 },
+ { 0x00000000, 0x000a42fd, 0x000e6465 },
+ { 0x00000000, 0x00000000, 0x00010000 },
+ }
+ };
+ pixman_image_t *src, *dest;
+
+ src = pixman_image_create_bits (
+ PIXMAN_a8r8g8b8, SRC_WIDTH, SRC_HEIGHT, NULL, -1);
+ dest = pixman_image_create_bits (
+ PIXMAN_a8r8g8b8, DST_WIDTH, DST_HEIGHT, NULL, -1);
+
+ pixman_image_set_transform (src, &transform);
+ pixman_image_set_repeat (src, PIXMAN_REPEAT_NORMAL);
+ pixman_image_set_filter (src, PIXMAN_FILTER_BILINEAR, NULL, 0);
+
+ if (argc == 1 || strcmp (argv[1], "-nf") != 0)
+ fail_after (1, "infinite loop detected");
+
+ pixman_image_composite (
+ PIXMAN_OP_OVER, src, NULL, dest, -3, -3, 0, 0, 0, 0, 6, 2);
+
+ return 0;
+}
diff --git a/pixman/test/rotate-test.c b/pixman/test/rotate-test.c
new file mode 100644
index 000000000..bc44281e3
--- /dev/null
+++ b/pixman/test/rotate-test.c
@@ -0,0 +1,111 @@
+#include <stdlib.h>
+#include "utils.h"
+
+#define WIDTH 32
+#define HEIGHT 32
+
+static const pixman_format_code_t formats[] =
+{
+ PIXMAN_a8r8g8b8,
+ PIXMAN_a8b8g8r8,
+ PIXMAN_x8r8g8b8,
+ PIXMAN_x8b8g8r8,
+ PIXMAN_r5g6b5,
+ PIXMAN_b5g6r5,
+ PIXMAN_a8,
+ PIXMAN_a1,
+};
+
+static const pixman_op_t ops[] =
+{
+ PIXMAN_OP_OVER,
+ PIXMAN_OP_SRC,
+ PIXMAN_OP_ADD,
+};
+
+#define TRANSFORM(v00, v01, v10, v11) \
+ { { { v00, v01, WIDTH * pixman_fixed_1 / 2 }, \
+ { v10, v11, HEIGHT * pixman_fixed_1 / 2 }, \
+ { 0, 0, pixman_fixed_1 } } }
+
+#define F1 pixman_fixed_1
+
+static const pixman_transform_t transforms[] =
+{
+ TRANSFORM (0, -1, 1, 0), /* wrong 90 degree rotation */
+ TRANSFORM (0, 1, -1, 0), /* wrong 270 degree rotation */
+ TRANSFORM (1, 0, 0, 1), /* wrong identity */
+ TRANSFORM (-1, 0, 0, -1), /* wrong 180 degree rotation */
+ TRANSFORM (0, -F1, F1, 0), /* correct 90 degree rotation */
+ TRANSFORM (0, F1, -F1, 0), /* correct 270 degree rotation */
+ TRANSFORM (F1, 0, 0, F1), /* correct identity */
+ TRANSFORM (-F1, 0, 0, -F1), /* correct 180 degree rotation */
+};
+
+#define RANDOM_FORMAT() \
+ (formats[lcg_rand_n (ARRAY_LENGTH (formats))])
+
+#define RANDOM_OP() \
+ (ops[lcg_rand_n (ARRAY_LENGTH (ops))])
+
+#define RANDOM_TRANSFORM() \
+ (&(transforms[lcg_rand_n (ARRAY_LENGTH (transforms))]))
+
+static void
+on_destroy (pixman_image_t *image, void *data)
+{
+ free (data);
+}
+
+static pixman_image_t *
+make_image (void)
+{
+ pixman_format_code_t format = RANDOM_FORMAT();
+ uint32_t *bytes = malloc (WIDTH * HEIGHT * 4);
+ pixman_image_t *image;
+ int i;
+
+ for (i = 0; i < WIDTH * HEIGHT * 4; ++i)
+ ((uint8_t *)bytes)[i] = lcg_rand_n (256);
+
+ image = pixman_image_create_bits (
+ format, WIDTH, HEIGHT, bytes, WIDTH * 4);
+
+ pixman_image_set_transform (image, RANDOM_TRANSFORM());
+ pixman_image_set_destroy_function (image, on_destroy, bytes);
+ pixman_image_set_repeat (image, PIXMAN_REPEAT_NORMAL);
+
+ return image;
+}
+
+static uint32_t
+test_transform (int testnum, int verbose)
+{
+ pixman_image_t *src, *dest;
+ uint32_t crc;
+
+ lcg_srand (testnum);
+
+ src = make_image ();
+ dest = make_image ();
+
+ pixman_image_composite (RANDOM_OP(),
+ src, NULL, dest,
+ 0, 0, 0, 0, WIDTH / 2, HEIGHT / 2,
+ WIDTH, HEIGHT);
+
+ crc = compute_crc32_for_image (0, dest);
+
+ pixman_image_unref (src);
+ pixman_image_unref (dest);
+
+ return crc;
+}
+
+int
+main (int argc, const char *argv[])
+{
+ return fuzzer_test_main ("rotate", 15000,
+ 0x03A24D51,
+ test_transform, argc, argv);
+}