| 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 |