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