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 <GLES/gl.h> 19 #include <GLES/glext.h> 20 #include <GLES2/gl2.h> 21 #include <GLES2/gl2ext.h> 22 23 #include "gltrace.pb.h" 24 #include "gltrace_api.h" 25 #include "gltrace_context.h" 26 #include "gltrace_fixup.h" 27 28 namespace android { 29 namespace gltrace { 30 31 unsigned getBytesPerTexel(const GLenum format, const GLenum type) { 32 /* 33 Description from glTexImage2D spec: 34 35 Data is read from data as a sequence of unsigned bytes or shorts, depending on type. 36 When type is GL_UNSIGNED_BYTE, each of the bytes is interpreted as one color component. 37 When type is one of GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, or 38 GL_UNSIGNED_SHORT_5_5_5_1, each unsigned short value is interpreted as containing all 39 the components for a single texel, with the color components arranged according to 40 format. Color components are treated as groups of one, two, three, or four values, 41 again based on format. Groups of components are referred to as texels. 42 43 width height texels are read from memory, starting at location data. By default, 44 these texels are taken from adjacent memory locations, except that after all width 45 texels are read, the read pointer is advanced to the next four-byte boundary. 46 The four-byte row alignment is specified by glPixelStorei with argument 47 GL_UNPACK_ALIGNMENT, and it can be set to one, two, four, or eight bytes. 48 */ 49 50 switch (type) { 51 case GL_UNSIGNED_SHORT_5_6_5: 52 case GL_UNSIGNED_SHORT_4_4_4_4: 53 case GL_UNSIGNED_SHORT_5_5_5_1: 54 return 2; 55 case GL_UNSIGNED_BYTE: 56 break; 57 default: 58 ALOGE("GetBytesPerPixel: unknown type %x", type); 59 } 60 61 switch (format) { 62 case GL_ALPHA: 63 case GL_LUMINANCE: 64 return 1; 65 case GL_LUMINANCE_ALPHA: 66 return 2; 67 case GL_RGB: 68 return 3; 69 case GL_RGBA: 70 case 0x80E1: // GL_BGRA_EXT 71 return 4; 72 default: 73 ALOGE("GetBytesPerPixel: unknown format %x", format); 74 } 75 76 return 1; // in doubt... 77 } 78 79 void fixup_GenericFloatArray(int argIndex, int nFloats, GLMessage *glmsg, void *src) { 80 GLMessage_DataType *arg_floatarray = glmsg->mutable_args(argIndex); 81 GLfloat *floatp = (GLfloat *)src; 82 83 if (floatp == NULL) { 84 return; 85 } 86 87 arg_floatarray->set_type(GLMessage::DataType::FLOAT); 88 arg_floatarray->set_isarray(true); 89 arg_floatarray->clear_floatvalue(); 90 91 for (int i = 0; i < nFloats; i++, floatp++) { 92 arg_floatarray->add_floatvalue(*floatp); 93 } 94 } 95 96 void fixup_GenericIntArray(int argIndex, int nInts, GLMessage *glmsg, void *src) { 97 GLMessage_DataType *arg_intarray = glmsg->mutable_args(argIndex); 98 GLint *intp = (GLint *)src; 99 100 if (intp == NULL) { 101 return; 102 } 103 104 arg_intarray->set_type(GLMessage::DataType::INT); 105 arg_intarray->set_isarray(true); 106 arg_intarray->clear_intvalue(); 107 108 for (int i = 0; i < nInts; i++, intp++) { 109 arg_intarray->add_intvalue(*intp); 110 } 111 } 112 113 void fixup_GenericEnumArray(int argIndex, int nEnums, GLMessage *glmsg, void *src) { 114 // fixup as if they were ints 115 fixup_GenericIntArray(argIndex, nEnums, glmsg, src); 116 117 // and then set the data type to be enum 118 GLMessage_DataType *arg_enumarray = glmsg->mutable_args(argIndex); 119 arg_enumarray->set_type(GLMessage::DataType::ENUM); 120 } 121 122 /** Generic helper function: extract pointer at argIndex and 123 replace it with the C style string at *pointer */ 124 void fixup_CStringPtr(int argIndex, GLMessage *glmsg, void *src) { 125 GLMessage_DataType *arg = glmsg->mutable_args(argIndex); 126 GLchar *ptr = (GLchar *) src; 127 128 arg->set_type(GLMessage::DataType::CHAR); 129 arg->set_isarray(true); 130 arg->add_charvalue(ptr); 131 } 132 133 void fixup_glGetString(GLMessage *glmsg, void *pointersToFixup[]) { 134 /* const GLubyte* GLTrace_glGetString(GLenum name) */ 135 GLMessage_DataType *ret = glmsg->mutable_returnvalue(); 136 GLchar *ptr = (GLchar *) pointersToFixup[0]; 137 138 if (ptr != NULL) { 139 ret->set_type(GLMessage::DataType::CHAR); 140 ret->set_isarray(true); 141 ret->add_charvalue(ptr); 142 } 143 } 144 145 /* Add the contents of the framebuffer to the protobuf message */ 146 void fixup_addFBContents(GLTraceContext *context, GLMessage *glmsg, FBBinding fbToRead) { 147 void *fbcontents; 148 unsigned fbsize, fbwidth, fbheight; 149 context->getCompressedFB(&fbcontents, &fbsize, &fbwidth, &fbheight, fbToRead); 150 151 GLMessage_FrameBuffer *fb = glmsg->mutable_fb(); 152 fb->set_width(fbwidth); 153 fb->set_height(fbheight); 154 fb->add_contents(fbcontents, fbsize); 155 } 156 157 /** Common fixup routing for glTexImage2D & glTexSubImage2D. */ 158 void fixup_glTexImage(int widthIndex, int heightIndex, GLMessage *glmsg, void *dataSrc) { 159 GLMessage_DataType arg_width = glmsg->args(widthIndex); 160 GLMessage_DataType arg_height = glmsg->args(heightIndex); 161 162 GLMessage_DataType arg_format = glmsg->args(6); 163 GLMessage_DataType arg_type = glmsg->args(7); 164 GLMessage_DataType *arg_data = glmsg->mutable_args(8); 165 166 GLsizei width = arg_width.intvalue(0); 167 GLsizei height = arg_height.intvalue(0); 168 GLenum format = arg_format.intvalue(0); 169 GLenum type = arg_type.intvalue(0); 170 void *data = (void *) dataSrc; 171 172 int bytesPerTexel = getBytesPerTexel(format, type); 173 174 arg_data->set_type(GLMessage::DataType::BYTE); 175 arg_data->clear_rawbytes(); 176 177 if (data != NULL) { 178 arg_data->set_isarray(true); 179 arg_data->add_rawbytes(data, bytesPerTexel * width * height); 180 } else { 181 arg_data->set_isarray(false); 182 arg_data->set_type(GLMessage::DataType::VOID); 183 } 184 } 185 186 187 void fixup_glTexImage2D(GLMessage *glmsg, void *pointersToFixup[]) { 188 /* void glTexImage2D(GLenum target, 189 GLint level, 190 GLint internalformat, 191 GLsizei width, 192 GLsizei height, 193 GLint border, 194 GLenum format, 195 GLenum type, 196 const GLvoid *data); 197 */ 198 int widthIndex = 3; 199 int heightIndex = 4; 200 fixup_glTexImage(widthIndex, heightIndex, glmsg, pointersToFixup[0]); 201 } 202 203 void fixup_glTexSubImage2D(GLMessage *glmsg, void *pointersToFixup[]) { 204 /* 205 void glTexSubImage2D(GLenum target, 206 GLint level, 207 GLint xoffset, 208 GLint yoffset, 209 GLsizei width, 210 GLsizei height, 211 GLenum format, 212 GLenum type, 213 const GLvoid * data); 214 */ 215 int widthIndex = 4; 216 int heightIndex = 5; 217 fixup_glTexImage(widthIndex, heightIndex, glmsg, pointersToFixup[0]); 218 } 219 220 void fixup_glShaderSource(GLMessage *glmsg, void *pointersToFixup[]) { 221 /* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string, 222 const GLint* length) */ 223 GLMessage_DataType arg_count = glmsg->args(1); 224 GLMessage_DataType arg_lenp = glmsg->args(3); 225 GLMessage_DataType *arg_strpp = glmsg->mutable_args(2); 226 227 GLsizei count = arg_count.intvalue(0); 228 GLchar **stringpp = (GLchar **) pointersToFixup[0]; 229 GLint *lengthp = (GLint *) pointersToFixup[1]; 230 231 arg_strpp->set_type(GLMessage::DataType::CHAR); 232 arg_strpp->set_isarray(true); 233 arg_strpp->clear_charvalue(); 234 235 ::std::string src = ""; 236 for (int i = 0; i < count; i++) { 237 if (lengthp != NULL) 238 src.append(*stringpp, *lengthp); 239 else 240 src.append(*stringpp); // assume null terminated 241 stringpp++; 242 lengthp++; 243 } 244 245 arg_strpp->add_charvalue(src); 246 } 247 248 void fixup_glUniformGenericInteger(int argIndex, int nIntegers, GLMessage *glmsg, 249 void *pointersToFixup[]) { 250 /* void glUniform?iv(GLint location, GLsizei count, const GLint *value); */ 251 fixup_GenericIntArray(argIndex, nIntegers, glmsg, pointersToFixup[0]); 252 } 253 254 void fixup_glUniformGeneric(int argIndex, int nFloats, GLMessage *glmsg, void *src) { 255 fixup_GenericFloatArray(argIndex, nFloats, glmsg, src); 256 } 257 258 void fixup_glUniformMatrixGeneric(int matrixSize, GLMessage *glmsg, void *pointersToFixup[]) { 259 /* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose, 260 const GLfloat* value) */ 261 GLMessage_DataType arg_count = glmsg->args(1); 262 int n_matrices = arg_count.intvalue(0); 263 fixup_glUniformGeneric(3, matrixSize * matrixSize * n_matrices, glmsg, pointersToFixup[0]); 264 } 265 266 void fixup_glGenGeneric(GLMessage *glmsg, void *pointersToFixup[]) { 267 /* void glGen*(GLsizei n, GLuint * buffers); */ 268 GLMessage_DataType arg_n = glmsg->args(0); 269 GLsizei n = arg_n.intvalue(0); 270 271 fixup_GenericIntArray(1, n, glmsg, pointersToFixup[0]); 272 } 273 274 void fixup_glDeleteGeneric(GLMessage *glmsg, void *pointersToFixup[]) { 275 /* void glDelete*(GLsizei n, GLuint *buffers); */ 276 GLMessage_DataType arg_n = glmsg->args(0); 277 GLsizei n = arg_n.intvalue(0); 278 279 fixup_GenericIntArray(1, n, glmsg, pointersToFixup[0]); 280 } 281 282 void fixup_glGetBooleanv(GLMessage *glmsg, void *pointersToFixup[]) { 283 /* void glGetBooleanv(GLenum pname, GLboolean *params); */ 284 GLMessage_DataType *arg_params = glmsg->mutable_args(1); 285 GLboolean *src = (GLboolean*) pointersToFixup[0]; 286 287 arg_params->set_type(GLMessage::DataType::BOOL); 288 arg_params->set_isarray(true); 289 arg_params->clear_boolvalue(); 290 arg_params->add_boolvalue(*src); 291 } 292 293 void fixup_glGetFloatv(GLMessage *glmsg, void *pointersToFixup[]) { 294 /* void glGetFloatv(GLenum pname, GLfloat *params); */ 295 GLMessage_DataType *arg_params = glmsg->mutable_args(1); 296 GLfloat *src = (GLfloat*) pointersToFixup[0]; 297 298 arg_params->set_type(GLMessage::DataType::FLOAT); 299 arg_params->set_isarray(true); 300 arg_params->clear_floatvalue(); 301 arg_params->add_floatvalue(*src); 302 } 303 304 void fixup_glLinkProgram(GLMessage *glmsg) { 305 /* void glLinkProgram(GLuint program); */ 306 GLuint program = glmsg->args(0).intvalue(0); 307 308 /* We don't have to fixup this call, but as soon as a program is linked, 309 we obtain information about all active attributes and uniforms to 310 pass on to the debugger. Note that in order to pass this info to 311 the debugger, all we need to do is call the trace versions of the 312 necessary calls. */ 313 314 GLint n, maxNameLength; 315 GLchar *name; 316 GLint size; 317 GLenum type; 318 319 // obtain info regarding active attributes 320 GLTrace_glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n); 321 GLTrace_glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLength); 322 323 name = (GLchar *) malloc(maxNameLength); 324 for (int i = 0; i < n; i++) { 325 GLTrace_glGetActiveAttrib(program, i, maxNameLength, NULL, &size, &type, name); 326 } 327 free(name); 328 329 // obtain info regarding active uniforms 330 GLTrace_glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &n); 331 GLTrace_glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength); 332 333 name = (GLchar *) malloc(maxNameLength); 334 for (int i = 0; i < n; i++) { 335 GLTrace_glGetActiveUniform(program, i, maxNameLength, NULL, &size, &type, name); 336 } 337 free(name); 338 } 339 340 /** Given a glGetActive[Uniform|Attrib] call, obtain the location 341 * of the variable of given name in the call. 342 */ 343 int getShaderVariableLocation(GLTraceContext *context, GLMessage *glmsg, GLchar *name) { 344 GLMessage_Function func = glmsg->function(); 345 if (func != GLMessage::glGetActiveAttrib && func != GLMessage::glGetActiveUniform) { 346 return -1; 347 } 348 349 int program = glmsg->args(0).intvalue(0); 350 351 if (func == GLMessage::glGetActiveAttrib) { 352 return context->hooks->gl.glGetAttribLocation(program, name); 353 } else { 354 return context->hooks->gl.glGetUniformLocation(program, name); 355 } 356 } 357 358 void fixup_glGetActiveAttribOrUniform(GLTraceContext *context, GLMessage *glmsg, 359 void *pointersToFixup[]) { 360 /* void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, 361 GLsizei* length, GLint* size, GLenum* type, GLchar* name); */ 362 /* void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, 363 GLsizei* length, GLint* size, GLenum* type, GLchar* name) */ 364 365 fixup_GenericIntArray(3, 1, glmsg, pointersToFixup[0]); // length 366 fixup_GenericIntArray(4, 1, glmsg, pointersToFixup[1]); // size 367 fixup_GenericEnumArray(5, 1, glmsg, pointersToFixup[2]); // type 368 fixup_CStringPtr(6, glmsg, pointersToFixup[3]); // name 369 370 // The index argument in the glGetActive[Attrib|Uniform] functions 371 // does not correspond to the actual location index as used in 372 // glUniform*() or glVertexAttrib*() to actually upload the data. 373 // In order to make things simpler for the debugger, we also pass 374 // a hidden location argument that stores the actual location. 375 // append the location value to the end of the argument list 376 int location = getShaderVariableLocation(context, glmsg, (GLchar*)pointersToFixup[3]); 377 GLMessage_DataType *arg_location = glmsg->add_args(); 378 arg_location->set_isarray(false); 379 arg_location->set_type(GLMessage::DataType::INT); 380 arg_location->add_intvalue(location); 381 } 382 383 GLint glGetInteger(GLTraceContext *context, GLenum param) { 384 GLint x; 385 context->hooks->gl.glGetIntegerv(param, &x); 386 return x; 387 } 388 389 GLint glGetVertexAttrib(GLTraceContext *context, GLuint index, GLenum pname) { 390 GLint x; 391 context->hooks->gl.glGetVertexAttribiv(index, pname, &x); 392 return x; 393 } 394 395 bool isUsingArrayBuffers(GLTraceContext *context) { 396 return glGetInteger(context, GL_ARRAY_BUFFER_BINDING) != 0; 397 } 398 399 bool isUsingElementArrayBuffers(GLTraceContext *context) { 400 return glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING) != 0; 401 } 402 403 /** Copy @len bytes of data from @src into the @dataIndex'th argument of the message. */ 404 void addGlBufferData(GLMessage *glmsg, int dataIndex, GLvoid *src, GLsizeiptr len) { 405 GLMessage_DataType *arg_datap = glmsg->mutable_args(dataIndex); 406 arg_datap->set_type(GLMessage::DataType::VOID); 407 arg_datap->set_isarray(true); 408 arg_datap->clear_intvalue(); 409 arg_datap->add_rawbytes(src, len); 410 } 411 412 void fixup_glBufferData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) { 413 /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */ 414 GLsizeiptr size = glmsg->args(1).intvalue(0); 415 GLvoid *datap = (GLvoid *) pointersToFixup[0]; 416 417 // Save element array buffers for future use to fixup glVertexAttribPointers 418 // when a glDrawElements() call is performed. 419 GLenum target = glmsg->args(0).intvalue(0); 420 if (target == GL_ELEMENT_ARRAY_BUFFER) { 421 GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING); 422 context->bindBuffer(bufferId, datap, size); 423 } 424 425 // add buffer data to the protobuf message 426 if (datap != NULL) { 427 addGlBufferData(glmsg, 2, datap, size); 428 } 429 } 430 431 void fixup_glBufferSubData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) { 432 /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */ 433 GLenum target = glmsg->args(0).intvalue(0); 434 GLintptr offset = glmsg->args(1).intvalue(0); 435 GLsizeiptr size = glmsg->args(2).intvalue(0); 436 GLvoid *datap = (GLvoid *) pointersToFixup[0]; 437 if (target == GL_ELEMENT_ARRAY_BUFFER) { 438 GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING); 439 context->updateBufferSubData(bufferId, offset, datap, size); 440 } 441 442 // add buffer data to the protobuf message 443 addGlBufferData(glmsg, 3, datap, size); 444 } 445 446 /** Obtain the size of each vertex attribute. */ 447 int vertexAttribSize(GLenum type, GLsizei numComponents) { 448 int sizePerComponent; 449 450 switch(type) { 451 case GL_BYTE: 452 case GL_UNSIGNED_BYTE: 453 sizePerComponent = 1; 454 break; 455 case GL_SHORT: 456 case GL_UNSIGNED_SHORT: 457 sizePerComponent = 2; 458 break; 459 case GL_FIXED: 460 case GL_FLOAT: 461 default: 462 sizePerComponent = 4; 463 break; 464 } 465 466 return sizePerComponent * numComponents; 467 } 468 469 /** Create and send a glVertexAttribPointerData trace message to the host. */ 470 void trace_glVertexAttribPointerData(GLTraceContext *context, 471 GLuint indx, GLint size, GLenum type, 472 GLboolean normalized, GLsizei stride, const GLvoid* ptr, 473 GLuint minIndex, GLuint maxIndex, nsecs_t startTime) { 474 /* void glVertexAttribPointerData(GLuint indx, GLint size, GLenum type, 475 GLboolean normalized, GLsizei stride, const GLvoid* ptr, 476 int minIndex, int maxIndex) */ 477 GLMessage glmsg; 478 GLTraceContext *glContext = context; 479 480 glmsg.set_function(GLMessage::glVertexAttribPointerData); 481 482 // copy argument indx 483 GLMessage_DataType *arg_indx = glmsg.add_args(); 484 arg_indx->set_isarray(false); 485 arg_indx->set_type(GLMessage::DataType::INT); 486 arg_indx->add_intvalue(indx); 487 488 // copy argument size 489 GLMessage_DataType *arg_size = glmsg.add_args(); 490 arg_size->set_isarray(false); 491 arg_size->set_type(GLMessage::DataType::INT); 492 arg_size->add_intvalue(size); 493 494 // copy argument type 495 GLMessage_DataType *arg_type = glmsg.add_args(); 496 arg_type->set_isarray(false); 497 arg_type->set_type(GLMessage::DataType::ENUM); 498 arg_type->add_intvalue((int)type); 499 500 // copy argument normalized 501 GLMessage_DataType *arg_normalized = glmsg.add_args(); 502 arg_normalized->set_isarray(false); 503 arg_normalized->set_type(GLMessage::DataType::BOOL); 504 arg_normalized->add_boolvalue(normalized); 505 506 // copy argument stride 507 GLMessage_DataType *arg_stride = glmsg.add_args(); 508 arg_stride->set_isarray(false); 509 arg_stride->set_type(GLMessage::DataType::INT); 510 arg_stride->add_intvalue(stride); 511 512 // copy argument ptr 513 GLMessage_DataType *arg_ptr = glmsg.add_args(); 514 arg_ptr->set_isarray(true); 515 arg_ptr->set_type(GLMessage::DataType::BYTE); 516 int perVertexSize = vertexAttribSize(type, size); 517 GLchar *p = (GLchar*) ptr; 518 std::string data; 519 for (GLuint i = minIndex; i < maxIndex; i++) { 520 data.append(p, perVertexSize); 521 p += stride == 0 ? perVertexSize : stride; 522 } 523 arg_ptr->add_rawbytes(data); 524 525 // copy argument min index 526 GLMessage_DataType *arg_min = glmsg.add_args(); 527 arg_min->set_isarray(false); 528 arg_min->set_type(GLMessage::DataType::INT); 529 arg_min->add_intvalue(minIndex); 530 531 // copy argument max index 532 GLMessage_DataType *arg_max = glmsg.add_args(); 533 arg_max->set_isarray(false); 534 arg_max->set_type(GLMessage::DataType::INT); 535 arg_max->add_intvalue(maxIndex); 536 537 glmsg.set_context_id(context->getId()); 538 glmsg.set_start_time(startTime); 539 glmsg.set_threadtime(0); 540 glmsg.set_duration(0); 541 542 context->traceGLMessage(&glmsg); 543 } 544 545 void findMinAndMaxIndices(GLvoid *indices, GLsizei count, GLenum type, 546 GLuint *minIndex, GLuint *maxIndex) { 547 GLuint index; 548 *minIndex = UINT_MAX; 549 *maxIndex = 0; 550 551 if (indices == NULL) { 552 return; 553 } 554 555 for (GLsizei i = 0; i < count; i++) { 556 if (type == GL_UNSIGNED_BYTE) { 557 index = *((GLubyte*) indices + i); 558 } else { 559 index = *((GLushort*) indices + i); 560 } 561 562 if (index < *minIndex) *minIndex = index; 563 if (index > *maxIndex) *maxIndex = index; 564 } 565 } 566 567 void trace_VertexAttribPointerData(GLTraceContext *context, 568 GLuint minIndex, GLuint maxIndex, nsecs_t time) { 569 GLuint maxAttribs = glGetInteger(context, GL_MAX_VERTEX_ATTRIBS); 570 for (GLuint index = 0; index < maxAttribs; index++) { 571 if (!glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_ENABLED)) { 572 // vertex array disabled 573 continue; 574 } 575 576 if (glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)) { 577 // vbo 578 continue; 579 } 580 581 GLint size = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_SIZE); 582 GLenum type = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_TYPE); 583 GLboolean norm = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED); 584 GLsizei stride = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_STRIDE); 585 GLvoid* ptr; 586 context->hooks->gl.glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr); 587 588 trace_glVertexAttribPointerData(context, 589 index, size, type, norm, stride, ptr, 590 minIndex, maxIndex, time); 591 } 592 } 593 594 void trace_VertexAttribPointerDataForGlDrawArrays(GLTraceContext *context, GLMessage *glmsg) { 595 /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */ 596 GLsizei count = glmsg->args(2).intvalue(0); 597 598 // Vertex attrib pointer data patchup calls should appear as if 599 // they occurred right before the draw call. 600 nsecs_t time = glmsg->start_time() - 1; 601 602 trace_VertexAttribPointerData(context, 0, count, time); 603 } 604 605 void trace_VertexAttribPointerDataForGlDrawElements(GLTraceContext *context, GLMessage *glmsg, 606 GLvoid *indices) { 607 /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */ 608 GLsizei count = glmsg->args(1).intvalue(0); 609 GLenum type = glmsg->args(2).intvalue(0); 610 GLuint index; 611 612 GLuint minIndex, maxIndex; 613 614 // The index buffer is either passed in as an argument to the glDrawElements() call, 615 // or it is stored in the current GL_ELEMENT_ARRAY_BUFFER. 616 GLvoid *indexBuffer; 617 if (isUsingElementArrayBuffers(context)) { 618 GLsizeiptr eaBufferSize; 619 GLuint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING); 620 context->getBuffer(bufferId, &indexBuffer, &eaBufferSize); 621 } else { 622 indexBuffer = indices; 623 } 624 625 // Rather than sending vertex attribute data that corresponds to the indices 626 // being drawn, we send the vertex attribute data for the entire range of 627 // indices being drawn, including the ones not drawn. The min & max indices 628 // provide the range of indices being drawn. 629 findMinAndMaxIndices(indexBuffer, count, type, &minIndex, &maxIndex); 630 631 // Vertex attrib pointer data patchup calls should appear as if 632 // they occurred right before the draw call. 633 nsecs_t time = glmsg->start_time() - 1; 634 635 trace_VertexAttribPointerData(context, minIndex, maxIndex + 1, time); 636 } 637 638 void fixup_glDrawArrays(GLTraceContext *context, GLMessage *glmsg) { 639 // Trace all vertex attribute data stored in client space. 640 trace_VertexAttribPointerDataForGlDrawArrays(context, glmsg); 641 642 // Attach the FB if requested 643 if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) { 644 fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB); 645 } 646 } 647 648 void fixup_glDrawElements(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) { 649 /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */ 650 GLvoid *indices = pointersToFixup[0]; 651 GLenum type = glmsg->args(2).intvalue(0); 652 GLsizei count = glmsg->args(1).intvalue(0); 653 GLuint index; 654 655 // Trace all vertex attribute data stored in client space. 656 trace_VertexAttribPointerDataForGlDrawElements(context, glmsg, indices); 657 658 // Fixup indices argument 659 if (!isUsingElementArrayBuffers(context)) { 660 GLMessage_DataType *arg_indices = glmsg->mutable_args(3); 661 arg_indices->set_isarray(true); 662 arg_indices->clear_intvalue(); 663 arg_indices->set_type(GLMessage::DataType::INT); 664 for (GLsizei i = 0; i < count; i++) { 665 if (type == GL_UNSIGNED_BYTE) { 666 index = *((GLubyte*) indices + i); 667 } else { 668 index = *((GLushort*) indices + i); 669 } 670 arg_indices->add_intvalue(index); 671 } 672 } 673 674 // Attach the FB if requested 675 if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) { 676 fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB); 677 } 678 } 679 680 void fixupGLMessage(GLTraceContext *context, nsecs_t wallStart, nsecs_t wallEnd, 681 nsecs_t threadStart, nsecs_t threadEnd, 682 GLMessage *glmsg, void *pointersToFixup[]) { 683 // for all messages, set the current context id 684 glmsg->set_context_id(context->getId()); 685 686 // set start time and duration 687 glmsg->set_start_time(wallStart); 688 glmsg->set_duration((unsigned)(wallEnd - wallStart)); 689 glmsg->set_threadtime((unsigned)(threadEnd - threadStart)); 690 691 // do any custom message dependent processing 692 switch (glmsg->function()) { 693 case GLMessage::glDeleteBuffers: /* glDeleteBuffers(GLsizei n, GLuint *buffers); */ 694 case GLMessage::glDeleteFramebuffers: /* glDeleteFramebuffers(GLsizei n, GLuint *buffers); */ 695 case GLMessage::glDeleteRenderbuffers:/* glDeleteRenderbuffers(GLsizei n, GLuint *buffers); */ 696 case GLMessage::glDeleteTextures: /* glDeleteTextures(GLsizei n, GLuint *textures); */ 697 fixup_glDeleteGeneric(glmsg, pointersToFixup); 698 break; 699 case GLMessage::glGenBuffers: /* void glGenBuffers(GLsizei n, GLuint *buffers); */ 700 case GLMessage::glGenFramebuffers: /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */ 701 case GLMessage::glGenRenderbuffers: /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */ 702 case GLMessage::glGenTextures: /* void glGenTextures(GLsizei n, GLuint *textures); */ 703 fixup_glGenGeneric(glmsg, pointersToFixup); 704 break; 705 case GLMessage::glLinkProgram: /* void glLinkProgram(GLuint program); */ 706 fixup_glLinkProgram(glmsg); 707 break; 708 case GLMessage::glGetActiveAttrib: 709 fixup_glGetActiveAttribOrUniform(context, glmsg, pointersToFixup); 710 break; 711 case GLMessage::glGetActiveUniform: 712 fixup_glGetActiveAttribOrUniform(context, glmsg, pointersToFixup); 713 break; 714 case GLMessage::glBindAttribLocation: 715 /* void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name); */ 716 fixup_CStringPtr(2, glmsg, pointersToFixup[0]); 717 break; 718 case GLMessage::glGetAttribLocation: 719 case GLMessage::glGetUniformLocation: 720 /* int glGetAttribLocation(GLuint program, const GLchar* name) */ 721 /* int glGetUniformLocation(GLuint program, const GLchar* name) */ 722 fixup_CStringPtr(1, glmsg, pointersToFixup[0]); 723 break; 724 case GLMessage::glGetBooleanv: 725 fixup_glGetBooleanv(glmsg, pointersToFixup); 726 break; 727 case GLMessage::glGetFloatv: 728 fixup_glGetFloatv(glmsg, pointersToFixup); 729 break; 730 case GLMessage::glGetIntegerv: /* void glGetIntegerv(GLenum pname, GLint *params); */ 731 fixup_GenericIntArray(1, 1, glmsg, pointersToFixup[0]); 732 break; 733 case GLMessage::glGetProgramiv: 734 case GLMessage::glGetRenderbufferParameteriv: 735 case GLMessage::glGetShaderiv: 736 /* void glGetProgramiv(GLuint program, GLenum pname, GLint* params) */ 737 /* void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) */ 738 /* void glGetShaderiv(GLuint shader, GLenum pname, GLint* params) */ 739 fixup_GenericIntArray(2, 1, glmsg, pointersToFixup[0]); 740 break; 741 case GLMessage::glGetString: 742 fixup_glGetString(glmsg, pointersToFixup); 743 break; 744 case GLMessage::glTexImage2D: 745 if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) { 746 fixup_glTexImage2D(glmsg, pointersToFixup); 747 } 748 break; 749 case GLMessage::glTexSubImage2D: 750 if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) { 751 fixup_glTexSubImage2D(glmsg, pointersToFixup); 752 } 753 break; 754 case GLMessage::glShaderSource: 755 fixup_glShaderSource(glmsg, pointersToFixup); 756 break; 757 case GLMessage::glUniform1iv: 758 /* void glUniform1iv(GLint location, GLsizei count, const GLint *value); */ 759 fixup_glUniformGenericInteger(2, 1, glmsg, pointersToFixup); 760 break; 761 case GLMessage::glUniform2iv: 762 /* void glUniform2iv(GLint location, GLsizei count, const GLint *value); */ 763 fixup_glUniformGenericInteger(2, 2, glmsg, pointersToFixup); 764 break; 765 case GLMessage::glUniform3iv: 766 /* void glUniform3iv(GLint location, GLsizei count, const GLint *value); */ 767 fixup_glUniformGenericInteger(2, 3, glmsg, pointersToFixup); 768 break; 769 case GLMessage::glUniform4iv: 770 /* void glUniform4iv(GLint location, GLsizei count, const GLint *value); */ 771 fixup_glUniformGenericInteger(2, 4, glmsg, pointersToFixup); 772 break; 773 case GLMessage::glUniform1fv: 774 /* void glUniform1fv(GLint location, GLsizei count, const GLfloat *value); */ 775 fixup_glUniformGeneric(2, 1, glmsg, pointersToFixup[0]); 776 break; 777 case GLMessage::glUniform2fv: 778 /* void glUniform2fv(GLint location, GLsizei count, const GLfloat *value); */ 779 fixup_glUniformGeneric(2, 2, glmsg, pointersToFixup[0]); 780 break; 781 case GLMessage::glUniform3fv: 782 /* void glUniform3fv(GLint location, GLsizei count, const GLfloat *value); */ 783 fixup_glUniformGeneric(2, 3, glmsg, pointersToFixup[0]); 784 break; 785 case GLMessage::glUniform4fv: 786 /* void glUniform4fv(GLint location, GLsizei count, const GLfloat *value); */ 787 fixup_glUniformGeneric(2, 4, glmsg, pointersToFixup[0]); 788 break; 789 case GLMessage::glUniformMatrix2fv: 790 /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, 791 const GLfloat* value) */ 792 fixup_glUniformMatrixGeneric(2, glmsg, pointersToFixup); 793 break; 794 case GLMessage::glUniformMatrix3fv: 795 /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, 796 const GLfloat* value) */ 797 fixup_glUniformMatrixGeneric(3, glmsg, pointersToFixup); 798 break; 799 case GLMessage::glUniformMatrix4fv: 800 /* void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, 801 const GLfloat* value) */ 802 fixup_glUniformMatrixGeneric(4, glmsg, pointersToFixup); 803 break; 804 case GLMessage::glBufferData: 805 /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */ 806 fixup_glBufferData(context, glmsg, pointersToFixup); 807 break; 808 case GLMessage::glBufferSubData: 809 /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */ 810 fixup_glBufferSubData(context, glmsg, pointersToFixup); 811 break; 812 case GLMessage::glDrawArrays: 813 /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */ 814 fixup_glDrawArrays(context, glmsg); 815 break; 816 case GLMessage::glDrawElements: 817 /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */ 818 fixup_glDrawElements(context, glmsg, pointersToFixup); 819 break; 820 case GLMessage::glPushGroupMarkerEXT: 821 /* void PushGroupMarkerEXT(sizei length, const char *marker); */ 822 fixup_CStringPtr(1, glmsg, pointersToFixup[0]); 823 break; 824 case GLMessage::glInsertEventMarkerEXT: 825 /* void InsertEventMarkerEXT(sizei length, const char *marker); */ 826 fixup_CStringPtr(1, glmsg, pointersToFixup[0]); 827 break; 828 default: 829 break; 830 } 831 } 832 833 }; 834 }; 835