diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h index eb8f6aefc8..e6e6ff1b96 100644 --- a/include/core/SkSurface.h +++ b/include/core/SkSurface.h @@ -146,9 +146,6 @@ public: } static sk_sp MakeRenderTarget(GrContext* gr, SkBudgeted b, const SkImageInfo& info) { - if (!info.width() || !info.height()) { - return nullptr; - } return MakeRenderTarget(gr, b, info, 0, kBottomLeft_GrSurfaceOrigin, nullptr); } diff --git a/include/gpu/GrRenderTarget.h b/include/gpu/GrRenderTarget.h index dcbe8ea974..ad96229dc7 100644 --- a/include/gpu/GrRenderTarget.h +++ b/include/gpu/GrRenderTarget.h @@ -119,6 +119,8 @@ public: return (GrRenderTargetOpList*) this->getLastOpList(); } + static size_t ComputeSize(const GrSurfaceDesc& desc, int colorValuesPerPixel); + protected: enum class Flags { kNone = 0, diff --git a/include/gpu/GrSurface.h b/include/gpu/GrSurface.h index 3f91a2fb70..8479599948 100644 --- a/include/gpu/GrSurface.h +++ b/include/gpu/GrSurface.h @@ -126,12 +126,11 @@ public: fReleaseCtx = ctx; } + static size_t WorstCaseSize(const GrSurfaceDesc& desc); + void setLastOpList(GrOpList* opList); GrOpList* getLastOpList() { return fLastOpList; } - static size_t WorstCaseSize(const GrSurfaceDesc& desc); - static size_t ComputeSize(const GrSurfaceDesc& desc, int colorSamplesPerPixel, bool hasMIPMaps); - protected: // Methods made available via GrSurfacePriv bool savePixels(const char* filename); diff --git a/include/gpu/GrTexture.h b/include/gpu/GrTexture.h index 211f1937da..c86496c3cf 100644 --- a/include/gpu/GrTexture.h +++ b/include/gpu/GrTexture.h @@ -45,6 +45,8 @@ public: inline GrTexturePriv texturePriv(); inline const GrTexturePriv texturePriv() const; + static size_t ComputeSize(const GrSurfaceDesc&, bool hasMipMaps); + protected: GrTexture(GrGpu*, const GrSurfaceDesc&, GrSLType, bool wasMipMapDataProvided); diff --git a/src/gpu/GrRenderTarget.cpp b/src/gpu/GrRenderTarget.cpp index f15e3b01bf..2828866435 100644 --- a/src/gpu/GrRenderTarget.cpp +++ b/src/gpu/GrRenderTarget.cpp @@ -84,6 +84,17 @@ void GrRenderTarget::onAbandon() { INHERITED::onAbandon(); } +size_t GrRenderTarget::ComputeSize(const GrSurfaceDesc& desc, int colorValuesPerPixel) { + SkASSERT(kUnknown_GrPixelConfig != desc.fConfig); + SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig)); + size_t colorBytes = GrBytesPerPixel(desc.fConfig); + SkASSERT(colorBytes > 0); + + size_t rtSize = colorValuesPerPixel * desc.fWidth * desc.fHeight * colorBytes; + SkASSERT(rtSize <= WorstCaseSize(desc)); + return rtSize; +} + /////////////////////////////////////////////////////////////////////////////// bool GrRenderTargetPriv::attachStencilAttachment(GrStencilAttachment* stencil) { diff --git a/src/gpu/GrRenderTargetProxy.cpp b/src/gpu/GrRenderTargetProxy.cpp index eb750847d2..ac8f5edb76 100644 --- a/src/gpu/GrRenderTargetProxy.cpp +++ b/src/gpu/GrRenderTargetProxy.cpp @@ -82,7 +82,7 @@ size_t GrRenderTargetProxy::onGpuMemorySize() const { } // TODO: do we have enough information to improve this worst case estimate? - return GrSurface::ComputeSize(fDesc, fDesc.fSampleCnt+1, false); + return GrRenderTarget::ComputeSize(fDesc, fDesc.fSampleCnt+1); } sk_sp GrRenderTargetProxy::Make(const GrCaps& caps, diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp index e06fc0109d..9fe00ded5d 100644 --- a/src/gpu/GrSurface.cpp +++ b/src/gpu/GrSurface.cpp @@ -38,16 +38,15 @@ size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc) { } SkASSERT(kUnknown_GrPixelConfig != desc.fConfig); SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig)); - size_t colorBytes = desc.fWidth * desc.fHeight * GrBytesPerPixel(desc.fConfig); + size_t colorBytes = GrBytesPerPixel(desc.fConfig); SkASSERT(colorBytes > 0); - size = colorValuesPerPixel * colorBytes; - size += colorBytes/3; // in case we have to mipmap + size = (size_t) colorValuesPerPixel * desc.fWidth * desc.fHeight * colorBytes; } else { if (GrPixelConfigIsCompressed(desc.fConfig)) { size = GrCompressedFormatDataSize(desc.fConfig, desc.fWidth, desc.fHeight); } else { - size = desc.fWidth * desc.fHeight * GrBytesPerPixel(desc.fConfig); + size = (size_t) desc.fWidth * desc.fHeight * GrBytesPerPixel(desc.fConfig); } size += size/3; // in case we have to mipmap @@ -56,31 +55,6 @@ size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc) { return size; } -size_t GrSurface::ComputeSize(const GrSurfaceDesc& desc, - int colorSamplesPerPixel, - bool hasMIPMaps) { - size_t colorSize; - - SkASSERT(kUnknown_GrPixelConfig != desc.fConfig); - if (GrPixelConfigIsCompressed(desc.fConfig)) { - colorSize = GrCompressedFormatDataSize(desc.fConfig, desc.fWidth, desc.fHeight); - } else { - colorSize = desc.fWidth * desc.fHeight * GrBytesPerPixel(desc.fConfig); - } - SkASSERT(colorSize > 0); - - size_t finalSize = colorSamplesPerPixel * colorSize; - - if (hasMIPMaps) { - // We don't have to worry about the mipmaps being a different size than - // we'd expect because we never change fDesc.fWidth/fHeight. - finalSize += colorSize/3; - } - - SkASSERT(finalSize <= WorstCaseSize(desc)); - return finalSize; -} - template static bool adjust_params(int surfaceWidth, int surfaceHeight, size_t bpp, diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp index de1135a1eb..91036bc156 100644 --- a/src/gpu/GrTexture.cpp +++ b/src/gpu/GrTexture.cpp @@ -35,8 +35,29 @@ void GrTexture::dirtyMipMaps(bool mipMapsDirty) { } } +size_t GrTexture::ComputeSize(const GrSurfaceDesc& desc, bool hasMipMaps) { + size_t textureSize; + + if (GrPixelConfigIsCompressed(desc.fConfig)) { + textureSize = GrCompressedFormatDataSize(desc.fConfig, desc.fWidth, desc.fHeight); + } else { + textureSize = (size_t) desc.fWidth * desc.fHeight * GrBytesPerPixel(desc.fConfig); + } + + if (hasMipMaps) { + // We don't have to worry about the mipmaps being a different size than + // we'd expect because we never change fDesc.fWidth/fHeight. + textureSize += textureSize/3; + } + + SkASSERT(!SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag)); + SkASSERT(textureSize <= WorstCaseSize(desc)); + + return textureSize; +} + size_t GrTexture::onGpuMemorySize() const { - return GrSurface::ComputeSize(fDesc, 1, this->texturePriv().hasMipMaps()); + return ComputeSize(fDesc, this->texturePriv().hasMipMaps()); } void GrTexture::validateDesc() const { diff --git a/src/gpu/GrTextureProxy.cpp b/src/gpu/GrTextureProxy.cpp index 0a7f767fa7..d60bf90ba4 100644 --- a/src/gpu/GrTextureProxy.cpp +++ b/src/gpu/GrTextureProxy.cpp @@ -46,7 +46,7 @@ size_t GrTextureProxy::onGpuMemorySize() const { static const bool kHasMipMaps = true; // TODO: add tracking of mipmap state to improve the estimate - return GrSurface::ComputeSize(fDesc, 1, kHasMipMaps); + return GrTexture::ComputeSize(fDesc, kHasMipMaps); } sk_sp GrTextureProxy::Make(GrTextureProvider* texProvider, diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 9af3acc474..d8f383a196 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -1642,11 +1642,6 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, return return_null_texture(); } - bool wasMipMapDataProvided = false; - if (texels.count() > 1) { - wasMipMapDataProvided = true; - } - GrGLTexture* tex; if (renderTarget) { // unbind the texture from the texture unit before binding it to the frame buffer @@ -1657,9 +1652,12 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); return return_null_texture(); } - tex = new GrGLTextureRenderTarget(this, budgeted, desc, idDesc, rtIDDesc, - wasMipMapDataProvided); + tex = new GrGLTextureRenderTarget(this, budgeted, desc, idDesc, rtIDDesc); } else { + bool wasMipMapDataProvided = false; + if (texels.count() > 1) { + wasMipMapDataProvided = true; + } tex = new GrGLTexture(this, budgeted, desc, idDesc, wasMipMapDataProvided); } tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); diff --git a/src/gpu/gl/GrGLRenderTarget.cpp b/src/gpu/gl/GrGLRenderTarget.cpp index 5af5e67676..2f92e0a82d 100644 --- a/src/gpu/gl/GrGLRenderTarget.cpp +++ b/src/gpu/gl/GrGLRenderTarget.cpp @@ -82,7 +82,7 @@ sk_sp GrGLRenderTarget::MakeWrapped(GrGLGpu* gpu, } size_t GrGLRenderTarget::onGpuMemorySize() const { - return GrSurface::ComputeSize(fDesc, fNumSamplesOwnedPerPixel, false); + return GrRenderTarget::ComputeSize(fDesc, fNumSamplesOwnedPerPixel); } bool GrGLRenderTarget::completeStencilAttachment() { @@ -183,7 +183,7 @@ void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) // Log any renderbuffer's contribution to memory. We only do this if we own the renderbuffer // (have a fMSColorRenderbufferID). if (fMSColorRenderbufferID) { - size_t size = GrSurface::ComputeSize(fDesc, this->msaaSamples(), false); + size_t size = GrRenderTarget::ComputeSize(fDesc, this->msaaSamples()); // Due to this resource having both a texture and a renderbuffer component, dump as // skia/gpu_resources/resource_#/renderbuffer diff --git a/src/gpu/gl/GrGLRenderTarget.h b/src/gpu/gl/GrGLRenderTarget.h index 11b23473cf..fc18e30437 100644 --- a/src/gpu/gl/GrGLRenderTarget.h +++ b/src/gpu/gl/GrGLRenderTarget.h @@ -77,7 +77,8 @@ protected: void onAbandon() override; void onRelease() override; - int numSamplesOwnedPerPixel() const { return fNumSamplesOwnedPerPixel; } + // In protected because subclass GrGLTextureRenderTarget calls this version. + size_t onGpuMemorySize() const override; private: // Constructor for instances wrapping backend objects. @@ -88,8 +89,6 @@ private: GrGLGpu* getGLGpu() const; bool completeStencilAttachment() override; - size_t onGpuMemorySize() const override; - int msaaSamples() const; // The number total number of samples, including both MSAA and resolve texture samples. int totalSamples() const; diff --git a/src/gpu/gl/GrGLTexture.cpp b/src/gpu/gl/GrGLTexture.cpp index ec0ad3b7f3..4653c5bce7 100644 --- a/src/gpu/gl/GrGLTexture.cpp +++ b/src/gpu/gl/GrGLTexture.cpp @@ -50,10 +50,9 @@ GrGLTexture::GrGLTexture(GrGLGpu* gpu, Wrapped, const GrSurfaceDesc& desc, const this->registerWithCacheWrapped(); } -GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc, - bool wasMipMapDataProvided) +GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc) : GrSurface(gpu, desc) - , INHERITED(gpu, desc, sampler_type(idDesc, gpu), wasMipMapDataProvided) { + , INHERITED(gpu, desc, sampler_type(idDesc, gpu), false) { this->init(desc, idDesc); } diff --git a/src/gpu/gl/GrGLTexture.h b/src/gpu/gl/GrGLTexture.h index 029fd87a1a..ee027d790d 100644 --- a/src/gpu/gl/GrGLTexture.h +++ b/src/gpu/gl/GrGLTexture.h @@ -59,7 +59,7 @@ public: static sk_sp MakeWrapped(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&); protected: // Constructor for subclasses. - GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, bool wasMipMapDataProvided); + GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&); enum Wrapped { kWrapped }; // Constructor for instances wrapping backend objects. diff --git a/src/gpu/gl/GrGLTextureRenderTarget.cpp b/src/gpu/gl/GrGLTextureRenderTarget.cpp index 9c350f89ae..9b37fbb343 100644 --- a/src/gpu/gl/GrGLTextureRenderTarget.cpp +++ b/src/gpu/gl/GrGLTextureRenderTarget.cpp @@ -49,5 +49,5 @@ sk_sp GrGLTextureRenderTarget::MakeWrapped( const GrGLTexture::IDDesc& texIDDesc, const GrGLRenderTarget::IDDesc& rtIDDesc) { return sk_sp( - new GrGLTextureRenderTarget(gpu, desc, texIDDesc, rtIDDesc, false)); + new GrGLTextureRenderTarget(gpu, desc, texIDDesc, rtIDDesc)); } diff --git a/src/gpu/gl/GrGLTextureRenderTarget.h b/src/gpu/gl/GrGLTextureRenderTarget.h index 7ff8d490e0..c5c020fef6 100644 --- a/src/gpu/gl/GrGLTextureRenderTarget.h +++ b/src/gpu/gl/GrGLTextureRenderTarget.h @@ -12,7 +12,6 @@ #include "GrGLGpu.h" #include "GrGLTexture.h" #include "GrGLRenderTarget.h" -#include "GrTexturePriv.h" class GrGLGpu; @@ -30,10 +29,9 @@ public: SkBudgeted budgeted, const GrSurfaceDesc& desc, const GrGLTexture::IDDesc& texIDDesc, - const GrGLRenderTarget::IDDesc& rtIDDesc, - bool wasMipMapDataProvided) + const GrGLRenderTarget::IDDesc& rtIDDesc) : GrSurface(gpu, desc) - , GrGLTexture(gpu, desc, texIDDesc, wasMipMapDataProvided) + , GrGLTexture(gpu, desc, texIDDesc) , GrGLRenderTarget(gpu, desc, rtIDDesc) { this->registerWithCache(budgeted); } @@ -61,18 +59,16 @@ private: GrGLTextureRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, const GrGLTexture::IDDesc& texIDDesc, - const GrGLRenderTarget::IDDesc& rtIDDesc, - bool wasMipMapDataProvided) + const GrGLRenderTarget::IDDesc& rtIDDesc) : GrSurface(gpu, desc) - , GrGLTexture(gpu, desc, texIDDesc, wasMipMapDataProvided) + , GrGLTexture(gpu, desc, texIDDesc) , GrGLRenderTarget(gpu, desc, rtIDDesc) { this->registerWithCacheWrapped(); } + // GrGLRenderTarget accounts for the texture's memory and any MSAA renderbuffer's memory. size_t onGpuMemorySize() const override { - return GrSurface::ComputeSize(fDesc, - this->numSamplesOwnedPerPixel(), - this->texturePriv().hasMipMaps()); + return GrGLRenderTarget::onGpuMemorySize(); } }; diff --git a/src/gpu/vk/GrVkRenderTarget.h b/src/gpu/vk/GrVkRenderTarget.h index 3e5c5eab17..2e2f60a5fd 100644 --- a/src/gpu/vk/GrVkRenderTarget.h +++ b/src/gpu/vk/GrVkRenderTarget.h @@ -100,8 +100,7 @@ protected: // This accounts for the texture's memory and any MSAA renderbuffer's memory. size_t onGpuMemorySize() const override { // The plus 1 is to account for the resolve texture. - // TODO: is this still correct? - return GrSurface::ComputeSize(fDesc, fDesc.fSampleCnt+1, false); + return GrRenderTarget::ComputeSize(fDesc, fDesc.fSampleCnt+1); // TODO: this still correct? } void createFramebuffer(GrVkGpu* gpu); diff --git a/src/gpu/vk/GrVkTextureRenderTarget.h b/src/gpu/vk/GrVkTextureRenderTarget.h index 2877a36265..daa168758d 100644 --- a/src/gpu/vk/GrVkTextureRenderTarget.h +++ b/src/gpu/vk/GrVkTextureRenderTarget.h @@ -13,8 +13,6 @@ #include "GrVkRenderTarget.h" #include "GrVkGpu.h" -#include "GrTexturePriv.h" - #ifdef SK_BUILD_FOR_WIN // Windows gives bogus warnings about inheriting asTexture/asRenderTarget via dominance. #pragma warning(push) @@ -114,9 +112,7 @@ private: // GrGLRenderTarget accounts for the texture's memory and any MSAA renderbuffer's memory. size_t onGpuMemorySize() const override { - // The plus 1 is to account for the resolve texture. - return GrSurface::ComputeSize(fDesc, fDesc.fSampleCnt+1, // TODO: this still correct? - this->texturePriv().hasMipMaps()); + return GrVkRenderTarget::onGpuMemorySize(); } }; diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp index 6c55f8a1a4..3a42474708 100644 --- a/tests/ResourceCacheTest.cpp +++ b/tests/ResourceCacheTest.cpp @@ -23,7 +23,6 @@ #include "SkCanvas.h" #include "SkGr.h" #include "SkMessageBus.h" -#include "SkMipMap.h" #include "SkSurface.h" #include "Test.h" @@ -1345,105 +1344,4 @@ DEF_GPUTEST(ResourceCacheMisc, reporter, factory) { test_abandoned(reporter); } -//////////////////////////////////////////////////////////////////////////////// -static sk_sp make_normal_texture(GrTextureProvider* provider, - GrSurfaceFlags flags, - int width, int height, - int sampleCnt) { - GrSurfaceDesc desc; - desc.fFlags = flags; - desc.fWidth = width; - desc.fHeight = height; - desc.fConfig = kRGBA_8888_GrPixelConfig; - desc.fSampleCnt = sampleCnt; - - return sk_sp(provider->createTexture(desc, SkBudgeted::kYes)); -} - -static sk_sp make_mipmap_texture(GrTextureProvider* provider, - GrSurfaceFlags flags, - int width, int height, - int sampleCnt) { - SkBitmap bm; - - bm.allocN32Pixels(width, height, true); - bm.eraseColor(SK_ColorBLUE); - - SkAutoTUnref mipmaps(SkMipMap::Build(bm, SkSourceGammaTreatment::kIgnore, nullptr)); - SkASSERT(mipmaps); - SkASSERT(mipmaps->countLevels() > 1); - - int mipLevelCount = mipmaps->countLevels() + 1; - - std::unique_ptr texels(new GrMipLevel[mipLevelCount]); - - texels[0].fPixels = bm.getPixels(); - texels[0].fRowBytes = bm.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(); - } - - GrSurfaceDesc desc; - desc.fFlags = flags; - desc.fWidth = width; - desc.fHeight = height; - desc.fConfig = kRGBA_8888_GrPixelConfig; - desc.fSampleCnt = sampleCnt; - desc.fIsMipMapped = true; - - return sk_sp(provider->createMipMappedTexture(desc, SkBudgeted::kYes, - texels.get(), mipLevelCount)); -} - -// Exercise GrSurface::gpuMemorySize for different combos of MSAA, RT-only, -// Texture-only, both-RT-and-Texture and MIPmapped -DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GPUMemorySize, reporter, ctxInfo) { - GrContext* context = ctxInfo.grContext(); - GrTextureProvider* provider = context->textureProvider(); - - static const int kSize = 64; - - sk_sp tex; - - // Normal versions - tex = make_normal_texture(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 0); - size_t size = tex->gpuMemorySize(); - REPORTER_ASSERT(reporter, kSize*kSize*4 == size); - - if (context->caps()->maxSampleCount() >= 4) { - tex = make_normal_texture(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 4); - size = tex->gpuMemorySize(); - REPORTER_ASSERT(reporter, kSize*kSize*4 == size || // msaa4 failed - kSize*kSize*4*4 == size || // auto-resolving - kSize*kSize*4*5 == size); // explicit resolve buffer - } - - tex = make_normal_texture(provider, kNone_GrSurfaceFlags, kSize, kSize, 0); - size = tex->gpuMemorySize(); - REPORTER_ASSERT(reporter, kSize*kSize*4 == size); - - // Mipmapped versions - tex = make_mipmap_texture(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 0); - size = tex->gpuMemorySize(); - REPORTER_ASSERT(reporter, kSize*kSize*4+(kSize*kSize*4)/3 == size); - - if (context->caps()->maxSampleCount() >= 4) { - tex = make_mipmap_texture(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 4); - size = tex->gpuMemorySize(); - REPORTER_ASSERT(reporter, - kSize*kSize*4+(kSize*kSize*4)/3 == size || // msaa4 failed - kSize*kSize*4*4+(kSize*kSize*4)/3 == size || // auto-resolving - kSize*kSize*4*5+(kSize*kSize*4)/3 == size); // explicit resolve buffer - } - - tex = make_mipmap_texture(provider, kNone_GrSurfaceFlags, kSize, kSize, 0); - size = tex->gpuMemorySize(); - REPORTER_ASSERT(reporter, kSize*kSize*4+(kSize*kSize*4)/3 == size); -} - - #endif