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