• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 Google LLC
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 
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkSurface.h"
12 #include "include/effects/SkGradientShader.h"
13 #include "tools/Resources.h"
14 #include "tools/ToolUtils.h"
15 
16 #if defined(SK_GRAPHITE)
17 #include "include/gpu/graphite/Context.h"
18 #include "include/gpu/graphite/Recorder.h"
19 #include "include/gpu/graphite/Recording.h"
20 #include "include/gpu/graphite/TextureInfo.h"
21 #include "src/gpu/graphite/RecorderPriv.h"
22 #include "src/gpu/graphite/Surface_Graphite.h"
23 #endif
24 
25 namespace skiagm {
26 
27 class GraphiteReplayGM : public GM {
28 public:
GraphiteReplayGM()29     GraphiteReplayGM() {
30         this->setBGColor(SK_ColorBLACK);
31         fImage = GetResourceAsImage("images/mandrill_128.png");
32     }
33 
34 protected:
onShortName()35     SkString onShortName() override { return SkString("graphite-replay"); }
36 
onISize()37     SkISize onISize() override { return SkISize::Make(kTileWidth * 3, kTileHeight * 2); }
38 
onAnimate(double nanos)39     bool onAnimate(double nanos) override {
40         fStartX = kTileWidth * (1.0f + sinf(nanos * 1e-9)) * 0.5f;
41         return true;
42     }
43 
onDraw(SkCanvas * canvas,SkString * errorMsg)44     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
45 #if defined(SK_GRAPHITE)
46         skgpu::graphite::Recorder* recorder = canvas->recorder();
47         if (recorder) {
48             this->drawGraphite(canvas, recorder);
49             return DrawResult::kOk;
50         }
51 #endif
52         return this->drawNonGraphite(canvas, errorMsg);
53     }
54 
55 private:
56     static constexpr int kImageSize = 128;
57     static constexpr int kPadding = 2;
58     static constexpr int kPaddedImageSize = kImageSize + kPadding * 2;
59     static constexpr int kTileWidth = kPaddedImageSize * 2;
60     static constexpr int kTileHeight = kPaddedImageSize * 2;
61 
62     float fStartX = 0.0f;
63 
64     sk_sp<SkImage> fImage;
65 
drawContent(SkCanvas * canvas,int y)66     void drawContent(SkCanvas* canvas, int y) {
67         SkPaint gradientPaint;
68         constexpr SkPoint points[2] = {{0.0f, 0.0f}, {kImageSize, kImageSize}};
69         constexpr SkColor colors[4] = {SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED};
70         gradientPaint.setShader(SkGradientShader::MakeLinear(
71                 points, colors, nullptr, std::size(colors), SkTileMode::kClamp));
72 
73         // Draw image.
74         canvas->drawImage(fImage, kPadding, kPadding + y);
75 
76         // Draw gradient.
77         canvas->save();
78         canvas->translate(kPaddedImageSize + kPadding, kPadding + y);
79         canvas->drawRect(SkRect::MakeXYWH(0, 0, kImageSize, kImageSize), gradientPaint);
80         canvas->restore();
81     }
82 
drawTile(SkCanvas * canvas)83     void drawTile(SkCanvas* canvas) {
84         // Clip off the right 1/4 of the tile, after clearing.
85         canvas->clear(SkColors::kRed);
86         canvas->clipIRect(SkIRect::MakeWH(3 * kTileWidth / 4, kTileHeight));
87 
88         // Draw content directly.
89         drawContent(canvas, 0);
90 
91         // Draw content to a saved layer.
92         SkPaint pAlpha;
93         pAlpha.setAlphaf(0.5f);
94         canvas->saveLayer(nullptr, &pAlpha);
95         drawContent(canvas, kPaddedImageSize);
96         canvas->restore();
97     }
98 
99 #if defined(SK_GRAPHITE)
drawGraphite(SkCanvas * canvas,skgpu::graphite::Recorder * canvasRecorder)100     void drawGraphite(SkCanvas* canvas, skgpu::graphite::Recorder* canvasRecorder) {
101         SkImageInfo tileImageInfo =
102                 canvas->imageInfo().makeDimensions(SkISize::Make(kTileWidth, kTileHeight));
103         skgpu::graphite::TextureInfo textureInfo =
104                 static_cast<skgpu::graphite::Surface*>(canvas->getSurface())
105                         ->backingTextureProxy()
106                         ->textureInfo();
107 
108         skgpu::graphite::Context* context = canvasRecorder->priv().context();
109         std::unique_ptr<skgpu::graphite::Recorder> recorder =
110                 context->makeRecorder(ToolUtils::CreateTestingRecorderOptions());
111         SkCanvas* recordingCanvas = recorder->makeDeferredCanvas(tileImageInfo, textureInfo);
112         this->drawTile(recordingCanvas);
113         std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();
114 
115         // Flush the initial clear added by MakeGraphite.
116         std::unique_ptr<skgpu::graphite::Recording> canvasRecording = canvasRecorder->snap();
117         context->insertRecording({canvasRecording.get()});
118 
119         for (int y = 0; y < 2; ++y) {
120             for (int x = 0; x < 2; ++x) {
121                 context->insertRecording(
122                         {recording.get(),
123                          canvas->getSurface(),
124                          {x * kTileWidth + SkScalarRoundToInt(fStartX), y * kTileHeight}});
125             }
126         }
127     }
128 #endif
129 
drawNonGraphite(SkCanvas * canvas,SkString * errorMsg)130     DrawResult drawNonGraphite(SkCanvas* canvas, SkString* errorMsg) {
131         SkImageInfo tileImageInfo =
132                 canvas->imageInfo().makeDimensions(SkISize::Make(kTileWidth, kTileHeight));
133 
134         sk_sp<SkSurface> imageSurface = canvas->makeSurface(tileImageInfo);
135         if (!imageSurface) {
136             *errorMsg = "Cannot create new SkSurface.";
137             return DrawResult::kSkip;
138         }
139 
140         SkCanvas* imageCanvas = imageSurface->getCanvas();
141         this->drawTile(imageCanvas);
142         sk_sp<SkImage> image = imageSurface->makeImageSnapshot();
143 
144         for (int y = 0; y < 2; ++y) {
145             for (int x = 0; x < 2; ++x) {
146                 canvas->drawImage(image, x * kTileWidth + fStartX, y * kTileHeight);
147             }
148         }
149         return DrawResult::kOk;
150     }
151 };
152 
153 DEF_GM(return new GraphiteReplayGM;)
154 
155 }  // namespace skiagm
156