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> ImplicitStringImplicitString31 ImplicitString(const T& s) : SkString(s) {} ImplicitStringImplicitString32 ImplicitString() : SkString("") {} 33 }; 34 typedef ImplicitString Name; 35 typedef ImplicitString Path; 36 37 class Error { 38 public: Error(const SkString & s)39 Error(const SkString& s) : fMsg(s), fFatal(!this->isEmpty()) {} Error(const char * s)40 Error(const char* s) : fMsg(s), fFatal(!this->isEmpty()) {} 41 42 Error(const Error&) = default; 43 Error& operator=(const Error&) = default; 44 Nonfatal(const SkString & s)45 static Error Nonfatal(const SkString& s) { return Nonfatal(s.c_str()); } Nonfatal(const char * s)46 static Error Nonfatal(const char* s) { 47 Error e(s); 48 e.fFatal = false; 49 return e; 50 } 51 c_str()52 const char* c_str() const { return fMsg.c_str(); } isEmpty()53 bool isEmpty() const { return fMsg.isEmpty(); } isFatal()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) typeSinkFlags66 : type(t), approach(a), multisampled(ms) {} 67 }; 68 69 struct Src { ~SrcSrc70 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; modifyGrContextOptionsSrc74 virtual void modifyGrContextOptions(GrContextOptions* options) const {} vetoSrc75 virtual bool veto(SinkFlags) const { return false; } 76 pageCountSrc77 virtual int pageCount() const { return 1; } drawSrc78 virtual Error SK_WARN_UNUSED_RESULT draw(int, SkCanvas* canvas) const { 79 return this->draw(canvas); 80 } sizeSrc81 virtual SkISize size(int) const { return this->size(); } 82 // Force Tasks using this Src to run on the main thread? serialSrc83 virtual bool serial() const { return false; } 84 }; 85 86 struct Sink { ~SinkSink87 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? serialSink93 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; veto(SinkFlags)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; veto(SinkFlags)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; veto(SinkFlags)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 std::unique_ptr<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: NullSink()331 NullSink() {} 332 333 Error draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()334 const char* fileExtension() const override { return ""; } flags()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 serial()350 bool serial() const override { return !fThreaded; } fileExtension()351 const char* fileExtension() const override { return "png"; } flags()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 } baseContextOptions()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 fileExtension()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: PDFSink(bool pdfa,SkScalar rasterDpi)394 PDFSink(bool pdfa, SkScalar rasterDpi) : fPDFA(pdfa), fRasterDpi(rasterDpi) {} 395 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()396 const char* fileExtension() const override { return "pdf"; } flags()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; fileExtension()407 const char* fileExtension() const override { return "xps"; } flags()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; fileExtension()416 const char* fileExtension() const override { return "skpipe"; } flags()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; fileExtension()425 const char* fileExtension() const override { return "png"; } flags()426 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; } 427 private: 428 SkColorType fColorType; 429 sk_sp<SkColorSpace> fColorSpace; 430 }; 431 432 class SKPSink : public Sink { 433 public: 434 SKPSink(); 435 436 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()437 const char* fileExtension() const override { return "skp"; } flags()438 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 439 }; 440 441 class DebugSink : public Sink { 442 public: 443 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()444 const char* fileExtension() const override { return "json"; } flags()445 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 446 }; 447 448 class SVGSink : public Sink { 449 public: 450 SVGSink(); 451 452 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()453 const char* fileExtension() const override { return "svg"; } flags()454 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 455 }; 456 457 458 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 459 460 class Via : public Sink { 461 public: Via(Sink * sink)462 explicit Via(Sink* sink) : fSink(sink) {} fileExtension()463 const char* fileExtension() const override { return fSink->fileExtension(); } serial()464 bool serial() const override { return fSink->serial(); } flags()465 SinkFlags flags() const override { 466 SinkFlags flags = fSink->flags(); 467 flags.approach = SinkFlags::kIndirect; 468 return flags; 469 } 470 protected: 471 std::unique_ptr<Sink> fSink; 472 }; 473 474 class ViaMatrix : public Via { 475 public: 476 ViaMatrix(SkMatrix, Sink*); 477 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 478 private: 479 const SkMatrix fMatrix; 480 }; 481 482 class ViaUpright : public Via { 483 public: 484 ViaUpright(SkMatrix, Sink*); 485 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 486 private: 487 const SkMatrix fMatrix; 488 }; 489 490 class ViaSerialization : public Via { 491 public: ViaSerialization(Sink * sink)492 explicit ViaSerialization(Sink* sink) : Via(sink) {} 493 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 494 }; 495 496 class ViaPicture : public Via { 497 public: ViaPicture(Sink * sink)498 explicit ViaPicture(Sink* sink) : Via(sink) {} 499 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 500 }; 501 502 class ViaPipe : public Via { 503 public: ViaPipe(Sink * sink)504 explicit ViaPipe(Sink* sink) : Via(sink) {} 505 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 506 }; 507 508 class ViaTiles : public Via { 509 public: 510 ViaTiles(int w, int h, SkBBHFactory*, Sink*); 511 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 512 private: 513 const int fW, fH; 514 std::unique_ptr<SkBBHFactory> fFactory; 515 }; 516 517 class ViaSVG : public Via { 518 public: ViaSVG(Sink * sink)519 explicit ViaSVG(Sink* sink) : Via(sink) {} 520 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 521 }; 522 523 class ViaLite : public Via { 524 public: ViaLite(Sink * sink)525 explicit ViaLite(Sink* sink) : Via(sink) {} 526 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 527 }; 528 529 class ViaCSXform : public Via { 530 public: 531 explicit ViaCSXform(Sink*, sk_sp<SkColorSpace>, bool colorSpin); 532 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 533 private: 534 sk_sp<SkColorSpace> fCS; 535 bool fColorSpin; 536 }; 537 538 } // namespace DM 539 540 #endif//DMSrcSink_DEFINED 541