gltrace_fixup.cpp revision 9801142afbe3d906259b634ef3bc8bebdafe0083
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 <GLES/gl.h>
19#include <GLES/glext.h>
20#include <GLES2/gl2.h>
21#include <GLES2/gl2ext.h>
22
23#include "gltrace.pb.h"
24#include "gltrace_api.h"
25#include "gltrace_context.h"
26#include "gltrace_fixup.h"
27
28namespace android {
29namespace gltrace {
30
31unsigned getBytesPerTexel(const GLenum format, const GLenum type) {
32    /*
33    Description from glTexImage2D spec:
34
35    Data is read from data as a sequence of unsigned bytes or shorts, depending on type.
36    When type is GL_UNSIGNED_BYTE, each of the bytes is interpreted as one color component.
37    When type is one of GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, or
38    GL_UNSIGNED_SHORT_5_5_5_1, each unsigned short value is interpreted as containing all
39    the components for a single texel, with the color components arranged according to
40    format. Color components are treated as groups of one, two, three, or four values,
41    again based on format. Groups of components are referred to as texels.
42
43    width × height texels are read from memory, starting at location data. By default,
44    these texels are taken from adjacent memory locations, except that after all width
45    texels are read, the read pointer is advanced to the next four-byte boundary.
46    The four-byte row alignment is specified by glPixelStorei with argument
47    GL_UNPACK_ALIGNMENT, and it can be set to one, two, four, or eight bytes.
48    */
49
50    switch (type) {
51    case GL_UNSIGNED_SHORT_5_6_5:
52    case GL_UNSIGNED_SHORT_4_4_4_4:
53    case GL_UNSIGNED_SHORT_5_5_5_1:
54        return 2;
55    case GL_UNSIGNED_BYTE:
56        break;
57    default:
58        ALOGE("GetBytesPerPixel: unknown type %x", type);
59    }
60
61    switch (format) {
62    case GL_ALPHA:
63    case GL_LUMINANCE:
64        return 1;
65    case GL_LUMINANCE_ALPHA:
66        return 2;
67    case GL_RGB:
68        return 3;
69    case GL_RGBA:
70    case 0x80E1: // GL_BGRA_EXT
71        return 4;
72    default:
73        ALOGE("GetBytesPerPixel: unknown format %x", format);
74    }
75
76    return 1;   // in doubt...
77}
78
79void fixup_GenericFloatArray(int argIndex, int nFloats, GLMessage *glmsg, void *src) {
80    GLMessage_DataType *arg_floatarray = glmsg->mutable_args(argIndex);
81    GLfloat *floatp = (GLfloat *)src;
82
83    if (floatp == NULL) {
84        return;
85    }
86
87    arg_floatarray->set_type(GLMessage::DataType::FLOAT);
88    arg_floatarray->set_isarray(true);
89    arg_floatarray->clear_floatvalue();
90
91    for (int i = 0; i < nFloats; i++, floatp++) {
92        arg_floatarray->add_floatvalue(*floatp);
93    }
94}
95
96void fixup_GenericIntArray(int argIndex, int nInts, GLMessage *glmsg, void *src) {
97    GLMessage_DataType *arg_intarray = glmsg->mutable_args(argIndex);
98    GLint *intp = (GLint *)src;
99
100    if (intp == NULL) {
101        return;
102    }
103
104    arg_intarray->set_type(GLMessage::DataType::INT);
105    arg_intarray->set_isarray(true);
106    arg_intarray->clear_intvalue();
107
108    for (int i = 0; i < nInts; i++, intp++) {
109        arg_intarray->add_intvalue(*intp);
110    }
111}
112
113void fixup_GenericEnumArray(int argIndex, int nEnums, GLMessage *glmsg, void *src) {
114    // fixup as if they were ints
115    fixup_GenericIntArray(argIndex, nEnums, glmsg, src);
116
117    // and then set the data type to be enum
118    GLMessage_DataType *arg_enumarray = glmsg->mutable_args(argIndex);
119    arg_enumarray->set_type(GLMessage::DataType::ENUM);
120}
121
122/** Generic helper function: extract pointer at argIndex and
123    replace it with the C style string at *pointer */
124void fixup_CStringPtr(int argIndex, GLMessage *glmsg, void *src) {
125    GLMessage_DataType *arg = glmsg->mutable_args(argIndex);
126    GLchar *ptr = (GLchar *) src;
127
128    arg->set_type(GLMessage::DataType::CHAR);
129    arg->set_isarray(true);
130    arg->add_charvalue(ptr);
131}
132
133void fixup_glGetString(GLMessage *glmsg, void *pointersToFixup[]) {
134    /* const GLubyte* GLTrace_glGetString(GLenum name) */
135    GLMessage_DataType *ret = glmsg->mutable_returnvalue();
136    GLchar *ptr = (GLchar *) pointersToFixup[0];
137
138    if (ptr != NULL) {
139        ret->set_type(GLMessage::DataType::CHAR);
140        ret->set_isarray(true);
141        ret->add_charvalue(ptr);
142    }
143}
144
145/* Add the contents of the framebuffer to the protobuf message */
146void fixup_addFBContents(GLTraceContext *context, GLMessage *glmsg, FBBinding fbToRead) {
147    void *fbcontents;
148    unsigned fbsize, fbwidth, fbheight;
149    context->getCompressedFB(&fbcontents, &fbsize, &fbwidth, &fbheight, fbToRead);
150
151    GLMessage_FrameBuffer *fb = glmsg->mutable_fb();
152    fb->set_width(fbwidth);
153    fb->set_height(fbheight);
154    fb->add_contents(fbcontents, fbsize);
155}
156
157/** Common fixup routing for glTexImage2D & glTexSubImage2D. */
158void fixup_glTexImage(int widthIndex, int heightIndex, GLMessage *glmsg, void *dataSrc) {
159    GLMessage_DataType arg_width  = glmsg->args(widthIndex);
160    GLMessage_DataType arg_height = glmsg->args(heightIndex);
161
162    GLMessage_DataType arg_format = glmsg->args(6);
163    GLMessage_DataType arg_type   = glmsg->args(7);
164    GLMessage_DataType *arg_data  = glmsg->mutable_args(8);
165
166    GLsizei width  = arg_width.intvalue(0);
167    GLsizei height = arg_height.intvalue(0);
168    GLenum format  = arg_format.intvalue(0);
169    GLenum type    = arg_type.intvalue(0);
170    void *data     = (void *) dataSrc;
171
172    int bytesPerTexel = getBytesPerTexel(format, type);
173
174    arg_data->set_type(GLMessage::DataType::BYTE);
175    arg_data->clear_rawbytes();
176
177    if (data != NULL) {
178        arg_data->set_isarray(true);
179        arg_data->add_rawbytes(data, bytesPerTexel * width * height);
180    } else {
181        arg_data->set_isarray(false);
182        arg_data->set_type(GLMessage::DataType::VOID);
183    }
184}
185
186
187void fixup_glTexImage2D(GLMessage *glmsg, void *pointersToFixup[]) {
188    /* void glTexImage2D(GLenum target,
189                        GLint level,
190                        GLint internalformat,
191                        GLsizei width,
192                        GLsizei height,
193                        GLint border,
194                        GLenum format,
195                        GLenum type,
196                        const GLvoid *data);
197    */
198    int widthIndex = 3;
199    int heightIndex = 4;
200    fixup_glTexImage(widthIndex, heightIndex, glmsg, pointersToFixup[0]);
201}
202
203void fixup_glTexSubImage2D(GLMessage *glmsg, void *pointersToFixup[]) {
204    /*
205    void glTexSubImage2D(GLenum target,
206                        GLint level,
207                        GLint xoffset,
208                        GLint yoffset,
209                        GLsizei width,
210                        GLsizei height,
211                        GLenum format,
212                        GLenum type,
213                        const GLvoid * data);
214    */
215    int widthIndex = 4;
216    int heightIndex = 5;
217    fixup_glTexImage(widthIndex, heightIndex, glmsg, pointersToFixup[0]);
218}
219
220void fixup_glShaderSource(GLMessage *glmsg, void *pointersToFixup[]) {
221    /* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string,
222                                    const GLint* length) */
223    GLMessage_DataType arg_count  = glmsg->args(1);
224    GLMessage_DataType arg_lenp   = glmsg->args(3);
225    GLMessage_DataType *arg_strpp = glmsg->mutable_args(2);
226
227    GLsizei count = arg_count.intvalue(0);
228    GLchar **stringpp = (GLchar **) pointersToFixup[0];
229    GLint *lengthp = (GLint *) pointersToFixup[1];
230
231    arg_strpp->set_type(GLMessage::DataType::CHAR);
232    arg_strpp->set_isarray(true);
233    arg_strpp->clear_charvalue();
234
235    ::std::string src = "";
236    for (int i = 0; i < count; i++) {
237        if (lengthp != NULL)
238            src.append(*stringpp, *lengthp);
239        else
240            src.append(*stringpp);  // assume null terminated
241        stringpp++;
242        lengthp++;
243    }
244
245    arg_strpp->add_charvalue(src);
246}
247
248void fixup_glUniformGenericInteger(int argIndex, int nIntegers, GLMessage *glmsg,
249                                                                    void *pointersToFixup[]) {
250    /* void glUniform?iv(GLint location, GLsizei count, const GLint *value); */
251    fixup_GenericIntArray(argIndex, nIntegers, glmsg, pointersToFixup[0]);
252}
253
254void fixup_glUniformGeneric(int argIndex, int nFloats, GLMessage *glmsg, void *src) {
255    fixup_GenericFloatArray(argIndex, nFloats, glmsg, src);
256}
257
258void fixup_glUniformMatrixGeneric(int matrixSize, GLMessage *glmsg, void *pointersToFixup[]) {
259    /* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose,
260                                                                const GLfloat* value) */
261    GLMessage_DataType arg_count  = glmsg->args(1);
262    int n_matrices = arg_count.intvalue(0);
263    fixup_glUniformGeneric(3, matrixSize * matrixSize * n_matrices, glmsg, pointersToFixup[0]);
264}
265
266void fixup_glBufferData(int sizeIndex, int dataIndex, GLMessage *glmsg, void *pointersToFixup[]) {
267    /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
268    /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
269    GLsizeiptr size = glmsg->args(sizeIndex).intvalue(0);
270
271    GLMessage_DataType *arg_datap = glmsg->mutable_args(dataIndex);
272    GLvoid *datap = (GLvoid *) pointersToFixup[0];
273
274    if (datap == NULL) {
275        // glBufferData can be called with a NULL data pointer
276        return;
277    }
278
279    arg_datap->set_type(GLMessage::DataType::VOID);
280    arg_datap->set_isarray(true);
281    arg_datap->clear_intvalue();
282
283    arg_datap->add_rawbytes(datap, size);
284}
285
286void fixup_glGenGeneric(GLMessage *glmsg, void *pointersToFixup[]) {
287    /* void glGen*(GLsizei n, GLuint * buffers); */
288    GLMessage_DataType arg_n  = glmsg->args(0);
289    GLsizei n = arg_n.intvalue(0);
290
291    fixup_GenericIntArray(1, n, glmsg, pointersToFixup[0]);
292}
293
294void fixup_glDeleteGeneric(GLMessage *glmsg, void *pointersToFixup[]) {
295    /* void glDelete*(GLsizei n, GLuint *buffers); */
296    GLMessage_DataType arg_n  = glmsg->args(0);
297    GLsizei n = arg_n.intvalue(0);
298
299    fixup_GenericIntArray(1, n, glmsg, pointersToFixup[0]);
300}
301
302void fixup_glGetBooleanv(GLMessage *glmsg, void *pointersToFixup[]) {
303    /* void glGetBooleanv(GLenum pname, GLboolean *params); */
304    GLMessage_DataType *arg_params = glmsg->mutable_args(1);
305    GLboolean *src = (GLboolean*) pointersToFixup[0];
306
307    arg_params->set_type(GLMessage::DataType::BOOL);
308    arg_params->set_isarray(true);
309    arg_params->clear_boolvalue();
310    arg_params->add_boolvalue(*src);
311}
312
313void fixup_glGetFloatv(GLMessage *glmsg, void *pointersToFixup[]) {
314    /* void glGetFloatv(GLenum pname, GLfloat *params); */
315    GLMessage_DataType *arg_params = glmsg->mutable_args(1);
316    GLfloat *src = (GLfloat*) pointersToFixup[0];
317
318    arg_params->set_type(GLMessage::DataType::FLOAT);
319    arg_params->set_isarray(true);
320    arg_params->clear_floatvalue();
321    arg_params->add_floatvalue(*src);
322}
323
324void fixup_glLinkProgram(GLMessage *glmsg) {
325    /* void glLinkProgram(GLuint program); */
326    GLuint program = glmsg->args(0).intvalue(0);
327
328    /* We don't have to fixup this call, but as soon as a program is linked,
329       we obtain information about all active attributes and uniforms to
330       pass on to the debugger. Note that in order to pass this info to
331       the debugger, all we need to do is call the trace versions of the
332       necessary calls. */
333
334    GLint n, maxNameLength;
335    GLchar *name;
336    GLint size;
337    GLenum type;
338
339    // obtain info regarding active attributes
340    GLTrace_glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n);
341    GLTrace_glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLength);
342
343    name = (GLchar *) malloc(maxNameLength);
344    for (int i = 0; i < n; i++) {
345        GLTrace_glGetActiveAttrib(program, i, maxNameLength, NULL, &size, &type, name);
346    }
347    free(name);
348
349    // obtain info regarding active uniforms
350    GLTrace_glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &n);
351    GLTrace_glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
352
353    name = (GLchar *) malloc(maxNameLength);
354    for (int i = 0; i < n; i++) {
355        GLTrace_glGetActiveUniform(program, i, maxNameLength, NULL, &size, &type, name);
356    }
357    free(name);
358}
359
360/** Given a glGetActive[Uniform|Attrib] call, obtain the location
361 *  of the variable of given name in the call.
362 */
363int getShaderVariableLocation(GLTraceContext *context, GLMessage *glmsg, GLchar *name) {
364    GLMessage_Function func = glmsg->function();
365    if (func != GLMessage::glGetActiveAttrib && func != GLMessage::glGetActiveUniform) {
366        return -1;
367    }
368
369    int program = glmsg->args(0).intvalue(0);
370
371    if (func == GLMessage::glGetActiveAttrib) {
372        return context->hooks->gl.glGetAttribLocation(program, name);
373    } else {
374        return context->hooks->gl.glGetUniformLocation(program, name);
375    }
376}
377
378void fixup_glGetActiveAttribOrUniform(GLTraceContext *context, GLMessage *glmsg,
379                                                                void *pointersToFixup[]) {
380    /* void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize,
381                GLsizei* length, GLint* size, GLenum* type, GLchar* name); */
382    /* void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize,
383                GLsizei* length, GLint* size, GLenum* type, GLchar* name) */
384
385    fixup_GenericIntArray(3, 1, glmsg, pointersToFixup[0]);     // length
386    fixup_GenericIntArray(4, 1, glmsg, pointersToFixup[1]);     // size
387    fixup_GenericEnumArray(5, 1, glmsg, pointersToFixup[2]);    // type
388    fixup_CStringPtr(6, glmsg, pointersToFixup[3]);             // name
389
390    // The index argument in the glGetActive[Attrib|Uniform] functions
391    // does not correspond to the actual location index as used in
392    // glUniform*() or glVertexAttrib*() to actually upload the data.
393    // In order to make things simpler for the debugger, we also pass
394    // a hidden location argument that stores the actual location.
395    // append the location value to the end of the argument list
396    int location = getShaderVariableLocation(context, glmsg, (GLchar*)pointersToFixup[3]);
397    GLMessage_DataType *arg_location = glmsg->add_args();
398    arg_location->set_isarray(false);
399    arg_location->set_type(GLMessage::DataType::INT);
400    arg_location->add_intvalue(location);
401}
402
403void fixupGLMessage(GLTraceContext *context, nsecs_t wallStart, nsecs_t wallEnd,
404                                             nsecs_t threadStart, nsecs_t threadEnd,
405                                             GLMessage *glmsg, void *pointersToFixup[]) {
406    // for all messages, set the current context id
407    glmsg->set_context_id(context->getId());
408
409    // set start time and duration
410    glmsg->set_start_time(wallStart);
411    glmsg->set_duration((unsigned)(wallEnd - wallStart));
412    glmsg->set_threadtime((unsigned)(threadEnd - threadStart));
413
414    // do any custom message dependent processing
415    switch (glmsg->function()) {
416    case GLMessage::glDeleteBuffers:      /* glDeleteBuffers(GLsizei n, GLuint *buffers); */
417    case GLMessage::glDeleteFramebuffers: /* glDeleteFramebuffers(GLsizei n, GLuint *buffers); */
418    case GLMessage::glDeleteRenderbuffers:/* glDeleteRenderbuffers(GLsizei n, GLuint *buffers); */
419    case GLMessage::glDeleteTextures:     /* glDeleteTextures(GLsizei n, GLuint *textures); */
420        fixup_glDeleteGeneric(glmsg, pointersToFixup);
421        break;
422    case GLMessage::glGenBuffers:        /* void glGenBuffers(GLsizei n, GLuint *buffers); */
423    case GLMessage::glGenFramebuffers:   /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */
424    case GLMessage::glGenRenderbuffers:  /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */
425    case GLMessage::glGenTextures:       /* void glGenTextures(GLsizei n, GLuint *textures); */
426        fixup_glGenGeneric(glmsg, pointersToFixup);
427        break;
428    case GLMessage::glLinkProgram:       /* void glLinkProgram(GLuint program); */
429        fixup_glLinkProgram(glmsg);
430        break;
431    case GLMessage::glGetActiveAttrib:
432        fixup_glGetActiveAttribOrUniform(context, glmsg, pointersToFixup);
433        break;
434    case GLMessage::glGetActiveUniform:
435        fixup_glGetActiveAttribOrUniform(context, glmsg, pointersToFixup);
436        break;
437    case GLMessage::glBindAttribLocation:
438        /* void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name); */
439        fixup_CStringPtr(2, glmsg, pointersToFixup[0]);
440        break;
441    case GLMessage::glGetAttribLocation:
442    case GLMessage::glGetUniformLocation:
443        /* int glGetAttribLocation(GLuint program, const GLchar* name) */
444        /* int glGetUniformLocation(GLuint program, const GLchar* name) */
445        fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
446        break;
447    case GLMessage::glGetBooleanv:
448        fixup_glGetBooleanv(glmsg, pointersToFixup);
449        break;
450    case GLMessage::glGetFloatv:
451        fixup_glGetFloatv(glmsg, pointersToFixup);
452        break;
453    case GLMessage::glGetIntegerv:        /* void glGetIntegerv(GLenum pname, GLint *params); */
454        fixup_GenericIntArray(1, 1, glmsg, pointersToFixup[0]);
455        break;
456    case GLMessage::glGetProgramiv:
457    case GLMessage::glGetRenderbufferParameteriv:
458    case GLMessage::glGetShaderiv:
459        /* void glGetProgramiv(GLuint program, GLenum pname, GLint* params) */
460        /* void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) */
461        /* void glGetShaderiv(GLuint shader, GLenum pname, GLint* params) */
462        fixup_GenericIntArray(2, 1, glmsg, pointersToFixup[0]);
463        break;
464    case GLMessage::glGetString:
465        fixup_glGetString(glmsg, pointersToFixup);
466        break;
467    case GLMessage::glTexImage2D:
468        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
469            fixup_glTexImage2D(glmsg, pointersToFixup);
470        }
471        break;
472    case GLMessage::glTexSubImage2D:
473        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
474            fixup_glTexSubImage2D(glmsg, pointersToFixup);
475        }
476        break;
477    case GLMessage::glShaderSource:
478        fixup_glShaderSource(glmsg, pointersToFixup);
479        break;
480    case GLMessage::glUniform1iv:
481        /* void glUniform1iv(GLint location, GLsizei count, const GLint *value); */
482        fixup_glUniformGenericInteger(2, 1, glmsg, pointersToFixup);
483        break;
484    case GLMessage::glUniform2iv:
485        /* void glUniform2iv(GLint location, GLsizei count, const GLint *value); */
486        fixup_glUniformGenericInteger(2, 2, glmsg, pointersToFixup);
487        break;
488    case GLMessage::glUniform3iv:
489        /* void glUniform3iv(GLint location, GLsizei count, const GLint *value); */
490        fixup_glUniformGenericInteger(2, 3, glmsg, pointersToFixup);
491        break;
492    case GLMessage::glUniform4iv:
493        /* void glUniform4iv(GLint location, GLsizei count, const GLint *value); */
494        fixup_glUniformGenericInteger(2, 4, glmsg, pointersToFixup);
495        break;
496    case GLMessage::glUniform1fv:
497        /* void glUniform1fv(GLint location, GLsizei count, const GLfloat *value); */
498        fixup_glUniformGeneric(2, 1, glmsg, pointersToFixup[0]);
499        break;
500    case GLMessage::glUniform2fv:
501        /* void glUniform2fv(GLint location, GLsizei count, const GLfloat *value); */
502        fixup_glUniformGeneric(2, 2, glmsg, pointersToFixup[0]);
503        break;
504    case GLMessage::glUniform3fv:
505        /* void glUniform3fv(GLint location, GLsizei count, const GLfloat *value); */
506        fixup_glUniformGeneric(2, 3, glmsg, pointersToFixup[0]);
507        break;
508    case GLMessage::glUniform4fv:
509        /* void glUniform4fv(GLint location, GLsizei count, const GLfloat *value); */
510        fixup_glUniformGeneric(2, 4, glmsg, pointersToFixup[0]);
511        break;
512    case GLMessage::glUniformMatrix2fv:
513        /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
514                                                                    const GLfloat* value) */
515        fixup_glUniformMatrixGeneric(2, glmsg, pointersToFixup);
516        break;
517    case GLMessage::glUniformMatrix3fv:
518        /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
519                                                                    const GLfloat* value) */
520        fixup_glUniformMatrixGeneric(3, glmsg, pointersToFixup);
521        break;
522    case GLMessage::glUniformMatrix4fv:
523        /* void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
524                                                                    const GLfloat* value) */
525        fixup_glUniformMatrixGeneric(4, glmsg, pointersToFixup);
526        break;
527    case GLMessage::glBufferData:
528        /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
529        fixup_glBufferData(1, 2, glmsg, pointersToFixup);
530        break;
531    case GLMessage::glBufferSubData:
532        /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
533        fixup_glBufferData(2, 3, glmsg, pointersToFixup);
534        break;
535    case GLMessage::glDrawArrays:
536        /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
537        if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
538            fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
539        }
540        break;
541    case GLMessage::glDrawElements:
542        /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
543        if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
544            fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
545        }
546        break;
547    case GLMessage::glPushGroupMarkerEXT:
548        /* void PushGroupMarkerEXT(sizei length, const char *marker); */
549        fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
550        break;
551    case GLMessage::glInsertEventMarkerEXT:
552        /* void InsertEventMarkerEXT(sizei length, const char *marker); */
553        fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
554        break;
555    default:
556        break;
557    }
558}
559
560};
561};
562