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 29namespace android { 30namespace gltrace { 31 32unsigned 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 80void 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 97void 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 114void 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 */ 125void 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 134void 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 */ 147void 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. */ 159void 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 188void 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 204void 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 221void 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 } 243 244 arg_strpp->add_charvalue(src); 245} 246 247void fixup_glUniformGenericInteger(int argIndex, int nIntegers, GLMessage *glmsg, 248 void *pointersToFixup[]) { 249 /* void glUniform?iv(GLint location, GLsizei count, const GLint *value); */ 250 fixup_GenericIntArray(argIndex, nIntegers, glmsg, pointersToFixup[0]); 251} 252 253void fixup_glUniformGeneric(int argIndex, int nFloats, GLMessage *glmsg, void *src) { 254 fixup_GenericFloatArray(argIndex, nFloats, glmsg, src); 255} 256 257void fixup_glUniformMatrixGeneric(int matrixSize, GLMessage *glmsg, void *pointersToFixup[]) { 258 /* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose, 259 const GLfloat* value) */ 260 GLMessage_DataType arg_count = glmsg->args(1); 261 int n_matrices = arg_count.intvalue(0); 262 fixup_glUniformGeneric(3, matrixSize * matrixSize * n_matrices, glmsg, pointersToFixup[0]); 263} 264 265void fixup_glGenGeneric(GLMessage *glmsg, void *pointersToFixup[]) { 266 /* void glGen*(GLsizei n, GLuint * buffers); */ 267 GLMessage_DataType arg_n = glmsg->args(0); 268 GLsizei n = arg_n.intvalue(0); 269 270 fixup_GenericIntArray(1, n, glmsg, pointersToFixup[0]); 271} 272 273void fixup_glDeleteGeneric(GLMessage *glmsg, void *pointersToFixup[]) { 274 /* void glDelete*(GLsizei n, GLuint *buffers); */ 275 GLMessage_DataType arg_n = glmsg->args(0); 276 GLsizei n = arg_n.intvalue(0); 277 278 fixup_GenericIntArray(1, n, glmsg, pointersToFixup[0]); 279} 280 281void fixup_glGetBooleanv(GLMessage *glmsg, void *pointersToFixup[]) { 282 /* void glGetBooleanv(GLenum pname, GLboolean *params); */ 283 GLMessage_DataType *arg_params = glmsg->mutable_args(1); 284 GLboolean *src = (GLboolean*) pointersToFixup[0]; 285 286 arg_params->set_type(GLMessage::DataType::BOOL); 287 arg_params->set_isarray(true); 288 arg_params->clear_boolvalue(); 289 arg_params->add_boolvalue(*src); 290} 291 292void fixup_glGetFloatv(GLMessage *glmsg, void *pointersToFixup[]) { 293 /* void glGetFloatv(GLenum pname, GLfloat *params); */ 294 GLMessage_DataType *arg_params = glmsg->mutable_args(1); 295 GLfloat *src = (GLfloat*) pointersToFixup[0]; 296 297 arg_params->set_type(GLMessage::DataType::FLOAT); 298 arg_params->set_isarray(true); 299 arg_params->clear_floatvalue(); 300 arg_params->add_floatvalue(*src); 301} 302 303void fixup_glLinkProgram(GLMessage *glmsg) { 304 /* void glLinkProgram(GLuint program); */ 305 GLuint program = glmsg->args(0).intvalue(0); 306 307 /* We don't have to fixup this call, but as soon as a program is linked, 308 we obtain information about all active attributes and uniforms to 309 pass on to the debugger. Note that in order to pass this info to 310 the debugger, all we need to do is call the trace versions of the 311 necessary calls. */ 312 313 GLint n, maxNameLength; 314 GLchar *name; 315 GLint size; 316 GLenum type; 317 318 // obtain info regarding active attributes 319 GLTrace_glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n); 320 GLTrace_glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLength); 321 322 name = (GLchar *) malloc(maxNameLength); 323 for (int i = 0; i < n; i++) { 324 GLTrace_glGetActiveAttrib(program, i, maxNameLength, NULL, &size, &type, name); 325 } 326 free(name); 327 328 // obtain info regarding active uniforms 329 GLTrace_glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &n); 330 GLTrace_glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength); 331 332 name = (GLchar *) malloc(maxNameLength); 333 for (int i = 0; i < n; i++) { 334 GLTrace_glGetActiveUniform(program, i, maxNameLength, NULL, &size, &type, name); 335 } 336 free(name); 337} 338 339/** Given a glGetActive[Uniform|Attrib] call, obtain the location 340 * of the variable of given name in the call. 341 */ 342GLint getShaderVariableLocation(GLTraceContext *context, GLMessage *glmsg, GLchar *name) { 343 GLMessage_Function func = glmsg->function(); 344 if (func != GLMessage::glGetActiveAttrib && func != GLMessage::glGetActiveUniform) { 345 return -1; 346 } 347 348 int program = glmsg->args(0).intvalue(0); 349 350 if (func == GLMessage::glGetActiveAttrib) { 351 return context->hooks->gl.glGetAttribLocation(program, name); 352 } else { 353 return context->hooks->gl.glGetUniformLocation(program, name); 354 } 355} 356 357void fixup_glGetActiveAttribOrUniform(GLTraceContext *context, GLMessage *glmsg, 358 void *pointersToFixup[]) { 359 /* void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, 360 GLsizei* length, GLint* size, GLenum* type, GLchar* name); */ 361 /* void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, 362 GLsizei* length, GLint* size, GLenum* type, GLchar* name) */ 363 364 fixup_GenericIntArray(3, 1, glmsg, pointersToFixup[0]); // length 365 fixup_GenericIntArray(4, 1, glmsg, pointersToFixup[1]); // size 366 fixup_GenericEnumArray(5, 1, glmsg, pointersToFixup[2]); // type 367 fixup_CStringPtr(6, glmsg, pointersToFixup[3]); // name 368 369 // The index argument in the glGetActive[Attrib|Uniform] functions 370 // does not correspond to the actual location index as used in 371 // glUniform*() or glVertexAttrib*() to actually upload the data. 372 // In order to make things simpler for the debugger, we also pass 373 // a hidden location argument that stores the actual location. 374 // append the location value to the end of the argument list 375 GLint location = getShaderVariableLocation(context, glmsg, (GLchar*)pointersToFixup[3]); 376 GLMessage_DataType *arg_location = glmsg->add_args(); 377 arg_location->set_isarray(false); 378 arg_location->set_type(GLMessage::DataType::INT); 379 arg_location->add_intvalue(location); 380} 381 382GLint glGetInteger(GLTraceContext *context, GLenum param) { 383 GLint x; 384 context->hooks->gl.glGetIntegerv(param, &x); 385 return x; 386} 387 388GLint glGetVertexAttrib(GLTraceContext *context, GLuint index, GLenum pname) { 389 GLint x; 390 context->hooks->gl.glGetVertexAttribiv(index, pname, &x); 391 return x; 392} 393 394bool isUsingArrayBuffers(GLTraceContext *context) { 395 return glGetInteger(context, GL_ARRAY_BUFFER_BINDING) != 0; 396} 397 398bool isUsingElementArrayBuffers(GLTraceContext *context) { 399 return glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING) != 0; 400} 401 402/** Copy @len bytes of data from @src into the @dataIndex'th argument of the message. */ 403void addGlBufferData(GLMessage *glmsg, int dataIndex, GLvoid *src, GLsizeiptr len) { 404 GLMessage_DataType *arg_datap = glmsg->mutable_args(dataIndex); 405 arg_datap->set_type(GLMessage::DataType::VOID); 406 arg_datap->set_isarray(true); 407 arg_datap->clear_intvalue(); 408 arg_datap->add_rawbytes(src, len); 409} 410 411void fixup_glBufferData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) { 412 /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */ 413 GLsizeiptr size = glmsg->args(1).intvalue(0); 414 GLvoid *datap = (GLvoid *) pointersToFixup[0]; 415 416 // Save element array buffers for future use to fixup glVertexAttribPointers 417 // when a glDrawElements() call is performed. 418 GLenum target = glmsg->args(0).intvalue(0); 419 if (target == GL_ELEMENT_ARRAY_BUFFER) { 420 GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING); 421 context->bindBuffer(bufferId, datap, size); 422 } 423 424 // add buffer data to the protobuf message 425 if (datap != NULL) { 426 addGlBufferData(glmsg, 2, datap, size); 427 } 428} 429 430void fixup_glBufferSubData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) { 431 /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */ 432 GLenum target = glmsg->args(0).intvalue(0); 433 GLintptr offset = glmsg->args(1).intvalue(0); 434 GLsizeiptr size = glmsg->args(2).intvalue(0); 435 GLvoid *datap = (GLvoid *) pointersToFixup[0]; 436 if (target == GL_ELEMENT_ARRAY_BUFFER) { 437 GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING); 438 context->updateBufferSubData(bufferId, offset, datap, size); 439 } 440 441 // add buffer data to the protobuf message 442 addGlBufferData(glmsg, 3, datap, size); 443} 444 445/** Obtain the size of each vertex attribute. */ 446int vertexAttribSize(GLenum type, GLsizei numComponents) { 447 int sizePerComponent; 448 449 switch(type) { 450 case GL_BYTE: 451 case GL_UNSIGNED_BYTE: 452 sizePerComponent = 1; 453 break; 454 case GL_SHORT: 455 case GL_UNSIGNED_SHORT: 456 sizePerComponent = 2; 457 break; 458 case GL_FIXED: 459 case GL_FLOAT: 460 default: 461 sizePerComponent = 4; 462 break; 463 } 464 465 return sizePerComponent * numComponents; 466} 467 468/** Create and send a glVertexAttribPointerData trace message to the host. */ 469void trace_glVertexAttribPointerData(GLTraceContext *context, 470 GLuint indx, GLint size, GLenum type, 471 GLboolean normalized, GLsizei stride, const GLvoid* ptr, 472 GLuint minIndex, GLuint maxIndex, nsecs_t startTime) { 473 /* void glVertexAttribPointerData(GLuint indx, GLint size, GLenum type, 474 GLboolean normalized, GLsizei stride, const GLvoid* ptr, 475 int minIndex, int maxIndex) */ 476 GLMessage glmsg; 477 GLTraceContext *glContext = context; 478 479 glmsg.set_function(GLMessage::glVertexAttribPointerData); 480 481 // copy argument indx 482 GLMessage_DataType *arg_indx = glmsg.add_args(); 483 arg_indx->set_isarray(false); 484 arg_indx->set_type(GLMessage::DataType::INT); 485 arg_indx->add_intvalue(indx); 486 487 // copy argument size 488 GLMessage_DataType *arg_size = glmsg.add_args(); 489 arg_size->set_isarray(false); 490 arg_size->set_type(GLMessage::DataType::INT); 491 arg_size->add_intvalue(size); 492 493 // copy argument type 494 GLMessage_DataType *arg_type = glmsg.add_args(); 495 arg_type->set_isarray(false); 496 arg_type->set_type(GLMessage::DataType::ENUM); 497 arg_type->add_intvalue((int)type); 498 499 // copy argument normalized 500 GLMessage_DataType *arg_normalized = glmsg.add_args(); 501 arg_normalized->set_isarray(false); 502 arg_normalized->set_type(GLMessage::DataType::BOOL); 503 arg_normalized->add_boolvalue(normalized); 504 505 // copy argument stride 506 GLMessage_DataType *arg_stride = glmsg.add_args(); 507 arg_stride->set_isarray(false); 508 arg_stride->set_type(GLMessage::DataType::INT); 509 arg_stride->add_intvalue(stride); 510 511 // copy argument ptr 512 GLMessage_DataType *arg_ptr = glmsg.add_args(); 513 arg_ptr->set_isarray(true); 514 arg_ptr->set_type(GLMessage::DataType::BYTE); 515 int perVertexSize = vertexAttribSize(type, size); 516 GLchar *p = (GLchar*) ptr; 517 std::string data; 518 for (GLuint i = minIndex; i < maxIndex; i++) { 519 data.append(p, perVertexSize); 520 p += stride == 0 ? perVertexSize : stride; 521 } 522 arg_ptr->add_rawbytes(data); 523 524 // copy argument min index 525 GLMessage_DataType *arg_min = glmsg.add_args(); 526 arg_min->set_isarray(false); 527 arg_min->set_type(GLMessage::DataType::INT); 528 arg_min->add_intvalue(minIndex); 529 530 // copy argument max index 531 GLMessage_DataType *arg_max = glmsg.add_args(); 532 arg_max->set_isarray(false); 533 arg_max->set_type(GLMessage::DataType::INT); 534 arg_max->add_intvalue(maxIndex); 535 536 glmsg.set_context_id(context->getId()); 537 glmsg.set_start_time(startTime); 538 glmsg.set_threadtime(0); 539 glmsg.set_duration(0); 540 541 context->traceGLMessage(&glmsg); 542} 543 544void findMinAndMaxIndices(GLvoid *indices, GLsizei count, GLenum type, 545 GLuint *minIndex, GLuint *maxIndex) { 546 GLuint index; 547 *minIndex = UINT_MAX; 548 *maxIndex = 0; 549 550 if (indices == NULL) { 551 return; 552 } 553 554 for (GLsizei i = 0; i < count; i++) { 555 if (type == GL_UNSIGNED_BYTE) { 556 index = *((GLubyte*) indices + i); 557 } else { 558 index = *((GLushort*) indices + i); 559 } 560 561 if (index < *minIndex) *minIndex = index; 562 if (index > *maxIndex) *maxIndex = index; 563 } 564} 565 566void trace_VertexAttribPointerData(GLTraceContext *context, 567 GLuint minIndex, GLuint maxIndex, nsecs_t time) { 568 GLuint maxAttribs = glGetInteger(context, GL_MAX_VERTEX_ATTRIBS); 569 for (GLuint index = 0; index < maxAttribs; index++) { 570 if (!glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_ENABLED)) { 571 // vertex array disabled 572 continue; 573 } 574 575 if (glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)) { 576 // vbo 577 continue; 578 } 579 580 GLint size = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_SIZE); 581 GLenum type = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_TYPE); 582 GLboolean norm = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED); 583 GLsizei stride = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_STRIDE); 584 GLvoid* ptr; 585 context->hooks->gl.glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr); 586 587 trace_glVertexAttribPointerData(context, 588 index, size, type, norm, stride, ptr, 589 minIndex, maxIndex, time); 590 } 591} 592 593void trace_VertexAttribPointerDataForGlDrawArrays(GLTraceContext *context, GLMessage *glmsg) { 594 if (context->getVersion() == egl_connection_t::GLESv1_INDEX) { 595 // only supported for GLES2 and above 596 return; 597 } 598 599 /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */ 600 GLsizei count = glmsg->args(2).intvalue(0); 601 602 // Vertex attrib pointer data patchup calls should appear as if 603 // they occurred right before the draw call. 604 nsecs_t time = glmsg->start_time() - 1; 605 606 trace_VertexAttribPointerData(context, 0, count, time); 607} 608 609void trace_VertexAttribPointerDataForGlDrawElements(GLTraceContext *context, GLMessage *glmsg, 610 GLvoid *indices) { 611 if (context->getVersion() == egl_connection_t::GLESv1_INDEX) { 612 // only supported for GLES2 and above 613 return; 614 } 615 616 /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */ 617 GLsizei count = glmsg->args(1).intvalue(0); 618 GLenum type = glmsg->args(2).intvalue(0); 619 GLuint index; 620 621 GLuint minIndex, maxIndex; 622 623 // The index buffer is either passed in as an argument to the glDrawElements() call, 624 // or it is stored in the current GL_ELEMENT_ARRAY_BUFFER. 625 GLvoid *indexBuffer; 626 if (isUsingElementArrayBuffers(context)) { 627 GLsizeiptr eaBufferSize; 628 GLuint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING); 629 context->getBuffer(bufferId, &indexBuffer, &eaBufferSize); 630 } else { 631 indexBuffer = indices; 632 } 633 634 // Rather than sending vertex attribute data that corresponds to the indices 635 // being drawn, we send the vertex attribute data for the entire range of 636 // indices being drawn, including the ones not drawn. The min & max indices 637 // provide the range of indices being drawn. 638 findMinAndMaxIndices(indexBuffer, count, type, &minIndex, &maxIndex); 639 640 // Vertex attrib pointer data patchup calls should appear as if 641 // they occurred right before the draw call. 642 nsecs_t time = glmsg->start_time() - 1; 643 644 trace_VertexAttribPointerData(context, minIndex, maxIndex + 1, time); 645} 646 647void fixup_glDrawArrays(GLTraceContext *context, GLMessage *glmsg) { 648 // Trace all vertex attribute data stored in client space. 649 trace_VertexAttribPointerDataForGlDrawArrays(context, glmsg); 650 651 // Attach the FB if requested 652 if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) { 653 fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB); 654 } 655} 656 657void fixup_glDrawElements(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) { 658 /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */ 659 GLvoid *indices = pointersToFixup[0]; 660 GLenum type = glmsg->args(2).intvalue(0); 661 GLsizei count = glmsg->args(1).intvalue(0); 662 GLuint index; 663 664 // Trace all vertex attribute data stored in client space. 665 trace_VertexAttribPointerDataForGlDrawElements(context, glmsg, indices); 666 667 // Fixup indices argument 668 if (!isUsingElementArrayBuffers(context)) { 669 GLMessage_DataType *arg_indices = glmsg->mutable_args(3); 670 arg_indices->set_isarray(true); 671 arg_indices->clear_intvalue(); 672 arg_indices->set_type(GLMessage::DataType::INT); 673 for (GLsizei i = 0; i < count; i++) { 674 if (type == GL_UNSIGNED_BYTE) { 675 index = *((GLubyte*) indices + i); 676 } else { 677 index = *((GLushort*) indices + i); 678 } 679 arg_indices->add_intvalue(index); 680 } 681 } 682 683 // Attach the FB if requested 684 if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) { 685 fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB); 686 } 687} 688 689void fixupGLMessage(GLTraceContext *context, nsecs_t wallStart, nsecs_t wallEnd, 690 nsecs_t threadStart, nsecs_t threadEnd, 691 GLMessage *glmsg, void *pointersToFixup[]) { 692 // for all messages, set the current context id 693 glmsg->set_context_id(context->getId()); 694 695 // set start time and duration 696 glmsg->set_start_time(wallStart); 697 glmsg->set_duration((unsigned)(wallEnd - wallStart)); 698 glmsg->set_threadtime((unsigned)(threadEnd - threadStart)); 699 700 // do any custom message dependent processing 701 switch (glmsg->function()) { 702 case GLMessage::glDeleteBuffers: /* glDeleteBuffers(GLsizei n, GLuint *buffers); */ 703 case GLMessage::glDeleteFramebuffers: /* glDeleteFramebuffers(GLsizei n, GLuint *buffers); */ 704 case GLMessage::glDeleteRenderbuffers:/* glDeleteRenderbuffers(GLsizei n, GLuint *buffers); */ 705 case GLMessage::glDeleteTextures: /* glDeleteTextures(GLsizei n, GLuint *textures); */ 706 fixup_glDeleteGeneric(glmsg, pointersToFixup); 707 break; 708 case GLMessage::glGenBuffers: /* void glGenBuffers(GLsizei n, GLuint *buffers); */ 709 case GLMessage::glGenFramebuffers: /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */ 710 case GLMessage::glGenRenderbuffers: /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */ 711 case GLMessage::glGenTextures: /* void glGenTextures(GLsizei n, GLuint *textures); */ 712 fixup_glGenGeneric(glmsg, pointersToFixup); 713 break; 714 case GLMessage::glLinkProgram: /* void glLinkProgram(GLuint program); */ 715 fixup_glLinkProgram(glmsg); 716 break; 717 case GLMessage::glGetActiveAttrib: 718 fixup_glGetActiveAttribOrUniform(context, glmsg, pointersToFixup); 719 break; 720 case GLMessage::glGetActiveUniform: 721 fixup_glGetActiveAttribOrUniform(context, glmsg, pointersToFixup); 722 break; 723 case GLMessage::glBindAttribLocation: 724 /* void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name); */ 725 fixup_CStringPtr(2, glmsg, pointersToFixup[0]); 726 break; 727 case GLMessage::glGetAttribLocation: 728 case GLMessage::glGetUniformLocation: 729 /* int glGetAttribLocation(GLuint program, const GLchar* name) */ 730 /* int glGetUniformLocation(GLuint program, const GLchar* name) */ 731 fixup_CStringPtr(1, glmsg, pointersToFixup[0]); 732 break; 733 case GLMessage::glGetBooleanv: 734 fixup_glGetBooleanv(glmsg, pointersToFixup); 735 break; 736 case GLMessage::glGetFloatv: 737 fixup_glGetFloatv(glmsg, pointersToFixup); 738 break; 739 case GLMessage::glGetIntegerv: /* void glGetIntegerv(GLenum pname, GLint *params); */ 740 fixup_GenericIntArray(1, 1, glmsg, pointersToFixup[0]); 741 break; 742 case GLMessage::glGetProgramiv: 743 case GLMessage::glGetRenderbufferParameteriv: 744 case GLMessage::glGetShaderiv: 745 /* void glGetProgramiv(GLuint program, GLenum pname, GLint* params) */ 746 /* void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) */ 747 /* void glGetShaderiv(GLuint shader, GLenum pname, GLint* params) */ 748 fixup_GenericIntArray(2, 1, glmsg, pointersToFixup[0]); 749 break; 750 case GLMessage::glGetString: 751 fixup_glGetString(glmsg, pointersToFixup); 752 break; 753 case GLMessage::glTexImage2D: 754 if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) { 755 fixup_glTexImage2D(glmsg, pointersToFixup); 756 } 757 break; 758 case GLMessage::glTexSubImage2D: 759 if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) { 760 fixup_glTexSubImage2D(glmsg, pointersToFixup); 761 } 762 break; 763 case GLMessage::glShaderSource: 764 fixup_glShaderSource(glmsg, pointersToFixup); 765 break; 766 case GLMessage::glUniform1iv: 767 /* void glUniform1iv(GLint location, GLsizei count, const GLint *value); */ 768 fixup_glUniformGenericInteger(2, 1, glmsg, pointersToFixup); 769 break; 770 case GLMessage::glUniform2iv: 771 /* void glUniform2iv(GLint location, GLsizei count, const GLint *value); */ 772 fixup_glUniformGenericInteger(2, 2, glmsg, pointersToFixup); 773 break; 774 case GLMessage::glUniform3iv: 775 /* void glUniform3iv(GLint location, GLsizei count, const GLint *value); */ 776 fixup_glUniformGenericInteger(2, 3, glmsg, pointersToFixup); 777 break; 778 case GLMessage::glUniform4iv: 779 /* void glUniform4iv(GLint location, GLsizei count, const GLint *value); */ 780 fixup_glUniformGenericInteger(2, 4, glmsg, pointersToFixup); 781 break; 782 case GLMessage::glUniform1fv: 783 /* void glUniform1fv(GLint location, GLsizei count, const GLfloat *value); */ 784 fixup_glUniformGeneric(2, 1, glmsg, pointersToFixup[0]); 785 break; 786 case GLMessage::glUniform2fv: 787 /* void glUniform2fv(GLint location, GLsizei count, const GLfloat *value); */ 788 fixup_glUniformGeneric(2, 2, glmsg, pointersToFixup[0]); 789 break; 790 case GLMessage::glUniform3fv: 791 /* void glUniform3fv(GLint location, GLsizei count, const GLfloat *value); */ 792 fixup_glUniformGeneric(2, 3, glmsg, pointersToFixup[0]); 793 break; 794 case GLMessage::glUniform4fv: 795 /* void glUniform4fv(GLint location, GLsizei count, const GLfloat *value); */ 796 fixup_glUniformGeneric(2, 4, glmsg, pointersToFixup[0]); 797 break; 798 case GLMessage::glUniformMatrix2fv: 799 /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, 800 const GLfloat* value) */ 801 fixup_glUniformMatrixGeneric(2, glmsg, pointersToFixup); 802 break; 803 case GLMessage::glUniformMatrix3fv: 804 /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, 805 const GLfloat* value) */ 806 fixup_glUniformMatrixGeneric(3, glmsg, pointersToFixup); 807 break; 808 case GLMessage::glUniformMatrix4fv: 809 /* void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, 810 const GLfloat* value) */ 811 fixup_glUniformMatrixGeneric(4, glmsg, pointersToFixup); 812 break; 813 case GLMessage::glBufferData: 814 /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */ 815 fixup_glBufferData(context, glmsg, pointersToFixup); 816 break; 817 case GLMessage::glBufferSubData: 818 /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */ 819 fixup_glBufferSubData(context, glmsg, pointersToFixup); 820 break; 821 case GLMessage::glDrawArrays: 822 /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */ 823 fixup_glDrawArrays(context, glmsg); 824 break; 825 case GLMessage::glDrawElements: 826 /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */ 827 fixup_glDrawElements(context, glmsg, pointersToFixup); 828 break; 829 case GLMessage::glPushGroupMarkerEXT: 830 /* void PushGroupMarkerEXT(sizei length, const char *marker); */ 831 fixup_CStringPtr(1, glmsg, pointersToFixup[0]); 832 break; 833 case GLMessage::glInsertEventMarkerEXT: 834 /* void InsertEventMarkerEXT(sizei length, const char *marker); */ 835 fixup_CStringPtr(1, glmsg, pointersToFixup[0]); 836 break; 837 default: 838 break; 839 } 840} 841 842}; 843}; 844