LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu - GrAuditTrail.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 190 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 21 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "GrAuditTrail.h"
       9             : #include "ops/GrOp.h"
      10             : 
      11             : const int GrAuditTrail::kGrAuditTrailInvalidID = -1;
      12             : 
      13           0 : void GrAuditTrail::addOp(const GrOp* op,
      14             :                          GrGpuResource::UniqueID resourceID,
      15             :                          GrRenderTargetProxy::UniqueID proxyID) {
      16           0 :     SkASSERT(fEnabled);
      17           0 :     Op* auditOp = new Op;
      18           0 :     fOpPool.emplace_back(auditOp);
      19           0 :     auditOp->fName = op->name();
      20           0 :     auditOp->fBounds = op->bounds();
      21           0 :     auditOp->fClientID = kGrAuditTrailInvalidID;
      22           0 :     auditOp->fOpListID = kGrAuditTrailInvalidID;
      23           0 :     auditOp->fChildID = kGrAuditTrailInvalidID;
      24             : 
      25             :     // consume the current stack trace if any
      26           0 :     auditOp->fStackTrace = fCurrentStackTrace;
      27           0 :     fCurrentStackTrace.reset();
      28             : 
      29           0 :     if (fClientID != kGrAuditTrailInvalidID) {
      30           0 :         auditOp->fClientID = fClientID;
      31           0 :         Ops** opsLookup = fClientIDLookup.find(fClientID);
      32           0 :         Ops* ops = nullptr;
      33           0 :         if (!opsLookup) {
      34           0 :             ops = new Ops;
      35           0 :             fClientIDLookup.set(fClientID, ops);
      36             :         } else {
      37           0 :             ops = *opsLookup;
      38             :         }
      39             : 
      40           0 :         ops->push_back(auditOp);
      41             :     }
      42             : 
      43             :     // Our algorithm doesn't bother to reorder inside of an OpNode so the ChildID will start at 0
      44           0 :     auditOp->fOpListID = fOpList.count();
      45           0 :     auditOp->fChildID = 0;
      46             : 
      47             :     // We use the op pointer as a key to find the OpNode we are 'glomming' ops onto
      48           0 :     fIDLookup.set(op->uniqueID(), auditOp->fOpListID);
      49           0 :     OpNode* opNode = new OpNode(resourceID, proxyID);
      50           0 :     opNode->fBounds = op->bounds();
      51           0 :     opNode->fChildren.push_back(auditOp);
      52           0 :     fOpList.emplace_back(opNode);
      53           0 : }
      54             : 
      55           0 : void GrAuditTrail::opsCombined(const GrOp* consumer, const GrOp* consumed) {
      56             :     // Look up the op we are going to glom onto
      57           0 :     int* indexPtr = fIDLookup.find(consumer->uniqueID());
      58           0 :     SkASSERT(indexPtr);
      59           0 :     int index = *indexPtr;
      60           0 :     SkASSERT(index < fOpList.count() && fOpList[index]);
      61           0 :     OpNode& consumerOp = *fOpList[index];
      62             : 
      63             :     // Look up the op which will be glommed
      64           0 :     int* consumedPtr = fIDLookup.find(consumed->uniqueID());
      65           0 :     SkASSERT(consumedPtr);
      66           0 :     int consumedIndex = *consumedPtr;
      67           0 :     SkASSERT(consumedIndex < fOpList.count() && fOpList[consumedIndex]);
      68           0 :     OpNode& consumedOp = *fOpList[consumedIndex];
      69             : 
      70             :     // steal all of consumed's ops
      71           0 :     for (int i = 0; i < consumedOp.fChildren.count(); i++) {
      72           0 :         Op* childOp = consumedOp.fChildren[i];
      73             : 
      74             :         // set the ids for the child op
      75           0 :         childOp->fOpListID = index;
      76           0 :         childOp->fChildID = consumerOp.fChildren.count();
      77           0 :         consumerOp.fChildren.push_back(childOp);
      78             :     }
      79             : 
      80             :     // Update the bounds for the combineWith node
      81           0 :     consumerOp.fBounds = consumer->bounds();
      82             : 
      83             :     // remove the old node from our opList and clear the combinee's lookup
      84             :     // NOTE: because we can't change the shape of the oplist, we use a sentinel
      85           0 :     fOpList[consumedIndex].reset(nullptr);
      86           0 :     fIDLookup.remove(consumed->uniqueID());
      87           0 : }
      88             : 
      89           0 : void GrAuditTrail::copyOutFromOpList(OpInfo* outOpInfo, int opListID) {
      90           0 :     SkASSERT(opListID < fOpList.count());
      91           0 :     const OpNode* bn = fOpList[opListID].get();
      92           0 :     SkASSERT(bn);
      93           0 :     outOpInfo->fBounds = bn->fBounds;
      94           0 :     outOpInfo->fResourceUniqueID = bn->fResourceUniqueID;
      95           0 :     outOpInfo->fProxyUniqueID    = bn->fProxyUniqueID;
      96           0 :     for (int j = 0; j < bn->fChildren.count(); j++) {
      97           0 :         OpInfo::Op& outOp = outOpInfo->fOps.push_back();
      98           0 :         const Op* currentOp = bn->fChildren[j];
      99           0 :         outOp.fBounds = currentOp->fBounds;
     100           0 :         outOp.fClientID = currentOp->fClientID;
     101             :     }
     102           0 : }
     103             : 
     104           0 : void GrAuditTrail::getBoundsByClientID(SkTArray<OpInfo>* outInfo, int clientID) {
     105           0 :     Ops** opsLookup = fClientIDLookup.find(clientID);
     106           0 :     if (opsLookup) {
     107             :         // We track which oplistID we're currently looking at.  If it changes, then we need to push
     108             :         // back a new op info struct.  We happen to know that ops are in sequential order in the
     109             :         // oplist, otherwise we'd have to do more bookkeeping
     110           0 :         int currentOpListID = kGrAuditTrailInvalidID;
     111           0 :         for (int i = 0; i < (*opsLookup)->count(); i++) {
     112           0 :             const Op* op = (**opsLookup)[i];
     113             : 
     114             :             // Because we will copy out all of the ops associated with a given op list id everytime
     115             :             // the id changes, we only have to update our struct when the id changes.
     116           0 :             if (kGrAuditTrailInvalidID == currentOpListID || op->fOpListID != currentOpListID) {
     117           0 :                 OpInfo& outOpInfo = outInfo->push_back();
     118             : 
     119             :                 // copy out all of the ops so the client can display them even if they have a
     120             :                 // different clientID
     121           0 :                 this->copyOutFromOpList(&outOpInfo, op->fOpListID);
     122             :             }
     123             :         }
     124             :     }
     125           0 : }
     126             : 
     127           0 : void GrAuditTrail::getBoundsByOpListID(OpInfo* outInfo, int opListID) {
     128           0 :     this->copyOutFromOpList(outInfo, opListID);
     129           0 : }
     130             : 
     131           0 : void GrAuditTrail::fullReset() {
     132           0 :     SkASSERT(fEnabled);
     133           0 :     fOpList.reset();
     134           0 :     fIDLookup.reset();
     135             :     // free all client ops
     136           0 :     fClientIDLookup.foreach ([](const int&, Ops** ops) { delete *ops; });
     137           0 :     fClientIDLookup.reset();
     138           0 :     fOpPool.reset();  // must be last, frees all of the memory
     139           0 : }
     140             : 
     141             : template <typename T>
     142           0 : void GrAuditTrail::JsonifyTArray(SkString* json, const char* name, const T& array,
     143             :                                  bool addComma) {
     144           0 :     if (array.count()) {
     145           0 :         if (addComma) {
     146           0 :             json->appendf(",");
     147             :         }
     148           0 :         json->appendf("\"%s\": [", name);
     149           0 :         const char* separator = "";
     150           0 :         for (int i = 0; i < array.count(); i++) {
     151             :             // Handle sentinel nullptrs
     152           0 :             if (array[i]) {
     153           0 :                 json->appendf("%s", separator);
     154           0 :                 json->append(array[i]->toJson());
     155           0 :                 separator = ",";
     156             :             }
     157             :         }
     158           0 :         json->append("]");
     159             :     }
     160           0 : }
     161             : 
     162             : // This will pretty print a very small subset of json
     163             : // The parsing rules are straightforward, aside from the fact that we do not want an extra newline
     164             : // before ',' and after '}', so we have a comma exception rule.
     165           0 : class PrettyPrintJson {
     166             : public:
     167           0 :     SkString prettify(const SkString& json) {
     168           0 :         fPrettyJson.reset();
     169           0 :         fTabCount = 0;
     170           0 :         fFreshLine = false;
     171           0 :         fCommaException = false;
     172           0 :         for (size_t i = 0; i < json.size(); i++) {
     173           0 :             if ('[' == json[i] || '{' == json[i]) {
     174           0 :                 this->newline();
     175           0 :                 this->appendChar(json[i]);
     176           0 :                 fTabCount++;
     177           0 :                 this->newline();
     178           0 :             } else if (']' == json[i] || '}' == json[i]) {
     179           0 :                 fTabCount--;
     180           0 :                 this->newline();
     181           0 :                 this->appendChar(json[i]);
     182           0 :                 fCommaException = true;
     183           0 :             } else if (',' == json[i]) {
     184           0 :                 this->appendChar(json[i]);
     185           0 :                 this->newline();
     186             :             } else {
     187           0 :                 this->appendChar(json[i]);
     188             :             }
     189             :         }
     190           0 :         return fPrettyJson;
     191             :     }
     192             : private:
     193           0 :     void appendChar(char appendee) {
     194           0 :         if (fCommaException && ',' != appendee) {
     195           0 :             this->newline();
     196             :         }
     197           0 :         this->tab();
     198           0 :         fPrettyJson += appendee;
     199           0 :         fFreshLine = false;
     200           0 :         fCommaException = false;
     201           0 :     }
     202             : 
     203           0 :     void tab() {
     204           0 :         if (fFreshLine) {
     205           0 :             for (int i = 0; i < fTabCount; i++) {
     206           0 :                 fPrettyJson += '\t';
     207             :             }
     208             :         }
     209           0 :     }
     210             : 
     211           0 :     void newline() {
     212           0 :         if (!fFreshLine) {
     213           0 :             fFreshLine = true;
     214           0 :             fPrettyJson += '\n';
     215             :         }
     216           0 :     }
     217             : 
     218             :     SkString fPrettyJson;
     219             :     int fTabCount;
     220             :     bool fFreshLine;
     221             :     bool fCommaException;
     222             : };
     223             : 
     224           0 : static SkString pretty_print_json(SkString json) {
     225           0 :     class PrettyPrintJson prettyPrintJson;
     226           0 :     return prettyPrintJson.prettify(json);
     227             : }
     228             : 
     229           0 : SkString GrAuditTrail::toJson(bool prettyPrint) const {
     230           0 :     SkString json;
     231           0 :     json.append("{");
     232           0 :     JsonifyTArray(&json, "Ops", fOpList, false);
     233           0 :     json.append("}");
     234             : 
     235           0 :     if (prettyPrint) {
     236           0 :         return pretty_print_json(json);
     237             :     } else {
     238           0 :         return json;
     239             :     }
     240             : }
     241             : 
     242           0 : SkString GrAuditTrail::toJson(int clientID, bool prettyPrint) const {
     243           0 :     SkString json;
     244           0 :     json.append("{");
     245           0 :     Ops** ops = fClientIDLookup.find(clientID);
     246           0 :     if (ops) {
     247           0 :         JsonifyTArray(&json, "Ops", **ops, false);
     248             :     }
     249           0 :     json.appendf("}");
     250             : 
     251           0 :     if (prettyPrint) {
     252           0 :         return pretty_print_json(json);
     253             :     } else {
     254           0 :         return json;
     255             :     }
     256             : }
     257             : 
     258           0 : static void skrect_to_json(SkString* json, const char* name, const SkRect& rect) {
     259           0 :     json->appendf("\"%s\": {", name);
     260           0 :     json->appendf("\"Left\": %f,", rect.fLeft);
     261           0 :     json->appendf("\"Right\": %f,", rect.fRight);
     262           0 :     json->appendf("\"Top\": %f,", rect.fTop);
     263           0 :     json->appendf("\"Bottom\": %f", rect.fBottom);
     264           0 :     json->append("}");
     265           0 : }
     266             : 
     267           0 : SkString GrAuditTrail::Op::toJson() const {
     268           0 :     SkString json;
     269           0 :     json.append("{");
     270           0 :     json.appendf("\"Name\": \"%s\",", fName.c_str());
     271           0 :     json.appendf("\"ClientID\": \"%d\",", fClientID);
     272           0 :     json.appendf("\"OpListID\": \"%d\",", fOpListID);
     273           0 :     json.appendf("\"ChildID\": \"%d\",", fChildID);
     274           0 :     skrect_to_json(&json, "Bounds", fBounds);
     275           0 :     if (fStackTrace.count()) {
     276           0 :         json.append(",\"Stack\": [");
     277           0 :         for (int i = 0; i < fStackTrace.count(); i++) {
     278           0 :             json.appendf("\"%s\"", fStackTrace[i].c_str());
     279           0 :             if (i < fStackTrace.count() - 1) {
     280           0 :                 json.append(",");
     281             :             }
     282             :         }
     283           0 :         json.append("]");
     284             :     }
     285           0 :     json.append("}");
     286           0 :     return json;
     287             : }
     288             : 
     289           0 : SkString GrAuditTrail::OpNode::toJson() const {
     290           0 :     SkString json;
     291           0 :     json.append("{");
     292           0 :     json.appendf("\"ResourceID\": \"%u\",", fResourceUniqueID.asUInt());
     293           0 :     json.appendf("\"ProxyID\": \"%u\",", fProxyUniqueID.asUInt());
     294           0 :     skrect_to_json(&json, "Bounds", fBounds);
     295           0 :     JsonifyTArray(&json, "Ops", fChildren, true);
     296           0 :     json.append("}");
     297           0 :     return json;
     298             : }

Generated by: LCOV version 1.13