• 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 "../tools/Registry.h"
12 #include "SkBitmap.h"
13 #include "SkCanvas.h"
14 #include "SkClipOpPriv.h"
15 #include "SkMacros.h"
16 #include "SkPaint.h"
17 #include "SkSize.h"
18 #include "SkString.h"
19 
20 class SkAnimTimer;
21 class SkMetaData;
22 struct GrContextOptions;
23 
24 #define DEF_GM(code) \
25     static skiagm::GM*          SK_MACRO_APPEND_LINE(F_)(void*) { code; } \
26     static skiagm::GMRegistry   SK_MACRO_APPEND_LINE(R_)(SK_MACRO_APPEND_LINE(F_));
27 
28 // A Simple GM is a rendering test that does not store state between rendering calls or make use of
29 // the onOnceBeforeDraw() virtual; it consists of:
30 //   *   A name.
31 //   *   Prefered width and height.
32 //   *   Optionally, a background color (default is white).
33 //   *   A standalone function pointer that implements its onDraw method.
34 #define DEF_SIMPLE_GM(NAME, CANVAS, W, H) \
35     DEF_SIMPLE_GM_BG_NAME(NAME, CANVAS, W, H, SK_ColorWHITE, SkString(#NAME))
36 #define DEF_SIMPLE_GM_BG(NAME, CANVAS, W, H, BGCOLOR) \
37     DEF_SIMPLE_GM_BG_NAME(NAME, CANVAS, W, H, BGCOLOR, SkString(#NAME))
38 #define DEF_SIMPLE_GM_BG_NAME(NAME, CANVAS, W, H, BGCOLOR, NAME_STR) \
39     static void SK_MACRO_CONCAT(NAME,_GM_inner)(SkCanvas*); \
40     DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS,, W, H, BGCOLOR, NAME_STR) { \
41         SK_MACRO_CONCAT(NAME,_GM_inner)(CANVAS); \
42         return skiagm::DrawResult::kOk; \
43     } \
44     void SK_MACRO_CONCAT(NAME,_GM_inner)(SkCanvas* CANVAS)
45 
46 #define DEF_SIMPLE_GM_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H) \
47     DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, SK_ColorWHITE, SkString(#NAME))
48 #define DEF_SIMPLE_GM_BG_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, BGCOLOR) \
49     DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, BGCOLOR, SkString(#NAME))
50 #define DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, BGCOLOR, NAME_STR) \
51     static skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)(SkCanvas*, SkString*); \
52     DEF_GM(return new skiagm::SimpleGM(BGCOLOR, NAME_STR, {W,H}, SK_MACRO_CONCAT(NAME,_GM));) \
53     skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)(SkCanvas* CANVAS, SkString* ERR_MSG)
54 
55 
56 // A Simple GpuGM makes direct GPU calls. Its onDraw hook that includes GPU objects as params, and
57 // is only invoked on GPU configs. Non-GPU configs automatically draw a GPU-only message and abort.
58 #define DEF_SIMPLE_GPU_GM(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS, W, H) \
59     DEF_SIMPLE_GPU_GM_BG(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS, W, H, SK_ColorWHITE)
60 #define DEF_SIMPLE_GPU_GM_BG(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS, W, H, BGCOLOR) \
61     static void SK_MACRO_CONCAT(NAME,_GM_inner)(GrContext*, GrRenderTargetContext*, SkCanvas*); \
62     DEF_SIMPLE_GPU_GM_BG_CAN_FAIL(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS,, W, H, \
63                                   BGCOLOR) { \
64         SK_MACRO_CONCAT(NAME,_GM_inner)(GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS); \
65         return skiagm::DrawResult::kOk; \
66     } \
67     void SK_MACRO_CONCAT(NAME,_GM_inner)( \
68             GrContext* GR_CONTEXT, GrRenderTargetContext* RENDER_TARGET_CONTEXT, SkCanvas* CANVAS)
69 
70 #define DEF_SIMPLE_GPU_GM_CAN_FAIL(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS, ERR_MSG, W, H) \
71     DEF_SIMPLE_GPU_GM_BG_CAN_FAIL(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS, \
72                                   ERR_MSG, W, H, SK_ColorWHITE)
73 #define DEF_SIMPLE_GPU_GM_BG_CAN_FAIL(NAME, GR_CONTEXT, RENDER_TARGET_CONTEXT, CANVAS, ERR_MSG, W, \
74                                       H, BGCOLOR) \
75     static skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)( \
76             GrContext*, GrRenderTargetContext*, SkCanvas*, SkString*); \
77     DEF_GM(return new skiagm::SimpleGpuGM(BGCOLOR, SkString(#NAME), {W,H}, \
78                                           SK_MACRO_CONCAT(NAME,_GM));) \
79     skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)( \
80             GrContext* GR_CONTEXT, GrRenderTargetContext* RENDER_TARGET_CONTEXT, SkCanvas* CANVAS, \
81             SkString* ERR_MSG)
82 
83 namespace skiagm {
84 
85     enum class DrawResult {
86         kOk,  // Test drew successfully.
87         kFail,  // Test failed to draw.
88         kSkip  // Test is not applicable in this context and should be skipped.
89     };
90 
91     class GM {
92     public:
93         using DrawResult = skiagm::DrawResult;
94 
95         GM(SkColor backgroundColor = SK_ColorWHITE);
96         virtual ~GM();
97 
98         enum Mode {
99             kGM_Mode,
100             kSample_Mode,
101             kBench_Mode,
102         };
103 
setMode(Mode mode)104         void setMode(Mode mode) { fMode = mode; }
getMode()105         Mode getMode() const { return fMode; }
106 
107         static constexpr char kErrorMsg_DrawSkippedGpuOnly[] = "This test is for GPU configs only.";
108 
draw(SkCanvas * canvas)109         DrawResult draw(SkCanvas* canvas) {
110             SkString errorMsg;
111             return this->draw(canvas, &errorMsg);
112         }
113         DrawResult draw(SkCanvas*, SkString* errorMsg);
114 
115         void drawBackground(SkCanvas*);
drawContent(SkCanvas * canvas)116         DrawResult drawContent(SkCanvas* canvas) {
117             SkString errorMsg;
118             return this->drawContent(canvas, &errorMsg);
119         }
120         DrawResult drawContent(SkCanvas*, SkString* errorMsg);
121 
getISize()122         SkISize getISize() { return this->onISize(); }
123         const char* getName();
124 
125         virtual bool runAsBench() const;
126 
width()127         SkScalar width() {
128             return SkIntToScalar(this->getISize().width());
129         }
height()130         SkScalar height() {
131             return SkIntToScalar(this->getISize().height());
132         }
133 
getBGColor()134         SkColor getBGColor() const { return fBGColor; }
135         void setBGColor(SkColor);
136 
137         // helper: fill a rect in the specified color based on the GM's getISize bounds.
138         void drawSizeBounds(SkCanvas*, SkColor);
139 
isCanvasDeferred()140         bool isCanvasDeferred() const { return fCanvasIsDeferred; }
setCanvasIsDeferred(bool isDeferred)141         void setCanvasIsDeferred(bool isDeferred) {
142             fCanvasIsDeferred = isDeferred;
143         }
144 
145         bool animate(const SkAnimTimer&);
handleKey(SkUnichar uni)146         bool handleKey(SkUnichar uni) {
147             return this->onHandleKey(uni);
148         }
149 
getControls(SkMetaData * controls)150         bool getControls(SkMetaData* controls) { return this->onGetControls(controls); }
setControls(const SkMetaData & controls)151         void setControls(const SkMetaData& controls) { this->onSetControls(controls); }
152 
153         virtual void modifyGrContextOptions(GrContextOptions* options);
154 
155     protected:
156         virtual void onOnceBeforeDraw();
157         virtual DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg);
158         virtual void onDraw(SkCanvas*);
159 
160         virtual SkISize onISize() = 0;
161         virtual SkString onShortName() = 0;
162 
163         virtual bool onAnimate(const SkAnimTimer&);
164         virtual bool onHandleKey(SkUnichar uni);
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     typedef GM*(*GMFactory)(void*) ;
177     typedef sk_tools::Registry<GMFactory> GMRegistry;
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 
231 void MarkGMGood(SkCanvas*, SkScalar x, SkScalar y);
232 void MarkGMBad (SkCanvas*, SkScalar x, SkScalar y);
233 
234 #endif
235