Home | History | Annotate | Download | only in src
      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     }
    243 
    244     arg_strpp->add_charvalue(src);
    245 }
    246 
    247 void 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 
    253 void fixup_glUniformGeneric(int argIndex, int nFloats, GLMessage *glmsg, void *src) {
    254     fixup_GenericFloatArray(argIndex, nFloats, glmsg, src);
    255 }
    256 
    257 void 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 
    265 void 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 
    273 void 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 
    281 void 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 
    292 void 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 
    303 void 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  */
    342 GLint 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 
    357 void 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 
    382 GLint glGetInteger(GLTraceContext *context, GLenum param) {
    383     GLint x;
    384     context->hooks->gl.glGetIntegerv(param, &x);
    385     return x;
    386 }
    387 
    388 GLint glGetVertexAttrib(GLTraceContext *context, GLuint index, GLenum pname) {
    389     GLint x;
    390     context->hooks->gl.glGetVertexAttribiv(index, pname, &x);
    391     return x;
    392 }
    393 
    394 bool isUsingArrayBuffers(GLTraceContext *context) {
    395     return glGetInteger(context, GL_ARRAY_BUFFER_BINDING) != 0;
    396 }
    397 
    398 bool 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. */
    403 void 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 
    411 void 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 
    430 void 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. */
    446 int 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. */
    469 void 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 
    544 void 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 
    566 void 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 
    593 void 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 
    609 void 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 
    647 void 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 
    657 void 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 
    689 void 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