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 "SkMultiPictureDocumentReader.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::GMRegistry::Factory); 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::GMRegistry::Factory 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 kIndex8_Always_DstColorType, 131 kGrayscale_Always_DstColorType, 132 kNonNative8888_Always_DstColorType, 133 }; 134 CodecSrc(Path, Mode, DstColorType, SkAlphaType, float); 135 136 Error draw(SkCanvas*) const override; 137 SkISize size() const override; 138 Name name() const override; veto(SinkFlags)139 bool veto(SinkFlags) const override; 140 bool serial() const override { return fRunSerially; } 141 private: 142 Path fPath; 143 Mode fMode; 144 DstColorType fDstColorType; 145 SkAlphaType fDstAlphaType; 146 float fScale; 147 bool fRunSerially; 148 }; 149 150 class AndroidCodecSrc : public Src { 151 public: 152 AndroidCodecSrc(Path, CodecSrc::DstColorType, SkAlphaType, int sampleSize); 153 154 Error draw(SkCanvas*) const override; 155 SkISize size() const override; 156 Name name() const override; veto(SinkFlags)157 bool veto(SinkFlags) const override; 158 bool serial() const override { return fRunSerially; } 159 private: 160 Path fPath; 161 CodecSrc::DstColorType fDstColorType; 162 SkAlphaType fDstAlphaType; 163 int fSampleSize; 164 bool fRunSerially; 165 }; 166 167 // Allows for testing of various implementations of Android's BitmapRegionDecoder 168 class BRDSrc : public Src { 169 public: 170 enum Mode { 171 // Decode the entire image as one region. 172 kFullImage_Mode, 173 // Splits the image into multiple regions using a divisor and decodes the regions 174 // separately. Also, this test adds a border of a few pixels to each of the regions 175 // that it is decoding. This tests the behavior when a client asks for a region that 176 // does not fully fit in the image. 177 kDivisor_Mode, 178 }; 179 180 BRDSrc(Path, Mode, CodecSrc::DstColorType, uint32_t); 181 182 Error draw(SkCanvas*) const override; 183 SkISize size() const override; 184 Name name() const override; 185 bool veto(SinkFlags) const override; 186 private: 187 Path fPath; 188 Mode fMode; 189 CodecSrc::DstColorType fDstColorType; 190 uint32_t fSampleSize; 191 }; 192 193 class ImageGenSrc : public Src { 194 public: 195 enum Mode { 196 kCodec_Mode, // Use CodecImageGenerator 197 kPlatform_Mode, // Uses CG or WIC 198 }; 199 ImageGenSrc(Path, Mode, SkAlphaType, bool); 200 201 Error draw(SkCanvas*) const override; 202 SkISize size() const override; 203 Name name() const override; veto(SinkFlags)204 bool veto(SinkFlags) const override; 205 bool serial() const override { return fRunSerially; } 206 private: 207 Path fPath; 208 Mode fMode; 209 SkAlphaType fDstAlphaType; 210 bool fIsGpu; 211 bool fRunSerially; 212 }; 213 214 class ColorCodecSrc : public Src { 215 public: 216 enum Mode { 217 // Mimic legacy behavior and apply no color correction. 218 kBaseline_Mode, 219 220 // Color correct images into a specific dst color space. If you happen to have this 221 // monitor, you're in luck! The unmarked outputs of this test should display 222 // correctly on this monitor in the Chrome browser. If not, it's useful to know 223 // that this monitor has a profile that is fairly similar to Adobe RGB. 224 kDst_HPZR30w_Mode, 225 226 kDst_sRGB_Mode, 227 }; 228 229 ColorCodecSrc(Path, Mode, SkColorType); 230 231 Error draw(SkCanvas*) const override; 232 SkISize size() const override; 233 Name name() const override; 234 bool veto(SinkFlags) const override; 235 private: 236 Path fPath; 237 Mode fMode; 238 SkColorType fColorType; 239 }; 240 241 class SKPSrc : public Src { 242 public: 243 explicit SKPSrc(Path path); 244 245 Error draw(SkCanvas*) const override; 246 SkISize size() const override; 247 Name name() const override; 248 private: 249 Path fPath; 250 }; 251 252 #if defined(SK_XML) 253 } // namespace DM 254 255 class SkSVGDOM; 256 257 namespace DM { 258 259 class SVGSrc : public Src { 260 public: 261 explicit SVGSrc(Path path); 262 263 Error draw(SkCanvas*) const override; 264 SkISize size() const override; 265 Name name() const override; 266 bool veto(SinkFlags) const override; 267 268 private: 269 Name fName; 270 sk_sp<SkSVGDOM> fDom; 271 SkScalar fScale; 272 273 typedef Src INHERITED; 274 }; 275 #endif // SK_XML 276 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 277 278 class MSKPSrc : public Src { 279 public: 280 explicit MSKPSrc(Path path); 281 282 int pageCount() const override; 283 Error draw(SkCanvas* c) const override; 284 Error draw(int, SkCanvas*) const override; 285 SkISize size() const override; 286 SkISize size(int) const override; 287 Name name() const override; 288 289 private: 290 Path fPath; 291 SkMultiPictureDocumentReader fReader; 292 }; 293 294 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 295 296 class NullSink : public Sink { 297 public: NullSink()298 NullSink() {} 299 300 Error draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()301 const char* fileExtension() const override { return ""; } flags()302 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; } 303 }; 304 305 306 class GPUSink : public Sink { 307 public: 308 GPUSink(sk_gpu_test::GrContextFactory::ContextType, 309 sk_gpu_test::GrContextFactory::ContextOverrides, 310 int samples, bool diText, SkColorType colorType, sk_sp<SkColorSpace> colorSpace, 311 bool threaded); 312 313 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; serial()314 bool serial() const override { return !fThreaded; } fileExtension()315 const char* fileExtension() const override { return "png"; } flags()316 SinkFlags flags() const override { 317 SinkFlags::Multisampled ms = fSampleCount > 0 ? SinkFlags::kMultisampled 318 : SinkFlags::kNotMultisampled; 319 return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect, ms }; 320 } 321 private: 322 sk_gpu_test::GrContextFactory::ContextType fContextType; 323 sk_gpu_test::GrContextFactory::ContextOverrides fContextOverrides; 324 int fSampleCount; 325 bool fUseDIText; 326 SkColorType fColorType; 327 sk_sp<SkColorSpace> fColorSpace; 328 bool fThreaded; 329 }; 330 331 class PDFSink : public Sink { 332 public: fPDFA(pdfa)333 PDFSink(bool pdfa = false) : fPDFA(pdfa) {} 334 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()335 const char* fileExtension() const override { return "pdf"; } flags()336 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 337 bool fPDFA; 338 }; 339 340 class XPSSink : public Sink { 341 public: 342 XPSSink(); 343 344 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()345 const char* fileExtension() const override { return "xps"; } flags()346 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 347 }; 348 349 class PipeSink : public Sink { 350 public: 351 PipeSink(); 352 353 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()354 const char* fileExtension() const override { return "skpipe"; } flags()355 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 356 }; 357 358 class RasterSink : public Sink { 359 public: 360 explicit RasterSink(SkColorType, sk_sp<SkColorSpace> = nullptr); 361 362 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()363 const char* fileExtension() const override { return "png"; } flags()364 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; } 365 private: 366 SkColorType fColorType; 367 sk_sp<SkColorSpace> fColorSpace; 368 }; 369 370 class SKPSink : public Sink { 371 public: 372 SKPSink(); 373 374 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()375 const char* fileExtension() const override { return "skp"; } flags()376 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 377 }; 378 379 class DebugSink : public Sink { 380 public: 381 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()382 const char* fileExtension() const override { return "json"; } flags()383 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 384 }; 385 386 class SVGSink : public Sink { 387 public: 388 SVGSink(); 389 390 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()391 const char* fileExtension() const override { return "svg"; } flags()392 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 393 }; 394 395 396 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 397 398 class Via : public Sink { 399 public: Via(Sink * sink)400 explicit Via(Sink* sink) : fSink(sink) {} fileExtension()401 const char* fileExtension() const override { return fSink->fileExtension(); } serial()402 bool serial() const override { return fSink->serial(); } flags()403 SinkFlags flags() const override { 404 SinkFlags flags = fSink->flags(); 405 flags.approach = SinkFlags::kIndirect; 406 return flags; 407 } 408 protected: 409 std::unique_ptr<Sink> fSink; 410 }; 411 412 class ViaMatrix : public Via { 413 public: 414 ViaMatrix(SkMatrix, Sink*); 415 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 416 private: 417 const SkMatrix fMatrix; 418 }; 419 420 class ViaUpright : public Via { 421 public: 422 ViaUpright(SkMatrix, Sink*); 423 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 424 private: 425 const SkMatrix fMatrix; 426 }; 427 428 class ViaSerialization : public Via { 429 public: ViaSerialization(Sink * sink)430 explicit ViaSerialization(Sink* sink) : Via(sink) {} 431 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 432 }; 433 434 class ViaPicture : public Via { 435 public: ViaPicture(Sink * sink)436 explicit ViaPicture(Sink* sink) : Via(sink) {} 437 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 438 }; 439 440 class ViaPipe : public Via { 441 public: ViaPipe(Sink * sink)442 explicit ViaPipe(Sink* sink) : Via(sink) {} 443 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 444 }; 445 446 class ViaDefer : public Via { 447 public: ViaDefer(Sink * sink)448 explicit ViaDefer(Sink* sink) : Via(sink) {} 449 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 450 }; 451 452 class ViaTiles : public Via { 453 public: 454 ViaTiles(int w, int h, SkBBHFactory*, Sink*); 455 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 456 private: 457 const int fW, fH; 458 std::unique_ptr<SkBBHFactory> fFactory; 459 }; 460 461 class ViaSecondPicture : public Via { 462 public: ViaSecondPicture(Sink * sink)463 explicit ViaSecondPicture(Sink* sink) : Via(sink) {} 464 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 465 }; 466 467 class ViaSingletonPictures : public Via { 468 public: ViaSingletonPictures(Sink * sink)469 explicit ViaSingletonPictures(Sink* sink) : Via(sink) {} 470 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 471 }; 472 473 class ViaTwice : public Via { 474 public: ViaTwice(Sink * sink)475 explicit ViaTwice(Sink* sink) : Via(sink) {} 476 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 477 }; 478 479 class ViaSVG : public Via { 480 public: ViaSVG(Sink * sink)481 explicit ViaSVG(Sink* sink) : Via(sink) {} 482 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 483 }; 484 485 class ViaMojo : public Via { 486 public: ViaMojo(Sink * sink)487 explicit ViaMojo(Sink* sink) : Via(sink) {} 488 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 489 }; 490 491 class ViaLite : public Via { 492 public: ViaLite(Sink * sink)493 explicit ViaLite(Sink* sink) : Via(sink) {} 494 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 495 }; 496 497 class ViaCSXform : public Via { 498 public: 499 explicit ViaCSXform(Sink*, sk_sp<SkColorSpace>, bool colorSpin); 500 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 501 private: 502 sk_sp<SkColorSpace> fCS; 503 bool fColorSpin; 504 }; 505 506 } // namespace DM 507 508 #endif//DMSrcSink_DEFINED 509