1 /* 2 * Copyright 2011, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <arpa/inet.h> 18 #include <stdlib.h> 19 #include <cutils/log.h> 20 #include <cutils/properties.h> 21 22 #include "hooks.h" 23 #include "glestrace.h" 24 25 #include "gltrace_context.h" 26 #include "gltrace_egl.h" 27 #include "gltrace_hooks.h" 28 #include "gltrace_transport.h" 29 30 namespace android { 31 32 using gltrace::GLTraceState; 33 using gltrace::GLTraceContext; 34 using gltrace::TCPStream; 35 36 static GLTraceState *sGLTraceState; 37 static pthread_t sReceiveThreadId; 38 39 /** 40 * Task that monitors the control stream from the host and updates 41 * the trace status according to commands received from the host. 42 */ 43 static void *commandReceiveTask(void *arg) { 44 GLTraceState *state = (GLTraceState *)arg; 45 TCPStream *stream = state->getStream(); 46 47 // The control stream always receives an integer size of the 48 // command buffer, followed by the actual command buffer. 49 uint32_t cmdSize; 50 51 // Command Buffer 52 void *cmdBuf = NULL; 53 uint32_t cmdBufSize = 0; 54 55 enum TraceSettingsMasks { 56 READ_FB_ON_EGLSWAP_MASK = 1 << 0, 57 READ_FB_ON_GLDRAW_MASK = 1 << 1, 58 READ_TEXTURE_DATA_ON_GLTEXIMAGE_MASK = 1 << 2, 59 }; 60 61 while (true) { 62 // read command size 63 if (stream->receive(&cmdSize, sizeof(uint32_t)) < 0) { 64 break; 65 } 66 cmdSize = ntohl(cmdSize); 67 68 // ensure command buffer is of required size 69 if (cmdBufSize < cmdSize) { 70 free(cmdBuf); 71 cmdBufSize = cmdSize; 72 cmdBuf = malloc(cmdSize); 73 if (cmdBuf == NULL) 74 break; 75 } 76 77 // receive the command 78 if (stream->receive(cmdBuf, cmdSize) < 0) { 79 break; 80 } 81 82 if (cmdSize != sizeof(uint32_t)) { 83 // Currently, we only support commands that are a single integer, 84 // so we skip all other commands 85 continue; 86 } 87 88 uint32_t cmd = ntohl(*(uint32_t*)cmdBuf); 89 90 bool collectFbOnEglSwap = (cmd & READ_FB_ON_EGLSWAP_MASK) != 0; 91 bool collectFbOnGlDraw = (cmd & READ_FB_ON_GLDRAW_MASK) != 0; 92 bool collectTextureData = (cmd & READ_TEXTURE_DATA_ON_GLTEXIMAGE_MASK) != 0; 93 94 state->setCollectFbOnEglSwap(collectFbOnEglSwap); 95 state->setCollectFbOnGlDraw(collectFbOnGlDraw); 96 state->setCollectTextureDataOnGlTexImage(collectTextureData); 97 98 ALOGD("trace options: eglswap: %d, gldraw: %d, texImage: %d", 99 collectFbOnEglSwap, collectFbOnGlDraw, collectTextureData); 100 } 101 102 ALOGE("Stopping OpenGL Trace Command Receiver\n"); 103 104 free(cmdBuf); 105 return NULL; 106 } 107 108 void GLTrace_start() { 109 char udsName[PROPERTY_VALUE_MAX]; 110 111 property_get("debug.egl.debug_portname", udsName, "gltrace"); 112 int clientSocket = gltrace::acceptClientConnection(udsName); 113 if (clientSocket < 0) { 114 ALOGE("Error creating GLTrace server socket. Quitting application."); 115 exit(-1); 116 } 117 118 // create communication channel to the host 119 TCPStream *stream = new TCPStream(clientSocket); 120 121 // initialize tracing state 122 sGLTraceState = new GLTraceState(stream); 123 124 pthread_create(&sReceiveThreadId, NULL, commandReceiveTask, sGLTraceState); 125 } 126 127 void GLTrace_stop() { 128 delete sGLTraceState; 129 sGLTraceState = NULL; 130 } 131 132 void GLTrace_eglCreateContext(int version, EGLContext c) { 133 // update trace state for new EGL context 134 GLTraceContext *traceContext = sGLTraceState->createTraceContext(version, c); 135 gltrace::setupTraceContextThreadSpecific(traceContext); 136 137 // trace command through to the host 138 gltrace::GLTrace_eglCreateContext(version, traceContext->getId()); 139 } 140 141 void GLTrace_eglMakeCurrent(const unsigned version, gl_hooks_t *hooks, EGLContext c) { 142 // setup per context state 143 GLTraceContext *traceContext = sGLTraceState->getTraceContext(c); 144 traceContext->hooks = hooks; 145 gltrace::setupTraceContextThreadSpecific(traceContext); 146 147 // trace command through to the host 148 gltrace::GLTrace_eglMakeCurrent(traceContext->getId()); 149 } 150 151 void GLTrace_eglReleaseThread() { 152 gltrace::releaseContext(); 153 } 154 155 void GLTrace_eglSwapBuffers(void *dpy, void *draw) { 156 gltrace::GLTrace_eglSwapBuffers(dpy, draw); 157 } 158 159 gl_hooks_t *GLTrace_getGLHooks() { 160 return gltrace::getGLHooks(); 161 } 162 163 } 164