gltrace: Send vertex attribute data after glDraw() call.

This patch enables tracing of vertex attribute data that
is specified using glVertexAttribPointer().

At the time the glVertexAttribPointer() call is made, we
only receive a pointer in client space, without any indication
of the size (# of attributes). This size is known only at
the time of the glDraw() call.

This patch generates a new message glVertexAttribPointerData()
when a draw call is issued that contains the vertex attribute
data.

A glDrawArrays() call directly gives the size of data to copy.
A glDrawElements() call gives the indices to copy. In such a
case, all data between the min & max indices drawn are copied
and sent to the host. To support glDrawElements() with an
element array buffer, this patch also adds state that maintains
a copy of all element array buffers.

Change-Id: I434da794a0aa9ada8e7474e219ffb1d79b183ecf
This commit is contained in:
Siva Velusamy 2012-02-29 14:04:04 -08:00
parent 91fe608f1c
commit 50129e4ae2
7 changed files with 418 additions and 51 deletions

View File

@ -6,10 +6,9 @@ genproto: gltrace.proto
aprotoc --cpp_out=src --java_out=java gltrace.proto
mv src/gltrace.pb.cc src/gltrace.pb.cpp
# NOTE: $OUT should be defined in the shell by doing a "lunch <config>"
# push updated files to device
push:
adb push $(OUT)/system/lib/libGLESv2.so /system/lib/
adb push $(OUT)/system/lib/libGLESv1_CM.so /system/lib/
adb push $(OUT)/system/lib/libGLES_trace.so /system/lib/
adb push $(OUT)/system/lib/libEGL.so /system/lib/
sync:
adb root
adb remount
adb shell stop
adb sync
adb shell start

View File

@ -510,7 +510,7 @@ message GLMessage {
eglGetSystemTimeNV = 2045;
invalid = 3000;
frameBufferContents = 3001;
glVertexAttribPointerData = 3001;
}
// A GL call's return data and arguments are formatted into this DataType

View File

@ -1018,7 +1018,7 @@ const GLMessage_Function GLMessage::eglGetRenderBufferANDROID;
const GLMessage_Function GLMessage::eglGetSystemTimeFrequencyNV;
const GLMessage_Function GLMessage::eglGetSystemTimeNV;
const GLMessage_Function GLMessage::invalid;
const GLMessage_Function GLMessage::frameBufferContents;
const GLMessage_Function GLMessage::glVertexAttribPointerData;
const GLMessage_Function GLMessage::Function_MIN;
const GLMessage_Function GLMessage::Function_MAX;
const int GLMessage::Function_ARRAYSIZE;

View File

@ -535,11 +535,11 @@ enum GLMessage_Function {
GLMessage_Function_eglGetSystemTimeFrequencyNV = 2044,
GLMessage_Function_eglGetSystemTimeNV = 2045,
GLMessage_Function_invalid = 3000,
GLMessage_Function_frameBufferContents = 3001
GLMessage_Function_glVertexAttribPointerData = 3001
};
bool GLMessage_Function_IsValid(int value);
const GLMessage_Function GLMessage_Function_Function_MIN = GLMessage_Function_glActiveTexture;
const GLMessage_Function GLMessage_Function_Function_MAX = GLMessage_Function_frameBufferContents;
const GLMessage_Function GLMessage_Function_Function_MAX = GLMessage_Function_glVertexAttribPointerData;
const int GLMessage_Function_Function_ARRAYSIZE = GLMessage_Function_Function_MAX + 1;
// ===================================================================
@ -1351,7 +1351,7 @@ class GLMessage : public ::google::protobuf::MessageLite {
static const Function eglGetSystemTimeFrequencyNV = GLMessage_Function_eglGetSystemTimeFrequencyNV;
static const Function eglGetSystemTimeNV = GLMessage_Function_eglGetSystemTimeNV;
static const Function invalid = GLMessage_Function_invalid;
static const Function frameBufferContents = GLMessage_Function_frameBufferContents;
static const Function glVertexAttribPointerData = GLMessage_Function_glVertexAttribPointerData;
static inline bool Function_IsValid(int value) {
return GLMessage_Function_IsValid(value);
}

View File

@ -129,13 +129,14 @@ GLTraceContext *GLTraceState::getTraceContext(EGLContext c) {
return mPerContextState[c];
}
GLTraceContext::GLTraceContext(int id, GLTraceState *state, BufferedOutputStream *stream) {
mId = id;
mState = state;
GLTraceContext::GLTraceContext(int id, GLTraceState *state, BufferedOutputStream *stream) :
mId(id),
mState(state),
mBufferedOutputStream(stream),
mElementArrayBuffers(DefaultKeyedVector<GLuint, ElementArrayBuffer*>(NULL))
{
fbcontents = fbcompressed = NULL;
fbcontentsSize = 0;
mBufferedOutputStream = stream;
}
int GLTraceContext::getId() {
@ -208,5 +209,74 @@ void GLTraceContext::traceGLMessage(GLMessage *msg) {
}
}
void GLTraceContext::bindBuffer(GLuint bufferId, GLvoid *data, GLsizeiptr size) {
// free previously bound buffer if any
ElementArrayBuffer *oldBuffer = mElementArrayBuffers.valueFor(bufferId);
if (oldBuffer != NULL) {
delete oldBuffer;
}
mElementArrayBuffers.add(bufferId, new ElementArrayBuffer(data, size));
}
void GLTraceContext::getBuffer(GLuint bufferId, GLvoid **data, GLsizeiptr *size) {
ElementArrayBuffer *buffer = mElementArrayBuffers.valueFor(bufferId);
if (buffer == NULL) {
*data = NULL;
*size = 0;
} else {
*data = buffer->getBuffer();
*size = buffer->getSize();
}
}
void GLTraceContext::updateBufferSubData(GLuint bufferId, GLintptr offset, GLvoid *data,
GLsizeiptr size) {
ElementArrayBuffer *buffer = mElementArrayBuffers.valueFor(bufferId);
if (buffer != NULL) {
buffer->updateSubBuffer(offset, data, size);
}
}
void GLTraceContext::deleteBuffer(GLuint bufferId) {
ElementArrayBuffer *buffer = mElementArrayBuffers.valueFor(bufferId);
if (buffer != NULL) {
delete buffer;
mElementArrayBuffers.removeItem(bufferId);
}
}
ElementArrayBuffer::ElementArrayBuffer(GLvoid *buf, GLsizeiptr size) {
mBuf = malloc(size);
mSize = size;
if (buf != NULL) {
memcpy(mBuf, buf, size);
}
}
ElementArrayBuffer::~ElementArrayBuffer() {
if (mBuf != NULL) {
free(mBuf);
mSize = 0;
}
mBuf = NULL;
}
void ElementArrayBuffer::updateSubBuffer(GLintptr offset, const GLvoid* data, GLsizeiptr size) {
if (offset + size <= mSize) {
memcpy((char*)mBuf + offset, data, size);
}
}
GLvoid *ElementArrayBuffer::getBuffer() {
return mBuf;
}
GLsizeiptr ElementArrayBuffer::getSize() {
return mSize;
}
}; // namespace gltrace
}; // namespace android

View File

@ -19,6 +19,7 @@
#include <map>
#include <pthread.h>
#include <utils/KeyedVector.h>
#include "hooks.h"
#include "gltrace_transport.h"
@ -32,6 +33,20 @@ enum FBBinding {CURRENTLY_BOUND_FB, FB0};
class GLTraceState;
class ElementArrayBuffer {
GLvoid *mBuf;
GLsizeiptr mSize;
public:
ElementArrayBuffer():mBuf(NULL), mSize(0) {}
ElementArrayBuffer(GLvoid *buf, GLsizeiptr size);
~ElementArrayBuffer();
void updateSubBuffer(GLintptr offset, const GLvoid* data, GLsizeiptr size);
GLvoid *getBuffer();
GLsizeiptr getSize();
};
/** GL Trace Context info associated with each EGLContext */
class GLTraceContext {
int mId; /* unique context id */
@ -43,6 +58,9 @@ class GLTraceContext {
BufferedOutputStream *mBufferedOutputStream; /* stream where trace info is sent */
/* list of element array buffers in use. */
DefaultKeyedVector<GLuint, ElementArrayBuffer*> mElementArrayBuffers;
void resizeFBMemory(unsigned minSize);
public:
gl_hooks_t *hooks;
@ -53,6 +71,13 @@ public:
void getCompressedFB(void **fb, unsigned *fbsize,
unsigned *fbwidth, unsigned *fbheight,
FBBinding fbToRead);
// Methods to work with element array buffers
void bindBuffer(GLuint bufferId, GLvoid *data, GLsizeiptr size);
void getBuffer(GLuint bufferId, GLvoid **data, GLsizeiptr *size);
void updateBufferSubData(GLuint bufferId, GLintptr offset, GLvoid *data, GLsizeiptr size);
void deleteBuffer(GLuint bufferId);
void traceGLMessage(GLMessage *msg);
};

View File

@ -193,7 +193,7 @@ void fixup_glTexImage2D(GLMessage *glmsg, void *pointersToFixup[]) {
GLint border,
GLenum format,
GLenum type,
const GLvoid *data);
const GLvoid *data);
*/
int widthIndex = 3;
int heightIndex = 4;
@ -218,7 +218,7 @@ void fixup_glTexSubImage2D(GLMessage *glmsg, void *pointersToFixup[]) {
}
void fixup_glShaderSource(GLMessage *glmsg, void *pointersToFixup[]) {
/* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string,
/* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string,
const GLint* length) */
GLMessage_DataType arg_count = glmsg->args(1);
GLMessage_DataType arg_lenp = glmsg->args(3);
@ -256,33 +256,13 @@ void fixup_glUniformGeneric(int argIndex, int nFloats, GLMessage *glmsg, void *s
}
void fixup_glUniformMatrixGeneric(int matrixSize, GLMessage *glmsg, void *pointersToFixup[]) {
/* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose,
/* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose,
const GLfloat* value) */
GLMessage_DataType arg_count = glmsg->args(1);
int n_matrices = arg_count.intvalue(0);
fixup_glUniformGeneric(3, matrixSize * matrixSize * n_matrices, glmsg, pointersToFixup[0]);
}
void fixup_glBufferData(int sizeIndex, int dataIndex, GLMessage *glmsg, void *pointersToFixup[]) {
/* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
/* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
GLsizeiptr size = glmsg->args(sizeIndex).intvalue(0);
GLMessage_DataType *arg_datap = glmsg->mutable_args(dataIndex);
GLvoid *datap = (GLvoid *) pointersToFixup[0];
if (datap == NULL) {
// glBufferData can be called with a NULL data pointer
return;
}
arg_datap->set_type(GLMessage::DataType::VOID);
arg_datap->set_isarray(true);
arg_datap->clear_intvalue();
arg_datap->add_rawbytes(datap, size);
}
void fixup_glGenGeneric(GLMessage *glmsg, void *pointersToFixup[]) {
/* void glGen*(GLsizei n, GLuint * buffers); */
GLMessage_DataType arg_n = glmsg->args(0);
@ -375,7 +355,7 @@ int getShaderVariableLocation(GLTraceContext *context, GLMessage *glmsg, GLchar
}
}
void fixup_glGetActiveAttribOrUniform(GLTraceContext *context, GLMessage *glmsg,
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); */
@ -400,6 +380,303 @@ void fixup_glGetActiveAttribOrUniform(GLTraceContext *context, GLMessage *glmsg,
arg_location->add_intvalue(location);
}
GLint glGetInteger(GLTraceContext *context, GLenum param) {
GLint x;
context->hooks->gl.glGetIntegerv(param, &x);
return x;
}
GLint glGetVertexAttrib(GLTraceContext *context, GLuint index, GLenum pname) {
GLint x;
context->hooks->gl.glGetVertexAttribiv(index, pname, &x);
return x;
}
bool isUsingArrayBuffers(GLTraceContext *context) {
return glGetInteger(context, GL_ARRAY_BUFFER_BINDING) != 0;
}
bool isUsingElementArrayBuffers(GLTraceContext *context) {
return glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING) != 0;
}
/** Copy @len bytes of data from @src into the @dataIndex'th argument of the message. */
void addGlBufferData(GLMessage *glmsg, int dataIndex, GLvoid *src, GLsizeiptr len) {
GLMessage_DataType *arg_datap = glmsg->mutable_args(dataIndex);
arg_datap->set_type(GLMessage::DataType::VOID);
arg_datap->set_isarray(true);
arg_datap->clear_intvalue();
arg_datap->add_rawbytes(src, len);
}
void fixup_glBufferData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
/* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
GLsizeiptr size = glmsg->args(1).intvalue(0);
GLvoid *datap = (GLvoid *) pointersToFixup[0];
// Save element array buffers for future use to fixup glVertexAttribPointers
// when a glDrawElements() call is performed.
GLenum target = glmsg->args(0).intvalue(0);
if (target == GL_ELEMENT_ARRAY_BUFFER) {
GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
context->bindBuffer(bufferId, datap, size);
}
// add buffer data to the protobuf message
if (datap != NULL) {
addGlBufferData(glmsg, 2, datap, size);
}
}
void fixup_glBufferSubData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
/* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
GLenum target = glmsg->args(0).intvalue(0);
GLintptr offset = glmsg->args(1).intvalue(0);
GLsizeiptr size = glmsg->args(2).intvalue(0);
GLvoid *datap = (GLvoid *) pointersToFixup[0];
if (target == GL_ELEMENT_ARRAY_BUFFER) {
GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
context->updateBufferSubData(bufferId, offset, datap, size);
}
// add buffer data to the protobuf message
addGlBufferData(glmsg, 3, datap, size);
}
/** Obtain the size of each vertex attribute. */
int vertexAttribSize(GLenum type, GLsizei numComponents) {
int sizePerComponent;
switch(type) {
case GL_BYTE:
case GL_UNSIGNED_BYTE:
sizePerComponent = 1;
break;
case GL_SHORT:
case GL_UNSIGNED_SHORT:
sizePerComponent = 2;
break;
case GL_FIXED:
case GL_FLOAT:
default:
sizePerComponent = 4;
break;
}
return sizePerComponent * numComponents;
}
/** Create and send a glVertexAttribPointerData trace message to the host. */
void trace_glVertexAttribPointerData(GLTraceContext *context,
GLuint indx, GLint size, GLenum type,
GLboolean normalized, GLsizei stride, const GLvoid* ptr,
GLuint minIndex, GLuint maxIndex, nsecs_t startTime) {
/* void glVertexAttribPointerData(GLuint indx, GLint size, GLenum type,
GLboolean normalized, GLsizei stride, const GLvoid* ptr,
int minIndex, int maxIndex) */
GLMessage glmsg;
GLTraceContext *glContext = context;
glmsg.set_function(GLMessage::glVertexAttribPointerData);
// copy argument indx
GLMessage_DataType *arg_indx = glmsg.add_args();
arg_indx->set_isarray(false);
arg_indx->set_type(GLMessage::DataType::INT);
arg_indx->add_intvalue(indx);
// copy argument size
GLMessage_DataType *arg_size = glmsg.add_args();
arg_size->set_isarray(false);
arg_size->set_type(GLMessage::DataType::INT);
arg_size->add_intvalue(size);
// copy argument type
GLMessage_DataType *arg_type = glmsg.add_args();
arg_type->set_isarray(false);
arg_type->set_type(GLMessage::DataType::ENUM);
arg_type->add_intvalue((int)type);
// copy argument normalized
GLMessage_DataType *arg_normalized = glmsg.add_args();
arg_normalized->set_isarray(false);
arg_normalized->set_type(GLMessage::DataType::BOOL);
arg_normalized->add_boolvalue(normalized);
// copy argument stride
GLMessage_DataType *arg_stride = glmsg.add_args();
arg_stride->set_isarray(false);
arg_stride->set_type(GLMessage::DataType::INT);
arg_stride->add_intvalue(stride);
// copy argument ptr
GLMessage_DataType *arg_ptr = glmsg.add_args();
arg_ptr->set_isarray(true);
arg_ptr->set_type(GLMessage::DataType::BYTE);
int perVertexSize = vertexAttribSize(type, size);
GLchar *p = (GLchar*) ptr;
std::string data;
for (GLuint i = minIndex; i < maxIndex; i++) {
data.append(p, perVertexSize);
p += stride == 0 ? perVertexSize : stride;
}
arg_ptr->add_rawbytes(data);
// copy argument min index
GLMessage_DataType *arg_min = glmsg.add_args();
arg_min->set_isarray(false);
arg_min->set_type(GLMessage::DataType::INT);
arg_min->add_intvalue(minIndex);
// copy argument max index
GLMessage_DataType *arg_max = glmsg.add_args();
arg_max->set_isarray(false);
arg_max->set_type(GLMessage::DataType::INT);
arg_max->add_intvalue(maxIndex);
glmsg.set_context_id(context->getId());
glmsg.set_start_time(startTime);
glmsg.set_threadtime(0);
glmsg.set_duration(0);
context->traceGLMessage(&glmsg);
}
void findMinAndMaxIndices(GLvoid *indices, GLsizei count, GLenum type,
GLuint *minIndex, GLuint *maxIndex) {
GLuint index;
*minIndex = UINT_MAX;
*maxIndex = 0;
if (indices == NULL) {
return;
}
for (GLsizei i = 0; i < count; i++) {
if (type == GL_UNSIGNED_BYTE) {
index = *((GLubyte*) indices + i);
} else {
index = *((GLushort*) indices + i);
}
if (index < *minIndex) *minIndex = index;
if (index > *maxIndex) *maxIndex = index;
}
}
void trace_VertexAttribPointerData(GLTraceContext *context,
GLuint minIndex, GLuint maxIndex, nsecs_t time) {
GLuint maxAttribs = glGetInteger(context, GL_MAX_VERTEX_ATTRIBS);
for (GLuint index = 0; index < maxAttribs; index++) {
if (!glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_ENABLED)) {
// vertex array disabled
continue;
}
if (glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)) {
// vbo
continue;
}
GLint size = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_SIZE);
GLenum type = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_TYPE);
GLboolean norm = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED);
GLsizei stride = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_STRIDE);
GLvoid* ptr;
context->hooks->gl.glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr);
trace_glVertexAttribPointerData(context,
index, size, type, norm, stride, ptr,
minIndex, maxIndex, time);
}
}
void trace_VertexAttribPointerDataForGlDrawArrays(GLTraceContext *context, GLMessage *glmsg) {
/* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
GLsizei count = glmsg->args(2).intvalue(0);
// Vertex attrib pointer data patchup calls should appear as if
// they occurred right before the draw call.
nsecs_t time = glmsg->start_time() - 1;
trace_VertexAttribPointerData(context, 0, count, time);
}
void trace_VertexAttribPointerDataForGlDrawElements(GLTraceContext *context, GLMessage *glmsg,
GLvoid *indices) {
/* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
GLsizei count = glmsg->args(1).intvalue(0);
GLenum type = glmsg->args(2).intvalue(0);
GLuint index;
GLuint minIndex, maxIndex;
// The index buffer is either passed in as an argument to the glDrawElements() call,
// or it is stored in the current GL_ELEMENT_ARRAY_BUFFER.
GLvoid *indexBuffer;
if (isUsingElementArrayBuffers(context)) {
GLsizeiptr eaBufferSize;
GLuint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
context->getBuffer(bufferId, &indexBuffer, &eaBufferSize);
} else {
indexBuffer = indices;
}
// Rather than sending vertex attribute data that corresponds to the indices
// being drawn, we send the vertex attribute data for the entire range of
// indices being drawn, including the ones not drawn. The min & max indices
// provide the range of indices being drawn.
findMinAndMaxIndices(indexBuffer, count, type, &minIndex, &maxIndex);
// Vertex attrib pointer data patchup calls should appear as if
// they occurred right before the draw call.
nsecs_t time = glmsg->start_time() - 1;
trace_VertexAttribPointerData(context, minIndex, maxIndex + 1, time);
}
void fixup_glDrawArrays(GLTraceContext *context, GLMessage *glmsg) {
// Trace all vertex attribute data stored in client space.
trace_VertexAttribPointerDataForGlDrawArrays(context, glmsg);
// Attach the FB if requested
if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
}
}
void fixup_glDrawElements(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
/* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
GLvoid *indices = pointersToFixup[0];
GLenum type = glmsg->args(2).intvalue(0);
GLsizei count = glmsg->args(1).intvalue(0);
GLuint index;
// Trace all vertex attribute data stored in client space.
trace_VertexAttribPointerDataForGlDrawElements(context, glmsg, indices);
// Fixup indices argument
if (!isUsingElementArrayBuffers(context)) {
GLMessage_DataType *arg_indices = glmsg->mutable_args(3);
arg_indices->set_isarray(true);
arg_indices->clear_intvalue();
arg_indices->set_type(GLMessage::DataType::INT);
for (GLsizei i = 0; i < count; i++) {
if (type == GL_UNSIGNED_BYTE) {
index = *((GLubyte*) indices + i);
} else {
index = *((GLushort*) indices + i);
}
arg_indices->add_intvalue(index);
}
}
// Attach the FB if requested
if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
}
}
void fixupGLMessage(GLTraceContext *context, nsecs_t wallStart, nsecs_t wallEnd,
nsecs_t threadStart, nsecs_t threadEnd,
GLMessage *glmsg, void *pointersToFixup[]) {
@ -438,8 +715,8 @@ void fixupGLMessage(GLTraceContext *context, nsecs_t wallStart, nsecs_t wallEnd,
/* void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name); */
fixup_CStringPtr(2, glmsg, pointersToFixup[0]);
break;
case GLMessage::glGetAttribLocation:
case GLMessage::glGetUniformLocation:
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]);
@ -526,23 +803,19 @@ void fixupGLMessage(GLTraceContext *context, nsecs_t wallStart, nsecs_t wallEnd,
break;
case GLMessage::glBufferData:
/* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
fixup_glBufferData(1, 2, glmsg, pointersToFixup);
fixup_glBufferData(context, glmsg, pointersToFixup);
break;
case GLMessage::glBufferSubData:
/* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
fixup_glBufferData(2, 3, glmsg, pointersToFixup);
fixup_glBufferSubData(context, glmsg, pointersToFixup);
break;
case GLMessage::glDrawArrays:
/* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
}
fixup_glDrawArrays(context, glmsg);
break;
case GLMessage::glDrawElements:
/* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
}
fixup_glDrawElements(context, glmsg, pointersToFixup);
break;
case GLMessage::glPushGroupMarkerEXT:
/* void PushGroupMarkerEXT(sizei length, const char *marker); */