DMSrcSink.cpp revision 45420a945cfce1b83da954ab5fcb63516f646c0f
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 "SkCodec.h"
12#include "SkCodecImageGenerator.h"
13#include "SkColorSpace.h"
14#include "SkColorSpace_Base.h"
15#include "SkColorSpaceXform.h"
16#include "SkCommonFlags.h"
17#include "SkData.h"
18#include "SkDocument.h"
19#include "SkError.h"
20#include "SkImageGenerator.h"
21#include "SkImageGeneratorCG.h"
22#include "SkImageGeneratorWIC.h"
23#include "SkMallocPixelRef.h"
24#include "SkMultiPictureDraw.h"
25#include "SkNullCanvas.h"
26#include "SkOSFile.h"
27#include "SkOpts.h"
28#include "SkPictureData.h"
29#include "SkPictureRecorder.h"
30#include "SkRandom.h"
31#include "SkRecordDraw.h"
32#include "SkRecorder.h"
33#include "SkSVGCanvas.h"
34#include "SkStream.h"
35#include "SkTLogic.h"
36#include "SkXMLWriter.h"
37#include "SkSwizzler.h"
38#include <functional>
39
40#if defined(SK_BUILD_FOR_WIN)
41    #include "SkAutoCoInitialize.h"
42#endif
43
44#if !defined(GOOGLE3)
45    #include "qcms.h"
46#endif
47
48DEFINE_bool(multiPage, false, "For document-type backends, render the source"
49            " into multiple pages");
50DEFINE_bool(RAW_threading, true, "Allow RAW decodes to run on multiple threads?");
51
52using sk_gpu_test::GrContextFactory;
53
54namespace DM {
55
56GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
57
58Error GMSrc::draw(SkCanvas* canvas) const {
59    SkAutoTDelete<skiagm::GM> gm(fFactory(nullptr));
60    canvas->concat(gm->getInitialTransform());
61    gm->draw(canvas);
62    return "";
63}
64
65SkISize GMSrc::size() const {
66    SkAutoTDelete<skiagm::GM> gm(fFactory(nullptr));
67    return gm->getISize();
68}
69
70Name GMSrc::name() const {
71    SkAutoTDelete<skiagm::GM> gm(fFactory(nullptr));
72    return gm->getName();
73}
74
75void GMSrc::modifyGrContextOptions(GrContextOptions* options) const {
76    SkAutoTDelete<skiagm::GM> gm(fFactory(nullptr));
77    gm->modifyGrContextOptions(options);
78}
79
80/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
81
82BRDSrc::BRDSrc(Path path, Mode mode, CodecSrc::DstColorType dstColorType, uint32_t sampleSize)
83    : fPath(path)
84    , fMode(mode)
85    , fDstColorType(dstColorType)
86    , fSampleSize(sampleSize)
87{}
88
89bool BRDSrc::veto(SinkFlags flags) const {
90    // No need to test to non-raster or indirect backends.
91    return flags.type != SinkFlags::kRaster
92        || flags.approach != SinkFlags::kDirect;
93}
94
95static SkBitmapRegionDecoder* create_brd(Path path) {
96    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
97    if (!encoded) {
98        return NULL;
99    }
100    return SkBitmapRegionDecoder::Create(encoded, SkBitmapRegionDecoder::kAndroidCodec_Strategy);
101}
102
103Error BRDSrc::draw(SkCanvas* canvas) const {
104    SkColorType colorType = canvas->imageInfo().colorType();
105    if (kRGB_565_SkColorType == colorType &&
106            CodecSrc::kGetFromCanvas_DstColorType != fDstColorType) {
107        return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
108    }
109    switch (fDstColorType) {
110        case CodecSrc::kGetFromCanvas_DstColorType:
111            break;
112        case CodecSrc::kIndex8_Always_DstColorType:
113            colorType = kIndex_8_SkColorType;
114            break;
115        case CodecSrc::kGrayscale_Always_DstColorType:
116            colorType = kGray_8_SkColorType;
117            break;
118        default:
119            SkASSERT(false);
120            break;
121    }
122
123    SkAutoTDelete<SkBitmapRegionDecoder> brd(create_brd(fPath));
124    if (nullptr == brd.get()) {
125        return Error::Nonfatal(SkStringPrintf("Could not create brd for %s.", fPath.c_str()));
126    }
127
128    if (!brd->conversionSupported(colorType)) {
129        return Error::Nonfatal("Cannot convert to color type.");
130    }
131
132    const uint32_t width = brd->width();
133    const uint32_t height = brd->height();
134    // Visually inspecting very small output images is not necessary.
135    if ((width / fSampleSize <= 10 || height / fSampleSize <= 10) && 1 != fSampleSize) {
136        return Error::Nonfatal("Scaling very small images is uninteresting.");
137    }
138    switch (fMode) {
139        case kFullImage_Mode: {
140            SkBitmap bitmap;
141            if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(0, 0, width, height),
142                    fSampleSize, colorType, false)) {
143                return "Cannot decode (full) region.";
144            }
145            if (colorType != bitmap.colorType()) {
146                return Error::Nonfatal("Cannot convert to color type.");
147            }
148            canvas->drawBitmap(bitmap, 0, 0);
149            return "";
150        }
151        case kDivisor_Mode: {
152            const uint32_t divisor = 2;
153            if (width < divisor || height < divisor) {
154                return Error::Nonfatal("Divisor is larger than image dimension.");
155            }
156
157            // Use a border to test subsets that extend outside the image.
158            // We will not allow the border to be larger than the image dimensions.  Allowing
159            // these large borders causes off by one errors that indicate a problem with the
160            // test suite, not a problem with the implementation.
161            const uint32_t maxBorder = SkTMin(width, height) / (fSampleSize * divisor);
162            const uint32_t scaledBorder = SkTMin(5u, maxBorder);
163            const uint32_t unscaledBorder = scaledBorder * fSampleSize;
164
165            // We may need to clear the canvas to avoid uninitialized memory.
166            // Assume we are scaling a 780x780 image with sampleSize = 8.
167            // The output image should be 97x97.
168            // Each subset will be 390x390.
169            // Each scaled subset be 48x48.
170            // Four scaled subsets will only fill a 96x96 image.
171            // The bottom row and last column will not be touched.
172            // This is an unfortunate result of our rounding rules when scaling.
173            // Maybe we need to consider testing scaled subsets without trying to
174            // combine them to match the full scaled image?  Or maybe this is the
175            // best we can do?
176            canvas->clear(0);
177
178            for (uint32_t x = 0; x < divisor; x++) {
179                for (uint32_t y = 0; y < divisor; y++) {
180                    // Calculate the subset dimensions
181                    uint32_t subsetWidth = width / divisor;
182                    uint32_t subsetHeight = height / divisor;
183                    const int left = x * subsetWidth;
184                    const int top = y * subsetHeight;
185
186                    // Increase the size of the last subset in each row or column, when the
187                    // divisor does not divide evenly into the image dimensions
188                    subsetWidth += (x + 1 == divisor) ? (width % divisor) : 0;
189                    subsetHeight += (y + 1 == divisor) ? (height % divisor) : 0;
190
191                    // Increase the size of the subset in order to have a border on each side
192                    const int decodeLeft = left - unscaledBorder;
193                    const int decodeTop = top - unscaledBorder;
194                    const uint32_t decodeWidth = subsetWidth + unscaledBorder * 2;
195                    const uint32_t decodeHeight = subsetHeight + unscaledBorder * 2;
196                    SkBitmap bitmap;
197                    if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(decodeLeft,
198                            decodeTop, decodeWidth, decodeHeight), fSampleSize, colorType, false)) {
199                        return "Cannot decode region.";
200                    }
201                    if (colorType != bitmap.colorType()) {
202                        return Error::Nonfatal("Cannot convert to color type.");
203                    }
204
205                    canvas->drawBitmapRect(bitmap,
206                            SkRect::MakeXYWH((SkScalar) scaledBorder, (SkScalar) scaledBorder,
207                                    (SkScalar) (subsetWidth / fSampleSize),
208                                    (SkScalar) (subsetHeight / fSampleSize)),
209                            SkRect::MakeXYWH((SkScalar) (left / fSampleSize),
210                                    (SkScalar) (top / fSampleSize),
211                                    (SkScalar) (subsetWidth / fSampleSize),
212                                    (SkScalar) (subsetHeight / fSampleSize)),
213                            nullptr);
214                }
215            }
216            return "";
217        }
218        default:
219            SkASSERT(false);
220            return "Error: Should not be reached.";
221    }
222}
223
224SkISize BRDSrc::size() const {
225    SkAutoTDelete<SkBitmapRegionDecoder> brd(create_brd(fPath));
226    if (brd) {
227        return SkISize::Make(SkTMax(1, brd->width() / (int) fSampleSize),
228                SkTMax(1, brd->height() / (int) fSampleSize));
229    }
230    return SkISize::Make(0, 0);
231}
232
233static SkString get_scaled_name(const Path& path, float scale) {
234    return SkStringPrintf("%s_%.3f", SkOSPath::Basename(path.c_str()).c_str(), scale);
235}
236
237Name BRDSrc::name() const {
238    // We will replicate the names used by CodecSrc so that images can
239    // be compared in Gold.
240    if (1 == fSampleSize) {
241        return SkOSPath::Basename(fPath.c_str());
242    }
243    return get_scaled_name(fPath, 1.0f / (float) fSampleSize);
244}
245
246/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
247
248static bool serial_from_path_name(const SkString& path) {
249    if (!FLAGS_RAW_threading) {
250        static const char* const exts[] = {
251            "arw", "cr2", "dng", "nef", "nrw", "orf", "raf", "rw2", "pef", "srw",
252            "ARW", "CR2", "DNG", "NEF", "NRW", "ORF", "RAF", "RW2", "PEF", "SRW",
253        };
254        const char* actualExt = strrchr(path.c_str(), '.');
255        if (actualExt) {
256            actualExt++;
257            for (auto* ext : exts) {
258                if (0 == strcmp(ext, actualExt)) {
259                    return true;
260                }
261            }
262        }
263    }
264    return false;
265}
266
267CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType, SkAlphaType dstAlphaType,
268                   float scale)
269    : fPath(path)
270    , fMode(mode)
271    , fDstColorType(dstColorType)
272    , fDstAlphaType(dstAlphaType)
273    , fScale(scale)
274    , fRunSerially(serial_from_path_name(path))
275{}
276
277bool CodecSrc::veto(SinkFlags flags) const {
278    // Test to direct raster backends (8888 and 565).
279    return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
280}
281
282// Allows us to test decodes to non-native 8888.
283static void swap_rb_if_necessary(SkBitmap& bitmap, CodecSrc::DstColorType dstColorType) {
284    if (CodecSrc::kNonNative8888_Always_DstColorType != dstColorType) {
285        return;
286    }
287
288    for (int y = 0; y < bitmap.height(); y++) {
289        uint32_t* row = (uint32_t*) bitmap.getAddr(0, y);
290        SkOpts::RGBA_to_BGRA(row, row, bitmap.width());
291    }
292}
293
294// FIXME: Currently we cannot draw unpremultiplied sources. skbug.com/3338 and skbug.com/3339.
295// This allows us to still test unpremultiplied decodes.
296static void premultiply_if_necessary(SkBitmap& bitmap) {
297    if (kUnpremul_SkAlphaType != bitmap.alphaType()) {
298        return;
299    }
300
301    switch (bitmap.colorType()) {
302        case kN32_SkColorType:
303            for (int y = 0; y < bitmap.height(); y++) {
304                uint32_t* row = (uint32_t*) bitmap.getAddr(0, y);
305                SkOpts::RGBA_to_rgbA(row, row, bitmap.width());
306            }
307            break;
308        case kIndex_8_SkColorType: {
309            SkColorTable* colorTable = bitmap.getColorTable();
310            SkPMColor* colorPtr = const_cast<SkPMColor*>(colorTable->readColors());
311            SkOpts::RGBA_to_rgbA(colorPtr, colorPtr, colorTable->count());
312            break;
313        }
314        default:
315            // No need to premultiply kGray or k565 outputs.
316            break;
317    }
318
319    // In the kIndex_8 case, the canvas won't even try to draw unless we mark the
320    // bitmap as kPremul.
321    bitmap.setAlphaType(kPremul_SkAlphaType);
322}
323
324static bool get_decode_info(SkImageInfo* decodeInfo, SkColorType canvasColorType,
325                            CodecSrc::DstColorType dstColorType, SkAlphaType dstAlphaType) {
326    switch (dstColorType) {
327        case CodecSrc::kIndex8_Always_DstColorType:
328            if (kRGB_565_SkColorType == canvasColorType) {
329                return false;
330            }
331            *decodeInfo = decodeInfo->makeColorType(kIndex_8_SkColorType);
332            break;
333        case CodecSrc::kGrayscale_Always_DstColorType:
334            if (kRGB_565_SkColorType == canvasColorType) {
335                return false;
336            }
337            *decodeInfo = decodeInfo->makeColorType(kGray_8_SkColorType);
338            break;
339        case CodecSrc::kNonNative8888_Always_DstColorType:
340            if (kRGB_565_SkColorType == canvasColorType) {
341                return false;
342            }
343#ifdef SK_PMCOLOR_IS_RGBA
344            *decodeInfo = decodeInfo->makeColorType(kBGRA_8888_SkColorType);
345#else
346            *decodeInfo = decodeInfo->makeColorType(kRGBA_8888_SkColorType);
347#endif
348            break;
349        default:
350            if (kRGB_565_SkColorType == canvasColorType &&
351                    kOpaque_SkAlphaType != decodeInfo->alphaType()) {
352                return false;
353            }
354            *decodeInfo = decodeInfo->makeColorType(canvasColorType);
355            break;
356    }
357
358    *decodeInfo = decodeInfo->makeAlphaType(dstAlphaType);
359    return true;
360}
361
362static void draw_to_canvas(SkCanvas* canvas, const SkImageInfo& info, void* pixels, size_t rowBytes,
363                           SkPMColor* colorPtr, int colorCount, CodecSrc::DstColorType dstColorType,
364                           SkScalar left = 0, SkScalar top = 0) {
365    SkAutoTUnref<SkColorTable> colorTable(new SkColorTable(colorPtr, colorCount));
366    SkBitmap bitmap;
367    bitmap.installPixels(info, pixels, rowBytes, colorTable.get(), nullptr, nullptr);
368    premultiply_if_necessary(bitmap);
369    swap_rb_if_necessary(bitmap, dstColorType);
370    canvas->drawBitmap(bitmap, left, top);
371}
372
373Error CodecSrc::draw(SkCanvas* canvas) const {
374    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
375    if (!encoded) {
376        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
377    }
378
379    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
380    if (nullptr == codec.get()) {
381        return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
382    }
383
384    SkImageInfo decodeInfo = codec->getInfo();
385    if (!get_decode_info(&decodeInfo, canvas->imageInfo().colorType(), fDstColorType,
386                         fDstAlphaType)) {
387        return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
388    }
389
390    // Try to scale the image if it is desired
391    SkISize size = codec->getScaledDimensions(fScale);
392    if (size == decodeInfo.dimensions() && 1.0f != fScale) {
393        return Error::Nonfatal("Test without scaling is uninteresting.");
394    }
395
396    // Visually inspecting very small output images is not necessary.  We will
397    // cover these cases in unit testing.
398    if ((size.width() <= 10 || size.height() <= 10) && 1.0f != fScale) {
399        return Error::Nonfatal("Scaling very small images is uninteresting.");
400    }
401    decodeInfo = decodeInfo.makeWH(size.width(), size.height());
402
403    const int bpp = SkColorTypeBytesPerPixel(decodeInfo.colorType());
404    const size_t rowBytes = size.width() * bpp;
405    SkAutoMalloc pixels(decodeInfo.getSafeSize(rowBytes));
406    SkPMColor colorPtr[256];
407    int colorCount = 256;
408
409    SkCodec::Options options;
410    if (kCodecZeroInit_Mode == fMode) {
411        memset(pixels.get(), 0, size.height() * rowBytes);
412        options.fZeroInitialized = SkCodec::kYes_ZeroInitialized;
413    }
414
415    SkImageInfo bitmapInfo = decodeInfo;
416    if (kRGBA_8888_SkColorType == decodeInfo.colorType() ||
417            kBGRA_8888_SkColorType == decodeInfo.colorType()) {
418        bitmapInfo = bitmapInfo.makeColorType(kN32_SkColorType);
419    }
420
421    switch (fMode) {
422        case kCodecZeroInit_Mode:
423        case kCodec_Mode: {
424            switch (codec->getPixels(decodeInfo, pixels.get(), rowBytes, &options,
425                    colorPtr, &colorCount)) {
426                case SkCodec::kSuccess:
427                    // We consider incomplete to be valid, since we should still decode what is
428                    // available.
429                case SkCodec::kIncompleteInput:
430                    break;
431                default:
432                    // Everything else is considered a failure.
433                    return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
434            }
435
436            draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, colorPtr, colorCount,
437                           fDstColorType);
438            break;
439        }
440        case kScanline_Mode: {
441            if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL, colorPtr,
442                                                                &colorCount)) {
443                return "Could not start scanline decoder";
444            }
445
446            void* dst = pixels.get();
447            uint32_t height = decodeInfo.height();
448            switch (codec->getScanlineOrder()) {
449                case SkCodec::kTopDown_SkScanlineOrder:
450                case SkCodec::kBottomUp_SkScanlineOrder:
451                case SkCodec::kNone_SkScanlineOrder:
452                    // We do not need to check the return value.  On an incomplete
453                    // image, memory will be filled with a default value.
454                    codec->getScanlines(dst, height, rowBytes);
455                    break;
456                case SkCodec::kOutOfOrder_SkScanlineOrder: {
457                    for (int y = 0; y < decodeInfo.height(); y++) {
458                        int dstY = codec->outputScanline(y);
459                        void* dstPtr = SkTAddOffset<void>(dst, rowBytes * dstY);
460                        // We complete the loop, even if this call begins to fail
461                        // due to an incomplete image.  This ensures any uninitialized
462                        // memory will be filled with the proper value.
463                        codec->getScanlines(dstPtr, 1, rowBytes);
464                    }
465                    break;
466                }
467            }
468
469            draw_to_canvas(canvas, bitmapInfo, dst, rowBytes, colorPtr, colorCount, fDstColorType);
470            break;
471        }
472        case kStripe_Mode: {
473            const int height = decodeInfo.height();
474            // This value is chosen arbitrarily.  We exercise more cases by choosing a value that
475            // does not align with image blocks.
476            const int stripeHeight = 37;
477            const int numStripes = (height + stripeHeight - 1) / stripeHeight;
478            void* dst = pixels.get();
479
480            // Decode odd stripes
481            if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, nullptr, colorPtr,
482                                                                &colorCount)) {
483                return "Could not start scanline decoder";
484            }
485
486            // This mode was designed to test the new skip scanlines API in libjpeg-turbo.
487            // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting
488            // to run this test for image types that do not have this scanline ordering.
489            // We only run this on Jpeg, which is always kTopDown.
490            SkASSERT(SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder());
491
492            for (int i = 0; i < numStripes; i += 2) {
493                // Skip a stripe
494                const int linesToSkip = SkTMin(stripeHeight, height - i * stripeHeight);
495                codec->skipScanlines(linesToSkip);
496
497                // Read a stripe
498                const int startY = (i + 1) * stripeHeight;
499                const int linesToRead = SkTMin(stripeHeight, height - startY);
500                if (linesToRead > 0) {
501                    codec->getScanlines(SkTAddOffset<void>(dst, rowBytes * startY), linesToRead,
502                                        rowBytes);
503                }
504            }
505
506            // Decode even stripes
507            const SkCodec::Result startResult = codec->startScanlineDecode(decodeInfo, nullptr,
508                    colorPtr, &colorCount);
509            if (SkCodec::kSuccess != startResult) {
510                return "Failed to restart scanline decoder with same parameters.";
511            }
512            for (int i = 0; i < numStripes; i += 2) {
513                // Read a stripe
514                const int startY = i * stripeHeight;
515                const int linesToRead = SkTMin(stripeHeight, height - startY);
516                codec->getScanlines(SkTAddOffset<void>(dst, rowBytes * startY), linesToRead,
517                                    rowBytes);
518
519                // Skip a stripe
520                const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) * stripeHeight);
521                if (linesToSkip > 0) {
522                    codec->skipScanlines(linesToSkip);
523                }
524            }
525
526            draw_to_canvas(canvas, bitmapInfo, dst, rowBytes, colorPtr, colorCount, fDstColorType);
527            break;
528        }
529        case kCroppedScanline_Mode: {
530            const int width = decodeInfo.width();
531            const int height = decodeInfo.height();
532            // This value is chosen because, as we move across the image, it will sometimes
533            // align with the jpeg block sizes and it will sometimes not.  This allows us
534            // to test interestingly different code paths in the implementation.
535            const int tileSize = 36;
536
537            SkCodec::Options opts;
538            SkIRect subset;
539            for (int x = 0; x < width; x += tileSize) {
540                subset = SkIRect::MakeXYWH(x, 0, SkTMin(tileSize, width - x), height);
541                opts.fSubset = &subset;
542                if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, &opts,
543                        colorPtr, &colorCount)) {
544                    return "Could not start scanline decoder.";
545                }
546
547                codec->getScanlines(SkTAddOffset<void>(pixels.get(), x * bpp), height, rowBytes);
548            }
549
550            draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, colorPtr, colorCount,
551                           fDstColorType);
552            break;
553        }
554        case kSubset_Mode: {
555            // Arbitrarily choose a divisor.
556            int divisor = 2;
557            // Total width/height of the image.
558            const int W = codec->getInfo().width();
559            const int H = codec->getInfo().height();
560            if (divisor > W || divisor > H) {
561                return Error::Nonfatal(SkStringPrintf("Cannot codec subset: divisor %d is too big "
562                                                      "for %s with dimensions (%d x %d)", divisor,
563                                                      fPath.c_str(), W, H));
564            }
565            // subset dimensions
566            // SkWebpCodec, the only one that supports subsets, requires even top/left boundaries.
567            const int w = SkAlign2(W / divisor);
568            const int h = SkAlign2(H / divisor);
569            SkIRect subset;
570            SkCodec::Options opts;
571            opts.fSubset = &subset;
572            SkBitmap subsetBm;
573            // We will reuse pixel memory from bitmap.
574            void* dst = pixels.get();
575            // Keep track of left and top (for drawing subsetBm into canvas). We could use
576            // fScale * x and fScale * y, but we want integers such that the next subset will start
577            // where the last one ended. So we'll add decodeInfo.width() and height().
578            int left = 0;
579            for (int x = 0; x < W; x += w) {
580                int top = 0;
581                for (int y = 0; y < H; y+= h) {
582                    // Do not make the subset go off the edge of the image.
583                    const int preScaleW = SkTMin(w, W - x);
584                    const int preScaleH = SkTMin(h, H - y);
585                    subset.setXYWH(x, y, preScaleW, preScaleH);
586                    // And scale
587                    // FIXME: Should we have a version of getScaledDimensions that takes a subset
588                    // into account?
589                    const int scaledW = SkTMax(1, SkScalarRoundToInt(preScaleW * fScale));
590                    const int scaledH = SkTMax(1, SkScalarRoundToInt(preScaleH * fScale));
591                    decodeInfo = decodeInfo.makeWH(scaledW, scaledH);
592                    SkImageInfo subsetBitmapInfo = bitmapInfo.makeWH(scaledW, scaledH);
593                    size_t subsetRowBytes = subsetBitmapInfo.minRowBytes();
594                    const SkCodec::Result result = codec->getPixels(decodeInfo, dst, subsetRowBytes,
595                            &opts, colorPtr, &colorCount);
596                    switch (result) {
597                        case SkCodec::kSuccess:
598                        case SkCodec::kIncompleteInput:
599                            break;
600                        default:
601                            return SkStringPrintf("subset codec failed to decode (%d, %d, %d, %d) "
602                                                  "from %s with dimensions (%d x %d)\t error %d",
603                                                  x, y, decodeInfo.width(), decodeInfo.height(),
604                                                  fPath.c_str(), W, H, result);
605                    }
606                    draw_to_canvas(canvas, subsetBitmapInfo, dst, subsetRowBytes, colorPtr,
607                                   colorCount, fDstColorType, SkIntToScalar(left),
608                                   SkIntToScalar(top));
609
610                    // translate by the scaled height.
611                    top += decodeInfo.height();
612                }
613                // translate by the scaled width.
614                left += decodeInfo.width();
615            }
616            return "";
617        }
618        default:
619            SkASSERT(false);
620            return "Invalid fMode";
621    }
622    return "";
623}
624
625SkISize CodecSrc::size() const {
626    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
627    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
628    if (nullptr == codec) {
629        return SkISize::Make(0, 0);
630    }
631    return codec->getScaledDimensions(fScale);
632}
633
634Name CodecSrc::name() const {
635    if (1.0f == fScale) {
636        return SkOSPath::Basename(fPath.c_str());
637    }
638    return get_scaled_name(fPath, fScale);
639}
640
641/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
642
643AndroidCodecSrc::AndroidCodecSrc(Path path, CodecSrc::DstColorType dstColorType,
644        SkAlphaType dstAlphaType, int sampleSize)
645    : fPath(path)
646    , fDstColorType(dstColorType)
647    , fDstAlphaType(dstAlphaType)
648    , fSampleSize(sampleSize)
649    , fRunSerially(serial_from_path_name(path))
650{}
651
652bool AndroidCodecSrc::veto(SinkFlags flags) const {
653    // No need to test decoding to non-raster or indirect backend.
654    return flags.type != SinkFlags::kRaster
655        || flags.approach != SinkFlags::kDirect;
656}
657
658Error AndroidCodecSrc::draw(SkCanvas* canvas) const {
659    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
660    if (!encoded) {
661        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
662    }
663    SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromData(encoded));
664    if (nullptr == codec.get()) {
665        return SkStringPrintf("Couldn't create android codec for %s.", fPath.c_str());
666    }
667
668    SkImageInfo decodeInfo = codec->getInfo();
669    if (!get_decode_info(&decodeInfo, canvas->imageInfo().colorType(), fDstColorType,
670                         fDstAlphaType)) {
671        return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
672    }
673
674    // Scale the image if it is desired.
675    SkISize size = codec->getSampledDimensions(fSampleSize);
676
677    // Visually inspecting very small output images is not necessary.  We will
678    // cover these cases in unit testing.
679    if ((size.width() <= 10 || size.height() <= 10) && 1 != fSampleSize) {
680        return Error::Nonfatal("Scaling very small images is uninteresting.");
681    }
682    decodeInfo = decodeInfo.makeWH(size.width(), size.height());
683
684    int bpp = SkColorTypeBytesPerPixel(decodeInfo.colorType());
685    size_t rowBytes = size.width() * bpp;
686    SkAutoMalloc pixels(size.height() * rowBytes);
687    SkPMColor colorPtr[256];
688    int colorCount = 256;
689
690    SkBitmap bitmap;
691    SkImageInfo bitmapInfo = decodeInfo;
692    if (kRGBA_8888_SkColorType == decodeInfo.colorType() ||
693            kBGRA_8888_SkColorType == decodeInfo.colorType()) {
694        bitmapInfo = bitmapInfo.makeColorType(kN32_SkColorType);
695    }
696
697    // Create options for the codec.
698    SkAndroidCodec::AndroidOptions options;
699    options.fColorPtr = colorPtr;
700    options.fColorCount = &colorCount;
701    options.fSampleSize = fSampleSize;
702
703    switch (codec->getAndroidPixels(decodeInfo, pixels.get(), rowBytes, &options)) {
704        case SkCodec::kSuccess:
705        case SkCodec::kIncompleteInput:
706            break;
707        default:
708            return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
709    }
710    draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, colorPtr, colorCount, fDstColorType);
711    return "";
712}
713
714SkISize AndroidCodecSrc::size() const {
715    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
716    SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromData(encoded));
717    if (nullptr == codec) {
718        return SkISize::Make(0, 0);
719    }
720    return codec->getSampledDimensions(fSampleSize);
721}
722
723Name AndroidCodecSrc::name() const {
724    // We will replicate the names used by CodecSrc so that images can
725    // be compared in Gold.
726    if (1 == fSampleSize) {
727        return SkOSPath::Basename(fPath.c_str());
728    }
729    return get_scaled_name(fPath, 1.0f / (float) fSampleSize);
730}
731
732/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
733
734ImageGenSrc::ImageGenSrc(Path path, Mode mode, SkAlphaType alphaType, bool isGpu)
735    : fPath(path)
736    , fMode(mode)
737    , fDstAlphaType(alphaType)
738    , fIsGpu(isGpu)
739    , fRunSerially(serial_from_path_name(path))
740{}
741
742bool ImageGenSrc::veto(SinkFlags flags) const {
743    if (fIsGpu) {
744        return flags.type != SinkFlags::kGPU || flags.approach != SinkFlags::kDirect;
745    }
746
747    return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
748}
749
750Error ImageGenSrc::draw(SkCanvas* canvas) const {
751    if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) {
752        return Error::Nonfatal("Uninteresting to test image generator to 565.");
753    }
754
755    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
756    if (!encoded) {
757        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
758    }
759
760#if defined(SK_BUILD_FOR_WIN)
761    // Initialize COM in order to test with WIC.
762    SkAutoCoInitialize com;
763    if (!com.succeeded()) {
764        return "Could not initialize COM.";
765    }
766#endif
767
768    SkAutoTDelete<SkImageGenerator> gen(nullptr);
769    switch (fMode) {
770        case kCodec_Mode:
771            gen.reset(SkCodecImageGenerator::NewFromEncodedCodec(encoded));
772            if (!gen) {
773                return "Could not create codec image generator.";
774            }
775            break;
776        case kPlatform_Mode: {
777#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
778            gen.reset(SkImageGeneratorCG::NewFromEncodedCG(encoded));
779#elif defined(SK_BUILD_FOR_WIN)
780            gen.reset(SkImageGeneratorWIC::NewFromEncodedWIC(encoded));
781#endif
782
783            if (!gen) {
784                return "Could not create platform image generator.";
785            }
786            break;
787        }
788        default:
789            SkASSERT(false);
790            return "Invalid image generator mode";
791    }
792
793    // Test deferred decoding path on GPU
794    if (fIsGpu) {
795        sk_sp<SkImage> image(SkImage::MakeFromGenerator(gen.release(), nullptr));
796        if (!image) {
797            return "Could not create image from codec image generator.";
798        }
799        canvas->drawImage(image, 0, 0);
800        return "";
801    }
802
803    // Test various color and alpha types on CPU
804    SkImageInfo decodeInfo = gen->getInfo().makeAlphaType(fDstAlphaType);
805
806    int bpp = SkColorTypeBytesPerPixel(decodeInfo.colorType());
807    size_t rowBytes = decodeInfo.width() * bpp;
808    SkAutoMalloc pixels(decodeInfo.height() * rowBytes);
809    SkPMColor colorPtr[256];
810    int colorCount = 256;
811
812    if (!gen->getPixels(decodeInfo, pixels.get(), rowBytes, colorPtr, &colorCount)) {
813        return SkStringPrintf("Image generator could not getPixels() for %s\n", fPath.c_str());
814    }
815
816    draw_to_canvas(canvas, decodeInfo, pixels.get(), rowBytes, colorPtr, colorCount,
817                   CodecSrc::kGetFromCanvas_DstColorType);
818    return "";
819}
820
821SkISize ImageGenSrc::size() const {
822    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
823    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
824    if (nullptr == codec) {
825        return SkISize::Make(0, 0);
826    }
827    return codec->getInfo().dimensions();
828}
829
830Name ImageGenSrc::name() const {
831    return SkOSPath::Basename(fPath.c_str());
832}
833
834/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
835
836ColorCodecSrc::ColorCodecSrc(Path path, Mode mode)
837    : fPath(path)
838    , fMode(mode)
839{}
840
841bool ColorCodecSrc::veto(SinkFlags flags) const {
842    // Test to direct raster backends (8888 and 565).
843    return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
844}
845
846Error ColorCodecSrc::draw(SkCanvas* canvas) const {
847    if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) {
848        return Error::Nonfatal("No need to test color correction to 565 backend.");
849    }
850
851    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
852    if (!encoded) {
853        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
854    }
855
856    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
857    if (nullptr == codec.get()) {
858        return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
859    }
860
861    SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
862    SkBitmap bitmap;
863    if (!bitmap.tryAllocPixels(info)) {
864        return SkStringPrintf("Image(%s) is too large (%d x %d)", fPath.c_str(),
865                              info.width(), info.height());
866    }
867
868    SkImageInfo decodeInfo = info;
869    if (kBaseline_Mode != fMode) {
870        decodeInfo = decodeInfo.makeColorType(kRGBA_8888_SkColorType);
871    }
872
873    SkCodec::Result r = codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes());
874    if (SkCodec::kSuccess != r) {
875        return SkStringPrintf("Couldn't getPixels %s. Error code %d", fPath.c_str(), r);
876    }
877
878    // Load the dst ICC profile.  This particular dst is fairly similar to Adobe RGB.
879    sk_sp<SkData> dstData = SkData::MakeFromFileName(
880            GetResourcePath("monitor_profiles/HP_ZR30w.icc").c_str());
881    if (!dstData) {
882        return "Cannot read monitor profile.  Is the resource path set correctly?";
883    }
884
885    switch (fMode) {
886        case kBaseline_Mode:
887            canvas->drawBitmap(bitmap, 0, 0);
888            break;
889        case kDst_HPZR30w_Mode: {
890            sk_sp<SkColorSpace> srcSpace = sk_ref_sp(codec->getColorSpace());
891            sk_sp<SkColorSpace> dstSpace = SkColorSpace::NewICC(dstData->data(), dstData->size());
892            SkASSERT(dstSpace);
893
894            std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcSpace, dstSpace);
895            if (!xform) {
896                // FIXME (msarett):
897                // I haven't implemented conversions for all of the images that I've uploaded for
898                // testing.  Once we support all of them, this should be a fatal error.
899                return Error::Nonfatal("Unimplemented color conversion.");
900            }
901
902            uint32_t* row = (uint32_t*) bitmap.getPixels();
903            for (int y = 0; y < info.height(); y++) {
904                xform->xform_RGBA_8888(row, row, info.width());
905                row = SkTAddOffset<uint32_t>(row, bitmap.rowBytes());
906            }
907
908            canvas->drawBitmap(bitmap, 0, 0);
909            break;
910        }
911#if !defined(GOOGLE3)
912        case kQCMS_HPZR30w_Mode: {
913            sk_sp<SkData> srcData = codec->getICCData();
914            SkAutoTCallVProc<qcms_profile, qcms_profile_release>
915                    srcSpace(qcms_profile_from_memory(srcData->data(), srcData->size()));
916            if (!srcSpace) {
917                return Error::Nonfatal(SkStringPrintf("QCMS cannot create profile for %s.\n",
918                                       fPath.c_str()));
919            }
920
921            SkAutoTCallVProc<qcms_profile, qcms_profile_release>
922                    dstSpace(qcms_profile_from_memory(dstData->data(), dstData->size()));
923            SkASSERT(dstSpace);
924            SkAutoTCallVProc<qcms_transform, qcms_transform_release>
925                    transform (qcms_transform_create(srcSpace, QCMS_DATA_RGBA_8, dstSpace,
926                                                     QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL));
927            if (!transform) {
928                return SkStringPrintf("QCMS cannot create transform for %s.\n", fPath.c_str());
929            }
930
931#ifdef SK_PMCOLOR_IS_RGBA
932            qcms_output_type outType = QCMS_OUTPUT_RGBX;
933#else
934            qcms_output_type outType = QCMS_OUTPUT_BGRX;
935#endif
936
937            // Perform color correction.
938            uint32_t* row = (uint32_t*) bitmap.getPixels();
939            for (int y = 0; y < info.height(); y++) {
940                qcms_transform_data_type(transform, row, row, info.width(), outType);
941                row = SkTAddOffset<uint32_t>(row, bitmap.rowBytes());
942            }
943
944            canvas->drawBitmap(bitmap, 0, 0);
945            break;
946        }
947#endif
948        default:
949            SkASSERT(false);
950            return "Invalid fMode";
951    }
952    return "";
953}
954
955SkISize ColorCodecSrc::size() const {
956    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
957    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
958    if (nullptr == codec) {
959        return SkISize::Make(0, 0);
960    }
961    return SkISize::Make(codec->getInfo().width(), codec->getInfo().height());
962}
963
964Name ColorCodecSrc::name() const {
965    return SkOSPath::Basename(fPath.c_str());
966}
967
968/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
969
970static const SkRect kSKPViewport = {0,0, 1000,1000};
971
972SKPSrc::SKPSrc(Path path) : fPath(path) {}
973
974Error SKPSrc::draw(SkCanvas* canvas) const {
975    SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
976    if (!stream) {
977        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
978    }
979    sk_sp<SkPicture> pic(SkPicture::MakeFromStream(stream));
980    if (!pic) {
981        return SkStringPrintf("Couldn't decode %s as a picture.", fPath.c_str());
982    }
983    stream.reset((SkStream*)nullptr);  // Might as well drop this when we're done with it.
984
985    canvas->clipRect(kSKPViewport);
986    canvas->drawPicture(pic);
987    return "";
988}
989
990SkISize SKPSrc::size() const {
991    SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
992    if (!stream) {
993        return SkISize::Make(0,0);
994    }
995    SkPictInfo info;
996    if (!SkPicture::InternalOnly_StreamIsSKP(stream, &info)) {
997        return SkISize::Make(0,0);
998    }
999    SkRect viewport = kSKPViewport;
1000    if (!viewport.intersect(info.fCullRect)) {
1001        return SkISize::Make(0,0);
1002    }
1003    return viewport.roundOut().size();
1004}
1005
1006Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
1007
1008/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1009
1010MSKPSrc::MSKPSrc(Path path) : fPath(path) {
1011    std::unique_ptr<SkStreamAsset> stream(SkStream::NewFromFile(fPath.c_str()));
1012    (void)fReader.init(stream.get());
1013}
1014
1015int MSKPSrc::pageCount() const { return fReader.pageCount(); }
1016
1017SkISize MSKPSrc::size() const { return this->size(0); }
1018SkISize MSKPSrc::size(int i) const { return fReader.pageSize(i).toCeil(); }
1019
1020Error MSKPSrc::draw(SkCanvas* c) const { return this->draw(0, c); }
1021Error MSKPSrc::draw(int i, SkCanvas* canvas) const {
1022    std::unique_ptr<SkStreamAsset> stream(SkStream::NewFromFile(fPath.c_str()));
1023    if (!stream) {
1024        return SkStringPrintf("Unable to open file: %s", fPath.c_str());
1025    }
1026    if (fReader.pageCount() == 0) {
1027        return SkStringPrintf("Unable to parse MultiPictureDocument file: %s", fPath.c_str());
1028    }
1029    if (i >= fReader.pageCount()) {
1030        return SkStringPrintf("MultiPictureDocument page number out of range: %d", i);
1031    }
1032    sk_sp<SkPicture> page = fReader.readPage(stream.get(), i);
1033    if (!page) {
1034        return SkStringPrintf("SkMultiPictureDocumentReader failed on page %d: %s",
1035                              i, fPath.c_str());
1036    }
1037    canvas->drawPicture(page);
1038    return "";
1039}
1040
1041Name MSKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
1042
1043/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1044
1045Error NullSink::draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const {
1046    SkAutoTDelete<SkCanvas> canvas(SkCreateNullCanvas());
1047    return src.draw(canvas);
1048}
1049
1050/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1051
1052DEFINE_bool(gpuStats, false, "Append GPU stats to the log for each GPU task?");
1053
1054GPUSink::GPUSink(GrContextFactory::ContextType ct,
1055                 GrContextFactory::ContextOptions options,
1056                 int samples,
1057                 bool diText,
1058                 SkColorType colorType,
1059                 SkColorProfileType profileType,
1060                 bool threaded)
1061    : fContextType(ct)
1062    , fContextOptions(options)
1063    , fSampleCount(samples)
1064    , fUseDIText(diText)
1065    , fColorType(colorType)
1066    , fProfileType(profileType)
1067    , fThreaded(threaded) {}
1068
1069void PreAbandonGpuContextErrorHandler(SkError, void*) {}
1070
1071DEFINE_bool(imm, false, "Run gpu configs in immediate mode.");
1072DEFINE_bool(batchClip, false, "Clip each GrBatch to its device bounds for testing.");
1073DEFINE_bool(batchBounds, false, "Draw a wireframe bounds of each GrBatch.");
1074DEFINE_int32(batchLookback, -1, "Maximum GrBatch lookback for combining, negative means default.");
1075DEFINE_int32(batchLookahead, -1, "Maximum GrBatch lookahead for combining, negative means "
1076                                 "default.");
1077
1078Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) const {
1079    GrContextOptions grOptions;
1080    grOptions.fImmediateMode = FLAGS_imm;
1081    grOptions.fClipBatchToBounds = FLAGS_batchClip;
1082    grOptions.fDrawBatchBounds = FLAGS_batchBounds;
1083    grOptions.fMaxBatchLookback = FLAGS_batchLookback;
1084    grOptions.fMaxBatchLookahead = FLAGS_batchLookahead;
1085
1086    src.modifyGrContextOptions(&grOptions);
1087
1088    GrContextFactory factory(grOptions);
1089    const SkISize size = src.size();
1090    const SkImageInfo info =
1091        SkImageInfo::Make(size.width(), size.height(), fColorType,
1092                          kPremul_SkAlphaType, fProfileType);
1093#if SK_SUPPORT_GPU
1094    GrContext* context = factory.getContextInfo(fContextType, fContextOptions).grContext();
1095    const int maxDimension = context->caps()->maxTextureSize();
1096    if (maxDimension < SkTMax(size.width(), size.height())) {
1097        return Error::Nonfatal("Src too large to create a texture.\n");
1098    }
1099#endif
1100
1101    auto surface(
1102            NewGpuSurface(&factory, fContextType, fContextOptions, info, fSampleCount, fUseDIText));
1103    if (!surface) {
1104        return "Could not create a surface.";
1105    }
1106    if (FLAGS_preAbandonGpuContext) {
1107        SkSetErrorCallback(&PreAbandonGpuContextErrorHandler, nullptr);
1108        factory.abandonContexts();
1109    }
1110    SkCanvas* canvas = surface->getCanvas();
1111    Error err = src.draw(canvas);
1112    if (!err.isEmpty()) {
1113        return err;
1114    }
1115    canvas->flush();
1116    if (FLAGS_gpuStats) {
1117        canvas->getGrContext()->dumpCacheStats(log);
1118        canvas->getGrContext()->dumpGpuStats(log);
1119    }
1120    dst->allocPixels(info);
1121    canvas->readPixels(dst, 0, 0);
1122    if (FLAGS_abandonGpuContext) {
1123        factory.abandonContexts();
1124    } else if (FLAGS_releaseAndAbandonGpuContext) {
1125        factory.releaseResourcesAndAbandonContexts();
1126    }
1127    return "";
1128}
1129
1130/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1131
1132static Error draw_skdocument(const Src& src, SkDocument* doc, SkWStream* dst) {
1133    if (src.size().isEmpty()) {
1134        return "Source has empty dimensions";
1135    }
1136    SkASSERT(doc);
1137    int pageCount = src.pageCount();
1138    for (int i = 0; i < pageCount; ++i) {
1139        int width = src.size(i).width(), height = src.size(i).height();
1140        SkCanvas* canvas =
1141                doc->beginPage(SkIntToScalar(width), SkIntToScalar(height));
1142        if (!canvas) {
1143            return "SkDocument::beginPage(w,h) returned nullptr";
1144        }
1145        Error err = src.draw(i, canvas);
1146        if (!err.isEmpty()) {
1147            return err;
1148        }
1149        doc->endPage();
1150    }
1151    if (!doc->close()) {
1152        return "SkDocument::close() returned false";
1153    }
1154    dst->flush();
1155    return "";
1156}
1157
1158Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
1159    SkDocument::PDFMetadata metadata;
1160    metadata.fTitle = src.name();
1161    metadata.fSubject = "rendering correctness test";
1162    metadata.fCreator = "Skia/DM";
1163    sk_sp<SkDocument> doc = SkDocument::MakePDF(dst, SK_ScalarDefaultRasterDPI,
1164                                                metadata, nullptr, fPDFA);
1165    if (!doc) {
1166        return "SkDocument::MakePDF() returned nullptr";
1167    }
1168    return draw_skdocument(src, doc.get(), dst);
1169}
1170
1171/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1172
1173XPSSink::XPSSink() {}
1174
1175Error XPSSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
1176    sk_sp<SkDocument> doc(SkDocument::MakeXPS(dst));
1177    if (!doc) {
1178        return "SkDocument::MakeXPS() returned nullptr";
1179    }
1180    return draw_skdocument(src, doc.get(), dst);
1181}
1182/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1183
1184SKPSink::SKPSink() {}
1185
1186Error SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
1187    SkSize size;
1188    size = src.size();
1189    SkPictureRecorder recorder;
1190    Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
1191    if (!err.isEmpty()) {
1192        return err;
1193    }
1194    recorder.finishRecordingAsPicture()->serialize(dst);
1195    return "";
1196}
1197
1198/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1199
1200SVGSink::SVGSink() {}
1201
1202Error SVGSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
1203    SkAutoTDelete<SkXMLWriter> xmlWriter(new SkXMLStreamWriter(dst));
1204    SkAutoTUnref<SkCanvas> canvas(SkSVGCanvas::Create(
1205        SkRect::MakeWH(SkIntToScalar(src.size().width()), SkIntToScalar(src.size().height())),
1206        xmlWriter));
1207    return src.draw(canvas);
1208}
1209
1210/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1211
1212RasterSink::RasterSink(SkColorType colorType, SkColorProfileType profileType)
1213    : fColorType(colorType)
1214    , fProfileType(profileType) {}
1215
1216Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const {
1217    const SkISize size = src.size();
1218    // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
1219    SkAlphaType alphaType = kPremul_SkAlphaType;
1220    (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
1221
1222    SkMallocPixelRef::ZeroedPRFactory factory;
1223    dst->allocPixels(SkImageInfo::Make(size.width(), size.height(),
1224                                       fColorType, alphaType, fProfileType),
1225                     &factory,
1226                     nullptr/*colortable*/);
1227    SkCanvas canvas(*dst);
1228    return src.draw(&canvas);
1229}
1230
1231/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1232
1233// Handy for front-patching a Src.  Do whatever up-front work you need, then call draw_to_canvas(),
1234// passing the Sink draw() arguments, a size, and a function draws into an SkCanvas.
1235// Several examples below.
1236
1237template <typename Fn>
1238static Error draw_to_canvas(Sink* sink, SkBitmap* bitmap, SkWStream* stream, SkString* log,
1239                            SkISize size, const Fn& draw) {
1240    class ProxySrc : public Src {
1241    public:
1242        ProxySrc(SkISize size, const Fn& draw) : fSize(size), fDraw(draw) {}
1243        Error   draw(SkCanvas* canvas) const override { return fDraw(canvas); }
1244        Name    name() const override { return "ProxySrc"; }
1245        SkISize size() const override { return fSize; }
1246    private:
1247        SkISize   fSize;
1248        const Fn& fDraw;
1249    };
1250    return sink->draw(ProxySrc(size, draw), bitmap, stream, log);
1251}
1252
1253/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1254
1255DEFINE_bool(check, true, "If true, have most Via- modes fail if they affect the output.");
1256
1257// Is *bitmap identical to what you get drawing src into sink?
1258static Error check_against_reference(const SkBitmap* bitmap, const Src& src, Sink* sink) {
1259    // We can only check raster outputs.
1260    // (Non-raster outputs like .pdf, .skp, .svg may differ but still draw identically.)
1261    if (FLAGS_check && bitmap) {
1262        SkBitmap reference;
1263        SkString log;
1264        SkDynamicMemoryWStream wStream;
1265        Error err = sink->draw(src, &reference, &wStream, &log);
1266        // If we can draw into this Sink via some pipeline, we should be able to draw directly.
1267        SkASSERT(err.isEmpty());
1268        if (!err.isEmpty()) {
1269            return err;
1270        }
1271        // The dimensions are a property of the Src only, and so should be identical.
1272        SkASSERT(reference.getSize() == bitmap->getSize());
1273        if (reference.getSize() != bitmap->getSize()) {
1274            return "Dimensions don't match reference";
1275        }
1276        // All SkBitmaps in DM are pre-locked and tight, so this comparison is easy.
1277        if (0 != memcmp(reference.getPixels(), bitmap->getPixels(), reference.getSize())) {
1278            return "Pixels don't match reference";
1279        }
1280    }
1281    return "";
1282}
1283
1284/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1285
1286static SkISize auto_compute_translate(SkMatrix* matrix, int srcW, int srcH) {
1287    SkRect bounds = SkRect::MakeIWH(srcW, srcH);
1288    matrix->mapRect(&bounds);
1289    matrix->postTranslate(-bounds.x(), -bounds.y());
1290    return SkISize::Make(SkScalarRoundToInt(bounds.width()), SkScalarRoundToInt(bounds.height()));
1291}
1292
1293ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
1294
1295Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1296    SkMatrix matrix = fMatrix;
1297    SkISize size = auto_compute_translate(&matrix, src.size().width(), src.size().height());
1298    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
1299        canvas->concat(matrix);
1300        return src.draw(canvas);
1301    });
1302}
1303
1304// Undoes any flip or 90 degree rotate without changing the scale of the bitmap.
1305// This should be pixel-preserving.
1306ViaUpright::ViaUpright(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
1307
1308Error ViaUpright::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1309    Error err = fSink->draw(src, bitmap, stream, log);
1310    if (!err.isEmpty()) {
1311        return err;
1312    }
1313
1314    SkMatrix inverse;
1315    if (!fMatrix.rectStaysRect() || !fMatrix.invert(&inverse)) {
1316        return "Cannot upright --matrix.";
1317    }
1318    SkMatrix upright = SkMatrix::I();
1319    upright.setScaleX(SkScalarSignAsScalar(inverse.getScaleX()));
1320    upright.setScaleY(SkScalarSignAsScalar(inverse.getScaleY()));
1321    upright.setSkewX(SkScalarSignAsScalar(inverse.getSkewX()));
1322    upright.setSkewY(SkScalarSignAsScalar(inverse.getSkewY()));
1323
1324    SkBitmap uprighted;
1325    SkISize size = auto_compute_translate(&upright, bitmap->width(), bitmap->height());
1326    uprighted.allocPixels(bitmap->info().makeWH(size.width(), size.height()));
1327
1328    SkCanvas canvas(uprighted);
1329    canvas.concat(upright);
1330    SkPaint paint;
1331    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
1332    canvas.drawBitmap(*bitmap, 0, 0, &paint);
1333
1334    *bitmap = uprighted;
1335    bitmap->lockPixels();
1336    return "";
1337}
1338
1339/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1340
1341Error ViaSerialization::draw(
1342        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1343    // Record our Src into a picture.
1344    auto size = src.size();
1345    SkPictureRecorder recorder;
1346    Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
1347                                                 SkIntToScalar(size.height())));
1348    if (!err.isEmpty()) {
1349        return err;
1350    }
1351    sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
1352
1353    // Serialize it and then deserialize it.
1354    SkDynamicMemoryWStream wStream;
1355    pic->serialize(&wStream);
1356    SkAutoTDelete<SkStream> rStream(wStream.detachAsStream());
1357    sk_sp<SkPicture> deserialized(SkPicture::MakeFromStream(rStream));
1358
1359    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
1360        canvas->drawPicture(deserialized);
1361        return check_against_reference(bitmap, src, fSink);
1362    });
1363}
1364
1365/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1366
1367ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
1368    : Via(sink)
1369    , fW(w)
1370    , fH(h)
1371    , fFactory(factory) {}
1372
1373Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1374    auto size = src.size();
1375    SkPictureRecorder recorder;
1376    Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
1377                                                 SkIntToScalar(size.height()),
1378                                                 fFactory.get()));
1379    if (!err.isEmpty()) {
1380        return err;
1381    }
1382    sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
1383
1384    return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) {
1385        const int xTiles = (size.width()  + fW - 1) / fW,
1386                  yTiles = (size.height() + fH - 1) / fH;
1387        SkMultiPictureDraw mpd(xTiles*yTiles);
1388        SkTArray<sk_sp<SkSurface>> surfaces;
1389//        surfaces.setReserve(xTiles*yTiles);
1390
1391        SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
1392        for (int j = 0; j < yTiles; j++) {
1393            for (int i = 0; i < xTiles; i++) {
1394                // This lets our ultimate Sink determine the best kind of surface.
1395                // E.g., if it's a GpuSink, the surfaces and images are textures.
1396                auto s = canvas->makeSurface(info);
1397                if (!s) {
1398                    s = SkSurface::MakeRaster(info);  // Some canvases can't create surfaces.
1399                }
1400                surfaces.push_back(s);
1401                SkCanvas* c = s->getCanvas();
1402                c->translate(SkIntToScalar(-i * fW),
1403                             SkIntToScalar(-j * fH));  // Line up the canvas with this tile.
1404                mpd.add(c, pic.get());
1405            }
1406        }
1407        mpd.draw();
1408        for (int j = 0; j < yTiles; j++) {
1409            for (int i = 0; i < xTiles; i++) {
1410                sk_sp<SkImage> image(surfaces[i+xTiles*j]->makeImageSnapshot());
1411                canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
1412            }
1413        }
1414        return "";
1415    });
1416}
1417
1418/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1419
1420Error ViaPicture::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1421    auto size = src.size();
1422    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
1423        SkPictureRecorder recorder;
1424        sk_sp<SkPicture> pic;
1425        Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
1426                                                     SkIntToScalar(size.height())));
1427        if (!err.isEmpty()) {
1428            return err;
1429        }
1430        pic = recorder.finishRecordingAsPicture();
1431        canvas->drawPicture(pic);
1432        return check_against_reference(bitmap, src, fSink);
1433    });
1434}
1435
1436/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1437
1438// Draw the Src into two pictures, then draw the second picture into the wrapped Sink.
1439// This tests that any shortcuts we may take while recording that second picture are legal.
1440Error ViaSecondPicture::draw(
1441        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1442    auto size = src.size();
1443    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
1444        SkPictureRecorder recorder;
1445        sk_sp<SkPicture> pic;
1446        for (int i = 0; i < 2; i++) {
1447            Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
1448                                                         SkIntToScalar(size.height())));
1449            if (!err.isEmpty()) {
1450                return err;
1451            }
1452            pic = recorder.finishRecordingAsPicture();
1453        }
1454        canvas->drawPicture(pic);
1455        return check_against_reference(bitmap, src, fSink);
1456    });
1457}
1458
1459/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1460
1461// Draw the Src twice.  This can help exercise caching.
1462Error ViaTwice::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1463    return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) -> Error {
1464        for (int i = 0; i < 2; i++) {
1465            SkAutoCanvasRestore acr(canvas, true/*save now*/);
1466            canvas->clear(SK_ColorTRANSPARENT);
1467            Error err = src.draw(canvas);
1468            if (err.isEmpty()) {
1469                return err;
1470            }
1471        }
1472        return check_against_reference(bitmap, src, fSink);
1473    });
1474}
1475
1476/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1477
1478// This is like SkRecords::Draw, in that it plays back SkRecords ops into a Canvas.
1479// Unlike SkRecords::Draw, it builds a single-op sub-picture out of each Draw-type op.
1480// This is an only-slightly-exaggerated simluation of Blink's Slimming Paint pictures.
1481struct DrawsAsSingletonPictures {
1482    SkCanvas* fCanvas;
1483    const SkDrawableList& fDrawables;
1484    SkRect fBounds;
1485
1486    template <typename T>
1487    void draw(const T& op, SkCanvas* canvas) {
1488        // We must pass SkMatrix::I() as our initial matrix.
1489        // By default SkRecords::Draw() uses the canvas' matrix as its initial matrix,
1490        // which would have the funky effect of applying transforms over and over.
1491        SkRecords::Draw d(canvas, nullptr, fDrawables.begin(), fDrawables.count(), &SkMatrix::I());
1492        d(op);
1493    }
1494
1495    // Draws get their own picture.
1496    template <typename T>
1497    SK_WHEN(T::kTags & SkRecords::kDraw_Tag, void) operator()(const T& op) {
1498        SkPictureRecorder rec;
1499        this->draw(op, rec.beginRecording(fBounds));
1500        sk_sp<SkPicture> pic(rec.finishRecordingAsPicture());
1501        fCanvas->drawPicture(pic);
1502    }
1503
1504    // We'll just issue non-draws directly.
1505    template <typename T>
1506    skstd::enable_if_t<!(T::kTags & SkRecords::kDraw_Tag), void> operator()(const T& op) {
1507        this->draw(op, fCanvas);
1508    }
1509};
1510
1511// Record Src into a picture, then record it into a macro picture with a sub-picture for each draw.
1512// Then play back that macro picture into our wrapped sink.
1513Error ViaSingletonPictures::draw(
1514        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1515    auto size = src.size();
1516    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
1517        // Use low-level (Skia-private) recording APIs so we can read the SkRecord.
1518        SkRecord skr;
1519        SkRecorder recorder(&skr, size.width(), size.height());
1520        Error err = src.draw(&recorder);
1521        if (!err.isEmpty()) {
1522            return err;
1523        }
1524
1525        // Record our macro-picture, with each draw op as its own sub-picture.
1526        SkPictureRecorder macroRec;
1527        SkCanvas* macroCanvas = macroRec.beginRecording(SkIntToScalar(size.width()),
1528                                                        SkIntToScalar(size.height()));
1529
1530        SkAutoTDelete<SkDrawableList> drawables(recorder.detachDrawableList());
1531        const SkDrawableList empty;
1532
1533        DrawsAsSingletonPictures drawsAsSingletonPictures = {
1534            macroCanvas,
1535            drawables ? *drawables : empty,
1536            SkRect::MakeWH((SkScalar)size.width(), (SkScalar)size.height()),
1537        };
1538        for (int i = 0; i < skr.count(); i++) {
1539            skr.visit(i, drawsAsSingletonPictures);
1540        }
1541        sk_sp<SkPicture> macroPic(macroRec.finishRecordingAsPicture());
1542
1543        canvas->drawPicture(macroPic);
1544        return check_against_reference(bitmap, src, fSink);
1545    });
1546}
1547
1548}  // namespace DM
1549