• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
ImplicitStringImplicitString31     ImplicitString(const T& s) : SkString(s) {}
ImplicitStringImplicitString32     ImplicitString() : SkString("") {}
33 };
34 typedef ImplicitString Name;
35 typedef ImplicitString Path;
36 
37 class Error {
38 public:
Error(const SkString & s)39     Error(const SkString& s) : fMsg(s), fFatal(!this->isEmpty()) {}
Error(const char * s)40     Error(const char* s)     : fMsg(s), fFatal(!this->isEmpty()) {}
41 
42     Error(const Error&)            = default;
43     Error& operator=(const Error&) = default;
44 
Nonfatal(const SkString & s)45     static Error Nonfatal(const SkString& s) { return Nonfatal(s.c_str()); }
Nonfatal(const char * s)46     static Error Nonfatal(const char* s) {
47         Error e(s);
48         e.fFatal = false;
49         return e;
50     }
51 
c_str()52     const char* c_str() const { return fMsg.c_str(); }
isEmpty()53     bool isEmpty() const { return fMsg.isEmpty(); }
isFatal()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)
typeSinkFlags66             : type(t), approach(a), multisampled(ms) {}
67 };
68 
69 struct Src {
~SrcSrc70     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;
modifyGrContextOptionsSrc74     virtual void modifyGrContextOptions(GrContextOptions* options) const {}
vetoSrc75     virtual bool veto(SinkFlags) const { return false; }
76 
pageCountSrc77     virtual int pageCount() const { return 1; }
drawSrc78     virtual Error SK_WARN_UNUSED_RESULT draw(int, SkCanvas* canvas) const {
79         return this->draw(canvas);
80     }
sizeSrc81     virtual SkISize size(int) const { return this->size(); }
82     // Force Tasks using this Src to run on the main thread?
serialSrc83     virtual bool serial() const { return false; }
84 };
85 
86 struct Sink {
~SinkSink87     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?
serialSink93     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;
veto(SinkFlags)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;
veto(SinkFlags)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;
veto(SinkFlags)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     std::unique_ptr<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:
NullSink()331     NullSink() {}
332 
333     Error draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()334     const char* fileExtension() const override { return ""; }
flags()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 
serial()350     bool serial() const override { return !fThreaded; }
fileExtension()351     const char* fileExtension() const override { return "png"; }
flags()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     }
baseContextOptions()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 
fileExtension()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:
PDFSink(bool pdfa,SkScalar rasterDpi)394     PDFSink(bool pdfa, SkScalar rasterDpi) : fPDFA(pdfa), fRasterDpi(rasterDpi) {}
395     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()396     const char* fileExtension() const override { return "pdf"; }
flags()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;
fileExtension()407     const char* fileExtension() const override { return "xps"; }
flags()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;
fileExtension()416     const char* fileExtension() const override { return "skpipe"; }
flags()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;
fileExtension()425     const char* fileExtension() const override { return "png"; }
flags()426     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; }
427 private:
428     SkColorType         fColorType;
429     sk_sp<SkColorSpace> fColorSpace;
430 };
431 
432 class SKPSink : public Sink {
433 public:
434     SKPSink();
435 
436     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()437     const char* fileExtension() const override { return "skp"; }
flags()438     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
439 };
440 
441 class DebugSink : public Sink {
442 public:
443     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()444     const char* fileExtension() const override { return "json"; }
flags()445     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
446 };
447 
448 class SVGSink : public Sink {
449 public:
450     SVGSink();
451 
452     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()453     const char* fileExtension() const override { return "svg"; }
flags()454     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
455 };
456 
457 
458 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
459 
460 class Via : public Sink {
461 public:
Via(Sink * sink)462     explicit Via(Sink* sink) : fSink(sink) {}
fileExtension()463     const char* fileExtension() const override { return fSink->fileExtension(); }
serial()464     bool               serial() const override { return fSink->serial(); }
flags()465     SinkFlags flags() const override {
466         SinkFlags flags = fSink->flags();
467         flags.approach = SinkFlags::kIndirect;
468         return flags;
469     }
470 protected:
471     std::unique_ptr<Sink> fSink;
472 };
473 
474 class ViaMatrix : public Via {
475 public:
476     ViaMatrix(SkMatrix, Sink*);
477     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
478 private:
479     const SkMatrix fMatrix;
480 };
481 
482 class ViaUpright : public Via {
483 public:
484     ViaUpright(SkMatrix, Sink*);
485     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
486 private:
487     const SkMatrix fMatrix;
488 };
489 
490 class ViaSerialization : public Via {
491 public:
ViaSerialization(Sink * sink)492     explicit ViaSerialization(Sink* sink) : Via(sink) {}
493     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
494 };
495 
496 class ViaPicture : public Via {
497 public:
ViaPicture(Sink * sink)498     explicit ViaPicture(Sink* sink) : Via(sink) {}
499     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
500 };
501 
502 class ViaPipe : public Via {
503 public:
ViaPipe(Sink * sink)504     explicit ViaPipe(Sink* sink) : Via(sink) {}
505     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
506 };
507 
508 class ViaTiles : public Via {
509 public:
510     ViaTiles(int w, int h, SkBBHFactory*, Sink*);
511     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
512 private:
513     const int                   fW, fH;
514     std::unique_ptr<SkBBHFactory> fFactory;
515 };
516 
517 class ViaSVG : public Via {
518 public:
ViaSVG(Sink * sink)519     explicit ViaSVG(Sink* sink) : Via(sink) {}
520     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
521 };
522 
523 class ViaLite : public Via {
524 public:
ViaLite(Sink * sink)525     explicit ViaLite(Sink* sink) : Via(sink) {}
526     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
527 };
528 
529 class ViaCSXform : public Via {
530 public:
531     explicit ViaCSXform(Sink*, sk_sp<SkColorSpace>, bool colorSpin);
532     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
533 private:
534     sk_sp<SkColorSpace> fCS;
535     bool                fColorSpin;
536 };
537 
538 }  // namespace DM
539 
540 #endif//DMSrcSink_DEFINED
541