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