blob: 6cbf336df5420ab0b599b70dee02a6b4608b71e9 [file] [log] [blame]
James Godfrey-Kittlef4a24bc2023-02-09 17:15:10 -05001/*
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"
Kevin Lubick8b741882023-10-06 11:41:38 -040013#include "tools/DecodeUtils.h"
Kevin Lubick9b028372023-10-05 15:04:54 -040014#include "tools/GpuToolUtils.h"
James Godfrey-Kittlef4a24bc2023-02-09 17:15:10 -050015#include "tools/Resources.h"
16#include "tools/ToolUtils.h"
17
Kevin Lubick0f7b44e2023-02-28 09:13:11 -050018#if defined(SK_GRAPHITE)
James Godfrey-Kittlef4a24bc2023-02-09 17:15:10 -050019#include "include/gpu/graphite/Context.h"
20#include "include/gpu/graphite/Recorder.h"
21#include "include/gpu/graphite/Recording.h"
22#include "include/gpu/graphite/TextureInfo.h"
23#include "src/gpu/graphite/RecorderPriv.h"
24#include "src/gpu/graphite/Surface_Graphite.h"
25#endif
26
27namespace skiagm {
28
29class GraphiteReplayGM : public GM {
30public:
John Stilesf4912092023-10-24 15:51:25 -040031 GraphiteReplayGM() = default;
32
33protected:
34 void onOnceBeforeDraw() override {
James Godfrey-Kittlef4a24bc2023-02-09 17:15:10 -050035 this->setBGColor(SK_ColorBLACK);
Kevin Lubick8b741882023-10-06 11:41:38 -040036 fImage = ToolUtils::GetResourceAsImage("images/mandrill_128.png");
James Godfrey-Kittlef4a24bc2023-02-09 17:15:10 -050037 }
38
Leandro Lovisolo24fa2112023-08-15 19:05:17 +000039 SkString getName() const override { return SkString("graphite-replay"); }
James Godfrey-Kittlef4a24bc2023-02-09 17:15:10 -050040
Leandro Lovisolo8f023882023-08-15 21:13:52 +000041 SkISize getISize() override { return SkISize::Make(kTileWidth * 3, kTileHeight * 2); }
James Godfrey-Kittlef4a24bc2023-02-09 17:15:10 -050042
43 bool onAnimate(double nanos) override {
44 fStartX = kTileWidth * (1.0f + sinf(nanos * 1e-9)) * 0.5f;
45 return true;
46 }
47
48 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
Kevin Lubick0f7b44e2023-02-28 09:13:11 -050049#if defined(SK_GRAPHITE)
James Godfrey-Kittlef4a24bc2023-02-09 17:15:10 -050050 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
59private:
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
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
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
Kevin Lubick0f7b44e2023-02-28 09:13:11 -0500103#if defined(SK_GRAPHITE)
James Godfrey-Kittlef4a24bc2023-02-09 17:15:10 -0500104 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
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
157DEF_GM(return new GraphiteReplayGM;)
158
159} // namespace skiagm