diff options
author | msarett <msarett@google.com> | 2016-03-09 14:20:58 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-09 14:20:58 -0800 |
commit | 1897631ebe417631ea7a046a2eb0995ab9d04539 (patch) | |
tree | 766fb1f25096283de72e39d0754f434525b5683e /dm | |
parent | beba90864ae4645b9f4f7a47065f567862ada12c (diff) |
Add an SkImageGeneratorCG
This will serve as a replacement for SkImageDecoder_CG.
BUG=skia:4914
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1718273004
Review URL: https://codereview.chromium.org/1718273004
Diffstat (limited to 'dm')
-rw-r--r-- | dm/DM.cpp | 84 | ||||
-rw-r--r-- | dm/DMSrcSink.cpp | 153 | ||||
-rw-r--r-- | dm/DMSrcSink.h | 22 |
3 files changed, 202 insertions, 57 deletions
@@ -343,9 +343,6 @@ static void push_codec_src(Path path, CodecSrc::Mode mode, CodecSrc::DstColorTyp case CodecSrc::kSubset_Mode: folder.append("codec_subset"); break; - case CodecSrc::kGen_Mode: - folder.append("gen"); - break; } switch (dstColorType) { @@ -426,6 +423,40 @@ static void push_android_codec_src(Path path, AndroidCodecSrc::Mode mode, push_src("image", folder, src); } +static void push_image_gen_src(Path path, ImageGenSrc::Mode mode, SkAlphaType alphaType, bool isGpu) +{ + SkString folder; + switch (mode) { + case ImageGenSrc::kCodec_Mode: + folder.append("gen_codec"); + break; + case ImageGenSrc::kPlatform_Mode: + folder.append("gen_platform"); + break; + } + + if (isGpu) { + folder.append("_gpu"); + } else { + switch (alphaType) { + case kOpaque_SkAlphaType: + folder.append("_opaque"); + break; + case kPremul_SkAlphaType: + folder.append("_premul"); + break; + case kUnpremul_SkAlphaType: + folder.append("_unpremul"); + break; + default: + break; + } + } + + ImageGenSrc* src = new ImageGenSrc(path, mode, alphaType, isGpu); + push_src("image", folder, src); +} + static void push_codec_srcs(Path path) { SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str())); if (!encoded) { @@ -445,7 +476,6 @@ static void push_codec_srcs(Path path) { 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); @@ -487,19 +517,6 @@ static void push_codec_srcs(Path path) { } for (CodecSrc::Mode mode : nativeModes) { - // SkCodecImageGenerator only runs for the default colorType - // recommended by SkCodec. There is no need to generate multiple - // tests for different colorTypes. - // TODO (msarett): Add scaling support to SkCodecImageGenerator. - if (CodecSrc::kGen_Mode == mode) { - // FIXME: The gpu backend does not draw kGray sources correctly. (skbug.com/4822) - if (kGray_8_SkColorType != codec->getInfo().colorType()) { - push_codec_src(path, mode, CodecSrc::kGetFromCanvas_DstColorType, - codec->getInfo().alphaType(), 1.0f); - } - continue; - } - for (float scale : nativeScales) { for (CodecSrc::DstColorType colorType : colorTypes) { for (SkAlphaType alphaType : alphaModes) { @@ -549,6 +566,39 @@ static void push_codec_srcs(Path path) { } } } + + static const char* const rawExts[] = { + "arw", "cr2", "dng", "nef", "nrw", "orf", "raf", "rw2", "pef", "srw", + "ARW", "CR2", "DNG", "NEF", "NRW", "ORF", "RAF", "RW2", "PEF", "SRW", + }; + + // There is not currently a reason to test RAW images on image generator. + // If we want to enable these tests, we will need to fix skbug.com/5079. + for (const char* ext : rawExts) { + if (path.endsWith(ext)) { + return; + } + } + + // Push image generator GPU test. + // FIXME: The gpu backend does not draw kGray sources correctly. (skbug.com/4822) + if (kGray_8_SkColorType != codec->getInfo().colorType()) { + push_image_gen_src(path, ImageGenSrc::kCodec_Mode, codec->getInfo().alphaType(), true); + } + + // Push image generator CPU tests. + for (SkAlphaType alphaType : alphaModes) { + push_image_gen_src(path, ImageGenSrc::kCodec_Mode, alphaType, false); + +#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) + if (kWEBP_SkEncodedFormat != codec->getEncodedFormat() && + kWBMP_SkEncodedFormat != codec->getEncodedFormat() && + kUnpremul_SkAlphaType != alphaType) + { + push_image_gen_src(path, ImageGenSrc::kPlatform_Mode, alphaType, false); + } +#endif + } } static bool brd_color_type_supported(SkBitmapRegionDecoder::Strategy strategy, diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index 9e45ce9b69..84af854dea 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -14,6 +14,7 @@ #include "SkDocument.h" #include "SkError.h" #include "SkImageGenerator.h" +#include "SkImageGeneratorCG.h" #include "SkMallocPixelRef.h" #include "SkMultiPictureDraw.h" #include "SkNullCanvas.h" @@ -263,15 +264,7 @@ CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType, SkAlphaType {} bool CodecSrc::veto(SinkFlags flags) const { - // Test CodecImageGenerator on 8888, 565, and gpu - if (kGen_Mode == fMode) { - // For image generator, we want to test kDirect approaches for kRaster and kGPU, - // while skipping everything else. - return (flags.type != SinkFlags::kRaster && flags.type != SinkFlags::kGPU) || - flags.approach != SinkFlags::kDirect; - } - - // Test all other modes to direct raster backends (8888 and 565). + // Test to direct raster backends (8888 and 565). return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect; } @@ -333,42 +326,12 @@ bool get_decode_info(SkImageInfo* decodeInfo, SkColorType canvasColorType, return true; } -Error test_gen(SkCanvas* canvas, SkData* data) { - SkAutoTDelete<SkImageGenerator> gen = SkCodecImageGenerator::NewFromEncodedCodec(data); - if (!gen) { - return "Could not create image generator."; - } - - // FIXME: The gpu backend does not draw kGray sources correctly. (skbug.com/4822) - // Currently, we will avoid creating a CodecSrc for this case (see DM.cpp). - SkASSERT(kGray_8_SkColorType != gen->getInfo().colorType()); - - if (kOpaque_SkAlphaType != gen->getInfo().alphaType() && - kRGB_565_SkColorType == canvas->imageInfo().colorType()) { - return Error::Nonfatal("Skip testing non-opaque images to 565."); - } - - SkAutoTDelete<SkImage> image(SkImage::NewFromGenerator(gen.detach(), nullptr)); - if (!image) { - return "Could not create image from codec image generator."; - } - - canvas->drawImage(image, 0, 0); - return ""; -} - Error CodecSrc::draw(SkCanvas* canvas) const { SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); if (!encoded) { return SkStringPrintf("Couldn't read %s.", fPath.c_str()); } - // The CodecImageGenerator test does not share much code with the other tests, - // so we will handle it in its own function. - if (kGen_Mode == fMode) { - return test_gen(canvas, encoded); - } - SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); if (nullptr == codec.get()) { return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str()); @@ -802,6 +765,118 @@ Name AndroidCodecSrc::name() const { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +ImageGenSrc::ImageGenSrc(Path path, Mode mode, SkAlphaType alphaType, bool isGpu) + : fPath(path) + , fMode(mode) + , fDstAlphaType(alphaType) + , fIsGpu(isGpu) + , fRunSerially(serial_from_path_name(path)) +{} + +bool ImageGenSrc::veto(SinkFlags flags) const { + if (fIsGpu) { + return flags.type != SinkFlags::kGPU || flags.approach != SinkFlags::kDirect; + } + + return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect; +} + +Error ImageGenSrc::draw(SkCanvas* canvas) const { + if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) { + return Error::Nonfatal("Uninteresting to test image generator to 565."); + } + + SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); + if (!encoded) { + return SkStringPrintf("Couldn't read %s.", fPath.c_str()); + } + + SkAutoTDelete<SkImageGenerator> gen(nullptr); + switch (fMode) { + case kCodec_Mode: + gen.reset(SkCodecImageGenerator::NewFromEncodedCodec(encoded)); + if (!gen) { + return "Could not create codec image generator."; + } + break; +#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) + case kPlatform_Mode: + gen.reset(SkImageGeneratorCG::NewFromEncodedCG(encoded)); + if (!gen) { + return "Could not create CG image generator."; + } + break; +#endif + default: + SkASSERT(false); + return "Invalid image generator mode"; + } + + // Test deferred decoding path on GPU + if (fIsGpu) { + // FIXME: The gpu backend does not draw kGray sources correctly. (skbug.com/4822) + // We have disabled these tests in DM.cpp. + SkASSERT(kGray_8_SkColorType != gen->getInfo().colorType()); + + SkAutoTDelete<SkImage> image(SkImage::NewFromGenerator(gen.detach(), nullptr)); + if (!image) { + return "Could not create image from codec image generator."; + } + canvas->drawImage(image, 0, 0); + return ""; + } + + // Test various color and alpha types on CPU + SkImageInfo decodeInfo = gen->getInfo().makeAlphaType(fDstAlphaType); + + if (kGray_8_SkColorType == decodeInfo.colorType() && + kOpaque_SkAlphaType != decodeInfo.alphaType()) { + return Error::Nonfatal("Avoid requesting non-opaque kGray8 decodes."); + } + + SkAutoTUnref<SkColorTable> colorTable(nullptr); + SkPMColor* colorPtr = nullptr; + int* colorCountPtr = nullptr; + int maxColors = 256; + if (kIndex_8_SkColorType == decodeInfo.colorType()) { + SkPMColor colors[256]; + colorTable.reset(new SkColorTable(colors, maxColors)); + colorPtr = const_cast<SkPMColor*>(colorTable->readColors()); + colorCountPtr = &maxColors; + } + + SkBitmap bitmap; + if (!bitmap.tryAllocPixels(decodeInfo, nullptr, colorTable.get())) { + return SkStringPrintf("Image(%s) is too large (%d x %d)", fPath.c_str(), + decodeInfo.width(), decodeInfo.height()); + } + + if (!gen->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), colorPtr, + colorCountPtr)) + { + return SkStringPrintf("Image generator could not getPixels() for %s\n", fPath.c_str()); + } + + premultiply_if_necessary(bitmap); + canvas->drawBitmap(bitmap, 0, 0); + return ""; +} + +SkISize ImageGenSrc::size() const { + SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); + SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); + if (nullptr == codec) { + return SkISize::Make(0, 0); + } + return codec->getInfo().dimensions(); +} + +Name ImageGenSrc::name() const { + return SkOSPath::Basename(fPath.c_str()); +} + +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + static const SkRect kSKPViewport = {0,0, 1000,1000}; SKPSrc::SKPSrc(Path path) : fPath(path) {} diff --git a/dm/DMSrcSink.h b/dm/DMSrcSink.h index 638d13824a..b6ee5f09d7 100644 --- a/dm/DMSrcSink.h +++ b/dm/DMSrcSink.h @@ -112,7 +112,6 @@ public: 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) }; enum DstColorType { kGetFromCanvas_DstColorType, @@ -187,6 +186,27 @@ private: uint32_t fSampleSize; }; +class ImageGenSrc : public Src { +public: + enum Mode { + kCodec_Mode, // Use CodecImageGenerator + kPlatform_Mode, // Uses CG or WIC + }; + ImageGenSrc(Path, Mode, SkAlphaType, bool); + + Error draw(SkCanvas*) const override; + SkISize size() const override; + Name name() const override; + bool veto(SinkFlags) const override; + bool serial() const override { return fRunSerially; } +private: + Path fPath; + Mode fMode; + SkAlphaType fDstAlphaType; + bool fIsGpu; + bool fRunSerially; +}; + class SKPSrc : public Src { public: explicit SKPSrc(Path path); |