Add SkDebugf trace event handler.

Also adds more trace events to GPU backend.

Change-Id: Ifa5f0cd4b1fd582f0cc30d37d9e6414dc498c75d
Reviewed-on: https://skia-review.googlesource.com/24622
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index f60c23b..2fac60e 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1028,6 +1028,7 @@
       "tools",
       "tools/debugger",
       "tools/timer",
+      "tools/trace",
     ]
     sources = [
       "tools/AndroidSkDebugToStdOut.cpp",
@@ -1046,6 +1047,8 @@
       "tools/sk_tool_utils.cpp",
       "tools/sk_tool_utils_font.cpp",
       "tools/timer/Timer.cpp",
+      "tools/trace/SkDebugfTracer.cpp",
+      "tools/trace/SkDebugfTracer.h",
     ]
     libs = []
     if (is_ios) {
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index e67415e..8cbaa23 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -18,13 +18,10 @@
 #include "CrashHandler.h"
 #include "GMBench.h"
 #include "ProcStats.h"
-#include "ResultsWriter.h"
 #include "RecordingBench.h"
+#include "ResultsWriter.h"
 #include "SKPAnimationBench.h"
 #include "SKPBench.h"
-#include "Stats.h"
-#include "ios_utils.h"
-
 #include "SkAndroidCodec.h"
 #include "SkAutoMalloc.h"
 #include "SkBBoxHierarchy.h"
@@ -35,6 +32,7 @@
 #include "SkCommonFlagsConfig.h"
 #include "SkCommonFlagsPathRenderer.h"
 #include "SkData.h"
+#include "SkDebugfTracer.h"
 #include "SkGraphics.h"
 #include "SkLeanWindows.h"
 #include "SkOSFile.h"
@@ -46,7 +44,9 @@
 #include "SkSurface.h"
 #include "SkTaskGroup.h"
 #include "SkThreadUtils.h"
+#include "Stats.h"
 #include "ThermalManager.h"
+#include "ios_utils.h"
 
 #include <stdlib.h>
 
@@ -1099,6 +1099,9 @@
 
 int main(int argc, char** argv) {
     SkCommandLineFlags::Parse(argc, argv);
+    if (FLAGS_trace) {
+        SkEventTracer::SetInstance(new SkDebugfTracer);
+    }
 #if defined(SK_BUILD_FOR_IOS)
     cd_Documents();
 #endif
diff --git a/dm/DM.cpp b/dm/DM.cpp
index b701bcc..ef048a4 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -19,6 +19,8 @@
 #include "SkCommonFlagsConfig.h"
 #include "SkCommonFlagsPathRenderer.h"
 #include "SkData.h"
+#include "SkDebugfTracer.h"
+#include "SkEventTracer.h"
 #include "SkFontMgr.h"
 #include "SkGraphics.h"
 #include "SkHalf.h"
@@ -29,6 +31,7 @@
 #include "SkOSPath.h"
 #include "SkPM4fPriv.h"
 #include "SkPngEncoder.h"
+#include "SkScan.h"
 #include "SkSpinlock.h"
 #include "SkTHash.h"
 #include "SkTaskGroup.h"
@@ -38,7 +41,6 @@
 #include "ios_utils.h"
 #include "picture_utils.h"
 #include "sk_tool_utils.h"
-#include "SkScan.h"
 
 #include <vector>
 
@@ -236,7 +238,8 @@
     #include <signal.h>
     #if !defined(SK_BUILD_FOR_ANDROID)
         #include <execinfo.h>
-    #endif
+
+#endif
 
     static constexpr int max_of() { return 0; }
     template <typename... Rest>
@@ -1263,7 +1266,10 @@
 
 int main(int argc, char** argv) {
     SkCommandLineFlags::Parse(argc, argv);
-#if defined(SK_BUILD_FOR_IOS)
+    if (FLAGS_trace) {
+        SkAssertResult(SkEventTracer::SetInstance(new SkDebugfTracer()));
+    }
+    #if defined(SK_BUILD_FOR_IOS)
     cd_Documents();
 #endif
     setbuf(stdout, nullptr);
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 2f3c30d..0c227e3 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -22,6 +22,7 @@
 #include "GrSurfaceProxyPriv.h"
 #include "GrTexture.h"
 #include "GrTextureContext.h"
+#include "GrTracing.h"
 #include "SkConvertPixels.h"
 #include "SkGr.h"
 #include "SkUnPreMultiplyPriv.h"
@@ -325,7 +326,7 @@
     RETURN_FALSE_IF_ABANDONED_PRIV
     SkASSERT(dst);
     ASSERT_OWNED_PROXY_PRIV(dst->asSurfaceProxy());
-    GR_AUDIT_TRAIL_AUTO_FRAME(&fContext->fAuditTrail, "GrContextPriv::writeSurfacePixels");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "writeSurfacePixels", fContext);
 
     if (!dst->asSurfaceProxy()->instantiate(fContext->resourceProvider())) {
         return false;
@@ -454,7 +455,7 @@
     RETURN_FALSE_IF_ABANDONED_PRIV
     SkASSERT(src);
     ASSERT_OWNED_PROXY_PRIV(src->asSurfaceProxy());
-    GR_AUDIT_TRAIL_AUTO_FRAME(&fContext->fAuditTrail, "GrContextPriv::readSurfacePixels");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "readSurfacePixels", fContext);
 
     // MDB TODO: delay this instantiation until later in the method
     if (!src->asSurfaceProxy()->instantiate(fContext->resourceProvider())) {
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index b06c97b..eeb1071 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -22,6 +22,7 @@
 #include "SkSurface_Gpu.h"
 #include "SkTTopoSort.h"
 
+#include "GrTracing.h"
 #include "text/GrAtlasTextContext.h"
 #include "text/GrStencilAndCoverTextContext.h"
 
@@ -83,6 +84,8 @@
 
 // MDB TODO: make use of the 'proxy' parameter.
 void GrDrawingManager::internalFlush(GrSurfaceProxy*, GrResourceCache::FlushType type) {
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawingManager", "internalFlush", fContext);
+
     if (fFlushing || this->wasAbandoned()) {
         return;
     }
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index ec63eb0..cab5d15 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -23,6 +23,7 @@
 #include "GrStencilSettings.h"
 #include "GrSurfacePriv.h"
 #include "GrTexturePriv.h"
+#include "GrTracing.h"
 #include "SkMathPriv.h"
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -131,6 +132,7 @@
 
 sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budgeted,
                                       const GrMipLevel texels[], int mipLevelCount) {
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrGpu", "createTexture", fContext);
     GrSurfaceDesc desc = origDesc;
 
     const GrCaps* caps = this->caps();
@@ -251,6 +253,7 @@
                         GrSurface* src,
                         const SkIRect& srcRect,
                         const SkIPoint& dstPoint) {
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrGpu", "copySurface", fContext);
     SkASSERT(dst && src);
     this->handleDirtyContext();
     // We don't allow conversion between integer configs and float/fixed configs.
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 8426668..6a08447 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -21,6 +21,7 @@
 #include "GrRenderTargetContextPriv.h"
 #include "GrResourceProvider.h"
 #include "GrStencilAttachment.h"
+#include "GrTracing.h"
 #include "SkDrawShadowRec.h"
 #include "SkLatticeIter.h"
 #include "SkMatrixPriv.h"
@@ -175,7 +176,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawText");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawText", fContext);
 
     GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
     atlasTextContext->drawText(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, text,
@@ -190,7 +191,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPosText");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPosText", fContext);
 
     GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
     atlasTextContext->drawPosText(fContext, this, clip, paint, viewMatrix, fSurfaceProps, text,
@@ -204,7 +205,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawTextBlob");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextBlob", fContext);
 
     GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
     atlasTextContext->drawTextBlob(fContext, this, clip, paint, viewMatrix, fSurfaceProps, blob, x,
@@ -215,7 +216,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::discard");
+            GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "discard", fContext);
 
     AutoCheckFlush acf(this->drawingManager());
 
@@ -236,7 +237,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::clear");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "clear", fContext);
 
     AutoCheckFlush acf(this->drawingManager());
     this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect);
@@ -246,8 +247,8 @@
     ASSERT_SINGLE_OWNER_PRIV
     RETURN_IF_ABANDONED_PRIV
     SkDEBUGCODE(fRenderTargetContext->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
-                              "GrRenderTargetContext::absClear");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "absClear",
+                                   fRenderTargetContext->fContext);
 
     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
 
@@ -298,8 +299,8 @@
     ASSERT_SINGLE_OWNER_PRIV
     RETURN_IF_ABANDONED_PRIV
     SkDEBUGCODE(fRenderTargetContext->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
-                              "GrRenderTargetContextPriv::clear");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clear",
+                                   fRenderTargetContext->fContext);
 
     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
     fRenderTargetContext->internalClear(clip, color, canIgnoreClip);
