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