/* Compile time options.
 * =====================
 * In a multi-arch build the compiler may compile the code several times for the
 * same object module, producing different binaries for different architectures.
 * When this happens configure-time setting of the target host options cannot be
 * done.  An example is iOS vs Android compilation of ARM NEON support.
 *
 * NOTE: symbol prefixing does not pass $(CFLAGS) to the preprocessor, because
 * this is not possible with certain compilers (Oracle SUN OS CC), as a result
 * it is necessary to ensure that all extern functions that *might* be used
 * regardless of $(CFLAGS) get declared in this file.  The test on __ARM_NEON
 * below is one example of this behavior because it is controlled by the
 * presence or not of -mfpu=neon on the GCC command line, it is possible to do
 * this in $(CC), e.g. "CC=gcc -mfpu=neon", but people who build libpng rarely
 * do this.
 */
#ifndef PNG_ARM_NEON_OPT
   /* ARM NEON optimizations are being controlled by the compiler settings,
    * typically the target FPU.  If the FPU supports NEON instructions then the
    * compiler will define __ARM_NEON and we can rely unconditionally on NEON
    * instructions not crashing, otherwise we must disable use of NEON
    * instructions.
    *
    * NOTE: at present these optimizations depend on 'ALIGNED_MEMORY', so they
    * can only be turned on automatically if that is supported too.  If
    * PNG_ARM_NEON_OPT is set in CPPFLAGS (to >0) then arm/arm_init.c will fail
    * to compile with an appropriate #error if ALIGNED_MEMORY has been turned
    * off.
    *
    * Note that older versions of GCC defined __ARM_NEON__; this is no longer
    * supported.  Also 32-bit ARM versions of GCC required the NEON FPU mode to
    * be turned on explicitly on the command line.  If this is not done (on
    * 32-bit ARM) NEON code will not be included.
    *
    * To disable ARM_NEON optimizations entirely, and skip compiling the
    * associated assembler code, pass --enable-arm-neon=no to configure
    * or put -DPNG_ARM_NEON_OPT=0 in CPPFLAGS.
    */
#  if defined(__ARM_NEON) && defined(PNG_ALIGNED_MEMORY_SUPPORTED)
#     define PNG_ARM_NEON_OPT 2
#  else
#     define PNG_ARM_NEON_OPT 0
#  endif
#endif

#if PNG_ARM_NEON_OPT > 0
   /* NEON optimizations are to be at least considered by libpng, so enable the
    * callbacks to do this.
    */
#  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon

   /* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used
    * if possible - if __ARM_NEON is set and the compiler version is not known
    * to be broken.  This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can
    * be:
    *
    *    1  The intrinsics code (the default with __ARM_NEON)
    *    2  The hand coded assembler (the default without __ARM_NEON)
    *
    * It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however
    * this is *NOT* supported and may cease to work even after a minor revision
    * to libpng.  It *is* valid to do this for testing purposes, e.g. speed
    * testing or a new compiler, but the results should be communicated to the
    * libpng implementation list for incorporation in the next minor release.
    */
#  ifndef PNG_ARM_NEON_IMPLEMENTATION
#     ifdef __ARM_NEON
#        if defined(__clang__)
            /* At present it is unknown by the libpng developers which versions
             * of clang support the intrinsics, however some or perhaps all
             * versions do not work with the assembler so this may be
             * irrelevant, so just use the default (do nothing here.)
             */
#        elif defined(__GNUC__)
            /* GCC 4.5.4 NEON support is known to be broken.  4.6.3 is known to
             * work, so if this *is* GCC, or G++, look for a version >4.5
             */
#           if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
#              define PNG_ARM_NEON_IMPLEMENTATION 2
#           endif /* no GNUC support */
#        endif /* __GNUC__ */
#     else /* !defined __ARM_NEON */
         /* The 'intrinsics' code simply won't compile without compiler support
          * and that support switches on __ARM_NEON, so use the assembler:
          */
#        define PNG_ARM_NEON_IMPLEMENTATION 2
#     endif /* __ARM_NEON */
#  endif /* !defined PNG_ARM_NEON_IMPLEMENTATION */

#  ifndef PNG_ARM_NEON_IMPLEMENTATION
      /* Use the intrinsics code by default. */
#     define PNG_ARM_NEON_IMPLEMENTATION 1
#  endif
#endif /* PNG_ARM_NEON_OPT > 0 */

#ifdef PNG_SET_OPTION_SUPPORTED
#ifdef PNG_ARM_NEON_API_SUPPORTED
#  define PNG_ARM_NEON   0 /* HARDWARE: ARM Neon SIMD instructions supported */
#endif
#endif /* SET_OPTION */

#if PNG_ARM_NEON_OPT > 0
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,
   (png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
    png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,
   (png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
    png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_neon,
   (png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
    png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_neon,
   (png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
    png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,
   (png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
    png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,
   (png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
    png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,
   (png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
    png_const_bytep prev_row),PNG_EMPTY);
#endif
