Bug 746695. Update libpixman to 0.24.4 a=joe

Alan Coopersmith (2):
      Change MMX ldq_u to return _m64 instead of forcing all callers to cast
      Make mmx code compatible with Solaris Studio 12.3 compilers

Andrea Canciani (13):
      Include noop in win32 builds
      Silence autoconf warnings
      radial: Improve documentation and naming
      radial: Fix typos and trailing whitespace
      win32: Build benchmarks
      Workaround bug in llvm-gcc
      test: Fix compilation on win32
      build: Reuse sources and pixman-combine build rules
      build: Reuse test sources
      build-win32: Share targets and variables across win32 makefiles
      build-win32: Add root Makefile.win32
      test: Do not include config.h unless HAVE_CONFIG_H is defined
      build-win32: Add 'check' target

Benjamin Otte (2):
      tests: Add PNG_CFLAGS/LIBS to tests
      build: replace @VAR@ with $(VAR) in makefiles

Bobby Salazar (1):
      Android Runtime Detection Support For ARM NEON

Chris Wilson (1):
      bits: optimise fetching width==1 repeats

Colin Walters (1):
      autogen.sh: Support GNOME Build API

Jeff Muizelaar (1):
      Add definitions of INT64_MIN and INT64_MAX

Jon TURNEY (1):
      Fix build on cygwin after commit efdf65c0c4fff551fb3cd9104deda9adb6261e22

Matt Turner (11):
      lowlevel-blt: add over_x888_8_8888
      mmx: fix formats in commented code
      mmx: convert while (w) to if (w) when possible
      mmx: rename USE_MMX to USE_X86_MMX
      mmx: wrap x86/MMX inline assembly in ifdef USE_X86_MMX
      mmx: fix unaligned accesses
      mmx: prepare pixman-mmx.c to be compiled for ARM/iwmmxt
      mmx: compile on ARM for iwmmxt optimizations
      mmx: optimize unaligned 64-bit ARM/iwmmxt loads
      Make sure iwMMXt is only detected on ARM
      Correct the minimum gcc version needed for iwmmxt

Naohiro Aota (1):
      Don't use non-POSIX test

Nis Martensen (1):
      Fix a few typos in pixman-combine.c.template

Siarhei Siamashka (4):
      C fast path for scaled src_x888_8888 with nearest filter
      ARM: workaround binutils bug #12931 (code sections alignment)
      test: better coverage for BILINEAR->NEAREST filter optimization
      BILINEAR->NEAREST filter optimization for simple rotation and translation

Søren Sandmann (5):
      mmx: Delete some unused variables
      sse2: Delete some unused variables
      demos: Comment out some unused variables
      ARM: Fix two bugs in neon_composite_over_n_8888_0565_ca().
      test: Make fuzzer-find-diff.pl executable

Søren Sandmann Pedersen (63):
      Add a "noop" implementation.
      Add a noop composite function for the DST operator
      Move noop dest fetching to noop implementation
      Add a noop src iterator
      Move NULL iterator into pixman-noop.c
      Move NOP src iterator into noop implementation.
      Replace instances of "dst_*" with "dest_*"
      In pixman-general.c rename image_parameters to {src, mask, dest}_image
      Replace argumentxs to composite functions with a pointer to a struct
      blitters-test: Make common formats more likely to be tested.
      Pre-release version bump to 0.23.2
      Post-release version bump to 0.23.3
      Makefile.am: Add pixman@lists.freedesktop.org to RELEASE_ANNOUNCE_LIST
      Fix lcg_rand_u32() to return 32 random bits.
      New test of pixman_region_contains_{rectangle,point}
      Speed up pixman_region{,32}_contains_rectangle()
      Use find_box_for_y() in pixman_region_contains_point() too
      Don't include stdint.h in lowlevel-blt-bench.c
      In pixman_image_create_bits() allow images larger than 2GB
      Rename pixman-fast-path.h to pixman-inlines.h
      Use repeat() function from pixman-inlines.h in pixman-bits-image.c
      Move bilinear interpolation to pixman-inlines.h
      Pre-release version bump to 0.23.4
      Post-release version bump to 0.23.5
      test: New function to save a pixman image to .png
      Use pkg-config to determine the flags to use with libpng
      test: Use smaller boxes in region_contains_test()
      A few tweaks to a comment in pixman-combine.c.template
      Add a generic unorm_to_unorm() conversion utility
      Add general pixel converter
      Add initial version of the MAKE_ACCESSORS() macro
      Use MAKE_ACCESSORS() to generate all the 32 bit accessors
      Use MAKE_ACCESSORS() to generate accessors for all the 16bpp formats
      Use MAKE_ACCESSORS() to generate accessors for 8bpp RGB formats
      Use MAKE_ACCESSORS() to generate accessors for 4 bpp RGB formats
      Use MAKE_ACCESSORS() to generate accessors for 24bpp formats
      Use MAKE_ACCESSORS() to generate accessors for the a1 format.
      Use MAKE_ACCESSORS() to generate accessors for paletted formats
      Remove x and y coordinates from analyze_extents() and compute_sample_extents()
      Split computation of sample area into own function
      Eliminate compute_sample_extents() function
      test: Occasionally use a BILINEAR filter in blitters-test
      Strength-reduce BILINEAR filter to NEAREST filter for identity transforms
      Don't include stdint.h in scaling-helpers-test.
      Add src, mask, and dest flags to the composite args struct.
      Pre-release version bump to 0.23.6
      Post-release version bump to 0.23.7
      Add stable release / development snapshot to draft release notes
      gradient walker: Correct types and fix formatting
      Use sentinels instead of special casing first and last stops
      Simplify gradient_walker_reset()
      Merge branch 'gradients'
      Fix use of uninitialized fields reported by valgrind
      Pre-release version bump to 0.23.8
      Post-release version bump to 0.23.9
      Pre-release version bump to 0.24.0
      Post-release version bump to 0.24.1
      gradient-walker: For NONE repeats, when x < 0 or x > 1, set both colors to 0
      pixman-image.c: Fix typo in pixman_image_set_transform()
      Fix some signed overflow bugs
      Reject trapezoids where top (botttom) is above (below) the edges
      Fix bugs with alpha maps
      Pre-release version bump to 0.24.2

Taekyun Kim (25):
      Replace boolean arguments with flags for bilinear fast path template
      REPEAT_NORMAL support for bilinear fast path template
      sse2: Declare bilinear src_8888_8888 REPEAT_NORMAL composite function
      ARM: Add REPEAT_NORMAL functions to bilinear BIND macros
      Enable REPEAT_NORMAL bilinear fast path entries
      Bilinear REPEAT_NORMAL source line extension for too short src_width
      ARM NEON: Standard fast path out_reverse_8_8888
      ARM: NEON better instruction scheduling of over_n_8_8888
      ARM: NEON better instruction scheduling of over_n_8888
      sse2: Macros for assembling bilinear interpolation code fractions
      sse2: Bilinear scaled over_8888_8888
      sse2: Bilinear scaled over_8888_8_8888
      init/fini functions for pixman_image_t
      Add new fast path flag FAST_PATH_BITS_IMAGE
      Move _pixman_lookup_composite_function() to pixman-utils.c
      Simple repeat fast path
      Simple repeat: Extend too short source scanlines into temporary buffer
      ARM: NEON: Some cleanup of bilinear scanline functions
      ARM: NEON: Bilinear macro template for instruction scheduling
      ARM: NEON: Replace old bilinear scanline generator with new template
      ARM: NEON: Instruction scheduling of bilinear over_8888_8888
      ARM: NEON: Instruction scheduling of bilinear over_8888_8_8888
      ARM: NEON: Standard fast path src_n_8_8888
      ARM: NEON: Standard fast path src_n_8_8
      ARM: NEON: Fix assembly typo error in src_n_8_8888
This commit is contained in:
Jeff Muizelaar 2012-04-20 00:07:56 -04:00
parent 33464ca392
commit 4277a03964
32 changed files with 5519 additions and 5240 deletions

View File

@ -8,7 +8,7 @@ http://www.cairographics.org/.
VERSIONS:
cairo (12d521df8acc483b2daa844d4f05dc2fe2765ba6)
pixman (2f4f2fb4859931bf6dc5632d8c919e7296736427)
pixman (0.24.2)
==== Patches ====
@ -188,7 +188,7 @@ NOTE: we previously supported ARM assembler on MSVC, this has been removed becau
pixman-export.patch: use cairo_public for PIXMAN_EXPORT to make sure pixman symbols are not exported in libxul
bad-memset.patch: Fix third argument in memcmp call in pixman-image.c
pixman-limits.patch: include limits.h for SIZE_MAX
==== disable printing patch ====

View File

@ -1,28 +0,0 @@
# HG changeset patch
# Parent a968f1430c74282c673c01a2c0a4417e238f2de7
# User Thomas Prip Vestergaard <thomas@prip.nu>
Bug 710992 - Fix third argument in memcmp call in pixman-image.c
diff --git a/gfx/cairo/libpixman/src/pixman-image.c b/gfx/cairo/libpixman/src/pixman-image.c
--- a/gfx/cairo/libpixman/src/pixman-image.c
+++ b/gfx/cairo/libpixman/src/pixman-image.c
@@ -512,17 +512,17 @@ pixman_image_set_transform (pixman_image
free (common->transform);
common->transform = NULL;
result = TRUE;
goto out;
}
if (common->transform &&
- memcmp (common->transform, transform, sizeof (pixman_transform_t) == 0))
+ memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0)
{
return TRUE;
}
if (common->transform == NULL)
common->transform = malloc (sizeof (pixman_transform_t));
if (common->transform == NULL)

View File

