blob: 371c8fbd3efd4f60727a6eb09d2ad98c0a994554 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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 */
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00007
reed@android.com00dae862009-06-10 15:38:48 +00008#ifndef skiagm_DEFINED
9#define skiagm_DEFINED
10
Tyler Denniston45f94f82020-02-04 16:09:08 -050011#include "gm/verifiers/gmverifier.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040012#include "include/core/SkColor.h"
13#include "include/core/SkScalar.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "include/core/SkSize.h"
15#include "include/core/SkString.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040016#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "include/private/SkMacros.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "tools/Registry.h"
reed@android.com00dae862009-06-10 15:38:48 +000019
Hal Canaryedda5652019-08-05 10:28:09 -040020#include <memory>
21
Robert Phillipsb87b39b2020-07-01 14:45:24 -040022class GrDirectContext;
Robert Phillips95c250c2020-06-29 15:36:12 -040023class GrRecordingContext;
Ben Wagner7fde8e12019-05-01 17:28:53 -040024class SkCanvas;
Mike Reed88f56712019-02-04 16:50:10 -050025class SkMetaData;
bsalomon4ee6bd82015-05-27 13:23:23 -070026struct GrContextOptions;
mtklein@google.com62b50b72013-09-16 20:42:15 +000027
Brian Salomon56c78f42021-02-03 16:56:55 -050028#define DEF_GM(CODE) \
29 static skiagm::GMRegistry SK_MACRO_APPEND_COUNTER(REG_)( \
30 []() { return std::unique_ptr<skiagm::GM>([]() { CODE; }()); });
reed@google.com4117a242012-10-30 20:26:58 +000031
Chris Dalton3a778372019-02-07 15:23:36 -070032// A Simple GM is a rendering test that does not store state between rendering calls or make use of
33// the onOnceBeforeDraw() virtual; it consists of:
halcanary2a243382015-09-09 08:16:41 -070034// * A name.
35// * Prefered width and height.
36// * Optionally, a background color (default is white).
Chris Dalton3a778372019-02-07 15:23:36 -070037// * A standalone function pointer that implements its onDraw method.
halcanary2a243382015-09-09 08:16:41 -070038#define DEF_SIMPLE_GM(NAME, CANVAS, W, H) \
39 DEF_SIMPLE_GM_BG_NAME(NAME, CANVAS, W, H, SK_ColorWHITE, SkString(#NAME))
Chris Dalton3a778372019-02-07 15:23:36 -070040#define DEF_SIMPLE_GM_BG(NAME, CANVAS, W, H, BGCOLOR) \
halcanary2a243382015-09-09 08:16:41 -070041 DEF_SIMPLE_GM_BG_NAME(NAME, CANVAS, W, H, BGCOLOR, SkString(#NAME))
Chris Dalton3a778372019-02-07 15:23:36 -070042#define DEF_SIMPLE_GM_BG_NAME(NAME, CANVAS, W, H, BGCOLOR, NAME_STR) \
Chris Dalton50e24d72019-02-07 16:20:09 -070043 static void SK_MACRO_CONCAT(NAME,_GM_inner)(SkCanvas*); \
44 DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS,, W, H, BGCOLOR, NAME_STR) { \
45 SK_MACRO_CONCAT(NAME,_GM_inner)(CANVAS); \
46 return skiagm::DrawResult::kOk; \
47 } \
48 void SK_MACRO_CONCAT(NAME,_GM_inner)(SkCanvas* CANVAS)
49
50#define DEF_SIMPLE_GM_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H) \
51 DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, SK_ColorWHITE, SkString(#NAME))
52#define DEF_SIMPLE_GM_BG_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, BGCOLOR) \
53 DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, BGCOLOR, SkString(#NAME))
54#define DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, BGCOLOR, NAME_STR) \
55 static skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)(SkCanvas*, SkString*); \
56 DEF_GM(return new skiagm::SimpleGM(BGCOLOR, NAME_STR, {W,H}, SK_MACRO_CONCAT(NAME,_GM));) \
57 skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)(SkCanvas* CANVAS, SkString* ERR_MSG)
58
halcanary30b83d42014-10-26 05:23:53 -070059
Chris Dalton3a778372019-02-07 15:23:36 -070060// A Simple GpuGM makes direct GPU calls. Its onDraw hook that includes GPU objects as params, and
61// is only invoked on GPU configs. Non-GPU configs automatically draw a GPU-only message and abort.
Robert Phillips7a0d3c32021-07-21 15:39:51 -040062#define DEF_SIMPLE_GPU_GM(NAME, GR_CONTEXT, CANVAS, W, H) \
63 DEF_SIMPLE_GPU_GM_BG(NAME, GR_CONTEXT, CANVAS, W, H, SK_ColorWHITE)
Chris Dalton3a778372019-02-07 15:23:36 -070064
Robert Phillips7a0d3c32021-07-21 15:39:51 -040065#define DEF_SIMPLE_GPU_GM_BG(NAME, GR_CONTEXT, CANVAS, W, H, BGCOLOR) \
66 static void SK_MACRO_CONCAT(NAME,_GM_inner)(GrRecordingContext*, SkCanvas*); \
67 DEF_SIMPLE_GPU_GM_BG_CAN_FAIL(NAME, GR_CONTEXT, CANVAS, /* ERR_MSG */, W, H, BGCOLOR) { \
68 SK_MACRO_CONCAT(NAME,_GM_inner)(GR_CONTEXT, CANVAS); \
69 return skiagm::DrawResult::kOk; \
70 } \
71 void SK_MACRO_CONCAT(NAME,_GM_inner)(GrRecordingContext* GR_CONTEXT, SkCanvas* CANVAS)
72
73#define DEF_SIMPLE_GPU_GM_CAN_FAIL(NAME, GR_CONTEXT, CANVAS, ERR_MSG, W, H) \
74 DEF_SIMPLE_GPU_GM_BG_CAN_FAIL(NAME, GR_CONTEXT, CANVAS, ERR_MSG, W, H, SK_ColorWHITE)
75
76#define DEF_SIMPLE_GPU_GM_BG_CAN_FAIL(NAME, GR_CONTEXT, CANVAS, ERR_MSG, W, H, BGCOLOR) \
77 static skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)( \
78 GrRecordingContext*, SkCanvas*, SkString*); \
79 DEF_GM(return new skiagm::SimpleGpuGM(BGCOLOR, SkString(#NAME), {W,H}, \
80 SK_MACRO_CONCAT(NAME,_GM));) \
81 skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)( \
82 GrRecordingContext* GR_CONTEXT, SkCanvas* CANVAS, SkString* ERR_MSG)
Chris Dalton50e24d72019-02-07 16:20:09 -070083
reed@android.com00dae862009-06-10 15:38:48 +000084namespace skiagm {
rmistry@google.comd6176b02012-08-23 18:14:13 +000085
Chris Dalton50e24d72019-02-07 16:20:09 -070086 enum class DrawResult {
Robert Phillips83b749a2020-06-25 11:41:19 -040087 kOk, // Test drew successfully.
88 kFail, // Test failed to draw.
Chris Dalton50e24d72019-02-07 16:20:09 -070089 kSkip // Test is not applicable in this context and should be skipped.
90 };
91
reed@android.com00dae862009-06-10 15:38:48 +000092 class GM {
93 public:
Chris Dalton50e24d72019-02-07 16:20:09 -070094 using DrawResult = skiagm::DrawResult;
95
Chris Dalton3a778372019-02-07 15:23:36 -070096 GM(SkColor backgroundColor = SK_ColorWHITE);
reed@android.com00dae862009-06-10 15:38:48 +000097 virtual ~GM();
rmistry@google.comd6176b02012-08-23 18:14:13 +000098
commit-bot@chromium.orgb21fac12014-02-07 21:13:11 +000099 enum Mode {
100 kGM_Mode,
101 kSample_Mode,
102 kBench_Mode,
103 };
104
105 void setMode(Mode mode) { fMode = mode; }
106 Mode getMode() const { return fMode; }
107
Chris Dalton50e24d72019-02-07 16:20:09 -0700108 static constexpr char kErrorMsg_DrawSkippedGpuOnly[] = "This test is for GPU configs only.";
109
Robert Phillipsb87b39b2020-07-01 14:45:24 -0400110 DrawResult gpuSetup(GrDirectContext* context, SkCanvas* canvas) {
Robert Phillipsd26d25e2020-06-25 13:26:22 -0400111 SkString errorMsg;
112 return this->gpuSetup(context, canvas, &errorMsg);
113 }
Robert Phillipsb87b39b2020-07-01 14:45:24 -0400114 DrawResult gpuSetup(GrDirectContext*, SkCanvas*, SkString* errorMsg);
Robert Phillipsb795bea2020-06-25 12:38:53 -0400115 void gpuTeardown();
Robert Phillips889d6132020-06-16 11:11:33 -0400116
Robert Phillips83b749a2020-06-25 11:41:19 -0400117 void onceBeforeDraw() {
118 if (!fHaveCalledOnceBeforeDraw) {
119 fHaveCalledOnceBeforeDraw = true;
120 this->onOnceBeforeDraw();
121 }
122 }
123
Chris Dalton50e24d72019-02-07 16:20:09 -0700124 DrawResult draw(SkCanvas* canvas) {
125 SkString errorMsg;
126 return this->draw(canvas, &errorMsg);
127 }
128 DrawResult draw(SkCanvas*, SkString* errorMsg);
129
bsalomon@google.com48dd1a22011-10-31 14:18:20 +0000130 void drawBackground(SkCanvas*);
Chris Dalton50e24d72019-02-07 16:20:09 -0700131 DrawResult drawContent(SkCanvas* canvas) {
132 SkString errorMsg;
133 return this->drawContent(canvas, &errorMsg);
134 }
135 DrawResult drawContent(SkCanvas*, SkString* errorMsg);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000136
mtkleinf4ba3212015-01-28 15:32:24 -0800137 SkISize getISize() { return this->onISize(); }
commit-bot@chromium.org38aeb0f2014-02-26 23:01:57 +0000138 const char* getName();
reed@android.com00dae862009-06-10 15:38:48 +0000139
Mike Klein9707e902019-02-07 16:18:22 -0500140 virtual bool runAsBench() const;
mtkleincf5d9c92015-01-23 10:31:45 -0800141
reed@google.com487b5602013-02-01 15:01:24 +0000142 SkScalar width() {
143 return SkIntToScalar(this->getISize().width());
144 }
145 SkScalar height() {
scroggo@google.comab026272013-04-12 22:14:03 +0000146 return SkIntToScalar(this->getISize().height());
reed@google.com487b5602013-02-01 15:01:24 +0000147 }
148
reed@google.comb4b49cc2011-12-06 16:15:42 +0000149 SkColor getBGColor() const { return fBGColor; }
bsalomon@google.com48dd1a22011-10-31 14:18:20 +0000150 void setBGColor(SkColor);
reed@google.com30db5992011-08-29 17:41:02 +0000151
Chris Dalton3a778372019-02-07 15:23:36 -0700152 // helper: fill a rect in the specified color based on the GM's getISize bounds.
reed@google.com2d6ef522012-01-03 17:20:38 +0000153 void drawSizeBounds(SkCanvas*, SkColor);
154
Hal Canary41248072019-07-11 16:32:53 -0400155 bool animate(double /*nanos*/);
Hal Canaryc74a5502019-07-08 14:55:15 -0400156 virtual bool onChar(SkUnichar);
reedd9adfe62015-02-01 19:01:04 -0800157
Mike Reed81f60ec2018-05-15 10:09:52 -0400158 bool getControls(SkMetaData* controls) { return this->onGetControls(controls); }
159 void setControls(const SkMetaData& controls) { this->onSetControls(controls); }
160
Chris Dalton5b5403e2019-06-05 11:54:39 -0600161 virtual void modifyGrContextOptions(GrContextOptions*);
bsalomon4ee6bd82015-05-27 13:23:23 -0700162
Tyler Denniston45f94f82020-02-04 16:09:08 -0500163 virtual std::unique_ptr<verifiers::VerifierList> getVerifiers() const;
164
halcanary2a243382015-09-09 08:16:41 -0700165 protected:
Robert Phillips889d6132020-06-16 11:11:33 -0400166 // onGpuSetup is called once before any other processing with a direct context.
Robert Phillipsb87b39b2020-07-01 14:45:24 -0400167 virtual DrawResult onGpuSetup(GrDirectContext*, SkString*) { return DrawResult::kOk; }
Robert Phillipsb795bea2020-06-25 12:38:53 -0400168 virtual void onGpuTeardown() {}
Mike Klein9707e902019-02-07 16:18:22 -0500169 virtual void onOnceBeforeDraw();
Robert Phillips889d6132020-06-16 11:11:33 -0400170 virtual DrawResult onDraw(SkCanvas*, SkString* errorMsg);
Mike Klein9707e902019-02-07 16:18:22 -0500171 virtual void onDraw(SkCanvas*);
172
robertphillips@google.com8570b5c2012-03-20 17:40:58 +0000173 virtual SkISize onISize() = 0;
reed@android.com8015dd82009-06-21 00:49:18 +0000174 virtual SkString onShortName() = 0;
mtklein1c402922015-01-23 11:07:07 -0800175
Hal Canary41248072019-07-11 16:32:53 -0400176 virtual bool onAnimate(double /*nanos*/);
Mike Klein9707e902019-02-07 16:18:22 -0500177 virtual bool onGetControls(SkMetaData*);
178 virtual void onSetControls(const SkMetaData&);
vandebo@chromium.org79d3cb42012-03-21 17:34:30 +0000179
reed@android.com8015dd82009-06-21 00:49:18 +0000180 private:
Robert Phillipse9229532020-06-26 10:10:49 -0400181 Mode fMode;
182 SkString fShortName;
183 SkColor fBGColor;
184 bool fHaveCalledOnceBeforeDraw = false;
185 bool fGpuSetup = false;
186 DrawResult fGpuSetupResult = DrawResult::kOk;
reed@android.com00dae862009-06-10 15:38:48 +0000187 };
188
Hal Canaryedda5652019-08-05 10:28:09 -0400189 using GMFactory = std::unique_ptr<skiagm::GM> (*)();
190 using GMRegistry = sk_tools::Registry<GMFactory>;
halcanaryf62c6342015-01-12 15:27:46 -0800191
Chris Dalton3a778372019-02-07 15:23:36 -0700192 // A GpuGM replaces the onDraw method with one that also accepts GPU objects alongside the
193 // SkCanvas. Its onDraw is only invoked on GPU configs; on non-GPU configs it will automatically
194 // draw a GPU-only message and abort.
195 class GpuGM : public GM {
halcanaryf62c6342015-01-12 15:27:46 -0800196 public:
Chris Dalton3a778372019-02-07 15:23:36 -0700197 GpuGM(SkColor backgroundColor = SK_ColorWHITE) : GM(backgroundColor) {}
Tyler Denniston45f94f82020-02-04 16:09:08 -0500198
199 // TODO(tdenniston): Currently GpuGMs don't have verifiers (because they do not render on
200 // CPU), but we may want to be able to verify the output images standalone, without
201 // requiring a gold image for comparison.
202 std::unique_ptr<verifiers::VerifierList> getVerifiers() const override { return nullptr; }
203
Chris Dalton382b1222019-02-07 10:05:55 +0000204 private:
Chris Dalton50e24d72019-02-07 16:20:09 -0700205 using GM::onDraw;
206 DrawResult onDraw(SkCanvas*, SkString* errorMsg) final;
Mike Klein9707e902019-02-07 16:18:22 -0500207
Robert Phillips7a0d3c32021-07-21 15:39:51 -0400208 virtual DrawResult onDraw(GrRecordingContext*, SkCanvas*, SkString* errorMsg);
209 virtual void onDraw(GrRecordingContext*, SkCanvas*);
Chris Daltonf5efa782019-02-05 17:42:14 -0700210 };
Chris Dalton3a778372019-02-07 15:23:36 -0700211
212 // SimpleGM is intended for basic GMs that can define their entire implementation inside a
213 // single "draw" function pointer.
214 class SimpleGM : public GM {
215 public:
Chris Dalton50e24d72019-02-07 16:20:09 -0700216 using DrawProc = DrawResult(*)(SkCanvas*, SkString*);
Robert Phillips7a0d3c32021-07-21 15:39:51 -0400217
Chris Dalton3a778372019-02-07 15:23:36 -0700218 SimpleGM(SkColor bgColor, const SkString& name, const SkISize& size, DrawProc drawProc)
219 : GM(bgColor), fName(name), fSize(size), fDrawProc(drawProc) {}
220
221 private:
Mike Klein9707e902019-02-07 16:18:22 -0500222 SkISize onISize() override;
223 SkString onShortName() override;
224 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override;
Chris Dalton3a778372019-02-07 15:23:36 -0700225
226 const SkString fName;
227 const SkISize fSize;
228 const DrawProc fDrawProc;
229 };
230
231 class SimpleGpuGM : public GpuGM {
232 public:
Robert Phillips7a0d3c32021-07-21 15:39:51 -0400233 using DrawProc = DrawResult (*)(GrRecordingContext*, SkCanvas*, SkString* errorMsg);
234
Chris Dalton3a778372019-02-07 15:23:36 -0700235 SimpleGpuGM(SkColor bgColor, const SkString& name, const SkISize& size, DrawProc drawProc)
236 : GpuGM(bgColor), fName(name), fSize(size), fDrawProc(drawProc) {}
237
238 private:
Mike Klein9707e902019-02-07 16:18:22 -0500239 SkISize onISize() override;
240 SkString onShortName() override;
Robert Phillips7a0d3c32021-07-21 15:39:51 -0400241 DrawResult onDraw(GrRecordingContext*, SkCanvas*, SkString* errorMsg) override;
Chris Dalton3a778372019-02-07 15:23:36 -0700242
243 const SkString fName;
244 const SkISize fSize;
245 const DrawProc fDrawProc;
246 };
John Stilesa6841be2020-08-06 14:11:56 -0400247} // namespace skiagm
reed@android.com00dae862009-06-10 15:38:48 +0000248
Mike Kleinc9eace82018-10-31 10:49:38 -0400249void MarkGMGood(SkCanvas*, SkScalar x, SkScalar y);
250void MarkGMBad (SkCanvas*, SkScalar x, SkScalar y);
251
reed@android.com00dae862009-06-10 15:38:48 +0000252#endif