From b764276b183d379d5b80e3f601ac42f574da5455 Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Tue, 16 Jan 2018 21:19:28 +0000 Subject: [PATCH] Revert "Revert "libpng: Optimize png_do_expand_palette with NEON."" This reverts commit 20a18ebc02429a40e4bc33fa28c4de29a39b609c. Reason for revert: Original change's description: > Revert "libpng: Optimize png_do_expand_palette with NEON." > > This reverts commit c4811af6d72836d44a3630beecebb0ff55875ab1. > > Reason for revert: This is failing to compile on ios-device-xcode-clang bot. > > https://uberchromegw.corp.google.com/i/chromium.mac/builders/ios-device-xcode-clang/builds/50225 > > Original change's description: > > libpng: Optimize png_do_expand_palette with NEON. > > > > ARM-specific optimization processes 8 or 4 pixels at once. > > > > * Without transparency: 22% performance gain on the A53 little core. > > * With transparency: 10% improvement on a big A72 core, 24% on little. > > > > (Numbers from image_decode_bench with PNG140 on the elm chromebook). > > > > Bug: 706134 > > Change-Id: I7b4a93d72a0afa2823f3bf9ff5f798b88c843e54 > > Reviewed-on: https://chromium-review.googlesource.com/817116 > > Reviewed-by: Adenilson Cavalcanti > > Reviewed-by: Mike Klein > > Reviewed-by: Leon Scroggins > > Reviewed-by: Chris Blume > > Commit-Queue: Adenilson Cavalcanti > > Cr-Commit-Position: refs/heads/master@{#529473} > > TBR=scroggo@chromium.org,cavalcantii@chromium.org,richard.townsend@arm.com,cblume@chromium.org,mtklein@chromium.org > > Change-Id: I2cd943e15ceadf4311b1b49a56de00d10684e294 > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Bug: 706134 > Reviewed-on: https://chromium-review.googlesource.com/868770 > Reviewed-by: Jonathan Ross > Commit-Queue: Jonathan Ross > Cr-Commit-Position: refs/heads/master@{#529484} TBR=scroggo@chromium.org,jonross@chromium.org,cavalcantii@chromium.org,richard.townsend@arm.com,cblume@chromium.org,mtklein@chromium.org Change-Id: I6baf17d35efbd5c6bc348d4f81264e8e1023be4f No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: 706134 --- third_party/libpng/BUILD.gn | 1 + third_party/libpng/arm/palette_neon_intrinsics.c | 137 ++++ third_party/libpng/patches/0000-plte.patch | 776 +++++++++++++++++++++++ third_party/libpng/patches/README | 4 + third_party/libpng/pngpriv.h | 23 + third_party/libpng/pngrtran.c | 49 +- third_party/libpng/pngstruct.h | 4 + third_party/libpng/pngwrite.c | 4 + 8 files changed, 990 insertions(+), 8 deletions(-) create mode 100644 third_party/libpng/arm/palette_neon_intrinsics.c create mode 100644 third_party/libpng/patches/0000-plte.patch create mode 100644 third_party/libpng/patches/README diff --git a/third_party/libpng/BUILD.gn b/third_party/libpng/BUILD.gn index e2658a7ba623..e48c790326c7 100644 --- a/third_party/libpng/BUILD.gn +++ b/third_party/libpng/BUILD.gn @@ -75,6 +75,7 @@ source_set("libpng_sources") { sources += [ "arm/arm_init.c", "arm/filter_neon_intrinsics.c", + "arm/palette_neon_intrinsics.c", ] defines += [ "PNG_ARM_NEON_OPT=2", diff --git a/third_party/libpng/arm/palette_neon_intrinsics.c b/third_party/libpng/arm/palette_neon_intrinsics.c new file mode 100644 index 000000000000..703b9ff25053 --- /dev/null +++ b/third_party/libpng/arm/palette_neon_intrinsics.c @@ -0,0 +1,137 @@ +/* palette_neon_intrinsics.c - NEON optimised palette expansion functions + * + * Copyright (c) 2017 The Chromium Authors. All rights reserved. + * Written by Richard Townsend , February 2017. + * + * 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 + +/* Build an RGBA palette from the RGB and separate alpha palettes. */ +void +png_riffle_palette_rgba(png_structrp png_ptr, png_row_infop row_info) +{ + png_const_colorp palette = png_ptr->palette; + png_bytep riffled_palette = png_ptr->riffled_palette; + png_const_bytep trans_alpha = png_ptr->trans_alpha; + int num_trans = png_ptr->num_trans; + + if (row_info->bit_depth != 8) { + png_error(png_ptr, "bit_depth must be 8 for png_riffle_palette_rgba"); + return; + } + + /* Initially black, opaque. */ + uint8x16x4_t w = {{ + vdupq_n_u8(0x00), + vdupq_n_u8(0x00), + vdupq_n_u8(0x00), + vdupq_n_u8(0xff), + }}; + + int i; + /* First, riffle the RGB colours into a RGBA palette, the A value is + * set to opaque for now. */ + for (i = 0; i < (1 << row_info->bit_depth); i += 16) { + uint8x16x3_t v = vld3q_u8((png_const_bytep)(palette + i)); + w.val[0] = v.val[0]; + w.val[1] = v.val[1]; + w.val[2] = v.val[2]; + vst4q_u8(riffled_palette + (i << 2), w); + } + + /* Fix up the missing transparency values. */ + for (i = 0; i < num_trans; i++) { + riffled_palette[(i << 2) + 3] = trans_alpha[i]; + } +} + + +/* Expands a palettized row into RGBA. */ +int +png_do_expand_palette_neon_rgba(png_structrp png_ptr, png_row_infop row_info, + png_const_bytep row, const png_bytepp ssp, const png_bytepp ddp) +{ + + png_uint_32 row_width = row_info->width; + const png_uint_32 *riffled_palette = (const png_uint_32*)png_ptr->riffled_palette; + const png_int_32 pixels_per_chunk = 4; + + if (row_width < pixels_per_chunk) { + return 0; + } + + /* This function originally gets the last byte of the output row. + The NEON part writes forward from a given position, so we have + to seek this back by 4 pixels x 4 bytes. */ + *ddp = *ddp - ((pixels_per_chunk * sizeof(png_uint_32)) - 1); + + int i; + for (i = 0; i < row_width; i += pixels_per_chunk) { + uint32x4_t cur; + png_bytep sp = *ssp - i, dp = *ddp - (i << 2); + cur = vld1q_dup_u32 (riffled_palette + *(sp - 3)); + cur = vld1q_lane_u32(riffled_palette + *(sp - 2), cur, 1); + cur = vld1q_lane_u32(riffled_palette + *(sp - 1), cur, 2); + cur = vld1q_lane_u32(riffled_palette + *(sp - 0), cur, 3); + vst1q_u32((void *)dp, cur); + } + if (i != row_width) { + i -= pixels_per_chunk; /* Remove the amount that wasn't processed. */ + } + + /* Decrement output pointers. */ + *ssp = *ssp - i; + *ddp = *ddp - (i << 2); + return i; +} + +/* Expands a palettized row into RGB format. */ +int +png_do_expand_palette_neon_rgb(png_structrp png_ptr, png_row_infop row_info, + png_const_bytep row, const png_bytepp ssp, const png_bytepp ddp) +{ + png_uint_32 row_width = row_info->width; + png_const_bytep palette = (png_const_bytep)png_ptr->palette; + const png_uint_32 pixels_per_chunk = 8; + + if (row_width <= pixels_per_chunk) { + return 0; + } + + /* Seeking this back by 8 pixels x 3 bytes. */ + *ddp = *ddp - ((pixels_per_chunk * sizeof(png_color)) - 1); + + int i; + for (i = 0; i < row_width; i += pixels_per_chunk) { + uint8x8x3_t cur; + png_bytep sp = *ssp - i, dp = *ddp - ((i << 1) + i); + cur = vld3_dup_u8(palette + sizeof(png_color) * (*(sp - 7))); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 6)), cur, 1); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 5)), cur, 2); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 4)), cur, 3); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 3)), cur, 4); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 2)), cur, 5); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 1)), cur, 6); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 0)), cur, 7); + vst3_u8((void *)dp, cur); + } + + if (i != row_width) { + i -= pixels_per_chunk; /* Remove the amount that wasn't processed. */ + } + + /* Decrement output pointers. */ + *ssp = *ssp - i; + *ddp = *ddp - ((i << 1) + i); + return i; +} + +#endif /* PNG_ARM_NEON_IMPLEMENTATION */ diff --git a/third_party/libpng/patches/0000-plte.patch b/third_party/libpng/patches/0000-plte.patch new file mode 100644 index 000000000000..feea4d874335 --- /dev/null +++ b/third_party/libpng/patches/0000-plte.patch @@ -0,0 +1,776 @@ +From 5d94e310951211886ee460701176cb36c6e4bc88 Mon Sep 17 00:00:00 2001 +From: Chris Blume +Date: Tue, 16 Jan 2018 21:19:28 +0000 +Subject: [PATCH 1/2] Revert "Revert "libpng: Optimize png_do_expand_palette + with NEON."" + +This reverts commit 20a18ebc02429a40e4bc33fa28c4de29a39b609c. + +Reason for revert: + +Original change's description: +> Revert "libpng: Optimize png_do_expand_palette with NEON." +> +> This reverts commit c4811af6d72836d44a3630beecebb0ff55875ab1. +> +> Reason for revert: This is failing to compile on ios-device-xcode-clang bot. +> +> https://uberchromegw.corp.google.com/i/chromium.mac/builders/ios-device-xcode-clang/builds/50225 +> +> Original change's description: +> > libpng: Optimize png_do_expand_palette with NEON. +> > +> > ARM-specific optimization processes 8 or 4 pixels at once. +> > +> > * Without transparency: 22% performance gain on the A53 little core. +> > * With transparency: 10% improvement on a big A72 core, 24% on little. +> > +> > (Numbers from image_decode_bench with PNG140 on the elm chromebook). +> > +> > Bug: 706134 +> > Change-Id: I7b4a93d72a0afa2823f3bf9ff5f798b88c843e54 +> > Reviewed-on: https://chromium-review.googlesource.com/817116 +> > Reviewed-by: Adenilson Cavalcanti +> > Reviewed-by: Mike Klein +> > Reviewed-by: Leon Scroggins +> > Reviewed-by: Chris Blume +> > Commit-Queue: Adenilson Cavalcanti +> > Cr-Commit-Position: refs/heads/master@{#529473} +> +> TBR=scroggo@chromium.org,cavalcantii@chromium.org,richard.townsend@arm.com,cblume@chromium.org,mtklein@chromium.org +> +> Change-Id: I2cd943e15ceadf4311b1b49a56de00d10684e294 +> No-Presubmit: true +> No-Tree-Checks: true +> No-Try: true +> Bug: 706134 +> Reviewed-on: https://chromium-review.googlesource.com/868770 +> Reviewed-by: Jonathan Ross +> Commit-Queue: Jonathan Ross +> Cr-Commit-Position: refs/heads/master@{#529484} + +TBR=scroggo@chromium.org,jonross@chromium.org,cavalcantii@chromium.org,richard.townsend@arm.com,cblume@chromium.org,mtklein@chromium.org + +Change-Id: I6baf17d35efbd5c6bc348d4f81264e8e1023be4f +No-Presubmit: true +No-Tree-Checks: true +No-Try: true +Bug: 706134 +--- + third_party/libpng/BUILD.gn | 1 + + third_party/libpng/arm/palette_neon_intrinsics.c | 137 +++++++++ + third_party/libpng/patches/0000-plte.patch | 340 +++++++++++++++++++++++ + third_party/libpng/patches/README | 4 + + third_party/libpng/pngpriv.h | 23 ++ + third_party/libpng/pngrtran.c | 49 +++- + third_party/libpng/pngstruct.h | 4 + + third_party/libpng/pngwrite.c | 4 + + 8 files changed, 554 insertions(+), 8 deletions(-) + create mode 100644 third_party/libpng/arm/palette_neon_intrinsics.c + create mode 100644 third_party/libpng/patches/0000-plte.patch + create mode 100644 third_party/libpng/patches/README + +diff --git a/third_party/libpng/BUILD.gn b/third_party/libpng/BUILD.gn +index e2658a7ba623..e48c790326c7 100644 +--- a/third_party/libpng/BUILD.gn ++++ b/third_party/libpng/BUILD.gn +@@ -75,6 +75,7 @@ source_set("libpng_sources") { + sources += [ + "arm/arm_init.c", + "arm/filter_neon_intrinsics.c", ++ "arm/palette_neon_intrinsics.c", + ] + defines += [ + "PNG_ARM_NEON_OPT=2", +diff --git a/third_party/libpng/arm/palette_neon_intrinsics.c b/third_party/libpng/arm/palette_neon_intrinsics.c +new file mode 100644 +index 000000000000..0c0c0a909f8d +--- /dev/null ++++ b/third_party/libpng/arm/palette_neon_intrinsics.c +@@ -0,0 +1,137 @@ ++/* palette_neon_intrinsics.c - NEON optimised palette expansion functions ++ * ++ * Copyright (c) 2017 The Chromium Authors. All rights reserved. ++ * Written by Richard Townsend , February 2017. ++ * ++ * 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 ++ ++/* Build an RGBA palette from the RGB and separate alpha palettes. */ ++void ++png_riffle_palette_rgba(png_structrp png_ptr, png_row_infop row_info) ++{ ++ png_const_colorp palette = png_ptr->palette; ++ png_bytep riffled_palette = png_ptr->riffled_palette; ++ png_const_bytep trans_alpha = png_ptr->trans_alpha; ++ int num_trans = png_ptr->num_trans; ++ ++ if (row_info->bit_depth != 8) { ++ png_error(png_ptr, "bit_depth must be 8 for png_riffle_palette_rgba"); ++ return; ++ } ++ ++ /* Initially black, opaque. */ ++ uint8x16x4_t w = { ++ vdupq_n_u8(0x00), ++ vdupq_n_u8(0x00), ++ vdupq_n_u8(0x00), ++ vdupq_n_u8(0xff), ++ }; ++ ++ int i; ++ /* First, riffle the RGB colours into a RGBA palette, the A value is ++ * set to opaque for now. */ ++ for (i = 0; i < (1 << row_info->bit_depth); i += 16) { ++ uint8x16x3_t v = vld3q_u8((png_const_bytep)(palette + i)); ++ w.val[0] = v.val[0]; ++ w.val[1] = v.val[1]; ++ w.val[2] = v.val[2]; ++ vst4q_u8(riffled_palette + (i << 2), w); ++ } ++ ++ /* Fix up the missing transparency values. */ ++ for (i = 0; i < num_trans; i++) { ++ riffled_palette[(i << 2) + 3] = trans_alpha[i]; ++ } ++} ++ ++ ++/* Expands a palettized row into RGBA. */ ++int ++png_do_expand_palette_neon_rgba(png_structrp png_ptr, png_row_infop row_info, ++ png_const_bytep row, const png_bytepp ssp, const png_bytepp ddp) ++{ ++ ++ png_uint_32 row_width = row_info->width; ++ const png_uint_32 *riffled_palette = (const png_uint_32*)png_ptr->riffled_palette; ++ const png_int_32 pixels_per_chunk = 4; ++ ++ if (row_width < pixels_per_chunk) { ++ return 0; ++ } ++ ++ /* This function originally gets the last byte of the output row. ++ The NEON part writes forward from a given position, so we have ++ to seek this back by 4 pixels x 4 bytes. */ ++ *ddp = *ddp - ((pixels_per_chunk * sizeof(png_uint_32)) - 1); ++ ++ int i; ++ for (i = 0; i < row_width; i += pixels_per_chunk) { ++ uint32x4_t cur; ++ png_bytep sp = *ssp - i, dp = *ddp - (i << 2); ++ cur = vld1q_dup_u32 (riffled_palette + *(sp - 3)); ++ cur = vld1q_lane_u32(riffled_palette + *(sp - 2), cur, 1); ++ cur = vld1q_lane_u32(riffled_palette + *(sp - 1), cur, 2); ++ cur = vld1q_lane_u32(riffled_palette + *(sp - 0), cur, 3); ++ vst1q_u32((void *)dp, cur); ++ } ++ if (i != row_width) { ++ i -= pixels_per_chunk; /* Remove the amount that wasn't processed. */ ++ } ++ ++ /* Decrement output pointers. */ ++ *ssp = *ssp - i; ++ *ddp = *ddp - (i << 2); ++ return i; ++} ++ ++/* Expands a palettized row into RGB format. */ ++int ++png_do_expand_palette_neon_rgb(png_structrp png_ptr, png_row_infop row_info, ++ png_const_bytep row, const png_bytepp ssp, const png_bytepp ddp) ++{ ++ png_uint_32 row_width = row_info->width; ++ png_const_bytep palette = (png_const_bytep)png_ptr->palette; ++ const png_uint_32 pixels_per_chunk = 8; ++ ++ if (row_width <= pixels_per_chunk) { ++ return 0; ++ } ++ ++ /* Seeking this back by 8 pixels x 3 bytes. */ ++ *ddp = *ddp - ((pixels_per_chunk * sizeof(png_color)) - 1); ++ ++ int i; ++ for (i = 0; i < row_width; i += pixels_per_chunk) { ++ uint8x8x3_t cur; ++ png_bytep sp = *ssp - i, dp = *ddp - ((i << 1) + i); ++ cur = vld3_dup_u8(palette + sizeof(png_color) * (*(sp - 7))); ++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 6)), cur, 1); ++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 5)), cur, 2); ++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 4)), cur, 3); ++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 3)), cur, 4); ++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 2)), cur, 5); ++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 1)), cur, 6); ++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 0)), cur, 7); ++ vst3_u8((void *)dp, cur); ++ } ++ ++ if (i != row_width) { ++ i -= pixels_per_chunk; /* Remove the amount that wasn't processed. */ ++ } ++ ++ /* Decrement output pointers. */ ++ *ssp = *ssp - i; ++ *ddp = *ddp - ((i << 1) + i); ++ return i; ++} ++ ++#endif /* PNG_ARM_NEON_IMPLEMENTATION */ +diff --git a/third_party/libpng/patches/0000-plte.patch b/third_party/libpng/patches/0000-plte.patch +new file mode 100644 +index 000000000000..6fceb2f2275a +--- /dev/null ++++ b/third_party/libpng/patches/0000-plte.patch +@@ -0,0 +1,340 @@ ++From aa270a19f7bb9d9cba207b38c0a98cb3a3dc681e Mon Sep 17 00:00:00 2001 ++From: Richard Townsend ++Date: Mon, 20 Feb 2017 14:06:14 +0000 ++Subject: [PATCH] libpng: Optimize png_do_expand_palette with NEON. ++ ++ARM-specific optimization processes 8 or 4 pixels at once. ++ ++* Without transparency: 22% performance gain on the A53 little core. ++* With transparency: 10% improvement on a big A72 core, 24% on little. ++ ++(Numbers from image_decode_bench with PNG140 on the elm chromebook). ++ ++Bug: 706134 ++Change-Id: I7b4a93d72a0afa2823f3bf9ff5f798b88c843e54 ++--- ++ third_party/libpng/BUILD.gn | 1 + ++ third_party/libpng/arm/palette_neon_intrinsics.c | 137 +++++++++++++++++++++++ ++ third_party/libpng/pngpriv.h | 23 ++++ ++ third_party/libpng/pngrtran.c | 49 ++++++-- ++ third_party/libpng/pngstruct.h | 4 + ++ third_party/libpng/pngwrite.c | 4 + ++ 6 files changed, 210 insertions(+), 8 deletions(-) ++ create mode 100644 third_party/libpng/arm/palette_neon_intrinsics.c ++ ++diff --git a/third_party/libpng/BUILD.gn b/third_party/libpng/BUILD.gn ++index e2658a7ba623..e48c790326c7 100644 ++--- a/third_party/libpng/BUILD.gn +++++ b/third_party/libpng/BUILD.gn ++@@ -75,6 +75,7 @@ source_set("libpng_sources") { ++ sources += [ ++ "arm/arm_init.c", ++ "arm/filter_neon_intrinsics.c", +++ "arm/palette_neon_intrinsics.c", ++ ] ++ defines += [ ++ "PNG_ARM_NEON_OPT=2", ++diff --git a/third_party/libpng/arm/palette_neon_intrinsics.c b/third_party/libpng/arm/palette_neon_intrinsics.c ++new file mode 100644 ++index 000000000000..0c0c0a909f8d ++--- /dev/null +++++ b/third_party/libpng/arm/palette_neon_intrinsics.c ++@@ -0,0 +1,137 @@ +++/* palette_neon_intrinsics.c - NEON optimised palette expansion functions +++ * +++ * Copyright (c) 2017 The Chromium Authors. All rights reserved. +++ * Written by Richard Townsend , February 2017. +++ * +++ * 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 +++ +++/* Build an RGBA palette from the RGB and separate alpha palettes. */ +++void +++png_riffle_palette_rgba(png_structrp png_ptr, png_row_infop row_info) +++{ +++ png_const_colorp palette = png_ptr->palette; +++ png_bytep riffled_palette = png_ptr->riffled_palette; +++ png_const_bytep trans_alpha = png_ptr->trans_alpha; +++ int num_trans = png_ptr->num_trans; +++ +++ if (row_info->bit_depth != 8) { +++ png_error(png_ptr, "bit_depth must be 8 for png_riffle_palette_rgba"); +++ return; +++ } +++ +++ /* Initially black, opaque. */ +++ uint8x16x4_t w = { +++ vdupq_n_u8(0x00), +++ vdupq_n_u8(0x00), +++ vdupq_n_u8(0x00), +++ vdupq_n_u8(0xff), +++ }; +++ +++ int i; +++ /* First, riffle the RGB colours into a RGBA palette, the A value is +++ * set to opaque for now. */ +++ for (i = 0; i < (1 << row_info->bit_depth); i += 16) { +++ uint8x16x3_t v = vld3q_u8((png_const_bytep)(palette + i)); +++ w.val[0] = v.val[0]; +++ w.val[1] = v.val[1]; +++ w.val[2] = v.val[2]; +++ vst4q_u8(riffled_palette + (i << 2), w); +++ } +++ +++ /* Fix up the missing transparency values. */ +++ for (i = 0; i < num_trans; i++) { +++ riffled_palette[(i << 2) + 3] = trans_alpha[i]; +++ } +++} +++ +++ +++/* Expands a palettized row into RGBA. */ +++int +++png_do_expand_palette_neon_rgba(png_structrp png_ptr, png_row_infop row_info, +++ png_const_bytep row, const png_bytepp ssp, const png_bytepp ddp) +++{ +++ +++ png_uint_32 row_width = row_info->width; +++ const png_uint_32 *riffled_palette = (const png_uint_32*)png_ptr->riffled_palette; +++ const png_int_32 pixels_per_chunk = 4; +++ +++ if (row_width < pixels_per_chunk) { +++ return 0; +++ } +++ +++ /* This function originally gets the last byte of the output row. +++ The NEON part writes forward from a given position, so we have +++ to seek this back by 4 pixels x 4 bytes. */ +++ *ddp = *ddp - ((pixels_per_chunk * sizeof(png_uint_32)) - 1); +++ +++ int i; +++ for (i = 0; i < row_width; i += pixels_per_chunk) { +++ uint32x4_t cur; +++ png_bytep sp = *ssp - i, dp = *ddp - (i << 2); +++ cur = vld1q_dup_u32 (riffled_palette + *(sp - 3)); +++ cur = vld1q_lane_u32(riffled_palette + *(sp - 2), cur, 1); +++ cur = vld1q_lane_u32(riffled_palette + *(sp - 1), cur, 2); +++ cur = vld1q_lane_u32(riffled_palette + *(sp - 0), cur, 3); +++ vst1q_u32((void *)dp, cur); +++ } +++ if (i != row_width) { +++ i -= pixels_per_chunk; /* Remove the amount that wasn't processed. */ +++ } +++ +++ /* Decrement output pointers. */ +++ *ssp = *ssp - i; +++ *ddp = *ddp - (i << 2); +++ return i; +++} +++ +++/* Expands a palettized row into RGB format. */ +++int +++png_do_expand_palette_neon_rgb(png_structrp png_ptr, png_row_infop row_info, +++ png_const_bytep row, const png_bytepp ssp, const png_bytepp ddp) +++{ +++ png_uint_32 row_width = row_info->width; +++ png_const_bytep palette = (png_const_bytep)png_ptr->palette; +++ const png_uint_32 pixels_per_chunk = 8; +++ +++ if (row_width <= pixels_per_chunk) { +++ return 0; +++ } +++ +++ /* Seeking this back by 8 pixels x 3 bytes. */ +++ *ddp = *ddp - ((pixels_per_chunk * sizeof(png_color)) - 1); +++ +++ int i; +++ for (i = 0; i < row_width; i += pixels_per_chunk) { +++ uint8x8x3_t cur; +++ png_bytep sp = *ssp - i, dp = *ddp - ((i << 1) + i); +++ cur = vld3_dup_u8(palette + sizeof(png_color) * (*(sp - 7))); +++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 6)), cur, 1); +++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 5)), cur, 2); +++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 4)), cur, 3); +++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 3)), cur, 4); +++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 2)), cur, 5); +++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 1)), cur, 6); +++ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 0)), cur, 7); +++ vst3_u8((void *)dp, cur); +++ } +++ +++ if (i != row_width) { +++ i -= pixels_per_chunk; /* Remove the amount that wasn't processed. */ +++ } +++ +++ /* Decrement output pointers. */ +++ *ssp = *ssp - i; +++ *ddp = *ddp - ((i << 1) + i); +++ return i; +++} +++ +++#endif /* PNG_ARM_NEON_IMPLEMENTATION */ ++diff --git a/third_party/libpng/pngpriv.h b/third_party/libpng/pngpriv.h ++index 1f2e90f2b37b..5652525b2b51 100644 ++--- a/third_party/libpng/pngpriv.h +++++ b/third_party/libpng/pngpriv.h ++@@ -2108,6 +2108,29 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, ++ PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, ++ png_const_charp key, png_bytep new_key), PNG_EMPTY); ++ +++#if PNG_ARM_NEON_IMPLEMENTATION == 1 +++PNG_INTERNAL_FUNCTION(void, +++ png_riffle_palette_rgba, +++ (png_structrp, png_row_infop), +++ PNG_EMPTY); +++PNG_INTERNAL_FUNCTION(int, +++ png_do_expand_palette_neon_rgba, +++ (png_structrp, +++ png_row_infop, +++ png_const_bytep, +++ const png_bytepp, +++ const png_bytepp), +++ PNG_EMPTY); +++PNG_INTERNAL_FUNCTION(int, +++ png_do_expand_palette_neon_rgb, +++ (png_structrp, +++ png_row_infop, +++ png_const_bytep, +++ const png_bytepp, +++ const png_bytepp), +++ PNG_EMPTY); +++#endif +++ ++ /* Maintainer: Put new private prototypes here ^ */ ++ ++ #include "pngdebug.h" ++diff --git a/third_party/libpng/pngrtran.c b/third_party/libpng/pngrtran.c ++index c1896503130e..9dd82c929bdc 100644 ++--- a/third_party/libpng/pngrtran.c +++++ b/third_party/libpng/pngrtran.c ++@@ -18,6 +18,13 @@ ++ ++ #include "pngpriv.h" ++ +++#ifdef PNG_ARM_NEON_IMPLEMENTATION +++#if PNG_ARM_NEON_IMPLEMENTATION == 1 +++#define PNG_ARM_NEON_INTRINSICS_AVAILABLE +++#include +++#endif +++#endif +++ ++ #ifdef PNG_READ_SUPPORTED ++ ++ /* Set the action on getting a CRC error for an ancillary or critical chunk. */ ++@@ -4202,8 +4209,9 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) ++ * upon whether you supply trans and num_trans. ++ */ ++ static void ++-png_do_expand_palette(png_row_infop row_info, png_bytep row, ++- png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) +++png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info, +++ png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha, +++ int num_trans) ++ { ++ int shift, value; ++ png_bytep sp, dp; ++@@ -4307,14 +4315,22 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, ++ sp = row + (png_size_t)row_width - 1; ++ dp = row + ((png_size_t)row_width << 2) - 1; ++ ++- for (i = 0; i < row_width; i++) +++ i = 0; +++#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE +++ if (png_ptr->riffled_palette != NULL) { +++ /* The RGBA optimization works with png_ptr->bit_depth == 8 +++ but sometimes row_info->bit_depth has been changed to 8. +++ In these cases, the palette hasn't been riffled. */ +++ i = png_do_expand_palette_neon_rgba(png_ptr, row_info, row, &sp, &dp); +++ } +++#endif +++ +++ for (; i < row_width; i++) ++ { ++ if ((int)(*sp) >= num_trans) ++ *dp-- = 0xff; ++- ++ else ++ *dp-- = trans_alpha[*sp]; ++- ++ *dp-- = palette[*sp].blue; ++ *dp-- = palette[*sp].green; ++ *dp-- = palette[*sp].red; ++@@ -4331,8 +4347,12 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, ++ { ++ sp = row + (png_size_t)row_width - 1; ++ dp = row + (png_size_t)(row_width * 3) - 1; +++ i = 0; +++#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE +++ i = png_do_expand_palette_neon_rgb(png_ptr, row_info, row, &sp, &dp); +++#endif ++ ++- for (i = 0; i < row_width; i++) +++ for (; i < row_width; i++) ++ { ++ *dp-- = palette[*sp].blue; ++ *dp-- = palette[*sp].green; ++@@ -4748,8 +4768,21 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) ++ { ++ if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) ++ { ++- png_do_expand_palette(row_info, png_ptr->row_buf + 1, ++- png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); +++#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE +++ if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8)) { +++ /* Allocate space for the decompressed full palette. */ +++ if (png_ptr->riffled_palette == NULL) { +++ png_ptr->riffled_palette = png_malloc(png_ptr, 256*4); +++ if (png_ptr->riffled_palette == NULL) { +++ png_error(png_ptr, "NULL row buffer"); +++ } +++ /* Build the RGBA palette. */ +++ png_riffle_palette_rgba(png_ptr, row_info); +++ } +++ } +++#endif +++ png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1, +++ png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); ++ } ++ ++ else ++diff --git a/third_party/libpng/pngstruct.h b/third_party/libpng/pngstruct.h ++index d83f971253fe..aac88df02d32 100644 ++--- a/third_party/libpng/pngstruct.h +++++ b/third_party/libpng/pngstruct.h ++@@ -228,6 +228,10 @@ struct png_struct_def ++ * big_row_buf; while writing it is separately ++ * allocated. ++ */ +++#ifdef PNG_READ_EXPAND_SUPPORTED +++ /* Buffer to accelerate palette transformations. */ +++ png_bytep riffled_palette; +++#endif ++ #ifdef PNG_WRITE_FILTER_SUPPORTED ++ png_bytep try_row; /* buffer to save trial row when filtering */ ++ png_bytep tst_row; /* buffer to save best trial row when filtering */ ++diff --git a/third_party/libpng/pngwrite.c b/third_party/libpng/pngwrite.c ++index a16d77ce00c6..e25e5dcfdc18 100644 ++--- a/third_party/libpng/pngwrite.c +++++ b/third_party/libpng/pngwrite.c ++@@ -948,6 +948,10 @@ png_write_destroy(png_structrp png_ptr) ++ png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); ++ png_free(png_ptr, png_ptr->row_buf); ++ png_ptr->row_buf = NULL; +++#ifdef PNG_READ_EXPANDED_SUPPORTED +++ png_free(png_ptr, png_ptr->riffled_palette); +++ png_ptr->riffled_palette = NULL; +++#endif ++ #ifdef PNG_WRITE_FILTER_SUPPORTED ++ png_free(png_ptr, png_ptr->prev_row); ++ png_free(png_ptr, png_ptr->try_row); ++-- ++2.15.1 ++ +diff --git a/third_party/libpng/patches/README b/third_party/libpng/patches/README +new file mode 100644 +index 000000000000..786aeabede37 +--- /dev/null ++++ b/third_party/libpng/patches/README +@@ -0,0 +1,4 @@ ++This directory contains patches applied on top of libpng, which haven't been ++upstreamed to the canonical libpng repository [1] yet. ++ ++[1] https://github.com/glennrp/libpng +diff --git a/third_party/libpng/pngpriv.h b/third_party/libpng/pngpriv.h +index 1f2e90f2b37b..5652525b2b51 100644 +--- a/third_party/libpng/pngpriv.h ++++ b/third_party/libpng/pngpriv.h +@@ -2108,6 +2108,29 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, + PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, + png_const_charp key, png_bytep new_key), PNG_EMPTY); + ++#if PNG_ARM_NEON_IMPLEMENTATION == 1 ++PNG_INTERNAL_FUNCTION(void, ++ png_riffle_palette_rgba, ++ (png_structrp, png_row_infop), ++ PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(int, ++ png_do_expand_palette_neon_rgba, ++ (png_structrp, ++ png_row_infop, ++ png_const_bytep, ++ const png_bytepp, ++ const png_bytepp), ++ PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(int, ++ png_do_expand_palette_neon_rgb, ++ (png_structrp, ++ png_row_infop, ++ png_const_bytep, ++ const png_bytepp, ++ const png_bytepp), ++ PNG_EMPTY); ++#endif ++ + /* Maintainer: Put new private prototypes here ^ */ + + #include "pngdebug.h" +diff --git a/third_party/libpng/pngrtran.c b/third_party/libpng/pngrtran.c +index c1896503130e..9dd82c929bdc 100644 +--- a/third_party/libpng/pngrtran.c ++++ b/third_party/libpng/pngrtran.c +@@ -18,6 +18,13 @@ + + #include "pngpriv.h" + ++#ifdef PNG_ARM_NEON_IMPLEMENTATION ++#if PNG_ARM_NEON_IMPLEMENTATION == 1 ++#define PNG_ARM_NEON_INTRINSICS_AVAILABLE ++#include ++#endif ++#endif ++ + #ifdef PNG_READ_SUPPORTED + + /* Set the action on getting a CRC error for an ancillary or critical chunk. */ +@@ -4202,8 +4209,9 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) + * upon whether you supply trans and num_trans. + */ + static void +-png_do_expand_palette(png_row_infop row_info, png_bytep row, +- png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) ++png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info, ++ png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha, ++ int num_trans) + { + int shift, value; + png_bytep sp, dp; +@@ -4307,14 +4315,22 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, + sp = row + (png_size_t)row_width - 1; + dp = row + ((png_size_t)row_width << 2) - 1; + +- for (i = 0; i < row_width; i++) ++ i = 0; ++#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE ++ if (png_ptr->riffled_palette != NULL) { ++ /* The RGBA optimization works with png_ptr->bit_depth == 8 ++ but sometimes row_info->bit_depth has been changed to 8. ++ In these cases, the palette hasn't been riffled. */ ++ i = png_do_expand_palette_neon_rgba(png_ptr, row_info, row, &sp, &dp); ++ } ++#endif ++ ++ for (; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; +- + else + *dp-- = trans_alpha[*sp]; +- + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; +@@ -4331,8 +4347,12 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; ++ i = 0; ++#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE ++ i = png_do_expand_palette_neon_rgb(png_ptr, row_info, row, &sp, &dp); ++#endif + +- for (i = 0; i < row_width; i++) ++ for (; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; +@@ -4748,8 +4768,21 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) + { + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { +- png_do_expand_palette(row_info, png_ptr->row_buf + 1, +- png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); ++#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE ++ if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8)) { ++ /* Allocate space for the decompressed full palette. */ ++ if (png_ptr->riffled_palette == NULL) { ++ png_ptr->riffled_palette = png_malloc(png_ptr, 256*4); ++ if (png_ptr->riffled_palette == NULL) { ++ png_error(png_ptr, "NULL row buffer"); ++ } ++ /* Build the RGBA palette. */ ++ png_riffle_palette_rgba(png_ptr, row_info); ++ } ++ } ++#endif ++ png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1, ++ png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); + } + + else +diff --git a/third_party/libpng/pngstruct.h b/third_party/libpng/pngstruct.h +index d83f971253fe..aac88df02d32 100644 +--- a/third_party/libpng/pngstruct.h ++++ b/third_party/libpng/pngstruct.h +@@ -228,6 +228,10 @@ struct png_struct_def + * big_row_buf; while writing it is separately + * allocated. + */ ++#ifdef PNG_READ_EXPAND_SUPPORTED ++ /* Buffer to accelerate palette transformations. */ ++ png_bytep riffled_palette; ++#endif + #ifdef PNG_WRITE_FILTER_SUPPORTED + png_bytep try_row; /* buffer to save trial row when filtering */ + png_bytep tst_row; /* buffer to save best trial row when filtering */ +diff --git a/third_party/libpng/pngwrite.c b/third_party/libpng/pngwrite.c +index a16d77ce00c6..e25e5dcfdc18 100644 +--- a/third_party/libpng/pngwrite.c ++++ b/third_party/libpng/pngwrite.c +@@ -948,6 +948,10 @@ png_write_destroy(png_structrp png_ptr) + png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); + png_free(png_ptr, png_ptr->row_buf); + png_ptr->row_buf = NULL; ++#ifdef PNG_READ_EXPANDED_SUPPORTED ++ png_free(png_ptr, png_ptr->riffled_palette); ++ png_ptr->riffled_palette = NULL; ++#endif + #ifdef PNG_WRITE_FILTER_SUPPORTED + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->try_row); +-- +2.16.0.rc1.238.g530d649a79-goog + + +From 736276e0ec02b5078ca98cfe6ed0bb3f86524a8b Mon Sep 17 00:00:00 2001 +From: Chris Blume +Date: Tue, 16 Jan 2018 13:25:38 -0800 +Subject: [PATCH 2/2] Explicitly initialize the member of the variable + +--- + third_party/libpng/arm/palette_neon_intrinsics.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/third_party/libpng/arm/palette_neon_intrinsics.c b/third_party/libpng/arm/palette_neon_intrinsics.c +index 0c0c0a909f8d..703b9ff25053 100644 +--- a/third_party/libpng/arm/palette_neon_intrinsics.c ++++ b/third_party/libpng/arm/palette_neon_intrinsics.c +@@ -29,12 +29,12 @@ png_riffle_palette_rgba(png_structrp png_ptr, png_row_infop row_info) + } + + /* Initially black, opaque. */ +- uint8x16x4_t w = { ++ uint8x16x4_t w = {{ + vdupq_n_u8(0x00), + vdupq_n_u8(0x00), + vdupq_n_u8(0x00), + vdupq_n_u8(0xff), +- }; ++ }}; + + int i; + /* First, riffle the RGB colours into a RGBA palette, the A value is +-- +2.16.0.rc1.238.g530d649a79-goog + diff --git a/third_party/libpng/patches/README b/third_party/libpng/patches/README new file mode 100644 index 000000000000..786aeabede37 --- /dev/null +++ b/third_party/libpng/patches/README @@ -0,0 +1,4 @@ +This directory contains patches applied on top of libpng, which haven't been +upstreamed to the canonical libpng repository [1] yet. + +[1] https://github.com/glennrp/libpng diff --git a/third_party/libpng/pngpriv.h b/third_party/libpng/pngpriv.h index 1f2e90f2b37b..5652525b2b51 100644 --- a/third_party/libpng/pngpriv.h +++ b/third_party/libpng/pngpriv.h @@ -2108,6 +2108,29 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, png_const_charp key, png_bytep new_key), PNG_EMPTY); +#if PNG_ARM_NEON_IMPLEMENTATION == 1 +PNG_INTERNAL_FUNCTION(void, + png_riffle_palette_rgba, + (png_structrp, png_row_infop), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, + png_do_expand_palette_neon_rgba, + (png_structrp, + png_row_infop, + png_const_bytep, + const png_bytepp, + const png_bytepp), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, + png_do_expand_palette_neon_rgb, + (png_structrp, + png_row_infop, + png_const_bytep, + const png_bytepp, + const png_bytepp), + PNG_EMPTY); +#endif + /* Maintainer: Put new private prototypes here ^ */ #include "pngdebug.h" diff --git a/third_party/libpng/pngrtran.c b/third_party/libpng/pngrtran.c index c1896503130e..9dd82c929bdc 100644 --- a/third_party/libpng/pngrtran.c +++ b/third_party/libpng/pngrtran.c @@ -18,6 +18,13 @@ #include "pngpriv.h" +#ifdef PNG_ARM_NEON_IMPLEMENTATION +#if PNG_ARM_NEON_IMPLEMENTATION == 1 +#define PNG_ARM_NEON_INTRINSICS_AVAILABLE +#include +#endif +#endif + #ifdef PNG_READ_SUPPORTED /* Set the action on getting a CRC error for an ancillary or critical chunk. */ @@ -4202,8 +4209,9 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) * upon whether you supply trans and num_trans. */ static void -png_do_expand_palette(png_row_infop row_info, png_bytep row, - png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) +png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info, + png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha, + int num_trans) { int shift, value; png_bytep sp, dp; @@ -4307,14 +4315,22 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, sp = row + (png_size_t)row_width - 1; dp = row + ((png_size_t)row_width << 2) - 1; - for (i = 0; i < row_width; i++) + i = 0; +#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE + if (png_ptr->riffled_palette != NULL) { + /* The RGBA optimization works with png_ptr->bit_depth == 8 + but sometimes row_info->bit_depth has been changed to 8. + In these cases, the palette hasn't been riffled. */ + i = png_do_expand_palette_neon_rgba(png_ptr, row_info, row, &sp, &dp); + } +#endif + + for (; i < row_width; i++) { if ((int)(*sp) >= num_trans) *dp-- = 0xff; - else *dp-- = trans_alpha[*sp]; - *dp-- = palette[*sp].blue; *dp-- = palette[*sp].green; *dp-- = palette[*sp].red; @@ -4331,8 +4347,12 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, { sp = row + (png_size_t)row_width - 1; dp = row + (png_size_t)(row_width * 3) - 1; + i = 0; +#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE + i = png_do_expand_palette_neon_rgb(png_ptr, row_info, row, &sp, &dp); +#endif - for (i = 0; i < row_width; i++) + for (; i < row_width; i++) { *dp-- = palette[*sp].blue; *dp-- = palette[*sp].green; @@ -4748,8 +4768,21 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) { if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) { - png_do_expand_palette(row_info, png_ptr->row_buf + 1, - png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); +#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE + if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8)) { + /* Allocate space for the decompressed full palette. */ + if (png_ptr->riffled_palette == NULL) { + png_ptr->riffled_palette = png_malloc(png_ptr, 256*4); + if (png_ptr->riffled_palette == NULL) { + png_error(png_ptr, "NULL row buffer"); + } + /* Build the RGBA palette. */ + png_riffle_palette_rgba(png_ptr, row_info); + } + } +#endif + png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); } else diff --git a/third_party/libpng/pngstruct.h b/third_party/libpng/pngstruct.h index d83f971253fe..aac88df02d32 100644 --- a/third_party/libpng/pngstruct.h +++ b/third_party/libpng/pngstruct.h @@ -228,6 +228,10 @@ struct png_struct_def * big_row_buf; while writing it is separately * allocated. */ +#ifdef PNG_READ_EXPAND_SUPPORTED + /* Buffer to accelerate palette transformations. */ + png_bytep riffled_palette; +#endif #ifdef PNG_WRITE_FILTER_SUPPORTED png_bytep try_row; /* buffer to save trial row when filtering */ png_bytep tst_row; /* buffer to save best trial row when filtering */ diff --git a/third_party/libpng/pngwrite.c b/third_party/libpng/pngwrite.c index a16d77ce00c6..e25e5dcfdc18 100644 --- a/third_party/libpng/pngwrite.c +++ b/third_party/libpng/pngwrite.c @@ -948,6 +948,10 @@ png_write_destroy(png_structrp png_ptr) png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); png_free(png_ptr, png_ptr->row_buf); png_ptr->row_buf = NULL; +#ifdef PNG_READ_EXPANDED_SUPPORTED + png_free(png_ptr, png_ptr->riffled_palette); + png_ptr->riffled_palette = NULL; +#endif #ifdef PNG_WRITE_FILTER_SUPPORTED png_free(png_ptr, png_ptr->prev_row); png_free(png_ptr, png_ptr->try_row); -- 2.16.0.rc1.238.g530d649a79-goog