aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/SkMathPriv.h22
-rw-r--r--src/gpu/GrResourceProvider.cpp4
-rw-r--r--tests/MathTest.cpp38
3 files changed, 62 insertions, 2 deletions
diff --git a/src/core/SkMathPriv.h b/src/core/SkMathPriv.h
index fca09f3ffc..14ebeb17b7 100644
--- a/src/core/SkMathPriv.h
+++ b/src/core/SkMathPriv.h
@@ -154,6 +154,28 @@ static inline uint32_t GrNextPow2(uint32_t n) {
return n ? (1 << (32 - SkCLZ(n - 1))) : 1;
}
+/**
+ * Returns the next power of 2 >= n or n if the next power of 2 can't be represented by size_t.
+ */
+static inline size_t GrNextSizePow2(size_t n) {
+ constexpr int kNumSizeTBits = 8 * sizeof(size_t);
+ constexpr size_t kHighBitSet = size_t(1) << (kNumSizeTBits - 1);
+
+ if (!n) {
+ return 1;
+ } else if (n >= kHighBitSet) {
+ return n;
+ }
+
+ n--;
+ uint32_t shift = 1;
+ while (shift < kNumSizeTBits) {
+ n |= n >> shift;
+ shift <<= 1;
+ }
+ return n + 1;
+}
+
static inline int GrNextPow2(int n) {
SkASSERT(n >= 0); // this impl only works for non-neg.
return n ? (1 << (32 - SkCLZ(n - 1))) : 1;
diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp
index 9739b05ad7..a6958e5440 100644
--- a/src/gpu/GrResourceProvider.cpp
+++ b/src/gpu/GrResourceProvider.cpp
@@ -109,8 +109,8 @@ GrBuffer* GrResourceProvider::createBuffer(size_t size, GrBufferType intendedTyp
}
// bin by pow2 with a reasonable min
- static const uint32_t MIN_SIZE = 1 << 12;
- size_t allocSize = SkTMax(MIN_SIZE, GrNextPow2(SkToUInt(size)));
+ static const size_t MIN_SIZE = 1 << 12;
+ size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size));
GrScratchKey key;
GrBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
diff --git a/tests/MathTest.cpp b/tests/MathTest.cpp
index 41a4104bd4..35b4136b44 100644
--- a/tests/MathTest.cpp
+++ b/tests/MathTest.cpp
@@ -685,3 +685,41 @@ DEF_TEST(divmod_s32, r) {
DEF_TEST(divmod_s64, r) {
test_divmod<int64_t>(r);
}
+
+static void test_nextsizepow2(skiatest::Reporter* r, size_t test, size_t expectedAns) {
+ size_t ans = GrNextSizePow2(test);
+
+ REPORTER_ASSERT(r, ans == expectedAns);
+ //SkDebugf("0x%zx -> 0x%zx (0x%zx)\n", test, ans, expectedAns);
+}
+
+DEF_TEST(GrNextSizePow2, reporter) {
+ constexpr int kNumSizeTBits = 8 * sizeof(size_t);
+
+ size_t test = 0, expectedAns = 1;
+
+ test_nextsizepow2(reporter, test, expectedAns);
+
+ test = 1; expectedAns = 1;
+
+ for (int i = 1; i < kNumSizeTBits; ++i) {
+ test_nextsizepow2(reporter, test, expectedAns);
+
+ test++;
+ expectedAns <<= 1;
+
+ test_nextsizepow2(reporter, test, expectedAns);
+
+ test = expectedAns;
+ }
+
+ // For the remaining three tests there is no higher power (of 2)
+ test = 0x1;
+ test <<= kNumSizeTBits-1;
+ test_nextsizepow2(reporter, test, test);
+
+ test++;
+ test_nextsizepow2(reporter, test, test);
+
+ test_nextsizepow2(reporter, SIZE_MAX, SIZE_MAX);
+}