| 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(nullptr)); | 61 SkAutoTDelete<skiagm::GM> gm(fFactory(nullptr)); |
| 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, float scale) | 67 CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType, float scale,
SkString* folder) |
| 68 : fPath(path) | 68 : fPath(path) |
| 69 , fMode(mode) | 69 , fMode(mode) |
| 70 , fDstColorType(dstColorType) | 70 , fDstColorType(dstColorType) |
| 71 , fScale(scale) | 71 , fScale(scale) |
| 72 , fFolder(folder) |
| 72 {} | 73 {} |
| 73 | 74 |
| 74 bool CodecSrc::veto(SinkFlags flags) const { | 75 bool CodecSrc::veto(SinkFlags flags) const { |
| 75 // No need to test decoding to non-raster or indirect backend. | 76 // No need to test decoding to non-raster or indirect backend. |
| 76 // TODO: Once we implement GPU paths (e.g. JPEG YUV), we should use a deferr
ed decode to | 77 // TODO: Once we implement GPU paths (e.g. JPEG YUV), we should use a deferr
ed decode to |
| 77 // let the GPU handle it. | 78 // let the GPU handle it. |
| 78 return flags.type != SinkFlags::kRaster | 79 return flags.type != SinkFlags::kRaster |
| 79 || flags.approach != SinkFlags::kDirect; | 80 || flags.approach != SinkFlags::kDirect; |
| 80 } | 81 } |
| 81 | 82 |
| 82 SkScanlineDecoder* start_scanline_decoder(SkData* encoded, const SkImageInfo& in
fo, | 83 SkScanlineDecoder* start_scanline_decoder(SkData* encoded, const SkImageInfo& in
fo, |
| 83 SkPMColor* colorPtr, int* colorCountPtr) { | 84 SkPMColor* colorPtr, int* colorCountPtr) { |
| 84 SkAutoTDelete<SkScanlineDecoder> scanlineDecoder(SkScanlineDecoder::NewFromD
ata(encoded)); | 85 SkAutoTDelete<SkScanlineDecoder> scanlineDecoder(SkScanlineDecoder::NewFromD
ata(encoded)); |
| 85 if (nullptr == scanlineDecoder) { | 86 if (nullptr == scanlineDecoder) { |
| 86 return nullptr; | 87 return nullptr; |
| 87 } | 88 } |
| 88 // DM scanline test assume kTopDown scanline ordering. Other orderings are | |
| 89 // tested from within SkScaledCodec. | |
| 90 // TODO (msarett): Redesign the CodecSrc tests to improve our coverage of Sk
Codec and | |
| 91 // SkScanlineDecoder functionality. Maybe we should write c
ode to explicitly | |
| 92 // test kNone, kOutOfOrder, and kBottomUp. | |
| 93 if (SkScanlineDecoder::kTopDown_SkScanlineOrder != scanlineDecoder->getScanl
ineOrder()) { | |
| 94 return nullptr; | |
| 95 } | |
| 96 if (SkCodec::kSuccess != scanlineDecoder->start(info, NULL, colorPtr, colorC
ountPtr)) { | 89 if (SkCodec::kSuccess != scanlineDecoder->start(info, NULL, colorPtr, colorC
ountPtr)) { |
| 97 return nullptr; | 90 return nullptr; |
| 98 } | 91 } |
| 99 return scanlineDecoder.detach(); | 92 return scanlineDecoder.detach(); |
| 100 } | 93 } |
| 101 | 94 |
| 102 Error CodecSrc::draw(SkCanvas* canvas) const { | 95 Error CodecSrc::draw(SkCanvas* canvas) const { |
| 103 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); | 96 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); |
| 104 if (!encoded) { | 97 if (!encoded) { |
| 105 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); | 98 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); |
| 106 } | 99 } |
| 107 SkAutoTDelete<SkCodec> codec(SkScaledCodec::NewFromData(encoded)); | 100 SkAutoTDelete<SkCodec> codec(NULL); |
| 101 if (kScaledCodec_Mode == fMode) { |
| 102 codec.reset(SkScaledCodec::NewFromData(encoded)); |
| 103 // TODO (msarett): This should fall through to a fatal error once we sup
port scaled |
| 104 // codecs for all image types. |
| 105 if (nullptr == codec.get()) { |
| 106 return Error::Nonfatal(SkStringPrintf("Couldn't create scaled codec
for %s.", |
| 107 fPath.c_str())); |
| 108 } |
| 109 } else { |
| 110 codec.reset(SkCodec::NewFromData(encoded)); |
| 111 } |
| 108 if (nullptr == codec.get()) { | 112 if (nullptr == codec.get()) { |
| 109 // scaledCodec not supported, try normal codec | 113 return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str()); |
| 110 codec.reset(SkCodec::NewFromData(encoded)); | |
| 111 if (nullptr == codec.get()) { | |
| 112 return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str()
); | |
| 113 } | |
| 114 } | 114 } |
| 115 | 115 |
| 116 // Choose the color type to decode to | 116 // Choose the color type to decode to |
| 117 SkImageInfo decodeInfo = codec->getInfo(); | 117 SkImageInfo decodeInfo = codec->getInfo(); |
| 118 SkColorType canvasColorType = canvas->imageInfo().colorType(); | 118 SkColorType canvasColorType = canvas->imageInfo().colorType(); |
| 119 switch (fDstColorType) { | 119 switch (fDstColorType) { |
| 120 case kIndex8_Always_DstColorType: | 120 case kIndex8_Always_DstColorType: |
| 121 decodeInfo = codec->getInfo().makeColorType(kIndex_8_SkColorType); | 121 decodeInfo = codec->getInfo().makeColorType(kIndex_8_SkColorType); |
| 122 if (kRGB_565_SkColorType == canvasColorType) { | 122 if (kRGB_565_SkColorType == canvasColorType) { |
| 123 return Error::Nonfatal("Testing non-565 to 565 is uninteresting.
"); | 123 return Error::Nonfatal("Testing non-565 to 565 is uninteresting.
"); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 decodeInfo = decodeInfo.makeAlphaType(kPremul_SkAlphaType); | 164 decodeInfo = decodeInfo.makeAlphaType(kPremul_SkAlphaType); |
| 165 } | 165 } |
| 166 | 166 |
| 167 SkBitmap bitmap; | 167 SkBitmap bitmap; |
| 168 if (!bitmap.tryAllocPixels(decodeInfo, nullptr, colorTable.get())) { | 168 if (!bitmap.tryAllocPixels(decodeInfo, nullptr, colorTable.get())) { |
| 169 return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPath.c_str(
), | 169 return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPath.c_str(
), |
| 170 decodeInfo.width(), decodeInfo.height()); | 170 decodeInfo.width(), decodeInfo.height()); |
| 171 } | 171 } |
| 172 | 172 |
| 173 switch (fMode) { | 173 switch (fMode) { |
| 174 case kNormal_Mode: { | 174 case kScaledCodec_Mode: |
| 175 case kCodec_Mode: { |
| 175 switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowB
ytes(), nullptr, | 176 switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowB
ytes(), nullptr, |
| 176 colorPtr, colorCountPtr)) { | 177 colorPtr, colorCountPtr)) { |
| 177 case SkCodec::kSuccess: | 178 case SkCodec::kSuccess: |
| 178 // We consider incomplete to be valid, since we should still
decode what is | 179 // We consider incomplete to be valid, since we should still
decode what is |
| 179 // available. | 180 // available. |
| 180 case SkCodec::kIncompleteInput: | 181 case SkCodec::kIncompleteInput: |
| 181 break; | 182 break; |
| 182 case SkCodec::kInvalidConversion: | 183 case SkCodec::kInvalidConversion: |
| 183 return Error::Nonfatal("Incompatible colortype conversion"); | 184 return Error::Nonfatal("Incompatible colortype conversion"); |
| 184 default: | 185 default: |
| 185 // Everything else is considered a failure. | 186 // Everything else is considered a failure. |
| 186 return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str(
)); | 187 return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str(
)); |
| 187 } | 188 } |
| 188 canvas->drawBitmap(bitmap, 0, 0); | 189 canvas->drawBitmap(bitmap, 0, 0); |
| 189 break; | 190 break; |
| 190 } | 191 } |
| 191 case kScanline_Mode: { | 192 case kScanline_Mode: { |
| 192 SkAutoTDelete<SkScanlineDecoder> scanlineDecoder( | 193 SkAutoTDelete<SkScanlineDecoder> scanlineDecoder( |
| 193 start_scanline_decoder(encoded.get(), decodeInfo, colorPtr,
colorCountPtr)); | 194 start_scanline_decoder(encoded.get(), decodeInfo, colorPtr,
colorCountPtr)); |
| 194 if (nullptr == scanlineDecoder) { | 195 if (nullptr == scanlineDecoder) { |
| 195 return Error::Nonfatal("Could not start top-down scanline decode
r"); | 196 return Error::Nonfatal("Could not start scanline decoder"); |
| 196 } | 197 } |
| 197 | 198 |
| 198 const SkCodec::Result result = scanlineDecoder->getScanlines( | 199 const SkCodec::Result result = scanlineDecoder->getScanlines( |
| 199 bitmap.getAddr(0, 0), decodeInfo.height(), bitmap.rowBytes()
); | 200 bitmap.getAddr(0, 0), decodeInfo.height(), bitmap.rowBytes()
); |
| 200 switch (result) { | 201 switch (result) { |
| 201 case SkCodec::kSuccess: | 202 case SkCodec::kSuccess: |
| 202 case SkCodec::kIncompleteInput: | 203 case SkCodec::kIncompleteInput: |
| 203 break; | 204 break; |
| 204 default: | 205 default: |
| 205 return SkStringPrintf("%s failed with error message %d", | 206 return SkStringPrintf("%s failed with error message %d", |
| (...skipping 21 matching lines...) Expand all Loading... |
| 227 * subsets to cover entire image. | 228 * subsets to cover entire image. |
| 228 * Add extraX and extraY to largestSubsetBm's width and height to adj
ust width | 229 * Add extraX and extraY to largestSubsetBm's width and height to adj
ust width |
| 229 * and height of end subsets. | 230 * and height of end subsets. |
| 230 * subsetBm is extracted from largestSubsetBm. | 231 * subsetBm is extracted from largestSubsetBm. |
| 231 * subsetBm's size is determined based on the current subset and may
be larger for end | 232 * subsetBm's size is determined based on the current subset and may
be larger for end |
| 232 * subsets. | 233 * subsets. |
| 233 */ | 234 */ |
| 234 SkImageInfo largestSubsetDecodeInfo = | 235 SkImageInfo largestSubsetDecodeInfo = |
| 235 decodeInfo.makeWH(subsetWidth + extraX, subsetHeight + extra
Y); | 236 decodeInfo.makeWH(subsetWidth + extraX, subsetHeight + extra
Y); |
| 236 SkBitmap largestSubsetBm; | 237 SkBitmap largestSubsetBm; |
| 237 if (!largestSubsetBm.tryAllocPixels(largestSubsetDecodeInfo, nullptr
, colorTable.get())) { | 238 if (!largestSubsetBm.tryAllocPixels(largestSubsetDecodeInfo, nullptr
, |
| 239 colorTable.get())) { |
| 238 return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPat
h.c_str(), | 240 return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPat
h.c_str(), |
| 239 largestSubsetDecodeInfo.width(), largestSubsetDecodeInfo
.height()); | 241 largestSubsetDecodeInfo.width(), largestSubsetDecodeInfo
.height()); |
| 240 } | 242 } |
| 241 const size_t rowBytes = decodeInfo.minRowBytes(); | 243 const size_t rowBytes = decodeInfo.minRowBytes(); |
| 242 char* buffer = new char[largestSubsetDecodeInfo.height() * rowBytes]
; | 244 char* buffer = new char[largestSubsetDecodeInfo.height() * rowBytes]
; |
| 243 SkAutoTDeleteArray<char> lineDeleter(buffer); | 245 SkAutoTDeleteArray<char> lineDeleter(buffer); |
| 244 for (int col = 0; col < divisor; col++) { | 246 for (int col = 0; col < divisor; col++) { |
| 245 //currentSubsetWidth may be larger than subsetWidth for rightmos
t subsets | 247 //currentSubsetWidth may be larger than subsetWidth for rightmos
t subsets |
| 246 const int currentSubsetWidth = (col + 1 == divisor) ? | 248 const int currentSubsetWidth = (col + 1 == divisor) ? |
| 247 subsetWidth + extraX : subsetWidth; | 249 subsetWidth + extraX : subsetWidth; |
| 248 const int x = col * subsetWidth; | 250 const int x = col * subsetWidth; |
| 249 for (int row = 0; row < divisor; row++) { | 251 for (int row = 0; row < divisor; row++) { |
| 250 //currentSubsetHeight may be larger than subsetHeight for bo
ttom subsets | 252 //currentSubsetHeight may be larger than subsetHeight for bo
ttom subsets |
| 251 const int currentSubsetHeight = (row + 1 == divisor) ? | 253 const int currentSubsetHeight = (row + 1 == divisor) ? |
| 252 subsetHeight + extraY : subsetHeight; | 254 subsetHeight + extraY : subsetHeight; |
| 253 const int y = row * subsetHeight; | 255 const int y = row * subsetHeight; |
| 254 //create scanline decoder for each subset | 256 //create scanline decoder for each subset |
| 255 SkAutoTDelete<SkScanlineDecoder> subsetScanlineDecoder( | 257 SkAutoTDelete<SkScanlineDecoder> decoder(start_scanline_deco
der(encoded.get(), |
| 256 start_scanline_decoder(encoded.get(), decodeInfo, | 258 decodeInfo, colorPtr, colorCountPtr)); |
| 257 colorPtr, colorCountPtr)); | 259 // TODO (msarett): Support this mode for all scanline orderi
ngs. |
| 258 if (nullptr == subsetScanlineDecoder) { | 260 if (nullptr == decoder || SkScanlineDecoder::kTopDown_SkScan
lineOrder != |
| 261 decoder->getScanlineOrder()) { |
| 259 if (x == 0 && y == 0) { | 262 if (x == 0 && y == 0) { |
| 260 //first try, image may not be compatible | 263 //first try, image may not be compatible |
| 261 return Error::Nonfatal("Could not start top-down sca
nline decoder"); | 264 return Error::Nonfatal("Could not start top-down sca
nline decoder"); |
| 262 } else { | 265 } else { |
| 263 return "Error scanline decoder is nullptr"; | 266 return "Error scanline decoder is nullptr"; |
| 264 } | 267 } |
| 265 } | 268 } |
| 266 //skip to first line of subset | 269 //skip to first line of subset |
| 267 const SkCodec::Result skipResult = | 270 const SkCodec::Result skipResult = decoder->skipScanlines(y)
; |
| 268 subsetScanlineDecoder->skipScanlines(y); | |
| 269 switch (skipResult) { | 271 switch (skipResult) { |
| 270 case SkCodec::kSuccess: | 272 case SkCodec::kSuccess: |
| 271 case SkCodec::kIncompleteInput: | 273 case SkCodec::kIncompleteInput: |
| 272 break; | 274 break; |
| 273 default: | 275 default: |
| 274 return SkStringPrintf("%s failed after attempting to
skip %d scanlines" | 276 return SkStringPrintf("%s failed after attempting to
skip %d scanlines" |
| 275 "with error message %d", fPath.c_str(), y, (
int) skipResult); | 277 "with error message %d", fPath.c_str(), y, (
int) skipResult); |
| 276 } | 278 } |
| 277 //create and set size of subsetBm | 279 //create and set size of subsetBm |
| 278 SkBitmap subsetBm; | 280 SkBitmap subsetBm; |
| 279 SkIRect bounds = SkIRect::MakeWH(subsetWidth, subsetHeight); | 281 SkIRect bounds = SkIRect::MakeWH(subsetWidth, subsetHeight); |
| 280 bounds.setXYWH(0, 0, currentSubsetWidth, currentSubsetHeight
); | 282 bounds.setXYWH(0, 0, currentSubsetWidth, currentSubsetHeight
); |
| 281 SkAssertResult(largestSubsetBm.extractSubset(&subsetBm, boun
ds)); | 283 SkAssertResult(largestSubsetBm.extractSubset(&subsetBm, boun
ds)); |
| 282 SkAutoLockPixels autlockSubsetBm(subsetBm, true); | 284 SkAutoLockPixels autlockSubsetBm(subsetBm, true); |
| 283 const SkCodec::Result subsetResult = | 285 const SkCodec::Result subsetResult = |
| 284 subsetScanlineDecoder->getScanlines(buffer, currentSubse
tHeight, rowBytes); | 286 decoder->getScanlines(buffer, currentSubsetHeight, r
owBytes); |
| 285 switch (subsetResult) { | 287 switch (subsetResult) { |
| 286 case SkCodec::kSuccess: | 288 case SkCodec::kSuccess: |
| 287 case SkCodec::kIncompleteInput: | 289 case SkCodec::kIncompleteInput: |
| 288 break; | 290 break; |
| 289 default: | 291 default: |
| 290 return SkStringPrintf("%s failed with error message
%d", | 292 return SkStringPrintf("%s failed with error message
%d", |
| 291 fPath.c_str(), (int) subsetResult); | 293 fPath.c_str(), (int) subsetResult); |
| 292 } | 294 } |
| 293 const size_t bpp = decodeInfo.bytesPerPixel(); | 295 const size_t bpp = decodeInfo.bytesPerPixel(); |
| 294 /* | 296 /* |
| (...skipping 21 matching lines...) Expand all Loading... |
| 316 case kStripe_Mode: { | 318 case kStripe_Mode: { |
| 317 const int height = decodeInfo.height(); | 319 const int height = decodeInfo.height(); |
| 318 // This value is chosen arbitrarily. We exercise more cases by choo
sing a value that | 320 // This value is chosen arbitrarily. We exercise more cases by choo
sing a value that |
| 319 // does not align with image blocks. | 321 // does not align with image blocks. |
| 320 const int stripeHeight = 37; | 322 const int stripeHeight = 37; |
| 321 const int numStripes = (height + stripeHeight - 1) / stripeHeight; | 323 const int numStripes = (height + stripeHeight - 1) / stripeHeight; |
| 322 | 324 |
| 323 // Decode odd stripes | 325 // Decode odd stripes |
| 324 SkAutoTDelete<SkScanlineDecoder> decoder( | 326 SkAutoTDelete<SkScanlineDecoder> decoder( |
| 325 start_scanline_decoder(encoded.get(), decodeInfo, colorPtr,
colorCountPtr)); | 327 start_scanline_decoder(encoded.get(), decodeInfo, colorPtr,
colorCountPtr)); |
| 326 if (nullptr == decoder) { | 328 if (nullptr == decoder || |
| 329 SkScanlineDecoder::kTopDown_SkScanlineOrder != decoder->getS
canlineOrder()) { |
| 330 // This mode was designed to test the new skip scanlines API in
libjpeg-turbo. |
| 331 // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is
not interesting |
| 332 // to run this test for image types that do not have this scanli
ne ordering. |
| 327 return Error::Nonfatal("Could not start top-down scanline decode
r"); | 333 return Error::Nonfatal("Could not start top-down scanline decode
r"); |
| 328 } | 334 } |
| 329 for (int i = 0; i < numStripes; i += 2) { | 335 for (int i = 0; i < numStripes; i += 2) { |
| 330 // Skip a stripe | 336 // Skip a stripe |
| 331 const int linesToSkip = SkTMin(stripeHeight, height - i * stripe
Height); | 337 const int linesToSkip = SkTMin(stripeHeight, height - i * stripe
Height); |
| 332 SkCodec::Result result = decoder->skipScanlines(linesToSkip); | 338 SkCodec::Result result = decoder->skipScanlines(linesToSkip); |
| 333 switch (result) { | 339 switch (result) { |
| 334 case SkCodec::kSuccess: | 340 case SkCodec::kSuccess: |
| 335 case SkCodec::kIncompleteInput: | 341 case SkCodec::kIncompleteInput: |
| 336 break; | 342 break; |
| (...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1081 skr.visit<void>(i, drawsAsSingletonPictures); | 1087 skr.visit<void>(i, drawsAsSingletonPictures); |
| 1082 } | 1088 } |
| 1083 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); | 1089 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); |
| 1084 | 1090 |
| 1085 canvas->drawPicture(macroPic); | 1091 canvas->drawPicture(macroPic); |
| 1086 return ""; | 1092 return ""; |
| 1087 }); | 1093 }); |
| 1088 } | 1094 } |
| 1089 | 1095 |
| 1090 } // namespace DM | 1096 } // namespace DM |
| OLD | NEW |