/* arm_init.c - NEON optimised filter functions * * Copyright (c) 2012 Glenn Randers-Pehrson * Written by Mans Rullgard, 2011. * Last changed in libpng 1.5.14 [(PENDING RELEASE)] * * 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" /* __arm__ is defined by GCC, MSVC defines _M_ARM to the ARM version number */ #if defined __linux__ && defined __arm__ #include #include #include static int png_have_hwcap(unsigned cap) { FILE *f = fopen("/proc/self/auxv", "r"); Elf32_auxv_t aux; int have_cap = 0; if (!f) return 0; while (fread(&aux, sizeof(aux), 1, f) > 0) { if (aux.a_type == AT_HWCAP && aux.a_un.a_val & cap) { have_cap = 1; break; } } fclose(f); return have_cap; } #endif /* __linux__ && __arm__ */ void png_init_filter_functions_neon(png_structp pp, unsigned int bpp) { #ifdef __arm__ #ifdef __linux__ if (!png_have_hwcap(HWCAP_NEON)) return; #endif /* IMPORTANT: any new external functions used here must be declared using * PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the * 'prefix' option to configure works: * * ./configure --with-libpng-prefix=foobar_ * * Verify you have got this right by running the above command, doing a build * and examining pngprefix.h; it must contain a #define for every external * function you add. (Notice that this happens automatically for the * initialization function.) */ pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon; if (bpp == 3) { pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon; pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon; pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_neon; } else if (bpp == 4) { pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon; pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon; pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_neon; } #else PNG_UNUSED(pp) PNG_UNUSED(bpp) #endif }