@@ -348,7 +349,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPaint");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPaint", fContext);
 
     // set rect to be big enough to fill the space, but not super-huge, so we
     // don't overflow fixed-point implementations
@@ -492,7 +493,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRect");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRect", fContext);
 
     // Path effects should've been devolved to a path in SkGpuDevice
     SkASSERT(!style->pathEffect());
@@ -601,8 +602,8 @@
     ASSERT_SINGLE_OWNER_PRIV
     RETURN_IF_ABANDONED_PRIV
     SkDEBUGCODE(fRenderTargetContext->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
-                              "GrRenderTargetContextPriv::clearStencilClip");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clearStencilClip",
+                                   fRenderTargetContext->fContext);
 
     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
 
@@ -622,8 +623,8 @@
     ASSERT_SINGLE_OWNER_PRIV
     RETURN_IF_ABANDONED_PRIV
     SkDEBUGCODE(fRenderTargetContext->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
-                              "GrRenderTargetContext::stencilPath");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilPath",
+                                   fRenderTargetContext->fContext);
 
     SkASSERT(aaType != GrAAType::kCoverage);
 
@@ -680,8 +681,9 @@
     ASSERT_SINGLE_OWNER_PRIV
     RETURN_IF_ABANDONED_PRIV
     SkDEBUGCODE(fRenderTargetContext->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
-                              "GrRenderTargetContext::stencilRect");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilRect",
+                                   fRenderTargetContext->fContext);
+
     SkASSERT(GrAAType::kCoverage != aaType);
     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
 
