• 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/core/SkBBHFactory.h"
13 #include "include/core/SkBitmap.h"
14 #include "include/core/SkCanvas.h"
15 #include "include/core/SkData.h"
16 #include "include/core/SkPicture.h"
17 #include "include/docs/SkMultiPictureDocument.h"
18 #include "include/gpu/graphite/ContextOptions.h"
19 #include "tools/flags/CommonFlagsConfig.h"
20 #include "tools/gpu/MemoryCache.h"
21 #include "tools/graphite/TestOptions.h"
22 
23 #include <functional>
24 
25 //#define TEST_VIA_SVG
26 
27 namespace skiagm::verifiers {
28 class VerifierList;
29 }
30 namespace DM {
31 
32 // This is just convenience.  It lets you use either return "foo" or return SkStringPrintf(...).
33 struct ImplicitString : public SkString {
34     template <typename T>
ImplicitStringImplicitString35     ImplicitString(const T& s) : SkString(s) {}
ImplicitStringImplicitString36     ImplicitString() : SkString("") {}
37 };
38 typedef ImplicitString Name;
39 typedef ImplicitString Path;
40 
41 class Result {
42 public:
43     enum class Status : int { Ok, Fatal, Skip };
44 
Result(Status status,SkString msg)45     Result(Status status, SkString msg) : fMsg(std::move(msg)), fStatus(status) {}
46 
47     Result(const Result&)            = default;
48     Result& operator=(const Result&) = default;
49 
Ok()50     static Result Ok() { return Result{Status::Ok, {}}; }
51 
Fatal(const char * fmt,...)52     static Result Fatal(const char* fmt, ...) SK_PRINTF_LIKE(1, 2) {
53         SkString msg;
54         va_list args;
55         va_start(args, fmt);
56         msg.printVAList(fmt, args);
57         va_end(args);
58 
59         return Result{Status::Fatal, std::move(msg)};
60     }
61 
Skip(const char * fmt,...)62     static Result Skip(const char* fmt, ...) SK_PRINTF_LIKE(1, 2) {
63         SkString msg;
64         va_list args;
65         va_start(args, fmt);
66         msg.printVAList(fmt, args);
67         va_end(args);
68 
69         return Result{Status::Skip, std::move(msg)};
70     }
71 
isOk()72     bool isOk() { return fStatus == Status::Ok; }
isFatal()73     bool isFatal() { return fStatus == Status::Fatal; }
isSkip()74     bool isSkip() { return fStatus == Status::Skip; }
75 
c_str()76     const char* c_str() const { return fMsg.c_str(); }
status()77     Status status() const { return fStatus; }
78 
79 private:
80     SkString fMsg;
81     Status   fStatus;
82 };
83 
84 struct SinkFlags {
85     enum Type { kNull, kGPU, kVector, kRaster } type;
86     enum Approach { kDirect, kIndirect } approach;
87     enum Multisampled { kNotMultisampled, kMultisampled } multisampled;
88     SinkFlags(Type t, Approach a, Multisampled ms = kNotMultisampled)
typeSinkFlags89             : type(t), approach(a), multisampled(ms) {}
90 };
91 
92 struct Src {
93     using GraphiteTestContext = skiatest::graphite::GraphiteTestContext;
94 
~SrcSrc95     virtual ~Src() {}
96     [[nodiscard]] virtual Result draw(SkCanvas* canvas, GraphiteTestContext*) const = 0;
97     virtual SkISize size() const = 0;
98     virtual Name name() const = 0;
modifyGrContextOptionsSrc99     virtual void modifyGrContextOptions(GrContextOptions*) const  {}
modifyGraphiteContextOptionsSrc100     virtual void modifyGraphiteContextOptions(skgpu::graphite::ContextOptions*) const {}
vetoSrc101     virtual bool veto(SinkFlags) const { return false; }
102 
pageCountSrc103     virtual int pageCount() const { return 1; }
drawSrc104     [[nodiscard]] virtual Result draw([[maybe_unused]] int page,
105                                       SkCanvas* canvas,
106                                       GraphiteTestContext* graphiteTestContext) const {
107         return this->draw(canvas, graphiteTestContext);
108     }
sizeSrc109     virtual SkISize size([[maybe_unused]] int page) const { return this->size(); }
110     // Force Tasks using this Src to run on the main thread?
serialSrc111     virtual bool serial() const { return false; }
112 };
113 
114 struct Sink {
~SinkSink115     virtual ~Sink() {}
116     // You may write to either the bitmap or stream.  If you write to log, we'll print that out.
117     [[nodiscard]] virtual Result draw(const Src&, SkBitmap*, SkWStream*, SkString* log) const = 0;
118 
119     // Override the color space of this Sink, after creation
setColorSpaceSink120     virtual void setColorSpace(sk_sp<SkColorSpace>) {}
121 
122     // Force Tasks using this Sink to run on the main thread?
serialSink123     virtual bool serial() const { return false; }
124 
125     // File extension for the content draw() outputs, e.g. "png", "pdf".
126     virtual const char* fileExtension() const  = 0;
127 
128     virtual SinkFlags flags() const = 0;
129 
130     /** Returns the color type and space used by the sink. */
colorInfoSink131     virtual SkColorInfo colorInfo() const { return SkColorInfo(); }
132 };
133 
134 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
135 
136 class GMSrc : public Src {
137 public:
138     explicit GMSrc(skiagm::GMFactory);
139 
140     Result draw(SkCanvas*, GraphiteTestContext*) const override;
141     SkISize size() const override;
142     Name name() const override;
143     void modifyGrContextOptions(GrContextOptions* options) const override;
144 #if defined(SK_GRAPHITE)
145     void modifyGraphiteContextOptions(skgpu::graphite::ContextOptions*) const override;
146 #endif
147 
148 private:
149     skiagm::GMFactory fFactory;
150 };
151 
152 class CodecSrc : public Src {
153 public:
154     enum Mode {
155         kCodec_Mode,
156         // We choose to test only one mode with zero initialized memory.
157         // This will exercise all of the interesting cases in SkSwizzler
158         // without doubling the size of our test suite.
159         kCodecZeroInit_Mode,
160         kScanline_Mode,
161         kStripe_Mode, // Tests the skipping of scanlines
162         kCroppedScanline_Mode, // Tests (jpeg) cropped scanline optimization
163         kSubset_Mode, // For codecs that support subsets directly.
164         kAnimated_Mode, // For codecs that support animation.
165     };
166     enum DstColorType {
167         kGetFromCanvas_DstColorType,
168         kGrayscale_Always_DstColorType,
169         kNonNative8888_Always_DstColorType,
170     };
171     CodecSrc(Path, Mode, DstColorType, SkAlphaType, float);
172 
173     Result draw(SkCanvas*, GraphiteTestContext*) const override;
174     SkISize size() const override;
175     Name name() const override;
veto(SinkFlags)176     bool veto(SinkFlags) const override;
177     bool serial() const override { return fRunSerially; }
178 private:
179     Path                    fPath;
180     Mode                    fMode;
181     DstColorType            fDstColorType;
182     SkAlphaType             fDstAlphaType;
183     float                   fScale;
184     bool                    fRunSerially;
185 };
186 
187 class AndroidCodecSrc : public Src {
188 public:
189     AndroidCodecSrc(Path, CodecSrc::DstColorType, SkAlphaType, int sampleSize);
190 
191     Result draw(SkCanvas*, GraphiteTestContext*) const override;
192     SkISize size() const override;
193     Name name() const override;
veto(SinkFlags)194     bool veto(SinkFlags) const override;
195     bool serial() const override { return fRunSerially; }
196 private:
197     Path                    fPath;
198     CodecSrc::DstColorType  fDstColorType;
199     SkAlphaType             fDstAlphaType;
200     int                     fSampleSize;
201     bool                    fRunSerially;
202 };
203 
204 #ifdef SK_ENABLE_ANDROID_UTILS
205 // Allows for testing of various implementations of Android's BitmapRegionDecoder
206 class BRDSrc : public Src {
207 public:
208     enum Mode {
209         // Decode the entire image as one region.
210         kFullImage_Mode,
211         // Splits the image into multiple regions using a divisor and decodes the regions
212         // separately.  Also, this test adds a border of a few pixels to each of the regions
213         // that it is decoding.  This tests the behavior when a client asks for a region that
214         // does not fully fit in the image.
215         kDivisor_Mode,
216     };
217 
218     BRDSrc(Path, Mode, CodecSrc::DstColorType, uint32_t);
219 
220     Result draw(SkCanvas*, GraphiteTestContext*) const override;
221     SkISize size() const override;
222     Name name() const override;
223     bool veto(SinkFlags) const override;
224 private:
225     Path                                     fPath;
226     Mode                                     fMode;
227     CodecSrc::DstColorType                   fDstColorType;
228     uint32_t                                 fSampleSize;
229 };
230 #endif
231 
232 class ImageGenSrc : public Src {
233 public:
234     enum Mode {
235         kCodec_Mode,    // Use CodecImageGenerator
236         kPlatform_Mode, // Uses CG or WIC
237     };
238     ImageGenSrc(Path, Mode, SkAlphaType, bool);
239 
240     Result draw(SkCanvas*, GraphiteTestContext*) const override;
241     SkISize size() const override;
242     Name name() const override;
veto(SinkFlags)243     bool veto(SinkFlags) const override;
244     bool serial() const override { return fRunSerially; }
245 private:
246     Path        fPath;
247     Mode        fMode;
248     SkAlphaType fDstAlphaType;
249     bool        fIsGpu;
250     bool        fRunSerially;
251 };
252 
253 class ColorCodecSrc : public Src {
254 public:
255     ColorCodecSrc(Path, bool decode_to_dst);
256 
257     Result draw(SkCanvas*, GraphiteTestContext*) const override;
258     SkISize size() const override;
259     Name name() const override;
260     bool veto(SinkFlags) const override;
261 private:
262     Path fPath;
263     bool fDecodeToDst;
264 };
265 
266 class SKPSrc : public Src {
267 public:
268     explicit SKPSrc(Path path);
269 
270     Result draw(SkCanvas*, GraphiteTestContext*) const override;
271     SkISize size() const override;
272     Name name() const override;
273 private:
274     Path fPath;
275 };
276 
277 // This class extracts all the paths from an SKP and then removes unwanted paths according to the
278 // provided l/r trail. It then just draws the remaining paths. (Non-path draws are thrown out.) It
279 // is useful for finding a reduced repo case for path drawing bugs.
280 class BisectSrc : public SKPSrc {
281 public:
282     explicit BisectSrc(Path path, const char* trail);
283 
284     Result draw(SkCanvas*, GraphiteTestContext*) const override;
285 
286 private:
287     SkString fTrail;
288 
289     using INHERITED = SKPSrc;
290 };
291 
292 #if defined(SK_ENABLE_SKOTTIE)
293 class SkottieSrc final : public Src {
294 public:
295     explicit SkottieSrc(Path path);
296 
297     Result draw(SkCanvas*, GraphiteTestContext*) const override;
298     SkISize size() const override;
299     Name name() const override;
300     bool veto(SinkFlags) const override;
301 
302 private:
303     // Generates a kTileCount x kTileCount filmstrip with evenly distributed frames.
304     inline static constexpr int      kTileCount = 5;
305 
306     // Fit kTileCount x kTileCount frames to a 1000x1000 film strip.
307     inline static constexpr SkScalar kTargetSize = 1000;
308     inline static constexpr SkScalar kTileSize = kTargetSize / kTileCount;
309 
310     Path                      fPath;
311 };
312 #endif
313 
314 #if defined(SK_ENABLE_SVG)
315 } // namespace DM
316 
317 class SkSVGDOM;
318 
319 namespace DM {
320 
321 class SVGSrc : public Src {
322 public:
323     explicit SVGSrc(Path path);
324 
325     Result draw(SkCanvas*, GraphiteTestContext*) const override;
326     SkISize size() const override;
327     Name name() const override;
328     bool veto(SinkFlags) const override;
329 
330 private:
331     Name            fName;
332     sk_sp<SkSVGDOM> fDom;
333     SkScalar        fScale;
334 
335     using INHERITED = Src;
336 };
337 #endif // SK_ENABLE_SVG
338 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
339 
340 class MSKPSrc : public Src {
341 public:
342     explicit MSKPSrc(Path path);
343 
344     int pageCount() const override;
345     Result draw(SkCanvas* c, GraphiteTestContext*) const override;
346     Result draw(int, SkCanvas*, GraphiteTestContext*) const override;
347     SkISize size() const override;
348     SkISize size(int) const override;
349     Name name() const override;
350 
351 private:
352     Path fPath;
353     mutable skia_private::TArray<SkDocumentPage> fPages;
354 };
355 
356 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
357 
358 class NullSink : public Sink {
359 public:
NullSink()360     NullSink() {}
361 
362     Result draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()363     const char* fileExtension() const override { return ""; }
flags()364     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; }
365 };
366 
367 class GPUSink : public Sink {
368 public:
369     GPUSink(const SkCommandLineConfigGpu*, const GrContextOptions&);
370 
371     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
372     Result onDraw(const Src&, SkBitmap*, SkWStream*, SkString*,
373                   const GrContextOptions& baseOptions,
374                   std::function<void(GrDirectContext*)> initContext = nullptr,
375                   std::function<SkCanvas*(SkCanvas*)> wrapCanvas = nullptr) const;
376 
contextType()377     skgpu::ContextType contextType() const { return fContextType; }
contextOverrides()378     const sk_gpu_test::GrContextFactory::ContextOverrides& contextOverrides() const {
379         return fContextOverrides;
380     }
surfType()381     SkCommandLineConfigGpu::SurfType surfType() const { return fSurfType; }
serial()382     bool serial() const override { return true; }
fileExtension()383     const char* fileExtension() const override { return "png"; }
flags()384     SinkFlags flags() const override {
385         SinkFlags::Multisampled ms = fSampleCount > 1 ? SinkFlags::kMultisampled
386                                                       : SinkFlags::kNotMultisampled;
387         return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect, ms };
388     }
baseContextOptions()389     const GrContextOptions& baseContextOptions() const { return fBaseContextOptions; }
setColorSpace(sk_sp<SkColorSpace> colorSpace)390     void setColorSpace(sk_sp<SkColorSpace> colorSpace) override { fColorSpace = colorSpace; }
colorInfo()391     SkColorInfo colorInfo() const override {
392         return SkColorInfo(fColorType, fAlphaType, fColorSpace);
393     }
394 
395 protected:
396     sk_sp<SkSurface> createDstSurface(GrDirectContext*, SkISize size) const;
397     bool readBack(SkSurface*, SkBitmap* dst) const;
398 
399 private:
400     skgpu::ContextType                                fContextType;
401     sk_gpu_test::GrContextFactory::ContextOverrides   fContextOverrides;
402     SkCommandLineConfigGpu::SurfType                  fSurfType;
403     int                                               fSampleCount;
404     uint32_t                                          fSurfaceFlags;
405     SkColorType                                       fColorType;
406     SkAlphaType                                       fAlphaType;
407     sk_sp<SkColorSpace>                               fColorSpace;
408     GrContextOptions                                  fBaseContextOptions;
409     sk_gpu_test::MemoryCache                          fMemoryCache;
410 };
411 
412 // Wrap a gpu canvas in one that routes all text draws through Slugs.
413 // Note that text blobs that have an RSXForm aren't converted.
414 class GPUSlugSink : public GPUSink {
415 public:
416     GPUSlugSink(const SkCommandLineConfigGpu*, const GrContextOptions&);
417 
418     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
419 };
420 
421 class GPUSerializeSlugSink : public GPUSink {
422 public:
423     GPUSerializeSlugSink(const SkCommandLineConfigGpu*, const GrContextOptions&);
424 
425     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
426 };
427 
428 class GPURemoteSlugSink : public GPUSink {
429 public:
430     GPURemoteSlugSink(const SkCommandLineConfigGpu*, const GrContextOptions&);
431 
432     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
433 };
434 
435 class GPUPersistentCacheTestingSink : public GPUSink {
436 public:
437     GPUPersistentCacheTestingSink(const SkCommandLineConfigGpu*, const GrContextOptions&);
438 
439     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
440 
fileExtension()441     const char* fileExtension() const override {
442         // Suppress writing out results from this config - we just want to do our matching test
443         return nullptr;
444     }
445 
446 private:
447     int fCacheType;
448 
449     using INHERITED = GPUSink;
450 };
451 
452 class GPUPrecompileTestingSink : public GPUSink {
453 public:
454     GPUPrecompileTestingSink(const SkCommandLineConfigGpu*, const GrContextOptions&);
455 
456     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
457 
fileExtension()458     const char* fileExtension() const override {
459         // Suppress writing out results from this config - we just want to do our matching test
460         return nullptr;
461     }
462 
463 private:
464     using INHERITED = GPUSink;
465 };
466 
467 // This sink attempts to better simulate the Chrome DDL use-case. It:
468 //    creates the DDLs on separate recording threads
469 //    performs all the GPU work on a separate GPU thread
470 // In the future this should be expanded to:
471 //    upload on a utility thread w/ access to a shared context
472 //    compile the programs on the utility thread
473 //    perform fine grained scheduling of gpu tasks based on their image and program prerequisites
474 //    create a single "compositing" DDL that is replayed last
475 class GPUDDLSink : public GPUSink {
476 public:
477     GPUDDLSink(const SkCommandLineConfigGpu*, const GrContextOptions&);
478 
479     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
480 
481 private:
482     Result ddlDraw(const Src&,
483                    sk_sp<SkSurface> dstSurface,
484                    SkTaskGroup* recordingTaskGroup,
485                    SkTaskGroup* gpuTaskGroup,
486                    sk_gpu_test::TestContext* gpuTestCtx,
487                    GrDirectContext* gpuThreadCtx) const;
488 
489     std::unique_ptr<SkExecutor> fRecordingExecutor;
490     std::unique_ptr<SkExecutor> fGPUExecutor;
491 
492     using INHERITED = GPUSink;
493 };
494 
495 class PDFSink : public Sink {
496 public:
PDFSink(bool pdfa,SkScalar rasterDpi)497     PDFSink(bool pdfa, SkScalar rasterDpi) : fPDFA(pdfa), fRasterDpi(rasterDpi) {}
498     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()499     const char* fileExtension() const override { return "pdf"; }
flags()500     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
501 
502     bool fPDFA;
503     SkScalar fRasterDpi;
504 };
505 
506 class XPSSink : public Sink {
507 public:
508     XPSSink();
509 
510     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()511     const char* fileExtension() const override { return "xps"; }
flags()512     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
513 };
514 
515 class RasterSink : public Sink {
516 public:
517     explicit RasterSink(SkColorType);
518 
519     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()520     const char* fileExtension() const override { return "png"; }
flags()521     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; }
setColorSpace(sk_sp<SkColorSpace> colorSpace)522     void setColorSpace(sk_sp<SkColorSpace> colorSpace) override { fColorSpace = colorSpace; }
523 
colorInfo()524     SkColorInfo colorInfo() const override {
525         // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
526         SkAlphaType alphaType = kPremul_SkAlphaType;
527         (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
528 
529         return SkColorInfo(fColorType, alphaType, fColorSpace);
530     }
531 
532 private:
533     SkColorType         fColorType;
534     sk_sp<SkColorSpace> fColorSpace;
535 };
536 
537 class SKPSink : public Sink {
538 public:
539     SKPSink();
540 
541     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()542     const char* fileExtension() const override { return "skp"; }
flags()543     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
544 };
545 
546 class DebugSink : public Sink {
547 public:
548     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()549     const char* fileExtension() const override { return "json"; }
flags()550     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
551 };
552 
553 class SVGSink : public Sink {
554 public:
555     SVGSink(int pageIndex = 0);
556 
557     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()558     const char* fileExtension() const override { return "svg"; }
flags()559     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
560 
561 private:
562     int fPageIndex;
563 };
564 
565 #if defined(SK_GRAPHITE)
566 
567 class GraphiteSink : public Sink {
568 public:
569     GraphiteSink(const SkCommandLineConfigGraphite*);
570 
571     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
serial()572     bool serial() const override { return true; }
fileExtension()573     const char* fileExtension() const override { return "png"; }
flags()574     SinkFlags flags() const override { return SinkFlags{SinkFlags::kGPU, SinkFlags::kDirect}; }
setColorSpace(sk_sp<SkColorSpace> colorSpace)575     void setColorSpace(sk_sp<SkColorSpace> colorSpace) override { fColorSpace = colorSpace; }
colorInfo()576     SkColorInfo colorInfo() const override {
577         return SkColorInfo(fColorType, fAlphaType, fColorSpace);
578     }
579 
580 protected:
581     sk_sp<SkSurface> makeSurface(skgpu::graphite::Recorder*, SkISize) const;
582 
583     using SurfaceType = SkCommandLineConfigGraphite::SurfaceType;
584 
585     skiatest::graphite::TestOptions fOptions;
586     skgpu::ContextType fContextType;
587     SurfaceType fSurfaceType;
588     SkColorType fColorType;
589     SkAlphaType fAlphaType;
590     sk_sp<SkColorSpace> fColorSpace;
591 };
592 
593 #if defined(SK_ENABLE_PRECOMPILE)
594 // In general this sink:
595 //   renders a gm, skp or svg (in drawSrc)
596 //   collects all the UniqueKeys                  |
597 //   clears the pipeline cache                    | (in resetAndRecreatePipelines)
598 //   recreates the pipelines from the UniqueKeys  |
599 //   renders a second time (in drawSrc)
600 //   asserts that no new pipelines were created
601 class GraphitePrecompileTestingSink : public GraphiteSink {
602 public:
603     GraphitePrecompileTestingSink(const SkCommandLineConfigGraphite*);
604     ~GraphitePrecompileTestingSink() override;
605 
606     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
607 
fileExtension()608     const char* fileExtension() const override {
609         // Suppress writing out results from this config - we just want to check that
610         // the precompilation API is expressive enough and prepopulates the cache.
611         // If desired, this could be updated to save the result of the precompiled rendering.
612         // However; if all the keys match, as is expected, the images should always match.
613         return nullptr;
614     }
615 
616 private:
617     Result drawSrc(const Src&,
618                    skgpu::graphite::Context*,
619                    skiatest::graphite::GraphiteTestContext*) const;
620     Result resetAndRecreatePipelines(skgpu::graphite::Context*) const;
621 
622     mutable std::unique_ptr<skgpu::graphite::Recorder> fRecorder;
623 };
624 #endif // SK_ENABLE_PRECOMPILE
625 #endif // SK_GRAPHITE
626 
627 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
628 
629 class Via : public Sink {
630 public:
Via(Sink * sink)631     explicit Via(Sink* sink) : fSink(sink) {}
fileExtension()632     const char* fileExtension() const override { return fSink->fileExtension(); }
serial()633     bool               serial() const override { return fSink->serial(); }
flags()634     SinkFlags flags() const override {
635         SinkFlags flags = fSink->flags();
636         flags.approach = SinkFlags::kIndirect;
637         return flags;
638     }
setColorSpace(sk_sp<SkColorSpace> colorSpace)639     void setColorSpace(sk_sp<SkColorSpace> colorSpace) override {
640         fSink->setColorSpace(colorSpace);
641     }
642 protected:
643     std::unique_ptr<Sink> fSink;
644 };
645 
646 class ViaMatrix : public Via {
647 public:
648     ViaMatrix(SkMatrix, Sink*);
649     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
650 
651 private:
652     const SkMatrix fMatrix;
653 };
654 
655 class ViaUpright : public Via {
656 public:
657     ViaUpright(SkMatrix, Sink*);
658     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
659 
660 private:
661     const SkMatrix fMatrix;
662 };
663 
664 class ViaSerialization : public Via {
665 public:
ViaSerialization(Sink * sink)666     explicit ViaSerialization(Sink* sink) : Via(sink) {}
667     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
668 };
669 
670 class ViaPicture : public Via {
671 public:
ViaPicture(Sink * sink)672     explicit ViaPicture(Sink* sink) : Via(sink) {}
673     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
674 };
675 
676 class ViaRuntimeBlend : public Via {
677 public:
ViaRuntimeBlend(Sink * sink)678     explicit ViaRuntimeBlend(Sink* sink) : Via(sink) {}
679     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
680 };
681 
682 class ViaSVG : public Via {
683 public:
ViaSVG(Sink * sink)684     explicit ViaSVG(Sink* sink) : Via(sink) {}
685     Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
686 };
687 
688 }  // namespace DM
689 
690 #endif//DMSrcSink_DEFINED
691