Home | History | Annotate | Download | only in gm
      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 
    104         void setMode(Mode mode) { fMode = mode; }
    105         Mode getMode() const { return fMode; }
    106 
    107         static constexpr char kErrorMsg_DrawSkippedGpuOnly[] = "This test is for GPU configs only.";
    108 
    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*);
    116         DrawResult drawContent(SkCanvas* canvas) {
    117             SkString errorMsg;
    118             return this->drawContent(canvas, &errorMsg);
    119         }
    120         DrawResult drawContent(SkCanvas*, SkString* errorMsg);
    121 
    122         SkISize getISize() { return this->onISize(); }
    123         const char* getName();
    124 
    125         virtual bool runAsBench() const;
    126 
    127         SkScalar width() {
    128             return SkIntToScalar(this->getISize().width());
    129         }
    130         SkScalar height() {
    131             return SkIntToScalar(this->getISize().height());
    132         }
    133 
    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 
    140         bool isCanvasDeferred() const { return fCanvasIsDeferred; }
    141         void setCanvasIsDeferred(bool isDeferred) {
    142             fCanvasIsDeferred = isDeferred;
    143         }
    144 
    145         bool animate(const SkAnimTimer&);
    146         bool handleKey(SkUnichar uni) {
    147             return this->onHandleKey(uni);
    148         }
    149 
    150         bool getControls(SkMetaData* controls) { return this->onGetControls(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:
    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*);
    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*);
    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