Revert "Update GrBitmapTextureMaker for handling mipped requests"
This reverts commit d1935c16e8
.
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 <egdaniel@google.com>
> Reviewed-by: Robert Phillips <robertphillips@google.com>
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 <egdaniel@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
parent
4b05000906
commit
8b059bd946
@ -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<GrTextureProxy> GrBitmapTextureMaker::refOriginalTextureProxy(bool willBeM
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<GrTextureProxy> originalProxy;
|
||||
sk_sp<GrTextureProxy> proxy;
|
||||
|
||||
if (fOriginalKey.isValid()) {
|
||||
originalProxy = this->context()->resourceProvider()->findOrCreateProxyByUniqueKey(
|
||||
proxy = this->context()->resourceProvider()->findOrCreateProxyByUniqueKey(
|
||||
fOriginalKey, kTopLeft_GrSurfaceOrigin);
|
||||
if (originalProxy && (!willBeMipped || originalProxy->isMipMapped())) {
|
||||
return originalProxy;
|
||||
if (proxy) {
|
||||
return proxy;
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<GrTextureProxy> 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<GrTextureProxy> 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());
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -303,36 +303,21 @@ sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferredMipMap(
|
||||
return nullptr;
|
||||
}
|
||||
return GrSurfaceProxy::MakeDeferred(resourceProvider, desc, budgeted, nullptr, 0);
|
||||
}
|
||||
} else if (1 == mipLevelCount) {
|
||||
if (!texels) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (1 == mipLevelCount) {
|
||||
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<GrTexture> tex(resourceProvider->createTexture(desc, budgeted,
|
||||
texels, mipLevelCount,
|
||||
mipColorMode));
|
||||
texels, mipLevelCount, mipColorMode));
|
||||
if (!tex) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -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<GrTextureProxy> GrGenerateMipMapsAndUploadToTextureProxy(GrContext* ctx,
|
||||
colorMode);
|
||||
}
|
||||
|
||||
sk_sp<GrTextureProxy> 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<GrMipLevel[]> 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<GrTextureProxy> 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<GrSurfaceContext> sContext = ctx->contextPriv().makeWrappedSurfaceContext(proxy, nullptr);
|
||||
SkASSERT(sContext);
|
||||
SkAssertResult(sContext->copy(baseProxy));
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
||||
sk_sp<GrTextureProxy> GrUploadMipMapToTextureProxy(GrContext* ctx, const SkImageInfo& info,
|
||||
const GrMipLevel texels[],
|
||||
int mipLevelCount,
|
||||
|
@ -224,13 +224,6 @@ sk_sp<GrTextureProxy> GrGenerateMipMapsAndUploadToTextureProxy(GrContext*, const
|
||||
sk_sp<GrTextureProxy> GrUploadPixmapToTextureProxy(GrResourceProvider*,
|
||||
const SkPixmap&, SkBudgeted, SkColorSpace*);
|
||||
|
||||
/**
|
||||
* Creates a new texture with mipmap levels and copies the baseProxy into the base layer.
|
||||
*/
|
||||
sk_sp<GrTextureProxy> GrCopyBaseMipMapToTextureProxy(GrContext*,
|
||||
GrTextureProxy* baseProxy,
|
||||
SkColorSpace* dstColorSpace);
|
||||
|
||||
/**
|
||||
* Creates a new texture populated with the mipmap levels.
|
||||
*/
|
||||
|
@ -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<size_t> individualMipOffsets(mipLevelCount);
|
||||
size_t combined_buffer_size = 0;
|
||||
SkTArray<size_t> 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);
|
||||
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);
|
||||
|
@ -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,7 +681,6 @@ 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) {
|
||||
@ -689,13 +688,6 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, GrSurfaceOrigin texOrigin,
|
||||
}
|
||||
individualMipOffsets.push_back(combinedBufferSize);
|
||||
combinedBufferSize += trimmedSize;
|
||||
} else {
|
||||
individualMipOffsets.push_back(0);
|
||||
}
|
||||
}
|
||||
if (0 == combinedBufferSize) {
|
||||
// We don't actually have any data to upload so just return success
|
||||
return true;
|
||||
}
|
||||
|
||||
// allocate buffer to hold our mip data
|
||||
@ -712,12 +704,11 @@ 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;
|
||||
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];
|
||||
@ -741,7 +732,7 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, GrSurfaceOrigin texOrigin,
|
||||
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<GrTexture> 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();
|
||||
|
@ -922,13 +922,6 @@ sk_sp<SkImage> 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<GrTextureProxy> proxy(GrUploadMipMapToTextureProxy(ctx, info, texels, mipLevelCount,
|
||||
colorMode));
|
||||
if (!proxy) {
|
||||
|
Loading…
Reference in New Issue
Block a user