diff options
author | Siva Velusamy <vsiva@google.com> | 2012-12-18 14:56:55 -0800 |
---|---|---|
committer | Siva Velusamy <vsiva@google.com> | 2012-12-20 10:38:47 -0800 |
commit | a73a97728befb5ba5ad647ab3b60058c4d536ba4 (patch) | |
tree | 8636701bc18989ad4d7c9e9948b8c744de2c84d1 /opengl/libs/GLES_trace | |
parent | 0859b78db2b094d20efb7b3e725c4732fcdeb4d5 (diff) | |
download | frameworks_native-a73a97728befb5ba5ad647ab3b60058c4d536ba4.zip frameworks_native-a73a97728befb5ba5ad647ab3b60058c4d536ba4.tar.gz frameworks_native-a73a97728befb5ba5ad647ab3b60058c4d536ba4.tar.bz2 |
gltrace: Add support for tracing running applications.
Currently, to activate OpenGL tracing, an application has to be
start with --opengl-trace option (or have a debug prop set).
This CL adds support for tracing an application which may already
be running. This is implemented as follows:
- DDMS initiates a JDWP message to the VM indicating that
opengl traces be enabled.
- When that message is received, a flag is set that indicates
that tracing should be enabled.
- The trace flag is checked during every eglSwap() operation,
and if it finds that tracing should be active and it isn't,
then it starts the tracing component.
Change-Id: I3347fe89fc06c7404d7aa9360f4b21e5bf36ebcb
Diffstat (limited to 'opengl/libs/GLES_trace')
-rw-r--r-- | opengl/libs/GLES_trace/DESIGN.txt | 34 | ||||
-rw-r--r-- | opengl/libs/GLES_trace/src/gltrace_eglapi.cpp | 67 |
2 files changed, 88 insertions, 13 deletions
diff --git a/opengl/libs/GLES_trace/DESIGN.txt b/opengl/libs/GLES_trace/DESIGN.txt index a189e1d..72a2e15 100644 --- a/opengl/libs/GLES_trace/DESIGN.txt +++ b/opengl/libs/GLES_trace/DESIGN.txt @@ -9,9 +9,6 @@ Code Runtime Behavior: control whether tracing should be enabled for a certain process. If tracing is enabled, this calls GLTrace_start() to start the trace server. - Note that initEglTraceLevel() is also called from early_egl_init(), but that happens in the - context of the zygote, so that invocation has no effect. - egl_display_t::initialize() then calls setGLHooksThreadSpecific() where we set the thread specific gl_hooks structure to point to the trace implementation. From this point on, every GLES call is redirected to the trace implementation. @@ -30,6 +27,37 @@ Code Runtime Behavior: to explore if a more graceful method of stopping the application, or detaching tracing from the application is required. + +Enabling tracing while the application is running: + + In order to allow tracing of an already running application, we allow DdmServer to enable + OpenGL tracing. In such a case, the application already has its GL hooks set up to point to the + real GL implementation, and we need to switch them to point to the trace implementation. + + This is achieved by checking whether tracing should be enabled at every eglSwap call. + (Note: We were already checking for tracing at every eglSwap, the only change now is that + the tracing could actually be ON/OFF at runtime - earlier it was set once and never changed). + + If eglSwap detects that tracing should be enabled now, then it performs the following steps: + - switch the gl hooks to point to the trace implementation. + - call trace eglMakeCurrent to indicate that there is now a new context that is current. + - continue on with tracing the eglSwap call. + This switches the hooks to point to the trace implementation only for the current context. + But the other contexts have their gl hooks updated when they perform eglMakeCurrent. + + The GLTrace version of eglMakeCurrent now has to be updated to allow switching to a context + it may not know of. In such a case, it creates a context matching the version that it is now + switching to. + +Disabling tracing: + + We disable tracing under two conditions: + - stop tracing request from DdmServer + - gltrace transport gets disconnected from the host. + In either case, both actions simply disable the tracing flag. The current context gets its + gl hooks restored in the next eglSwap, and the other traced contexts get their gl hooks + restored when they perform a eglMakeCurrent. + Code Structure: glestrace.h declares all the hooks exposed by libglestrace. These are used by EGL/egl.cpp and diff --git a/opengl/libs/GLES_trace/src/gltrace_eglapi.cpp b/opengl/libs/GLES_trace/src/gltrace_eglapi.cpp index 9698bf9..512d562 100644 --- a/opengl/libs/GLES_trace/src/gltrace_eglapi.cpp +++ b/opengl/libs/GLES_trace/src/gltrace_eglapi.cpp @@ -33,6 +33,9 @@ using gltrace::GLTraceState; using gltrace::GLTraceContext; using gltrace::TCPStream; +static pthread_mutex_t sGlTraceStateLock = PTHREAD_MUTEX_INITIALIZER; + +static int sGlTraceInProgress; static GLTraceState *sGLTraceState; static pthread_t sReceiveThreadId; @@ -105,33 +108,66 @@ static void *commandReceiveTask(void *arg) { return NULL; } -void GLTrace_start() { - char udsName[PROPERTY_VALUE_MAX]; +/** + * Starts Trace Server and waits for connection from the host. + * Returns -1 in case of connection error, 0 otherwise. + */ +int GLTrace_start() { + int status = 0; + int clientSocket = -1; + TCPStream *stream = NULL; + + pthread_mutex_lock(&sGlTraceStateLock); + if (sGlTraceInProgress) { + goto done; + } + + char udsName[PROPERTY_VALUE_MAX]; property_get("debug.egl.debug_portname", udsName, "gltrace"); - int clientSocket = gltrace::acceptClientConnection(udsName); + clientSocket = gltrace::acceptClientConnection(udsName); if (clientSocket < 0) { - ALOGE("Error creating GLTrace server socket. Quitting application."); - exit(-1); + ALOGE("Error creating GLTrace server socket. Tracing disabled."); + status = -1; + goto done; } + sGlTraceInProgress = 1; + // create communication channel to the host - TCPStream *stream = new TCPStream(clientSocket); + stream = new TCPStream(clientSocket); // initialize tracing state sGLTraceState = new GLTraceState(stream); pthread_create(&sReceiveThreadId, NULL, commandReceiveTask, sGLTraceState); + +done: + pthread_mutex_unlock(&sGlTraceStateLock); + return status; } void GLTrace_stop() { - delete sGLTraceState; - sGLTraceState = NULL; + pthread_mutex_lock(&sGlTraceStateLock); + + if (sGlTraceInProgress) { + sGlTraceInProgress = 0; + delete sGLTraceState; + sGLTraceState = NULL; + } + + pthread_mutex_unlock(&sGlTraceStateLock); } void GLTrace_eglCreateContext(int version, EGLContext c) { + pthread_mutex_lock(&sGlTraceStateLock); + GLTraceState *state = sGLTraceState; + pthread_mutex_unlock(&sGlTraceStateLock); + + if (state == NULL) return; + // update trace state for new EGL context - GLTraceContext *traceContext = sGLTraceState->createTraceContext(version, c); + GLTraceContext *traceContext = state->createTraceContext(version, c); gltrace::setupTraceContextThreadSpecific(traceContext); // trace command through to the host @@ -139,8 +175,19 @@ void GLTrace_eglCreateContext(int version, EGLContext c) { } void GLTrace_eglMakeCurrent(const unsigned version, gl_hooks_t *hooks, EGLContext c) { + pthread_mutex_lock(&sGlTraceStateLock); + GLTraceState *state = sGLTraceState; + pthread_mutex_unlock(&sGlTraceStateLock); + + if (state == NULL) return; + // setup per context state - GLTraceContext *traceContext = sGLTraceState->getTraceContext(c); + GLTraceContext *traceContext = state->getTraceContext(c); + if (traceContext == NULL) { + GLTrace_eglCreateContext(version, c); + traceContext = state->getTraceContext(c); + } + traceContext->hooks = hooks; gltrace::setupTraceContextThreadSpecific(traceContext); |