Skip to content

Commit

Permalink
HARDWARE: remove build system requirements
Browse files Browse the repository at this point in the history
This introduces png_hardware.c which is pretty much a copy of pngpriv.h
but then moves the hardware-specific parts to the arch/arch_init.c
files.

The change is extensive by line numbers but quite simple by effect;
since we have established that all the hardware-specific files can be
compiled on all platforms it is no longer necessary to have any hardware
specific tests in the main part of libpng.

This was easy for the filter code but the palette code requires work
within the main body of libpng, for this reason this is a
work-in-progress and therefore a draft pull request.  Some amount of
testing is important at this point as my cross-platform tests are
limited.  Nevertheless this can be included in a 1.8 alpha; it meets all
the requirements of an alpha, it just needs a little review from parties
who can do the cross platform stuff on platforms other than intel and
arm.

Signed-off-by: John Bowler <jbowler@acm.org>
  • Loading branch information
jbowler committed Sep 7, 2024
1 parent d3e103e commit 20ced64
Show file tree
Hide file tree
Showing 23 changed files with 487 additions and 3,528 deletions.
56 changes: 1 addition & 55 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,56 +134,6 @@ else()
# libm is not available or not needed.
endif()

if(PNG_HARDWARE_OPTIMIZATIONS)

# Set definitions and sources for ARM.
set(libpng_arm_sources
arm/arm_init.c
arm/filter_neon_intrinsics.c
arm/palette_neon_intrinsics.c)

# Set definitions and sources for PowerPC.
set(libpng_powerpc_sources
powerpc/powerpc_init.c
powerpc/filter_vsx_intrinsics.c)

# Set definitions and sources for Intel.
set(libpng_intel_sources
intel/intel_init.c
intel/filter_sse2_intrinsics.c)

# Set definitions and sources for MIPS.
set(libpng_mips_sources
mips/mips_init.c
mips/filter_msa_intrinsics.c
mips/filter_mmi_inline_assembly.c)

# Set definitions and sources for LoongArch.
set(libpng_loongarch_sources
loongarch/loongarch_lsx_init.c
loongarch/filter_lsx_intrinsics.c)
include(CheckCCompilerFlag)
check_c_compiler_flag("-mlsx" COMPILER_SUPPORTS_LSX)
if(COMPILER_SUPPORTS_LSX)
set_source_files_properties(${libpng_loongarch_sources}
PROPERTIES
COMPILE_FLAGS "-mlsx")
endif()

else(PNG_HARDWARE_OPTIMIZATIONS)

# Disable opt for all arches
add_definitions(
-DPNG_ARM_NEON_OPT=0
-DPNG_ARM_NEON_OPT=0
-DPNG_POWERPC_VSX_OPT=0
-DPNG_INTEL_SSE_OPT=0
-DPNG_MIPS_MSA_OPT=0
-DPNG_LOONGARCH_LSX_OPT=0
)

endif(PNG_HARDWARE_OPTIMIZATIONS)