@ -129,6 +129,7 @@ CSRCS = \
pixman-implementation.c \
pixman-linear-gradient.c \
pixman-matrix.c \
pixman-noop.c \
pixman-radial-gradient.c \
pixman-region16.c \
pixman-region32.c \

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,10 @@
#ifdef PIXMAN_FB_ACCESSORS
#define ACCESS(sym) sym##_accessors
#define READ(img, ptr) \
(((bits_image_t *)(img))->read_func ((ptr), sizeof(*(ptr))))
#define WRITE(img, ptr,val) \
(((bits_image_t *)(img))->write_func ((ptr), (val), sizeof (*(ptr))))
#define MEMCPY_WRAPPED(img, dst, src, size) \
do { \
size_t _i; \
uint8_t *_dst = (uint8_t*)(dst), *_src = (uint8_t*)(src); \
for(_i = 0; _i < size; _i++) { \
WRITE((img), _dst +_i, READ((img), _src + _i)); \
} \
} while (0)
#define MEMSET_WRAPPED(img, dst, val, size) \
do { \
size_t _i; \
@ -27,12 +16,8 @@
#else
#define ACCESS(sym) sym
#define READ(img, ptr) (*(ptr))
#define WRITE(img, ptr, val) (*(ptr) = (val))
#define MEMCPY_WRAPPED(img, dst, src, size) \
memcpy(dst, src, size)
#define MEMSET_WRAPPED(img, dst, val, size) \
memset(dst, val, size)

View File

@ -26,7 +26,7 @@
#ifndef PIXMAN_ARM_COMMON_H
#define PIXMAN_ARM_COMMON_H
#include "pixman-fast-path.h"
#include "pixman-inlines.h"
/* Define some macros which can expand into proxy functions between
* ARM assembly optimized functions and the rest of pixman fast path API.
@ -63,26 +63,16 @@ pixman_composite_##name##_asm_##cputype (int32_t w, \
\
static void \
cputype##_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) \
pixman_composite_info_t *info) \
{ \
dst_type *dst_line; \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line; \
src_type *src_line; \
int32_t dst_stride, src_stride; \
\
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
src_stride, src_line, src_cnt); \
PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, dst_type, \
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
\
pixman_composite_##name##_asm_##cputype (width, height, \
@ -101,30 +91,20 @@ pixman_composite_##name##_asm_##cputype (int32_t w, \
\
static void \
cputype##_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) \
pixman_composite_info_t *info) \
{ \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line; \
int32_t dst_stride; \
uint32_t src; \
\
src = _pixman_image_get_solid ( \
imp, src_image, dst_image->bits.format); \
imp, src_image, dest_image->bits.format); \
\
if ((flags & SKIP_ZERO_SRC) && src == 0) \
return; \
\
PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, dst_type, \
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
\
pixman_composite_##name##_asm_##cputype (width, height, \
@ -147,31 +127,21 @@ pixman_composite_##name##_asm_##cputype (int32_t w, \
\
static void \
cputype##_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) \
pixman_composite_info_t *info) \
{ \
dst_type *dst_line; \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line; \
mask_type *mask_line; \
int32_t dst_stride, mask_stride; \
uint32_t src; \
\
src = _pixman_image_get_solid ( \
imp, src_image, dst_image->bits.format); \
imp, src_image, dest_image->bits.format); \
\
if ((flags & SKIP_ZERO_SRC) && src == 0) \
return; \
\
PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, dst_type, \
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \
mask_stride, mask_line, mask_cnt); \
@ -196,31 +166,21 @@ pixman_composite_##name##_asm_##cputype (int32_t w, \
\
static void \
cputype##_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) \
pixman_composite_info_t *info) \
{ \
dst_type *dst_line; \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line; \
src_type *src_line; \
int32_t dst_stride, src_stride; \
uint32_t mask; \
\
mask = _pixman_image_get_solid ( \
imp, mask_image, dst_image->bits.format); \
imp, mask_image, dest_image->bits.format); \
\
if ((flags & SKIP_ZERO_MASK) && mask == 0) \
return; \
\
PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, dst_type, \
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
src_stride, src_line, src_cnt); \
@ -247,25 +207,15 @@ pixman_composite_##name##_asm_##cputype (int32_t w, \
\
static void \
cputype##_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) \
pixman_composite_info_t *info) \
{ \
dst_type *dst_line; \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line; \
src_type *src_line; \
mask_type *mask_line; \
int32_t dst_stride, src_stride, mask_stride; \
\
PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, dst_type, \
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
src_stride, src_line, src_cnt); \
@ -398,13 +348,17 @@ scaled_bilinear_scanline_##cputype##_##name##_##op ( \
\
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint32_t, dst_type, COVER, FALSE, FALSE) \
src_type, uint32_t, dst_type, COVER, FLAG_NONE) \
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint32_t, dst_type, NONE, FALSE, FALSE) \
src_type, uint32_t, dst_type, NONE, FLAG_NONE) \
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint32_t, dst_type, PAD, FALSE, FALSE)
src_type, uint32_t, dst_type, PAD, FLAG_NONE) \
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_normal_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint32_t, dst_type, NORMAL, \
FLAG_NONE)
#define PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST(flags, cputype, name, op, \
@ -443,12 +397,20 @@ scaled_bilinear_scanline_##cputype##_##name##_##op ( \
\
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint8_t, dst_type, COVER, TRUE, FALSE) \
src_type, uint8_t, dst_type, COVER, \
FLAG_HAVE_NON_SOLID_MASK) \
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint8_t, dst_type, NONE, TRUE, FALSE) \
src_type, uint8_t, dst_type, NONE, \
FLAG_HAVE_NON_SOLID_MASK) \
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint8_t, dst_type, PAD, TRUE, FALSE)
src_type, uint8_t, dst_type, PAD, \
FLAG_HAVE_NON_SOLID_MASK) \
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_normal_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint8_t, dst_type, NORMAL, \
FLAG_HAVE_NON_SOLID_MASK)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -706,13 +706,55 @@ generate_composite_function_single_scanline \
/******************************************************************************/
/* TODO: expand macros and do better instructions scheduling */
.macro pixman_composite_over_n_8888_process_pixblock_head
/* deinterleaved source pixels in {d0, d1, d2, d3} */
/* inverted alpha in {d24} */
/* destination pixels in {d4, d5, d6, d7} */
vmull.u8 q8, d24, d4
vmull.u8 q9, d24, d5
vmull.u8 q10, d24, d6
vmull.u8 q11, d24, d7
.endm
.macro pixman_composite_over_n_8888_process_pixblock_tail
vrshr.u16 q14, q8, #8
vrshr.u16 q15, q9, #8
vrshr.u16 q2, q10, #8
vrshr.u16 q3, q11, #8
vraddhn.u16 d28, q14, q8
vraddhn.u16 d29, q15, q9
vraddhn.u16 d30, q2, q10
vraddhn.u16 d31, q3, q11
vqadd.u8 q14, q0, q14
vqadd.u8 q15, q1, q15
.endm
.macro pixman_composite_over_n_8888_process_pixblock_tail_head
pixman_composite_over_8888_8888_process_pixblock_tail
vrshr.u16 q14, q8, #8
vrshr.u16 q15, q9, #8
vrshr.u16 q2, q10, #8
vrshr.u16 q3, q11, #8
vraddhn.u16 d28, q14, q8
vraddhn.u16 d29, q15, q9
vraddhn.u16 d30, q2, q10
vraddhn.u16 d31, q3, q11
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
cache_preload 8, 8
vqadd.u8 q14, q0, q14
PF add PF_X, PF_X, #8
PF tst PF_CTL, #0x0F
PF addne PF_X, PF_X, #8
PF subne PF_CTL, PF_CTL, #1
vqadd.u8 q15, q1, q15
PF cmp PF_X, ORIG_W
vmull.u8 q8, d24, d4
PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift]
vmull.u8 q9, d24, d5
PF subge PF_X, PF_X, ORIG_W
vmull.u8 q10, d24, d6
PF subges PF_CTL, PF_CTL, #0x10
vmull.u8 q11, d24, d7
PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]!
vst4.8 {d28, d29, d30, d31}, [DST_W, :128]!
.endm
.macro pixman_composite_over_n_8888_init
@ -722,6 +764,7 @@ generate_composite_function_single_scanline \
vdup.8 d1, d3[1]
vdup.8 d2, d3[2]
vdup.8 d3, d3[3]
vmvn.8 d24, d3 /* get inverted alpha */
.endm
generate_composite_function \
@ -1176,6 +1219,145 @@ generate_composite_function \
/******************************************************************************/
.macro pixman_composite_src_n_8_8888_process_pixblock_head
/* expecting solid source in {d0, d1, d2, d3} */
/* mask is in d24 (d25, d26, d27 are unused) */
/* in */
vmull.u8 q8, d24, d0
vmull.u8 q9, d24, d1
vmull.u8 q10, d24, d2
vmull.u8 q11, d24, d3
vrsra.u16 q8, q8, #8
vrsra.u16 q9, q9, #8
vrsra.u16 q10, q10, #8
vrsra.u16 q11, q11, #8
.endm
.macro pixman_composite_src_n_8_8888_process_pixblock_tail
vrshrn.u16 d28, q8, #8
vrshrn.u16 d29, q9, #8
vrshrn.u16 d30, q10, #8
vrshrn.u16 d31, q11, #8
.endm
.macro pixman_composite_src_n_8_8888_process_pixblock_tail_head
fetch_mask_pixblock
PF add PF_X, PF_X, #8
vrshrn.u16 d28, q8, #8
PF tst PF_CTL, #0x0F
vrshrn.u16 d29, q9, #8
PF addne PF_X, PF_X, #8
vrshrn.u16 d30, q10, #8
PF subne PF_CTL, PF_CTL, #1
vrshrn.u16 d31, q11, #8
PF cmp PF_X, ORIG_W
vmull.u8 q8, d24, d0
PF pld, [PF_MASK, PF_X, lsl #mask_bpp_shift]
vmull.u8 q9, d24, d1
PF subge PF_X, PF_X, ORIG_W
vmull.u8 q10, d24, d2
PF subges PF_CTL, PF_CTL, #0x10
vmull.u8 q11, d24, d3
PF ldrgeb DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]!
vst4.8 {d28, d29, d30, d31}, [DST_W, :128]!
vrsra.u16 q8, q8, #8
vrsra.u16 q9, q9, #8
vrsra.u16 q10, q10, #8
vrsra.u16 q11, q11, #8
.endm
.macro pixman_composite_src_n_8_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
.macro pixman_composite_src_n_8_8888_cleanup
.endm
generate_composite_function \
pixman_composite_src_n_8_8888_asm_neon, 0, 8, 32, \
FLAG_DST_WRITEONLY | FLAG_DEINTERLEAVE_32BPP, \
8, /* number of pixels, processed in a single block */ \
5, /* prefetch distance */ \
pixman_composite_src_n_8_8888_init, \
pixman_composite_src_n_8_8888_cleanup, \
pixman_composite_src_n_8_8888_process_pixblock_head, \
pixman_composite_src_n_8_8888_process_pixblock_tail, \
pixman_composite_src_n_8_8888_process_pixblock_tail_head, \
/******************************************************************************/
.macro pixman_composite_src_n_8_8_process_pixblock_head
vmull.u8 q0, d24, d16
vmull.u8 q1, d25, d16
vmull.u8 q2, d26, d16
vmull.u8 q3, d27, d16
vrsra.u16 q0, q0, #8
vrsra.u16 q1, q1, #8
vrsra.u16 q2, q2, #8
vrsra.u16 q3, q3, #8
.endm
.macro pixman_composite_src_n_8_8_process_pixblock_tail
vrshrn.u16 d28, q0, #8
vrshrn.u16 d29, q1, #8
vrshrn.u16 d30, q2, #8
vrshrn.u16 d31, q3, #8
.endm
.macro pixman_composite_src_n_8_8_process_pixblock_tail_head
fetch_mask_pixblock
PF add PF_X, PF_X, #8
vrshrn.u16 d28, q0, #8
PF tst PF_CTL, #0x0F
vrshrn.u16 d29, q1, #8
PF addne PF_X, PF_X, #8
vrshrn.u16 d30, q2, #8
PF subne PF_CTL, PF_CTL, #1
vrshrn.u16 d31, q3, #8
PF cmp PF_X, ORIG_W
vmull.u8 q0, d24, d16
PF pld, [PF_MASK, PF_X, lsl #mask_bpp_shift]
vmull.u8 q1, d25, d16
PF subge PF_X, PF_X, ORIG_W
vmull.u8 q2, d26, d16
PF subges PF_CTL, PF_CTL, #0x10
vmull.u8 q3, d27, d16
PF ldrgeb DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]!
vst1.8 {d28, d29, d30, d31}, [DST_W, :128]!
vrsra.u16 q0, q0, #8
vrsra.u16 q1, q1, #8
vrsra.u16 q2, q2, #8
vrsra.u16 q3, q3, #8
.endm
.macro pixman_composite_src_n_8_8_init
add DUMMY, sp, #ARGS_STACK_OFFSET
vld1.32 {d16[0]}, [DUMMY]
vdup.8 d16, d16[3]
.endm
.macro pixman_composite_src_n_8_8_cleanup
.endm
generate_composite_function \
pixman_composite_src_n_8_8_asm_neon, 0, 8, 8, \
FLAG_DST_WRITEONLY, \
32, /* number of pixels, processed in a single block */ \
5, /* prefetch distance */ \
pixman_composite_src_n_8_8_init, \
pixman_composite_src_n_8_8_cleanup, \
pixman_composite_src_n_8_8_process_pixblock_head, \
pixman_composite_src_n_8_8_process_pixblock_tail, \
pixman_composite_src_n_8_8_process_pixblock_tail_head
/******************************************************************************/
.macro pixman_composite_over_n_8_8888_process_pixblock_head
/* expecting deinterleaved source data in {d8, d9, d10, d11} */
/* d8 - blue, d9 - green, d10 - red, d11 - alpha */
@ -1183,49 +1365,83 @@ generate_composite_function \
/* mask is in d24 (d25, d26, d27 are unused) */
/* in */
vmull.u8 q0, d24, d8
vmull.u8 q1, d24, d9
vmull.u8 q6, d24, d10
vmull.u8 q7, d24, d11
vrshr.u16 q10, q0, #8
vrshr.u16 q11, q1, #8
vrshr.u16 q12, q6, #8
vrshr.u16 q13, q7, #8
vraddhn.u16 d0, q0, q10
vraddhn.u16 d1, q1, q11
vraddhn.u16 d2, q6, q12
vraddhn.u16 d3, q7, q13
vmvn.8 d24, d3 /* get inverted alpha */
vmull.u8 q6, d24, d8
vmull.u8 q7, d24, d9
vmull.u8 q8, d24, d10
vmull.u8 q9, d24, d11
vrshr.u16 q10, q6, #8
vrshr.u16 q11, q7, #8
vrshr.u16 q12, q8, #8
vrshr.u16 q13, q9, #8
vraddhn.u16 d0, q6, q10
vraddhn.u16 d1, q7, q11
vraddhn.u16 d2, q8, q12
vraddhn.u16 d3, q9, q13
vmvn.8 d25, d3 /* get inverted alpha */
/* source: d0 - blue, d1 - green, d2 - red, d3 - alpha */
/* destination: d4 - blue, d5 - green, d6 - red, d7 - alpha */
/* now do alpha blending */
vmull.u8 q8, d24, d4
vmull.u8 q9, d24, d5
vmull.u8 q10, d24, d6
vmull.u8 q11, d24, d7
vmull.u8 q8, d25, d4
vmull.u8 q9, d25, d5
vmull.u8 q10, d25, d6
vmull.u8 q11, d25, d7
.endm
.macro pixman_composite_over_n_8_8888_process_pixblock_tail
vrshr.u16 q14, q8, #8
vrshr.u16 q15, q9, #8
vrshr.u16 q12, q10, #8
vrshr.u16 q13, q11, #8
vrshr.u16 q6, q10, #8
vrshr.u16 q7, q11, #8
vraddhn.u16 d28, q14, q8
vraddhn.u16 d29, q15, q9
vraddhn.u16 d30, q12, q10
vraddhn.u16 d31, q13, q11
vraddhn.u16 d30, q6, q10
vraddhn.u16 d31, q7, q11
vqadd.u8 q14, q0, q14
vqadd.u8 q15, q1, q15
.endm
/* TODO: expand macros and do better instructions scheduling */
.macro pixman_composite_over_n_8_8888_process_pixblock_tail_head
pixman_composite_over_n_8_8888_process_pixblock_tail
vst4.8 {d28, d29, d30, d31}, [DST_W, :128]!
vrshr.u16 q14, q8, #8
vld4.8 {d4, d5, d6, d7}, [DST_R, :128]!
vrshr.u16 q15, q9, #8
fetch_mask_pixblock
cache_preload 8, 8
pixman_composite_over_n_8_8888_process_pixblock_head
vrshr.u16 q6, q10, #8
PF add PF_X, PF_X, #8
vrshr.u16 q7, q11, #8
PF tst PF_CTL, #0x0F
vraddhn.u16 d28, q14, q8
PF addne PF_X, PF_X, #8
vraddhn.u16 d29, q15, q9
PF subne PF_CTL, PF_CTL, #1
vraddhn.u16 d30, q6, q10
PF cmp PF_X, ORIG_W
vraddhn.u16 d31, q7, q11
PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift]
vmull.u8 q6, d24, d8
PF pld, [PF_MASK, PF_X, lsl #mask_bpp_shift]
vmull.u8 q7, d24, d9
PF subge PF_X, PF_X, ORIG_W
vmull.u8 q8, d24, d10
PF subges PF_CTL, PF_CTL, #0x10
vmull.u8 q9, d24, d11
PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]!
vqadd.u8 q14, q0, q14
PF ldrgeb DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]!
vqadd.u8 q15, q1, q15
vrshr.u16 q10, q6, #8
vrshr.u16 q11, q7, #8
vrshr.u16 q12, q8, #8
vrshr.u16 q13, q9, #8
vraddhn.u16 d0, q6, q10
vraddhn.u16 d1, q7, q11
vraddhn.u16 d2, q8, q12
vraddhn.u16 d3, q9, q13
vst4.8 {d28, d29, d30, d31}, [DST_W, :128]!
vmvn.8 d25, d3
vmull.u8 q8, d25, d4
vmull.u8 q9, d25, d5
vmull.u8 q10, d25, d6
vmull.u8 q11, d25, d7
.endm
.macro pixman_composite_over_n_8_8888_init
@ -1515,11 +1731,11 @@ generate_composite_function \
* output: updated src in {d0, d1, d2 } [B, G, R]
* updated mask in {d24, d25, d26} [B, G, R]
*/
vmull.u8 q1, d25, d9
vmull.u8 q6, d26, d10
vqadd.u8 q8, q0, q8
vmull.u8 q0, d24, d8
vqadd.u8 d22, d2, d22
vmull.u8 q6, d26, d10
vmull.u8 q1, d25, d9
/*
* convert the result in d16, d17, d22 to r5g6b5 and store
* it into {d28, d29}
@ -1542,6 +1758,7 @@ generate_composite_function \
vrshr.u16 q11, q12, #8
vrshr.u16 q8, q9, #8
vrshr.u16 q6, q13, #8
vraddhn.u16 d24, q12, q11
vraddhn.u16 d25, q9, q8
/*
* convert 8 r5g6b5 pixel data from {d4, d5} to planar
@ -1550,11 +1767,10 @@ generate_composite_function \
*/
vshrn.u16 d17, q2, #3
vshrn.u16 d18, q2, #8
vraddhn.u16 d24, q12, q11
vraddhn.u16 d26, q13, q6
vsli.u16 q2, q2, #5
vsri.u8 d18, d18, #5
vsri.u8 d17, d17, #6
vsri.u8 d18, d18, #5
/*
* 'combine_over_ca' replacement
*
@ -2489,6 +2705,56 @@ generate_composite_function \
/******************************************************************************/
.macro pixman_composite_out_reverse_8_8888_process_pixblock_head
/* src is in d0 */
/* destination pixel data is in {d4, d5, d6, d7} */
vmvn.8 d1, d0 /* get inverted alpha */
/* now do alpha blending */
vmull.u8 q8, d1, d4
vmull.u8 q9, d1, d5
vmull.u8 q10, d1, d6
vmull.u8 q11, d1, d7
.endm
.macro pixman_composite_out_reverse_8_8888_process_pixblock_tail
vrshr.u16 q14, q8, #8
vrshr.u16 q15, q9, #8
vrshr.u16 q12, q10, #8
vrshr.u16 q13, q11, #8
vraddhn.u16 d28, q14, q8
vraddhn.u16 d29, q15, q9
vraddhn.u16 d30, q12, q10
vraddhn.u16 d31, q13, q11
/* 32bpp result is in {d28, d29, d30, d31} */
.endm
/* TODO: expand macros and do better instructions scheduling */
.macro pixman_composite_out_reverse_8_8888_process_pixblock_tail_head
fetch_src_pixblock
pixman_composite_out_reverse_8_8888_process_pixblock_tail
vld4.8 {d4, d5, d6, d7}, [DST_R, :128]!
cache_preload 8, 8
pixman_composite_out_reverse_8_8888_process_pixblock_head
vst4.8 {d28, d29, d30, d31}, [DST_W, :128]!
.endm
generate_composite_function \
pixman_composite_out_reverse_8_8888_asm_neon, 8, 0, 32, \
FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \
8, /* number of pixels, processed in a single block */ \
5, /* prefetch distance */ \
default_init, \
default_cleanup, \
pixman_composite_out_reverse_8_8888_process_pixblock_head, \
pixman_composite_out_reverse_8_8888_process_pixblock_tail, \
pixman_composite_out_reverse_8_8888_process_pixblock_tail_head, \
28, /* dst_w_basereg */ \
4, /* dst_r_basereg */ \
0, /* src_basereg */ \
0 /* mask_basereg */
/******************************************************************************/
generate_composite_function_nearest_scanline \
pixman_scaled_nearest_scanline_8888_8888_OVER_asm_neon, 32, 0, 32, \
FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \

View File

@ -64,6 +64,8 @@ PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, over_8888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, out_reverse_8_0565,
uint8_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, out_reverse_8_8888,
uint8_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, neon, over_n_0565,
uint16_t, 1)
@ -88,6 +90,10 @@ PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, add_n_8_8,
uint8_t, 1, uint8_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, add_n_8_8888,
uint8_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (0, neon, src_n_8_8888,
uint8_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (0, neon, src_n_8_8,
uint8_t, 1, uint8_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, over_8888_n_8888,
uint32_t, 1, uint32_t, 1)
@ -229,8 +235,8 @@ pixman_blt_neon (uint32_t *src_bits,
int dst_bpp,
int src_x,
int src_y,
int dst_x,
int dst_y,
int dest_x,
int dest_y,
int width,
int height)
{
@ -243,7 +249,7 @@ pixman_blt_neon (uint32_t *src_bits,
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,
dest_y * dst_stride * 4 + dest_x * 2), dst_stride * 2,
(uint16_t *)(((char *) src_bits) +
src_y * src_stride * 4 + src_x * 2), src_stride * 2);
return TRUE;
@ -251,7 +257,7 @@ pixman_blt_neon (uint32_t *src_bits,
pixman_composite_src_8888_8888_asm_neon (
width, height,
(uint32_t *)(((char *) dst_bits) +
dst_y * dst_stride * 4 + dst_x * 4), dst_stride,
dest_y * dst_stride * 4 + dest_x * 4), dst_stride,
(uint32_t *)(((char *) src_bits) +
src_y * src_stride * 4 + src_x * 4), src_stride);
return TRUE;
@ -287,6 +293,12 @@ static const pixman_fast_path_t arm_neon_fast_paths[] =
PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8b8g8r8, neon_composite_src_rpixbuf_8888),
PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8r8g8b8, neon_composite_src_rpixbuf_8888),
PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8b8g8r8, neon_composite_src_pixbuf_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8r8g8b8, neon_composite_src_n_8_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, neon_composite_src_n_8_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, neon_composite_src_n_8_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8b8g8r8, neon_composite_src_n_8_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8, neon_composite_src_n_8_8),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8, neon_composite_over_n_8_8),
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),
@ -345,6 +357,8 @@ static const pixman_fast_path_t arm_neon_fast_paths[] =
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, neon_composite_over_reverse_n_8888),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, r5g6b5, neon_composite_out_reverse_8_0565),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, b5g6r5, neon_composite_out_reverse_8_0565),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, a8r8g8b8, neon_composite_out_reverse_8_8888),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, a8b8g8r8, neon_composite_out_reverse_8_8888),
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, neon_8888_8888),
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, neon_8888_8888),
@ -418,20 +432,20 @@ arm_neon_blt (pixman_implementation_t *imp,
int dst_bpp,
int src_x,
int src_y,
int dst_x,
int dst_y,
int dest_x,
int dest_y,
int width,
int height)
{
if (!pixman_blt_neon (
src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
src_x, src_y, dst_x, dst_y, width, height))
src_x, src_y, dest_x, dest_y, width, height))
{
return _pixman_implementation_blt (
imp->delegate,
src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
src_x, src_y, dst_x, dst_y, width, height);
src_x, src_y, dest_x, dest_y, width, height);
}
return TRUE;

