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 "SkMultiPictureDocumentReader.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         kIndex8_Always_DstColorType,
    131         kGrayscale_Always_DstColorType,
    132         kNonNative8888_Always_DstColorType,
    133     };
    134     CodecSrc(Path, Mode, DstColorType, SkAlphaType, float);
    135 
    136     Error draw(SkCanvas*) const override;
    137     SkISize size() const override;
    138     Name name() const override;
    139     bool veto(SinkFlags) const override;
    140     bool serial() const override { return fRunSerially; }
    141 private:
    142     Path                    fPath;
    143     Mode                    fMode;
    144     DstColorType            fDstColorType;
    145     SkAlphaType             fDstAlphaType;
    146     float                   fScale;
    147     bool                    fRunSerially;
    148 };
    149 
    150 class AndroidCodecSrc : public Src {
    151 public:
    152     AndroidCodecSrc(Path, CodecSrc::DstColorType, SkAlphaType, int sampleSize);
    153 
    154     Error draw(SkCanvas*) const override;
    155     SkISize size() const override;
    156     Name name() const override;
    157     bool veto(SinkFlags) const override;
    158     bool serial() const override { return fRunSerially; }
    159 private:
    160     Path                    fPath;
    161     CodecSrc::DstColorType  fDstColorType;
    162     SkAlphaType             fDstAlphaType;
    163     int                     fSampleSize;
    164     bool                    fRunSerially;
    165 };
    166 
    167 // Allows for testing of various implementations of Android's BitmapRegionDecoder
    168 class BRDSrc : public Src {
    169 public:
    170     enum Mode {
    171         // Decode the entire image as one region.
    172         kFullImage_Mode,
    173         // Splits the image into multiple regions using a divisor and decodes the regions
    174         // separately.  Also, this test adds a border of a few pixels to each of the regions
    175         // that it is decoding.  This tests the behavior when a client asks for a region that
    176         // does not fully fit in the image.
    177         kDivisor_Mode,
    178     };
    179 
    180     BRDSrc(Path, Mode, CodecSrc::DstColorType, uint32_t);
    181 
    182     Error draw(SkCanvas*) const override;
    183     SkISize size() const override;
    184     Name name() const override;
    185     bool veto(SinkFlags) const override;
    186 private:
    187     Path                                     fPath;
    188     Mode                                     fMode;
    189     CodecSrc::DstColorType                   fDstColorType;
    190     uint32_t                                 fSampleSize;
    191 };
    192 
    193 class ImageGenSrc : public Src {
    194 public:
    195     enum Mode {
    196         kCodec_Mode,    // Use CodecImageGenerator
    197         kPlatform_Mode, // Uses CG or WIC
    198     };
    199     ImageGenSrc(Path, Mode, SkAlphaType, bool);
    200 
    201     Error draw(SkCanvas*) const override;
    202     SkISize size() const override;
    203     Name name() const override;
    204     bool veto(SinkFlags) const override;
    205     bool serial() const override { return fRunSerially; }
    206 private:
    207     Path        fPath;
    208     Mode        fMode;
    209     SkAlphaType fDstAlphaType;
    210     bool        fIsGpu;
    211     bool        fRunSerially;
    212 };
    213 
    214 class ColorCodecSrc : public Src {
    215 public:
    216     enum Mode {
    217         // Mimic legacy behavior and apply no color correction.
    218         kBaseline_Mode,
    219 
    220         // Color correct images into a specific dst color space.  If you happen to have this
    221         // monitor, you're in luck!  The unmarked outputs of this test should display
    222         // correctly on this monitor in the Chrome browser.  If not, it's useful to know
    223         // that this monitor has a profile that is fairly similar to Adobe RGB.
    224         kDst_HPZR30w_Mode,
    225 
    226         kDst_sRGB_Mode,
    227     };
    228 
    229     ColorCodecSrc(Path, Mode, SkColorType);
    230 
    231     Error draw(SkCanvas*) const override;
    232     SkISize size() const override;
    233     Name name() const override;
    234     bool veto(SinkFlags) const override;
    235 private:
    236     Path                    fPath;
    237     Mode                    fMode;
    238     SkColorType             fColorType;
    239 };
    240 
    241 class SKPSrc : public Src {
    242 public:
    243     explicit SKPSrc(Path path);
    244 
    245     Error draw(SkCanvas*) const override;
    246     SkISize size() const override;
    247     Name name() const override;
    248 private:
    249     Path fPath;
    250 };
    251 
    252 #if defined(SK_XML)
    253 } // namespace DM
    254 
    255 class SkSVGDOM;
    256 
    257 namespace DM {
    258 
    259 class SVGSrc : public Src {
    260 public:
    261     explicit SVGSrc(Path path);
    262 
    263     Error draw(SkCanvas*) const override;
    264     SkISize size() const override;
    265     Name name() const override;
    266     bool veto(SinkFlags) const override;
    267 
    268 private:
    269     Name            fName;
    270     sk_sp<SkSVGDOM> fDom;
    271     SkScalar        fScale;
    272 
    273     typedef Src INHERITED;
    274 };
    275 #endif // SK_XML
    276 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    277 
    278 class MSKPSrc : public Src {
    279 public:
    280     explicit MSKPSrc(Path path);
    281 
    282     int pageCount() const override;
    283     Error draw(SkCanvas* c) const override;
    284     Error draw(int, SkCanvas*) const override;
    285     SkISize size() const override;
    286     SkISize size(int) const override;
    287     Name name() const override;
    288 
    289 private:
    290     Path fPath;
    291     SkMultiPictureDocumentReader fReader;
    292 };
    293 
    294 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    295 
    296 class NullSink : public Sink {
    297 public:
    298     NullSink() {}
    299 
    300     Error draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override;
    301     const char* fileExtension() const override { return ""; }
    302     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; }
    303 };
    304 
    305 
    306 class GPUSink : public Sink {
    307 public:
    308     GPUSink(sk_gpu_test::GrContextFactory::ContextType,
    309             sk_gpu_test::GrContextFactory::ContextOverrides,
    310             int samples, bool diText, SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
    311             bool threaded);
    312 
    313     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
    314     bool serial() const override { return !fThreaded; }
    315     const char* fileExtension() const override { return "png"; }
    316     SinkFlags flags() const override {
    317         SinkFlags::Multisampled ms = fSampleCount > 0 ? SinkFlags::kMultisampled
    318                                                       : SinkFlags::kNotMultisampled;
    319         return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect, ms };
    320     }
    321 private:
    322     sk_gpu_test::GrContextFactory::ContextType        fContextType;
    323     sk_gpu_test::GrContextFactory::ContextOverrides   fContextOverrides;
    324     int                                               fSampleCount;
    325     bool                                              fUseDIText;
    326     SkColorType                                       fColorType;
    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