diff options
author | msarett <msarett@google.com> | 2016-02-22 12:27:46 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-22 12:27:46 -0800 |
commit | 91c22b2ea6bd13a31321ead01645467f21858cd0 (patch) | |
tree | 99f66c26c87bbcade9c7eac84099e2fae7c01cd5 /dm | |
parent | 7499e69d9991a113c452a2a44a10078df41f3758 (diff) |
Use new jpeg_crop_scanlines() API to optimize jpeg subset decodes
This was adapted from:
https://codereview.chromium.org/1530933003
Subset Decode Runtime (Original / Optimized) on Nexus 6P
TopLeft 0.51x
TopRight 0.56x
Middle 0.71x
BottomLeft 0.79x
BottomRight 0.79x
BUG=skia:4256
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1719073002
Review URL: https://codereview.chromium.org/1719073002
Diffstat (limited to 'dm')
-rw-r--r-- | dm/DM.cpp | 59 | ||||
-rw-r--r-- | dm/DMSrcSink.cpp | 25 | ||||
-rw-r--r-- | dm/DMSrcSink.h | 1 |
3 files changed, 64 insertions, 21 deletions
@@ -242,6 +242,9 @@ static void push_codec_src(Path path, CodecSrc::Mode mode, CodecSrc::DstColorTyp case CodecSrc::kStripe_Mode: folder.append("stripe"); break; + case CodecSrc::kCroppedScanline_Mode: + folder.append("crop"); + break; case CodecSrc::kSubset_Mode: folder.append("codec_subset"); break; @@ -346,31 +349,38 @@ static void push_codec_srcs(Path path) { // SkJpegCodec natively supports scaling to: 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875 const float nativeScales[] = { 0.125f, 0.25f, 0.375f, 0.5f, 0.625f, 0.750f, 0.875f, 1.0f }; - const CodecSrc::Mode nativeModes[] = { CodecSrc::kCodec_Mode, CodecSrc::kCodecZeroInit_Mode, - CodecSrc::kScanline_Mode, CodecSrc::kStripe_Mode, CodecSrc::kSubset_Mode, - CodecSrc::kGen_Mode }; + SkTArray<CodecSrc::Mode> nativeModes; + nativeModes.push_back(CodecSrc::kCodec_Mode); + nativeModes.push_back(CodecSrc::kCodecZeroInit_Mode); + nativeModes.push_back(CodecSrc::kGen_Mode); + switch (codec->getEncodedFormat()) { + case SkEncodedFormat::kJPEG_SkEncodedFormat: + nativeModes.push_back(CodecSrc::kScanline_Mode); + nativeModes.push_back(CodecSrc::kStripe_Mode); + nativeModes.push_back(CodecSrc::kCroppedScanline_Mode); + break; + case SkEncodedFormat::kWEBP_SkEncodedFormat: + nativeModes.push_back(CodecSrc::kSubset_Mode); + break; + default: + nativeModes.push_back(CodecSrc::kScanline_Mode); + nativeModes.push_back(CodecSrc::kStripe_Mode); + break; + } - CodecSrc::DstColorType colorTypes[3]; - uint32_t numColorTypes; + SkTArray<CodecSrc::DstColorType> colorTypes; + colorTypes.push_back(CodecSrc::kGetFromCanvas_DstColorType); switch (codec->getInfo().colorType()) { case kGray_8_SkColorType: - colorTypes[0] = CodecSrc::kGetFromCanvas_DstColorType; - colorTypes[1] = CodecSrc::kGrayscale_Always_DstColorType; + colorTypes.push_back(CodecSrc::kGrayscale_Always_DstColorType); if (kWBMP_SkEncodedFormat == codec->getEncodedFormat()) { - colorTypes[2] = CodecSrc::kIndex8_Always_DstColorType; - numColorTypes = 3; - } else { - numColorTypes = 2; + colorTypes.push_back(CodecSrc::kIndex8_Always_DstColorType); } break; case kIndex_8_SkColorType: - colorTypes[0] = CodecSrc::kGetFromCanvas_DstColorType; - colorTypes[1] = CodecSrc::kIndex8_Always_DstColorType; - numColorTypes = 2; + colorTypes.push_back(CodecSrc::kIndex8_Always_DstColorType); break; default: - colorTypes[0] = CodecSrc::kGetFromCanvas_DstColorType; - numColorTypes = 1; break; } @@ -396,9 +406,16 @@ static void push_codec_srcs(Path path) { } for (float scale : nativeScales) { - for (uint32_t i = 0; i < numColorTypes; i++) { + for (CodecSrc::DstColorType colorType : colorTypes) { for (SkAlphaType alphaType : alphaModes) { - push_codec_src(path, mode, colorTypes[i], alphaType, scale); + // Only test kCroppedScanline_Mode when the alpha type is opaque. The test is + // slow and won't be interestingly different with different alpha types. + if (CodecSrc::kCroppedScanline_Mode == mode && + kOpaque_SkAlphaType != alphaType) { + continue; + } + + push_codec_src(path, mode, colorType, alphaType, scale); } } } @@ -422,12 +439,12 @@ static void push_codec_srcs(Path path) { const int sampleSizes[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; for (int sampleSize : sampleSizes) { - for (uint32_t i = 0; i < numColorTypes; i++) { + for (CodecSrc::DstColorType colorType : colorTypes) { for (SkAlphaType alphaType : alphaModes) { - push_android_codec_src(path, AndroidCodecSrc::kFullImage_Mode, colorTypes[i], + push_android_codec_src(path, AndroidCodecSrc::kFullImage_Mode, colorType, alphaType, sampleSize); if (subset) { - push_android_codec_src(path, AndroidCodecSrc::kDivisor_Mode, colorTypes[i], + push_android_codec_src(path, AndroidCodecSrc::kDivisor_Mode, colorType, alphaType, sampleSize); } } diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index 7ccaf223fc..bd881e8381 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -522,6 +522,31 @@ Error CodecSrc::draw(SkCanvas* canvas) const { canvas->drawBitmap(bitmap, 0, 0); break; } + case kCroppedScanline_Mode: { + const int width = decodeInfo.width(); + const int height = decodeInfo.height(); + // This value is chosen because, as we move across the image, it will sometimes + // align with the jpeg block sizes and it will sometimes not. This allows us + // to test interestingly different code paths in the implementation. + const int tileSize = 36; + + SkCodec::Options opts; + SkIRect subset; + for (int x = 0; x < width; x += tileSize) { + subset = SkIRect::MakeXYWH(x, 0, SkTMin(tileSize, width - x), height); + opts.fSubset = ⊂ + if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, &opts, + colorPtr, colorCountPtr)) { + return "Could not start scanline decoder."; + } + + codec->getScanlines(bitmap.getAddr(x, 0), height, bitmap.rowBytes()); + } + + premultiply_if_necessary(bitmap); + canvas->drawBitmap(bitmap, 0, 0); + break; + } case kSubset_Mode: { // Arbitrarily choose a divisor. int divisor = 2; diff --git a/dm/DMSrcSink.h b/dm/DMSrcSink.h index a987c7d45d..3190576c68 100644 --- a/dm/DMSrcSink.h +++ b/dm/DMSrcSink.h @@ -110,6 +110,7 @@ public: kCodecZeroInit_Mode, kScanline_Mode, kStripe_Mode, // Tests the skipping of scanlines + kCroppedScanline_Mode, // Tests (jpeg) cropped scanline optimization kSubset_Mode, // For codecs that support subsets directly. kGen_Mode, // Test SkCodecImageGenerator (includes YUV) }; |