Revert "Defer mip-mapping until lazy proxy instantiation"

This reverts commit 475819cab7.

Reason for revert: No, let's not defer.

Original change's description:
> Defer mip-mapping until lazy proxy instantiation
> 
> - Remove some checks for truly impossible failures (levelCount < 0)
> - Use helper method to predict number of mips, then verify correct
>   results in the lambda.
> - Split up SkMipMap::Build with a CanBuild helper, so GPU code can
>   predict success/failure accurately.
> - This is going to simplify the case where we need to change the
>   config for unsupported formats.
> 
> Bug: skia:8375
> Change-Id: Ied523ab55c38b8c8e7e2ae983744ed400497939b
> Reviewed-on: https://skia-review.googlesource.com/154080
> Commit-Queue: Brian Osman <brianosman@google.com>
> Reviewed-by: Robert Phillips <robertphillips@google.com>

TBR=bsalomon@google.com,robertphillips@google.com,brianosman@google.com,reed@google.com

Change-Id: I04dbc458103f7bb5a7c28da28b0256d7a2b8b3d3
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:8375
Reviewed-on: https://skia-review.googlesource.com/154304
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2018-09-13 17:33:48 +00:00 committed by Skia Commit-Bot
parent 4089df8690
commit 1b97f13904
3 changed files with 121 additions and 141 deletions

View File

