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:
parent
4089df8690
commit
1b97f13904
@ -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(), ¶ms)) {
|
||||
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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user