• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 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 skiagm_DEFINED
9 #define skiagm_DEFINED
10 
11 #include "include/core/SkColor.h"
12 #include "include/core/SkScalar.h"
13 #include "include/core/SkSize.h"
14 #include "include/core/SkString.h"
15 #include "include/core/SkTypes.h"
16 #include "include/private/SkMacros.h"
17 #include "tools/Registry.h"
18 
19 #include <memory>
20 
21 class GrContext;
22 class GrRenderTargetContext;
23 class SkCanvas;
24 class SkMetaData;
25 struct GrContextOptions;
26 
27 #define DEF_GM(CODE) \
28     static skiagm::GMRegistry SK_MACRO_APPEND_LINE(REG_)(\
29             [](){return std::unique_ptr<skiagm::GM>([](){ CODE ; }());});
30 
31 // A Simple GM is a rendering test that does not store state between rendering calls or make use of
32 // the onOnceBeforeDraw() virtual; it consists of:
33 //   *   A name.
34 //   *   Prefered width and height.
35 //   *   Optionally, a background color (default is white).
36 //   *   A standalone function pointer that implements its onDraw method.
37 #define DEF_SIMPLE_GM(NAME, CANVAS, W, H) \
38     DEF_SIMPLE_GM_BG_NAME(NAME, CANVAS, W, H, SK_ColorWHITE, SkString(#NAME))
39 #define DEF_SIMPLE_GM_BG(NAME, CANVAS, W, H, BGCOLOR) \
40     DEF_SIMPLE_GM_BG_NAME(NAME, CANVAS, W, H, BGCOLOR, SkString(#NAME))
41 #define DEF_SIMPLE_GM_BG_NAME(NAME, CANVAS, W, H, BGCOLOR, NAME_STR) \
42     static void SK_MACRO_CONCAT(NAME,_GM_inner)(SkCanvas*); \
43     DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS,, W, H, BGCOLOR, NAME_STR) { \
44         SK_MACRO_CONCAT(NAME,_GM_inner)(CANVAS); \
45         return skiagm::DrawResult::kOk; \
46     } \
47     void SK_MACRO_CONCAT(NAME,_GM_inner)(SkCanvas* CANVAS)
48 
49 #define DEF_SIMPLE_GM_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H) \
50     DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, SK_ColorWHITE, SkString(#NAME))
51 #define DEF_SIMPLE_GM_BG_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, BGCOLOR) \
52     DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, BGCOLOR, SkString(#NAME))
53 #define DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, BGCOLOR, NAME_STR) \
54     static skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)(SkCanvas*, SkString*); \
55     DEF_GM(return new skiagm::SimpleGM(BGCOLOR, NAME_STR, {W,H}, SK_MACRO_CONCAT(NAME,_GM));) \
56     skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)(SkCanvas* CANVAS, SkString* ERR_MSG)
57 
58 
59 // A Simple GpuGM makes direct GPU calls. Its onDraw hook that includes GPU objects as params, and
60 // is only invoked on GPU configs. Non-GPU configs automatically draw a GPU-only message and abort.
61 #define DEF_SIMPLE_GPU_GM(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS, W, H) \
62     DEF_SIMPLE_GPU_GM_BG(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS, W, H, SK_ColorWHITE)
63 #define DEF_SIMPLE_GPU_GM_BG(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS, W, H, BGCOLOR) \
64     static void SK_MACRO_CONCAT(NAME,_GM_inner)(GrContext*, GrRenderTargetContext*, SkCanvas*); \
65     DEF_SIMPLE_GPU_GM_BG_CAN_FAIL(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS,, W, H, \
66                                   BGCOLOR) { \
67         SK_MACRO_CONCAT(NAME,_GM_inner)(GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS); \
68         return skiagm::DrawResult::kOk; \
69     } \
70     void SK_MACRO_CONCAT(NAME,_GM_inner)( \
71             GrContext* GR_CONTEXT, GrRenderTargetContext* RENDER_TARGET_CONTEXT, SkCanvas* CANVAS)
72 
73 #define DEF_SIMPLE_GPU_GM_CAN_FAIL(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS, ERR_MSG, W, H) \
74     DEF_SIMPLE_GPU_GM_BG_CAN_FAIL(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS, \
75                                   ERR_MSG, W, H, SK_ColorWHITE)
76 #define DEF_SIMPLE_GPU_GM_BG_CAN_FAIL(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS, ERR_MSG, W, \
77                                       H, BGCOLOR) \
78     static skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)( \
79             GrContext*, GrRenderTargetContext*, SkCanvas*, SkString*); \
80     DEF_GM(return new skiagm::SimpleGpuGM(BGCOLOR, SkString(#NAME), {W,H}, \
81                                           SK_MACRO_CONCAT(NAME,_GM));) \
82     skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)( \
83             GrContext* GR_CONTEXT, GrRenderTargetContext* RENDER_TARGET_CONTEXT, SkCanvas* CANVAS, \
84             SkString* ERR_MSG)
85 
86 namespace skiagm {
87 
88     enum class DrawResult {
89         kOk,  // Test drew successfully.
90         kFail,  // Test failed to draw.
91         kSkip  // Test is not applicable in this context and should be skipped.
92     };
93 
94     class GM {
95     public:
96         using DrawResult = skiagm::DrawResult;
97 
98         GM(SkColor backgroundColor = SK_ColorWHITE);
99         virtual ~GM();
100 
101         enum Mode {
102             kGM_Mode,
103             kSample_Mode,
104             kBench_Mode,
105         };
106 
setMode(Mode mode)107         void setMode(Mode mode) { fMode = mode; }
getMode()108         Mode getMode() const { return fMode; }
109 
110         static constexpr char kErrorMsg_DrawSkippedGpuOnly[] = "This test is for GPU configs only.";
111 
draw(SkCanvas * canvas)112         DrawResult draw(SkCanvas* canvas) {
113             SkString errorMsg;
114             return this->draw(canvas, &errorMsg);
115         }
116         DrawResult draw(SkCanvas*, SkString* errorMsg);
117 
118         void drawBackground(SkCanvas*);
drawContent(SkCanvas * canvas)119         DrawResult drawContent(SkCanvas* canvas) {
120             SkString errorMsg;
121             return this->drawContent(canvas, &errorMsg);
122         }
123         DrawResult drawContent(SkCanvas*, SkString* errorMsg);
124 
getISize()125         SkISize getISize() { return this->onISize(); }
126         const char* getName();
127 
128         virtual bool runAsBench() const;
129 
width()130         SkScalar width() {
131             return SkIntToScalar(this->getISize().width());
132         }
height()133         SkScalar height() {
134             return SkIntToScalar(this->getISize().height());
135         }
136 
getBGColor()137         SkColor getBGColor() const { return fBGColor; }
138         void setBGColor(SkColor);
139 
140         // helper: fill a rect in the specified color based on the GM's getISize bounds.
141         void drawSizeBounds(SkCanvas*, SkColor);
142 
isCanvasDeferred()143         bool isCanvasDeferred() const { return fCanvasIsDeferred; }
setCanvasIsDeferred(bool isDeferred)144         void setCanvasIsDeferred(bool isDeferred) {
145             fCanvasIsDeferred = isDeferred;
146         }
147 
148         bool animate(double /*nanos*/);
149         virtual bool onChar(SkUnichar);
150 
getControls(SkMetaData * controls)151         bool getControls(SkMetaData* controls) { return this->onGetControls(controls); }
setControls(const SkMetaData & controls)152         void setControls(const SkMetaData& controls) { this->onSetControls(controls); }
153 
154         virtual void modifyGrContextOptions(GrContextOptions*);
155 
156     protected:
157         virtual void onOnceBeforeDraw();
158         virtual DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg);
159         virtual void onDraw(SkCanvas*);
160 
161         virtual SkISize onISize() = 0;
162         virtual SkString onShortName() = 0;
163 
164         virtual bool onAnimate(double /*nanos*/);
165         virtual bool onGetControls(SkMetaData*);
166         virtual void onSetControls(const SkMetaData&);
167 
168     private:
169         Mode     fMode;
170         SkString fShortName;
171         SkColor  fBGColor;
172         bool     fCanvasIsDeferred; // work-around problem in srcmode.cpp
173         bool     fHaveCalledOnceBeforeDraw;
174     };
175 
176     using GMFactory = std::unique_ptr<skiagm::GM> (*)();
177     using GMRegistry = sk_tools::Registry<GMFactory>;
178 
179     // A GpuGM replaces the onDraw method with one that also accepts GPU objects alongside the
180     // SkCanvas. Its onDraw is only invoked on GPU configs; on non-GPU configs it will automatically
181     // draw a GPU-only message and abort.
182     class GpuGM : public GM {
183     public:
GM(backgroundColor)184         GpuGM(SkColor backgroundColor = SK_ColorWHITE) : GM(backgroundColor) {}
185     private:
186         using GM::onDraw;
187         DrawResult onDraw(SkCanvas*, SkString* errorMsg) final;
188 
189         virtual DrawResult onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* canvas,
190                                   SkString* errorMsg);
191         virtual void onDraw(GrContext*, GrRenderTargetContext*, SkCanvas*);
192     };
193 
194     // SimpleGM is intended for basic GMs that can define their entire implementation inside a
195     // single "draw" function pointer.
196     class SimpleGM : public GM {
197     public:
198         using DrawProc = DrawResult(*)(SkCanvas*, SkString*);
SimpleGM(SkColor bgColor,const SkString & name,const SkISize & size,DrawProc drawProc)199         SimpleGM(SkColor bgColor, const SkString& name, const SkISize& size, DrawProc drawProc)
200                 : GM(bgColor), fName(name), fSize(size), fDrawProc(drawProc) {}
201 
202     private:
203         SkISize onISize() override;
204         SkString onShortName() override;
205         DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override;
206 
207         const SkString fName;
208         const SkISize fSize;
209         const DrawProc fDrawProc;
210     };
211 
212     class SimpleGpuGM : public GpuGM {
213     public:
214         using DrawProc = DrawResult(*)(GrContext*, GrRenderTargetContext*, SkCanvas*, SkString*);
SimpleGpuGM(SkColor bgColor,const SkString & name,const SkISize & size,DrawProc drawProc)215         SimpleGpuGM(SkColor bgColor, const SkString& name, const SkISize& size, DrawProc drawProc)
216                 : GpuGM(bgColor), fName(name), fSize(size), fDrawProc(drawProc) {}
217 
218     private:
219         SkISize onISize() override;
220         SkString onShortName() override;
221         DrawResult onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* canvas,
222                           SkString* errorMsg) override;
223 
224         const SkString fName;
225         const SkISize fSize;
226         const DrawProc fDrawProc;
227     };
228 }
229 
230 void MarkGMGood(SkCanvas*, SkScalar x, SkScalar y);
231 void MarkGMBad (SkCanvas*, SkScalar x, SkScalar y);
232 
233 #endif
234