@ -312,168 +312,148 @@ size_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) {
return SkTo<int32_t>(size);
}
struct SkMipMap::BuildParams {
typedef void (*FilterProc)(void*, const void* srcPtr, size_t srcRB, int count);
FilterProc fProc_1_2 = nullptr;
FilterProc fProc_1_3 = nullptr;
FilterProc fProc_2_1 = nullptr;
FilterProc fProc_2_2 = nullptr;
FilterProc fProc_2_3 = nullptr;
FilterProc fProc_3_1 = nullptr;
FilterProc fProc_3_2 = nullptr;
FilterProc fProc_3_3 = nullptr;
int fCountLevels = 0;
size_t fSize = 0;
size_t fStorageSize = 0;
};
bool SkMipMap::CanBuild(const SkImageInfo& info, SkMipMap::BuildParams* outParams) {
BuildParams params;
const SkColorType ct = info.colorType();
switch (ct) {
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType:
params.fProc_1_2 = downsample_1_2<ColorTypeFilter_8888>;
params.fProc_1_3 = downsample_1_3<ColorTypeFilter_8888>;
params.fProc_2_1 = downsample_2_1<ColorTypeFilter_8888>;
params.fProc_2_2 = downsample_2_2<ColorTypeFilter_8888>;
params.fProc_2_3 = downsample_2_3<ColorTypeFilter_8888>;
params.fProc_3_1 = downsample_3_1<ColorTypeFilter_8888>;
params.fProc_3_2 = downsample_3_2<ColorTypeFilter_8888>;
params.fProc_3_3 = downsample_3_3<ColorTypeFilter_8888>;
break;
case kRGB_565_SkColorType:
params.fProc_1_2 = downsample_1_2<ColorTypeFilter_565>;
params.fProc_1_3 = downsample_1_3<ColorTypeFilter_565>;
params.fProc_2_1 = downsample_2_1<ColorTypeFilter_565>;
params.fProc_2_2 = downsample_2_2<ColorTypeFilter_565>;
params.fProc_2_3 = downsample_2_3<ColorTypeFilter_565>;
params.fProc_3_1 = downsample_3_1<ColorTypeFilter_565>;
params.fProc_3_2 = downsample_3_2<ColorTypeFilter_565>;
params.fProc_3_3 = downsample_3_3<ColorTypeFilter_565>;
break;
case kARGB_4444_SkColorType:
params.fProc_1_2 = downsample_1_2<ColorTypeFilter_4444>;
params.fProc_1_3 = downsample_1_3<ColorTypeFilter_4444>;
params.fProc_2_1 = downsample_2_1<ColorTypeFilter_4444>;
params.fProc_2_2 = downsample_2_2<ColorTypeFilter_4444>;
params.fProc_2_3 = downsample_2_3<ColorTypeFilter_4444>;
params.fProc_3_1 = downsample_3_1<ColorTypeFilter_4444>;
params.fProc_3_2 = downsample_3_2<ColorTypeFilter_4444>;
params.fProc_3_3 = downsample_3_3<ColorTypeFilter_4444>;
break;
case kAlpha_8_SkColorType:
case kGray_8_SkColorType:
params.fProc_1_2 = downsample_1_2<ColorTypeFilter_8>;
params.fProc_1_3 = downsample_1_3<ColorTypeFilter_8>;
params.fProc_2_1 = downsample_2_1<ColorTypeFilter_8>;
params.fProc_2_2 = downsample_2_2<ColorTypeFilter_8>;
params.fProc_2_3 = downsample_2_3<ColorTypeFilter_8>;
params.fProc_3_1 = downsample_3_1<ColorTypeFilter_8>;
params.fProc_3_2 = downsample_3_2<ColorTypeFilter_8>;
params.fProc_3_3 = downsample_3_3<ColorTypeFilter_8>;
break;
case kRGBA_F16_SkColorType:
params.fProc_1_2 = downsample_1_2<ColorTypeFilter_F16>;
params.fProc_1_3 = downsample_1_3<ColorTypeFilter_F16>;
params.fProc_2_1 = downsample_2_1<ColorTypeFilter_F16>;
params.fProc_2_2 = downsample_2_2<ColorTypeFilter_F16>;
params.fProc_2_3 = downsample_2_3<ColorTypeFilter_F16>;
params.fProc_3_1 = downsample_3_1<ColorTypeFilter_F16>;
params.fProc_3_2 = downsample_3_2<ColorTypeFilter_F16>;
params.fProc_3_3 = downsample_3_3<ColorTypeFilter_F16>;
break;
default:
return false;
}
if (info.width() <= 1 && info.height() <= 1) {
return false;
}
// whip through our loop to compute the exact size needed
params.fCountLevels = ComputeLevelCount(info.width(), info.height());
for (int currentMipLevel = params.fCountLevels; currentMipLevel >= 0; currentMipLevel--) {
SkISize mipSize = ComputeLevelSize(info.width(), info.height(), currentMipLevel);
params.fSize += SkColorTypeMinRowBytes(ct, mipSize.fWidth) * mipSize.fHeight;
}
params.fStorageSize = SkMipMap::AllocLevelsSize(params.fCountLevels, params.fSize);
if (0 == params.fStorageSize) {
return false;
}
if (outParams) {
*outParams = params;
}
return true;
}
SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) {
BuildParams params;
if (!CanBuild(src.info(), &params)) {
return nullptr;
}
typedef void FilterProc(void*, const void* srcPtr, size_t srcRB, int count);
FilterProc* proc_1_2 = nullptr;
FilterProc* proc_1_3 = nullptr;
FilterProc* proc_2_1 = nullptr;
FilterProc* proc_2_2 = nullptr;
FilterProc* proc_2_3 = nullptr;
FilterProc* proc_3_1 = nullptr;
FilterProc* proc_3_2 = nullptr;
FilterProc* proc_3_3 = nullptr;
const SkColorType ct = src.colorType();
const SkAlphaType at = src.alphaType();
switch (ct) {
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType:
proc_1_2 = downsample_1_2<ColorTypeFilter_8888>;
proc_1_3 = downsample_1_3<ColorTypeFilter_8888>;
proc_2_1 = downsample_2_1<ColorTypeFilter_8888>;
proc_2_2 = downsample_2_2<ColorTypeFilter_8888>;
proc_2_3 = downsample_2_3<ColorTypeFilter_8888>;
proc_3_1 = downsample_3_1<ColorTypeFilter_8888>;
proc_3_2 = downsample_3_2<ColorTypeFilter_8888>;
proc_3_3 = downsample_3_3<ColorTypeFilter_8888>;
break;
case kRGB_565_SkColorType:
proc_1_2 = downsample_1_2<ColorTypeFilter_565>;
proc_1_3 = downsample_1_3<ColorTypeFilter_565>;
proc_2_1 = downsample_2_1<ColorTypeFilter_565>;
proc_2_2 = downsample_2_2<ColorTypeFilter_565>;
proc_2_3 = downsample_2_3<ColorTypeFilter_565>;
proc_3_1 = downsample_3_1<ColorTypeFilter_565>;
proc_3_2 = downsample_3_2<ColorTypeFilter_565>;
proc_3_3 = downsample_3_3<ColorTypeFilter_565>;
break;
case kARGB_4444_SkColorType:
proc_1_2 = downsample_1_2<ColorTypeFilter_4444>;
proc_1_3 = downsample_1_3<ColorTypeFilter_4444>;
proc_2_1 = downsample_2_1<ColorTypeFilter_4444>;
proc_2_2 = downsample_2_2<ColorTypeFilter_4444>;
proc_2_3 = downsample_2_3<ColorTypeFilter_4444>;
proc_3_1 = downsample_3_1<ColorTypeFilter_4444>;
proc_3_2 = downsample_3_2<ColorTypeFilter_4444>;
proc_3_3 = downsample_3_3<ColorTypeFilter_4444>;
break;
case kAlpha_8_SkColorType:
case kGray_8_SkColorType:
proc_1_2 = downsample_1_2<ColorTypeFilter_8>;
proc_1_3 = downsample_1_3<ColorTypeFilter_8>;
proc_2_1 = downsample_2_1<ColorTypeFilter_8>;
proc_2_2 = downsample_2_2<ColorTypeFilter_8>;
proc_2_3 = downsample_2_3<ColorTypeFilter_8>;
proc_3_1 = downsample_3_1<ColorTypeFilter_8>;
proc_3_2 = downsample_3_2<ColorTypeFilter_8>;
proc_3_3 = downsample_3_3<ColorTypeFilter_8>;
break;
case kRGBA_F16_SkColorType:
proc_1_2 = downsample_1_2<ColorTypeFilter_F16>;
proc_1_3 = downsample_1_3<ColorTypeFilter_F16>;
proc_2_1 = downsample_2_1<ColorTypeFilter_F16>;
proc_2_2 = downsample_2_2<ColorTypeFilter_F16>;
proc_2_3 = downsample_2_3<ColorTypeFilter_F16>;
proc_3_1 = downsample_3_1<ColorTypeFilter_F16>;
proc_3_2 = downsample_3_2<ColorTypeFilter_F16>;
proc_3_3 = downsample_3_3<ColorTypeFilter_F16>;
break;
default:
return nullptr;
}
if (src.width() <= 1 && src.height() <= 1) {
return nullptr;
}
// whip through our loop to compute the exact size needed
size_t size = 0;
int countLevels = ComputeLevelCount(src.width(), src.height());
for (int currentMipLevel = countLevels; currentMipLevel >= 0; currentMipLevel--) {
SkISize mipSize = ComputeLevelSize(src.width(), src.height(), currentMipLevel);
size += SkColorTypeMinRowBytes(ct, mipSize.fWidth) * mipSize.fHeight;
}
size_t storageSize = SkMipMap::AllocLevelsSize(countLevels, size);
if (0 == storageSize) {
return nullptr;
}
SkMipMap* mipmap;
if (fact) {
SkDiscardableMemory* dm = fact(params.fStorageSize);
SkDiscardableMemory* dm = fact(storageSize);
if (nullptr == dm) {
return nullptr;
}
mipmap = new SkMipMap(params.fStorageSize, dm);
mipmap = new SkMipMap(storageSize, dm);
} else {
mipmap = new SkMipMap(sk_malloc_throw(params.fStorageSize), params.fStorageSize);
mipmap = new SkMipMap(sk_malloc_throw(storageSize), storageSize);
}
// init
mipmap->fCS = sk_ref_sp(src.info().colorSpace());
mipmap->fCount = params.fCountLevels;
mipmap->fCount = countLevels;
mipmap->fLevels = (Level*)mipmap->writable_data();
SkASSERT(mipmap->fLevels);
Level* levels = mipmap->fLevels;
uint8_t* baseAddr = (uint8_t*)&levels[params.fCountLevels];
uint8_t* baseAddr = (uint8_t*)&levels[countLevels];
uint8_t* addr = baseAddr;
int width = src.width();
int height = src.height();
uint32_t rowBytes;
SkPixmap srcPM(src);
for (int i = 0; i < params.fCountLevels; ++i) {
BuildParams::FilterProc proc;
for (int i = 0; i < countLevels; ++i) {
FilterProc* proc;
if (height & 1) {
if (height == 1) { // src-height is 1
if (width & 1) { // src-width is 3
proc = params.fProc_3_1;
proc = proc_3_1;
} else { // src-width is 2
proc = params.fProc_2_1;
proc = proc_2_1;
}
} else { // src-height is 3
if (width & 1) {
if (width == 1) { // src-width is 1
proc = params.fProc_1_3;
proc = proc_1_3;
} else { // src-width is 3
proc = params.fProc_3_3;
proc = proc_3_3;
}
} else { // src-width is 2
proc = params.fProc_2_3;
proc = proc_2_3;
}
}
} else { // src-height is 2
if (width & 1) {
if (width == 1) { // src-width is 1
proc = params.fProc_1_2;
proc = proc_1_2;
} else { // src-width is 3
proc = params.fProc_3_2;
proc = proc_3_2;
}
} else { // src-width is 2
proc = params.fProc_2_2;
proc = proc_2_2;
}
}
width = SkTMax(1, width >> 1);
@ -500,7 +480,7 @@ SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) {
srcPM = dstPM;
addr += height * rowBytes;
}
SkASSERT(addr == baseAddr + params.fSize);
SkASSERT(addr == baseAddr + size);
SkASSERT(mipmap->fLevels);
return mipmap;

View File

@ -29,10 +29,6 @@ typedef SkDiscardableMemory* (*SkDiscardableFactoryProc)(size_t bytes);
*/
class SkMipMap : public SkCachedData {
public:
struct BuildParams;
static bool CanBuild(const SkImageInfo& info, BuildParams*);
static SkMipMap* Build(const SkPixmap& src, SkDiscardableFactoryProc);
static SkMipMap* Build(const SkBitmap& src, SkDiscardableFactoryProc);

View File

@ -279,7 +279,20 @@ sk_sp<GrTextureProxy> GrProxyProvider::createMipMapProxyFromBitmap(const SkBitma
return nullptr;
}
ATRACE_ANDROID_FRAMEWORK("Upload MipMap Texture [%ux%u]", bitmap.width(), bitmap.height());
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, 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
@ -287,39 +300,30 @@ sk_sp<GrTextureProxy> GrProxyProvider::createMipMapProxyFromBitmap(const SkBitma
SkCopyPixelsMode copyMode = this->recordingDDL() ? kIfMutable_SkCopyPixelsMode
: kNever_SkCopyPixelsMode;
sk_sp<SkImage> baseLevel = SkMakeImageFromRasterBitmap(bitmap, copyMode);
if (!baseLevel) {
return nullptr;
}
// This was never going to have mips anyway
if (0 == SkMipMap::ComputeLevelCount(baseLevel->width(), baseLevel->height())) {
GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info());
if (0 == mipmaps->countLevels()) {
return this->createTextureProxy(baseLevel, kNone_GrSurfaceFlags, 1, SkBudgeted::kYes,
SkBackingFit::kExact);
}
if (!SkMipMap::CanBuild(bitmap.info(), nullptr)) {
return nullptr;
}
GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info());
sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
[desc, baseLevel](GrResourceProvider* resourceProvider) {
[desc, baseLevel, mipmaps](GrResourceProvider* resourceProvider) {
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));
int mipLevelCount = 1;
sk_sp<SkMipMap> mipmaps(SkMipMap::Build(pixmap, nullptr));
if (mipmaps) {
mipLevelCount += mipmaps->countLevels();
}
std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
// 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();