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