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