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 |