Test color correction in DM
[platform/upstream/libSkiaSharp.git] / dm / DMSrcSink.h
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 "SkPicture.h"
19 #include "gm.h"
20
21 namespace DM {
22
23 // This is just convenience.  It lets you use either return "foo" or return SkStringPrintf(...).
24 struct ImplicitString : public SkString {
25     template <typename T>
26     ImplicitString(const T& s) : SkString(s) {}
27     ImplicitString() : SkString("") {}
28 };
29 typedef ImplicitString Name;
30 typedef ImplicitString Path;
31
32 class Error {
33 public:
34     Error(const SkString& s) : fMsg(s), fFatal(!this->isEmpty()) {}
35     Error(const char* s)     : fMsg(s), fFatal(!this->isEmpty()) {}
36
37     Error(const Error&)            = default;
38     Error& operator=(const Error&) = default;
39
40     static Error Nonfatal(const SkString& s) { return Nonfatal(s.c_str()); }
41     static Error Nonfatal(const char* s) {
42         Error e(s);
43         e.fFatal = false;
44         return e;
45     }
46
47     const char* c_str() const { return fMsg.c_str(); }
48     bool isEmpty() const { return fMsg.isEmpty(); }
49     bool isFatal() const { return fFatal; }
50
51 private:
52     SkString fMsg;
53     bool     fFatal;
54 };
55
56 struct SinkFlags {
57     enum { kNull, kGPU, kVector, kRaster } type;
58     enum { kDirect, kIndirect } approach;
59 };
60
61 struct Src {
62     virtual ~Src() {}
63     virtual Error SK_WARN_UNUSED_RESULT draw(SkCanvas*) const = 0;
64     virtual SkISize size() const = 0;
65     virtual Name name() const = 0;
66     virtual void modifyGrContextOptions(GrContextOptions* options) const {}
67     virtual bool veto(SinkFlags) const { return false; }
68
69     // Force Tasks using this Src to run on the main thread?
70     virtual bool serial() const { return false; }
71 };
72
73 struct Sink {
74     virtual ~Sink() {}
75     // You may write to either the bitmap or stream.  If you write to log, we'll print that out.
76     virtual Error SK_WARN_UNUSED_RESULT draw(const Src&, SkBitmap*, SkWStream*, SkString* log)
77         const = 0;
78
79     // Force Tasks using this Sink to run on the main thread?
80     virtual bool serial() const { return false; }
81
82     // File extension for the content draw() outputs, e.g. "png", "pdf".
83     virtual const char* fileExtension() const  = 0;
84
85     virtual SinkFlags flags() const = 0;
86 };
87
88 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
89
90 class GMSrc : public Src {
91 public:
92     explicit GMSrc(skiagm::GMRegistry::Factory);
93
94     Error draw(SkCanvas*) const override;
95     SkISize size() const override;
96     Name name() const override;
97     void modifyGrContextOptions(GrContextOptions* options) const override;
98
99 private:
100     skiagm::GMRegistry::Factory fFactory;
101 };
102
103 class CodecSrc : public Src {
104 public:
105     enum Mode {
106         kCodec_Mode,
107         // We choose to test only one mode with zero initialized memory.
108         // This will exercise all of the interesting cases in SkSwizzler
109         // without doubling the size of our test suite.
110         kCodecZeroInit_Mode,
111         kScanline_Mode,
112         kStripe_Mode, // Tests the skipping of scanlines
113         kCroppedScanline_Mode, // Tests (jpeg) cropped scanline optimization
114         kSubset_Mode, // For codecs that support subsets directly.
115     };
116     enum DstColorType {
117         kGetFromCanvas_DstColorType,
118         kIndex8_Always_DstColorType,
119         kGrayscale_Always_DstColorType,
120         kNonNative8888_Always_DstColorType,
121     };
122     CodecSrc(Path, Mode, DstColorType, SkAlphaType, float);
123
124     Error draw(SkCanvas*) const override;
125     SkISize size() const override;
126     Name name() const override;
127     bool veto(SinkFlags) const override;
128     bool serial() const override { return fRunSerially; }
129 private:
130     Path                    fPath;
131     Mode                    fMode;
132     DstColorType            fDstColorType;
133     SkAlphaType             fDstAlphaType;
134     float                   fScale;
135     bool                    fRunSerially;
136 };
137
138 class AndroidCodecSrc : public Src {
139 public:
140     AndroidCodecSrc(Path, CodecSrc::DstColorType, SkAlphaType, int sampleSize);
141
142     Error draw(SkCanvas*) const override;
143     SkISize size() const override;
144     Name name() const override;
145     bool veto(SinkFlags) const override;
146     bool serial() const override { return fRunSerially; }
147 private:
148     Path                    fPath;
149     CodecSrc::DstColorType  fDstColorType;
150     SkAlphaType             fDstAlphaType;
151     int                     fSampleSize;
152     bool                    fRunSerially;
153 };
154
155 // Allows for testing of various implementations of Android's BitmapRegionDecoder
156 class BRDSrc : public Src {
157 public:
158     enum Mode {
159         // Decode the entire image as one region.
160         kFullImage_Mode,
161         // Splits the image into multiple regions using a divisor and decodes the regions
162         // separately.  Also, this test adds a border of a few pixels to each of the regions
163         // that it is decoding.  This tests the behavior when a client asks for a region that
164         // does not fully fit in the image.
165         kDivisor_Mode,
166     };
167
168     BRDSrc(Path, Mode, CodecSrc::DstColorType, uint32_t);
169
170     Error draw(SkCanvas*) const override;
171     SkISize size() const override;
172     Name name() const override;
173     bool veto(SinkFlags) const override;
174 private:
175     Path                                     fPath;
176     Mode                                     fMode;
177     CodecSrc::DstColorType                   fDstColorType;
178     uint32_t                                 fSampleSize;
179 };
180
181 class ImageGenSrc : public Src {
182 public:
183     enum Mode {
184         kCodec_Mode,    // Use CodecImageGenerator
185         kPlatform_Mode, // Uses CG or WIC
186     };
187     ImageGenSrc(Path, Mode, SkAlphaType, bool);
188
189     Error draw(SkCanvas*) const override;
190     SkISize size() const override;
191     Name name() const override;
192     bool veto(SinkFlags) const override;
193     bool serial() const override { return fRunSerially; }
194 private:
195     Path        fPath;
196     Mode        fMode;
197     SkAlphaType fDstAlphaType;
198     bool        fIsGpu;
199     bool        fRunSerially;
200 };
201
202 class ColorCodecSrc : public Src {
203 public:
204     enum Mode {
205         // Mimic legacy behavior and apply no color correction.
206         kBaseline_Mode,
207
208         // Color correct images into a specific dst color space.  If you happen to have this
209         // monitor, you're in luck!  The unmarked outputs of this test should display
210         // correctly on this monitor in the Chrome browser.  If not, it's useful to know
211         // that this monitor has a profile that is fairly similar to Adobe RGB.
212         // TODO (msarett): Should we add a new test with a new monitor and verify that outputs
213         //                 look identical on two different dsts?
214         kDst_HPZR30w_Mode,
215     };
216
217     ColorCodecSrc(Path, Mode, sk_sp<SkColorSpace>);
218
219     Error draw(SkCanvas*) const override;
220     SkISize size() const override;
221     Name name() const override;
222     bool veto(SinkFlags) const override;
223 private:
224     Path                    fPath;
225     Mode                    fMode;
226     sk_sp<SkColorSpace>     fDstSpace;
227 };
228
229 class SKPSrc : public Src {
230 public:
231     explicit SKPSrc(Path path);
232
233     Error draw(SkCanvas*) const override;
234     SkISize size() const override;
235     Name name() const override;
236 private:
237     Path fPath;
238 };
239
240 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
241
242 class NullSink : public Sink {
243 public:
244     NullSink() {}
245
246     Error draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override;
247     const char* fileExtension() const override { return ""; }
248     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; }
249 };
250
251
252 class GPUSink : public Sink {
253 public:
254     GPUSink(sk_gpu_test::GrContextFactory::ContextType,
255             sk_gpu_test::GrContextFactory::ContextOptions,
256             int samples, bool diText, SkColorType colorType, SkColorProfileType profileType,
257             bool threaded);
258
259     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
260     bool serial() const override { return !fThreaded; }
261     const char* fileExtension() const override { return "png"; }
262     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect }; }
263 private:
264     sk_gpu_test::GrContextFactory::ContextType      fContextType;
265     sk_gpu_test::GrContextFactory::ContextOptions   fContextOptions;
266     int                                             fSampleCount;
267     bool                                            fUseDIText;
268     SkColorType                                     fColorType;
269     SkColorProfileType                              fProfileType;
270     bool                                            fThreaded;
271 };
272
273 class PDFSink : public Sink {
274 public:
275     PDFSink(bool pdfa = false) : fPDFA(pdfa) {}
276     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
277     const char* fileExtension() const override { return "pdf"; }
278     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
279     bool fPDFA;
280 };
281
282 class XPSSink : public Sink {
283 public:
284     XPSSink();
285
286     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
287     const char* fileExtension() const override { return "xps"; }
288     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
289 };
290
291 class RasterSink : public Sink {
292 public:
293     explicit RasterSink(SkColorType, SkColorProfileType=kLinear_SkColorProfileType);
294
295     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
296     const char* fileExtension() const override { return "png"; }
297     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; }
298 private:
299     SkColorType        fColorType;
300     SkColorProfileType fProfileType;
301 };
302
303 class SKPSink : public Sink {
304 public:
305     SKPSink();
306
307     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
308     const char* fileExtension() const override { return "skp"; }
309     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
310 };
311
312 class SVGSink : public Sink {
313 public:
314     SVGSink();
315
316     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
317     const char* fileExtension() const override { return "svg"; }
318     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
319 };
320
321
322 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
323
324 class Via : public Sink {
325 public:
326     explicit Via(Sink* sink) : fSink(sink) {}
327     const char* fileExtension() const override { return fSink->fileExtension(); }
328     bool               serial() const override { return fSink->serial(); }
329     SinkFlags flags() const override {
330         SinkFlags flags = fSink->flags();
331         flags.approach = SinkFlags::kIndirect;
332         return flags;
333     }
334 protected:
335     SkAutoTDelete<Sink> fSink;
336 };
337
338 class ViaMatrix : public Via {
339 public:
340     ViaMatrix(SkMatrix, Sink*);
341     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
342 private:
343     const SkMatrix fMatrix;
344 };
345
346 class ViaUpright : public Via {
347 public:
348     ViaUpright(SkMatrix, Sink*);
349     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
350 private:
351     const SkMatrix fMatrix;
352 };
353
354 class ViaSerialization : public Via {
355 public:
356     explicit ViaSerialization(Sink* sink) : Via(sink) {}
357     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
358 };
359
360 class ViaPicture : public Via {
361 public:
362     explicit ViaPicture(Sink* sink) : Via(sink) {}
363     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
364 };
365
366 class ViaTiles : public Via {
367 public:
368     ViaTiles(int w, int h, SkBBHFactory*, Sink*);
369     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
370 private:
371     const int                   fW, fH;
372     SkAutoTDelete<SkBBHFactory> fFactory;
373 };
374
375 class ViaSecondPicture : public Via {
376 public:
377     explicit ViaSecondPicture(Sink* sink) : Via(sink) {}
378     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
379 };
380
381 class ViaSingletonPictures : public Via {
382 public:
383     explicit ViaSingletonPictures(Sink* sink) : Via(sink) {}
384     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
385 };
386
387 class ViaTwice : public Via {
388 public:
389     explicit ViaTwice(Sink* sink) : Via(sink) {}
390     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
391 };
392
393 class ViaMojo : public Via {
394 public:
395     explicit ViaMojo(Sink* sink) : Via(sink) {}
396     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
397 };
398
399 }  // namespace DM
400
401 #endif//DMSrcSink_DEFINED