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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « no previous file | third_party/libpng/pnglibconf.h » ('j') | third_party/libpng/pnglibconf.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkCodecPriv.h" 8 #include "SkCodecPriv.h"
9 #include "SkColorPriv.h" 9 #include "SkColorPriv.h"
10 #include "SkColorTable.h" 10 #include "SkColorTable.h"
11 #include "SkBitmap.h" 11 #include "SkBitmap.h"
12 #include "SkMath.h" 12 #include "SkMath.h"
13 #include "SkPngCodec.h" 13 #include "SkPngCodec.h"
14 #include "SkSize.h" 14 #include "SkSize.h"
15 #include "SkStream.h" 15 #include "SkStream.h"
16 #include "SkSwizzler.h" 16 #include "SkSwizzler.h"
17 #include "SkTemplates.h" 17 #include "SkTemplates.h"
18 18
19 #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
20 #include "pngstruct.h"
21
22 // Returns bytewise |x-y|.
23 static __m128i absdiff_u8(__m128i x, __m128i y) {
24 // One of these two saturated subtractions will be the answer, the other zero.
25 return _mm_or_si128(_mm_subs_epu8(x,y), _mm_subs_epu8(y,x));
26 }
27
28 // Bytewise c ? t : e.
29 static __m128i if_then_else(__m128i c, __m128i t, __m128i e) {
30 // SSE 4.1+ would be: return _mm_blendv_epi8(e,t,c);
31 return _mm_or_si128(_mm_and_si128(c, t), _mm_andnot_si128(c, e));
32 }
33
34 static void sk_paeth4_sse2(png_row_infop row_info, png_bytep row_u8, png_con st_bytep prev_u8) {
35 auto prev = (const uint32_t*)prev_u8;
36 auto row = (uint32_t*)row_u8;
37 int n = row_info->rowbytes / 4;
38
39 // Paeth tries to predict pixel d using the pixel to the left of it, a,
40 // and two pixels from the previous row, b and c:
41 // prev: c b
42 // row: a d
43 // The Paeth function predicts d to be whichever of a, b, or c is neares t to p=a+b-c.
44
45 // The first pixel has no left context, and so uses an Up filter, p = b.
46 // This works naturally with our main loop's p = a+b-c if we force a and c to zero.
47 // Here we zero b and d, which become c and a respectively at the start of the loop.
48 __m128i c, b = _mm_setzero_si128(),
49 a, d = _mm_setzero_si128();
50
51 while (n --> 0) {
52 c = b; b = _mm_cvtsi32_si128(*prev++);
53 a = d; d = _mm_cvtsi32_si128(*row);
54
55 // We can't express p in 8 bits, but luckily we can use this faux p instead:
56 __m128i min = _mm_min_epu8(a,b),
57 max = _mm_max_epu8(a,b),
58 faux_p = _mm_adds_epu8(min, _mm_subs_epu8(max, c));
59
60 // We could use faux_p for calculating all three of pa,pb,pc,
61 // but it's a little quicker to calculate the correct pa and pb dire ctly.
62 __m128i pa = absdiff_u8(b,c), // |a+b-c - a| == |b-c|
63 pb = absdiff_u8(a,c), // |a+b-c - b| == |a-c|
64 faux_pc = absdiff_u8(faux_p, c);
65
66 // From here, things are straightforward. Find the smallest distanc e to p...
67 __m128i smallest = _mm_min_epu8(_mm_min_epu8(pa, pb), faux_pc);
68
69 // ... then the predictor is the input corresponding to that smalles t distance,
70 // breaking ties in favor of a over b over c.
71 __m128i nearest = if_then_else(_mm_cmpeq_epi8(smallest, pa), a,
72 if_then_else(_mm_cmpeq_epi8(smallest, pb), b,
73 c));
74
75 // We've reconstructed d! Leave it for next round to become a, and write it out.
76 d = _mm_add_epi8(d, nearest);
77 *row++ = _mm_cvtsi128_si32(d);
78 }
79 }
80
81 extern "C" void sk_png_init_filter_functions_sse2(png_structp png, unsigned int bpp) {
82 if (bpp == 4) {
83 png->read_filter[PNG_FILTER_VALUE_PAETH-1] = sk_paeth4_sse2;
84 }
85 }
86 #endif
87
19 /////////////////////////////////////////////////////////////////////////////// 88 ///////////////////////////////////////////////////////////////////////////////
20 // Helper macros 89 // Helper macros
21 /////////////////////////////////////////////////////////////////////////////// 90 ///////////////////////////////////////////////////////////////////////////////
22 91
23 #ifndef png_jmpbuf 92 #ifndef png_jmpbuf
24 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 93 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
25 #endif 94 #endif
26 95
27 /* These were dropped in libpng >= 1.4 */ 96 /* These were dropped in libpng >= 1.4 */
28 #ifndef png_infopp_NULL 97 #ifndef png_infopp_NULL
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 png_set_tRNS_to_alpha(png_ptr); 393 png_set_tRNS_to_alpha(png_ptr);
325 png_set_gray_to_rgb(png_ptr); 394 png_set_gray_to_rgb(png_ptr);
326 skColorType = kN32_SkColorType; 395 skColorType = kN32_SkColorType;
327 skAlphaType = kUnpremul_SkAlphaType; 396 skAlphaType = kUnpremul_SkAlphaType;
328 } else { 397 } else {
329 skColorType = kGray_8_SkColorType; 398 skColorType = kGray_8_SkColorType;
330 skAlphaType = kOpaque_SkAlphaType; 399 skAlphaType = kOpaque_SkAlphaType;
331 } 400 }
332 break; 401 break;
333 case PNG_COLOR_TYPE_GRAY_ALPHA: 402 case PNG_COLOR_TYPE_GRAY_ALPHA:
334 //FIXME: support gray with alpha as a color type 403 //FIXME: support gray with alpha as a color type
335 //convert to RGBA 404 //convert to RGBA
336 png_set_gray_to_rgb(png_ptr); 405 png_set_gray_to_rgb(png_ptr);
337 skColorType = kN32_SkColorType; 406 skColorType = kN32_SkColorType;
338 skAlphaType = kUnpremul_SkAlphaType; 407 skAlphaType = kUnpremul_SkAlphaType;
339 break; 408 break;
340 case PNG_COLOR_TYPE_RGBA: 409 case PNG_COLOR_TYPE_RGBA:
341 skColorType = kN32_SkColorType; 410 skColorType = kN32_SkColorType;
342 skAlphaType = kUnpremul_SkAlphaType; 411 skAlphaType = kUnpremul_SkAlphaType;
343 break; 412 break;
344 default: 413 default:
345 //all the color types have been covered above 414 //all the color types have been covered above
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, 468 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo,
400 const Options& options, 469 const Options& options,
401 SkPMColor ctable[], 470 SkPMColor ctable[],
402 int* ctableCount) { 471 int* ctableCount) {
403 // FIXME: Could we use the return value of setjmp to specify the type of 472 // FIXME: Could we use the return value of setjmp to specify the type of
404 // error? 473 // error?
405 if (setjmp(png_jmpbuf(fPng_ptr))) { 474 if (setjmp(png_jmpbuf(fPng_ptr))) {
406 SkCodecPrintf("setjmp long jump!\n"); 475 SkCodecPrintf("setjmp long jump!\n");
407 return kInvalidInput; 476 return kInvalidInput;
408 } 477 }
409 png_read_update_info(fPng_ptr, fInfo_ptr); 478 png_read_update_info(fPng_ptr, fInfo_ptr);
410 479
411 //srcColorType was determined in read_header() which determined png color ty pe 480 //srcColorType was determined in read_header() which determined png color ty pe
412 const SkColorType srcColorType = this->getInfo().colorType(); 481 const SkColorType srcColorType = this->getInfo().colorType();
413 482
414 switch (srcColorType) { 483 switch (srcColorType) {
415 case kIndex_8_SkColorType: 484 case kIndex_8_SkColorType:
416 //decode palette to Skia format 485 //decode palette to Skia format
417 fSrcConfig = SkSwizzler::kIndex; 486 fSrcConfig = SkSwizzler::kIndex;
418 if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaT ype(), 487 if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaT ype(),
419 ctableCount)) { 488 ctableCount)) {
420 return kInvalidInput; 489 return kInvalidInput;
421 } 490 }
422 break; 491 break;
423 case kGray_8_SkColorType: 492 case kGray_8_SkColorType:
424 fSrcConfig = SkSwizzler::kGray; 493 fSrcConfig = SkSwizzler::kGray;
425 break; 494 break;
426 case kN32_SkColorType: 495 case kN32_SkColorType:
427 if (this->getInfo().alphaType() == kOpaque_SkAlphaType) { 496 if (this->getInfo().alphaType() == kOpaque_SkAlphaType) {
428 fSrcConfig = SkSwizzler::kRGB; 497 fSrcConfig = SkSwizzler::kRGB;
429 } else { 498 } else {
430 fSrcConfig = SkSwizzler::kRGBA; 499 fSrcConfig = SkSwizzler::kRGBA;
431 } 500 }
432 break; 501 break;
433 default: 502 default:
434 //would have exited before now if the colorType was supported by png 503 //would have exited before now if the colorType was supported by png
435 SkASSERT(false); 504 SkASSERT(false);
436 } 505 }
437 506
438 // Copy the color table to the client if they request kIndex8 mode 507 // Copy the color table to the client if they request kIndex8 mode
439 copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); 508 copy_color_table(requestedInfo, fColorTable, ctable, ctableCount);
440 509
441 // Create the swizzler. SkPngCodec retains ownership of the color table. 510 // Create the swizzler. SkPngCodec retains ownership of the color table.
442 const SkPMColor* colors = get_color_ptr(fColorTable.get()); 511 const SkPMColor* colors = get_color_ptr(fColorTable.get());
443 fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo , options)); 512 fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo , options));
444 if (!fSwizzler) { 513 if (!fSwizzler) {
445 // FIXME: CreateSwizzler could fail for another reason. 514 // FIXME: CreateSwizzler could fail for another reason.
446 return kUnimplemented; 515 return kUnimplemented;
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 686
618 return row; 687 return row;
619 } 688 }
620 689
621 bool onSkipScanlines(int count) override { 690 bool onSkipScanlines(int count) override {
622 // Assume that an error in libpng indicates an incomplete input. 691 // Assume that an error in libpng indicates an incomplete input.
623 if (setjmp(png_jmpbuf(this->png_ptr()))) { 692 if (setjmp(png_jmpbuf(this->png_ptr()))) {
624 SkCodecPrintf("setjmp long jump!\n"); 693 SkCodecPrintf("setjmp long jump!\n");
625 return false; 694 return false;
626 } 695 }
627 //there is a potential tradeoff of memory vs speed created by putting th is in a loop. 696 //there is a potential tradeoff of memory vs speed created by putting th is in a loop.
628 //calling png_read_rows in a loop is insignificantly slower than calling it once with count 697 //calling png_read_rows in a loop is insignificantly slower than calling it once with count
629 //as png_read_rows has it's own loop which calls png_read_row count time s. 698 //as png_read_rows has it's own loop which calls png_read_row count time s.
630 for (int row = 0; row < count; row++) { 699 for (int row = 0; row < count; row++) {
631 png_read_rows(this->png_ptr(), &fSrcRow, png_bytepp_NULL, 1); 700 png_read_rows(this->png_ptr(), &fSrcRow, png_bytepp_NULL, 1);
632 } 701 }
633 return true; 702 return true;
634 } 703 }
635 704
636 private: 705 private:
637 SkAutoTMalloc<uint8_t> fStorage; 706 SkAutoTMalloc<uint8_t> fStorage;
638 uint8_t* fSrcRow; 707 uint8_t* fSrcRow;
(...skipping 10 matching lines...) Expand all
649 : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, n umberPasses) 718 : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, n umberPasses)
650 , fHeight(-1) 719 , fHeight(-1)
651 , fCanSkipRewind(false) 720 , fCanSkipRewind(false)
652 { 721 {
653 SkASSERT(numberPasses != 1); 722 SkASSERT(numberPasses != 1);
654 } 723 }
655 724
656 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons, 725 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons,
657 SkPMColor ctable[], int* ctableCount) override { 726 SkPMColor ctable[], int* ctableCount) override {
658 if (!conversion_possible(dstInfo, this->getInfo())) { 727 if (!conversion_possible(dstInfo, this->getInfo())) {
659 return kInvalidConversion; 728 return kInvalidConversion;
660 } 729 }
661 730
662 const Result result = this->initializeSwizzler(dstInfo, options, ctable, 731 const Result result = this->initializeSwizzler(dstInfo, options, ctable,
663 ctableCount); 732 ctableCount);
664 if (result != kSuccess) { 733 if (result != kSuccess) {
665 return result; 734 return result;
666 } 735 }
667 736
668 fHeight = dstInfo.height(); 737 fHeight = dstInfo.height();
669 // FIXME: This need not be called on a second call to onStartScanlineDec ode. 738 // FIXME: This need not be called on a second call to onStartScanlineDec ode.
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 } 847 }
779 848
780 if (1 == numberPasses) { 849 if (1 == numberPasses) {
781 return new SkPngScanlineDecoder(imageInfo, streamDeleter.detach(), chunk Reader, 850 return new SkPngScanlineDecoder(imageInfo, streamDeleter.detach(), chunk Reader,
782 png_ptr, info_ptr, bitDepth); 851 png_ptr, info_ptr, bitDepth);
783 } 852 }
784 853
785 return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.detach(), chunkReader, 854 return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.detach(), chunkReader,
786 png_ptr, info_ptr, bitDepth, numbe rPasses); 855 png_ptr, info_ptr, bitDepth, numbe rPasses);
787 } 856 }
OLDNEW
« 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