void fixup_glDeleteGeneric(GLMessage *glmsg, void *pointersToFixup[]) {
    /* void glDelete*(GLsizei n, GLuint *buffers); */
    GLMessage_DataType arg_n  = glmsg->args(0);
    GLsizei n = arg_n.intvalue(0);

    fixup_GenericIntArray(1, n, glmsg, pointersToFixup[0]);
}
void fixup_glUniformGenericInteger(int argIndex, int nElemsPerVector, GLMessage *glmsg,
                                                                    void *pointersToFixup[]) {
    /* void glUniform?iv(GLint location, GLsizei count, const GLint *value); */
    GLMessage_DataType arg_count  = glmsg->args(1);
    int n_vectors = arg_count.intvalue(0);
    fixup_GenericIntArray(argIndex, nElemsPerVector * n_vectors, glmsg, pointersToFixup[0]);
}
void fixup_GenericEnumArray(int argIndex, int nEnums, GLMessage *glmsg, void *src) {
    // fixup as if they were ints
    fixup_GenericIntArray(argIndex, nEnums, glmsg, src);

    // and then set the data type to be enum
    GLMessage_DataType *arg_enumarray = glmsg->mutable_args(argIndex);
    arg_enumarray->set_type(GLMessage::DataType::ENUM);
}
void fixup_glGetActiveAttribOrUniform(GLTraceContext *context, GLMessage *glmsg,
                                                                void *pointersToFixup[]) {
    /* void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize,
                GLsizei* length, GLint* size, GLenum* type, GLchar* name); */
    /* void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize,
                GLsizei* length, GLint* size, GLenum* type, GLchar* name) */

    fixup_GenericIntArray(3, 1, glmsg, pointersToFixup[0]);     // length
    fixup_GenericIntArray(4, 1, glmsg, pointersToFixup[1]);     // size
    fixup_GenericEnumArray(5, 1, glmsg, pointersToFixup[2]);    // type
    fixup_CStringPtr(6, glmsg, pointersToFixup[3]);             // name

    // The index argument in the glGetActive[Attrib|Uniform] functions
    // does not correspond to the actual location index as used in
    // glUniform*() or glVertexAttrib*() to actually upload the data.
    // In order to make things simpler for the debugger, we also pass
    // a hidden location argument that stores the actual location.
    // append the location value to the end of the argument list
    GLint location = getShaderVariableLocation(context, glmsg, (GLchar*)pointersToFixup[3]);
    GLMessage_DataType *arg_location = glmsg->add_args();
    arg_location->set_isarray(false);
    arg_location->set_type(GLMessage::DataType::INT);
    arg_location->add_intvalue(location);
}
void fixupGLMessage(GLTraceContext *context, nsecs_t wallStart, nsecs_t wallEnd,
                                             nsecs_t threadStart, nsecs_t threadEnd,
                                             GLMessage *glmsg, void *pointersToFixup[]) {
    // for all messages, set the current context id
    glmsg->set_context_id(context->getId());

    // set start time and duration
    glmsg->set_start_time(wallStart);
    glmsg->set_duration((unsigned)(wallEnd - wallStart));
    glmsg->set_threadtime((unsigned)(threadEnd - threadStart));

    // do any custom message dependent processing
    switch (glmsg->function()) {
    case GLMessage::glDeleteBuffers:      /* glDeleteBuffers(GLsizei n, GLuint *buffers); */
    case GLMessage::glDeleteFramebuffers: /* glDeleteFramebuffers(GLsizei n, GLuint *buffers); */
    case GLMessage::glDeleteRenderbuffers:/* glDeleteRenderbuffers(GLsizei n, GLuint *buffers); */
    case GLMessage::glDeleteTextures:     /* glDeleteTextures(GLsizei n, GLuint *textures); */
        fixup_glDeleteGeneric(glmsg, pointersToFixup);
        break;
    case GLMessage::glGenBuffers:        /* void glGenBuffers(GLsizei n, GLuint *buffers); */
    case GLMessage::glGenFramebuffers:   /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */
    case GLMessage::glGenRenderbuffers:  /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */
    case GLMessage::glGenTextures:       /* void glGenTextures(GLsizei n, GLuint *textures); */
        fixup_glGenGeneric(glmsg, pointersToFixup);
        break;
    case GLMessage::glLinkProgram:       /* void glLinkProgram(GLuint program); */
        fixup_glLinkProgram(glmsg);
        break;
    case GLMessage::glGetActiveAttrib:
        fixup_glGetActiveAttribOrUniform(context, glmsg, pointersToFixup);
        break;
    case GLMessage::glGetActiveUniform:
        fixup_glGetActiveAttribOrUniform(context, glmsg, pointersToFixup);
        break;
    case GLMessage::glBindAttribLocation:
        /* void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name); */
        fixup_CStringPtr(2, glmsg, pointersToFixup[0]);
        break;
    case GLMessage::glGetAttribLocation:
    case GLMessage::glGetUniformLocation:
        /* int glGetAttribLocation(GLuint program, const GLchar* name) */
        /* int glGetUniformLocation(GLuint program, const GLchar* name) */
        fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
        break;
    case GLMessage::glGetBooleanv:
        fixup_glGetBooleanv(glmsg, pointersToFixup);
        break;
    case GLMessage::glGetFloatv:
        fixup_glGetFloatv(glmsg, pointersToFixup);
        break;
    case GLMessage::glGetIntegerv:        /* void glGetIntegerv(GLenum pname, GLint *params); */
        fixup_GenericIntArray(1, 1, glmsg, pointersToFixup[0]);
        break;
    case GLMessage::glGetProgramiv:
    case GLMessage::glGetRenderbufferParameteriv:
    case GLMessage::glGetShaderiv:
        /* void glGetProgramiv(GLuint program, GLenum pname, GLint* params) */
        /* void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) */
        /* void glGetShaderiv(GLuint shader, GLenum pname, GLint* params) */
        fixup_GenericIntArray(2, 1, glmsg, pointersToFixup[0]);
        break;
    case GLMessage::glGetString:
        fixup_glGetString(glmsg, pointersToFixup);
        break;
    case GLMessage::glTexImage2D:
        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
            fixup_glTexImage2D(context, glmsg, pointersToFixup);
        }
        break;
    case GLMessage::glTexSubImage2D:
        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
            fixup_glTexSubImage2D(context, glmsg, pointersToFixup);
        }
        break;
    case GLMessage::glCompressedTexImage2D:
        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
            fixup_glCompressedTexImage2D(context, glmsg, pointersToFixup);
        }
        break;
    case GLMessage::glCompressedTexSubImage2D:
        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
            fixup_glCompressedTexSubImage2D(context, glmsg, pointersToFixup);
        }
        break;
    case GLMessage::glShaderSource:
        fixup_glShaderSource(glmsg, pointersToFixup);
        break;
    case GLMessage::glUniform1iv:
        /* void glUniform1iv(GLint location, GLsizei count, const GLint *value); */
        fixup_glUniformGenericInteger(2, 1, glmsg, pointersToFixup);
        break;
    case GLMessage::glUniform2iv:
        /* void glUniform2iv(GLint location, GLsizei count, const GLint *value); */
        fixup_glUniformGenericInteger(2, 2, glmsg, pointersToFixup);
        break;
    case GLMessage::glUniform3iv:
        /* void glUniform3iv(GLint location, GLsizei count, const GLint *value); */
        fixup_glUniformGenericInteger(2, 3, glmsg, pointersToFixup);
        break;
    case GLMessage::glUniform4iv:
        /* void glUniform4iv(GLint location, GLsizei count, const GLint *value); */
        fixup_glUniformGenericInteger(2, 4, glmsg, pointersToFixup);
        break;
    case GLMessage::glUniform1fv:
        /* void glUniform1fv(GLint location, GLsizei count, const GLfloat *value); */
        fixup_glUniformGeneric(2, 1, glmsg, pointersToFixup[0]);
        break;
    case GLMessage::glUniform2fv:
        /* void glUniform2fv(GLint location, GLsizei count, const GLfloat *value); */
        fixup_glUniformGeneric(2, 2, glmsg, pointersToFixup[0]);
        break;
    case GLMessage::glUniform3fv:
        /* void glUniform3fv(GLint location, GLsizei count, const GLfloat *value); */
        fixup_glUniformGeneric(2, 3, glmsg, pointersToFixup[0]);
        break;
    case GLMessage::glUniform4fv:
        /* void glUniform4fv(GLint location, GLsizei count, const GLfloat *value); */
        fixup_glUniformGeneric(2, 4, glmsg, pointersToFixup[0]);
        break;
    case GLMessage::glUniformMatrix2fv:
        /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
                                                                    const GLfloat* value) */
        fixup_glUniformMatrixGeneric(2, glmsg, pointersToFixup);
        break;
    case GLMessage::glUniformMatrix3fv:
        /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
                                                                    const GLfloat* value) */
        fixup_glUniformMatrixGeneric(3, glmsg, pointersToFixup);
        break;
    case GLMessage::glUniformMatrix4fv:
        /* void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
                                                                    const GLfloat* value) */
        fixup_glUniformMatrixGeneric(4, glmsg, pointersToFixup);
        break;
    case GLMessage::glBufferData:
        /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
        fixup_glBufferData(context, glmsg, pointersToFixup);
        break;
    case GLMessage::glBufferSubData:
        /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
        fixup_glBufferSubData(context, glmsg, pointersToFixup);
        break;
    case GLMessage::glDrawArrays:
        /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
        fixup_glDrawArrays(context, glmsg);
        break;
    case GLMessage::glDrawElements:
        /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
        fixup_glDrawElements(context, glmsg, pointersToFixup);
        break;
    case GLMessage::glPushGroupMarkerEXT:
        /* void PushGroupMarkerEXT(sizei length, const char *marker); */
        fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
        break;
    case GLMessage::glInsertEventMarkerEXT:
        /* void InsertEventMarkerEXT(sizei length, const char *marker); */
        fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
        break;
    default:
        break;
    }
}
void fixup_glUniformGenericInteger(int argIndex, int nIntegers, GLMessage *glmsg,
                                                                    void *pointersToFixup[]) {
    /* void glUniform?iv(GLint location, GLsizei count, const GLint *value); */
    fixup_GenericIntArray(argIndex, nIntegers, glmsg, pointersToFixup[0]);
}