DMSrcSink.cpp revision 7fcfb621998648ba018e3b89e2cab3135bd46a1f
1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "DMSrcSink.h"
9#include "Resources.h"
10#include "SkAndroidCodec.h"
11#include "SkAutoMalloc.h"
12#include "SkBase64.h"
13#include "SkCodec.h"
14#include "SkCodecImageGenerator.h"
15#include "SkColorSpace.h"
16#include "SkColorSpaceXform.h"
17#include "SkColorSpaceXformCanvas.h"
18#include "SkColorSpace_XYZ.h"
19#include "SkCommonFlags.h"
20#include "SkCommonFlagsGpu.h"
21#include "SkData.h"
22#include "SkDebugCanvas.h"
23#include "SkDeferredDisplayListRecorder.h"
24#include "SkDocument.h"
25#include "SkExecutor.h"
26#include "SkImageGenerator.h"
27#include "SkImageGeneratorCG.h"
28#include "SkImageGeneratorWIC.h"
29#include "SkImageInfoPriv.h"
30#include "SkLiteDL.h"
31#include "SkLiteRecorder.h"
32#include "SkMallocPixelRef.h"
33#include "SkMultiPictureDocumentPriv.h"
34#include "SkMultiPictureDraw.h"
35#include "SkNullCanvas.h"
36#include "SkOSFile.h"
37#include "SkOSPath.h"
38#include "SkOpts.h"
39#include "SkPictureCommon.h"
40#include "SkPictureData.h"
41#include "SkPictureRecorder.h"
42#include "SkPipe.h"
43#include "SkPngEncoder.h"
44#include "SkRandom.h"
45#include "SkRecordDraw.h"
46#include "SkRecorder.h"
47#include "SkSurfaceCharacterization.h"
48#include "SkSVGCanvas.h"
49#include "SkStream.h"
50#include "SkSwizzler.h"
51#include "SkTaskGroup.h"
52#include "SkTLogic.h"
53#include <cmath>
54#include <functional>
55#include "../src/jumper/SkJumper.h"
56
57#if defined(SK_BUILD_FOR_WIN)
58    #include "SkAutoCoInitialize.h"
59    #include "SkHRESULT.h"
60    #include "SkTScopedComPtr.h"
61    #include <XpsObjectModel.h>
62#endif
63
64#if !defined(SK_BUILD_FOR_GOOGLE3)
65    #include "Skottie.h"
66#endif
67
68#if defined(SK_XML)
69    #include "SkSVGDOM.h"
70    #include "SkXMLWriter.h"
71#endif
72
73DEFINE_bool(multiPage, false, "For document-type backends, render the source"
74            " into multiple pages");
75DEFINE_bool(RAW_threading, true, "Allow RAW decodes to run on multiple threads?");
76
77using sk_gpu_test::GrContextFactory;
78
79namespace DM {
80
81GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
82
83Error GMSrc::draw(SkCanvas* canvas) const {
84    std::unique_ptr<skiagm::GM> gm(fFactory(nullptr));
85    gm->draw(canvas);
86    return "";
87}
88
89SkISize GMSrc::size() const {
90    std::unique_ptr<skiagm::GM> gm(fFactory(nullptr));
91    return gm->getISize();
92}
93
94Name GMSrc::name() const {
95    std::unique_ptr<skiagm::GM> gm(fFactory(nullptr));
96    return gm->getName();
97}
98
99void GMSrc::modifyGrContextOptions(GrContextOptions* options) const {
100    std::unique_ptr<skiagm::GM> gm(fFactory(nullptr));
101    gm->modifyGrContextOptions(options);
102}
103
104/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
105
106BRDSrc::BRDSrc(Path path, Mode mode, CodecSrc::DstColorType dstColorType, uint32_t sampleSize)
107    : fPath(path)
108    , fMode(mode)
109    , fDstColorType(dstColorType)
110    , fSampleSize(sampleSize)
111{}
112
113bool BRDSrc::veto(SinkFlags flags) const {
114    // No need to test to non-raster or indirect backends.
115    return flags.type != SinkFlags::kRaster
116        || flags.approach != SinkFlags::kDirect;
117}
118
119static SkBitmapRegionDecoder* create_brd(Path path) {
120    sk_sp<SkData> encoded(SkData::MakeFromFileName(path.c_str()));
121    if (!encoded) {
122        return nullptr;
123    }
124    return SkBitmapRegionDecoder::Create(encoded, SkBitmapRegionDecoder::kAndroidCodec_Strategy);
125}
126
127static inline void alpha8_to_gray8(SkBitmap* bitmap) {
128    // Android requires kGray8 bitmaps to be tagged as kAlpha8.  Here we convert
129    // them back to kGray8 so our test framework can draw them correctly.
130    if (kAlpha_8_SkColorType == bitmap->info().colorType()) {
131        SkImageInfo newInfo = bitmap->info().makeColorType(kGray_8_SkColorType)
132                                            .makeAlphaType(kOpaque_SkAlphaType);
133        *const_cast<SkImageInfo*>(&bitmap->info()) = newInfo;
134    }
135}
136
137Error BRDSrc::draw(SkCanvas* canvas) const {
138    if (canvas->imageInfo().colorSpace() &&
139            kRGBA_F16_SkColorType != canvas->imageInfo().colorType()) {
140        // SkAndroidCodec uses legacy premultiplication and blending.  Therefore, we only
141        // run these tests on legacy canvases.
142        // We allow an exception for F16, since Android uses F16.
143        return Error::Nonfatal("Skip testing to color correct canvas.");
144    }
145
146    SkColorType colorType = canvas->imageInfo().colorType();
147    if (kRGB_565_SkColorType == colorType &&
148            CodecSrc::kGetFromCanvas_DstColorType != fDstColorType) {
149        return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
150    }
151    switch (fDstColorType) {
152        case CodecSrc::kGetFromCanvas_DstColorType:
153            break;
154        case CodecSrc::kGrayscale_Always_DstColorType:
155            colorType = kGray_8_SkColorType;
156            break;
157        default:
158            SkASSERT(false);
159            break;
160    }
161
162    std::unique_ptr<SkBitmapRegionDecoder> brd(create_brd(fPath));
163    if (nullptr == brd.get()) {
164        return Error::Nonfatal(SkStringPrintf("Could not create brd for %s.", fPath.c_str()));
165    }
166
167    if (kRGB_565_SkColorType == colorType) {
168        auto recommendedCT = brd->computeOutputColorType(colorType);
169        if (recommendedCT != colorType) {
170            return Error::Nonfatal("Skip decoding non-opaque to 565.");
171        }
172    }
173
174    const uint32_t width = brd->width();
175    const uint32_t height = brd->height();
176    // Visually inspecting very small output images is not necessary.
177    if ((width / fSampleSize <= 10 || height / fSampleSize <= 10) && 1 != fSampleSize) {
178        return Error::Nonfatal("Scaling very small images is uninteresting.");
179    }
180    switch (fMode) {
181        case kFullImage_Mode: {
182            SkBitmap bitmap;
183            if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(0, 0, width, height),
184                    fSampleSize, colorType, false, SkColorSpace::MakeSRGB())) {
185                return "Cannot decode (full) region.";
186            }
187            alpha8_to_gray8(&bitmap);
188
189            canvas->drawBitmap(bitmap, 0, 0);
190            return "";
191        }
192        case kDivisor_Mode: {
193            const uint32_t divisor = 2;
194            if (width < divisor || height < divisor) {
195                return Error::Nonfatal("Divisor is larger than image dimension.");
196            }
197
198            // Use a border to test subsets that extend outside the image.
199            // We will not allow the border to be larger than the image dimensions.  Allowing
200            // these large borders causes off by one errors that indicate a problem with the
201            // test suite, not a problem with the implementation.
202            const uint32_t maxBorder = SkTMin(width, height) / (fSampleSize * divisor);
203            const uint32_t scaledBorder = SkTMin(5u, maxBorder);
204            const uint32_t unscaledBorder = scaledBorder * fSampleSize;
205
206            // We may need to clear the canvas to avoid uninitialized memory.
207            // Assume we are scaling a 780x780 image with sampleSize = 8.
208            // The output image should be 97x97.
209            // Each subset will be 390x390.
210            // Each scaled subset be 48x48.
211            // Four scaled subsets will only fill a 96x96 image.
212            // The bottom row and last column will not be touched.
213            // This is an unfortunate result of our rounding rules when scaling.
214            // Maybe we need to consider testing scaled subsets without trying to
215            // combine them to match the full scaled image?  Or maybe this is the
216            // best we can do?
217            canvas->clear(0);
218
219            for (uint32_t x = 0; x < divisor; x++) {
220                for (uint32_t y = 0; y < divisor; y++) {
221                    // Calculate the subset dimensions
222                    uint32_t subsetWidth = width / divisor;
223                    uint32_t subsetHeight = height / divisor;
224                    const int left = x * subsetWidth;
225                    const int top = y * subsetHeight;
226
227                    // Increase the size of the last subset in each row or column, when the
228                    // divisor does not divide evenly into the image dimensions
229                    subsetWidth += (x + 1 == divisor) ? (width % divisor) : 0;
230                    subsetHeight += (y + 1 == divisor) ? (height % divisor) : 0;
231
232                    // Increase the size of the subset in order to have a border on each side
233                    const int decodeLeft = left - unscaledBorder;
234                    const int decodeTop = top - unscaledBorder;
235                    const uint32_t decodeWidth = subsetWidth + unscaledBorder * 2;
236                    const uint32_t decodeHeight = subsetHeight + unscaledBorder * 2;
237                    SkBitmap bitmap;
238                    if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(decodeLeft,
239                            decodeTop, decodeWidth, decodeHeight), fSampleSize, colorType, false,
240                            SkColorSpace::MakeSRGB())) {
241                        return "Cannot decode region.";
242                    }
243
244                    alpha8_to_gray8(&bitmap);
245                    canvas->drawBitmapRect(bitmap,
246                            SkRect::MakeXYWH((SkScalar) scaledBorder, (SkScalar) scaledBorder,
247                                    (SkScalar) (subsetWidth / fSampleSize),
248                                    (SkScalar) (subsetHeight / fSampleSize)),
249                            SkRect::MakeXYWH((SkScalar) (left / fSampleSize),
250                                    (SkScalar) (top / fSampleSize),
251                                    (SkScalar) (subsetWidth / fSampleSize),
252                                    (SkScalar) (subsetHeight / fSampleSize)),
253                            nullptr);
254                }
255            }
256            return "";
257        }
258        default:
259            SkASSERT(false);
260            return "Error: Should not be reached.";
261    }
262}
263
264SkISize BRDSrc::size() const {
265    std::unique_ptr<SkBitmapRegionDecoder> brd(create_brd(fPath));
266    if (brd) {
267        return {SkTMax(1, brd->width() / (int)fSampleSize),
268                SkTMax(1, brd->height() / (int)fSampleSize)};
269    }
270    return {0, 0};
271}
272
273static SkString get_scaled_name(const Path& path, float scale) {
274    return SkStringPrintf("%s_%.3f", SkOSPath::Basename(path.c_str()).c_str(), scale);
275}
276
277Name BRDSrc::name() const {
278    // We will replicate the names used by CodecSrc so that images can
279    // be compared in Gold.
280    if (1 == fSampleSize) {
281        return SkOSPath::Basename(fPath.c_str());
282    }
283    return get_scaled_name(fPath, 1.0f / (float) fSampleSize);
284}
285
286/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
287
288static bool serial_from_path_name(const SkString& path) {
289    if (!FLAGS_RAW_threading) {
290        static const char* const exts[] = {
291            "arw", "cr2", "dng", "nef", "nrw", "orf", "raf", "rw2", "pef", "srw",
292            "ARW", "CR2", "DNG", "NEF", "NRW", "ORF", "RAF", "RW2", "PEF", "SRW",
293        };
294        const char* actualExt = strrchr(path.c_str(), '.');
295        if (actualExt) {
296            actualExt++;
297            for (auto* ext : exts) {
298                if (0 == strcmp(ext, actualExt)) {
299                    return true;
300                }
301            }
302        }
303    }
304    return false;
305}
306
307CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType, SkAlphaType dstAlphaType,
308                   float scale)
309    : fPath(path)
310    , fMode(mode)
311    , fDstColorType(dstColorType)
312    , fDstAlphaType(dstAlphaType)
313    , fScale(scale)
314    , fRunSerially(serial_from_path_name(path))
315{}
316
317bool CodecSrc::veto(SinkFlags flags) const {
318    // Test to direct raster backends (8888 and 565).
319    return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
320}
321
322// Allows us to test decodes to non-native 8888.
323static void swap_rb_if_necessary(SkBitmap& bitmap, CodecSrc::DstColorType dstColorType) {
324    if (CodecSrc::kNonNative8888_Always_DstColorType != dstColorType) {
325        return;
326    }
327
328    for (int y = 0; y < bitmap.height(); y++) {
329        uint32_t* row = (uint32_t*) bitmap.getAddr(0, y);
330        SkOpts::RGBA_to_BGRA(row, row, bitmap.width());
331    }
332}
333
334// FIXME: Currently we cannot draw unpremultiplied sources. skbug.com/3338 and skbug.com/3339.
335// This allows us to still test unpremultiplied decodes.
336static void premultiply_if_necessary(SkBitmap& bitmap) {
337    if (kUnpremul_SkAlphaType != bitmap.alphaType()) {
338        return;
339    }
340
341    switch (bitmap.colorType()) {
342        case kRGBA_F16_SkColorType: {
343            SkJumper_MemoryCtx ctx = { bitmap.getAddr(0,0), bitmap.rowBytesAsPixels() };
344            SkRasterPipeline_<256> p;
345            p.append(SkRasterPipeline::load_f16, &ctx);
346            p.append(SkRasterPipeline::premul);
347            p.append(SkRasterPipeline::store_f16, &ctx);
348            p.run(0,0, bitmap.width(), bitmap.height());
349        }
350            break;
351        case kN32_SkColorType:
352            for (int y = 0; y < bitmap.height(); y++) {
353                uint32_t* row = (uint32_t*) bitmap.getAddr(0, y);
354                SkOpts::RGBA_to_rgbA(row, row, bitmap.width());
355            }
356            break;
357        default:
358            // No need to premultiply kGray or k565 outputs.
359            break;
360    }
361
362    // In the kIndex_8 case, the canvas won't even try to draw unless we mark the
363    // bitmap as kPremul.
364    bitmap.setAlphaType(kPremul_SkAlphaType);
365}
366
367static bool get_decode_info(SkImageInfo* decodeInfo, SkColorType canvasColorType,
368                            CodecSrc::DstColorType dstColorType, SkAlphaType dstAlphaType) {
369    switch (dstColorType) {
370        case CodecSrc::kGrayscale_Always_DstColorType:
371            if (kRGB_565_SkColorType == canvasColorType) {
372                return false;
373            }
374            *decodeInfo = decodeInfo->makeColorType(kGray_8_SkColorType);
375            break;
376        case CodecSrc::kNonNative8888_Always_DstColorType:
377            if (kRGB_565_SkColorType == canvasColorType
378                    || kRGBA_F16_SkColorType == canvasColorType) {
379                return false;
380            }
381#ifdef SK_PMCOLOR_IS_RGBA
382            *decodeInfo = decodeInfo->makeColorType(kBGRA_8888_SkColorType);
383#else
384            *decodeInfo = decodeInfo->makeColorType(kRGBA_8888_SkColorType);
385#endif
386            break;
387        default:
388            if (kRGB_565_SkColorType == canvasColorType &&
389                    kOpaque_SkAlphaType != decodeInfo->alphaType()) {
390                return false;
391            }
392
393            if (kRGBA_F16_SkColorType == canvasColorType) {
394                sk_sp<SkColorSpace> linearSpace = decodeInfo->colorSpace()->makeLinearGamma();
395                *decodeInfo = decodeInfo->makeColorSpace(std::move(linearSpace));
396            }
397
398            *decodeInfo = decodeInfo->makeColorType(canvasColorType);
399            break;
400    }
401
402    *decodeInfo = decodeInfo->makeAlphaType(dstAlphaType);
403    return true;
404}
405
406static void draw_to_canvas(SkCanvas* canvas, const SkImageInfo& info, void* pixels, size_t rowBytes,
407                           CodecSrc::DstColorType dstColorType,
408                           SkScalar left = 0, SkScalar top = 0) {
409    SkBitmap bitmap;
410    bitmap.installPixels(info, pixels, rowBytes);
411    premultiply_if_necessary(bitmap);
412    swap_rb_if_necessary(bitmap, dstColorType);
413    canvas->drawBitmap(bitmap, left, top);
414}
415
416// For codec srcs, we want the "draw" step to be a memcpy.  Any interesting color space or
417// color format conversions should be performed by the codec.  Sometimes the output of the
418// decode will be in an interesting color space.  On our srgb and f16 backends, we need to
419// "pretend" that the color space is standard sRGB to avoid triggering color conversion
420// at draw time.
421static void set_bitmap_color_space(SkImageInfo* info) {
422    if (kRGBA_F16_SkColorType == info->colorType()) {
423        *info = info->makeColorSpace(SkColorSpace::MakeSRGBLinear());
424    } else {
425        *info = info->makeColorSpace(SkColorSpace::MakeSRGB());
426    }
427}
428
429Error CodecSrc::draw(SkCanvas* canvas) const {
430    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
431    if (!encoded) {
432        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
433    }
434
435    std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
436    if (nullptr == codec.get()) {
437        return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
438    }
439
440    SkImageInfo decodeInfo = codec->getInfo();
441    if (!get_decode_info(&decodeInfo, canvas->imageInfo().colorType(), fDstColorType,
442                         fDstAlphaType)) {
443        return Error::Nonfatal("Skipping uninteresting test.");
444    }
445
446    // Try to scale the image if it is desired
447    SkISize size = codec->getScaledDimensions(fScale);
448    if (size == decodeInfo.dimensions() && 1.0f != fScale) {
449        return Error::Nonfatal("Test without scaling is uninteresting.");
450    }
451
452    // Visually inspecting very small output images is not necessary.  We will
453    // cover these cases in unit testing.
454    if ((size.width() <= 10 || size.height() <= 10) && 1.0f != fScale) {
455        return Error::Nonfatal("Scaling very small images is uninteresting.");
456    }
457    decodeInfo = decodeInfo.makeWH(size.width(), size.height());
458
459    const int bpp = decodeInfo.bytesPerPixel();
460    const size_t rowBytes = size.width() * bpp;
461    const size_t safeSize = decodeInfo.computeByteSize(rowBytes);
462    SkAutoMalloc pixels(safeSize);
463
464    SkCodec::Options options;
465    options.fPremulBehavior = canvas->imageInfo().colorSpace() ?
466            SkTransferFunctionBehavior::kRespect : SkTransferFunctionBehavior::kIgnore;
467    if (kCodecZeroInit_Mode == fMode) {
468        memset(pixels.get(), 0, size.height() * rowBytes);
469        options.fZeroInitialized = SkCodec::kYes_ZeroInitialized;
470    }
471
472    SkImageInfo bitmapInfo = decodeInfo;
473    set_bitmap_color_space(&bitmapInfo);
474    if (kRGBA_8888_SkColorType == decodeInfo.colorType() ||
475            kBGRA_8888_SkColorType == decodeInfo.colorType()) {
476        bitmapInfo = bitmapInfo.makeColorType(kN32_SkColorType);
477    }
478
479    switch (fMode) {
480        case kAnimated_Mode: {
481            std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo();
482            if (frameInfos.size() <= 1) {
483                return SkStringPrintf("%s is not an animated image.", fPath.c_str());
484            }
485
486            // As in CodecSrc::size(), compute a roughly square grid to draw the frames
487            // into. "factor" is the number of frames to draw on one row. There will be
488            // up to "factor" rows as well.
489            const float root = sqrt((float) frameInfos.size());
490            const int factor = sk_float_ceil2int(root);
491
492            // Used to cache a frame that future frames will depend on.
493            SkAutoMalloc priorFramePixels;
494            int cachedFrame = SkCodec::kNone;
495            for (int i = 0; static_cast<size_t>(i) < frameInfos.size(); i++) {
496                options.fFrameIndex = i;
497                // Check for a prior frame
498                const int reqFrame = frameInfos[i].fRequiredFrame;
499                if (reqFrame != SkCodec::kNone && reqFrame == cachedFrame
500                        && priorFramePixels.get()) {
501                    // Copy into pixels
502                    memcpy(pixels.get(), priorFramePixels.get(), safeSize);
503                    options.fPriorFrame = reqFrame;
504                } else {
505                    options.fPriorFrame = SkCodec::kNone;
506                }
507                SkCodec::Result result = codec->getPixels(decodeInfo, pixels.get(),
508                                                          rowBytes, &options);
509                if (SkCodec::kInvalidInput == result && i > 0) {
510                    // Some of our test images have truncated later frames. Treat that
511                    // the same as incomplete.
512                    result = SkCodec::kIncompleteInput;
513                }
514                switch (result) {
515                    case SkCodec::kSuccess:
516                    case SkCodec::kErrorInInput:
517                    case SkCodec::kIncompleteInput: {
518                        // If the next frame depends on this one, store it in priorFrame.
519                        // It is possible that we may discard a frame that future frames depend on,
520                        // but the codec will simply redecode the discarded frame.
521                        // Do this before calling draw_to_canvas, which premultiplies in place. If
522                        // we're decoding to unpremul, we want to pass the unmodified frame to the
523                        // codec for decoding the next frame.
524                        if (static_cast<size_t>(i+1) < frameInfos.size()
525                                && frameInfos[i+1].fRequiredFrame == i) {
526                            memcpy(priorFramePixels.reset(safeSize), pixels.get(), safeSize);
527                            cachedFrame = i;
528                        }
529
530                        SkAutoCanvasRestore acr(canvas, true);
531                        const int xTranslate = (i % factor) * decodeInfo.width();
532                        const int yTranslate = (i / factor) * decodeInfo.height();
533                        canvas->translate(SkIntToScalar(xTranslate), SkIntToScalar(yTranslate));
534                        draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, fDstColorType);
535                        if (result != SkCodec::kSuccess) {
536                            return "";
537                        }
538                        break;
539                    }
540                    case SkCodec::kInvalidConversion:
541                        if (i > 0 && (decodeInfo.colorType() == kRGB_565_SkColorType)) {
542                            return Error::Nonfatal(SkStringPrintf(
543                                "Cannot decode frame %i to 565 (%s).", i, fPath.c_str()));
544                        }
545                        // Fall through.
546                    default:
547                        return SkStringPrintf("Couldn't getPixels for frame %i in %s.",
548                                              i, fPath.c_str());
549                }
550            }
551            break;
552        }
553        case kCodecZeroInit_Mode:
554        case kCodec_Mode: {
555            switch (codec->getPixels(decodeInfo, pixels.get(), rowBytes, &options)) {
556                case SkCodec::kSuccess:
557                    // We consider these to be valid, since we should still decode what is
558                    // available.
559                case SkCodec::kErrorInInput:
560                case SkCodec::kIncompleteInput:
561                    break;
562                default:
563                    // Everything else is considered a failure.
564                    return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
565            }
566
567            draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, fDstColorType);
568            break;
569        }
570        case kScanline_Mode: {
571            void* dst = pixels.get();
572            uint32_t height = decodeInfo.height();
573            const bool useIncremental = [this]() {
574                auto exts = { "png", "PNG", "gif", "GIF" };
575                for (auto ext : exts) {
576                    if (fPath.endsWith(ext)) {
577                        return true;
578                    }
579                }
580                return false;
581            }();
582            // ico may use the old scanline method or the new one, depending on whether it
583            // internally holds a bmp or a png.
584            const bool ico = fPath.endsWith("ico");
585            bool useOldScanlineMethod = !useIncremental && !ico;
586            if (useIncremental || ico) {
587                if (SkCodec::kSuccess == codec->startIncrementalDecode(decodeInfo, dst,
588                        rowBytes, &options)) {
589                    int rowsDecoded;
590                    auto result = codec->incrementalDecode(&rowsDecoded);
591                    if (SkCodec::kIncompleteInput == result || SkCodec::kErrorInInput == result) {
592                        codec->fillIncompleteImage(decodeInfo, dst, rowBytes,
593                                                   SkCodec::kNo_ZeroInitialized, height,
594                                                   rowsDecoded);
595                    }
596                } else {
597                    if (useIncremental) {
598                        // Error: These should support incremental decode.
599                        return "Could not start incremental decode";
600                    }
601                    // Otherwise, this is an ICO. Since incremental failed, it must contain a BMP,
602                    // which should work via startScanlineDecode
603                    useOldScanlineMethod = true;
604                }
605            }
606
607            if (useOldScanlineMethod) {
608                if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo)) {
609                    return "Could not start scanline decoder";
610                }
611
612                switch (codec->getScanlineOrder()) {
613                    case SkCodec::kTopDown_SkScanlineOrder:
614                    case SkCodec::kBottomUp_SkScanlineOrder:
615                        // We do not need to check the return value.  On an incomplete
616                        // image, memory will be filled with a default value.
617                        codec->getScanlines(dst, height, rowBytes);
618                        break;
619                }
620            }
621
622            draw_to_canvas(canvas, bitmapInfo, dst, rowBytes, fDstColorType);
623            break;
624        }
625        case kStripe_Mode: {
626            const int height = decodeInfo.height();
627            // This value is chosen arbitrarily.  We exercise more cases by choosing a value that
628            // does not align with image blocks.
629            const int stripeHeight = 37;
630            const int numStripes = (height + stripeHeight - 1) / stripeHeight;
631            void* dst = pixels.get();
632
633            // Decode odd stripes
634            if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, &options)) {
635                return "Could not start scanline decoder";
636            }
637
638            // This mode was designed to test the new skip scanlines API in libjpeg-turbo.
639            // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting
640            // to run this test for image types that do not have this scanline ordering.
641            // We only run this on Jpeg, which is always kTopDown.
642            SkASSERT(SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder());
643
644            for (int i = 0; i < numStripes; i += 2) {
645                // Skip a stripe
646                const int linesToSkip = SkTMin(stripeHeight, height - i * stripeHeight);
647                codec->skipScanlines(linesToSkip);
648
649                // Read a stripe
650                const int startY = (i + 1) * stripeHeight;
651                const int linesToRead = SkTMin(stripeHeight, height - startY);
652                if (linesToRead > 0) {
653                    codec->getScanlines(SkTAddOffset<void>(dst, rowBytes * startY), linesToRead,
654                                        rowBytes);
655                }
656            }
657
658            // Decode even stripes
659            const SkCodec::Result startResult = codec->startScanlineDecode(decodeInfo);
660            if (SkCodec::kSuccess != startResult) {
661                return "Failed to restart scanline decoder with same parameters.";
662            }
663            for (int i = 0; i < numStripes; i += 2) {
664                // Read a stripe
665                const int startY = i * stripeHeight;
666                const int linesToRead = SkTMin(stripeHeight, height - startY);
667                codec->getScanlines(SkTAddOffset<void>(dst, rowBytes * startY), linesToRead,
668                                    rowBytes);
669
670                // Skip a stripe
671                const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) * stripeHeight);
672                if (linesToSkip > 0) {
673                    codec->skipScanlines(linesToSkip);
674                }
675            }
676
677            draw_to_canvas(canvas, bitmapInfo, dst, rowBytes, fDstColorType);
678            break;
679        }
680        case kCroppedScanline_Mode: {
681            const int width = decodeInfo.width();
682            const int height = decodeInfo.height();
683            // This value is chosen because, as we move across the image, it will sometimes
684            // align with the jpeg block sizes and it will sometimes not.  This allows us
685            // to test interestingly different code paths in the implementation.
686            const int tileSize = 36;
687            SkIRect subset;
688            for (int x = 0; x < width; x += tileSize) {
689                subset = SkIRect::MakeXYWH(x, 0, SkTMin(tileSize, width - x), height);
690                options.fSubset = &subset;
691                if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, &options)) {
692                    return "Could not start scanline decoder.";
693                }
694
695                codec->getScanlines(SkTAddOffset<void>(pixels.get(), x * bpp), height, rowBytes);
696            }
697
698            draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, fDstColorType);
699            break;
700        }
701        case kSubset_Mode: {
702            // Arbitrarily choose a divisor.
703            int divisor = 2;
704            // Total width/height of the image.
705            const int W = codec->getInfo().width();
706            const int H = codec->getInfo().height();
707            if (divisor > W || divisor > H) {
708                return Error::Nonfatal(SkStringPrintf("Cannot codec subset: divisor %d is too big "
709                                                      "for %s with dimensions (%d x %d)", divisor,
710                                                      fPath.c_str(), W, H));
711            }
712            // subset dimensions
713            // SkWebpCodec, the only one that supports subsets, requires even top/left boundaries.
714            const int w = SkAlign2(W / divisor);
715            const int h = SkAlign2(H / divisor);
716            SkIRect subset;
717            options.fSubset = &subset;
718            SkBitmap subsetBm;
719            // We will reuse pixel memory from bitmap.
720            void* dst = pixels.get();
721            // Keep track of left and top (for drawing subsetBm into canvas). We could use
722            // fScale * x and fScale * y, but we want integers such that the next subset will start
723            // where the last one ended. So we'll add decodeInfo.width() and height().
724            int left = 0;
725            for (int x = 0; x < W; x += w) {
726                int top = 0;
727                for (int y = 0; y < H; y+= h) {
728                    // Do not make the subset go off the edge of the image.
729                    const int preScaleW = SkTMin(w, W - x);
730                    const int preScaleH = SkTMin(h, H - y);
731                    subset.setXYWH(x, y, preScaleW, preScaleH);
732                    // And scale
733                    // FIXME: Should we have a version of getScaledDimensions that takes a subset
734                    // into account?
735                    const int scaledW = SkTMax(1, SkScalarRoundToInt(preScaleW * fScale));
736                    const int scaledH = SkTMax(1, SkScalarRoundToInt(preScaleH * fScale));
737                    decodeInfo = decodeInfo.makeWH(scaledW, scaledH);
738                    SkImageInfo subsetBitmapInfo = bitmapInfo.makeWH(scaledW, scaledH);
739                    size_t subsetRowBytes = subsetBitmapInfo.minRowBytes();
740                    const SkCodec::Result result = codec->getPixels(decodeInfo, dst, subsetRowBytes,
741                            &options);
742                    switch (result) {
743                        case SkCodec::kSuccess:
744                        case SkCodec::kErrorInInput:
745                        case SkCodec::kIncompleteInput:
746                            break;
747                        default:
748                            return SkStringPrintf("subset codec failed to decode (%d, %d, %d, %d) "
749                                                  "from %s with dimensions (%d x %d)\t error %d",
750                                                  x, y, decodeInfo.width(), decodeInfo.height(),
751                                                  fPath.c_str(), W, H, result);
752                    }
753                    draw_to_canvas(canvas, subsetBitmapInfo, dst, subsetRowBytes, fDstColorType,
754                                   SkIntToScalar(left), SkIntToScalar(top));
755
756                    // translate by the scaled height.
757                    top += decodeInfo.height();
758                }
759                // translate by the scaled width.
760                left += decodeInfo.width();
761            }
762            return "";
763        }
764        default:
765            SkASSERT(false);
766            return "Invalid fMode";
767    }
768    return "";
769}
770
771SkISize CodecSrc::size() const {
772    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
773    std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
774    if (nullptr == codec) {
775        return {0, 0};
776    }
777
778    auto imageSize = codec->getScaledDimensions(fScale);
779    if (fMode == kAnimated_Mode) {
780        // We'll draw one of each frame, so make it big enough to hold them all
781        // in a grid. The grid will be roughly square, with "factor" frames per
782        // row and up to "factor" rows.
783        const size_t count = codec->getFrameInfo().size();
784        const float root = sqrt((float) count);
785        const int factor = sk_float_ceil2int(root);
786        imageSize.fWidth  = imageSize.fWidth  * factor;
787        imageSize.fHeight = imageSize.fHeight * sk_float_ceil2int((float) count / (float) factor);
788    }
789    return imageSize;
790}
791
792Name CodecSrc::name() const {
793    if (1.0f == fScale) {
794        Name name = SkOSPath::Basename(fPath.c_str());
795        if (fMode == kAnimated_Mode) {
796            name.append("_animated");
797        }
798        return name;
799    }
800    SkASSERT(fMode != kAnimated_Mode);
801    return get_scaled_name(fPath, fScale);
802}
803
804/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
805
806AndroidCodecSrc::AndroidCodecSrc(Path path, CodecSrc::DstColorType dstColorType,
807        SkAlphaType dstAlphaType, int sampleSize)
808    : fPath(path)
809    , fDstColorType(dstColorType)
810    , fDstAlphaType(dstAlphaType)
811    , fSampleSize(sampleSize)
812    , fRunSerially(serial_from_path_name(path))
813{}
814
815bool AndroidCodecSrc::veto(SinkFlags flags) const {
816    // No need to test decoding to non-raster or indirect backend.
817    return flags.type != SinkFlags::kRaster
818        || flags.approach != SinkFlags::kDirect;
819}
820
821Error AndroidCodecSrc::draw(SkCanvas* canvas) const {
822    if (canvas->imageInfo().colorSpace() &&
823            kRGBA_F16_SkColorType != canvas->imageInfo().colorType()) {
824        // SkAndroidCodec uses legacy premultiplication and blending.  Therefore, we only
825        // run these tests on legacy canvases.
826        // We allow an exception for F16, since Android uses F16.
827        return Error::Nonfatal("Skip testing to color correct canvas.");
828    }
829
830    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
831    if (!encoded) {
832        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
833    }
834    std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::MakeFromData(encoded));
835    if (nullptr == codec) {
836        return SkStringPrintf("Couldn't create android codec for %s.", fPath.c_str());
837    }
838
839    SkImageInfo decodeInfo = codec->getInfo();
840    if (!get_decode_info(&decodeInfo, canvas->imageInfo().colorType(), fDstColorType,
841                         fDstAlphaType)) {
842        return Error::Nonfatal("Skipping uninteresting test.");
843    }
844
845    // Scale the image if it is desired.
846    SkISize size = codec->getSampledDimensions(fSampleSize);
847
848    // Visually inspecting very small output images is not necessary.  We will
849    // cover these cases in unit testing.
850    if ((size.width() <= 10 || size.height() <= 10) && 1 != fSampleSize) {
851        return Error::Nonfatal("Scaling very small images is uninteresting.");
852    }
853    decodeInfo = decodeInfo.makeWH(size.width(), size.height());
854
855    int bpp = decodeInfo.bytesPerPixel();
856    size_t rowBytes = size.width() * bpp;
857    SkAutoMalloc pixels(size.height() * rowBytes);
858
859    SkBitmap bitmap;
860    SkImageInfo bitmapInfo = decodeInfo;
861    set_bitmap_color_space(&bitmapInfo);
862    if (kRGBA_8888_SkColorType == decodeInfo.colorType() ||
863            kBGRA_8888_SkColorType == decodeInfo.colorType()) {
864        bitmapInfo = bitmapInfo.makeColorType(kN32_SkColorType);
865    }
866
867    // Create options for the codec.
868    SkAndroidCodec::AndroidOptions options;
869    options.fSampleSize = fSampleSize;
870
871    switch (codec->getAndroidPixels(decodeInfo, pixels.get(), rowBytes, &options)) {
872        case SkCodec::kSuccess:
873        case SkCodec::kErrorInInput:
874        case SkCodec::kIncompleteInput:
875            break;
876        default:
877            return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
878    }
879    draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, fDstColorType);
880    return "";
881}
882
883SkISize AndroidCodecSrc::size() const {
884    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
885    std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::MakeFromData(encoded));
886    if (nullptr == codec) {
887        return {0, 0};
888    }
889    return codec->getSampledDimensions(fSampleSize);
890}
891
892Name AndroidCodecSrc::name() const {
893    // We will replicate the names used by CodecSrc so that images can
894    // be compared in Gold.
895    if (1 == fSampleSize) {
896        return SkOSPath::Basename(fPath.c_str());
897    }
898    return get_scaled_name(fPath, 1.0f / (float) fSampleSize);
899}
900
901/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
902
903ImageGenSrc::ImageGenSrc(Path path, Mode mode, SkAlphaType alphaType, bool isGpu)
904    : fPath(path)
905    , fMode(mode)
906    , fDstAlphaType(alphaType)
907    , fIsGpu(isGpu)
908    , fRunSerially(serial_from_path_name(path))
909{}
910
911bool ImageGenSrc::veto(SinkFlags flags) const {
912    if (fIsGpu) {
913        // MSAA runs tend to run out of memory and tests the same code paths as regular gpu configs.
914        return flags.type != SinkFlags::kGPU || flags.approach != SinkFlags::kDirect ||
915               flags.multisampled == SinkFlags::kMultisampled;
916    }
917
918    return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
919}
920
921Error ImageGenSrc::draw(SkCanvas* canvas) const {
922    if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) {
923        return Error::Nonfatal("Uninteresting to test image generator to 565.");
924    }
925
926    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
927    if (!encoded) {
928        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
929    }
930
931#if defined(SK_BUILD_FOR_WIN)
932    // Initialize COM in order to test with WIC.
933    SkAutoCoInitialize com;
934    if (!com.succeeded()) {
935        return "Could not initialize COM.";
936    }
937#endif
938
939    std::unique_ptr<SkImageGenerator> gen(nullptr);
940    switch (fMode) {
941        case kCodec_Mode:
942            gen = SkCodecImageGenerator::MakeFromEncodedCodec(encoded);
943            if (!gen) {
944                return "Could not create codec image generator.";
945            }
946            break;
947        case kPlatform_Mode: {
948#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
949            gen = SkImageGeneratorCG::MakeFromEncodedCG(encoded);
950#elif defined(SK_BUILD_FOR_WIN)
951            gen.reset(SkImageGeneratorWIC::NewFromEncodedWIC(encoded.get()));
952#endif
953
954            if (!gen) {
955                return "Could not create platform image generator.";
956            }
957            break;
958        }
959        default:
960            SkASSERT(false);
961            return "Invalid image generator mode";
962    }
963
964    // Test deferred decoding path on GPU
965    if (fIsGpu) {
966        sk_sp<SkImage> image(SkImage::MakeFromGenerator(std::move(gen), nullptr));
967        if (!image) {
968            return "Could not create image from codec image generator.";
969        }
970        canvas->drawImage(image, 0, 0);
971        return "";
972    }
973
974    // Test various color and alpha types on CPU
975    SkImageInfo decodeInfo = gen->getInfo().makeAlphaType(fDstAlphaType);
976
977    SkImageGenerator::Options options;
978    options.fBehavior = canvas->imageInfo().colorSpace() ?
979            SkTransferFunctionBehavior::kRespect : SkTransferFunctionBehavior::kIgnore;
980
981    int bpp = decodeInfo.bytesPerPixel();
982    size_t rowBytes = decodeInfo.width() * bpp;
983    SkAutoMalloc pixels(decodeInfo.height() * rowBytes);
984    if (!gen->getPixels(decodeInfo, pixels.get(), rowBytes, &options)) {
985        SkString err =
986                SkStringPrintf("Image generator could not getPixels() for %s\n", fPath.c_str());
987
988#if defined(SK_BUILD_FOR_WIN)
989        if (kPlatform_Mode == fMode) {
990            // Do not issue a fatal error for WIC flakiness.
991            return Error::Nonfatal(err);
992        }
993#endif
994
995        return err;
996    }
997
998    set_bitmap_color_space(&decodeInfo);
999    draw_to_canvas(canvas, decodeInfo, pixels.get(), rowBytes,
1000                   CodecSrc::kGetFromCanvas_DstColorType);
1001    return "";
1002}
1003
1004SkISize ImageGenSrc::size() const {
1005    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
1006    std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
1007    if (nullptr == codec) {
1008        return {0, 0};
1009    }
1010    return codec->getInfo().dimensions();
1011}
1012
1013Name ImageGenSrc::name() const {
1014    return SkOSPath::Basename(fPath.c_str());
1015}
1016
1017/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1018
1019ColorCodecSrc::ColorCodecSrc(Path path, Mode mode, SkColorType colorType)
1020    : fPath(path)
1021    , fMode(mode)
1022    , fColorType(colorType)
1023{}
1024
1025bool ColorCodecSrc::veto(SinkFlags flags) const {
1026    // Test to direct raster backends (8888 and 565).
1027    return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
1028}
1029
1030void clamp_if_necessary(const SkBitmap& bitmap, SkColorType dstCT) {
1031    if (kRGBA_F16_SkColorType != bitmap.colorType() || kRGBA_F16_SkColorType == dstCT) {
1032        // No need to clamp if the dst is F16.  We will clamp when we encode to PNG.
1033        return;
1034    }
1035
1036    SkJumper_MemoryCtx ptr = { bitmap.getAddr(0,0), bitmap.rowBytesAsPixels() };
1037
1038    SkRasterPipeline_<256> p;
1039    p.append(SkRasterPipeline::load_f16, &ptr);
1040    p.append(SkRasterPipeline::clamp_0);
1041    if (kPremul_SkAlphaType == bitmap.alphaType()) {
1042        p.append(SkRasterPipeline::clamp_a);
1043    } else {
1044        p.append(SkRasterPipeline::clamp_1);
1045    }
1046    p.append(SkRasterPipeline::store_f16, &ptr);
1047
1048    p.run(0,0, bitmap.width(), bitmap.height());
1049}
1050
1051Error ColorCodecSrc::draw(SkCanvas* canvas) const {
1052    if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) {
1053        return Error::Nonfatal("No need to test color correction to 565 backend.");
1054    }
1055
1056    bool runInLegacyMode = kBaseline_Mode == fMode;
1057    if (runInLegacyMode && canvas->imageInfo().colorSpace()) {
1058        return Error::Nonfatal("Skipping tests that are only interesting in legacy mode.");
1059    } else if (!runInLegacyMode && !canvas->imageInfo().colorSpace()) {
1060        return Error::Nonfatal("Skipping tests that are only interesting in srgb mode.");
1061    }
1062
1063    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
1064    if (!encoded) {
1065        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
1066    }
1067
1068    std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
1069    if (nullptr == codec) {
1070        return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
1071    }
1072
1073    // Load the dst ICC profile.  This particular dst is fairly similar to Adobe RGB.
1074    sk_sp<SkData> dstData = GetResourceAsData("icc_profiles/HP_ZR30w.icc");
1075    if (!dstData) {
1076        return "Cannot read monitor profile.  Is the resource path set correctly?";
1077    }
1078
1079    sk_sp<SkColorSpace> dstSpace = nullptr;
1080    if (kDst_sRGB_Mode == fMode) {
1081        dstSpace = SkColorSpace::MakeSRGB();
1082    } else if (kDst_HPZR30w_Mode == fMode) {
1083        dstSpace = SkColorSpace::MakeICC(dstData->data(), dstData->size());
1084    }
1085
1086    SkImageInfo decodeInfo = codec->getInfo().makeColorType(fColorType).makeColorSpace(dstSpace);
1087    if (kUnpremul_SkAlphaType == decodeInfo.alphaType()) {
1088        decodeInfo = decodeInfo.makeAlphaType(kPremul_SkAlphaType);
1089    }
1090    if (kRGBA_F16_SkColorType == fColorType) {
1091        decodeInfo = decodeInfo.makeColorSpace(decodeInfo.colorSpace()->makeLinearGamma());
1092    }
1093
1094    SkImageInfo bitmapInfo = decodeInfo;
1095    set_bitmap_color_space(&bitmapInfo);
1096    if (kRGBA_8888_SkColorType == decodeInfo.colorType() ||
1097        kBGRA_8888_SkColorType == decodeInfo.colorType())
1098    {
1099        bitmapInfo = bitmapInfo.makeColorType(kN32_SkColorType);
1100    }
1101
1102    SkBitmap bitmap;
1103    if (!bitmap.tryAllocPixels(bitmapInfo)) {
1104        return SkStringPrintf("Image(%s) is too large (%d x %d)", fPath.c_str(),
1105                              bitmapInfo.width(), bitmapInfo.height());
1106    }
1107
1108    size_t rowBytes = bitmap.rowBytes();
1109    SkCodec::Result r = codec->getPixels(decodeInfo, bitmap.getPixels(), rowBytes);
1110    switch (r) {
1111        case SkCodec::kSuccess:
1112        case SkCodec::kErrorInInput:
1113        case SkCodec::kIncompleteInput:
1114            break;
1115        default:
1116            return SkStringPrintf("Couldn't getPixels %s. Error code %d", fPath.c_str(), r);
1117    }
1118
1119    switch (fMode) {
1120        case kBaseline_Mode:
1121        case kDst_sRGB_Mode:
1122        case kDst_HPZR30w_Mode:
1123            // We do not support drawing unclamped F16.
1124            clamp_if_necessary(bitmap, canvas->imageInfo().colorType());
1125            canvas->drawBitmap(bitmap, 0, 0);
1126            break;
1127        default:
1128            SkASSERT(false);
1129            return "Invalid fMode";
1130    }
1131    return "";
1132}
1133
1134SkISize ColorCodecSrc::size() const {
1135    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
1136    std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
1137    if (nullptr == codec) {
1138        return {0, 0};
1139    }
1140    return {codec->getInfo().width(), codec->getInfo().height()};
1141}
1142
1143Name ColorCodecSrc::name() const {
1144    return SkOSPath::Basename(fPath.c_str());
1145}
1146
1147/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1148
1149static const SkRect kSKPViewport = {0, 0, 1000, 1000};
1150
1151SKPSrc::SKPSrc(Path path) : fPath(path) { }
1152
1153static sk_sp<SkPicture> read_skp(const char* path) {
1154    std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(path);
1155    if (!stream) {
1156        return nullptr;
1157    }
1158    sk_sp<SkPicture> pic(SkPicture::MakeFromStream(stream.get()));
1159    if (!pic) {
1160        return nullptr;
1161    }
1162    stream = nullptr;  // Might as well drop this when we're done with it.
1163
1164    return pic;
1165}
1166
1167Error SKPSrc::draw(SkCanvas* canvas) const {
1168    sk_sp<SkPicture> pic = read_skp(fPath.c_str());
1169    if (!pic) {
1170        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
1171    }
1172
1173    canvas->clipRect(kSKPViewport);
1174    canvas->drawPicture(pic);
1175    return "";
1176}
1177
1178static SkRect get_cull_rect_for_skp(const char* path) {
1179    std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(path);
1180    if (!stream) {
1181        return SkRect::MakeEmpty();
1182    }
1183    SkPictInfo info;
1184    if (!SkPicture_StreamIsSKP(stream.get(), &info)) {
1185        return SkRect::MakeEmpty();
1186    }
1187
1188    return info.fCullRect;
1189}
1190
1191SkISize SKPSrc::size() const {
1192    SkRect viewport = get_cull_rect_for_skp(fPath.c_str());
1193    if (!viewport.intersect(kSKPViewport)) {
1194        return {0, 0};
1195    }
1196    return viewport.roundOut().size();
1197}
1198
1199Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
1200
1201/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1202
1203static const int kNumDDLXTiles = 4;
1204static const int kNumDDLYTiles = 4;
1205static const int kDDLTileSize = 1024;
1206static const SkRect kDDLSKPViewport = { 0, 0,
1207                                        kNumDDLXTiles * kDDLTileSize,
1208                                        kNumDDLYTiles * kDDLTileSize };
1209
1210DDLSKPSrc::DDLSKPSrc(Path path) : fPath(path) { }
1211
1212Error DDLSKPSrc::draw(SkCanvas* canvas) const {
1213    class TileData {
1214    public:
1215        // Note: we could just pass in surface characterization
1216        TileData(sk_sp<SkSurface> surf, const SkIRect& clip)
1217                : fSurface(std::move(surf))
1218                , fClip(clip) {
1219            SkAssertResult(fSurface->characterize(&fCharacterization));
1220        }
1221
1222        // This method operates in parallel
1223        void preprocess(SkPicture* pic) {
1224            SkDeferredDisplayListRecorder recorder(fCharacterization);
1225
1226            SkCanvas* subCanvas = recorder.getCanvas();
1227
1228            subCanvas->clipRect(SkRect::MakeWH(fClip.width(), fClip.height()));
1229            subCanvas->translate(-fClip.fLeft, -fClip.fTop);
1230
1231            // Note: in this use case we only render a picture to the deferred canvas
1232            // but, more generally, clients will use arbitrary draw calls.
1233            subCanvas->drawPicture(pic);
1234
1235            fDisplayList = recorder.detach();
1236        }
1237
1238        // This method operates serially
1239        void draw() {
1240            fSurface->draw(fDisplayList.get());
1241        }
1242
1243        // This method also operates serially
1244        void compose(SkCanvas* dst) {
1245            sk_sp<SkImage> img = fSurface->makeImageSnapshot();
1246            dst->save();
1247            dst->clipRect(SkRect::Make(fClip));
1248            dst->drawImage(std::move(img), fClip.fLeft, fClip.fTop);
1249            dst->restore();
1250        }
1251
1252    private:
1253        sk_sp<SkSurface> fSurface;
1254        SkIRect          fClip;    // in the device space of the destination canvas
1255        std::unique_ptr<SkDeferredDisplayList> fDisplayList;
1256        SkSurfaceCharacterization              fCharacterization;
1257    };
1258
1259    SkTArray<TileData> tileData;
1260    tileData.reserve(16);
1261
1262    sk_sp<SkPicture> pic = read_skp(fPath.c_str());
1263    if (!pic) {
1264        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
1265    }
1266
1267    const SkRect cullRect = pic->cullRect();
1268
1269    // All the destination tiles are the same size
1270    const SkImageInfo tileII = SkImageInfo::MakeN32Premul(kDDLTileSize, kDDLTileSize);
1271
1272    // First, create the destination tiles
1273    for (int y = 0; y < kNumDDLYTiles; ++y) {
1274        for (int x = 0; x < kNumDDLXTiles; ++x) {
1275            SkRect clip = SkRect::MakeXYWH(x * kDDLTileSize, y * kDDLTileSize,
1276                                           kDDLTileSize, kDDLTileSize);
1277
1278            if (!clip.intersect(cullRect)) {
1279                continue;
1280            }
1281
1282            tileData.push_back(TileData(canvas->makeSurface(tileII), clip.roundOut()));
1283        }
1284    }
1285
1286    // Second, run the cpu pre-processing in threads
1287    SkTaskGroup().batch(tileData.count(), [&](int i) {
1288        tileData[i].preprocess(pic.get());
1289    });
1290
1291    // Third, synchronously render the display lists into the dest tiles
1292    // TODO: it would be cool to not wait until all the tiles are drawn to begin
1293    // drawing to the GPU
1294    for (int i = 0; i < tileData.count(); ++i) {
1295        tileData[i].draw();
1296    }
1297
1298    // Finally, compose the drawn tiles into the result
1299    // Note: the separation between the tiles and the final composition better
1300    // matches Chrome but costs us a copy
1301    for (int i = 0; i < tileData.count(); ++i) {
1302        tileData[i].compose(canvas);
1303    }
1304
1305    return "";
1306}
1307
1308SkISize DDLSKPSrc::size() const {
1309    SkRect viewport = get_cull_rect_for_skp(fPath.c_str());
1310    if (!viewport.intersect(kDDLSKPViewport)) {
1311        return {0, 0};
1312    }
1313    return viewport.roundOut().size();
1314}
1315
1316Name DDLSKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
1317
1318/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1319
1320#if !defined(SK_BUILD_FOR_GOOGLE3)
1321SkottieSrc::SkottieSrc(Path path)
1322    : fName(SkOSPath::Basename(path.c_str())) {
1323
1324    fAnimation  = skottie::Animation::MakeFromFile(path.c_str());
1325    if (!fAnimation) {
1326        return;
1327    }
1328
1329    // Fit kTileCount x kTileCount frames to a 1000x1000 film strip.
1330    static constexpr SkScalar kTargetSize = 1000;
1331    const auto scale = kTargetSize / (kTileCount * std::max(fAnimation->size().width(),
1332                                                            fAnimation->size().height()));
1333    fTileSize = SkSize::Make(scale * fAnimation->size().width(),
1334                             scale * fAnimation->size().height()).toCeil();
1335
1336}
1337
1338Error SkottieSrc::draw(SkCanvas* canvas) const {
1339    if (!fAnimation) {
1340        return SkStringPrintf("Unable to parse file: %s", fName.c_str());
1341    }
1342
1343    canvas->drawColor(SK_ColorWHITE);
1344
1345    SkPaint paint, clockPaint;
1346    paint.setColor(0xffa0a0a0);
1347    paint.setStyle(SkPaint::kStroke_Style);
1348    paint.setStrokeWidth(1);
1349    paint.setAntiAlias(true);
1350
1351    clockPaint.setTextSize(12);
1352    clockPaint.setAntiAlias(true);
1353
1354    const auto ip = fAnimation->inPoint() * 1000 / fAnimation->frameRate(),
1355               op = fAnimation->outPoint() * 1000 / fAnimation->frameRate(),
1356               fr = (op - ip) / (kTileCount * kTileCount - 1);
1357
1358    // Shuffled order to exercise non-linear frame progression.
1359    static constexpr int frames[] = { 4, 0, 3, 1, 2 };
1360    static_assert(SK_ARRAY_COUNT(frames) == kTileCount, "");
1361
1362    const auto canvas_size = this->size();
1363    for (int i = 0; i < kTileCount; ++i) {
1364        const SkScalar y = frames[i] * (fTileSize.height() + 1);
1365
1366        for (int j = 0; j < kTileCount; ++j) {
1367            const SkScalar x = frames[j] * (fTileSize.width() + 1);
1368            SkRect dest = SkRect::MakeXYWH(x, y, fTileSize.width(), fTileSize.height());
1369
1370            const auto t = fr * (frames[i] * kTileCount + frames[j]);
1371            {
1372                SkAutoCanvasRestore acr(canvas, true);
1373                canvas->clipRect(dest, true);
1374                canvas->concat(SkMatrix::MakeRectToRect(SkRect::MakeSize(fAnimation->size()),
1375                                                        dest,
1376                                                        SkMatrix::kFill_ScaleToFit));
1377
1378                fAnimation->animationTick(t);
1379                fAnimation->render(canvas);
1380            }
1381
1382            canvas->drawLine(x + fTileSize.width() + .5f, 0,
1383                             x + fTileSize.width() + .5f, canvas_size.height(), paint);
1384            const auto label = SkStringPrintf("%.3f", t);
1385            canvas->drawText(label.c_str(), label.size(), dest.x(),
1386                             dest.bottom(), clockPaint);
1387        }
1388
1389        canvas->drawLine(0                  , y + fTileSize.height() + .5f,
1390                         canvas_size.width(), y + fTileSize.height() + .5f, paint);
1391    }
1392
1393    return "";
1394}
1395
1396SkISize SkottieSrc::size() const {
1397    // Padding for grid.
1398    return SkISize::Make(kTileCount * (fTileSize.width()  + 1),
1399                         kTileCount * (fTileSize.height() + 1));
1400}
1401
1402Name SkottieSrc::name() const { return fName; }
1403
1404bool SkottieSrc::veto(SinkFlags flags) const {
1405    // No need to test to non-(raster||gpu||vector) or indirect backends.
1406    bool type_ok = flags.type == SinkFlags::kRaster
1407                || flags.type == SinkFlags::kGPU
1408                || flags.type == SinkFlags::kVector;
1409
1410    return !type_ok || flags.approach != SinkFlags::kDirect;
1411}
1412#endif
1413
1414/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1415#if defined(SK_XML)
1416// Used when the image doesn't have an intrinsic size.
1417static const SkSize kDefaultSVGSize = {1000, 1000};
1418
1419// Used to force-scale tiny fixed-size images.
1420static const SkSize kMinimumSVGSize = {128, 128};
1421
1422SVGSrc::SVGSrc(Path path)
1423    : fName(SkOSPath::Basename(path.c_str()))
1424    , fScale(1) {
1425
1426  SkFILEStream stream(path.c_str());
1427  if (!stream.isValid()) {
1428      return;
1429  }
1430  fDom = SkSVGDOM::MakeFromStream(stream);
1431  if (!fDom) {
1432      return;
1433  }
1434
1435  const SkSize& sz = fDom->containerSize();
1436  if (sz.isEmpty()) {
1437      // no intrinsic size
1438      fDom->setContainerSize(kDefaultSVGSize);
1439  } else {
1440      fScale = SkTMax(1.f, SkTMax(kMinimumSVGSize.width()  / sz.width(),
1441                                  kMinimumSVGSize.height() / sz.height()));
1442  }
1443}
1444
1445Error SVGSrc::draw(SkCanvas* canvas) const {
1446    if (!fDom) {
1447        return SkStringPrintf("Unable to parse file: %s", fName.c_str());
1448    }
1449
1450    SkAutoCanvasRestore acr(canvas, true);
1451    canvas->scale(fScale, fScale);
1452    fDom->render(canvas);
1453
1454    return "";
1455}
1456
1457SkISize SVGSrc::size() const {
1458    if (!fDom) {
1459        return {0, 0};
1460    }
1461
1462    return SkSize{fDom->containerSize().width() * fScale, fDom->containerSize().height() * fScale}
1463            .toRound();
1464}
1465
1466Name SVGSrc::name() const { return fName; }
1467
1468bool SVGSrc::veto(SinkFlags flags) const {
1469    // No need to test to non-(raster||gpu||vector) or indirect backends.
1470    bool type_ok = flags.type == SinkFlags::kRaster
1471                || flags.type == SinkFlags::kGPU
1472                || flags.type == SinkFlags::kVector;
1473
1474    return !type_ok || flags.approach != SinkFlags::kDirect;
1475}
1476
1477#endif // defined(SK_XML)
1478/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1479
1480MSKPSrc::MSKPSrc(Path path) : fPath(path) {
1481    std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(fPath.c_str());
1482    int count = SkMultiPictureDocumentReadPageCount(stream.get());
1483    if (count > 0) {
1484        fPages.reset(count);
1485        (void)SkMultiPictureDocumentReadPageSizes(stream.get(), &fPages[0], fPages.count());
1486    }
1487}
1488
1489int MSKPSrc::pageCount() const { return fPages.count(); }
1490
1491SkISize MSKPSrc::size() const { return this->size(0); }
1492SkISize MSKPSrc::size(int i) const {
1493    return i >= 0 && i < fPages.count() ? fPages[i].fSize.toCeil() : SkISize{0, 0};
1494}
1495
1496Error MSKPSrc::draw(SkCanvas* c) const { return this->draw(0, c); }
1497Error MSKPSrc::draw(int i, SkCanvas* canvas) const {
1498    if (this->pageCount() == 0) {
1499        return SkStringPrintf("Unable to parse MultiPictureDocument file: %s", fPath.c_str());
1500    }
1501    if (i >= fPages.count() || i < 0) {
1502        return SkStringPrintf("MultiPictureDocument page number out of range: %d", i);
1503    }
1504    SkPicture* page = fPages[i].fPicture.get();
1505    if (!page) {
1506        std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(fPath.c_str());
1507        if (!stream) {
1508            return SkStringPrintf("Unable to open file: %s", fPath.c_str());
1509        }
1510        if (!SkMultiPictureDocumentRead(stream.get(), &fPages[0], fPages.count())) {
1511            return SkStringPrintf("SkMultiPictureDocument reader failed on page %d: %s", i,
1512                                  fPath.c_str());
1513        }
1514        page = fPages[i].fPicture.get();
1515    }
1516    canvas->drawPicture(page);
1517    return "";
1518}
1519
1520Name MSKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
1521
1522/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1523
1524Error NullSink::draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const {
1525    return src.draw(SkMakeNullCanvas().get());
1526}
1527
1528/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1529
1530static bool encode_png_base64(const SkBitmap& bitmap, SkString* dst) {
1531    SkPixmap pm;
1532    if (!bitmap.peekPixels(&pm)) {
1533        dst->set("peekPixels failed");
1534        return false;
1535    }
1536
1537    // We're going to embed this PNG in a data URI, so make it as small as possible
1538    SkPngEncoder::Options options;
1539    options.fFilterFlags = SkPngEncoder::FilterFlag::kAll;
1540    options.fZLibLevel = 9;
1541    options.fUnpremulBehavior = pm.colorSpace() ? SkTransferFunctionBehavior::kRespect
1542                                                : SkTransferFunctionBehavior::kIgnore;
1543
1544    SkDynamicMemoryWStream wStream;
1545    if (!SkPngEncoder::Encode(&wStream, pm, options)) {
1546        dst->set("SkPngEncoder::Encode failed");
1547        return false;
1548    }
1549
1550    sk_sp<SkData> pngData = wStream.detachAsData();
1551    size_t len = SkBase64::Encode(pngData->data(), pngData->size(), nullptr);
1552
1553    // The PNG can be almost arbitrarily large. We don't want to fill our logs with enormous URLs.
1554    // Infra says these can be pretty big, as long as we're only outputting them on failure.
1555    static const size_t kMaxBase64Length = 1024 * 1024;
1556    if (len > kMaxBase64Length) {
1557        dst->printf("Encoded image too large (%u bytes)", static_cast<uint32_t>(len));
1558        return false;
1559    }
1560
1561    dst->resize(len);
1562    SkBase64::Encode(pngData->data(), pngData->size(), dst->writable_str());
1563    return true;
1564}
1565
1566static Error compare_bitmaps(const SkBitmap& reference, const SkBitmap& bitmap) {
1567    // The dimensions are a property of the Src only, and so should be identical.
1568    SkASSERT(reference.computeByteSize() == bitmap.computeByteSize());
1569    if (reference.computeByteSize() != bitmap.computeByteSize()) {
1570        return "Dimensions don't match reference";
1571    }
1572    // All SkBitmaps in DM are tight, so this comparison is easy.
1573    if (0 != memcmp(reference.getPixels(), bitmap.getPixels(), reference.computeByteSize())) {
1574        SkString encoded;
1575        SkString errString("Pixels don't match reference");
1576        if (encode_png_base64(reference, &encoded)) {
1577            errString.append("\nExpected: data:image/png;base64,");
1578            errString.append(encoded);
1579        } else {
1580            errString.append("\nExpected image failed to encode: ");
1581            errString.append(encoded);
1582        }
1583        if (encode_png_base64(bitmap, &encoded)) {
1584            errString.append("\nActual: data:image/png;base64,");
1585            errString.append(encoded);
1586        } else {
1587            errString.append("\nActual image failed to encode: ");
1588            errString.append(encoded);
1589        }
1590        return errString;
1591    }
1592    return "";
1593}
1594
1595/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1596
1597DEFINE_bool(gpuStats, false, "Append GPU stats to the log for each GPU task?");
1598
1599GPUSink::GPUSink(GrContextFactory::ContextType ct,
1600                 GrContextFactory::ContextOverrides overrides,
1601                 int samples,
1602                 bool diText,
1603                 SkColorType colorType,
1604                 SkAlphaType alphaType,
1605                 sk_sp<SkColorSpace> colorSpace,
1606                 bool threaded,
1607                 const GrContextOptions& grCtxOptions)
1608        : fContextType(ct)
1609        , fContextOverrides(overrides)
1610        , fSampleCount(samples)
1611        , fUseDIText(diText)
1612        , fColorType(colorType)
1613        , fAlphaType(alphaType)
1614        , fColorSpace(std::move(colorSpace))
1615        , fThreaded(threaded)
1616        , fBaseContextOptions(grCtxOptions) {}
1617
1618DEFINE_bool(drawOpClip, false, "Clip each GrDrawOp to its device bounds for testing.");
1619
1620Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream* dstStream, SkString* log) const {
1621    return this->onDraw(src, dst, dstStream, log, fBaseContextOptions);
1622}
1623
1624Error GPUSink::onDraw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log,
1625                      const GrContextOptions& baseOptions) const {
1626    GrContextOptions grOptions = baseOptions;
1627
1628    src.modifyGrContextOptions(&grOptions);
1629
1630    GrContextFactory factory(grOptions);
1631    const SkISize size = src.size();
1632    SkImageInfo info =
1633            SkImageInfo::Make(size.width(), size.height(), fColorType, fAlphaType, fColorSpace);
1634#if SK_SUPPORT_GPU
1635    GrContext* context = factory.getContextInfo(fContextType, fContextOverrides).grContext();
1636    const int maxDimension = context->caps()->maxTextureSize();
1637    if (maxDimension < SkTMax(size.width(), size.height())) {
1638        return Error::Nonfatal("Src too large to create a texture.\n");
1639    }
1640#endif
1641
1642    auto surface(
1643        NewGpuSurface(&factory, fContextType, fContextOverrides, info, fSampleCount, fUseDIText));
1644    if (!surface) {
1645        return "Could not create a surface.";
1646    }
1647    if (FLAGS_preAbandonGpuContext) {
1648        factory.abandonContexts();
1649    }
1650    SkCanvas* canvas = surface->getCanvas();
1651    Error err = src.draw(canvas);
1652    if (!err.isEmpty()) {
1653        return err;
1654    }
1655    canvas->flush();
1656    if (FLAGS_gpuStats) {
1657        canvas->getGrContext()->dumpCacheStats(log);
1658        canvas->getGrContext()->dumpGpuStats(log);
1659    }
1660    if (info.colorType() == kRGB_565_SkColorType || info.colorType() == kARGB_4444_SkColorType) {
1661        // We don't currently support readbacks into these formats on the GPU backend. Convert to
1662        // 32 bit.
1663        info = SkImageInfo::Make(size.width(), size.height(), kRGBA_8888_SkColorType,
1664                                 kPremul_SkAlphaType, fColorSpace);
1665    }
1666    dst->allocPixels(info);
1667    canvas->readPixels(*dst, 0, 0);
1668    if (FLAGS_abandonGpuContext) {
1669        factory.abandonContexts();
1670    } else if (FLAGS_releaseAndAbandonGpuContext) {
1671        factory.releaseResourcesAndAbandonContexts();
1672    }
1673    return "";
1674}
1675
1676/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1677
1678GPUThreadTestingSink::GPUThreadTestingSink(GrContextFactory::ContextType ct,
1679                                           GrContextFactory::ContextOverrides overrides,
1680                                           int samples,
1681                                           bool diText,
1682                                           SkColorType colorType,
1683                                           SkAlphaType alphaType,
1684                                           sk_sp<SkColorSpace> colorSpace,
1685                                           bool threaded,
1686                                           const GrContextOptions& grCtxOptions)
1687        : INHERITED(ct, overrides, samples, diText, colorType, alphaType, std::move(colorSpace),
1688                    threaded, grCtxOptions)
1689#if SK_SUPPORT_GPU
1690        , fExecutor(SkExecutor::MakeFIFOThreadPool(FLAGS_gpuThreads)) {
1691#else
1692        , fExecutor(nullptr) {
1693#endif
1694    SkASSERT(fExecutor);
1695}
1696
1697Error GPUThreadTestingSink::draw(const Src& src, SkBitmap* dst, SkWStream* wStream,
1698                                 SkString* log) const {
1699    // Draw twice, once with worker threads, and once without. Verify that we get the same result.
1700    // Also, force us to only use the software path renderer, so we really stress-test the threaded
1701    // version of that code.
1702    GrContextOptions contextOptions = this->baseContextOptions();
1703    contextOptions.fGpuPathRenderers = GpuPathRenderers::kNone;
1704
1705    contextOptions.fExecutor = fExecutor.get();
1706    Error err = this->onDraw(src, dst, wStream, log, contextOptions);
1707    if (!err.isEmpty() || !dst) {
1708        return err;
1709    }
1710
1711    SkBitmap reference;
1712    SkString refLog;
1713    SkDynamicMemoryWStream refStream;
1714    contextOptions.fExecutor = nullptr;
1715    Error refErr = this->onDraw(src, &reference, &refStream, &refLog, contextOptions);
1716    if (!refErr.isEmpty()) {
1717        return refErr;
1718    }
1719
1720    return compare_bitmaps(reference, *dst);
1721}
1722
1723/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1724
1725static Error draw_skdocument(const Src& src, SkDocument* doc, SkWStream* dst) {
1726    if (src.size().isEmpty()) {
1727        return "Source has empty dimensions";
1728    }
1729    SkASSERT(doc);
1730    int pageCount = src.pageCount();
1731    for (int i = 0; i < pageCount; ++i) {
1732        int width = src.size(i).width(), height = src.size(i).height();
1733        SkCanvas* canvas =
1734                doc->beginPage(SkIntToScalar(width), SkIntToScalar(height));
1735        if (!canvas) {
1736            return "SkDocument::beginPage(w,h) returned nullptr";
1737        }
1738        Error err = src.draw(i, canvas);
1739        if (!err.isEmpty()) {
1740            return err;
1741        }
1742        doc->endPage();
1743    }
1744    doc->close();
1745    dst->flush();
1746    return "";
1747}
1748
1749Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
1750    SkDocument::PDFMetadata metadata;
1751    metadata.fTitle = src.name();
1752    metadata.fSubject = "rendering correctness test";
1753    metadata.fCreator = "Skia/DM";
1754    metadata.fRasterDPI = fRasterDpi;
1755    metadata.fPDFA = fPDFA;
1756    sk_sp<SkDocument> doc = SkDocument::MakePDF(dst, metadata);
1757    if (!doc) {
1758        return "SkDocument::MakePDF() returned nullptr";
1759    }
1760    return draw_skdocument(src, doc.get(), dst);
1761}
1762
1763/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1764
1765XPSSink::XPSSink() {}
1766
1767#ifdef SK_BUILD_FOR_WIN
1768static SkTScopedComPtr<IXpsOMObjectFactory> make_xps_factory() {
1769    IXpsOMObjectFactory* factory;
1770    HRN(CoCreateInstance(CLSID_XpsOMObjectFactory,
1771                         nullptr,
1772                         CLSCTX_INPROC_SERVER,
1773                         IID_PPV_ARGS(&factory)));
1774    return SkTScopedComPtr<IXpsOMObjectFactory>(factory);
1775}
1776
1777Error XPSSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
1778    SkAutoCoInitialize com;
1779    if (!com.succeeded()) {
1780        return "Could not initialize COM.";
1781    }
1782    SkTScopedComPtr<IXpsOMObjectFactory> factory = make_xps_factory();
1783    if (!factory) {
1784        return "Failed to create XPS Factory.";
1785    }
1786    sk_sp<SkDocument> doc(SkDocument::MakeXPS(dst, factory.get()));
1787    if (!doc) {
1788        return "SkDocument::MakeXPS() returned nullptr";
1789    }
1790    return draw_skdocument(src, doc.get(), dst);
1791}
1792#else
1793Error XPSSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
1794    return "XPS not supported on this platform.";
1795}
1796#endif
1797
1798/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1799
1800PipeSink::PipeSink() {}
1801
1802Error PipeSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
1803    return src.draw(SkPipeSerializer().beginWrite(SkRect::Make(src.size()), dst));
1804}
1805
1806/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1807
1808SKPSink::SKPSink() {}
1809
1810Error SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
1811    SkSize size;
1812    size = src.size();
1813    SkPictureRecorder recorder;
1814    Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
1815    if (!err.isEmpty()) {
1816        return err;
1817    }
1818    recorder.finishRecordingAsPicture()->serialize(dst);
1819    return "";
1820}
1821
1822/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1823
1824Error DebugSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
1825    SkDebugCanvas debugCanvas(src.size().width(), src.size().height());
1826    Error err = src.draw(&debugCanvas);
1827    if (!err.isEmpty()) {
1828        return err;
1829    }
1830    std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
1831    UrlDataManager dataManager(SkString("data"));
1832    Json::Value json = debugCanvas.toJSON(
1833            dataManager, debugCanvas.getSize(), nullCanvas.get());
1834    std::string value = Json::StyledWriter().write(json);
1835    return dst->write(value.c_str(), value.size()) ? "" : "SkWStream Error";
1836}
1837
1838/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1839
1840SVGSink::SVGSink() {}
1841
1842Error SVGSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
1843#if defined(SK_XML)
1844    std::unique_ptr<SkXMLWriter> xmlWriter(new SkXMLStreamWriter(dst));
1845    return src.draw(SkSVGCanvas::Make(SkRect::MakeWH(SkIntToScalar(src.size().width()),
1846                                                     SkIntToScalar(src.size().height())),
1847                                      xmlWriter.get()).get());
1848#else
1849    return Error("SVG sink is disabled.");
1850#endif // SK_XML
1851}
1852
1853/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1854
1855RasterSink::RasterSink(SkColorType colorType, sk_sp<SkColorSpace> colorSpace)
1856    : fColorType(colorType)
1857    , fColorSpace(std::move(colorSpace)) {}
1858
1859Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const {
1860    const SkISize size = src.size();
1861    // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
1862    SkAlphaType alphaType = kPremul_SkAlphaType;
1863    (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
1864
1865    dst->allocPixelsFlags(SkImageInfo::Make(size.width(), size.height(),
1866                                            fColorType, alphaType, fColorSpace),
1867                          SkBitmap::kZeroPixels_AllocFlag);
1868    SkCanvas canvas(*dst);
1869    return src.draw(&canvas);
1870}
1871
1872/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1873
1874// Handy for front-patching a Src.  Do whatever up-front work you need, then call draw_to_canvas(),
1875// passing the Sink draw() arguments, a size, and a function draws into an SkCanvas.
1876// Several examples below.
1877
1878template <typename Fn>
1879static Error draw_to_canvas(Sink* sink, SkBitmap* bitmap, SkWStream* stream, SkString* log,
1880                            SkISize size, const Fn& draw) {
1881    class ProxySrc : public Src {
1882    public:
1883        ProxySrc(SkISize size, const Fn& draw) : fSize(size), fDraw(draw) {}
1884        Error   draw(SkCanvas* canvas) const override { return fDraw(canvas); }
1885        Name    name() const override { return "ProxySrc"; }
1886        SkISize size() const override { return fSize; }
1887    private:
1888        SkISize   fSize;
1889        const Fn& fDraw;
1890    };
1891    return sink->draw(ProxySrc(size, draw), bitmap, stream, log);
1892}
1893
1894/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1895
1896DEFINE_bool(check, true, "If true, have most Via- modes fail if they affect the output.");
1897
1898// Is *bitmap identical to what you get drawing src into sink?
1899static Error check_against_reference(const SkBitmap* bitmap, const Src& src, Sink* sink) {
1900    // We can only check raster outputs.
1901    // (Non-raster outputs like .pdf, .skp, .svg may differ but still draw identically.)
1902    if (FLAGS_check && bitmap) {
1903        SkBitmap reference;
1904        SkString log;
1905        SkDynamicMemoryWStream wStream;
1906        Error err = sink->draw(src, &reference, &wStream, &log);
1907        // If we can draw into this Sink via some pipeline, we should be able to draw directly.
1908        SkASSERT(err.isEmpty());
1909        if (!err.isEmpty()) {
1910            return err;
1911        }
1912        return compare_bitmaps(reference, *bitmap);
1913    }
1914    return "";
1915}
1916
1917/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1918
1919static SkISize auto_compute_translate(SkMatrix* matrix, int srcW, int srcH) {
1920    SkRect bounds = SkRect::MakeIWH(srcW, srcH);
1921    matrix->mapRect(&bounds);
1922    matrix->postTranslate(-bounds.x(), -bounds.y());
1923    return {SkScalarRoundToInt(bounds.width()), SkScalarRoundToInt(bounds.height())};
1924}
1925
1926ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
1927
1928Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1929    SkMatrix matrix = fMatrix;
1930    SkISize size = auto_compute_translate(&matrix, src.size().width(), src.size().height());
1931    return draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) {
1932        canvas->concat(matrix);
1933        return src.draw(canvas);
1934    });
1935}
1936
1937// Undoes any flip or 90 degree rotate without changing the scale of the bitmap.
1938// This should be pixel-preserving.
1939ViaUpright::ViaUpright(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
1940
1941Error ViaUpright::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1942    Error err = fSink->draw(src, bitmap, stream, log);
1943    if (!err.isEmpty()) {
1944        return err;
1945    }
1946
1947    SkMatrix inverse;
1948    if (!fMatrix.rectStaysRect() || !fMatrix.invert(&inverse)) {
1949        return "Cannot upright --matrix.";
1950    }
1951    SkMatrix upright = SkMatrix::I();
1952    upright.setScaleX(SkScalarSignAsScalar(inverse.getScaleX()));
1953    upright.setScaleY(SkScalarSignAsScalar(inverse.getScaleY()));
1954    upright.setSkewX(SkScalarSignAsScalar(inverse.getSkewX()));
1955    upright.setSkewY(SkScalarSignAsScalar(inverse.getSkewY()));
1956
1957    SkBitmap uprighted;
1958    SkISize size = auto_compute_translate(&upright, bitmap->width(), bitmap->height());
1959    uprighted.allocPixels(bitmap->info().makeWH(size.width(), size.height()));
1960
1961    SkCanvas canvas(uprighted);
1962    canvas.concat(upright);
1963    SkPaint paint;
1964    paint.setBlendMode(SkBlendMode::kSrc);
1965    canvas.drawBitmap(*bitmap, 0, 0, &paint);
1966
1967    *bitmap = uprighted;
1968    return "";
1969}
1970
1971/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1972
1973Error ViaSerialization::draw(
1974        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1975    // Record our Src into a picture.
1976    auto size = src.size();
1977    SkPictureRecorder recorder;
1978    Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
1979                                                 SkIntToScalar(size.height())));
1980    if (!err.isEmpty()) {
1981        return err;
1982    }
1983    sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
1984
1985    // Serialize it and then deserialize it.
1986    sk_sp<SkPicture> deserialized(SkPicture::MakeFromData(pic->serialize().get()));
1987
1988    return draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) {
1989        canvas->drawPicture(deserialized);
1990        return check_against_reference(bitmap, src, fSink.get());
1991    });
1992}
1993
1994/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1995
1996ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
1997    : Via(sink)
1998    , fW(w)
1999    , fH(h)
2000    , fFactory(factory) {}
2001
2002Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
2003    auto size = src.size();
2004    SkPictureRecorder recorder;
2005    Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
2006                                                 SkIntToScalar(size.height()),
2007                                                 fFactory.get()));
2008    if (!err.isEmpty()) {
2009        return err;
2010    }
2011    sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
2012
2013    return draw_to_canvas(fSink.get(), bitmap, stream, log, src.size(), [&](SkCanvas* canvas) {
2014        const int xTiles = (size.width()  + fW - 1) / fW,
2015                  yTiles = (size.height() + fH - 1) / fH;
2016        SkMultiPictureDraw mpd(xTiles*yTiles);
2017        SkTArray<sk_sp<SkSurface>> surfaces;
2018//        surfaces.setReserve(xTiles*yTiles);
2019
2020        SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
2021        for (int j = 0; j < yTiles; j++) {
2022            for (int i = 0; i < xTiles; i++) {
2023                // This lets our ultimate Sink determine the best kind of surface.
2024                // E.g., if it's a GpuSink, the surfaces and images are textures.
2025                auto s = canvas->makeSurface(info);
2026                if (!s) {
2027                    s = SkSurface::MakeRaster(info);  // Some canvases can't create surfaces.
2028                }
2029                surfaces.push_back(s);
2030                SkCanvas* c = s->getCanvas();
2031                c->translate(SkIntToScalar(-i * fW),
2032                             SkIntToScalar(-j * fH));  // Line up the canvas with this tile.
2033                mpd.add(c, pic.get());
2034            }
2035        }
2036        mpd.draw();
2037        for (int j = 0; j < yTiles; j++) {
2038            for (int i = 0; i < xTiles; i++) {
2039                sk_sp<SkImage> image(surfaces[i+xTiles*j]->makeImageSnapshot());
2040                canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
2041            }
2042        }
2043        return "";
2044    });
2045}
2046
2047/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2048
2049Error ViaPicture::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
2050    auto size = src.size();
2051    return draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
2052        SkPictureRecorder recorder;
2053        sk_sp<SkPicture> pic;
2054        Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
2055                                                     SkIntToScalar(size.height())));
2056        if (!err.isEmpty()) {
2057            return err;
2058        }
2059        pic = recorder.finishRecordingAsPicture();
2060        canvas->drawPicture(pic);
2061        return check_against_reference(bitmap, src, fSink.get());
2062    });
2063}
2064
2065/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2066
2067Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
2068    auto size = src.size();
2069    return draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
2070        SkDynamicMemoryWStream tmpStream;
2071        Error err = src.draw(SkPipeSerializer().beginWrite(SkRect::Make(size), &tmpStream));
2072        if (!err.isEmpty()) {
2073            return err;
2074        }
2075        sk_sp<SkData> data = tmpStream.detachAsData();
2076        SkPipeDeserializer().playback(data->data(), data->size(), canvas);
2077        return check_against_reference(bitmap, src, fSink.get());
2078    });
2079}
2080
2081/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2082
2083#ifdef TEST_VIA_SVG
2084#include "SkXMLWriter.h"
2085#include "SkSVGCanvas.h"
2086#include "SkSVGDOM.h"
2087
2088Error ViaSVG::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
2089    auto size = src.size();
2090    return draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
2091        SkDynamicMemoryWStream wstream;
2092        SkXMLStreamWriter writer(&wstream);
2093        Error err = src.draw(SkSVGCanvas::Make(SkRect::Make(size), &writer).get());
2094        if (!err.isEmpty()) {
2095            return err;
2096        }
2097        std::unique_ptr<SkStream> rstream(wstream.detachAsStream());
2098        auto dom = SkSVGDOM::MakeFromStream(*rstream);
2099        if (dom) {
2100            dom->setContainerSize(SkSize::Make(size));
2101            dom->render(canvas);
2102        }
2103        return "";
2104    });
2105}
2106#endif
2107
2108/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2109
2110Error ViaLite::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
2111    auto size = src.size();
2112    SkIRect bounds = {0,0, size.width(), size.height()};
2113    return draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
2114        SkLiteDL dl;
2115        SkLiteRecorder rec;
2116        rec.reset(&dl, bounds);
2117
2118        Error err = src.draw(&rec);
2119        if (!err.isEmpty()) {
2120            return err;
2121        }
2122        dl.draw(canvas);
2123        return check_against_reference(bitmap, src, fSink.get());
2124    });
2125}
2126
2127/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2128
2129ViaCSXform::ViaCSXform(Sink* sink, sk_sp<SkColorSpace> cs, bool colorSpin)
2130    : Via(sink)
2131    , fCS(std::move(cs))
2132    , fColorSpin(colorSpin) {}
2133
2134Error ViaCSXform::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
2135    return draw_to_canvas(fSink.get(), bitmap, stream, log, src.size(),
2136                          [&](SkCanvas* canvas) -> Error {
2137        {
2138            SkAutoCanvasRestore acr(canvas, true);
2139            auto proxy = SkCreateColorSpaceXformCanvas(canvas, fCS);
2140            Error err = src.draw(proxy.get());
2141            if (!err.isEmpty()) {
2142                return err;
2143            }
2144        }
2145
2146        // Undo the color spin, so we can look at the pixels in Gold.
2147        if (fColorSpin) {
2148            SkBitmap pixels;
2149            pixels.allocPixels(canvas->imageInfo());
2150            canvas->readPixels(pixels, 0, 0);
2151
2152            SkPaint rotateColors;
2153            SkScalar matrix[20] = { 0, 0, 1, 0, 0,   // B -> R
2154                                    1, 0, 0, 0, 0,   // R -> G
2155                                    0, 1, 0, 0, 0,   // G -> B
2156                                    0, 0, 0, 1, 0 };
2157            rotateColors.setBlendMode(SkBlendMode::kSrc);
2158            rotateColors.setColorFilter(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));
2159            canvas->drawBitmap(pixels, 0, 0, &rotateColors);
2160        }
2161
2162        return "";
2163    });
2164}
2165
2166}  // namespace DM
2167