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