gltrace_fixup.cpp revision a7167f364737c12e621d836f470cf328c6e111cd
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 ALOGE("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 ALOGE("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 110/** Common fixup routing for glTexImage2D & glTexSubImage2D. */ 111void fixup_glTexImage(int widthIndex, int heightIndex, GLMessage *glmsg) { 112 GLMessage_DataType arg_width = glmsg->args(widthIndex); 113 GLMessage_DataType arg_height = glmsg->args(heightIndex); 114 115 GLMessage_DataType arg_format = glmsg->args(6); 116 GLMessage_DataType arg_type = glmsg->args(7); 117 GLMessage_DataType *arg_data = glmsg->mutable_args(8); 118 119 GLsizei width = arg_width.intvalue(0); 120 GLsizei height = arg_height.intvalue(0); 121 GLenum format = arg_format.intvalue(0); 122 GLenum type = arg_type.intvalue(0); 123 void *data = (void *)arg_data->intvalue(0); 124 125 int bytesPerTexel = getBytesPerTexel(format, type); 126 127 arg_data->set_type(GLMessage::DataType::BYTE); 128 arg_data->clear_rawbytes(); 129 130 if (data != NULL) { 131 arg_data->set_isarray(true); 132 arg_data->add_rawbytes(data, bytesPerTexel * width * height); 133 } else { 134 arg_data->set_isarray(false); 135 arg_data->set_type(GLMessage::DataType::VOID); 136 } 137} 138 139 140void fixup_glTexImage2D(GLMessage *glmsg) { 141 /* void glTexImage2D(GLenum target, 142 GLint level, 143 GLint internalformat, 144 GLsizei width, 145 GLsizei height, 146 GLint border, 147 GLenum format, 148 GLenum type, 149 const GLvoid *data); 150 */ 151 int widthIndex = 3; 152 int heightIndex = 4; 153 fixup_glTexImage(widthIndex, heightIndex, glmsg); 154} 155 156void fixup_glTexSubImage2D(GLMessage *glmsg) { 157 /* 158 void glTexSubImage2D(GLenum target, 159 GLint level, 160 GLint xoffset, 161 GLint yoffset, 162 GLsizei width, 163 GLsizei height, 164 GLenum format, 165 GLenum type, 166 const GLvoid * data); 167 */ 168 int widthIndex = 4; 169 int heightIndex = 5; 170 fixup_glTexImage(widthIndex, heightIndex, glmsg); 171} 172 173void fixup_glShaderSource(GLMessage *glmsg) { 174 /* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string, 175 const GLint* length) */ 176 GLMessage_DataType arg_count = glmsg->args(1); 177 GLMessage_DataType arg_lenp = glmsg->args(3); 178 GLMessage_DataType *arg_strpp = glmsg->mutable_args(2); 179 180 GLsizei count = arg_count.intvalue(0); 181 GLchar **stringpp = (GLchar **)arg_strpp->intvalue(0); 182 GLint *lengthp = (GLint *)arg_lenp.intvalue(0); 183 184 arg_strpp->set_type(GLMessage::DataType::CHAR); 185 arg_strpp->set_isarray(true); 186 arg_strpp->clear_charvalue(); 187 188 ::std::string src = ""; 189 for (int i = 0; i < count; i++) { 190 if (lengthp != NULL) 191 src.append(*stringpp, *lengthp); 192 else 193 src.append(*stringpp); // assume null terminated 194 stringpp++; 195 lengthp++; 196 } 197 198 arg_strpp->add_charvalue(src); 199} 200 201void fixup_glUniformGeneric(int argIndex, int nFloats, GLMessage *glmsg) { 202 GLMessage_DataType *arg_values = glmsg->mutable_args(argIndex); 203 GLfloat *src = (GLfloat*)arg_values->intvalue(0); 204 205 arg_values->set_type(GLMessage::DataType::FLOAT); 206 arg_values->set_isarray(true); 207 arg_values->clear_floatvalue(); 208 209 for (int i = 0; i < nFloats; i++) { 210 arg_values->add_floatvalue(*src++); 211 } 212} 213 214void fixup_glUniformMatrixGeneric(int matrixSize, GLMessage *glmsg) { 215 /* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose, 216 const GLfloat* value) */ 217 GLMessage_DataType arg_count = glmsg->args(1); 218 int n_matrices = arg_count.intvalue(0); 219 fixup_glUniformGeneric(3, matrixSize * matrixSize * n_matrices, glmsg); 220} 221 222void fixup_GenericIntArray(int argIndex, int nInts, GLMessage *glmsg) { 223 GLMessage_DataType *arg_intarray = glmsg->mutable_args(argIndex); 224 GLint *intp = (GLint *)arg_intarray->intvalue(0); 225 226 arg_intarray->set_type(GLMessage::DataType::INT); 227 arg_intarray->set_isarray(true); 228 arg_intarray->clear_intvalue(); 229 230 for (int i = 0; i < nInts; i++, intp++) { 231 arg_intarray->add_intvalue(*intp); 232 } 233} 234 235void fixup_glGenGeneric(GLMessage *glmsg) { 236 /* void glGen*(GLsizei n, GLuint * buffers); */ 237 GLMessage_DataType arg_n = glmsg->args(0); 238 GLsizei n = arg_n.intvalue(0); 239 240 fixup_GenericIntArray(1, n, glmsg); 241} 242 243void fixup_glDeleteGeneric(GLMessage *glmsg) { 244 /* void glDelete*(GLsizei n, GLuint *buffers); */ 245 GLMessage_DataType arg_n = glmsg->args(0); 246 GLsizei n = arg_n.intvalue(0); 247 248 fixup_GenericIntArray(1, n, glmsg); 249} 250 251void fixup_glGetBooleanv(GLMessage *glmsg) { 252 /* void glGetBooleanv(GLenum pname, GLboolean *params); */ 253 GLMessage_DataType *arg_params = glmsg->mutable_args(1); 254 GLboolean *src = (GLboolean*)arg_params->intvalue(0); 255 256 arg_params->set_type(GLMessage::DataType::BOOL); 257 arg_params->set_isarray(true); 258 arg_params->clear_boolvalue(); 259 arg_params->add_boolvalue(*src); 260} 261 262void fixup_glGetFloatv(GLMessage *glmsg) { 263 /* void glGetFloatv(GLenum pname, GLfloat *params); */ 264 GLMessage_DataType *arg_params = glmsg->mutable_args(1); 265 GLfloat *src = (GLfloat*)arg_params->intvalue(0); 266 267 arg_params->set_type(GLMessage::DataType::FLOAT); 268 arg_params->set_isarray(true); 269 arg_params->clear_floatvalue(); 270 arg_params->add_floatvalue(*src); 271} 272 273void fixupGLMessage(GLTraceContext *context, nsecs_t start, nsecs_t end, GLMessage *glmsg) { 274 // for all messages, set the current context id 275 glmsg->set_context_id(context->getId()); 276 277 // set start time and duration 278 glmsg->set_start_time(start); 279 glmsg->set_duration((unsigned)(end - start)); 280 281 // do any custom message dependent processing 282 switch (glmsg->function()) { 283 case GLMessage::glDeleteBuffers: /* glDeleteBuffers(GLsizei n, GLuint *buffers); */ 284 case GLMessage::glDeleteFramebuffers: /* glDeleteFramebuffers(GLsizei n, GLuint *buffers); */ 285 case GLMessage::glDeleteRenderbuffers:/* glDeleteRenderbuffers(GLsizei n, GLuint *buffers); */ 286 case GLMessage::glDeleteTextures: /* glDeleteTextures(GLsizei n, GLuint *textures); */ 287 fixup_glDeleteGeneric(glmsg); 288 break; 289 case GLMessage::glGenBuffers: /* void glGenBuffers(GLsizei n, GLuint *buffers); */ 290 case GLMessage::glGenFramebuffers: /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */ 291 case GLMessage::glGenRenderbuffers: /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */ 292 case GLMessage::glGenTextures: /* void glGenTextures(GLsizei n, GLuint *textures); */ 293 fixup_glGenGeneric(glmsg); 294 break; 295 case GLMessage::glGetAttribLocation: 296 case GLMessage::glGetUniformLocation: 297 /* int glGetAttribLocation(GLuint program, const GLchar* name) */ 298 /* int glGetUniformLocation(GLuint program, const GLchar* name) */ 299 fixup_CStringPtr(1, glmsg); 300 break; 301 case GLMessage::glGetBooleanv: 302 fixup_glGetBooleanv(glmsg); 303 break; 304 case GLMessage::glGetFloatv: 305 fixup_glGetFloatv(glmsg); 306 break; 307 case GLMessage::glGetIntegerv: /* void glGetIntegerv(GLenum pname, GLint *params); */ 308 fixup_GenericIntArray(1, 1, glmsg); 309 break; 310 case GLMessage::glGetProgramiv: 311 case GLMessage::glGetRenderbufferParameteriv: 312 case GLMessage::glGetShaderiv: 313 /* void glGetProgramiv(GLuint program, GLenum pname, GLint* params) */ 314 /* void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) */ 315 /* void glGetShaderiv(GLuint shader, GLenum pname, GLint* params) */ 316 fixup_GenericIntArray(2, 1, glmsg); 317 break; 318 case GLMessage::glGetString: 319 fixup_glGetString(glmsg); 320 break; 321 case GLMessage::glTexImage2D: 322 if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) { 323 fixup_glTexImage2D(glmsg); 324 } 325 break; 326 case GLMessage::glTexSubImage2D: 327 if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) { 328 fixup_glTexSubImage2D(glmsg); 329 } 330 break; 331 case GLMessage::glShaderSource: 332 fixup_glShaderSource(glmsg); 333 break; 334 case GLMessage::glUniformMatrix2fv: 335 /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, 336 const GLfloat* value) */ 337 fixup_glUniformMatrixGeneric(2, glmsg); 338 break; 339 case GLMessage::glUniformMatrix3fv: 340 /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, 341 const GLfloat* value) */ 342 fixup_glUniformMatrixGeneric(3, glmsg); 343 break; 344 case GLMessage::glUniformMatrix4fv: 345 /* void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, 346 const GLfloat* value) */ 347 fixup_glUniformMatrixGeneric(4, glmsg); 348 break; 349 case GLMessage::glDrawArrays: 350 /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */ 351 if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) { 352 fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB); 353 } 354 break; 355 case GLMessage::glDrawElements: 356 /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */ 357 if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) { 358 fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB); 359 } 360 break; 361 case GLMessage::glPushGroupMarkerEXT: 362 /* void PushGroupMarkerEXT(sizei length, const char *marker); */ 363 fixup_CStringPtr(1, glmsg); 364 break; 365 case GLMessage::glInsertEventMarkerEXT: 366 /* void InsertEventMarkerEXT(sizei length, const char *marker); */ 367 fixup_CStringPtr(1, glmsg); 368 break; 369 default: 370 break; 371 } 372} 373 374}; 375}; 376