diff options
Diffstat (limited to 'thirdparty/libpng/arm')
-rw-r--r-- | thirdparty/libpng/arm/arm_init.c | 3 | ||||
-rw-r--r-- | thirdparty/libpng/arm/filter_neon.S | 2 | ||||
-rw-r--r-- | thirdparty/libpng/arm/filter_neon_intrinsics.c | 27 | ||||
-rw-r--r-- | thirdparty/libpng/arm/palette_neon_intrinsics.c | 149 |
4 files changed, 173 insertions, 8 deletions
diff --git a/thirdparty/libpng/arm/arm_init.c b/thirdparty/libpng/arm/arm_init.c index 02df812e77..a34ecdbef7 100644 --- a/thirdparty/libpng/arm/arm_init.c +++ b/thirdparty/libpng/arm/arm_init.c @@ -1,14 +1,15 @@ /* arm_init.c - NEON optimised filter functions * + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 2014,2016 Glenn Randers-Pehrson * Written by Mans Rullgard, 2011. - * Last changed in libpng 1.6.22 [May 26, 2016] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ + /* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are * called. */ diff --git a/thirdparty/libpng/arm/filter_neon.S b/thirdparty/libpng/arm/filter_neon.S index 000764cd21..2308aad13e 100644 --- a/thirdparty/libpng/arm/filter_neon.S +++ b/thirdparty/libpng/arm/filter_neon.S @@ -1,9 +1,9 @@ /* filter_neon.S - NEON optimised filter functions * + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 2014,2017 Glenn Randers-Pehrson * Written by Mans Rullgard, 2011. - * Last changed in libpng 1.6.31 [July 27, 2017] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer diff --git a/thirdparty/libpng/arm/filter_neon_intrinsics.c b/thirdparty/libpng/arm/filter_neon_intrinsics.c index ea7e356bcc..553c0be21c 100644 --- a/thirdparty/libpng/arm/filter_neon_intrinsics.c +++ b/thirdparty/libpng/arm/filter_neon_intrinsics.c @@ -1,12 +1,11 @@ /* filter_neon_intrinsics.c - NEON optimised filter functions * + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 2014,2016 Glenn Randers-Pehrson * Written by James Yu <james.yu at linaro.org>, October 2013. * Based on filter_neon.S, written by Mans Rullgard, 2011. * - * Last changed in libpng 1.6.22 [May 26, 2016] - * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h @@ -19,7 +18,11 @@ /* This code requires -mfpu=neon on the command line: */ #if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */ -#include <arm_neon.h> +#if defined(_MSC_VER) && defined(_M_ARM64) +# include <arm64_neon.h> +#else +# include <arm_neon.h> +#endif /* libpng row pointers are not necessarily aligned to any particular boundary, * however this code will only work with appropriate alignment. arm/arm_init.c @@ -33,6 +36,11 @@ * 'type'. This is written this way just to hide the GCC strict aliasing * warning; note that the code is safe because there never is an alias between * the input and output pointers. + * + * When compiling with MSVC ARM64, the png_ldr macro can't be passed directly + * to vst4_lane_u32, because of an internal compiler error inside MSVC. + * To avoid this compiler bug, we use a temporary variable (vdest_val) to store + * the result of png_ldr. */ #define png_ldr(type,pointer)\ (temp_pointer = png_ptr(type,pointer), *temp_pointer) @@ -125,12 +133,15 @@ png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row, uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp); uint8x8x4_t vrp = *vrpt; uint32x2x4_t *temp_pointer; + uint32x2x4_t vdest_val; vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]); vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]); vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]); vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]); - vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); + + vdest_val = png_ldr(uint32x2x4_t, &vdest); + vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0); } PNG_UNUSED(prev_row) @@ -223,6 +234,7 @@ png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row, uint8x8x4_t *vrpt, *vppt; uint8x8x4_t vrp, vpp; uint32x2x4_t *temp_pointer; + uint32x2x4_t vdest_val; vtmp = vld4_u32(png_ptr(uint32_t,rp)); vrpt = png_ptr(uint8x8x4_t,&vtmp); @@ -240,7 +252,8 @@ png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row, vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]); vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]); - vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); + vdest_val = png_ldr(uint32x2x4_t, &vdest); + vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0); } } @@ -359,6 +372,7 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row, uint8x8x4_t *vrpt, *vppt; uint8x8x4_t vrp, vpp; uint32x2x4_t *temp_pointer; + uint32x2x4_t vdest_val; vtmp = vld4_u32(png_ptr(uint32_t,rp)); vrpt = png_ptr(uint8x8x4_t,&vtmp); @@ -378,7 +392,8 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row, vlast = vpp.val[3]; - vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); + vdest_val = png_ldr(uint32x2x4_t, &vdest); + vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0); } } diff --git a/thirdparty/libpng/arm/palette_neon_intrinsics.c b/thirdparty/libpng/arm/palette_neon_intrinsics.c new file mode 100644 index 0000000000..b4d1fd2abf --- /dev/null +++ b/thirdparty/libpng/arm/palette_neon_intrinsics.c @@ -0,0 +1,149 @@ + +/* palette_neon_intrinsics.c - NEON optimised palette expansion functions + * + * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 2017-2018 Arm Holdings. All rights reserved. + * Written by Richard Townsend <Richard.Townsend@arm.com>, February 2017. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "../pngpriv.h" + +#if PNG_ARM_NEON_IMPLEMENTATION == 1 + +#if defined(_MSC_VER) && defined(_M_ARM64) +# include <arm64_neon.h> +#else +# include <arm_neon.h> +#endif + +/* Build an RGBA8 palette from the separate RGB and alpha palettes. */ +void +png_riffle_palette_neon(png_structrp png_ptr) +{ + png_const_colorp palette = png_ptr->palette; + png_bytep riffled_palette = png_ptr->riffled_palette; + png_const_bytep trans_alpha = png_ptr->trans_alpha; + int num_trans = png_ptr->num_trans; + int i; + + png_debug(1, "in png_riffle_palette_neon"); + + /* Initially black, opaque. */ + uint8x16x4_t w = {{ + vdupq_n_u8(0x00), + vdupq_n_u8(0x00), + vdupq_n_u8(0x00), + vdupq_n_u8(0xff), + }}; + + /* First, riffle the RGB colours into an RGBA8 palette. + * The alpha component is set to opaque for now. + */ + for (i = 0; i < 256; i += 16) + { + uint8x16x3_t v = vld3q_u8((png_const_bytep)(palette + i)); + w.val[0] = v.val[0]; + w.val[1] = v.val[1]; + w.val[2] = v.val[2]; + vst4q_u8(riffled_palette + (i << 2), w); + } + + /* Fix up the missing transparency values. */ + for (i = 0; i < num_trans; i++) + riffled_palette[(i << 2) + 3] = trans_alpha[i]; +} + +/* Expands a palettized row into RGBA8. */ +int +png_do_expand_palette_rgba8_neon(png_structrp png_ptr, png_row_infop row_info, + png_const_bytep row, png_bytepp ssp, png_bytepp ddp) +{ + png_uint_32 row_width = row_info->width; + const png_uint_32 *riffled_palette = + (const png_uint_32 *)png_ptr->riffled_palette; + const png_int_32 pixels_per_chunk = 4; + int i; + + png_debug(1, "in png_do_expand_palette_rgba8_neon"); + + if (row_width < pixels_per_chunk) + return 0; + + /* This function originally gets the last byte of the output row. + * The NEON part writes forward from a given position, so we have + * to seek this back by 4 pixels x 4 bytes. + */ + *ddp = *ddp - ((pixels_per_chunk * sizeof(png_uint_32)) - 1); + + for (i = 0; i < row_width; i += pixels_per_chunk) + { + uint32x4_t cur; + png_bytep sp = *ssp - i, dp = *ddp - (i << 2); + cur = vld1q_dup_u32 (riffled_palette + *(sp - 3)); + cur = vld1q_lane_u32(riffled_palette + *(sp - 2), cur, 1); + cur = vld1q_lane_u32(riffled_palette + *(sp - 1), cur, 2); + cur = vld1q_lane_u32(riffled_palette + *(sp - 0), cur, 3); + vst1q_u32((void *)dp, cur); + } + if (i != row_width) + { + /* Remove the amount that wasn't processed. */ + i -= pixels_per_chunk; + } + + /* Decrement output pointers. */ + *ssp = *ssp - i; + *ddp = *ddp - (i << 2); + return i; +} + +/* Expands a palettized row into RGB8. */ +int +png_do_expand_palette_rgb8_neon(png_structrp png_ptr, png_row_infop row_info, + png_const_bytep row, png_bytepp ssp, png_bytepp ddp) +{ + png_uint_32 row_width = row_info->width; + png_const_bytep palette = (png_const_bytep)png_ptr->palette; + const png_uint_32 pixels_per_chunk = 8; + int i; + + png_debug(1, "in png_do_expand_palette_rgb8_neon"); + + if (row_width <= pixels_per_chunk) + return 0; + + /* Seeking this back by 8 pixels x 3 bytes. */ + *ddp = *ddp - ((pixels_per_chunk * sizeof(png_color)) - 1); + + for (i = 0; i < row_width; i += pixels_per_chunk) + { + uint8x8x3_t cur; + png_bytep sp = *ssp - i, dp = *ddp - ((i << 1) + i); + cur = vld3_dup_u8(palette + sizeof(png_color) * (*(sp - 7))); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 6)), cur, 1); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 5)), cur, 2); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 4)), cur, 3); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 3)), cur, 4); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 2)), cur, 5); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 1)), cur, 6); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 0)), cur, 7); + vst3_u8((void *)dp, cur); + } + + if (i != row_width) + { + /* Remove the amount that wasn't processed. */ + i -= pixels_per_chunk; + } + + /* Decrement output pointers. */ + *ssp = *ssp - i; + *ddp = *ddp - ((i << 1) + i); + return i; +} + +#endif /* PNG_ARM_NEON_IMPLEMENTATION */ |