From 8b059bd946d9f14607f6d2e8b966267dd8e5a54d Mon Sep 17 00:00:00 2001 From: Greg Daniel Date: Thu, 28 Sep 2017 20:46:45 +0000 Subject: [PATCH] Revert "Update GrBitmapTextureMaker for handling mipped requests" This reverts commit d1935c16e889b6707a522f711e79c75353caa343. Reason for revert: breaking lots of GMs, especially on gles Original change's description: > Update GrBitmapTextureMaker for handling mipped requests > > Specifically this updates the case when we are requesting to use mip > maps but there is already an unmipped version in the cache. Previously > we just grabbed the unmipped. > > Now we will create a new mipped resource. Upload the cpu data to all > the levels besides the base, copy the base level on GPU from the > original resource to the mipped one. Then the mipped resource will > take over the originals unique key. > > Bug: skia: > Change-Id: I38e9725c93280dc2460a0be8a7a229e7f20e1614 > Reviewed-on: https://skia-review.googlesource.com/43840 > Commit-Queue: Greg Daniel > Reviewed-by: Robert Phillips TBR=egdaniel@google.com,robertphillips@google.com,brianosman@google.com Change-Id: Id82e8b6e8ab69e46ff018bb07ae5d1f6ea8d7e76 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: skia: Reviewed-on: https://skia-review.googlesource.com/52901 Reviewed-by: Greg Daniel Commit-Queue: Greg Daniel --- src/gpu/GrBitmapTextureMaker.cpp | 32 +++---------- src/gpu/GrGpu.cpp | 5 ++ src/gpu/GrSurfaceProxy.cpp | 31 ++++-------- src/gpu/SkGr.cpp | 46 ------------------ src/gpu/SkGr.h | 7 --- src/gpu/gl/GrGLGpu.cpp | 48 ++++++++----------- src/gpu/vk/GrVkGpu.cpp | 82 ++++++++++++++------------------ src/image/SkImage_Gpu.cpp | 7 --- 8 files changed, 75 insertions(+), 183 deletions(-) diff --git a/src/gpu/GrBitmapTextureMaker.cpp b/src/gpu/GrBitmapTextureMaker.cpp index 00dd48d0a9..6654901e20 100644 --- a/src/gpu/GrBitmapTextureMaker.cpp +++ b/src/gpu/GrBitmapTextureMaker.cpp @@ -8,13 +8,10 @@ #include "GrBitmapTextureMaker.h" #include "GrContext.h" -#include "GrContextPriv.h" #include "GrGpuResourcePriv.h" #include "GrResourceProvider.h" -#include "GrSurfaceContext.h" #include "SkBitmap.h" #include "SkGr.h" -#include "SkMipMap.h" #include "SkPixelRef.h" static bool bmp_is_alpha_only(const SkBitmap& bm) { return kAlpha_8_SkColorType == bm.colorType(); } @@ -37,25 +34,17 @@ sk_sp GrBitmapTextureMaker::refOriginalTextureProxy(bool willBeM return nullptr; } - sk_sp originalProxy; + sk_sp proxy; if (fOriginalKey.isValid()) { - originalProxy = this->context()->resourceProvider()->findOrCreateProxyByUniqueKey( - fOriginalKey, kTopLeft_GrSurfaceOrigin); - if (originalProxy && (!willBeMipped || originalProxy->isMipMapped())) { - return originalProxy; + proxy = this->context()->resourceProvider()->findOrCreateProxyByUniqueKey( + fOriginalKey, kTopLeft_GrSurfaceOrigin); + if (proxy) { + return proxy; } } - - sk_sp proxy; if (willBeMipped) { - if (!originalProxy) { - proxy = GrGenerateMipMapsAndUploadToTextureProxy(this->context(), fBitmap, - dstColorSpace); - } else { - proxy = GrCopyBaseMipMapToTextureProxy(this->context(), originalProxy.get(), - dstColorSpace); - } + proxy = GrGenerateMipMapsAndUploadToTextureProxy(this->context(), fBitmap, dstColorSpace); } if (!proxy) { proxy = GrUploadBitmapToTextureProxy(this->context()->resourceProvider(), fBitmap, @@ -63,15 +52,6 @@ sk_sp GrBitmapTextureMaker::refOriginalTextureProxy(bool willBeM } if (proxy && fOriginalKey.isValid()) { SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin); - if (originalProxy) { - // In this case we are stealing the key from the original proxy which should only happen - // when we have just generated mipmaps for an originally unmipped proxy/texture. This - // means that all future uses of the key will access the mipmapped version. The texture - // backing the unmipped version will remain in the resource cache until the last texture - // proxy referencing it is deleted at which time it too will be deleted or recycled. - this->context()->resourceProvider()->removeUniqueKeyFromProxy(fOriginalKey, - originalProxy.get()); - } this->context()->resourceProvider()->assignUniqueKeyToProxy(fOriginalKey, proxy.get()); GrInstallBitmapUniqueKeyInvalidator(fOriginalKey, fBitmap.pixelRef()); } diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 31939bc1fa..c83d9828e8 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -114,6 +114,11 @@ static bool check_texture_creation_params(const GrCaps& caps, const GrSurfaceDes } } + for (int i = 0; i < mipLevelCount; ++i) { + if (!texels[i].fPixels) { + return false; + } + } return true; } diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp index 2ef384677b..d9711e2365 100644 --- a/src/gpu/GrSurfaceProxy.cpp +++ b/src/gpu/GrSurfaceProxy.cpp @@ -303,36 +303,21 @@ sk_sp GrSurfaceProxy::MakeDeferredMipMap( return nullptr; } return GrSurfaceProxy::MakeDeferred(resourceProvider, desc, budgeted, nullptr, 0); - } - if (!texels) { - return nullptr; - } - - if (1 == mipLevelCount) { + } else if (1 == mipLevelCount) { + if (!texels) { + return nullptr; + } return resourceProvider->createTextureProxy(desc, budgeted, texels[0]); } -#ifdef SK_DEBUG - // There are only three states we want to be in when uploading data to a mipped surface. - // 1) We have data to upload to all layers - // 2) We are not uploading data to any layers - // 3) We are only uploading data to the base layer - // We check here to make sure we do not have any other state. - bool firstLevelHasData = SkToBool(texels[0].fPixels); - bool allOtherLevelsHaveData = true, allOtherLevelsLackData = true; - for (int i = 1; i < mipLevelCount; ++i) { - if (texels[i].fPixels) { - allOtherLevelsLackData = false; - } else { - allOtherLevelsHaveData = false; + for (int i = 0; i < mipLevelCount; ++i) { + if (!texels[i].fPixels) { + return nullptr; } } - SkASSERT((firstLevelHasData && allOtherLevelsHaveData) || allOtherLevelsLackData); -#endif sk_sp tex(resourceProvider->createTexture(desc, budgeted, - texels, mipLevelCount, - mipColorMode)); + texels, mipLevelCount, mipColorMode)); if (!tex) { return nullptr; } diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index e26de49e36..5c26877101 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -10,7 +10,6 @@ #include "GrBitmapTextureMaker.h" #include "GrCaps.h" #include "GrContext.h" -#include "GrContextPriv.h" #include "GrGpuResourcePriv.h" #include "GrRenderTargetContext.h" #include "GrResourceProvider.h" @@ -218,51 +217,6 @@ sk_sp GrGenerateMipMapsAndUploadToTextureProxy(GrContext* ctx, colorMode); } -sk_sp GrCopyBaseMipMapToTextureProxy(GrContext* ctx, - GrTextureProxy* baseProxy, - SkColorSpace* dstColorSpace) { - SkASSERT(baseProxy); - - SkDestinationSurfaceColorMode colorMode = dstColorSpace - ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware - : SkDestinationSurfaceColorMode::kLegacy; - - // SkMipMap doesn't include the base level in the level count so we have to add 1 - int mipLevelCount = SkMipMap::ComputeLevelCount(baseProxy->width(), baseProxy->height()) + 1; - - std::unique_ptr texels(new GrMipLevel[mipLevelCount]); - - // We don't want to upload any texel data - for (int i = 0; i < mipLevelCount; i++) { - texels[i].fPixels = nullptr; - texels[i].fRowBytes = 0; - } - - GrSurfaceDesc desc; - desc.fFlags = kNone_GrSurfaceFlags; - desc.fOrigin = baseProxy->origin(); - desc.fWidth = baseProxy->width(); - desc.fHeight = baseProxy->height(); - desc.fConfig = baseProxy->config(); - desc.fSampleCnt = 0; - - sk_sp proxy = GrSurfaceProxy::MakeDeferredMipMap(ctx->resourceProvider(), - desc, - SkBudgeted::kYes, texels.get(), - mipLevelCount, colorMode); - if (!proxy) { - return nullptr; - } - - // Copy the base layer to our proxy - sk_sp sContext = ctx->contextPriv().makeWrappedSurfaceContext(proxy, nullptr); - SkASSERT(sContext); - SkAssertResult(sContext->copy(baseProxy)); - - return proxy; -} - - sk_sp GrUploadMipMapToTextureProxy(GrContext* ctx, const SkImageInfo& info, const GrMipLevel texels[], int mipLevelCount, diff --git a/src/gpu/SkGr.h b/src/gpu/SkGr.h index 20110a516f..7ecec96477 100644 --- a/src/gpu/SkGr.h +++ b/src/gpu/SkGr.h @@ -224,13 +224,6 @@ sk_sp GrGenerateMipMapsAndUploadToTextureProxy(GrContext*, const sk_sp GrUploadPixmapToTextureProxy(GrResourceProvider*, const SkPixmap&, SkBudgeted, SkColorSpace*); -/** - * Creates a new texture with mipmap levels and copies the baseProxy into the base layer. - */ -sk_sp GrCopyBaseMipMapToTextureProxy(GrContext*, - GrTextureProxy* baseProxy, - SkColorSpace* dstColorSpace); - /** * Creates a new texture populated with the mipmap levels. */ diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 930e2e447a..ff19bb6fc3 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -952,13 +952,10 @@ static bool allocate_and_populate_texture(GrPixelConfig config, } } else { for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) { - const void* currentMipData = texels[currentMipLevel].fPixels; - if (!currentMipData) { - continue; - } int twoToTheMipLevel = 1 << currentMipLevel; int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel); int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel); + const void* currentMipData = texels[currentMipLevel].fPixels; // Even if curremtMipData is nullptr, continue to call TexImage2D. // This will allocate texture memory which we can later populate. GL_ALLOC_CALL(&interface, @@ -1036,6 +1033,10 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight memcpy(texelsShallowCopy.get(), texels, mipLevelCount*sizeof(GrMipLevel)); } + for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; ++currentMipLevel) { + SkASSERT(texelsShallowCopy[currentMipLevel].fPixels); + } + const GrGLInterface* interface = this->glInterface(); const GrGLCaps& caps = this->glCaps(); @@ -1080,27 +1081,19 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight // find the combined size of all the mip levels and the relative offset of // each into the collective buffer - size_t combinedBufferSize = 0; - SkTArray individualMipOffsets(mipLevelCount); + size_t combined_buffer_size = 0; + SkTArray individual_mip_offsets(mipLevelCount); for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) { - if (texelsShallowCopy[currentMipLevel].fPixels) { - int twoToTheMipLevel = 1 << currentMipLevel; - int currentWidth = SkTMax(1, width / twoToTheMipLevel); - int currentHeight = SkTMax(1, height / twoToTheMipLevel); - const size_t trimmedSize = currentWidth * bpp * currentHeight; - individualMipOffsets.push_back(combinedBufferSize); - combinedBufferSize += trimmedSize; - } else { - individualMipOffsets.push_back(0); - } - + int twoToTheMipLevel = 1 << currentMipLevel; + int currentWidth = SkTMax(1, width / twoToTheMipLevel); + int currentHeight = SkTMax(1, height / twoToTheMipLevel); + const size_t trimmedSize = currentWidth * bpp * currentHeight; + individual_mip_offsets.push_back(combined_buffer_size); + combined_buffer_size += trimmedSize; } - char* buffer = (char*)tempStorage.reset(combinedBufferSize); + char* buffer = (char*)tempStorage.reset(combined_buffer_size); for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) { - if (!texelsShallowCopy[currentMipLevel].fPixels) { - continue; - } int twoToTheMipLevel = 1 << currentMipLevel; int currentWidth = SkTMax(1, width / twoToTheMipLevel); int currentHeight = SkTMax(1, height / twoToTheMipLevel); @@ -1114,9 +1107,9 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight */ restoreGLRowLength = false; - const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes - ? texelsShallowCopy[currentMipLevel].fRowBytes - : trimRowBytes; + const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes ? + texelsShallowCopy[currentMipLevel].fRowBytes : + trimRowBytes; // TODO: This optimization should be enabled with or without mips. // For use with mips, we must set GR_GL_UNPACK_ROW_LENGTH once per @@ -1135,7 +1128,7 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight if (swFlipY && currentHeight >= 1) { src += (currentHeight - 1) * rowBytes; } - char* dst = buffer + individualMipOffsets[currentMipLevel]; + char* dst = buffer + individual_mip_offsets[currentMipLevel]; for (int y = 0; y < currentHeight; y++) { memcpy(dst, src, trimRowBytes); if (swFlipY) { @@ -1147,7 +1140,7 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight } // now point data to our copied version texelsShallowCopy[currentMipLevel].fPixels = buffer + - individualMipOffsets[currentMipLevel]; + individual_mip_offsets[currentMipLevel]; texelsShallowCopy[currentMipLevel].fRowBytes = trimRowBytes; } } @@ -1174,9 +1167,6 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight top = texHeight - (top + height); } for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) { - if (!texelsShallowCopy[currentMipLevel].fPixels) { - continue; - } int twoToTheMipLevel = 1 << currentMipLevel; int currentWidth = SkTMax(1, width / twoToTheMipLevel); int currentHeight = SkTMax(1, height / twoToTheMipLevel); diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index e9adb4db67..6617318f26 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -661,6 +661,10 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, GrSurfaceOrigin texOrigin, memcpy(texelsShallowCopy.get(), texels, mipLevelCount*sizeof(GrMipLevel)); } + for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; ++currentMipLevel) { + SkASSERT(texelsShallowCopy[currentMipLevel].fPixels); + } + // Determine whether we need to flip when we copy into the buffer bool flipY = (kBottomLeft_GrSurfaceOrigin == texOrigin && mipLevelCount); @@ -669,10 +673,6 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, GrSurfaceOrigin texOrigin, size_t combinedBufferSize = width * bpp * height; int currentWidth = width; int currentHeight = height; - if (mipLevelCount > 0 && !texelsShallowCopy[0].fPixels) { - combinedBufferSize = 0; - } - // The alignment must be at least 4 bytes and a multiple of the bytes per pixel of the image // config. This works with the assumption that the bytes in pixel config is always a power of 2. SkASSERT((bpp & (bpp - 1)) == 0); @@ -681,21 +681,13 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, GrSurfaceOrigin texOrigin, currentWidth = SkTMax(1, currentWidth/2); currentHeight = SkTMax(1, currentHeight/2); - if (texelsShallowCopy[currentMipLevel].fPixels) { - const size_t trimmedSize = currentWidth * bpp * currentHeight; - const size_t alignmentDiff = combinedBufferSize & alignmentMask; - if (alignmentDiff != 0) { - combinedBufferSize += alignmentMask - alignmentDiff + 1; - } - individualMipOffsets.push_back(combinedBufferSize); - combinedBufferSize += trimmedSize; - } else { - individualMipOffsets.push_back(0); + const size_t trimmedSize = currentWidth * bpp * currentHeight; + const size_t alignmentDiff = combinedBufferSize & alignmentMask; + if (alignmentDiff != 0) { + combinedBufferSize += alignmentMask - alignmentDiff + 1; } - } - if (0 == combinedBufferSize) { - // We don't actually have any data to upload so just return success - return true; + individualMipOffsets.push_back(combinedBufferSize); + combinedBufferSize += trimmedSize; } // allocate buffer to hold our mip data @@ -712,36 +704,35 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, GrSurfaceOrigin texOrigin, currentHeight = height; int layerHeight = tex->height(); for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) { - if (texelsShallowCopy[currentMipLevel].fPixels) { - SkASSERT(1 == mipLevelCount || currentHeight == layerHeight); - const size_t trimRowBytes = currentWidth * bpp; - const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes - ? texelsShallowCopy[currentMipLevel].fRowBytes - : trimRowBytes; + SkASSERT(1 == mipLevelCount || currentHeight == layerHeight); + const size_t trimRowBytes = currentWidth * bpp; + const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes ? + texelsShallowCopy[currentMipLevel].fRowBytes : + trimRowBytes; - // copy data into the buffer, skipping the trailing bytes - char* dst = buffer + individualMipOffsets[currentMipLevel]; - const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels; - if (flipY) { - src += (currentHeight - 1) * rowBytes; - for (int y = 0; y < currentHeight; y++) { - memcpy(dst, src, trimRowBytes); - src -= rowBytes; - dst += trimRowBytes; - } - } else { - SkRectMemcpy(dst, trimRowBytes, src, rowBytes, trimRowBytes, currentHeight); + // copy data into the buffer, skipping the trailing bytes + char* dst = buffer + individualMipOffsets[currentMipLevel]; + const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels; + if (flipY) { + src += (currentHeight - 1) * rowBytes; + for (int y = 0; y < currentHeight; y++) { + memcpy(dst, src, trimRowBytes); + src -= rowBytes; + dst += trimRowBytes; } - - VkBufferImageCopy& region = regions.push_back(); - memset(®ion, 0, sizeof(VkBufferImageCopy)); - region.bufferOffset = transferBuffer->offset() + individualMipOffsets[currentMipLevel]; - region.bufferRowLength = currentWidth; - region.bufferImageHeight = currentHeight; - region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 }; - region.imageOffset = { left, flipY ? layerHeight - top - currentHeight : top, 0 }; - region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 }; + } else { + SkRectMemcpy(dst, trimRowBytes, src, rowBytes, trimRowBytes, currentHeight); } + + VkBufferImageCopy& region = regions.push_back(); + memset(®ion, 0, sizeof(VkBufferImageCopy)); + region.bufferOffset = transferBuffer->offset() + individualMipOffsets[currentMipLevel]; + region.bufferRowLength = currentWidth; + region.bufferImageHeight = currentHeight; + region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 }; + region.imageOffset = { left, flipY ? layerHeight - top - currentHeight : top, 0 }; + region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 }; + currentWidth = SkTMax(1, currentWidth/2); currentHeight = SkTMax(1, currentHeight/2); layerHeight = currentHeight; @@ -831,6 +822,7 @@ sk_sp GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted } if (mipLevelCount) { + SkASSERT(texels[0].fPixels); if (!this->uploadTexDataOptimal(tex.get(), desc.fOrigin, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig, texels, mipLevelCount)) { tex->unref(); diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp index 356b800e83..d3a1865039 100644 --- a/src/image/SkImage_Gpu.cpp +++ b/src/image/SkImage_Gpu.cpp @@ -922,13 +922,6 @@ sk_sp SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& if (!ctx) { return nullptr; } - // For images where the client is passing the mip data we require that all the mip levels have - // valid data. - for (int i = 0; i < mipLevelCount; ++i) { - if (!texels[i].fPixels) { - return nullptr; - } - } sk_sp proxy(GrUploadMipMapToTextureProxy(ctx, info, texels, mipLevelCount, colorMode)); if (!proxy) {