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