From a4ead65e2c80b6e649f31e28e8fa116aca83fad4 Mon Sep 17 00:00:00 2001 From: Greg Daniel Date: Wed, 7 Feb 2018 10:21:48 -0500 Subject: [PATCH] Add function to GrProxyProvider to lazily upload mip map data Bug: skia: Change-Id: I906207727242bed8a109bf3ca10b5a6e8e4b952e Reviewed-on: https://skia-review.googlesource.com/104581 Reviewed-by: Robert Phillips Commit-Queue: Greg Daniel --- gm/gamut.cpp | 1 + src/gpu/GrBitmapTextureMaker.cpp | 2 +- src/gpu/GrProxyProvider.cpp | 88 ++++++++++++++++++++++++++++++++ src/gpu/GrProxyProvider.h | 7 +++ src/gpu/SkGr.cpp | 44 ---------------- src/gpu/SkGr.h | 3 -- src/image/SkImage_Gpu.cpp | 2 +- src/image/SkImage_Lazy.cpp | 2 +- 8 files changed, 99 insertions(+), 50 deletions(-) diff --git a/gm/gamut.cpp b/gm/gamut.cpp index c2303af594..55f1b28acf 100644 --- a/gm/gamut.cpp +++ b/gm/gamut.cpp @@ -43,6 +43,7 @@ struct BitmapCellRenderer : public CellRenderer { int scaledSize = sk_float_round2int(scale * gRectSize); fBitmap.allocPixels(SkImageInfo::MakeS32(scaledSize, scaledSize, kPremul_SkAlphaType)); fBitmap.eraseColor(color); + fBitmap.setImmutable(); const char* qualityNames[] = { "None", "Low", "Medium", "High" }; fLabel = SkStringPrintf("Bitmap (%s)", qualityNames[quality]); } diff --git a/src/gpu/GrBitmapTextureMaker.cpp b/src/gpu/GrBitmapTextureMaker.cpp index 7531bf6680..2fd8016818 100644 --- a/src/gpu/GrBitmapTextureMaker.cpp +++ b/src/gpu/GrBitmapTextureMaker.cpp @@ -49,7 +49,7 @@ sk_sp GrBitmapTextureMaker::refOriginalTextureProxy(bool willBeM if (!proxy) { if (willBeMipped) { - proxy = GrGenerateMipMapsAndUploadToTextureProxy(proxyProvider, fBitmap, dstColorSpace); + proxy = proxyProvider->createMipMapProxyFromBitmap(fBitmap, dstColorSpace); } if (!proxy) { proxy = GrUploadBitmapToTextureProxy(proxyProvider, fBitmap, dstColorSpace); diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp index 4e37ac88e9..b73d92446d 100644 --- a/src/gpu/GrProxyProvider.cpp +++ b/src/gpu/GrProxyProvider.cpp @@ -17,10 +17,14 @@ #include "GrTextureProxyCacheAccess.h" #include "GrTextureRenderTargetProxy.h" #include "../private/GrSingleOwner.h" +#include "SkBitmap.h" #include "SkGr.h" #include "SkImage.h" #include "SkImage_Base.h" +#include "SkImageInfoPriv.h" +#include "SkImagePriv.h" #include "SkMipMap.h" +#include "SkTraceEvent.h" #define ASSERT_SINGLE_OWNER \ SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) @@ -309,6 +313,90 @@ sk_sp GrProxyProvider::createMipMapProxy(const GrSurfaceDesc& de SkDestinationSurfaceColorMode::kLegacy); } +sk_sp GrProxyProvider::createMipMapProxyFromBitmap(const SkBitmap& bitmap, + SkColorSpace* dstColorSpace) { + SkDestinationSurfaceColorMode mipColorMode = dstColorSpace + ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware + : SkDestinationSurfaceColorMode::kLegacy; + + if (!SkImageInfoIsValid(bitmap.info(), mipColorMode)) { + return nullptr; + } + + SkPixmap pixmap; + if (!bitmap.peekPixels(&pixmap)) { + return nullptr; + } + + ATRACE_ANDROID_FRAMEWORK("Upload MipMap Texture [%ux%u]", pixmap.width(), pixmap.height()); + sk_sp mipmaps(SkMipMap::Build(pixmap, mipColorMode, nullptr)); + if (!mipmaps) { + return nullptr; + } + + if (mipmaps->countLevels() < 0) { + return nullptr; + } + + // 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; + sk_sp baseLevel = SkMakeImageFromRasterBitmap(bitmap, copyMode); + + if (!baseLevel) { + return nullptr; + } + + GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info(), *this->caps()); + + if (0 == mipmaps->countLevels()) { + return this->createTextureProxy(baseLevel, kNone_GrSurfaceFlags, kTopLeft_GrSurfaceOrigin, + 1, SkBudgeted::kYes, SkBackingFit::kExact); + + } + + sk_sp proxy = this->createLazyProxy( + [desc, baseLevel, mipmaps, mipColorMode] + (GrResourceProvider* resourceProvider, GrSurfaceOrigin* /*outOrigin*/) { + if (!resourceProvider) { + return sk_sp(); + } + + const int mipLevelCount = mipmaps->countLevels() + 1; + std::unique_ptr texels(new GrMipLevel[mipLevelCount]); + + SkPixmap pixmap; + SkAssertResult(baseLevel->peekPixels(&pixmap)); + + // DDL TODO: Instead of copying all this info into GrMipLevels we should just plumb + // the use of SkMipMap down through Ganesh. + texels[0].fPixels = pixmap.addr(); + texels[0].fRowBytes = pixmap.rowBytes(); + + for (int i = 1; i < mipLevelCount; ++i) { + SkMipMap::Level generatedMipLevel; + mipmaps->getLevel(i - 1, &generatedMipLevel); + texels[i].fPixels = generatedMipLevel.fPixmap.addr(); + texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes(); + SkASSERT(texels[i].fPixels); + } + + return resourceProvider->createTexture(desc, SkBudgeted::kYes, texels.get(), + mipLevelCount, mipColorMode); + }, desc, GrMipMapped::kYes, SkBackingFit::kExact, SkBudgeted::kYes); + + if (fResourceProvider) { + // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however + // we're better off instantiating the proxy immediately here. + if (!proxy->priv().doLazyInstantiation(fResourceProvider)) { + return nullptr; + } + } + return proxy; +} + sk_sp GrProxyProvider::createProxy(const GrSurfaceDesc& desc, SkBackingFit fit, SkBudgeted budgeted, diff --git a/src/gpu/GrProxyProvider.h b/src/gpu/GrProxyProvider.h index c5191a681c..aa1d991fae 100644 --- a/src/gpu/GrProxyProvider.h +++ b/src/gpu/GrProxyProvider.h @@ -18,6 +18,7 @@ class GrCaps; class GrResourceProvider; class GrSingleOwner; class GrBackendRenderTarget; +class SkBitmap; class SkImage; /* @@ -109,6 +110,12 @@ public: */ sk_sp createMipMapProxy(const GrSurfaceDesc&, SkBudgeted); + /* + * Creates a new mipmapped texture proxy for the bitmap with mip levels generated by the cpu. + */ + sk_sp createMipMapProxyFromBitmap(const SkBitmap& bitmap, + SkColorSpace* dstColorSpace); + /* * Create a GrSurfaceProxy without any data. */ diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index 09ad206b50..1d210c4008 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -112,50 +112,6 @@ void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, SkPixelRef* pix pixelRef->addGenIDChangeListener(new Invalidator(key)); } -sk_sp GrGenerateMipMapsAndUploadToTextureProxy(GrProxyProvider* proxyProvider, - const SkBitmap& bitmap, - SkColorSpace* dstColorSpace) { - SkDestinationSurfaceColorMode colorMode = dstColorSpace - ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware - : SkDestinationSurfaceColorMode::kLegacy; - - if (!SkImageInfoIsValid(bitmap.info(), colorMode)) { - return nullptr; - } - - SkPixmap pixmap; - if (!bitmap.peekPixels(&pixmap)) { - return nullptr; - } - - ATRACE_ANDROID_FRAMEWORK("Upload MipMap Texture [%ux%u]", pixmap.width(), pixmap.height()); - GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info(), *proxyProvider->caps()); - std::unique_ptr mipmaps(SkMipMap::Build(pixmap, colorMode, nullptr)); - if (!mipmaps) { - return nullptr; - } - - const int mipLevelCount = mipmaps->countLevels() + 1; - if (mipLevelCount < 1) { - return nullptr; - } - - std::unique_ptr texels(new GrMipLevel[mipLevelCount]); - - texels[0].fPixels = pixmap.addr(); - texels[0].fRowBytes = pixmap.rowBytes(); - - for (int i = 1; i < mipLevelCount; ++i) { - SkMipMap::Level generatedMipLevel; - mipmaps->getLevel(i - 1, &generatedMipLevel); - texels[i].fPixels = generatedMipLevel.fPixmap.addr(); - texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes(); - } - - return proxyProvider->createMipMapProxy(desc, SkBudgeted::kYes, texels.get(), mipLevelCount, - colorMode); -} - sk_sp GrCopyBaseMipMapToTextureProxy(GrContext* ctx, GrTextureProxy* baseProxy) { SkASSERT(baseProxy); diff --git a/src/gpu/SkGr.h b/src/gpu/SkGr.h index c131ef8f22..86f584cf58 100644 --- a/src/gpu/SkGr.h +++ b/src/gpu/SkGr.h @@ -208,9 +208,6 @@ sk_sp GrRefCachedBitmapTextureProxy(GrContext*, sk_sp GrUploadBitmapToTextureProxy(GrProxyProvider*, const SkBitmap&, SkColorSpace* dstColorSpace); -sk_sp GrGenerateMipMapsAndUploadToTextureProxy(GrProxyProvider*, const SkBitmap&, - SkColorSpace* dstColorSpace); - /** * Creates a new texture for the pixmap. */ diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp index df342ceee3..042670b6c4 100644 --- a/src/image/SkImage_Gpu.cpp +++ b/src/image/SkImage_Gpu.cpp @@ -628,7 +628,7 @@ sk_sp SkImage::MakeCrossContextFromPixmap(GrContext* context, const SkP if (buildMips) { SkBitmap bmp; bmp.installPixels(pixmap); - proxy = GrGenerateMipMapsAndUploadToTextureProxy(proxyProvider, bmp, dstColorSpace); + proxy = proxyProvider->createMipMapProxyFromBitmap(bmp, dstColorSpace); } else { proxy = GrUploadPixmapToTextureProxy(proxyProvider, pixmap, SkBudgeted::kYes, dstColorSpace); diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp index 92d3a2fed9..1fc6d95094 100644 --- a/src/image/SkImage_Lazy.cpp +++ b/src/image/SkImage_Lazy.cpp @@ -830,7 +830,7 @@ sk_sp SkImage_Lazy::lockTextureProxy(GrContext* ctx, SkBitmap bitmap; if (!proxy && this->lockAsBitmap(&bitmap, chint, format, genPixelsInfo, behavior)) { if (willBeMipped) { - proxy = GrGenerateMipMapsAndUploadToTextureProxy(proxyProvider, bitmap, dstColorSpace); + proxy = proxyProvider->createMipMapProxyFromBitmap(bitmap, dstColorSpace); } if (!proxy) { proxy = GrUploadBitmapToTextureProxy(proxyProvider, bitmap, dstColorSpace);