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 #include "gm.h"
      9 
     10 #include "GrContext.h"
     11 #include "sk_tool_utils.h"
     12 #include "SkShader.h"
     13 #include "SkTraceEvent.h"
     14 using namespace skiagm;
     15 
     16 constexpr char GM::kErrorMsg_DrawSkippedGpuOnly[];
     17 
     18 static void draw_failure_message(SkCanvas* canvas, const char format[], ...)  {
     19     SkString failureMsg;
     20 
     21     va_list argp;
     22     va_start(argp, format);
     23     failureMsg.appendVAList(format, argp);
     24     va_end(argp);
     25 
     26     constexpr SkScalar kOffset = 5.0f;
     27     canvas->drawColor(SkColorSetRGB(200,0,0));
     28     SkFont font;
     29     SkRect bounds;
     30     font.measureText(failureMsg.c_str(), failureMsg.size(), kUTF8_SkTextEncoding, &bounds);
     31     SkPaint textPaint;
     32     textPaint.setColor(SK_ColorWHITE);
     33     canvas->drawString(failureMsg, kOffset, bounds.height() + kOffset, font, textPaint);
     34 }
     35 
     36 static void draw_gpu_only_message(SkCanvas* canvas) {
     37     SkBitmap bmp;
     38     bmp.allocN32Pixels(128, 64);
     39     SkCanvas bmpCanvas(bmp);
     40     bmpCanvas.drawColor(SK_ColorWHITE);
     41     SkFont font(sk_tool_utils::create_portable_typeface(), 20);
     42     SkPaint paint;
     43     paint.setColor(SK_ColorRED);
     44     bmpCanvas.drawString("GPU Only", 20, 40, font, paint);
     45     SkMatrix localM;
     46     localM.setRotate(35.f);
     47     localM.postTranslate(10.f, 0.f);
     48     paint.setShader(SkShader::MakeBitmapShader(
     49             bmp, SkShader::kMirror_TileMode, SkShader::kMirror_TileMode, &localM));
     50     paint.setFilterQuality(kMedium_SkFilterQuality);
     51     canvas->drawPaint(paint);
     52 }
     53 
     54 GM::GM(SkColor bgColor) {
     55     fMode = kGM_Mode;
     56     fBGColor = bgColor;
     57     fCanvasIsDeferred = false;
     58     fHaveCalledOnceBeforeDraw = false;
     59 }
     60 
     61 GM::~GM() {}
     62 
     63 DrawResult GM::draw(SkCanvas* canvas, SkString* errorMsg) {
     64     TRACE_EVENT1("GM", TRACE_FUNC, "name", TRACE_STR_COPY(this->getName()));
     65     this->drawBackground(canvas);
     66     return this->drawContent(canvas, errorMsg);
     67 }
     68 
     69 DrawResult GM::drawContent(SkCanvas* canvas, SkString* errorMsg) {
     70     TRACE_EVENT0("GM", TRACE_FUNC);
     71     if (!fHaveCalledOnceBeforeDraw) {
     72         fHaveCalledOnceBeforeDraw = true;
     73         this->onOnceBeforeDraw();
     74     }
     75     SkAutoCanvasRestore acr(canvas, true);
     76     DrawResult drawResult = this->onDraw(canvas, errorMsg);
     77     if (DrawResult::kOk != drawResult) {
     78         if (DrawResult::kFail == drawResult) {
     79             draw_failure_message(canvas, "DRAW FAILED: %s", errorMsg->c_str());
     80         } else if (SkString(kErrorMsg_DrawSkippedGpuOnly) == *errorMsg) {
     81             draw_gpu_only_message(canvas);
     82         } else {
     83             draw_failure_message(canvas, "DRAW SKIPPED: %s", errorMsg->c_str());
     84         }
     85     }
     86     return drawResult;
     87 }
     88 
     89 void GM::drawBackground(SkCanvas* canvas) {
     90     TRACE_EVENT0("GM", TRACE_FUNC);
     91     if (!fHaveCalledOnceBeforeDraw) {
     92         fHaveCalledOnceBeforeDraw = true;
     93         this->onOnceBeforeDraw();
     94     }
     95     SkAutoCanvasRestore acr(canvas, true);
     96     canvas->drawColor(fBGColor, SkBlendMode::kSrc);
     97 }
     98 
     99 DrawResult GM::onDraw(SkCanvas* canvas, SkString* errorMsg) {
    100     this->onDraw(canvas);
    101     return DrawResult::kOk;
    102 }
    103 void GM::onDraw(SkCanvas*) { SK_ABORT("Not implemented."); }
    104 
    105 
    106 SkISize SimpleGM::onISize() { return fSize; }
    107 SkString SimpleGM::onShortName() { return fName; }
    108 DrawResult SimpleGM::onDraw(SkCanvas* canvas, SkString* errorMsg) {
    109     return fDrawProc(canvas, errorMsg);
    110 }
    111 
    112 SkISize SimpleGpuGM::onISize() { return fSize; }
    113 SkString SimpleGpuGM::onShortName() { return fName; }
    114 DrawResult SimpleGpuGM::onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* canvas,
    115                                SkString* errorMsg) {
    116     return fDrawProc(ctx, rtc, canvas, errorMsg);
    117 }
    118 
    119 const char* GM::getName() {
    120     if (fShortName.size() == 0) {
    121         fShortName = this->onShortName();
    122     }
    123     return fShortName.c_str();
    124 }
    125 
    126 void GM::setBGColor(SkColor color) {
    127     fBGColor = color;
    128 }
    129 
    130 bool GM::animate(const SkAnimTimer& timer) {
    131     return this->onAnimate(timer);
    132 }
    133 
    134 bool GM::runAsBench() const { return false; }
    135 void GM::modifyGrContextOptions(GrContextOptions* options) {}
    136 
    137 void GM::onOnceBeforeDraw() {}
    138 
    139 bool GM::onAnimate(const SkAnimTimer&) { return false; }
    140 bool GM::onHandleKey(SkUnichar uni) { return false; }
    141 bool GM::onGetControls(SkMetaData*) { return false; }
    142 void GM::onSetControls(const SkMetaData&) {}
    143 
    144 /////////////////////////////////////////////////////////////////////////////////////////////
    145 
    146 void GM::drawSizeBounds(SkCanvas* canvas, SkColor color) {
    147     SkISize size = this->getISize();
    148     SkRect r = SkRect::MakeWH(SkIntToScalar(size.width()),
    149                               SkIntToScalar(size.height()));
    150     SkPaint paint;
    151     paint.setColor(color);
    152     canvas->drawRect(r, paint);
    153 }
    154 
    155 // need to explicitly declare this, or we get some weird infinite loop llist
    156 template GMRegistry* GMRegistry::gHead;
    157 
    158 DrawResult GpuGM::onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* canvas,
    159                           SkString* errorMsg) {
    160     this->onDraw(ctx, rtc, canvas);
    161     return DrawResult::kOk;
    162 }
    163 void GpuGM::onDraw(GrContext*, GrRenderTargetContext*, SkCanvas*) {
    164     SK_ABORT("Not implemented.");
    165 }
    166 
    167 DrawResult GpuGM::onDraw(SkCanvas* canvas, SkString* errorMsg) {
    168     GrContext* ctx = canvas->getGrContext();
    169     GrRenderTargetContext* rtc = canvas->internal_private_accessTopLayerRenderTargetContext();
    170     if (!ctx || !rtc) {
    171         *errorMsg = kErrorMsg_DrawSkippedGpuOnly;
    172         return DrawResult::kSkip;
    173     }
    174     if (ctx->abandoned()) {
    175         *errorMsg = "GrContext abandoned.";
    176         return DrawResult::kFail;
    177     }
    178     return this->onDraw(ctx, rtc, canvas, errorMsg);
    179 }
    180 
    181 template <typename Fn>
    182 static void mark(SkCanvas* canvas, SkScalar x, SkScalar y, Fn&& fn) {
    183     SkPaint alpha;
    184     alpha.setAlpha(0x50);
    185     canvas->saveLayer(nullptr, &alpha);
    186         canvas->translate(x,y);
    187         canvas->scale(2,2);
    188         fn();
    189     canvas->restore();
    190 }
    191 
    192 void MarkGMGood(SkCanvas* canvas, SkScalar x, SkScalar y) {
    193     mark(canvas, x,y, [&]{
    194         SkPaint paint;
    195 
    196         // A green circle.
    197         paint.setColor(SkColorSetRGB(27, 158, 119));
    198         canvas->drawCircle(0,0, 12, paint);
    199 
    200         // Cut out a check mark.
    201         paint.setBlendMode(SkBlendMode::kSrc);
    202         paint.setColor(0x00000000);
    203         paint.setStrokeWidth(2);
    204         paint.setStyle(SkPaint::kStroke_Style);
    205         canvas->drawLine(-6, 0,
    206                          -1, 5, paint);
    207         canvas->drawLine(-1, +5,
    208                          +7, -5, paint);
    209     });
    210 }
    211 
    212 void MarkGMBad(SkCanvas* canvas, SkScalar x, SkScalar y) {
    213     mark(canvas, x,y, [&] {
    214         SkPaint paint;
    215 
    216         // A red circle.
    217         paint.setColor(SkColorSetRGB(231, 41, 138));
    218         canvas->drawCircle(0,0, 12, paint);
    219 
    220         // Cut out an 'X'.
    221         paint.setBlendMode(SkBlendMode::kSrc);
    222         paint.setColor(0x00000000);
    223         paint.setStrokeWidth(2);
    224         paint.setStyle(SkPaint::kStroke_Style);
    225         canvas->drawLine(-5,-5,
    226                          +5,+5, paint);
    227         canvas->drawLine(+5,-5,
    228                          -5,+5, paint);
    229     });
    230 }
    231