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