From d88f080b7ecb988295568718f5f69d2eabc75a24 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 5 Dec 2025 07:52:26 +0300 Subject: [PATCH] Update to libpng 1.6.52 with RISC-V RVV fix. --- .../patches/riscv_rvv_issue_28126.patch | 20 ------ 3rdparty/libpng/png.c | 4 +- 3rdparty/libpng/png.h | 14 ++-- 3rdparty/libpng/pngconf.h | 2 +- 3rdparty/libpng/pngmem.c | 39 ++++++----- 3rdparty/libpng/pngread.c | 51 +++++++++++---- 3rdparty/libpng/pngrtran.c | 1 + 3rdparty/libpng/riscv/filter_rvv_intrinsics.c | 65 +++++++------------ 3rdparty/libpng/riscv/riscv_init.c | 4 +- 9 files changed, 92 insertions(+), 108 deletions(-) delete mode 100644 3rdparty/libpng/patches/riscv_rvv_issue_28126.patch diff --git a/3rdparty/libpng/patches/riscv_rvv_issue_28126.patch b/3rdparty/libpng/patches/riscv_rvv_issue_28126.patch deleted file mode 100644 index 12f8e3a38e..0000000000 --- a/3rdparty/libpng/patches/riscv_rvv_issue_28126.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/3rdparty/libpng/riscv/riscv_init.c b/3rdparty/libpng/riscv/riscv_init.c -index 36a41b54f7..f2796ebccb 100644 ---- a/3rdparty/libpng/riscv/riscv_init.c -+++ b/3rdparty/libpng/riscv/riscv_init.c -@@ -30,13 +30,13 @@ png_init_filter_functions_rvv(png_structp pp, unsigned int bpp) - if (bpp == 3) - { - pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_rvv; -- pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_rvv; -+ //pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_rvv; - pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_rvv; - } - else if (bpp == 4) - { - pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_rvv; -- pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_rvv; -+ //pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_rvv; - pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_rvv; - } - } diff --git a/3rdparty/libpng/png.c b/3rdparty/libpng/png.c index 380c4c19e6..11b65d1f13 100644 --- a/3rdparty/libpng/png.c +++ b/3rdparty/libpng/png.c @@ -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_51 Your_png_h_is_not_version_1_6_51; +typedef png_libpng_version_1_6_52 Your_png_h_is_not_version_1_6_52; /* Sanity check the chunks definitions - PNG_KNOWN_CHUNKS from pngpriv.h and the * corresponding macro definitions. This causes a compile time failure if @@ -817,7 +817,7 @@ png_get_copyright(png_const_structrp png_ptr) return PNG_STRING_COPYRIGHT #else return PNG_STRING_NEWLINE \ - "libpng version 1.6.51" PNG_STRING_NEWLINE \ + "libpng version 1.6.52" 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 \ diff --git a/3rdparty/libpng/png.h b/3rdparty/libpng/png.h index fb93d2242b..bceb9aa45d 100644 --- a/3rdparty/libpng/png.h +++ b/3rdparty/libpng/png.h @@ -1,6 +1,6 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.51 + * libpng version 1.6.52 * * Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson @@ -14,7 +14,7 @@ * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger * libpng versions 0.97, January 1998, through 1.6.35, July 2018: * Glenn Randers-Pehrson - * libpng versions 1.6.36, December 2018, through 1.6.51, November 2025: + * libpng versions 1.6.36, December 2018, through 1.6.52, December 2025: * Cosmin Truta * See also "Contributing Authors", below. */ @@ -238,7 +238,7 @@ * ... * 1.5.30 15 10530 15.so.15.30[.0] * ... - * 1.6.51 16 10651 16.so.16.51[.0] + * 1.6.52 16 10651 16.so.16.52[.0] * * Henceforth the source version will match the shared-library major and * minor numbers; the shared-library major version number will be used for @@ -274,7 +274,7 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.51" +#define PNG_LIBPNG_VER_STRING "1.6.52" #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,7 +285,7 @@ /* 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 51 +#define PNG_LIBPNG_VER_RELEASE 52 /* This should be zero for a public release, or non-zero for a * development version. @@ -316,7 +316,7 @@ * From version 1.0.1 it is: * XXYYZZ, where XX=major, YY=minor, ZZ=release */ -#define PNG_LIBPNG_VER 10651 /* 1.6.51 */ +#define PNG_LIBPNG_VER 10652 /* 1.6.52 */ /* 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_51; +typedef char* png_libpng_version_1_6_52; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * diff --git a/3rdparty/libpng/pngconf.h b/3rdparty/libpng/pngconf.h index 981df68d87..76b5c20bdf 100644 --- a/3rdparty/libpng/pngconf.h +++ b/3rdparty/libpng/pngconf.h @@ -1,6 +1,6 @@ /* pngconf.h - machine-configurable file for libpng * - * libpng version 1.6.51 + * libpng version 1.6.52 * * Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson diff --git a/3rdparty/libpng/pngmem.c b/3rdparty/libpng/pngmem.c index d391c13ff4..71e61c99f7 100644 --- a/3rdparty/libpng/pngmem.c +++ b/3rdparty/libpng/pngmem.c @@ -1,6 +1,6 @@ /* pngmem.c - stub functions for memory allocation * - * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -72,30 +72,29 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), * to implement a user memory handler. This checks to be sure it isn't * called with big numbers. */ -#ifndef PNG_USER_MEM_SUPPORTED - PNG_UNUSED(png_ptr) -#endif +# ifdef PNG_MAX_MALLOC_64K + /* This is support for legacy systems which had segmented addressing + * limiting the maximum allocation size to 65536. It takes precedence + * over PNG_SIZE_MAX which is set to 65535 on true 16-bit systems. + * + * TODO: libpng-1.8: finally remove both cases. + */ + if (size > 65536U) return NULL; +# endif - /* Some compilers complain that this is always true. However, it - * can be false when integer overflow happens. + /* This is checked too because the system malloc call below takes a (size_t). */ - if (size > 0 && size <= PNG_SIZE_MAX -# ifdef PNG_MAX_MALLOC_64K - && size <= 65536U -# endif - ) - { -#ifdef PNG_USER_MEM_SUPPORTED + if (size > PNG_SIZE_MAX) return NULL; + +# ifdef PNG_USER_MEM_SUPPORTED if (png_ptr != NULL && png_ptr->malloc_fn != NULL) return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size); +# else + PNG_UNUSED(png_ptr) +# endif - else -#endif - return malloc((size_t)size); /* checked for truncation above */ - } - - else - return NULL; + /* Use the system malloc */ + return malloc((size_t)/*SAFE*/size); /* checked for truncation above */ } #if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\ diff --git a/3rdparty/libpng/pngread.c b/3rdparty/libpng/pngread.c index 79917daaaf..f8ca2b7e31 100644 --- a/3rdparty/libpng/pngread.c +++ b/3rdparty/libpng/pngread.c @@ -3207,6 +3207,7 @@ png_image_read_composite(png_voidp argument) ptrdiff_t step_row = display->row_bytes; unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; + int optimize_alpha = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; int pass; for (pass = 0; pass < passes; ++pass) @@ -3263,20 +3264,44 @@ png_image_read_composite(png_voidp argument) if (alpha < 255) /* else just use component */ { - /* This is PNG_OPTIMIZED_ALPHA, the component value - * is a linear 8-bit value. Combine this with the - * current outrow[c] value which is sRGB encoded. - * Arithmetic here is 16-bits to preserve the output - * values correctly. - */ - component *= 257*255; /* =65535 */ - component += (255-alpha)*png_sRGB_table[outrow[c]]; + if (optimize_alpha != 0) + { + /* This is PNG_OPTIMIZED_ALPHA, the component value + * is a linear 8-bit value. Combine this with the + * current outrow[c] value which is sRGB encoded. + * Arithmetic here is 16-bits to preserve the output + * values correctly. + */ + component *= 257*255; /* =65535 */ + component += (255-alpha)*png_sRGB_table[outrow[c]]; - /* So 'component' is scaled by 255*65535 and is - * therefore appropriate for the sRGB to linear - * conversion table. - */ - component = PNG_sRGB_FROM_LINEAR(component); + /* Clamp to the valid range to defend against + * unforeseen cases where the data might be sRGB + * instead of linear premultiplied. + * (Belt-and-suspenders for GitHub Issue #764.) + */ + if (component > 255*65535) + component = 255*65535; + + /* So 'component' is scaled by 255*65535 and is + * therefore appropriate for the sRGB-to-linear + * conversion table. + */ + component = PNG_sRGB_FROM_LINEAR(component); + } + else + { + /* Compositing was already done on the palette + * entries. The data is sRGB premultiplied on black. + * Composite with the background in sRGB space. + * This is not gamma-correct, but matches what was + * done to the palette. + */ + png_uint_32 background = outrow[c]; + component += ((255-alpha) * background + 127) / 255; + if (component > 255) + component = 255; + } } outrow[c] = (png_byte)component; diff --git a/3rdparty/libpng/pngrtran.c b/3rdparty/libpng/pngrtran.c index 2f52022551..507d11381e 100644 --- a/3rdparty/libpng/pngrtran.c +++ b/3rdparty/libpng/pngrtran.c @@ -1843,6 +1843,7 @@ png_init_read_transformations(png_structrp png_ptr) * transformations elsewhere. */ png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; } /* color_type == PNG_COLOR_TYPE_PALETTE */ /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ diff --git a/3rdparty/libpng/riscv/filter_rvv_intrinsics.c b/3rdparty/libpng/riscv/filter_rvv_intrinsics.c index a71e561bba..8d277d14cd 100644 --- a/3rdparty/libpng/riscv/filter_rvv_intrinsics.c +++ b/3rdparty/libpng/riscv/filter_rvv_intrinsics.c @@ -3,7 +3,8 @@ * Copyright (c) 2023 Google LLC * Written by Manfred SCHLAEGL, 2022 * DragoČ™ Tiselice , May 2023. - * Filip Wasil , March 2025. + * Filip Wasil , March 2025. + * Liang Junzhao , November 2025. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -140,11 +141,8 @@ png_read_filter_row_avg_rvv(size_t len, size_t bpp, unsigned char* row, /* x = *row */ x = __riscv_vle8_v_u8m1(row, vl); - /* tmp = a + b */ - vuint16m2_t tmp = __riscv_vwaddu_vv_u16m2(a, b, vl); - - /* a = tmp/2 */ - a = __riscv_vnsrl_wx_u8m1(tmp, 1, vl); + /* a = (a + b) / 2, round to zero with vxrm = 2 */ + a = __riscv_vaaddu_wx_u8m1(a, b, 2, vl); /* a += x */ a = __riscv_vadd_vv_u8m1(a, x, vl); @@ -265,27 +263,22 @@ png_read_filter_row_paeth_rvv(size_t len, size_t bpp, unsigned char* row, /* x = *row */ vuint8m1_t x = __riscv_vle8_v_u8m1(row, vl); - /* 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); - - /* 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); + /* p = b - c and pc = a - c */ + vuint16m2_t p = __riscv_vwsubu_vv_u16m2(b, c, vl); + vuint16m2_t pc = __riscv_vwsubu_vv_u16m2(a, c, vl); /* 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); + vuint16m2_t tmp = __riscv_vrsub_vx_u16m2(p, 0, vl); + vuint16m2_t pa = __riscv_vminu_vv_u16m2(p, tmp, vl); /* 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); + tmp = __riscv_vrsub_vx_u16m2(pc, 0, vl); + vuint16m2_t pb = __riscv_vminu_vv_u16m2(pc, tmp, vl); /* 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); + pc = __riscv_vadd_vv_u16m2(p, pc, vl); + tmp = __riscv_vrsub_vx_u16m2(pc, 0, vl); + pc = __riscv_vminu_vv_u16m2(pc, tmp, vl); /* * The key insight is that we want the minimum of pa, pb, pc. @@ -294,31 +287,17 @@ png_read_filter_row_paeth_rvv(size_t len, size_t bpp, unsigned char* row, * - Else use c */ - /* 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); + /* if (pb < pa) { pa = pb; a = b; } */ + vbool8_t m1 = __riscv_vmsltu_vv_u16m2_b8(pb, pa, vl); + pa = __riscv_vmerge_vvm_u16m2(pa, pb, m1, vl); + a = __riscv_vmerge_vvm_u8m1(a, b, m1, vl); - /* use_a = pa <= pb && pa <= pc */ - vbool8_t use_a = __riscv_vmand_mm_b8(pa_le_pb, pa_le_pc, vl16); - - /* 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); - - /* Switch back to e8m1 for final operations */ - vl = __riscv_vsetvl_e8m1(bpp); - - /* 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); + /* if (pc < pa) a = c; */ + vbool8_t m2 = __riscv_vmsltu_vv_u16m2_b8(pc, pa, vl); + a = __riscv_vmerge_vvm_u8m1(a, c, m2, vl); /* a = result + x */ - a = __riscv_vadd_vv_u8m1(result, x, vl); + a = __riscv_vadd_vv_u8m1(a, x, vl); /* *row = a */ __riscv_vse8_v_u8m1(row, a, vl); diff --git a/3rdparty/libpng/riscv/riscv_init.c b/3rdparty/libpng/riscv/riscv_init.c index f2796ebccb..36a41b54f7 100644 --- a/3rdparty/libpng/riscv/riscv_init.c +++ b/3rdparty/libpng/riscv/riscv_init.c @@ -30,13 +30,13 @@ png_init_filter_functions_rvv(png_structp pp, unsigned int bpp) if (bpp == 3) { pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_rvv; - //pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_rvv; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_rvv; pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_rvv; } else if (bpp == 4) { pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_rvv; - //pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_rvv; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_rvv; pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_rvv; } }