OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 "DMSrcSink.h" | 8 #include "DMSrcSink.h" |
9 #include "SamplePipeControllers.h" | 9 #include "SamplePipeControllers.h" |
10 #include "SkCodec.h" | 10 #include "SkCodec.h" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 return gm->getName(); | 57 return gm->getName(); |
58 } | 58 } |
59 | 59 |
60 void GMSrc::modifyGrContextOptions(GrContextOptions* options) const { | 60 void GMSrc::modifyGrContextOptions(GrContextOptions* options) const { |
61 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL)); | 61 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL)); |
62 gm->modifyGrContextOptions(options); | 62 gm->modifyGrContextOptions(options); |
63 } | 63 } |
64 | 64 |
65 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~*/ | 65 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~*/ |
66 | 66 |
67 CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType) | 67 CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType, float scale) |
68 : fPath(path) | 68 : fPath(path) |
69 , fMode(mode) | 69 , fMode(mode) |
70 , fDstColorType(dstColorType) | 70 , fDstColorType(dstColorType) |
| 71 , fScale(scale) |
71 {} | 72 {} |
72 | 73 |
73 Error CodecSrc::draw(SkCanvas* canvas) const { | 74 Error CodecSrc::draw(SkCanvas* canvas) const { |
74 SkImageInfo canvasInfo; | 75 SkImageInfo canvasInfo; |
75 if (NULL == canvas->peekPixels(&canvasInfo, NULL)) { | 76 if (NULL == canvas->peekPixels(&canvasInfo, NULL)) { |
76 // TODO: Once we implement GPU paths (e.g. JPEG YUV), we should use a de
ferred decode to | 77 // TODO: Once we implement GPU paths (e.g. JPEG YUV), we should use a de
ferred decode to |
77 // let the GPU handle it. | 78 // let the GPU handle it. |
78 return Error::Nonfatal("No need to test decoding to non-raster backend."
); | 79 return Error::Nonfatal("No need to test decoding to non-raster backend."
); |
79 } | 80 } |
80 | 81 |
(...skipping 20 matching lines...) Expand all Loading... |
101 decodeInfo = codec->getInfo().makeColorType(kGray_8_SkColorType); | 102 decodeInfo = codec->getInfo().makeColorType(kGray_8_SkColorType); |
102 if (kRGB_565_SkColorType == canvasColorType) { | 103 if (kRGB_565_SkColorType == canvasColorType) { |
103 return Error::Nonfatal("Testing non-565 to 565 is uninteresting.
"); | 104 return Error::Nonfatal("Testing non-565 to 565 is uninteresting.
"); |
104 } | 105 } |
105 break; | 106 break; |
106 default: | 107 default: |
107 decodeInfo = decodeInfo.makeColorType(canvasColorType); | 108 decodeInfo = decodeInfo.makeColorType(canvasColorType); |
108 break; | 109 break; |
109 } | 110 } |
110 | 111 |
| 112 // Try to scale the image if it is desired |
| 113 SkISize size = codec->getScaledDimensions(fScale); |
| 114 if (size == decodeInfo.dimensions() && 1.0f != fScale) { |
| 115 return Error::Nonfatal("Test without scaling is uninteresting."); |
| 116 } |
| 117 decodeInfo = decodeInfo.makeWH(size.width(), size.height()); |
| 118 |
111 // Construct a color table for the decode if necessary | 119 // Construct a color table for the decode if necessary |
112 SkAutoTUnref<SkColorTable> colorTable(NULL); | 120 SkAutoTUnref<SkColorTable> colorTable(NULL); |
113 SkPMColor* colorPtr = NULL; | 121 SkPMColor* colorPtr = NULL; |
114 int* colorCountPtr = NULL; | 122 int* colorCountPtr = NULL; |
115 int maxColors = 256; | 123 int maxColors = 256; |
116 if (kIndex_8_SkColorType == decodeInfo.colorType()) { | 124 if (kIndex_8_SkColorType == decodeInfo.colorType()) { |
117 SkPMColor colors[256]; | 125 SkPMColor colors[256]; |
118 colorTable.reset(SkNEW_ARGS(SkColorTable, (colors, maxColors))); | 126 colorTable.reset(SkNEW_ARGS(SkColorTable, (colors, maxColors))); |
119 colorPtr = const_cast<SkPMColor*>(colorTable->readColors()); | 127 colorPtr = const_cast<SkPMColor*>(colorTable->readColors()); |
120 colorCountPtr = &maxColors; | 128 colorCountPtr = &maxColors; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 const int extraY = h % divisor; | 196 const int extraY = h % divisor; |
189 /* | 197 /* |
190 * if w or h are not evenly divided by divisor need to adjust width a
nd height of end | 198 * if w or h are not evenly divided by divisor need to adjust width a
nd height of end |
191 * subsets to cover entire image. | 199 * subsets to cover entire image. |
192 * Add extraX and extraY to largestSubsetBm's width and height to adj
ust width | 200 * Add extraX and extraY to largestSubsetBm's width and height to adj
ust width |
193 * and height of end subsets. | 201 * and height of end subsets. |
194 * subsetBm is extracted from largestSubsetBm. | 202 * subsetBm is extracted from largestSubsetBm. |
195 * subsetBm's size is determined based on the current subset and may
be larger for end | 203 * subsetBm's size is determined based on the current subset and may
be larger for end |
196 * subsets. | 204 * subsets. |
197 */ | 205 */ |
198 SkImageInfo largestSubsetDecodeInfo = | 206 SkImageInfo largestSubsetDecodeInfo = |
199 decodeInfo.makeWH(subsetWidth + extraX, subsetHeight + extra
Y); | 207 decodeInfo.makeWH(subsetWidth + extraX, subsetHeight + extra
Y); |
200 SkBitmap largestSubsetBm; | 208 SkBitmap largestSubsetBm; |
201 if (!largestSubsetBm.tryAllocPixels(largestSubsetDecodeInfo, NULL, c
olorTable.get())) { | 209 if (!largestSubsetBm.tryAllocPixels(largestSubsetDecodeInfo, NULL, c
olorTable.get())) { |
202 return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPat
h.c_str(), | 210 return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPat
h.c_str(), |
203 largestSubsetDecodeInfo.width(), largestSubsetDecodeInfo
.height()); | 211 largestSubsetDecodeInfo.width(), largestSubsetDecodeInfo
.height()); |
204 } | 212 } |
205 char* line = SkNEW_ARRAY(char, decodeInfo.minRowBytes()); | 213 char* line = SkNEW_ARRAY(char, decodeInfo.minRowBytes()); |
206 SkAutoTDeleteArray<char> lineDeleter(line); | 214 SkAutoTDeleteArray<char> lineDeleter(line); |
207 for (int col = 0; col < divisor; col++) { | 215 for (int col = 0; col < divisor; col++) { |
208 //currentSubsetWidth may be larger than subsetWidth for rightmos
t subsets | 216 //currentSubsetWidth may be larger than subsetWidth for rightmos
t subsets |
(...skipping 10 matching lines...) Expand all Loading... |
219 NULL, colorPtr, colorCountPtr); | 227 NULL, colorPtr, colorCountPtr); |
220 if (NULL == subsetScanlineDecoder) { | 228 if (NULL == subsetScanlineDecoder) { |
221 if (x == 0 && y == 0) { | 229 if (x == 0 && y == 0) { |
222 //first try, image may not be compatible | 230 //first try, image may not be compatible |
223 return Error::Nonfatal("Cannot use scanline decoder
for all images"); | 231 return Error::Nonfatal("Cannot use scanline decoder
for all images"); |
224 } else { | 232 } else { |
225 return "Error scanline decoder is NULL"; | 233 return "Error scanline decoder is NULL"; |
226 } | 234 } |
227 } | 235 } |
228 //skip to first line of subset | 236 //skip to first line of subset |
229 const SkImageGenerator::Result skipResult = | 237 const SkImageGenerator::Result skipResult = |
230 subsetScanlineDecoder->skipScanlines(y); | 238 subsetScanlineDecoder->skipScanlines(y); |
231 switch (skipResult) { | 239 switch (skipResult) { |
232 case SkImageGenerator::kSuccess: | 240 case SkImageGenerator::kSuccess: |
233 case SkImageGenerator::kIncompleteInput: | 241 case SkImageGenerator::kIncompleteInput: |
234 break; | 242 break; |
235 default: | 243 default: |
236 return SkStringPrintf("%s failed after attempting to
skip %d scanlines" | 244 return SkStringPrintf("%s failed after attempting to
skip %d scanlines" |
237 "with error message %d", fPath.c_str(), y, (
int) skipResult); | 245 "with error message %d", fPath.c_str(), y, (
int) skipResult); |
238 } | 246 } |
239 //create and set size of subsetBm | 247 //create and set size of subsetBm |
(...skipping 15 matching lines...) Expand all Loading... |
255 default: | 263 default: |
256 return SkStringPrintf("%s failed after %d scanli
nes with error" | 264 return SkStringPrintf("%s failed after %d scanli
nes with error" |
257 "message %d", fPath.c_str(), y-1, (int)
subsetResult); | 265 "message %d", fPath.c_str(), y-1, (int)
subsetResult); |
258 } | 266 } |
259 } | 267 } |
260 canvas->drawBitmap(subsetBm, SkIntToScalar(x), SkIntToScalar
(y)); | 268 canvas->drawBitmap(subsetBm, SkIntToScalar(x), SkIntToScalar
(y)); |
261 } | 269 } |
262 } | 270 } |
263 break; | 271 break; |
264 } | 272 } |
| 273 case kStripe_Mode: { |
| 274 const int height = decodeInfo.height(); |
| 275 // This value is chosen arbitrarily. We exercise more cases by choo
sing a value that |
| 276 // does not align with image blocks. |
| 277 const int stripeHeight = 37; |
| 278 const int numStripes = (height + stripeHeight - 1) / stripeHeight; |
| 279 |
| 280 // Decode odd stripes |
| 281 SkScanlineDecoder* decoder = codec->getScanlineDecoder(decodeInfo, N
ULL, colorPtr, |
| 282 colorCountPtr); |
| 283 if (NULL == decoder) { |
| 284 return Error::Nonfatal("Cannot use scanline decoder for all imag
es"); |
| 285 } |
| 286 for (int i = 0; i < numStripes; i += 2) { |
| 287 // Skip a stripe |
| 288 const int linesToSkip = SkTMin(stripeHeight, height - i * stripe
Height); |
| 289 SkImageGenerator::Result result = decoder->skipScanlines(linesTo
Skip); |
| 290 switch (result) { |
| 291 case SkImageGenerator::kSuccess: |
| 292 case SkImageGenerator::kIncompleteInput: |
| 293 break; |
| 294 default: |
| 295 return SkStringPrintf("Cannot skip scanlines for %s.", f
Path.c_str()); |
| 296 } |
| 297 |
| 298 // Read a stripe |
| 299 const int startY = (i + 1) * stripeHeight; |
| 300 const int linesToRead = SkTMin(stripeHeight, height - startY); |
| 301 if (linesToRead > 0) { |
| 302 result = decoder->getScanlines(bitmap.getAddr(0, startY), |
| 303 linesToRead, bitmap.rowBytes()); |
| 304 switch (result) { |
| 305 case SkImageGenerator::kSuccess: |
| 306 case SkImageGenerator::kIncompleteInput: |
| 307 break; |
| 308 default: |
| 309 return SkStringPrintf("Cannot get scanlines for %s."
, fPath.c_str()); |
| 310 } |
| 311 } |
| 312 } |
| 313 |
| 314 // Decode even stripes |
| 315 decoder = codec->getScanlineDecoder(decodeInfo, NULL, colorPtr, colo
rCountPtr); |
| 316 if (NULL == decoder) { |
| 317 return "Failed to create second scanline decoder."; |
| 318 } |
| 319 for (int i = 0; i < numStripes; i += 2) { |
| 320 // Read a stripe |
| 321 const int startY = i * stripeHeight; |
| 322 const int linesToRead = SkTMin(stripeHeight, height - startY); |
| 323 SkImageGenerator::Result result = decoder->getScanlines(bitmap.g
etAddr(0, startY), |
| 324 linesToRead, bitmap.rowBytes()); |
| 325 switch (result) { |
| 326 case SkImageGenerator::kSuccess: |
| 327 case SkImageGenerator::kIncompleteInput: |
| 328 break; |
| 329 default: |
| 330 return SkStringPrintf("Cannot get scanlines for %s.", fP
ath.c_str()); |
| 331 } |
| 332 |
| 333 // Skip a stripe |
| 334 const int linesToSkip = SkTMax(0, SkTMin(stripeHeight, |
| 335 height - (i + 1) * stripeHeight)); |
| 336 result = decoder->skipScanlines(linesToSkip); |
| 337 switch (result) { |
| 338 case SkImageGenerator::kSuccess: |
| 339 case SkImageGenerator::kIncompleteInput: |
| 340 break; |
| 341 default: |
| 342 return SkStringPrintf("Cannot skip scanlines for %s.", f
Path.c_str()); |
| 343 } |
| 344 } |
| 345 canvas->drawBitmap(bitmap, 0, 0); |
| 346 } |
265 } | 347 } |
266 return ""; | 348 return ""; |
267 } | 349 } |
268 | 350 |
269 SkISize CodecSrc::size() const { | 351 SkISize CodecSrc::size() const { |
270 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); | 352 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); |
271 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); | 353 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); |
272 if (NULL != codec) { | 354 if (NULL != codec) { |
273 return codec->getInfo().dimensions(); | 355 SkISize size = codec->getScaledDimensions(fScale); |
| 356 return size; |
274 } else { | 357 } else { |
275 return SkISize::Make(0, 0); | 358 return SkISize::Make(0, 0); |
276 } | 359 } |
277 } | 360 } |
278 | 361 |
279 Name CodecSrc::name() const { | 362 Name CodecSrc::name() const { |
280 return SkOSPath::Basename(fPath.c_str()); | 363 if (1.0f == fScale) { |
| 364 return SkOSPath::Basename(fPath.c_str()); |
| 365 } else { |
| 366 return SkStringPrintf("%s_%.3f", SkOSPath::Basename(fPath.c_str()).c_str
(), fScale); |
| 367 } |
281 } | 368 } |
282 | 369 |
283 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~*/ | 370 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~*/ |
284 | 371 |
285 ImageSrc::ImageSrc(Path path, int divisor) : fPath(path), fDivisor(divisor) {} | 372 ImageSrc::ImageSrc(Path path, int divisor) : fPath(path), fDivisor(divisor) {} |
286 | 373 |
287 Error ImageSrc::draw(SkCanvas* canvas) const { | 374 Error ImageSrc::draw(SkCanvas* canvas) const { |
288 SkImageInfo canvasInfo; | 375 SkImageInfo canvasInfo; |
289 if (NULL == canvas->peekPixels(&canvasInfo, NULL)) { | 376 if (NULL == canvas->peekPixels(&canvasInfo, NULL)) { |
290 // TODO: Instead, use lazy decoding to allow the GPU to handle cases lik
e YUV. | 377 // TODO: Instead, use lazy decoding to allow the GPU to handle cases lik
e YUV. |
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
882 skr.visit<void>(i, drawsAsSingletonPictures); | 969 skr.visit<void>(i, drawsAsSingletonPictures); |
883 } | 970 } |
884 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); | 971 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); |
885 | 972 |
886 canvas->drawPicture(macroPic); | 973 canvas->drawPicture(macroPic); |
887 return ""; | 974 return ""; |
888 }); | 975 }); |
889 } | 976 } |
890 | 977 |
891 } // namespace DM | 978 } // namespace DM |
OLD | NEW |