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