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