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