Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Unified Diff: src/codec/SkPngCodec.cpp

Issue 1573943002: sketch hooking into PNG_FILTER_OPTIMIZATIONS (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: awkwording Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | third_party/libpng/pnglibconf.h » ('j') | third_party/libpng/pnglibconf.h » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codec/SkPngCodec.cpp
diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp
index 66215a6c73eef2ffa6206ab30795b6b7d544932c..6de757469c115f5d31ddaa9c06bb154ec7430bc9 100644
--- a/src/codec/SkPngCodec.cpp
+++ b/src/codec/SkPngCodec.cpp
@@ -16,6 +16,75 @@
#include "SkSwizzler.h"
#include "SkTemplates.h"
+#if defined(__SSE2__)
msarett 2016/01/26 22:35:02 Is there another file we can put this in? Seems t
mtklein 2016/01/26 22:52:17 I do think there will be more of these. We'll def
mtklein_C 2016/01/27 00:21:26 I've moved things to a new file, src/codec/SkPngFi
+ #include "pngstruct.h"
+
+ // Returns bytewise |x-y|.
+ static __m128i absdiff_u8(__m128i x, __m128i y) {
+ // One of these two saturated subtractions will be the answer, the other zero.
+ return _mm_or_si128(_mm_subs_epu8(x,y), _mm_subs_epu8(y,x));
+ }
+
+ // Bytewise c ? t : e.
+ static __m128i if_then_else(__m128i c, __m128i t, __m128i e) {
+ // SSE 4.1+ would be: return _mm_blendv_epi8(e,t,c);
+ return _mm_or_si128(_mm_and_si128(c, t), _mm_andnot_si128(c, e));
+ }
+
+ static void sk_paeth4_sse2(png_row_infop row_info, png_bytep row_u8, png_const_bytep prev_u8) {
+ auto prev = (const uint32_t*)prev_u8;
+ auto row = (uint32_t*)row_u8;
+ int n = row_info->rowbytes / 4;
+
+ // Paeth tries to predict pixel d using the pixel to the left of it, a,
+ // and two pixels from the previous row, b and c:
+ // prev: c b
+ // row: a d
+ // The Paeth function predicts d to be whichever of a, b, or c is nearest to p=a+b-c.
+
+ // The first pixel has no left context, and so uses an Up filter, p = b.
+ // This works naturally with our main loop's p = a+b-c if we force a and c to zero.
+ // Here we zero b and d, which become c and a respectively at the start of the loop.
+ __m128i c, b = _mm_setzero_si128(),
+ a, d = _mm_setzero_si128();
+
+ while (n --> 0) {
+ c = b; b = _mm_cvtsi32_si128(*prev++);
+ a = d; d = _mm_cvtsi32_si128(*row);
+
+ // We can't express p in 8 bits, but luckily we can use this faux p instead:
+ __m128i min = _mm_min_epu8(a,b),
+ max = _mm_max_epu8(a,b),
+ faux_p = _mm_adds_epu8(min, _mm_subs_epu8(max, c));
+
+ // We could use faux_p for calculating all three of pa,pb,pc,
+ // but it's a little quicker to calculate the correct pa and pb directly.
+ __m128i pa = absdiff_u8(b,c), // |a+b-c - a| == |b-c|
+ pb = absdiff_u8(a,c), // |a+b-c - b| == |a-c|
+ faux_pc = absdiff_u8(faux_p, c);
+
+ // From here, things are straightforward. Find the smallest distance to p...
+ __m128i smallest = _mm_min_epu8(_mm_min_epu8(pa, pb), faux_pc);
+
+ // ... then the predictor is the input corresponding to that smallest distance,
+ // breaking ties in favor of a over b over c.
+ __m128i nearest = if_then_else(_mm_cmpeq_epi8(smallest, pa), a,
+ if_then_else(_mm_cmpeq_epi8(smallest, pb), b,
+ c));
+
+ // We've reconstructed d! Leave it for next round to become a, and write it out.
+ d = _mm_add_epi8(d, nearest);
+ *row++ = _mm_cvtsi128_si32(d);
+ }
+ }
+
+ extern "C" void sk_png_init_filter_functions_sse2(png_structp png, unsigned int bpp) {
+ if (bpp == 4) {
+ png->read_filter[PNG_FILTER_VALUE_PAETH-1] = sk_paeth4_sse2;
+ }
+ }
+#endif
+
///////////////////////////////////////////////////////////////////////////////
// Helper macros
///////////////////////////////////////////////////////////////////////////////
@@ -331,8 +400,8 @@ static bool read_header(SkStream* stream, SkPngChunkReader* chunkReader,
}
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
- //FIXME: support gray with alpha as a color type
- //convert to RGBA
+ //FIXME: support gray with alpha as a color type
+ //convert to RGBA
png_set_gray_to_rgb(png_ptr);
skColorType = kN32_SkColorType;
skAlphaType = kUnpremul_SkAlphaType;
@@ -406,7 +475,7 @@ SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo,
SkCodecPrintf("setjmp long jump!\n");
return kInvalidInput;
}
- png_read_update_info(fPng_ptr, fInfo_ptr);
+ png_read_update_info(fPng_ptr, fInfo_ptr);
//srcColorType was determined in read_header() which determined png color type
const SkColorType srcColorType = this->getInfo().colorType();
@@ -422,7 +491,7 @@ SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo,
break;
case kGray_8_SkColorType:
fSrcConfig = SkSwizzler::kGray;
- break;
+ break;
case kN32_SkColorType:
if (this->getInfo().alphaType() == kOpaque_SkAlphaType) {
fSrcConfig = SkSwizzler::kRGB;
@@ -433,7 +502,7 @@ SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo,
default:
//would have exited before now if the colorType was supported by png
SkASSERT(false);
- }
+ }
// Copy the color table to the client if they request kIndex8 mode
copy_color_table(requestedInfo, fColorTable, ctable, ctableCount);
@@ -624,8 +693,8 @@ public:
SkCodecPrintf("setjmp long jump!\n");
return false;
}
- //there is a potential tradeoff of memory vs speed created by putting this in a loop.
- //calling png_read_rows in a loop is insignificantly slower than calling it once with count
+ //there is a potential tradeoff of memory vs speed created by putting this in a loop.
+ //calling png_read_rows in a loop is insignificantly slower than calling it once with count
//as png_read_rows has it's own loop which calls png_read_row count times.
for (int row = 0; row < count; row++) {
png_read_rows(this->png_ptr(), &fSrcRow, png_bytepp_NULL, 1);
@@ -656,7 +725,7 @@ public:
Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& options,
SkPMColor ctable[], int* ctableCount) override {
if (!conversion_possible(dstInfo, this->getInfo())) {
- return kInvalidConversion;
+ return kInvalidConversion;
}
const Result result = this->initializeSwizzler(dstInfo, options, ctable,
« no previous file with comments | « no previous file | third_party/libpng/pnglibconf.h » ('j') | third_party/libpng/pnglibconf.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698