Flutter Engine
The Flutter Engine
fp_sample_chaining.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2019 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"
10#include "include/core/SkFont.h"
16#include "src/gpu/ganesh/SkGr.h"
21#include "tools/ToolUtils.h"
23
24namespace {
25
26// Samples child with a uniform matrix (functionally identical to GrMatrixEffect)
27// Scales along Y
28class UniformMatrixEffect : public GrFragmentProcessor {
29public:
30 inline static constexpr GrProcessor::ClassID CLASS_ID = (GrProcessor::ClassID) 4;
31
32 UniformMatrixEffect(std::unique_ptr<GrFragmentProcessor> child)
33 : GrFragmentProcessor(CLASS_ID, kNone_OptimizationFlags) {
34 this->registerChild(std::move(child),
35 SkSL::SampleUsage::UniformMatrix(/*hasPerspective=*/false));
36 }
37
38 const char* name() const override { return "UniformMatrixEffect"; }
39 void onAddToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const override {}
40 bool onIsEqual(const GrFragmentProcessor& that) const override { return this == &that; }
41 std::unique_ptr<GrFragmentProcessor> clone() const override { return nullptr; }
42
43 std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override {
44 class Impl : public ProgramImpl {
45 public:
46 void emitCode(EmitArgs& args) override {
47 fMatrixVar =
48 args.fUniformHandler->addUniform(&args.fFp,
52 SkString sample = this->invokeChildWithMatrix(0, args);
53 args.fFragBuilder->codeAppendf("return %s;\n", sample.c_str());
54 }
55
56 private:
57 void onSetData(const GrGLSLProgramDataManager& pdman,
58 const GrFragmentProcessor& proc) override {
59 pdman.setSkMatrix(fMatrixVar, SkMatrix::Scale(1, 0.5f));
60 }
61 UniformHandle fMatrixVar;
62 };
63 return std::make_unique<Impl>();
64 }
65};
66
67// Samples child with explicit coords
68// Translates along Y
69class ExplicitCoordEffect : public GrFragmentProcessor {
70public:
71 inline static constexpr GrProcessor::ClassID CLASS_ID = (GrProcessor::ClassID) 6;
72
73 ExplicitCoordEffect(std::unique_ptr<GrFragmentProcessor> child)
74 : GrFragmentProcessor(CLASS_ID, kNone_OptimizationFlags) {
75 this->registerChild(std::move(child), SkSL::SampleUsage::Explicit());
77 }
78
79 const char* name() const override { return "ExplicitCoordEffect"; }
80 void onAddToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const override {}
81 bool onIsEqual(const GrFragmentProcessor& that) const override { return this == &that; }
82 std::unique_ptr<GrFragmentProcessor> clone() const override { return nullptr; }
83
84 std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override {
85 class Impl : public ProgramImpl {
86 public:
87 void emitCode(EmitArgs& args) override {
88 args.fFragBuilder->codeAppendf("float2 coord = %s + float2(0, 8);",
89 args.fSampleCoord);
90 SkString sample = this->invokeChild(0, args, "coord");
91 args.fFragBuilder->codeAppendf("return %s;\n", sample.c_str());
92 }
93 };
94
95 return std::make_unique<Impl>();
96 }
97};
98
99// Generates test pattern
100class TestPatternEffect : public GrFragmentProcessor {
101public:
102 inline static constexpr GrProcessor::ClassID CLASS_ID = (GrProcessor::ClassID) 7;
103
104 TestPatternEffect() : GrFragmentProcessor(CLASS_ID, kNone_OptimizationFlags) {
106 }
107
108 const char* name() const override { return "TestPatternEffect"; }
109 void onAddToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const override {}
110 bool onIsEqual(const GrFragmentProcessor& that) const override { return this == &that; }
111 std::unique_ptr<GrFragmentProcessor> clone() const override { return nullptr; }
112
113 std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override {
114 class Impl : public ProgramImpl {
115 public:
116 void emitCode(EmitArgs& args) override {
117 auto fb = args.fFragBuilder;
118 fb->codeAppendf("float2 coord = %s / 64.0;", args.fSampleCoord);
119 fb->codeAppendf("coord = floor(coord * 4) / 3;");
120 fb->codeAppendf("return half2(coord).rg01;\n");
121 }
122 };
123
124 return std::make_unique<Impl>();
125 }
126};
127
128SkBitmap make_test_bitmap() {
130 bitmap.allocN32Pixels(64, 64);
131 SkCanvas canvas(bitmap);
132
134 const char* alpha = "ABCDEFGHIJKLMNOP";
135
136 for (int i = 0; i < 16; ++i) {
137 int tx = i % 4,
138 ty = i / 4;
139 int x = tx * 16,
140 y = ty * 16;
142 paint.setColor4f({ tx / 3.0f, ty / 3.0f, 0.0f, 1.0f });
143 canvas.drawRect(SkRect::MakeXYWH(x, y, 16, 16), paint);
144 paint.setColor4f({ (3-tx) / 3.0f, (3-ty)/3.0f, 1.0f, 1.0f });
145 canvas.drawSimpleText(alpha + i, 1, SkTextEncoding::kUTF8, x + 3, y + 13, font, paint);
146 }
147
148 return bitmap;
149}
150
151enum EffectType {
152 kUniform,
153 kExplicit,
154 kDevice,
155};
156
157static std::unique_ptr<GrFragmentProcessor> wrap(std::unique_ptr<GrFragmentProcessor> fp,
158 EffectType effectType,
159 int drawX, int drawY) {
160 switch (effectType) {
161 case kUniform:
162 return std::make_unique<UniformMatrixEffect>(std::move(fp));
163 case kExplicit:
164 return std::make_unique<ExplicitCoordEffect>(std::move(fp));
165 case kDevice:
166 // Subtract out upper-left corner of draw so that device is effectively identity.
167 fp = GrMatrixEffect::Make(SkMatrix::Translate(-drawX, -drawY), std::move(fp));
168 return GrFragmentProcessor::DeviceSpace(std::move(fp));
169 }
171}
172
173} // namespace
174
175namespace skiagm {
176
177DEF_SIMPLE_GPU_GM_CAN_FAIL(fp_sample_chaining, rContext, canvas, errorMsg, 232, 306) {
179 if (!sdc) {
181 return DrawResult::kSkip;
182 }
183
184 SkBitmap bmp = make_test_bitmap();
185
186 int x = 10, y = 10;
187
188 auto nextCol = [&] { x += (64 + 10); };
189 auto nextRow = [&] { x = 10; y += (64 + 10); };
190
191 auto draw = [&](std::initializer_list<EffectType> effects) {
192 // Enable TestPatternEffect to get a fully procedural inner effect. It's not quite as nice
193 // visually (no text labels in each box), but it avoids the extra GrMatrixEffect.
194 // Switching it on actually triggers *more* shader compilation failures.
195#if 0
196 auto fp = std::unique_ptr<GrFragmentProcessor>(new TestPatternEffect());
197#else
199 rContext, bmp, /*label=*/"FpSampleChaining", skgpu::Mipmapped::kNo));
200 auto fp = GrTextureEffect::Make(std::move(view), bmp.alphaType());
201#endif
202 for (EffectType effectType : effects) {
203 fp = wrap(std::move(fp), effectType, x, y);
204 }
206 paint.setColorFragmentProcessor(std::move(fp));
207 sdc->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::Translate(x, y),
208 SkRect::MakeIWH(64, 64));
209 nextCol();
210 };
211
212 // Reminder, in every case, the chain is more complicated than it seems, because the
213 // GrTextureEffect is wrapped in a GrMatrixEffect, which is subject to the same bugs that
214 // we're testing (particularly the bug about owner/base in UniformMatrixEffect).
215
216 // First row: no transform, then each one independently applied
217 draw({}); // Identity (4 rows and columns)
218 draw({ kUniform }); // Scale Y axis by 2x (2 visible rows)
219 draw({ kExplicit }); // Translate up by 8px
220 nextRow();
221
222 // Second row: transform duplicated
223 draw({ kUniform, kUniform }); // Scale Y axis by 4x (1 visible row)
224 draw({ kExplicit, kExplicit }); // Translate up by 16px
225 nextRow();
226
227 // Third row: Remember, these are applied inside out:
228 draw({ kUniform, kExplicit }); // Scale Y by 2x and translate up by 8px
229 draw({ kExplicit, kUniform }); // Scale Y by 2x and translate up by 16px
230 nextRow();
231
232 // Fourth row: device space.
233 draw({ kDevice, kUniform }); // Same as identity (uniform applied *before*
234 // device so ignored).
235 draw({ kExplicit, kUniform, kDevice }); // Scale Y by 2x and translate up by 16px
236 draw({ kDevice, kExplicit, kUniform, kDevice }); // Identity, again.
237
238 return DrawResult::kOk;
239}
240
241} // namespace skiagm
@ kFragment_GrShaderFlag
Definition: GrTypesPriv.h:287
#define SkUNREACHABLE
Definition: SkAssert.h:135
@ kUTF8
uses bytes to represent UTF-8 or ASCII
std::tuple< GrSurfaceProxyView, GrColorType > GrMakeCachedBitmapProxyView(GrRecordingContext *rContext, const SkBitmap &bitmap, std::string_view label, skgpu::Mipmapped mipmapped)
Definition: SkGr.cpp:188
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition: aaclip.cpp:27
virtual std::unique_ptr< GrFragmentProcessor > clone() const =0
static std::unique_ptr< GrFragmentProcessor > DeviceSpace(std::unique_ptr< GrFragmentProcessor >)
void registerChild(std::unique_ptr< GrFragmentProcessor > child, SkSL::SampleUsage sampleUsage=SkSL::SampleUsage::PassThrough())
virtual void onAddToKey(const GrShaderCaps &, skgpu::KeyBuilder *) const =0
virtual bool onIsEqual(const GrFragmentProcessor &) const =0
virtual std::unique_ptr< ProgramImpl > onMakeProgramImpl() const =0
void setSkMatrix(UniformHandle, const SkMatrix &) const
static std::unique_ptr< GrFragmentProcessor > Make(const SkMatrix &matrix, std::unique_ptr< GrFragmentProcessor > child)
virtual const char * name() const =0
static std::unique_ptr< GrFragmentProcessor > Make(GrSurfaceProxyView, SkAlphaType, const SkMatrix &=SkMatrix::I(), GrSamplerState::Filter=GrSamplerState::Filter::kNearest, GrSamplerState::MipmapMode mipmapMode=GrSamplerState::MipmapMode::kNone)
SkAlphaType alphaType() const
Definition: SkBitmap.h:162
Definition: SkFont.h:35
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.h:91
static SampleUsage Explicit()
static SampleUsage UniformMatrix(bool hasPerspective)
static const char * MatrixUniformName()
const char * c_str() const
Definition: SkString.h:133
static constexpr char kErrorMsg_DrawSkippedGpuOnly[]
Definition: gm.h:127
const Paint & paint
Definition: color_source.cc:38
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
double y
double x
SkFont DefaultPortableFont()
Definition: bitmap.py:1
const uint32_t fp
font
Font Metadata and Metrics.
const myers::Point & get< 0 >(const myers::Segment &s)
Definition: Myers.h:80
SurfaceDrawContext * TopDeviceSurfaceDrawContext(const SkCanvas *canvas)
Definition: GrCanvas.cpp:20
DEF_SIMPLE_GPU_GM_CAN_FAIL(clear_swizzle, rContext, canvas, errorMsg, 6 *kSize, 2 *kSize)
static SkRect MakeIWH(int w, int h)
Definition: SkRect.h:623
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659