Add hooks for GL_EXT_debug_marker in gpu

BUG=skia:
R=bsalomon@google.com

Author: egdaniel@google.com

Review URL: https://codereview.chromium.org/174123003

git-svn-id: http://skia.googlecode.com/svn/trunk@13538 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/gl/GrGLExtensions.h b/include/gpu/gl/GrGLExtensions.h
index 76516cf..dbfc3be 100644
--- a/include/gpu/gl/GrGLExtensions.h
+++ b/include/gpu/gl/GrGLExtensions.h
@@ -54,6 +54,11 @@
      */
     bool remove(const char[]);
 
+    /**
+     * Adds an extension to list
+     */
+    void add(const char[]);
+
     void reset() { fStrings->reset(); }
 
     void print(const char* sep = "\n") const;
diff --git a/include/gpu/gl/GrGLFunctions.h b/include/gpu/gl/GrGLFunctions.h
index b6d68c7..634af56 100644
--- a/include/gpu/gl/GrGLFunctions.h
+++ b/include/gpu/gl/GrGLFunctions.h
@@ -147,10 +147,13 @@
     typedef const GrGLubyte* (GR_GL_FUNCTION_TYPE* GrGLGetStringiProc)(GrGLenum name, GrGLuint index);
     typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetTexLevelParameterivProc)(GrGLenum target, GrGLint level, GrGLenum pname, GrGLint* params);
     typedef GrGLint (GR_GL_FUNCTION_TYPE* GrGLGetUniformLocationProc)(GrGLuint program, const char* name);
+    typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLInsertEventMarkerProc)(GrGLsizei length, const char* marker);
     typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLLineWidthProc)(GrGLfloat width);
     typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLLinkProgramProc)(GrGLuint program);
     typedef GrGLvoid* (GR_GL_FUNCTION_TYPE* GrGLMapBufferProc)(GrGLenum target, GrGLenum access);
     typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPixelStoreiProc)(GrGLenum pname, GrGLint param);
+    typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPopGroupMarkerProc)();
+    typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPushGroupMarkerProc)(GrGLsizei length, const char* marker);
     typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLQueryCounterProc)(GrGLuint id, GrGLenum target);
     typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLReadBufferProc)(GrGLenum src);
     typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLReadPixelsProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLvoid* pixels);
@@ -261,6 +264,7 @@
     typedef GrGLboolean (GR_GL_FUNCTION_TYPE* GrGLIsPointInStrokePathProc)(GrGLuint path, GrGLfloat x, GrGLfloat y);
     typedef GrGLfloat (GR_GL_FUNCTION_TYPE* GrGLGetPathLengthProc)(GrGLuint path, GrGLsizei startSegment, GrGLsizei numSegments);
     typedef GrGLboolean (GR_GL_FUNCTION_TYPE* GrGLPointAlongPathProc)(GrGLuint path, GrGLsizei startSegment, GrGLsizei numSegments, GrGLfloat distance, GrGLfloat *x, GrGLfloat *y, GrGLfloat *tangentX, GrGLfloat *tangentY);
+
 }  // extern "C"
 
 #endif
diff --git a/include/gpu/gl/GrGLInterface.h b/include/gpu/gl/GrGLInterface.h
index f5bcd16..52d96ef 100644
--- a/include/gpu/gl/GrGLInterface.h
+++ b/include/gpu/gl/GrGLInterface.h
@@ -76,6 +76,13 @@
     GL_NV_path_rendering. */
 const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface*);
 
