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 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 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 enum Mode { 216 // Mimic legacy behavior and apply no color correction. 217 kBaseline_Mode, 218 219 // Color correct images into a specific dst color space. If you happen to have this 220 // monitor, you're in luck! The unmarked outputs of this test should display 221 // correctly on this monitor in the Chrome browser. If not, it's useful to know 222 // that this monitor has a profile that is fairly similar to Adobe RGB. 223 kDst_HPZR30w_Mode, 224 225 kDst_sRGB_Mode, 226 }; 227 228 ColorCodecSrc(Path, Mode, SkColorType); 229 230 Error draw(SkCanvas*) const override; 231 SkISize size() const override; 232 Name name() const override; 233 bool veto(SinkFlags) const override; 234 private: 235 Path fPath; 236 Mode fMode; 237 SkColorType fColorType; 238 }; 239 240 class SKPSrc : public Src { 241 public: 242 explicit SKPSrc(Path path); 243 244 Error draw(SkCanvas*) const override; 245 SkISize size() const override; 246 Name name() const override; 247 private: 248 Path fPath; 249 }; 250 251 #if defined(SK_XML) 252 } // namespace DM 253 254 class SkSVGDOM; 255 256 namespace DM { 257 258 class SVGSrc : public Src { 259 public: 260 explicit SVGSrc(Path path); 261 262 Error draw(SkCanvas*) const override; 263 SkISize size() const override; 264 Name name() const override; 265 bool veto(SinkFlags) const override; 266 267 private: 268 Name fName; 269 sk_sp<SkSVGDOM> fDom; 270 SkScalar fScale; 271 272 typedef Src INHERITED; 273 }; 274 #endif // SK_XML 275 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 276 277 class MSKPSrc : public Src { 278 public: 279 explicit MSKPSrc(Path path); 280 281 int pageCount() const override; 282 Error draw(SkCanvas* c) const override; 283 Error draw(int, SkCanvas*) const override; 284 SkISize size() const override; 285 SkISize size(int) const override; 286 Name name() const override; 287 288 private: 289 Path fPath; 290 mutable SkTArray<SkDocumentPage> fPages; 291 }; 292 293 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 294 295 class NullSink : public Sink { 296 public: NullSink()297 NullSink() {} 298 299 Error draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()300 const char* fileExtension() const override { return ""; } flags()301 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; } 302 }; 303 304 305 class GPUSink : public Sink { 306 public: 307 GPUSink(sk_gpu_test::GrContextFactory::ContextType, 308 sk_gpu_test::GrContextFactory::ContextOverrides, int samples, bool diText, 309 SkColorType colorType, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace, 310 bool threaded); 311 312 Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; serial()313 bool serial() const override { return !fThreaded; } fileExtension()314 const char* fileExtension() const override { return "png"; } flags()315 SinkFlags flags() const override { 316 SinkFlags::Multisampled ms = fSampleCount > 0 ? SinkFlags::kMultisampled 317 : SinkFlags::kNotMultisampled; 318 return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect, ms }; 319 } 320 private: 321 sk_gpu_test::GrContextFactory::ContextType fContextType; 322 sk_gpu_test::GrContextFactory::ContextOverrides fContextOverrides; 323 int fSampleCount; 324 bool fUseDIText; 325 SkColorType fColorType; 326 SkAlphaType fAlphaType; 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