blob: 72708644a516778d7073bb48149590e57bde9db1 [file] [log] [blame]
joshualitt27a48dc2016-01-08 07:19:47 -08001/*
2 * Copyright 2016 Google Inc.
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#ifndef GrAuditTrail_DEFINED
9#define GrAuditTrail_DEFINED
10
joshualitt5651ee62016-01-11 10:39:11 -080011#include "GrConfig.h"
joshualitt086cee12016-01-12 06:45:24 -080012#include "SkRect.h"
joshualitt27a48dc2016-01-08 07:19:47 -080013#include "SkString.h"
14#include "SkTArray.h"
joshualitt18d6b752016-02-26 08:07:50 -080015#include "SkTHash.h"
16
17class GrBatch;
joshualitt27a48dc2016-01-08 07:19:47 -080018
19/*
20 * GrAuditTrail collects a list of draw ops, detailed information about those ops, and can dump them
21 * to json.
ethannicholasc85d9fb2016-02-18 13:45:39 -080022 *
23 * Capturing this information is expensive and consumes a lot of memory, therefore it is important
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 information has been dealt
26 * with, be sure to call reset(), or the log will simply keep growing.
joshualitt27a48dc2016-01-08 07:19:47 -080027 */
28class GrAuditTrail {
29public:
ethannicholasc85d9fb2016-02-18 13:45:39 -080030 GrAuditTrail()
joshualitt08fc8072016-02-29 06:32:24 -080031 : fEnabled(false)
32 , fUniqueID(0) {}
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 };
joshualitt87a721b2016-01-12 12:59:28 -080052
ethannicholasc85d9fb2016-02-18 13:45:39 -080053 class AutoEnable {
54 public:
55 AutoEnable(GrAuditTrail* auditTrail)
56 : fAuditTrail(auditTrail) {
57 SkASSERT(!fAuditTrail->isEnabled());
58 fAuditTrail->setEnabled(true);
59 }
60
61 ~AutoEnable() {
62 SkASSERT(fAuditTrail->isEnabled());
63 fAuditTrail->setEnabled(false);
64 }
65
66 private:
67 GrAuditTrail* fAuditTrail;
68 };
69
joshualitt18d6b752016-02-26 08:07:50 -080070 class AutoManageBatchList {
71 public:
72 AutoManageBatchList(GrAuditTrail* auditTrail)
73 : fAutoEnable(auditTrail)
74 , fAuditTrail(auditTrail) {
75 }
76
77 ~AutoManageBatchList() {
78 fAuditTrail->fullReset();
79 }
80
81 private:
82 AutoEnable fAutoEnable;
83 GrAuditTrail* fAuditTrail;
84 };
85
joshualitt08fc8072016-02-29 06:32:24 -080086 void pushFrame(const char* name) {
87 SkASSERT(fEnabled);
88 Frame* frame = new Frame;
89 fEvents.emplace_back(frame);
90 if (fStack.empty()) {
91 fFrames.push_back(frame);
92 } else {
93 fStack.back()->fChildren.push_back(frame);
joshualitt87a721b2016-01-12 12:59:28 -080094 }
95
joshualitt08fc8072016-02-29 06:32:24 -080096 frame->fUniqueID = fUniqueID++;
97 frame->fName = name;
98 fStack.push_back(frame);
99 }
joshualitt27a48dc2016-01-08 07:19:47 -0800100
joshualitt08fc8072016-02-29 06:32:24 -0800101 void popFrame() {
102 SkASSERT(fEnabled);
103 fStack.pop_back();
104 }
joshualitt87a721b2016-01-12 12:59:28 -0800105
106 void addBatch(const char* name, const SkRect& bounds) {
joshualitt08fc8072016-02-29 06:32:24 -0800107 SkASSERT(fEnabled && !fStack.empty());
joshualitt11fae872016-01-14 10:58:07 -0800108 Batch* batch = new Batch;
joshualitt08fc8072016-02-29 06:32:24 -0800109 fEvents.emplace_back(batch);
110 fStack.back()->fChildren.push_back(batch);
joshualitt11fae872016-01-14 10:58:07 -0800111 batch->fName = name;
112 batch->fBounds = bounds;
joshualitt18d6b752016-02-26 08:07:50 -0800113 fCurrentBatch = batch;
joshualitt086cee12016-01-12 06:45:24 -0800114 }
115
joshualitt18d6b752016-02-26 08:07:50 -0800116 void batchingResultCombined(GrBatch* combiner);
117
118 void batchingResultNew(GrBatch* batch);
119
joshualitt08fc8072016-02-29 06:32:24 -0800120 SkString toJson(bool batchList = false, bool prettyPrint = false) const;
joshualitt27a48dc2016-01-08 07:19:47 -0800121
ethannicholasc85d9fb2016-02-18 13:45:39 -0800122 bool isEnabled() { return fEnabled; }
123 void setEnabled(bool enabled) { fEnabled = enabled; }
124
joshualitt08fc8072016-02-29 06:32:24 -0800125 void reset() {
126 SkASSERT(fEnabled && fStack.empty());
127 fFrames.reset();
128 }
129
130 void resetBatchList() {
131 SkASSERT(fEnabled);
132 fBatches.reset();
133 fIDLookup.reset();
134 }
joshualitt18d6b752016-02-26 08:07:50 -0800135
136 void fullReset() {
137 SkASSERT(fEnabled);
joshualitt08fc8072016-02-29 06:32:24 -0800138 this->reset();
139 this->resetBatchList();
140 fEvents.reset(); // must be last, frees all of the memory
joshualitt18d6b752016-02-26 08:07:50 -0800141 }
joshualitt27a48dc2016-01-08 07:19:47 -0800142
143private:
joshualitt11fae872016-01-14 10:58:07 -0800144 // TODO if performance becomes an issue, we can move to using SkVarAlloc
joshualitt08fc8072016-02-29 06:32:24 -0800145 struct Event {
146 virtual ~Event() {}
147 virtual SkString toJson() const=0;
joshualitt9b48a6e2016-02-29 05:20:38 -0800148
joshualitt08fc8072016-02-29 06:32:24 -0800149 const char* fName;
150 uint64_t fUniqueID;
joshualitt9b48a6e2016-02-29 05:20:38 -0800151 };
joshualitt08fc8072016-02-29 06:32:24 -0800152
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;
joshualitt11fae872016-01-14 10:58:07 -0800164
joshualitt18d6b752016-02-26 08:07:50 -0800165 template <typename T>
166 static void JsonifyTArray(SkString* json, const char* name, const T& array,
joshualittadab5a22016-02-18 05:04:39 -0800167 bool addComma);
joshualitt11fae872016-01-14 10:58:07 -0800168
joshualitt08fc8072016-02-29 06:32:24 -0800169 // We store both an array of frames, and also a flatter array just of the batches
joshualitt9b48a6e2016-02-29 05:20:38 -0800170 bool fEnabled;
joshualitt08fc8072016-02-29 06:32:24 -0800171 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;
joshualitt27a48dc2016-01-08 07:19:47 -0800179};
180
ethannicholasc85d9fb2016-02-18 13:45:39 -0800181#define GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, invoke, ...) \
182 if (audit_trail->isEnabled()) { \
183 audit_trail->invoke(__VA_ARGS__); \
joshualitt5651ee62016-01-11 10:39:11 -0800184 }
185
joshualitt87a721b2016-01-12 12:59:28 -0800186#define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename) \
joshualitt08fc8072016-02-29 06:32:24 -0800187 GrAuditTrail::AutoFrame SK_MACRO_APPEND_LINE(auto_frame)(audit_trail, framename);
joshualitt5651ee62016-01-11 10:39:11 -0800188
189#define GR_AUDIT_TRAIL_RESET(audit_trail) \
joshualitt08fc8072016-02-29 06:32:24 -0800190 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, reset);
joshualitt5651ee62016-01-11 10:39:11 -0800191
joshualitt086cee12016-01-12 06:45:24 -0800192#define GR_AUDIT_TRAIL_ADDBATCH(audit_trail, batchname, bounds) \
ethannicholasc85d9fb2016-02-18 13:45:39 -0800193 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addBatch, batchname, bounds);
joshualitt086cee12016-01-12 06:45:24 -0800194
joshualitt18d6b752016-02-26 08:07:50 -0800195#define GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(audit_trail, combiner) \
196 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, batchingResultCombined, combiner);
197
198#define GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(audit_trail, batch) \
199 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, batchingResultNew, batch);
200
joshualitt27a48dc2016-01-08 07:19:47 -0800201#endif