• 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 "gm/gm.h"
12 #include "include/android/SkBitmapRegionDecoder.h"
13 #include "include/core/SkBBHFactory.h"
14 #include "include/core/SkBitmap.h"
15 #include "include/core/SkCanvas.h"
16 #include "include/core/SkData.h"
17 #include "include/core/SkPicture.h"
18 #include "src/core/SkBBoxHierarchy.h"
19 #include "src/utils/SkMultiPictureDocument.h"
20 #include "tools/flags/CommonFlagsConfig.h"
21 #include "tools/gpu/MemoryCache.h"
22 
23 //#define TEST_VIA_SVG
24 
25 namespace DM {
26 
27 // This is just convenience.  It lets you use either return "foo" or return SkStringPrintf(...).
28 struct ImplicitString : public SkString {
29     template <typename T>
ImplicitStringImplicitString30     ImplicitString(const T& s) : SkString(s) {}
ImplicitStringImplicitString31     ImplicitString() : SkString("") {}
32 };
33 typedef ImplicitString Name;
34 typedef ImplicitString Path;
35 
36 class Error {
37 public:
Error(const SkString & s)38     Error(const SkString& s) : fMsg(s), fFatal(!this->isEmpty()) {}
Error(const char * s)39     Error(const char* s)     : fMsg(s), fFatal(!this->isEmpty()) {}
40 
41     Error(const Error&)            = default;
42     Error& operator=(const Error&) = default;
43 
Nonfatal(const SkString & s)44     static Error Nonfatal(const SkString& s) { return Nonfatal(s.c_str()); }
Nonfatal(const char * s)45     static Error Nonfatal(const char* s) {
46         Error e(s);
47         e.fFatal = false;
48         return e;
49     }
50 
c_str()51     const char* c_str() const { return fMsg.c_str(); }
isEmpty()52     bool isEmpty() const { return fMsg.isEmpty(); }
isFatal()53     bool isFatal() const { return fFatal; }
54 
55 private:
56     SkString fMsg;
57     bool     fFatal;
58 };
59 
60 struct SinkFlags {
61     enum Type { kNull, kGPU, kVector, kRaster } type;
62     enum Approach { kDirect, kIndirect } approach;
63     enum Multisampled { kNotMultisampled, kMultisampled } multisampled;
64     SinkFlags(Type t, Approach a, Multisampled ms = kNotMultisampled)
typeSinkFlags65             : type(t), approach(a), multisampled(ms) {}
66 };
67 
68 struct Src {
~SrcSrc69     virtual ~Src() {}
70     virtual Error SK_WARN_UNUSED_RESULT draw(SkCanvas*) const = 0;
71     virtual SkISize size() const = 0;
72     virtual Name name() const = 0;
modifyGrContextOptionsSrc73     virtual void modifyGrContextOptions(GrContextOptions* options) const {}
vetoSrc74     virtual bool veto(SinkFlags) const { return false; }
75 
pageCountSrc76     virtual int pageCount() const { return 1; }
drawSrc77     virtual Error SK_WARN_UNUSED_RESULT draw(int, SkCanvas* canvas) const {
78         return this->draw(canvas);
79     }
sizeSrc80     virtual SkISize size(int) const { return this->size(); }
81     // Force Tasks using this Src to run on the main thread?
serialSrc82     virtual bool serial() const { return false; }
83 };
84 
85 struct Sink {
~SinkSink86     virtual ~Sink() {}
87     // You may write to either the bitmap or stream.  If you write to log, we'll print that out.
88     virtual Error SK_WARN_UNUSED_RESULT draw(const Src&, SkBitmap*, SkWStream*, SkString* log)
89         const = 0;
90 
91     // Force Tasks using this Sink to run on the main thread?
serialSink92     virtual bool serial() const { return false; }
93 
94     // File extension for the content draw() outputs, e.g. "png", "pdf".
95     virtual const char* fileExtension() const  = 0;
96 
97     virtual SinkFlags flags() const = 0;
98 };
99 
100 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
101 
102 class GMSrc : public Src {
103 public:
104     explicit GMSrc(skiagm::GMFactory);
105 
106     Error draw(SkCanvas*) const override;
107     SkISize size() const override;
108     Name name() const override;
109     void modifyGrContextOptions(GrContextOptions* options) const override;
110 
111 private:
112     skiagm::GMFactory fFactory;
113 };
114 
115 class CodecSrc : public Src {
116 public:
117     enum Mode {
118         kCodec_Mode,
119         // We choose to test only one mode with zero initialized memory.
120         // This will exercise all of the interesting cases in SkSwizzler
121         // without doubling the size of our test suite.
122         kCodecZeroInit_Mode,
123         kScanline_Mode,
124         kStripe_Mode, // Tests the skipping of scanlines
125         kCroppedScanline_Mode, // Tests (jpeg) cropped scanline optimization
126         kSubset_Mode, // For codecs that support subsets directly.
127         kAnimated_Mode, // For codecs that support animation.
128     };
129     enum DstColorType {
130         kGetFromCanvas_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;
veto(SinkFlags)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;
veto(SinkFlags)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;
veto(SinkFlags)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     ColorCodecSrc(Path, bool decode_to_dst);
217 
218     Error draw(SkCanvas*) const override;
219     SkISize size() const override;
220     Name name() const override;
221     bool veto(SinkFlags) const override;
222 private:
223     Path fPath;
224     bool fDecodeToDst;
225 };
226 
227 class SKPSrc : public Src {
228 public:
229     explicit SKPSrc(Path path);
230 
231     Error draw(SkCanvas*) const override;
232     SkISize size() const override;
233     Name name() const override;
234 private:
235     Path fPath;
236 };
237 
238 // This class extracts all the paths from an SKP and then removes unwanted paths according to the
239 // provided l/r trail. It then just draws the remaining paths. (Non-path draws are thrown out.) It
240 // is useful for finding a reduced repo case for path drawing bugs.
241 class BisectSrc : public SKPSrc {
242 public:
243     explicit BisectSrc(Path path, const char* trail);
244 
245     Error draw(SkCanvas*) const override;
246 
247 private:
248     SkString fTrail;
249 
250     typedef SKPSrc INHERITED;
251 };
252 
253 
254 #if defined(SK_ENABLE_SKOTTIE)
255 class SkottieSrc final : public Src {
256 public:
257     explicit SkottieSrc(Path path);
258 
259     Error draw(SkCanvas*) const override;
260     SkISize size() const override;
261     Name name() const override;
262     bool veto(SinkFlags) const override;
263 
264 private:
265     // Generates a kTileCount x kTileCount filmstrip with evenly distributed frames.
266     static constexpr int      kTileCount = 5;
267 
268     // Fit kTileCount x kTileCount frames to a 1000x1000 film strip.
269     static constexpr SkScalar kTargetSize = 1000;
270     static constexpr SkScalar kTileSize = kTargetSize / kTileCount;
271 
272     Path                      fPath;
273 };
274 #endif
275 
276 #if defined(SK_XML)
277 } // namespace DM
278 
279 class SkSVGDOM;
280 
281 namespace DM {
282 
283 class SVGSrc : public Src {
284 public:
285     explicit SVGSrc(Path path);
286 
287     Error draw(SkCanvas*) const override;
288     SkISize size() const override;
289     Name name() const override;
290     bool veto(SinkFlags) const override;
291 
292 private:
293     Name            fName;
294     sk_sp<SkSVGDOM> fDom;
295     SkScalar        fScale;
296 
297     typedef Src INHERITED;
298 };
299 #endif // SK_XML
300 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
301 
302 class MSKPSrc : public Src {
303 public:
304     explicit MSKPSrc(Path path);
305 
306     int pageCount() const override;
307     Error draw(SkCanvas* c) const override;
308     Error draw(int, SkCanvas*) const override;
309     SkISize size() const override;
310     SkISize size(int) const override;
311     Name name() const override;
312 
313 private:
314     Path fPath;
315     mutable SkTArray<SkDocumentPage> fPages;
316 };
317 
318 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
319 
320 class NullSink : public Sink {
321 public:
NullSink()322     NullSink() {}
323 
324     Error draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()325     const char* fileExtension() const override { return ""; }
flags()326     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; }
327 };
328 
329 class GPUSink : public Sink {
330 public:
331     GPUSink(sk_gpu_test::GrContextFactory::ContextType,
332             sk_gpu_test::GrContextFactory::ContextOverrides,
333             SkCommandLineConfigGpu::SurfType surfType, int samples, bool diText,
334             SkColorType colorType, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace,
335             bool threaded, const GrContextOptions& grCtxOptions);
336 
337     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
338     Error onDraw(const Src&, SkBitmap*, SkWStream*, SkString*,
339                  const GrContextOptions& baseOptions) const;
340 
contextType()341     sk_gpu_test::GrContextFactory::ContextType contextType() const { return fContextType; }
contextOverrides()342     const sk_gpu_test::GrContextFactory::ContextOverrides& contextOverrides() {
343         return fContextOverrides;
344     }
surfType()345     SkCommandLineConfigGpu::SurfType surfType() const { return fSurfType; }
useDIText()346     bool useDIText() const { return fUseDIText; }
serial()347     bool serial() const override { return !fThreaded; }
fileExtension()348     const char* fileExtension() const override { return "png"; }
flags()349     SinkFlags flags() const override {
350         SinkFlags::Multisampled ms = fSampleCount > 1 ? SinkFlags::kMultisampled
351                                                       : SinkFlags::kNotMultisampled;
352         return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect, ms };
353     }
baseContextOptions()354     const GrContextOptions& baseContextOptions() const { return fBaseContextOptions; }
355 
356 private:
357     sk_gpu_test::GrContextFactory::ContextType        fContextType;
358     sk_gpu_test::GrContextFactory::ContextOverrides   fContextOverrides;
359     SkCommandLineConfigGpu::SurfType                  fSurfType;
360     int                                               fSampleCount;
361     bool                                              fUseDIText;
362     SkColorType                                       fColorType;
363     SkAlphaType                                       fAlphaType;
364     sk_sp<SkColorSpace>                               fColorSpace;
365     bool                                              fThreaded;
366     GrContextOptions                                  fBaseContextOptions;
367     sk_gpu_test::MemoryCache                          fMemoryCache;
368 };
369 
370 class GPUThreadTestingSink : public GPUSink {
371 public:
372     GPUThreadTestingSink(sk_gpu_test::GrContextFactory::ContextType,
373                          sk_gpu_test::GrContextFactory::ContextOverrides,
374                          SkCommandLineConfigGpu::SurfType surfType, 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 GPUPersistentCacheTestingSink : public GPUSink {
393 public:
394     GPUPersistentCacheTestingSink(sk_gpu_test::GrContextFactory::ContextType,
395                                   sk_gpu_test::GrContextFactory::ContextOverrides,
396                                   SkCommandLineConfigGpu::SurfType surfType, int samples,
397                                   bool diText, SkColorType colorType, SkAlphaType alphaType,
398                                   sk_sp<SkColorSpace> colorSpace, bool threaded,
399                                   const GrContextOptions& grCtxOptions,
400                                   int cacheType);
401 
402     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
403 
fileExtension()404     const char* fileExtension() const override {
405         // Suppress writing out results from this config - we just want to do our matching test
406         return nullptr;
407     }
408 
409 private:
410     int fCacheType;
411 
412     typedef GPUSink INHERITED;
413 };
414 
415 class PDFSink : public Sink {
416 public:
PDFSink(bool pdfa,SkScalar rasterDpi)417     PDFSink(bool pdfa, SkScalar rasterDpi) : fPDFA(pdfa), fRasterDpi(rasterDpi) {}
418     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()419     const char* fileExtension() const override { return "pdf"; }
flags()420     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
421     bool fPDFA;
422     SkScalar fRasterDpi;
423 };
424 
425 class XPSSink : public Sink {
426 public:
427     XPSSink();
428 
429     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()430     const char* fileExtension() const override { return "xps"; }
flags()431     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
432 };
433 
434 class RasterSink : public Sink {
435 public:
436     explicit RasterSink(SkColorType, sk_sp<SkColorSpace> = nullptr);
437 
438     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()439     const char* fileExtension() const override { return "png"; }
flags()440     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; }
441 
442 private:
443     SkColorType         fColorType;
444     sk_sp<SkColorSpace> fColorSpace;
445 };
446 
447 class ThreadedSink : public RasterSink {
448 public:
449     explicit ThreadedSink(SkColorType, sk_sp<SkColorSpace> = nullptr);
450     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
451 };
452 
453 class SKPSink : public Sink {
454 public:
455     SKPSink();
456 
457     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()458     const char* fileExtension() const override { return "skp"; }
flags()459     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
460 };
461 
462 class DebugSink : public Sink {
463 public:
464     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()465     const char* fileExtension() const override { return "json"; }
flags()466     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
467 };
468 
469 class SVGSink : public Sink {
470 public:
471     SVGSink(int pageIndex = 0);
472 
473     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()474     const char* fileExtension() const override { return "svg"; }
flags()475     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
476 
477 private:
478     int fPageIndex;
479 };
480 
481 
482 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
483 
484 class Via : public Sink {
485 public:
Via(Sink * sink)486     explicit Via(Sink* sink) : fSink(sink) {}
fileExtension()487     const char* fileExtension() const override { return fSink->fileExtension(); }
serial()488     bool               serial() const override { return fSink->serial(); }
flags()489     SinkFlags flags() const override {
490         SinkFlags flags = fSink->flags();
491         flags.approach = SinkFlags::kIndirect;
492         return flags;
493     }
494 protected:
495     std::unique_ptr<Sink> fSink;
496 };
497 
498 class ViaMatrix : public Via {
499 public:
500     ViaMatrix(SkMatrix, Sink*);
501     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
502 private:
503     const SkMatrix fMatrix;
504 };
505 
506 class ViaUpright : public Via {
507 public:
508     ViaUpright(SkMatrix, Sink*);
509     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
510 private:
511     const SkMatrix fMatrix;
512 };
513 
514 class ViaSerialization : public Via {
515 public:
ViaSerialization(Sink * sink)516     explicit ViaSerialization(Sink* sink) : Via(sink) {}
517     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
518 };
519 
520 class ViaPicture : public Via {
521 public:
ViaPicture(Sink * sink)522     explicit ViaPicture(Sink* sink) : Via(sink) {}
523     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
524 };
525 
526 class ViaTiles : public Via {
527 public:
528     ViaTiles(int w, int h, SkBBHFactory*, Sink*);
529     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
530 private:
531     const int                   fW, fH;
532     std::unique_ptr<SkBBHFactory> fFactory;
533 };
534 
535 class ViaDDL : public Via {
536 public:
537     ViaDDL(int numReplays, int numDivisions, Sink* sink);
538     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
539 private:
540     const int fNumReplays;
541     const int fNumDivisions;
542 };
543 
544 class ViaSVG : public Via {
545 public:
ViaSVG(Sink * sink)546     explicit ViaSVG(Sink* sink) : Via(sink) {}
547     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
548 };
549 
550 }  // namespace DM
551 
552 #endif//DMSrcSink_DEFINED
553