@@ -702,8 +704,8 @@
     ASSERT_SINGLE_OWNER_PRIV
     RETURN_FALSE_IF_ABANDONED_PRIV
     SkDEBUGCODE(fRenderTargetContext->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
-                              "GrRenderTargetContext::drawAndStencilRect");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilRect",
+                                   fRenderTargetContext->fContext);
 
     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
 
@@ -728,7 +730,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectToRect");
+            GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectToRect", fContext);
 
     SkRect croppedRect = rectToDraw;
     SkRect croppedLocalRect = localRect;
@@ -786,7 +788,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectWithLocalMatrix");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectWithLocalMatrix", fContext);
 
     SkRect croppedRect = rectToDraw;
     if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
@@ -842,7 +844,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawVertices", fContext);
 
     AutoCheckFlush acf(this->drawingManager());
 
@@ -866,7 +868,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawAtlas");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawAtlas", fContext);
 
     AutoCheckFlush acf(this->drawingManager());
 
@@ -887,7 +889,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRRect");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRRect", fContext);
     if (rrect.isEmpty()) {
        return;
     }
@@ -960,7 +962,7 @@
         return true;
     }
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawFastShadow");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawFastShadow", fContext);
 
     // check z plane
     bool tiltZPlane = SkToBool(!SkScalarNearlyZero(rec.fZPlaneParams.fX) ||
@@ -1248,7 +1250,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawDRRect");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawDRRect", fContext);
 
     SkASSERT(!outer.isEmpty());
     SkASSERT(!inner.isEmpty());
@@ -1283,7 +1285,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRegion");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRegion", fContext);
 
     if (GrAA::kYes == aa) {
         // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
@@ -1315,7 +1317,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawOval");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawOval", fContext);
 
     if (oval.isEmpty()) {
        return;
@@ -1366,7 +1368,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawArc");
+            GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawArc", fContext);
 
     AutoCheckFlush acf(this->drawingManager());
 
@@ -1402,7 +1404,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawImageLattice");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawImageLattice", fContext);
 
     AutoCheckFlush acf(this->drawingManager());
 
