gltrace_fixup.cpp revision 3f194e6e3a62cbb846e8948eac8e4ce9aa7444a6
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 <cutils/log.h> 18#include <GLES2/gl2.h> 19 20#include "gltrace.pb.h" 21#include "gltrace_context.h" 22#include "gltrace_fixup.h" 23 24namespace android { 25namespace gltrace { 26 27unsigned getBytesPerTexel(const GLenum format, const GLenum type) { 28 /* 29 Description from glTexImage2D spec: 30 31 Data is read from data as a sequence of unsigned bytes or shorts, depending on type. 32 When type is GL_UNSIGNED_BYTE, each of the bytes is interpreted as one color component. 33 When type is one of GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, or 34 GL_UNSIGNED_SHORT_5_5_5_1, each unsigned short value is interpreted as containing all 35 the components for a single texel, with the color components arranged according to 36 format. Color components are treated as groups of one, two, three, or four values, 37 again based on format. Groups of components are referred to as texels. 38 39 width × height texels are read from memory, starting at location data. By default, 40 these texels are taken from adjacent memory locations, except that after all width 41 texels are read, the read pointer is advanced to the next four-byte boundary. 42 The four-byte row alignment is specified by glPixelStorei with argument 43 GL_UNPACK_ALIGNMENT, and it can be set to one, two, four, or eight bytes. 44 */ 45 46 switch (type) { 47 case GL_UNSIGNED_SHORT_5_6_5: 48 case GL_UNSIGNED_SHORT_4_4_4_4: 49 case GL_UNSIGNED_SHORT_5_5_5_1: 50 return 2; 51 case GL_UNSIGNED_BYTE: 52 break; 53 default: 54 LOGE("GetBytesPerPixel: unknown type %x", type); 55 } 56 57 switch (format) { 58 case GL_ALPHA: 59 case GL_LUMINANCE: 60 return 1; 61 case GL_LUMINANCE_ALPHA: 62 return 2; 63 case GL_RGB: 64 return 3; 65 case GL_RGBA: 66 case 0x80E1: // GL_BGRA_EXT 67 return 4; 68 default: 69 LOGE("GetBytesPerPixel: unknown format %x", format); 70 } 71 72 return 1; // in doubt... 73} 74 75/** Generic helper function: extract pointer at argIndex and 76 replace it with the C style string at *pointer */ 77void fixup_CStringPtr(int argIndex, GLMessage *glmsg) { 78 GLMessage_DataType *arg = glmsg->mutable_args(argIndex); 79 GLchar *ptr = (GLchar *)arg->intvalue(0); 80 81 arg->set_type(GLMessage::DataType::CHAR); 82 arg->set_isarray(true); 83 arg->add_charvalue(ptr); 84} 85 86void fixup_glGetString(GLMessage *glmsg) { 87 /* const GLubyte* GLTrace_glGetString(GLenum name) */ 88 GLMessage_DataType *ret = glmsg->mutable_returnvalue(); 89 GLchar *ptr = (GLchar *)ret->intvalue(0); 90 91 if (ptr != NULL) { 92 ret->set_type(GLMessage::DataType::CHAR); 93 ret->set_isarray(true); 94 ret->add_charvalue(ptr); 95 } 96} 97 98/* Add the contents of the framebuffer to the protobuf message */ 99void fixup_addFBContents(GLTraceContext *context, GLMessage *glmsg, FBBinding fbToRead) { 100 void *fbcontents; 101 unsigned fbsize, fbwidth, fbheight; 102 context->getCompressedFB(&fbcontents, &fbsize, &fbwidth, &fbheight, fbToRead); 103 104 GLMessage_FrameBuffer *fb = glmsg->mutable_fb(); 105 fb->set_width(fbwidth); 106 fb->set_height(fbheight); 107 fb->add_contents(fbcontents, fbsize); 108} 109 110void fixup_glTexImage2D(GLMessage *glmsg) { 111 /* void glTexImage2D(GLenum target, 112 GLint level, 113 GLint internalformat, 114 GLsizei width, 115 GLsizei height, 116 GLint border, 117 GLenum format, 118 GLenum type, 119 const GLvoid *data); 120 */ 121 GLMessage_DataType arg_width = glmsg->args(3); 122 GLMessage_DataType arg_height = glmsg->args(4); 123 GLMessage_DataType arg_format = glmsg->args(6); 124 GLMessage_DataType arg_type = glmsg->args(7); 125 GLMessage_DataType *arg_data = glmsg->mutable_args(8); 126 127 GLsizei width = arg_width.intvalue(0); 128 GLsizei height = arg_height.intvalue(0); 129 GLenum format = arg_format.intvalue(0); 130 GLenum type = arg_type.intvalue(0); 131 void *data = (void *)arg_data->intvalue(0); 132 133 int bytesPerTexel = getBytesPerTexel(format, type); 134 135 arg_data->set_type(GLMessage::DataType::BYTE); 136 arg_data->set_isarray(true); 137 arg_data->clear_rawbytes(); 138 139 if (data != NULL) { 140 arg_data->add_rawbytes(data, bytesPerTexel * width * height); 141 } else { 142 LOGE("fixup_glTexImage2D: image data is NULL.\n"); 143 arg_data->set_type(GLMessage::DataType::VOID); 144 // FIXME: 145 // This will create the texture, but it will be uninitialized. 146 // It can later be initialized with glTexSubImage2D or by 147 // attaching an FBO to it and rendering into the FBO. 148 } 149} 150 151void fixup_glShaderSource(GLMessage *glmsg) { 152 /* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string, 153 const GLint* length) */ 154 GLMessage_DataType arg_count = glmsg->args(1); 155 GLMessage_DataType arg_lenp = glmsg->args(3); 156 GLMessage_DataType *arg_strpp = glmsg->mutable_args(2); 157 158 GLsizei count = arg_count.intvalue(0); 159 GLchar **stringpp = (GLchar **)arg_strpp->intvalue(0); 160 GLint *lengthp = (GLint *)arg_lenp.intvalue(0); 161 162 arg_strpp->set_type(GLMessage::DataType::CHAR); 163 arg_strpp->set_isarray(true); 164 arg_strpp->clear_charvalue(); 165 166 ::std::string src = ""; 167 for (int i = 0; i < count; i++) { 168 if (lengthp != NULL) 169 src.append(*stringpp, *lengthp); 170 else 171 src.append(*stringpp); // assume null terminated 172 stringpp++; 173 lengthp++; 174 } 175 176 arg_strpp->add_charvalue(src); 177} 178 179void fixup_glUniformGeneric(int argIndex, int nFloats, GLMessage *glmsg) { 180 GLMessage_DataType *arg_values = glmsg->mutable_args(argIndex); 181 GLfloat *src = (GLfloat*)arg_values->intvalue(0); 182 183 arg_values->set_type(GLMessage::DataType::FLOAT); 184 arg_values->set_isarray(true); 185 arg_values->clear_floatvalue(); 186 187 for (int i = 0; i < nFloats; i++) { 188 arg_values->add_floatvalue(*src++); 189 } 190} 191 192void fixup_glUniformMatrixGeneric(int matrixSize, GLMessage *glmsg) { 193 /* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose, 194 const GLfloat* value) */ 195 GLMessage_DataType arg_count = glmsg->args(1); 196 int n_matrices = arg_count.intvalue(0); 197 fixup_glUniformGeneric(3, matrixSize * matrixSize * n_matrices, glmsg); 198} 199 200void fixup_GenericIntArray(int argIndex, int nInts, GLMessage *glmsg) { 201 GLMessage_DataType *arg_intarray = glmsg->mutable_args(argIndex); 202 GLint *intp = (GLint *)arg_intarray->intvalue(0); 203 204 arg_intarray->set_type(GLMessage::DataType::INT); 205 arg_intarray->set_isarray(true); 206 arg_intarray->clear_intvalue(); 207 208 for (int i = 0; i < nInts; i++, intp++) { 209 arg_intarray->add_intvalue(*intp); 210 } 211} 212 213void fixup_glGenGeneric(GLMessage *glmsg) { 214 /* void glGen*(GLsizei n, GLuint * buffers); */ 215 GLMessage_DataType arg_n = glmsg->args(0); 216 GLsizei n = arg_n.intvalue(0); 217 218 fixup_GenericIntArray(1, n, glmsg); 219} 220 221void fixup_glGetBooleanv(GLMessage *glmsg) { 222 /* void glGetBooleanv(GLenum pname, GLboolean *params); */ 223 GLMessage_DataType *arg_params = glmsg->mutable_args(1); 224 GLboolean *src = (GLboolean*)arg_params->intvalue(0); 225 226 arg_params->set_type(GLMessage::DataType::BOOL); 227 arg_params->set_isarray(true); 228 arg_params->clear_boolvalue(); 229 arg_params->add_boolvalue(*src); 230} 231 232void fixup_glGetFloatv(GLMessage *glmsg) { 233 /* void glGetFloatv(GLenum pname, GLfloat *params); */ 234 GLMessage_DataType *arg_params = glmsg->mutable_args(1); 235 GLfloat *src = (GLfloat*)arg_params->intvalue(0); 236 237 arg_params->set_type(GLMessage::DataType::FLOAT); 238 arg_params->set_isarray(true); 239 arg_params->clear_floatvalue(); 240 arg_params->add_floatvalue(*src); 241} 242 243void fixupGLMessage(GLTraceContext *context, nsecs_t start, nsecs_t end, GLMessage *glmsg) { 244 // for all messages, set the current context id 245 glmsg->set_context_id(context->getId()); 246 247 // set start time and duration 248 glmsg->set_start_time(start); 249 glmsg->set_duration((unsigned)(end - start)); 250 251 // do any custom message dependent processing 252 switch (glmsg->function()) { 253 case GLMessage::glGenBuffers: /* void glGenBuffers(GLsizei n, GLuint * buffers); */ 254 case GLMessage::glGenFramebuffers: /* void glGenFramebuffers(GLsizei n, GLuint * buffers); */ 255 case GLMessage::glGenRenderbuffers: /* void glGenFramebuffers(GLsizei n, GLuint * buffers); */ 256 case GLMessage::glGenTextures: /* void glGenTextures(GLsizei n, GLuint * buffers); */ 257 fixup_glGenGeneric(glmsg); 258 break; 259 case GLMessage::glGetAttribLocation: 260 case GLMessage::glGetUniformLocation: 261 /* int glGetAttribLocation(GLuint program, const GLchar* name) */ 262 /* int glGetUniformLocation(GLuint program, const GLchar* name) */ 263 fixup_CStringPtr(1, glmsg); 264 break; 265 case GLMessage::glGetBooleanv: 266 fixup_glGetBooleanv(glmsg); 267 break; 268 case GLMessage::glGetFloatv: 269 fixup_glGetFloatv(glmsg); 270 break; 271 case GLMessage::glGetIntegerv: /* void glGetIntegerv(GLenum pname, GLint *params); */ 272 fixup_GenericIntArray(1, 1, glmsg); 273 break; 274 case GLMessage::glGetProgramiv: 275 case GLMessage::glGetRenderbufferParameteriv: 276 case GLMessage::glGetShaderiv: 277 /* void glGetProgramiv(GLuint program, GLenum pname, GLint* params) */ 278 /* void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) */ 279 /* void glGetShaderiv(GLuint shader, GLenum pname, GLint* params) */ 280 fixup_GenericIntArray(2, 1, glmsg); 281 break; 282 case GLMessage::glGetString: 283 fixup_glGetString(glmsg); 284 break; 285 case GLMessage::glTexImage2D: 286 if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) { 287 fixup_glTexImage2D(glmsg); 288 } 289 break; 290 case GLMessage::glShaderSource: 291 fixup_glShaderSource(glmsg); 292 break; 293 case GLMessage::glUniformMatrix2fv: 294 /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, 295 const GLfloat* value) */ 296 fixup_glUniformMatrixGeneric(2, glmsg); 297 break; 298 case GLMessage::glUniformMatrix3fv: 299 /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, 300 const GLfloat* value) */ 301 fixup_glUniformMatrixGeneric(3, glmsg); 302 break; 303 case GLMessage::glUniformMatrix4fv: 304 /* void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, 305 const GLfloat* value) */ 306 fixup_glUniformMatrixGeneric(4, glmsg); 307 break; 308 case GLMessage::glDrawArrays: 309 /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */ 310 if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) { 311 fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB); 312 } 313 break; 314 case GLMessage::glDrawElements: 315 /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */ 316 if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) { 317 fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB); 318 } 319 break; 320 default: 321 break; 322 } 323} 324 325}; 326}; 327