Compare commits

...

9 Commits

Author SHA1 Message Date
Filip Wasil
4266c75f40 riscv: Remove unused argument
Signed-off-by: Cosmin Truta <ctruta@gmail.com>
2025-06-28 16:19:11 +03:00
Filip Wasil
f451a4de09 riscv: Simplify the runtime check to always be present
Signed-off-by: Cosmin Truta <ctruta@gmail.com>
2025-06-28 16:19:11 +03:00
Filip Wasil
6aa47debba riscv: Do not overwrite -march when testing against SIMD availability
Signed-off-by: Cosmin Truta <ctruta@gmail.com>
2025-06-28 16:19:11 +03:00
Filip Wasil
3391bb98e3 riscv: Use C intrinsics
Signed-off-by: Cosmin Truta <ctruta@gmail.com>
2025-06-28 16:19:11 +03:00
Filip Wasil
21895b05ab riscv: Clearly separate the build flow for autotools and cmake
Signed-off-by: Cosmin Truta <ctruta@gmail.com>
2025-06-18 14:43:36 +03:00
Cosmin Truta
be81ebe1a4 chore: Rerun ./autogen.sh --maintainer 2025-06-17 11:41:32 +03:00
Filip Wasil
edf46621f3 riscv: Improve the RVV availability check
In some cases, the vector extension is not supported, although the
compiler allows the "v" flag in `-march` and includes `<riscv_vector>`
without raising an error.

Signed-off-by: Cosmin Truta <ctruta@gmail.com>
2025-06-17 11:40:57 +03:00
Cosmin Truta
5dc5937b30 chore: Update .gitignore
This is a cherry-pick of commit df3b9173277aae60b08a216dc23484f6ec171ef5
from branch 'libpng18'.
2025-06-14 18:35:46 +03:00
Cosmin Truta
7084241c75 Bump version to 1.6.50.git 2025-06-14 17:13:02 +03:00
18 changed files with 206 additions and 255 deletions

24
.gitignore vendored
View File

@@ -122,6 +122,7 @@ ipch/
*.out
*out.png
[._]deps/
[._]libs/
.dirstamp
/Makefile
/autom4te.cache/
@@ -143,13 +144,16 @@ pnglibconf.dfn
pnglibconf.pre
pngprefix.h
# Libpng test programs
png-fix-itxt
pngcp
pngfix
pngimage
pngstest
pngtest
pngunknown
pngvalid
timepng
# Libpng test programs, scripts and artifacts
/test-suite.log
/tests/*.log
/tests/*.trs
/png-fix-itxt
/pngcp
/pngfix
/pngimage
/pngstest
/pngtest
/pngunknown
/pngvalid
/timepng

View File

@@ -1,3 +1,11 @@
libpng 1.6.50.git
=================
This is a development version, not intended to be a public release.
It will be replaced by a public release, or by another development
version, at a later time.
libpng 1.6.49 - June 12, 2025
=============================

View File

@@ -6267,6 +6267,8 @@ Version 1.6.49 [June 12, 2025]
Added various fixes and improvements to the build scripts and to
the sample code.
Version 1.6.50 [TODO]
Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
Subscription is required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement

View File

@@ -18,9 +18,9 @@ cmake_minimum_required(VERSION 3.14...4.0)
set(PNGLIB_MAJOR 1)
set(PNGLIB_MINOR 6)
set(PNGLIB_REVISION 49)
set(PNGLIB_SUBREVISION 0)
#set(PNGLIB_SUBREVISION "git")
set(PNGLIB_REVISION 50)
#set(PNGLIB_SUBREVISION 0)
set(PNGLIB_SUBREVISION "git")
set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_REVISION})
set(PNGLIB_ABI_VERSION ${PNGLIB_MAJOR}${PNGLIB_MINOR})
set(PNGLIB_SHARED_VERSION ${PNGLIB_ABI_VERSION}.${PNGLIB_REVISION}.${PNGLIB_SUBREVISION})
@@ -322,26 +322,40 @@ if(PNG_HARDWARE_OPTIMIZATIONS)
# Set definitions and sources for RISC-V.
if(PNG_TARGET_ARCHITECTURE MATCHES "^(riscv)")
include(CheckCCompilerFlag)
set(PNG_RISCV_RVV_POSSIBLE_VALUES check on off)
set(PNG_RISCV_RVV_POSSIBLE_VALUES on off)
set(PNG_RISCV_RVV "off"
CACHE STRING "Enable RISC-V Vector optimizations: check|on|off; off is default")
CACHE STRING "Enable RISC-V Vector optimizations: on|off; off is default")
set_property(CACHE PNG_RISCV_RVV
PROPERTY STRINGS ${PNG_RISCV_RVV_POSSIBLE_VALUES})
list(FIND PNG_RISCV_RVV_POSSIBLE_VALUES ${PNG_RISCV_RVV} index)
if(index EQUAL -1)
message(FATAL_ERROR "PNG_RISCV_RVV must be one of [${PNG_RISCV_RVV_POSSIBLE_VALUES}]")
elseif(NOT PNG_RISCV_RVV STREQUAL "off")
check_c_compiler_flag("-march=rv64gv1p0" COMPILER_SUPPORTS_RVV)
check_c_source_compiles("
#include <riscv_vector.h>
#include <asm/hwcap.h>
#ifndef COMPAT_HWCAP_ISA_V /* added in linux-6.5 */
#error \"COMPAT_HWCAP_ISA_V is not available\"
#endif
int main() {
const float src[] = { 0.0f, 0.0f, 0.0f, 0.0f };
uint64_t ptr[2] = {0x0908060504020100, 0xFFFFFFFF0E0D0C0A};
vuint8m1_t a = __riscv_vreinterpret_v_u64m1_u8m1(__riscv_vle64_v_u64m1(ptr, 2));
vfloat32m1_t val = __riscv_vle32_v_f32m1((const float*)(src), 4);
return (int)__riscv_vfmv_f_s_f32m1_f32(val);
}" COMPILER_SUPPORTS_RVV)
if(NOT COMPILER_SUPPORTS_RVV)
message(FATAL_ERROR "Compiler does not support -march=rv64gv1p0 option")
message(FATAL_ERROR "Compiler does not support RISC-V Vector extension or its unable to detect it")
endif()
set(libpng_riscv_sources
riscv/filter_rvv_intrinsics.c
riscv/riscv_init.c)
if(PNG_RISCV_RVV STREQUAL "on")
add_definitions(-DPNG_RISCV_RVV_OPT=2)
elseif(PNG_RISCV_RVV STREQUAL "check")
add_definitions(-DPNG_RISCV_RVV_CHECK_SUPPORTED)
else()
add_definitions(-DPNG_RISCV_RVV_OPT=0)
endif()
else()
add_definitions(-DPNG_RISCV_RVV_OPT=0)

