|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* filter_neon_intrinsics.c - NEON optimised filter functions
|
|
fukasawa |
e60969 |
*
|
|
fukasawa |
e60969 |
* Copyright (c) 2014 Glenn Randers-Pehrson
|
|
fukasawa |
e60969 |
* Written by James Yu <james.yu at="" linaro.org="">, October 2013.</james.yu>
|
|
fukasawa |
e60969 |
* Based on filter_neon.S, written by Mans Rullgard, 2011.
|
|
fukasawa |
e60969 |
*
|
|
fukasawa |
e60969 |
* Last changed in libpng 1.6.16 [December 22, 2014]
|
|
fukasawa |
e60969 |
*
|
|
fukasawa |
e60969 |
* This code is released under the libpng license.
|
|
fukasawa |
e60969 |
* For conditions of distribution and use, see the disclaimer
|
|
fukasawa |
e60969 |
* and license in png.h
|
|
fukasawa |
e60969 |
*/
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
#include "../pngpriv.h"
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
#ifdef PNG_READ_SUPPORTED
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* This code requires -mfpu=neon on the command line: */
|
|
fukasawa |
e60969 |
#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
#include <arm_neon.h></arm_neon.h>
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* libpng row pointers are not necessarily aligned to any particular boundary,
|
|
fukasawa |
e60969 |
* however this code will only work with appropriate alignment. arm/arm_init.c
|
|
fukasawa |
e60969 |
* checks for this (and will not compile unless it is done). This code uses
|
|
fukasawa |
e60969 |
* variants of png_aligncast to avoid compiler warnings.
|
|
fukasawa |
e60969 |
*/
|
|
fukasawa |
e60969 |
#define png_ptr(type,pointer) png_aligncast(type *,pointer)
|
|
fukasawa |
e60969 |
#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer)
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* The following relies on a variable 'temp_pointer' being declared with type
|
|
fukasawa |
e60969 |
* 'type'. This is written this way just to hide the GCC strict aliasing
|
|
fukasawa |
e60969 |
* warning; note that the code is safe because there never is an alias between
|
|
fukasawa |
e60969 |
* the input and output pointers.
|
|
fukasawa |
e60969 |
*/
|
|
fukasawa |
e60969 |
#define png_ldr(type,pointer)\
|
|
fukasawa |
e60969 |
(temp_pointer = png_ptr(type,pointer), *temp_pointer)
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
#if PNG_ARM_NEON_OPT > 0
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
void
|
|
fukasawa |
e60969 |
png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
|
|
fukasawa |
e60969 |
png_const_bytep prev_row)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
png_bytep rp = row;
|
|
fukasawa |
e60969 |
png_bytep rp_stop = row + row_info->rowbytes;
|
|
fukasawa |
e60969 |
png_const_bytep pp = prev_row;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
for (; rp < rp_stop; rp += 16, pp += 16)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
uint8x16_t qrp, qpp;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
qrp = vld1q_u8(rp);
|
|
fukasawa |
e60969 |
qpp = vld1q_u8(pp);
|
|
fukasawa |
e60969 |
qrp = vaddq_u8(qrp, qpp);
|
|
fukasawa |
e60969 |
vst1q_u8(rp, qrp);
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
void
|
|
fukasawa |
e60969 |
png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
|
|
fukasawa |
e60969 |
png_const_bytep prev_row)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
png_bytep rp = row;
|
|
fukasawa |
e60969 |
png_bytep rp_stop = row + row_info->rowbytes;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
uint8x16_t vtmp = vld1q_u8(rp);
|
|
fukasawa |
e60969 |
uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp);
|
|
fukasawa |
e60969 |
uint8x8x2_t vrp = *vrpt;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
uint8x8x4_t vdest;
|
|
fukasawa |
e60969 |
vdest.val[3] = vdup_n_u8(0);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
for (; rp < rp_stop;)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
uint8x8_t vtmp1, vtmp2;
|
|
fukasawa |
e60969 |
uint32x2_t *temp_pointer;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
|
fukasawa |
e60969 |
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
|
|
fukasawa |
e60969 |
vtmp2 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
|
fukasawa |
e60969 |
vdest.val[1] = vadd_u8(vdest.val[0], vtmp1);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
|
fukasawa |
e60969 |
vdest.val[2] = vadd_u8(vdest.val[1], vtmp2);
|
|
fukasawa |
e60969 |
vdest.val[3] = vadd_u8(vdest.val[2], vtmp1);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp = vld1q_u8(rp + 12);
|
|
fukasawa |
e60969 |
vrpt = png_ptr(uint8x8x2_t, &vtmp);
|
|
fukasawa |
e60969 |
vrp = *vrpt;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
|
fukasawa |
e60969 |
rp += 3;
|
|
fukasawa |
e60969 |
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
|
fukasawa |
e60969 |
rp += 3;
|
|
fukasawa |
e60969 |
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
|
fukasawa |
e60969 |
rp += 3;
|
|
fukasawa |
e60969 |
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
|
fukasawa |
e60969 |
rp += 3;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
PNG_UNUSED(prev_row)
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
void
|
|
fukasawa |
e60969 |
png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
|
|
fukasawa |
e60969 |
png_const_bytep prev_row)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
png_bytep rp = row;
|
|
fukasawa |
e60969 |
png_bytep rp_stop = row + row_info->rowbytes;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
uint8x8x4_t vdest;
|
|
fukasawa |
e60969 |
vdest.val[3] = vdup_n_u8(0);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
for (; rp < rp_stop; rp += 16)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
uint32x2x4_t vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
|
fukasawa |
e60969 |
uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
|
fukasawa |
e60969 |
uint8x8x4_t vrp = *vrpt;
|
|
fukasawa |
e60969 |
uint32x2x4_t *temp_pointer;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
|
|
fukasawa |
e60969 |
vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]);
|
|
fukasawa |
e60969 |
vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]);
|
|
fukasawa |
e60969 |
vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]);
|
|
fukasawa |
e60969 |
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
PNG_UNUSED(prev_row)
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
void
|
|
fukasawa |
e60969 |
png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
|
|
fukasawa |
e60969 |
png_const_bytep prev_row)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
png_bytep rp = row;
|
|
fukasawa |
e60969 |
png_const_bytep pp = prev_row;
|
|
fukasawa |
e60969 |
png_bytep rp_stop = row + row_info->rowbytes;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
uint8x16_t vtmp;
|
|
fukasawa |
e60969 |
uint8x8x2_t *vrpt;
|
|
fukasawa |
e60969 |
uint8x8x2_t vrp;
|
|
fukasawa |
e60969 |
uint8x8x4_t vdest;
|
|
fukasawa |
e60969 |
vdest.val[3] = vdup_n_u8(0);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp = vld1q_u8(rp);
|
|
fukasawa |
e60969 |
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
|
fukasawa |
e60969 |
vrp = *vrpt;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
for (; rp < rp_stop; pp += 12)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
uint8x8_t vtmp1, vtmp2, vtmp3;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
uint8x8x2_t *vppt;
|
|
fukasawa |
e60969 |
uint8x8x2_t vpp;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
uint32x2_t *temp_pointer;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp = vld1q_u8(pp);
|
|
fukasawa |
e60969 |
vppt = png_ptr(uint8x8x2_t,&vtmp);
|
|
fukasawa |
e60969 |
vpp = *vppt;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
|
fukasawa |
e60969 |
vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
|
|
fukasawa |
e60969 |
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
|
|
fukasawa |
e60969 |
vtmp3 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
|
fukasawa |
e60969 |
vdest.val[1] = vhadd_u8(vdest.val[0], vtmp2);
|
|
fukasawa |
e60969 |
vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 6);
|
|
fukasawa |
e60969 |
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp = vld1q_u8(rp + 12);
|
|
fukasawa |
e60969 |
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
|
fukasawa |
e60969 |
vrp = *vrpt;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vdest.val[2] = vhadd_u8(vdest.val[1], vtmp2);
|
|
fukasawa |
e60969 |
vdest.val[2] = vadd_u8(vdest.val[2], vtmp3);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vdest.val[3] = vhadd_u8(vdest.val[2], vtmp2);
|
|
fukasawa |
e60969 |
vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
|
fukasawa |
e60969 |
rp += 3;
|
|
fukasawa |
e60969 |
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
|
fukasawa |
e60969 |
rp += 3;
|
|
fukasawa |
e60969 |
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
|
fukasawa |
e60969 |
rp += 3;
|
|
fukasawa |
e60969 |
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
|
fukasawa |
e60969 |
rp += 3;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
void
|
|
fukasawa |
e60969 |
png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
|
|
fukasawa |
e60969 |
png_const_bytep prev_row)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
png_bytep rp = row;
|
|
fukasawa |
e60969 |
png_bytep rp_stop = row + row_info->rowbytes;
|
|
fukasawa |
e60969 |
png_const_bytep pp = prev_row;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
uint8x8x4_t vdest;
|
|
fukasawa |
e60969 |
vdest.val[3] = vdup_n_u8(0);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
for (; rp < rp_stop; rp += 16, pp += 16)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
uint32x2x4_t vtmp;
|
|
fukasawa |
e60969 |
uint8x8x4_t *vrpt, *vppt;
|
|
fukasawa |
e60969 |
uint8x8x4_t vrp, vpp;
|
|
fukasawa |
e60969 |
uint32x2x4_t *temp_pointer;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
|
fukasawa |
e60969 |
vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
|
fukasawa |
e60969 |
vrp = *vrpt;
|
|
fukasawa |
e60969 |
vtmp = vld4_u32(png_ptrc(uint32_t,pp));
|
|
fukasawa |
e60969 |
vppt = png_ptr(uint8x8x4_t,&vtmp);
|
|
fukasawa |
e60969 |
vpp = *vppt;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
|
|
fukasawa |
e60969 |
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
|
fukasawa |
e60969 |
vdest.val[1] = vhadd_u8(vdest.val[0], vpp.val[1]);
|
|
fukasawa |
e60969 |
vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
|
|
fukasawa |
e60969 |
vdest.val[2] = vhadd_u8(vdest.val[1], vpp.val[2]);
|
|
fukasawa |
e60969 |
vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
|
|
fukasawa |
e60969 |
vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]);
|
|
fukasawa |
e60969 |
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
static uint8x8_t
|
|
fukasawa |
e60969 |
paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
uint8x8_t d, e;
|
|
fukasawa |
e60969 |
uint16x8_t p1, pa, pb, pc;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
p1 = vaddl_u8(a, b); /* a + b */
|
|
fukasawa |
e60969 |
pc = vaddl_u8(c, c); /* c * 2 */
|
|
fukasawa |
e60969 |
pa = vabdl_u8(b, c); /* pa */
|
|
fukasawa |
e60969 |
pb = vabdl_u8(a, c); /* pb */
|
|
fukasawa |
e60969 |
pc = vabdq_u16(p1, pc); /* pc */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
p1 = vcleq_u16(pa, pb); /* pa <= pb */
|
|
fukasawa |
e60969 |
pa = vcleq_u16(pa, pc); /* pa <= pc */
|
|
fukasawa |
e60969 |
pb = vcleq_u16(pb, pc); /* pb <= pc */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
p1 = vandq_u16(p1, pa); /* pa <= pb && pa <= pc */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
d = vmovn_u16(pb);
|
|
fukasawa |
e60969 |
e = vmovn_u16(p1);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
d = vbsl_u8(d, b, c);
|
|
fukasawa |
e60969 |
e = vbsl_u8(e, a, d);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
return e;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
void
|
|
fukasawa |
e60969 |
png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
|
|
fukasawa |
e60969 |
png_const_bytep prev_row)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
png_bytep rp = row;
|
|
fukasawa |
e60969 |
png_const_bytep pp = prev_row;
|
|
fukasawa |
e60969 |
png_bytep rp_stop = row + row_info->rowbytes;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
uint8x16_t vtmp;
|
|
fukasawa |
e60969 |
uint8x8x2_t *vrpt;
|
|
fukasawa |
e60969 |
uint8x8x2_t vrp;
|
|
fukasawa |
e60969 |
uint8x8_t vlast = vdup_n_u8(0);
|
|
fukasawa |
e60969 |
uint8x8x4_t vdest;
|
|
fukasawa |
e60969 |
vdest.val[3] = vdup_n_u8(0);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp = vld1q_u8(rp);
|
|
fukasawa |
e60969 |
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
|
fukasawa |
e60969 |
vrp = *vrpt;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
for (; rp < rp_stop; pp += 12)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
uint8x8x2_t *vppt;
|
|
fukasawa |
e60969 |
uint8x8x2_t vpp;
|
|
fukasawa |
e60969 |
uint8x8_t vtmp1, vtmp2, vtmp3;
|
|
fukasawa |
e60969 |
uint32x2_t *temp_pointer;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp = vld1q_u8(pp);
|
|
fukasawa |
e60969 |
vppt = png_ptr(uint8x8x2_t,&vtmp);
|
|
fukasawa |
e60969 |
vpp = *vppt;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
|
|
fukasawa |
e60969 |
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
|
fukasawa |
e60969 |
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
|
|
fukasawa |
e60969 |
vdest.val[1] = paeth(vdest.val[0], vtmp2, vpp.val[0]);
|
|
fukasawa |
e60969 |
vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
|
fukasawa |
e60969 |
vtmp3 = vext_u8(vpp.val[0], vpp.val[1], 6);
|
|
fukasawa |
e60969 |
vdest.val[2] = paeth(vdest.val[1], vtmp3, vtmp2);
|
|
fukasawa |
e60969 |
vdest.val[2] = vadd_u8(vdest.val[2], vtmp1);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
|
fukasawa |
e60969 |
vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp = vld1q_u8(rp + 12);
|
|
fukasawa |
e60969 |
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
|
fukasawa |
e60969 |
vrp = *vrpt;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vdest.val[3] = paeth(vdest.val[2], vtmp2, vtmp3);
|
|
fukasawa |
e60969 |
vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vlast = vtmp2;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
|
fukasawa |
e60969 |
rp += 3;
|
|
fukasawa |
e60969 |
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
|
fukasawa |
e60969 |
rp += 3;
|
|
fukasawa |
e60969 |
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
|
fukasawa |
e60969 |
rp += 3;
|
|
fukasawa |
e60969 |
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
|
fukasawa |
e60969 |
rp += 3;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
void
|
|
fukasawa |
e60969 |
png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
|
|
fukasawa |
e60969 |
png_const_bytep prev_row)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
png_bytep rp = row;
|
|
fukasawa |
e60969 |
png_bytep rp_stop = row + row_info->rowbytes;
|
|
fukasawa |
e60969 |
png_const_bytep pp = prev_row;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
uint8x8_t vlast = vdup_n_u8(0);
|
|
fukasawa |
e60969 |
uint8x8x4_t vdest;
|
|
fukasawa |
e60969 |
vdest.val[3] = vdup_n_u8(0);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
for (; rp < rp_stop; rp += 16, pp += 16)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
uint32x2x4_t vtmp;
|
|
fukasawa |
e60969 |
uint8x8x4_t *vrpt, *vppt;
|
|
fukasawa |
e60969 |
uint8x8x4_t vrp, vpp;
|
|
fukasawa |
e60969 |
uint32x2x4_t *temp_pointer;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
|
fukasawa |
e60969 |
vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
|
fukasawa |
e60969 |
vrp = *vrpt;
|
|
fukasawa |
e60969 |
vtmp = vld4_u32(png_ptrc(uint32_t,pp));
|
|
fukasawa |
e60969 |
vppt = png_ptr(uint8x8x4_t,&vtmp);
|
|
fukasawa |
e60969 |
vpp = *vppt;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
|
|
fukasawa |
e60969 |
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
|
fukasawa |
e60969 |
vdest.val[1] = paeth(vdest.val[0], vpp.val[1], vpp.val[0]);
|
|
fukasawa |
e60969 |
vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
|
|
fukasawa |
e60969 |
vdest.val[2] = paeth(vdest.val[1], vpp.val[2], vpp.val[1]);
|
|
fukasawa |
e60969 |
vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
|
|
fukasawa |
e60969 |
vdest.val[3] = paeth(vdest.val[2], vpp.val[3], vpp.val[2]);
|
|
fukasawa |
e60969 |
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vlast = vpp.val[3];
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
#endif /* PNG_ARM_NEON_OPT > 0 */
|
|
fukasawa |
e60969 |
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 1 (intrinsics) */
|
|
fukasawa |
e60969 |
#endif /* READ */
|