Index: src/core/SkMipMap.cpp |
diff --git a/src/core/SkMipMap.cpp b/src/core/SkMipMap.cpp |
index 08602b7e00728b100d78862f76288a6afd4770f1..b9ebd4671ad08dcbd5f7a2a631f65895f241368c 100644 |
--- a/src/core/SkMipMap.cpp |
+++ b/src/core/SkMipMap.cpp |
@@ -8,7 +8,9 @@ |
#include "SkMipMap.h" |
#include "SkBitmap.h" |
#include "SkColorPriv.h" |
+#include "SkMath.h" |
#include "SkNx.h" |
+#include "SkTypes.h" |
// |
// ColorTypeFilter is the "Type" we pass to some downsample template functions. |
@@ -249,6 +251,10 @@ SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) { |
return nullptr; |
} |
+ // We add 1 below because countLevels stores the extra, non-base mipmap |
+ // levels. That is, SkMipMap stores levels 1-x not 0-x. |
+ SkASSERT(countLevels + 1 == SkMipMap::ComputeLevelCount(src.width(), src.height())); |
+ |
size_t storageSize = SkMipMap::AllocLevelsSize(countLevels, size); |
if (0 == storageSize) { |
return nullptr; |
@@ -367,3 +373,53 @@ SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) { |
return Build(srcPixmap, fact); |
} |
+int SkMipMap::ComputeLevelCount(int baseWidth, int 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. |
+ // Continue scaling down until both axes are size 1. |
+ // |
+ // This means when it maintains isotropic space (both axes scaling down |
+ // at the same rate) until one axis hits size 1. |
+ // At that point, OpenGL continues to scale down into anisotropic space |
+ // (where the scales are not the same between axes). |
+ // |
+ // Skia currently does not go into anisotropic space. |
+ // Once an axis hits size 1 we stop. |
+ // All this means is rather than use the largest axis we will use the |
+ // smallest axis. |
+ |
+ const int smallestAxis = SkTMin(baseWidth, baseHeight); |
+ if (smallestAxis < 2) { |
+ // SkMipMap::Build requires a minimum size of 2. |
+ return 0; |
+ } |
+ const int leadingZeros = SkCLZ(static_cast<uint32_t>(smallestAxis)); |
+ // If the value 00011010 has 3 leading 0s then it has 5 significant bits |
+ // (the bits which are not leading zeros) |
+ const int significantBits = (sizeof(uint32_t) * 8) - leadingZeros; |
+ // This is making the assumption that the size of a byte is 8 bits |
+ // and that sizeof(uint32_t)'s implementation-defined behavior is 4. |
+ const int mipLevelCount = significantBits; |
+ |
+ return mipLevelCount; |
+} |
+ |
+int SkMipMap::countLevels() const { |
+ return fCount; |
+} |
+ |
+void SkMipMap::getLevel(int index, Level* levelPtr) const { |
+ if (NULL == fLevels) { |
reed1
2016/02/05 22:37:11
I think we should either assert or return a bool (
cblume
2016/02/06 13:38:16
Done.
|
+ return; |
+ } |
+ if (index < 0) { |
+ return; |
+ } |
+ if (index > fCount - 1) { |
+ return; |
+ } |
+ if (levelPtr) { |
+ *levelPtr = fLevels[index]; |
+ } |
+} |