summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSiva Velusamy <vsiva@google.com>2012-02-29 14:04:04 -0800
committerSiva Velusamy <vsiva@google.com>2012-03-01 17:41:53 -0800
commit1c5387e1cb12a2aa2b1aaf4c2f4f5c61be4828aa (patch)
tree729b9c07f11ed481c08145e1e53bc52e1cb032e8
parentb5d3dd2cd5780c48fb79cc2f5a0c0f6237ebc952 (diff)
downloadframeworks_base-1c5387e1cb12a2aa2b1aaf4c2f4f5c61be4828aa.zip
frameworks_base-1c5387e1cb12a2aa2b1aaf4c2f4f5c61be4828aa.tar.gz
frameworks_base-1c5387e1cb12a2aa2b1aaf4c2f4f5c61be4828aa.tar.bz2
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
-rw-r--r--opengl/libs/GLES_trace/dev.make13
-rw-r--r--opengl/libs/GLES_trace/gltrace.proto2
-rw-r--r--opengl/libs/GLES_trace/src/gltrace.pb.cpp2
-rw-r--r--opengl/libs/GLES_trace/src/gltrace.pb.h6
-rw-r--r--opengl/libs/GLES_trace/src/gltrace_context.cpp80
-rw-r--r--opengl/libs/GLES_trace/src/gltrace_context.h25
-rw-r--r--opengl/libs/GLES_trace/src/gltrace_fixup.cpp341
7 files changed, 418 insertions, 51 deletions
diff --git a/opengl/libs/GLES_trace/dev.make b/opengl/libs/GLES_trace/dev.make
index 1d89999..a46260c 100644
--- a/opengl/libs/GLES_trace/dev.make
+++ b/opengl/libs/GLES_trace/dev.make
@@ -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
diff --git a/opengl/libs/GLES_trace/gltrace.proto b/opengl/libs/GLES_trace/gltrace.proto
index 2893e6e..bbf3554 100644
--- a/opengl/libs/GLES_trace/gltrace.proto
+++ b/opengl/libs/GLES_trace/gltrace.proto
@@ -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
diff --git a/opengl/libs/GLES_trace/src/gltrace.pb.cpp b/opengl/libs/GLES_trace/src/gltrace.pb.cpp
index d5f8180..d587c49 100644
--- a/opengl/libs/GLES_trace/src/gltrace.pb.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace.pb.cpp
@@ -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;
diff --git a/opengl/libs/GLES_trace/src/gltrace.pb.h b/opengl/libs/GLES_trace/src/gltrace.pb.h
index a4fcbd3..0901be7 100644
--- a/opengl/libs/GLES_trace/src/gltrace.pb.h
+++ b/opengl/libs/GLES_trace/src/gltrace.pb.h
@@ -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);
}
diff --git a/opengl/libs/GLES_trace/src/gltrace_context.cpp b/opengl/libs/GLES_trace/src/gltrace_context.cpp
index 65b7662..45dbb43 100644
--- a/opengl/libs/GLES_trace/src/gltrace_context.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_context.cpp
@@ -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
diff --git a/opengl/libs/GLES_trace/src/gltrace_context.h b/opengl/libs/GLES_trace/src/gltrace_context.h
index 129116a..323cfdc 100644
--- a/opengl/libs/GLES_trace/src/gltrace_context.h
+++ b/opengl/libs/GLES_trace/src/gltrace_context.h
@@ -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);
};
diff --git a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
index c69ba5e..3597b26 100644
--- a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
@@ -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); */