1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2021 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/SkSLDebuggerSlide.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "tools/sk_app/Application.h"
16*c8dee2aaSAndroid Build Coastguard Worker
17*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
18*c8dee2aaSAndroid Build Coastguard Worker #include <cstdio>
19*c8dee2aaSAndroid Build Coastguard Worker #include <string>
20*c8dee2aaSAndroid Build Coastguard Worker #include <unordered_map>
21*c8dee2aaSAndroid Build Coastguard Worker #include <unordered_set>
22*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
23*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
24*c8dee2aaSAndroid Build Coastguard Worker
25*c8dee2aaSAndroid Build Coastguard Worker #include "imgui.h"
26*c8dee2aaSAndroid Build Coastguard Worker
27*c8dee2aaSAndroid Build Coastguard Worker using namespace sk_app;
28*c8dee2aaSAndroid Build Coastguard Worker using LineNumberMap = SkSL::SkSLDebugTracePlayer::LineNumberMap;
29*c8dee2aaSAndroid Build Coastguard Worker
SkSLDebuggerSlide()30*c8dee2aaSAndroid Build Coastguard Worker SkSLDebuggerSlide::SkSLDebuggerSlide() {
31*c8dee2aaSAndroid Build Coastguard Worker fName = "Debugger";
32*c8dee2aaSAndroid Build Coastguard Worker fTrace = sk_make_sp<SkSL::DebugTracePriv>();
33*c8dee2aaSAndroid Build Coastguard Worker }
34*c8dee2aaSAndroid Build Coastguard Worker
load(SkScalar winWidth,SkScalar winHeight)35*c8dee2aaSAndroid Build Coastguard Worker void SkSLDebuggerSlide::load(SkScalar winWidth, SkScalar winHeight) {}
36*c8dee2aaSAndroid Build Coastguard Worker
unload()37*c8dee2aaSAndroid Build Coastguard Worker void SkSLDebuggerSlide::unload() {
38*c8dee2aaSAndroid Build Coastguard Worker fTrace = sk_make_sp<SkSL::DebugTracePriv>();
39*c8dee2aaSAndroid Build Coastguard Worker fPlayer.reset(nullptr);
40*c8dee2aaSAndroid Build Coastguard Worker fPlayer.setBreakpoints(std::unordered_set<int>{});
41*c8dee2aaSAndroid Build Coastguard Worker }
42*c8dee2aaSAndroid Build Coastguard Worker
showLoadTraceGUI()43*c8dee2aaSAndroid Build Coastguard Worker void SkSLDebuggerSlide::showLoadTraceGUI() {
44*c8dee2aaSAndroid Build Coastguard Worker ImGui::InputText("Trace Path", fTraceFile, std::size(fTraceFile));
45*c8dee2aaSAndroid Build Coastguard Worker bool load = ImGui::Button("Load Debug Trace");
46*c8dee2aaSAndroid Build Coastguard Worker
47*c8dee2aaSAndroid Build Coastguard Worker if (load) {
48*c8dee2aaSAndroid Build Coastguard Worker SkFILEStream file(fTraceFile);
49*c8dee2aaSAndroid Build Coastguard Worker if (!file.isValid()) {
50*c8dee2aaSAndroid Build Coastguard Worker ImGui::OpenPopup("Can't Open Trace");
51*c8dee2aaSAndroid Build Coastguard Worker } else if (!fTrace->readTrace(&file)) {
52*c8dee2aaSAndroid Build Coastguard Worker ImGui::OpenPopup("Invalid Trace");
53*c8dee2aaSAndroid Build Coastguard Worker } else {
54*c8dee2aaSAndroid Build Coastguard Worker // Trace loaded successfully. On the next refresh, the user will see the debug UI.
55*c8dee2aaSAndroid Build Coastguard Worker fPlayer.reset(fTrace);
56*c8dee2aaSAndroid Build Coastguard Worker fPlayer.step();
57*c8dee2aaSAndroid Build Coastguard Worker fRefresh = true;
58*c8dee2aaSAndroid Build Coastguard Worker return;
59*c8dee2aaSAndroid Build Coastguard Worker }
60*c8dee2aaSAndroid Build Coastguard Worker }
61*c8dee2aaSAndroid Build Coastguard Worker
62*c8dee2aaSAndroid Build Coastguard Worker if (ImGui::BeginPopupModal("Can't Open Trace", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
63*c8dee2aaSAndroid Build Coastguard Worker ImGui::Text("The trace file doesn't exist.");
64*c8dee2aaSAndroid Build Coastguard Worker ImGui::Separator();
65*c8dee2aaSAndroid Build Coastguard Worker if (ImGui::Button("OK", ImVec2(120, 0))) {
66*c8dee2aaSAndroid Build Coastguard Worker ImGui::CloseCurrentPopup();
67*c8dee2aaSAndroid Build Coastguard Worker }
68*c8dee2aaSAndroid Build Coastguard Worker ImGui::EndPopup();
69*c8dee2aaSAndroid Build Coastguard Worker }
70*c8dee2aaSAndroid Build Coastguard Worker
71*c8dee2aaSAndroid Build Coastguard Worker if (ImGui::BeginPopupModal("Invalid Trace", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
72*c8dee2aaSAndroid Build Coastguard Worker ImGui::Text("The trace data could not be parsed.");
73*c8dee2aaSAndroid Build Coastguard Worker ImGui::Separator();
74*c8dee2aaSAndroid Build Coastguard Worker if (ImGui::Button("OK", ImVec2(120, 0))) {
75*c8dee2aaSAndroid Build Coastguard Worker ImGui::CloseCurrentPopup();
76*c8dee2aaSAndroid Build Coastguard Worker }
77*c8dee2aaSAndroid Build Coastguard Worker ImGui::EndPopup();
78*c8dee2aaSAndroid Build Coastguard Worker }
79*c8dee2aaSAndroid Build Coastguard Worker }
80*c8dee2aaSAndroid Build Coastguard Worker
showDebuggerGUI()81*c8dee2aaSAndroid Build Coastguard Worker void SkSLDebuggerSlide::showDebuggerGUI() {
82*c8dee2aaSAndroid Build Coastguard Worker if (ImGui::Button("Reset")) {
83*c8dee2aaSAndroid Build Coastguard Worker fPlayer.reset(fTrace);
84*c8dee2aaSAndroid Build Coastguard Worker fRefresh = true;
85*c8dee2aaSAndroid Build Coastguard Worker }
86*c8dee2aaSAndroid Build Coastguard Worker ImGui::SameLine(/*offset_from_start_x=*/0, /*spacing=*/100);
87*c8dee2aaSAndroid Build Coastguard Worker if (ImGui::Button("Step")) {
88*c8dee2aaSAndroid Build Coastguard Worker fPlayer.step();
89*c8dee2aaSAndroid Build Coastguard Worker fRefresh = true;
90*c8dee2aaSAndroid Build Coastguard Worker }
91*c8dee2aaSAndroid Build Coastguard Worker ImGui::SameLine();
92*c8dee2aaSAndroid Build Coastguard Worker if (ImGui::Button("Step Over")) {
93*c8dee2aaSAndroid Build Coastguard Worker fPlayer.stepOver();
94*c8dee2aaSAndroid Build Coastguard Worker fRefresh = true;
95*c8dee2aaSAndroid Build Coastguard Worker }
96*c8dee2aaSAndroid Build Coastguard Worker ImGui::SameLine();
97*c8dee2aaSAndroid Build Coastguard Worker if (ImGui::Button("Step Out")) {
98*c8dee2aaSAndroid Build Coastguard Worker fPlayer.stepOut();
99*c8dee2aaSAndroid Build Coastguard Worker fRefresh = true;
100*c8dee2aaSAndroid Build Coastguard Worker }
101*c8dee2aaSAndroid Build Coastguard Worker ImGui::SameLine(/*offset_from_start_x=*/0, /*spacing=*/100);
102*c8dee2aaSAndroid Build Coastguard Worker if (ImGui::Button(fPlayer.getBreakpoints().empty() ? "Run" : "Run to Breakpoint")) {
103*c8dee2aaSAndroid Build Coastguard Worker fPlayer.run();
104*c8dee2aaSAndroid Build Coastguard Worker fRefresh = true;
105*c8dee2aaSAndroid Build Coastguard Worker }
106*c8dee2aaSAndroid Build Coastguard Worker
107*c8dee2aaSAndroid Build Coastguard Worker this->showStackTraceTable();
108*c8dee2aaSAndroid Build Coastguard Worker this->showVariableTable();
109*c8dee2aaSAndroid Build Coastguard Worker this->showCodeTable();
110*c8dee2aaSAndroid Build Coastguard Worker }
111*c8dee2aaSAndroid Build Coastguard Worker
showCodeTable()112*c8dee2aaSAndroid Build Coastguard Worker void SkSLDebuggerSlide::showCodeTable() {
113*c8dee2aaSAndroid Build Coastguard Worker constexpr ImGuiTableFlags kTableFlags =
114*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter |
115*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableFlags_BordersV;
116*c8dee2aaSAndroid Build Coastguard Worker constexpr ImGuiTableColumnFlags kColumnFlags =
117*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoReorder |
118*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoSort |
119*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableColumnFlags_NoHeaderLabel;
120*c8dee2aaSAndroid Build Coastguard Worker
121*c8dee2aaSAndroid Build Coastguard Worker ImVec2 contentRect = ImGui::GetContentRegionAvail();
122*c8dee2aaSAndroid Build Coastguard Worker ImVec2 codeViewSize = ImVec2(0.0f, contentRect.y);
123*c8dee2aaSAndroid Build Coastguard Worker if (ImGui::BeginTable("Code View", /*column=*/2, kTableFlags, codeViewSize)) {
124*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableSetupColumn("", kColumnFlags | ImGuiTableColumnFlags_WidthFixed);
125*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableSetupColumn("Code", kColumnFlags | ImGuiTableColumnFlags_WidthStretch);
126*c8dee2aaSAndroid Build Coastguard Worker
127*c8dee2aaSAndroid Build Coastguard Worker ImGuiListClipper clipper;
128*c8dee2aaSAndroid Build Coastguard Worker clipper.Begin(fTrace->fSource.size());
129*c8dee2aaSAndroid Build Coastguard Worker while (clipper.Step()) {
130*c8dee2aaSAndroid Build Coastguard Worker for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) {
131*c8dee2aaSAndroid Build Coastguard Worker size_t humanReadableLine = row + 1;
132*c8dee2aaSAndroid Build Coastguard Worker
133*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableNextRow();
134*c8dee2aaSAndroid Build Coastguard Worker if (fPlayer.getCurrentLine() == (int)humanReadableLine) {
135*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableSetBgColor(
136*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableBgTarget_RowBg1,
137*c8dee2aaSAndroid Build Coastguard Worker ImGui::GetColorU32(ImGui::GetStyleColorVec4(ImGuiCol_TextSelectedBg)));
138*c8dee2aaSAndroid Build Coastguard Worker }
139*c8dee2aaSAndroid Build Coastguard Worker
140*c8dee2aaSAndroid Build Coastguard Worker // Show line numbers and breakpoints.
141*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableSetColumnIndex(0);
142*c8dee2aaSAndroid Build Coastguard Worker const LineNumberMap& lineNumberMap = fPlayer.getLineNumbersReached();
143*c8dee2aaSAndroid Build Coastguard Worker LineNumberMap::const_iterator iter = lineNumberMap.find(humanReadableLine);
144*c8dee2aaSAndroid Build Coastguard Worker bool reachable = iter != lineNumberMap.end() && iter->second > 0;
145*c8dee2aaSAndroid Build Coastguard Worker bool breakpointOn = fPlayer.getBreakpoints().count(humanReadableLine);
146*c8dee2aaSAndroid Build Coastguard Worker if (breakpointOn) {
147*c8dee2aaSAndroid Build Coastguard Worker ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
148*c8dee2aaSAndroid Build Coastguard Worker ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 0.0f, 0.0f, 0.70f));
149*c8dee2aaSAndroid Build Coastguard Worker ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 0.0f, 0.0f, 0.85f));
150*c8dee2aaSAndroid Build Coastguard Worker ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 0.0f, 0.0f, 1.0f));
151*c8dee2aaSAndroid Build Coastguard Worker } else if (reachable) {
152*c8dee2aaSAndroid Build Coastguard Worker ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 0.75f));
153*c8dee2aaSAndroid Build Coastguard Worker ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
154*c8dee2aaSAndroid Build Coastguard Worker ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.2f));
155*c8dee2aaSAndroid Build Coastguard Worker ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 1.0f, 1.0f, 0.4f));
156*c8dee2aaSAndroid Build Coastguard Worker } else {
157*c8dee2aaSAndroid Build Coastguard Worker ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 0.25f));
158*c8dee2aaSAndroid Build Coastguard Worker ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
159*c8dee2aaSAndroid Build Coastguard Worker ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
160*c8dee2aaSAndroid Build Coastguard Worker ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
161*c8dee2aaSAndroid Build Coastguard Worker }
162*c8dee2aaSAndroid Build Coastguard Worker if (ImGui::SmallButton(SkStringPrintf("%03zu ", humanReadableLine).c_str())) {
163*c8dee2aaSAndroid Build Coastguard Worker if (breakpointOn) {
164*c8dee2aaSAndroid Build Coastguard Worker fPlayer.removeBreakpoint(humanReadableLine);
165*c8dee2aaSAndroid Build Coastguard Worker } else if (reachable) {
166*c8dee2aaSAndroid Build Coastguard Worker fPlayer.addBreakpoint(humanReadableLine);
167*c8dee2aaSAndroid Build Coastguard Worker }
168*c8dee2aaSAndroid Build Coastguard Worker }
169*c8dee2aaSAndroid Build Coastguard Worker ImGui::PopStyleColor(4);
170*c8dee2aaSAndroid Build Coastguard Worker
171*c8dee2aaSAndroid Build Coastguard Worker // Show lines of code.
172*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableSetColumnIndex(1);
173*c8dee2aaSAndroid Build Coastguard Worker ImGui::Text("%s", fTrace->fSource[row].c_str());
174*c8dee2aaSAndroid Build Coastguard Worker }
175*c8dee2aaSAndroid Build Coastguard Worker }
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker if (fRefresh) {
178*c8dee2aaSAndroid Build Coastguard Worker int linesVisible = contentRect.y / ImGui::GetTextLineHeightWithSpacing();
179*c8dee2aaSAndroid Build Coastguard Worker int centerLine = (fPlayer.getCurrentLine() - 1) - (linesVisible / 2);
180*c8dee2aaSAndroid Build Coastguard Worker centerLine = std::max(0, centerLine);
181*c8dee2aaSAndroid Build Coastguard Worker ImGui::SetScrollY(clipper.ItemsHeight * centerLine);
182*c8dee2aaSAndroid Build Coastguard Worker fRefresh = false;
183*c8dee2aaSAndroid Build Coastguard Worker }
184*c8dee2aaSAndroid Build Coastguard Worker
185*c8dee2aaSAndroid Build Coastguard Worker ImGui::EndTable();
186*c8dee2aaSAndroid Build Coastguard Worker }
187*c8dee2aaSAndroid Build Coastguard Worker }
188*c8dee2aaSAndroid Build Coastguard Worker
showStackTraceTable()189*c8dee2aaSAndroid Build Coastguard Worker void SkSLDebuggerSlide::showStackTraceTable() {
190*c8dee2aaSAndroid Build Coastguard Worker constexpr ImGuiTableFlags kTableFlags =
191*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter |
192*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableFlags_BordersV | ImGuiTableFlags_NoHostExtendX;
193*c8dee2aaSAndroid Build Coastguard Worker constexpr ImGuiTableColumnFlags kColumnFlags =
194*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableColumnFlags_NoReorder | ImGuiTableColumnFlags_NoHide |
195*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableColumnFlags_NoSort;
196*c8dee2aaSAndroid Build Coastguard Worker
197*c8dee2aaSAndroid Build Coastguard Worker std::vector<int> callStack = fPlayer.getCallStack();
198*c8dee2aaSAndroid Build Coastguard Worker
199*c8dee2aaSAndroid Build Coastguard Worker ImVec2 contentRect = ImGui::GetContentRegionAvail();
200*c8dee2aaSAndroid Build Coastguard Worker ImVec2 stackViewSize = ImVec2(contentRect.x / 3.0f,
201*c8dee2aaSAndroid Build Coastguard Worker ImGui::GetTextLineHeightWithSpacing() * kNumTopRows);
202*c8dee2aaSAndroid Build Coastguard Worker if (ImGui::BeginTable("Call Stack", /*column=*/1, kTableFlags, stackViewSize)) {
203*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableSetupColumn("Stack", kColumnFlags);
204*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableHeadersRow();
205*c8dee2aaSAndroid Build Coastguard Worker
206*c8dee2aaSAndroid Build Coastguard Worker ImGuiListClipper clipper;
207*c8dee2aaSAndroid Build Coastguard Worker clipper.Begin(callStack.size());
208*c8dee2aaSAndroid Build Coastguard Worker while (clipper.Step()) {
209*c8dee2aaSAndroid Build Coastguard Worker for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) {
210*c8dee2aaSAndroid Build Coastguard Worker int funcIdx = callStack.rbegin()[row];
211*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(funcIdx >= 0 && (size_t)funcIdx < fTrace->fFuncInfo.size());
212*c8dee2aaSAndroid Build Coastguard Worker const SkSL::FunctionDebugInfo& funcInfo = fTrace->fFuncInfo[funcIdx];
213*c8dee2aaSAndroid Build Coastguard Worker
214*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableNextRow();
215*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableSetColumnIndex(0);
216*c8dee2aaSAndroid Build Coastguard Worker ImGui::Text("%s", funcInfo.name.c_str());
217*c8dee2aaSAndroid Build Coastguard Worker }
218*c8dee2aaSAndroid Build Coastguard Worker }
219*c8dee2aaSAndroid Build Coastguard Worker ImGui::EndTable();
220*c8dee2aaSAndroid Build Coastguard Worker }
221*c8dee2aaSAndroid Build Coastguard Worker
222*c8dee2aaSAndroid Build Coastguard Worker ImGui::SameLine();
223*c8dee2aaSAndroid Build Coastguard Worker }
224*c8dee2aaSAndroid Build Coastguard Worker
showVariableTable()225*c8dee2aaSAndroid Build Coastguard Worker void SkSLDebuggerSlide::showVariableTable() {
226*c8dee2aaSAndroid Build Coastguard Worker constexpr ImGuiTableFlags kTableFlags =
227*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter |
228*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable;
229*c8dee2aaSAndroid Build Coastguard Worker constexpr ImGuiTableColumnFlags kColumnFlags =
230*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableColumnFlags_NoReorder | ImGuiTableColumnFlags_NoHide |
231*c8dee2aaSAndroid Build Coastguard Worker ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthStretch;
232*c8dee2aaSAndroid Build Coastguard Worker
233*c8dee2aaSAndroid Build Coastguard Worker int frame = fPlayer.getStackDepth() - 1;
234*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkSL::SkSLDebugTracePlayer::VariableData> vars;
235*c8dee2aaSAndroid Build Coastguard Worker if (frame >= 0) {
236*c8dee2aaSAndroid Build Coastguard Worker vars = fPlayer.getLocalVariables(frame);
237*c8dee2aaSAndroid Build Coastguard Worker } else {
238*c8dee2aaSAndroid Build Coastguard Worker vars = fPlayer.getGlobalVariables();
239*c8dee2aaSAndroid Build Coastguard Worker }
240*c8dee2aaSAndroid Build Coastguard Worker ImVec2 varViewSize = ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * kNumTopRows);
241*c8dee2aaSAndroid Build Coastguard Worker if (ImGui::BeginTable("Variables", /*column=*/2, kTableFlags, varViewSize)) {
242*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableSetupColumn("Variable", kColumnFlags);
243*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableSetupColumn("Value", kColumnFlags);
244*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableHeadersRow();
245*c8dee2aaSAndroid Build Coastguard Worker if (!vars.empty()) {
246*c8dee2aaSAndroid Build Coastguard Worker ImGuiListClipper clipper;
247*c8dee2aaSAndroid Build Coastguard Worker clipper.Begin(vars.size());
248*c8dee2aaSAndroid Build Coastguard Worker while (clipper.Step()) {
249*c8dee2aaSAndroid Build Coastguard Worker for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) {
250*c8dee2aaSAndroid Build Coastguard Worker const SkSL::SkSLDebugTracePlayer::VariableData& var = vars.at(row);
251*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(var.fSlotIndex >= 0);
252*c8dee2aaSAndroid Build Coastguard Worker SkASSERT((size_t)var.fSlotIndex < fTrace->fSlotInfo.size());
253*c8dee2aaSAndroid Build Coastguard Worker const SkSL::SlotDebugInfo& slotInfo = fTrace->fSlotInfo[var.fSlotIndex];
254*c8dee2aaSAndroid Build Coastguard Worker
255*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableNextRow();
256*c8dee2aaSAndroid Build Coastguard Worker if (var.fDirty) {
257*c8dee2aaSAndroid Build Coastguard Worker // Highlight recently-changed variables.
258*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg1,
259*c8dee2aaSAndroid Build Coastguard Worker ImGui::GetColorU32(ImVec4{0.0f, 1.0f, 0.0f, 0.20f}));
260*c8dee2aaSAndroid Build Coastguard Worker }
261*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableSetColumnIndex(0);
262*c8dee2aaSAndroid Build Coastguard Worker ImGui::Text("%s%s", slotInfo.name.c_str(),
263*c8dee2aaSAndroid Build Coastguard Worker fTrace->getSlotComponentSuffix(var.fSlotIndex).c_str());
264*c8dee2aaSAndroid Build Coastguard Worker ImGui::TableSetColumnIndex(1);
265*c8dee2aaSAndroid Build Coastguard Worker ImGui::Text("%s",
266*c8dee2aaSAndroid Build Coastguard Worker fTrace->slotValueToString(var.fSlotIndex, var.fValue).c_str());
267*c8dee2aaSAndroid Build Coastguard Worker }
268*c8dee2aaSAndroid Build Coastguard Worker }
269*c8dee2aaSAndroid Build Coastguard Worker }
270*c8dee2aaSAndroid Build Coastguard Worker ImGui::EndTable();
271*c8dee2aaSAndroid Build Coastguard Worker }
272*c8dee2aaSAndroid Build Coastguard Worker }
273*c8dee2aaSAndroid Build Coastguard Worker
showRootGUI()274*c8dee2aaSAndroid Build Coastguard Worker void SkSLDebuggerSlide::showRootGUI() {
275*c8dee2aaSAndroid Build Coastguard Worker if (fTrace->fSource.empty()) {
276*c8dee2aaSAndroid Build Coastguard Worker this->showLoadTraceGUI();
277*c8dee2aaSAndroid Build Coastguard Worker return;
278*c8dee2aaSAndroid Build Coastguard Worker }
279*c8dee2aaSAndroid Build Coastguard Worker
280*c8dee2aaSAndroid Build Coastguard Worker this->showDebuggerGUI();
281*c8dee2aaSAndroid Build Coastguard Worker }
282*c8dee2aaSAndroid Build Coastguard Worker
draw(SkCanvas * canvas)283*c8dee2aaSAndroid Build Coastguard Worker void SkSLDebuggerSlide::draw(SkCanvas* canvas) {
284*c8dee2aaSAndroid Build Coastguard Worker canvas->clear(SK_ColorWHITE);
285*c8dee2aaSAndroid Build Coastguard Worker ImGui::Begin("Debugger", nullptr, ImGuiWindowFlags_AlwaysVerticalScrollbar);
286*c8dee2aaSAndroid Build Coastguard Worker this->showRootGUI();
287*c8dee2aaSAndroid Build Coastguard Worker ImGui::End();
288*c8dee2aaSAndroid Build Coastguard Worker }
289*c8dee2aaSAndroid Build Coastguard Worker
animate(double nanos)290*c8dee2aaSAndroid Build Coastguard Worker bool SkSLDebuggerSlide::animate(double nanos) {
291*c8dee2aaSAndroid Build Coastguard Worker return true;
292*c8dee2aaSAndroid Build Coastguard Worker }
293