OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2015 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #include "CodecSubsetBench.h" | |
9 #include "SkData.h" | |
10 #include "SkCodec.h" | |
11 #include "SkImageDecoder.h" | |
12 #include "SkOSFile.h" | |
13 #include "SkStream.h" | |
14 | |
15 /* | |
16 * | |
17 * This benchmark is designed to test the performance of subset decoding. | |
18 * | |
19 */ | |
20 CodecSubsetBench::CodecSubsetBench(SkString* path, | |
21 SubsetMode subsetMode, | |
22 SkColorType colorType, | |
23 uint32_t subsetWidth, | |
24 uint32_t subsetHeight, | |
25 uint32_t offsetLeft, | |
26 uint32_t offsetTop, | |
27 uint32_t divisor, | |
28 bool useCodec) | |
29 : fSubsetMode(subsetMode) | |
30 , fColorType(colorType) | |
31 , fSubsetWidth(subsetWidth) | |
32 , fSubsetHeight(subsetHeight) | |
33 , fOffsetLeft(offsetLeft) | |
34 , fOffsetTop(offsetTop) | |
35 , fDivisor(divisor) | |
36 , fUseCodec(useCodec) | |
37 { | |
38 // Parse the filename | |
39 SkString baseName = SkOSPath::Basename(path->c_str()); | |
40 | |
41 // Choose an informative subset mode name | |
42 SkString modeName; | |
43 switch(fSubsetMode) { | |
44 case kSingle_SubsetMode: | |
45 SkASSERT(0 == divisor); | |
46 modeName.printf("Single_%dx%d +%d_+%d", fSubsetWidth, fSubsetHeight, fOffsetLeft, | |
47 fOffsetTop); | |
48 break; | |
49 case kDivisor_SubsetMode: | |
50 SkASSERT(0 == subsetWidth); | |
51 SkASSERT(0 == subsetHeight); | |
52 SkASSERT(0 == offsetLeft); | |
53 SkASSERT(0 == offsetTop); | |
54 modeName.printf("Divisor_%dx%d", fDivisor, fDivisor); | |
55 break; | |
56 case kTranslate_SubsetMode: | |
57 SkASSERT(0 == divisor); | |
58 SkASSERT(0 == offsetLeft); | |
59 SkASSERT(0 == offsetTop); | |
60 modeName.printf("Size_%dx%d", fSubsetWidth, fSubsetHeight); | |
61 break; | |
62 case kScale_SubsetMode: | |
63 SkASSERT(0 == divisor); | |
64 SkASSERT(0 == offsetLeft); | |
65 SkASSERT(0 == offsetTop); | |
66 modeName.printf("Scale_%dx%d", fSubsetWidth, fSubsetHeight); | |
67 break; | |
68 } | |
69 | |
70 // Choose an informative color name | |
71 const char* colorName; | |
72 switch(fColorType) { | |
scroggo
2015/05/29 15:36:02
What about kIndex8?
msarett
2015/06/01 14:03:25
Agreed!
| |
73 case kN32_SkColorType: | |
74 colorName = "N32"; | |
75 break; | |
76 case kRGB_565_SkColorType: | |
77 colorName = "565"; | |
78 break; | |
79 case kGray_8_SkColorType: | |
80 colorName = "Gray8"; | |
81 break; | |
82 case kAlpha_8_SkColorType: | |
83 colorName = "Alpha8"; | |
84 break; | |
85 default: | |
86 colorName = "Unknown"; | |
87 } | |
88 fName.printf("%sSubset%s_%s_%s", fUseCodec ? "Codec" : "Image", modeName.c_s tr(), | |
89 baseName.c_str(), colorName); | |
90 | |
91 // Perform the decode setup | |
92 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path->c_str())); | |
93 fStream.reset(new SkMemoryStream(encoded)); | |
94 } | |
95 | |
96 const char* CodecSubsetBench::onGetName() { | |
97 return fName.c_str(); | |
98 } | |
99 | |
100 bool CodecSubsetBench::isSuitableFor(Backend backend) { | |
101 return kNonRendering_Backend == backend; | |
102 } | |
103 | |
104 void CodecSubsetBench::onDraw(const int n, SkCanvas* canvas) { | |
105 // Choose a different benchmark depending on the mode | |
106 switch(fSubsetMode) { | |
scroggo
2015/05/29 15:36:02
This giant switch statement might argue for using
msarett
2015/06/01 14:03:25
Agreed.
| |
107 case kSingle_SubsetMode: | |
108 if (fUseCodec) { | |
109 for (int count = 0; count < n; count++) { | |
110 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(fStream- >duplicate())); | |
111 const SkImageInfo info = codec->getInfo(); | |
112 SkAutoTDeleteArray<uint8_t> row(SkNEW_ARRAY(uint8_t, info.mi nRowBytes())); | |
113 SkScanlineDecoder* scanlineDecoder = codec->getScanlineDecod er(info); | |
114 | |
115 SkBitmap bitmap; | |
116 if (!bitmap.tryAllocPixels(info.makeWH(fSubsetWidth, fSubset Height))) { | |
117 SkDebugf("Could not allocate memory. Aborting bench.\n" ); | |
118 return; | |
119 } | |
120 | |
121 scanlineDecoder->skipScanlines(fOffsetTop); | |
122 uint32_t bpp = info.bytesPerPixel(); | |
123 for (uint32_t y = 0; y < fSubsetHeight; y++) { | |
124 scanlineDecoder->getScanlines(row.get(), 1, 0); | |
125 memcpy(bitmap.getAddr(0, y), row.get() + fOffsetLeft * b pp, | |
126 fSubsetWidth * bpp); | |
127 } | |
128 } | |
129 } else { | |
130 for (int count = 0; count < n; count++) { | |
131 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factor y(fStream)); | |
132 int width, height; | |
133 decoder->buildTileIndex(fStream->duplicate(), &width, &heigh t); | |
scroggo
2015/05/29 15:36:02
Do we need to safely early exit in case buildTileI
msarett
2015/06/01 14:03:24
Let's check that the decode succeeds before creati
| |
134 SkBitmap bitmap; | |
135 SkIRect rect = SkIRect::MakeXYWH(fOffsetLeft, fOffsetTop, fS ubsetWidth, | |
136 fSubsetHeight); | |
137 decoder->decodeSubset(&bitmap, rect, fColorType); | |
138 } | |
139 } | |
140 break; | |
141 case kDivisor_SubsetMode: | |
142 if (fUseCodec) { | |
143 for (int count = 0; count < n; count++) { | |
144 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(fStream- >duplicate())); | |
145 const SkImageInfo info = codec->getInfo(); | |
146 SkAutoTDeleteArray<uint8_t> row(SkNEW_ARRAY(uint8_t, info.mi nRowBytes())); | |
147 SkScanlineDecoder* scanlineDecoder = codec->getScanlineDecod er(info); | |
148 | |
149 uint32_t subsetWidth = info.width() / fDivisor; | |
scroggo
2015/05/29 15:36:02
These variables could all be const?
msarett
2015/06/01 14:03:25
Done.
| |
150 uint32_t subsetHeight = info.height() / fDivisor; | |
151 uint32_t maxSubsetWidth = subsetWidth + info.width() % fDivi sor; | |
152 uint32_t maxSubsetHeight = subsetHeight + info.height() % fD ivisor; | |
153 SkBitmap bitmap; | |
154 // Note that we use the same bitmap for all of the subsets. | |
155 // It might be slightly larger than necessary for some of th e subsets. | |
156 if (!bitmap.tryAllocPixels(info.makeWH(maxSubsetWidth, maxSu bsetHeight))) { | |
157 SkDebugf("Could not allocate memory. Aborting bench.\n" ); | |
158 return; | |
159 } | |
160 | |
161 for (uint32_t blockX = 0; blockX < fDivisor; blockX++) { | |
162 for (uint32_t blockY = 0; blockY < fDivisor; blockY++) { | |
163 scanlineDecoder->skipScanlines(blockY * subsetHeight ); | |
164 uint32_t currSubsetWidth = | |
165 (blockX == fDivisor - 1) ? maxSubsetWidth : subsetWidth; | |
166 uint32_t currSubsetHeight = | |
167 (blockY == fDivisor - 1) ? maxSubsetHeight : subsetHeight; | |
168 uint32_t bpp = info.bytesPerPixel(); | |
169 for (uint32_t y = 0; y < currSubsetHeight; y++) { | |
170 scanlineDecoder->getScanlines(row.get(), 1, 0); | |
171 memcpy(bitmap.getAddr(0, y), row.get() + fOffset Left * bpp, | |
172 currSubsetWidth * bpp); | |
173 } | |
174 } | |
175 } | |
176 } | |
177 } else { | |
178 for (int count = 0; count < n; count++) { | |
179 int width, height; | |
180 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factor y(fStream)); | |
181 decoder->buildTileIndex(fStream->duplicate(), &width, &heigh t); | |
182 | |
183 uint32_t subsetWidth = width / fDivisor; | |
184 uint32_t subsetHeight = height / fDivisor; | |
185 uint32_t maxSubsetWidth = subsetWidth + width % fDivisor; | |
186 uint32_t maxSubsetHeight = subsetHeight + height % fDivisor; | |
187 SkBitmap bitmap; | |
188 // Note that we use the same bitmap for all of the subsets. | |
189 // It might be slightly larger than necessary for some of th e subsets. | |
190 if (!bitmap.tryAllocPixels(SkImageInfo::Make(maxSubsetWidth, maxSubsetHeight, | |
scroggo
2015/05/29 15:36:02
When using SkImageDecoder, you don't need to alloc
msarett
2015/06/01 14:03:24
The reason I allocate here is so that SkImageDecod
scroggo
2015/06/01 17:25:14
Got it. We talked about this in person and you con
msarett
2015/06/01 20:37:01
Done.
| |
191 fColorType, kOpaque_SkAlphaType))) { | |
192 SkDebugf("Could not allocate memory. Aborting bench.\n" ); | |
193 return; | |
194 } | |
195 | |
196 for (uint32_t blockX = 0; blockX < fDivisor; blockX++) { | |
197 for (uint32_t blockY = 0; blockY < fDivisor; blockY++) { | |
198 uint32_t currSubsetWidth = | |
199 (blockX == fDivisor - 1) ? maxSubsetWidth : subsetWidth; | |
200 uint32_t currSubsetHeight = | |
201 (blockY == fDivisor - 1) ? maxSubsetHeight : subsetHeight; | |
202 SkIRect rect = SkIRect::MakeXYWH(blockX * subsetWidt h, | |
203 blockY * subsetHeight, currSubsetWidth, curr SubsetHeight); | |
204 decoder->decodeSubset(&bitmap, rect, fColorType); | |
205 } | |
206 } | |
207 } | |
208 } | |
209 break; | |
210 case kTranslate_SubsetMode: | |
211 if (fUseCodec) { | |
212 for (int count = 0; count < n; count++) { | |
213 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(fStream- >duplicate())); | |
214 const SkImageInfo info = codec->getInfo(); | |
215 SkAutoTDeleteArray<uint8_t> row(SkNEW_ARRAY(uint8_t, info.mi nRowBytes())); | |
216 SkScanlineDecoder* scanlineDecoder = codec->getScanlineDecod er(info); | |
217 | |
218 SkBitmap bitmap; | |
219 // Note that we use the same bitmap for all of the subsets. | |
220 // It might be larger than necessary for the end subsets. | |
221 if (!bitmap.tryAllocPixels(info.makeWH(fSubsetWidth, fSubset Height))) { | |
222 SkDebugf("Could not allocate memory. Aborting bench.\n" ); | |
223 return; | |
224 } | |
225 | |
226 for (int x = 0; x < info.width(); x += fSubsetWidth) { | |
227 for (int y = 0; y < info.height(); y += fSubsetHeight) { | |
228 scanlineDecoder->skipScanlines(y); | |
229 uint32_t currSubsetWidth = x + (int) fSubsetWidth > info.width() ? | |
230 info.width() - x : fSubsetWidth; | |
231 uint32_t currSubsetHeight = y + (int) fSubsetHeight > info.height() ? | |
232 info.height() - y : fSubsetHeight; | |
233 uint32_t bpp = info.bytesPerPixel(); | |
234 for (uint32_t y = 0; y < currSubsetHeight; y++) { | |
235 scanlineDecoder->getScanlines(row.get(), 1, 0); | |
236 memcpy(bitmap.getAddr(0, y), row.get() + x * bpp , | |
237 currSubsetWidth * bpp); | |
238 } | |
239 } | |
240 } | |
241 } | |
242 } else { | |
243 for (int count = 0; count < n; count++) { | |
244 int width, height; | |
245 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factor y(fStream)); | |
246 decoder->buildTileIndex(fStream->duplicate(), &width, &heigh t); | |
247 SkBitmap bitmap; | |
248 // Note that we use the same bitmap for all of the subsets. | |
249 // It might be larger than necessary for the end subsets. | |
250 if (!bitmap.tryAllocPixels(SkImageInfo::Make(fSubsetWidth, f SubsetHeight, | |
scroggo
2015/05/29 15:36:02
Again, this is not necessary.
msarett
2015/06/01 14:03:25
Acknowledged.
| |
251 fColorType, kOpaque_SkAlphaType))) { | |
252 SkDebugf("Could not allocate memory. Aborting bench.\n" ); | |
253 return; | |
254 } | |
255 | |
256 for (int x = 0; x < width; x += fSubsetWidth) { | |
257 for (int y = 0; y < height; y += fSubsetHeight) { | |
258 uint32_t currSubsetWidth = x + (int) fSubsetWidth > width ? | |
259 width - x : fSubsetWidth; | |
260 uint32_t currSubsetHeight = y + (int) fSubsetHeight > height ? | |
261 height - y : fSubsetHeight; | |
262 SkIRect rect = SkIRect::MakeXYWH(x, y, currSubsetWid th, | |
263 currSubsetHeight); | |
264 decoder->decodeSubset(&bitmap, rect, fColorType); | |
265 } | |
266 } | |
267 } | |
268 } | |
269 break; | |
270 case kScale_SubsetMode: | |
271 if (fUseCodec) { | |
272 for (int count = 0; count < n; count++) { | |
273 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(fStream- >duplicate())); | |
274 const SkImageInfo info = codec->getInfo(); | |
275 SkAutoTDeleteArray<uint8_t> row(SkNEW_ARRAY(uint8_t, info.mi nRowBytes())); | |
276 SkScanlineDecoder* scanlineDecoder = codec->getScanlineDecod er(info); | |
277 | |
278 int centerX = info.width() / 2; | |
279 int centerY = info.height() / 2; | |
280 int w = fSubsetWidth; | |
281 int h = fSubsetHeight; | |
282 do { | |
283 int subsetStartX = SkTMax(0, centerX - w / 2); | |
284 int subsetStartY = SkTMax(0, centerY - h / 2); | |
285 int subsetWidth = SkTMin(w, info.width() - subsetStartX) ; | |
286 int subsetHeight = SkTMin(h, info.height() - subsetStart Y); | |
287 // Note that if we subseted and scaled in a single step, we could use the | |
scroggo
2015/05/29 15:36:02
subsetted? (Technically not a verb, but it seems l
msarett
2015/06/01 14:03:25
Done.
| |
288 // same bitmap - as is often done in actual use cases. | |
289 SkBitmap bitmap; | |
290 if (!bitmap.tryAllocPixels(info.makeWH(subsetWidth, subs etHeight))) { | |
291 SkDebugf("Could not allocate memory. Aborting bench .\n"); | |
292 return; | |
293 } | |
294 | |
295 uint32_t bpp = info.bytesPerPixel(); | |
296 scanlineDecoder->skipScanlines(subsetStartY); | |
297 for (int y = 0; y < subsetHeight; y++) { | |
298 scanlineDecoder->getScanlines(row.get(), 1, 0); | |
299 memcpy(bitmap.getAddr(0, y), row.get() + subsetStart X * bpp, | |
300 subsetWidth * bpp); | |
301 } | |
302 w <<= 1; | |
303 h <<= 1; | |
304 } while (w < 2 * info.width() || h < 2 * info.height()); | |
305 } | |
306 } else { | |
307 for (int count = 0; count < n; count++) { | |
308 int width, height; | |
309 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factor y(fStream)); | |
310 decoder->buildTileIndex(fStream->duplicate(), &width, &heigh t); | |
311 | |
312 int centerX = width / 2; | |
313 int centerY = height / 2; | |
314 int w = fSubsetWidth; | |
315 int h = fSubsetHeight; | |
316 do { | |
317 int subsetStartX = SkTMax(0, centerX - w / 2); | |
318 int subsetStartY = SkTMax(0, centerY - h / 2); | |
319 int subsetWidth = SkTMin(w, width - subsetStartX); | |
320 int subsetHeight = SkTMin(h, height - subsetStartY); | |
321 // Note that if we subseted and scaled in a single step, we could use the | |
322 // same bitmap - as is often done in actual use cases. | |
323 SkBitmap bitmap; | |
324 if (!bitmap.tryAllocPixels(SkImageInfo::Make(subsetWidth , subsetHeight, | |
scroggo
2015/05/29 15:36:03
Again, not needed. There are some cases where a bi
msarett
2015/06/01 14:03:24
Agreed that this allocation is unnecessary here.
| |
325 fColorType, kOpaque_SkAlphaType))) { | |
326 SkDebugf("Could not allocate memory. Aborting bench .\n"); | |
327 return; | |
328 } | |
329 | |
330 SkIRect rect = SkIRect::MakeXYWH(subsetStartX, subsetSta rtY, subsetWidth, | |
331 subsetHeight); | |
332 decoder->decodeSubset(&bitmap, rect, fColorType); | |
333 w <<= 1; | |
334 h <<= 1; | |
335 } while (w < 2 * width || h < 2 * height); | |
336 } | |
337 } | |
338 break; | |
339 } | |
340 } | |
OLD | NEW |