OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef GrAuditTrail_DEFINED | 8 #ifndef GrAuditTrail_DEFINED |
9 #define GrAuditTrail_DEFINED | 9 #define GrAuditTrail_DEFINED |
10 | 10 |
(...skipping 10 matching lines...) Expand all Loading... |
21 * to json. | 21 * to json. |
22 * | 22 * |
23 * Capturing this information is expensive and consumes a lot of memory, therefo
re it is important | 23 * Capturing this information is expensive and consumes a lot of memory, therefo
re it is important |
24 * to enable auditing only when required and disable it promptly. The AutoEnable
class helps to | 24 * to enable auditing only when required and disable it promptly. The AutoEnable
class helps to |
25 * ensure that the audit trail is disabled in a timely fashion. Once the informa
tion has been dealt | 25 * ensure that the audit trail is disabled in a timely fashion. Once the informa
tion has been dealt |
26 * with, be sure to call reset(), or the log will simply keep growing. | 26 * with, be sure to call reset(), or the log will simply keep growing. |
27 */ | 27 */ |
28 class GrAuditTrail { | 28 class GrAuditTrail { |
29 public: | 29 public: |
30 GrAuditTrail() | 30 GrAuditTrail() |
31 : fEnabled(false) | 31 : fClientID(kGrAuditTrailInvalidID) |
32 , fUniqueID(0) {} | 32 , fEnabled(false) {} |
33 | |
34 class AutoFrame { | |
35 public: | |
36 AutoFrame(GrAuditTrail* auditTrail, const char* name) | |
37 : fAuditTrail(auditTrail) { | |
38 if (fAuditTrail->fEnabled) { | |
39 fAuditTrail->pushFrame(name); | |
40 } | |
41 } | |
42 | |
43 ~AutoFrame() { | |
44 if (fAuditTrail->fEnabled) { | |
45 fAuditTrail->popFrame(); | |
46 } | |
47 } | |
48 | |
49 private: | |
50 GrAuditTrail* fAuditTrail; | |
51 }; | |
52 | 33 |
53 class AutoEnable { | 34 class AutoEnable { |
54 public: | 35 public: |
55 AutoEnable(GrAuditTrail* auditTrail) | 36 AutoEnable(GrAuditTrail* auditTrail) |
56 : fAuditTrail(auditTrail) { | 37 : fAuditTrail(auditTrail) { |
57 SkASSERT(!fAuditTrail->isEnabled()); | 38 SkASSERT(!fAuditTrail->isEnabled()); |
58 fAuditTrail->setEnabled(true); | 39 fAuditTrail->setEnabled(true); |
59 } | 40 } |
60 | 41 |
61 ~AutoEnable() { | 42 ~AutoEnable() { |
(...skipping 14 matching lines...) Expand all Loading... |
76 | 57 |
77 ~AutoManageBatchList() { | 58 ~AutoManageBatchList() { |
78 fAuditTrail->fullReset(); | 59 fAuditTrail->fullReset(); |
79 } | 60 } |
80 | 61 |
81 private: | 62 private: |
82 AutoEnable fAutoEnable; | 63 AutoEnable fAutoEnable; |
83 GrAuditTrail* fAuditTrail; | 64 GrAuditTrail* fAuditTrail; |
84 }; | 65 }; |
85 | 66 |
86 void pushFrame(const char* name) { | 67 class AutoCollectBatches { |
87 SkASSERT(fEnabled); | 68 public: |
88 Frame* frame = new Frame; | 69 AutoCollectBatches(GrAuditTrail* auditTrail, int clientID) |
89 fEvents.emplace_back(frame); | 70 : fAutoEnable(auditTrail) |
90 if (fStack.empty()) { | 71 , fAuditTrail(auditTrail) { |
91 fFrames.push_back(frame); | 72 fAuditTrail->setClientID(clientID); |
92 } else { | |
93 fStack.back()->fChildren.push_back(frame); | |
94 } | 73 } |
95 | 74 |
96 frame->fUniqueID = fUniqueID++; | 75 ~AutoCollectBatches() { fAuditTrail->setClientID(kGrAuditTrailInvalidID)
; } |
97 frame->fName = name; | |
98 fStack.push_back(frame); | |
99 } | |
100 | 76 |
101 void popFrame() { | 77 private: |
102 SkASSERT(fEnabled); | 78 AutoEnable fAutoEnable; |
103 fStack.pop_back(); | 79 GrAuditTrail* fAuditTrail; |
104 } | 80 }; |
105 | 81 |
106 void addBatch(const char* name, const SkRect& bounds) { | 82 void addBatch(const char* name, const SkRect& bounds) { |
107 SkASSERT(fEnabled && !fStack.empty()); | 83 SkASSERT(fEnabled); |
108 Batch* batch = new Batch; | 84 Batch* batch = new Batch; |
109 fEvents.emplace_back(batch); | 85 fBatchPool.emplace_back(batch); |
110 fStack.back()->fChildren.push_back(batch); | |
111 batch->fName = name; | 86 batch->fName = name; |
112 batch->fBounds = bounds; | 87 batch->fBounds = bounds; |
| 88 batch->fClientID = kGrAuditTrailInvalidID; |
| 89 batch->fBatchListID = kGrAuditTrailInvalidID; |
| 90 batch->fChildID = kGrAuditTrailInvalidID; |
113 fCurrentBatch = batch; | 91 fCurrentBatch = batch; |
| 92 |
| 93 if (fClientID != kGrAuditTrailInvalidID) { |
| 94 batch->fClientID = fClientID; |
| 95 Batches** batchesLookup = fClientIDLookup.find(fClientID); |
| 96 Batches* batches = nullptr; |
| 97 if (!batchesLookup) { |
| 98 batches = new Batches; |
| 99 fClientIDLookup.set(fClientID, batches); |
| 100 } else { |
| 101 batches = *batchesLookup; |
| 102 } |
| 103 |
| 104 batches->push_back(fCurrentBatch); |
| 105 } |
114 } | 106 } |
115 | 107 |
116 void batchingResultCombined(GrBatch* combiner); | 108 void batchingResultCombined(GrBatch* combiner); |
117 | 109 |
118 void batchingResultNew(GrBatch* batch); | 110 void batchingResultNew(GrBatch* batch); |
119 | 111 |
120 SkString toJson(bool batchList = false, bool prettyPrint = false) const; | 112 // Because batching is heavily dependent on sequence of draw calls, these ca
lls will only |
| 113 // produce valid information for the given draw sequence which preceeded the
m. |
| 114 // Specifically, future draw calls may change the batching and thus would in
validate |
| 115 // the json. What this means is that for some sequence of draw calls N, the
below toJson |
| 116 // calls will only produce JSON which reflects N draw calls. This JSON may
or may not be |
| 117 // accurate for N + 1 or N - 1 draws depending on the actual batching algori
thm used. |
| 118 SkString toJson(bool prettyPrint = false) const; |
| 119 |
| 120 // returns a json string of all of the batches associated with a given clien
t id |
| 121 SkString toJson(int clientID, bool prettyPrint = false) const; |
121 | 122 |
122 bool isEnabled() { return fEnabled; } | 123 bool isEnabled() { return fEnabled; } |
123 void setEnabled(bool enabled) { fEnabled = enabled; } | 124 void setEnabled(bool enabled) { fEnabled = enabled; } |
124 | 125 |
125 void reset() { | 126 void setClientID(int clientID) { fClientID = clientID; } |
126 SkASSERT(fEnabled && fStack.empty()); | |
127 fFrames.reset(); | |
128 } | |
129 | |
130 void resetBatchList() { | |
131 SkASSERT(fEnabled); | |
132 fBatches.reset(); | |
133 fIDLookup.reset(); | |
134 } | |
135 | 127 |
136 void fullReset() { | 128 void fullReset() { |
137 SkASSERT(fEnabled); | 129 SkASSERT(fEnabled); |
138 this->reset(); | 130 fBatchList.reset(); |
139 this->resetBatchList(); | 131 fIDLookup.reset(); |
140 fEvents.reset(); // must be last, frees all of the memory | 132 // free all client batches |
| 133 fClientIDLookup.foreach([](const int&, Batches** batches) { delete *batc
hes; }); |
| 134 fClientIDLookup.reset(); |
| 135 fBatchPool.reset(); // must be last, frees all of the memory |
141 } | 136 } |
142 | 137 |
| 138 static const int kGrAuditTrailInvalidID; |
| 139 |
143 private: | 140 private: |
144 // TODO if performance becomes an issue, we can move to using SkVarAlloc | 141 // TODO if performance becomes an issue, we can move to using SkVarAlloc |
145 struct Event { | 142 struct Batch { |
146 virtual ~Event() {} | 143 SkString toJson() const; |
147 virtual SkString toJson() const=0; | 144 SkString fName; |
| 145 SkRect fBounds; |
| 146 int fClientID; |
| 147 int fBatchListID; |
| 148 int fChildID; |
| 149 }; |
| 150 typedef SkTArray<SkAutoTDelete<Batch>, true> BatchPool; |
148 | 151 |
149 const char* fName; | 152 typedef SkTArray<Batch*> Batches; |
150 uint64_t fUniqueID; | 153 |
| 154 struct BatchNode { |
| 155 SkString toJson() const; |
| 156 SkRect fBounds; |
| 157 Batches fChildren; |
151 }; | 158 }; |
152 | 159 typedef SkTArray<SkAutoTDelete<BatchNode>, true> BatchList; |
153 struct Frame : public Event { | |
154 SkString toJson() const override; | |
155 SkTArray<Event*> fChildren; | |
156 }; | |
157 | |
158 struct Batch : public Event { | |
159 SkString toJson() const override; | |
160 SkRect fBounds; | |
161 SkTArray<Batch*> fChildren; | |
162 }; | |
163 typedef SkTArray<SkAutoTDelete<Event>, true> EventArrayPool; | |
164 | 160 |
165 template <typename T> | 161 template <typename T> |
166 static void JsonifyTArray(SkString* json, const char* name, const T& array, | 162 static void JsonifyTArray(SkString* json, const char* name, const T& array, |
167 bool addComma); | 163 bool addComma); |
168 | 164 |
169 // We store both an array of frames, and also a flatter array just of the ba
tches | 165 Batch* fCurrentBatch; |
| 166 BatchPool fBatchPool; |
| 167 SkTHashMap<GrBatch*, int> fIDLookup; |
| 168 SkTHashMap<int, Batches*> fClientIDLookup; |
| 169 BatchList fBatchList; |
| 170 |
| 171 // The client cas pass in an optional client ID which we will use to mark th
e batches |
| 172 int fClientID; |
170 bool fEnabled; | 173 bool fEnabled; |
171 EventArrayPool fEvents; // manages the lifetimes of the events | |
172 SkTArray<Event*> fFrames; | |
173 SkTArray<Frame*> fStack; | |
174 uint64_t fUniqueID; | |
175 | |
176 Batch* fCurrentBatch; | |
177 SkTHashMap<GrBatch*, int> fIDLookup; | |
178 SkTArray<Batch*> fBatches; | |
179 }; | 174 }; |
180 | 175 |
181 #define GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, invoke, ...) \ | 176 #define GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, invoke, ...) \ |
182 if (audit_trail->isEnabled()) { \ | 177 if (audit_trail->isEnabled()) { \ |
183 audit_trail->invoke(__VA_ARGS__); \ | 178 audit_trail->invoke(__VA_ARGS__); \ |
184 } | 179 } |
185 | 180 |
186 #define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename) \ | 181 #define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename) \ |
187 GrAuditTrail::AutoFrame SK_MACRO_APPEND_LINE(auto_frame)(audit_trail, framen
ame); | 182 // TODO fill out the frame stuff |
| 183 //GrAuditTrail::AutoFrame SK_MACRO_APPEND_LINE(auto_frame)(audit_trail, fram
ename); |
188 | 184 |
189 #define GR_AUDIT_TRAIL_RESET(audit_trail) \ | 185 #define GR_AUDIT_TRAIL_RESET(audit_trail) \ |
190 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, reset); | 186 //GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, reset); |
191 | 187 |
192 #define GR_AUDIT_TRAIL_ADDBATCH(audit_trail, batchname, bounds) \ | 188 #define GR_AUDIT_TRAIL_ADDBATCH(audit_trail, batchname, bounds) \ |
193 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addBatch, batchname, bounds); | 189 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addBatch, batchname, bounds); |
194 | 190 |
195 #define GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(audit_trail, combiner) \ | 191 #define GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(audit_trail, combiner) \ |
196 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, batchingResultCombined, combiner); | 192 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, batchingResultCombined, combiner); |
197 | 193 |
198 #define GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(audit_trail, batch) \ | 194 #define GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(audit_trail, batch) \ |
199 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, batchingResultNew, batch); | 195 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, batchingResultNew, batch); |
200 | 196 |
201 #endif | 197 #endif |
OLD | NEW |