xref: /aosp_15_r20/external/skia/tools/viewer/SkSLSlide.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2019 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "tools/viewer/SkSLSlide.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkClipOp.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontTypes.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTileMode.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkSpan_impl.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/sksl/SkSLDebugTrace.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "tools/DecodeUtils.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "tools/sk_app/Application.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "tools/viewer/Viewer.h"
32*c8dee2aaSAndroid Build Coastguard Worker 
33*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
34*c8dee2aaSAndroid Build Coastguard Worker #include <cmath>
35*c8dee2aaSAndroid Build Coastguard Worker #include <cstdio>
36*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
37*c8dee2aaSAndroid Build Coastguard Worker #include <string>
38*c8dee2aaSAndroid Build Coastguard Worker #include <string_view>
39*c8dee2aaSAndroid Build Coastguard Worker 
40*c8dee2aaSAndroid Build Coastguard Worker #include "imgui.h"
41*c8dee2aaSAndroid Build Coastguard Worker 
42*c8dee2aaSAndroid Build Coastguard Worker using namespace sk_app;
43*c8dee2aaSAndroid Build Coastguard Worker 
44*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
45*c8dee2aaSAndroid Build Coastguard Worker 
InputTextCallback(ImGuiInputTextCallbackData * data)46*c8dee2aaSAndroid Build Coastguard Worker static int InputTextCallback(ImGuiInputTextCallbackData* data) {
47*c8dee2aaSAndroid Build Coastguard Worker     if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) {
48*c8dee2aaSAndroid Build Coastguard Worker         SkString* s = (SkString*)data->UserData;
49*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(data->Buf == s->data());
50*c8dee2aaSAndroid Build Coastguard Worker         SkString tmp(data->Buf, data->BufTextLen);
51*c8dee2aaSAndroid Build Coastguard Worker         s->swap(tmp);
52*c8dee2aaSAndroid Build Coastguard Worker         data->Buf = s->data();
53*c8dee2aaSAndroid Build Coastguard Worker     }
54*c8dee2aaSAndroid Build Coastguard Worker     return 0;
55*c8dee2aaSAndroid Build Coastguard Worker }
56*c8dee2aaSAndroid Build Coastguard Worker 
SkSLSlide()57*c8dee2aaSAndroid Build Coastguard Worker SkSLSlide::SkSLSlide() {
58*c8dee2aaSAndroid Build Coastguard Worker     // Register types for serialization
59*c8dee2aaSAndroid Build Coastguard Worker     fName = "SkSL";
60*c8dee2aaSAndroid Build Coastguard Worker 
61*c8dee2aaSAndroid Build Coastguard Worker     fSkSL =
62*c8dee2aaSAndroid Build Coastguard Worker 
63*c8dee2aaSAndroid Build Coastguard Worker         "uniform shader child;\n"
64*c8dee2aaSAndroid Build Coastguard Worker         "\n"
65*c8dee2aaSAndroid Build Coastguard Worker         "half4 main(float2 p) {\n"
66*c8dee2aaSAndroid Build Coastguard Worker         "    return child.eval(p);\n"
67*c8dee2aaSAndroid Build Coastguard Worker         "}\n";
68*c8dee2aaSAndroid Build Coastguard Worker 
69*c8dee2aaSAndroid Build Coastguard Worker     fCodeIsDirty = true;
70*c8dee2aaSAndroid Build Coastguard Worker }
71*c8dee2aaSAndroid Build Coastguard Worker 
load(SkScalar winWidth,SkScalar winHeight)72*c8dee2aaSAndroid Build Coastguard Worker void SkSLSlide::load(SkScalar winWidth, SkScalar winHeight) {
73*c8dee2aaSAndroid Build Coastguard Worker     SkPoint points[] = { { 0, 0 }, { 256, 0 } };
74*c8dee2aaSAndroid Build Coastguard Worker     SkColor colors[] = { SK_ColorRED, SK_ColorGREEN };
75*c8dee2aaSAndroid Build Coastguard Worker 
76*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkShader> shader;
77*c8dee2aaSAndroid Build Coastguard Worker 
78*c8dee2aaSAndroid Build Coastguard Worker     fShaders.push_back(std::make_pair("Null", nullptr));
79*c8dee2aaSAndroid Build Coastguard Worker 
80*c8dee2aaSAndroid Build Coastguard Worker     shader = SkGradientShader::MakeLinear(points, colors, nullptr, 2, SkTileMode::kClamp);
81*c8dee2aaSAndroid Build Coastguard Worker     fShaders.push_back(std::make_pair("Linear Gradient", shader));
82*c8dee2aaSAndroid Build Coastguard Worker 
83*c8dee2aaSAndroid Build Coastguard Worker     shader = SkGradientShader::MakeRadial({ 256, 256 }, 256, colors, nullptr, 2,
84*c8dee2aaSAndroid Build Coastguard Worker                                           SkTileMode::kClamp);
85*c8dee2aaSAndroid Build Coastguard Worker     fShaders.push_back(std::make_pair("Radial Gradient", shader));
86*c8dee2aaSAndroid Build Coastguard Worker 
87*c8dee2aaSAndroid Build Coastguard Worker     shader = SkGradientShader::MakeSweep(256, 256, colors, nullptr, 2);
88*c8dee2aaSAndroid Build Coastguard Worker     fShaders.push_back(std::make_pair("Sweep Gradient", shader));
89*c8dee2aaSAndroid Build Coastguard Worker 
90*c8dee2aaSAndroid Build Coastguard Worker     shader = ToolUtils::GetResourceAsImage("images/mandrill_256.png")
91*c8dee2aaSAndroid Build Coastguard Worker                      ->makeShader(SkSamplingOptions());
92*c8dee2aaSAndroid Build Coastguard Worker     fShaders.push_back(std::make_pair("Mandrill", shader));
93*c8dee2aaSAndroid Build Coastguard Worker 
94*c8dee2aaSAndroid Build Coastguard Worker     fResolution = { winWidth, winHeight, 1.0f };
95*c8dee2aaSAndroid Build Coastguard Worker }
96*c8dee2aaSAndroid Build Coastguard Worker 
unload()97*c8dee2aaSAndroid Build Coastguard Worker void SkSLSlide::unload() {
98*c8dee2aaSAndroid Build Coastguard Worker     fEffect.reset();
99*c8dee2aaSAndroid Build Coastguard Worker     fInputs.reset();
100*c8dee2aaSAndroid Build Coastguard Worker     fChildren.clear();
101*c8dee2aaSAndroid Build Coastguard Worker     fShaders.clear();
102*c8dee2aaSAndroid Build Coastguard Worker }
103*c8dee2aaSAndroid Build Coastguard Worker 
rebuild()104*c8dee2aaSAndroid Build Coastguard Worker bool SkSLSlide::rebuild() {
105*c8dee2aaSAndroid Build Coastguard Worker     // Some of the standard shadertoy inputs:
106*c8dee2aaSAndroid Build Coastguard Worker     SkString sksl;
107*c8dee2aaSAndroid Build Coastguard Worker     // TODO(skia:11209): This interferes with user-authored #version directives
108*c8dee2aaSAndroid Build Coastguard Worker     if (fShadertoyUniforms) {
109*c8dee2aaSAndroid Build Coastguard Worker         sksl = "uniform float3 iResolution;\n"
110*c8dee2aaSAndroid Build Coastguard Worker                "uniform float  iTime;\n"
111*c8dee2aaSAndroid Build Coastguard Worker                "uniform float4 iMouse;\n";
112*c8dee2aaSAndroid Build Coastguard Worker     }
113*c8dee2aaSAndroid Build Coastguard Worker     sksl.append(fSkSL);
114*c8dee2aaSAndroid Build Coastguard Worker 
115*c8dee2aaSAndroid Build Coastguard Worker     // It shouldn't happen, but it's possible to assert in the compiler, especially mid-edit.
116*c8dee2aaSAndroid Build Coastguard Worker     // To guard against losing your work, write out the shader to a backup file, then remove it
117*c8dee2aaSAndroid Build Coastguard Worker     // when we compile successfully.
118*c8dee2aaSAndroid Build Coastguard Worker     constexpr char kBackupFile[] = "sksl.bak";
119*c8dee2aaSAndroid Build Coastguard Worker     FILE* backup = fopen(kBackupFile, "w");
120*c8dee2aaSAndroid Build Coastguard Worker     if (backup) {
121*c8dee2aaSAndroid Build Coastguard Worker         fwrite(fSkSL.c_str(), 1, fSkSL.size(), backup);
122*c8dee2aaSAndroid Build Coastguard Worker         fclose(backup);
123*c8dee2aaSAndroid Build Coastguard Worker     }
124*c8dee2aaSAndroid Build Coastguard Worker     auto [effect, errorText] = SkRuntimeEffect::MakeForShader(sksl);
125*c8dee2aaSAndroid Build Coastguard Worker     if (backup) {
126*c8dee2aaSAndroid Build Coastguard Worker         std::remove(kBackupFile);
127*c8dee2aaSAndroid Build Coastguard Worker     }
128*c8dee2aaSAndroid Build Coastguard Worker 
129*c8dee2aaSAndroid Build Coastguard Worker     if (!effect) {
130*c8dee2aaSAndroid Build Coastguard Worker         Viewer::ShaderErrorHandler()->compileError(sksl.c_str(), errorText.c_str());
131*c8dee2aaSAndroid Build Coastguard Worker         return false;
132*c8dee2aaSAndroid Build Coastguard Worker     }
133*c8dee2aaSAndroid Build Coastguard Worker 
134*c8dee2aaSAndroid Build Coastguard Worker     size_t oldSize = fEffect ? fEffect->uniformSize() : 0;
135*c8dee2aaSAndroid Build Coastguard Worker     fInputs.realloc(effect->uniformSize());
136*c8dee2aaSAndroid Build Coastguard Worker     if (effect->uniformSize() > oldSize) {
137*c8dee2aaSAndroid Build Coastguard Worker         memset(fInputs.get() + oldSize, 0, effect->uniformSize() - oldSize);
138*c8dee2aaSAndroid Build Coastguard Worker     }
139*c8dee2aaSAndroid Build Coastguard Worker     fChildren.resize_back(effect->children().size());
140*c8dee2aaSAndroid Build Coastguard Worker 
141*c8dee2aaSAndroid Build Coastguard Worker     fEffect = effect;
142*c8dee2aaSAndroid Build Coastguard Worker     fCodeIsDirty = false;
143*c8dee2aaSAndroid Build Coastguard Worker     return true;
144*c8dee2aaSAndroid Build Coastguard Worker }
145*c8dee2aaSAndroid Build Coastguard Worker 
draw(SkCanvas * canvas)146*c8dee2aaSAndroid Build Coastguard Worker void SkSLSlide::draw(SkCanvas* canvas) {
147*c8dee2aaSAndroid Build Coastguard Worker     canvas->clear(SK_ColorWHITE);
148*c8dee2aaSAndroid Build Coastguard Worker 
149*c8dee2aaSAndroid Build Coastguard Worker     ImGui::Begin("SkSL", nullptr, ImGuiWindowFlags_AlwaysVerticalScrollbar);
150*c8dee2aaSAndroid Build Coastguard Worker 
151*c8dee2aaSAndroid Build Coastguard Worker     // Edit box for shader code
152*c8dee2aaSAndroid Build Coastguard Worker     ImGuiInputTextFlags flags = ImGuiInputTextFlags_CallbackResize;
153*c8dee2aaSAndroid Build Coastguard Worker     ImVec2 boxSize(-1.0f, ImGui::GetTextLineHeight() * 30);
154*c8dee2aaSAndroid Build Coastguard Worker     if (ImGui::InputTextMultiline("Code", fSkSL.data(), fSkSL.size() + 1, boxSize, flags,
155*c8dee2aaSAndroid Build Coastguard Worker                                   InputTextCallback, &fSkSL)) {
156*c8dee2aaSAndroid Build Coastguard Worker         fCodeIsDirty = true;
157*c8dee2aaSAndroid Build Coastguard Worker     }
158*c8dee2aaSAndroid Build Coastguard Worker 
159*c8dee2aaSAndroid Build Coastguard Worker     if (ImGui::Checkbox("ShaderToy Uniforms (iResolution/iTime/iMouse)", &fShadertoyUniforms)) {
160*c8dee2aaSAndroid Build Coastguard Worker         fCodeIsDirty = true;
161*c8dee2aaSAndroid Build Coastguard Worker     }
162*c8dee2aaSAndroid Build Coastguard Worker 
163*c8dee2aaSAndroid Build Coastguard Worker     if (fCodeIsDirty || !fEffect) {
164*c8dee2aaSAndroid Build Coastguard Worker         this->rebuild();
165*c8dee2aaSAndroid Build Coastguard Worker     }
166*c8dee2aaSAndroid Build Coastguard Worker 
167*c8dee2aaSAndroid Build Coastguard Worker     if (!fEffect) {
168*c8dee2aaSAndroid Build Coastguard Worker         ImGui::End();
169*c8dee2aaSAndroid Build Coastguard Worker         return;
170*c8dee2aaSAndroid Build Coastguard Worker     }
171*c8dee2aaSAndroid Build Coastguard Worker 
172*c8dee2aaSAndroid Build Coastguard Worker     bool writeTrace = false;
173*c8dee2aaSAndroid Build Coastguard Worker     bool writeDump = false;
174*c8dee2aaSAndroid Build Coastguard Worker     if (!canvas->recordingContext()) {
175*c8dee2aaSAndroid Build Coastguard Worker         ImGui::InputInt2("Trace Coordinate (X/Y)", fTraceCoord);
176*c8dee2aaSAndroid Build Coastguard Worker         writeTrace = ImGui::Button("Write Debug Trace (JSON)");
177*c8dee2aaSAndroid Build Coastguard Worker         writeDump = ImGui::Button("Write Debug Dump (Human-Readable)");
178*c8dee2aaSAndroid Build Coastguard Worker     }
179*c8dee2aaSAndroid Build Coastguard Worker 
180*c8dee2aaSAndroid Build Coastguard Worker     // Update fMousePos
181*c8dee2aaSAndroid Build Coastguard Worker     ImVec2 mousePos = ImGui::GetMousePos();
182*c8dee2aaSAndroid Build Coastguard Worker     if (ImGui::IsMouseDown(0)) {
183*c8dee2aaSAndroid Build Coastguard Worker         fMousePos.x = mousePos.x;
184*c8dee2aaSAndroid Build Coastguard Worker         fMousePos.y = mousePos.y;
185*c8dee2aaSAndroid Build Coastguard Worker     }
186*c8dee2aaSAndroid Build Coastguard Worker     if (ImGui::IsMouseClicked(0)) {
187*c8dee2aaSAndroid Build Coastguard Worker         fMousePos.z = mousePos.x;
188*c8dee2aaSAndroid Build Coastguard Worker         fMousePos.w = mousePos.y;
189*c8dee2aaSAndroid Build Coastguard Worker     }
190*c8dee2aaSAndroid Build Coastguard Worker     fMousePos.z = std::abs(fMousePos.z) * (ImGui::IsMouseDown(0)    ? 1 : -1);
191*c8dee2aaSAndroid Build Coastguard Worker     fMousePos.w = std::abs(fMousePos.w) * (ImGui::IsMouseClicked(0) ? 1 : -1);
192*c8dee2aaSAndroid Build Coastguard Worker 
193*c8dee2aaSAndroid Build Coastguard Worker     for (const SkRuntimeEffect::Uniform& v : fEffect->uniforms()) {
194*c8dee2aaSAndroid Build Coastguard Worker         char* data = fInputs.get() + v.offset;
195*c8dee2aaSAndroid Build Coastguard Worker         if (v.name == "iResolution") {
196*c8dee2aaSAndroid Build Coastguard Worker             memcpy(data, &fResolution, sizeof(fResolution));
197*c8dee2aaSAndroid Build Coastguard Worker             continue;
198*c8dee2aaSAndroid Build Coastguard Worker         }
199*c8dee2aaSAndroid Build Coastguard Worker         if (v.name == "iTime") {
200*c8dee2aaSAndroid Build Coastguard Worker             memcpy(data, &fSeconds, sizeof(fSeconds));
201*c8dee2aaSAndroid Build Coastguard Worker             continue;
202*c8dee2aaSAndroid Build Coastguard Worker         }
203*c8dee2aaSAndroid Build Coastguard Worker         if (v.name == "iMouse") {
204*c8dee2aaSAndroid Build Coastguard Worker             memcpy(data, &fMousePos, sizeof(fMousePos));
205*c8dee2aaSAndroid Build Coastguard Worker             continue;
206*c8dee2aaSAndroid Build Coastguard Worker         }
207*c8dee2aaSAndroid Build Coastguard Worker         switch (v.type) {
208*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::Uniform::Type::kFloat:
209*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::Uniform::Type::kFloat2:
210*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::Uniform::Type::kFloat3:
211*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::Uniform::Type::kFloat4: {
212*c8dee2aaSAndroid Build Coastguard Worker                 int rows = ((int)v.type - (int)SkRuntimeEffect::Uniform::Type::kFloat) + 1;
213*c8dee2aaSAndroid Build Coastguard Worker                 float* f = reinterpret_cast<float*>(data);
214*c8dee2aaSAndroid Build Coastguard Worker                 for (int c = 0; c < v.count; ++c, f += rows) {
215*c8dee2aaSAndroid Build Coastguard Worker                     SkString name = v.isArray()
216*c8dee2aaSAndroid Build Coastguard Worker                             ? SkStringPrintf("%.*s[%d]", (int)v.name.size(), v.name.data(), c)
217*c8dee2aaSAndroid Build Coastguard Worker                             : SkString(v.name);
218*c8dee2aaSAndroid Build Coastguard Worker                     ImGui::PushID(c);
219*c8dee2aaSAndroid Build Coastguard Worker                     ImGui::DragScalarN(name.c_str(), ImGuiDataType_Float, f, rows, 1.0f);
220*c8dee2aaSAndroid Build Coastguard Worker                     ImGui::PopID();
221*c8dee2aaSAndroid Build Coastguard Worker                 }
222*c8dee2aaSAndroid Build Coastguard Worker                 break;
223*c8dee2aaSAndroid Build Coastguard Worker             }
224*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::Uniform::Type::kFloat2x2:
225*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::Uniform::Type::kFloat3x3:
226*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::Uniform::Type::kFloat4x4: {
227*c8dee2aaSAndroid Build Coastguard Worker                 int rows = ((int)v.type - (int)SkRuntimeEffect::Uniform::Type::kFloat2x2) + 2;
228*c8dee2aaSAndroid Build Coastguard Worker                 int cols = rows;
229*c8dee2aaSAndroid Build Coastguard Worker                 float* f = reinterpret_cast<float*>(data);
230*c8dee2aaSAndroid Build Coastguard Worker                 for (int e = 0; e < v.count; ++e) {
231*c8dee2aaSAndroid Build Coastguard Worker                     for (int c = 0; c < cols; ++c, f += rows) {
232*c8dee2aaSAndroid Build Coastguard Worker                         SkString name = v.isArray()
233*c8dee2aaSAndroid Build Coastguard Worker                            ? SkStringPrintf("%.*s[%d][%d]", (int)v.name.size(), v.name.data(), e, c)
234*c8dee2aaSAndroid Build Coastguard Worker                            : SkStringPrintf("%.*s[%d]", (int)v.name.size(), v.name.data(), c);
235*c8dee2aaSAndroid Build Coastguard Worker                         ImGui::DragScalarN(name.c_str(), ImGuiDataType_Float, f, rows, 1.0f);
236*c8dee2aaSAndroid Build Coastguard Worker                     }
237*c8dee2aaSAndroid Build Coastguard Worker                 }
238*c8dee2aaSAndroid Build Coastguard Worker                 break;
239*c8dee2aaSAndroid Build Coastguard Worker             }
240*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::Uniform::Type::kInt:
241*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::Uniform::Type::kInt2:
242*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::Uniform::Type::kInt3:
243*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::Uniform::Type::kInt4: {
244*c8dee2aaSAndroid Build Coastguard Worker                 int rows = ((int)v.type - (int)SkRuntimeEffect::Uniform::Type::kInt) + 1;
245*c8dee2aaSAndroid Build Coastguard Worker                 int* i = reinterpret_cast<int*>(data);
246*c8dee2aaSAndroid Build Coastguard Worker                 for (int c = 0; c < v.count; ++c, i += rows) {
247*c8dee2aaSAndroid Build Coastguard Worker                     SkString name = v.isArray()
248*c8dee2aaSAndroid Build Coastguard Worker                             ? SkStringPrintf("%.*s[%d]", (int)v.name.size(), v.name.data(), c)
249*c8dee2aaSAndroid Build Coastguard Worker                             : SkString(v.name);
250*c8dee2aaSAndroid Build Coastguard Worker                     ImGui::PushID(c);
251*c8dee2aaSAndroid Build Coastguard Worker                     ImGui::DragScalarN(name.c_str(), ImGuiDataType_S32, i, rows, 1.0f);
252*c8dee2aaSAndroid Build Coastguard Worker                     ImGui::PopID();
253*c8dee2aaSAndroid Build Coastguard Worker                 }
254*c8dee2aaSAndroid Build Coastguard Worker                 break;
255*c8dee2aaSAndroid Build Coastguard Worker             }
256*c8dee2aaSAndroid Build Coastguard Worker         }
257*c8dee2aaSAndroid Build Coastguard Worker     }
258*c8dee2aaSAndroid Build Coastguard Worker 
259*c8dee2aaSAndroid Build Coastguard Worker     for (const SkRuntimeEffect::Child& c : fEffect->children()) {
260*c8dee2aaSAndroid Build Coastguard Worker         auto curShader = std::find_if(
261*c8dee2aaSAndroid Build Coastguard Worker                 fShaders.begin(),
262*c8dee2aaSAndroid Build Coastguard Worker                 fShaders.end(),
263*c8dee2aaSAndroid Build Coastguard Worker                 [tgt = fChildren[c.index]](const std::pair<const char*, sk_sp<SkShader>>& p) {
264*c8dee2aaSAndroid Build Coastguard Worker                     return p.second == tgt;
265*c8dee2aaSAndroid Build Coastguard Worker                 });
266*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(curShader != fShaders.end());
267*c8dee2aaSAndroid Build Coastguard Worker 
268*c8dee2aaSAndroid Build Coastguard Worker         if (ImGui::BeginCombo(std::string(c.name).c_str(), curShader->first)) {
269*c8dee2aaSAndroid Build Coastguard Worker             for (const auto& namedShader : fShaders) {
270*c8dee2aaSAndroid Build Coastguard Worker                 if (ImGui::Selectable(namedShader.first, curShader->second == namedShader.second)) {
271*c8dee2aaSAndroid Build Coastguard Worker                     fChildren[c.index] = namedShader.second;
272*c8dee2aaSAndroid Build Coastguard Worker                 }
273*c8dee2aaSAndroid Build Coastguard Worker             }
274*c8dee2aaSAndroid Build Coastguard Worker             ImGui::EndCombo();
275*c8dee2aaSAndroid Build Coastguard Worker         }
276*c8dee2aaSAndroid Build Coastguard Worker     }
277*c8dee2aaSAndroid Build Coastguard Worker 
278*c8dee2aaSAndroid Build Coastguard Worker     static SkColor4f gPaintColor { 1.0f, 1.0f, 1.0f , 1.0f };
279*c8dee2aaSAndroid Build Coastguard Worker     ImGui::ColorEdit4("Paint Color", gPaintColor.vec());
280*c8dee2aaSAndroid Build Coastguard Worker 
281*c8dee2aaSAndroid Build Coastguard Worker     ImGui::RadioButton("Fill",      &fGeometry, kFill);      ImGui::SameLine();
282*c8dee2aaSAndroid Build Coastguard Worker     ImGui::RadioButton("Circle",    &fGeometry, kCircle);    ImGui::SameLine();
283*c8dee2aaSAndroid Build Coastguard Worker     ImGui::RadioButton("RoundRect", &fGeometry, kRoundRect); ImGui::SameLine();
284*c8dee2aaSAndroid Build Coastguard Worker     ImGui::RadioButton("Capsule",   &fGeometry, kCapsule);   ImGui::SameLine();
285*c8dee2aaSAndroid Build Coastguard Worker     ImGui::RadioButton("Text",      &fGeometry, kText);
286*c8dee2aaSAndroid Build Coastguard Worker 
287*c8dee2aaSAndroid Build Coastguard Worker     ImGui::End();
288*c8dee2aaSAndroid Build Coastguard Worker 
289*c8dee2aaSAndroid Build Coastguard Worker     auto inputs = SkData::MakeWithoutCopy(fInputs.get(), fEffect->uniformSize());
290*c8dee2aaSAndroid Build Coastguard Worker 
291*c8dee2aaSAndroid Build Coastguard Worker     canvas->save();
292*c8dee2aaSAndroid Build Coastguard Worker 
293*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkSL::DebugTrace> debugTrace;
294*c8dee2aaSAndroid Build Coastguard Worker     auto shader = fEffect->makeShader(std::move(inputs), fChildren.data(), fChildren.size());
295*c8dee2aaSAndroid Build Coastguard Worker     if (writeTrace || writeDump) {
296*c8dee2aaSAndroid Build Coastguard Worker         SkIPoint traceCoord = {fTraceCoord[0], fTraceCoord[1]};
297*c8dee2aaSAndroid Build Coastguard Worker         SkRuntimeEffect::TracedShader traced = SkRuntimeEffect::MakeTraced(std::move(shader),
298*c8dee2aaSAndroid Build Coastguard Worker                                                                            traceCoord);
299*c8dee2aaSAndroid Build Coastguard Worker         shader = std::move(traced.shader);
300*c8dee2aaSAndroid Build Coastguard Worker         debugTrace = std::move(traced.debugTrace);
301*c8dee2aaSAndroid Build Coastguard Worker 
302*c8dee2aaSAndroid Build Coastguard Worker         // Reduce debug trace delay by clipping to a 4x4 rectangle for this paint, centered on the
303*c8dee2aaSAndroid Build Coastguard Worker         // pixel to trace. A minor complication is that the canvas might have a transform applied to
304*c8dee2aaSAndroid Build Coastguard Worker         // it, but we want to clip in device space. This can be worked around by resetting the
305*c8dee2aaSAndroid Build Coastguard Worker         // canvas matrix temporarily.
306*c8dee2aaSAndroid Build Coastguard Worker         SkM44 canvasMatrix = canvas->getLocalToDevice();
307*c8dee2aaSAndroid Build Coastguard Worker         canvas->resetMatrix();
308*c8dee2aaSAndroid Build Coastguard Worker         auto r = SkRect::MakeXYWH(fTraceCoord[0] - 1, fTraceCoord[1] - 1, 4, 4);
309*c8dee2aaSAndroid Build Coastguard Worker         canvas->clipRect(r, SkClipOp::kIntersect);
310*c8dee2aaSAndroid Build Coastguard Worker         canvas->setMatrix(canvasMatrix);
311*c8dee2aaSAndroid Build Coastguard Worker     }
312*c8dee2aaSAndroid Build Coastguard Worker     SkPaint p;
313*c8dee2aaSAndroid Build Coastguard Worker     p.setColor4f(gPaintColor);
314*c8dee2aaSAndroid Build Coastguard Worker     p.setShader(std::move(shader));
315*c8dee2aaSAndroid Build Coastguard Worker 
316*c8dee2aaSAndroid Build Coastguard Worker     switch (fGeometry) {
317*c8dee2aaSAndroid Build Coastguard Worker         case kFill:
318*c8dee2aaSAndroid Build Coastguard Worker             canvas->drawPaint(p);
319*c8dee2aaSAndroid Build Coastguard Worker             break;
320*c8dee2aaSAndroid Build Coastguard Worker         case kCircle:
321*c8dee2aaSAndroid Build Coastguard Worker             canvas->drawCircle({ 256, 256 }, 256, p);
322*c8dee2aaSAndroid Build Coastguard Worker             break;
323*c8dee2aaSAndroid Build Coastguard Worker         case kRoundRect:
324*c8dee2aaSAndroid Build Coastguard Worker             canvas->drawRoundRect({ 0, 0, 512, 512 }, 64, 64, p);
325*c8dee2aaSAndroid Build Coastguard Worker             break;
326*c8dee2aaSAndroid Build Coastguard Worker         case kCapsule:
327*c8dee2aaSAndroid Build Coastguard Worker             canvas->drawRoundRect({ 0, 224, 512, 288 }, 32, 32, p);
328*c8dee2aaSAndroid Build Coastguard Worker             break;
329*c8dee2aaSAndroid Build Coastguard Worker         case kText: {
330*c8dee2aaSAndroid Build Coastguard Worker             SkFont font = ToolUtils::DefaultFont();
331*c8dee2aaSAndroid Build Coastguard Worker             font.setSize(SkIntToScalar(96));
332*c8dee2aaSAndroid Build Coastguard Worker             canvas->drawSimpleText("Hello World", strlen("Hello World"), SkTextEncoding::kUTF8, 0,
333*c8dee2aaSAndroid Build Coastguard Worker                                    256, font, p);
334*c8dee2aaSAndroid Build Coastguard Worker         } break;
335*c8dee2aaSAndroid Build Coastguard Worker         default: break;
336*c8dee2aaSAndroid Build Coastguard Worker     }
337*c8dee2aaSAndroid Build Coastguard Worker 
338*c8dee2aaSAndroid Build Coastguard Worker     canvas->restore();
339*c8dee2aaSAndroid Build Coastguard Worker 
340*c8dee2aaSAndroid Build Coastguard Worker     if (debugTrace && writeTrace) {
341*c8dee2aaSAndroid Build Coastguard Worker         SkFILEWStream traceFile("SkSLDebugTrace.json");
342*c8dee2aaSAndroid Build Coastguard Worker         debugTrace->writeTrace(&traceFile);
343*c8dee2aaSAndroid Build Coastguard Worker     }
344*c8dee2aaSAndroid Build Coastguard Worker     if (debugTrace && writeDump) {
345*c8dee2aaSAndroid Build Coastguard Worker         SkFILEWStream dumpFile("SkSLDebugTrace.dump.txt");
346*c8dee2aaSAndroid Build Coastguard Worker         debugTrace->dump(&dumpFile);
347*c8dee2aaSAndroid Build Coastguard Worker     }
348*c8dee2aaSAndroid Build Coastguard Worker }
349*c8dee2aaSAndroid Build Coastguard Worker 
animate(double nanos)350*c8dee2aaSAndroid Build Coastguard Worker bool SkSLSlide::animate(double nanos) {
351*c8dee2aaSAndroid Build Coastguard Worker     fSeconds = static_cast<float>(nanos * 1E-9);
352*c8dee2aaSAndroid Build Coastguard Worker     return true;
353*c8dee2aaSAndroid Build Coastguard Worker }
354