diff options
33 files changed, 3124 insertions, 1841 deletions
@@ -18,6 +18,7 @@ Copyright 2008 Rodrigo Kumpera Copyright 2008 André Tupinambá Copyright 2008 Mozilla Corporation Copyright 2008 Frederic Plourde +Copyright 2009 Sun Microsystems, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -48,7 +48,6 @@ Here are the steps to follow to create a new pixman release: xorg-announce@lists.freedesktop.org - 7) Increment pixman_micro to the next larger (odd) number in configure.ac. Commit this change, and push all commits created during this process using diff --git a/configure.ac b/configure.ac index 8ee91d3..df0965e 100644 --- a/configure.ac +++ b/configure.ac @@ -54,7 +54,7 @@ AC_PREREQ([2.57]) m4_define([pixman_major], 0) m4_define([pixman_minor], 17) -m4_define([pixman_micro], 1) +m4_define([pixman_micro], 7) m4_define([pixman_version],[pixman_major.pixman_minor.pixman_micro]) @@ -253,7 +253,7 @@ AC_COMPILE_IFELSE([ #include <xmmintrin.h> #include <emmintrin.h> int main () { - __m128i a, b, c; + __m128i a = _mm_set1_epi32 (0), b = _mm_set1_epi32 (0), c; c = _mm_xor_si128 (a, b); return 0; }], have_sse2_intrinsics=yes) diff --git a/pixman/pixman-arm-neon-asm.S b/pixman/pixman-arm-neon-asm.S index e8ccf77..2986884 100644 --- a/pixman/pixman-arm-neon-asm.S +++ b/pixman/pixman-arm-neon-asm.S @@ -1,24 +1,24 @@ /* * Copyright © 2009 Nokia Corporation * - * 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 Nokia Corporation not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Nokia Corporation makes no - * representations about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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. + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. * * Author: Siarhei Siamashka (siarhei.siamashka@nokia.com) */ @@ -41,6 +41,7 @@ .text .fpu neon + .arch armv7a .altmacro #include "pixman-arm-neon-asm.h" @@ -343,6 +344,75 @@ generate_composite_function \ /******************************************************************************/ +.macro pixman_composite_over_n_0565_process_pixblock_head + /* convert 8 r5g6b5 pixel data from {d4, d5} to planar 8-bit format + and put data into d6 - red, d7 - green, d30 - blue */ + vshrn.u16 d6, q2, #8 + vshrn.u16 d7, q2, #3 + vsli.u16 q2, q2, #5 + vsri.u8 d6, d6, #5 + vsri.u8 d7, d7, #6 + vshrn.u16 d30, q2, #2 + /* now do alpha blending, storing results in 8-bit planar format + into d16 - red, d19 - green, d18 - blue */ + vmull.u8 q10, d3, d6 + vmull.u8 q11, d3, d7 + vmull.u8 q12, d3, d30 + vrshr.u16 q13, q10, #8 + vrshr.u16 q3, q11, #8 + vrshr.u16 q15, q12, #8 + vraddhn.u16 d20, q10, q13 + vraddhn.u16 d23, q11, q3 + vraddhn.u16 d22, q12, q15 +.endm + +.macro pixman_composite_over_n_0565_process_pixblock_tail + /* ... continue alpha blending */ + vqadd.u8 d16, d2, d20 + vqadd.u8 q9, q0, q11 + /* convert the result to r5g6b5 and store it into {d28, d29} */ + vshll.u8 q14, d16, #8 + vshll.u8 q8, d19, #8 + vshll.u8 q9, d18, #8 + vsri.u16 q14, q8, #5 + vsri.u16 q14, q9, #11 +.endm + +/* TODO: expand macros and do better instructions scheduling */ +.macro pixman_composite_over_n_0565_process_pixblock_tail_head + pixman_composite_over_n_0565_process_pixblock_tail + vld1.16 {d4, d5}, [DST_R, :128]! + vst1.16 {d28, d29}, [DST_W, :128]! + pixman_composite_over_n_0565_process_pixblock_head +.endm + +.macro pixman_composite_over_n_0565_init + add DUMMY, sp, #ARGS_STACK_OFFSET + vld1.32 {d3[0]}, [DUMMY] + vdup.8 d0, d3[0] + vdup.8 d1, d3[1] + vdup.8 d2, d3[2] + vdup.8 d3, d3[3] + vmvn.8 d3, d3 /* invert source alpha */ +.endm + +generate_composite_function \ + pixman_composite_over_n_0565_asm_neon, 0, 0, 16, \ + FLAG_DST_READWRITE, \ + 8, /* number of pixels, processed in a single block */ \ + 5, /* prefetch distance */ \ + pixman_composite_over_n_0565_init, \ + default_cleanup, \ + pixman_composite_over_n_0565_process_pixblock_head, \ + pixman_composite_over_n_0565_process_pixblock_tail, \ + pixman_composite_over_n_0565_process_pixblock_tail_head, \ + 28, /* dst_w_basereg */ \ + 4, /* dst_r_basereg */ \ + 0, /* src_basereg */ \ + 24 /* mask_basereg */ + +/******************************************************************************/ + .macro pixman_composite_src_8888_0565_process_pixblock_head vshll.u8 q8, d1, #8 vshll.u8 q14, d2, #8 @@ -386,6 +456,41 @@ generate_composite_function \ /******************************************************************************/ +.macro pixman_composite_src_0565_8888_process_pixblock_head + vshrn.u16 d30, q0, #8 + vshrn.u16 d29, q0, #3 + vsli.u16 q0, q0, #5 + vmov.u8 d31, #255 + vsri.u8 d30, d30, #5 + vsri.u8 d29, d29, #6 + vshrn.u16 d28, q0, #2 +.endm + +.macro pixman_composite_src_0565_8888_process_pixblock_tail +.endm + +/* TODO: expand macros and do better instructions scheduling */ +.macro pixman_composite_src_0565_8888_process_pixblock_tail_head + pixman_composite_src_0565_8888_process_pixblock_tail + vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! + vld1.16 {d0, d1}, [SRC]! + pixman_composite_src_0565_8888_process_pixblock_head + cache_preload 8, 8 +.endm + +generate_composite_function \ + pixman_composite_src_0565_8888_asm_neon, 16, 0, 32, \ + FLAG_DST_WRITEONLY | FLAG_DEINTERLEAVE_32BPP, \ + 8, /* number of pixels, processed in a single block */ \ + 10, /* prefetch distance */ \ + default_init, \ + default_cleanup, \ + pixman_composite_src_0565_8888_process_pixblock_head, \ + pixman_composite_src_0565_8888_process_pixblock_tail, \ + pixman_composite_src_0565_8888_process_pixblock_tail_head + +/******************************************************************************/ + .macro pixman_composite_add_8000_8000_process_pixblock_head vqadd.u8 q14, q0, q2 vqadd.u8 q15, q1, q3 @@ -426,6 +531,48 @@ generate_composite_function \ /******************************************************************************/ +.macro pixman_composite_add_8888_8888_process_pixblock_tail_head + vld1.8 {d0, d1, d2, d3}, [SRC]! + PF add PF_X, PF_X, #8 + PF tst PF_CTL, #0xF + vld1.8 {d4, d5, d6, d7}, [DST_R, :128]! + PF addne PF_X, PF_X, #8 + PF subne PF_CTL, PF_CTL, #1 + vst1.8 {d28, d29, d30, d31}, [DST_W, :128]! + PF cmp PF_X, ORIG_W + PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] + PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] + PF subge PF_X, PF_X, ORIG_W + PF subges PF_CTL, PF_CTL, #0x10 + vqadd.u8 q14, q0, q2 + PF ldrgeb DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! + PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! + vqadd.u8 q15, q1, q3 +.endm + +generate_composite_function \ + pixman_composite_add_8888_8888_asm_neon, 32, 0, 32, \ + FLAG_DST_READWRITE, \ + 8, /* number of pixels, processed in a single block */ \ + 10, /* prefetch distance */ \ + default_init, \ + default_cleanup, \ + pixman_composite_add_8000_8000_process_pixblock_head, \ + pixman_composite_add_8000_8000_process_pixblock_tail, \ + pixman_composite_add_8888_8888_process_pixblock_tail_head + +generate_composite_function_single_scanline \ + pixman_composite_scanline_add_asm_neon, 32, 0, 32, \ + FLAG_DST_READWRITE, \ + 8, /* number of pixels, processed in a single block */ \ + default_init, \ + default_cleanup, \ + pixman_composite_add_8000_8000_process_pixblock_head, \ + pixman_composite_add_8000_8000_process_pixblock_tail, \ + pixman_composite_add_8888_8888_process_pixblock_tail_head + +/******************************************************************************/ + .macro pixman_composite_over_8888_8888_process_pixblock_head vmvn.8 d24, d3 /* get inverted alpha */ /* do alpha blending */ @@ -491,6 +638,46 @@ generate_composite_function \ pixman_composite_over_8888_8888_process_pixblock_tail, \ pixman_composite_over_8888_8888_process_pixblock_tail_head +generate_composite_function_single_scanline \ + pixman_composite_scanline_over_asm_neon, 32, 0, 32, \ + FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ + 8, /* number of pixels, processed in a single block */ \ + default_init, \ + default_cleanup, \ + pixman_composite_over_8888_8888_process_pixblock_head, \ + pixman_composite_over_8888_8888_process_pixblock_tail, \ + pixman_composite_over_8888_8888_process_pixblock_tail_head + +/******************************************************************************/ + +/* TODO: expand macros and do better instructions scheduling */ +.macro pixman_composite_over_n_8888_process_pixblock_tail_head + pixman_composite_over_8888_8888_process_pixblock_tail + vld4.8 {d4, d5, d6, d7}, [DST_R, :128]! + vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! + pixman_composite_over_8888_8888_process_pixblock_head +.endm + +.macro pixman_composite_over_n_8888_init + add DUMMY, sp, #ARGS_STACK_OFFSET + vld1.32 {d3[0]}, [DUMMY] + vdup.8 d0, d3[0] + vdup.8 d1, d3[1] + vdup.8 d2, d3[2] + vdup.8 d3, d3[3] +.endm + +generate_composite_function \ + pixman_composite_over_n_8888_asm_neon, 0, 0, 32, \ + FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ + 8, /* number of pixels, processed in a single block */ \ + 5, /* prefetch distance */ \ + pixman_composite_over_n_8888_init, \ + default_cleanup, \ + pixman_composite_over_8888_8888_process_pixblock_head, \ + pixman_composite_over_8888_8888_process_pixblock_tail, \ + pixman_composite_over_n_8888_process_pixblock_tail_head + /******************************************************************************/ .macro pixman_composite_over_n_8_0565_process_pixblock_head @@ -950,6 +1137,63 @@ generate_composite_function \ /******************************************************************************/ +.macro pixman_composite_add_8888_8888_8888_process_pixblock_head + /* expecting source data in {d0, d1, d2, d3} */ + /* destination data in {d4, d5, d6, d7} */ + /* mask in {d24, d25, d26, d27} */ + vmull.u8 q8, d27, d0 + vmull.u8 q9, d27, d1 + vmull.u8 q10, d27, d2 + vmull.u8 q11, d27, d3 + vrshr.u16 q0, q8, #8 + vrshr.u16 q1, q9, #8 + vrshr.u16 q12, q10, #8 + vrshr.u16 q13, q11, #8 + vraddhn.u16 d0, q0, q8 + vraddhn.u16 d1, q1, q9 + vraddhn.u16 d2, q12, q10 + vraddhn.u16 d3, q13, q11 + vqadd.u8 q14, q0, q2 + vqadd.u8 q15, q1, q3 +.endm + +.macro pixman_composite_add_8888_8888_8888_process_pixblock_tail +.endm + +/* TODO: expand macros and do better instructions scheduling */ +.macro pixman_composite_add_8888_8888_8888_process_pixblock_tail_head + pixman_composite_add_8888_8888_8888_process_pixblock_tail + vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! + vld4.8 {d4, d5, d6, d7}, [DST_R, :128]! + vld4.8 {d24, d25, d26, d27}, [MASK]! + vld4.8 {d0, d1, d2, d3}, [SRC]! + cache_preload 8, 8 + pixman_composite_add_8888_8888_8888_process_pixblock_head +.endm + +generate_composite_function \ + pixman_composite_add_8888_8888_8888_asm_neon, 32, 32, 32, \ + FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ + 8, /* number of pixels, processed in a single block */ \ + 10, /* prefetch distance */ \ + default_init, \ + default_cleanup, \ + pixman_composite_add_8888_8888_8888_process_pixblock_head, \ + pixman_composite_add_8888_8888_8888_process_pixblock_tail, \ + pixman_composite_add_8888_8888_8888_process_pixblock_tail_head + +generate_composite_function_single_scanline \ + pixman_composite_scanline_add_mask_asm_neon, 32, 32, 32, \ + FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ + 8, /* number of pixels, processed in a single block */ \ + default_init, \ + default_cleanup, \ + pixman_composite_add_8888_8888_8888_process_pixblock_head, \ + pixman_composite_add_8888_8888_8888_process_pixblock_tail, \ + pixman_composite_add_8888_8888_8888_process_pixblock_tail_head + +/******************************************************************************/ + .macro pixman_composite_over_8888_n_8888_process_pixblock_head /* expecting source data in {d0, d1, d2, d3} */ /* destination data in {d4, d5, d6, d7} */ @@ -1023,6 +1267,92 @@ generate_composite_function \ /******************************************************************************/ +/* TODO: expand macros and do better instructions scheduling */ +.macro pixman_composite_over_8888_8888_8888_process_pixblock_tail_head + vld4.8 {d4, d5, d6, d7}, [DST_R, :128]! + pixman_composite_over_8888_n_8888_process_pixblock_tail + vld4.8 {d0, d1, d2, d3}, [SRC]! + cache_preload 8, 8 + vld4.8 {d12, d13, d14, d15}, [MASK]! + pixman_composite_over_8888_n_8888_process_pixblock_head + vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! +.endm + +.macro pixman_composite_over_8888_8888_8888_init + vpush {d8-d15} +.endm + +.macro pixman_composite_over_8888_8888_8888_cleanup + vpop {d8-d15} +.endm + +generate_composite_function \ + pixman_composite_over_8888_8888_8888_asm_neon, 32, 32, 32, \ + FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ + 8, /* number of pixels, processed in a single block */ \ + 5, /* prefetch distance */ \ + pixman_composite_over_8888_8888_8888_init, \ + pixman_composite_over_8888_8888_8888_cleanup, \ + pixman_composite_over_8888_n_8888_process_pixblock_head, \ + pixman_composite_over_8888_n_8888_process_pixblock_tail, \ + pixman_composite_over_8888_8888_8888_process_pixblock_tail_head \ + 28, /* dst_w_basereg */ \ + 4, /* dst_r_basereg */ \ + 0, /* src_basereg */ \ + 12 /* mask_basereg */ + +generate_composite_function_single_scanline \ + pixman_composite_scanline_over_mask_asm_neon, 32, 32, 32, \ + FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ + 8, /* number of pixels, processed in a single block */ \ + pixman_composite_over_8888_8888_8888_init, \ + pixman_composite_over_8888_8888_8888_cleanup, \ + pixman_composite_over_8888_n_8888_process_pixblock_head, \ + pixman_composite_over_8888_n_8888_process_pixblock_tail, \ + pixman_composite_over_8888_8888_8888_process_pixblock_tail_head \ + 28, /* dst_w_basereg */ \ + 4, /* dst_r_basereg */ \ + 0, /* src_basereg */ \ + 12 /* mask_basereg */ + +/******************************************************************************/ + +/* TODO: expand macros and do better instructions scheduling */ +.macro pixman_composite_over_8888_8_8888_process_pixblock_tail_head + vld4.8 {d4, d5, d6, d7}, [DST_R, :128]! + pixman_composite_over_8888_n_8888_process_pixblock_tail + vld4.8 {d0, d1, d2, d3}, [SRC]! + cache_preload 8, 8 + vld1.8 {d15}, [MASK]! + pixman_composite_over_8888_n_8888_process_pixblock_head + vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! +.endm + +.macro pixman_composite_over_8888_8_8888_init + vpush {d8-d15} +.endm + +.macro pixman_composite_over_8888_8_8888_cleanup + vpop {d8-d15} +.endm + +generate_composite_function \ + pixman_composite_over_8888_8_8888_asm_neon, 32, 8, 32, \ + FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ + 8, /* number of pixels, processed in a single block */ \ + 5, /* prefetch distance */ \ + pixman_composite_over_8888_8_8888_init, \ + pixman_composite_over_8888_8_8888_cleanup, \ + pixman_composite_over_8888_n_8888_process_pixblock_head, \ + pixman_composite_over_8888_n_8888_process_pixblock_tail, \ + pixman_composite_over_8888_8_8888_process_pixblock_tail_head \ + 28, /* dst_w_basereg */ \ + 4, /* dst_r_basereg */ \ + 0, /* src_basereg */ \ + 15 /* mask_basereg */ + +/******************************************************************************/ + .macro pixman_composite_src_0888_0888_process_pixblock_head .endm @@ -1049,3 +1379,133 @@ generate_composite_function \ 0, /* dst_r_basereg */ \ 0, /* src_basereg */ \ 0 /* mask_basereg */ + +/******************************************************************************/ + +.macro pixman_composite_src_0888_8888_rev_process_pixblock_head + vswp d0, d2 +.endm + +.macro pixman_composite_src_0888_8888_rev_process_pixblock_tail +.endm + +.macro pixman_composite_src_0888_8888_rev_process_pixblock_tail_head + vst4.8 {d0, d1, d2, d3}, [DST_W]! + vld3.8 {d0, d1, d2}, [SRC]! + vswp d0, d2 + cache_preload 8, 8 +.endm + +.macro pixman_composite_src_0888_8888_rev_init + veor d3, d3, d3 +.endm + +generate_composite_function \ + pixman_composite_src_0888_8888_rev_asm_neon, 24, 0, 32, \ + FLAG_DST_WRITEONLY | FLAG_DEINTERLEAVE_32BPP, \ + 8, /* number of pixels, processed in a single block */ \ + 10, /* prefetch distance */ \ + pixman_composite_src_0888_8888_rev_init, \ + default_cleanup, \ + pixman_composite_src_0888_8888_rev_process_pixblock_head, \ + pixman_composite_src_0888_8888_rev_process_pixblock_tail, \ + pixman_composite_src_0888_8888_rev_process_pixblock_tail_head, \ + 0, /* dst_w_basereg */ \ + 0, /* dst_r_basereg */ \ + 0, /* src_basereg */ \ + 0 /* mask_basereg */ + +/******************************************************************************/ + +.macro pixman_composite_src_0888_0565_rev_process_pixblock_head + vshll.u8 q8, d1, #8 + vshll.u8 q9, d2, #8 +.endm + +.macro pixman_composite_src_0888_0565_rev_process_pixblock_tail + vshll.u8 q14, d0, #8 + vsri.u16 q14, q8, #5 + vsri.u16 q14, q9, #11 +.endm + +.macro pixman_composite_src_0888_0565_rev_process_pixblock_tail_head + vshll.u8 q14, d0, #8 + vld3.8 {d0, d1, d2}, [SRC]! + vsri.u16 q14, q8, #5 + vsri.u16 q14, q9, #11 + vshll.u8 q8, d1, #8 + vst1.16 {d28, d29}, [DST_W, :128]! + vshll.u8 q9, d2, #8 +.endm + +generate_composite_function \ + pixman_composite_src_0888_0565_rev_asm_neon, 24, 0, 16, \ + FLAG_DST_WRITEONLY, \ + 8, /* number of pixels, processed in a single block */ \ + 10, /* prefetch distance */ \ + default_init, \ + default_cleanup, \ + pixman_composite_src_0888_0565_rev_process_pixblock_head, \ + pixman_composite_src_0888_0565_rev_process_pixblock_tail, \ + pixman_composite_src_0888_0565_rev_process_pixblock_tail_head, \ + 28, /* dst_w_basereg */ \ + 0, /* dst_r_basereg */ \ + 0, /* src_basereg */ \ + 0 /* mask_basereg */ + +/******************************************************************************/ + +.macro pixman_composite_src_pixbuf_8888_process_pixblock_head + vmull.u8 q8, d3, d0 + vmull.u8 q9, d3, d1 + vmull.u8 q10, d3, d2 +.endm + +.macro pixman_composite_src_pixbuf_8888_process_pixblock_tail + vrshr.u16 q11, q8, #8 + vswp d3, d31 + vrshr.u16 q12, q9, #8 + vrshr.u16 q13, q10, #8 + vraddhn.u16 d30, q11, q8 + vraddhn.u16 d29, q12, q9 + vraddhn.u16 d28, q13, q10 +.endm + +.macro pixman_composite_src_pixbuf_8888_process_pixblock_tail_head + vrshr.u16 q11, q8, #8 + vswp d3, d31 + vrshr.u16 q12, q9, #8 + vrshr.u16 q13, q10, #8 + vld4.8 {d0, d1, d2, d3}, [SRC]! + vraddhn.u16 d30, q11, q8 + PF add PF_X, PF_X, #8 + PF tst PF_CTL, #0xF + PF addne PF_X, PF_X, #8 + PF subne PF_CTL, PF_CTL, #1 + vraddhn.u16 d29, q12, q9 + vraddhn.u16 d28, q13, q10 + vmull.u8 q8, d3, d0 + vmull.u8 q9, d3, d1 + vmull.u8 q10, d3, d2 + vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! + PF cmp PF_X, ORIG_W + PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] + PF subge PF_X, PF_X, ORIG_W + PF subges PF_CTL, PF_CTL, #0x10 + PF ldrgeb DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! +.endm + +generate_composite_function \ + pixman_composite_src_pixbuf_8888_asm_neon, 32, 0, 32, \ + FLAG_DST_WRITEONLY | FLAG_DEINTERLEAVE_32BPP, \ + 8, /* number of pixels, processed in a single block */ \ + 10, /* prefetch distance */ \ + default_init, \ + default_cleanup, \ + pixman_composite_src_pixbuf_8888_process_pixblock_head, \ + pixman_composite_src_pixbuf_8888_process_pixblock_tail, \ + pixman_composite_src_pixbuf_8888_process_pixblock_tail_head, \ + 28, /* dst_w_basereg */ \ + 0, /* dst_r_basereg */ \ + 0, /* src_basereg */ \ + 0 /* mask_basereg */ diff --git a/pixman/pixman-arm-neon-asm.h b/pixman/pixman-arm-neon-asm.h index e7be5cd..56c3fae 100644 --- a/pixman/pixman-arm-neon-asm.h +++ b/pixman/pixman-arm-neon-asm.h @@ -1,24 +1,24 @@ /* * Copyright © 2009 Nokia Corporation * - * 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 Nokia Corporation not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Nokia Corporation makes no - * representations about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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. + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. * * Author: Siarhei Siamashka (siarhei.siamashka@nokia.com) */ @@ -780,6 +780,125 @@ fname: .endfunc .endm +/* + * A simplified variant of function generation template for a single + * scanline processing (for implementing pixman combine functions) + */ +.macro generate_composite_function_single_scanline fname, \ + src_bpp_, \ + mask_bpp_, \ + dst_w_bpp_, \ + flags, \ + pixblock_size_, \ + init, \ + cleanup, \ + process_pixblock_head, \ + process_pixblock_tail, \ + process_pixblock_tail_head, \ + dst_w_basereg_ = 28, \ + dst_r_basereg_ = 4, \ + src_basereg_ = 0, \ + mask_basereg_ = 24 + + .func fname + .global fname + /* For ELF format also set function visibility to hidden */ +#ifdef __ELF__ + .hidden fname + .type fname, %function +#endif +fname: + .set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_NONE +/* + * Make some macro arguments globally visible and accessible + * from other macros + */ + .set src_bpp, src_bpp_ + .set mask_bpp, mask_bpp_ + .set dst_w_bpp, dst_w_bpp_ + .set pixblock_size, pixblock_size_ + .set dst_w_basereg, dst_w_basereg_ + .set dst_r_basereg, dst_r_basereg_ + .set src_basereg, src_basereg_ + .set mask_basereg, mask_basereg_ +/* + * Assign symbolic names to registers + */ + W .req r0 /* width (is updated during processing) */ + DST_W .req r1 /* destination buffer pointer for writes */ + SRC .req r2 /* source buffer pointer */ + DST_R .req ip /* destination buffer pointer for reads */ + MASK .req r3 /* mask pointer */ + +.if (((flags) & FLAG_DST_READWRITE) != 0) + .set dst_r_bpp, dst_w_bpp +.else + .set dst_r_bpp, 0 +.endif +.if (((flags) & FLAG_DEINTERLEAVE_32BPP) != 0) + .set DEINTERLEAVE_32BPP_ENABLED, 1 +.else + .set DEINTERLEAVE_32BPP_ENABLED, 0 +.endif + + init + mov DST_R, DST_W + + cmp W, #pixblock_size + blt 8f + + ensure_destination_ptr_alignment process_pixblock_head, \ + process_pixblock_tail, \ + process_pixblock_tail_head + + subs W, W, #pixblock_size + blt 7f + + /* Implement "head (tail_head) ... (tail_head) tail" loop pattern */ + pixld_a pixblock_size, dst_r_bpp, \ + (dst_r_basereg - pixblock_size * dst_r_bpp / 64), DST_R + pixld pixblock_size, src_bpp, \ + (src_basereg - pixblock_size * src_bpp / 64), SRC + pixld pixblock_size, mask_bpp, \ + (mask_basereg - pixblock_size * mask_bpp / 64), MASK + process_pixblock_head + subs W, W, #pixblock_size + blt 2f +1: + process_pixblock_tail_head + subs W, W, #pixblock_size + bge 1b +2: + process_pixblock_tail + pixst_a pixblock_size, dst_w_bpp, \ + (dst_w_basereg - pixblock_size * dst_w_bpp / 64), DST_W +7: + /* Process the remaining trailing pixels in the scanline (dst aligned) */ + process_trailing_pixels 0, 1, \ + process_pixblock_head, \ + process_pixblock_tail, \ + process_pixblock_tail_head + + cleanup + bx lr /* exit */ +8: + /* Process the remaining trailing pixels in the scanline (dst unaligned) */ + process_trailing_pixels 0, 0, \ + process_pixblock_head, \ + process_pixblock_tail, \ + process_pixblock_tail_head + + cleanup + bx lr /* exit */ + + .unreq SRC + .unreq MASK + .unreq DST_R + .unreq DST_W + .unreq W + .endfunc +.endm + .macro default_init .endm diff --git a/pixman/pixman-arm-neon.c b/pixman/pixman-arm-neon.c index 2ed8b4b..557301e 100644 --- a/pixman/pixman-arm-neon.c +++ b/pixman/pixman-arm-neon.c @@ -35,27 +35,27 @@ #define BIND_SRC_NULL_DST(name, src_type, src_cnt, dst_type, dst_cnt) \ void \ -pixman_##name##_asm_neon (int32_t w, \ - int32_t h, \ - dst_type *dst, \ - int32_t dst_stride, \ - src_type *src, \ - int32_t src_stride); \ +pixman_composite_##name##_asm_neon (int32_t w, \ + int32_t h, \ + dst_type *dst, \ + int32_t dst_stride, \ + src_type *src, \ + int32_t src_stride); \ \ static void \ -neon_##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 dest_x, \ - int32_t dest_y, \ - int32_t width, \ - int32_t height) \ +neon_composite_##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 dest_x, \ + int32_t dest_y, \ + int32_t width, \ + int32_t height) \ { \ dst_type *dst_line; \ src_type *src_line; \ @@ -66,36 +66,76 @@ neon_##name (pixman_implementation_t *imp, \ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, dst_type, \ dst_stride, dst_line, dst_cnt); \ \ - pixman_##name##_asm_neon (width, height, \ - dst_line, dst_stride, \ - src_line, src_stride); \ + pixman_composite_##name##_asm_neon (width, height, \ + dst_line, dst_stride, \ + src_line, src_stride); \ +} + +#define BIND_N_NULL_DST(name, dst_type, dst_cnt) \ +void \ +pixman_composite_##name##_asm_neon (int32_t w, \ + int32_t h, \ + dst_type *dst, \ + int32_t dst_stride, \ + uint32_t src); \ + \ +static void \ +neon_composite_##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 dest_x, \ + int32_t dest_y, \ + int32_t width, \ + int32_t height) \ +{ \ + dst_type *dst_line; \ + int32_t dst_stride; \ + uint32_t src; \ + \ + src = _pixman_image_get_solid (src_image, dst_image->bits.format); \ + \ + if (src == 0) \ + return; \ + \ + PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, dst_type, \ + dst_stride, dst_line, dst_cnt); \ + \ + pixman_composite_##name##_asm_neon (width, height, \ + dst_line, dst_stride, \ + src); \ } #define BIND_N_MASK_DST(name, mask_type, mask_cnt, dst_type, dst_cnt) \ void \ -pixman_##name##_asm_neon (int32_t w, \ - int32_t h, \ - dst_type *dst, \ - int32_t dst_stride, \ - uint32_t src, \ - int32_t unused, \ - mask_type *mask, \ - int32_t mask_stride); \ +pixman_composite_##name##_asm_neon (int32_t w, \ + int32_t h, \ + dst_type *dst, \ + int32_t dst_stride, \ + uint32_t src, \ + int32_t unused, \ + mask_type *mask, \ + int32_t mask_stride); \ \ static void \ -neon_##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 dest_x, \ - int32_t dest_y, \ - int32_t width, \ - int32_t height) \ +neon_composite_##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 dest_x, \ + int32_t dest_y, \ + int32_t width, \ + int32_t height) \ { \ dst_type *dst_line; \ mask_type *mask_line; \ @@ -112,36 +152,36 @@ neon_##name (pixman_implementation_t *imp, \ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \ mask_stride, mask_line, mask_cnt); \ \ - pixman_##name##_asm_neon (width, height, \ - dst_line, dst_stride, \ - src, 0, \ - mask_line, mask_stride); \ + pixman_composite_##name##_asm_neon (width, height, \ + dst_line, dst_stride, \ + src, 0, \ + mask_line, mask_stride); \ } #define BIND_SRC_N_DST(name, src_type, src_cnt, dst_type, dst_cnt) \ void \ -pixman_##name##_asm_neon (int32_t w, \ - int32_t h, \ - dst_type *dst, \ - int32_t dst_stride, \ - src_type *src, \ - int32_t src_stride, \ - uint32_t mask); \ +pixman_composite_##name##_asm_neon (int32_t w, \ + int32_t h, \ + dst_type *dst, \ + int32_t dst_stride, \ + src_type *src, \ + int32_t src_stride, \ + uint32_t mask); \ \ static void \ -neon_##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 dest_x, \ - int32_t dest_y, \ - int32_t width, \ - int32_t height) \ +neon_composite_##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 dest_x, \ + int32_t dest_y, \ + int32_t width, \ + int32_t height) \ { \ dst_type *dst_line; \ src_type *src_line; \ @@ -158,38 +198,38 @@ neon_##name (pixman_implementation_t *imp, \ PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \ src_stride, src_line, src_cnt); \ \ - pixman_##name##_asm_neon (width, height, \ - dst_line, dst_stride, \ - src_line, src_stride, \ - mask); \ + pixman_composite_##name##_asm_neon (width, height, \ + dst_line, dst_stride, \ + src_line, src_stride, \ + mask); \ } #define BIND_SRC_MASK_DST(name, src_type, src_cnt, mask_type, mask_cnt, \ dst_type, dst_cnt) \ void \ -pixman_##name##_asm_neon (int32_t w, \ - int32_t h, \ - dst_type *dst, \ - int32_t dst_stride, \ - src_type *src, \ - int32_t src_stride, \ - mask_type *mask, \ - int32_t mask_stride); \ +pixman_composite_##name##_asm_neon (int32_t w, \ + int32_t h, \ + dst_type *dst, \ + int32_t dst_stride, \ + src_type *src, \ + int32_t src_stride, \ + mask_type *mask, \ + int32_t mask_stride); \ \ static void \ -neon_##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 dest_x, \ - int32_t dest_y, \ - int32_t width, \ - int32_t height) \ +neon_composite_##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 dest_x, \ + int32_t dest_y, \ + int32_t width, \ + int32_t height) \ { \ dst_type *dst_line; \ src_type *src_line; \ @@ -203,29 +243,40 @@ neon_##name (pixman_implementation_t *imp, \ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \ mask_stride, mask_line, mask_cnt); \ \ - pixman_##name##_asm_neon (width, height, \ - dst_line, dst_stride, \ - src_line, src_stride, \ - mask_line, mask_stride); \ + pixman_composite_##name##_asm_neon (width, height, \ + dst_line, dst_stride, \ + src_line, src_stride, \ + mask_line, mask_stride); \ } -BIND_SRC_NULL_DST(composite_src_8888_8888, uint32_t, 1, uint32_t, 1) -BIND_SRC_NULL_DST(composite_src_0565_0565, uint16_t, 1, uint16_t, 1) -BIND_SRC_NULL_DST(composite_src_0888_0888, uint8_t, 3, uint8_t, 3) -BIND_SRC_NULL_DST(composite_src_8888_0565, uint32_t, 1, uint16_t, 1) -BIND_SRC_NULL_DST(composite_add_8000_8000, uint8_t, 1, uint8_t, 1) +BIND_SRC_NULL_DST(src_8888_8888, uint32_t, 1, uint32_t, 1) +BIND_SRC_NULL_DST(src_0565_0565, uint16_t, 1, uint16_t, 1) +BIND_SRC_NULL_DST(src_0888_0888, uint8_t, 3, uint8_t, 3) +BIND_SRC_NULL_DST(src_8888_0565, uint32_t, 1, uint16_t, 1) +BIND_SRC_NULL_DST(src_0565_8888, uint16_t, 1, uint32_t, 1) +BIND_SRC_NULL_DST(src_0888_8888_rev, uint8_t, 3, uint32_t, 1) +BIND_SRC_NULL_DST(src_0888_0565_rev, uint8_t, 3, uint16_t, 1) +BIND_SRC_NULL_DST(src_pixbuf_8888, uint32_t, 1, uint32_t, 1) +BIND_SRC_NULL_DST(add_8000_8000, uint8_t, 1, uint8_t, 1) +BIND_SRC_NULL_DST(add_8888_8888, uint32_t, 1, uint32_t, 1) + +BIND_N_NULL_DST(over_n_0565, uint16_t, 1) +BIND_N_NULL_DST(over_n_8888, uint32_t, 1) -BIND_SRC_NULL_DST(composite_over_8888_0565, uint32_t, 1, uint16_t, 1) -BIND_SRC_NULL_DST(composite_over_8888_8888, uint32_t, 1, uint32_t, 1) +BIND_SRC_NULL_DST(over_8888_0565, uint32_t, 1, uint16_t, 1) +BIND_SRC_NULL_DST(over_8888_8888, uint32_t, 1, uint32_t, 1) -BIND_N_MASK_DST(composite_over_n_8_0565, uint8_t, 1, uint16_t, 1) -BIND_N_MASK_DST(composite_over_n_8_8888, uint8_t, 1, uint32_t, 1) -BIND_N_MASK_DST(composite_add_n_8_8, uint8_t, 1, uint8_t, 1) +BIND_N_MASK_DST(over_n_8_0565, uint8_t, 1, uint16_t, 1) +BIND_N_MASK_DST(over_n_8_8888, uint8_t, 1, uint32_t, 1) +BIND_N_MASK_DST(add_n_8_8, uint8_t, 1, uint8_t, 1) -BIND_SRC_N_DST(composite_over_8888_n_8888, uint32_t, 1, uint32_t, 1) +BIND_SRC_N_DST(over_8888_n_8888, uint32_t, 1, uint32_t, 1) -BIND_SRC_MASK_DST(composite_add_8_8_8, uint8_t, 1, uint8_t, 1, uint8_t, 1) +BIND_SRC_MASK_DST(add_8_8_8, uint8_t, 1, uint8_t, 1, uint8_t, 1) +BIND_SRC_MASK_DST(add_8888_8888_8888, uint32_t, 1, uint32_t, 1, uint32_t, 1) +BIND_SRC_MASK_DST(over_8888_8_8888, uint32_t, 1, uint8_t, 1, uint32_t, 1) +BIND_SRC_MASK_DST(over_8888_8888_8888, uint32_t, 1, uint32_t, 1, uint32_t, 1) void pixman_composite_src_n_8_asm_neon (int32_t w, @@ -292,72 +343,125 @@ pixman_fill_neon (uint32_t *bits, } } -static const pixman_fast_path_t arm_neon_fast_path_array[] = +static pixman_bool_t +pixman_blt_neon (uint32_t *src_bits, + uint32_t *dst_bits, + int src_stride, + int dst_stride, + int src_bpp, + int dst_bpp, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height) { - { PIXMAN_OP_SRC, PIXMAN_r5g6b5, PIXMAN_null, PIXMAN_r5g6b5, neon_composite_src_0565_0565 }, - { PIXMAN_OP_SRC, PIXMAN_b5g6r5, PIXMAN_null, PIXMAN_b5g6r5, neon_composite_src_0565_0565 }, - { PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, neon_composite_src_8888_0565 }, - { PIXMAN_OP_SRC, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, neon_composite_src_8888_0565 }, - { PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, neon_composite_src_8888_0565 }, - { PIXMAN_OP_SRC, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, neon_composite_src_8888_0565 }, - { PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, neon_composite_src_8888_8888 }, - { PIXMAN_OP_SRC, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, neon_composite_src_8888_8888 }, - { PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, neon_composite_src_8888_8888 }, - { PIXMAN_OP_SRC, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, neon_composite_src_8888_8888 }, - { PIXMAN_OP_SRC, PIXMAN_r8g8b8, PIXMAN_null, PIXMAN_r8g8b8, neon_composite_src_0888_0888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_r5g6b5, neon_composite_over_n_8_0565 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_b5g6r5, neon_composite_over_n_8_0565 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8r8g8b8, neon_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8r8g8b8, neon_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8b8g8r8, neon_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8b8g8r8, neon_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_solid, PIXMAN_a8r8g8b8, neon_composite_over_8888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_solid, PIXMAN_x8r8g8b8, neon_composite_over_8888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, neon_composite_over_8888_0565 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, neon_composite_over_8888_0565 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, neon_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, neon_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, neon_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, neon_composite_over_8888_8888 }, - { PIXMAN_OP_ADD, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, neon_composite_add_n_8_8 }, - { PIXMAN_OP_ADD, PIXMAN_a8, PIXMAN_a8, PIXMAN_a8, neon_composite_add_8_8_8 }, - { PIXMAN_OP_ADD, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, neon_composite_add_8000_8000 }, + if (src_bpp != dst_bpp) + return FALSE; + + switch (src_bpp) + { + case 16: + pixman_composite_src_0565_0565_asm_neon ( + width, height, + (uint16_t *)(((char *) dst_bits) + + dst_y * dst_stride * 4 + dst_x * 2), dst_stride * 2, + (uint16_t *)(((char *) src_bits) + + src_y * src_stride * 4 + src_x * 2), src_stride * 2); + return TRUE; + case 32: + pixman_composite_src_8888_8888_asm_neon ( + width, height, + (uint32_t *)(((char *) dst_bits) + + dst_y * dst_stride * 4 + dst_x * 4), dst_stride, + (uint32_t *)(((char *) src_bits) + + src_y * src_stride * 4 + src_x * 4), src_stride); + return TRUE; + default: + return FALSE; + } +} + +static const pixman_fast_path_t arm_neon_fast_paths[] = +{ + PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, neon_composite_src_0565_0565), + PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, neon_composite_src_0565_0565), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, neon_composite_src_8888_0565), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, neon_composite_src_8888_0565), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, neon_composite_src_8888_0565), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, neon_composite_src_8888_0565), + PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, a8r8g8b8, neon_composite_src_0565_8888), + PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, x8r8g8b8, neon_composite_src_0565_8888), + PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, a8b8g8r8, neon_composite_src_0565_8888), + PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, x8b8g8r8, neon_composite_src_0565_8888), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, neon_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, neon_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, neon_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, neon_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, neon_composite_src_0888_0888), + PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, x8r8g8b8, neon_composite_src_0888_8888_rev), + PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, r5g6b5, neon_composite_src_0888_0565_rev), + PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8r8g8b8, neon_composite_src_pixbuf_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, neon_composite_over_n_8_0565), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, neon_composite_over_n_8_0565), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, neon_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, neon_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, neon_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, neon_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, null, r5g6b5, neon_composite_over_n_0565), + PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, neon_composite_over_n_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, neon_composite_over_n_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, neon_composite_over_8888_n_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, neon_composite_over_8888_n_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, a8r8g8b8, neon_composite_over_8888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, x8r8g8b8, neon_composite_over_8888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, a8b8g8r8, neon_composite_over_8888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, x8b8g8r8, neon_composite_over_8888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, a8r8g8b8, neon_composite_over_8888_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, neon_composite_over_8888_0565), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, neon_composite_over_8888_0565), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, neon_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, neon_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, neon_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, neon_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, neon_composite_add_n_8_8), + PIXMAN_STD_FAST_PATH (ADD, a8, a8, a8, neon_composite_add_8_8_8), + PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, a8r8g8b8, neon_composite_add_8888_8888_8888), + PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, neon_composite_add_8000_8000), + PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, neon_composite_add_8888_8888), + PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, neon_composite_add_8888_8888), + { PIXMAN_OP_NONE }, }; -const pixman_fast_path_t *const arm_neon_fast_paths = arm_neon_fast_path_array; - -static void -arm_neon_composite (pixman_implementation_t *imp, - pixman_op_t op, - pixman_image_t * src, - pixman_image_t * mask, - pixman_image_t * dest, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) +static pixman_bool_t +arm_neon_blt (pixman_implementation_t *imp, + uint32_t * src_bits, + uint32_t * dst_bits, + int src_stride, + int dst_stride, + int src_bpp, + int dst_bpp, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height) { - if (_pixman_run_fast_path (arm_neon_fast_paths, imp, - op, src, mask, dest, - src_x, src_y, - mask_x, mask_y, - dest_x, dest_y, - width, height)) + if (!pixman_blt_neon ( + src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, + src_x, src_y, dst_x, dst_y, width, height)) + { - return; + return _pixman_implementation_blt ( + imp->delegate, + src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, + src_x, src_y, dst_x, dst_y, width, height); } - _pixman_implementation_composite (imp->delegate, op, - src, mask, dest, - src_x, src_y, - mask_x, mask_y, - dest_x, dest_y, - width, height); + return TRUE; } static pixman_bool_t @@ -378,13 +482,47 @@ arm_neon_fill (pixman_implementation_t *imp, imp->delegate, bits, stride, bpp, x, y, width, height, xor); } +#define BIND_COMBINE_U(name) \ +void \ +pixman_composite_scanline_##name##_mask_asm_neon (int32_t w, \ + const uint32_t *dst, \ + const uint32_t *src, \ + const uint32_t *mask); \ + \ +void \ +pixman_composite_scanline_##name##_asm_neon (int32_t w, \ + const uint32_t *dst, \ + const uint32_t *src); \ + \ +static void \ +neon_combine_##name##_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_scanline_##name##_mask_asm_neon (width, dest, \ + src, mask); \ + else \ + pixman_composite_scanline_##name##_asm_neon (width, dest, src); \ +} + +BIND_COMBINE_U (over) +BIND_COMBINE_U (add) + pixman_implementation_t * _pixman_implementation_create_arm_neon (void) { pixman_implementation_t *general = _pixman_implementation_create_fast_path (); - pixman_implementation_t *imp = _pixman_implementation_create (general); + pixman_implementation_t *imp = + _pixman_implementation_create (general, arm_neon_fast_paths); + + imp->combine_32[PIXMAN_OP_OVER] = neon_combine_over_u; + imp->combine_32[PIXMAN_OP_ADD] = neon_combine_add_u; - imp->composite = arm_neon_composite; + imp->blt = arm_neon_blt; imp->fill = arm_neon_fill; return imp; diff --git a/pixman/pixman-arm-simd.c b/pixman/pixman-arm-simd.c index 265c820..09a2888 100644 --- a/pixman/pixman-arm-simd.c +++ b/pixman/pixman-arm-simd.c @@ -31,23 +31,23 @@ static void arm_composite_add_8000_8000 (pixman_implementation_t * impl, - 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 dest_x, - int32_t dest_y, - int32_t width, - int32_t height) + 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 dest_x, + int32_t dest_y, + int32_t width, + int32_t height) { uint8_t *dst_line, *dst; uint8_t *src_line, *src; int dst_stride, src_stride; - uint16_t w; + int32_t w; uint8_t s, d; PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1); @@ -103,23 +103,23 @@ arm_composite_add_8000_8000 (pixman_implementation_t * impl, static void arm_composite_over_8888_8888 (pixman_implementation_t * impl, - 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 dest_x, - int32_t dest_y, - int32_t width, - int32_t height) + 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 dest_x, + int32_t dest_y, + int32_t width, + int32_t height) { uint32_t *dst_line, *dst; uint32_t *src_line, *src; int dst_stride, src_stride; - uint16_t w; + int32_t w; uint32_t component_half = 0x800080; uint32_t upper_component_mask = 0xff00ff00; uint32_t alpha_mask = 0xff; @@ -188,33 +188,32 @@ arm_composite_over_8888_8888 (pixman_implementation_t * impl, "2:\n\t" : [w] "+r" (w), [dest] "+r" (dst), [src] "+r" (src) : [component_half] "r" (component_half), [upper_component_mask] "r" (upper_component_mask), - [alpha_mask] "r" (alpha_mask) + [alpha_mask] "r" (alpha_mask) : "r4", "r5", "r6", "r7", "r8", "cc", "memory" ); } } static void -arm_composite_over_8888_n_8888 ( - pixman_implementation_t * impl, - 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 dest_x, - int32_t dest_y, - int32_t width, - int32_t height) +arm_composite_over_8888_n_8888 (pixman_implementation_t * impl, + 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 dest_x, + int32_t dest_y, + int32_t width, + int32_t height) { uint32_t *dst_line, *dst; uint32_t *src_line, *src; uint32_t mask; int dst_stride, src_stride; - uint16_t w; + int32_t w; uint32_t component_half = 0x800080; uint32_t alpha_mask = 0xff; @@ -298,7 +297,7 @@ arm_composite_over_8888_n_8888 ( "2:\n\t" : [w] "+r" (w), [dest] "+r" (dst), [src] "+r" (src) : [component_half] "r" (component_half), [mask_alpha] "r" (mask), - [alpha_mask] "r" (alpha_mask) + [alpha_mask] "r" (alpha_mask) : "r4", "r5", "r6", "r7", "r8", "r9", "cc", "memory" ); } @@ -323,7 +322,7 @@ arm_composite_over_n_8_8888 (pixman_implementation_t * impl, uint32_t *dst_line, *dst; uint8_t *mask_line, *mask; int dst_stride, mask_stride; - uint16_t w; + int32_t w; src = _pixman_image_get_solid (src_image, dst_image->bits.format); @@ -384,7 +383,8 @@ arm_composite_over_n_8_8888 (pixman_implementation_t * impl, "uxtb16 r7, r4, ror #8\n\t" /* we could simplify this to use 'sub' if we were - * willing to give up a register for alpha_mask */ + * willing to give up a register for alpha_mask + */ "mvn r8, r5\n\t" "mov r8, r8, lsr #24\n\t" @@ -419,68 +419,30 @@ arm_composite_over_n_8_8888 (pixman_implementation_t * impl, } } -static const pixman_fast_path_t arm_simd_fast_path_array[] = +static const pixman_fast_path_t arm_simd_fast_paths[] = { - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, arm_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, arm_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, arm_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, arm_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_solid, PIXMAN_a8r8g8b8, arm_composite_over_8888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_solid, PIXMAN_x8r8g8b8, arm_composite_over_8888_n_8888 }, + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, arm_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, arm_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, arm_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, arm_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, arm_composite_over_8888_n_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, arm_composite_over_8888_n_8888), - { PIXMAN_OP_ADD, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, arm_composite_add_8000_8000 }, + PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, arm_composite_add_8000_8000), - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8r8g8b8, arm_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8r8g8b8, arm_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8b8g8r8, arm_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8b8g8r8, arm_composite_over_n_8_8888 }, + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, arm_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, arm_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, arm_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, arm_composite_over_n_8_8888), { PIXMAN_OP_NONE }, }; -const pixman_fast_path_t *const arm_simd_fast_paths = arm_simd_fast_path_array; - -static void -arm_simd_composite (pixman_implementation_t *imp, - pixman_op_t op, - pixman_image_t * src, - pixman_image_t * mask, - pixman_image_t * dest, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) -{ - if (_pixman_run_fast_path (arm_simd_fast_paths, imp, - op, src, mask, dest, - src_x, src_y, - mask_x, mask_y, - dest_x, dest_y, - width, height)) - { - return; - } - - _pixman_implementation_composite (imp->delegate, op, - src, mask, dest, - src_x, src_y, - mask_x, mask_y, - dest_x, dest_y, - width, height); -} - pixman_implementation_t * _pixman_implementation_create_arm_simd (void) { pixman_implementation_t *general = _pixman_implementation_create_fast_path (); - pixman_implementation_t *imp = _pixman_implementation_create (general); - - imp->composite = arm_simd_composite; + pixman_implementation_t *imp = _pixman_implementation_create (general, arm_simd_fast_paths); return imp; } - diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 5a5a690..6befcbb 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -115,12 +115,13 @@ bits_image_fetch_pixel_alpha (bits_image_t *image, int x, int y) } else { - pixel_a = image->fetch_pixel_raw_32 ( + pixel_a = image->common.alpha_map->fetch_pixel_raw_32 ( image->common.alpha_map, x, y); pixel_a = ALPHA_8 (pixel_a); } - UN8x4_MUL_UN8 (pixel, pixel_a); + pixel &= 0x00ffffff; + pixel |= (pixel_a << 24); return pixel; } @@ -1040,8 +1041,10 @@ pixman_image_create_bits (pixman_format_code_t format, /* must be a whole number of uint32_t's */ - return_val_if_fail (bits == NULL || - (rowstride_bytes % sizeof (uint32_t)) == 0, NULL); + return_val_if_fail ( + bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL); + + return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL); if (!bits && width && height) { diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradient.c index d720db3..369a7a5 100644 --- a/pixman/pixman-conical-gradient.c +++ b/pixman/pixman-conical-gradient.c @@ -49,7 +49,7 @@ conical_gradient_get_scanline_32 (pixman_image_t *image, double rx = x + 0.5; double ry = y + 0.5; double rz = 1.; - double a = conical->angle / (180. * 65536); + double a = (conical->angle * M_PI) / (180. * 65536); _pixman_gradient_walker_init (&walker, gradient, source->common.repeat); diff --git a/pixman/pixman-cpu.c b/pixman/pixman-cpu.c index 5d5469b..e96b140 100644 --- a/pixman/pixman-cpu.c +++ b/pixman/pixman-cpu.c @@ -253,8 +253,6 @@ pixman_arm_read_auxv () if (aux.a_type == AT_HWCAP) { uint32_t hwcap = aux.a_un.a_val; - if (getenv ("ARM_FORCE_HWCAP")) - hwcap = strtoul (getenv ("ARM_FORCE_HWCAP"), NULL, 0); /* hardcode these values to avoid depending on specific * versions of the hwcap header, e.g. HWCAP_NEON */ @@ -266,8 +264,6 @@ pixman_arm_read_auxv () else if (aux.a_type == AT_PLATFORM) { const char *plat = (const char*) aux.a_un.a_val; - if (getenv ("ARM_FORCE_PLATFORM")) - plat = getenv ("ARM_FORCE_PLATFORM"); if (strncmp (plat, "v7l", 3) == 0) { arm_has_v7 = TRUE; @@ -280,12 +276,6 @@ pixman_arm_read_auxv () } } close (fd); - - /* if we don't have 2.6.29, we have to do this hack; set - * the env var to trust HWCAP. - */ - if (!getenv ("ARM_TRUST_HWCAP") && arm_has_v7) - arm_has_neon = TRUE; } arm_tests_initialized = TRUE; @@ -319,7 +309,7 @@ pixman_have_arm_neon (void) #endif /* USE_ARM_SIMD || USE_ARM_NEON */ -#ifdef USE_MMX +#if defined(USE_MMX) || defined(USE_SSE2) /* The CPU detection code needs to be in a file not compiled with * "-mmmx -msse", as gcc would generate CMOV instructions otherwise * that would lead to SIGILL instructions on old CPUs that don't have diff --git a/pixman/pixman-edge-imp.h b/pixman/pixman-edge-imp.h index d786ea7..a4698ed 100644 --- a/pixman/pixman-edge-imp.h +++ b/pixman/pixman-edge-imp.h @@ -83,14 +83,6 @@ RASTERIZE_EDGES (pixman_image_t *image, #if N_BITS == 1 { -#ifdef WORDS_BIGENDIAN -# define SCREEN_SHIFT_LEFT(x,n) ((x) << (n)) -# define SCREEN_SHIFT_RIGHT(x,n) ((x) >> (n)) -#else -# define SCREEN_SHIFT_LEFT(x,n) ((x) >> (n)) -# define SCREEN_SHIFT_RIGHT(x,n) ((x) << (n)) -#endif - #define LEFT_MASK(x) \ (((x) & 0x1f) ? \ SCREEN_SHIFT_RIGHT (0xffffffff, (x) & 0x1f) : 0) diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index d2c456b..4d26b0f 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -125,7 +125,7 @@ fast_composite_over_x888_8_8888 (pixman_implementation_t *imp, int src_stride, mask_stride, dst_stride; uint8_t m; uint32_t s, d; - uint16_t w; + int32_t w; PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1); @@ -183,7 +183,7 @@ fast_composite_in_n_8_8 (pixman_implementation_t *imp, uint8_t *dst_line, *dst; uint8_t *mask_line, *mask, m; int dst_stride, mask_stride; - uint16_t w; + int32_t w; uint16_t t; src = _pixman_image_get_solid (src_image, dest_image->bits.format); @@ -260,7 +260,7 @@ fast_composite_in_8_8 (pixman_implementation_t *imp, uint8_t *dst_line, *dst; uint8_t *src_line, *src; int dst_stride, src_stride; - uint16_t w; + int32_t w; uint8_t s; uint16_t t; @@ -308,7 +308,7 @@ fast_composite_over_n_8_8888 (pixman_implementation_t *imp, uint32_t *dst_line, *dst, d; uint8_t *mask_line, *mask, m; int dst_stride, mask_stride; - uint16_t w; + int32_t w; src = _pixman_image_get_solid (src_image, dst_image->bits.format); @@ -366,7 +366,7 @@ fast_composite_add_n_8888_8888_ca (pixman_implementation_t *imp, uint32_t *dst_line, *dst, d; uint32_t *mask_line, *mask, ma; int dst_stride, mask_stride; - uint16_t w; + int32_t w; src = _pixman_image_get_solid (src_image, dst_image->bits.format); @@ -423,7 +423,7 @@ fast_composite_over_n_8888_8888_ca (pixman_implementation_t *imp, uint32_t *dst_line, *dst, d; uint32_t *mask_line, *mask, ma; int dst_stride, mask_stride; - uint16_t w; + int32_t w; src = _pixman_image_get_solid (src_image, dst_image->bits.format); @@ -490,7 +490,7 @@ fast_composite_over_n_8_0888 (pixman_implementation_t *imp, uint32_t d; uint8_t *mask_line, *mask, m; int dst_stride, mask_stride; - uint16_t w; + int32_t w; src = _pixman_image_get_solid (src_image, dst_image->bits.format); @@ -555,7 +555,7 @@ fast_composite_over_n_8_0565 (pixman_implementation_t *imp, uint32_t d; uint8_t *mask_line, *mask, m; int dst_stride, mask_stride; - uint16_t w; + int32_t w; src = _pixman_image_get_solid (src_image, dst_image->bits.format); @@ -622,7 +622,7 @@ fast_composite_over_n_8888_0565_ca (pixman_implementation_t *imp, uint32_t d; uint32_t *mask_line, *mask, ma; int dst_stride, mask_stride; - uint16_t w; + int32_t w; src = _pixman_image_get_solid (src_image, dst_image->bits.format); @@ -697,7 +697,7 @@ fast_composite_over_8888_8888 (pixman_implementation_t *imp, uint32_t *src_line, *src, s; int dst_stride, src_stride; uint8_t a; - uint16_t w; + int32_t w; PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); @@ -744,7 +744,7 @@ fast_composite_over_8888_0888 (pixman_implementation_t *imp, uint32_t *src_line, *src, s; uint8_t a; int dst_stride, src_stride; - uint16_t w; + int32_t w; PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 3); PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); @@ -796,7 +796,7 @@ fast_composite_over_8888_0565 (pixman_implementation_t *imp, uint32_t *src_line, *src, s; uint8_t a; int dst_stride, src_stride; - uint16_t w; + int32_t w; PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); @@ -849,7 +849,7 @@ fast_composite_src_x888_0565 (pixman_implementation_t *imp, uint16_t *dst_line, *dst; uint32_t *src_line, *src, s; int dst_stride, src_stride; - uint16_t w; + int32_t w; PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); @@ -889,7 +889,7 @@ fast_composite_add_8000_8000 (pixman_implementation_t *imp, uint8_t *dst_line, *dst; uint8_t *src_line, *src; int dst_stride, src_stride; - uint16_t w; + int32_t w; uint8_t s, d; uint16_t t; @@ -940,7 +940,7 @@ fast_composite_add_8888_8888 (pixman_implementation_t *imp, uint32_t *dst_line, *dst; uint32_t *src_line, *src; int dst_stride, src_stride; - uint16_t w; + int32_t w; uint32_t s, d; PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); @@ -990,7 +990,7 @@ fast_composite_add_n_8_8 (pixman_implementation_t *imp, uint8_t *dst_line, *dst; uint8_t *mask_line, *mask; int dst_stride, mask_stride; - uint16_t w; + int32_t w; uint32_t src; uint8_t sa; @@ -1033,10 +1033,10 @@ fast_composite_add_n_8_8 (pixman_implementation_t *imp, #define UPDATE_BITMASK(n) ((n) << 1) #endif -#define TEST_BIT(p, n) \ - (*((p) + ((n) >> 5)) & CREATE_BITMASK ((n) & 31)) -#define SET_BIT(p, n) \ - do { *((p) + ((n) >> 5)) |= CREATE_BITMASK ((n) & 31); } while (0); +#define TEST_BIT(p, n) \ + (*((p) + ((n) >> 5)) & CREATE_BITMASK ((n) & 31)) +#define SET_BIT(p, n) \ + do { *((p) + ((n) >> 5)) |= CREATE_BITMASK ((n) & 31); } while (0); static void fast_composite_add_1000_1000 (pixman_implementation_t *imp, @@ -1175,6 +1175,104 @@ fast_composite_over_n_1_8888 (pixman_implementation_t *imp, } } +static void +fast_composite_over_n_1_0565 (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 dest_x, + int32_t dest_y, + int32_t width, + int32_t height) +{ + uint32_t src, srca; + uint16_t *dst, *dst_line; + uint32_t *mask, *mask_line; + int mask_stride, dst_stride; + uint32_t bitcache, bitmask; + int32_t w; + uint32_t d; + uint16_t src565; + + if (width <= 0) + return; + + src = _pixman_image_get_solid (src_image, dst_image->bits.format); + srca = src >> 24; + if (src == 0) + return; + + PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, + dst_stride, dst_line, 1); + PIXMAN_IMAGE_GET_LINE (mask_image, 0, mask_y, uint32_t, + mask_stride, mask_line, 1); + mask_line += mask_x >> 5; + + if (srca == 0xff) + { + src565 = CONVERT_8888_TO_0565 (src); + while (height--) + { + dst = dst_line; + dst_line += dst_stride; + mask = mask_line; + mask_line += mask_stride; + w = width; + + bitcache = *mask++; + bitmask = CREATE_BITMASK (mask_x & 31); + + while (w--) + { + if (bitmask == 0) + { + bitcache = *mask++; + bitmask = CREATE_BITMASK (0); + } + if (bitcache & bitmask) + *dst = src565; + bitmask = UPDATE_BITMASK (bitmask); + dst++; + } + } + } + else + { + while (height--) + { + dst = dst_line; + dst_line += dst_stride; + mask = mask_line; + mask_line += mask_stride; + w = width; + + bitcache = *mask++; + bitmask = CREATE_BITMASK (mask_x & 31); + + while (w--) + { + if (bitmask == 0) + { + bitcache = *mask++; + bitmask = CREATE_BITMASK (0); + } + if (bitcache & bitmask) + { + d = over (src, CONVERT_0565_TO_0888 (*dst)); + *dst = CONVERT_8888_TO_0565 (d); + } + bitmask = UPDATE_BITMASK (bitmask); + dst++; + } + } + } +} + /* * Simple bitblt */ @@ -1247,86 +1345,102 @@ fast_composite_src_8888_x888 (pixman_implementation_t *imp, } } -static const pixman_fast_path_t c_fast_paths[] = +static force_inline pixman_bool_t +repeat (pixman_repeat_t repeat, int *c, int size) { - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_r5g6b5, fast_composite_over_n_8_0565 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_b5g6r5, fast_composite_over_n_8_0565 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_r8g8b8, fast_composite_over_n_8_0888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_b8g8r8, fast_composite_over_n_8_0888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8r8g8b8, fast_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8r8g8b8, fast_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8b8g8r8, fast_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8b8g8r8, fast_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_a8r8g8b8, fast_composite_over_n_1_8888, }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_x8r8g8b8, fast_composite_over_n_1_8888, }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_a8b8g8r8, fast_composite_over_n_1_8888, }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_x8b8g8r8, fast_composite_over_n_1_8888, }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8_ca, PIXMAN_a8r8g8b8, fast_composite_over_n_8888_8888_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8_ca, PIXMAN_x8r8g8b8, fast_composite_over_n_8888_8888_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8_ca, PIXMAN_r5g6b5, fast_composite_over_n_8888_0565_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8_ca, PIXMAN_a8b8g8r8, fast_composite_over_n_8888_8888_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8_ca, PIXMAN_x8b8g8r8, fast_composite_over_n_8888_8888_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8_ca, PIXMAN_b5g6r5, fast_composite_over_n_8888_0565_ca }, - { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_x8r8g8b8, fast_composite_over_x888_8_8888, }, - { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_a8r8g8b8, fast_composite_over_x888_8_8888, }, - { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8, PIXMAN_x8b8g8r8, fast_composite_over_x888_8_8888, }, - { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8, PIXMAN_a8b8g8r8, fast_composite_over_x888_8_8888, }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fast_composite_over_8888_8888, }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fast_composite_over_8888_8888, }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, fast_composite_over_8888_0565, }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fast_composite_over_8888_8888, }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fast_composite_over_8888_8888, }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, fast_composite_over_8888_0565, }, - { PIXMAN_OP_ADD, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fast_composite_add_8888_8888, }, - { PIXMAN_OP_ADD, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fast_composite_add_8888_8888, }, - { PIXMAN_OP_ADD, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, fast_composite_add_8000_8000, }, - { PIXMAN_OP_ADD, PIXMAN_a1, PIXMAN_null, PIXMAN_a1, fast_composite_add_1000_1000, }, - { PIXMAN_OP_ADD, PIXMAN_solid, PIXMAN_a8r8g8b8_ca, PIXMAN_a8r8g8b8, fast_composite_add_n_8888_8888_ca }, - { PIXMAN_OP_ADD, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, fast_composite_add_n_8_8, }, - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_a8r8g8b8, fast_composite_solid_fill }, - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_x8r8g8b8, fast_composite_solid_fill }, - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_a8b8g8r8, fast_composite_solid_fill }, - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_x8b8g8r8, fast_composite_solid_fill }, - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_a8, fast_composite_solid_fill }, - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_r5g6b5, fast_composite_solid_fill }, - { PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fast_composite_src_8888_x888 }, - { PIXMAN_OP_SRC, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fast_composite_src_8888_x888 }, - { PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fast_composite_src_8888_x888 }, - { PIXMAN_OP_SRC, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fast_composite_src_8888_x888 }, - { PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, fast_composite_src_x888_0565 }, - { PIXMAN_OP_SRC, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, fast_composite_src_x888_0565 }, - { PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, fast_composite_src_x888_0565 }, - { PIXMAN_OP_SRC, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, fast_composite_src_x888_0565 }, - { PIXMAN_OP_IN, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, fast_composite_in_8_8, }, - { PIXMAN_OP_IN, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, fast_composite_in_n_8_8 }, - { PIXMAN_OP_NONE }, -}; + if (repeat == PIXMAN_REPEAT_NONE) + { + if (*c < 0 || *c >= size) + return FALSE; + } + else if (repeat == PIXMAN_REPEAT_NORMAL) + { + while (*c >= size) + *c -= size; + while (*c < 0) + *c += size; + } + else if (repeat == PIXMAN_REPEAT_PAD) + { + *c = CLIP (*c, 0, size - 1); + } + else /* REFLECT */ + { + *c = MOD (*c, size * 2); + if (*c >= size) + *c = size * 2 - *c - 1; + } + return TRUE; +} + +static force_inline uint32_t +fetch_nearest (pixman_repeat_t src_repeat, + pixman_format_code_t format, + uint32_t *src, int x, int src_width) +{ + if (repeat (src_repeat, &x, src_width)) + { + if (format == PIXMAN_x8r8g8b8) + return *(src + x) | 0xff000000; + else + return *(src + x); + } + else + { + return 0; + } +} + +static force_inline void +combine_over (uint32_t s, uint32_t *dst) +{ + if (s) + { + uint8_t ia = 0xff - (s >> 24); + + if (ia) + UN8x4_MUL_UN8_ADD_UN8x4 (*dst, ia, s); + else + *dst = s; + } +} + +static force_inline void +combine_src (uint32_t s, uint32_t *dst) +{ + *dst = s; +} static void -fast_composite_src_scale_nearest (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 dest_x, - int32_t dest_y, - int32_t width, - int32_t height) +fast_composite_scaled_nearest (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 dest_x, + int32_t dest_y, + int32_t width, + int32_t height) { - uint32_t *dst; - uint32_t *src; - int dst_stride, src_stride; - int i, j; + uint32_t *dst_line; + uint32_t *src_line; + int dst_stride, src_stride; + int src_width, src_height; + pixman_repeat_t src_repeat; + pixman_fixed_t unit_x, unit_y; + pixman_format_code_t src_format; pixman_vector_t v; + pixman_fixed_t vy; - PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst, 1); + PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_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, uint32_t, src_stride, src, 1); + * transformed from destination space to source space + */ + PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, uint32_t, src_stride, src_line, 1); /* reference point is the center of the pixel */ v.vector[0] = pixman_int_to_fixed (src_x) + pixman_fixed_1 / 2; @@ -1336,145 +1450,181 @@ fast_composite_src_scale_nearest (pixman_implementation_t *imp, 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]; + /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */ v.vector[0] -= pixman_fixed_e; v.vector[1] -= pixman_fixed_e; - for (j = 0; j < height; j++) + src_height = src_image->bits.height; + src_width = src_image->bits.width; + src_repeat = src_image->common.repeat; + src_format = src_image->bits.format; + + vy = v.vector[1]; + while (height--) { - pixman_fixed_t vx = v.vector[0]; - pixman_fixed_t vy = v.vector[1]; + pixman_fixed_t vx = v.vector[0]; + int y = pixman_fixed_to_int (vy); + uint32_t *dst = dst_line; - for (i = 0; i < width; ++i) + dst_line += dst_stride; + + /* adjust the y location by a unit vector in the y direction + * this is equivalent to transforming y+1 of the destination point to source space */ + vy += unit_y; + + if (!repeat (src_repeat, &y, src_height)) { - pixman_bool_t inside_bounds; - uint32_t result; - int x, y; - x = vx >> 16; - y = vy >> 16; - - /* apply the repeat function */ - switch (src_image->common.repeat) - { - case PIXMAN_REPEAT_NORMAL: - x = MOD (x, src_image->bits.width); - y = MOD (y, src_image->bits.height); - inside_bounds = TRUE; - break; - - case PIXMAN_REPEAT_PAD: - x = CLIP (x, 0, src_image->bits.width - 1); - y = CLIP (y, 0, src_image->bits.height - 1); - inside_bounds = TRUE; - break; - - case PIXMAN_REPEAT_REFLECT: - x = MOD (x, src_image->bits.width * 2); - if (x >= src_image->bits.width) - x = src_image->bits.width * 2 - x - 1; - y = MOD (y, src_image->bits.height * 2); - if (y >= src_image->bits.height) - y = src_image->bits.height * 2 - y - 1; - inside_bounds = TRUE; - break; - - case PIXMAN_REPEAT_NONE: - default: - inside_bounds = - (x >= 0 && - x < src_image->bits.width && - y >= 0 && - y < src_image->bits.height); - break; - } + if (op == PIXMAN_OP_SRC) + memset (dst, 0, sizeof (*dst) * width); + } + else + { + int w = width; + + uint32_t *src = src_line + y * src_stride; - if (inside_bounds) + while (w >= 2) { - /* XXX: we should move this multiplication out of the loop */ - result = *(src + y * src_stride + x); + uint32_t s1, s2; + int x1, x2; + + x1 = pixman_fixed_to_int (vx); + vx += unit_x; + + x2 = pixman_fixed_to_int (vx); + vx += unit_x; + + w -= 2; + + s1 = fetch_nearest (src_repeat, src_format, src, x1, src_width); + s2 = fetch_nearest (src_repeat, src_format, src, x2, src_width); + + if (op == PIXMAN_OP_OVER) + { + combine_over (s1, dst++); + combine_over (s2, dst++); + } + else + { + combine_src (s1, dst++); + combine_src (s2, dst++); + } } - else + + while (w--) { - result = 0; - } - *(dst + i) = result; + uint32_t s; + int x; - /* adjust the x location by a unit vector in the x direction: - * this is equivalent to transforming x+1 of the destination - * point to source space - */ - vx += src_image->common.transform->matrix[0][0]; + x = pixman_fixed_to_int (vx); + vx += unit_x; + + s = fetch_nearest (src_repeat, src_format, src, x, src_width); + + if (op == PIXMAN_OP_OVER) + combine_over (s, dst++); + else + combine_src (s, dst++); + } } - /* adjust the y location by a unit vector in the y direction - * this is equivalent to transforming y+1 of the destination point - * to source space - */ - v.vector[1] += src_image->common.transform->matrix[1][1]; - dst += dst_stride; } } -static void -fast_path_composite (pixman_implementation_t *imp, - pixman_op_t op, - pixman_image_t * src, - pixman_image_t * mask, - pixman_image_t * dest, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) +static const pixman_fast_path_t c_fast_paths[] = { - if (src->type == BITS - && src->common.transform - && !mask - && op == PIXMAN_OP_SRC - && !src->common.alpha_map && !dest->common.alpha_map - && (src->common.filter == PIXMAN_FILTER_NEAREST) - && PIXMAN_FORMAT_BPP (dest->bits.format) == 32 - && src->bits.format == dest->bits.format - && !src->bits.read_func && !src->bits.write_func - && !dest->bits.read_func && !dest->bits.write_func) - { - /* ensure that the transform matrix only has a scale */ - if (src->common.transform->matrix[0][1] == 0 && - src->common.transform->matrix[1][0] == 0 && - src->common.transform->matrix[2][0] == 0 && - src->common.transform->matrix[2][1] == 0 && - src->common.transform->matrix[2][2] == pixman_fixed_1) - { - _pixman_walk_composite_region (imp, op, - src, mask, dest, - src_x, src_y, - mask_x, mask_y, - dest_x, dest_y, - width, height, - fast_composite_src_scale_nearest); - return; - } + PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, fast_composite_over_n_8_0565), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, fast_composite_over_n_8_0565), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, r8g8b8, fast_composite_over_n_8_0888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, b8g8r8, fast_composite_over_n_8_0888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, fast_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, fast_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, fast_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, fast_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a1, a8r8g8b8, fast_composite_over_n_1_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a1, x8r8g8b8, fast_composite_over_n_1_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a1, a8b8g8r8, fast_composite_over_n_1_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a1, x8b8g8r8, fast_composite_over_n_1_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a1, r5g6b5, fast_composite_over_n_1_0565), + PIXMAN_STD_FAST_PATH (OVER, solid, a1, b5g6r5, fast_composite_over_n_1_0565), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, fast_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, fast_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, fast_composite_over_n_8888_0565_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, fast_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, fast_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, fast_composite_over_n_8888_0565_ca), + PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, x8r8g8b8, fast_composite_over_x888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, a8r8g8b8, fast_composite_over_x888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, x8b8g8r8, fast_composite_over_x888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, a8b8g8r8, fast_composite_over_x888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, fast_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, fast_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, fast_composite_over_8888_0565), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, fast_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, fast_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, fast_composite_over_8888_0565), + PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, fast_composite_add_8888_8888), + PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, fast_composite_add_8888_8888), + PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, fast_composite_add_8000_8000), + PIXMAN_STD_FAST_PATH (ADD, a1, null, a1, fast_composite_add_1000_1000), + PIXMAN_STD_FAST_PATH_CA (ADD, solid, a8r8g8b8, a8r8g8b8, fast_composite_add_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, fast_composite_add_n_8_8), + PIXMAN_STD_FAST_PATH (SRC, solid, null, a8r8g8b8, fast_composite_solid_fill), + PIXMAN_STD_FAST_PATH (SRC, solid, null, x8r8g8b8, fast_composite_solid_fill), + PIXMAN_STD_FAST_PATH (SRC, solid, null, a8b8g8r8, fast_composite_solid_fill), + PIXMAN_STD_FAST_PATH (SRC, solid, null, x8b8g8r8, fast_composite_solid_fill), + PIXMAN_STD_FAST_PATH (SRC, solid, null, a8, fast_composite_solid_fill), + PIXMAN_STD_FAST_PATH (SRC, solid, null, r5g6b5, fast_composite_solid_fill), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, fast_composite_src_8888_x888), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, fast_composite_src_8888_x888), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, fast_composite_src_8888_x888), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, fast_composite_src_8888_x888), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, fast_composite_src_x888_0565), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, fast_composite_src_x888_0565), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, fast_composite_src_x888_0565), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, fast_composite_src_x888_0565), + PIXMAN_STD_FAST_PATH (IN, a8, null, a8, fast_composite_in_8_8), + PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, fast_composite_in_n_8_8), + +#define SCALED_NEAREST_FLAGS \ + (FAST_PATH_SCALE_TRANSFORM | \ + FAST_PATH_NO_ALPHA_MAP | \ + FAST_PATH_NEAREST_FILTER | \ + FAST_PATH_NO_ACCESSORS | \ + FAST_PATH_NO_WIDE_FORMAT) + +#define NEAREST_FAST_PATH(op,s,d) \ + { PIXMAN_OP_ ## op, \ + PIXMAN_ ## s, SCALED_NEAREST_FLAGS, \ + PIXMAN_null, 0, \ + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ + fast_composite_scaled_nearest, \ } - if (_pixman_run_fast_path (c_fast_paths, imp, - op, src, mask, dest, - src_x, src_y, - mask_x, mask_y, - dest_x, dest_y, - width, height)) - { - return; - } + NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8), + NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8), + NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8), + NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8), - _pixman_implementation_composite (imp->delegate, op, - src, mask, dest, - src_x, src_y, - mask_x, mask_y, - dest_x, dest_y, - width, height); -} + NEAREST_FAST_PATH (SRC, x8r8g8b8, a8r8g8b8), + NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8), + NEAREST_FAST_PATH (SRC, x8b8g8r8, a8b8g8r8), + NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8), + + NEAREST_FAST_PATH (OVER, x8r8g8b8, x8r8g8b8), + NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8), + NEAREST_FAST_PATH (OVER, x8b8g8r8, x8b8g8r8), + NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8), + + NEAREST_FAST_PATH (OVER, x8r8g8b8, a8r8g8b8), + NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8), + NEAREST_FAST_PATH (OVER, x8b8g8r8, a8b8g8r8), + NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8), + + { PIXMAN_OP_NONE }, +}; static void pixman_fill8 (uint32_t *bits, @@ -1587,11 +1737,9 @@ pixman_implementation_t * _pixman_implementation_create_fast_path (void) { pixman_implementation_t *general = _pixman_implementation_create_general (); - pixman_implementation_t *imp = _pixman_implementation_create (general); + pixman_implementation_t *imp = _pixman_implementation_create (general, c_fast_paths); - imp->composite = fast_path_composite; imp->fill = fast_path_fill; return imp; } - diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index c96a3f9..bddf79a 100644 --- a/pixman/pixman-general.c +++ b/pixman/pixman-general.c @@ -264,26 +264,11 @@ general_composite_rect (pixman_implementation_t *imp, free (scanline_buffer); } -static void -general_composite (pixman_implementation_t * imp, - pixman_op_t op, - pixman_image_t * src, - pixman_image_t * mask, - pixman_image_t * dest, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) +static const pixman_fast_path_t general_fast_path[] = { - _pixman_walk_composite_region (imp, op, src, mask, dest, src_x, src_y, - mask_x, mask_y, dest_x, dest_y, - width, height, - general_composite_rect); -} + { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect }, + { PIXMAN_OP_NONE } +}; static pixman_bool_t general_blt (pixman_implementation_t *imp, @@ -322,12 +307,11 @@ general_fill (pixman_implementation_t *imp, pixman_implementation_t * _pixman_implementation_create_general (void) { - pixman_implementation_t *imp = _pixman_implementation_create (NULL); + pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path); _pixman_setup_combiner_functions_32 (imp); _pixman_setup_combiner_functions_64 (imp); - imp->composite = general_composite; imp->blt = general_blt; imp->fill = general_fill; diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index e55ba2c..6036c56 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -231,6 +231,12 @@ pixman_image_set_destroy_function (pixman_image_t * image, 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) { @@ -245,6 +251,9 @@ _pixman_image_validate (pixman_image_t *image) 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 @@ -588,7 +597,7 @@ _pixman_image_is_opaque (pixman_image_t *image) break; case SOLID: - if (ALPHA_8 (image->solid.color) != 0xff) + if (image->solid.color.alpha != 0xffff) return FALSE; break; diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c index 6488332..bc3749e 100644 --- a/pixman/pixman-implementation.c +++ b/pixman/pixman-implementation.c @@ -28,30 +28,6 @@ #include "pixman-private.h" static void -delegate_composite (pixman_implementation_t * imp, - pixman_op_t op, - pixman_image_t * src, - pixman_image_t * mask, - pixman_image_t * dest, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) -{ - _pixman_implementation_composite (imp->delegate, - op, - src, mask, dest, - src_x, src_y, - mask_x, mask_y, - dest_x, dest_y, - width, height); -} - -static void delegate_combine_32 (pixman_implementation_t * imp, pixman_op_t op, uint32_t * dest, @@ -136,7 +112,8 @@ delegate_fill (pixman_implementation_t *imp, } pixman_implementation_t * -_pixman_implementation_create (pixman_implementation_t *delegate) +_pixman_implementation_create (pixman_implementation_t *delegate, + const pixman_fast_path_t *fast_paths) { pixman_implementation_t *imp = malloc (sizeof (pixman_implementation_t)); pixman_implementation_t *d; @@ -145,6 +122,8 @@ _pixman_implementation_create (pixman_implementation_t *delegate) if (!imp) return NULL; + assert (fast_paths); + /* Make sure the whole delegate chain has the right toplevel */ imp->delegate = delegate; for (d = imp; d != NULL; d = d->delegate) @@ -152,7 +131,6 @@ _pixman_implementation_create (pixman_implementation_t *delegate) /* Fill out function pointers with ones that just delegate */ - imp->composite = delegate_composite; imp->blt = delegate_blt; imp->fill = delegate_fill; @@ -164,6 +142,8 @@ _pixman_implementation_create (pixman_implementation_t *delegate) imp->combine_64_ca[i] = delegate_combine_64_ca; } + imp->fast_paths = fast_paths; + return imp; } @@ -211,27 +191,6 @@ _pixman_implementation_combine_64_ca (pixman_implementation_t * imp, (*imp->combine_64_ca[op]) (imp, op, dest, src, mask, width); } -void -_pixman_implementation_composite (pixman_implementation_t * imp, - pixman_op_t op, - pixman_image_t * src, - pixman_image_t * mask, - pixman_image_t * dest, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) -{ - (*imp->composite) (imp, op, - src, mask, dest, - src_x, src_y, mask_x, mask_y, dest_x, dest_y, - width, height); -} - pixman_bool_t _pixman_implementation_blt (pixman_implementation_t * imp, uint32_t * src_bits, diff --git a/pixman/pixman-mmx.c b/pixman/pixman-mmx.c index 819e3a0..e084e7f 100644 --- a/pixman/pixman-mmx.c +++ b/pixman/pixman-mmx.c @@ -485,7 +485,7 @@ mmx_combine_over_reverse_u (pixman_implementation_t *imp, { __m64 d, da; uint32_t s = combine (src, mask); - + d = load8888 (*dest); da = expand_alpha (d); *dest = store8888 (over (d, da, load8888 (s))); @@ -511,12 +511,12 @@ mmx_combine_in_u (pixman_implementation_t *imp, while (dest < end) { __m64 x, a; - + x = load8888 (combine (src, mask)); a = load8888 (*dest); a = expand_alpha (a); x = pix_multiply (x, a); - + *dest = store8888 (x); ++dest; @@ -540,7 +540,7 @@ mmx_combine_in_reverse_u (pixman_implementation_t *imp, while (dest < end) { __m64 x, a; - + x = load8888 (*dest); a = load8888 (combine (src, mask)); a = expand_alpha (a); @@ -568,7 +568,7 @@ mmx_combine_out_u (pixman_implementation_t *imp, while (dest < end) { __m64 x, a; - + x = load8888 (combine (src, mask)); a = load8888 (*dest); a = expand_alpha (a); @@ -597,7 +597,7 @@ mmx_combine_out_reverse_u (pixman_implementation_t *imp, while (dest < end) { __m64 x, a; - + x = load8888 (*dest); a = load8888 (combine (src, mask)); a = expand_alpha (a); @@ -627,7 +627,7 @@ mmx_combine_atop_u (pixman_implementation_t *imp, while (dest < end) { __m64 s, da, d, sia; - + s = load8888 (combine (src, mask)); d = load8888 (*dest); sia = expand_alpha (s); @@ -659,7 +659,7 @@ mmx_combine_atop_reverse_u (pixman_implementation_t *imp, while (dest < end) { __m64 s, dia, d, sa; - + s = load8888 (combine (src, mask)); d = load8888 (*dest); sa = expand_alpha (s); @@ -689,7 +689,7 @@ mmx_combine_xor_u (pixman_implementation_t *imp, while (dest < end) { __m64 s, dia, d, sia; - + s = load8888 (combine (src, mask)); d = load8888 (*dest); sia = expand_alpha (s); @@ -720,7 +720,7 @@ mmx_combine_add_u (pixman_implementation_t *imp, while (dest < end) { __m64 s, d; - + s = load8888 (combine (src, mask)); d = load8888 (*dest); s = pix_add (s, d); @@ -785,7 +785,7 @@ mmx_combine_src_ca (pixman_implementation_t *imp, { __m64 a = load8888 (*mask); __m64 s = load8888 (*src); - + s = pix_multiply (s, a); *dest = store8888 (s); @@ -864,7 +864,7 @@ mmx_combine_in_ca (pixman_implementation_t *imp, __m64 s = load8888 (*src); __m64 d = load8888 (*dest); __m64 da = expand_alpha (d); - + s = pix_multiply (s, a); s = pix_multiply (s, da); *dest = store8888 (s); @@ -892,7 +892,7 @@ mmx_combine_in_reverse_ca (pixman_implementation_t *imp, __m64 s = load8888 (*src); __m64 d = load8888 (*dest); __m64 sa = expand_alpha (s); - + a = pix_multiply (a, sa); d = pix_multiply (d, a); *dest = store8888 (d); @@ -920,7 +920,7 @@ mmx_combine_out_ca (pixman_implementation_t *imp, __m64 s = load8888 (*src); __m64 d = load8888 (*dest); __m64 da = expand_alpha (d); - + da = negate (da); s = pix_multiply (s, a); s = pix_multiply (s, da); @@ -1102,7 +1102,7 @@ mmx_composite_over_n_8888 (pixman_implementation_t *imp, { uint32_t src; uint32_t *dst_line, *dst; - uint16_t w; + int32_t w; int dst_stride; __m64 vsrc, vsrca; @@ -1181,7 +1181,7 @@ mmx_composite_over_n_0565 (pixman_implementation_t *imp, { uint32_t src; uint16_t *dst_line, *dst; - uint16_t w; + int32_t w; int dst_stride; __m64 vsrc, vsrca; @@ -1209,7 +1209,7 @@ mmx_composite_over_n_0565 (pixman_implementation_t *imp, { uint64_t d = *dst; __m64 vdest = expand565 (M64 (d), 0); - + vdest = pack_565 (over (vsrc, vsrca, vdest), vdest, 0); *dst = UINT64 (vdest); @@ -1240,7 +1240,7 @@ mmx_composite_over_n_0565 (pixman_implementation_t *imp, { uint64_t d = *dst; __m64 vdest = expand565 (M64 (d), 0); - + vdest = pack_565 (over (vsrc, vsrca, vdest), vdest, 0); *dst = UINT64 (vdest); @@ -1376,7 +1376,7 @@ mmx_composite_over_8888_n_8888 (pixman_implementation_t *imp, uint32_t mask; __m64 vmask; int dst_stride, src_stride; - uint16_t w; + int32_t w; __m64 srca; CHECKPOINT (); @@ -1461,7 +1461,7 @@ mmx_composite_over_x888_n_8888 (pixman_implementation_t *imp, uint32_t mask; __m64 vmask; int dst_stride, src_stride; - uint16_t w; + int32_t w; __m64 srca; CHECKPOINT (); @@ -1596,7 +1596,7 @@ mmx_composite_over_8888_8888 (pixman_implementation_t *imp, uint32_t s; int dst_stride, src_stride; uint8_t a; - uint16_t w; + int32_t w; CHECKPOINT (); @@ -1615,7 +1615,7 @@ mmx_composite_over_8888_8888 (pixman_implementation_t *imp, { s = *src++; a = s >> 24; - + if (a == 0xff) { *dst = s; @@ -1627,7 +1627,7 @@ mmx_composite_over_8888_8888 (pixman_implementation_t *imp, sa = expand_alpha (ms); *dst = store8888 (over (ms, sa, load8888 (*dst))); } - + dst++; } } @@ -1652,7 +1652,7 @@ mmx_composite_over_8888_0565 (pixman_implementation_t *imp, uint16_t *dst_line, *dst; uint32_t *src_line, *src; int dst_stride, src_stride; - uint16_t w; + int32_t w; CHECKPOINT (); @@ -1756,7 +1756,7 @@ mmx_composite_over_n_8_8888 (pixman_implementation_t *imp, uint32_t *dst_line, *dst; uint8_t *mask_line, *mask; int dst_stride, mask_stride; - uint16_t w; + int32_t w; __m64 vsrc, vsrca; uint64_t srcsrc; @@ -1795,7 +1795,7 @@ mmx_composite_over_n_8_8888 (pixman_implementation_t *imp, __m64 vdest = in_over (vsrc, vsrca, expand_alpha_rev (M64 (m)), load8888 (*dst)); - + *dst = store8888 (vdest); } @@ -1809,7 +1809,7 @@ mmx_composite_over_n_8_8888 (pixman_implementation_t *imp, while (w >= 2) { uint64_t m0, m1; - + m0 = *mask; m1 = *(mask + 1); @@ -1883,22 +1883,13 @@ pixman_fill_mmx (uint32_t *bits, if (bpp != 16 && bpp != 32 && bpp != 8) return FALSE; - if (bpp == 16 && (xor >> 16 != (xor & 0xffff))) - return FALSE; - - if (bpp == 8 && - ((xor >> 16 != (xor & 0xffff)) || - (xor >> 24 != (xor & 0x00ff) >> 16))) - { - return FALSE; - } - if (bpp == 8) { stride = stride * (int) sizeof (uint32_t) / 1; byte_line = (uint8_t *)(((uint8_t *)bits) + stride * y + x); byte_width = width; stride *= 1; + xor = (xor & 0xff) * 0x01010101; } else if (bpp == 16) { @@ -1906,6 +1897,7 @@ pixman_fill_mmx (uint32_t *bits, byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x); byte_width = 2 * width; stride *= 2; + xor = (xor & 0xffff) * 0x00010001; } else { @@ -1928,7 +1920,7 @@ pixman_fill_mmx (uint32_t *bits, "movq %7, %5\n" "movq %7, %6\n" : "=y" (v1), "=y" (v2), "=y" (v3), - "=y" (v4), "=y" (v5), "=y" (v6), "=y" (v7) + "=y" (v4), "=y" (v5), "=y" (v6), "=y" (v7) : "y" (vfill)); #endif @@ -1936,7 +1928,7 @@ pixman_fill_mmx (uint32_t *bits, { int w; uint8_t *d = byte_line; - + byte_line += stride; w = byte_width; @@ -1976,8 +1968,8 @@ pixman_fill_mmx (uint32_t *bits, "movq %8, 56(%0)\n" : : "r" (d), - "y" (vfill), "y" (v1), "y" (v2), "y" (v3), - "y" (v4), "y" (v5), "y" (v6), "y" (v7) + "y" (vfill), "y" (v1), "y" (v2), "y" (v3), + "y" (v4), "y" (v5), "y" (v6), "y" (v7) : "memory"); #else *(__m64*) (d + 0) = vfill; @@ -2038,7 +2030,7 @@ mmx_composite_src_n_8_8888 (pixman_implementation_t *imp, uint32_t *dst_line, *dst; uint8_t *mask_line, *mask; int dst_stride, mask_stride; - uint16_t w; + int32_t w; __m64 vsrc, vsrca; uint64_t srcsrc; @@ -2080,7 +2072,7 @@ mmx_composite_src_n_8_8888 (pixman_implementation_t *imp, if (m) { __m64 vdest = in (vsrc, expand_alpha_rev (M64 (m))); - + *dst = store8888 (vdest); } else @@ -2136,7 +2128,7 @@ mmx_composite_src_n_8_8888 (pixman_implementation_t *imp, if (m) { __m64 vdest = load8888 (*dst); - + vdest = in (vsrc, expand_alpha_rev (M64 (m))); *dst = store8888 (vdest); } @@ -2173,7 +2165,7 @@ mmx_composite_over_n_8_0565 (pixman_implementation_t *imp, uint16_t *dst_line, *dst; uint8_t *mask_line, *mask; int dst_stride, mask_stride; - uint16_t w; + int32_t w; __m64 vsrc, vsrca, tmp; uint64_t srcsrcsrcsrc, src16; @@ -2218,7 +2210,7 @@ mmx_composite_over_n_8_0565 (pixman_implementation_t *imp, __m64 vd = M64 (d); __m64 vdest = in_over ( vsrc, vsrca, expand_alpha_rev (M64 (m)), expand565 (vd, 0)); - + vd = pack_565 (vdest, _mm_setzero_si64 (), 0); *dst = UINT64 (vd); } @@ -2313,7 +2305,7 @@ mmx_composite_over_pixbuf_0565 (pixman_implementation_t *imp, uint16_t *dst_line, *dst; uint32_t *src_line, *src; int dst_stride, src_stride; - uint16_t w; + int32_t w; CHECKPOINT (); @@ -2433,7 +2425,7 @@ mmx_composite_over_pixbuf_8888 (pixman_implementation_t *imp, uint32_t *dst_line, *dst; uint32_t *src_line, *src; int dst_stride, src_stride; - uint16_t w; + int32_t w; CHECKPOINT (); @@ -2641,7 +2633,7 @@ mmx_composite_in_n_8_8 (pixman_implementation_t *imp, uint8_t *dst_line, *dst; uint8_t *mask_line, *mask; int dst_stride, mask_stride; - uint16_t w; + int32_t w; uint32_t src; uint8_t sa; __m64 vsrc, vsrca; @@ -2723,7 +2715,7 @@ mmx_composite_in_8_8 (pixman_implementation_t *imp, uint8_t *dst_line, *dst; uint8_t *src_line, *src; int src_stride, dst_stride; - uint16_t w; + int32_t w; PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1); PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1); @@ -2788,7 +2780,7 @@ mmx_composite_add_n_8_8 (pixman_implementation_t *imp, uint8_t *dst_line, *dst; uint8_t *mask_line, *mask; int dst_stride, mask_stride; - uint16_t w; + int32_t w; uint32_t src; uint8_t sa; __m64 vsrc, vsrca; @@ -2868,7 +2860,7 @@ mmx_composite_add_8000_8000 (pixman_implementation_t *imp, uint8_t *dst_line, *dst; uint8_t *src_line, *src; int dst_stride, src_stride; - uint16_t w; + int32_t w; uint8_t s, d; uint16_t t; @@ -2942,7 +2934,7 @@ mmx_composite_add_8888_8888 (pixman_implementation_t *imp, uint32_t *dst_line, *dst; uint32_t *src_line, *src; int dst_stride, src_stride; - uint16_t w; + int32_t w; CHECKPOINT (); @@ -3082,8 +3074,8 @@ pixman_blt_mmx (uint32_t *src_bits, : : "r" (d), "r" (s) : "memory", - "%mm0", "%mm1", "%mm2", "%mm3", - "%mm4", "%mm5", "%mm6", "%mm7"); + "%mm0", "%mm1", "%mm2", "%mm3", + "%mm4", "%mm5", "%mm6", "%mm7"); #else __m64 v0 = *(__m64 *)(s + 0); __m64 v1 = *(__m64 *)(s + 8); @@ -3173,7 +3165,7 @@ mmx_composite_over_x888_8_8888 (pixman_implementation_t *imp, uint32_t *dst, *dst_line; uint8_t *mask, *mask_line; int src_stride, mask_stride, dst_stride; - uint16_t w; + int32_t w; PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1); @@ -3224,107 +3216,78 @@ mmx_composite_over_x888_8_8888 (pixman_implementation_t *imp, static const pixman_fast_path_t mmx_fast_paths[] = { - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_r5g6b5, mmx_composite_over_n_8_0565 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_b5g6r5, mmx_composite_over_n_8_0565 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8r8g8b8, mmx_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8r8g8b8, mmx_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8b8g8r8, mmx_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8b8g8r8, mmx_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8_ca, PIXMAN_a8r8g8b8, mmx_composite_over_n_8888_8888_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8_ca, PIXMAN_x8r8g8b8, mmx_composite_over_n_8888_8888_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8_ca, PIXMAN_r5g6b5, mmx_composite_over_n_8888_0565_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8_ca, PIXMAN_a8b8g8r8, mmx_composite_over_n_8888_8888_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8_ca, PIXMAN_x8b8g8r8, mmx_composite_over_n_8888_8888_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8_ca, PIXMAN_b5g6r5, mmx_composite_over_n_8888_0565_ca }, - { PIXMAN_OP_OVER, PIXMAN_pixbuf, PIXMAN_pixbuf, PIXMAN_a8r8g8b8, mmx_composite_over_pixbuf_8888 }, - { PIXMAN_OP_OVER, PIXMAN_pixbuf, PIXMAN_pixbuf, PIXMAN_x8r8g8b8, mmx_composite_over_pixbuf_8888 }, - { PIXMAN_OP_OVER, PIXMAN_pixbuf, PIXMAN_pixbuf, PIXMAN_r5g6b5, mmx_composite_over_pixbuf_0565 }, - { PIXMAN_OP_OVER, PIXMAN_rpixbuf, PIXMAN_rpixbuf, PIXMAN_a8b8g8r8, mmx_composite_over_pixbuf_8888 }, - { PIXMAN_OP_OVER, PIXMAN_rpixbuf, PIXMAN_rpixbuf, PIXMAN_x8b8g8r8, mmx_composite_over_pixbuf_8888 }, - { PIXMAN_OP_OVER, PIXMAN_rpixbuf, PIXMAN_rpixbuf, PIXMAN_b5g6r5, mmx_composite_over_pixbuf_0565 }, - { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_solid, PIXMAN_a8r8g8b8, mmx_composite_over_x888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_solid, PIXMAN_x8r8g8b8, mmx_composite_over_x888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_solid, PIXMAN_a8b8g8r8, mmx_composite_over_x888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_solid, PIXMAN_x8b8g8r8, mmx_composite_over_x888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_solid, PIXMAN_a8r8g8b8, mmx_composite_over_8888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_solid, PIXMAN_x8r8g8b8, mmx_composite_over_8888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_solid, PIXMAN_a8b8g8r8, mmx_composite_over_8888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_solid, PIXMAN_x8b8g8r8, mmx_composite_over_8888_n_8888 }, + PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, mmx_composite_over_n_8_0565 ), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, mmx_composite_over_n_8_0565 ), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, mmx_composite_over_n_8_8888 ), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, mmx_composite_over_n_8_8888 ), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, mmx_composite_over_n_8_8888 ), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, mmx_composite_over_n_8_8888 ), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, mmx_composite_over_n_8888_8888_ca ), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, mmx_composite_over_n_8888_8888_ca ), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, mmx_composite_over_n_8888_0565_ca ), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, mmx_composite_over_n_8888_8888_ca ), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, mmx_composite_over_n_8888_8888_ca ), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, mmx_composite_over_n_8888_0565_ca ), + PIXMAN_STD_FAST_PATH (OVER, pixbuf, pixbuf, a8r8g8b8, mmx_composite_over_pixbuf_8888 ), + PIXMAN_STD_FAST_PATH (OVER, pixbuf, pixbuf, x8r8g8b8, mmx_composite_over_pixbuf_8888 ), + PIXMAN_STD_FAST_PATH (OVER, pixbuf, pixbuf, r5g6b5, mmx_composite_over_pixbuf_0565 ), + PIXMAN_STD_FAST_PATH (OVER, rpixbuf, rpixbuf, a8b8g8r8, mmx_composite_over_pixbuf_8888 ), + PIXMAN_STD_FAST_PATH (OVER, rpixbuf, rpixbuf, x8b8g8r8, mmx_composite_over_pixbuf_8888 ), + PIXMAN_STD_FAST_PATH (OVER, rpixbuf, rpixbuf, b5g6r5, mmx_composite_over_pixbuf_0565 ), + PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, solid, a8r8g8b8, mmx_composite_over_x888_n_8888 ), + PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, solid, x8r8g8b8, mmx_composite_over_x888_n_8888 ), + PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, solid, a8b8g8r8, mmx_composite_over_x888_n_8888 ), + PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, solid, x8b8g8r8, mmx_composite_over_x888_n_8888 ), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, mmx_composite_over_8888_n_8888 ), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, mmx_composite_over_8888_n_8888 ), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, a8b8g8r8, mmx_composite_over_8888_n_8888 ), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, x8b8g8r8, mmx_composite_over_8888_n_8888 ), #if 0 - /* FIXME: This code is commented out since it's apparently not actually faster than the generic code. */ - { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_x8r8g8b8, mmx_composite_over_x888_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_a8r8g8b8, mmx_composite_over_x888_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8b8r8g8, PIXMAN_a8, PIXMAN_x8b8g8r8, mmx_composite_over_x888_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8b8r8g8, PIXMAN_a8, PIXMAN_a8r8g8b8, mmx_composite_over_x888_8_8888 }, + /* FIXME: This code is commented out since it's apparently + * not actually faster than the generic code. + */ + PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, x8r8g8b8, mmx_composite_over_x888_8_8888 ), + PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, a8r8g8b8, mmx_composite_over_x888_8_8888 ), + PIXMAN_STD_FAST_PATH (OVER, x8b8r8g8, a8, x8b8g8r8, mmx_composite_over_x888_8_8888 ), + PIXMAN_STD_FAST_PATH (OVER, x8b8r8g8, a8, a8r8g8b8, mmx_composite_over_x888_8_8888 ), #endif - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_a8r8g8b8, mmx_composite_over_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_x8r8g8b8, mmx_composite_over_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_r5g6b5, mmx_composite_over_n_0565 }, - { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, mmx_composite_copy_area }, - { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, mmx_composite_copy_area }, - - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, mmx_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, mmx_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, mmx_composite_over_8888_0565 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, mmx_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, mmx_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, mmx_composite_over_8888_0565 }, - - { PIXMAN_OP_ADD, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, mmx_composite_add_8888_8888 }, - { PIXMAN_OP_ADD, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, mmx_composite_add_8888_8888 }, - { PIXMAN_OP_ADD, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, mmx_composite_add_8000_8000 }, - { PIXMAN_OP_ADD, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, mmx_composite_add_n_8_8 }, - - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8r8g8b8, mmx_composite_src_n_8_8888 }, - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8r8g8b8, mmx_composite_src_n_8_8888 }, - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8b8g8r8, mmx_composite_src_n_8_8888 }, - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8b8g8r8, mmx_composite_src_n_8_8888 }, - { PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, mmx_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, mmx_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, mmx_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, mmx_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, mmx_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, mmx_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_r5g6b5, PIXMAN_null, PIXMAN_r5g6b5, mmx_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_b5g6r5, PIXMAN_null, PIXMAN_b5g6r5, mmx_composite_copy_area }, - - { PIXMAN_OP_IN, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, mmx_composite_in_8_8 }, - { PIXMAN_OP_IN, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, mmx_composite_in_n_8_8 }, + PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, mmx_composite_over_n_8888 ), + PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, mmx_composite_over_n_8888 ), + PIXMAN_STD_FAST_PATH (OVER, solid, null, r5g6b5, mmx_composite_over_n_0565 ), + PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, null, x8r8g8b8, mmx_composite_copy_area ), + PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, null, x8b8g8r8, mmx_composite_copy_area ), + + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, mmx_composite_over_8888_8888 ), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, mmx_composite_over_8888_8888 ), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, mmx_composite_over_8888_0565 ), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, mmx_composite_over_8888_8888 ), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, mmx_composite_over_8888_8888 ), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, mmx_composite_over_8888_0565 ), + + PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, mmx_composite_add_8888_8888 ), + PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, mmx_composite_add_8888_8888 ), + PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, mmx_composite_add_8000_8000 ), + PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, mmx_composite_add_n_8_8 ), + + PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8r8g8b8, mmx_composite_src_n_8_8888 ), + PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, mmx_composite_src_n_8_8888 ), + PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, mmx_composite_src_n_8_8888 ), + PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8b8g8r8, mmx_composite_src_n_8_8888 ), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, mmx_composite_copy_area ), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, mmx_composite_copy_area ), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, mmx_composite_copy_area ), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, mmx_composite_copy_area ), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, mmx_composite_copy_area ), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, mmx_composite_copy_area ), + PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, mmx_composite_copy_area ), + PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, mmx_composite_copy_area ), + + PIXMAN_STD_FAST_PATH (IN, a8, null, a8, mmx_composite_in_8_8 ), + PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, mmx_composite_in_n_8_8 ), { PIXMAN_OP_NONE }, }; -static void -mmx_composite (pixman_implementation_t *imp, - pixman_op_t op, - pixman_image_t * src, - pixman_image_t * mask, - pixman_image_t * dest, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) -{ - if (_pixman_run_fast_path (mmx_fast_paths, imp, - op, src, mask, dest, - src_x, src_y, - mask_x, mask_y, - dest_x, dest_y, - width, height)) - { - return; - } - - _pixman_implementation_composite (imp->delegate, - op, src, mask, dest, src_x, src_y, - mask_x, mask_y, dest_x, dest_y, - width, height); -} - static pixman_bool_t mmx_blt (pixman_implementation_t *imp, uint32_t * src_bits, @@ -3346,9 +3309,9 @@ mmx_blt (pixman_implementation_t *imp, { return _pixman_implementation_blt ( - imp->delegate, - src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, - src_x, src_y, dst_x, dst_y, width, height); + imp->delegate, + src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, + src_x, src_y, dst_x, dst_y, width, height); } return TRUE; @@ -3368,7 +3331,7 @@ mmx_fill (pixman_implementation_t *imp, if (!pixman_fill_mmx (bits, stride, bpp, x, y, width, height, xor)) { return _pixman_implementation_fill ( - imp->delegate, bits, stride, bpp, x, y, width, height, xor); + imp->delegate, bits, stride, bpp, x, y, width, height, xor); } return TRUE; @@ -3378,7 +3341,7 @@ pixman_implementation_t * _pixman_implementation_create_mmx (void) { pixman_implementation_t *general = _pixman_implementation_create_fast_path (); - pixman_implementation_t *imp = _pixman_implementation_create (general); + pixman_implementation_t *imp = _pixman_implementation_create (general, mmx_fast_paths); imp->combine_32[PIXMAN_OP_OVER] = mmx_combine_over_u; imp->combine_32[PIXMAN_OP_OVER_REVERSE] = mmx_combine_over_reverse_u; @@ -3404,7 +3367,6 @@ _pixman_implementation_create_mmx (void) imp->combine_32_ca[PIXMAN_OP_XOR] = mmx_combine_xor_ca; imp->combine_32_ca[PIXMAN_OP_ADD] = mmx_combine_add_ca; - imp->composite = mmx_composite; imp->blt = mmx_blt; imp->fill = mmx_fill; diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 0745149..7ed8aa7 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -114,7 +114,10 @@ struct source_image struct solid_fill { source_image_t common; - uint32_t color; /* FIXME: shouldn't this be a pixman_color_t? */ + pixman_color_t color; + + uint32_t color_32; + uint64_t color_64; }; struct gradient @@ -254,10 +257,6 @@ _pixman_image_store_scanline_32 (bits_image_t * image, int y, int width, const uint32_t *buffer); -void -_pixman_image_fetch_pixels (bits_image_t *image, - uint32_t * buffer, - int n_pixels); /* Even though the type of buffer is uint32_t *, the function * actually expects a uint64_t *buffer. @@ -373,7 +372,6 @@ pixman_rasterize_edges_accessors (pixman_image_t *image, /* * Implementations */ - typedef struct pixman_implementation_t pixman_implementation_t; typedef void (*pixman_combine_32_func_t) (pixman_implementation_t *imp, @@ -429,23 +427,36 @@ typedef pixman_bool_t (*pixman_fill_func_t) (pixman_implementation_t *imp, void _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp); void _pixman_setup_combiner_functions_64 (pixman_implementation_t *imp); -struct pixman_implementation_t +typedef struct { - pixman_implementation_t *toplevel; - pixman_implementation_t *delegate; - - pixman_composite_func_t composite; - pixman_blt_func_t blt; - pixman_fill_func_t fill; + pixman_op_t op; + pixman_format_code_t src_format; + uint32_t src_flags; + pixman_format_code_t mask_format; + uint32_t mask_flags; + pixman_format_code_t dest_format; + uint32_t dest_flags; + pixman_composite_func_t func; +} pixman_fast_path_t; - pixman_combine_32_func_t combine_32[PIXMAN_N_OPERATORS]; - pixman_combine_32_func_t combine_32_ca[PIXMAN_N_OPERATORS]; - pixman_combine_64_func_t combine_64[PIXMAN_N_OPERATORS]; - pixman_combine_64_func_t combine_64_ca[PIXMAN_N_OPERATORS]; +struct pixman_implementation_t +{ + pixman_implementation_t * toplevel; + pixman_implementation_t * delegate; + const pixman_fast_path_t * fast_paths; + + pixman_blt_func_t blt; + pixman_fill_func_t fill; + + pixman_combine_32_func_t combine_32[PIXMAN_N_OPERATORS]; + pixman_combine_32_func_t combine_32_ca[PIXMAN_N_OPERATORS]; + pixman_combine_64_func_t combine_64[PIXMAN_N_OPERATORS]; + pixman_combine_64_func_t combine_64_ca[PIXMAN_N_OPERATORS]; }; pixman_implementation_t * -_pixman_implementation_create (pixman_implementation_t *delegate); +_pixman_implementation_create (pixman_implementation_t *delegate, + const pixman_fast_path_t *fast_paths); void _pixman_implementation_combine_32 (pixman_implementation_t *imp, @@ -475,20 +486,6 @@ _pixman_implementation_combine_64_ca (pixman_implementation_t *imp, const uint64_t * src, const uint64_t * mask, int width); -void -_pixman_implementation_composite (pixman_implementation_t *imp, - pixman_op_t op, - pixman_image_t * src, - pixman_image_t * mask, - pixman_image_t * dest, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height); pixman_bool_t _pixman_implementation_blt (pixman_implementation_t *imp, @@ -562,19 +559,73 @@ _pixman_choose_implementation (void); */ #define PIXMAN_null PIXMAN_FORMAT (0, 0, 0, 0, 0, 0) #define PIXMAN_solid PIXMAN_FORMAT (0, 1, 0, 0, 0, 0) -#define PIXMAN_a8r8g8b8_ca PIXMAN_FORMAT (0, 2, 0, 0, 0, 0) -#define PIXMAN_a8b8g8r8_ca PIXMAN_FORMAT (0, 3, 0, 0, 0, 0) -#define PIXMAN_pixbuf PIXMAN_FORMAT (0, 4, 0, 0, 0, 0) -#define PIXMAN_rpixbuf PIXMAN_FORMAT (0, 5, 0, 0, 0, 0) - -typedef struct -{ - pixman_op_t op; - pixman_format_code_t src_format; - pixman_format_code_t mask_format; - pixman_format_code_t dest_format; - pixman_composite_func_t func; -} pixman_fast_path_t; +#define PIXMAN_pixbuf PIXMAN_FORMAT (0, 2, 0, 0, 0, 0) +#define PIXMAN_rpixbuf PIXMAN_FORMAT (0, 3, 0, 0, 0, 0) +#define PIXMAN_unknown PIXMAN_FORMAT (0, 4, 0, 0, 0, 0) +#define PIXMAN_any PIXMAN_FORMAT (0, 5, 0, 0, 0, 0) + +#define PIXMAN_OP_any (PIXMAN_N_OPERATORS + 1) + +#define FAST_PATH_ID_TRANSFORM (1 << 0) +#define FAST_PATH_NO_ALPHA_MAP (1 << 1) +#define FAST_PATH_NO_CONVOLUTION_FILTER (1 << 2) +#define FAST_PATH_NO_PAD_REPEAT (1 << 3) +#define FAST_PATH_NO_REFLECT_REPEAT (1 << 4) +#define FAST_PATH_NO_ACCESSORS (1 << 5) +#define FAST_PATH_NO_WIDE_FORMAT (1 << 6) +#define FAST_PATH_COVERS_CLIP (1 << 7) +#define FAST_PATH_COMPONENT_ALPHA (1 << 8) +#define FAST_PATH_UNIFIED_ALPHA (1 << 9) +#define FAST_PATH_SCALE_TRANSFORM (1 << 10) +#define FAST_PATH_NEAREST_FILTER (1 << 11) + +#define _FAST_PATH_STANDARD_FLAGS \ + (FAST_PATH_ID_TRANSFORM | \ + FAST_PATH_NO_ALPHA_MAP | \ + FAST_PATH_NO_CONVOLUTION_FILTER | \ + FAST_PATH_NO_PAD_REPEAT | \ + FAST_PATH_NO_REFLECT_REPEAT | \ + FAST_PATH_NO_ACCESSORS | \ + FAST_PATH_NO_WIDE_FORMAT | \ + FAST_PATH_COVERS_CLIP) + +#define FAST_PATH_STD_SRC_FLAGS \ + _FAST_PATH_STANDARD_FLAGS +#define FAST_PATH_STD_MASK_U_FLAGS \ + (_FAST_PATH_STANDARD_FLAGS | \ + FAST_PATH_UNIFIED_ALPHA) +#define FAST_PATH_STD_MASK_CA_FLAGS \ + (_FAST_PATH_STANDARD_FLAGS | \ + FAST_PATH_COMPONENT_ALPHA) +#define FAST_PATH_STD_DEST_FLAGS \ + (FAST_PATH_NO_ACCESSORS | \ + FAST_PATH_NO_WIDE_FORMAT) + +#define FAST_PATH(op, src, src_flags, mask, mask_flags, dest, dest_flags, func) \ + PIXMAN_OP_ ## op, \ + PIXMAN_ ## src, \ + src_flags, \ + PIXMAN_ ## mask, \ + mask_flags, \ + PIXMAN_ ## dest, \ + dest_flags, \ + func + +#define PIXMAN_STD_FAST_PATH(op, src, mask, dest, func) \ + { FAST_PATH ( \ + op, \ + src, FAST_PATH_STD_SRC_FLAGS, \ + mask, (PIXMAN_ ## mask) ? FAST_PATH_STD_MASK_U_FLAGS : 0, \ + dest, FAST_PATH_STD_DEST_FLAGS, \ + func) } + +#define PIXMAN_STD_FAST_PATH_CA(op, src, mask, dest, func) \ + { FAST_PATH ( \ + op, \ + src, FAST_PATH_STD_SRC_FLAGS, \ + mask, FAST_PATH_STD_MASK_CA_FLAGS, \ + dest, FAST_PATH_STD_DEST_FLAGS, \ + func) } /* Memory allocation helpers */ void * @@ -590,38 +641,6 @@ pixman_bool_t pixman_addition_overflows_int (unsigned int a, unsigned int b); /* Compositing utilities */ -pixman_bool_t -_pixman_run_fast_path (const pixman_fast_path_t *paths, - pixman_implementation_t * imp, - pixman_op_t op, - pixman_image_t * src, - pixman_image_t * mask, - pixman_image_t * dest, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height); - -void -_pixman_walk_composite_region (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 dest_x, - int32_t dest_y, - int32_t width, - int32_t height, - pixman_composite_func_t composite_rect); - void pixman_expand (uint64_t * dst, const uint32_t * src, @@ -690,23 +709,50 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst, PIXMAN_FORMAT_G (f) > 8 || \ PIXMAN_FORMAT_B (f) > 8) +#ifdef WORDS_BIGENDIAN +# define SCREEN_SHIFT_LEFT(x,n) ((x) << (n)) +# define SCREEN_SHIFT_RIGHT(x,n) ((x) >> (n)) +#else +# define SCREEN_SHIFT_LEFT(x,n) ((x) >> (n)) +# define SCREEN_SHIFT_RIGHT(x,n) ((x) << (n)) +#endif + /* * Various debugging code */ #undef DEBUG -#define DEBUG 0 -#if DEBUG +/* Turn on debugging depending on what type of release this is + */ +#if (((PIXMAN_VERSION_MICRO % 2) == 0) && ((PIXMAN_VERSION_MINOR % 2) == 1)) + +/* Debugging gets turned on for development releases because these + * are the things that end up in bleeding edge distributions such + * as Rawhide etc. + * + * For performance reasons we don't turn it on for stable releases or + * random git checkouts. (Random git checkouts are often used for + * performance work). + */ + +# define DEBUG + +#endif + +#ifdef DEBUG + +void +_pixman_log_error (const char *function, const char *message); #define return_if_fail(expr) \ do \ { \ - if (!(expr)) \ - { \ - fprintf (stderr, "In %s: %s failed\n", FUNC, # expr); \ - return; \ - } \ + if (!(expr)) \ + { \ + _pixman_log_error (FUNC, "The expression " # expr " was false"); \ + return; \ + } \ } \ while (0) @@ -714,16 +760,27 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst, do \ { \ if (!(expr)) \ - { \ - fprintf (stderr, "In %s: %s failed\n", FUNC, # expr); \ - return (retval); \ - } \ + { \ + _pixman_log_error (FUNC, "The expression " # expr " was false"); \ + return (retval); \ + } \ } \ while (0) +#define critical_if_fail(expr) \ + do \ + { \ + if (!(expr)) \ + _pixman_log_error (FUNC, "The expression " # expr " was false"); \ + } \ + while (0) + + #else -#define return_if_fail(expr) \ +#define _pixman_log_error(f,m) do { } while (0) \ + +#define return_if_fail(expr) \ do \ { \ if (!(expr)) \ @@ -739,6 +796,11 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst, } \ while (0) +#define critical_if_fail(expr) \ + do \ + { \ + } \ + while (0) #endif /* diff --git a/pixman/pixman-region.c b/pixman/pixman-region.c index f88955f..a6a4005 100644 --- a/pixman/pixman-region.c +++ b/pixman/pixman-region.c @@ -42,6 +42,25 @@ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * + * Copyright © 1998 Keith Packard + * + * 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 Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. */ #include <stdlib.h> @@ -66,41 +85,17 @@ #define GOOD_RECT(rect) ((rect)->x1 < (rect)->x2 && (rect)->y1 < (rect)->y2) #define BAD_RECT(rect) ((rect)->x1 > (rect)->x2 || (rect)->y1 > (rect)->y2) -#define noPIXMAN_REGION_LOG_FAILURES - -#if defined PIXMAN_REGION_LOG_FAILURES || defined PIXMAN_REGION_DEBUG - -static void -log_region_error (const char *function, const char *message) -{ - static int n_messages = 0; - - if (n_messages < 50) - { - fprintf (stderr, - "*** BUG ***\n" - "%s: %s\n" - "Set a breakpoint on 'log_region_error' to debug\n\n", - function, message); - -#if defined PIXMAN_REGION_DEBUG - abort (); -#endif - - n_messages++; - } -} +#ifdef DEBUG #define GOOD(reg) \ do \ { \ if (!PREFIX (_selfcheck (reg))) \ - log_region_error (FUNC, "Malformed region " # reg); \ + _pixman_log_error (FUNC, "Malformed region " # reg); \ } while (0) #else -#define log_region_error(function, name) #define GOOD(reg) #endif @@ -262,7 +257,7 @@ alloc_data (size_t n) } \ ADDRECT (next_rect, nx1, ny1, nx2, ny2); \ region->data->numRects++; \ - assert (region->data->numRects <= region->data->size); \ + critical_if_fail (region->data->numRects <= region->data->size); \ } while (0) #define DOWNSIZE(reg, numRects) \ @@ -387,7 +382,7 @@ PREFIX (_init_rect) (region_type_t * region, if (!GOOD_RECT (®ion->extents)) { if (BAD_RECT (®ion->extents)) - log_region_error (FUNC, "Invalid rectangle passed"); + _pixman_log_error (FUNC, "Invalid rectangle passed"); PREFIX (_init) (region); return; } @@ -401,7 +396,7 @@ PREFIX (_init_with_extents) (region_type_t *region, box_type_t *extents) if (!GOOD_RECT (extents)) { if (BAD_RECT (extents)) - log_region_error (FUNC, "Invalid rectangle passed"); + _pixman_log_error (FUNC, "Invalid rectangle passed"); PREFIX (_init) (region); return; } @@ -579,7 +574,7 @@ pixman_coalesce (region_type_t * region, /* Region to coalesce */ * Figure out how many rectangles are in the band. */ numRects = cur_start - prev_start; - assert (numRects == region->data->numRects - cur_start); + critical_if_fail (numRects == region->data->numRects - cur_start); if (!numRects) return cur_start; @@ -667,8 +662,8 @@ pixman_region_append_non_o (region_type_t * region, new_rects = r_end - r; - assert (y1 < y2); - assert (new_rects != 0); + critical_if_fail (y1 < y2); + critical_if_fail (new_rects != 0); /* Make sure we have enough space for all rectangles to be added */ RECTALLOC (region, new_rects); @@ -677,7 +672,7 @@ pixman_region_append_non_o (region_type_t * region, do { - assert (r->x1 < r->x2); + critical_if_fail (r->x1 < r->x2); ADDRECT (next_rect, r->x1, y1, r->x2, y2); r++; } @@ -802,8 +797,8 @@ pixman_op (region_type_t * new_reg, /* Place to store result r2 = PIXREGION_RECTS (reg2); r2_end = r2 + numRects; - assert (r1 != r1_end); - assert (r2 != r2_end); + critical_if_fail (r1 != r1_end); + critical_if_fail (r2 != r2_end); old_data = (region_data_type_t *)NULL; @@ -871,8 +866,8 @@ pixman_op (region_type_t * new_reg, /* Place to store result * rectangle after the last one in the current band for their * respective regions. */ - assert (r1 != r1_end); - assert (r2 != r2_end); + critical_if_fail (r1 != r1_end); + critical_if_fail (r2 != r2_end); FIND_BAND (r1, r1_band_end, r1_end, r1y1); FIND_BAND (r2, r2_band_end, r2_end, r2y1); @@ -1079,7 +1074,7 @@ pixman_set_extents (region_type_t *region) region->extents.x2 = box_end->x2; region->extents.y2 = box_end->y2; - assert (region->extents.y1 < region->extents.y2); + critical_if_fail (region->extents.y1 < region->extents.y2); while (box <= box_end) { @@ -1090,7 +1085,7 @@ pixman_set_extents (region_type_t *region) box++; } - assert (region->extents.x1 < region->extents.x2); + critical_if_fail (region->extents.x1 < region->extents.x2); } /*====================================================================== @@ -1126,8 +1121,8 @@ pixman_region_intersect_o (region_type_t *region, next_rect = PIXREGION_TOP (region); - assert (y1 < y2); - assert (r1 != r1_end && r2 != r2_end); + critical_if_fail (y1 < y2); + critical_if_fail (r1 != r1_end && r2 != r2_end); do { @@ -1284,8 +1279,8 @@ pixman_region_union_o (region_type_t *region, int x1; /* left and right side of current union */ int x2; - assert (y1 < y2); - assert (r1 != r1_end && r2 != r2_end); + critical_if_fail (y1 < y2); + critical_if_fail (r1 != r1_end && r2 != r2_end); next_rect = PIXREGION_TOP (region); @@ -1355,10 +1350,10 @@ PREFIX (_union_rect) (region_type_t *dest, if (!GOOD_RECT (®ion.extents)) { if (BAD_RECT (®ion.extents)) - log_region_error (FUNC, "Invalid rectangle passed"); + _pixman_log_error (FUNC, "Invalid rectangle passed"); return PREFIX (_copy) (dest, source); } - + region.data = NULL; return PREFIX (_union) (dest, source, ®ion); @@ -1848,8 +1843,8 @@ pixman_region_subtract_o (region_type_t * region, x1 = r1->x1; - assert (y1 < y2); - assert (r1 != r1_end && r2 != r2_end); + critical_if_fail (y1 < y2); + critical_if_fail (r1 != r1_end && r2 != r2_end); next_rect = PIXREGION_TOP (region); @@ -1893,7 +1888,7 @@ pixman_region_subtract_o (region_type_t * region, * Left part of subtrahend covers part of minuend: add uncovered * part of minuend to region and skip to next subtrahend. */ - assert (x1 < r2->x1); + critical_if_fail (x1 < r2->x1); NEWRECT (region, next_rect, x1, y1, r2->x1, y2); x1 = r2->x2; @@ -1935,7 +1930,7 @@ pixman_region_subtract_o (region_type_t * region, */ while (r1 != r1_end) { - assert (x1 < r1->x2); + critical_if_fail (x1 < r1->x2); NEWRECT (region, next_rect, x1, y1, r1->x2, y2); @@ -2297,7 +2292,7 @@ PREFIX (_reset) (region_type_t *region, box_type_t *box) { GOOD (region); - assert (GOOD_RECT (box)); + critical_if_fail (GOOD_RECT (box)); region->extents = *box; @@ -2437,7 +2432,7 @@ PREFIX (_selfcheck) (region_type_t *reg) PIXMAN_EXPORT pixman_bool_t PREFIX (_init_rects) (region_type_t *region, - box_type_t *boxes, int count) + const box_type_t *boxes, int count) { box_type_t *rects; int displacement; @@ -2517,3 +2512,240 @@ PREFIX (_init_rects) (region_type_t *region, return validate (region, &i); } + +#define READ(_ptr) (*(_ptr)) + +static inline box_type_t * +bitmap_addrect (region_type_t *reg, + box_type_t *r, + box_type_t **first_rect, + int rx1, int ry1, + int rx2, int ry2) +{ + if ((rx1 < rx2) && (ry1 < ry2) && + (!(reg->data->numRects && + ((r-1)->y1 == ry1) && ((r-1)->y2 == ry2) && + ((r-1)->x1 <= rx1) && ((r-1)->x2 >= rx2)))) + { + if (!reg->data || + reg->data->numRects == reg->data->size) + { + if (!pixman_rect_alloc (reg, 1)) + return NULL; + *first_rect = PIXREGION_BOXPTR(reg); + r = *first_rect + reg->data->numRects; + } + r->x1 = rx1; + r->y1 = ry1; + r->x2 = rx2; + r->y2 = ry2; + reg->data->numRects++; + if (r->x1 < reg->extents.x1) + reg->extents.x1 = r->x1; + if (r->x2 > reg->extents.x2) + reg->extents.x2 = r->x2; + r++; + } + return r; +} + +/* Convert bitmap clip mask into clipping region. + * First, goes through each line and makes boxes by noting the transitions + * from 0 to 1 and 1 to 0. + * Then it coalesces the current line with the previous if they have boxes + * at the same X coordinates. + * Stride is in number of uint32_t per line. + */ +PIXMAN_EXPORT void +PREFIX (_init_from_image) (region_type_t *region, + pixman_image_t *image) +{ + uint32_t mask0 = 0xffffffff & ~SCREEN_SHIFT_RIGHT(0xffffffff, 1); + box_type_t *first_rect, *rects, *prect_line_start; + box_type_t *old_rect, *new_rect; + uint32_t *pw, w, *pw_line, *pw_line_end; + int irect_prev_start, irect_line_start; + int h, base, rx1 = 0, crects; + int ib; + pixman_bool_t in_box, same; + int width, height, stride; + + PREFIX(_init) (region); + + return_if_fail (image->type == BITS); + return_if_fail (image->bits.format == PIXMAN_a1); + + pw_line = pixman_image_get_data (image); + width = pixman_image_get_width (image); + height = pixman_image_get_height (image); + stride = pixman_image_get_stride (image) / 4; + + first_rect = PIXREGION_BOXPTR(region); + rects = first_rect; + + region->extents.x1 = width - 1; + region->extents.x2 = 0; + irect_prev_start = -1; + for (h = 0; h < height; h++) + { + pw = pw_line; + pw_line += stride; + irect_line_start = rects - first_rect; + + /* If the Screen left most bit of the word is set, we're starting in + * a box */ + if (READ(pw) & mask0) + { + in_box = TRUE; + rx1 = 0; + } + else + { + in_box = FALSE; + } + + /* Process all words which are fully in the pixmap */ + pw_line_end = pw + (width >> 5); + for (base = 0; pw < pw_line_end; base += 32) + { + w = READ(pw++); + if (in_box) + { + if (!~w) + continue; + } + else + { + if (!w) + continue; + } + for (ib = 0; ib < 32; ib++) + { + /* If the Screen left most bit of the word is set, we're + * starting a box */ + if (w & mask0) + { + if (!in_box) + { + rx1 = base + ib; + /* start new box */ + in_box = TRUE; + } + } + else + { + if (in_box) + { + /* end box */ + rects = bitmap_addrect (region, rects, &first_rect, + rx1, h, base + ib, h + 1); + if (rects == NULL) + goto error; + in_box = FALSE; + } + } + /* Shift the word VISUALLY left one. */ + w = SCREEN_SHIFT_LEFT(w, 1); + } + } + + if (width & 31) + { + /* Process final partial word on line */ + w = READ(pw++); + for (ib = 0; ib < (width & 31); ib++) + { + /* If the Screen left most bit of the word is set, we're + * starting a box */ + if (w & mask0) + { + if (!in_box) + { + rx1 = base + ib; + /* start new box */ + in_box = TRUE; + } + } + else + { + if (in_box) + { + /* end box */ + rects = bitmap_addrect(region, rects, &first_rect, + rx1, h, base + ib, h + 1); + if (rects == NULL) + goto error; + in_box = FALSE; + } + } + /* Shift the word VISUALLY left one. */ + w = SCREEN_SHIFT_LEFT(w, 1); + } + } + /* If scanline ended with last bit set, end the box */ + if (in_box) + { + rects = bitmap_addrect(region, rects, &first_rect, + rx1, h, base + (width & 31), h + 1); + if (rects == NULL) + goto error; + } + /* if all rectangles on this line have the same x-coords as + * those on the previous line, then add 1 to all the previous y2s and + * throw away all the rectangles from this line + */ + same = FALSE; + if (irect_prev_start != -1) + { + crects = irect_line_start - irect_prev_start; + if (crects != 0 && + crects == ((rects - first_rect) - irect_line_start)) + { + old_rect = first_rect + irect_prev_start; + new_rect = prect_line_start = first_rect + irect_line_start; + same = TRUE; + while (old_rect < prect_line_start) + { + if ((old_rect->x1 != new_rect->x1) || + (old_rect->x2 != new_rect->x2)) + { + same = FALSE; + break; + } + old_rect++; + new_rect++; + } + if (same) + { + old_rect = first_rect + irect_prev_start; + while (old_rect < prect_line_start) + { + old_rect->y2 += 1; + old_rect++; + } + rects -= crects; + region->data->numRects -= crects; + } + } + } + if(!same) + irect_prev_start = irect_line_start; + } + if (!region->data->numRects) + { + region->extents.x1 = region->extents.x2 = 0; + } + else + { + region->extents.y1 = PIXREGION_BOXPTR(region)->y1; + region->extents.y2 = PIXREGION_END(region)->y2; + if (region->data->numRects == 1) + { + free (region->data); + region->data = NULL; + } + } + + error: + return; +} diff --git a/pixman/pixman-solid-fill.c b/pixman/pixman-solid-fill.c index 38675dc..48c999a 100644 --- a/pixman/pixman-solid-fill.c +++ b/pixman/pixman-solid-fill.c @@ -36,7 +36,7 @@ solid_fill_get_scanline_32 (pixman_image_t *image, uint32_t mask_bits) { uint32_t *end = buffer + width; - register uint32_t color = ((solid_fill_t *)image)->color; + uint32_t color = image->solid.color_32; while (buffer < end) *(buffer++) = color; @@ -44,6 +44,23 @@ solid_fill_get_scanline_32 (pixman_image_t *image, return; } +static void +solid_fill_get_scanline_64 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask, + uint32_t mask_bits) +{ + uint64_t *b = (uint64_t *)buffer; + uint64_t *e = b + width; + uint64_t color = image->solid.color_64; + + while (b < e) + *(b++) = color; +} + static source_image_class_t solid_fill_classify (pixman_image_t *image, int x, @@ -58,7 +75,7 @@ static void solid_fill_property_changed (pixman_image_t *image) { image->common.get_scanline_32 = solid_fill_get_scanline_32; - image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64; + image->common.get_scanline_64 = solid_fill_get_scanline_64; } static uint32_t @@ -71,6 +88,16 @@ color_to_uint32 (const pixman_color_t *color) (color->blue >> 8); } +static uint64_t +color_to_uint64 (const pixman_color_t *color) +{ + return + ((uint64_t)color->alpha << 48) | + ((uint64_t)color->red << 32) | + ((uint64_t)color->green << 16) | + ((uint64_t)color->blue); +} + PIXMAN_EXPORT pixman_image_t * pixman_image_create_solid_fill (pixman_color_t *color) { @@ -80,7 +107,9 @@ pixman_image_create_solid_fill (pixman_color_t *color) return NULL; img->type = SOLID; - img->solid.color = color_to_uint32 (color); + img->solid.color = *color; + img->solid.color_32 = color_to_uint32 (color); + img->solid.color_64 = color_to_uint64 (color); img->source.class = SOURCE_IMAGE_CLASS_UNKNOWN; img->common.classify = solid_fill_classify; diff --git a/pixman/pixman-sse2.c b/pixman/pixman-sse2.c index 78b0ad1..946e7ba 100644 --- a/pixman/pixman-sse2.c +++ b/pixman/pixman-sse2.c @@ -998,7 +998,7 @@ core_combine_reverse_out_u_sse2 (uint32_t* pd, pix_multiply_1x64 ( unpack_32_1x64 (d), negate_1x64 ( expand_alpha_1x64 (unpack_32_1x64 (s))))); - + if (pm) pm++; ps++; @@ -2652,8 +2652,8 @@ create_mask_2x32_64 (uint32_t mask0, /* Work around a code generation bug in Sun Studio 12. */ #if defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590) -# define create_mask_2x32_128(mask0, mask1) \ - (_mm_set_epi32 ((mask0), (mask1), (mask0), (mask1))) +# define create_mask_2x32_128(mask0, mask1) \ + (_mm_set_epi32 ((mask0), (mask1), (mask0), (mask1))) #else static force_inline __m128i create_mask_2x32_128 (uint32_t mask0, @@ -2950,7 +2950,7 @@ sse2_composite_over_n_8888 (pixman_implementation_t *imp, { uint32_t src; uint32_t *dst_line, *dst, d; - uint16_t w; + int32_t w; int dst_stride; __m128i xmm_src, xmm_alpha; __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; @@ -3041,7 +3041,7 @@ sse2_composite_over_n_0565 (pixman_implementation_t *imp, { uint32_t src; uint16_t *dst_line, *dst, d; - uint16_t w; + int32_t w; int dst_stride; __m128i xmm_src, xmm_alpha; __m128i xmm_dst, xmm_dst0, xmm_dst1, xmm_dst2, xmm_dst3; @@ -3152,7 +3152,7 @@ sse2_composite_add_n_8888_8888_ca (pixman_implementation_t *imp, src = _pixman_image_get_solid (src_image, dst_image->bits.format); srca = src >> 24; - + if (src == 0) return; @@ -3187,7 +3187,7 @@ sse2_composite_add_n_8888_8888_ca (pixman_implementation_t *imp, if (m) { d = *pd; - + mmx_mask = unpack_32_1x64 (m); mmx_dest = unpack_32_1x64 (d); @@ -3226,7 +3226,7 @@ sse2_composite_add_n_8888_8888_ca (pixman_implementation_t *imp, &xmm_mask_lo, &xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); xmm_mask_hi = pack_2x128_128 (xmm_mask_lo, xmm_mask_hi); - + save_128_aligned ( (__m128i*)pd, _mm_adds_epu8 (xmm_mask_hi, xmm_dst)); } @@ -3421,7 +3421,7 @@ sse2_composite_over_8888_n_8888 (pixman_implementation_t *imp, uint32_t *dst_line, *dst; uint32_t *src_line, *src; uint32_t mask; - uint16_t w; + int32_t w; int dst_stride, src_stride; __m128i xmm_mask; @@ -3539,7 +3539,7 @@ sse2_composite_over_x888_n_8888 (pixman_implementation_t *imp, uint32_t *src_line, *src; uint32_t mask; int dst_stride, src_stride; - uint16_t w; + int32_t w; __m128i xmm_mask, xmm_alpha; __m128i xmm_src, xmm_src_lo, xmm_src_hi; @@ -3707,7 +3707,7 @@ sse2_composite_over_8888_0565 (pixman_implementation_t *imp, uint16_t *dst_line, *dst, d; uint32_t *src_line, *src, s; int dst_stride, src_stride; - uint16_t w; + int32_t w; __m128i xmm_alpha_lo, xmm_alpha_hi; __m128i xmm_src, xmm_src_lo, xmm_src_hi; @@ -3837,7 +3837,7 @@ sse2_composite_over_n_8_8888 (pixman_implementation_t *imp, uint32_t *dst_line, *dst; uint8_t *mask_line, *mask; int dst_stride, mask_stride; - uint16_t w; + int32_t w; uint32_t m, d; __m128i xmm_src, xmm_alpha, xmm_def; @@ -3981,9 +3981,6 @@ pixman_fill_sse2 (uint32_t *bits, __m128i xmm_def; - if (bpp == 16 && (data >> 16 != (data & 0xffff))) - return FALSE; - if (bpp != 16 && bpp != 32) return FALSE; @@ -3993,6 +3990,7 @@ pixman_fill_sse2 (uint32_t *bits, byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x); byte_width = 2 * width; stride *= 2; + data = (data & 0xffff) * 0x00010001; } else { @@ -4122,7 +4120,7 @@ sse2_composite_src_n_8_8888 (pixman_implementation_t *imp, uint32_t *dst_line, *dst; uint8_t *mask_line, *mask; int dst_stride, mask_stride; - uint16_t w; + int32_t w; uint32_t m; __m128i xmm_src, xmm_def; @@ -4268,7 +4266,7 @@ sse2_composite_over_n_8_0565 (pixman_implementation_t *imp, uint16_t *dst_line, *dst, d; uint8_t *mask_line, *mask; int dst_stride, mask_stride; - uint16_t w; + int32_t w; uint32_t m; __m64 mmx_src, mmx_alpha, mmx_mask, mmx_dest; @@ -4431,7 +4429,7 @@ sse2_composite_over_pixbuf_0565 (pixman_implementation_t *imp, uint16_t *dst_line, *dst, d; uint32_t *src_line, *src, s; int dst_stride, src_stride; - uint16_t w; + int32_t w; uint32_t opaque, zero; __m64 ms; @@ -4577,7 +4575,7 @@ sse2_composite_over_pixbuf_8888 (pixman_implementation_t *imp, uint32_t *dst_line, *dst, d; uint32_t *src_line, *src, s; int dst_stride, src_stride; - uint16_t w; + int32_t w; uint32_t opaque, zero; __m128i xmm_src_lo, xmm_src_hi; @@ -4863,9 +4861,10 @@ sse2_composite_in_n_8_8 (pixman_implementation_t *imp, uint8_t *dst_line, *dst; uint8_t *mask_line, *mask; int dst_stride, mask_stride; - uint16_t w, d, m; + uint32_t d, m; uint32_t src; uint8_t sa; + int32_t w; __m128i xmm_alpha; __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; @@ -4978,7 +4977,7 @@ sse2_composite_in_8_8 (pixman_implementation_t *imp, uint8_t *dst_line, *dst; uint8_t *src_line, *src; int src_stride, dst_stride; - uint16_t w; + int32_t w; uint32_t s, d; __m128i xmm_src, xmm_src_lo, xmm_src_hi; @@ -5076,7 +5075,7 @@ sse2_composite_add_n_8_8 (pixman_implementation_t *imp, uint8_t *dst_line, *dst; uint8_t *mask_line, *mask; int dst_stride, mask_stride; - uint16_t w; + int32_t w; uint32_t src; uint8_t sa; uint32_t m, d; @@ -5192,7 +5191,7 @@ sse2_composite_add_8000_8000 (pixman_implementation_t *imp, uint8_t *dst_line, *dst; uint8_t *src_line, *src; int dst_stride, src_stride; - uint16_t w; + int32_t w; uint16_t t; PIXMAN_IMAGE_GET_LINE ( @@ -5470,7 +5469,7 @@ sse2_composite_over_x888_8_8888 (pixman_implementation_t *imp, uint8_t *mask, *mask_line; uint32_t m; int src_stride, mask_stride, dst_stride; - uint16_t w; + int32_t w; __m64 ms; __m128i xmm_src, xmm_src_lo, xmm_src_hi; @@ -5617,7 +5616,7 @@ sse2_composite_over_8888_8_8888 (pixman_implementation_t *imp, uint8_t *mask, *mask_line; uint32_t m; int src_stride, mask_stride, dst_stride; - uint16_t w; + int32_t w; __m128i xmm_src, xmm_src_lo, xmm_src_hi, xmm_srca_lo, xmm_srca_hi; __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; @@ -5714,7 +5713,7 @@ sse2_composite_over_8888_8_8888 (pixman_implementation_t *imp, expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, &xmm_srca_lo, &xmm_srca_hi); expand_alpha_rev_2x128 (xmm_mask_lo, xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); - + in_over_2x128 (&xmm_src_lo, &xmm_src_hi, &xmm_srca_lo, &xmm_srca_hi, &xmm_mask_lo, &xmm_mask_hi, &xmm_dst_lo, &xmm_dst_hi); @@ -5768,132 +5767,81 @@ sse2_composite_over_8888_8_8888 (pixman_implementation_t *imp, static const pixman_fast_path_t sse2_fast_paths[] = { - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_r5g6b5, sse2_composite_over_n_8_0565 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_b5g6r5, sse2_composite_over_n_8_0565 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_a8r8g8b8, sse2_composite_over_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_x8r8g8b8, sse2_composite_over_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_r5g6b5, sse2_composite_over_n_0565 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, sse2_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, sse2_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, sse2_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, sse2_composite_over_8888_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, sse2_composite_over_8888_0565 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, sse2_composite_over_8888_0565 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8r8g8b8, sse2_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8r8g8b8, sse2_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8b8g8r8, sse2_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8b8g8r8, sse2_composite_over_n_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_a8, PIXMAN_x8r8g8b8, sse2_composite_over_8888_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_a8, PIXMAN_a8r8g8b8, sse2_composite_over_8888_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_a8, PIXMAN_x8b8g8r8, sse2_composite_over_8888_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_a8, PIXMAN_a8b8g8r8, sse2_composite_over_8888_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_x8r8g8b8, sse2_composite_over_x888_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_a8r8g8b8, sse2_composite_over_x888_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8, PIXMAN_x8b8g8r8, sse2_composite_over_x888_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8, PIXMAN_a8b8g8r8, sse2_composite_over_x888_8_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_solid, PIXMAN_a8r8g8b8, sse2_composite_over_x888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_solid, PIXMAN_x8r8g8b8, sse2_composite_over_x888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_solid, PIXMAN_a8b8g8r8, sse2_composite_over_x888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_solid, PIXMAN_x8b8g8r8, sse2_composite_over_x888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_solid, PIXMAN_a8r8g8b8, sse2_composite_over_8888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_solid, PIXMAN_x8r8g8b8, sse2_composite_over_8888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_solid, PIXMAN_a8b8g8r8, sse2_composite_over_8888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_solid, PIXMAN_x8b8g8r8, sse2_composite_over_8888_n_8888 }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8_ca, PIXMAN_a8r8g8b8, sse2_composite_over_n_8888_8888_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8_ca, PIXMAN_x8r8g8b8, sse2_composite_over_n_8888_8888_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8_ca, PIXMAN_a8b8g8r8, sse2_composite_over_n_8888_8888_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8_ca, PIXMAN_x8b8g8r8, sse2_composite_over_n_8888_8888_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8_ca, PIXMAN_r5g6b5, sse2_composite_over_n_8888_0565_ca }, - { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8_ca, PIXMAN_b5g6r5, sse2_composite_over_n_8888_0565_ca }, - { PIXMAN_OP_OVER, PIXMAN_pixbuf, PIXMAN_pixbuf, PIXMAN_a8r8g8b8, sse2_composite_over_pixbuf_8888 }, - { PIXMAN_OP_OVER, PIXMAN_pixbuf, PIXMAN_pixbuf, PIXMAN_x8r8g8b8, sse2_composite_over_pixbuf_8888 }, - { PIXMAN_OP_OVER, PIXMAN_rpixbuf, PIXMAN_rpixbuf, PIXMAN_a8b8g8r8, sse2_composite_over_pixbuf_8888 }, - { PIXMAN_OP_OVER, PIXMAN_rpixbuf, PIXMAN_rpixbuf, PIXMAN_x8b8g8r8, sse2_composite_over_pixbuf_8888 }, - { PIXMAN_OP_OVER, PIXMAN_pixbuf, PIXMAN_pixbuf, PIXMAN_r5g6b5, sse2_composite_over_pixbuf_0565 }, - { PIXMAN_OP_OVER, PIXMAN_rpixbuf, PIXMAN_rpixbuf, PIXMAN_b5g6r5, sse2_composite_over_pixbuf_0565 }, - { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, sse2_composite_copy_area }, - { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, sse2_composite_copy_area }, - - { PIXMAN_OP_ADD, PIXMAN_solid, PIXMAN_a8r8g8b8_ca, PIXMAN_a8r8g8b8, sse2_composite_add_n_8888_8888_ca }, - { PIXMAN_OP_ADD, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, sse2_composite_add_8000_8000 }, - { PIXMAN_OP_ADD, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, sse2_composite_add_8888_8888 }, - { PIXMAN_OP_ADD, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, sse2_composite_add_8888_8888 }, - { PIXMAN_OP_ADD, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, sse2_composite_add_n_8_8 }, - - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8r8g8b8, sse2_composite_src_n_8_8888 }, - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8r8g8b8, sse2_composite_src_n_8_8888 }, - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8b8g8r8, sse2_composite_src_n_8_8888 }, - { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8b8g8r8, sse2_composite_src_n_8_8888 }, - { PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, sse2_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, sse2_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, sse2_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, sse2_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, sse2_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, sse2_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_r5g6b5, PIXMAN_null, PIXMAN_r5g6b5, sse2_composite_copy_area }, - { PIXMAN_OP_SRC, PIXMAN_b5g6r5, PIXMAN_null, PIXMAN_b5g6r5, sse2_composite_copy_area }, - - { PIXMAN_OP_IN, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, sse2_composite_in_8_8 }, - { PIXMAN_OP_IN, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, sse2_composite_in_n_8_8 }, + /* PIXMAN_OP_OVER */ + PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, sse2_composite_over_n_8_0565), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, sse2_composite_over_n_8_0565), + PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, sse2_composite_over_n_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, sse2_composite_over_n_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, null, r5g6b5, sse2_composite_over_n_0565), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, sse2_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, sse2_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, sse2_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, sse2_composite_over_8888_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, sse2_composite_over_8888_0565), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, sse2_composite_over_8888_0565), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, sse2_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, sse2_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, sse2_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, sse2_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, x8r8g8b8, sse2_composite_over_8888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, a8r8g8b8, sse2_composite_over_8888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, x8b8g8r8, sse2_composite_over_8888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, a8b8g8r8, sse2_composite_over_8888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, x8r8g8b8, sse2_composite_over_x888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, a8r8g8b8, sse2_composite_over_x888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, x8b8g8r8, sse2_composite_over_x888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, a8b8g8r8, sse2_composite_over_x888_8_8888), + PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, solid, a8r8g8b8, sse2_composite_over_x888_n_8888), + PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, solid, x8r8g8b8, sse2_composite_over_x888_n_8888), + PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, solid, a8b8g8r8, sse2_composite_over_x888_n_8888), + PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, solid, x8b8g8r8, sse2_composite_over_x888_n_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, sse2_composite_over_8888_n_8888), + PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, sse2_composite_over_8888_n_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, a8b8g8r8, sse2_composite_over_8888_n_8888), + PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, x8b8g8r8, sse2_composite_over_8888_n_8888), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, sse2_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, sse2_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, sse2_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, sse2_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, sse2_composite_over_n_8888_0565_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, sse2_composite_over_n_8888_0565_ca), + PIXMAN_STD_FAST_PATH (OVER, pixbuf, pixbuf, a8r8g8b8, sse2_composite_over_pixbuf_8888), + PIXMAN_STD_FAST_PATH (OVER, pixbuf, pixbuf, x8r8g8b8, sse2_composite_over_pixbuf_8888), + PIXMAN_STD_FAST_PATH (OVER, rpixbuf, rpixbuf, a8b8g8r8, sse2_composite_over_pixbuf_8888), + PIXMAN_STD_FAST_PATH (OVER, rpixbuf, rpixbuf, x8b8g8r8, sse2_composite_over_pixbuf_8888), + PIXMAN_STD_FAST_PATH (OVER, pixbuf, pixbuf, r5g6b5, sse2_composite_over_pixbuf_0565), + PIXMAN_STD_FAST_PATH (OVER, rpixbuf, rpixbuf, b5g6r5, sse2_composite_over_pixbuf_0565), + PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, null, x8r8g8b8, sse2_composite_copy_area), + PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, null, x8b8g8r8, sse2_composite_copy_area), + + /* PIXMAN_OP_ADD */ + PIXMAN_STD_FAST_PATH_CA (ADD, solid, a8r8g8b8, a8r8g8b8, sse2_composite_add_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, sse2_composite_add_8000_8000), + PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, sse2_composite_add_8888_8888), + PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, sse2_composite_add_8888_8888), + PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, sse2_composite_add_n_8_8), + + /* PIXMAN_OP_SRC */ + PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8r8g8b8, sse2_composite_src_n_8_8888), + PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, sse2_composite_src_n_8_8888), + PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, sse2_composite_src_n_8_8888), + PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8b8g8r8, sse2_composite_src_n_8_8888), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, sse2_composite_copy_area), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, sse2_composite_copy_area), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, sse2_composite_copy_area), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, sse2_composite_copy_area), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, sse2_composite_copy_area), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, sse2_composite_copy_area), + PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, sse2_composite_copy_area), + PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, sse2_composite_copy_area), + + /* PIXMAN_OP_IN */ + PIXMAN_STD_FAST_PATH (IN, a8, null, a8, sse2_composite_in_8_8), + PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, sse2_composite_in_n_8_8), { PIXMAN_OP_NONE }, }; -/* - * Work around GCC bug causing crashes in Mozilla with SSE2 - * - * When using -msse, gcc generates movdqa instructions assuming that - * the stack is 16 byte aligned. Unfortunately some applications, such - * as Mozilla and Mono, end up aligning the stack to 4 bytes, which - * causes the movdqa instructions to fail. - * - * The __force_align_arg_pointer__ makes gcc generate a prologue that - * realigns the stack pointer to 16 bytes. - * - * On x86-64 this is not necessary because the standard ABI already - * calls for a 16 byte aligned stack. - * - * See https://bugs.freedesktop.org/show_bug.cgi?id=15693 - */ -#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) -__attribute__((__force_align_arg_pointer__)) -#endif -static void -sse2_composite (pixman_implementation_t *imp, - pixman_op_t op, - pixman_image_t * src, - pixman_image_t * mask, - pixman_image_t * dest, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) -{ - if (_pixman_run_fast_path (sse2_fast_paths, imp, - op, src, mask, dest, - src_x, src_y, - mask_x, mask_y, - dest_x, dest_y, - width, height)) - { - return; - } - - _pixman_implementation_composite (imp->delegate, op, - src, mask, dest, - src_x, src_y, - mask_x, mask_y, - dest_x, dest_y, - width, height); -} - -#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) -__attribute__((__force_align_arg_pointer__)) -#endif static pixman_bool_t sse2_blt (pixman_implementation_t *imp, uint32_t * src_bits, @@ -5952,8 +5900,12 @@ __attribute__((__force_align_arg_pointer__)) pixman_implementation_t * _pixman_implementation_create_sse2 (void) { - pixman_implementation_t *mmx = _pixman_implementation_create_mmx (); - pixman_implementation_t *imp = _pixman_implementation_create (mmx); +#ifdef USE_MMX + pixman_implementation_t *fallback = _pixman_implementation_create_mmx (); +#else + pixman_implementation_t *fallback = _pixman_implementation_create_fast_path (); +#endif + pixman_implementation_t *imp = _pixman_implementation_create (fallback, sse2_fast_paths); /* SSE2 constants */ mask_565_r = create_mask_2x32_128 (0x00f80000, 0x00f80000); @@ -6011,7 +5963,6 @@ _pixman_implementation_create_sse2 (void) imp->combine_32_ca[PIXMAN_OP_XOR] = sse2_combine_xor_ca; imp->combine_32_ca[PIXMAN_OP_ADD] = sse2_combine_add_ca; - imp->composite = sse2_composite; imp->blt = sse2_blt; imp->fill = sse2_fill; diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c index 6d03f3c..3ef88b7 100644 --- a/pixman/pixman-utils.c +++ b/pixman/pixman-utils.c @@ -30,208 +30,6 @@ #include "pixman-private.h" -/* - * Computing composite region - */ -static inline pixman_bool_t -clip_general_image (pixman_region32_t * region, - pixman_region32_t * clip, - int dx, - int dy) -{ - if (pixman_region32_n_rects (region) == 1 && - pixman_region32_n_rects (clip) == 1) - { - pixman_box32_t * rbox = pixman_region32_rectangles (region, NULL); - pixman_box32_t * cbox = pixman_region32_rectangles (clip, NULL); - int v; - - if (rbox->x1 < (v = cbox->x1 + dx)) - rbox->x1 = v; - if (rbox->x2 > (v = cbox->x2 + dx)) - rbox->x2 = v; - if (rbox->y1 < (v = cbox->y1 + dy)) - rbox->y1 = v; - if (rbox->y2 > (v = cbox->y2 + dy)) - rbox->y2 = v; - if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2) - { - pixman_region32_init (region); - return FALSE; - } - } - else if (!pixman_region32_not_empty (clip)) - { - return FALSE; - } - else - { - if (dx || dy) - pixman_region32_translate (region, -dx, -dy); - - if (!pixman_region32_intersect (region, region, clip)) - return FALSE; - - if (dx || dy) - pixman_region32_translate (region, dx, dy); - } - - return pixman_region32_not_empty (region); -} - -static inline pixman_bool_t -clip_source_image (pixman_region32_t * region, - pixman_image_t * image, - int dx, - int dy) -{ - /* Source clips are ignored, unless they are explicitly turned on - * and the clip in question was set by an X client. (Because if - * the clip was not set by a client, then it is a hierarchy - * clip and those should always be ignored for sources). - */ - if (!image->common.clip_sources || !image->common.client_clip) - return TRUE; - - return clip_general_image (region, - &image->common.clip_region, - dx, dy); -} - -/* - * returns FALSE if the final region is empty. Indistinguishable from - * an allocation failure, but rendering ignores those anyways. - */ -static pixman_bool_t -pixman_compute_composite_region32 (pixman_region32_t * region, - 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 dest_x, - int32_t dest_y, - int32_t width, - int32_t height) -{ - region->extents.x1 = dest_x; - region->extents.x2 = dest_x + width; - region->extents.y1 = dest_y; - region->extents.y2 = dest_y + height; - - region->extents.x1 = MAX (region->extents.x1, 0); - region->extents.y1 = MAX (region->extents.y1, 0); - region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width); - region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height); - - region->data = 0; - - /* Check for empty operation */ - if (region->extents.x1 >= region->extents.x2 || - region->extents.y1 >= region->extents.y2) - { - pixman_region32_init (region); - return FALSE; - } - - if (dst_image->common.have_clip_region) - { - if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0)) - { - pixman_region32_fini (region); - return FALSE; - } - } - - if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region) - { - if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region, - -dst_image->common.alpha_origin_x, - -dst_image->common.alpha_origin_y)) - { - pixman_region32_fini (region); - return FALSE; - } - } - - /* clip against src */ - if (src_image->common.have_clip_region) - { - if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y)) - { - pixman_region32_fini (region); - return FALSE; - } - } - if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region) - { - if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map, - dest_x - (src_x - src_image->common.alpha_origin_x), - dest_y - (src_y - src_image->common.alpha_origin_y))) - { - pixman_region32_fini (region); - return FALSE; - } - } - /* clip against mask */ - if (mask_image && mask_image->common.have_clip_region) - { - if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y)) - { - pixman_region32_fini (region); - return FALSE; - } - if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region) - { - if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map, - dest_x - (mask_x - mask_image->common.alpha_origin_x), - dest_y - (mask_y - mask_image->common.alpha_origin_y))) - { - pixman_region32_fini (region); - return FALSE; - } - } - } - - return TRUE; -} - -PIXMAN_EXPORT pixman_bool_t -pixman_compute_composite_region (pixman_region16_t * region, - pixman_image_t * src_image, - pixman_image_t * mask_image, - pixman_image_t * dst_image, - int16_t src_x, - int16_t src_y, - int16_t mask_x, - int16_t mask_y, - int16_t dest_x, - int16_t dest_y, - uint16_t width, - uint16_t height) -{ - pixman_region32_t r32; - pixman_bool_t retval; - - pixman_region32_init (&r32); - - retval = pixman_compute_composite_region32 ( - &r32, src_image, mask_image, dst_image, - src_x, src_y, mask_x, mask_y, dest_x, dest_y, - width, height); - - if (retval) - { - if (!pixman_region16_copy_from_region32 (region, &r32)) - retval = FALSE; - } - - pixman_region32_fini (&r32); - return retval; -} - pixman_bool_t pixman_multiply_overflows_int (unsigned int a, unsigned int b) @@ -369,405 +167,6 @@ pixman_contract (uint32_t * dst, } } -static void -walk_region_internal (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 dest_x, - int32_t dest_y, - int32_t width, - int32_t height, - pixman_bool_t src_repeat, - pixman_bool_t mask_repeat, - pixman_region32_t * region, - pixman_composite_func_t composite_rect) -{ - int n; - const pixman_box32_t *pbox; - int w, h, w_this, h_this; - int x_msk, y_msk, x_src, y_src, x_dst, y_dst; - - pbox = pixman_region32_rectangles (region, &n); - while (n--) - { - h = pbox->y2 - pbox->y1; - y_src = pbox->y1 - dest_y + src_y; - y_msk = pbox->y1 - dest_y + mask_y; - y_dst = pbox->y1; - - while (h) - { - h_this = h; - w = pbox->x2 - pbox->x1; - x_src = pbox->x1 - dest_x + src_x; - x_msk = pbox->x1 - dest_x + mask_x; - x_dst = pbox->x1; - - if (mask_repeat) - { - y_msk = MOD (y_msk, mask_image->bits.height); - if (h_this > mask_image->bits.height - y_msk) - h_this = mask_image->bits.height - y_msk; - } - - if (src_repeat) - { - y_src = MOD (y_src, src_image->bits.height); - if (h_this > src_image->bits.height - y_src) - h_this = src_image->bits.height - y_src; - } - - while (w) - { - w_this = w; - - if (mask_repeat) - { - x_msk = MOD (x_msk, mask_image->bits.width); - if (w_this > mask_image->bits.width - x_msk) - w_this = mask_image->bits.width - x_msk; - } - - if (src_repeat) - { - x_src = MOD (x_src, src_image->bits.width); - if (w_this > src_image->bits.width - x_src) - w_this = src_image->bits.width - x_src; - } - - (*composite_rect) (imp, op, - src_image, mask_image, dst_image, - x_src, y_src, x_msk, y_msk, x_dst, y_dst, - w_this, h_this); - w -= w_this; - - x_src += w_this; - x_msk += w_this; - x_dst += w_this; - } - - h -= h_this; - y_src += h_this; - y_msk += h_this; - y_dst += h_this; - } - - pbox++; - } -} - -void -_pixman_walk_composite_region (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 dest_x, - int32_t dest_y, - int32_t width, - int32_t height, - pixman_composite_func_t composite_rect) -{ - pixman_region32_t region; - - pixman_region32_init (®ion); - - if (pixman_compute_composite_region32 ( - ®ion, src_image, mask_image, dst_image, - src_x, src_y, mask_x, mask_y, dest_x, dest_y, - width, height)) - { - walk_region_internal (imp, op, - src_image, mask_image, dst_image, - src_x, src_y, mask_x, mask_y, dest_x, dest_y, - width, height, FALSE, FALSE, - ®ion, - composite_rect); - - pixman_region32_fini (®ion); - } -} - -static const pixman_fast_path_t * -get_fast_path (const pixman_fast_path_t *fast_paths, - pixman_op_t op, - pixman_image_t * src_image, - pixman_image_t * mask_image, - pixman_image_t * dst_image, - int src_x, - int src_y, - int mask_x, - int mask_y) -{ - pixman_format_code_t src_format, mask_format; - const pixman_fast_path_t *info; - - /* Check for pixbufs */ - if (mask_image && mask_image->type == BITS && - (mask_image->bits.format == PIXMAN_a8r8g8b8 || mask_image->bits.format == PIXMAN_a8b8g8r8) && - (src_image->type == BITS && src_image->bits.bits == mask_image->bits.bits) && - (src_image->common.repeat == mask_image->common.repeat) && - (src_x == mask_x && src_y == mask_y)) - { - if (src_image->bits.format == PIXMAN_x8b8g8r8) - src_format = mask_format = PIXMAN_pixbuf; - else if (src_image->bits.format == PIXMAN_x8r8g8b8) - src_format = mask_format = PIXMAN_rpixbuf; - else - return NULL; - } - else - { - if (_pixman_image_is_solid (src_image)) - { - src_format = PIXMAN_solid; - } - else if (src_image->type == BITS) - { - src_format = src_image->bits.format; - } - else - { - return NULL; - } - - if (!mask_image) - { - mask_format = PIXMAN_null; - } - else if (mask_image->common.component_alpha) - { - if (mask_image->type == BITS) - { - /* These are the *only* component_alpha formats - * we support for fast paths - */ - if (mask_image->bits.format == PIXMAN_a8r8g8b8) - mask_format = PIXMAN_a8r8g8b8_ca; - else if (mask_image->bits.format == PIXMAN_a8b8g8r8) - mask_format = PIXMAN_a8b8g8r8_ca; - else - return NULL; - } - else - { - return NULL; - } - } - else if (_pixman_image_is_solid (mask_image)) - { - mask_format = PIXMAN_solid; - } - else if (mask_image->common.type == BITS) - { - mask_format = mask_image->bits.format; - } - else - { - return NULL; - } - } - - for (info = fast_paths; info->op != PIXMAN_OP_NONE; info++) - { - if (info->op != op) - continue; - - if (info->src_format != src_format) - continue; - if (info->mask_format != mask_format) - continue; - - if (info->dest_format != dst_image->bits.format) - continue; - - return info; - } - - return NULL; -} - -static force_inline pixman_bool_t -image_covers (pixman_image_t *image, - pixman_box32_t *extents, - int x, - int y) -{ - if (image->common.type == BITS && - image->common.repeat == PIXMAN_REPEAT_NONE) - { - if (x > extents->x1 || y > extents->y1 || - x + image->bits.width < extents->x2 || - y + image->bits.height < extents->y2) - { - return FALSE; - } - } - - return TRUE; -} - -static force_inline pixman_bool_t -sources_cover (pixman_image_t *src, - pixman_image_t *mask, - pixman_box32_t *extents, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dest_x, - int dest_y) -{ - if (!image_covers (src, extents, dest_x - src_x, dest_y - src_y)) - return FALSE; - - if (!mask) - return TRUE; - - if (!image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y)) - return FALSE; - - return TRUE; -} - -pixman_bool_t -_pixman_run_fast_path (const pixman_fast_path_t *paths, - pixman_implementation_t * imp, - pixman_op_t op, - pixman_image_t * src, - pixman_image_t * mask, - pixman_image_t * dest, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) -{ - pixman_composite_func_t func = NULL; - pixman_bool_t src_repeat = - src->common.repeat == PIXMAN_REPEAT_NORMAL; - pixman_bool_t mask_repeat = - mask && mask->common.repeat == PIXMAN_REPEAT_NORMAL; - pixman_bool_t result; - pixman_bool_t has_fast_path; - - has_fast_path = !dest->common.alpha_map && - !dest->bits.read_func && - !dest->bits.write_func; - - if (has_fast_path) - { - has_fast_path = !src->common.transform && - !src->common.alpha_map && - src->common.filter != PIXMAN_FILTER_CONVOLUTION && - src->common.repeat != PIXMAN_REPEAT_PAD && - src->common.repeat != PIXMAN_REPEAT_REFLECT; - if (has_fast_path && src->type == BITS) - { - has_fast_path = !src->bits.read_func && - !src->bits.write_func && - !PIXMAN_FORMAT_IS_WIDE (src->bits.format); - } - } - - if (mask && has_fast_path) - { - has_fast_path = - !mask->common.transform && - !mask->common.alpha_map && - !mask->bits.read_func && - !mask->bits.write_func && - mask->common.filter != PIXMAN_FILTER_CONVOLUTION && - mask->common.repeat != PIXMAN_REPEAT_PAD && - mask->common.repeat != PIXMAN_REPEAT_REFLECT && - !PIXMAN_FORMAT_IS_WIDE (mask->bits.format); - } - - if (has_fast_path) - { - const pixman_fast_path_t *info; - - if ((info = get_fast_path (paths, op, src, mask, dest, src_x, src_y, mask_x, mask_y))) - { - func = info->func; - - if (info->src_format == PIXMAN_solid) - src_repeat = FALSE; - - if (info->mask_format == PIXMAN_solid) - { - mask_repeat = FALSE; - } - - if ((src_repeat && - src->bits.width == 1 && - src->bits.height == 1) || - (mask_repeat && - mask->bits.width == 1 && - mask->bits.height == 1)) - { - /* If src or mask are repeating 1x1 images and src_repeat or - * mask_repeat are still TRUE, it means the fast path we - * selected does not actually handle repeating images. - * - * So rather than call the "fast path" with a zillion - * 1x1 requests, we just fall back to the general code (which - * does do something sensible with 1x1 repeating images). - */ - func = NULL; - } - } - } - - result = FALSE; - - if (func) - { - pixman_region32_t region; - pixman_region32_init (®ion); - - if (pixman_compute_composite_region32 ( - ®ion, src, mask, dest, - src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height)) - { - pixman_box32_t *extents = pixman_region32_extents (®ion); - - if (sources_cover ( - src, mask, extents, - src_x, src_y, mask_x, mask_y, dest_x, dest_y)) - { - walk_region_internal (imp, op, - src, mask, dest, - src_x, src_y, mask_x, mask_y, - dest_x, dest_y, - width, height, - src_repeat, mask_repeat, - ®ion, - func); - - result = TRUE; - } - - pixman_region32_fini (®ion); - } - } - - return result; -} - #define N_TMP_BOXES (16) pixman_bool_t @@ -836,3 +235,24 @@ pixman_region32_copy_from_region16 (pixman_region32_t *dst, return retval; } + +#ifdef DEBUG + +void +_pixman_log_error (const char *function, const char *message) +{ + static int n_messages = 0; + + if (n_messages < 10) + { + fprintf (stderr, + "*** BUG ***\n" + "In %s: %s\n" + "Set a breakpoint on '_pixman_log_error' to debug\n\n", + function, message); + + n_messages++; + } +} + +#endif diff --git a/pixman/pixman-vmx.c b/pixman/pixman-vmx.c index 06325a7..e811cf7 100644 --- a/pixman/pixman-vmx.c +++ b/pixman/pixman-vmx.c @@ -1607,11 +1607,16 @@ vmx_combine_add_ca (pixman_implementation_t *imp, } } +static const pixman_fast_path_t vmx_fast_paths[] = +{ + { PIXMAN_OP_NONE }, +}; + pixman_implementation_t * _pixman_implementation_create_vmx (void) { pixman_implementation_t *fast = _pixman_implementation_create_fast_path (); - pixman_implementation_t *imp = _pixman_implementation_create (fast); + pixman_implementation_t *imp = _pixman_implementation_create (fast, vmx_fast_paths); /* Set up function pointers */ diff --git a/pixman/pixman.c b/pixman/pixman.c index 0edd967..6a260ed 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -28,6 +28,8 @@ #endif #include "pixman-private.h" +#include <stdlib.h> + /* * Operator optimizations based on source or destination opacity */ @@ -109,49 +111,560 @@ pixman_optimize_operator (pixman_op_t op, static void apply_workaround (pixman_image_t *image, - int16_t * x, - int16_t * y, + int32_t * x, + int32_t * y, uint32_t ** save_bits, int * save_dx, int * save_dy) { - /* Some X servers generate images that point to the - * wrong place in memory, but then set the clip region - * to point to the right place. Because of an old bug - * in pixman, this would actually work. - * - * Here we try and undo the damage + if (image && image->common.need_workaround) + { + /* Some X servers generate images that point to the + * wrong place in memory, but then set the clip region + * to point to the right place. Because of an old bug + * in pixman, this would actually work. + * + * Here we try and undo the damage + */ + int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8; + pixman_box32_t *extents; + uint8_t *t; + int dx, dy; + + extents = pixman_region32_extents (&(image->common.clip_region)); + dx = extents->x1; + dy = extents->y1; + + *save_bits = image->bits.bits; + + *x -= dx; + *y -= dy; + pixman_region32_translate (&(image->common.clip_region), -dx, -dy); + + t = (uint8_t *)image->bits.bits; + t += dy * image->bits.rowstride * 4 + dx * bpp; + image->bits.bits = (uint32_t *)t; + + *save_dx = dx; + *save_dy = dy; + } +} + +static void +unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy) +{ + if (image && image->common.need_workaround) + { + image->bits.bits = bits; + pixman_region32_translate (&image->common.clip_region, dx, dy); + } +} + +/* + * Computing composite region + */ +static inline pixman_bool_t +clip_general_image (pixman_region32_t * region, + pixman_region32_t * clip, + int dx, + int dy) +{ + if (pixman_region32_n_rects (region) == 1 && + pixman_region32_n_rects (clip) == 1) + { + pixman_box32_t * rbox = pixman_region32_rectangles (region, NULL); + pixman_box32_t * cbox = pixman_region32_rectangles (clip, NULL); + int v; + + if (rbox->x1 < (v = cbox->x1 + dx)) + rbox->x1 = v; + if (rbox->x2 > (v = cbox->x2 + dx)) + rbox->x2 = v; + if (rbox->y1 < (v = cbox->y1 + dy)) + rbox->y1 = v; + if (rbox->y2 > (v = cbox->y2 + dy)) + rbox->y2 = v; + if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2) + { + pixman_region32_init (region); + return FALSE; + } + } + else if (!pixman_region32_not_empty (clip)) + { + return FALSE; + } + else + { + if (dx || dy) + pixman_region32_translate (region, -dx, -dy); + + if (!pixman_region32_intersect (region, region, clip)) + return FALSE; + + if (dx || dy) + pixman_region32_translate (region, dx, dy); + } + + return pixman_region32_not_empty (region); +} + +static inline pixman_bool_t +clip_source_image (pixman_region32_t * region, + pixman_image_t * image, + int dx, + int dy) +{ + /* Source clips are ignored, unless they are explicitly turned on + * and the clip in question was set by an X client. (Because if + * the clip was not set by a client, then it is a hierarchy + * clip and those should always be ignored for sources). */ - int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8; - pixman_box32_t *extents; - uint8_t *t; - int dx, dy; + if (!image->common.clip_sources || !image->common.client_clip) + return TRUE; - extents = pixman_region32_extents (&(image->common.clip_region)); - dx = extents->x1; - dy = extents->y1; + return clip_general_image (region, + &image->common.clip_region, + dx, dy); +} - *save_bits = image->bits.bits; +/* + * returns FALSE if the final region is empty. Indistinguishable from + * an allocation failure, but rendering ignores those anyways. + */ +static pixman_bool_t +pixman_compute_composite_region32 (pixman_region32_t * region, + 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 dest_x, + int32_t dest_y, + int32_t width, + int32_t height) +{ + region->extents.x1 = dest_x; + region->extents.x2 = dest_x + width; + region->extents.y1 = dest_y; + region->extents.y2 = dest_y + height; - *x -= dx; - *y -= dy; - pixman_region32_translate (&(image->common.clip_region), -dx, -dy); + region->extents.x1 = MAX (region->extents.x1, 0); + region->extents.y1 = MAX (region->extents.y1, 0); + region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width); + region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height); - t = (uint8_t *)image->bits.bits; - t += dy * image->bits.rowstride * 4 + dx * bpp; - image->bits.bits = (uint32_t *)t; + region->data = 0; - *save_dx = dx; - *save_dy = dy; + /* Check for empty operation */ + if (region->extents.x1 >= region->extents.x2 || + region->extents.y1 >= region->extents.y2) + { + pixman_region32_init (region); + return FALSE; + } + + if (dst_image->common.have_clip_region) + { + if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0)) + { + pixman_region32_fini (region); + return FALSE; + } + } + + if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region) + { + if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region, + -dst_image->common.alpha_origin_x, + -dst_image->common.alpha_origin_y)) + { + pixman_region32_fini (region); + return FALSE; + } + } + + /* clip against src */ + if (src_image->common.have_clip_region) + { + if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y)) + { + pixman_region32_fini (region); + return FALSE; + } + } + if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region) + { + if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map, + dest_x - (src_x - src_image->common.alpha_origin_x), + dest_y - (src_y - src_image->common.alpha_origin_y))) + { + pixman_region32_fini (region); + return FALSE; + } + } + /* clip against mask */ + if (mask_image && mask_image->common.have_clip_region) + { + if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y)) + { + pixman_region32_fini (region); + return FALSE; + } + if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region) + { + if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map, + dest_x - (mask_x - mask_image->common.alpha_origin_x), + dest_y - (mask_y - mask_image->common.alpha_origin_y))) + { + pixman_region32_fini (region); + return FALSE; + } + } + } + + return TRUE; } static void -unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy) +walk_region_internal (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 dest_x, + int32_t dest_y, + int32_t width, + int32_t height, + pixman_bool_t src_repeat, + pixman_bool_t mask_repeat, + pixman_region32_t * region, + pixman_composite_func_t composite_rect) { - image->bits.bits = bits; - pixman_region32_translate (&image->common.clip_region, dx, dy); + int w, h, w_this, h_this; + int x_msk, y_msk, x_src, y_src, x_dst, y_dst; + int src_dy = src_y - dest_y; + int src_dx = src_x - dest_x; + int mask_dy = mask_y - dest_y; + int mask_dx = mask_x - dest_x; + const pixman_box32_t *pbox; + int n; + + pbox = pixman_region32_rectangles (region, &n); + + /* Fast path for non-repeating sources */ + if (!src_repeat && !mask_repeat) + { + while (n--) + { + (*composite_rect) (imp, op, + src_image, mask_image, dst_image, + pbox->x1 + src_dx, + pbox->y1 + src_dy, + pbox->x1 + mask_dx, + pbox->y1 + mask_dy, + pbox->x1, + pbox->y1, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + + pbox++; + } + + return; + } + + while (n--) + { + h = pbox->y2 - pbox->y1; + y_src = pbox->y1 + src_dy; + y_msk = pbox->y1 + mask_dy; + y_dst = pbox->y1; + + while (h) + { + h_this = h; + w = pbox->x2 - pbox->x1; + x_src = pbox->x1 + src_dx; + x_msk = pbox->x1 + mask_dx; + x_dst = pbox->x1; + + if (mask_repeat) + { + y_msk = MOD (y_msk, mask_image->bits.height); + if (h_this > mask_image->bits.height - y_msk) + h_this = mask_image->bits.height - y_msk; + } + + if (src_repeat) + { + y_src = MOD (y_src, src_image->bits.height); + if (h_this > src_image->bits.height - y_src) + h_this = src_image->bits.height - y_src; + } + + while (w) + { + w_this = w; + + if (mask_repeat) + { + x_msk = MOD (x_msk, mask_image->bits.width); + if (w_this > mask_image->bits.width - x_msk) + w_this = mask_image->bits.width - x_msk; + } + + if (src_repeat) + { + x_src = MOD (x_src, src_image->bits.width); + if (w_this > src_image->bits.width - x_src) + w_this = src_image->bits.width - x_src; + } + + (*composite_rect) (imp, op, + src_image, mask_image, dst_image, + x_src, y_src, x_msk, y_msk, x_dst, y_dst, + w_this, h_this); + w -= w_this; + + x_src += w_this; + x_msk += w_this; + x_dst += w_this; + } + + h -= h_this; + y_src += h_this; + y_msk += h_this; + y_dst += h_this; + } + + pbox++; + } } +static void +get_image_info (pixman_image_t *image, + pixman_format_code_t *code, + uint32_t *flags) +{ + *flags = 0; + + if (!image->common.transform) + { + *flags |= FAST_PATH_ID_TRANSFORM; + } + else + { + if (image->common.transform->matrix[0][1] == 0 && + image->common.transform->matrix[1][0] == 0 && + 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_SCALE_TRANSFORM; + } + } + + if (!image->common.alpha_map) + *flags |= FAST_PATH_NO_ALPHA_MAP; + + if (image->common.filter != PIXMAN_FILTER_CONVOLUTION) + { + *flags |= FAST_PATH_NO_CONVOLUTION_FILTER; + + if (image->common.filter == PIXMAN_FILTER_NEAREST) + *flags |= FAST_PATH_NEAREST_FILTER; + } + + if (image->common.repeat != PIXMAN_REPEAT_PAD) + *flags |= FAST_PATH_NO_PAD_REPEAT; + + if (image->common.repeat != PIXMAN_REPEAT_REFLECT) + *flags |= FAST_PATH_NO_REFLECT_REPEAT; + + *flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NO_WIDE_FORMAT); + if (image->type == BITS) + { + 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_NO_WIDE_FORMAT; + } + + if (image->common.component_alpha) + *flags |= FAST_PATH_COMPONENT_ALPHA; + else + *flags |= FAST_PATH_UNIFIED_ALPHA; + + if (_pixman_image_is_solid (image)) + *code = PIXMAN_solid; + else if (image->common.type == BITS) + *code = image->bits.format; + else + *code = PIXMAN_unknown; +} + +static force_inline pixman_bool_t +image_covers (pixman_image_t *image, + pixman_box32_t *extents, + int x, + int y) +{ + if (image->common.type == BITS && + image->common.repeat == PIXMAN_REPEAT_NONE) + { + if (x > extents->x1 || y > extents->y1 || + x + image->bits.width < extents->x2 || + y + image->bits.height < extents->y2) + { + return FALSE; + } + } + + return TRUE; +} + +static void +do_composite (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t *src, + pixman_image_t *mask, + pixman_image_t *dest, + int src_x, + int src_y, + int mask_x, + int mask_y, + int dest_x, + int dest_y, + int width, + int height) +{ + pixman_format_code_t src_format, mask_format, dest_format; + uint32_t src_flags, mask_flags, dest_flags; + pixman_bool_t src_repeat, mask_repeat; + pixman_region32_t region; + pixman_box32_t *extents; + + get_image_info (src, &src_format, &src_flags); + if (mask) + { + get_image_info (mask, &mask_format, &mask_flags); + } + else + { + mask_format = PIXMAN_null; + mask_flags = 0; + } + get_image_info (dest, &dest_format, &dest_flags); + + /* Check for pixbufs */ + if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) && + (src->type == BITS && src->bits.bits == mask->bits.bits) && + (src->common.repeat == mask->common.repeat) && + (src_x == mask_x && src_y == mask_y)) + { + if (src_format == PIXMAN_x8b8g8r8) + src_format = mask_format = PIXMAN_pixbuf; + else if (src_format == PIXMAN_x8r8g8b8) + src_format = mask_format = PIXMAN_rpixbuf; + } + + src_repeat = + src->type == BITS && + src_flags & FAST_PATH_ID_TRANSFORM && + src->common.repeat == PIXMAN_REPEAT_NORMAL && + src_format != PIXMAN_solid; + + mask_repeat = + mask && + mask->type == BITS && + mask_flags & FAST_PATH_ID_TRANSFORM && + mask->common.repeat == PIXMAN_REPEAT_NORMAL && + mask_format != PIXMAN_solid; + + pixman_region32_init (®ion); + + if (!pixman_compute_composite_region32 ( + ®ion, src, mask, dest, + src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height)) + { + return; + } + + extents = pixman_region32_extents (®ion); + + if (image_covers (src, extents, dest_x - src_x, dest_y - src_y)) + src_flags |= FAST_PATH_COVERS_CLIP; + + if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y)) + mask_flags |= FAST_PATH_COVERS_CLIP; + + while (imp) + { + const pixman_fast_path_t *info; + + for (info = imp->fast_paths; info->op != PIXMAN_OP_NONE; ++info) + { + if ((info->op == op || info->op == PIXMAN_OP_any) && + /* src */ + ((info->src_format == src_format) || + (info->src_format == PIXMAN_any)) && + (info->src_flags & src_flags) == info->src_flags && + /* mask */ + ((info->mask_format == mask_format) || + (info->mask_format == PIXMAN_any)) && + (info->mask_flags & mask_flags) == info->mask_flags && + /* dest */ + ((info->dest_format == dest_format) || + (info->dest_format == PIXMAN_any)) && + (info->dest_flags & dest_flags) == info->dest_flags) + { + walk_region_internal (imp, op, + src, mask, dest, + src_x, src_y, mask_x, mask_y, + dest_x, dest_y, + width, height, + src_repeat, mask_repeat, + ®ion, + info->func); + + goto done; + } + } + + imp = imp->delegate; + } + +done: + pixman_region32_fini (®ion); +} + +/* + * Work around GCC bug causing crashes in Mozilla with SSE2 + * + * When using -msse, gcc generates movdqa instructions assuming that + * the stack is 16 byte aligned. Unfortunately some applications, such + * as Mozilla and Mono, end up aligning the stack to 4 bytes, which + * causes the movdqa instructions to fail. + * + * The __force_align_arg_pointer__ makes gcc generate a prologue that + * realigns the stack pointer to 16 bytes. + * + * On x86-64 this is not necessary because the standard ABI already + * calls for a 16 byte aligned stack. + * + * See https://bugs.freedesktop.org/show_bug.cgi?id=15693 + */ +#if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) +__attribute__((__force_align_arg_pointer__)) +#endif PIXMAN_EXPORT void pixman_image_composite (pixman_op_t op, pixman_image_t * src, @@ -166,12 +679,31 @@ pixman_image_composite (pixman_op_t op, uint16_t width, uint16_t height) { + pixman_image_composite32 (op, src, mask, dest, src_x, src_y, + mask_x, mask_y, dest_x, dest_y, width, height); +} + +PIXMAN_EXPORT void +pixman_image_composite32 (pixman_op_t op, + pixman_image_t * src, + pixman_image_t * mask, + pixman_image_t * dest, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) +{ uint32_t *src_bits; int src_dx, src_dy; uint32_t *mask_bits; int mask_dx, mask_dy; uint32_t *dest_bits; int dest_dx, dest_dy; + pixman_bool_t need_workaround; _pixman_image_validate (src); if (mask) @@ -194,26 +726,34 @@ pixman_image_composite (pixman_op_t op, if (!imp) imp = _pixman_choose_implementation (); - if (src->common.need_workaround) + need_workaround = + (src->common.need_workaround) || + (mask && mask->common.need_workaround) || + (dest->common.need_workaround); + + if (need_workaround) + { apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy); - if (mask && mask->common.need_workaround) apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy); - if (dest->common.need_workaround) apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy); + } - _pixman_implementation_composite (imp, op, - src, mask, dest, - src_x, src_y, - mask_x, mask_y, - dest_x, dest_y, - width, height); - - if (src->common.need_workaround) - unapply_workaround (src, src_bits, src_dx, src_dy); - if (mask && mask->common.need_workaround) - unapply_workaround (mask, mask_bits, mask_dx, mask_dy); - if (dest->common.need_workaround) - unapply_workaround (dest, dest_bits, dest_dx, dest_dy); + do_composite (imp, op, + src, mask, dest, + src_x, src_y, + mask_x, mask_y, + dest_x, dest_y, + width, height); + + if (need_workaround) + { + if (src->common.need_workaround) + unapply_workaround (src, src_bits, src_dx, src_dy); + if (mask && mask->common.need_workaround) + unapply_workaround (mask, mask_bits, mask_dx, mask_dy); + if (dest->common.need_workaround) + unapply_workaround (dest, dest_bits, dest_dx, dest_dy); + } } PIXMAN_EXPORT pixman_bool_t @@ -323,6 +863,45 @@ pixman_image_fill_rectangles (pixman_op_t op, int n_rects, const pixman_rectangle16_t *rects) { + pixman_box32_t stack_boxes[6]; + pixman_box32_t *boxes; + pixman_bool_t result; + int i; + + if (n_rects > 6) + { + boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects); + if (boxes == NULL) + return FALSE; + } + else + { + boxes = stack_boxes; + } + + for (i = 0; i < n_rects; ++i) + { + boxes[i].x1 = rects[i].x; + boxes[i].y1 = rects[i].y; + boxes[i].x2 = boxes[i].x1 + rects[i].width; + boxes[i].y2 = boxes[i].y1 + rects[i].height; + } + + result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes); + + if (boxes != stack_boxes) + free (boxes); + + return result; +} + +PIXMAN_EXPORT pixman_bool_t +pixman_image_fill_boxes (pixman_op_t op, + pixman_image_t * dest, + pixman_color_t * color, + int n_boxes, + const pixman_box32_t *boxes) +{ pixman_image_t *solid; pixman_color_t c; int i; @@ -331,71 +910,69 @@ pixman_image_fill_rectangles (pixman_op_t op, if (color->alpha == 0xffff) { - if (op == PIXMAN_OP_OVER) - op = PIXMAN_OP_SRC; + if (op == PIXMAN_OP_OVER) + op = PIXMAN_OP_SRC; } if (op == PIXMAN_OP_CLEAR) { - c.red = 0; - c.green = 0; - c.blue = 0; - c.alpha = 0; + c.red = 0; + c.green = 0; + c.blue = 0; + c.alpha = 0; - color = &c; + color = &c; - op = PIXMAN_OP_SRC; + op = PIXMAN_OP_SRC; } if (op == PIXMAN_OP_SRC) { - uint32_t pixel; + uint32_t pixel; - if (color_to_pixel (color, &pixel, dest->bits.format)) - { - for (i = 0; i < n_rects; ++i) - { - pixman_region32_t fill_region; - int n_boxes, j; - pixman_box32_t *boxes; + if (color_to_pixel (color, &pixel, dest->bits.format)) + { + pixman_region32_t fill_region; + int n_rects, j; + pixman_box32_t *rects; - pixman_region32_init_rect (&fill_region, rects[i].x, rects[i].y, rects[i].width, rects[i].height); + if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes)) + return FALSE; - if (dest->common.have_clip_region) - { - if (!pixman_region32_intersect (&fill_region, - &fill_region, - &dest->common.clip_region)) - return FALSE; - } + if (dest->common.have_clip_region) + { + if (!pixman_region32_intersect (&fill_region, + &fill_region, + &dest->common.clip_region)) + return FALSE; + } - boxes = pixman_region32_rectangles (&fill_region, &n_boxes); - for (j = 0; j < n_boxes; ++j) - { - const pixman_box32_t *box = &(boxes[j]); - pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format), - box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1, - pixel); - } + rects = pixman_region32_rectangles (&fill_region, &n_rects); + for (j = 0; j < n_rects; ++j) + { + const pixman_box32_t *rect = &(rects[j]); + pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format), + rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1, + pixel); + } - pixman_region32_fini (&fill_region); - } - return TRUE; - } + pixman_region32_fini (&fill_region); + return TRUE; + } } solid = pixman_image_create_solid_fill (color); if (!solid) - return FALSE; + return FALSE; - for (i = 0; i < n_rects; ++i) + for (i = 0; i < n_boxes; ++i) { - const pixman_rectangle16_t *rect = &(rects[i]); + const pixman_box32_t *box = &(boxes[i]); - pixman_image_composite (op, solid, NULL, dest, - 0, 0, 0, 0, - rect->x, rect->y, - rect->width, rect->height); + pixman_image_composite32 (op, solid, NULL, dest, + 0, 0, 0, 0, + box->x1, box->y1, + box->x2 - box->x1, box->y2 - box->y1); } pixman_image_unref (solid); @@ -541,3 +1118,36 @@ pixman_format_supported_destination (pixman_format_code_t format) return pixman_format_supported_source (format); } +PIXMAN_EXPORT pixman_bool_t +pixman_compute_composite_region (pixman_region16_t * region, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dst_image, + int16_t src_x, + int16_t src_y, + int16_t mask_x, + int16_t mask_y, + int16_t dest_x, + int16_t dest_y, + uint16_t width, + uint16_t height) +{ + pixman_region32_t r32; + pixman_bool_t retval; + + pixman_region32_init (&r32); + + retval = pixman_compute_composite_region32 ( + &r32, src_image, mask_image, dst_image, + src_x, src_y, mask_x, mask_y, dest_x, dest_y, + width, height); + + if (retval) + { + if (!pixman_region16_copy_from_region32 (region, &r32)) + retval = FALSE; + } + + pixman_region32_fini (&r32); + return retval; +} diff --git a/pixman/pixman.h b/pixman/pixman.h index ba2b242..69af0f9 100644 --- a/pixman/pixman.h +++ b/pixman/pixman.h @@ -71,6 +71,16 @@ SOFTWARE. #include <pixman-version.h> +#ifdef __cplusplus +#define PIXMAN_BEGIN_DECLS extern "C" { +#define PIXMAN_END_DECLS } +#else +#define PIXMAN_BEGIN_DECLS +#define PIXMAN_END_DECLS +#endif + +PIXMAN_BEGIN_DECLS + /* * Standard integers */ @@ -166,6 +176,7 @@ struct pixman_transform /* forward declaration (sorry) */ struct pixman_box16; +typedef union pixman_image pixman_image_t; void pixman_transform_init_identity (struct pixman_transform *matrix); pixman_bool_t pixman_transform_point_3d (const struct pixman_transform *transform, @@ -393,10 +404,12 @@ void pixman_region_init_rect (pixman_region16_t *reg unsigned int width, unsigned int height); pixman_bool_t pixman_region_init_rects (pixman_region16_t *region, - pixman_box16_t *boxes, + const pixman_box16_t *boxes, int count); void pixman_region_init_with_extents (pixman_region16_t *region, pixman_box16_t *extents); +void pixman_region_init_from_image (pixman_region16_t *region, + pixman_image_t *image); void pixman_region_fini (pixman_region16_t *region); @@ -429,7 +442,7 @@ pixman_bool_t pixman_region_contains_point (pixman_region16_t *reg int x, int y, pixman_box16_t *box); -pixman_region_overlap_t pixman_region_contains_rectangle (pixman_region16_t *pixman_region16_t, +pixman_region_overlap_t pixman_region_contains_rectangle (pixman_region16_t *region, pixman_box16_t *prect); pixman_bool_t pixman_region_not_empty (pixman_region16_t *region); pixman_box16_t * pixman_region_extents (pixman_region16_t *region); @@ -480,10 +493,12 @@ void pixman_region32_init_rect (pixman_region32_t *r unsigned int width, unsigned int height); pixman_bool_t pixman_region32_init_rects (pixman_region32_t *region, - pixman_box32_t *boxes, + const pixman_box32_t *boxes, int count); void pixman_region32_init_with_extents (pixman_region32_t *region, pixman_box32_t *extents); +void pixman_region32_init_from_image (pixman_region32_t *region, + pixman_image_t *image); void pixman_region32_fini (pixman_region32_t *region); @@ -557,7 +572,6 @@ const char* pixman_version_string (void); /* * Images */ -typedef union pixman_image pixman_image_t; typedef struct pixman_indexed pixman_indexed_t; typedef struct pixman_gradient_stop pixman_gradient_stop_t; @@ -722,6 +736,7 @@ pixman_bool_t pixman_image_unref (pixman_image_t void pixman_image_set_destroy_function (pixman_image_t *image, pixman_image_destroy_func_t function, void *data); +void * pixman_image_get_destroy_data (pixman_image_t *image); /* Set properties */ pixman_bool_t pixman_image_set_clip_region (pixman_image_t *image, @@ -761,6 +776,11 @@ pixman_bool_t pixman_image_fill_rectangles (pixman_op_t op, pixman_color_t *color, int n_rects, const pixman_rectangle16_t *rects); +pixman_bool_t pixman_image_fill_boxes (pixman_op_t op, + pixman_image_t *dest, + pixman_color_t *color, + int n_boxes, + const pixman_box32_t *boxes); /* Composite */ pixman_bool_t pixman_compute_composite_region (pixman_region16_t *region, @@ -787,6 +807,18 @@ void pixman_image_composite (pixman_op_t op, int16_t dest_y, uint16_t width, uint16_t height); +void pixman_image_composite32 (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *mask, + pixman_image_t *dest, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height); /* Old X servers rely on out-of-bounds accesses when they are asked * to composite with a window as the source. They create a pixman image @@ -892,4 +924,6 @@ void pixman_rasterize_trapezoid (pixman_image_t *image, int x_off, int y_off); +PIXMAN_END_DECLS + #endif /* PIXMAN_H__ */ diff --git a/pixman/solaris-hwcap.mapfile b/pixman/solaris-hwcap.mapfile index 7f439a9..3605ca7 100644 --- a/pixman/solaris-hwcap.mapfile +++ b/pixman/solaris-hwcap.mapfile @@ -3,29 +3,23 @@ # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, and/or sell copies of the Software, and to permit persons -# to whom the Software is furnished to do so, provided that the above -# copyright notice(s) and this permission notice appear in all copies of -# the Software and that both the above copyright notice(s) and this -# permission notice appear in supporting documentation. +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: # -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -# OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -# HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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. +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. # -# Except as contained in this notice, the name of a copyright holder -# shall not be used in advertising or otherwise to promote the sale, use -# or other dealings in this Software without prior written authorization -# of the copyright holder. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. # ############################################################################### # diff --git a/test/Makefile.am b/test/Makefile.am index 89d32e9..841ff8d 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -2,28 +2,36 @@ TEST_LDADD = $(top_builddir)/pixman/libpixman-1.la INCLUDES = -I$(top_srcdir)/pixman -I$(top_builddir)/pixman TESTPROGRAMS = \ + a1-trap-test \ region-test \ - scaling-test \ - blitters-test \ - composite \ fetch-test \ oob-test \ window-test \ - trap-crasher + trap-crasher \ + alphamap \ + blitters-test \ + scaling-test \ + composite +a1_trap_test_LDADD = $(TEST_LDADD) fetch_test_LDADD = $(TEST_LDADD) -region_test_LDADD = $(TEST_LDADD) composite_LDADD = $(TEST_LDADD) trap_crasher_LDADD = $(TEST_LDADD) oob_test_LDADD = $(TEST_LDADD) window_test_LDADD = $(TEST_LDADD) +region_test_LDADD = $(TEST_LDADD) +region_test_SOURCES = region-test.c utils.c utils.h + blitters_test_LDADD = $(TEST_LDADD) blitters_test_SOURCES = blitters-test.c utils.c utils.h scaling_test_LDADD = $(TEST_LDADD) scaling_test_SOURCES = scaling-test.c utils.c utils.h +alphamap_LDADD = $(TEST_LDADD) +alphamap_SOURCES = alphamap.c utils.c utils.h + # GTK using test programs if HAVE_GTK @@ -31,7 +39,7 @@ if HAVE_GTK GTK_LDADD = $(TEST_LDADD) $(GTK_LIBS) GTK_UTILS = gtk-utils.c gtk-utils.h -TESTPROGRAMS += \ +TESTPROGRAMS_GTK = \ clip-test \ clip-in \ composite-test \ @@ -39,7 +47,8 @@ TESTPROGRAMS += \ alpha-test \ screen-test \ convolution-test \ - trap-test + trap-test \ + alphamap INCLUDES += $(GTK_CFLAGS) @@ -69,5 +78,7 @@ convolution_test_SOURCES = convolution-test.c $(GTK_UTILS) endif -noinst_PROGRAMS = $(TESTPROGRAMS) +noinst_PROGRAMS = $(TESTPROGRAMS) $(TESTPROGRAMS_GTK) + +TESTS = $(TESTPROGRAMS) diff --git a/test/a1-trap-test.c b/test/a1-trap-test.c new file mode 100644 index 0000000..6163e7c --- /dev/null +++ b/test/a1-trap-test.c @@ -0,0 +1,50 @@ +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "pixman.h" + +int +main (int argc, char **argv) +{ +#define WIDTH 20 +#define HEIGHT 20 + + pixman_image_t *src_img; + pixman_image_t *mask_img; + pixman_image_t *dest_img; + pixman_trap_t trap; + pixman_color_t red = { 0xffff, 0x0000, 0x0000, 0xffff }; + uint32_t *bits = malloc (WIDTH * HEIGHT * 4); + uint32_t *mbits = malloc (WIDTH * HEIGHT); + + memset (mbits, 0, WIDTH * HEIGHT); + memset (bits, 0xff, WIDTH * HEIGHT * 4); + + trap.top.l = pixman_double_to_fixed (0.5); + trap.top.r = pixman_double_to_fixed (1.5); + trap.top.y = pixman_double_to_fixed (0.5); + + trap.bot.l = pixman_double_to_fixed (0.5); + trap.bot.r = pixman_double_to_fixed (1.5); + trap.bot.y = pixman_double_to_fixed (1.5); + + mask_img = pixman_image_create_bits ( + PIXMAN_a1, WIDTH, HEIGHT, mbits, WIDTH); + src_img = pixman_image_create_solid_fill (&red); + dest_img = pixman_image_create_bits ( + PIXMAN_a8r8g8b8, WIDTH, HEIGHT, bits, WIDTH * 4); + + pixman_add_traps (mask_img, 0, 0, 1, &trap); + + pixman_image_composite (PIXMAN_OP_OVER, + src_img, mask_img, dest_img, + 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); + + assert (bits[0] == 0xffff0000); + assert (bits[1] == 0xffffffff); + assert (bits[1 * WIDTH + 0] == 0xffffffff); + assert (bits[1 * WIDTH + 1] == 0xffffffff); + + return 0; +} diff --git a/test/alphamap.c b/test/alphamap.c new file mode 100644 index 0000000..e6a25ef --- /dev/null +++ b/test/alphamap.c @@ -0,0 +1,49 @@ +#include <stdio.h> +#include <stdlib.h> +#include "utils.h" + +#define WIDTH 400 +#define HEIGHT 200 + +int +main (int argc, char **argv) +{ + uint8_t *alpha = make_random_bytes (WIDTH * HEIGHT); + uint32_t *src = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); + uint32_t *dest = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); + int i; + + pixman_image_t *a = pixman_image_create_bits (PIXMAN_a8, WIDTH, HEIGHT, (uint32_t *)alpha, WIDTH); + pixman_image_t *d = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, dest, WIDTH * 4); + + for (i = 0; i < 2; ++i) + { + pixman_format_code_t sformat = (i == 0)? PIXMAN_a8r8g8b8 : PIXMAN_a2r10g10b10; + pixman_image_t *s = pixman_image_create_bits (sformat, WIDTH, HEIGHT, src, WIDTH * 4); + int j, k; + + pixman_image_set_alpha_map (s, a, 0, 0); + + pixman_image_composite (PIXMAN_OP_SRC, s, NULL, d, 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); + + for (j = 0; j < HEIGHT; ++j) + { + for (k = 0; k < WIDTH; ++k) + { + uint8_t ap = ((uint8_t *)alpha)[j * WIDTH + k]; + uint32_t dap = (dest[j * WIDTH + k] >> 24); + uint32_t sap = (src[j * WIDTH + k] >> 24); + + if (ap != dap) + { + printf ("Wrong alpha value at (%d, %d). Should be %d; got %d (src was %d)\n", k, j, ap, dap, sap); + return 1; + } + } + } + + pixman_image_unref (s); + } + + return 0; +} diff --git a/test/blitters-test.c b/test/blitters-test.c index 979af24..4664db6 100644 --- a/test/blitters-test.c +++ b/test/blitters-test.c @@ -96,7 +96,7 @@ free_random_image (uint32_t initcrc, uint32_t crc32 = 0; int stride = pixman_image_get_stride (img); uint32_t *data = pixman_image_get_data (img); - int height = pixman_image_get_height (img);; + int height = pixman_image_get_height (img); if (fmt != -1) { @@ -270,7 +270,7 @@ test_composite (uint32_t initcrc, int testnum, int verbose) int w, h; int op; pixman_format_code_t src_fmt, dst_fmt, mask_fmt; - uint32_t *dstbuf; + uint32_t *dstbuf, *srcbuf, *maskbuf; uint32_t crc32; int max_width, max_height, max_extra_stride; @@ -308,12 +308,43 @@ test_composite (uint32_t initcrc, int testnum, int verbose) dst_img = create_random_image (img_fmt_list, max_width, max_height, max_extra_stride, &dst_fmt); + src_width = pixman_image_get_width (src_img); + src_height = pixman_image_get_height (src_img); + src_stride = pixman_image_get_stride (src_img); + + dst_width = pixman_image_get_width (dst_img); + dst_height = pixman_image_get_height (dst_img); + dst_stride = pixman_image_get_stride (dst_img); + + dstbuf = pixman_image_get_data (dst_img); + srcbuf = pixman_image_get_data (src_img); + + src_x = lcg_rand_n (src_width); + src_y = lcg_rand_n (src_height); + dst_x = lcg_rand_n (dst_width); + dst_y = lcg_rand_n (dst_height); + mask_img = NULL; mask_fmt = -1; mask_x = 0; mask_y = 0; + maskbuf = NULL; - if (lcg_rand_n (2)) + if ((src_fmt == PIXMAN_x8r8g8b8 || src_fmt == PIXMAN_x8b8g8r8) && + (lcg_rand_n (4) == 0)) + { + /* PIXBUF */ + mask_fmt = lcg_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8; + mask_img = pixman_image_create_bits (mask_fmt, + src_width, + src_height, + srcbuf, + src_stride); + mask_x = src_x; + mask_y = src_y; + maskbuf = srcbuf; + } + else if (lcg_rand_n (2)) { if (lcg_rand_n (2)) { @@ -335,20 +366,6 @@ test_composite (uint32_t initcrc, int testnum, int verbose) mask_y = lcg_rand_n (pixman_image_get_height (mask_img)); } - src_width = pixman_image_get_width (src_img); - src_height = pixman_image_get_height (src_img); - src_stride = pixman_image_get_stride (src_img); - - dst_width = pixman_image_get_width (dst_img); - dst_height = pixman_image_get_height (dst_img); - dst_stride = pixman_image_get_stride (dst_img); - - dstbuf = pixman_image_get_data (dst_img); - - src_x = lcg_rand_n (src_width); - src_y = lcg_rand_n (src_height); - dst_x = lcg_rand_n (dst_width); - dst_y = lcg_rand_n (dst_height); w = lcg_rand_n (dst_width - dst_x + 1); h = lcg_rand_n (dst_height - dst_y + 1); @@ -392,7 +409,13 @@ test_composite (uint32_t initcrc, int testnum, int verbose) crc32 = free_random_image (initcrc, dst_img, dst_fmt); if (mask_img) - free_random_image (initcrc, mask_img, -1); + { + if (srcbuf == maskbuf) + pixman_image_unref(mask_img); + else + free_random_image (initcrc, mask_img, -1); + } + return crc32; } @@ -440,7 +463,7 @@ main (int argc, char *argv[]) /* Predefined value for running with all the fastpath functions disabled. It needs to be updated every time when changes are introduced to this program or behavior of pixman changes! */ - if (crc == 0x1911E2C3) + if (crc == 0x20CBE02C) { printf ("blitters test passed\n"); } diff --git a/test/fetch-test.c b/test/fetch-test.c index 6306a4c..2ca16dd 100644 --- a/test/fetch-test.c +++ b/test/fetch-test.c @@ -6,7 +6,8 @@ #define SIZE 1024 -pixman_indexed_t mono_pallete = { +static pixman_indexed_t mono_palette = +{ .rgba = { 0x00000000, 0x00ffffff }, }; @@ -20,14 +21,15 @@ typedef struct { pixman_indexed_t *indexed; } testcase_t; -testcase_t testcases[] = { +static testcase_t testcases[] = +{ { .format = PIXMAN_a8r8g8b8, .width = 2, .height = 2, .stride = 8, - .src = { 0x00112233, 0x44556677, + .src = { 0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff }, - .dst = { 0x00112233, 0x44556677, + .dst = { 0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff }, .indexed = NULL, }, @@ -36,24 +38,33 @@ testcase_t testcases[] = { .width = 8, .height = 2, .stride = 4, #ifdef WORDS_BIGENDIAN - .src = { 0xaa000000, - 0x55000000 }, + .src = + { + 0xaa000000, + 0x55000000 + }, #else - .src = { 0x00000055, - 0x000000aa }, + .src = + { + 0x00000055, + 0x000000aa + }, #endif - .dst = { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, - 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff }, - .indexed = &mono_pallete, + .dst = + { + 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, + 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff + }, + .indexed = &mono_palette, }, #if 0 { .format = PIXMAN_g8, .width = 4, .height = 2, .stride = 4, - .src = { 0x01234567, + .src = { 0x01234567, 0x89abcdef }, - .dst = { 0x00010101, 0x00232323, 0x00454545, 0x00676767, + .dst = { 0x00010101, 0x00232323, 0x00454545, 0x00676767, 0x00898989, 0x00ababab, 0x00cdcdcd, 0x00efefef, }, }, #endif @@ -63,28 +74,33 @@ testcase_t testcases[] = { .width = 8, .height = 2, .stride = 8, #ifdef WORDS_BIGENDIAN - .src = { 0x00ff00ff, 0x00ff00ff, - 0xff00ff00, 0xff00ff00, - 0x80ff8000, - 0x800080ff + .src = + { + 0x00ff00ff, 0x00ff00ff, + 0xff00ff00, 0xff00ff00, + 0x80ff8000, + 0x800080ff }, #else - .src = { 0xff00ff00, 0xff00ff00, - 0x00ff00ff, 0x00ff00ff, - 0x0080ff80, - 0xff800080 - }, + .src = + { + 0xff00ff00, 0xff00ff00, + 0x00ff00ff, 0x00ff00ff, + 0x0080ff80, + 0xff800080 + }, #endif - .dst = { - 0xff000000, 0xffffffff, 0xffb80000, 0xffffe113, - 0xff000000, 0xffffffff, 0xff0023ee, 0xff4affff, - 0xffffffff, 0xff000000, 0xffffe113, 0xffb80000, - 0xffffffff, 0xff000000, 0xff4affff, 0xff0023ee, + .dst = + { + 0xff000000, 0xffffffff, 0xffb80000, 0xffffe113, + 0xff000000, 0xffffffff, 0xff0023ee, 0xff4affff, + 0xffffffff, 0xff000000, 0xffffe113, 0xffb80000, + 0xffffffff, 0xff000000, 0xff4affff, 0xff0023ee, }, }, }; -const int ntestcases = sizeof(testcases)/sizeof(testcases[0]); +int n_test_cases = sizeof(testcases)/sizeof(testcases[0]); static uint32_t @@ -133,26 +149,29 @@ main (int argc, char **argv) int i, j, x, y; int ret = 0; - for (i = 0; i < ntestcases; ++i) { - for (j = 0; j < 2; ++j) { + for (i = 0; i < n_test_cases; ++i) + { + for (j = 0; j < 2; ++j) + { src_img = pixman_image_create_bits (testcases[i].format, - testcases[i].width, + testcases[i].width, testcases[i].height, testcases[i].src, testcases[i].stride); pixman_image_set_indexed(src_img, testcases[i].indexed); dst_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, - testcases[i].width, + testcases[i].width, testcases[i].height, dst, testcases[i].width*4); - if (j) { + if (j) + { pixman_image_set_accessors (src_img, reader, writer); pixman_image_set_accessors (dst_img, reader, writer); } - + pixman_image_composite (PIXMAN_OP_SRC, src_img, NULL, dst_img, 0, 0, 0, 0, 0, 0, testcases[i].width, testcases[i].height); @@ -160,18 +179,23 @@ main (int argc, char **argv) pixman_image_unref (dst_img); for (y = 0; y < testcases[i].height; ++y) - for (x = 0; x < testcases[i].width; ++x) { - int offset = y*testcases[i].width + x; - if (dst[offset] != testcases[i].dst[offset]) { + { + for (x = 0; x < testcases[i].width; ++x) + { + int offset = y * testcases[i].width + x; + + if (dst[offset] != testcases[i].dst[offset]) + { printf ("test %i%c: pixel mismatch at (x=%d,y=%d): %08x expected, %08x obtained\n", i + 1, 'a' + j, - x, y, + x, y, testcases[i].dst[offset], dst[offset]); ret = 1; } } + } } } - + return ret; } diff --git a/test/region-test.c b/test/region-test.c index 3568969..9d5a41e 100644 --- a/test/region-test.c +++ b/test/region-test.c @@ -1,7 +1,7 @@ #include <assert.h> #include <stdlib.h> #include <stdio.h> -#include "pixman.h" +#include "utils.h" int main () @@ -22,8 +22,15 @@ main () { 2, 6, 7, 6 }, { 4, 1, 6, 1 }, }; - int i; + int i, j; pixman_box32_t *b; + pixman_image_t *image, *fill; + pixman_color_t white = { + 0xffff, + 0xffff, + 0xffff, + 0xffff + }; /* This used to go into an infinite loop before pixman-region.c * was fixed to not use explict "short" variables @@ -74,5 +81,43 @@ main () assert (i == 0); + fill = pixman_image_create_solid_fill (&white); + for (i = 0; i < 100; i++) + { + int image_size = 128; + + pixman_region32_init (&r1); + + /* Add some random rectangles */ + for (j = 0; j < 64; j++) + pixman_region32_union_rect (&r1, &r1, + lcg_rand_n (image_size), + lcg_rand_n (image_size), + lcg_rand_n (25), + lcg_rand_n (25)); + + /* Clip to image size */ + pixman_region32_init_rect (&r2, 0, 0, image_size, image_size); + pixman_region32_intersect (&r1, &r1, &r2); + pixman_region32_fini (&r2); + + /* render region to a1 mask */ + image = pixman_image_create_bits (PIXMAN_a1, image_size, image_size, NULL, 0); + pixman_image_set_clip_region32 (image, &r1); + pixman_image_composite32 (PIXMAN_OP_SRC, + fill, NULL, image, + 0, 0, 0, 0, 0, 0, + image_size, image_size); + pixman_region32_init_from_image (&r2, image); + + pixman_image_unref (image); + + assert (pixman_region32_equal (&r1, &r2)); + pixman_region32_fini (&r1); + pixman_region32_fini (&r2); + + } + pixman_image_unref (fill); + return 0; } diff --git a/test/utils.c b/test/utils.c index 1e42d89..58cd100 100644 --- a/test/utils.c +++ b/test/utils.c @@ -192,3 +192,17 @@ image_endian_swap (pixman_image_t *img, int bpp) } } +uint8_t * +make_random_bytes (int n_bytes) +{ + uint8_t *bytes = malloc (n_bytes); + int i; + + if (!bytes) + return NULL; + + for (i = 0; i < n_bytes; ++i) + bytes[i] = lcg_rand () & 0xff; + + return bytes; +} diff --git a/test/utils.h b/test/utils.h index 8fdb2ce..fb1ccec 100644 --- a/test/utils.h +++ b/test/utils.h @@ -39,3 +39,7 @@ compute_crc32 (uint32_t in_crc32, */ void image_endian_swap (pixman_image_t *img, int bpp); + +/* Generate n_bytes random bytes in malloced memory */ +uint8_t * +make_random_bytes (int n_bytes); |