OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBitmap.h" | 8 #include "SkBitmap.h" |
9 #include "SkMipMap.h" | 9 #include "SkMipMap.h" |
10 #include "SkRandom.h" | 10 #include "SkRandom.h" |
11 #include "Test.h" | 11 #include "Test.h" |
12 | 12 |
13 static void make_bitmap(SkBitmap* bm, SkRandom& rand) { | 13 static void make_bitmap(SkBitmap* bm, int width, int height) { |
14 // for now, Build needs a min size of 2, otherwise it will return nullptr. | 14 bm->allocN32Pixels(width, height); |
15 // should fix that to support 1 X N, where N > 1 to return non-null. | |
16 int w = 2 + rand.nextU() % 1000; | |
17 int h = 2 + rand.nextU() % 1000; | |
18 bm->allocN32Pixels(w, h); | |
19 bm->eraseColor(SK_ColorWHITE); | 15 bm->eraseColor(SK_ColorWHITE); |
20 } | 16 } |
21 | 17 |
22 DEF_TEST(MipMap, reporter) { | 18 DEF_TEST(MipMap, reporter) { |
23 SkBitmap bm; | 19 SkBitmap bm; |
24 SkRandom rand; | 20 SkRandom rand; |
25 | 21 |
26 for (int i = 0; i < 500; ++i) { | 22 for (int i = 0; i < 500; ++i) { |
27 make_bitmap(&bm, rand); | 23 // for now, Build needs a min size of 2, otherwise it will return nullpt
r. |
| 24 // should fix that to support 1 X N, where N > 1 to return non-null. |
| 25 int width = 2 + rand.nextU() % 1000; |
| 26 int height = 2 + rand.nextU() % 1000; |
| 27 make_bitmap(&bm, width, height); |
28 SkAutoTUnref<SkMipMap> mm(SkMipMap::Build(bm, nullptr)); | 28 SkAutoTUnref<SkMipMap> mm(SkMipMap::Build(bm, nullptr)); |
29 | 29 |
| 30 // Add 1 because SkMipMap doesn't store the base mip level. |
| 31 // It stores levels 1-x, not 0-x. |
| 32 REPORTER_ASSERT(reporter, mm->countLevels() + 1 == SkMipMap::ComputeLeve
lCount(width, |
| 33
height)); |
| 34 |
30 REPORTER_ASSERT(reporter, !mm->extractLevel(SK_Scalar1, nullptr)); | 35 REPORTER_ASSERT(reporter, !mm->extractLevel(SK_Scalar1, nullptr)); |
31 REPORTER_ASSERT(reporter, !mm->extractLevel(SK_Scalar1 * 2, nullptr)); | 36 REPORTER_ASSERT(reporter, !mm->extractLevel(SK_Scalar1 * 2, nullptr)); |
32 | 37 |
33 SkMipMap::Level prevLevel; | 38 SkMipMap::Level prevLevel; |
34 sk_bzero(&prevLevel, sizeof(prevLevel)); | 39 sk_bzero(&prevLevel, sizeof(prevLevel)); |
35 | 40 |
36 SkScalar scale = SK_Scalar1; | 41 SkScalar scale = SK_Scalar1; |
37 for (int j = 0; j < 30; ++j) { | 42 for (int j = 0; j < 30; ++j) { |
38 scale = scale * 2 / 3; | 43 scale = scale * 2 / 3; |
39 | 44 |
40 SkMipMap::Level level; | 45 SkMipMap::Level level; |
41 if (mm->extractLevel(scale, &level)) { | 46 if (mm->extractLevel(scale, &level)) { |
42 REPORTER_ASSERT(reporter, level.fPixmap.addr()); | 47 REPORTER_ASSERT(reporter, level.fPixmap.addr()); |
43 REPORTER_ASSERT(reporter, level.fPixmap.width() > 0); | 48 REPORTER_ASSERT(reporter, level.fPixmap.width() > 0); |
44 REPORTER_ASSERT(reporter, level.fPixmap.height() > 0); | 49 REPORTER_ASSERT(reporter, level.fPixmap.height() > 0); |
45 REPORTER_ASSERT(reporter, (int)level.fPixmap.rowBytes() >= level
.fPixmap.width() * 4); | 50 REPORTER_ASSERT(reporter, (int)level.fPixmap.rowBytes() >= level
.fPixmap.width() * 4); |
46 | 51 |
47 if (prevLevel.fPixmap.addr()) { | 52 if (prevLevel.fPixmap.addr()) { |
48 REPORTER_ASSERT(reporter, level.fPixmap.width() <= prevLevel
.fPixmap.width()); | 53 REPORTER_ASSERT(reporter, level.fPixmap.width() <= prevLevel
.fPixmap.width()); |
49 REPORTER_ASSERT(reporter, level.fPixmap.height() <= prevLeve
l.fPixmap.height()); | 54 REPORTER_ASSERT(reporter, level.fPixmap.height() <= prevLeve
l.fPixmap.height()); |
50 } | 55 } |
51 prevLevel = level; | 56 prevLevel = level; |
52 } | 57 } |
53 } | 58 } |
54 } | 59 } |
55 } | 60 } |
| 61 |
| 62 static void test_mipmap_generation(int width, int height, int expectedMipLevelCo
unt, |
| 63 skiatest::Reporter* reporter) { |
| 64 SkBitmap bm; |
| 65 bm.allocN32Pixels(width, height); |
| 66 bm.eraseColor(SK_ColorWHITE); |
| 67 SkAutoTUnref<SkMipMap> mm(SkMipMap::Build(bm, nullptr)); |
| 68 |
| 69 const int mipLevelCount = mm->countLevels(); |
| 70 REPORTER_ASSERT(reporter, mipLevelCount == expectedMipLevelCount); |
| 71 for (int i = 0; i < mipLevelCount; ++i) { |
| 72 SkMipMap::Level level; |
| 73 mm->getLevel(i, &level); |
| 74 // Make sure the mipmaps contain valid data and that the sizes are |
| 75 // correct |
| 76 REPORTER_ASSERT(reporter, level.fPixmap.addr()); |
| 77 |
| 78 // + 1 because SkMipMap does not include the base mipmap level. |
| 79 int twoToTheMipLevel = 1 << (i + 1); |
| 80 int currentWidth = width / twoToTheMipLevel; |
| 81 int currentHeight = height / twoToTheMipLevel; |
| 82 REPORTER_ASSERT(reporter, level.fPixmap.width() == currentWidth); |
| 83 REPORTER_ASSERT(reporter, level.fPixmap.height() == currentHeight); |
| 84 } |
| 85 } |
| 86 |
| 87 DEF_TEST(MipMap_DirectLevelAccess, reporter) { |
| 88 // create mipmap with invalid size |
| 89 { |
| 90 // SkMipMap current requires the dimensions be greater than 2x2 |
| 91 SkBitmap bm; |
| 92 bm.allocN32Pixels(1, 1); |
| 93 bm.eraseColor(SK_ColorWHITE); |
| 94 SkAutoTUnref<SkMipMap> mm(SkMipMap::Build(bm, nullptr)); |
| 95 |
| 96 REPORTER_ASSERT(reporter, mm == nullptr); |
| 97 } |
| 98 |
| 99 |
| 100 // check small mipmap's count and levels |
| 101 // There should be 5 mipmap levels generated: |
| 102 // 16x16, 8x8, 4x4, 2x2, 1x1 |
| 103 test_mipmap_generation(32, 32, 5, reporter); |
| 104 |
| 105 // check large mipmap's count and levels |
| 106 // There should be 9 mipmap levels generated: |
| 107 // 500x500, 250x250, 125x125, 62x62, 31x31, 15x15, 7x7, 3x3. 1x1 |
| 108 test_mipmap_generation(1000, 1000, 9, reporter); |
| 109 } |
| 110 |
| 111 DEF_TEST(MipMap_ComputeLevelCount, reporter) { |
| 112 // Test mipmaps with negative sizes |
| 113 int negativeWidthResult = SkMipMap::ComputeLevelCount(-100, 100); |
| 114 REPORTER_ASSERT(reporter, negativeWidthResult == 0); |
| 115 |
| 116 int negativeHeightResult = SkMipMap::ComputeLevelCount(100, -100); |
| 117 REPORTER_ASSERT(reporter, negativeHeightResult == 0); |
| 118 |
| 119 int negativeBothResult = SkMipMap::ComputeLevelCount(-100, -100); |
| 120 REPORTER_ASSERT(reporter, negativeBothResult == 0); |
| 121 |
| 122 |
| 123 // Test mipmaps with 0, 1, 2 as dimensions |
| 124 // (SkMipMap::Build requires a min size of 2) |
| 125 // |
| 126 // 0 |
| 127 int zeroWidthResult = SkMipMap::ComputeLevelCount(0, 100); |
| 128 REPORTER_ASSERT(reporter, zeroWidthResult == 0); |
| 129 |
| 130 int zeroHeightResult = SkMipMap::ComputeLevelCount(100, 0); |
| 131 REPORTER_ASSERT(reporter, zeroHeightResult == 0); |
| 132 |
| 133 int zeroBothResult = SkMipMap::ComputeLevelCount(0, 0); |
| 134 REPORTER_ASSERT(reporter, zeroBothResult == 0); |
| 135 |
| 136 // 1 |
| 137 int oneWidthResult = SkMipMap::ComputeLevelCount(1, 100); |
| 138 REPORTER_ASSERT(reporter, oneWidthResult == 0); |
| 139 |
| 140 int oneHeightResult = SkMipMap::ComputeLevelCount(100, 1); |
| 141 REPORTER_ASSERT(reporter, oneHeightResult == 0); |
| 142 |
| 143 int oneBothResult = SkMipMap::ComputeLevelCount(1, 1); |
| 144 REPORTER_ASSERT(reporter, oneBothResult == 0); |
| 145 |
| 146 // 2 |
| 147 int twoWidthResult = SkMipMap::ComputeLevelCount(2, 100); |
| 148 REPORTER_ASSERT(reporter, twoWidthResult == 2); |
| 149 |
| 150 int twoHeightResult = SkMipMap::ComputeLevelCount(100, 2); |
| 151 REPORTER_ASSERT(reporter, twoHeightResult == 2); |
| 152 |
| 153 int twoBothResult = SkMipMap::ComputeLevelCount(2, 2); |
| 154 REPORTER_ASSERT(reporter, twoBothResult == 2); |
| 155 |
| 156 |
| 157 // Test a handful of boundaries such as 63x63 and 64x64 |
| 158 int sixtyThreeResult = SkMipMap::ComputeLevelCount(63, 63); |
| 159 REPORTER_ASSERT(reporter, sixtyThreeResult == 6); |
| 160 |
| 161 int sixtyFourResult = SkMipMap::ComputeLevelCount(64, 64); |
| 162 REPORTER_ASSERT(reporter, sixtyFourResult == 7); |
| 163 |
| 164 int oneHundredTwentySevenResult = SkMipMap::ComputeLevelCount(127, 127); |
| 165 REPORTER_ASSERT(reporter, oneHundredTwentySevenResult == 7); |
| 166 |
| 167 int oneHundredTwentyEightResult = SkMipMap::ComputeLevelCount(128, 128); |
| 168 REPORTER_ASSERT(reporter, oneHundredTwentyEightResult == 8); |
| 169 |
| 170 int twoHundredFiftyFiveResult = SkMipMap::ComputeLevelCount(255, 255); |
| 171 REPORTER_ASSERT(reporter, twoHundredFiftyFiveResult == 8); |
| 172 |
| 173 int twoHundredFiftySixResult = SkMipMap::ComputeLevelCount(256, 256); |
| 174 REPORTER_ASSERT(reporter, twoHundredFiftySixResult == 9); |
| 175 |
| 176 |
| 177 // Test different dimensions, such as 256x64 |
| 178 int smallestAxisIsSixtyFourResult = SkMipMap::ComputeLevelCount(64, 129); |
| 179 REPORTER_ASSERT(reporter, smallestAxisIsSixtyFourResult == 7); |
| 180 |
| 181 int smallestAxisIsThirtyTwoResult = SkMipMap::ComputeLevelCount(255, 32); |
| 182 REPORTER_ASSERT(reporter, smallestAxisIsThirtyTwoResult == 6); |
| 183 |
| 184 int smallestAxisIsFiveHundredResult = SkMipMap::ComputeLevelCount(500, 1000)
; |
| 185 REPORTER_ASSERT(reporter, smallestAxisIsFiveHundredResult == 9); |
| 186 |
| 187 // Test a few calls to SkMipMap::Build to make sure it matches |
| 188 // SkMipMap::ComputeLevelCount |
| 189 // |
| 190 // Add 1 to mm->countLevels() because SkMipMap does not contain the base |
| 191 // mipmap level. |
| 192 // It contains mipmap levels 1-x, not 0-x. |
| 193 { |
| 194 SkBitmap bm; |
| 195 bm.allocN32Pixels(255, 255); |
| 196 bm.eraseColor(SK_ColorWHITE); |
| 197 SkAutoTUnref<SkMipMap> mm(SkMipMap::Build(bm, nullptr)); |
| 198 |
| 199 REPORTER_ASSERT(reporter, mm->countLevels() + 1 == SkMipMap::ComputeLeve
lCount(255, 255)); |
| 200 } |
| 201 |
| 202 { |
| 203 SkBitmap bm; |
| 204 bm.allocN32Pixels(32, 32); |
| 205 bm.eraseColor(SK_ColorWHITE); |
| 206 SkAutoTUnref<SkMipMap> mm(SkMipMap::Build(bm, nullptr)); |
| 207 |
| 208 REPORTER_ASSERT(reporter, mm->countLevels() + 1 == SkMipMap::ComputeLeve
lCount(32, 32)); |
| 209 } |
| 210 |
| 211 { |
| 212 SkBitmap bm; |
| 213 bm.allocN32Pixels(1000, 1000); |
| 214 bm.eraseColor(SK_ColorWHITE); |
| 215 SkAutoTUnref<SkMipMap> mm(SkMipMap::Build(bm, nullptr)); |
| 216 |
| 217 REPORTER_ASSERT(reporter, mm->countLevels() + 1 == SkMipMap::ComputeLeve
lCount(1000, 1000)); |
| 218 } |
| 219 } |
OLD | NEW |