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 "SkBBHFactory.h" 12 #include "SkBBoxHierarchy.h" 13 #include "SkBitmap.h" 14 #include "SkBitmapRegionDecoder.h" 15 #include "SkCanvas.h" 16 #include "SkCommonFlagsConfig.h" 17 #include "SkData.h" 18 #include "SkMultiPictureDocument.h" 19 #include "SkPicture.h" 20 #include "gm.h" 21 22 //#define TEST_VIA_SVG 23 24 namespace DM { 25 26 // This is just convenience. It lets you use either return "foo" or return SkStringPrintf(...). 27 struct ImplicitString : public SkString { 28 template <typename T> ImplicitStringImplicitString29 ImplicitString(const T& s) : SkString(s) {} ImplicitStringImplicitString30 ImplicitString() : SkString("") {} 31 }; 32 typedef ImplicitString Name; 33 typedef ImplicitString Path; 34 35 class Error { 36 public: Error(const SkString & s)37 Error(const SkString& s) : fMsg(s), fFatal(!this->isEmpty()) {} Error(const char * s)38 Error(const char* s) : fMsg(s), fFatal(!this->isEmpty()) {} 39 40 Error(const Error&) = default; 41 Error& operator=(const Error&) = default; 42 Nonfatal(const SkString & s)43 static Error Nonfatal(const SkString& s) { return Nonfatal(s.c_str()); } Nonfatal(const char * s)44 static Error Nonfatal(const char* s) { 45 Error e(s); 46 e.fFatal = false; 47 return e; 48 } 49 c_str()50 const char* c_str() const { return fMsg.c_str(); } isEmpty()51 bool isEmpty() const { return fMsg.isEmpty(); } isFatal()52 bool isFatal() const { return fFatal; } 53 54 private: 55 SkString fMsg; 56 bool fFatal; 57 }; 58 59 struct SinkFlags { 60 enum Type { kNull, kGPU, kVector, kRaster } type; 61 enum Approach { kDirect, kIndirect } approach; 62 enum Multisampled { kNotMultisampled, kMultisampled } multisampled; 63 SinkFlags(Type t, Approach a, Multisampled ms = kNotMultisampled) typeSinkFlags64 : type(t), approach(a), multisampled(ms) {} 65 }; 66 67 struct Src { ~SrcSrc68 virtual ~Src() {} 69 virtual Error SK_WARN_UNUSED_RESULT draw(SkCanvas*) const = 0; 70 virtual SkISize size() const = 0; 71 virtual Name name() const = 0; modifyGrContextOptionsSrc72 virtual void modifyGrContextOptions(GrContextOptions* options) const {} vetoSrc73 virtual bool veto(SinkFlags) const { return false; } 74 pageCountSrc75 virtual int pageCount() const { return 1; } drawSrc76 virtual Error SK_WARN_UNUSED_RESULT draw(int, SkCanvas* canvas) const { 77 return this->draw(canvas); 78 } sizeSrc79 virtual SkISize size(int) const { return this->size(); } 80 // Force Tasks using this Src to run on the main thread? serialSrc81 virtual bool serial() const { return false; } 82 }; 83 84 struct Sink { ~SinkSink85 virtual ~Sink() {} 86 // You may write to either the bitmap or stream. If you write to log, we'll print that out. 87 virtual Error SK_WARN_UNUSED_RESULT draw(const Src&, SkBitmap*, SkWStream*, SkString* log) 88 const = 0; 89 90 // Force Tasks using this Sink to run on the main thread? serialSink91 virtual bool serial() const { return false; } 92 93 // File extension for the content draw() outputs, e.g. "png", "pdf". 94 virtual const char* fileExtension() const = 0; 95 96 virtual SinkFlags flags() const = 0; 97 }; 98 99 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 100 101 class GMSrc : public Src { 102 public: 103 explicit GMSrc(skiagm::GMFactory); 104 105 Error draw(SkCanvas*) const override; 106 SkISize size() const override; 107 Name name() const override; 108 void modifyGrContextOptions(GrContextOptions* options) const override; 109 110 private: 111 skiagm::GMFactory fFactory; 112 }; 113 114 class CodecSrc : public Src { 115 public: 116 enum Mode { 117 kCodec_Mode, 118 // We choose to test only one mode with zero initialized memory. 119 // This will exercise all of the interesting cases in SkSwizzler 120 // without doubling the size of our test suite. 121 kCodecZeroInit_Mode, 122 kScanline_Mode, 123 kStripe_Mode, // Tests the skipping of scanlines 124 kCroppedScanline_Mode, // Tests (jpeg) cropped scanline optimization 125 kSubset_Mode, // For codecs that support subsets directly. 126 kAnimated_Mode, // For codecs that support animation. 127 }; 128 enum DstColorType { 129 kGetFromCanvas_DstColorType, 130 kGrayscale_Always_DstColorType, 131 kNonNative8888_Always_DstColorType, 132 }; 133 CodecSrc(Path, Mode, DstColorType, SkAlphaType, float); 134 135 Error draw(SkCanvas*) const override; 136 SkISize size() const override; 137 Name name() const override; veto(SinkFlags)138 bool veto(SinkFlags) const override; 139 bool serial() const override { return fRunSerially; } 140 private: 141 Path fPath; 142 Mode fMode; 143 DstColorType fDstColorType; 144 SkAlphaType fDstAlphaType; 145 float fScale; 146 bool fRunSerially; 147 }; 148 149 class AndroidCodecSrc : public Src { 150 public: 151 AndroidCodecSrc(Path, CodecSrc::DstColorType, SkAlphaType, int sampleSize); 152 153 Error draw(SkCanvas*) const override; 154 SkISize size() const override; 155 Name name() const override; veto(SinkFlags)156 bool veto(SinkFlags) const override; 157 bool serial() const override { return fRunSerially; } 158 private: 159 Path fPath; 160 CodecSrc::DstColorType fDstColorType; 161 SkAlphaType fDstAlphaType; 162 int fSampleSize; 163 bool fRunSerially; 164 }; 165 166 // Allows for testing of various implementations of Android's BitmapRegionDecoder 167 class BRDSrc : public Src { 168 public: 169 enum Mode { 170 // Decode the entire image as one region. 171 kFullImage_Mode, 172 // Splits the image into multiple regions using a divisor and decodes the regions 173 // separately. Also, this test adds a border of a few pixels to each of the regions 174 // that it is decoding. This tests the behavior when a client asks for a region that 175 // does not fully fit in the image. 176 kDivisor_Mode, 177 }; 178 179 BRDSrc(Path, Mode, CodecSrc::DstColorType, uint32_t); 180 181 Error draw(SkCanvas*) const override; 182 SkISize size() const override; 183 Name name() const override; 184 bool veto(SinkFlags) const override; 185 private: 186 Path fPath; 187 Mode fMode; 188 CodecSrc::DstColorType fDstColorType; 189 uint32_t fSampleSize; 190 }; 191 192 class ImageGenSrc : public Src { 193 public: 194 enum Mode { 195 kCodec_Mode, // Use CodecImageGenerator 196 kPlatform_Mode, // Uses CG or WIC 197 }; 198 ImageGenSrc(Path, Mode, SkAlphaType, bool); 199 200 Error draw(SkCanvas*) const override; 201 SkISize size() const override; 202 Name name() const override; veto(SinkFlags)203 bool veto(SinkFlags) const override; 204 bool serial() const override { return fRunSerially; } 205 private: 206 Path fPath; 207 Mode fMode; 208 SkAlphaType fDstAlphaType; 209 bool fIsGpu; 210 bool fRunSerially; 211 }; 212 213 class ColorCodecSrc : public Src { 214 public: 215 ColorCodecSrc(Path, bool decode_to_dst); 216 217 Error draw(SkCanvas*) const override; 218 SkISize size() const override; 219 Name name() const override; 220 bool veto(SinkFlags) const override; 221 private: 222 Path fPath; 223 bool fDecodeToDst; 224 }; 225 226 class SKPSrc : public Src { 227 public: 228 explicit SKPSrc(Path path); 229 230 Error draw(SkCanvas*) const override; 231 SkISize size() const override; 232 Name name() const override; 233 private: 234 Path fPath; 235 }; 236 237 // This class extracts all the paths from an SKP and then removes unwanted paths according to the 238 // provided l/r trail. It then just draws the remaining paths. (Non-path draws are thrown out.) It 239 // is useful for finding a reduced repo case for path drawing bugs. 240 class BisectSrc : public SKPSrc { 241 public: 242 explicit BisectSrc(Path path, const char* trail); 243 244 Error draw(SkCanvas*) const override; 245 246 private: 247 SkString fTrail; 248 249 typedef SKPSrc INHERITED; 250 }; 251 252 253 #if defined(SK_ENABLE_SKOTTIE) 254 class SkottieSrc final : public Src { 255 public: 256 explicit SkottieSrc(Path path); 257 258 Error draw(SkCanvas*) const override; 259 SkISize size() const override; 260 Name name() const override; 261 bool veto(SinkFlags) const override; 262 263 private: 264 // Generates a kTileCount x kTileCount filmstrip with evenly distributed frames. 265 static constexpr int kTileCount = 5; 266 267 // Fit kTileCount x kTileCount frames to a 1000x1000 film strip. 268 static constexpr SkScalar kTargetSize = 1000; 269 static constexpr SkScalar kTileSize = kTargetSize / kTileCount; 270 271 Path fPath; 272 }; 273 #endif 274 275 #if defined(SK_XML) 276 } // namespace DM 277 278 class SkSVGDOM; 279 280 namespace DM { 281 282 class SVGSrc : public Src { 283 public: 284 explicit SVGSrc(Path path); 285 286 Error draw(SkCanvas*) const override; 287 SkISize size() const override; 288 Name name() const override; 289 bool veto(SinkFlags) const override; 290 291 private: 292 Name fName; 293 sk_sp<SkSVGDOM> fDom; 294 SkScalar fScale; 295 296 typedef Src INHERITED; 297 }; 298 #endif // SK_XML 299 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 300 301 class MSKPSrc : public Src { 302 public: 303 explicit MSKPSrc(Path path); 304 305 int pageCount() const override; 306 Error draw(SkCanvas* c) const override; 307 Error draw(int, SkCanvas*) const override; 308 SkISize size() const override; 309 SkISize size(int) const override; 310 Name name() const override; 311 312 private: 313 Path fPath; 314 mutable SkTArray<SkDocumentPage> fPages; 315 }; 316 317 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 318 319 class NullSink : public Sink { 320 public: NullSink()321 NullSink() {} 322 323 Error draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()324 const char* fileExtension() const override { return ""; } flags()325 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; } 326 }; 327 328 class GPUSink : public Sink { 329 public: 330 GPUSink(sk_gpu_test::GrContextFactory::ContextType, 331 sk_gpu_test::GrContextFactory::ContextOverrides, 332 SkCommandLineConfigGpu::SurfType surfType, int samples, bool diText, 333 SkColorType colorType, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace, 334 bool threaded, const GrContextOptions& grCtxOptions); 335 336 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 337 Error onDraw(const Src&, SkBitmap*, SkWStream*, SkString*, 338 const GrContextOptions& baseOptions) const; 339 contextType()340 sk_gpu_test::GrContextFactory::ContextType contextType() const { return fContextType; } contextOverrides()341 const sk_gpu_test::GrContextFactory::ContextOverrides& contextOverrides() { 342 return fContextOverrides; 343 } surfType()344 SkCommandLineConfigGpu::SurfType surfType() const { return fSurfType; } useDIText()345 bool useDIText() const { return fUseDIText; } serial()346 bool serial() const override { return !fThreaded; } fileExtension()347 const char* fileExtension() const override { return "png"; } flags()348 SinkFlags flags() const override { 349 SinkFlags::Multisampled ms = fSampleCount > 1 ? SinkFlags::kMultisampled 350 : SinkFlags::kNotMultisampled; 351 return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect, ms }; 352 } baseContextOptions()353 const GrContextOptions& baseContextOptions() const { return fBaseContextOptions; } 354 355 private: 356 sk_gpu_test::GrContextFactory::ContextType fContextType; 357 sk_gpu_test::GrContextFactory::ContextOverrides fContextOverrides; 358 SkCommandLineConfigGpu::SurfType fSurfType; 359 int fSampleCount; 360 bool fUseDIText; 361 SkColorType fColorType; 362 SkAlphaType fAlphaType; 363 sk_sp<SkColorSpace> fColorSpace; 364 bool fThreaded; 365 GrContextOptions fBaseContextOptions; 366 }; 367 368 class GPUThreadTestingSink : public GPUSink { 369 public: 370 GPUThreadTestingSink(sk_gpu_test::GrContextFactory::ContextType, 371 sk_gpu_test::GrContextFactory::ContextOverrides, 372 SkCommandLineConfigGpu::SurfType surfType, int samples, bool diText, 373 SkColorType colorType, SkAlphaType alphaType, 374 sk_sp<SkColorSpace> colorSpace, bool threaded, 375 const GrContextOptions& grCtxOptions); 376 377 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 378 fileExtension()379 const char* fileExtension() const override { 380 // Suppress writing out results from this config - we just want to do our matching test 381 return nullptr; 382 } 383 384 private: 385 std::unique_ptr<SkExecutor> fExecutor; 386 387 typedef GPUSink INHERITED; 388 }; 389 390 class GPUPersistentCacheTestingSink : public GPUSink { 391 public: 392 GPUPersistentCacheTestingSink(sk_gpu_test::GrContextFactory::ContextType, 393 sk_gpu_test::GrContextFactory::ContextOverrides, 394 SkCommandLineConfigGpu::SurfType surfType, int samples, 395 bool diText, SkColorType colorType, SkAlphaType alphaType, 396 sk_sp<SkColorSpace> colorSpace, bool threaded, 397 const GrContextOptions& grCtxOptions); 398 399 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 400 fileExtension()401 const char* fileExtension() const override { 402 // Suppress writing out results from this config - we just want to do our matching test 403 return nullptr; 404 } 405 406 private: 407 typedef GPUSink INHERITED; 408 }; 409 410 class PDFSink : public Sink { 411 public: PDFSink(bool pdfa,SkScalar rasterDpi)412 PDFSink(bool pdfa, SkScalar rasterDpi) : fPDFA(pdfa), fRasterDpi(rasterDpi) {} 413 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()414 const char* fileExtension() const override { return "pdf"; } flags()415 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 416 bool fPDFA; 417 SkScalar fRasterDpi; 418 }; 419 420 class XPSSink : public Sink { 421 public: 422 XPSSink(); 423 424 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()425 const char* fileExtension() const override { return "xps"; } flags()426 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 427 }; 428 429 class RasterSink : public Sink { 430 public: 431 explicit RasterSink(SkColorType, sk_sp<SkColorSpace> = nullptr); 432 433 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()434 const char* fileExtension() const override { return "png"; } flags()435 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; } 436 437 private: 438 SkColorType fColorType; 439 sk_sp<SkColorSpace> fColorSpace; 440 }; 441 442 class ThreadedSink : public RasterSink { 443 public: 444 explicit ThreadedSink(SkColorType, sk_sp<SkColorSpace> = nullptr); 445 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 446 }; 447 448 class SKPSink : public Sink { 449 public: 450 SKPSink(); 451 452 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()453 const char* fileExtension() const override { return "skp"; } flags()454 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 455 }; 456 457 class DebugSink : public Sink { 458 public: 459 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()460 const char* fileExtension() const override { return "json"; } flags()461 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 462 }; 463 464 class SVGSink : public Sink { 465 public: 466 SVGSink(int pageIndex = 0); 467 468 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()469 const char* fileExtension() const override { return "svg"; } flags()470 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 471 472 private: 473 int fPageIndex; 474 }; 475 476 477 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 478 479 class Via : public Sink { 480 public: Via(Sink * sink)481 explicit Via(Sink* sink) : fSink(sink) {} fileExtension()482 const char* fileExtension() const override { return fSink->fileExtension(); } serial()483 bool serial() const override { return fSink->serial(); } flags()484 SinkFlags flags() const override { 485 SinkFlags flags = fSink->flags(); 486 flags.approach = SinkFlags::kIndirect; 487 return flags; 488 } 489 protected: 490 std::unique_ptr<Sink> fSink; 491 }; 492 493 class ViaMatrix : public Via { 494 public: 495 ViaMatrix(SkMatrix, Sink*); 496 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 497 private: 498 const SkMatrix fMatrix; 499 }; 500 501 class ViaUpright : public Via { 502 public: 503 ViaUpright(SkMatrix, Sink*); 504 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 505 private: 506 const SkMatrix fMatrix; 507 }; 508 509 class ViaSerialization : public Via { 510 public: ViaSerialization(Sink * sink)511 explicit ViaSerialization(Sink* sink) : Via(sink) {} 512 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 513 }; 514 515 class ViaPicture : public Via { 516 public: ViaPicture(Sink * sink)517 explicit ViaPicture(Sink* sink) : Via(sink) {} 518 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 519 }; 520 521 class ViaTiles : public Via { 522 public: 523 ViaTiles(int w, int h, SkBBHFactory*, Sink*); 524 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 525 private: 526 const int fW, fH; 527 std::unique_ptr<SkBBHFactory> fFactory; 528 }; 529 530 class ViaDDL : public Via { 531 public: 532 ViaDDL(int numReplays, int numDivisions, Sink* sink); 533 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 534 private: 535 const int fNumReplays; 536 const int fNumDivisions; 537 }; 538 539 class ViaSVG : public Via { 540 public: ViaSVG(Sink * sink)541 explicit ViaSVG(Sink* sink) : Via(sink) {} 542 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 543 }; 544 545 class ViaLite : public Via { 546 public: ViaLite(Sink * sink)547 explicit ViaLite(Sink* sink) : Via(sink) {} 548 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 549 }; 550 551 class ViaCSXform : public Via { 552 public: 553 explicit ViaCSXform(Sink*, sk_sp<SkColorSpace>, bool colorSpin); 554 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 555 private: 556 sk_sp<SkColorSpace> fCS; 557 bool fColorSpin; 558 }; 559 560 } // namespace DM 561 562 #endif//DMSrcSink_DEFINED 563