@@ -1416,7 +1418,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_FALSE_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::prepareForExternalIO");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "prepareForExternalIO", fContext);
 
     if (numSemaphores && !this->caps()->fenceSyncSupport()) {
         this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get());
@@ -1447,7 +1449,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_FALSE_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::waitOnSemaphores");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "waitOnSemaphores", fContext);
 
     AutoCheckFlush acf(this->drawingManager());
 
@@ -1520,7 +1522,7 @@
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPath");
+            GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawPath", fContext);
 
     if (path.isEmpty()) {
        if (path.isInverseFillType()) {
@@ -1579,8 +1581,8 @@
     ASSERT_SINGLE_OWNER_PRIV
     RETURN_FALSE_IF_ABANDONED_PRIV
     SkDEBUGCODE(fRenderTargetContext->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
-                              "GrRenderTargetContextPriv::drawAndStencilPath");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilPath",
+                                   fRenderTargetContext->fContext);
 
     if (path.isEmpty() && path.isInverseFillType()) {
         this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
@@ -1650,6 +1652,8 @@
                                              const GrStyle& style) {
     ASSERT_SINGLE_OWNER
     RETURN_IF_ABANDONED
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "internalDrawPath", fContext);
+
     SkASSERT(!path.isEmpty());
     GrShape shape;
     // NVPR cannot handle hairlines, so this would get picked up by a different stencil and
@@ -1756,7 +1760,7 @@
         return SK_InvalidUniqueID;
     }
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addDrawOp");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "addDrawOp", fContext);
 
     // Setup clip
     SkRect bounds;
@@ -1803,7 +1807,7 @@
         return SK_InvalidUniqueID;
     }
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addLegacyMeshDrawOp");
+    GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "addLegacyMeshDrawOp", fContext);
 
     // Setup clip
     SkRect bounds;
diff --git a/tools/flags/SkCommonFlags.cpp b/tools/flags/SkCommonFlags.cpp
index 0148bcd..35fc0cf 100644
--- a/tools/flags/SkCommonFlags.cpp
+++ b/tools/flags/SkCommonFlags.cpp
@@ -72,6 +72,8 @@
                                     "whether it's concave or convex, we consider a path complicated"
                                     "if its number of points is comparable to its resolution.");
 
