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>
ImplicitStringImplicitString26     ImplicitString(const T& s) : SkString(s) {}
ImplicitStringImplicitString27     ImplicitString() : SkString("") {}
28 };
29 typedef ImplicitString Name;
30 typedef ImplicitString Path;
31 
32 class Error {
33 public:
Error(const SkString & s)34     Error(const SkString& s) : fMsg(s), fFatal(!this->isEmpty()) {}
Error(const char * s)35     Error(const char* s)     : fMsg(s), fFatal(!this->isEmpty()) {}
36 
37     Error(const Error&)            = default;
38     Error& operator=(const Error&) = default;
39 
Nonfatal(const SkString & s)40     static Error Nonfatal(const SkString& s) { return Nonfatal(s.c_str()); }
Nonfatal(const char * s)41     static Error Nonfatal(const char* s) {
42         Error e(s);
43         e.fFatal = false;
44         return e;
45     }
46 
c_str()47     const char* c_str() const { return fMsg.c_str(); }
isEmpty()48     bool isEmpty() const { return fMsg.isEmpty(); }
isFatal()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 {
~SrcSrc62     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;
modifyGrContextOptionsSrc66     virtual void modifyGrContextOptions(GrContextOptions* options) const {}
vetoSrc67     virtual bool veto(SinkFlags) const { return false; }
68 
69     // Force Tasks using this Src to run on the main thread?
serialSrc70     virtual bool serial() const { return false; }
71 };
72 
73 struct Sink {
~SinkSink74     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?
serialSink80     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         kGen_Mode,    // Test SkCodecImageGenerator (includes YUV)
116     };
117     enum DstColorType {
118         kGetFromCanvas_DstColorType,
119         kIndex8_Always_DstColorType,
120         kGrayscale_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;
veto(SinkFlags)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     enum Mode {
141         kFullImage_Mode,
142         // Splits the image into multiple subsets using a divisor and decodes the subsets
143         // separately.
144         kDivisor_Mode,
145     };
146 
147     AndroidCodecSrc(Path, Mode, CodecSrc::DstColorType, SkAlphaType, int sampleSize);
148 
149     Error draw(SkCanvas*) const override;
150     SkISize size() const override;
151     Name name() const override;
veto(SinkFlags)152     bool veto(SinkFlags) const override;
153     bool serial() const override { return fRunSerially; }
154 private:
155     Path                    fPath;
156     Mode                    fMode;
157     CodecSrc::DstColorType  fDstColorType;
158     SkAlphaType             fDstAlphaType;
159     int                     fSampleSize;
160     bool                    fRunSerially;
161 };
162 
163 // Allows for testing of various implementations of Android's BitmapRegionDecoder
164 class BRDSrc : public Src {
165 public:
166     enum Mode {
167         // Decode the entire image as one region.
168         kFullImage_Mode,
169         // Splits the image into multiple regions using a divisor and decodes the regions
170         // separately.  Also, this test adds a border of a few pixels to each of the regions
171         // that it is decoding.  This tests the behavior when a client asks for a region that
172         // does not fully fit in the image.
173         kDivisor_Mode,
174     };
175 
176     BRDSrc(Path, SkBitmapRegionDecoder::Strategy, Mode, CodecSrc::DstColorType, uint32_t);
177 
178     Error draw(SkCanvas*) const override;
179     SkISize size() const override;
180     Name name() const override;
181     bool veto(SinkFlags) const override;
182 private:
183     Path                                     fPath;
184     SkBitmapRegionDecoder::Strategy          fStrategy;
185     Mode                                     fMode;
186     CodecSrc::DstColorType                   fDstColorType;
187     uint32_t                                 fSampleSize;
188 };
189 
190 class SKPSrc : public Src {
191 public:
192     explicit SKPSrc(Path path);
193 
194     Error draw(SkCanvas*) const override;
195     SkISize size() const override;
196     Name name() const override;
197 private:
198     Path fPath;
199 };
200 
201 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
202 
203 class NullSink : public Sink {
204 public:
NullSink()205     NullSink() {}
206 
207     Error draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()208     const char* fileExtension() const override { return ""; }
flags()209     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; }
210 };
211 
212 
213 class GPUSink : public Sink {
214 public:
215     GPUSink(GrContextFactory::GLContextType, GrContextFactory::GLContextOptions,
216             int samples, bool diText, bool threaded);
217 
218     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
serial()219     bool serial() const override { return !fThreaded; }
fileExtension()220     const char* fileExtension() const override { return "png"; }
flags()221     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect }; }
222 private:
223     GrContextFactory::GLContextType    fContextType;
224     GrContextFactory::GLContextOptions fContextOptions;
225     int                                fSampleCount;
226     bool                               fUseDIText;
227     bool                               fThreaded;
228 };
229 
230 class PDFSink : public Sink {
231 public:
232     PDFSink(const char* rasterizer);
233 
234     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()235     const char* fileExtension() const override { return "pdf"; }
flags()236     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
237 private:
238     const char* fRasterizer;
239 };
240 
241 class XPSSink : public Sink {
242 public:
243     XPSSink();
244 
245     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()246     const char* fileExtension() const override { return "xps"; }
flags()247     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
248 };
249 
250 class RasterSink : public Sink {
251 public:
252     explicit RasterSink(SkColorType);
253 
254     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()255     const char* fileExtension() const override { return "png"; }
flags()256     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; }
257 private:
258     SkColorType    fColorType;
259 };
260 
261 class SKPSink : public Sink {
262 public:
263     SKPSink();
264 
265     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()266     const char* fileExtension() const override { return "skp"; }
flags()267     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
268 };
269 
270 class SVGSink : public Sink {
271 public:
272     SVGSink();
273 
274     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()275     const char* fileExtension() const override { return "svg"; }
flags()276     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
277 };
278 
279 
280 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
281 
282 class Via : public Sink {
283 public:
Via(Sink * sink)284     explicit Via(Sink* sink) : fSink(sink) {}
fileExtension()285     const char* fileExtension() const override { return fSink->fileExtension(); }
serial()286     bool               serial() const override { return fSink->serial(); }
flags()287     SinkFlags flags() const override {
288         SinkFlags flags = fSink->flags();
289         flags.approach = SinkFlags::kIndirect;
290         return flags;
291     }
292 protected:
293     SkAutoTDelete<Sink> fSink;
294 };
295 
296 class ViaMatrix : public Via {
297 public:
298     ViaMatrix(SkMatrix, Sink*);
299     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
300 private:
301     const SkMatrix fMatrix;
302 };
303 
304 class ViaUpright : public Via {
305 public:
306     ViaUpright(SkMatrix, Sink*);
307     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
308 private:
309     const SkMatrix fMatrix;
310 };
311 
312 class ViaRemote : public Via {
313 public:
ViaRemote(bool cache,Sink * sink)314     ViaRemote(bool cache, Sink* sink) : Via(sink), fCache(cache) {}
315     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
316 private:
317     bool fCache;
318 };
319 
320 class ViaSerialization : public Via {
321 public:
ViaSerialization(Sink * sink)322     explicit ViaSerialization(Sink* sink) : Via(sink) {}
323     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
324 };
325 
326 class ViaPicture : public Via {
327 public:
ViaPicture(Sink * sink)328     explicit ViaPicture(Sink* sink) : Via(sink) {}
329     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
330 };
331 
332 class ViaTiles : public Via {
333 public:
334     ViaTiles(int w, int h, SkBBHFactory*, Sink*);
335     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
336 private:
337     const int                   fW, fH;
338     SkAutoTDelete<SkBBHFactory> fFactory;
339 };
340 
341 class ViaSecondPicture : public Via {
342 public:
ViaSecondPicture(Sink * sink)343     explicit ViaSecondPicture(Sink* sink) : Via(sink) {}
344     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
345 };
346 
347 class ViaSingletonPictures : public Via {
348 public:
ViaSingletonPictures(Sink * sink)349     explicit ViaSingletonPictures(Sink* sink) : Via(sink) {}
350     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
351 };
352 
353 class ViaTwice : public Via {
354 public:
ViaTwice(Sink * sink)355     explicit ViaTwice(Sink* sink) : Via(sink) {}
356     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
357 };
358 
359 class ViaMojo : public Via {
360 public:
ViaMojo(Sink * sink)361     explicit ViaMojo(Sink* sink) : Via(sink) {}
362     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
363 };
364 
365 }  // namespace DM
366 
367 #endif//DMSrcSink_DEFINED
368