mirror of
https://git.code.sf.net/p/libpng/code.git
synced 2025-07-10 18:04:09 +02:00
Add optimized RISC-V Vector functions
Largely based off of the ARM NEON implementation. Signed-off-by: Cosmin Truta <ctruta@gmail.com>
This commit is contained in:
parent
b4800bae33
commit
cc5ee6b213
3
AUTHORS
3
AUTHORS
@ -40,8 +40,9 @@ Authors, for copyright and licensing purposes.
|
|||||||
- Zixu Wang (王子旭)
|
- Zixu Wang (王子旭)
|
||||||
* Arm Holdings
|
* Arm Holdings
|
||||||
- Richard Townsend
|
- Richard Townsend
|
||||||
* Google Inc.
|
* Google LLC
|
||||||
- Dan Field
|
- Dan Field
|
||||||
|
- Dragoș Tiselice
|
||||||
- Leon Scroggins III
|
- Leon Scroggins III
|
||||||
- Matt Sarett
|
- Matt Sarett
|
||||||
- Mike Klein
|
- Mike Klein
|
||||||
|
@ -312,6 +312,31 @@ if(PNG_HARDWARE_OPTIMIZATIONS)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Set definitions and sources for RISC-V.
|
||||||
|
if(TARGET_ARCH MATCHES "riscv*")
|
||||||
|
set(PNG_RISCV_VECTOR_POSSIBLE_VALUES check on off)
|
||||||
|
set(PNG_RISCV_VECTOR "off"
|
||||||
|
CACHE STRING "Enable RISC-V Vector optimizations: check|on|off; off is default")
|
||||||
|
set_property(CACHE PNG_RISCV_VECTOR
|
||||||
|
PROPERTY STRINGS ${PNG_RISCV_VECTOR_POSSIBLE_VALUES})
|
||||||
|
list(FIND PNG_RISCV_VECTOR_POSSIBLE_VALUES ${PNG_RISCV_VECTOR} index)
|
||||||
|
if(index EQUAL -1)
|
||||||
|
message(FATAL_ERROR "PNG_RISCV_VECTOR must be one of [${PNG_RISCV_VECTOR_POSSIBLE_VALUES}]")
|
||||||
|
elseif(NOT ${PNG_RISCV_VECTOR} STREQUAL "off")
|
||||||
|
set(libpng_riscv_sources
|
||||||
|
riscv/filter_vector_intrinsics.c
|
||||||
|
riscv/palette_vector_intrinsics.c
|
||||||
|
riscv/riscv_init.c)
|
||||||
|
if(${PNG_RISCV_VECTOR} STREQUAL "on")
|
||||||
|
add_definitions(-DPNG_RISCV_VECTOR_OPT=2)
|
||||||
|
elseif(${PNG_RISCV_VECTOR} STREQUAL "check")
|
||||||
|
add_definitions(-DPNG_RISCV_VECTOR_CHECK_SUPPORTED)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
add_definitions(-DPNG_RISCV_VECTOR_OPT=0)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
else(PNG_HARDWARE_OPTIMIZATIONS)
|
else(PNG_HARDWARE_OPTIMIZATIONS)
|
||||||
|
|
||||||
# Set definitions and sources for ARM.
|
# Set definitions and sources for ARM.
|
||||||
@ -339,6 +364,11 @@ else(PNG_HARDWARE_OPTIMIZATIONS)
|
|||||||
add_definitions(-DPNG_LOONGARCH_LSX_OPT=0)
|
add_definitions(-DPNG_LOONGARCH_LSX_OPT=0)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Set definitions and sources for RISC-V.
|
||||||
|
if(TARGET_ARCH MATCHES "^riscv")
|
||||||
|
add_definitions(-DPNG_RISCV_VECTOR_OPT=0)
|
||||||
|
endif()
|
||||||
|
|
||||||
endif(PNG_HARDWARE_OPTIMIZATIONS)
|
endif(PNG_HARDWARE_OPTIMIZATIONS)
|
||||||
|
|
||||||
option(ld-version-script "Enable linker version script" ON)
|
option(ld-version-script "Enable linker version script" ON)
|
||||||
@ -613,7 +643,9 @@ set(libpng_sources
|
|||||||
${libpng_mips_sources}
|
${libpng_mips_sources}
|
||||||
${libpng_powerpc_sources}
|
${libpng_powerpc_sources}
|
||||||
${libpng_loongarch_sources}
|
${libpng_loongarch_sources}
|
||||||
|
${libpng_riscv_sources}
|
||||||
)
|
)
|
||||||
|
|
||||||
set(pngtest_sources
|
set(pngtest_sources
|
||||||
pngtest.c
|
pngtest.c
|
||||||
)
|
)
|
||||||
|
10
INSTALL
10
INSTALL
@ -136,7 +136,7 @@ Your directory structure should look like this:
|
|||||||
depcomp, install-sh, mkinstalldirs, test-pngtest.sh, etc.
|
depcomp, install-sh, mkinstalldirs, test-pngtest.sh, etc.
|
||||||
contrib
|
contrib
|
||||||
arm-neon, conftest, examples, gregbook, libtests, pngminim,
|
arm-neon, conftest, examples, gregbook, libtests, pngminim,
|
||||||
pngminus, pngsuite, tools, visupng
|
pngminus, pngsuite, tools, visupng, riscv-vector
|
||||||
projects
|
projects
|
||||||
owatcom, visualc71, vstudio
|
owatcom, visualc71, vstudio
|
||||||
scripts
|
scripts
|
||||||
@ -289,6 +289,7 @@ such as one of
|
|||||||
--enable-mips-msa=yes
|
--enable-mips-msa=yes
|
||||||
--enable-intel-sse=yes
|
--enable-intel-sse=yes
|
||||||
--enable-powerpc-vsx=yes
|
--enable-powerpc-vsx=yes
|
||||||
|
--enable-riscv-vector=yes
|
||||||
|
|
||||||
or enable them all at once with
|
or enable them all at once with
|
||||||
|
|
||||||
@ -301,6 +302,7 @@ or more of
|
|||||||
CPPFLAGS += "-DPNG_MIPS_MSA"
|
CPPFLAGS += "-DPNG_MIPS_MSA"
|
||||||
CPPFLAGS += "-DPNG_INTEL_SSE"
|
CPPFLAGS += "-DPNG_INTEL_SSE"
|
||||||
CPPFLAGS += "-DPNG_POWERPC_VSX"
|
CPPFLAGS += "-DPNG_POWERPC_VSX"
|
||||||
|
CPPFLAGS += "-DPNG_RISCV_VECTOR"
|
||||||
|
|
||||||
See for example scripts/makefile.linux-opt
|
See for example scripts/makefile.linux-opt
|
||||||
|
|
||||||
@ -317,13 +319,15 @@ to disable a particular one,
|
|||||||
or via compiler-command options such as
|
or via compiler-command options such as
|
||||||
|
|
||||||
CPPFLAGS += "-DPNG_ARM_NEON_OPT=0, -DPNG_MIPS_MSA_OPT=0,
|
CPPFLAGS += "-DPNG_ARM_NEON_OPT=0, -DPNG_MIPS_MSA_OPT=0,
|
||||||
-DPNG_INTEL_SSE_OPT=0, -DPNG_POWERPC_VSX_OPT=0"
|
-DPNG_INTEL_SSE_OPT=0, -DPNG_POWERPC_VSX_OPT=0,
|
||||||
|
-DPNG_RISCV_VECTOR_OPT=0"
|
||||||
|
|
||||||
If you are using cmake, hardware optimizations are "on"
|
If you are using cmake, hardware optimizations are "on"
|
||||||
by default. To disable them, use
|
by default. To disable them, use
|
||||||
|
|
||||||
cmake . -DPNG_ARM_NEON=no -DPNG_INTEL_SSE=no \
|
cmake . -DPNG_ARM_NEON=no -DPNG_INTEL_SSE=no \
|
||||||
-DPNG_MIPS_MSA=no -DPNG_POWERPC_VSX=no
|
-DPNG_MIPS_MSA=no -DPNG_POWERPC_VSX=no \
|
||||||
|
-DPNG_RISCV_VECTOR=no
|
||||||
|
|
||||||
or disable them all at once with
|
or disable them all at once with
|
||||||
|
|
||||||
|
@ -134,6 +134,11 @@ libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += powerpc/powerpc_init.c\
|
|||||||
powerpc/filter_vsx_intrinsics.c
|
powerpc/filter_vsx_intrinsics.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if PNG_RISCV_VECTOR
|
||||||
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += riscv/riscv_init.c\
|
||||||
|
riscv/filter_vector_intrinsics.c riscv/palette_vector_intrinsics.c
|
||||||
|
endif
|
||||||
|
|
||||||
if PNG_LOONGARCH_LSX
|
if PNG_LOONGARCH_LSX
|
||||||
noinst_LTLIBRARIES= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx.la
|
noinst_LTLIBRARIES= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx.la
|
||||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx_la_SOURCES = loongarch/loongarch_lsx_init.c\
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx_la_SOURCES = loongarch/loongarch_lsx_init.c\
|
||||||
|
41
Makefile.in
41
Makefile.in
@ -132,6 +132,10 @@ host_triplet = @host@
|
|||||||
@HAVE_LD_VERSION_SCRIPT_FALSE@am__append_10 = -export-symbols libpng.sym
|
@HAVE_LD_VERSION_SCRIPT_FALSE@am__append_10 = -export-symbols libpng.sym
|
||||||
@PNG_LOONGARCH_LSX_TRUE@am__append_11 = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx.la
|
@PNG_LOONGARCH_LSX_TRUE@am__append_11 = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx.la
|
||||||
@DO_PNG_PREFIX_TRUE@am__append_12 = -DPNG_PREFIX='@PNG_PREFIX@'
|
@DO_PNG_PREFIX_TRUE@am__append_12 = -DPNG_PREFIX='@PNG_PREFIX@'
|
||||||
|
|
||||||
|
@PNG_RISCV_VECTOR_TRUE@am__append_13 = riscv/riscv_init.c\
|
||||||
|
@PNG_RISCV_VECTOR_TRUE@ riscv/filter_vector_intrinsics.c riscv/palette_vector_intrinsics.c
|
||||||
|
|
||||||
subdir = .
|
subdir = .
|
||||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
am__aclocal_m4_deps = $(top_srcdir)/scripts/autoconf/libtool.m4 \
|
am__aclocal_m4_deps = $(top_srcdir)/scripts/autoconf/libtool.m4 \
|
||||||
@ -193,7 +197,9 @@ am__libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES_DIST = png.c \
|
|||||||
mips/mips_init.c mips/filter_msa_intrinsics.c \
|
mips/mips_init.c mips/filter_msa_intrinsics.c \
|
||||||
mips/filter_mmi_inline_assembly.c intel/intel_init.c \
|
mips/filter_mmi_inline_assembly.c intel/intel_init.c \
|
||||||
intel/filter_sse2_intrinsics.c powerpc/powerpc_init.c \
|
intel/filter_sse2_intrinsics.c powerpc/powerpc_init.c \
|
||||||
powerpc/filter_vsx_intrinsics.c
|
powerpc/filter_vsx_intrinsics.c riscv/riscv_init.c \
|
||||||
|
riscv/filter_vector_intrinsics.c \
|
||||||
|
riscv/palette_vector_intrinsics.c
|
||||||
am__dirstamp = $(am__leading_dot)dirstamp
|
am__dirstamp = $(am__leading_dot)dirstamp
|
||||||
@PNG_ARM_NEON_TRUE@am__objects_1 = arm/arm_init.lo \
|
@PNG_ARM_NEON_TRUE@am__objects_1 = arm/arm_init.lo \
|
||||||
@PNG_ARM_NEON_TRUE@ arm/filter_neon_intrinsics.lo \
|
@PNG_ARM_NEON_TRUE@ arm/filter_neon_intrinsics.lo \
|
||||||
@ -207,12 +213,15 @@ am__dirstamp = $(am__leading_dot)dirstamp
|
|||||||
@PNG_INTEL_SSE_TRUE@ intel/filter_sse2_intrinsics.lo
|
@PNG_INTEL_SSE_TRUE@ intel/filter_sse2_intrinsics.lo
|
||||||
@PNG_POWERPC_VSX_TRUE@am__objects_6 = powerpc/powerpc_init.lo \
|
@PNG_POWERPC_VSX_TRUE@am__objects_6 = powerpc/powerpc_init.lo \
|
||||||
@PNG_POWERPC_VSX_TRUE@ powerpc/filter_vsx_intrinsics.lo
|
@PNG_POWERPC_VSX_TRUE@ powerpc/filter_vsx_intrinsics.lo
|
||||||
|
@PNG_RISCV_VECTOR_TRUE@am__objects_7 = riscv/riscv_init.lo \
|
||||||
|
@PNG_RISCV_VECTOR_TRUE@ riscv/filter_vector_intrinsics.lo \
|
||||||
|
@PNG_RISCV_VECTOR_TRUE@ riscv/palette_vector_intrinsics.lo
|
||||||
am_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS = png.lo pngerror.lo \
|
am_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS = png.lo pngerror.lo \
|
||||||
pngget.lo pngmem.lo pngpread.lo pngread.lo pngrio.lo \
|
pngget.lo pngmem.lo pngpread.lo pngread.lo pngrio.lo \
|
||||||
pngrtran.lo pngrutil.lo pngset.lo pngtrans.lo pngwio.lo \
|
pngrtran.lo pngrutil.lo pngset.lo pngtrans.lo pngwio.lo \
|
||||||
pngwrite.lo pngwtran.lo pngwutil.lo $(am__objects_1) \
|
pngwrite.lo pngwtran.lo pngwutil.lo $(am__objects_1) \
|
||||||
$(am__objects_2) $(am__objects_3) $(am__objects_4) \
|
$(am__objects_2) $(am__objects_3) $(am__objects_4) \
|
||||||
$(am__objects_5) $(am__objects_6)
|
$(am__objects_5) $(am__objects_6) $(am__objects_7)
|
||||||
nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS =
|
nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS =
|
||||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS = \
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS = \
|
||||||
$(am_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) \
|
$(am_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) \
|
||||||
@ -332,7 +341,10 @@ am__depfiles_remade = ./$(DEPDIR)/png.Plo ./$(DEPDIR)/pngerror.Plo \
|
|||||||
mips/$(DEPDIR)/filter_msa_intrinsics.Plo \
|
mips/$(DEPDIR)/filter_msa_intrinsics.Plo \
|
||||||
mips/$(DEPDIR)/mips_init.Plo \
|
mips/$(DEPDIR)/mips_init.Plo \
|
||||||
powerpc/$(DEPDIR)/filter_vsx_intrinsics.Plo \
|
powerpc/$(DEPDIR)/filter_vsx_intrinsics.Plo \
|
||||||
powerpc/$(DEPDIR)/powerpc_init.Plo
|
powerpc/$(DEPDIR)/powerpc_init.Plo \
|
||||||
|
riscv/$(DEPDIR)/filter_vector_intrinsics.Plo \
|
||||||
|
riscv/$(DEPDIR)/palette_vector_intrinsics.Plo \
|
||||||
|
riscv/$(DEPDIR)/riscv_init.Plo
|
||||||
am__mv = mv -f
|
am__mv = mv -f
|
||||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||||
@ -825,7 +837,7 @@ libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngerror.c \
|
|||||||
pngwutil.c png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h \
|
pngwutil.c png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h \
|
||||||
pngstruct.h pngusr.dfa $(am__append_2) $(am__append_3) \
|
pngstruct.h pngusr.dfa $(am__append_2) $(am__append_3) \
|
||||||
$(am__append_4) $(am__append_5) $(am__append_6) \
|
$(am__append_4) $(am__append_5) $(am__append_6) \
|
||||||
$(am__append_7)
|
$(am__append_7) $(am__append_13)
|
||||||
@PNG_LOONGARCH_LSX_TRUE@noinst_LTLIBRARIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx.la
|
@PNG_LOONGARCH_LSX_TRUE@noinst_LTLIBRARIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx.la
|
||||||
@PNG_LOONGARCH_LSX_TRUE@libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx_la_SOURCES = loongarch/loongarch_lsx_init.c\
|
@PNG_LOONGARCH_LSX_TRUE@libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@lsx_la_SOURCES = loongarch/loongarch_lsx_init.c\
|
||||||
@PNG_LOONGARCH_LSX_TRUE@ loongarch/filter_lsx_intrinsics.c
|
@PNG_LOONGARCH_LSX_TRUE@ loongarch/filter_lsx_intrinsics.c
|
||||||
@ -1071,6 +1083,18 @@ powerpc/powerpc_init.lo: powerpc/$(am__dirstamp) \
|
|||||||
powerpc/$(DEPDIR)/$(am__dirstamp)
|
powerpc/$(DEPDIR)/$(am__dirstamp)
|
||||||
powerpc/filter_vsx_intrinsics.lo: powerpc/$(am__dirstamp) \
|
powerpc/filter_vsx_intrinsics.lo: powerpc/$(am__dirstamp) \
|
||||||
powerpc/$(DEPDIR)/$(am__dirstamp)
|
powerpc/$(DEPDIR)/$(am__dirstamp)
|
||||||
|
riscv/$(am__dirstamp):
|
||||||
|
@$(MKDIR_P) riscv
|
||||||
|
@: > riscv/$(am__dirstamp)
|
||||||
|
riscv/$(DEPDIR)/$(am__dirstamp):
|
||||||
|
@$(MKDIR_P) riscv/$(DEPDIR)
|
||||||
|
@: > riscv/$(DEPDIR)/$(am__dirstamp)
|
||||||
|
riscv/riscv_init.lo: riscv/$(am__dirstamp) \
|
||||||
|
riscv/$(DEPDIR)/$(am__dirstamp)
|
||||||
|
riscv/filter_vector_intrinsics.lo: riscv/$(am__dirstamp) \
|
||||||
|
riscv/$(DEPDIR)/$(am__dirstamp)
|
||||||
|
riscv/palette_vector_intrinsics.lo: riscv/$(am__dirstamp) \
|
||||||
|
riscv/$(DEPDIR)/$(am__dirstamp)
|
||||||
|
|
||||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la: $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES) $(EXTRA_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES)
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la: $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES) $(EXTRA_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES)
|
||||||
$(AM_V_CCLD)$(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LINK) -rpath $(libdir) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LIBADD) $(LIBS)
|
$(AM_V_CCLD)$(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LINK) -rpath $(libdir) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LIBADD) $(LIBS)
|
||||||
@ -1202,6 +1226,8 @@ mostlyclean-compile:
|
|||||||
-rm -f mips/*.lo
|
-rm -f mips/*.lo
|
||||||
-rm -f powerpc/*.$(OBJEXT)
|
-rm -f powerpc/*.$(OBJEXT)
|
||||||
-rm -f powerpc/*.lo
|
-rm -f powerpc/*.lo
|
||||||
|
-rm -f riscv/*.$(OBJEXT)
|
||||||
|
-rm -f riscv/*.lo
|
||||||
|
|
||||||
distclean-compile:
|
distclean-compile:
|
||||||
-rm -f *.tab.c
|
-rm -f *.tab.c
|
||||||
@ -1297,6 +1323,7 @@ clean-libtool:
|
|||||||
-rm -rf loongarch/.libs loongarch/_libs
|
-rm -rf loongarch/.libs loongarch/_libs
|
||||||
-rm -rf mips/.libs mips/_libs
|
-rm -rf mips/.libs mips/_libs
|
||||||
-rm -rf powerpc/.libs powerpc/_libs
|
-rm -rf powerpc/.libs powerpc/_libs
|
||||||
|
-rm -rf riscv/.libs riscv/_libs
|
||||||
|
|
||||||
distclean-libtool:
|
distclean-libtool:
|
||||||
-rm -f libtool config.lt
|
-rm -f libtool config.lt
|
||||||
@ -2201,6 +2228,9 @@ distclean: distclean-am
|
|||||||
-rm -f mips/$(DEPDIR)/mips_init.Plo
|
-rm -f mips/$(DEPDIR)/mips_init.Plo
|
||||||
-rm -f powerpc/$(DEPDIR)/filter_vsx_intrinsics.Plo
|
-rm -f powerpc/$(DEPDIR)/filter_vsx_intrinsics.Plo
|
||||||
-rm -f powerpc/$(DEPDIR)/powerpc_init.Plo
|
-rm -f powerpc/$(DEPDIR)/powerpc_init.Plo
|
||||||
|
-rm -f riscv/$(DEPDIR)/filter_vector_intrinsics.Plo
|
||||||
|
-rm -f riscv/$(DEPDIR)/palette_vector_intrinsics.Plo
|
||||||
|
-rm -f riscv/$(DEPDIR)/riscv_init.Plo
|
||||||
-rm -f Makefile
|
-rm -f Makefile
|
||||||
distclean-am: clean-am distclean-compile distclean-generic \
|
distclean-am: clean-am distclean-compile distclean-generic \
|
||||||
distclean-hdr distclean-libtool distclean-tags
|
distclean-hdr distclean-libtool distclean-tags
|
||||||
@ -2288,6 +2318,9 @@ maintainer-clean: maintainer-clean-am
|
|||||||
-rm -f mips/$(DEPDIR)/mips_init.Plo
|
-rm -f mips/$(DEPDIR)/mips_init.Plo
|
||||||
-rm -f powerpc/$(DEPDIR)/filter_vsx_intrinsics.Plo
|
-rm -f powerpc/$(DEPDIR)/filter_vsx_intrinsics.Plo
|
||||||
-rm -f powerpc/$(DEPDIR)/powerpc_init.Plo
|
-rm -f powerpc/$(DEPDIR)/powerpc_init.Plo
|
||||||
|
-rm -f riscv/$(DEPDIR)/filter_vector_intrinsics.Plo
|
||||||
|
-rm -f riscv/$(DEPDIR)/palette_vector_intrinsics.Plo
|
||||||
|
-rm -f riscv/$(DEPDIR)/riscv_init.Plo
|
||||||
-rm -f Makefile
|
-rm -f Makefile
|
||||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
|
2
README
2
README
@ -147,6 +147,7 @@ Files included in this distribution
|
|||||||
loongarch/ => Optimized code for LoongArch LSX
|
loongarch/ => Optimized code for LoongArch LSX
|
||||||
mips/ => Optimized code for MIPS MSA and MIPS MMI
|
mips/ => Optimized code for MIPS MSA and MIPS MMI
|
||||||
powerpc/ => Optimized code for PowerPC VSX
|
powerpc/ => Optimized code for PowerPC VSX
|
||||||
|
riscv/ => Optimized code for the RISC-V platform
|
||||||
ci/ => Scripts for continuous integration
|
ci/ => Scripts for continuous integration
|
||||||
contrib/ => External contributions
|
contrib/ => External contributions
|
||||||
arm-neon/ => Optimized code for the ARM-NEON platform
|
arm-neon/ => Optimized code for the ARM-NEON platform
|
||||||
@ -162,6 +163,7 @@ Files included in this distribution
|
|||||||
programs demonstrating the use of pngusr.dfa
|
programs demonstrating the use of pngusr.dfa
|
||||||
pngminus/ => Simple pnm2png and png2pnm programs
|
pngminus/ => Simple pnm2png and png2pnm programs
|
||||||
pngsuite/ => Test images
|
pngsuite/ => Test images
|
||||||
|
riscv-vector/ => Optimized code for the RISC-V Vector platform
|
||||||
testpngs/ => Test images
|
testpngs/ => Test images
|
||||||
tools/ => Various tools
|
tools/ => Various tools
|
||||||
visupng/ => VisualPng, a Windows viewer for PNG images
|
visupng/ => VisualPng, a Windows viewer for PNG images
|
||||||
|
11
config.h.in
11
config.h.in
@ -108,7 +108,16 @@
|
|||||||
/* Enable POWERPC VSX optimizations */
|
/* Enable POWERPC VSX optimizations */
|
||||||
#undef PNG_POWERPC_VSX_OPT
|
#undef PNG_POWERPC_VSX_OPT
|
||||||
|
|
||||||
/* Define to 1 if all of the C89 standard headers exist (not just the ones
|
/* Turn on RISC-V Vector optimizations at run-time */
|
||||||
|
#undef PNG_RISCV_VECTOR_API_SUPPORTED
|
||||||
|
|
||||||
|
/* Check for RISC-V Vector support at run-time */
|
||||||
|
#undef PNG_RISCV_VECTOR_CHECK_SUPPORTED
|
||||||
|
|
||||||
|
/* Enable RISC-V Vector optimizations */
|
||||||
|
#undef PNG_RISCV_VECTOR_OPT
|
||||||
|
|
||||||
|
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||||
required in a freestanding environment). This macro is provided for
|
required in a freestanding environment). This macro is provided for
|
||||||
backward compatibility; new code need not use it. */
|
backward compatibility; new code need not use it. */
|
||||||
#undef STDC_HEADERS
|
#undef STDC_HEADERS
|
||||||
|
54
configure.ac
54
configure.ac
@ -343,6 +343,9 @@ AC_ARG_ENABLE([hardware-optimizations],
|
|||||||
enable_loongarch_lsx=no
|
enable_loongarch_lsx=no
|
||||||
AC_DEFINE([PNG_LOONGARCH_LSX_OPT], [0],
|
AC_DEFINE([PNG_LOONGARCH_LSX_OPT], [0],
|
||||||
[Disable LOONGARCH_LSX optimizations])
|
[Disable LOONGARCH_LSX optimizations])
|
||||||
|
enable_riscv_vector=no
|
||||||
|
AC_DEFINE([PNG_RISCV_VECTOR_OPT], [0],
|
||||||
|
[Disable RISC-V Vector optimizations])
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
# allow enabling hardware optimization on any system:
|
# allow enabling hardware optimization on any system:
|
||||||
@ -374,6 +377,10 @@ AC_ARG_ENABLE([hardware-optimizations],
|
|||||||
enable_loongarch_lsx=yes
|
enable_loongarch_lsx=yes
|
||||||
AC_DEFINE([PNG_LOONGARCH_LSX_OPT], [1],
|
AC_DEFINE([PNG_LOONGARCH_LSX_OPT], [1],
|
||||||
[Enable LOONGARCH_LSX optimizations])
|
[Enable LOONGARCH_LSX optimizations])
|
||||||
|
riscv*)
|
||||||
|
enable_riscv_vector=yes
|
||||||
|
AC_DEFINE([PNG_RISCV_VECTOR_OPT], [2],
|
||||||
|
[Enable RISC-V Vector optimizations])
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
@ -661,6 +668,53 @@ AM_CONDITIONAL([PNG_LOONGARCH_LSX],
|
|||||||
*) test "$enable_loongarch_lsx" != '' ;;
|
*) test "$enable_loongarch_lsx" != '' ;;
|
||||||
esac])
|
esac])
|
||||||
|
|
||||||
|
# RISC-V
|
||||||
|
# ======
|
||||||
|
#
|
||||||
|
# RISC-V Vector support.
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([riscv-vector],
|
||||||
|
AS_HELP_STRING([[[--enable-riscv-vector]]],
|
||||||
|
[Enable RISC-V Vector optimizations: =no/off, check, api, yes/on:]
|
||||||
|
[no/off: disable the optimizations; check: use internal checking code]
|
||||||
|
[api: disable by default, enable by a call to png_set_option]
|
||||||
|
[yes/on: turn on unconditionally.]
|
||||||
|
[If not specified: determined by the compiler.]),
|
||||||
|
[case "$enableval" in
|
||||||
|
no|off)
|
||||||
|
# disable the default enabling on __ppc64__ systems:
|
||||||
|
AC_DEFINE([PNG_RISCV_VECTOR_OPT], [0],
|
||||||
|
[Disable RISC-V Vector optimizations])
|
||||||
|
# Prevent inclusion of the platform-specific files below:
|
||||||
|
enable_riscv_vector=no ;;
|
||||||
|
check)
|
||||||
|
AC_DEFINE([PNG_RISCV_VECTOR_CHECK_SUPPORTED], [],
|
||||||
|
[Check for RISC-V Vector support at run-time])
|
||||||
|
AC_MSG_WARN([--enable-riscv-vector Please check contrib/riscv-vector/README file]
|
||||||
|
[for the list of supported OSes.]);;
|
||||||
|
api)
|
||||||
|
AC_DEFINE([PNG_RISCV_VECTOR_API_SUPPORTED], [],
|
||||||
|
[Turn on RISC-V Vector optimizations at run-time]);;
|
||||||
|
yes|on)
|
||||||
|
AC_DEFINE([PNG_RISCV_VECTOR_OPT], [2],
|
||||||
|
[Enable RISC-V Vector optimizations])
|
||||||
|
AC_MSG_WARN([--enable-riscv-vector: please specify 'check' or 'api', if]
|
||||||
|
[you want the optimizations unconditionally pass e.g. '-march=rv64gcv']
|
||||||
|
[to the compiler.]);;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR([--enable-riscv-vector=${enable_riscv_vector}: invalid value])
|
||||||
|
esac])
|
||||||
|
|
||||||
|
# Add RISC-V-specific files to all builds where $host_cpu is riscv ('riscv*')
|
||||||
|
# or where RISC-V optimizations were explicitly requested (this allows a fallback
|
||||||
|
# if a future host CPU does not match 'riscv*')
|
||||||
|
|
||||||
|
AM_CONDITIONAL([PNG_RISCV_VECTOR],
|
||||||
|
[test "$enable_riscv_vector" != 'no' &&
|
||||||
|
case "$host_cpu" in
|
||||||
|
riscv*) : ;;
|
||||||
|
esac])
|
||||||
|
|
||||||
AC_MSG_NOTICE([[Extra options for compiler: $PNG_COPTS]])
|
AC_MSG_NOTICE([[Extra options for compiler: $PNG_COPTS]])
|
||||||
|
|
||||||
# Config files, substituting as above
|
# Config files, substituting as above
|
||||||
|
85
contrib/riscv-vector/README
Normal file
85
contrib/riscv-vector/README
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
OPERATING SYSTEM SPECIFIC ARM NEON DETECTION
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
Detection of the ability to execute RISC-V Vector on a RISC-V processor
|
||||||
|
requires operating system support. (The information is not available in user
|
||||||
|
mode.)
|
||||||
|
|
||||||
|
HOW TO USE THIS
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This directory contains C code fragments that can be included in
|
||||||
|
riscv/riscv_init.c by setting the macro PNG_RISCV_VECTOR_FILE to the file name
|
||||||
|
in "" or <> at build time. This setting is not recorded in pnglibconf.h and
|
||||||
|
can be changed simply by rebuilding riscv/riscv_init.o with the required macro
|
||||||
|
definition.
|
||||||
|
|
||||||
|
For any of this code to be used the RISC-V Vector code must be enabled and run
|
||||||
|
time checks must be supported. I.e.:
|
||||||
|
|
||||||
|
#if PNG_RISCV_VECTOR_OPT > 0
|
||||||
|
#ifdef PNG_RISCV_VECTOR_CHECK_SUPPORTED
|
||||||
|
|
||||||
|
This is done in a 'configure' build by passing configure the argument:
|
||||||
|
|
||||||
|
--enable-riscv-vector=check
|
||||||
|
|
||||||
|
Apart from the basic Linux implementation in contrib/riscv-vector/linux.c this
|
||||||
|
code is unsupported. That means that it is not even compiled on a regular
|
||||||
|
basis and may be broken in any given minor release.
|
||||||
|
|
||||||
|
FILE FORMAT
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Each file documents its testing status as of the last time it was tested (which
|
||||||
|
may have been a long time ago):
|
||||||
|
|
||||||
|
STATUS: one of:
|
||||||
|
SUPPORTED: This indicates that the file is included in the regularly
|
||||||
|
performed test builds and bugs are fixed when discovered.
|
||||||
|
COMPILED: This indicates that the code did compile at least once. See the
|
||||||
|
more detailed description for the extent to which the result was
|
||||||
|
successful.
|
||||||
|
TESTED: This means the code was fully compiled into the libpng test programs
|
||||||
|
and these were run at least once.
|
||||||
|
|
||||||
|
BUG REPORTS: an email address to which to send reports of problems
|
||||||
|
|
||||||
|
The file is a fragment of C code. It should not define any 'extern' symbols;
|
||||||
|
everything should be static. It must define the function:
|
||||||
|
|
||||||
|
static int png_have_vector(png_structp png_ptr);
|
||||||
|
|
||||||
|
That function must return 1 if RISC-V Vector instructions are supported, 0 if
|
||||||
|
not. It must not execute png_error unless it detects a bug. A png_error will
|
||||||
|
prevent the reading of the PNG and in the future, writing too.
|
||||||
|
|
||||||
|
BUG REPORTS
|
||||||
|
-----------
|
||||||
|
|
||||||
|
If you mail a bug report for any file that is not SUPPORTED there may only be
|
||||||
|
limited response. Consider fixing it and sending a patch to fix the problem -
|
||||||
|
this is more likely to result in action.
|
||||||
|
|
||||||
|
CONTRIBUTIONS
|
||||||
|
-------------
|
||||||
|
|
||||||
|
You may send contributions of new implementations to
|
||||||
|
png-mng-implement@sourceforge.net. Please write code in strict C90 C where
|
||||||
|
possible. Obviously OS dependencies are to be expected. If you submit code you
|
||||||
|
must have the authors permission and it must have a license that is acceptable
|
||||||
|
to the current maintainer; in particular that license must permit modification
|
||||||
|
and redistribution.
|
||||||
|
|
||||||
|
Please try to make the contribution a single file and give the file a clear and
|
||||||
|
unambiguous name that identifies the target OS. If multiple files really are
|
||||||
|
required put them all in a sub-directory.
|
||||||
|
|
||||||
|
You must also be prepared to handle bug reports from users of the code, either
|
||||||
|
by joining the png-mng-implement mailing list or by providing an email for the
|
||||||
|
"BUG REPORTS" entry or both. Please make sure that the header of the file
|
||||||
|
contains the STATUS and BUG REPORTS fields as above.
|
||||||
|
|
||||||
|
Please list the OS requirements as precisely as possible. Ideally you should
|
||||||
|
also list the environment in which the code has been tested and certainly list
|
||||||
|
any environments where you suspect it might not work.
|
57
contrib/riscv-vector/linux.c
Normal file
57
contrib/riscv-vector/linux.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* contrib/riscv-vector/linux.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Google LLC
|
||||||
|
* Written by Dragoș Tiselice <dtiselice@google.com>, May 2023.
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*
|
||||||
|
* SEE contrib/riscv-vector/README before reporting bugs
|
||||||
|
*
|
||||||
|
* STATUS: SUPPORTED
|
||||||
|
* BUG REPORTS: png-mng-implement@sourceforge.net
|
||||||
|
*
|
||||||
|
* png_have_vector implemented for Linux by reading the widely available
|
||||||
|
* pseudo-file /proc/cpuinfo.
|
||||||
|
*
|
||||||
|
* This code is strict ANSI-C and is probably moderately portable; it does
|
||||||
|
* however use <stdio.h> and it assumes that /proc/cpuinfo is never localized.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
png_have_vector(png_structp png_ptr) {
|
||||||
|
FILE* f = fopen("/proc/cpuinfo", "rb");
|
||||||
|
|
||||||
|
if (f == NULL) {
|
||||||
|
#ifdef PNG_WARNINGS_SUPPORTED
|
||||||
|
png_warning(png_ptr, "/proc/cpuinfo open failed");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char line[256];
|
||||||
|
|
||||||
|
while (fgets(line, sizeof line, f)) {
|
||||||
|
if (strncmp(line, "isa", 3) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* isa = strstr(line, "rv");
|
||||||
|
|
||||||
|
if (isa == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strchr(isa + 2, 'v') != NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
53
pngpriv.h
53
pngpriv.h
@ -288,6 +288,10 @@
|
|||||||
# define PNG_LOONGARCH_LSX_IMPLEMENTATION 0
|
# define PNG_LOONGARCH_LSX_IMPLEMENTATION 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PNG_RISCV_VECTOR_OPT > 0
|
||||||
|
# define PNG_RISCV_VECTOR_IMPLEMENTATION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Is this a build of a DLL where compilation of the object modules requires
|
/* Is this a build of a DLL where compilation of the object modules requires
|
||||||
* different preprocessor settings to those required for a simple library? If
|
* different preprocessor settings to those required for a simple library? If
|
||||||
* so PNG_BUILD_DLL must be set.
|
* so PNG_BUILD_DLL must be set.
|
||||||
@ -1522,6 +1526,27 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_lsx,(png_row_infop
|
|||||||
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
|
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PNG_RISCV_VECTOR_OPT > 0
|
||||||
|
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_vector,(png_row_infop
|
||||||
|
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
|
||||||
|
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_vector_128,(png_row_infop
|
||||||
|
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
|
||||||
|
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_vector_256,(png_row_infop
|
||||||
|
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
|
||||||
|
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_vector_128,(png_row_infop
|
||||||
|
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
|
||||||
|
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_vector_256,(png_row_infop
|
||||||
|
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
|
||||||
|
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_vector,(png_row_infop
|
||||||
|
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
|
||||||
|
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_vector,(png_row_infop
|
||||||
|
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
|
||||||
|
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_vector,(png_row_infop
|
||||||
|
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
|
||||||
|
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_vector,(png_row_infop
|
||||||
|
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Choose the best filter to use and filter the row data */
|
/* Choose the best filter to use and filter the row data */
|
||||||
PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
|
PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
|
||||||
png_row_infop row_info),PNG_EMPTY);
|
png_row_infop row_info),PNG_EMPTY);
|
||||||
@ -2134,6 +2159,11 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_lsx,
|
|||||||
(png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
|
(png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
# if PNG_RISCV_VECTOR_OPT > 0
|
||||||
|
PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_vector,
|
||||||
|
(png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
|
||||||
|
#endif
|
||||||
|
|
||||||
PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
|
PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
|
||||||
png_const_charp key, png_bytep new_key), PNG_EMPTY);
|
png_const_charp key, png_bytep new_key), PNG_EMPTY);
|
||||||
|
|
||||||
@ -2160,6 +2190,29 @@ PNG_INTERNAL_FUNCTION(int,
|
|||||||
PNG_EMPTY);
|
PNG_EMPTY);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PNG_RISCV_VECTOR_IMPLEMENTATION == 1
|
||||||
|
PNG_INTERNAL_FUNCTION(void,
|
||||||
|
png_riffle_palette_vector,
|
||||||
|
(png_structrp),
|
||||||
|
PNG_EMPTY);
|
||||||
|
PNG_INTERNAL_FUNCTION(int,
|
||||||
|
png_do_expand_palette_rgba8_vector,
|
||||||
|
(png_structrp,
|
||||||
|
png_row_infop,
|
||||||
|
png_const_bytep,
|
||||||
|
const png_bytepp,
|
||||||
|
const png_bytepp),
|
||||||
|
PNG_EMPTY);
|
||||||
|
PNG_INTERNAL_FUNCTION(int,
|
||||||
|
png_do_expand_palette_rgb8_vector,
|
||||||
|
(png_structrp,
|
||||||
|
png_row_infop,
|
||||||
|
png_const_bytep,
|
||||||
|
const png_bytepp,
|
||||||
|
const png_bytepp),
|
||||||
|
PNG_EMPTY);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Maintainer: Put new private prototypes here ^ */
|
/* Maintainer: Put new private prototypes here ^ */
|
||||||
|
|
||||||
#include "pngdebug.h"
|
#include "pngdebug.h"
|
||||||
|
@ -809,7 +809,7 @@ png_read_destroy(png_structrp png_ptr)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PNG_READ_EXPAND_SUPPORTED) && \
|
#if defined(PNG_READ_EXPAND_SUPPORTED) && \
|
||||||
defined(PNG_ARM_NEON_IMPLEMENTATION)
|
(defined(PNG_ARM_NEON_IMPLEMENTATION) || defined(PNG_RISCV_VECTOR_IMPLEMENTATION))
|
||||||
png_free(png_ptr, png_ptr->riffled_palette);
|
png_free(png_ptr, png_ptr->riffled_palette);
|
||||||
png_ptr->riffled_palette = NULL;
|
png_ptr->riffled_palette = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
26
pngrtran.c
26
pngrtran.c
@ -28,6 +28,12 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PNG_RISCV_VECTOR_IMPLEMENTATION
|
||||||
|
# if PNG_RISCV_VECTOR_IMPLEMENTATION == 1
|
||||||
|
# define PNG_RISCV_VECTOR_INTRINSICS_AVAILABLE
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PNG_READ_SUPPORTED
|
#ifdef PNG_READ_SUPPORTED
|
||||||
|
|
||||||
/* Set the action on getting a CRC error for an ancillary or critical chunk. */
|
/* Set the action on getting a CRC error for an ancillary or critical chunk. */
|
||||||
@ -4397,6 +4403,12 @@ png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info,
|
|||||||
i = png_do_expand_palette_rgba8_neon(png_ptr, row_info, row,
|
i = png_do_expand_palette_rgba8_neon(png_ptr, row_info, row,
|
||||||
&sp, &dp);
|
&sp, &dp);
|
||||||
}
|
}
|
||||||
|
#elif defined PNG_RISCV_VECTOR_INTRINSICS_AVAILABLE
|
||||||
|
if (png_ptr->riffled_palette != NULL)
|
||||||
|
{
|
||||||
|
i = png_do_expand_palette_rgba8_vector(png_ptr, row_info, row,
|
||||||
|
&sp, &dp);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
PNG_UNUSED(png_ptr)
|
PNG_UNUSED(png_ptr)
|
||||||
#endif
|
#endif
|
||||||
@ -4427,6 +4439,9 @@ png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info,
|
|||||||
#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
|
#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
|
||||||
i = png_do_expand_palette_rgb8_neon(png_ptr, row_info, row,
|
i = png_do_expand_palette_rgb8_neon(png_ptr, row_info, row,
|
||||||
&sp, &dp);
|
&sp, &dp);
|
||||||
|
#elif defined PNG_RISCV_VECTOR_INTRINSICS_AVAILABLE
|
||||||
|
i = png_do_expand_palette_rgb8_vector(png_ptr, row_info, row,
|
||||||
|
&sp, &dp);
|
||||||
#else
|
#else
|
||||||
PNG_UNUSED(png_ptr)
|
PNG_UNUSED(png_ptr)
|
||||||
#endif
|
#endif
|
||||||
@ -4856,6 +4871,17 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
|
|||||||
png_riffle_palette_neon(png_ptr);
|
png_riffle_palette_neon(png_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#elif defined PNG_RISCV_VECTOR_INTRINSICS_AVAILABLE
|
||||||
|
if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8))
|
||||||
|
{
|
||||||
|
if (png_ptr->riffled_palette == NULL)
|
||||||
|
{
|
||||||
|
/* Initialize the accelerated palette expansion. */
|
||||||
|
png_ptr->riffled_palette =
|
||||||
|
(png_bytep)png_malloc(png_ptr, 256 * 4);
|
||||||
|
png_riffle_palette_vector(png_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1,
|
png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1,
|
||||||
png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
|
png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
|
||||||
|
@ -375,7 +375,7 @@ struct png_struct_def
|
|||||||
|
|
||||||
/* New member added in libpng-1.6.36 */
|
/* New member added in libpng-1.6.36 */
|
||||||
#if defined(PNG_READ_EXPAND_SUPPORTED) && \
|
#if defined(PNG_READ_EXPAND_SUPPORTED) && \
|
||||||
defined(PNG_ARM_NEON_IMPLEMENTATION)
|
(defined(PNG_ARM_NEON_IMPLEMENTATION) || defined(PNG_RISCV_VECTOR_IMPLEMENTATION))
|
||||||
png_bytep riffled_palette; /* buffer for accelerated palette expansion */
|
png_bytep riffled_palette; /* buffer for accelerated palette expansion */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
280
riscv/filter_vector_intrinsics.c
Normal file
280
riscv/filter_vector_intrinsics.c
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
/* filter_neon_intrinsics.c - RISC-V Vector optimized filter functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Google LLC
|
||||||
|
* Written by Dragoș Tiselice <dtiselice@google.com>, May 2023.
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
#ifdef PNG_READ_SUPPORTED
|
||||||
|
|
||||||
|
#if PNG_RISCV_VECTOR_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
|
||||||
|
|
||||||
|
#include <riscv_vector.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_up_vector(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
size_t len = row_info->rowbytes;
|
||||||
|
|
||||||
|
for (size_t vl; len > 0; len -= vl, row += vl, prev_row += vl) {
|
||||||
|
vl = __riscv_vsetvl_e8m8(len);
|
||||||
|
|
||||||
|
vuint8m8_t prev_vals = __riscv_vle8_v_u8m8(prev_row, vl);
|
||||||
|
vuint8m8_t row_vals = __riscv_vle8_v_u8m8(row, vl);
|
||||||
|
|
||||||
|
row_vals = __riscv_vadd_vv_u8m8(row_vals, prev_vals, vl);
|
||||||
|
|
||||||
|
__riscv_vse8_v_u8m8(row, row_vals, vl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
png_read_filter_row_sub_vector_128(size_t len, size_t vl, unsigned char* row)
|
||||||
|
{
|
||||||
|
vuint8m1_t sum;
|
||||||
|
vuint8m1_t chunk = __riscv_vmv_v_x_u8m1(0, vl);
|
||||||
|
|
||||||
|
for (; len > 0; len -= vl, row += vl) {
|
||||||
|
__riscv_vsetvl_e8m1(vl);
|
||||||
|
|
||||||
|
sum = chunk;
|
||||||
|
chunk = __riscv_vle8_v_u8m1(row, vl);
|
||||||
|
|
||||||
|
chunk = __riscv_vadd_vv_u8m1(chunk, sum, vl);
|
||||||
|
|
||||||
|
__riscv_vse8_v_u8m1(row, chunk, vl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_sub3_vector_128(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
size_t len = row_info->rowbytes;
|
||||||
|
|
||||||
|
png_read_filter_row_sub_vector_128(len, 3, row);
|
||||||
|
|
||||||
|
PNG_UNUSED(prev_row)
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_sub4_vector_128(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
size_t len = row_info->rowbytes;
|
||||||
|
|
||||||
|
png_read_filter_row_sub_vector_128(len, 4, row);
|
||||||
|
|
||||||
|
PNG_UNUSED(prev_row)
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
png_read_filter_row_avg_vector(size_t len, size_t vl, unsigned char* row,
|
||||||
|
const unsigned char* prev_row)
|
||||||
|
{
|
||||||
|
vuint8m1_t avg;
|
||||||
|
vuint8m1_t chunk = __riscv_vmv_v_x_u8m1(0, vl);
|
||||||
|
|
||||||
|
for (; len > 0; len -= vl, row += vl) {
|
||||||
|
__riscv_vsetvl_e8m1(vl);
|
||||||
|
|
||||||
|
vuint8m1_t prev_chunk = __riscv_vle8_v_u8m1(prev_row, vl);
|
||||||
|
avg = chunk;
|
||||||
|
chunk = __riscv_vle8_v_u8m1(row, vl);
|
||||||
|
|
||||||
|
vuint8m1_t sum = __riscv_vadd_vv_u8m1(chunk, prev_chunk, vl);
|
||||||
|
vuint8m1_t avg = __riscv_vsrl_vx_u8m1(sum, 1, vl);
|
||||||
|
|
||||||
|
chunk = __riscv_vadd_vv_u8m1(chunk, avg, vl);
|
||||||
|
|
||||||
|
__riscv_vse8_v_u8m1(row, chunk, vl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_avg3_vector(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
size_t len = row_info->rowbytes;
|
||||||
|
|
||||||
|
png_read_filter_row_avg_vector(len, 3, row, prev_row);
|
||||||
|
|
||||||
|
PNG_UNUSED(prev_row)
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_avg4_vector(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
size_t len = row_info->rowbytes;
|
||||||
|
|
||||||
|
png_read_filter_row_avg_vector(len, 4, row, prev_row);
|
||||||
|
|
||||||
|
PNG_UNUSED(prev_row)
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MIN_CHUNK_LEN 256
|
||||||
|
#define MAX_CHUNK_LEN 2048
|
||||||
|
|
||||||
|
static inline vuint8m1_t
|
||||||
|
prefix_sum(vuint8m1_t chunk, unsigned char* carry, size_t vl,
|
||||||
|
size_t max_chunk_len)
|
||||||
|
{
|
||||||
|
size_t r;
|
||||||
|
|
||||||
|
for (r = 1; r < MIN_CHUNK_LEN; r <<= 1) {
|
||||||
|
vbool8_t shift_mask = __riscv_vmsgeu_vx_u8m1_b8(__riscv_vid_v_u8m1(vl), r, vl);
|
||||||
|
chunk = __riscv_vadd_vv_u8m1_mu(shift_mask, chunk, chunk, __riscv_vslideup_vx_u8m1(__riscv_vundefined_u8m1(), chunk, r, vl), vl);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (r = MIN_CHUNK_LEN; r < MAX_CHUNK_LEN && r < max_chunk_len; r <<= 1) {
|
||||||
|
vbool8_t shift_mask = __riscv_vmsgeu_vx_u8m1_b8(__riscv_vid_v_u8m1(vl), r, vl);
|
||||||
|
chunk = __riscv_vadd_vv_u8m1_mu(shift_mask, chunk, chunk, __riscv_vslideup_vx_u8m1(__riscv_vundefined_u8m1(), chunk, r, vl), vl);
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = __riscv_vadd_vx_u8m1(chunk, *carry, vl);
|
||||||
|
*carry = __riscv_vmv_x_s_u8m1_u8(__riscv_vslidedown_vx_u8m1(chunk, vl - 1, vl));
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_sub3_vector_256(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
size_t len = row_info->rowbytes;
|
||||||
|
const size_t max_chunk_len = __riscv_vsetvlmax_e8m1();
|
||||||
|
|
||||||
|
vuint8m1_t r;
|
||||||
|
vuint8m1_t g;
|
||||||
|
vuint8m1_t b;
|
||||||
|
|
||||||
|
unsigned char r_carry = 0;
|
||||||
|
unsigned char g_carry = 0;
|
||||||
|
unsigned char b_carry = 0;
|
||||||
|
|
||||||
|
for (size_t vl; len > 0; len -= vl * 3, row += vl * 3) {
|
||||||
|
vl = __riscv_vsetvl_e8m1(len / 3);
|
||||||
|
|
||||||
|
__riscv_vlseg3e8_v_u8m1(&r, &g, &b, row, vl);
|
||||||
|
|
||||||
|
r = prefix_sum(r, &r_carry, vl, max_chunk_len);
|
||||||
|
g = prefix_sum(g, &g_carry, vl, max_chunk_len);
|
||||||
|
b = prefix_sum(b, &b_carry, vl, max_chunk_len);
|
||||||
|
|
||||||
|
__riscv_vsseg3e8_v_u8m1(row, r, g, b, vl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_sub4_vector_256(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
size_t len = row_info->rowbytes;
|
||||||
|
const size_t max_chunk_len = __riscv_vsetvlmax_e8m1();
|
||||||
|
|
||||||
|
vuint8m1_t r;
|
||||||
|
vuint8m1_t g;
|
||||||
|
vuint8m1_t b;
|
||||||
|
vuint8m1_t a;
|
||||||
|
|
||||||
|
unsigned char r_carry = 0;
|
||||||
|
unsigned char g_carry = 0;
|
||||||
|
unsigned char b_carry = 0;
|
||||||
|
unsigned char a_carry = 0;
|
||||||
|
|
||||||
|
for (size_t vl; len > 0; len -= vl * 4, row += vl * 4) {
|
||||||
|
vl = __riscv_vsetvl_e8m1(len / 4);
|
||||||
|
|
||||||
|
__riscv_vlseg4e8_v_u8m1(&r, &g, &b, &a, row, vl);
|
||||||
|
|
||||||
|
r = prefix_sum(r, &r_carry, vl, max_chunk_len);
|
||||||
|
g = prefix_sum(g, &g_carry, vl, max_chunk_len);
|
||||||
|
b = prefix_sum(b, &b_carry, vl, max_chunk_len);
|
||||||
|
a = prefix_sum(a, &a_carry, vl, max_chunk_len);
|
||||||
|
|
||||||
|
__riscv_vsseg4e8_v_u8m1(row, r, g, b, a, vl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vint16m1_t
|
||||||
|
abs_diff(vuint16m1_t a, vuint16m1_t b, size_t vl)
|
||||||
|
{
|
||||||
|
vint16m1_t diff = __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vsub_vv_u16m1(a, b, vl));
|
||||||
|
vint16m1_t neg = __riscv_vneg_v_i16m1(diff, vl);
|
||||||
|
|
||||||
|
return __riscv_vmax_vv_i16m1(diff, neg, vl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vint16m1_t
|
||||||
|
abs_sum(vint16m1_t a, vint16m1_t b, size_t vl)
|
||||||
|
{
|
||||||
|
vint16m1_t sum = __riscv_vadd_vv_i16m1(a, b, vl);
|
||||||
|
vint16m1_t neg = __riscv_vneg_v_i16m1(sum, vl);
|
||||||
|
|
||||||
|
return __riscv_vmax_vv_i16m1(sum, neg, vl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
png_read_filter_row_paeth_vector(size_t len, size_t vl, unsigned char* row,
|
||||||
|
const unsigned char* prev)
|
||||||
|
{
|
||||||
|
vuint16m1_t a;
|
||||||
|
vuint16m1_t b = __riscv_vmv_v_x_u16m1(0, vl);
|
||||||
|
vuint16m1_t c;
|
||||||
|
vuint16m1_t d = __riscv_vmv_v_x_u16m1(0, vl);
|
||||||
|
|
||||||
|
for (; len > 0; len -= vl, row += vl, prev += vl) {
|
||||||
|
__riscv_vsetvl_e16m1(vl);
|
||||||
|
|
||||||
|
c = b;
|
||||||
|
b = __riscv_vzext_vf2_u16m1(__riscv_vle8_v_u8mf2(prev, vl), vl);
|
||||||
|
a = d;
|
||||||
|
d = __riscv_vzext_vf2_u16m1(__riscv_vle8_v_u8mf2(row, vl), vl);
|
||||||
|
|
||||||
|
vint16m1_t pa = abs_diff(b, c, vl);
|
||||||
|
vint16m1_t pb = abs_diff(a, c, vl);
|
||||||
|
vint16m1_t pc = abs_sum(pa, pb, vl);
|
||||||
|
|
||||||
|
vint16m1_t smallest = __riscv_vmin_vv_i16m1(pa, __riscv_vmin_vv_i16m1(pb, pc, vl), vl);
|
||||||
|
|
||||||
|
vuint16m1_t nearest = c;
|
||||||
|
nearest = __riscv_vmerge_vvm_u16m1(nearest, a, __riscv_vmseq_vv_i16m1_b16(smallest, pa, vl), vl);
|
||||||
|
nearest = __riscv_vmerge_vvm_u16m1(nearest, b, __riscv_vmseq_vv_i16m1_b16(smallest, pb, vl), vl);
|
||||||
|
|
||||||
|
d = __riscv_vadd_vv_u16m1(d, nearest, vl);
|
||||||
|
|
||||||
|
__riscv_vse8_v_u8mf2(row, __riscv_vnsrl_wx_u8mf2(d, 0, vl), vl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_paeth3_vector(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
size_t len = row_info->rowbytes;
|
||||||
|
|
||||||
|
png_read_filter_row_paeth_vector(len, 3, row, prev_row);
|
||||||
|
|
||||||
|
PNG_UNUSED(prev_row)
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_paeth4_vector(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
size_t len = row_info->rowbytes;
|
||||||
|
|
||||||
|
png_read_filter_row_paeth_vector(len, 4, row, prev_row);
|
||||||
|
|
||||||
|
PNG_UNUSED(prev_row)
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* PNG_RISCV_VECTOR_IMPLEMENTATION */
|
||||||
|
#endif /* READ */
|
104
riscv/palette_vector_intrinsics.c
Normal file
104
riscv/palette_vector_intrinsics.c
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/* palette_neon_intrinsics.c - RISC-V Vector optimized palette expansion
|
||||||
|
* functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Google LLC
|
||||||
|
* Written by Dragoș Tiselice <dtiselice@google.com>, May 2023.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
#include <riscv_vector.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
png_riffle_palette_vector(png_structrp png_ptr)
|
||||||
|
{
|
||||||
|
png_const_bytep palette = (png_const_bytep)png_ptr->palette;
|
||||||
|
png_bytep riffled_palette = png_ptr->riffled_palette;
|
||||||
|
png_const_bytep trans_alpha = png_ptr->trans_alpha;
|
||||||
|
|
||||||
|
size_t len = 256;
|
||||||
|
|
||||||
|
vuint8m1_t r;
|
||||||
|
vuint8m1_t g;
|
||||||
|
vuint8m1_t b;
|
||||||
|
|
||||||
|
for (size_t vl; len > 0; len -= vl, palette += vl * 3, trans_alpha += vl, riffled_palette += vl * 4) {
|
||||||
|
vl = __riscv_vsetvl_e8m1(len);
|
||||||
|
|
||||||
|
__riscv_vlseg3e8_v_u8m1(&r, &g, &b, palette, vl);
|
||||||
|
vuint8m1_t a = __riscv_vle8_v_u8m1(trans_alpha, vl);
|
||||||
|
|
||||||
|
__riscv_vsseg4e8_v_u8m1(riffled_palette, r, g, b, a, vl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
png_do_expand_palette_rgba8_vector(png_structrp png_ptr, png_row_infop row_info,
|
||||||
|
png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
|
||||||
|
{
|
||||||
|
size_t row_width = (size_t)row_info->width;
|
||||||
|
const png_uint_32* palette = (const png_uint_32*)png_ptr->riffled_palette;
|
||||||
|
|
||||||
|
size_t vl = __riscv_vsetvl_e8m1(row_width);
|
||||||
|
png_bytep sp = *ssp - vl;
|
||||||
|
png_bytep dp = *ddp - vl * 4;
|
||||||
|
|
||||||
|
for (; row_width > 0; row_width -= vl, dp -= vl * 4, sp -= vl) {
|
||||||
|
vl = __riscv_vsetvl_e8m1(row_width);
|
||||||
|
|
||||||
|
vuint8m1_t indices = __riscv_vle8_v_u8m1(sp, vl);
|
||||||
|
|
||||||
|
vuint32m4_t pixels = __riscv_vluxei8_v_u32m4(palette, indices, vl);
|
||||||
|
|
||||||
|
__riscv_vse32_v_u32m4((unsigned int *)dp, pixels, vl);
|
||||||
|
}
|
||||||
|
|
||||||
|
row_width = (size_t)row_info->width;
|
||||||
|
|
||||||
|
*ssp = *ssp - row_width;
|
||||||
|
*ddp = *ddp - row_width * 4;
|
||||||
|
|
||||||
|
return row_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
png_do_expand_palette_rgb8_vector(png_structrp png_ptr, png_row_infop row_info,
|
||||||
|
png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
|
||||||
|
{
|
||||||
|
size_t row_width = (size_t)row_info->width;
|
||||||
|
const png_const_bytep palette = (png_const_bytep)png_ptr->palette;
|
||||||
|
|
||||||
|
size_t vl = __riscv_vsetvl_e8m1(row_width);
|
||||||
|
png_bytep sp = *ssp - vl;
|
||||||
|
png_bytep dp = *ddp - vl * 3;
|
||||||
|
|
||||||
|
vuint8m1_t r;
|
||||||
|
vuint8m1_t g;
|
||||||
|
vuint8m1_t b;
|
||||||
|
|
||||||
|
|
||||||
|
for (; row_width > 0; row_width -= vl, dp -= vl * 3, sp -= vl) {
|
||||||
|
vl = __riscv_vsetvl_e8m1(row_width);
|
||||||
|
|
||||||
|
vuint16m2_t indices = __riscv_vwmulu_vx_u16m2(__riscv_vle8_v_u8m1(sp, vl), 3, vl);
|
||||||
|
|
||||||
|
__riscv_vluxseg3ei16_v_u8m1(&r, &g, &b, palette, indices, vl);
|
||||||
|
|
||||||
|
__riscv_vsseg3e8_v_u8m1(dp, r, g, b, vl);
|
||||||
|
}
|
||||||
|
|
||||||
|
row_width = (size_t)row_info->width;
|
||||||
|
|
||||||
|
*ssp = *ssp - row_width;
|
||||||
|
*ddp = *ddp - row_width * 3;
|
||||||
|
|
||||||
|
return row_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* PNG_ARM_NEON_IMPLEMENTATION */
|
130
riscv/riscv_init.c
Normal file
130
riscv/riscv_init.c
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/* arm_init.c - RISC-V Vector optimized filter functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Google LLC
|
||||||
|
* Written by Dragoș Tiselice <dtiselice@google.com>, May 2023.
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
#ifdef PNG_READ_SUPPORTED
|
||||||
|
|
||||||
|
#if PNG_RISCV_VECTOR_OPT > 0
|
||||||
|
#ifdef PNG_RISCV_VECTOR_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
|
||||||
|
* RISC-V Vector 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_RISCV_VECTOR_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/riscv-vector, but the only one that
|
||||||
|
* has partial support is contrib/riscv-vector/linux.c - a generic Linux
|
||||||
|
* implementation which reads /proc/cpuinfo.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PNG_RISCV_VECTOR_FILE
|
||||||
|
# if defined(__linux__)
|
||||||
|
# define PNG_RISCV_VECTOR_FILE "contrib/riscv-vector/linux.c"
|
||||||
|
# else
|
||||||
|
# error "No support for run-time RISC-V Vector checking; use compile-time options"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int png_have_vector(png_structp png_ptr);
|
||||||
|
#ifdef PNG_RISCV_VECTOR_FILE
|
||||||
|
# include PNG_RISCV_VECTOR_FILE
|
||||||
|
#endif
|
||||||
|
#endif /* PNG_RISCV_VECTOR_CHECK_SUPPORTED */
|
||||||
|
|
||||||
|
void
|
||||||
|
png_init_filter_functions_vector(png_structp pp, unsigned int bpp)
|
||||||
|
{
|
||||||
|
/* The switch statement is compiled in for RISCV_VECTOR_API, the call to
|
||||||
|
* png_have_vector is compiled in for RISCV_VECTOR_CHECK. If both are
|
||||||
|
* defined the check is only performed if the API has not set the VECTOR
|
||||||
|
* 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_vector");
|
||||||
|
#ifdef PNG_RISCV_VECTOR_API_SUPPORTED
|
||||||
|
switch ((pp->options >> PNG_RISCV_VECTOR) & 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_RISCV_VECTOR_API_SUPPORTED */
|
||||||
|
#ifdef PNG_RISCV_VECTOR_CHECK_SUPPORTED
|
||||||
|
{
|
||||||
|
static volatile sig_atomic_t no_vector = -1; /* not checked */
|
||||||
|
|
||||||
|
if (no_vector < 0)
|
||||||
|
no_vector = !png_have_vector(pp);
|
||||||
|
|
||||||
|
if (no_vector)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef PNG_RISCV_VECTOR_API_SUPPORTED
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#endif /* PNG_RISCV_VECTOR_CHECK_SUPPORTED */
|
||||||
|
|
||||||
|
#ifdef PNG_RISCV_VECTOR_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_
|
||||||
|
*
|
||||||
|
* 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_vector;
|
||||||
|
|
||||||
|
if (bpp == 3)
|
||||||
|
{
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_vector;
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_vector;
|
||||||
|
if (__riscv_vsetvlmax_e8m1() > 16) {
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_vector_128;
|
||||||
|
} else {
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_vector_256;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bpp == 4)
|
||||||
|
{
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_vector;
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_vector;
|
||||||
|
if (__riscv_vsetvlmax_e8m1() > 16) {
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_vector_128;
|
||||||
|
} else {
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_vector_256;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* PNG_RISCV_VECTOR_OPT > 0 */
|
||||||
|
#endif /* PNG_READ_SUPPORTED */
|
Loading…
x
Reference in New Issue
Block a user