aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar cblume <cblume@chromium.org>2016-02-17 14:53:23 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-02-17 14:53:23 -0800
commite2412d5738e4ee37a897cc51996431a4dfb10436 (patch)
treec33a1ec22c240e43f9ea84d3d9b47e86be5cf629 /src
parent3bc2624a4b89c49efd65f5e548ac5f2dd9351431 (diff)
Adding direct access to SkMipMap levels.
Diffstat (limited to 'src')
-rw-r--r--src/core/SkMipMap.cpp63
-rw-r--r--src/core/SkMipMap.h6
2 files changed, 69 insertions, 0 deletions
diff --git a/src/core/SkMipMap.cpp b/src/core/SkMipMap.cpp
index 1f69c2411b..eae5e618f6 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,8 @@ SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) {
return nullptr;
}
+ SkASSERT(countLevels == SkMipMap::ComputeLevelCount(src.width(), src.height()));
+
size_t storageSize = SkMipMap::AllocLevelsSize(countLevels, size);
if (0 == storageSize) {
return nullptr;
@@ -318,6 +322,46 @@ SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) {
return mipmap;
}
+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 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.
+ int mipLevelCount = significantBits;
+
+ // SkMipMap does not include the base mip level.
+ // For example, it contains levels 1-x instead of 0-x.
+ // This is because the image used to create SkMipMap is the base level.
+ // So subtract 1 from the mip level count.
+ if (mipLevelCount > 0) {
+ --mipLevelCount;
+ }
+
+ return mipLevelCount;
+}
+
///////////////////////////////////////////////////////////////////////////////
bool SkMipMap::extractLevel(const SkSize& scaleSize, Level* levelPtr) const {
@@ -379,3 +423,22 @@ SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) {
return Build(srcPixmap, fact);
}
+int SkMipMap::countLevels() const {
+ return fCount;
+}
+
+bool SkMipMap::getLevel(int index, Level* levelPtr) const {
+ if (NULL == fLevels) {
+ return false;
+ }
+ if (index < 0) {
+ return false;
+ }
+ if (index > fCount - 1) {
+ return false;
+ }
+ if (levelPtr) {
+ *levelPtr = fLevels[index];
+ }
+ return true;
+}
diff --git a/src/core/SkMipMap.h b/src/core/SkMipMap.h
index fe2018c670..928c12d436 100644
--- a/src/core/SkMipMap.h
+++ b/src/core/SkMipMap.h
@@ -23,12 +23,18 @@ public:
static SkMipMap* Build(const SkPixmap& src, SkDiscardableFactoryProc);
static SkMipMap* Build(const SkBitmap& src, SkDiscardableFactoryProc);
+ // This function lets you determine how many levels a SkMipMap will have without
+ // creating that mipmap.
+ static int ComputeLevelCount(int baseWidth, int baseHeight);
+
struct Level {
SkPixmap fPixmap;
SkSize fScale; // < 1.0
};
bool extractLevel(const SkSize& scale, Level*) const;
+ int countLevels() const;
+ bool getLevel(int index, Level*) const;
protected:
void onDataChange(void* oldData, void* newData) override {