Home | History | Annotate | Download | only in dm
      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 #ifndef DMSrcSink_DEFINED
      9 #define DMSrcSink_DEFINED
     10 
     11 #include "DMGpuSupport.h"
     12 #include "SkBBHFactory.h"
     13 #include "SkBBoxHierarchy.h"
     14 #include "SkBitmap.h"
     15 #include "SkBitmapRegionDecoder.h"
     16 #include "SkCanvas.h"
     17 #include "SkData.h"
     18 #include "SkMultiPictureDocument.h"
     19 #include "SkPicture.h"
     20 #include "gm.h"
     21 
     22 //#define TEST_VIA_SVG
     23 
     24 namespace skottie { class Animation; }
     25 
     26 namespace DM {
     27 
     28 // This is just convenience.  It lets you use either return "foo" or return SkStringPrintf(...).
     29 struct ImplicitString : public SkString {
     30     template <typename T>
     31     ImplicitString(const T& s) : SkString(s) {}
     32     ImplicitString() : SkString("") {}
     33 };
     34 typedef ImplicitString Name;
     35 typedef ImplicitString Path;
     36 
     37 class Error {
     38 public:
     39     Error(const SkString& s) : fMsg(s), fFatal(!this->isEmpty()) {}
     40     Error(const char* s)     : fMsg(s), fFatal(!this->isEmpty()) {}
     41 
     42     Error(const Error&)            = default;
     43     Error& operator=(const Error&) = default;
     44 
     45     static Error Nonfatal(const SkString& s) { return Nonfatal(s.c_str()); }
     46     static Error Nonfatal(const char* s) {
     47         Error e(s);
     48         e.fFatal = false;
     49         return e;
     50     }
     51 
     52     const char* c_str() const { return fMsg.c_str(); }
     53     bool isEmpty() const { return fMsg.isEmpty(); }
     54     bool isFatal() const { return fFatal; }
     55 
     56 private:
     57     SkString fMsg;
     58     bool     fFatal;
     59 };
     60 
     61 struct SinkFlags {
     62     enum Type { kNull, kGPU, kVector, kRaster } type;
     63     enum Approach { kDirect, kIndirect } approach;
     64     enum Multisampled { kNotMultisampled, kMultisampled } multisampled;
     65     SinkFlags(Type t, Approach a, Multisampled ms = kNotMultisampled)
     66             : type(t), approach(a), multisampled(ms) {}
     67 };
     68 
     69 struct Src {
     70     virtual ~Src() {}
     71     virtual Error SK_WARN_UNUSED_RESULT draw(SkCanvas*) const = 0;
     72     virtual SkISize size() const = 0;
     73     virtual Name name() const = 0;
     74     virtual void modifyGrContextOptions(GrContextOptions* options) const {}
     75     virtual bool veto(SinkFlags) const { return false; }
     76 
     77     virtual int pageCount() const { return 1; }
     78     virtual Error SK_WARN_UNUSED_RESULT draw(int, SkCanvas* canvas) const {
     79         return this->draw(canvas);
     80     }
     81     virtual SkISize size(int) const { return this->size(); }
     82     // Force Tasks using this Src to run on the main thread?
     83     virtual bool serial() const { return false; }
     84 };
     85 
     86 struct Sink {
     87     virtual ~Sink() {}
     88     // You may write to either the bitmap or stream.  If you write to log, we'll print that out.
     89     virtual Error SK_WARN_UNUSED_RESULT draw(const Src&, SkBitmap*, SkWStream*, SkString* log)
     90         const = 0;
     91 
     92     // Force Tasks using this Sink to run on the main thread?
     93     virtual bool serial() const { return false; }
     94 
     95     // File extension for the content draw() outputs, e.g. "png", "pdf".
     96     virtual const char* fileExtension() const  = 0;
     97 
     98     virtual SinkFlags flags() const = 0;
     99 };
    100 
    101 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    102 
    103 class GMSrc : public Src {
    104 public:
    105     explicit GMSrc(skiagm::GMRegistry::Factory);
    106 
    107     Error draw(SkCanvas*) const override;
    108     SkISize size() const override;
    109     Name name() const override;
    110     void modifyGrContextOptions(GrContextOptions* options) const override;
    111 
    112 private:
    113     skiagm::GMRegistry::Factory fFactory;
    114 };
    115 
    116 class CodecSrc : public Src {
    117 public:
    118     enum Mode {
    119         kCodec_Mode,
    120         // We choose to test only one mode with zero initialized memory.
    121         // This will exercise all of the interesting cases in SkSwizzler
    122         // without doubling the size of our test suite.
    123         kCodecZeroInit_Mode,
    124         kScanline_Mode,
    125         kStripe_Mode, // Tests the skipping of scanlines
    126         kCroppedScanline_Mode, // Tests (jpeg) cropped scanline optimization
    127         kSubset_Mode, // For codecs that support subsets directly.
    128         kAnimated_Mode, // For codecs that support animation.
    129     };
    130     enum DstColorType {
    131         kGetFromCanvas_DstColorType,
    132         kGrayscale_Always_DstColorType,
    133         kNonNative8888_Always_DstColorType,
    134     };
    135     CodecSrc(Path, Mode, DstColorType, SkAlphaType, float);
    136 
    137     Error draw(SkCanvas*) const override;
    138     SkISize size() const override;
    139     Name name() const override;
    140     bool veto(SinkFlags) const override;
    141     bool serial() const override { return fRunSerially; }
    142 private:
    143     Path                    fPath;
    144     Mode                    fMode;
    145     DstColorType            fDstColorType;
    146     SkAlphaType             fDstAlphaType;
    147     float                   fScale;
    148     bool                    fRunSerially;
    149 };
    150 
    151 class AndroidCodecSrc : public Src {
    152 public:
    153     AndroidCodecSrc(Path, CodecSrc::DstColorType, SkAlphaType, int sampleSize);
    154 
    155     Error draw(SkCanvas*) const override;
    156     SkISize size() const override;
    157     Name name() const override;
    158     bool veto(SinkFlags) const override;
    159     bool serial() const override { return fRunSerially; }
    160 private:
    161     Path                    fPath;
    162     CodecSrc::DstColorType  fDstColorType;
    163     SkAlphaType             fDstAlphaType;
    164     int                     fSampleSize;
    165     bool                    fRunSerially;
    166 };
    167 
    168 // Allows for testing of various implementations of Android's BitmapRegionDecoder
    169 class BRDSrc : public Src {
    170 public:
    171     enum Mode {
    172         // Decode the entire image as one region.
    173         kFullImage_Mode,
    174         // Splits the image into multiple regions using a divisor and decodes the regions
    175         // separately.  Also, this test adds a border of a few pixels to each of the regions
    176         // that it is decoding.  This tests the behavior when a client asks for a region that
    177         // does not fully fit in the image.
    178         kDivisor_Mode,
    179     };
    180 
    181     BRDSrc(Path, Mode, CodecSrc::DstColorType, uint32_t);
    182 
    183     Error draw(SkCanvas*) const override;
    184     SkISize size() const override;
    185     Name name() const override;
    186     bool veto(SinkFlags) const override;
    187 private:
    188     Path                                     fPath;
    189     Mode                                     fMode;
    190     CodecSrc::DstColorType                   fDstColorType;
    191     uint32_t                                 fSampleSize;
    192 };
    193 
    194 class ImageGenSrc : public Src {
    195 public:
    196     enum Mode {
    197         kCodec_Mode,    // Use CodecImageGenerator
    198         kPlatform_Mode, // Uses CG or WIC
    199     };
    200     ImageGenSrc(Path, Mode, SkAlphaType, bool);
    201 
    202     Error draw(SkCanvas*) const override;
    203     SkISize size() const override;
    204     Name name() const override;
    205     bool veto(SinkFlags) const override;
    206     bool serial() const override { return fRunSerially; }
    207 private:
    208     Path        fPath;
    209     Mode        fMode;
    210     SkAlphaType fDstAlphaType;
    211     bool        fIsGpu;
    212     bool        fRunSerially;
    213 };
    214 
    215 class ColorCodecSrc : public Src {
    216 public:
    217     enum Mode {
    218         // Mimic legacy behavior and apply no color correction.
    219         kBaseline_Mode,
    220 
    221         // Color correct images into a specific dst color space.  If you happen to have this
    222         // monitor, you're in luck!  The unmarked outputs of this test should display
    223         // correctly on this monitor in the Chrome browser.  If not, it's useful to know
    224         // that this monitor has a profile that is fairly similar to Adobe RGB.
    225         kDst_HPZR30w_Mode,
    226 
    227         kDst_sRGB_Mode,
    228     };
    229 
    230     ColorCodecSrc(Path, Mode, SkColorType);
    231 
    232     Error draw(SkCanvas*) const override;
    233     SkISize size() const override;
    234     Name name() const override;
    235     bool veto(SinkFlags) const override;
    236 private:
    237     Path                    fPath;
    238     Mode                    fMode;
    239     SkColorType             fColorType;
    240 };
    241 
    242 class SKPSrc : public Src {
    243 public:
    244     explicit SKPSrc(Path path);
    245 
    246     Error draw(SkCanvas*) const override;
    247     SkISize size() const override;
    248     Name name() const override;
    249 private:
    250     Path fPath;
    251 };
    252 
    253 // DeferredDisplayList flavor
    254 class DDLSKPSrc : public Src {
    255 public:
    256     explicit DDLSKPSrc(Path path);
    257 
    258     Error draw(SkCanvas*) const override;
    259     SkISize size() const override;
    260     Name name() const override;
    261 private:
    262     Path fPath;
    263 };
    264 
    265 #if !defined(SK_BUILD_FOR_GOOGLE3)
    266 class SkottieSrc final : public Src {
    267 public:
    268     explicit SkottieSrc(Path path);
    269 
    270     Error draw(SkCanvas*) const override;
    271     SkISize size() const override;
    272     Name name() const override;
    273     bool veto(SinkFlags) const override;
    274 
    275 private:
    276     // Generates a kTileCount x kTileCount filmstrip with evenly distributed frames.
    277     static constexpr int      kTileCount = 5;
    278 
    279     Name                      fName;
    280     SkISize                   fTileSize = SkISize::MakeEmpty();
    281     sk_sp<skottie::Animation> fAnimation;
    282 };
    283 #endif
    284 
    285 #if defined(SK_XML)
    286 } // namespace DM
    287 
    288 class SkSVGDOM;
    289 
    290 namespace DM {
    291 
    292 class SVGSrc : public Src {
    293 public:
    294     explicit SVGSrc(Path path);
    295 
    296     Error draw(SkCanvas*) const override;
    297     SkISize size() const override;
    298     Name name() const override;
    299     bool veto(SinkFlags) const override;
    300 
    301 private:
    302     Name            fName;
    303     sk_sp<SkSVGDOM> fDom;
    304     SkScalar        fScale;
    305 
    306     typedef Src INHERITED;
    307 };
    308 #endif // SK_XML
    309 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    310 
    311 class MSKPSrc : public Src {
    312 public:
    313     explicit MSKPSrc(Path path);
    314 
    315     int pageCount() const override;
    316     Error draw(SkCanvas* c) const override;
    317     Error draw(int, SkCanvas*) const override;
    318     SkISize size() const override;
    319     SkISize size(int) const override;
    320     Name name() const override;
    321 
    322 private:
    323     Path fPath;
    324     mutable SkTArray<SkDocumentPage> fPages;
    325 };
    326 
    327 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    328 
    329 class NullSink : public Sink {
    330 public:
    331     NullSink() {}
    332 
    333     Error draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override;
    334     const char* fileExtension() const override { return ""; }
    335     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; }
    336 };
    337 
    338 
    339 class GPUSink : public Sink {
    340 public:
    341     GPUSink(sk_gpu_test::GrContextFactory::ContextType,
    342             sk_gpu_test::GrContextFactory::ContextOverrides, int samples, bool diText,
    343             SkColorType colorType, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace,
    344             bool threaded, const GrContextOptions& grCtxOptions);
    345 
    346     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    347     Error onDraw(const Src&, SkBitmap*, SkWStream*, SkString*,
    348                  const GrContextOptions& baseOptions) const;
    349 
    350     bool serial() const override { return !fThreaded; }
    351     const char* fileExtension() const override { return "png"; }
    352     SinkFlags flags() const override {
    353         SinkFlags::Multisampled ms = fSampleCount > 1 ? SinkFlags::kMultisampled
    354                                                       : SinkFlags::kNotMultisampled;
    355         return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect, ms };
    356     }
    357     const GrContextOptions& baseContextOptions() const { return fBaseContextOptions; }
    358 
    359 private:
    360     sk_gpu_test::GrContextFactory::ContextType        fContextType;
    361     sk_gpu_test::GrContextFactory::ContextOverrides   fContextOverrides;
    362     int                                               fSampleCount;
    363     bool                                              fUseDIText;
    364     SkColorType                                       fColorType;
    365     SkAlphaType                                       fAlphaType;
    366     sk_sp<SkColorSpace>                               fColorSpace;
    367     bool                                              fThreaded;
    368     GrContextOptions                                  fBaseContextOptions;
    369 };
    370 
    371 class GPUThreadTestingSink : public GPUSink {
    372 public:
    373     GPUThreadTestingSink(sk_gpu_test::GrContextFactory::ContextType,
    374                          sk_gpu_test::GrContextFactory::ContextOverrides, int samples, bool diText,
    375                          SkColorType colorType, SkAlphaType alphaType,
    376                          sk_sp<SkColorSpace> colorSpace, bool threaded,
    377                          const GrContextOptions& grCtxOptions);
    378 
    379     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    380 
    381     const char* fileExtension() const override {
    382         // Suppress writing out results from this config - we just want to do our matching test
    383         return nullptr;
    384     }
    385 
    386 private:
    387     std::unique_ptr<SkExecutor> fExecutor;
    388 
    389     typedef GPUSink INHERITED;
    390 };
    391 
    392 class PDFSink : public Sink {
    393 public:
    394     PDFSink(bool pdfa, SkScalar rasterDpi) : fPDFA(pdfa), fRasterDpi(rasterDpi) {}
    395     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    396     const char* fileExtension() const override { return "pdf"; }
    397     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
    398     bool fPDFA;
    399     SkScalar fRasterDpi;
    400 };
    401 
    402 class XPSSink : public Sink {
    403 public:
    404     XPSSink();
    405 
    406     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    407     const char* fileExtension() const override { return "xps"; }
    408     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
    409 };
    410 
    411 class PipeSink : public Sink {
    412 public:
    413     PipeSink();
    414 
    415     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    416     const char* fileExtension() const override { return "skpipe"; }
    417     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
    418 };
    419 
    420 class RasterSink : public Sink {
    421 public:
    422     explicit RasterSink(SkColorType, sk_sp<SkColorSpace> = nullptr);
    423 
    424     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    425     const char* fileExtension() const override { return "png"; }
    426     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; }
    427 protected:
    428     void allocPixels(const Src& src, SkBitmap*) const;
    429 
    430     SkColorType         fColorType;
    431     sk_sp<SkColorSpace> fColorSpace;
    432 };
    433 
    434 class ThreadedSink : public RasterSink {
    435 public:
    436     explicit ThreadedSink(SkColorType, sk_sp<SkColorSpace> = nullptr);
    437     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    438 
    439 private:
    440     std::unique_ptr<SkExecutor> fExecutor;
    441 };
    442 
    443 class SKPSink : public Sink {
    444 public:
    445     SKPSink();
    446 
    447     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    448     const char* fileExtension() const override { return "skp"; }
    449     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
    450 };
    451 
    452 class DebugSink : public Sink {
    453 public:
    454     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    455     const char* fileExtension() const override { return "json"; }
    456     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
    457 };
    458 
    459 class SVGSink : public Sink {
    460 public:
    461     SVGSink(int pageIndex = 0);
    462 
    463     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    464     const char* fileExtension() const override { return "svg"; }
    465     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
    466 
    467 private:
    468     int fPageIndex;
    469 };
    470 
    471 
    472 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    473 
    474 class Via : public Sink {
    475 public:
    476     explicit Via(Sink* sink) : fSink(sink) {}
    477     const char* fileExtension() const override { return fSink->fileExtension(); }
    478     bool               serial() const override { return fSink->serial(); }
    479     SinkFlags flags() const override {
    480         SinkFlags flags = fSink->flags();
    481         flags.approach = SinkFlags::kIndirect;
    482         return flags;
    483     }
    484 protected:
    485     std::unique_ptr<Sink> fSink;
    486 };
    487 
    488 class ViaMatrix : public Via {
    489 public:
    490     ViaMatrix(SkMatrix, Sink*);
    491     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    492 private:
    493     const SkMatrix fMatrix;
    494 };
    495 
    496 class ViaUpright : public Via {
    497 public:
    498     ViaUpright(SkMatrix, Sink*);
    499     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    500 private:
    501     const SkMatrix fMatrix;
    502 };
    503 
    504 class ViaSerialization : public Via {
    505 public:
    506     explicit ViaSerialization(Sink* sink) : Via(sink) {}
    507     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    508 };
    509 
    510 class ViaPicture : public Via {
    511 public:
    512     explicit ViaPicture(Sink* sink) : Via(sink) {}
    513     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    514 };
    515 
    516 class ViaPipe : public Via {
    517 public:
    518     explicit ViaPipe(Sink* sink) : Via(sink) {}
    519     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    520 };
    521 
    522 class ViaTiles : public Via {
    523 public:
    524     ViaTiles(int w, int h, SkBBHFactory*, Sink*);
    525     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    526 private:
    527     const int                   fW, fH;
    528     std::unique_ptr<SkBBHFactory> fFactory;
    529 };
    530 
    531 class ViaSVG : public Via {
    532 public:
    533     explicit ViaSVG(Sink* sink) : Via(sink) {}
    534     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    535 };
    536 
    537 class ViaLite : public Via {
    538 public:
    539     explicit ViaLite(Sink* sink) : Via(sink) {}
    540     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    541 };
    542 
    543 class ViaCSXform : public Via {
    544 public:
    545     explicit ViaCSXform(Sink*, sk_sp<SkColorSpace>, bool colorSpin);
    546     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    547 private:
    548     sk_sp<SkColorSpace> fCS;
    549     bool                fColorSpin;
    550 };
    551 
    552 }  // namespace DM
    553 
    554 #endif//DMSrcSink_DEFINED
    555