Index: src/core/SkMipMap.cpp |
diff --git a/src/core/SkMipMap.cpp b/src/core/SkMipMap.cpp |
index c851d64a908a959b4b90234aba4ba81377f0566b..4c075ea6bb7d03fd58c84efc42467008a8f1b04b 100644 |
--- a/src/core/SkMipMap.cpp |
+++ b/src/core/SkMipMap.cpp |
@@ -371,23 +371,12 @@ SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) { |
} |
// whip through our loop to compute the exact size needed |
size_t size = 0; |
- int countLevels = 0; |
- { |
- int width = src.width(); |
- int height = src.height(); |
- for (;;) { |
- width = SkTMax(1, width >> 1); |
- height = SkTMax(1, height >> 1); |
- size += SkColorTypeMinRowBytes(ct, width) * height; |
- countLevels += 1; |
- if (1 == width && 1 == height) { |
- break; |
- } |
- } |
+ int countLevels = ComputeLevelCount(src.width(), src.height()); |
+ for (int currentMipLevel = countLevels; currentMipLevel > 0; currentMipLevel--) { |
+ SkSize mipSize = ComputeLevelSize(src.width(), src.height(), currentMipLevel); |
+ size += SkColorTypeMinRowBytes(ct, mipSize.fWidth) * mipSize.fHeight; |
} |
- SkASSERT(countLevels == SkMipMap::ComputeLevelCount(src.width(), src.height())); |
- |
size_t storageSize = SkMipMap::AllocLevelsSize(countLevels, size); |
if (0 == storageSize) { |
return nullptr; |
@@ -507,6 +496,29 @@ int SkMipMap::ComputeLevelCount(int baseWidth, int baseHeight) { |
return mipLevelCount; |
} |
+SkSize SkMipMap::ComputeLevelSize(int baseWidth, int baseHeight, int level) { |
+ if (baseWidth < 1 || baseHeight < 1) { |
+ return SkSize::Make(0, 0); |
+ } |
+ |
+ int maxLevelCount = ComputeLevelCount(baseWidth, baseHeight); |
+ if (level > maxLevelCount || level < 0) { |
+ return SkSize::Make(0, 0); |
+ } |
+ if (level == 0) { |
+ return SkSize::Make(baseWidth, baseHeight); |
+ } |
+ |
+ // OpenGL's spec requires that each mipmap level have height/width equal to |
+ // max(1, floor(original_height / 2^i) |
+ // (or original_width) where i is the mipmap level. |
+ |
+ int width = SkTMax(1, baseWidth >> level); |
+ int height = SkTMax(1, baseHeight >> level); |
+ |
+ return SkSize::Make(width, height); |
+} |
+ |
/////////////////////////////////////////////////////////////////////////////// |
bool SkMipMap::extractLevel(const SkSize& scaleSize, Level* levelPtr) const { |