From 57ae6cfe01b811aaead80872ed9e5e1d30f35f81 Mon Sep 17 00:00:00 2001 From: Brian Osman Date: Tue, 15 Nov 2016 18:07:26 +0000 Subject: Revert "Support decoding images to multiple formats, depending on usage" This reverts commit c73a1ecbed64652b3d7aa8dc6face9a2205ce830. Reason for revert: ANGLE and CommandBuffer failures Original change's description: > Support decoding images to multiple formats, depending on usage > > Our codec generator will now preserve any asked-for color space, and > convert the encoded data to that representation. Cacherator now > allows decoding an image to both legacy (nullptr color space), and > color-correct formats. In color-correct mode, we choose the best > decoded format, based on the original properties, and our backend's > capabilities. Preference is given to the native format, when it's > already texturable (sRGB 8888 or F16 linear). Otherwise, we prefer > linear F16, and fall back to sRGB when that's not an option. > > BUG=skia:5907 > > GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4438 > > Change-Id: I847c243dcfb72d8c0f1f6fc73c09547adea933f0 > Reviewed-on: https://skia-review.googlesource.com/4438 > Reviewed-by: Matt Sarett > Commit-Queue: Brian Osman > TBR=mtklein@google.com,bsalomon@google.com,msarett@google.com,brianosman@google.com,reed@google.com NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Change-Id: I1818f937464573d601f64e5a1f1eb43f5a778f4e Reviewed-on: https://skia-review.googlesource.com/4832 Commit-Queue: Brian Osman Reviewed-by: Brian Osman --- src/core/SkImageCacherator.cpp | 255 ++++------------------------------------- 1 file changed, 24 insertions(+), 231 deletions(-) (limited to 'src/core/SkImageCacherator.cpp') diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp index d6f816e8ef..54045d5821 100644 --- a/src/core/SkImageCacherator.cpp +++ b/src/core/SkImageCacherator.cpp @@ -7,7 +7,6 @@ #include "SkBitmap.h" #include "SkBitmapCache.h" -#include "SkColorSpace_Base.h" #include "SkImage_Base.h" #include "SkImageCacherator.h" #include "SkMallocPixelRef.h" @@ -85,19 +84,8 @@ SkImageCacherator::Validator::Validator(sk_sp gen, const SkIRec subset = &bounds; } - fInfo = info.makeWH(subset->width(), subset->height()); + fInfo = info.makeWH(subset->width(), subset->height()); fOrigin = SkIPoint::Make(subset->x(), subset->y()); - - // If the encoded data is in a strange color space (it's not an XYZ matrix space), we won't be - // able to preserve the gamut of the encoded data when we decode it. Instead, we'll have to - // decode to a known color space (linear sRGB is a good choice). But we need to adjust the - // stored color space, because drawing code will ask the SkImage for its color space, which - // will in turn ask the cacherator. If we return the A2B color space, then we will be unable to - // construct a source-to-dest gamut transformation matrix. - if (fInfo.colorSpace() && - SkColorSpace_Base::Type::kXYZ != as_CSB(fInfo.colorSpace())->type()) { - fInfo = fInfo.makeColorSpace(SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named)); - } } SkImageCacherator* SkImageCacherator::NewFromGenerator(SkImageGenerator* gen, @@ -111,12 +99,8 @@ SkImageCacherator::SkImageCacherator(Validator* validator) : fSharedGenerator(std::move(validator->fSharedGenerator)) // we take ownership , fInfo(validator->fInfo) , fOrigin(validator->fOrigin) + , fUniqueID(validator->fUniqueID) { - fUniqueIDs[kLegacy_CachedFormat] = validator->fUniqueID; - for (int i = 1; i < kNumCachedFormats; ++i) { - // We lazily allocate IDs for non-default caching cases - fUniqueIDs[i] = kNeedNewImageUniqueID; - } SkASSERT(fSharedGenerator); } @@ -137,26 +121,24 @@ static bool check_output_bitmap(const SkBitmap& bitmap, uint32_t expectedID) { // Note, this returns a new, mutable, bitmap, with a new genID. // If you want the immutable bitmap with the same ID as our cacherator, call tryLockAsBitmap() // -bool SkImageCacherator::generateBitmap(SkBitmap* bitmap, const SkImageInfo& decodeInfo) { +bool SkImageCacherator::generateBitmap(SkBitmap* bitmap) { SkBitmap::Allocator* allocator = SkResourceCache::GetAllocator(); ScopedGenerator generator(fSharedGenerator); const SkImageInfo& genInfo = generator->getInfo(); - if (decodeInfo.dimensions() == genInfo.dimensions()) { + if (fInfo.dimensions() == genInfo.dimensions()) { SkASSERT(fOrigin.x() == 0 && fOrigin.y() == 0); // fast-case, no copy needed - return generator->tryGenerateBitmap(bitmap, decodeInfo, allocator); + return generator->tryGenerateBitmap(bitmap, fInfo, allocator); } else { // need to handle subsetting, so we first generate the full size version, and then // "read" from it to get our subset. See https://bug.skia.org/4213 SkBitmap full; - if (!generator->tryGenerateBitmap(&full, - decodeInfo.makeWH(genInfo.width(), genInfo.height()), - allocator)) { + if (!generator->tryGenerateBitmap(&full, genInfo, allocator)) { return false; } - if (!bitmap->tryAllocPixels(decodeInfo, nullptr, full.getColorTable())) { + if (!bitmap->tryAllocPixels(fInfo, nullptr, full.getColorTable())) { return false; } return full.readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), @@ -177,28 +159,22 @@ bool SkImageCacherator::directGeneratePixels(const SkImageInfo& info, void* pixe ////////////////////////////////////////////////////////////////////////////////////////////////// -bool SkImageCacherator::lockAsBitmapOnlyIfAlreadyCached(SkBitmap* bitmap, CachedFormat format) { - return kNeedNewImageUniqueID != fUniqueIDs[format] && - SkBitmapCache::Find(fUniqueIDs[format], bitmap) && - check_output_bitmap(*bitmap, fUniqueIDs[format]); +bool SkImageCacherator::lockAsBitmapOnlyIfAlreadyCached(SkBitmap* bitmap) { + return SkBitmapCache::Find(fUniqueID, bitmap) && check_output_bitmap(*bitmap, fUniqueID); } bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap, const SkImage* client, - SkImage::CachingHint chint, CachedFormat format, - const SkImageInfo& info) { - if (this->lockAsBitmapOnlyIfAlreadyCached(bitmap, format)) { + SkImage::CachingHint chint) { + if (this->lockAsBitmapOnlyIfAlreadyCached(bitmap)) { return true; } - if (!this->generateBitmap(bitmap, info)) { + if (!this->generateBitmap(bitmap)) { return false; } - if (kNeedNewImageUniqueID == fUniqueIDs[format]) { - fUniqueIDs[format] = SkNextID::ImageID(); - } - bitmap->pixelRef()->setImmutableWithID(fUniqueIDs[format]); + bitmap->pixelRef()->setImmutableWithID(fUniqueID); if (SkImage::kAllow_CachingHint == chint) { - SkBitmapCache::Add(fUniqueIDs[format], *bitmap); + SkBitmapCache::Add(fUniqueID, *bitmap); if (client) { as_IB(client)->notifyAddedToCache(); } @@ -207,17 +183,9 @@ bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap, const SkImage* client, } bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap, const SkImage* client, - SkDestinationSurfaceColorMode colorMode, SkImage::CachingHint chint) { - CachedFormat format = chooseCacheFormat(colorMode); - SkImageInfo cacheInfo = buildCacheInfo(format); - - if (kNeedNewImageUniqueID == fUniqueIDs[format]) { - fUniqueIDs[format] = SkNextID::ImageID(); - } - - if (this->tryLockAsBitmap(bitmap, client, chint, format, cacheInfo)) { - return check_output_bitmap(*bitmap, fUniqueIDs[format]); + if (this->tryLockAsBitmap(bitmap, client, chint)) { + return check_output_bitmap(*bitmap, fUniqueID); } #if SK_SUPPORT_GPU @@ -226,8 +194,7 @@ bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap, const SkImage* client, { ScopedGenerator generator(fSharedGenerator); - SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), - cacheInfo.width(), cacheInfo.height()); + SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width(), fInfo.height()); tex.reset(generator->generateTexture(nullptr, &subset)); } if (!tex) { @@ -235,27 +202,27 @@ bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap, const SkImage* client, return false; } - if (!bitmap->tryAllocPixels(cacheInfo)) { + if (!bitmap->tryAllocPixels(fInfo)) { bitmap->reset(); return false; } const uint32_t pixelOpsFlags = 0; if (!tex->readPixels(0, 0, bitmap->width(), bitmap->height(), - SkImageInfo2GrPixelConfig(cacheInfo, *tex->getContext()->caps()), + SkImageInfo2GrPixelConfig(fInfo, *tex->getContext()->caps()), bitmap->getPixels(), bitmap->rowBytes(), pixelOpsFlags)) { bitmap->reset(); return false; } - bitmap->pixelRef()->setImmutableWithID(fUniqueIDs[format]); + bitmap->pixelRef()->setImmutableWithID(fUniqueID); if (SkImage::kAllow_CachingHint == chint) { - SkBitmapCache::Add(fUniqueIDs[format], *bitmap); + SkBitmapCache::Add(fUniqueID, *bitmap); if (client) { as_IB(client)->notifyAddedToCache(); } } - return check_output_bitmap(*bitmap, fUniqueIDs[format]); + return check_output_bitmap(*bitmap, fUniqueID); #else return false; #endif @@ -301,171 +268,6 @@ static GrTexture* set_key_and_return(GrTexture* tex, const GrUniqueKey& key) { return tex; } -// Abstraction of GrCaps that handles the cases where we don't have a caps pointer (because -// we're in raster mode), or where GPU support is entirely missing. -struct CacheCaps { - CacheCaps(const GrCaps* caps) : fCaps(caps) {} - -#if SK_SUPPORT_GPU - bool supportsHalfFloat() const { - return !fCaps || fCaps->isConfigTexturable(kRGBA_half_GrPixelConfig); - } - - bool supportsSRGB() const { - return !fCaps || fCaps->isConfigTexturable(kSRGBA_8888_GrPixelConfig); - } - - bool supportsSBGR() const { - return !fCaps || fCaps->isConfigTexturable(kSBGRA_8888_GrPixelConfig); - } -#else - bool supportsHalfFloat() const { return true; } - bool supportsSRGB() const { return true; } - bool supportsSBGR() const { return true; } -#endif - - const GrCaps* fCaps; -}; - -SkImageCacherator::CachedFormat SkImageCacherator::chooseCacheFormat( - SkDestinationSurfaceColorMode colorMode, - const GrCaps* grCaps) { - SkColorSpace* cs = fInfo.colorSpace(); - if (!cs || SkDestinationSurfaceColorMode::kLegacy == colorMode) { - return kLegacy_CachedFormat; - } - - CacheCaps caps(grCaps); - switch (fInfo.colorType()) { - case kUnknown_SkColorType: - case kAlpha_8_SkColorType: - case kRGB_565_SkColorType: - case kARGB_4444_SkColorType: - // We don't support color space on these formats, so always decode in legacy mode: - // TODO: Ask the codec to decode these to something else (at least sRGB 8888)? - return kLegacy_CachedFormat; - - case kIndex_8_SkColorType: - // We can't draw from indexed textures with a color space, so ask the codec to expand - if (cs->gammaCloseToSRGB()) { - if (caps.supportsSRGB()) { - return kSRGB8888_CachedFormat; - } else if (caps.supportsHalfFloat()) { - return kLinearF16_CachedFormat; - } else { - return kLegacy_CachedFormat; - } - } else { - if (caps.supportsHalfFloat()) { - return kLinearF16_CachedFormat; - } else if (caps.supportsSRGB()) { - return kSRGB8888_CachedFormat; - } else { - return kLegacy_CachedFormat; - } - } - - case kGray_8_SkColorType: - // TODO: What do we do with grayscale sources that have strange color spaces attached? - // The codecs and color space xform don't handle this correctly (yet), so drop it on - // the floor. (Also, inflating by a factor of 8 is going to be unfortunate). - // As it is, we don't directly support sRGB grayscale, so ask the codec to convert - // it for us. This bypasses some really sketchy code GrUploadPixmapToTexture. - if (cs->gammaCloseToSRGB() && caps.supportsSRGB()) { - return kSRGB8888_CachedFormat; - } else { - return kLegacy_CachedFormat; - } - - case kRGBA_8888_SkColorType: - if (cs->gammaCloseToSRGB()) { - if (caps.supportsSRGB()) { - return kAsIs_CachedFormat; - } else if (caps.supportsHalfFloat()) { - return kLinearF16_CachedFormat; - } else { - return kLegacy_CachedFormat; - } - } else { - if (caps.supportsHalfFloat()) { - return kLinearF16_CachedFormat; - } else if (caps.supportsSRGB()) { - return kSRGB8888_CachedFormat; - } else { - return kLegacy_CachedFormat; - } - } - - case kBGRA_8888_SkColorType: - // Odd case. sBGRA isn't a real thing, so we may not have this texturable. - if (caps.supportsSBGR()) { - if (cs->gammaCloseToSRGB()) { - return kAsIs_CachedFormat; - } else if (caps.supportsHalfFloat()) { - return kLinearF16_CachedFormat; - } else if (caps.supportsSRGB()) { - return kSRGB8888_CachedFormat; - } else { - // sBGRA support without sRGBA is highly unlikely (impossible?) Nevertheless. - return kLegacy_CachedFormat; - } - } else { - if (cs->gammaCloseToSRGB()) { - if (caps.supportsSRGB()) { - return kSRGB8888_CachedFormat; - } else if (caps.supportsHalfFloat()) { - return kLinearF16_CachedFormat; - } else { - return kLegacy_CachedFormat; - } - } else { - if (caps.supportsHalfFloat()) { - return kLinearF16_CachedFormat; - } else if (caps.supportsSRGB()) { - return kSRGB8888_CachedFormat; - } else { - return kLegacy_CachedFormat; - } - } - } - - case kRGBA_F16_SkColorType: - if (!caps.supportsHalfFloat()) { - if (caps.supportsSRGB()) { - return kSRGB8888_CachedFormat; - } else { - return kLegacy_CachedFormat; - } - } else if (cs->gammaIsLinear()) { - return kAsIs_CachedFormat; - } else { - return kLinearF16_CachedFormat; - } - } - SkDEBUGFAIL("Unreachable"); - return kLegacy_CachedFormat; -} - -SkImageInfo SkImageCacherator::buildCacheInfo(CachedFormat format) { - switch (format) { - case kLegacy_CachedFormat: - return fInfo.makeColorSpace(nullptr); - case kAsIs_CachedFormat: - return fInfo; - case kLinearF16_CachedFormat: - return fInfo - .makeColorType(kRGBA_F16_SkColorType) - .makeColorSpace(as_CSB(fInfo.colorSpace())->makeLinearGamma()); - case kSRGB8888_CachedFormat: - return fInfo - .makeColorType(kRGBA_8888_SkColorType) - .makeColorSpace(as_CSB(fInfo.colorSpace())->makeSRGBGamma()); - default: - SkDEBUGFAIL("Invalid cached format"); - return fInfo; - } -} - /* * We have a 5 ways to try to return a texture (in sorted order) * @@ -512,16 +314,7 @@ GrTexture* SkImageCacherator::lockTexture(GrContext* ctx, const GrUniqueKey& key } } - // Determine which cached format we're going to use (which may involve decoding to a different - // info than the generator provides). - CachedFormat format = chooseCacheFormat(colorMode, ctx->caps()); - - // The CachedFormat is both an index for which cache "slot" we'll use to store this particular - // decoded variant of the encoded data, and also a recipe for how to transform the original - // info to get the one that we're going to decode to. - SkImageInfo cacheInfo = buildCacheInfo(format); - - const GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(cacheInfo, *ctx->caps()); + const GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(fInfo, *ctx->caps()); #ifdef SK_SUPPORT_COMPRESSED_TEXTURES_IN_CACHERATOR // 3. Ask the generator to return a compressed form that the GPU might support @@ -550,7 +343,7 @@ GrTexture* SkImageCacherator::lockTexture(GrContext* ctx, const GrUniqueKey& key // 5. Ask the generator to return RGB(A) data, which the GPU can convert SkBitmap bitmap; - if (this->tryLockAsBitmap(&bitmap, client, chint, format, cacheInfo)) { + if (this->tryLockAsBitmap(&bitmap, client, chint)) { GrTexture* tex = nullptr; if (willBeMipped) { tex = GrGenerateMipMapsAndUploadToTexture(ctx, bitmap, colorMode); -- cgit v1.2.3