option(ld-version-script "Enable linker version script" ON)
if(ld-version-script AND NOT ANDROID AND NOT APPLE)
# Check if LD supports linker scripts.
Expand Down Expand Up @@ -496,11 +446,7 @@ set(libpng_sources
pngwrite.c
pngwtran.c
pngwutil.c
${libpng_arm_sources}
${libpng_intel_sources}
${libpng_mips_sources}
${libpng_powerpc_sources}
${libpng_loongarch_sources}
pnghardware.c
)
set(pngtest_sources
pngtest.c
Expand Down
42 changes: 1 addition & 41 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -104,45 +104,9 @@ lib_LTLIBRARIES=libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngerror.c\
pngget.c pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c pngrutil.c\
pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\
pnghardware.c\
png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h pngusr.dfa

if PNG_ARM_NEON
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += arm/arm_init.c\
arm/filter_neon_intrinsics.c \
arm/palette_neon_intrinsics.c
endif

if PNG_MIPS_MSA
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += mips/mips_init.c\
mips/filter_msa_intrinsics.c
endif

if PNG_MIPS_MMI
if !PNG_MIPS_MSA
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += mips/mips_init.c
endif
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += mips/filter_mmi_inline_assembly.c
endif

if PNG_INTEL_SSE
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += intel/intel_init.c\
intel/filter_sse2_intrinsics.c
endif

if PNG_POWERPC_VSX
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += powerpc/powerpc_init.c\
powerpc/filter_vsx_intrinsics.c
endif

if PNG_LOONGARCH_LSX
noinst_LTLIBRARIES= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx.la
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx_la_SOURCES = loongarch/loongarch_lsx_init.c\
loongarch/filter_lsx_intrinsics.c
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx_la_CFLAGS = -mlsx
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LIBADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx.la
# libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx.la
endif

nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h

libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS = -no-undefined -export-dynamic \
Expand All @@ -163,10 +127,6 @@ else
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.sym
endif

if PNG_LOONGARCH_LSX
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES += libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx.la
endif

#distribute headers in /usr/include/libpng/*
pkgincludedir= $(includedir)/$(PNGLIB_BASENAME)
pkginclude_HEADERS= png.h pngconf.h
Expand Down
138 changes: 39 additions & 99 deletions arm/arm_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,113 +9,30 @@
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
#if (defined(__ARM_NEON__) || defined(__ARM_NEON)) &&\
defined(PNG_ALIGNED_MEMORY_SUPPORTED) && defined(PNG_READ_SUPPORTED)

/* This module requires POSIX 1003.1 functions. */
#define _POSIX_SOURCE 1
#define png_hardware_impl "arm-neon"

#include "../pngpriv.h"

#ifdef PNG_READ_SUPPORTED

#if PNG_ARM_NEON_OPT > 0
#ifdef PNG_ARM_NEON_CHECK_SUPPORTED /* Do run-time checks */
/* WARNING: it is strongly recommended that you do not build libpng with
* run-time checks for CPU features if at all possible. In the case of the ARM
* NEON instructions there is no processor-specific way of detecting the
* presence of the required support, therefore run-time detection is extremely
* OS specific.
*
* You may set the macro PNG_ARM_NEON_FILE to the file name of file containing
* a fragment of C source code which defines the png_have_neon function. There
* are a number of implementations in contrib/arm-neon, but the only one that
* has partial support is contrib/arm-neon/linux.c - a generic Linux
* implementation which reads /proc/cpufino.
*/
#include <signal.h> /* for sig_atomic_t */

#ifndef PNG_ARM_NEON_FILE
# if defined(__aarch64__) || defined(_M_ARM64)
/* ARM Neon is expected to be unconditionally available on ARM64. */
# error "PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on ARM64"
# elif defined(__ARM_NEON__) || defined(__ARM_NEON)
/* ARM Neon is expected to be available on the target CPU architecture. */
# error "PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on this CPU arch"
# elif defined(__linux__)
# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c"
# else
# error "No support for run-time ARM Neon checking; use compile-time options"
# endif
#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64)
# include <arm64_neon.h>
#else
# include <arm_neon.h>
#endif

static int png_have_neon(png_structp png_ptr);
#ifdef PNG_ARM_NEON_FILE
# include PNG_ARM_NEON_FILE
#endif
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
/* Obtain the definitions of the actual filter functions: */
#include "filter_neon_intrinsics.c"

#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
#endif

void
static void
png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
{
/* The switch statement is compiled in for ARM_NEON_API, the call to
* png_have_neon is compiled in for ARM_NEON_CHECK. If both are defined
* the check is only performed if the API has not set the NEON option on
* or off explicitly. In this case the check controls what happens.
*
* If the CHECK is not compiled in and the option is UNSET the behavior prior
* to 1.6.7 was to use the NEON code - this was a bug caused by having the
* wrong order of the 'ON' and 'default' cases. UNSET now defaults to OFF,
* as documented in png.h
*/
png_debug(1, "in png_init_filter_functions_neon");
#ifdef PNG_ARM_NEON_API_SUPPORTED
switch ((pp->options >> PNG_ARM_NEON) & 3)
{
case PNG_OPTION_UNSET:
/* Allow the run-time check to execute if it has been enabled -
* thus both API and CHECK can be turned on. If it isn't supported
* this case will fall through to the 'default' below, which just
* returns.
*/
#endif /* PNG_ARM_NEON_API_SUPPORTED */
#ifdef PNG_ARM_NEON_CHECK_SUPPORTED
{
static volatile sig_atomic_t no_neon = -1; /* not checked */

if (no_neon < 0)
no_neon = !png_have_neon(pp);

if (no_neon)
return;
}
#ifdef PNG_ARM_NEON_API_SUPPORTED
break;
#endif
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */

#ifdef PNG_ARM_NEON_API_SUPPORTED
default: /* OFF or INVALID */
return;

case PNG_OPTION_ON:
/* Option turned on */
break;
}
#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_
/* IMPORTANT: DO NOT DEFINE EXTERNAL FUNCTIONS HERE
*
* 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.)
* This is because external functions must be declared with
* PNG_INTERNAL_FUNCTION in pngpriv.h; without this the PNG_PREFIX option to
* the build will not work (it will not know about these symbols).
*/
pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;

Expand All @@ -135,5 +52,28 @@ png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
png_read_filter_row_paeth4_neon;
}
}
#endif /* PNG_ARM_NEON_OPT > 0 */
#endif /* READ */