+/** Function that returns a new interface identical to "interface" but with support for
+    test version of GL_EXT_debug_marker. */
+const GrGLInterface* GrGLInterfaceAddTestDebugMarker(const GrGLInterface*,
+                                                     GrGLInsertEventMarkerProc insertEventMarkerFn,
+                                                     GrGLPushGroupMarkerProc pushGroupMarkerFn,
+                                                     GrGLPopGroupMarkerProc popGroupMarkerFn);
+
 /**
  * GrContext uses the following interface to make all calls into OpenGL. When a
  * GrContext is created it is given a GrGLInterface. The interface's function
@@ -228,6 +235,7 @@
         GLPtr<GrGLGetStringiProc> fGetStringi;
         GLPtr<GrGLGetTexLevelParameterivProc> fGetTexLevelParameteriv;
         GLPtr<GrGLGetUniformLocationProc> fGetUniformLocation;
+        GLPtr<GrGLInsertEventMarkerProc> fInsertEventMarker;
         GLPtr<GrGLLineWidthProc> fLineWidth;
         GLPtr<GrGLLinkProgramProc> fLinkProgram;
         GLPtr<GrGLLoadIdentityProc> fLoadIdentity;
@@ -235,6 +243,8 @@
         GLPtr<GrGLMapBufferProc> fMapBuffer;
         GLPtr<GrGLMatrixModeProc> fMatrixMode;
         GLPtr<GrGLPixelStoreiProc> fPixelStorei;
+        GLPtr<GrGLPopGroupMarkerProc> fPopGroupMarker;
+        GLPtr<GrGLPushGroupMarkerProc> fPushGroupMarker;
         GLPtr<GrGLQueryCounterProc> fQueryCounter;
         GLPtr<GrGLReadBufferProc> fReadBuffer;
         GLPtr<GrGLReadPixelsProc> fReadPixels;
@@ -445,6 +455,7 @@
     GLPtrAlias<GrGLGetStringiProc> fGetStringi;
     GLPtrAlias<GrGLGetTexLevelParameterivProc> fGetTexLevelParameteriv;
     GLPtrAlias<GrGLGetUniformLocationProc> fGetUniformLocation;
+    GLPtrAlias<GrGLInsertEventMarkerProc> fInsertEventMarker;
     GLPtrAlias<GrGLLineWidthProc> fLineWidth;
     GLPtrAlias<GrGLLinkProgramProc> fLinkProgram;
     GLPtrAlias<GrGLLoadIdentityProc> fLoadIdentity;
@@ -452,6 +463,8 @@
     GLPtrAlias<GrGLMapBufferProc> fMapBuffer;
     GLPtrAlias<GrGLMatrixModeProc> fMatrixMode;
     GLPtrAlias<GrGLPixelStoreiProc> fPixelStorei;
+    GLPtrAlias<GrGLPopGroupMarkerProc> fPopGroupMarker;
+    GLPtrAlias<GrGLPushGroupMarkerProc> fPushGroupMarker;
     GLPtrAlias<GrGLQueryCounterProc> fQueryCounter;
     GLPtrAlias<GrGLReadBufferProc> fReadBuffer;
     GLPtrAlias<GrGLReadPixelsProc> fReadPixels;
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 0909e08..fb4c9a1 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -88,7 +88,8 @@
 
 GrDrawTarget::GrDrawTarget(GrContext* context)
     : fClip(NULL)
-    , fContext(context) {
+    , fContext(context)
+    , fPushGpuTraceCount(0) {
     SkASSERT(NULL != context);
 
     fDrawState = &fDefaultDrawState;
@@ -547,6 +548,28 @@
     this->onDrawPath(path, fill, dstCopy.texture() ? &dstCopy : NULL);
 }
 
+void GrDrawTarget::instantGpuTraceEvent(const char* marker) {
+    if (this->caps()->gpuTracingSupport()) {
+        this->onInstantGpuTraceEvent(marker);
+    }
+}
+
+void GrDrawTarget::pushGpuTraceEvent(const char* marker) {
+    SkASSERT(fPushGpuTraceCount >= 0);
+    if (this->caps()->gpuTracingSupport()) {
+        this->onPushGpuTraceEvent(marker);
+        ++fPushGpuTraceCount;
+    }
+}
+
+void GrDrawTarget::popGpuTraceEvent() {
+    SkASSERT(fPushGpuTraceCount >= 1);
+    if (this->caps()->gpuTracingSupport()) {
+        this->onPopGpuTraceEvent();
+        --fPushGpuTraceCount;
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 bool GrDrawTarget::willUseHWAALines() const {
@@ -971,6 +994,7 @@
     fPathRenderingSupport = false;
     fDstReadInShaderSupport = false;
     fReuseScratchTextures = true;
+    fGpuTracingSupport = false;
 
     fMaxRenderTargetSize = 0;
     fMaxTextureSize = 0;
@@ -993,6 +1017,7 @@
     fPathRenderingSupport = other.fPathRenderingSupport;
     fDstReadInShaderSupport = other.fDstReadInShaderSupport;
     fReuseScratchTextures = other.fReuseScratchTextures;
+    fGpuTracingSupport = other.fGpuTracingSupport;
 
     fMaxRenderTargetSize = other.fMaxRenderTargetSize;
     fMaxTextureSize = other.fMaxTextureSize;
@@ -1019,6 +1044,7 @@
     r.appendf("Path Rendering Support      : %s\n", gNY[fPathRenderingSupport]);
     r.appendf("Dst Read In Shader Support  : %s\n", gNY[fDstReadInShaderSupport]);
     r.appendf("Reuse Scratch Textures      : %s\n", gNY[fReuseScratchTextures]);
+    r.appendf("Gpu Tracing Support         : %s\n", gNY[fGpuTracingSupport]);
     r.appendf("Max Texture Size            : %d\n", fMaxTextureSize);
     r.appendf("Max Render Target Size      : %d\n", fMaxRenderTargetSize);
     r.appendf("Max Sample Count            : %d\n", fMaxSampleCount);
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index c505869..19ce16f 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -423,6 +423,20 @@
                        GrRenderTarget* renderTarget = NULL) = 0;
 
     /**
+     * instantGpuTraceEvent places a single "sign post" type marker into command stream. The
+     * argument marker will be the name of the annotation that is added.
+     */
+    void instantGpuTraceEvent(const char* marker);
+    /**
+     * The following two functions are used for marking groups of commands. Use pushGpuTraceEvent
+     * to set the beginning of a command set, and popGpuTraceEvent is be called at end of the
+     * command set. The argument marker is the name for the annotation that is added. The push and
+     * pops can be used hierarchically, but every push must have a match pop.
+     */
+    void pushGpuTraceEvent(const char* marker);
+    void popGpuTraceEvent();
+
+    /**
      * Copies a pixel rectangle from one surface to another. This call may finalize
      * reserved vertex/index data (as though a draw call was made). The src pixels
      * copied are specified by srcRect. They are copied to a rect of the same
@@ -854,6 +868,10 @@
     virtual void onDrawPath(const GrPath*, SkPath::FillType,
                             const GrDeviceCoordTexture* dstCopy) = 0;
 
+    virtual void onInstantGpuTraceEvent(const char* marker) = 0;
+    virtual void onPushGpuTraceEvent(const char* marker) = 0;
+    virtual void onPopGpuTraceEvent() = 0;
+
     // helpers for reserving vertex and index space.
     bool reserveVertexSpace(size_t vertexSize,
                             int vertexCount,
@@ -888,6 +906,8 @@
     GrDrawState                                                     fDefaultDrawState;
     // The context owns us, not vice-versa, so this ptr is not ref'ed by DrawTarget.
     GrContext*                                                      fContext;
+    // To keep track that we always have at least as many debug marker pushes as pops
+    int                                                             fPushGpuTraceCount;
 
     typedef SkRefCnt INHERITED;
 };
diff --git a/src/gpu/GrDrawTargetCaps.h b/src/gpu/GrDrawTargetCaps.h
index b316e49..b33217a 100644
--- a/src/gpu/GrDrawTargetCaps.h
+++ b/src/gpu/GrDrawTargetCaps.h
@@ -40,6 +40,7 @@
     bool bufferLockSupport() const { return fBufferLockSupport; }
     bool pathRenderingSupport() const { return fPathRenderingSupport; }
     bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; }
+    bool gpuTracingSupport() const { return fGpuTracingSupport; }
 
     // Scratch textures not being reused means that those scratch textures
     // that we upload to (i.e., don't have a render target) will not be
@@ -71,6 +72,7 @@
     bool fPathRenderingSupport      : 1;
     bool fDstReadInShaderSupport    : 1;
     bool fReuseScratchTextures      : 1;
+    bool fGpuTracingSupport         : 1;
 
     int fMaxRenderTargetSize;
     int fMaxTextureSize;
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 669167c..44bf4ed 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -441,6 +441,18 @@
     renderTarget->ref();
 }
 
+void GrInOrderDrawBuffer::onInstantGpuTraceEvent(const char* marker) {
+    // TODO: adds command to buffer
+}
+
+void GrInOrderDrawBuffer::onPushGpuTraceEvent(const char* marker) {
+    // TODO: adds command to buffer
+}
+
+void GrInOrderDrawBuffer::onPopGpuTraceEvent() {
+    // TODO: adds command to buffer
+}
+
 void GrInOrderDrawBuffer::reset() {
     SkASSERT(1 == fGeoPoolStateStack.count());
     this->resetVertexSource();
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 6b680b2..60e01f0 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -168,6 +168,11 @@
 
     bool quickInsideClip(const SkRect& devBounds);
 
+    virtual void onInstantGpuTraceEvent(const char* marker) SK_OVERRIDE;
+    virtual void onPushGpuTraceEvent(const char* marker) SK_OVERRIDE;
+    virtual void onPopGpuTraceEvent() SK_OVERRIDE;
+
+
     // Attempts to concat instances from info onto the previous draw. info must represent an
     // instanced draw. The caller must have already recorded a new draw state and clip if necessary.
     int concatInstancedDraw(const DrawInfo& info);
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index bdb19e2..a60230a 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -312,6 +312,8 @@
     fPathRenderingSupport = ctxInfo.hasExtension("GL_NV_path_rendering");
     SkASSERT(!fPathRenderingSupport || fFixedFunctionSupport);
 
+    fGpuTracingSupport = ctxInfo.hasExtension("GL_EXT_debug_marker");
+
     fDstReadInShaderSupport = kNone_FBFetchType != fFBFetchType;
 
     // Disable scratch texture reuse on Mali and Adreno devices
diff --git a/src/gpu/gl/GrGLCreateNullInterface.cpp b/src/gpu/gl/GrGLCreateNullInterface.cpp
index 105fb0b..fa404ce 100644
--- a/src/gpu/gl/GrGLCreateNullInterface.cpp
+++ b/src/gpu/gl/GrGLCreateNullInterface.cpp
@@ -335,12 +335,15 @@
         functions->fGetStringi = noOpGLGetStringi;
         functions->fGetTexLevelParameteriv = noOpGLGetTexLevelParameteriv;
         functions->fGetUniformLocation = noOpGLGetUniformLocation;
+        functions->fInsertEventMarker = noOpGLInsertEventMarker;
         functions->fLoadIdentity = noOpGLLoadIdentity;
         functions->fLoadMatrixf = noOpGLLoadMatrixf;
         functions->fLineWidth = noOpGLLineWidth;
         functions->fLinkProgram = noOpGLLinkProgram;
         functions->fMatrixMode = noOpGLMatrixMode;
         functions->fPixelStorei = nullGLPixelStorei;
+        functions->fPopGroupMarker = noOpGLPopGroupMarker;
+        functions->fPushGroupMarker = noOpGLPushGroupMarker;
         functions->fQueryCounter = noOpGLQueryCounter;
         functions->fReadBuffer = noOpGLReadBuffer;
         functions->fReadPixels = nullGLReadPixels;
diff --git a/src/gpu/gl/GrGLExtensions.cpp b/src/gpu/gl/GrGLExtensions.cpp
index 33273e5..6d1b04d 100644
--- a/src/gpu/gl/GrGLExtensions.cpp
+++ b/src/gpu/gl/GrGLExtensions.cpp
@@ -120,6 +120,17 @@
     }
 }
 
+void GrGLExtensions::add(const char ext[]) {
+    int idx = find_string(*fStrings, ext);
+    if (idx < 0) {
+        // This is not the most effecient approach since we end up doing a full sort of the
+        // extensions after the add
+        fStrings->push_back().set(ext);
+        SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
+        SkTQSort(&fStrings->front(), &fStrings->back(), cmp);
+    }
+}
+
 void GrGLExtensions::print(const char* sep) const {
     if (NULL == sep) {
         sep = " ";
diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp
index f7b0a53..5bee408 100644
--- a/src/gpu/gl/GrGLInterface.cpp
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -18,6 +18,23 @@
 }
 #endif
 
+const GrGLInterface* GrGLInterfaceAddTestDebugMarker(const GrGLInterface* interface,
+                                                     GrGLInsertEventMarkerProc insertEventMarkerFn,
+                                                     GrGLPushGroupMarkerProc pushGroupMarkerFn,
+                                                     GrGLPopGroupMarkerProc popGroupMarkerFn) {
+    GrGLInterface* newInterface = GrGLInterface::NewClone(interface);
+
+    if (!newInterface->fExtensions.has("GL_EXT_debug_marker")) {
+        newInterface->fExtensions.add("GL_EXT_debug_marker");
+    }
+
+    newInterface->fInsertEventMarker = insertEventMarkerFn;
+    newInterface->fPushGroupMarker = pushGroupMarkerFn;
+    newInterface->fPopGroupMarker = popGroupMarkerFn;
+
+    return newInterface;
+}
+
 const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface* interface) {
     GrGLInterface* newInterface = GrGLInterface::NewClone(interface);
 
@@ -157,6 +174,7 @@
     , fGetStringi(&fFunctions.fGetStringi)
     , fGetTexLevelParameteriv(&fFunctions.fGetTexLevelParameteriv)
     , fGetUniformLocation(&fFunctions.fGetUniformLocation)
+    , fInsertEventMarker(&fFunctions.fInsertEventMarker)
     , fLineWidth(&fFunctions.fLineWidth)
     , fLinkProgram(&fFunctions.fLinkProgram)
     , fLoadIdentity(&fFunctions.fLoadIdentity)
@@ -164,6 +182,8 @@
     , fMapBuffer(&fFunctions.fMapBuffer)
     , fMatrixMode(&fFunctions.fMatrixMode)
     , fPixelStorei(&fFunctions.fPixelStorei)
+    , fPopGroupMarker(&fFunctions.fPopGroupMarker)
+    , fPushGroupMarker(&fFunctions.fPushGroupMarker)
     , fQueryCounter(&fFunctions.fQueryCounter)
     , fReadBuffer(&fFunctions.fReadBuffer)
     , fReadPixels(&fFunctions.fReadPixels)
@@ -655,5 +675,15 @@
             }
         }
     }
+
+#if 0
+    if (fExtensions.has("GL_EXT_debug_marker")) {
+        if (NULL == fFunctions.fInsertEventMarker ||
+            NULL == fFunctions.fPushGroupMarker ||
+            NULL == fFunctions.fPopGroupMarker) {
+            return false;
+        }
+    }
+#endif
     return true;
 }
diff --git a/src/gpu/gl/GrGLNoOpInterface.cpp b/src/gpu/gl/GrGLNoOpInterface.cpp
index 0641af8..a9a7d3f 100644
--- a/src/gpu/gl/GrGLNoOpInterface.cpp
+++ b/src/gpu/gl/GrGLNoOpInterface.cpp
@@ -656,3 +656,10 @@
     static int gUniLocation = 0;
     return ++gUniLocation;
 }
+
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLInsertEventMarker(GrGLsizei length, const char* marker) {
+}
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLPushGroupMarker(GrGLsizei length  , const char* marker) {
+}
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLPopGroupMarker() {
+}
diff --git a/src/gpu/gl/GrGLNoOpInterface.h b/src/gpu/gl/GrGLNoOpInterface.h
index 8fe9b44..20c67a3 100644
--- a/src/gpu/gl/GrGLNoOpInterface.h
+++ b/src/gpu/gl/GrGLNoOpInterface.h
@@ -375,4 +375,8 @@
 
 GrGLint GR_GL_FUNCTION_TYPE noOpGLGetUniformLocation(GrGLuint program, const char* name);
 
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLInsertEventMarker(GrGLsizei length, const char* marker);
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLPushGroupMarker(GrGLsizei length  , const char* marker);
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLPopGroupMarker();
+
 #endif
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index ec9c8d6..5fb2688 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -117,14 +117,12 @@
     , fGLContext(ctx) {
 
     SkASSERT(ctx.isInitialized());
-
     fCaps.reset(SkRef(ctx.caps()));
 
     fHWBoundTextures.reset(this->glCaps().maxFragmentTextureUnits());
     fHWTexGenSettings.reset(this->glCaps().maxFixedFunctionTextureCoords());
 
     GrGLClearErr(fGLContext.interface());
-
     if (gPrintStartupSpew) {
         const GrGLubyte* vendor;
         const GrGLubyte* renderer;
@@ -2663,6 +2661,23 @@
     return INHERITED::onCanCopySurface(dst, src, srcRect, dstPoint);
 }
 
+void GrGpuGL::onInstantGpuTraceEvent(const char* marker) {
+    if (this->caps()->gpuTracingSupport()) {
+        // GL_CALL(InsertEventMarker(0, marker));
+    }
+}
+
+void GrGpuGL::onPushGpuTraceEvent(const char* marker) {
+    if (this->caps()->gpuTracingSupport()) {
+        // GL_CALL(PushGroupMarker(0, marker));
+    }
+}
+
+void GrGpuGL::onPopGpuTraceEvent() {
+    if (this->caps()->gpuTracingSupport()) {
+        // GL_CALL(PopGroupMarker());
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index edd58c4..0580255 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -162,6 +162,12 @@
                                   bool insideClip) SK_OVERRIDE;
     virtual bool flushGraphicsState(DrawType, const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
 
+    // GrDrawTarget ovverides
+    virtual void onInstantGpuTraceEvent(const char* marker) SK_OVERRIDE;
+    virtual void onPushGpuTraceEvent(const char* marker) SK_OVERRIDE;
+    virtual void onPopGpuTraceEvent() SK_OVERRIDE;
+
+
     // binds texture unit in GL
     void setTextureUnit(int unitIdx);
 
diff --git a/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp b/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
index 1f91165..4c8c378 100644
--- a/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
+++ b/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
@@ -190,6 +190,12 @@
     functions->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES");
 #endif
 
+    if (extensions.has("GL_EXT_debug_marker")) {
+        functions->fInsertEventMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glInsertEventMarkerEXT");
+        functions->fPushGroupMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glPushGroupMarkerEXT");
+        functions->fPopGroupMarker = (GrGLPopGroupMarkerProc) eglGetProcAddress("glPopGropuMarkerEXT");
+    }
+
     return interface;
 }
 
@@ -389,6 +395,12 @@
         functions->fPointAlongPath = (GrGLPointAlongPathProc) eglGetProcAddress("glPointAlongPathNV");
     }
 
+    if (extensions.has("GL_EXT_debug_marker")) {
+        functions->fInsertEventMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glInsertEventMarkerEXT");
+        functions->fPushGroupMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glPushGroupMarkerEXT");
+        functions->fPopGroupMarker = (GrGLPopGroupMarkerProc) eglGetProcAddress("glPopGropuMarkerEXT");
+    }
+
     return interface;
 }
 
diff --git a/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp b/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp
index 1695c3c..95229df 100644
--- a/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp
+++ b/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp
@@ -153,6 +153,12 @@
     functions->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBufferOES");
     functions->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES");
 
+    if (extensions.has("GL_EXT_debug_marker")) {
+        functions->fInsertEventMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glInsertEventMarkerEXT");
+        functions->fPushGroupMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glPushGroupMarkerEXT");
+        functions->fPopGroupMarker = (GrGLPopGroupMarkerProc) eglGetProcAddress("glPopGropuMarkerEXT");
+    }
+
     interface->fExtensions.init(kGLES_GrGLStandard,
                                 interface->fFunctions.fGetString,
                                 interface->fFunctions.fGetStringi,
diff --git a/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp b/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp
index d8b4e1f..ee41df7 100644
--- a/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp
+++ b/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp
@@ -144,6 +144,12 @@
     functions->fGenVertexArrays = glGenVertexArraysOES;
 #endif
 
+#if GL_EXT_debug_marker
+    functions->fInsertEventMarker = glInsertEventMarkerEXT;
+    functions->fPushGroupMarker = glPushGroupMarkerEXT;
+    functions->fPopGroupMarker = glPopGropuMarkerEXT;
+#endif
+
     interface->fStandard = kGLES_GrGLStandard;
     interface->fExtensions.init(kGLES_GrGLStandard, glGetString, NULL, glGetIntegerv);
 
diff --git a/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp b/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp
index f57b80e..f580997 100644
--- a/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp
+++ b/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp
@@ -241,6 +241,12 @@
         GET_PROC(BindFragDataLocationIndexed);
     }
 
+    if (extensions.has("GL_EXT_debug_marker")) {
+        GET_PROC_SUFFIX(InsertEventMarker, EXT);
+        GET_PROC_SUFFIX(PushGroupMarker, EXT);
+        GET_PROC_SUFFIX(PopGroupMarker, EXT);
+    }
+
     interface->fExtensions.swap(&extensions);
     return interface;
 }
diff --git a/src/gpu/gl/mesa/GrGLCreateMesaInterface.cpp b/src/gpu/gl/mesa/GrGLCreateMesaInterface.cpp
index 5931444..0ce6d2f 100644
--- a/src/gpu/gl/mesa/GrGLCreateMesaInterface.cpp
+++ b/src/gpu/gl/mesa/GrGLCreateMesaInterface.cpp
@@ -221,6 +221,12 @@
         }
         GR_GL_GET_PROC(BindFragDataLocationIndexed);
 
+        if (extensions.has("GL_EXT_debug_marker")) {
+            GR_GL_GET_PROC_SUFFIX(InsertEventMarker, EXT);
+            GR_GL_GET_PROC_SUFFIX(PopGroupMarker, EXT);
+            GR_GL_GET_PROC_SUFFIX(PushGroupMarker, EXT);
+        }
+
         interface->fStandard = kGL_GrGLStandard;
         interface->fExtensions.swap(&extensions);
 
diff --git a/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp b/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
index 67d7ef5..8ef5ca2 100644
--- a/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
+++ b/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
@@ -275,6 +275,12 @@
             GR_GL_GET_PROC_SUFFIX(PointAlongPath, NV);
         }
 
+        if (extensions.has("GL_EXT_debug_marker")) {
+            GR_GL_GET_PROC_SUFFIX(InsertEventMarker, EXT);
+            GR_GL_GET_PROC_SUFFIX(PushGroupMarker, EXT);
+            GR_GL_GET_PROC_SUFFIX(PopGroupMarker, EXT);
+        }
+
         interface->fStandard = kGL_GrGLStandard;
         interface->fExtensions.swap(&extensions);
 
diff --git a/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp b/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
index e901b36..645a582 100644
--- a/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
+++ b/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
@@ -304,6 +304,12 @@
             WGL_SET_PROC_SUFFIX(PointAlongPath, NV);
         }
 
+        if (extensions.has("GL_EXT_debug_marker")) {
+            WGL_SET_PROC_SUFFIX(InsertEventMarker, EXT);
+            WGL_SET_PROC_SUFFIX(PushGroupMarker, EXT);
+            WGL_SET_PROC_SUFFIX(PopGroupMarker, EXT);
+        }
+
         interface->fStandard = kGL_GrGLStandard;
         interface->fExtensions.swap(&extensions);