diff options
-rw-r--r-- | src/core/SkMathPriv.h | 22 | ||||
-rw-r--r-- | src/gpu/GrResourceProvider.cpp | 4 | ||||
-rw-r--r-- | tests/MathTest.cpp | 38 |
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); +} |