1 /*
2  * Copyright 2014 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/gm.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkImageInfo.h"
12 #include "include/core/SkPaint.h"
13 #include "include/core/SkRefCnt.h"
14 #include "include/core/SkShader.h"
15 #include "include/core/SkSize.h"
16 #include "include/core/SkString.h"
17 #include "include/core/SkSurface.h"
18 #include "include/core/SkTypes.h"
19 #include "include/gpu/GrDirectContext.h"
20 #include "include/gpu/GrRecordingContext.h"
21 #include "include/utils/SkRandom.h"
22 #include "tools/ToolUtils.h"
23 
24 class GrRenderTargetContext;
25 
26 namespace skiagm {
27 
28 /*
29  * This GM exercises SkCanvas::discard() by creating an offscreen SkSurface and repeatedly
30  * discarding it, drawing to it, and then drawing it to the main canvas.
31  */
32 class DiscardGM : public GpuGM {
33 
34 public:
DiscardGM()35     DiscardGM() {}
36 
37 protected:
onShortName()38     SkString onShortName() override {
39         return SkString("discard");
40     }
41 
onISize()42     SkISize onISize() override {
43         return SkISize::Make(100, 100);
44     }
45 
onDraw(GrRecordingContext * context,GrRenderTargetContext *,SkCanvas * canvas,SkString * errorMsg)46     DrawResult onDraw(GrRecordingContext* context, GrRenderTargetContext*, SkCanvas* canvas,
47                       SkString* errorMsg) override {
48         auto direct = context->asDirectContext();
49         if (!direct) {
50             *errorMsg = "GM relies on having access to a live direct context.";
51             return DrawResult::kSkip;
52         }
53 
54         SkISize size = this->getISize();
55         size.fWidth /= 10;
56         size.fHeight /= 10;
57         SkImageInfo info = SkImageInfo::MakeN32Premul(size);
58         sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(direct, SkBudgeted::kNo, info);
59         if (nullptr == surface) {
60             *errorMsg = "Could not create render target.";
61             return DrawResult::kFail;
62         }
63 
64         canvas->clear(SK_ColorBLACK);
65 
66         SkRandom rand;
67         for (int x = 0; x < 10; ++x) {
68             for (int y = 0; y < 10; ++y) {
69               surface->getCanvas()->discard();
70               // Make something that isn't too close to the background color, black.
71               SkColor color = ToolUtils::color_to_565(rand.nextU() | 0xFF404040);
72               switch (rand.nextULessThan(3)) {
73                   case 0:
74                       surface->getCanvas()->drawColor(color);
75                       break;
76                   case 1:
77                       surface->getCanvas()->clear(color);
78                       break;
79                   case 2:
80                       SkPaint paint;
81                       paint.setShader(SkShaders::Color(color));
82                       surface->getCanvas()->drawPaint(paint);
83                       break;
84               }
85               surface->draw(canvas, 10.f*x, 10.f*y, nullptr);
86             }
87         }
88 
89         surface->getCanvas()->discard();
90         return DrawResult::kOk;
91     }
92 
93 private:
94     using INHERITED = GM;
95 };
96 
97 //////////////////////////////////////////////////////////////////////////////
98 
99 DEF_GM(return new DiscardGM;)
100 
101 }  // namespace skiagm
102