• 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/utils/SkMultiPictureDocument.h"
19 #include "tools/flags/CommonFlagsConfig.h"
20 #include "tools/gpu/MemoryCache.h"
21 
22 #include <functional>
23 
24 //#define TEST_VIA_SVG
25 
26 namespace skiagm {
27 namespace verifiers {
28 class VerifierList;
29 }
30 }
31 
32 namespace DM {
33 
34 // This is just convenience.  It lets you use either return "foo" or return SkStringPrintf(...).
35 struct ImplicitString : public SkString {
36     template <typename T>
ImplicitStringImplicitString37     ImplicitString(const T& s) : SkString(s) {}
ImplicitStringImplicitString38     ImplicitString() : SkString("") {}
39 };
40 typedef ImplicitString Name;
41 typedef ImplicitString Path;
42 
43 class Result {
44 public:
45     enum class Status : int { Ok, Fatal, Skip };
Result(Status status,const SkString & s)46     Result(Status status, const SkString& s) : fMsg(s), fStatus(status) {}
Result(Status status,const char * s)47     Result(Status status, const char* s) : fMsg(s), fStatus(status) {}
Result(Status status,const char * s,Args...args)48     template <typename... Args> Result (Status status, const char* s, Args... args)
49         : fMsg(SkStringPrintf(s, args...)), fStatus(status) {}
50 
51     Result(const Result&)            = default;
52     Result& operator=(const Result&) = default;
53 
Ok()54     static Result Ok() { return Result(Status::Ok, nullptr); }
55 
Fatal(const SkString & s)56     static Result Fatal(const SkString& s) { return Result(Status::Fatal, s); }
Fatal(const char * s)57     static Result Fatal(const char* s) { return Result(Status::Fatal, s); }
Fatal(const char * s,Args...args)58     template <typename... Args> static Result Fatal(const char* s, Args... args) {
59         return Result(Status::Fatal, s, args...);
60     }
61 
Skip(const SkString & s)62     static Result Skip(const SkString& s) { return Result(Status::Skip, s); }
Skip(const char * s)63     static Result Skip(const char* s) { return Result(Status::Skip, s); }
Skip(const char * s,Args...args)64     template <typename... Args> static Result Skip(const char* s, Args... args) {
65         return Result(Status::Skip, s, args...);
66     }
67 
isOk()68     bool isOk() { return fStatus == Status::Ok; }
isFatal()69     bool isFatal() { return fStatus == Status::Fatal; }
isSkip()70     bool isSkip() { return fStatus == Status::Skip; }
71 
c_str()72     const char* c_str() const { return fMsg.c_str(); }
status()73     Status status() const { return fStatus; }
74 
75 private:
76     SkString fMsg;
77     Status   fStatus;
78 };
79 
80 struct SinkFlags {
81     enum Type { kNull, kGPU, kVector, kRaster } type;
82     enum Approach { kDirect, kIndirect } approach;
83     enum Multisampled { kNotMultisampled, kMultisampled } multisampled;
84     SinkFlags(Type t, Approach a, Multisampled ms = kNotMultisampled)
typeSinkFlags85             : type(t), approach(a), multisampled(ms) {}
86 };
87 
88 struct Src {
~SrcSrc89     virtual ~Src() {}
90     virtual Result SK_WARN_UNUSED_RESULT draw(SkCanvas*) const = 0;
91     virtual SkISize size() const = 0;
92     virtual Name name() const = 0;
modifyGrContextOptionsSrc93     virtual void modifyGrContextOptions(GrContextOptions* options) const {}
vetoSrc94     virtual bool veto(SinkFlags) const { return false; }
95 
pageCountSrc96     virtual int pageCount() const { return 1; }
drawSrc97     virtual Result SK_WARN_UNUSED_RESULT draw(int, SkCanvas* canvas) const {
98         return this->draw(canvas);
99     }
sizeSrc100     virtual SkISize size(int) const { return this->size(); }
101     // Force Tasks using this Src to run on the main thread?
serialSrc102     virtual bool serial() const { return false; }
103 
104     /** Return a list of verifiers for the src, or null if no verifiers should be run .*/
getVerifiersSrc105     virtual std::unique_ptr<skiagm::verifiers::VerifierList> getVerifiers() const {
106         return nullptr;
107     }
108 };
109 
110 struct Sink {
~SinkSink111     virtual ~Sink() {}
112     // You may write to either the bitmap or stream.  If you write to log, we'll print that out.
113     virtual Result SK_WARN_UNUSED_RESULT draw(const Src&, SkBitmap*, SkWStream*, SkString* log)
114         const = 0;
115 
116     // Force Tasks using this Sink to run on the main thread?
serialSink117     virtual bool serial() const { return false; }
118 
119     // File extension for the content draw() outputs, e.g. "png", "pdf".
120     virtual const char* fileExtension() const  = 0;
121 
122     virtual SinkFlags flags() const = 0;
123 
124     /** Returns the color type and space used by the sink. */
colorInfoSink125     virtual SkColorInfo colorInfo() const { return SkColorInfo(); }
126 };
127 
128 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
129 
130 class GMSrc : public Src {
131 public:
132     explicit GMSrc(skiagm::GMFactory);
133 
134     Result draw(SkCanvas*) const override;
135     SkISize size() const override;
136     Name name() const override;
137     void modifyGrContextOptions(GrContextOptions* options) const override;
138 
139     std::unique_ptr<skiagm::verifiers::VerifierList> getVerifiers() const override;
140 
141 private:
142     skiagm::GMFactory fFactory;
143 };
144 
145 class CodecSrc : public Src {
146 public:
147     enum Mode {
148         kCodec_Mode,
149         // We choose to test only one mode with zero initialized memory.
150         // This will exercise all of the interesting cases in SkSwizzler
151         // without doubling the size of our test suite.
152         kCodecZeroInit_Mode,
153         kScanline_Mode,
154         kStripe_Mode, // Tests the skipping of scanlines
155         kCroppedScanline_Mode, // Tests (jpeg) cropped scanline optimization
156         kSubset_Mode, // For codecs that support subsets directly.
157         kAnimated_Mode, // For codecs that support animation.
158     };
159     enum DstColorType {
160         kGetFromCanvas_DstColorType,
161         kGrayscale_Always_DstColorType,
162         kNonNative8888_Always_DstColorType,
163     };
164     CodecSrc(Path, Mode, DstColorType, SkAlphaType, float);
165 
166     Result draw(SkCanvas*) const override;
167     SkISize size() const override;
168     Name name() const override;
veto(SinkFlags)169     bool veto(SinkFlags) const override;
170     bool serial() const override { return fRunSerially; }
171 private:
172     Path                    fPath;
173     Mode                    fMode;
174     DstColorType            fDstColorType;
175     SkAlphaType             fDstAlphaType;
176     float                   fScale;
177     bool                    fRunSerially;
178 };
179 
180 class AndroidCodecSrc : public Src {
181 public:
182     AndroidCodecSrc(Path, CodecSrc::DstColorType, SkAlphaType, int sampleSize);
183 
184     Result draw(SkCanvas*) const override;
185     SkISize size() const override;
186     Name name() const override;
veto(SinkFlags)187     bool veto(SinkFlags) const override;
188     bool serial() const override { return fRunSerially; }
189 private:
190     Path                    fPath;
191     CodecSrc::DstColorType  fDstColorType;
192     SkAlphaType             fDstAlphaType;
193     int                     fSampleSize;
194     bool                    fRunSerially;
195 };
196 
197 // Allows for testing of various implementations of Android's BitmapRegionDecoder
198 class BRDSrc : public Src {
199 public:
200     enum Mode {
201         // Decode the entire image as one region.
202         kFullImage_Mode,
203         // Splits the image into multiple regions using a divisor and decodes the regions
204         // separately.  Also, this test adds a border of a few pixels to each of the regions
205         // that it is decoding.  This tests the behavior when a client asks for a region that
206         // does not fully fit in the image.
207         kDivisor_Mode,
208     };
209 
210     BRDSrc(Path, Mode, CodecSrc::DstColorType, uint32_t);
211 
212     Result draw(SkCanvas*) const override;
213     SkISize size() const override;
214     Name name() const override;
215     bool veto(SinkFlags) const override;
216 private:
217     Path                                     fPath;
218     Mode                                     fMode;
219     CodecSrc::DstColorType                   fDstColorType;
220     uint32_t                                 fSampleSize;
221 };
222 
223 class ImageGenSrc : public Src {
224 public:
225     enum Mode {
226         kCodec_Mode,    // Use CodecImageGenerator
227         kPlatform_Mode, // Uses CG or WIC
228     };
229     ImageGenSrc(Path, Mode, SkAlphaType, bool);
230 
231     Result draw(SkCanvas*) const override;
232     SkISize size() const override;
233     Name name() const override;
veto(SinkFlags)234     bool veto(SinkFlags) const override;
235     bool serial() const override { return fRunSerially; }
236 private:
237     Path        fPath;
238     Mode        fMode;
239     SkAlphaType fDstAlphaType;
240     bool        fIsGpu;
241     bool        fRunSerially;
242 };
243 
244 class ColorCodecSrc : public Src {
245 public:
246     ColorCodecSrc(Path, bool decode_to_dst);
247 
248     Result draw(SkCanvas*) const override;
249     SkISize size() const override;
250     Name name() const override;
251     bool veto(SinkFlags) const override;
252 private:
253     Path fPath;
254     bool fDecodeToDst;
255 };
256 
257 class SKPSrc : public Src {
258 public:
259     explicit SKPSrc(Path path);
260 
261     Result draw(SkCanvas*) const override;
262     SkISize size() const override;
263     Name name() const override;
264 private:
265     Path fPath;
266 };
267 
268 // This class extracts all the paths from an SKP and then removes unwanted paths according to the
269 // provided l/r trail. It then just draws the remaining paths. (Non-path draws are thrown out.) It
270 // is useful for finding a reduced repo case for path drawing bugs.
271 class BisectSrc : public SKPSrc {
272 public:
273     explicit BisectSrc(Path path, const char* trail);
274 
275     Result draw(SkCanvas*) const override;
276 
277 private:
278     SkString fTrail;
279 
280     typedef SKPSrc INHERITED;
281 };
282 
283 
284 #if defined(SK_ENABLE_SKOTTIE)
285 class SkottieSrc final : public Src {
286 public:
287     explicit SkottieSrc(Path path);
288 
289     Result draw(SkCanvas*) const override;
290     SkISize size() const override;
291     Name name() const override;
292     bool veto(SinkFlags) const override;
293 
294 private:
295     // Generates a kTileCount x kTileCount filmstrip with evenly distributed frames.
296     static constexpr int      kTileCount = 5;
297 
298     // Fit kTileCount x kTileCount frames to a 1000x1000 film strip.
299     static constexpr SkScalar kTargetSize = 1000;
300     static constexpr SkScalar kTileSize = kTargetSize / kTileCount;
301 
302     Path                      fPath;
303 };
304 #endif
305 
306 #if defined(SK_XML)
307 } // namespace DM
308 
309 class SkSVGDOM;
310 
311 namespace DM {
312 
313 class SVGSrc : public Src {
314 public:
315     explicit SVGSrc(Path path);
316 
317     Result draw(SkCanvas*) const override;
318     SkISize size() const override;
319     Name name() const override;
320     bool veto(SinkFlags) const override;
321 
322 private:
323     Name            fName;
324     sk_sp<SkSVGDOM> fDom;
325     SkScalar        fScale;
326 
327     typedef Src INHERITED;
328 };
329 #endif // SK_XML
330 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
331 
332 class MSKPSrc : public Src {
333 public:
334     explicit MSKPSrc(Path path);
335 
336     int pageCount() const override;
337     Result draw(SkCanvas* c) const override;
338     Result draw(int, SkCanvas*) const override;
339     SkISize size() const override;
340     SkISize size(int) const override;
341     Name name() const override;
342 
343 private:
344     Path fPath;
345     mutable SkTArray<SkDocumentPage> fPages;
346 };
347 
348 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
349 
350 class NullSink : public Sink {
351 public:
NullSink()352     NullSink() {}
353 
354     Result draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()355     const char* fileExtension() const override { return ""; }
flags()356     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; }
357 };
358 
359 class GPUSink : public Sink {
360 public:
361     GPUSink(const SkCommandLineConfigGpu*, const GrContextOptions&);
362 
363     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
364     Result onDraw(const Src&, SkBitmap*, SkWStream*, SkString*,
365                   const GrContextOptions& baseOptions,
366                   std::function<void(GrContext*)> initContext = nullptr) const;
367 
contextType()368     sk_gpu_test::GrContextFactory::ContextType contextType() const { return fContextType; }
contextOverrides()369     const sk_gpu_test::GrContextFactory::ContextOverrides& contextOverrides() const {
370         return fContextOverrides;
371     }
surfType()372     SkCommandLineConfigGpu::SurfType surfType() const { return fSurfType; }
useDIText()373     bool useDIText() const { return fUseDIText; }
serial()374     bool serial() const override { return true; }
fileExtension()375     const char* fileExtension() const override { return "png"; }
flags()376     SinkFlags flags() const override {
377         SinkFlags::Multisampled ms = fSampleCount > 1 ? SinkFlags::kMultisampled
378                                                       : SinkFlags::kNotMultisampled;
379         return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect, ms };
380     }
baseContextOptions()381     const GrContextOptions& baseContextOptions() const { return fBaseContextOptions; }
colorInfo()382     SkColorInfo colorInfo() const override {
383         return SkColorInfo(fColorType, fAlphaType, fColorSpace);
384     }
385 
386 protected:
387     sk_sp<SkSurface> createDstSurface(GrContext*, SkISize size, GrBackendTexture*,
388                                       GrBackendRenderTarget*) const;
389     bool readBack(SkSurface*, SkBitmap* dst) const;
390 
391 private:
392     sk_gpu_test::GrContextFactory::ContextType        fContextType;
393     sk_gpu_test::GrContextFactory::ContextOverrides   fContextOverrides;
394     SkCommandLineConfigGpu::SurfType                  fSurfType;
395     int                                               fSampleCount;
396     bool                                              fUseDIText;
397     SkColorType                                       fColorType;
398     SkAlphaType                                       fAlphaType;
399     sk_sp<SkColorSpace>                               fColorSpace;
400     GrContextOptions                                  fBaseContextOptions;
401     sk_gpu_test::MemoryCache                          fMemoryCache;
402 };
403 
404 class GPUThreadTestingSink : public GPUSink {
405 public:
406     GPUThreadTestingSink(const SkCommandLineConfigGpu*, const GrContextOptions&);
407 
408     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
409 
fileExtension()410     const char* fileExtension() const override {
411         // Suppress writing out results from this config - we just want to do our matching test
412         return nullptr;
413     }
414 
415 private:
416     std::unique_ptr<SkExecutor> fExecutor;
417 
418     typedef GPUSink INHERITED;
419 };
420 
421 class GPUPersistentCacheTestingSink : public GPUSink {
422 public:
423     GPUPersistentCacheTestingSink(const SkCommandLineConfigGpu*, const GrContextOptions&);
424 
425     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
426 
fileExtension()427     const char* fileExtension() const override {
428         // Suppress writing out results from this config - we just want to do our matching test
429         return nullptr;
430     }
431 
432 private:
433     int fCacheType;
434 
435     typedef GPUSink INHERITED;
436 };
437 
438 class GPUPrecompileTestingSink : public GPUSink {
439 public:
440     GPUPrecompileTestingSink(const SkCommandLineConfigGpu*, const GrContextOptions&);
441 
442     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
443 
fileExtension()444     const char* fileExtension() const override {
445         // Suppress writing out results from this config - we just want to do our matching test
446         return nullptr;
447     }
448 
449 private:
450     typedef GPUSink INHERITED;
451 };
452 
453 // This sink attempts to better simulate the Chrome DDL use-case. It:
454 //    creates the DDLs on separate recording threads
455 //    performs all the GPU work on a separate GPU thread
456 // In the future this should be expanded to:
457 //    upload on a utility thread w/ access to a shared context
458 //    compile the programs on the utility thread
459 //    perform fine grained scheduling of gpu tasks based on their image and program prerequisites
460 //    create a single "compositing" DDL that is replayed last
461 class GPUDDLSink : public GPUSink {
462 public:
463     GPUDDLSink(const SkCommandLineConfigGpu*, const GrContextOptions&);
464 
465     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
466 
467 private:
468     Result ddlDraw(const Src&,
469                    sk_sp<SkSurface> dstSurface,
470                    SkTaskGroup* recordingTaskGroup,
471                    SkTaskGroup* gpuTaskGroup,
472                    GrContext* gpuCtx) const;
473 
474     std::unique_ptr<SkExecutor> fRecordingThreadPool;
475     std::unique_ptr<SkExecutor> fGPUThread;
476 
477     typedef GPUSink INHERITED;
478 };
479 
480 class PDFSink : public Sink {
481 public:
PDFSink(bool pdfa,SkScalar rasterDpi)482     PDFSink(bool pdfa, SkScalar rasterDpi) : fPDFA(pdfa), fRasterDpi(rasterDpi) {}
483     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()484     const char* fileExtension() const override { return "pdf"; }
flags()485     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
486     bool fPDFA;
487     SkScalar fRasterDpi;
488 };
489 
490 class XPSSink : public Sink {
491 public:
492     XPSSink();
493 
494     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()495     const char* fileExtension() const override { return "xps"; }
flags()496     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
497 };
498 
499 class RasterSink : public Sink {
500 public:
501     explicit RasterSink(SkColorType, sk_sp<SkColorSpace> = nullptr);
502 
503     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()504     const char* fileExtension() const override { return "png"; }
flags()505     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; }
506 
507 private:
508     SkColorType         fColorType;
509     sk_sp<SkColorSpace> fColorSpace;
510 };
511 
512 class ThreadedSink : public RasterSink {
513 public:
514     explicit ThreadedSink(SkColorType, sk_sp<SkColorSpace> = nullptr);
515     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
516 };
517 
518 class SKPSink : public Sink {
519 public:
520     SKPSink();
521 
522     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()523     const char* fileExtension() const override { return "skp"; }
flags()524     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
525 };
526 
527 class DebugSink : public Sink {
528 public:
529     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()530     const char* fileExtension() const override { return "json"; }
flags()531     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
532 };
533 
534 class SVGSink : public Sink {
535 public:
536     SVGSink(int pageIndex = 0);
537 
538     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()539     const char* fileExtension() const override { return "svg"; }
flags()540     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
541 
542 private:
543     int fPageIndex;
544 };
545 
546 
547 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
548 
549 class Via : public Sink {
550 public:
Via(Sink * sink)551     explicit Via(Sink* sink) : fSink(sink) {}
fileExtension()552     const char* fileExtension() const override { return fSink->fileExtension(); }
serial()553     bool               serial() const override { return fSink->serial(); }
flags()554     SinkFlags flags() const override {
555         SinkFlags flags = fSink->flags();
556         flags.approach = SinkFlags::kIndirect;
557         return flags;
558     }
559 protected:
560     std::unique_ptr<Sink> fSink;
561 };
562 
563 class ViaMatrix : public Via {
564 public:
565     ViaMatrix(SkMatrix, Sink*);
566     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
567 private:
568     const SkMatrix fMatrix;
569 };
570 
571 class ViaUpright : public Via {
572 public:
573     ViaUpright(SkMatrix, Sink*);
574     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
575 private:
576     const SkMatrix fMatrix;
577 };
578 
579 class ViaSerialization : public Via {
580 public:
ViaSerialization(Sink * sink)581     explicit ViaSerialization(Sink* sink) : Via(sink) {}
582     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
583 };
584 
585 class ViaPicture : public Via {
586 public:
ViaPicture(Sink * sink)587     explicit ViaPicture(Sink* sink) : Via(sink) {}
588     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
589 };
590 
591 class ViaDDL : public Via {
592 public:
593     ViaDDL(int numReplays, int numDivisions, Sink* sink);
594     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
595 private:
596     const int fNumReplays;
597     const int fNumDivisions;
598 };
599 
600 class ViaSVG : public Via {
601 public:
ViaSVG(Sink * sink)602     explicit ViaSVG(Sink* sink) : Via(sink) {}
603     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
604 };
605 
606 }  // namespace DM
607 
608 #endif//DMSrcSink_DEFINED
609