From 7e1912a8ab48134eb3a631f188ad8aa262e8eaa0 Mon Sep 17 00:00:00 2001 From: Greg Daniel Date: Thu, 8 Feb 2018 09:15:33 -0500 Subject: [PATCH] Move GrMakeCachedBitmapProxy work in lazy mode This basically wraps the bitmap in an SkImage and uses the GrMakeCachedImageProxy call to create the proxy. Bug: skia: Change-Id: I648a9cac3a316231bfb1bcedaae2009b7de0356c Reviewed-on: https://skia-review.googlesource.com/105360 Commit-Queue: Greg Daniel Reviewed-by: Robert Phillips --- src/gpu/GrProxyProvider.cpp | 4 +- src/gpu/GrProxyProvider.h | 6 ++ src/gpu/SkGr.cpp | 36 +++++------- src/gpu/SkGr.h | 18 ++---- src/shaders/SkPerlinNoiseShader.cpp | 88 +++++++++++++++++------------ 5 files changed, 80 insertions(+), 72 deletions(-) diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp index b73d92446d..0076a1a82d 100644 --- a/src/gpu/GrProxyProvider.cpp +++ b/src/gpu/GrProxyProvider.cpp @@ -341,8 +341,8 @@ sk_sp GrProxyProvider::createMipMapProxyFromBitmap(const SkBitma // In non-ddl we will always instantiate right away. Thus we never want to copy the SkBitmap // even if its mutable. In ddl, if the bitmap is mutable then we must make a copy since the // upload of the data to the gpu can happen at anytime and the bitmap may change by then. - SkCopyPixelsMode copyMode = fResourceProvider ? kNever_SkCopyPixelsMode - : kIfMutable_SkCopyPixelsMode; + SkCopyPixelsMode copyMode = this->mutableBitmapsNeedCopy() ? kIfMutable_SkCopyPixelsMode + : kNever_SkCopyPixelsMode; sk_sp baseLevel = SkMakeImageFromRasterBitmap(bitmap, copyMode); if (!baseLevel) { diff --git a/src/gpu/GrProxyProvider.h b/src/gpu/GrProxyProvider.h index aa1d991fae..af661c1f4d 100644 --- a/src/gpu/GrProxyProvider.h +++ b/src/gpu/GrProxyProvider.h @@ -228,6 +228,12 @@ public: void removeAllUniqueKeys(); + /** + * Helper function for callers who are wrapping a bitmap into an SkImage so they know whether or + * not that bitmap should be copied or not. + */ + bool mutableBitmapsNeedCopy() const { return !SkToBool(fResourceProvider); } + private: friend class GrAHardwareBufferImageGenerator; // for createWrapped diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index 1d210c4008..cf8b3ab864 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -25,6 +25,7 @@ #include "SkData.h" #include "SkImage_Base.h" #include "SkImageInfoPriv.h" +#include "SkImagePriv.h" #include "SkMaskFilterBase.h" #include "SkMessageBus.h" #include "SkMipMap.h" @@ -167,33 +168,24 @@ sk_sp GrRefCachedBitmapTextureProxy(GrContext* ctx, } sk_sp GrMakeCachedBitmapProxy(GrProxyProvider* proxyProvider, - const SkBitmap& bitmap) { - GrUniqueKey originalKey; - - if (!bitmap.isVolatile()) { - SkIPoint origin = bitmap.pixelRefOrigin(); - SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.width(), bitmap.height()); - GrMakeKeyFromImageID(&originalKey, bitmap.pixelRef()->getGenerationID(), subset); + const SkBitmap& bitmap, + SkBackingFit fit) { + if (!bitmap.peekPixels(nullptr)) { + return nullptr; } - sk_sp proxy; + // In non-ddl we will always instantiate right away. Thus we never want to copy the SkBitmap + // even if its mutable. In ddl, if the bitmap is mutable then we must make a copy since the + // upload of the data to the gpu can happen at anytime and the bitmap may change by then. + SkCopyPixelsMode cpyMode = proxyProvider->mutableBitmapsNeedCopy() ? kIfMutable_SkCopyPixelsMode + : kNever_SkCopyPixelsMode; + sk_sp image = SkMakeImageFromRasterBitmap(bitmap, cpyMode); - if (originalKey.isValid()) { - proxy = proxyProvider->findOrCreateProxyByUniqueKey(originalKey, kTopLeft_GrSurfaceOrigin); - } - if (!proxy) { - // Pass nullptr for |dstColorSpace|. This is lenient - we allow a wider range of - // color spaces in legacy mode. Unfortunately, we have to be lenient here, since - // we can't necessarily know the |dstColorSpace| at this time. - proxy = GrUploadBitmapToTextureProxy(proxyProvider, bitmap, nullptr); - if (proxy && originalKey.isValid()) { - SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin); - proxyProvider->assignUniqueKeyToProxy(originalKey, proxy.get()); - GrInstallBitmapUniqueKeyInvalidator(originalKey, bitmap.pixelRef()); - } + if (!image) { + return nullptr; } - return proxy; + return GrMakeCachedImageProxy(proxyProvider, std::move(image), fit); } static void create_unique_key_for_image(const SkImage* image, GrUniqueKey* result) { diff --git a/src/gpu/SkGr.h b/src/gpu/SkGr.h index 86f584cf58..ea3221074c 100644 --- a/src/gpu/SkGr.h +++ b/src/gpu/SkGr.h @@ -228,18 +228,12 @@ sk_sp GrUploadMipMapToTextureProxy(GrProxyProvider*, const SkIma int mipLevelCount, SkDestinationSurfaceColorMode colorMode); -// This is intended to replace: -// SkAutoLockPixels alp(bitmap, true); -// if (!bitmap.readyToDraw()) { -// return nullptr; -// } -// sk_sp texture = GrMakeCachedBitmapTexture(fContext.get(), bitmap, -// GrSamplerState::ClampNearest(), -// nullptr); -// if (!texture) { -// return nullptr; -// } -sk_sp GrMakeCachedBitmapProxy(GrProxyProvider*, const SkBitmap& bitmap); +/* + * Create a texture proxy from the provided bitmap by wrapping it in an image and calling + * GrMakeCachedImageProxy. + */ +sk_sp GrMakeCachedBitmapProxy(GrProxyProvider*, const SkBitmap& bitmap, + SkBackingFit fit = SkBackingFit::kExact); /* * Create a texture proxy from the provided 'srcImage' and add it to the texture cache diff --git a/src/shaders/SkPerlinNoiseShader.cpp b/src/shaders/SkPerlinNoiseShader.cpp index 5979a9b4b0..e43fe01fb2 100644 --- a/src/shaders/SkPerlinNoiseShader.cpp +++ b/src/shaders/SkPerlinNoiseShader.cpp @@ -12,10 +12,10 @@ #include "SkColorFilter.h" #include "SkMakeUnique.h" #include "SkReadBuffer.h" -#include "SkWriteBuffer.h" #include "SkShader.h" -#include "SkUnPreMultiply.h" #include "SkString.h" +#include "SkUnPreMultiply.h" +#include "SkWriteBuffer.h" #if SK_SUPPORT_GPU #include "GrContext.h" @@ -107,16 +107,19 @@ public: } #if SK_SUPPORT_GPU - fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1)); - fPermutationsBitmap.setPixels(fLatticeSelector); + SkImageInfo info = SkImageInfo::MakeA8(kBlockSize, 1); + SkPixmap permutationsPixmap(info, fLatticeSelector, info.minRowBytes()); + fPermutationsImage = SkImage::MakeFromRaster(permutationsPixmap, nullptr, nullptr); - fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4)); - fNoiseBitmap.setPixels(fNoise[0][0]); + info = SkImageInfo::MakeN32Premul(kBlockSize, 4); + SkPixmap noisePixmap(info, fNoise[0][0], info.minRowBytes()); + fNoiseImage = SkImage::MakeFromRaster(noisePixmap, nullptr, nullptr); - fImprovedPermutationsBitmap.setInfo(SkImageInfo::MakeA8(256, 1)); - fImprovedPermutationsBitmap.setPixels(improved_noise_permutations); + info = SkImageInfo::MakeA8(256, 1); + SkPixmap impPermutationsPixmap(info, improved_noise_permutations, info.minRowBytes()); + fImprovedPermutationsImage = SkImage::MakeFromRaster(impPermutationsPixmap, nullptr, + nullptr); - fGradientBitmap.setInfo(SkImageInfo::MakeN32Premul(16, 1)); static uint8_t gradients[] = { 2, 2, 1, 0, 0, 2, 1, 0, 2, 0, 1, 0, @@ -133,7 +136,9 @@ public: 1, 0, 2, 0, 0, 2, 1, 0, 1, 0, 0, 0 }; - fGradientBitmap.setPixels(gradients); + info = SkImageInfo::MakeN32Premul(16, 1); + SkPixmap gradPixmap(info, gradients, info.minRowBytes()); + fGradientImage = SkImage::MakeFromRaster(gradPixmap, nullptr, nullptr); #endif } @@ -143,10 +148,10 @@ public: , fTileSize(that.fTileSize) , fBaseFrequency(that.fBaseFrequency) , fStitchDataInit(that.fStitchDataInit) - , fPermutationsBitmap(that.fPermutationsBitmap) - , fNoiseBitmap(that.fNoiseBitmap) - , fImprovedPermutationsBitmap(that.fImprovedPermutationsBitmap) - , fGradientBitmap(that.fGradientBitmap) { + , fPermutationsImage(that.fPermutationsImage) + , fNoiseImage(that.fNoiseImage) + , fImprovedPermutationsImage(that.fImprovedPermutationsImage) + , fGradientImage(that.fGradientImage) { memcpy(fLatticeSelector, that.fLatticeSelector, sizeof(fLatticeSelector)); memcpy(fNoise, that.fNoise, sizeof(fNoise)); memcpy(fGradient, that.fGradient, sizeof(fGradient)); @@ -164,10 +169,10 @@ public: private: #if SK_SUPPORT_GPU - SkBitmap fPermutationsBitmap; - SkBitmap fNoiseBitmap; - SkBitmap fImprovedPermutationsBitmap; - SkBitmap fGradientBitmap; + sk_sp fPermutationsImage; + sk_sp fNoiseImage; + sk_sp fImprovedPermutationsImage; + sk_sp fGradientImage; #endif inline int random() { @@ -294,13 +299,15 @@ public: public: #if SK_SUPPORT_GPU - const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; } + const sk_sp getPermutationsImage() const { return fPermutationsImage; } - const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; } + const sk_sp getNoiseImage() const { return fNoiseImage; } - const SkBitmap& getImprovedPermutationsBitmap() const { return fImprovedPermutationsBitmap; } + const sk_sp getImprovedPermutationsImage() const { + return fImprovedPermutationsImage; + } - const SkBitmap& getGradientBitmap() const { return fGradientBitmap; } + const sk_sp getGradientImage() const { return fGradientImage; } #endif }; @@ -1409,17 +1416,20 @@ std::unique_ptr SkPerlinNoiseShaderImpl::asFragmentProcesso m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1); m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1); + auto proxyProvider = args.fContext->contextPriv().proxyProvider(); if (fType == kImprovedNoise_Type) { - GrSamplerState textureParams(GrSamplerState::WrapMode::kRepeat, - GrSamplerState::Filter::kNearest); + // Need to assert that the textures we'll create are power of 2 so a copy isn't needed. + // We also know that we will not be using mipmaps. If things things weren't true we should + // go through GrBitmapTextureMaker to handle needed copies. + const sk_sp permutationsImage = paintingData->getImprovedPermutationsImage(); + SkASSERT(SkIsPow2(permutationsImage->width()) && SkIsPow2(permutationsImage->height())); sk_sp permutationsTexture( - GrRefCachedBitmapTextureProxy(args.fContext, - paintingData->getImprovedPermutationsBitmap(), - textureParams, nullptr)); + GrMakeCachedImageProxy(proxyProvider, std::move(permutationsImage))); + + const sk_sp gradientImage = paintingData->getGradientImage(); + SkASSERT(SkIsPow2(gradientImage->width()) && SkIsPow2(gradientImage->height())); sk_sp gradientTexture( - GrRefCachedBitmapTextureProxy(args.fContext, - paintingData->getGradientBitmap(), - textureParams, nullptr)); + GrMakeCachedImageProxy(proxyProvider, std::move(gradientImage))); return GrImprovedPerlinNoiseEffect::Make(fNumOctaves, fSeed, std::move(paintingData), std::move(permutationsTexture), std::move(gradientTexture), m); @@ -1441,12 +1451,18 @@ std::unique_ptr SkPerlinNoiseShaderImpl::asFragmentProcesso GrConstColorProcessor::InputMode::kIgnore); } - sk_sp permutationsProxy = GrMakeCachedBitmapProxy( - args.fContext->contextPriv().proxyProvider(), - paintingData->getPermutationsBitmap()); - sk_sp noiseProxy = GrMakeCachedBitmapProxy( - args.fContext->contextPriv().proxyProvider(), - paintingData->getNoiseBitmap()); + // Need to assert that the textures we'll create are power of 2 so that now copy is needed. We + // also know that we will not be using mipmaps. If things things weren't true we should go + // through GrBitmapTextureMaker to handle needed copies. + const sk_sp permutationsImage = paintingData->getPermutationsImage(); + SkASSERT(SkIsPow2(permutationsImage->width()) && SkIsPow2(permutationsImage->height())); + sk_sp permutationsProxy = GrMakeCachedImageProxy(proxyProvider, + std::move(permutationsImage)); + + const sk_sp noiseImage = paintingData->getNoiseImage(); + SkASSERT(SkIsPow2(noiseImage->width()) && SkIsPow2(noiseImage->height())); + sk_sp noiseProxy = GrMakeCachedImageProxy(proxyProvider, + std::move(noiseImage)); if (permutationsProxy && noiseProxy) { auto inner = GrPerlinNoise2Effect::Make(fType,