#define png_hardware_init_filter_functions_impl png_init_filter_functions_neon

#ifndef PNG_WIP_DISABLE_PALETTE /*TODO*/
#include "palette_neon_intrinsics.c"
#endif /*TODO*/

/* TODO:
* png_hardware_free_data_impl
* Must be defined if the implementation stores data in
* png_struct::hardware_data. Need not be defined otherwise.
*
* png_hardware_init_palette_support_impl
* Contains code to initialize a palette transformation. This returns
* true if something has been set up. Only called if the state contains
* png_hardware_palette, need not be defined, may cancel the state flag
* in the png_struct to prevent further calls.
*
* png_hardware_do_expand_palette
* Handles palette expansion. Need not be defined, only called if the
* state contains png_hardware_palette, may set this flag to zero, may
* return false to indicate that the expansion was not done.
*/

#endif /* READ, ALIGNEDMEMORY && ARM_NEON */
33 changes: 8 additions & 25 deletions arm/filter_neon_intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,7 @@
* and license in png.h
*/

#include "../pngpriv.h"

#ifdef PNG_READ_SUPPORTED

/* This code requires -mfpu=neon on the command line: */
#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */

#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64)
# include <arm64_neon.h>
#else
# include <arm_neon.h>
#endif
/* [[libpng-1.8]] this is file is included by arm/arm_init.c */

/* libpng row pointers are not necessarily aligned to any particular boundary,
* however this code will only work with appropriate alignment. arm/arm_init.c
Expand All @@ -45,9 +34,7 @@
#define png_ldr(type,pointer)\
(temp_pointer = png_ptr(type,pointer), *temp_pointer)

#if PNG_ARM_NEON_OPT > 0

void
static void
png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
Expand All @@ -68,7 +55,7 @@ png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
}
}

void
static void
png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
Expand Down Expand Up @@ -115,7 +102,7 @@ png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
PNG_UNUSED(prev_row)
}

void
static void
png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
Expand Down Expand Up @@ -147,7 +134,7 @@ png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
PNG_UNUSED(prev_row)
}

void
static void
png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
Expand Down Expand Up @@ -215,7 +202,7 @@ png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
}
}

void
static void
png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
Expand Down Expand Up @@ -284,7 +271,7 @@ paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c)
return e;
}

void
static void
png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
Expand Down Expand Up @@ -352,7 +339,7 @@ png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
}
}

void
static void
png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
Expand Down Expand Up @@ -396,7 +383,3 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
}
}

#endif /* PNG_ARM_NEON_OPT > 0 */
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 1 (intrinsics) */
#endif /* READ */
Loading

0 comments on commit 20ced64

Please sign in to comment.