View File

@ -29,7 +29,7 @@
#include "pixman-private.h"
#include "pixman-arm-common.h"
#include "pixman-fast-path.h"
#include "pixman-inlines.h"
#if 0 /* This code was moved to 'pixman-arm-simd-asm.S' */

View File

@ -34,6 +34,7 @@
#include <string.h>
#include "pixman-private.h"
#include "pixman-combine32.h"
#include "pixman-inlines.h"
/*
* By default, just evaluate the image at 32bpp and expand. Individual image
@ -90,34 +91,6 @@ fetch_pixel_no_alpha (bits_image_t *image,
typedef uint32_t (* get_pixel_t) (bits_image_t *image,
int x, int y, pixman_bool_t check_bounds);
static force_inline void
repeat (pixman_repeat_t repeat, int size, int *coord)
{
switch (repeat)
{
case PIXMAN_REPEAT_NORMAL:
*coord = MOD (*coord, size);
break;
case PIXMAN_REPEAT_PAD:
*coord = CLIP (*coord, 0, size - 1);
break;
case PIXMAN_REPEAT_REFLECT:
*coord = MOD (*coord, size * 2);
if (*coord >= size)
*coord = size * 2 - *coord - 1;
break;
case PIXMAN_REPEAT_NONE:
break;
default:
break;
}
}
static force_inline uint32_t
bits_image_fetch_pixel_nearest (bits_image_t *image,
pixman_fixed_t x,
@ -129,8 +102,8 @@ bits_image_fetch_pixel_nearest (bits_image_t *image,
if (image->common.repeat != PIXMAN_REPEAT_NONE)
{
repeat (image->common.repeat, image->width, &x0);
repeat (image->common.repeat, image->height, &y0);
repeat (image->common.repeat, &x0, image->width);
repeat (image->common.repeat, &y0, image->height);
return get_pixel (image, x0, y0, FALSE);
}
@ -140,97 +113,6 @@ bits_image_fetch_pixel_nearest (bits_image_t *image,
}
}
#if SIZEOF_LONG > 4
static force_inline uint32_t
bilinear_interpolation (uint32_t tl, uint32_t tr,
uint32_t bl, uint32_t br,
int distx, int disty)
{
uint64_t distxy, distxiy, distixy, distixiy;
uint64_t tl64, tr64, bl64, br64;
uint64_t f, r;
distxy = distx * disty;
distxiy = distx * (256 - disty);
distixy = (256 - distx) * disty;
distixiy = (256 - distx) * (256 - disty);
/* Alpha and Blue */
tl64 = tl & 0xff0000ff;
tr64 = tr & 0xff0000ff;
bl64 = bl & 0xff0000ff;
br64 = br & 0xff0000ff;
f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
r = f & 0x0000ff0000ff0000ull;
/* Red and Green */
tl64 = tl;
tl64 = ((tl64 << 16) & 0x000000ff00000000ull) | (tl64 & 0x0000ff00ull);
tr64 = tr;
tr64 = ((tr64 << 16) & 0x000000ff00000000ull) | (tr64 & 0x0000ff00ull);
bl64 = bl;
bl64 = ((bl64 << 16) & 0x000000ff00000000ull) | (bl64 & 0x0000ff00ull);
br64 = br;
br64 = ((br64 << 16) & 0x000000ff00000000ull) | (br64 & 0x0000ff00ull);
f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
r |= ((f >> 16) & 0x000000ff00000000ull) | (f & 0xff000000ull);
return (uint32_t)(r >> 16);
}
#else
static force_inline uint32_t
bilinear_interpolation (uint32_t tl, uint32_t tr,
uint32_t bl, uint32_t br,
int distx, int disty)
{
int distxy, distxiy, distixy, distixiy;
uint32_t f, r;
distxy = distx * disty;
distxiy = (distx << 8) - distxy; /* distx * (256 - disty) */
distixy = (disty << 8) - distxy; /* disty * (256 - distx) */
distixiy =
256 * 256 - (disty << 8) -
(distx << 8) + distxy; /* (256 - distx) * (256 - disty) */
/* Blue */
r = (tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy
+ (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy;
/* Green */
f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy
+ (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy;
r |= f & 0xff000000;
tl >>= 16;
tr >>= 16;
bl >>= 16;
br >>= 16;
r >>= 16;
/* Red */
f = (tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy
+ (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy;
r |= f & 0x00ff0000;
/* Alpha */
f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy
+ (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy;
r |= f & 0xff000000;
return r;
}
#endif
static force_inline uint32_t
bits_image_fetch_pixel_bilinear (bits_image_t *image,
pixman_fixed_t x,
@ -257,10 +139,10 @@ bits_image_fetch_pixel_bilinear (bits_image_t *image,
if (repeat_mode != PIXMAN_REPEAT_NONE)
{
repeat (repeat_mode, width, &x1);
repeat (repeat_mode, height, &y1);
repeat (repeat_mode, width, &x2);
repeat (repeat_mode, height, &y2);
repeat (repeat_mode, &x1, width);
repeat (repeat_mode, &y1, height);
repeat (repeat_mode, &x2, width);
repeat (repeat_mode, &y2, height);
tl = get_pixel (image, x1, y1, FALSE);
bl = get_pixel (image, x1, y2, FALSE);
@ -529,8 +411,8 @@ bits_image_fetch_pixel_convolution (bits_image_t *image,
if (repeat_mode != PIXMAN_REPEAT_NONE)
{
repeat (repeat_mode, width, &rx);
repeat (repeat_mode, height, &ry);
repeat (repeat_mode, &rx, width);
repeat (repeat_mode, &ry, height);
pixel = get_pixel (image, rx, ry, FALSE);
}
@ -812,10 +694,10 @@ bits_image_fetch_bilinear_affine (pixman_image_t * image,
mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
repeat (repeat_mode, width, &x1);
repeat (repeat_mode, height, &y1);
repeat (repeat_mode, width, &x2);
repeat (repeat_mode, height, &y2);
repeat (repeat_mode, &x1, width);
repeat (repeat_mode, &y1, height);
repeat (repeat_mode, &x2, width);
repeat (repeat_mode, &y2, height);
row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
@ -960,8 +842,8 @@ bits_image_fetch_nearest_affine (pixman_image_t * image,
if (repeat_mode != PIXMAN_REPEAT_NONE)
{
repeat (repeat_mode, width, &x0);
repeat (repeat_mode, height, &y0);
repeat (repeat_mode, &x0, width);
repeat (repeat_mode, &y0, height);
}
row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;
@ -1053,17 +935,16 @@ MAKE_FETCHERS (reflect_r5g6b5, r5g6b5, PIXMAN_REPEAT_REFLECT)
MAKE_FETCHERS (normal_r5g6b5, r5g6b5, PIXMAN_REPEAT_NORMAL)
static void
bits_image_fetch_solid_32 (pixman_image_t * image,
int x,
int y,
int width,
uint32_t * buffer,
const uint32_t * mask)
replicate_pixel_32 (bits_image_t * bits,
int x,
int y,
int width,
uint32_t * buffer)
{
uint32_t color;
uint32_t *end;
color = image->bits.fetch_pixel_32 (&image->bits, 0, 0);
color = bits->fetch_pixel_32 (bits, x, y);
end = buffer + width;
while (buffer < end)
@ -1071,18 +952,17 @@ bits_image_fetch_solid_32 (pixman_image_t * image,
}
static void
bits_image_fetch_solid_64 (pixman_image_t * image,
int x,
int y,
int width,
uint32_t * b,
const uint32_t * unused)
replicate_pixel_64 (bits_image_t * bits,
int x,
int y,
int width,
uint32_t * b)
{
uint64_t color;
uint64_t *buffer = (uint64_t *)b;
uint64_t *end;
color = image->bits.fetch_pixel_64 (&image->bits, 0, 0);
color = bits->fetch_pixel_64 (bits, x, y);
end = buffer + width;
while (buffer < end)
@ -1149,6 +1029,16 @@ bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
while (y >= image->height)
y -= image->height;
if (image->width == 1)
{
if (wide)
replicate_pixel_64 (image, 0, y, width, buffer);
else
replicate_pixel_32 (image, 0, y, width, buffer);
return;
}
while (width)
{
while (x < 0)
@ -1219,12 +1109,6 @@ typedef struct
static const fetcher_info_t fetcher_info[] =
{
{ PIXMAN_solid,
FAST_PATH_NO_ALPHA_MAP,
bits_image_fetch_solid_32,
bits_image_fetch_solid_64
},
{ PIXMAN_any,
(FAST_PATH_NO_ALPHA_MAP |
FAST_PATH_ID_TRANSFORM |
@ -1382,12 +1266,27 @@ dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
if (image->common.alpha_map)
{
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
uint32_t *alpha;
image->common.alpha_map->fetch_scanline_32 (
(pixman_image_t *)image->common.alpha_map,
x, y, width, buffer, mask);
if ((alpha = malloc (width * sizeof (uint32_t))))
{
int i;
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
image->common.alpha_map->fetch_scanline_32 (
(pixman_image_t *)image->common.alpha_map,
x, y, width, alpha, mask);
for (i = 0; i < width; ++i)
{
buffer[i] &= ~0xff000000;
buffer[i] |= (alpha[i] & 0xff000000);
}
free (alpha);
}
}
return iter->buffer;
@ -1400,17 +1299,33 @@ dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
int x = iter->x;
int y = iter->y;
int width = iter->width;
uint32_t * buffer = iter->buffer;
uint64_t * buffer = (uint64_t *)iter->buffer;
image->fetch_scanline_64 (
(pixman_image_t *)image, x, y, width, buffer, mask);
(pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask);
if (image->common.alpha_map)
{
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
uint64_t *alpha;
image->common.alpha_map->fetch_scanline_64 (
(pixman_image_t *)image->common.alpha_map, x, y, width, buffer, mask);
if ((alpha = malloc (width * sizeof (uint64_t))))
{
int i;
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
image->common.alpha_map->fetch_scanline_64 (
(pixman_image_t *)image->common.alpha_map,
x, y, width, (uint32_t *)alpha, mask);
for (i = 0; i < width; ++i)
{
buffer[i] &= ~0xffff000000000000ULL;
buffer[i] |= (alpha[i] & 0xffff000000000000ULL);
}
free (alpha);
}
}
return iter->buffer;
@ -1462,43 +1377,22 @@ dest_write_back_wide (pixman_iter_t *iter)
iter->y++;
}
static void
dest_write_back_direct (pixman_iter_t *iter)
{
iter->buffer += iter->image->bits.rowstride;
}
void
_pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter)
{
if (iter->flags & ITER_NARROW)
{
if (((image->common.flags &
(FAST_PATH_NO_ALPHA_MAP | FAST_PATH_NO_ACCESSORS)) ==
(FAST_PATH_NO_ALPHA_MAP | FAST_PATH_NO_ACCESSORS)) &&
(image->bits.format == PIXMAN_a8r8g8b8 ||
(image->bits.format == PIXMAN_x8r8g8b8 &&
(iter->flags & ITER_LOCALIZED_ALPHA))))
if ((iter->flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
(ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
{
iter->buffer = image->bits.bits + iter->y * image->bits.rowstride + iter->x;
iter->get_scanline = _pixman_iter_get_scanline_noop;
iter->write_back = dest_write_back_direct;
}
else
{
if ((iter->flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
(ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
{
iter->get_scanline = _pixman_iter_get_scanline_noop;
}
else
{
iter->get_scanline = dest_get_scanline_narrow;
}
iter->write_back = dest_write_back_narrow;
iter->get_scanline = dest_get_scanline_narrow;
}
iter->write_back = dest_write_back_narrow;
}
else
{
@ -1511,10 +1405,10 @@ static uint32_t *
create_bits (pixman_format_code_t format,
int width,
int height,
int * rowstride_bytes)
int * rowstride_bytes)
{
int stride;
int buf_size;
size_t buf_size;
int bpp;
/* what follows is a long-winded way, avoiding any possibility of integer
@ -1523,11 +1417,11 @@ create_bits (pixman_format_code_t format,
*/
bpp = PIXMAN_FORMAT_BPP (format);
if (pixman_multiply_overflows_int (width, bpp))
if (_pixman_multiply_overflows_int (width, bpp))
return NULL;
stride = width * bpp;
if (pixman_addition_overflows_int (stride, 0x1f))
if (_pixman_addition_overflows_int (stride, 0x1f))
return NULL;
stride += 0x1f;
@ -1535,7 +1429,7 @@ create_bits (pixman_format_code_t format,
stride *= sizeof (uint32_t);
if (pixman_multiply_overflows_int (height, stride))
if (_pixman_multiply_overflows_size (height, stride))
return NULL;
buf_size = height * stride;
@ -1546,39 +1440,29 @@ create_bits (pixman_format_code_t format,
return calloc (buf_size, 1);
}
PIXMAN_EXPORT pixman_image_t *
pixman_image_create_bits (pixman_format_code_t format,
int width,
int height,
uint32_t * bits,
int rowstride_bytes)
pixman_bool_t
_pixman_bits_image_init (pixman_image_t * image,
pixman_format_code_t format,
int width,
int height,
uint32_t * bits,
int rowstride)
{
pixman_image_t *image;
uint32_t *free_me = NULL;
/* 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 (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
if (!bits && width && height)
{
int rowstride_bytes;
free_me = bits = create_bits (format, width, height, &rowstride_bytes);
if (!bits)
return NULL;
return FALSE;
rowstride = rowstride_bytes / (int) sizeof (uint32_t);
}
image = _pixman_image_allocate ();
if (!image)
{
if (free_me)
free (free_me);
return NULL;
}
_pixman_image_init (image);
image->type = BITS;
image->bits.format = format;
@ -1588,15 +1472,43 @@ pixman_image_create_bits (pixman_format_code_t format,
image->bits.free_me = free_me;
image->bits.read_func = NULL;
image->bits.write_func = NULL;
/* The rowstride is stored in number of uint32_t */
image->bits.rowstride = rowstride_bytes / (int) sizeof (uint32_t);
image->bits.rowstride = rowstride;
image->bits.indexed = NULL;
image->common.property_changed = bits_image_property_changed;
_pixman_image_reset_clip_region (image);
return TRUE;
}
PIXMAN_EXPORT pixman_image_t *
pixman_image_create_bits (pixman_format_code_t format,
int width,
int height,
uint32_t * bits,
int rowstride_bytes)
{
pixman_image_t *image;
/* 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 (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
image = _pixman_image_allocate ();
if (!image)
return NULL;
if (!_pixman_bits_image_init (image, format, width, height, bits,
rowstride_bytes / (int) sizeof (uint32_t)))
{
free (image);
return NULL;
}
return image;
}

View File

@ -437,7 +437,7 @@ combine_saturate_u (pixman_implementation_t *imp,
* PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an
* argument. Note that this implementation operates on premultiplied colors,
* while the PDF specification does not. Therefore the code uses the formula
* ar.Cra = (1 as) . Dca + (1 ad) . Sca + B(Dca, ad, Sca, as)
* Cra = (1 as) . Dca + (1 ad) . Sca + B(Dca, ad, Sca, as)
*/
/*
@ -522,7 +522,7 @@ combine_multiply_ca (pixman_implementation_t *imp,
UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (result, isa, s, ida); \
\
*(dest + i) = result + \
(DIV_ONE_UNc (sa * da) << A_SHIFT) + \
(DIV_ONE_UNc (sa * (comp4_t)da) << A_SHIFT) + \
(blend_ ## name (RED_c (d), da, RED_c (s), sa) << R_SHIFT) + \
(blend_ ## name (GREEN_c (d), da, GREEN_c (s), sa) << G_SHIFT) + \
(blend_ ## name (BLUE_c (d), da, BLUE_c (s), sa)); \
@ -552,7 +552,7 @@ combine_multiply_ca (pixman_implementation_t *imp,
UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (result, ~m, s, ida); \
\
result += \
(DIV_ONE_UNc (ALPHA_c (m) * da) << A_SHIFT) + \
(DIV_ONE_UNc (ALPHA_c (m) * (comp4_t)da) << A_SHIFT) + \
(blend_ ## name (RED_c (d), da, RED_c (s), RED_c (m)) << R_SHIFT) + \
(blend_ ## name (GREEN_c (d), da, GREEN_c (s), GREEN_c (m)) << G_SHIFT) + \
(blend_ ## name (BLUE_c (d), da, BLUE_c (s), BLUE_c (m))); \
@ -849,7 +849,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion)
*
* r * set_sat (C, s) = set_sat (x * C, r * s)
*
* The above holds for all non-zero x, because they x'es in the fraction for
* The above holds for all non-zero x, because the x'es in the fraction for
* C_mid cancel out. Specifically, it holds for x = r:
*
* r * set_sat (C, s) = set_sat (r_c, rs)
@ -885,8 +885,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion)
*
* a_s * a_d * B(s, d)
* = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1)
* = a_s * a_d * set_lum (set_sat (a_d * S, a_s * SAT (D)),
* a_s * LUM (D), a_s * a_d)
* = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d)
*
*/
@ -927,7 +926,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion)
blend_ ## name (c, dc, da, sc, sa); \
\
*(dest + i) = result + \
(DIV_ONE_UNc (sa * da) << A_SHIFT) + \
(DIV_ONE_UNc (sa * (comp4_t)da) << A_SHIFT) + \
(DIV_ONE_UNc (c[0]) << R_SHIFT) + \
(DIV_ONE_UNc (c[1]) << G_SHIFT) + \
(DIV_ONE_UNc (c[2])); \
@ -1144,9 +1143,7 @@ PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity)
#undef CH_MIN
#undef PDF_NON_SEPARABLE_BLEND_MODE
/* Overlay
*
* All of the disjoint composing functions
/* All of the disjoint/conjoint composing functions
*
* The four entries in the first column indicate what source contributions
* come from each of the four areas of the picture -- areas covered by neither
@ -1167,6 +1164,9 @@ PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity)
* (0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0)
* (0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b)
* (0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0)
*
* See http://marc.info/?l=xfree-render&m=99792000027857&w=2 for more
* information about these operators.
*/
#define COMBINE_A_OUT 1

View File

@ -25,10 +25,10 @@
*/
#define MUL_UNc(a, b, t) \
((t) = (a) * (b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
((t) = (a) * (comp2_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
#define DIV_UNc(a, b) \
(((comp2_t) (a) * MASK) / (b))
(((comp2_t) (a) * MASK + ((b) / 2)) / (b))
#define ADD_UNc(x, y, t) \
((t) = (x) + (y), \

View File

@ -18,6 +18,12 @@
# define FUNC ((const char*) ("???"))
#endif
#if defined (__GNUC__)
# define MAYBE_UNUSED __attribute__((unused))
#else
# define MAYBE_UNUSED
#endif
#ifndef INT16_MIN
# define INT16_MIN (-32767-1)
#endif
@ -42,6 +48,15 @@
# define UINT32_MAX (4294967295U)
#endif
#ifndef INT64_MIN
# define INT64_MIN (-9223372036854775807-1)
#endif
#ifndef INT64_MAX
# define INT64_MAX (9223372036854775807)
#endif
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
@ -89,10 +104,10 @@
# define PIXMAN_GET_THREAD_LOCAL(name) \
(&name)
#elif defined(TOOLCHAIN_SUPPORTS__THREAD)
#elif defined(TLS)
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
static __thread type name
static TLS type name
# define PIXMAN_GET_THREAD_LOCAL(name) \
(&name)

View File

@ -24,12 +24,17 @@
#endif
#include <string.h>
#include <stdlib.h>
#if defined(USE_ARM_SIMD) && defined(_MSC_VER)
/* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */
#include <windows.h>
#endif
#if defined(__APPLE__)
#include "TargetConditionals.h"
#endif
#include "pixman-private.h"
#ifdef USE_VMX
@ -187,7 +192,7 @@ pixman_have_vmx (void)
#endif /* __APPLE__ */
#endif /* USE_VMX */
#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON)
#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT)
#if defined(_MSC_VER)
@ -244,16 +249,48 @@ pixman_have_arm_neon (void)
#endif /* USE_ARM_NEON */
#elif defined (__linux__) || defined(ANDROID) /* linux ELF */
#elif (defined (__APPLE__) && defined(TARGET_OS_IPHONE)) /* iOS (iPhone/iPad/iPod touch) */
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#include <elf.h>
/* Detection of ARM NEON on iOS is fairly simple because iOS binaries
* contain separate executable images for each processor architecture.
* So all we have to do is detect the armv7 architecture build. The
* operating system automatically runs the armv7 binary for armv7 devices
* and the armv6 binary for armv6 devices.
*/
pixman_bool_t
pixman_have_arm_simd (void)
{
#if defined(USE_ARM_SIMD)
return TRUE;
#else
return FALSE;
#endif
}
pixman_bool_t
pixman_have_arm_neon (void)
{
#if defined(USE_ARM_NEON) && defined(__ARM_NEON__)
/* This is an armv7 cpu build */
return TRUE;
#else
/* This is an armv6 cpu build */
return FALSE;
#endif
}
pixman_bool_t
pixman_have_arm_iwmmxt (void)
{
#if defined(USE_ARM_IWMMXT)
return FALSE;
#else
return FALSE;
#endif
}
#elif defined (__linux__) || defined(__ANDROID__) || defined(ANDROID) /* linux ELF or ANDROID */
static pixman_bool_t arm_has_v7 = FALSE;
static pixman_bool_t arm_has_v6 = FALSE;
@ -262,15 +299,10 @@ static pixman_bool_t arm_has_neon = FALSE;
static pixman_bool_t arm_has_iwmmxt = FALSE;
static pixman_bool_t arm_tests_initialized = FALSE;
#ifdef ANDROID
/* on Android, we can't reliably access /proc/self/auxv,
* so instead read the text version in /proc/cpuinfo and
* parse that instead.
*/
#if defined(__ANDROID__) || defined(ANDROID) /* Android device support */
static void
pixman_arm_detect_cpu_features (void)
pixman_arm_read_auxv_or_cpu_features ()
{
char buf[1024];
char* pos;
@ -298,10 +330,18 @@ pixman_arm_detect_cpu_features (void)
arm_tests_initialized = TRUE;
}
#else
#elif defined (__linux__) /* linux ELF */
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#include <elf.h>
static void
pixman_arm_detect_cpu_features (void)
pixman_arm_read_auxv_or_cpu_features ()
{
int fd;
Elf32_auxv_t aux;
@ -341,14 +381,15 @@ pixman_arm_detect_cpu_features (void)
arm_tests_initialized = TRUE;
}
#endif
#endif /* Linux elf */
#if defined(USE_ARM_SIMD)
pixman_bool_t
pixman_have_arm_simd (void)
{
if (!arm_tests_initialized)
pixman_arm_detect_cpu_features ();
pixman_arm_read_auxv_or_cpu_features ();
return arm_has_v6;
}
@ -360,23 +401,84 @@ pixman_bool_t
pixman_have_arm_neon (void)
{
if (!arm_tests_initialized)
pixman_arm_detect_cpu_features ();
pixman_arm_read_auxv_or_cpu_features ();
return arm_has_neon;
}
#endif /* USE_ARM_NEON */
#else /* linux ELF */
#if defined(USE_ARM_IWMMXT)
pixman_bool_t
pixman_have_arm_iwmmxt (void)
{
if (!arm_tests_initialized)
pixman_arm_read_auxv_or_cpu_features ();
return arm_has_iwmmxt;
}
#endif /* USE_ARM_IWMMXT */
#else /* !_MSC_VER && !Linux elf && !Android */
#define pixman_have_arm_simd() FALSE
#define pixman_have_arm_neon() FALSE
#define pixman_have_arm_iwmmxt() FALSE
#endif
#endif /* USE_ARM_SIMD || USE_ARM_NEON */
#endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */
#if defined(USE_MMX) || defined(USE_SSE2)
#if defined(USE_MIPS_DSPR2)
#if defined (__linux__) /* linux ELF */
pixman_bool_t
pixman_have_mips_dspr2 (void)
{
const char *search_string = "MIPS 74K";
const char *file_name = "/proc/cpuinfo";
/* Simple detection of MIPS DSP ASE (revision 2) at runtime for Linux.
* It is based on /proc/cpuinfo, which reveals hardware configuration
* to user-space applications. According to MIPS (early 2010), no similar
* facility is universally available on the MIPS architectures, so it's up
* to individual OSes to provide such.
*
* Only currently available MIPS core that supports DSPr2 is 74K.
*/
char cpuinfo_line[256];
FILE *f = NULL;
if ((f = fopen (file_name, "r")) == NULL)
return FALSE;
while (fgets (cpuinfo_line, sizeof (cpuinfo_line), f) != NULL)
{
if (strstr (cpuinfo_line, search_string) != NULL)
{
fclose (f);
return TRUE;
}
}
fclose (f);
/* Did not find string in the proc file. */
return FALSE;
}
#else /* linux ELF */
#define pixman_have_mips_dspr2() FALSE
#endif /* linux ELF */
#endif /* USE_MIPS_DSPR2 */
#if defined(USE_X86_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
@ -567,6 +669,7 @@ detect_cpu_features (void)
return features;
}
#ifdef USE_X86_MMX
static pixman_bool_t
pixman_have_mmx (void)
{
@ -582,6 +685,7 @@ pixman_have_mmx (void)
return mmx_present;
}
#endif
#ifdef USE_SSE2
static pixman_bool_t
@ -603,7 +707,7 @@ pixman_have_sse2 (void)
#endif
#else /* __amd64__ */
#ifdef USE_MMX
#ifdef USE_X86_MMX
#define pixman_have_mmx() TRUE
#endif
#ifdef USE_SSE2
@ -612,39 +716,84 @@ pixman_have_sse2 (void)
#endif /* __amd64__ */
#endif
static pixman_bool_t
disabled (const char *name)
{
const char *env;
if ((env = getenv ("PIXMAN_DISABLE")))
{
do
{
const char *end;
int len;
if ((end = strchr (env, ' ')))
len = end - env;
else
len = strlen (env);
if (strlen (name) == len && strncmp (name, env, len) == 0)
{
printf ("pixman: Disabled %s implementation\n", name);
return TRUE;
}
env += len;
}
while (*env++);
}
return FALSE;
}
pixman_implementation_t *
_pixman_choose_implementation (void)
{
pixman_implementation_t *imp;
imp = _pixman_implementation_create_general();
imp = _pixman_implementation_create_fast_path (imp);
#ifdef USE_MMX
if (pixman_have_mmx ())
if (!disabled ("fast"))
imp = _pixman_implementation_create_fast_path (imp);
#ifdef USE_X86_MMX
if (!disabled ("mmx") && pixman_have_mmx ())
imp = _pixman_implementation_create_mmx (imp);
#endif
#ifdef USE_SSE2
if (pixman_have_sse2 ())
if (!disabled ("sse2") && pixman_have_sse2 ())
imp = _pixman_implementation_create_sse2 (imp);
#endif
#ifdef USE_ARM_SIMD
if (pixman_have_arm_simd ())
if (!disabled ("arm-simd") && pixman_have_arm_simd ())
imp = _pixman_implementation_create_arm_simd (imp);
#endif
#ifdef USE_ARM_IWMMXT
if (!disabled ("arm-iwmmxt") && pixman_have_arm_iwmmxt ())
imp = _pixman_implementation_create_mmx (imp);
#endif
#ifdef USE_ARM_NEON
if (pixman_have_arm_neon ())
if (!disabled ("arm-neon") && pixman_have_arm_neon ())
imp = _pixman_implementation_create_arm_neon (imp);
#endif
#ifdef USE_MIPS_DSPR2
if (!disabled ("mips-dspr2") && pixman_have_mips_dspr2 ())
imp = _pixman_implementation_create_mips_dspr2 (imp);
#endif
#ifdef USE_VMX
if (pixman_have_vmx ())
if (!disabled ("vmx") && pixman_have_vmx ())
imp = _pixman_implementation_create_vmx (imp);
#endif
imp = _pixman_implementation_create_noop (imp);
return imp;
}

File diff suppressed because it is too large Load Diff

View File

@ -101,19 +101,9 @@ static const op_info_t op_flags[PIXMAN_N_OPERATORS] =
static void
general_composite_rect (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_info_t *info)
{
PIXMAN_COMPOSITE_ARGS (info);
uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8];
uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
uint8_t *src_buffer, *mask_buffer, *dest_buffer;
@ -124,9 +114,9 @@ general_composite_rect (pixman_implementation_t *imp,
int Bpp;
int i;
if ((src->common.flags & FAST_PATH_NARROW_FORMAT) &&
(!mask || mask->common.flags & FAST_PATH_NARROW_FORMAT) &&
(dest->common.flags & FAST_PATH_NARROW_FORMAT))
if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
(!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
(dest_image->common.flags & FAST_PATH_NARROW_FORMAT))
{
narrow = ITER_NARROW;
Bpp = 4;
@ -152,7 +142,7 @@ general_composite_rect (pixman_implementation_t *imp,
/* src iter */
src_flags = narrow | op_flags[op].src;
_pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src,
_pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src_image,
src_x, src_y, width, height,
src_buffer, src_flags);
@ -163,39 +153,26 @@ general_composite_rect (pixman_implementation_t *imp,
/* If it doesn't matter what the source is, then it doesn't matter
* what the mask is
*/
mask = NULL;
mask_image = NULL;
}
component_alpha =
mask &&
mask->common.type == BITS &&
mask->common.component_alpha &&
PIXMAN_FORMAT_RGB (mask->bits.format);
mask_image &&
mask_image->common.type == BITS &&
mask_image->common.component_alpha &&
PIXMAN_FORMAT_RGB (mask_image->bits.format);
_pixman_implementation_src_iter_init (
imp->toplevel, &mask_iter, mask, mask_x, mask_y, width, height,
imp->toplevel, &mask_iter, mask_image, mask_x, mask_y, width, height,
mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB));
/* dest iter */
_pixman_implementation_dest_iter_init (imp->toplevel, &dest_iter, dest,
dest_x, dest_y, width, height,
dest_buffer,
narrow | op_flags[op].dst);
_pixman_implementation_dest_iter_init (
imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height,
dest_buffer, narrow | op_flags[op].dst);
if (narrow)
{
if (component_alpha)
compose = _pixman_implementation_combine_32_ca;
else
compose = _pixman_implementation_combine_32;
}
else
{
if (component_alpha)
compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
else
compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
}
compose = _pixman_implementation_lookup_combiner (
imp->toplevel, op, component_alpha, narrow);
if (!compose)
return;
@ -233,8 +210,8 @@ general_blt (pixman_implementation_t *imp,
int dst_bpp,
int src_x,
int src_y,
int dst_x,
int dst_y,
int dest_x,
int dest_y,
int width,
int height)
{

View File

@ -31,7 +31,7 @@
void
_pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
gradient_t * gradient,
unsigned int spread)
pixman_repeat_t repeat)
{
walker->num_stops = gradient->n_stops;
walker->stops = gradient->stops;
@ -42,112 +42,54 @@ _pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
walker->left_rb = 0;
walker->right_ag = 0;
walker->right_rb = 0;
walker->spread = spread;
walker->repeat = repeat;
walker->need_reset = TRUE;
}
void
_pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
pixman_fixed_32_32_t pos)
static void
gradient_walker_reset (pixman_gradient_walker_t *walker,
pixman_fixed_48_16_t pos)
{
int32_t x, left_x, right_x;
pixman_color_t *left_c, *right_c;
pixman_color_t *left_c, *right_c;
int n, count = walker->num_stops;
pixman_gradient_stop_t * stops = walker->stops;
pixman_gradient_stop_t *stops = walker->stops;
static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
switch (walker->spread)
if (walker->repeat == PIXMAN_REPEAT_NORMAL)
{
case PIXMAN_REPEAT_NORMAL:
x = (int32_t)pos & 0xFFFF;
for (n = 0; n < count; n++)
if (x < stops[n].x)
break;
if (n == 0)
{
left_x = stops[count - 1].x - 0x10000;
left_c = &stops[count - 1].color;
}
else
{
left_x = stops[n - 1].x;
left_c = &stops[n - 1].color;
}
if (n == count)
{
right_x = stops[0].x + 0x10000;
right_c = &stops[0].color;
}
else
{
right_x = stops[n].x;
right_c = &stops[n].color;
}
left_x += (pos - x);
right_x += (pos - x);
break;
case PIXMAN_REPEAT_PAD:
for (n = 0; n < count; n++)
if (pos < stops[n].x)
break;
if (n == 0)
{
left_x = INT32_MIN;
left_c = &stops[0].color;
}
else
{
left_x = stops[n - 1].x;
left_c = &stops[n - 1].color;
}
if (n == count)
{
right_x = INT32_MAX;
right_c = &stops[n - 1].color;
}
else
{
right_x = stops[n].x;
right_c = &stops[n].color;
}
break;
case PIXMAN_REPEAT_REFLECT:
x = (int32_t)pos & 0xFFFF;
x = (int32_t)pos & 0xffff;
}
else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
{
x = (int32_t)pos & 0xffff;
if ((int32_t)pos & 0x10000)
x = 0x10000 - x;
for (n = 0; n < count; n++)
if (x < stops[n].x)
break;
if (n == 0)
{
left_x = -stops[0].x;
left_c = &stops[0].color;
}
else
{
left_x = stops[n - 1].x;
left_c = &stops[n - 1].color;
}
if (n == count)
{
right_x = 0x20000 - stops[n - 1].x;
right_c = &stops[n - 1].color;
}
else
{
right_x = stops[n].x;
right_c = &stops[n].color;
}
}
else
{
x = pos;
}
for (n = 0; n < count; n++)
{
if (x < stops[n].x)
break;
}
left_x = stops[n - 1].x;
left_c = &stops[n - 1].color;
right_x = stops[n].x;
right_c = &stops[n].color;
if (walker->repeat == PIXMAN_REPEAT_NORMAL)
{
left_x += (pos - x);
right_x += (pos - x);
}
else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
{
if ((int32_t)pos & 0x10000)
{
pixman_color_t *tmp_c;
@ -165,32 +107,13 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
}
left_x += (pos - x);
right_x += (pos - x);
break;
default: /* REPEAT_NONE */
for (n = 0; n < count; n++)
if (pos < stops[n].x)
break;
}
else if (walker->repeat == PIXMAN_REPEAT_NONE)
{
if (n == 0)
{
left_x = INT32_MIN;
right_x = stops[0].x;
left_c = right_c = (pixman_color_t*) &transparent_black;
}
right_c = left_c;
else if (n == count)
{
left_x = stops[n - 1].x;
right_x = INT32_MAX;
left_c = right_c = (pixman_color_t*) &transparent_black;
}
else
{
left_x = stops[n - 1].x;
right_x = stops[n].x;
left_c = &stops[n - 1].color;
right_c = &stops[n].color;
}
left_c = right_c;
}
walker->left_x = left_x;
@ -201,8 +124,8 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8);
if (walker->left_x == walker->right_x ||
( walker->left_ag == walker->right_ag &&
walker->left_rb == walker->right_rb ) )
(walker->left_ag == walker->right_ag &&
walker->left_rb == walker->right_rb))
{
walker->stepper = 0;
}
@ -215,20 +138,15 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
walker->need_reset = FALSE;
}
#define PIXMAN_GRADIENT_WALKER_NEED_RESET(w, x) \
( (w)->need_reset || (x) < (w)->left_x || (x) >= (w)->right_x)
/* the following assumes that PIXMAN_GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */
uint32_t
_pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
pixman_fixed_32_32_t x)
pixman_fixed_48_16_t x)
{
int dist, idist;
uint32_t t1, t2, a, color;
if (PIXMAN_GRADIENT_WALKER_NEED_RESET (walker, x))
_pixman_gradient_walker_reset (walker, x);
if (walker->need_reset || x < walker->left_x || x >= walker->right_x)
gradient_walker_reset (walker, x);
dist = ((int)(x - walker->left_x) * walker->stepper) >> 16;
idist = 256 - dist;

View File

@ -31,6 +31,50 @@
#include "pixman-private.h"
static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
static void
gradient_property_changed (pixman_image_t *image)
{
gradient_t *gradient = &image->gradient;
int n = gradient->n_stops;
pixman_gradient_stop_t *stops = gradient->stops;
pixman_gradient_stop_t *begin = &(gradient->stops[-1]);
pixman_gradient_stop_t *end = &(gradient->stops[n]);
switch (gradient->common.repeat)
{
default:
case PIXMAN_REPEAT_NONE:
begin->x = INT32_MIN;
begin->color = transparent_black;
end->x = INT32_MAX;
end->color = transparent_black;
break;
case PIXMAN_REPEAT_NORMAL:
begin->x = stops[n - 1].x - pixman_fixed_1;
begin->color = stops[n - 1].color;
end->x = stops[0].x + pixman_fixed_1;
end->color = stops[0].color;
break;
case PIXMAN_REPEAT_REFLECT:
begin->x = - stops[0].x;
begin->color = stops[0].color;
end->x = pixman_int_to_fixed (2) - stops[n - 1].x;
end->color = stops[n - 1].color;
break;
case PIXMAN_REPEAT_PAD:
begin->x = INT32_MIN;
begin->color = stops[0].color;
end->x = INT32_MAX;
end->color = stops[n - 1].color;
break;
}
}
pixman_bool_t
_pixman_init_gradient (gradient_t * gradient,
const pixman_gradient_stop_t *stops,
@ -38,45 +82,109 @@ _pixman_init_gradient (gradient_t * gradient,
{
return_val_if_fail (n_stops > 0, FALSE);
gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t));
/* We allocate two extra stops, one before the beginning of the stop list,
* and one after the end. These stops are initialized to whatever color
* would be used for positions outside the range of the stop list.
*
* This saves a bit of computation in the gradient walker.
*
* The pointer we store in the gradient_t struct still points to the
* first user-supplied struct, so when freeing, we will have to
* subtract one.
*/
gradient->stops =
pixman_malloc_ab (n_stops + 2, sizeof (pixman_gradient_stop_t));
if (!gradient->stops)
return FALSE;
gradient->stops += 1;
memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
gradient->n_stops = n_stops;
gradient->common.property_changed = gradient_property_changed;
return TRUE;
}
void
_pixman_image_init (pixman_image_t *image)
{
image_common_t *common = &image->common;
pixman_region32_init (&common->clip_region);
common->alpha_count = 0;
common->have_clip_region = FALSE;
common->clip_sources = FALSE;
common->transform = NULL;
common->repeat = PIXMAN_REPEAT_NONE;
common->filter = PIXMAN_FILTER_NEAREST;
common->filter_params = NULL;
common->n_filter_params = 0;
common->alpha_map = NULL;
common->component_alpha = FALSE;
common->ref_count = 1;
common->property_changed = NULL;
common->client_clip = FALSE;
common->destroy_func = NULL;
common->destroy_data = NULL;
common->dirty = TRUE;
}
pixman_bool_t
_pixman_image_fini (pixman_image_t *image)
{
image_common_t *common = (image_common_t *)image;
common->ref_count--;
if (common->ref_count == 0)
{
if (image->common.destroy_func)
image->common.destroy_func (image, image->common.destroy_data);
pixman_region32_fini (&common->clip_region);
free (common->transform);
free (common->filter_params);
if (common->alpha_map)
pixman_image_unref ((pixman_image_t *)common->alpha_map);
if (image->type == LINEAR ||
image->type == RADIAL ||
image->type == CONICAL)
{
if (image->gradient.stops)
{
/* See _pixman_init_gradient() for an explanation of the - 1 */
free (image->gradient.stops - 1);
}
/* This will trigger if someone adds a property_changed
* method to the linear/radial/conical gradient overwriting
* the general one.
*/
assert (
image->common.property_changed == gradient_property_changed);
}
if (image->type == BITS && image->bits.free_me)
free (image->bits.free_me);
return TRUE;
}
return FALSE;
}
pixman_image_t *
_pixman_image_allocate (void)
{
pixman_image_t *image = malloc (sizeof (pixman_image_t));
if (image)
{
image_common_t *common = &image->common;
pixman_region32_init (&common->clip_region);
common->alpha_count = 0;
common->have_clip_region = FALSE;
common->clip_sources = FALSE;
common->transform = NULL;
common->repeat = PIXMAN_REPEAT_NONE;
common->filter = PIXMAN_FILTER_NEAREST;
common->filter_params = NULL;
common->n_filter_params = 0;
common->alpha_map = NULL;
common->component_alpha = FALSE;
common->ref_count = 1;
common->property_changed = NULL;
common->client_clip = FALSE;
common->destroy_func = NULL;
common->destroy_data = NULL;
common->dirty = TRUE;
}
_pixman_image_init (image);
return image;
}
@ -100,39 +208,9 @@ pixman_image_ref (pixman_image_t *image)
PIXMAN_EXPORT pixman_bool_t
pixman_image_unref (pixman_image_t *image)
{
image_common_t *common = (image_common_t *)image;
common->ref_count--;
if (common->ref_count == 0)
if (_pixman_image_fini (image))
{
if (image->common.destroy_func)
image->common.destroy_func (image, image->common.destroy_data);
pixman_region32_fini (&common->clip_region);
if (common->transform)
free (common->transform);
if (common->filter_params)
free (common->filter_params);
if (common->alpha_map)
pixman_image_unref ((pixman_image_t *)common->alpha_map);
if (image->type == LINEAR ||
image->type == RADIAL ||
image->type == CONICAL)
{
if (image->gradient.stops)
free (image->gradient.stops);
}
if (image->type == BITS && image->bits.free_me)
free (image->bits.free_me);
free (image);
return TRUE;
}
@ -221,13 +299,12 @@ compute_image_info (pixman_image_t *image)
image->common.transform->matrix[1][1] == 0)
{
pixman_fixed_t m01 = image->common.transform->matrix[0][1];
if (m01 == -image->common.transform->matrix[1][0])
{
if (m01 == -pixman_fixed_1)
flags |= FAST_PATH_ROTATE_90_TRANSFORM;
else if (m01 == pixman_fixed_1)
flags |= FAST_PATH_ROTATE_270_TRANSFORM;
}
pixman_fixed_t m10 = image->common.transform->matrix[1][0];
if (m01 == -1 && m10 == 1)
flags |= FAST_PATH_ROTATE_90_TRANSFORM;
else if (m01 == 1 && m10 == -1)
flags |= FAST_PATH_ROTATE_270_TRANSFORM;
}
}
@ -250,6 +327,47 @@ compute_image_info (pixman_image_t *image)
case PIXMAN_FILTER_GOOD:
case PIXMAN_FILTER_BEST:
flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
/* Here we have a chance to optimize BILINEAR filter to NEAREST if
* they are equivalent for the currently used transformation matrix.
*/
if (flags & FAST_PATH_ID_TRANSFORM)
{
flags |= FAST_PATH_NEAREST_FILTER;
}
else if (
/* affine and integer translation components in matrix ... */
((flags & FAST_PATH_AFFINE_TRANSFORM) &&
!pixman_fixed_frac (image->common.transform->matrix[0][2] |
image->common.transform->matrix[1][2])) &&
(
/* ... combined with a simple rotation */
(flags & (FAST_PATH_ROTATE_90_TRANSFORM |
FAST_PATH_ROTATE_180_TRANSFORM |
FAST_PATH_ROTATE_270_TRANSFORM)) ||
/* ... or combined with a simple non-rotated translation */
(image->common.transform->matrix[0][0] == pixman_fixed_1 &&
image->common.transform->matrix[1][1] == pixman_fixed_1 &&
image->common.transform->matrix[0][1] == 0 &&
image->common.transform->matrix[1][0] == 0)
)
)
{
/* FIXME: there are some affine-test failures, showing that
* handling of BILINEAR and NEAREST filter is not quite
* equivalent when getting close to 32K for the translation
* components of the matrix. That's likely some bug, but for
* now just skip BILINEAR->NEAREST optimization in this case.
*/
pixman_fixed_t magic_limit = pixman_int_to_fixed (30000);
if (image->common.transform->matrix[0][2] <= magic_limit &&
image->common.transform->matrix[1][2] <= magic_limit &&
image->common.transform->matrix[0][2] >= -magic_limit &&
image->common.transform->matrix[1][2] >= -magic_limit)
{
flags |= FAST_PATH_NEAREST_FILTER;
}
}
break;
case PIXMAN_FILTER_CONVOLUTION:
@ -320,12 +438,7 @@ compute_image_info (pixman_image_t *image)
else
{
code = image->bits.format;
if (!image->common.transform &&
image->common.repeat == PIXMAN_REPEAT_NORMAL)
{
flags |= FAST_PATH_SIMPLE_REPEAT | FAST_PATH_SAMPLES_COVER_CLIP;
}
flags |= FAST_PATH_BITS_IMAGE;
}
if (!PIXMAN_FORMAT_A (image->bits.format) &&

View File

@ -27,54 +27,6 @@
#include <stdlib.h>
#include "pixman-private.h"
static void
delegate_combine_32 (pixman_implementation_t * imp,
pixman_op_t op,
uint32_t * dest,
const uint32_t * src,
const uint32_t * mask,
int width)
{
_pixman_implementation_combine_32 (imp->delegate,
op, dest, src, mask, width);
}
static void
delegate_combine_64 (pixman_implementation_t * imp,
pixman_op_t op,
uint64_t * dest,
const uint64_t * src,
const uint64_t * mask,
int width)
{
_pixman_implementation_combine_64 (imp->delegate,
op, dest, src, mask, width);
}
static void
delegate_combine_32_ca (pixman_implementation_t * imp,
pixman_op_t op,
uint32_t * dest,
const uint32_t * src,
const uint32_t * mask,
int width)
{
_pixman_implementation_combine_32_ca (imp->delegate,
op, dest, src, mask, width);
}
static void
delegate_combine_64_ca (pixman_implementation_t * imp,
pixman_op_t op,
uint64_t * dest,
const uint64_t * src,
const uint64_t * mask,
int width)
{
_pixman_implementation_combine_64_ca (imp->delegate,
op, dest, src, mask, width);
}
static pixman_bool_t
delegate_blt (pixman_implementation_t * imp,
uint32_t * src_bits,
@ -85,14 +37,14 @@ delegate_blt (pixman_implementation_t * imp,
int dst_bpp,
int src_x,
int src_y,
int dst_x,
int dst_y,
int dest_x,
int dest_y,
int width,
int height)
{
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,
src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y,
width, height);
}
@ -150,61 +102,44 @@ _pixman_implementation_create (pixman_implementation_t *delegate,
imp->src_iter_init = delegate_src_iter_init;
imp->dest_iter_init = delegate_dest_iter_init;
imp->fast_paths = fast_paths;
for (i = 0; i < PIXMAN_N_OPERATORS; ++i)
{
imp->combine_32[i] = delegate_combine_32;
imp->combine_64[i] = delegate_combine_64;
imp->combine_32_ca[i] = delegate_combine_32_ca;
imp->combine_64_ca[i] = delegate_combine_64_ca;
imp->combine_32[i] = NULL;
imp->combine_64[i] = NULL;
imp->combine_32_ca[i] = NULL;
imp->combine_64_ca[i] = NULL;
}
imp->fast_paths = fast_paths;
return imp;
}
void
_pixman_implementation_combine_32 (pixman_implementation_t * imp,
pixman_op_t op,
uint32_t * dest,
const uint32_t * src,
const uint32_t * mask,
int width)
pixman_combine_32_func_t
_pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
pixman_op_t op,
pixman_bool_t component_alpha,
pixman_bool_t narrow)
{
(*imp->combine_32[op]) (imp, op, dest, src, mask, width);
}
pixman_combine_32_func_t f;
void
_pixman_implementation_combine_64 (pixman_implementation_t * imp,
pixman_op_t op,
uint64_t * dest,
const uint64_t * src,
const uint64_t * mask,
int width)
{
(*imp->combine_64[op]) (imp, op, dest, src, mask, width);
}
do
{
pixman_combine_32_func_t (*combiners[]) =
{
(pixman_combine_32_func_t *)imp->combine_64,
(pixman_combine_32_func_t *)imp->combine_64_ca,
imp->combine_32,
imp->combine_32_ca,
};
void
_pixman_implementation_combine_32_ca (pixman_implementation_t * imp,
pixman_op_t op,
uint32_t * dest,
const uint32_t * src,
const uint32_t * mask,
int width)
{
(*imp->combine_32_ca[op]) (imp, op, dest, src, mask, width);
}
f = combiners[component_alpha | (narrow << 1)][op];
void
_pixman_implementation_combine_64_ca (pixman_implementation_t * imp,
pixman_op_t op,
uint64_t * dest,
const uint64_t * src,
const uint64_t * mask,
int width)
{
(*imp->combine_64_ca[op]) (imp, op, dest, src, mask, width);
imp = imp->delegate;
}
while (!f);
return f;
}
pixman_bool_t
@ -217,13 +152,13 @@ _pixman_implementation_blt (pixman_implementation_t * imp,
int dst_bpp,
int src_x,
int src_y,
int dst_x,
int dst_y,
int dest_x,
int dest_y,
int width,
int height)
{
return (*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride,
src_bpp, dst_bpp, src_x, src_y, dst_x, dst_y,
src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y,
width, height);
}
@ -241,12 +176,6 @@ _pixman_implementation_fill (pixman_implementation_t *imp,
return (*imp->fill) (imp, bits, stride, bpp, x, y, width, height, xor);
}
static uint32_t *
get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
{
return NULL;
}
void
_pixman_implementation_src_iter_init (pixman_implementation_t *imp,
pixman_iter_t *iter,
@ -266,19 +195,7 @@ _pixman_implementation_src_iter_init (pixman_implementation_t *imp,
iter->height = height;
iter->flags = flags;
if (!image)
{
iter->get_scanline = get_scanline_null;
}
else if ((flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
{
iter->get_scanline = _pixman_iter_get_scanline_noop;
}
else
{
(*imp->src_iter_init) (imp, iter);
}
(*imp->src_iter_init) (imp, iter);
}
void

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,164 @@
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
/*
* Copyright © 2011 Red Hat, Inc.
*
* 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 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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <stdlib.h>
#include "pixman-private.h"
#include "pixman-combine32.h"
#include "pixman-inlines.h"
static void
noop_composite (pixman_implementation_t *imp,
pixman_composite_info_t *info)
{
return;
}
static void
dest_write_back_direct (pixman_iter_t *iter)
{
iter->buffer += iter->image->bits.rowstride;
}
static uint32_t *
noop_get_scanline (pixman_iter_t *iter, const uint32_t *mask)
{
uint32_t *result = iter->buffer;
iter->buffer += iter->image->bits.rowstride;
return result;
}
static uint32_t *
get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
{
return NULL;
}
static void
noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
{
pixman_image_t *image = iter->image;
#define FLAGS \
(FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM)
if (!image)
{
iter->get_scanline = get_scanline_null;
}
else if ((iter->flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
{
iter->get_scanline = _pixman_iter_get_scanline_noop;
}
else if (image->common.extended_format_code == PIXMAN_solid &&
((image->common.flags & (FAST_PATH_BITS_IMAGE | FAST_PATH_NO_ALPHA_MAP)) ==
(FAST_PATH_BITS_IMAGE | FAST_PATH_NO_ALPHA_MAP)))
{
bits_image_t *bits = &image->bits;
if (iter->flags & ITER_NARROW)
{
uint32_t color = bits->fetch_pixel_32 (bits, 0, 0);
uint32_t *buffer = iter->buffer;
uint32_t *end = buffer + iter->width;
while (buffer < end)
*(buffer++) = color;
}
else
{
uint64_t color = bits->fetch_pixel_64 (bits, 0, 0);
uint64_t *buffer = (uint64_t *)iter->buffer;
uint64_t *end = buffer + iter->width;
while (buffer < end)
*(buffer++) = color;
}
iter->get_scanline = _pixman_iter_get_scanline_noop;
}
else if (image->common.extended_format_code == PIXMAN_a8r8g8b8 &&
(iter->flags & ITER_NARROW) &&
(image->common.flags & FLAGS) == FLAGS &&
iter->x >= 0 && iter->y >= 0 &&
iter->x + iter->width <= image->bits.width &&
iter->y + iter->height <= image->bits.height)
{
iter->buffer =
image->bits.bits + iter->y * image->bits.rowstride + iter->x;
iter->get_scanline = noop_get_scanline;
}
else
{
(* imp->delegate->src_iter_init) (imp->delegate, iter);
}
}
static void
noop_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
{
pixman_image_t *image = iter->image;
uint32_t image_flags = image->common.flags;
uint32_t iter_flags = iter->flags;
if ((image_flags & FAST_PATH_STD_DEST_FLAGS) == FAST_PATH_STD_DEST_FLAGS &&
(iter_flags & ITER_NARROW) == ITER_NARROW &&
((image->common.extended_format_code == PIXMAN_a8r8g8b8) ||
(image->common.extended_format_code == PIXMAN_x8r8g8b8 &&
(iter_flags & (ITER_LOCALIZED_ALPHA)))))
{
iter->buffer = image->bits.bits + iter->y * image->bits.rowstride + iter->x;
iter->get_scanline = _pixman_iter_get_scanline_noop;
iter->write_back = dest_write_back_direct;
}
else
{
(* imp->delegate->dest_iter_init) (imp->delegate, iter);
}
}
static const pixman_fast_path_t noop_fast_paths[] =
{
{ PIXMAN_OP_DST, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, noop_composite },
{ PIXMAN_OP_NONE },
};
pixman_implementation_t *
_pixman_implementation_create_noop (pixman_implementation_t *fallback)
{
pixman_implementation_t *imp =
_pixman_implementation_create (fallback, noop_fast_paths);
imp->src_iter_init = noop_src_iter_init;
imp->dest_iter_init = noop_dest_iter_init;
return imp;
}

View File

@ -250,6 +250,19 @@ _pixman_radial_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter);
void
_pixman_conical_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter);
void
_pixman_image_init (pixman_image_t *image);
pixman_bool_t
_pixman_bits_image_init (pixman_image_t * image,
pixman_format_code_t format,
int width,
int height,
uint32_t * bits,
int rowstride);
pixman_bool_t
_pixman_image_fini (pixman_image_t *image);
pixman_image_t *
_pixman_image_allocate (void);
@ -286,29 +299,29 @@ typedef struct
uint32_t left_rb;
uint32_t right_ag;
uint32_t right_rb;
int32_t left_x;
int32_t right_x;
int32_t stepper;
pixman_fixed_t left_x;
pixman_fixed_t right_x;
pixman_fixed_t stepper;
pixman_gradient_stop_t *stops;
int num_stops;
unsigned int spread;
pixman_repeat_t repeat;
int need_reset;
pixman_bool_t need_reset;
} pixman_gradient_walker_t;
void
_pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
gradient_t * gradient,
unsigned int spread);
pixman_repeat_t repeat);
void
_pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
pixman_fixed_32_32_t pos);
pixman_fixed_48_16_t pos);
uint32_t
_pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
pixman_fixed_32_32_t x);
pixman_fixed_48_16_t x);
/*
* Edges
@ -346,6 +359,40 @@ pixman_rasterize_edges_accessors (pixman_image_t *image,
*/
typedef struct pixman_implementation_t pixman_implementation_t;
typedef struct
{
pixman_op_t op;
pixman_image_t * src_image;
pixman_image_t * mask_image;
pixman_image_t * dest_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_flags;
uint32_t mask_flags;
uint32_t dest_flags;
} pixman_composite_info_t;
#define PIXMAN_COMPOSITE_ARGS(info) \
MAYBE_UNUSED pixman_op_t op = info->op; \
MAYBE_UNUSED pixman_image_t * src_image = info->src_image; \
MAYBE_UNUSED pixman_image_t * mask_image = info->mask_image; \
MAYBE_UNUSED pixman_image_t * dest_image = info->dest_image; \
MAYBE_UNUSED int32_t src_x = info->src_x; \
MAYBE_UNUSED int32_t src_y = info->src_y; \
MAYBE_UNUSED int32_t mask_x = info->mask_x; \
MAYBE_UNUSED int32_t mask_y = info->mask_y; \
MAYBE_UNUSED int32_t dest_x = info->dest_x; \
MAYBE_UNUSED int32_t dest_y = info->dest_y; \
MAYBE_UNUSED int32_t width = info->width; \
MAYBE_UNUSED int32_t height = info->height
typedef void (*pixman_combine_32_func_t) (pixman_implementation_t *imp,
pixman_op_t op,
uint32_t * dest,
@ -361,18 +408,7 @@ typedef void (*pixman_combine_64_func_t) (pixman_implementation_t *imp,
int width);
typedef void (*pixman_composite_func_t) (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_info_t *info);
typedef pixman_bool_t (*pixman_blt_func_t) (pixman_implementation_t *imp,
uint32_t * src_bits,
uint32_t * dst_bits,
@ -382,8 +418,8 @@ typedef pixman_bool_t (*pixman_blt_func_t) (pixman_implementation_t *imp,
int dst_bpp,
int src_x,
int src_y,
int dst_x,
int dst_y,
int dest_x,
int dest_y,
int width,
int height);
typedef pixman_bool_t (*pixman_fill_func_t) (pixman_implementation_t *imp,
@ -439,34 +475,11 @@ pixman_implementation_t *
_pixman_implementation_create (pixman_implementation_t *delegate,
const pixman_fast_path_t *fast_paths);
void
_pixman_implementation_combine_32 (pixman_implementation_t *imp,
pixman_op_t op,
uint32_t * dest,
const uint32_t * src,
const uint32_t * mask,
int width);
void
_pixman_implementation_combine_64 (pixman_implementation_t *imp,
pixman_op_t op,
uint64_t * dest,
const uint64_t * src,
const uint64_t * mask,
int width);
void
_pixman_implementation_combine_32_ca (pixman_implementation_t *imp,
pixman_op_t op,
uint32_t * dest,
const uint32_t * src,
const uint32_t * mask,
int width);
void
_pixman_implementation_combine_64_ca (pixman_implementation_t *imp,
pixman_op_t op,
uint64_t * dest,
const uint64_t * src,
const uint64_t * mask,
int width);
pixman_combine_32_func_t
_pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
pixman_op_t op,
pixman_bool_t component_alpha,
pixman_bool_t wide);
pixman_bool_t
_pixman_implementation_blt (pixman_implementation_t *imp,
@ -478,8 +491,8 @@ _pixman_implementation_blt (pixman_implementation_t *imp,
int dst_bpp,
int src_x,
int src_y,
int dst_x,
int dst_y,
int dest_x,
int dest_y,
int width,
int height);
@ -523,7 +536,10 @@ _pixman_implementation_create_general (void);
pixman_implementation_t *
_pixman_implementation_create_fast_path (pixman_implementation_t *fallback);
#ifdef USE_MMX
pixman_implementation_t *
_pixman_implementation_create_noop (pixman_implementation_t *fallback);
#if defined USE_X86_MMX || defined USE_ARM_IWMMXT
pixman_implementation_t *
_pixman_implementation_create_mmx (pixman_implementation_t *fallback);
#endif
@ -543,6 +559,11 @@ pixman_implementation_t *
_pixman_implementation_create_arm_neon (pixman_implementation_t *fallback);
#endif
#ifdef USE_MIPS_DSPR2
pixman_implementation_t *
_pixman_implementation_create_mips_dspr2 (pixman_implementation_t *fallback);
#endif
#ifdef USE_VMX
pixman_implementation_t *
_pixman_implementation_create_vmx (pixman_implementation_t *fallback);
@ -587,15 +608,16 @@ _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask);
#define FAST_PATH_IS_OPAQUE (1 << 13)
#define FAST_PATH_NO_NORMAL_REPEAT (1 << 14)
#define FAST_PATH_NO_NONE_REPEAT (1 << 15)
#define FAST_PATH_SAMPLES_COVER_CLIP (1 << 16)
#define FAST_PATH_X_UNIT_POSITIVE (1 << 17)
#define FAST_PATH_AFFINE_TRANSFORM (1 << 18)
#define FAST_PATH_Y_UNIT_ZERO (1 << 19)
#define FAST_PATH_BILINEAR_FILTER (1 << 20)
#define FAST_PATH_ROTATE_90_TRANSFORM (1 << 21)
#define FAST_PATH_ROTATE_180_TRANSFORM (1 << 22)
#define FAST_PATH_ROTATE_270_TRANSFORM (1 << 23)
#define FAST_PATH_SIMPLE_REPEAT (1 << 24)
#define FAST_PATH_X_UNIT_POSITIVE (1 << 16)
#define FAST_PATH_AFFINE_TRANSFORM (1 << 17)
#define FAST_PATH_Y_UNIT_ZERO (1 << 18)
#define FAST_PATH_BILINEAR_FILTER (1 << 19)
#define FAST_PATH_ROTATE_90_TRANSFORM (1 << 20)
#define FAST_PATH_ROTATE_180_TRANSFORM (1 << 21)
#define FAST_PATH_ROTATE_270_TRANSFORM (1 << 22)
#define FAST_PATH_SAMPLES_COVER_CLIP_NEAREST (1 << 23)
#define FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR (1 << 24)
#define FAST_PATH_BITS_IMAGE (1 << 25)
#define FAST_PATH_PAD_REPEAT \
(FAST_PATH_NO_NONE_REPEAT | \
@ -631,7 +653,7 @@ _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask);
#define SOURCE_FLAGS(format) \
(FAST_PATH_STANDARD_FLAGS | \
((PIXMAN_ ## format == PIXMAN_solid) ? \
0 : (FAST_PATH_SAMPLES_COVER_CLIP | FAST_PATH_ID_TRANSFORM)))
0 : (FAST_PATH_SAMPLES_COVER_CLIP_NEAREST | FAST_PATH_NEAREST_FILTER | FAST_PATH_ID_TRANSFORM)))
#define MASK_FLAGS(format, extra) \
((PIXMAN_ ## format == PIXMAN_null) ? 0 : (SOURCE_FLAGS (format) | extra))
@ -670,10 +692,13 @@ void *
pixman_malloc_abc (unsigned int a, unsigned int b, unsigned int c);
pixman_bool_t
pixman_multiply_overflows_int (unsigned int a, unsigned int b);
_pixman_multiply_overflows_size (size_t a, size_t b);
pixman_bool_t
pixman_addition_overflows_int (unsigned int a, unsigned int b);
_pixman_multiply_overflows_int (unsigned int a, unsigned int b);
pixman_bool_t
_pixman_addition_overflows_int (unsigned int a, unsigned int b);
/* Compositing utilities */
void
@ -687,6 +712,17 @@ pixman_contract (uint32_t * dst,
const uint64_t *src,
int width);
pixman_bool_t
_pixman_lookup_composite_function (pixman_implementation_t *toplevel,
pixman_op_t op,
pixman_format_code_t src_format,
uint32_t src_flags,
pixman_format_code_t mask_format,
uint32_t mask_flags,
pixman_format_code_t dest_format,
uint32_t dest_flags,
pixman_implementation_t **out_imp,
pixman_composite_func_t *out_func);
/* Region Helpers */
pixman_bool_t
@ -742,6 +778,7 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst,
/* Trivial versions that are useful in macros */
#define CONVERT_8888_TO_8888(s) (s)
#define CONVERT_x888_TO_8888(s) ((s) | 0xff000000)
#define CONVERT_0565_TO_0565(s) (s)
#define PIXMAN_FORMAT_IS_WIDE(f) \
@ -758,6 +795,49 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst,
# define SCREEN_SHIFT_RIGHT(x,n) ((x) << (n))
#endif
static force_inline uint32_t
unorm_to_unorm (uint32_t val, int from_bits, int to_bits)
{
uint32_t result;
if (from_bits == 0)
return 0;
/* Delete any extra bits */
val &= ((1 << from_bits) - 1);
if (from_bits >= to_bits)
return val >> (from_bits - to_bits);
/* Start out with the high bit of val in the high bit of result. */
result = val << (to_bits - from_bits);
/* Copy the bits in result, doubling the number of bits each time, until
* we fill all to_bits. Unrolled manually because from_bits and to_bits
* are usually known statically, so the compiler can turn all of this
* into a few shifts.
*/
#define REPLICATE() \
do \
{ \
if (from_bits < to_bits) \
{ \
result |= result >> from_bits; \
\
from_bits *= 2; \
} \
} \
while (0)
REPLICATE();
REPLICATE();
REPLICATE();
REPLICATE();
REPLICATE();
return result;
}
/*
* Various debugging code
*/
@ -856,10 +936,11 @@ _pixman_log_error (const char *function, const char *message);
static inline uint64_t
oil_profile_stamp_rdtsc (void)
{
uint64_t ts;
uint32_t hi, lo;
__asm__ __volatile__ ("rdtsc\n" : "=A" (ts));
return ts;
__asm__ __volatile__ ("rdtsc\n" : "=a" (lo), "=d" (hi));
return lo | (((uint64_t)hi) << 32);
}
#define OIL_STAMP oil_profile_stamp_rdtsc

View File

@ -78,11 +78,11 @@ radial_compute_color (double a,
{
/*
* In this function error propagation can lead to bad results:
* - det can have an unbound error (if b*b-a*c is very small),
* - discr can have an unbound error (if b*b-a*c is very small),
* potentially making it the opposite sign of what it should have been
* (thus clearing a pixel that would have been colored or vice-versa)
* or propagating the error to sqrtdet;
* if det has the wrong sign or b is very small, this can lead to bad
* or propagating the error to sqrtdiscr;
* if discr has the wrong sign or b is very small, this can lead to bad
* results
*
* - the algorithm used to compute the solutions of the quadratic
@ -92,7 +92,7 @@ radial_compute_color (double a,
*
* - the above problems are worse if a is small (as inva becomes bigger)
*/
double det;
double discr;
if (a == 0)
{
@ -116,15 +116,26 @@ radial_compute_color (double a,
return 0;
}
det = fdot (b, a, 0, b, -c, 0);
if (det >= 0)
discr = fdot (b, a, 0, b, -c, 0);
if (discr >= 0)
{
double sqrtdet, t0, t1;
double sqrtdiscr, t0, t1;
sqrtdet = sqrt (det);
t0 = (b + sqrtdet) * inva;
t1 = (b - sqrtdet) * inva;
sqrtdiscr = sqrt (discr);
t0 = (b + sqrtdiscr) * inva;
t1 = (b - sqrtdiscr) * inva;
/*
* The root that must be used is the biggest one that belongs
* to the valid range ([0,1] for PIXMAN_REPEAT_NONE, any
* solution that results in a positive radius otherwise).
*
* If a > 0, t0 is the biggest solution, so if it is valid, it
* is the correct result.
*
* If a < 0, only one of the solutions can be valid, so the
* order in which they are tested is not important.
*/
if (repeat == PIXMAN_REPEAT_NONE)
{
if (0 <= t0 && t0 <= pixman_fixed_1)
@ -151,7 +162,7 @@ radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
* Implementation of radial gradients following the PDF specification.
* See section 8.7.4.5.4 Type 3 (Radial) Shadings of the PDF Reference
* Manual (PDF 32000-1:2008 at the time of this writing).
*
*
* In the radial gradient problem we are given two circles (c,r) and
* (c,r) that define the gradient itself.
*
@ -168,7 +179,7 @@ radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
*
* The graphical result is the same as drawing the valid (radius > 0)
* circles with increasing t in [-inf, +inf] (or in [0,1] if the gradient
* is not repeated) using SOURCE operatior composition.
* is not repeated) using SOURCE operator composition.
*
* It looks like a cone pointing towards the viewer if the ending circle
* is smaller than the starting one, a cone pointing inside the page if
@ -179,14 +190,14 @@ radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
* in, compute the t values for that point, solving for t in:
*
* length((1-t)·c + t·(c) - p) = (1-t)·r + t·r
*
*
* Let's rewrite it in a simpler way, by defining some auxiliary
* variables:
*
* cd = c - c
* pd = p - c
* dr = r - r
* lenght(t·cd - pd) = r + t·dr
* length(t·cd - pd) = r + t·dr
*
* which actually means
*
@ -212,7 +223,7 @@ radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
* B = pdx·cdx + pdy·cdy + r·dr
* C = pdx² + pdy² - r²
* At² - 2Bt + C = 0
*
*
* The solutions (unless the equation degenerates because of A = 0) are:
*
* t = (B ± (B² - A·C)) / A
@ -251,7 +262,7 @@ radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
{
if (!pixman_transform_point_3d (image->common.transform, &v))
return iter->buffer;
unit.vector[0] = image->common.transform->matrix[0][0];
unit.vector[1] = image->common.transform->matrix[1][0];
unit.vector[2] = image->common.transform->matrix[2][0];
@ -457,4 +468,3 @@ pixman_image_create_radial_gradient (pixman_point_fixed_t * inner,
return image;
}

View File

@ -102,7 +102,11 @@
static const box_type_t PREFIX (_empty_box_) = { 0, 0, 0, 0 };
static const region_data_type_t PREFIX (_empty_data_) = { 0, 0 };
#if defined (__llvm__) && !defined (__clang__)
static const volatile region_data_type_t PREFIX (_broken_data_) = { 0, 0 };
#else
static const region_data_type_t PREFIX (_broken_data_) = { 0, 0 };
#endif
static box_type_t *pixman_region_empty_box =
(box_type_t *)&PREFIX (_empty_box_);
@ -824,8 +828,7 @@ pixman_op (region_type_t * new_reg, /* Place to store result
{
if (!pixman_rect_alloc (new_reg, new_size))
{
if (old_data)
free (old_data);
free (old_data);
return FALSE;
}
}
@ -1001,8 +1004,7 @@ pixman_op (region_type_t * new_reg, /* Place to store result
APPEND_REGIONS (new_reg, r2_band_end, r2_end);
}
if (old_data)
free (old_data);
free (old_data);
if (!(numRects = new_reg->data->numRects))
{
@ -1023,8 +1025,7 @@ pixman_op (region_type_t * new_reg, /* Place to store result
return TRUE;
bail:
if (old_data)
free (old_data);
free (old_data);
return pixman_break (new_reg);
}
@ -2086,6 +2087,40 @@ PIXMAN_EXPORT PREFIX (_inverse) (region_type_t *new_reg, /* Destination region
return TRUE;
}
/* In time O(log n), locate the first box whose y2 is greater than y.
* Return @end if no such box exists.
*/
static box_type_t *
find_box_for_y (box_type_t *begin, box_type_t *end, int y)
{
box_type_t *mid;
if (end == begin)
return end;
if (end - begin == 1)
{
if (begin->y2 > y)
return begin;
else
return end;
}
mid = begin + (end - begin) / 2;
if (mid->y2 > y)
{
/* If no box is found in [begin, mid], the function
* will return @mid, which is then known to be the
* correct answer.
*/
return find_box_for_y (begin, mid, y);
}
else
{
return find_box_for_y (mid, end, y);
}
}
/*
* rect_in(region, rect)
* This routine takes a pointer to a region and a pointer to a box
@ -2102,7 +2137,6 @@ PIXMAN_EXPORT PREFIX (_inverse) (region_type_t *new_reg, /* Destination region
* partially in the region) or is outside the region (we reached a band
* that doesn't overlap the box at all and part_in is false)
*/
pixman_region_overlap_t
PIXMAN_EXPORT PREFIX (_contains_rectangle) (region_type_t * region,
box_type_t * prect)
@ -2139,12 +2173,15 @@ PIXMAN_EXPORT PREFIX (_contains_rectangle) (region_type_t * region,
/* can stop when both part_out and part_in are TRUE, or we reach prect->y2 */
for (pbox = PIXREGION_BOXPTR (region), pbox_end = pbox + numRects;
pbox != pbox_end;
pbox++)
pbox != pbox_end;
pbox++)
{
if (pbox->y2 <= y)
continue; /* getting up to speed or skipping remainder of band */
/* getting up to speed or skipping remainder of band */
if (pbox->y2 <= y)
{
if ((pbox = find_box_for_y (pbox, pbox_end, y)) == pbox_end)
break;
}
if (pbox->y1 > y)
{
@ -2319,6 +2356,16 @@ PREFIX (_reset) (region_type_t *region, box_type_t *box)
region->data = NULL;
}
PIXMAN_EXPORT void
PREFIX (_clear) (region_type_t *region)
{
GOOD (region);
FREE_DATA (region);
region->extents = *pixman_region_empty_box;
region->data = pixman_region_empty_data;
}
/* box is "return" value */
PIXMAN_EXPORT int
PREFIX (_contains_point) (region_type_t * region,
@ -2342,13 +2389,13 @@ PREFIX (_contains_point) (region_type_t * region,
return(TRUE);
}
for (pbox = PIXREGION_BOXPTR (region), pbox_end = pbox + numRects;
pbox != pbox_end;
pbox++)
{
if (y >= pbox->y2)
continue; /* not there yet */
pbox = PIXREGION_BOXPTR (region);
pbox_end = pbox + numRects;
pbox = find_box_for_y (pbox, pbox_end, y);
for (;pbox != pbox_end; pbox++)
{
if ((y < pbox->y1) || (x < pbox->x1))
break; /* missed it */

File diff suppressed because it is too large Load Diff

View File

@ -139,7 +139,7 @@ _pixman_edge_multi_init (pixman_edge_t * e,
if (ne > 0)
{
int nx = ne / e->dy;
ne -= nx * e->dy;
ne -= nx * (pixman_fixed_48_16_t)e->dy;
stepx += nx * e->signdx;
}

View File

@ -27,19 +27,136 @@
#endif
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "pixman-private.h"
#define N_CACHED_FAST_PATHS 8
typedef struct
{
struct
{
pixman_implementation_t * imp;
pixman_fast_path_t fast_path;
} cache [N_CACHED_FAST_PATHS];
} cache_t;
PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
pixman_bool_t
pixman_multiply_overflows_int (unsigned int a,
unsigned int b)
_pixman_lookup_composite_function (pixman_implementation_t *toplevel,
pixman_op_t op,
pixman_format_code_t src_format,
uint32_t src_flags,
pixman_format_code_t mask_format,
uint32_t mask_flags,
pixman_format_code_t dest_format,
uint32_t dest_flags,
pixman_implementation_t **out_imp,
pixman_composite_func_t *out_func)
{
pixman_implementation_t *imp;
cache_t *cache;
int i;
/* Check cache for fast paths */
cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
{
const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
/* Note that we check for equality here, not whether
* the cached fast path matches. This is to prevent
* us from selecting an overly general fast path
* when a more specific one would work.
*/
if (info->op == op &&
info->src_format == src_format &&
info->mask_format == mask_format &&
info->dest_format == dest_format &&
info->src_flags == src_flags &&
info->mask_flags == mask_flags &&
info->dest_flags == dest_flags &&
info->func)
{
*out_imp = cache->cache[i].imp;
*out_func = cache->cache[i].fast_path.func;
goto update_cache;
}
}
for (imp = toplevel; imp != NULL; imp = imp->delegate)
{
const pixman_fast_path_t *info = imp->fast_paths;
while (info->op != PIXMAN_OP_NONE)
{
if ((info->op == op || info->op == PIXMAN_OP_any) &&
/* Formats */
((info->src_format == src_format) ||
(info->src_format == PIXMAN_any)) &&
((info->mask_format == mask_format) ||
(info->mask_format == PIXMAN_any)) &&
((info->dest_format == dest_format) ||
(info->dest_format == PIXMAN_any)) &&
/* Flags */
(info->src_flags & src_flags) == info->src_flags &&
(info->mask_flags & mask_flags) == info->mask_flags &&
(info->dest_flags & dest_flags) == info->dest_flags)
{
*out_imp = imp;
*out_func = info->func;
/* Set i to the last spot in the cache so that the
* move-to-front code below will work
*/
i = N_CACHED_FAST_PATHS - 1;
goto update_cache;
}
++info;
}
}
return FALSE;
update_cache:
if (i)
{
while (i--)
cache->cache[i + 1] = cache->cache[i];
cache->cache[0].imp = *out_imp;
cache->cache[0].fast_path.op = op;
cache->cache[0].fast_path.src_format = src_format;
cache->cache[0].fast_path.src_flags = src_flags;
cache->cache[0].fast_path.mask_format = mask_format;
cache->cache[0].fast_path.mask_flags = mask_flags;
cache->cache[0].fast_path.dest_format = dest_format;
cache->cache[0].fast_path.dest_flags = dest_flags;
cache->cache[0].fast_path.func = *out_func;
}
return TRUE;
}
pixman_bool_t
_pixman_multiply_overflows_size (size_t a, size_t b)
{
return a >= SIZE_MAX / b;
}
pixman_bool_t
_pixman_multiply_overflows_int (unsigned int a, unsigned int b)
{
return a >= INT32_MAX / b;
}
pixman_bool_t
pixman_addition_overflows_int (unsigned int a,
unsigned int b)
_pixman_addition_overflows_int (unsigned int a, unsigned int b)
{
return a > INT32_MAX - b;
}
@ -67,31 +184,6 @@ pixman_malloc_abc (unsigned int a,
return malloc (a * b * c);
}
/*
* Helper routine to expand a color component from 0 < n <= 8 bits to 16
* bits by replication.
*/
static inline uint64_t
expand16 (const uint8_t val, int nbits)
{
/* Start out with the high bit of val in the high bit of result. */
uint16_t result = (uint16_t)val << (16 - nbits);
if (nbits == 0)
return 0;
/* Copy the bits in result, doubling the number of bits each time, until
* we fill all 16 bits.
*/
while (nbits < 16)
{
result |= result >> nbits;
nbits *= 2;
}
return result;
}
/*
* This function expands images from ARGB8 format to ARGB16. To preserve
* precision, it needs to know the original source format. For example, if the
@ -129,15 +221,33 @@ pixman_expand (uint64_t * dst,
for (i = width - 1; i >= 0; i--)
{
const uint32_t pixel = src[i];
const uint8_t a = (pixel >> a_shift) & a_mask,
r = (pixel >> r_shift) & r_mask,
g = (pixel >> g_shift) & g_mask,
b = (pixel >> b_shift) & b_mask;
const uint64_t a16 = a_size ? expand16 (a, a_size) : 0xffff,
r16 = expand16 (r, r_size),
g16 = expand16 (g, g_size),
b16 = expand16 (b, b_size);
uint8_t a, r, g, b;
uint64_t a16, r16, g16, b16;
if (a_size)
{
a = (pixel >> a_shift) & a_mask;
a16 = unorm_to_unorm (a, a_size, 16);
}
else
{
a16 = 0xffff;
}
if (r_size)
{
r = (pixel >> r_shift) & r_mask;
g = (pixel >> g_shift) & g_mask;
b = (pixel >> b_shift) & b_mask;
r16 = unorm_to_unorm (r, r_size, 16);
g16 = unorm_to_unorm (g, g_size, 16);
b16 = unorm_to_unorm (b, b_size, 16);
}
else
{
r16 = g16 = b16 = 0;
}
dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16;
}
}

View File

@ -238,7 +238,7 @@ 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,
pixman_image_t * dest_image,
int32_t src_x,
int32_t src_y,
int32_t mask_x,
@ -255,8 +255,8 @@ pixman_compute_composite_region32 (pixman_region32_t * region,
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->extents.x2 = MIN (region->extents.x2, dest_image->bits.width);
region->extents.y2 = MIN (region->extents.y2, dest_image->bits.height);
region->data = 0;
@ -271,29 +271,29 @@ pixman_compute_composite_region32 (pixman_region32_t * region,
return FALSE;
}
if (dst_image->common.have_clip_region)
if (dest_image->common.have_clip_region)
{
if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
if (!clip_general_image (region, &dest_image->common.clip_region, 0, 0))
return FALSE;
}
if (dst_image->common.alpha_map)
if (dest_image->common.alpha_map)
{
if (!pixman_region32_intersect_rect (region, region,
dst_image->common.alpha_origin_x,
dst_image->common.alpha_origin_y,
dst_image->common.alpha_map->width,
dst_image->common.alpha_map->height))
dest_image->common.alpha_origin_x,
dest_image->common.alpha_origin_y,
dest_image->common.alpha_map->width,
dest_image->common.alpha_map->height))
{
return FALSE;
}
if (!pixman_region32_not_empty (region))
return FALSE;
if (dst_image->common.alpha_map->common.have_clip_region)
if (dest_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))
if (!clip_general_image (region, &dest_image->common.alpha_map->common.clip_region,
-dest_image->common.alpha_origin_x,
-dest_image->common.alpha_origin_y))
{
return FALSE;
}
@ -335,340 +335,89 @@ pixman_compute_composite_region32 (pixman_region32_t * region,
return TRUE;
}
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 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++;
}
}
#define N_CACHED_FAST_PATHS 8
typedef struct
{
struct
{
pixman_implementation_t * imp;
pixman_fast_path_t fast_path;
} cache [N_CACHED_FAST_PATHS];
} cache_t;
pixman_fixed_48_16_t x1;
pixman_fixed_48_16_t y1;
pixman_fixed_48_16_t x2;
pixman_fixed_48_16_t y2;
} box_48_16_t;
PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
static force_inline pixman_bool_t
lookup_composite_function (pixman_op_t op,
pixman_format_code_t src_format,
uint32_t src_flags,
pixman_format_code_t mask_format,
uint32_t mask_flags,
pixman_format_code_t dest_format,
uint32_t dest_flags,
pixman_implementation_t **out_imp,
pixman_composite_func_t *out_func)
static pixman_bool_t
compute_transformed_extents (pixman_transform_t *transform,
const pixman_box32_t *extents,
box_48_16_t *transformed)
{
pixman_implementation_t *imp;
cache_t *cache;
pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
pixman_fixed_t x1, y1, x2, y2;
int i;
/* Check cache for fast paths */
cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2;
y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2;
x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2;
y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2;
for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
if (!transform)
{
const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
transformed->x1 = x1;
transformed->y1 = y1;
transformed->x2 = x2;
transformed->y2 = y2;
/* Note that we check for equality here, not whether
* the cached fast path matches. This is to prevent
* us from selecting an overly general fast path
* when a more specific one would work.
*/
if (info->op == op &&
info->src_format == src_format &&
info->mask_format == mask_format &&
info->dest_format == dest_format &&
info->src_flags == src_flags &&
info->mask_flags == mask_flags &&
info->dest_flags == dest_flags &&
info->func)
{
*out_imp = cache->cache[i].imp;
*out_func = cache->cache[i].fast_path.func;
goto update_cache;
}
return TRUE;
}
for (imp = get_implementation (); imp != NULL; imp = imp->delegate)
tx1 = ty1 = INT64_MAX;
tx2 = ty2 = INT64_MIN;
for (i = 0; i < 4; ++i)
{
const pixman_fast_path_t *info = imp->fast_paths;
pixman_fixed_48_16_t tx, ty;
pixman_vector_t v;
while (info->op != PIXMAN_OP_NONE)
{
if ((info->op == op || info->op == PIXMAN_OP_any) &&
/* Formats */
((info->src_format == src_format) ||
(info->src_format == PIXMAN_any)) &&
((info->mask_format == mask_format) ||
(info->mask_format == PIXMAN_any)) &&
((info->dest_format == dest_format) ||
(info->dest_format == PIXMAN_any)) &&
/* Flags */
(info->src_flags & src_flags) == info->src_flags &&
(info->mask_flags & mask_flags) == info->mask_flags &&
(info->dest_flags & dest_flags) == info->dest_flags)
{
*out_imp = imp;
*out_func = info->func;
v.vector[0] = (i & 0x01)? x1 : x2;
v.vector[1] = (i & 0x02)? y1 : y2;
v.vector[2] = pixman_fixed_1;
/* Set i to the last spot in the cache so that the
* move-to-front code below will work
*/
i = N_CACHED_FAST_PATHS - 1;
if (!pixman_transform_point (transform, &v))
return FALSE;
goto update_cache;
}
tx = (pixman_fixed_48_16_t)v.vector[0];
ty = (pixman_fixed_48_16_t)v.vector[1];
++info;
}
if (tx < tx1)
tx1 = tx;
if (ty < ty1)
ty1 = ty;
if (tx > tx2)
tx2 = tx;
if (ty > ty2)
ty2 = ty;
}
return FALSE;
update_cache:
if (i)
{
while (i--)
cache->cache[i + 1] = cache->cache[i];
cache->cache[0].imp = *out_imp;
cache->cache[0].fast_path.op = op;
cache->cache[0].fast_path.src_format = src_format;
cache->cache[0].fast_path.src_flags = src_flags;
cache->cache[0].fast_path.mask_format = mask_format;
cache->cache[0].fast_path.mask_flags = mask_flags;
cache->cache[0].fast_path.dest_format = dest_format;
cache->cache[0].fast_path.dest_flags = dest_flags;
cache->cache[0].fast_path.func = *out_func;
}
transformed->x1 = tx1;
transformed->y1 = ty1;
transformed->x2 = tx2;
transformed->y2 = ty2;
return TRUE;
}
static pixman_bool_t
compute_sample_extents (pixman_transform_t *transform,
pixman_box32_t *extents, int x, int y,
pixman_fixed_t x_off, pixman_fixed_t y_off,
pixman_fixed_t width, pixman_fixed_t height)
{
pixman_fixed_t x1, y1, x2, y2;
pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
/* We have checked earlier that (extents->x1 - x) etc. fit in a pixman_fixed_t */
x1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x1 - x) + pixman_fixed_1 / 2;
y1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y1 - y) + pixman_fixed_1 / 2;
x2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x2 - x) - pixman_fixed_1 / 2;
y2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y2 - y) - pixman_fixed_1 / 2;
if (!transform)
{
tx1 = (pixman_fixed_48_16_t)x1;
ty1 = (pixman_fixed_48_16_t)y1;
tx2 = (pixman_fixed_48_16_t)x2;
ty2 = (pixman_fixed_48_16_t)y2;
}
else
{
int i;
/* Silence GCC */
tx1 = ty1 = tx2 = ty2 = 0;
for (i = 0; i < 4; ++i)
{
pixman_fixed_48_16_t tx, ty;
pixman_vector_t v;
v.vector[0] = (i & 0x01)? x1 : x2;
v.vector[1] = (i & 0x02)? y1 : y2;
v.vector[2] = pixman_fixed_1;
if (!pixman_transform_point (transform, &v))
return FALSE;
tx = (pixman_fixed_48_16_t)v.vector[0];
ty = (pixman_fixed_48_16_t)v.vector[1];
if (i == 0)
{
tx1 = tx;
ty1 = ty;
tx2 = tx;
ty2 = ty;
}
else
{
if (tx < tx1)
tx1 = tx;
if (ty < ty1)
ty1 = ty;
if (tx > tx2)
tx2 = tx;
if (ty > ty2)
ty2 = ty;
}
}
}
/* Expand the source area by a tiny bit so account of different rounding that
* may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
* 0.5 so this won't cause the area computed to be overly pessimistic.
*/
tx1 += x_off - 8 * pixman_fixed_e;
ty1 += y_off - 8 * pixman_fixed_e;
tx2 += x_off + width + 8 * pixman_fixed_e;
ty2 += y_off + height + 8 * pixman_fixed_e;
if (tx1 < pixman_min_fixed_48_16 || tx1 > pixman_max_fixed_48_16 ||
ty1 < pixman_min_fixed_48_16 || ty1 > pixman_max_fixed_48_16 ||
tx2 < pixman_min_fixed_48_16 || tx2 > pixman_max_fixed_48_16 ||
ty2 < pixman_min_fixed_48_16 || ty2 > pixman_max_fixed_48_16)
{
return FALSE;
}
else
{
extents->x1 = pixman_fixed_to_int (tx1);
extents->y1 = pixman_fixed_to_int (ty1);
extents->x2 = pixman_fixed_to_int (tx2) + 1;
extents->y2 = pixman_fixed_to_int (ty2) + 1;
return TRUE;
}
}
#define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
#define ABS(f) (((f) < 0)? (-(f)) : (f))
#define IS_16_16(f) (((f) >= pixman_min_fixed_48_16 && ((f) <= pixman_max_fixed_48_16)))
static pixman_bool_t
analyze_extent (pixman_image_t *image, int x, int y,
const pixman_box32_t *extents, uint32_t *flags)
analyze_extent (pixman_image_t *image,
const pixman_box32_t *extents,
uint32_t *flags)
{
pixman_transform_t *transform;
pixman_fixed_t *params;
pixman_fixed_t x_off, y_off;
pixman_fixed_t width, height;
pixman_box32_t ex;
pixman_fixed_t *params;
box_48_16_t transformed;
pixman_box32_t exp_extents;
if (!image)
return TRUE;
@ -678,10 +427,10 @@ analyze_extent (pixman_image_t *image, int x, int y,
* check here that the expanded-by-one source
* extents in destination space fits in 16 bits
*/
if (!IS_16BIT (extents->x1 - x - 1) ||
!IS_16BIT (extents->y1 - y - 1) ||
!IS_16BIT (extents->x2 - x + 1) ||
!IS_16BIT (extents->y2 - y + 1))
if (!IS_16BIT (extents->x1 - 1) ||
!IS_16BIT (extents->y1 - 1) ||
!IS_16BIT (extents->x2 + 1) ||
!IS_16BIT (extents->y2 + 1))
{
return FALSE;
}
@ -696,18 +445,16 @@ analyze_extent (pixman_image_t *image, int x, int y,
if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff)
return FALSE;
#define ID_AND_NEAREST (FAST_PATH_ID_TRANSFORM | FAST_PATH_NEAREST_FILTER)
if ((image->common.flags & ID_AND_NEAREST) == ID_AND_NEAREST &&
extents->x1 - x >= 0 &&
extents->y1 - y >= 0 &&
extents->x2 - x <= image->bits.width &&
extents->y2 - y <= image->bits.height)
if ((image->common.flags & FAST_PATH_ID_TRANSFORM) == FAST_PATH_ID_TRANSFORM &&
extents->x1 >= 0 &&
extents->y1 >= 0 &&
extents->x2 <= image->bits.width &&
extents->y2 <= image->bits.height)
{
*flags |= FAST_PATH_SAMPLES_COVER_CLIP;
*flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
return TRUE;
}
switch (image->common.filter)
{
case PIXMAN_FILTER_CONVOLUTION:
@ -738,17 +485,6 @@ analyze_extent (pixman_image_t *image, int x, int y,
default:
return FALSE;
}
/* Check whether the non-expanded, transformed extent is entirely within
* the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is.
*/
ex = *extents;
if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height) &&
ex.x1 >= 0 && ex.y1 >= 0 &&
ex.x2 <= image->bits.width && ex.y2 <= image->bits.height)
{
*flags |= FAST_PATH_SAMPLES_COVER_CLIP;
}
}
else
{
@ -758,18 +494,58 @@ analyze_extent (pixman_image_t *image, int x, int y,
height = 0;
}
/* Check that the extents expanded by one don't overflow. This ensures that
* compositing functions can simply walk the source space using 16.16
* variables without worrying about overflow.
*/
ex.x1 = extents->x1 - 1;
ex.y1 = extents->y1 - 1;
ex.x2 = extents->x2 + 1;
ex.y2 = extents->y2 + 1;
if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
if (!compute_transformed_extents (transform, extents, &transformed))
return FALSE;
/* Expand the source area by a tiny bit so account of different rounding that
* may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
* 0.5 so this won't cause the area computed to be overly pessimistic.
*/
transformed.x1 -= 8 * pixman_fixed_e;
transformed.y1 -= 8 * pixman_fixed_e;
transformed.x2 += 8 * pixman_fixed_e;
transformed.y2 += 8 * pixman_fixed_e;
if (image->common.type == BITS)
{
if (pixman_fixed_to_int (transformed.x1) >= 0 &&
pixman_fixed_to_int (transformed.y1) >= 0 &&
pixman_fixed_to_int (transformed.x2) < image->bits.width &&
pixman_fixed_to_int (transformed.y2) < image->bits.height)
{
*flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
}
if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_1 / 2) >= 0 &&
pixman_fixed_to_int (transformed.y1 - pixman_fixed_1 / 2) >= 0 &&
pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2) < image->bits.width &&
pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2) < image->bits.height)
{
*flags |= FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR;
}
}
/* Check we don't overflow when the destination extents are expanded by one.
* This ensures that compositing functions can simply walk the source space
* using 16.16 variables without worrying about overflow.
*/
exp_extents = *extents;
exp_extents.x1 -= 1;
exp_extents.y1 -= 1;
exp_extents.x2 += 1;
exp_extents.y2 += 1;
if (!compute_transformed_extents (transform, &exp_extents, &transformed))
return FALSE;
if (!IS_16_16 (transformed.x1 + x_off - 8 * pixman_fixed_e) ||
!IS_16_16 (transformed.y1 + y_off - 8 * pixman_fixed_e) ||
!IS_16_16 (transformed.x2 + x_off + 8 * pixman_fixed_e + width) ||
!IS_16_16 (transformed.y2 + y_off + 8 * pixman_fixed_e + height))
{
return FALSE;
}
return TRUE;
}
@ -809,7 +585,7 @@ pixman_image_composite32 (pixman_op_t op,
pixman_format_code_t src_format, mask_format, dest_format;
uint32_t src_flags, mask_flags, dest_flags;
pixman_region32_t region;
pixman_box32_t *extents;
pixman_box32_t extents;
pixman_implementation_t *imp;
pixman_composite_func_t func;
@ -856,48 +632,87 @@ pixman_image_composite32 (pixman_op_t op,
goto out;
}
extents = pixman_region32_extents (&region);
extents = *pixman_region32_extents (&region);
if (!analyze_extent (src, dest_x - src_x, dest_y - src_y, extents, &src_flags))
extents.x1 -= dest_x - src_x;
extents.y1 -= dest_y - src_y;
extents.x2 -= dest_x - src_x;
extents.y2 -= dest_y - src_y;
if (!analyze_extent (src, &extents, &src_flags))
goto out;
if (!analyze_extent (mask, dest_x - mask_x, dest_y - mask_y, extents, &mask_flags))
extents.x1 -= src_x - mask_x;
extents.y1 -= src_y - mask_y;
extents.x2 -= src_x - mask_x;
extents.y2 -= src_y - mask_y;
if (!analyze_extent (mask, &extents, &mask_flags))
goto out;
/* If the clip is within the source samples, and the samples are opaque,
* then the source is effectively opaque.
/* If the clip is within the source samples, and the samples are
* opaque, then the source is effectively opaque.
*/
#define BOTH (FAST_PATH_SAMPLES_OPAQUE | FAST_PATH_SAMPLES_COVER_CLIP)
#define NEAREST_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \
FAST_PATH_NEAREST_FILTER | \
FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
#define BILINEAR_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \
FAST_PATH_BILINEAR_FILTER | \
FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR)
if ((src_flags & BOTH) == BOTH)
if ((src_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
(src_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
{
src_flags |= FAST_PATH_IS_OPAQUE;
if ((mask_flags & BOTH) == BOTH)
}
if ((mask_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
(mask_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
{
mask_flags |= FAST_PATH_IS_OPAQUE;
}
/*
* Check if we can replace our operator by a simpler one
* if the src or dest are opaque. The output operator should be
* mathematically equivalent to the source.
*/
op = optimize_operator (op, src_flags, mask_flags, dest_flags);
if (op == PIXMAN_OP_DST)
goto out;
if (lookup_composite_function (op,
src_format, src_flags,
mask_format, mask_flags,
dest_format, dest_flags,
&imp, &func))
if (_pixman_lookup_composite_function (
get_implementation (), op,
src_format, src_flags, mask_format, mask_flags, dest_format, dest_flags,
&imp, &func))
{
walk_region_internal (imp, op,
src, mask, dest,
src_x, src_y, mask_x, mask_y,
dest_x, dest_y,
width, height,
(src_flags & FAST_PATH_SIMPLE_REPEAT),
(mask_flags & FAST_PATH_SIMPLE_REPEAT),
&region, func);
pixman_composite_info_t info;
const pixman_box32_t *pbox;
int n;
info.op = op;
info.src_image = src;
info.mask_image = mask;
info.dest_image = dest;
info.src_flags = src_flags;
info.mask_flags = mask_flags;
info.dest_flags = dest_flags;
pbox = pixman_region32_rectangles (&region, &n);
while (n--)
{
info.src_x = pbox->x1 + src_x - dest_x;
info.src_y = pbox->y1 + src_y - dest_y;
info.mask_x = pbox->x1 + mask_x - dest_x;
info.mask_y = pbox->y1 + mask_y - dest_y;
info.dest_x = pbox->x1;
info.dest_y = pbox->y1;
info.width = pbox->x2 - pbox->x1;
info.height = pbox->y2 - pbox->y1;
func (imp, &info);
pbox++;
}
}
out:
@ -931,8 +746,8 @@ pixman_blt (uint32_t *src_bits,
int dst_bpp,
int src_x,
int src_y,
int dst_x,
int dst_y,
int dest_x,
int dest_y,
int width,
int height)
{
@ -940,7 +755,7 @@ pixman_blt (uint32_t *src_bits,
src_bits, dst_bits, src_stride, dst_stride,
src_bpp, dst_bpp,
src_x, src_y,
dst_x, dst_y,
dest_x, dest_y,
width, height);
}
@ -1294,7 +1109,7 @@ 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,
pixman_image_t * dest_image,
int16_t src_x,
int16_t src_y,
int16_t mask_x,
@ -1310,7 +1125,7 @@ pixman_compute_composite_region (pixman_region16_t * region,
pixman_region32_init (&r32);
retval = pixman_compute_composite_region32 (
&r32, src_image, mask_image, dst_image,
&r32, src_image, mask_image, dest_image,
src_x, src_y, mask_x, mask_y, dest_x, dest_y,
width, height);

View File

@ -468,6 +468,7 @@ pixman_bool_t pixman_region_equal (pixman_region16_t *reg
pixman_bool_t pixman_region_selfcheck (pixman_region16_t *region);
void pixman_region_reset (pixman_region16_t *region,
pixman_box16_t *box);
void pixman_region_clear (pixman_region16_t *region);
/*
* 32 bit regions
*/
@ -562,6 +563,7 @@ pixman_bool_t pixman_region32_equal (pixman_region32_t *r
pixman_bool_t pixman_region32_selfcheck (pixman_region32_t *region);
void pixman_region32_reset (pixman_region32_t *region,
pixman_box32_t *box);
void pixman_region32_clear (pixman_region32_t *region);
/* Copy / Fill / Misc */
@ -573,8 +575,8 @@ pixman_bool_t pixman_blt (uint32_t *src_bits,
int dst_bpp,
int src_x,
int src_y,
int dst_x,
int dst_y,
int dest_x,
int dest_y,
int width,
int height);
pixman_bool_t pixman_fill (uint32_t *bits,
@ -813,7 +815,7 @@ pixman_bool_t pixman_image_fill_boxes (pixman_op_t
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,
pixman_image_t *dest_image,
int16_t src_x,
int16_t src_y,
int16_t mask_x,

View File

@ -0,0 +1,18 @@
commit 3c275c75e381184fb3fa0537c4bfce50b44690e7
Author: Jeff Muizelaar <jmuizelaar@mozilla.com>
Date: Fri Apr 20 00:12:32 2012 -0400
limits
diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
index 2ec2594..de05c0e 100644
--- a/pixman/pixman-utils.c
+++ b/pixman/pixman-utils.c
@@ -27,6 +27,7 @@
#endif
#include <stdio.h>
#include <stdlib.h>
+#include <limits.h>
#include "pixman-private.h"