+DEFINE_bool(trace, false, "Show trace events using SkDebugf.");
+
 bool CollectImages(SkCommandLineFlags::StringArray images, SkTArray<SkString>* output) {
     SkASSERT(output);
 
diff --git a/tools/flags/SkCommonFlags.h b/tools/flags/SkCommonFlags.h
index 92ac141..71ff8c3 100644
--- a/tools/flags/SkCommonFlags.h
+++ b/tools/flags/SkCommonFlags.h
@@ -34,6 +34,7 @@
 DECLARE_bool(pre_log);
 DECLARE_bool(analyticAA);
 DECLARE_bool(forceAnalyticAA);
+DECLARE_bool(trace)
 
 DECLARE_string(key);
 DECLARE_string(properties);
diff --git a/tools/trace/SkDebugfTracer.cpp b/tools/trace/SkDebugfTracer.cpp
new file mode 100644
index 0000000..272af78
--- /dev/null
+++ b/tools/trace/SkDebugfTracer.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkDebugfTracer.h"
+#include "SkTraceEvent.h"
+
+SkEventTracer::Handle SkDebugfTracer::addTraceEvent(char phase,
+                                                    const uint8_t* categoryEnabledFlag,
+                                                    const char* name,
+                                                    uint64_t id,
+                                                    int numArgs,
+                                                    const char** argNames,
+                                                    const uint8_t* argTypes,
+                                                    const uint64_t* argValues,
+                                                    uint8_t flags) {
+    SkString args;
+    for (int i = 0; i < numArgs; ++i) {
+        if (i > 0) {
+            args.append(", ");
+        } else {
+            args.append(" ");
+        }
+        switch (argTypes[i]) {
+            case TRACE_VALUE_TYPE_BOOL:
+                args.appendf("%s=%s",
+                             argNames[i],
+                             (*reinterpret_cast<bool*>(argValues[i]) ? "true" : "false"));
+                break;
+            case TRACE_VALUE_TYPE_UINT:
+                args.appendf("%s=%u", argNames[i], static_cast<uint32_t>(argValues[i]));
+                break;
+            case TRACE_VALUE_TYPE_INT:
+                args.appendf("%s=%d", argNames[i], static_cast<int32_t>(argValues[i]));
+                break;
+            case TRACE_VALUE_TYPE_DOUBLE:
+                args.appendf("%s=%g", argNames[i], *SkTCast<const double*>(&argValues[i]));
+                break;
+            case TRACE_VALUE_TYPE_POINTER:
+                args.appendf("%s=0x%p", argNames[i], reinterpret_cast<void*>(argValues[i]));
+                break;
+            case TRACE_VALUE_TYPE_STRING:
+            case TRACE_VALUE_TYPE_COPY_STRING: {
+                static constexpr size_t kMaxLen = 20;
+                const char* str = reinterpret_cast<const char*>(argValues[i]);
+                SkString string(str);
+                size_t truncAt = string.size();
+                size_t newLineAt = SkStrFind(string.c_str(), "\n");
+                if (newLineAt > 0) {
+                    truncAt = newLineAt;
+                }
+                truncAt = SkTMin(truncAt, kMaxLen);
+                if (truncAt < string.size()) {
+                    string.resize(truncAt);
+                    string.append("...");
+                }
+                args.appendf("%s=\"%s\"", argNames[i], string.c_str());
+                break;
+            }
+            default:
+                args.appendf("%s=<unknown type>", argNames[i]);
+                break;
+        }
+    }
+    bool open = (phase == TRACE_EVENT_PHASE_COMPLETE);
+    if (open) {
+        SkDebugf(
+                "[% 2d]%s %s%s #%d {\n", fIndent.size(), fIndent.c_str(), name, args.c_str(), fCnt);
+        fIndent.append(" ");
+    } else {
+        SkDebugf("%s%s #%d\n", name, args.c_str(), fCnt);
+    }
+    ++fCnt;
+    return 0;
+}
+
+void SkDebugfTracer::updateTraceEventDuration(const uint8_t* categoryEnabledFlag,
+                                              const char* name,
+                                              SkEventTracer::Handle handle) {
+    fIndent.resize(fIndent.size() - 1);
+    SkDebugf("[% 2d]%s } %s\n", fIndent.size(), fIndent.c_str(), name);
+}
+
+const uint8_t* SkDebugfTracer::getCategoryGroupEnabled(const char* name) {
+    static uint8_t yes = SkEventTracer::kEnabledForRecording_CategoryGroupEnabledFlags;
+    return &yes;
+}
diff --git a/tools/trace/SkDebugfTracer.h b/tools/trace/SkDebugfTracer.h
new file mode 100644
index 0000000..4350d1a
--- /dev/null
+++ b/tools/trace/SkDebugfTracer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDebugfTracer_DEFINED
+#define SkDebugfTracer_DEFINED
+
+#include "SkEventTracer.h"
+#include "SkString.h"
+
+/**
+ * A SkEventTracer implementation that logs events using SkDebugf.
+ */
+class SkDebugfTracer : public SkEventTracer {
+public:
+    SkDebugfTracer() {}
+
+    SkEventTracer::Handle addTraceEvent(char phase,
+                                        const uint8_t* categoryEnabledFlag,
+                                        const char* name,
+                                        uint64_t id,
+                                        int numArgs,
+                                        const char** argNames,
+                                        const uint8_t* argTypes,
+                                        const uint64_t* argValues,
+                                        uint8_t flags) override;
+
+    void updateTraceEventDuration(const uint8_t* categoryEnabledFlag,
+                                  const char* name,
+                                  SkEventTracer::Handle handle) override;
+
+    const uint8_t* getCategoryGroupEnabled(const char* name) override;
+
+    const char* getCategoryGroupName(const uint8_t* categoryEnabledFlag) override {
+        static const char* category = "category?";
+        return category;
+    }
+
+private:
+    SkString fIndent;
+    int fCnt = 0;
+};
+
+#endif