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:
parent
2a223358ed
commit
a4ead65e2c
@ -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]);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user