Merge "Add runtime debugging capabilities to OpenGL" into jb-mr1-dev
diff --git a/include/utils/Trace.h b/include/utils/Trace.h
index e5cc7ec..93e2285 100644
--- a/include/utils/Trace.h
+++ b/include/utils/Trace.h
@@ -67,6 +67,11 @@
 // function body.
 #define ATRACE_CALL() android::ScopedTrace ___tracer(ATRACE_TAG, __FUNCTION__)
 
+// ATRACE_NAME traces the beginning and end of the current function.  To trace
+// the correct start and end times this macro should be the first line of the
+// function body.
+#define ATRACE_NAME(name) android::ScopedTrace ___tracer(ATRACE_TAG, name)
+
 // ATRACE_INT traces a named integer value.  This can be used to track how the
 // value changes over time in a trace.
 #define ATRACE_INT(name, value) android::Tracer::traceCounter(ATRACE_TAG, name, value)
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 7ca210c..96e1cba 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -62,12 +62,18 @@
 // ----------------------------------------------------------------------------
 
 /**
- * There are two different tracing methods:
- * 1. libs/EGL/trace.cpp: Traces all functions to logcat.
+ * There are three different tracing methods:
+ * 1. libs/EGL/trace.cpp: Traces all functions to systrace.
+ *    To enable:
+ *      - set system property "debug.egl.trace" to "systrace" to trace all apps.
+ * 2. libs/EGL/trace.cpp: Logs a stack trace for GL errors after each function call.
+ *    To enable:
+ *      - set system property "debug.egl.trace" to "error" to trace all apps.
+ * 3. libs/EGL/trace.cpp: Traces all functions to logcat.
  *    To enable:
  *      - set system property "debug.egl.trace" to 1 to trace all apps.
  *      - or call setGLTraceLevel(1) from an app to enable tracing for that app.
- * 2. libs/GLES_trace: Traces all functions via protobuf to host.
+ * 4. libs/GLES_trace: Traces all functions via protobuf to host.
  *    To enable:
  *        - set system property "debug.egl.debug_proc" to the application name.
  *      - or call setGLDebugLevel(1) from the app.
@@ -75,10 +81,15 @@
 static int sEGLTraceLevel;
 static int sEGLApplicationTraceLevel;
 
+static bool sEGLSystraceEnabled;
+static bool sEGLGetErrorEnabled;
+
 int gEGLDebugLevel;
 static int sEGLApplicationDebugLevel;
 
 extern gl_hooks_t gHooksTrace;
+extern gl_hooks_t gHooksSystrace;
+extern gl_hooks_t gHooksErrorTrace;
 
 static inline void setGlTraceThreadSpecific(gl_hooks_t const *value) {
     pthread_setspecific(gGLTraceKey, value);
@@ -91,6 +102,20 @@
 void initEglTraceLevel() {
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.egl.trace", value, "0");
+
+    sEGLGetErrorEnabled = !strcasecmp(value, "error");
+    if (sEGLGetErrorEnabled) {
+        sEGLSystraceEnabled = false;
+        sEGLTraceLevel = 0;
+        return;
+    }
+
+    sEGLSystraceEnabled = !strcasecmp(value, "systrace");
+    if (sEGLSystraceEnabled) {
+        sEGLTraceLevel = 0;
+        return;
+    }
+
     int propertyLevel = atoi(value);
     int applicationLevel = sEGLApplicationTraceLevel;
     sEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
@@ -125,7 +150,13 @@
 }
 
 void setGLHooksThreadSpecific(gl_hooks_t const *value) {
-    if (sEGLTraceLevel > 0) {
+    if (sEGLGetErrorEnabled) {
+        setGlTraceThreadSpecific(value);
+        setGlThreadSpecific(&gHooksErrorTrace);
+    } else if (sEGLSystraceEnabled) {
+        setGlTraceThreadSpecific(value);
+        setGlThreadSpecific(&gHooksSystrace);
+    } else if (sEGLTraceLevel > 0) {
         setGlTraceThreadSpecific(value);
         setGlThreadSpecific(&gHooksTrace);
     } else if (gEGLDebugLevel > 0 && value != &gHooksNoContext) {
diff --git a/opengl/libs/EGL/trace.cpp b/opengl/libs/EGL/trace.cpp
index 52907c1..a51b086 100644
--- a/opengl/libs/EGL/trace.cpp
+++ b/opengl/libs/EGL/trace.cpp
@@ -26,6 +26,11 @@
 
 #include <cutils/log.h>
 
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <utils/Trace.h>
+
+#include <utils/CallStack.h>
+
 #include "egl_tls.h"
 #include "hooks.h"
 
@@ -314,6 +319,10 @@
     va_end(argp);
 }
 
+///////////////////////////////////////////////////////////////////////////
+// Log trace
+///////////////////////////////////////////////////////////////////////////
+
 #undef TRACE_GL_VOID
 #undef TRACE_GL
 
@@ -349,7 +358,6 @@
 };
 #undef GL_ENTRY
 
-
 #undef TRACE_GL_VOID
 #undef TRACE_GL
 
@@ -372,6 +380,99 @@
 #include "../debug.in"
 }
 
+///////////////////////////////////////////////////////////////////////////
+// Systrace
+///////////////////////////////////////////////////////////////////////////
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
+static void Systrace_ ## _api _args {                                     \
+    ATRACE_NAME(#_api);                                                   \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    _c->_api _argList;                                                    \
+}
+
+#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
+static _type Systrace_ ## _api _args {                                    \
+    ATRACE_NAME(#_api);                                                   \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    return _c->_api _argList;                                             \
+}
+
+extern "C" {
+#include "../trace.in"
+}
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define GL_ENTRY(_r, _api, ...) Systrace_ ## _api,
+EGLAPI gl_hooks_t gHooksSystrace = {
+    {
+        #include "entries.in"
+    },
+    {
+        {0}
+    }
+};
+#undef GL_ENTRY
+
+///////////////////////////////////////////////////////////////////////////
+//
+///////////////////////////////////////////////////////////////////////////
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define CHECK_ERROR(_c, _api)                                             \
+    GLenum status = GL_NO_ERROR;                                          \
+    bool error = false;                                                   \
+    while ((status = _c->glGetError()) != GL_NO_ERROR) {                  \
+        ALOGD("[" #_api "] 0x%x", status);                                \
+        error = true;                                                     \
+    }                                                                     \
+    if (error) {                                                          \
+        CallStack s;                                                      \
+        s.update();                                                       \
+        s.dump("glGetError:" #_api);                                      \
+    }                                                                     \
+
+#define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
+static void ErrorTrace_ ## _api _args {                                   \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    _c->_api _argList;                                                    \
+    CHECK_ERROR(_c, _api);                                                \
+}
+
+#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
+static _type ErrorTrace_ ## _api _args {                                  \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    _type _r = _c->_api _argList;                                         \
+    CHECK_ERROR(_c, _api);                                                \
+    return _r;                                                            \
+}
+
+extern "C" {
+#include "../trace.in"
+}
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define GL_ENTRY(_r, _api, ...) ErrorTrace_ ## _api,
+EGLAPI gl_hooks_t gHooksErrorTrace = {
+    {
+        #include "entries.in"
+    },
+    {
+        {0}
+    }
+};
+#undef GL_ENTRY
+#undef CHECK_ERROR
+
 #undef TRACE_GL_VOID
 #undef TRACE_GL
 
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index 2d0045e..55ef499 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -26,11 +26,6 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <utils/Trace.h>
-
-#include <utils/CallStack.h>
-
 #include "hooks.h"
 #include "egl_impl.h"
 
@@ -44,10 +39,6 @@
 #undef CALL_GL_API
 #undef CALL_GL_API_RETURN
 
-#define DEBUG_CALL_GL_API 0
-#define DEBUG_PRINT_CALL_STACK_ON_ERROR 0
-#define SYSTRACE_CALL_GL_API 0
-
 #if USE_FAST_TLS_KEY
 
     #ifdef HAVE_ARM_TLS_REGISTER
@@ -83,38 +74,10 @@
 
     #define API_ENTRY(_api) _api
 
-#if DEBUG_CALL_GL_API
-
-    #define CALL_GL_API(_api, ...)                                       \
-        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
-        _c->_api(__VA_ARGS__); \
-        GLenum status = GL_NO_ERROR; \
-        bool error = false; \
-        while ((status = glGetError()) != GL_NO_ERROR) { \
-            ALOGD("[" #_api "] 0x%x", status); \
-            error = true; \
-        } \
-        if (DEBUG_PRINT_CALL_STACK_ON_ERROR && error) { \
-            CallStack s; \
-            s.update(); \
-            s.dump("glGetError:" #_api); \
-        }
-
-#elif SYSTRACE_CALL_GL_API
-
-    #define CALL_GL_API(_api, ...)                                       \
-        ATRACE_CALL();                                                   \
-        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
-        _c->_api(__VA_ARGS__);
-
-#else
-
     #define CALL_GL_API(_api, ...)                                       \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
         _c->_api(__VA_ARGS__);
 
-#endif
-
     #define CALL_GL_API_RETURN(_api, ...)                                \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
         return _c->_api(__VA_ARGS__)