4
README
View File

@@ -1,5 +1,5 @@
README for libpng version 1.6.49
================================
README for libpng version 1.6.50.git
====================================
See the note about version numbers near the top of `png.h`.
See `INSTALL` for instructions on how to install libpng.

42
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.72 for libpng 1.6.49.
# Generated by GNU Autoconf 2.72 for libpng 1.6.50.git.
#
# Report bugs to <png-mng-implement@lists.sourceforge.net>.
#
@@ -614,8 +614,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libpng'
PACKAGE_TARNAME='libpng'
PACKAGE_VERSION='1.6.49'
PACKAGE_STRING='libpng 1.6.49'
PACKAGE_VERSION='1.6.50.git'
PACKAGE_STRING='libpng 1.6.50.git'
PACKAGE_BUGREPORT='png-mng-implement@lists.sourceforge.net'
PACKAGE_URL=''
@@ -1424,7 +1424,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
'configure' configures libpng 1.6.49 to adapt to many kinds of systems.
'configure' configures libpng 1.6.50.git to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1495,7 +1495,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of libpng 1.6.49:";;
short | recursive ) echo "Configuration of libpng 1.6.50.git:";;
esac
cat <<\_ACEOF
@@ -1698,7 +1698,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
libpng configure 1.6.49
libpng configure 1.6.50.git
generated by GNU Autoconf 2.72
Copyright (C) 2023 Free Software Foundation, Inc.
@@ -1961,7 +1961,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by libpng $as_me 1.6.49, which was
It was created by libpng $as_me 1.6.50.git, which was
generated by GNU Autoconf 2.72. Invocation command line was
$ $0$ac_configure_args_raw
@@ -3446,7 +3446,7 @@ fi
# Define the identity of the package.
PACKAGE='libpng'
VERSION='1.6.49'
VERSION='1.6.50.git'
printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -3665,10 +3665,10 @@ fi
PNGLIB_VERSION=1.6.49
PNGLIB_VERSION=1.6.50.git
PNGLIB_MAJOR=1
PNGLIB_MINOR=6
PNGLIB_RELEASE=49
PNGLIB_RELEASE=50
@@ -15733,10 +15733,10 @@ printf "%s\n" "#define PNG_RISCV_RVV_API_SUPPORTED /**/" >>confdefs.h
printf "%s\n" "#define PNG_RISCV_RVV_OPT 2" >>confdefs.h
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --enable-riscv-rvv: please specify 'check' or 'api', if
you want the optimizations unconditionally pass e.g. '-march=rv64gv'
you want the optimizations unconditionally pass e.g. '-march=rv64gv1p0'
to the compiler." >&5
printf "%s\n" "$as_me: WARNING: --enable-riscv-rvv: please specify 'check' or 'api', if
you want the optimizations unconditionally pass e.g. '-march=rv64gv'
you want the optimizations unconditionally pass e.g. '-march=rv64gv1p0'
to the compiler." >&2;};;
*)
as_fn_error $? "--enable-riscv-rvv=${enable_riscv_rvv}: invalid value" "$LINENO" 5
@@ -15755,13 +15755,21 @@ then
printf %s "checking whether to use RISC-V RVV intrinsics... " >&6; }
save_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS -march=rv64gv"
CFLAGS="$CFLAGS -march=rv64gv1p0"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <riscv_vector.h>
int main(){
return 0;
#include <asm/hwcap.h>
#ifndef COMPAT_HWCAP_ISA_V /* added in linux-6.5 */
#error "COMPAT_HWCAP_ISA_V is not available"
#endif
int main() {
const float src[] = { 0.0f, 0.0f, 0.0f, 0.0f };
uint64_t ptr[2] = {0x0908060504020100, 0xFFFFFFFF0E0D0C0A};
vuint8m1_t a = __riscv_vreinterpret_v_u64m1_u8m1(__riscv_vle64_v_u64m1(ptr, 2));
vfloat32m1_t val = __riscv_vle32_v_f32m1((const float*)(src), 4);
return (int)__riscv_vfmv_f_s_f32m1_f32(val);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
@@ -16419,7 +16427,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by libpng $as_me 1.6.49, which was
This file was extended by libpng $as_me 1.6.50.git, which was
generated by GNU Autoconf 2.72. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -16487,7 +16495,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
libpng config.status 1.6.49
libpng config.status 1.6.50.git
configured by $0, generated by GNU Autoconf 2.72,
with options \\"\$ac_cs_config\\"

View File

@@ -25,7 +25,7 @@ AC_PREREQ([2.68])
dnl Version number stuff here:
AC_INIT([libpng],[1.6.49],[png-mng-implement@lists.sourceforge.net])
AC_INIT([libpng],[1.6.50.git],[png-mng-implement@lists.sourceforge.net])
AC_CONFIG_MACRO_DIR([scripts/autoconf])
# libpng does not follow GNU file name conventions (hence 'foreign')
@@ -46,10 +46,10 @@ dnl automake, so the following is not necessary (and is not defined anyway):
dnl AM_PREREQ([1.11.2])
dnl stop configure from automagically running automake
PNGLIB_VERSION=1.6.49
PNGLIB_VERSION=1.6.50.git
PNGLIB_MAJOR=1
PNGLIB_MINOR=6
PNGLIB_RELEASE=49
PNGLIB_RELEASE=50
dnl End of version number stuff
@@ -679,8 +679,7 @@ AS_HELP_STRING([[[--enable-riscv-rvv]]],
[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.]),
[yes/on: turn on. If not specified: determined by the compiler.]),
[case "$enableval" in
no|off)
# disable the default enabling on __riscv systems:
@@ -688,20 +687,11 @@ AS_HELP_STRING([[[--enable-riscv-rvv]]],
[Disable RISC-V Vector optimizations])
# Prevent inclusion of the platform-specific files below:
enable_riscv_rvv=no ;;
check)
AC_DEFINE([PNG_RISCV_RVV_CHECK_SUPPORTED], [],
[Check for RISC-V Vector support at run-time])
AC_MSG_WARN([--enable-riscv-rvv Please check contrib/riscv-rvv/README file]
[for the list of supported OSes.]);;
api)
AC_DEFINE([PNG_RISCV_RVV_API_SUPPORTED], [],
[Turn on RISC-V Vector optimizations at run-time]);;
yes|on)
AC_DEFINE([PNG_RISCV_RVV_OPT], [2],
[Enable RISC-V Vector optimizations])
AC_MSG_WARN([--enable-riscv-rvv: please specify 'check' or 'api', if]
[you want the optimizations unconditionally pass e.g. '-march=rv64gv']
[to the compiler.]);;
AC_MSG_WARN([--enable-riscv-rvv:]
[if you want the optimizations pass e.g. '-march=rv64gv1p0' to the compiler.]);;
*)
AC_MSG_ERROR([--enable-riscv-rvv=${enable_riscv_rvv}: invalid value])
esac])
@@ -715,12 +705,18 @@ then
compiler_support_riscv_rvv=no
AC_MSG_CHECKING(whether to use RISC-V RVV intrinsics)
save_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS -march=rv64gv"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#include <riscv_vector.h>
int main(){
return 0;
#include <asm/hwcap.h>
#ifndef COMPAT_HWCAP_ISA_V /* added in linux-6.5 */
#error "COMPAT_HWCAP_ISA_V is not available"
#endif
int main() {
const float src[] = { 0.0f, 0.0f, 0.0f, 0.0f };
uint64_t ptr[2] = {0x0908060504020100, 0xFFFFFFFF0E0D0C0A};
vuint8m1_t a = __riscv_vreinterpret_v_u64m1_u8m1(__riscv_vle64_v_u64m1(ptr, 2));
vfloat32m1_t val = __riscv_vle32_v_f32m1((const float*)(src), 4);
return (int)__riscv_vfmv_f_s_f32m1_f32(val);
}]])],compiler_support_riscv_rvv=yes)
AC_MSG_RESULT($compiler_support_riscv_rvv)
if test "$compiler_support_riscv_rvv" = "yes"; then
@@ -729,7 +725,6 @@ int main(){
else
AC_MSG_WARN([Compiler does not support riscv rvv.])
fi
CFLAGS=$save_CFLAGS
fi
# Add RISC-V-specific files to all builds where $host_cpu is riscv ('riscv64')

View File

@@ -25,7 +25,7 @@
#endif
static int
png_have_rvv(png_structp png_ptr) {
png_have_rvv() {
#if defined(__linux__)
return getauxval (AT_HWCAP) & COMPAT_HWCAP_ISA_V ? 1 : 0;
#else

4
png.c
View File

@@ -13,7 +13,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
typedef png_libpng_version_1_6_49 Your_png_h_is_not_version_1_6_49;
typedef png_libpng_version_1_6_50_git Your_png_h_is_not_version_1_6_50_git;
/* Sanity check the chunks definitions - PNG_KNOWN_CHUNKS from pngpriv.h and the
* corresponding macro definitions. This causes a compile time failure if
@@ -815,7 +815,7 @@ png_get_copyright(png_const_structrp png_ptr)
return PNG_STRING_COPYRIGHT
#else
return PNG_STRING_NEWLINE \
"libpng version 1.6.49" PNG_STRING_NEWLINE \
"libpng version 1.6.50.git" PNG_STRING_NEWLINE \
"Copyright (c) 2018-2025 Cosmin Truta" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
PNG_STRING_NEWLINE \

14
png.h
View File

@@ -1,6 +1,6 @@
/* png.h - header file for PNG reference library
*
* libpng version 1.6.49
* libpng version 1.6.50.git
*
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
@@ -274,7 +274,7 @@
*/
/* Version information for png.h - this should match the version in png.c */
#define PNG_LIBPNG_VER_STRING "1.6.49"
#define PNG_LIBPNG_VER_STRING "1.6.50.git"
#define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n"
/* The versions of shared library builds should stay in sync, going forward */
@@ -285,12 +285,12 @@
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 6
#define PNG_LIBPNG_VER_RELEASE 49
#define PNG_LIBPNG_VER_RELEASE 50
/* This should be zero for a public release, or non-zero for a
* development version.
*/
#define PNG_LIBPNG_VER_BUILD 0
#define PNG_LIBPNG_VER_BUILD 1
/* Release Status */
#define PNG_LIBPNG_BUILD_ALPHA 1
@@ -307,7 +307,7 @@
#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with
PNG_LIBPNG_BUILD_PRIVATE */
#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE
#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA
/* Careful here. At one time, Guy wanted to use 082, but that
* would be octal. We must not include leading zeros.
@@ -316,7 +316,7 @@
* From version 1.0.1 it is:
* XXYYZZ, where XX=major, YY=minor, ZZ=release
*/
#define PNG_LIBPNG_VER 10649 /* 1.6.49 */
#define PNG_LIBPNG_VER 10650 /* 1.6.50.git */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -426,7 +426,7 @@ extern "C" {
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
typedef char* png_libpng_version_1_6_49;
typedef char* png_libpng_version_1_6_50_git;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*

View File

@@ -1,6 +1,6 @@
/* pngconf.h - machine-configurable file for libpng
*
* libpng version 1.6.49
* libpng version 1.6.50.git
*
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson

View File

@@ -154,11 +154,7 @@
* to configure or put -DPNG_RISCV_RVV_OPT=2 in CPPFLAGS.
*/
# if defined(__riscv) && defined(PNG_ALIGNED_MEMORY_SUPPORTED)
# define PNG_RISCV_RVV_OPT 1
# else
# define PNG_RISCV_RVV_OPT 0
# endif
# define PNG_RISCV_RVV_OPT 0
#endif
#if PNG_ARM_NEON_OPT > 0

View File

@@ -50,7 +50,7 @@
#define STDERR stdout
/* Generate a compiler error if there is an old png.h in the search path. */
typedef png_libpng_version_1_6_49 Your_png_h_is_not_version_1_6_49;
typedef png_libpng_version_1_6_50_git Your_png_h_is_not_version_1_6_50_git;
/* Ensure that all version numbers in png.h are consistent with one another. */
#if (PNG_LIBPNG_VER != PNG_LIBPNG_VER_MAJOR * 10000 + \

View File

@@ -51,21 +51,22 @@ png_read_filter_row_sub_rvv(size_t len, size_t bpp, unsigned char* row)
* x .. [v8](e8)
*/
asm volatile ("vsetvli zero, %0, e8, m1" : : "r" (bpp));
size_t vl = __riscv_vsetvl_e8m1(bpp);
/* a = *row */
asm volatile ("vle8.v v0, (%0)" : : "r" (row));
vuint8m1_t a = __riscv_vle8_v_u8m1(row, vl);
row += bpp;
while (row < rp_end)
{
/* x = *row */
asm volatile ("vle8.v v8, (%0)" : : "r" (row));
vuint8m1_t x = __riscv_vle8_v_u8m1(row, vl);
/* a = a + x */
asm volatile ("vadd.vv v0, v0, v8");
a = __riscv_vadd_vv_u8m1(a, x, vl);
/* *row = a */
asm volatile ("vse8.v v0, (%0)" : : "r" (row));
__riscv_vse8_v_u8m1(row, a, vl);
row += bpp;
}
}
@@ -110,44 +111,46 @@ png_read_filter_row_avg_rvv(size_t len, size_t bpp, unsigned char* row,
/* first pixel */
asm volatile ("vsetvli zero, %0, e8, m1" : : "r" (bpp));
size_t vl = __riscv_vsetvl_e8m1(bpp);
/* b = *prev_row */
asm volatile ("vle8.v v4, (%0)" : : "r" (prev_row));
vuint8m1_t b = __riscv_vle8_v_u8m1(prev_row, vl);
prev_row += bpp;
/* x = *row */
asm volatile ("vle8.v v8, (%0)" : : "r" (row));
vuint8m1_t x = __riscv_vle8_v_u8m1(row, vl);
/* b = b / 2 */
asm volatile ("vsrl.vi v4, v4, 1");
b = __riscv_vsrl_vx_u8m1(b, 1, vl);
/* a = x + b */
asm volatile ("vadd.vv v2, v4, v8");
vuint8m1_t a = __riscv_vadd_vv_u8m1(b, x, vl);
/* *row = a */
asm volatile ("vse8.v v2, (%0)" : : "r" (row));
__riscv_vse8_v_u8m1(row, a, vl);
row += bpp;
/* remaining pixels */
while (row < rp_end)
{
/* b = *prev_row */
asm volatile ("vle8.v v4, (%0)" : : "r" (prev_row));
b = __riscv_vle8_v_u8m1(prev_row, vl);
prev_row += bpp;
/* x = *row */
asm volatile ("vle8.v v8, (%0)" : : "r" (row));
x = __riscv_vle8_v_u8m1(row, vl);
/* tmp = a + b */
asm volatile ("vwaddu.vv v12, v2, v4"); /* add with widening */
vuint16m2_t tmp = __riscv_vwaddu_vv_u16m2(a, b, vl);
/* a = tmp/2 */
asm volatile ("vnsrl.wi v2, v12, 1"); /* divide/shift with narrowing */
a = __riscv_vnsrl_wx_u8m1(tmp, 1, vl);
/* a += x */
asm volatile ("vadd.vv v2, v2, v8");
a = __riscv_vadd_vv_u8m1(a, x, vl);
/* *row = a */
asm volatile ("vse8.v v2, (%0)" : : "r" (row));
__riscv_vse8_v_u8m1(row, a, vl);
row += bpp;
}
}
@@ -205,18 +208,14 @@ 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);
vbool16_t mask = __riscv_vmslt_vx_i16m1_b16(diff, 0, vl);
return __riscv_vrsub_vx_i16m1_m(mask, diff, 0, 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);
return __riscv_vadd_vv_i16m1(a, b, vl);
}
static inline void
@@ -226,122 +225,109 @@ png_read_filter_row_paeth_rvv(size_t len, size_t bpp, unsigned char* row,
png_bytep rp_end = row + len;
/*
* row: | a | x |
* prev: | c | b |
* row: | a | x |
* prev: | c | b |
*
* mask .. [v0]
* a .. [v2](e8)
* b .. [v4](e8)
* c .. [v6](e8)
* x .. [v8](e8)
* p .. [v12-v13](e16)
* pa .. [v16-v17](e16)
* pb .. [v20-v21](e16)
* pc .. [v24-v25](e16)
* tmpmask ..[v31]
* a .. [v2](e8)
* b .. [v4](e8)
* c .. [v6](e8)
* x .. [v8](e8)
* p .. [v12-v13](e16)
* pa, pb, pc .. [v16-v17, v20-v21, v24-v25](e16)
*/
/* first pixel */
asm volatile ("vsetvli zero, %0, e8, m1" : : "r" (bpp));
size_t vl = __riscv_vsetvl_e8m1(bpp);
/* a = *row + *prev_row */
asm volatile ("vle8.v v2, (%0)" : : "r" (row));
asm volatile ("vle8.v v6, (%0)" : : "r" (prev));
prev += bpp;
asm volatile ("vadd.vv v2, v2, v6");
/* a = *row */
vuint8m1_t a = __riscv_vle8_v_u8m1(row, vl);
/* c = *prev */
vuint8m1_t c = __riscv_vle8_v_u8m1(prev, vl);
/* a += c */
a = __riscv_vadd_vv_u8m1(a, c, vl);
/* *row = a */
asm volatile ("vse8.v v2, (%0)" : : "r" (row));
__riscv_vse8_v_u8m1(row, a, vl);
row += bpp;
prev += bpp;
/* remaining pixels */
while (row < rp_end)
{
/* b = *prev_row */
asm volatile ("vle8.v v4, (%0)" : : "r" (prev));
/* b = *prev */
vuint8m1_t b = __riscv_vle8_v_u8m1(prev, vl);
prev += bpp;
/* x = *row */
asm volatile ("vle8.v v8, (%0)" : : "r" (row));
vuint8m1_t x = __riscv_vle8_v_u8m1(row, vl);
/* sub (widening to 16bit) */
/* p = b - c */
asm volatile ("vwsubu.vv v12, v4, v6");
/* pc = a - c */
asm volatile ("vwsubu.vv v24, v2, v6");
/* Calculate p = b - c and pc = a - c using widening subtraction */
vuint16m2_t p_wide = __riscv_vwsubu_vv_u16m2(b, c, vl);
vuint16m2_t pc_wide = __riscv_vwsubu_vv_u16m2(a, c, vl);
/* switch to widened */
asm volatile ("vsetvli zero, %0, e16, m2" : : "r" (bpp));
/* Convert to signed for easier manipulation */
size_t vl16 = __riscv_vsetvl_e16m2(bpp);
vint16m2_t p = __riscv_vreinterpret_v_u16m2_i16m2(p_wide);
vint16m2_t pc = __riscv_vreinterpret_v_u16m2_i16m2(pc_wide);
/* pa = abs(p) -> pa = p < 0 ? -p : p */
asm volatile ("vmv.v.v v16, v12"); /* pa = p */
asm volatile ("vmslt.vx v0, v16, zero"); /* set mask[i] if pa[i] < 0 */
asm volatile ("vrsub.vx v16, v16, zero, v0.t"); /* invert negative values in pa; vd[i] = 0 - vs2[i] (if mask[i])
* could be replaced by vneg in rvv >= 1.0
*/
/* pa = |p| */
vbool8_t p_neg_mask = __riscv_vmslt_vx_i16m2_b8(p, 0, vl16);
vint16m2_t pa = __riscv_vrsub_vx_i16m2_m(p_neg_mask, p, 0, vl16);
/* pb = abs(p) -> pb = pc < 0 ? -pc : pc */
asm volatile ("vmv.v.v v20, v24"); /* pb = pc */
asm volatile ("vmslt.vx v0, v20, zero"); /* set mask[i] if pc[i] < 0 */
asm volatile ("vrsub.vx v20, v20, zero, v0.t"); /* invert negative values in pb; vd[i] = 0 - vs2[i] (if mask[i])
* could be replaced by vneg in rvv >= 1.0
*/
/* pb = |pc| */
vbool8_t pc_neg_mask = __riscv_vmslt_vx_i16m2_b8(pc, 0, vl16);
vint16m2_t pb = __riscv_vrsub_vx_i16m2_m(pc_neg_mask, pc, 0, vl16);
/* pc = abs(p + pc) -> pc = (p + pc) < 0 ? -(p + pc) : p + pc */
asm volatile ("vadd.vv v24, v24, v12"); /* pc = p + pc */
asm volatile ("vmslt.vx v0, v24, zero"); /* set mask[i] if pc[i] < 0 */
asm volatile ("vrsub.vx v24, v24, zero, v0.t"); /* invert negative values in pc; vd[i] = 0 - vs2[i] (if mask[i])
* could be replaced by vneg in rvv >= 1.0
*/
/* pc = |p + pc| */
vint16m2_t p_plus_pc = __riscv_vadd_vv_i16m2(p, pc, vl16);
vbool8_t p_plus_pc_neg_mask = __riscv_vmslt_vx_i16m2_b8(p_plus_pc, 0, vl16);
pc = __riscv_vrsub_vx_i16m2_m(p_plus_pc_neg_mask, p_plus_pc, 0, vl16);
/*
* if (pb < pa)
* {
* pa = pb;
* a = b;
* // see (*1)
* }
* The key insight is that we want the minimum of pa, pb, pc.
* - If pa <= pb and pa <= pc, use a
* - Else if pb <= pc, use b
* - Else use c
*/
asm volatile ("vmslt.vv v0, v20, v16"); /* set mask[i] if pb[i] < pa[i] */
asm volatile ("vmerge.vvm v16, v16, v20, v0"); /* pa[i] = pb[i] (if mask[i]) */
/*
* if (pc < pa)
* {
* a = c;
* // see (*2)
* }
*/
asm volatile ("vmslt.vv v31, v24, v16"); /* set tmpmask[i] if pc[i] < pa[i] */
/* Find which predictor to use based on minimum absolute difference */
vbool8_t pa_le_pb = __riscv_vmsle_vv_i16m2_b8(pa, pb, vl16);
vbool8_t pa_le_pc = __riscv_vmsle_vv_i16m2_b8(pa, pc, vl16);
vbool8_t pb_le_pc = __riscv_vmsle_vv_i16m2_b8(pb, pc, vl16);
/* switch to narrow */
asm volatile ("vsetvli zero, %0, e8, m1" : : "r" (bpp));
/* use_a = pa <= pb && pa <= pc */
vbool8_t use_a = __riscv_vmand_mm_b8(pa_le_pb, pa_le_pc, vl16);
/* (*1) */
asm volatile ("vmerge.vvm v2, v2, v4, v0"); /* a = b (if mask[i]) */
/* use_b = !use_a && pb <= pc */
vbool8_t not_use_a = __riscv_vmnot_m_b8(use_a, vl16);
vbool8_t use_b = __riscv_vmand_mm_b8(not_use_a, pb_le_pc, vl16);
/* (*2) */
asm volatile ("vmand.mm v0, v31, v31"); /* mask = tmpmask
* vmand works for rvv 0.7 up to 1.0
* could be replaced by vmcpy in 0.7.1/0.8.1
* or vmmv.m in 1.0
*/
asm volatile ("vmerge.vvm v2, v2, v6, v0"); /* a = c (if mask[i]) */
/* Switch back to e8m1 for final operations */
vl = __riscv_vsetvl_e8m1(bpp);
/* a += x */
asm volatile ("vadd.vv v2, v2, v8");
/* Start with a, then conditionally replace with b or c */
vuint8m1_t result = a;
result = __riscv_vmerge_vvm_u8m1(result, b, use_b, vl);
/* use_c = !use_a && !use_b */
vbool8_t use_c = __riscv_vmnand_mm_b8(__riscv_vmor_mm_b8(use_a, use_b, vl), __riscv_vmor_mm_b8(use_a, use_b, vl), vl);
result = __riscv_vmerge_vvm_u8m1(result, c, use_c, vl);
/* a = result + x */
a = __riscv_vadd_vv_u8m1(result, x, vl);
/* *row = a */
asm volatile ("vse8.v v2, (%0)" : : "r" (row));
__riscv_vse8_v_u8m1(row, a, vl);
row += bpp;
/* prepare next iteration (prev is already in a) */
/* c = b */
asm volatile ("vmv.v.v v6, v4");
/* c = b for next iteration */
c = b;
}
}
void
png_read_filter_row_paeth3_rvv(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
@@ -349,8 +335,6 @@ png_read_filter_row_paeth3_rvv(png_row_infop row_info, png_bytep row,
size_t len = row_info->rowbytes;
png_read_filter_row_paeth_rvv(len, 3, row, prev_row);
PNG_UNUSED(prev_row)
}
void
@@ -360,9 +344,7 @@ png_read_filter_row_paeth4_rvv(png_row_infop row_info, png_bytep row,
size_t len = row_info->rowbytes;
png_read_filter_row_paeth_rvv(len, 4, row, prev_row);
PNG_UNUSED(prev_row)
}
#endif /* PNG_RISCV_RVV_IMPLEMENTATION */
#endif /* READ */
#endif /* PNG_RISCV_RVV_IMPLEMENTATION == 1 */
#endif /* PNG_READ_SUPPORTED */

View File

@@ -16,20 +16,6 @@
#include <riscv_vector.h>
#ifdef PNG_RISCV_RVV_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_RVV_FILE to the file name of file containing
* a fragment of C source code which defines the png_have_rvv function. There
* are a number of implementations in contrib/riscv-rvv, but the only one that
* has partial support is contrib/riscv-rvv/linux.c - a generic Linux
* implementation which reads /proc/cpuinfo.
*/
#include <signal.h>
#ifndef PNG_RISCV_RVV_FILE
@@ -40,11 +26,10 @@
# endif
#endif
static int png_have_rvv(png_structp png_ptr);
static int png_have_rvv();
#ifdef PNG_RISCV_RVV_FILE
# include PNG_RISCV_RVV_FILE
#endif
#endif /* PNG_RISCV_RVV_CHECK_SUPPORTED */
#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
@@ -53,59 +38,16 @@ static int png_have_rvv(png_structp png_ptr);
void
png_init_filter_functions_rvv(png_structp pp, unsigned int bpp)
{
/* The switch statement is compiled in for RISCV_RVV_API, the call to
* png_have_rvv is compiled in for RISCV_RVV_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.
*/
png_debug(1, "in png_init_filter_functions_rvv");
#ifdef PNG_RISCV_RVV_API_SUPPORTED
switch ((pp->options >> PNG_RISCV_RVV) & 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_RVV_API_SUPPORTED */
#ifdef PNG_RISCV_RVV_CHECK_SUPPORTED
{
static volatile sig_atomic_t no_rvv = -1; /* not checked */
if (no_rvv < 0)
no_rvv = !png_have_rvv(pp);
static volatile sig_atomic_t no_rvv = -1; /* not checked */
if (no_rvv)
return;
}
#ifdef PNG_RISCV_RVV_API_SUPPORTED
break;
#endif
#endif /* PNG_RISCV_RVV_CHECK_SUPPORTED */
if (no_rvv < 0)
no_rvv = !png_have_rvv();
#ifdef PNG_RISCV_RVV_API_SUPPORTED
default: /* OFF or INVALID */
return;
if (no_rvv)
return;
case PNG_OPTION_ON:
/* Option turned on */
break;
}
#endif /* PNG_RISCV_RVV_API_SUPPORTED */
/* 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_rvv;
if (bpp == 3)

View File

@@ -11,7 +11,7 @@
# Modeled after libxml-config.
version=1.6.49
version=1.6.50.git
prefix=""
libdir=""
libs=""

View File

@@ -5,6 +5,6 @@ includedir=@includedir@/libpng16
Name: libpng
Description: Loads and saves PNG files
Version: 1.6.49
Version: 1.6.50.git
Libs: -L${libdir} -lpng16
Cflags: -I${includedir}

View File

@@ -1,6 +1,6 @@
/* pnglibconf.h - library build configuration */
/* libpng version 1.6.49 */
/* libpng version 1.6.50.git */
/* Copyright (c) 2018-2025 Cosmin Truta */
/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */