• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 #include "src/sksl/tracing/SkSLDebugTracePriv.h"
8 
9 #include "include/core/SkStream.h"
10 #include "include/core/SkTypes.h"
11 #include "src/sksl/ir/SkSLType.h"
12 
13 #include <cstdio>
14 #include <cstring>
15 #include <sstream>
16 #include <string>
17 
18 namespace SkSL {
19 
getSlotComponentSuffix(int slotIndex) const20 std::string DebugTracePriv::getSlotComponentSuffix(int slotIndex) const {
21     const SkSL::SlotDebugInfo& slot = fSlotInfo[slotIndex];
22 
23     if (slot.rows > 1) {
24         return "["  + std::to_string(slot.componentIndex / slot.rows) +
25                "][" + std::to_string(slot.componentIndex % slot.rows) +
26                "]";
27     }
28     if (slot.columns > 1) {
29         switch (slot.componentIndex) {
30             case 0:  return ".x";
31             case 1:  return ".y";
32             case 2:  return ".z";
33             case 3:  return ".w";
34             default: return "[???]";
35         }
36     }
37     return {};
38 }
39 
interpretValueBits(int slotIndex,int32_t valueBits) const40 double DebugTracePriv::interpretValueBits(int slotIndex, int32_t valueBits) const {
41     SkASSERT(slotIndex >= 0);
42     SkASSERT((size_t)slotIndex < fSlotInfo.size());
43     switch (fSlotInfo[slotIndex].numberKind) {
44         case SkSL::Type::NumberKind::kUnsigned: {
45             uint32_t uintValue;
46             static_assert(sizeof(uintValue) == sizeof(valueBits));
47             memcpy(&uintValue, &valueBits, sizeof(uintValue));
48             return uintValue;
49         }
50         case SkSL::Type::NumberKind::kFloat: {
51             float floatValue;
52             static_assert(sizeof(floatValue) == sizeof(valueBits));
53             memcpy(&floatValue, &valueBits, sizeof(floatValue));
54             return floatValue;
55         }
56         default: {
57             return valueBits;
58         }
59     }
60 }
61 
slotValueToString(int slotIndex,double value) const62 std::string DebugTracePriv::slotValueToString(int slotIndex, double value) const {
63     SkASSERT(slotIndex >= 0);
64     SkASSERT((size_t)slotIndex < fSlotInfo.size());
65     switch (fSlotInfo[slotIndex].numberKind) {
66         case SkSL::Type::NumberKind::kBoolean: {
67             return value ? "true" : "false";
68         }
69         default: {
70             char buffer[32];
71             snprintf(buffer, std::size(buffer), "%.8g", value);
72             return buffer;
73         }
74     }
75 }
76 
getSlotValue(int slotIndex,int32_t valueBits) const77 std::string DebugTracePriv::getSlotValue(int slotIndex, int32_t valueBits) const {
78     return this->slotValueToString(slotIndex, this->interpretValueBits(slotIndex, valueBits));
79 }
80 
setTraceCoord(const SkIPoint & coord)81 void DebugTracePriv::setTraceCoord(const SkIPoint& coord) {
82     fTraceCoord = coord;
83 }
84 
setSource(const std::string & source)85 void DebugTracePriv::setSource(const std::string& source) {
86     fSource.clear();
87     std::stringstream stream{source};
88     while (stream.good()) {
89         fSource.push_back({});
90         std::getline(stream, fSource.back(), '\n');
91     }
92 }
93 
dump(SkWStream * o) const94 void DebugTracePriv::dump(SkWStream* o) const {
95     for (size_t index = 0; index < fSlotInfo.size(); ++index) {
96         const SlotDebugInfo& info = fSlotInfo[index];
97 
98         o->writeText("$");
99         o->writeDecAsText(index);
100         o->writeText(" = ");
101         o->writeText(info.name.c_str());
102         o->writeText(" (");
103         switch (info.numberKind) {
104             case Type::NumberKind::kFloat:      o->writeText("float"); break;
105             case Type::NumberKind::kSigned:     o->writeText("int"); break;
106             case Type::NumberKind::kUnsigned:   o->writeText("uint"); break;
107             case Type::NumberKind::kBoolean:    o->writeText("bool"); break;
108             case Type::NumberKind::kNonnumeric: o->writeText("???"); break;
109         }
110         if (info.rows * info.columns > 1) {
111             o->writeDecAsText(info.columns);
112             if (info.rows != 1) {
113                 o->writeText("x");
114                 o->writeDecAsText(info.rows);
115             }
116             o->writeText(" : ");
117             o->writeText("slot ");
118             o->writeDecAsText(info.componentIndex + 1);
119             o->writeText("/");
120             o->writeDecAsText(info.rows * info.columns);
121         }
122         o->writeText(", L");
123         o->writeDecAsText(info.line);
124         o->writeText(")");
125         o->newline();
126     }
127 
128     for (size_t index = 0; index < fFuncInfo.size(); ++index) {
129         const FunctionDebugInfo& info = fFuncInfo[index];
130 
131         o->writeText("F");
132         o->writeDecAsText(index);
133         o->writeText(" = ");
134         o->writeText(info.name.c_str());
135         o->newline();
136     }
137 
138     o->newline();
139 
140     if (!fTraceInfo.empty()) {
141         std::string indent = "";
142         for (const SkSL::TraceInfo& traceInfo : fTraceInfo) {
143             int data0 = traceInfo.data[0];
144             int data1 = traceInfo.data[1];
145             switch (traceInfo.op) {
146                 case SkSL::TraceInfo::Op::kLine:
147                     o->writeText(indent.c_str());
148                     o->writeText("line ");
149                     o->writeDecAsText(data0);
150                     break;
151 
152                 case SkSL::TraceInfo::Op::kVar: {
153                     const SlotDebugInfo& slot = fSlotInfo[data0];
154                     o->writeText(indent.c_str());
155                     o->writeText(slot.name.c_str());
156                     o->writeText(this->getSlotComponentSuffix(data0).c_str());
157                     o->writeText(" = ");
158                     o->writeText(this->getSlotValue(data0, data1).c_str());
159                     break;
160                 }
161                 case SkSL::TraceInfo::Op::kEnter:
162                     o->writeText(indent.c_str());
163                     o->writeText("enter ");
164                     o->writeText(fFuncInfo[data0].name.c_str());
165                     indent += "  ";
166                     break;
167 
168                 case SkSL::TraceInfo::Op::kExit:
169                     indent.resize(indent.size() - 2);
170                     o->writeText(indent.c_str());
171                     o->writeText("exit ");
172                     o->writeText(fFuncInfo[data0].name.c_str());
173                     break;
174 
175                 case SkSL::TraceInfo::Op::kScope:
176                     for (int delta = data0; delta < 0; ++delta) {
177                         indent.pop_back();
178                     }
179                     o->writeText(indent.c_str());
180                     o->writeText("scope ");
181                     o->writeText((data0 >= 0) ? "+" : "");
182                     o->writeDecAsText(data0);
183                     for (int delta = data0; delta > 0; --delta) {
184                         indent.push_back(' ');
185                     }
186                     break;
187             }
188             o->newline();
189         }
190     }
191 }
192 
193 }  // namespace SkSL
194