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 <robertphillips@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Greg Daniel 2018-02-07 10:21:48 -05:00 committed by Skia Commit-Bot
parent 2a223358ed
commit a4ead65e2c
8 changed files with 99 additions and 50 deletions

View File

@ -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]);
}

View File

@ -49,7 +49,7 @@ sk_sp<GrTextureProxy> 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);

View File

@ -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<GrTextureProxy> GrProxyProvider::createMipMapProxy(const GrSurfaceDesc& de
SkDestinationSurfaceColorMode::kLegacy);
}
sk_sp<GrTextureProxy> 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<SkMipMap> 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<SkImage> 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<GrTextureProxy> proxy = this->createLazyProxy(
[desc, baseLevel, mipmaps, mipColorMode]
(GrResourceProvider* resourceProvider, GrSurfaceOrigin* /*outOrigin*/) {
if (!resourceProvider) {
return sk_sp<GrTexture>();
}
const int mipLevelCount = mipmaps->countLevels() + 1;
std::unique_ptr<GrMipLevel[]> 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<GrTextureProxy> GrProxyProvider::createProxy(const GrSurfaceDesc& desc,
SkBackingFit fit,
SkBudgeted budgeted,

View File

@ -18,6 +18,7 @@ class GrCaps;
class GrResourceProvider;
class GrSingleOwner;
class GrBackendRenderTarget;
class SkBitmap;
class SkImage;
/*
@ -109,6 +110,12 @@ public:
*/
sk_sp<GrTextureProxy> createMipMapProxy(const GrSurfaceDesc&, SkBudgeted);
/*
* Creates a new mipmapped texture proxy for the bitmap with mip levels generated by the cpu.
*/
sk_sp<GrTextureProxy> createMipMapProxyFromBitmap(const SkBitmap& bitmap,
SkColorSpace* dstColorSpace);
/*
* Create a GrSurfaceProxy without any data.
*/

View File

@ -112,50 +112,6 @@ void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, SkPixelRef* pix
pixelRef->addGenIDChangeListener(new Invalidator(key));
}
sk_sp<GrTextureProxy> 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<SkMipMap> mipmaps(SkMipMap::Build(pixmap, colorMode, nullptr));
if (!mipmaps) {
return nullptr;
}
const int mipLevelCount = mipmaps->countLevels() + 1;
if (mipLevelCount < 1) {
return nullptr;
}
std::unique_ptr<GrMipLevel[]> 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<GrTextureProxy> GrCopyBaseMipMapToTextureProxy(GrContext* ctx, GrTextureProxy* baseProxy) {
SkASSERT(baseProxy);

View File

@ -208,9 +208,6 @@ sk_sp<GrTextureProxy> GrRefCachedBitmapTextureProxy(GrContext*,
sk_sp<GrTextureProxy> GrUploadBitmapToTextureProxy(GrProxyProvider*, const SkBitmap&,
SkColorSpace* dstColorSpace);
sk_sp<GrTextureProxy> GrGenerateMipMapsAndUploadToTextureProxy(GrProxyProvider*, const SkBitmap&,
SkColorSpace* dstColorSpace);
/**
* Creates a new texture for the pixmap.
*/

View File

@ -628,7 +628,7 @@ sk_sp<SkImage> 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);

View File

@ -830,7 +830,7 @@ sk_sp<GrTextureProxy> 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);