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