Home | History | Annotate | Download | only in private
      1 /*
      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 
     11 #include "GrConfig.h"
     12 #include "SkRect.h"
     13 #include "SkString.h"
     14 #include "SkTArray.h"
     15 
     16 /*
     17  * GrAuditTrail collects a list of draw ops, detailed information about those ops, and can dump them
     18  * to json.
     19  *
     20  * Capturing this information is expensive and consumes a lot of memory, therefore it is important
     21  * to enable auditing only when required and disable it promptly. The AutoEnable class helps to
     22  * ensure that the audit trail is disabled in a timely fashion. Once the information has been dealt
     23  * with, be sure to call reset(), or the log will simply keep growing.
     24  */
     25 class GrAuditTrail {
     26 public:
     27     GrAuditTrail()
     28     : fEnabled(false)
     29     , fUniqueID(0) {}
     30 
     31     class AutoFrame {
     32     public:
     33         AutoFrame(GrAuditTrail* auditTrail, const char* name)
     34             : fAuditTrail(auditTrail) {
     35             if (fAuditTrail->fEnabled) {
     36                 fAuditTrail->pushFrame(name);
     37             }
     38         }
     39 
     40         ~AutoFrame() {
     41             if (fAuditTrail->fEnabled) {
     42                 fAuditTrail->popFrame();
     43             }
     44         }
     45 
     46     private:
     47         GrAuditTrail* fAuditTrail;
     48     };
     49 
     50     class AutoEnable {
     51     public:
     52         AutoEnable(GrAuditTrail* auditTrail)
     53             : fAuditTrail(auditTrail) {
     54             SkASSERT(!fAuditTrail->isEnabled());
     55             fAuditTrail->setEnabled(true);
     56         }
     57 
     58         ~AutoEnable() {
     59             SkASSERT(fAuditTrail->isEnabled());
     60             fAuditTrail->setEnabled(false);
     61         }
     62 
     63     private:
     64         GrAuditTrail* fAuditTrail;
     65     };
     66 
     67     void pushFrame(const char* name) {
     68         SkASSERT(fEnabled);
     69         Frame* frame = new Frame;
     70         if (fStack.empty()) {
     71             fFrames.emplace_back(frame);
     72         } else {
     73             fStack.back()->fChildren.emplace_back(frame);
     74         }
     75 
     76         frame->fUniqueID = fUniqueID++;
     77         frame->fName = name;
     78         fStack.push_back(frame);
     79     }
     80 
     81     void popFrame() {
     82         SkASSERT(fEnabled);
     83         fStack.pop_back();
     84     }
     85 
     86     void addBatch(const char* name, const SkRect& bounds) {
     87         SkASSERT(fEnabled && !fStack.empty());
     88         Batch* batch = new Batch;
     89         fStack.back()->fChildren.emplace_back(batch);
     90         batch->fName = name;
     91         batch->fBounds = bounds;
     92     }
     93 
     94     SkString toJson(bool prettyPrint = false) const;
     95 
     96     bool isEnabled() { return fEnabled; }
     97     void setEnabled(bool enabled) { fEnabled = enabled; }
     98 
     99     void reset() { SkASSERT(fEnabled && fStack.empty()); fFrames.reset(); }
    100 
    101 private:
    102     // TODO if performance becomes an issue, we can move to using SkVarAlloc
    103     struct Event {
    104         virtual ~Event() {}
    105         virtual SkString toJson() const=0;
    106 
    107         const char* fName;
    108         uint64_t fUniqueID;
    109     };
    110 
    111     typedef SkTArray<SkAutoTDelete<Event>, true> FrameArray;
    112     struct Frame : public Event {
    113         SkString toJson() const override;
    114         FrameArray fChildren;
    115     };
    116 
    117     struct Batch : public Event {
    118         SkString toJson() const override;
    119         SkRect fBounds;
    120     };
    121 
    122     static void JsonifyTArray(SkString* json, const char* name, const FrameArray& array,
    123                               bool addComma);
    124 
    125     bool fEnabled;
    126     FrameArray fFrames;
    127     SkTArray<Frame*> fStack;
    128     uint64_t fUniqueID;
    129 };
    130 
    131 #define GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, invoke, ...) \
    132     if (audit_trail->isEnabled()) {                           \
    133         audit_trail->invoke(__VA_ARGS__);                     \
    134     }
    135 
    136 #define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename) \
    137     GrAuditTrail::AutoFrame SK_MACRO_APPEND_LINE(auto_frame)(audit_trail, framename);
    138 
    139 #define GR_AUDIT_TRAIL_RESET(audit_trail) \
    140     GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, reset);
    141 
    142 #define GR_AUDIT_TRAIL_ADDBATCH(audit_trail, batchname, bounds) \
    143     GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addBatch, batchname, bounds);
    144 
    145 #endif
    146