// Don't include these in the .h file, or we get weird compile errors.
#include <GLES3/gl3.h>
#include <GLES3/gl31.h>
-GLClientState::GLClientState(int nLocations)
-{
- if (nLocations < LAST_LOCATION) {
- nLocations = LAST_LOCATION;
- }
- m_nLocations = nLocations;
- m_states = new VertexAttribState[m_nLocations];
- for (int i = 0; i < m_nLocations; i++) {
- m_states[i].enabled = 0;
- m_states[i].enableDirty = false;
- m_states[i].data = 0;
- }
- m_currentArrayVbo = 0;
- m_currentIndexVbo = 0;
+
+void GLClientState::init() {
+ m_initialized = false;
+ m_nLocations = CODEC_MAX_VERTEX_ATTRIBUTES;
+
+ m_arrayBuffer = 0;
+ m_max_vertex_attrib_bindings = m_nLocations;
+ addVertexArrayObject(0);
+ setVertexArrayObject(0);
// init gl constans;
- m_states[VERTEX_LOCATION].glConst = GL_VERTEX_ARRAY;
- m_states[NORMAL_LOCATION].glConst = GL_NORMAL_ARRAY;
- m_states[COLOR_LOCATION].glConst = GL_COLOR_ARRAY;
- m_states[POINTSIZE_LOCATION].glConst = GL_POINT_SIZE_ARRAY_OES;
- m_states[TEXCOORD0_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
- m_states[TEXCOORD1_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
- m_states[TEXCOORD2_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
- m_states[TEXCOORD3_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
- m_states[TEXCOORD4_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
- m_states[TEXCOORD5_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
- m_states[TEXCOORD6_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
- m_states[TEXCOORD7_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
- m_states[MATRIXINDEX_LOCATION].glConst = GL_MATRIX_INDEX_ARRAY_OES;
- m_states[WEIGHT_LOCATION].glConst = GL_WEIGHT_ARRAY_OES;
+ m_currVaoState[VERTEX_LOCATION].glConst = GL_VERTEX_ARRAY;
+ m_currVaoState[NORMAL_LOCATION].glConst = GL_NORMAL_ARRAY;
+ m_currVaoState[COLOR_LOCATION].glConst = GL_COLOR_ARRAY;
+ m_currVaoState[POINTSIZE_LOCATION].glConst = GL_POINT_SIZE_ARRAY_OES;
+ m_currVaoState[TEXCOORD0_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
+ m_currVaoState[TEXCOORD1_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
+ m_currVaoState[TEXCOORD2_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
+ m_currVaoState[TEXCOORD3_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
+ m_currVaoState[TEXCOORD4_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
+ m_currVaoState[TEXCOORD5_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
+ m_currVaoState[TEXCOORD6_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
+ m_currVaoState[TEXCOORD7_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
+ m_currVaoState[MATRIXINDEX_LOCATION].glConst = GL_MATRIX_INDEX_ARRAY_OES;
+ m_currVaoState[WEIGHT_LOCATION].glConst = GL_WEIGHT_ARRAY_OES;
+
+ m_copyReadBuffer = 0;
+ m_copyWriteBuffer = 0;
+ m_pixelPackBuffer = 0;
+ m_pixelUnpackBuffer = 0;
+ m_transformFeedbackBuffer = 0;
+ m_uniformBuffer = 0;
+ m_atomicCounterBuffer = 0;
+ m_dispatchIndirectBuffer = 0;
+ m_drawIndirectBuffer = 0;
+ m_shaderStorageBuffer = 0;
+
+ m_transformFeedbackActiveUnpaused = false;
+
+ // to be modified later when these are queried from host.
+ m_max_transform_feedback_separate_attribs = 0;
+ m_max_uniform_buffer_bindings = 0;
+ m_max_atomic_counter_buffer_bindings = 0;
+ m_max_shader_storage_buffer_bindings = 0;
+
m_activeTexture = 0;
m_currentProgram = 0;
m_maxVertexAttribsDirty = true;
}
+GLClientState::GLClientState()
+{
+ init();
+}
+
+GLClientState::GLClientState(int majorVersion, int minorVersion) :
+ m_glesMajorVersion(majorVersion),
+ m_glesMinorVersion(minorVersion) {
+ init();
+}
+
GLClientState::~GLClientState()
{
- delete m_states;
}
void GLClientState::enable(int location, int state)
{
- if (!validLocation(location)) {
+ m_currVaoState[location].enableDirty |= (state != m_currVaoState[location].enabled);
+ m_currVaoState[location].enabled = state;
+}
+
+void GLClientState::setVertexAttribState(int location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data, bool isInt)
+{
+ m_currVaoState[location].size = size;
+ m_currVaoState[location].type = type;
+ m_currVaoState[location].stride = stride;
+ m_currVaoState[location].data = (void*)data;
+ m_currVaoState[location].bufferObject = m_arrayBuffer;
+ m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
+ switch (type) {
+ case GL_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ m_currVaoState[location].elementSize =
+ m_currVaoState[location].elementSize / 4;
+ break;
+ default:
+ break;
+ }
+ m_currVaoState[location].normalized = normalized;
+ m_currVaoState[location].isInt = isInt;
+}
+
+void GLClientState::setVertexBindingDivisor(int bindingindex, GLuint divisor) {
+ m_currVaoState.bufferBinding(bindingindex).divisor = divisor;
+}
+
+const GLClientState::BufferBinding& GLClientState::getCurrAttributeBindingInfo(int attribindex) {
+ return m_currVaoState.bufferBindings_const().at(m_currVaoState[attribindex].bindingindex);
+}
+
+void GLClientState::setVertexAttribBinding(int attribindex, int bindingindex) {
+ m_currVaoState[attribindex].bindingindex = bindingindex;
+}
+
+void GLClientState::setVertexAttribFormat(int location, int size, GLenum type, GLboolean normalized, GLuint reloffset, bool isInt) {
+ m_currVaoState[location].size = size;
+ m_currVaoState[location].type = type;
+ m_currVaoState[location].normalized = normalized;
+ m_currVaoState[location].reloffset = reloffset;
+ m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
+ switch (type) {
+ case GL_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ m_currVaoState[location].elementSize =
+ m_currVaoState[location].elementSize / 4;
+ break;
+ default:
+ break;
+ }
+ m_currVaoState[location].isInt = isInt;
+}
+
+void GLClientState::addVertexArrayObjects(GLsizei n, GLuint* arrays) {
+ for (GLsizei i = 0; i < n; i++) {
+ addVertexArrayObject(arrays[i]);
+ }
+}
+
+void GLClientState::removeVertexArrayObjects(GLsizei n, const GLuint* arrays) {
+ for (GLsizei i = 0; i < n; i++) {
+ if (arrays[i] && m_currVaoState.vaoId() == arrays[i]) {
+ setVertexArrayObject(0);
+ }
+ removeVertexArrayObject(arrays[i]);
+ }
+}
+
+void GLClientState::addVertexArrayObject(GLuint name) {
+ if (m_vaoMap.find(name) !=
+ m_vaoMap.end()) {
+ ALOGE("%s: ERROR: %u already part of current VAO state!",
+ __FUNCTION__, name);
return;
}
- m_states[location].enableDirty |= (state != m_states[location].enabled);
- m_states[location].enabled = state;
+ m_vaoMap.insert(
+ VAOStateMap::value_type(
+ name,
+ VAOState(0, m_nLocations, std::max(m_nLocations, m_max_vertex_attrib_bindings))));
+ VertexAttribStateVector& attribState =
+ m_vaoMap.at(name).attribState;
+ for (int i = 0; i < m_nLocations; i++) {
+ attribState[i].enabled = 0;
+ attribState[i].enableDirty = false;
+ attribState[i].data = 0;
+ attribState[i].reloffset = 0;
+ attribState[i].bindingindex = i;
+ attribState[i].divisor = 0;
+ attribState[i].size = 4; // 4 is the default size
+ attribState[i].type = GL_FLOAT; // GL_FLOAT is the default type
+ }
}
-void GLClientState::setState(int location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data)
-{
- if (!validLocation(location)) {
+void GLClientState::removeVertexArrayObject(GLuint name) {
+ if (name == 0) {
+ ALOGE("%s: ERROR: cannot delete VAO 0!",
+ __FUNCTION__);
+ return;
+ }
+ if (m_vaoMap.find(name) ==
+ m_vaoMap.end()) {
+ ALOGE("%s: ERROR: %u not found in VAO state!",
+ __FUNCTION__, name);
return;
}
- m_states[location].size = size;
- m_states[location].type = type;
- m_states[location].stride = stride;
- m_states[location].data = (void*)data;
- m_states[location].bufferObject = m_currentArrayVbo;
- m_states[location].elementSize = size ? (glSizeof(type) * size) : 0;
- m_states[location].normalized = normalized;
+ m_vaoMap.erase(name);
}
-void GLClientState::setBufferObject(int location, GLuint id)
-{
- if (!validLocation(location)) {
+void GLClientState::setVertexArrayObject(GLuint name) {
+ if (m_vaoMap.find(name) ==
+ m_vaoMap.end()) {
+ ALOGE("%s: ERROR: %u not found in VAO state!",
+ __FUNCTION__, name);
return;
}
- m_states[location].bufferObject = id;
+ if (name && m_currVaoState.vaoId() == name) {
+ ALOGV("%s: set vao to self, no-op (%u)",
+ __FUNCTION__, name);
+ return;
+ }
+
+ m_currVaoState =
+ VAOStateRef(m_vaoMap.find(name));
+ ALOGV("%s: set vao to %u (%u) %u %u", __FUNCTION__,
+ name,
+ m_currVaoState.vaoId(),
+ m_arrayBuffer,
+ m_currVaoState.iboId());
}
-const GLClientState::VertexAttribState * GLClientState::getState(int location)
-{
- if (!validLocation(location)) {
- return NULL;
- }
- return & m_states[location];
+bool GLClientState::isVertexArrayObject(GLuint vao) const {
+ return m_vaoMap.find(vao) != m_vaoMap.end();
}
-const GLClientState::VertexAttribState * GLClientState::getStateAndEnableDirty(int location, bool *enableChanged)
+const GLClientState::VertexAttribState& GLClientState::getState(int location)
{
- if (!validLocation(location)) {
- return NULL;
- }
+ return m_currVaoState[location];
+}
+const GLClientState::VertexAttribState& GLClientState::getStateAndEnableDirty(int location, bool *enableChanged)
+{
if (enableChanged) {
- *enableChanged = m_states[location].enableDirty;
+ *enableChanged = m_currVaoState[location].enableDirty;
}
- m_states[location].enableDirty = false;
- return & m_states[location];
+ m_currVaoState[location].enableDirty = false;
+ return m_currVaoState[location];
}
int GLClientState::getLocation(GLenum loc)
return retval;
}
+void GLClientState::unBindBuffer(GLuint id) {
+ if (m_arrayBuffer == id) m_arrayBuffer = 0;
+ if (m_currVaoState.iboId() == id) m_currVaoState.iboId() = 0;
+ if (m_copyReadBuffer == id)
+ m_copyReadBuffer = 0;
+ if (m_copyWriteBuffer == id)
+ m_copyWriteBuffer = 0;
+ if (m_pixelPackBuffer == id)
+ m_pixelPackBuffer = 0;
+ if (m_pixelUnpackBuffer == id)
+ m_pixelUnpackBuffer = 0;
+ if (m_transformFeedbackBuffer == id)
+ m_transformFeedbackBuffer = 0;
+ if (m_uniformBuffer == id)
+ m_uniformBuffer = 0;
+ if (m_atomicCounterBuffer == id)
+ m_atomicCounterBuffer = 0;
+ if (m_dispatchIndirectBuffer == id)
+ m_dispatchIndirectBuffer = 0;
+ if (m_drawIndirectBuffer == id)
+ m_drawIndirectBuffer = 0;
+ if (m_shaderStorageBuffer == id)
+ m_shaderStorageBuffer = 0;
+}
+
+int GLClientState::bindBuffer(GLenum target, GLuint id)
+{
+ int err = 0;
+ switch(target) {
+ case GL_ARRAY_BUFFER:
+ m_arrayBuffer = id;
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ m_currVaoState.iboId() = id;
+ break;
+ case GL_COPY_READ_BUFFER:
+ m_copyReadBuffer = id;
+ break;
+ case GL_COPY_WRITE_BUFFER:
+ m_copyWriteBuffer = id;
+ break;
+ case GL_PIXEL_PACK_BUFFER:
+ m_pixelPackBuffer = id;
+ break;
+ case GL_PIXEL_UNPACK_BUFFER:
+ m_pixelUnpackBuffer = id;
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ m_transformFeedbackBuffer = id;
+ break;
+ case GL_UNIFORM_BUFFER:
+ m_uniformBuffer = id;
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ m_atomicCounterBuffer = id;
+ break;
+ case GL_DISPATCH_INDIRECT_BUFFER:
+ m_dispatchIndirectBuffer = id;
+ break;
+ case GL_DRAW_INDIRECT_BUFFER:
+ m_drawIndirectBuffer = id;
+ break;
+ case GL_SHADER_STORAGE_BUFFER:
+ m_shaderStorageBuffer = id;
+ break;
+ default:
+ err = -1;
+ }
+ return err;
+}
+
+void GLClientState::bindIndexedBuffer(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride) {
+ switch (target) {
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ m_indexedTransformFeedbackBuffers[index].buffer = buffer;
+ m_indexedTransformFeedbackBuffers[index].offset = offset;
+ m_indexedTransformFeedbackBuffers[index].size = size;
+ m_indexedTransformFeedbackBuffers[index].stride = stride;
+ break;
+ case GL_UNIFORM_BUFFER:
+ m_indexedUniformBuffers[index].buffer = buffer;
+ m_indexedUniformBuffers[index].offset = offset;
+ m_indexedUniformBuffers[index].size = size;
+ m_indexedUniformBuffers[index].stride = stride;
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ m_indexedAtomicCounterBuffers[index].buffer = buffer;
+ m_indexedAtomicCounterBuffers[index].offset = offset;
+ m_indexedAtomicCounterBuffers[index].size = size;
+ m_indexedAtomicCounterBuffers[index].stride = stride;
+ break;
+ case GL_SHADER_STORAGE_BUFFER:
+ m_indexedShaderStorageBuffers[index].buffer = buffer;
+ m_indexedShaderStorageBuffers[index].offset = offset;
+ m_indexedShaderStorageBuffers[index].size = size;
+ m_indexedShaderStorageBuffers[index].stride = stride;
+ break;
+ default:
+ m_currVaoState.bufferBinding(index).buffer = buffer;
+ m_currVaoState.bufferBinding(index).offset = offset;
+ m_currVaoState.bufferBinding(index).size = size;
+ m_currVaoState.bufferBinding(index).stride = stride;
+ m_currVaoState.bufferBinding(index).effectiveStride = effectiveStride;
+ return;
+ }
+}
+
+int GLClientState::getMaxIndexedBufferBindings(GLenum target) const {
+ switch (target) {
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ return m_indexedTransformFeedbackBuffers.size();
+ case GL_UNIFORM_BUFFER:
+ return m_indexedUniformBuffers.size();
+ case GL_ATOMIC_COUNTER_BUFFER:
+ return m_indexedAtomicCounterBuffers.size();
+ case GL_SHADER_STORAGE_BUFFER:
+ return m_indexedShaderStorageBuffers.size();
+ default:
+ return m_currVaoState.bufferBindings_const().size();
+ }
+}
+
+int GLClientState::getBuffer(GLenum target) {
+ int ret=0;
+ switch (target) {
+ case GL_ARRAY_BUFFER:
+ ret = m_arrayBuffer;
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ ret = m_currVaoState.iboId();
+ break;
+ case GL_COPY_READ_BUFFER:
+ ret = m_copyReadBuffer;
+ break;
+ case GL_COPY_WRITE_BUFFER:
+ ret = m_copyWriteBuffer;
+ break;
+ case GL_PIXEL_PACK_BUFFER:
+ ret = m_pixelPackBuffer;
+ break;
+ case GL_PIXEL_UNPACK_BUFFER:
+ ret = m_pixelUnpackBuffer;
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ ret = m_transformFeedbackBuffer;
+ break;
+ case GL_UNIFORM_BUFFER:
+ ret = m_uniformBuffer;
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ ret = m_atomicCounterBuffer;
+ break;
+ case GL_DISPATCH_INDIRECT_BUFFER:
+ ret = m_dispatchIndirectBuffer;
+ break;
+ case GL_DRAW_INDIRECT_BUFFER:
+ ret = m_drawIndirectBuffer;
+ break;
+ case GL_SHADER_STORAGE_BUFFER:
+ ret = m_shaderStorageBuffer;
+ break;
+ default:
+ ret = -1;
+ }
+ return ret;
+}
+
void GLClientState::getClientStatePointer(GLenum pname, GLvoid** params)
{
- const GLClientState::VertexAttribState *state = NULL;
+ GLenum which_state = -1;
switch (pname) {
case GL_VERTEX_ARRAY_POINTER: {
- state = getState(GLClientState::VERTEX_LOCATION);
+ which_state = GLClientState::VERTEX_LOCATION;
break;
}
case GL_NORMAL_ARRAY_POINTER: {
- state = getState(GLClientState::NORMAL_LOCATION);
+ which_state = GLClientState::NORMAL_LOCATION;
break;
}
case GL_COLOR_ARRAY_POINTER: {
- state = getState(GLClientState::COLOR_LOCATION);
+ which_state = GLClientState::COLOR_LOCATION;
break;
}
case GL_TEXTURE_COORD_ARRAY_POINTER: {
- state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
+ which_state = getActiveTexture() + GLClientState::TEXCOORD0_LOCATION;
break;
}
case GL_POINT_SIZE_ARRAY_POINTER_OES: {
- state = getState(GLClientState::POINTSIZE_LOCATION);
+ which_state = GLClientState::POINTSIZE_LOCATION;
break;
}
case GL_MATRIX_INDEX_ARRAY_POINTER_OES: {
- state = getState(GLClientState::MATRIXINDEX_LOCATION);
+ which_state = GLClientState::MATRIXINDEX_LOCATION;
break;
}
case GL_WEIGHT_ARRAY_POINTER_OES: {
- state = getState(GLClientState::WEIGHT_LOCATION);
+ which_state = GLClientState::WEIGHT_LOCATION;
break;
}
}
- if (state && params)
- *params = state->data;
+ if (which_state != -1)
+ *params = getState(which_state).data;
}
int GLClientState::setPixelStore(GLenum param, GLint value)
default_fb_props.depthAttachment_hasRbo = true;
default_fb_props.stencilAttachment_hasRbo = true;
}
+
+void GLClientState::initFromCaps(
+ int max_transform_feedback_separate_attribs,
+ int max_uniform_buffer_bindings,
+ int max_atomic_counter_buffer_bindings,
+ int max_shader_storage_buffer_bindings,
+ int max_vertex_attrib_bindings,
+ int max_color_attachments,
+ int max_draw_buffers) {
+
+ m_max_vertex_attrib_bindings = max_vertex_attrib_bindings;
+
+ if (m_glesMajorVersion >= 3) {
+ m_max_transform_feedback_separate_attribs = max_transform_feedback_separate_attribs;
+ m_max_uniform_buffer_bindings = max_uniform_buffer_bindings;
+ m_max_atomic_counter_buffer_bindings = max_atomic_counter_buffer_bindings;
+ m_max_shader_storage_buffer_bindings = max_shader_storage_buffer_bindings;
+
+ if (m_max_transform_feedback_separate_attribs)
+ m_indexedTransformFeedbackBuffers.resize(m_max_transform_feedback_separate_attribs);
+ if (m_max_uniform_buffer_bindings)
+ m_indexedUniformBuffers.resize(m_max_uniform_buffer_bindings);
+ if (m_max_atomic_counter_buffer_bindings)
+ m_indexedAtomicCounterBuffers.resize(m_max_atomic_counter_buffer_bindings);
+ if (m_max_shader_storage_buffer_bindings)
+ m_indexedShaderStorageBuffers.resize(m_max_shader_storage_buffer_bindings);
+
+ BufferBinding buf0Binding;
+ buf0Binding.buffer = 0;
+ buf0Binding.offset = 0;
+ buf0Binding.size = 0;
+ buf0Binding.stride = 0;
+ buf0Binding.effectiveStride = 0;
+
+ for (size_t i = 0; i < m_indexedTransformFeedbackBuffers.size(); ++i)
+ m_indexedTransformFeedbackBuffers[i] = buf0Binding;
+ for (size_t i = 0; i < m_indexedUniformBuffers.size(); ++i)
+ m_indexedUniformBuffers[i] = buf0Binding;
+ for (size_t i = 0; i < m_indexedAtomicCounterBuffers.size(); ++i)
+ m_indexedAtomicCounterBuffers[i] = buf0Binding;
+ for (size_t i = 0; i < m_indexedShaderStorageBuffers.size(); ++i)
+ m_indexedShaderStorageBuffers[i] = buf0Binding;
+ }
+
+ m_max_color_attachments = max_color_attachments;
+ m_max_draw_buffers = max_draw_buffers;
+
+ addFreshRenderbuffer(0);
+ addFreshFramebuffer(0);
+
+ m_initialized = true;
+}
+
+bool GLClientState::needsInitFromCaps() const {
+ return !m_initialized;
+}
GLenum type;
GLsizei stride;
void *data;
+ GLuint reloffset;
GLuint bufferObject;
GLenum glConst;
unsigned int elementSize;
bool enableDirty; // true if any enable state has changed since last draw
bool normalized;
+ GLuint divisor;
+ bool isInt;
+ int bindingindex;
} VertexAttribState;
+ struct BufferBinding {
+ GLintptr offset;
+ GLintptr stride;
+ GLintptr effectiveStride;
+ GLsizeiptr size;
+ GLuint buffer;
+ GLuint divisor;
+ };
+
+ typedef std::vector<VertexAttribState> VertexAttribStateVector;
+ typedef std::vector<BufferBinding> VertexAttribBindingVector;
+
+ struct VAOState {
+ VAOState(GLuint ibo, int nLoc, int nBindings) :
+ element_array_buffer_binding(ibo),
+ attribState(nLoc),
+ bindingState(nBindings) { }
+ VertexAttribStateVector attribState;
+ VertexAttribBindingVector bindingState;
+ GLuint element_array_buffer_binding;
+ };
+
+ typedef std::map<GLuint, VAOState> VAOStateMap;
+ struct VAOStateRef {
+ VAOStateRef() { }
+ VAOStateRef(
+ VAOStateMap::iterator iter) : it(iter) { }
+ VertexAttribState& operator[](size_t k) { return it->second.attribState[k]; }
+ BufferBinding& bufferBinding(size_t k) { return it->second.bindingState[k]; }
+ VertexAttribBindingVector& bufferBindings() { return it->second.bindingState; }
+ const VertexAttribBindingVector& bufferBindings_const() const { return it->second.bindingState; }
+ GLuint vaoId() const { return it->first; }
+ GLuint& iboId() { return it->second.element_array_buffer_binding; }
+ VAOStateMap::iterator it;
+ };
+
typedef struct {
int unpack_alignment;
};
public:
- GLClientState(int nLocations = CODEC_MAX_VERTEX_ATTRIBUTES);
+ GLClientState();
+ GLClientState(int majorVersion, int minorVersion);
~GLClientState();
int nLocations() { return m_nLocations; }
const PixelStoreState *pixelStoreState() { return &m_pixelStore; }
int setPixelStore(GLenum param, GLint value);
- GLuint currentArrayVbo() { return m_currentArrayVbo; }
- GLuint currentIndexVbo() { return m_currentIndexVbo; }
+ GLuint currentVertexArrayObject() const { return m_currVaoState.vaoId(); }
+ GLuint currentArrayVbo() { return m_arrayBuffer; }
+ GLuint currentIndexVbo() { return m_currVaoState.iboId(); }
void enable(int location, int state);
- void setState(int location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data);
- void setBufferObject(int location, GLuint id);
- const VertexAttribState *getState(int location);
- const VertexAttribState *getStateAndEnableDirty(int location, bool *enableChanged);
+ // Vertex array objects and vertex attributes
+ void addVertexArrayObjects(GLsizei n, GLuint* arrays);
+ void removeVertexArrayObjects(GLsizei n, const GLuint* arrays);
+ void addVertexArrayObject(GLuint name);
+ void removeVertexArrayObject(GLuint name);
+ void setVertexArrayObject(GLuint vao);
+ bool isVertexArrayObject(GLuint vao) const;
+ void setVertexAttribState(int location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data, bool isInt = false);
+ void setVertexBindingDivisor(int bindingindex, GLuint divisor);
+ const BufferBinding& getCurrAttributeBindingInfo(int attribindex);
+ void setVertexAttribBinding(int attribindex, int bindingindex);
+ void setVertexAttribFormat(int location, int size, GLenum type, GLboolean normalized, GLuint reloffset, bool isInt = false);
+ const VertexAttribState& getState(int location);
+ const VertexAttribState& getStateAndEnableDirty(int location, bool *enableChanged);
int getLocation(GLenum loc);
void setActiveTexture(int texUnit) {m_activeTexture = texUnit; };
int getActiveTexture() const { return m_activeTexture; }
m_maxVertexAttribsDirty = false;
}
- void unBindBuffer(GLuint id)
- {
- if (m_currentArrayVbo == id) m_currentArrayVbo = 0;
- else if (m_currentIndexVbo == id) m_currentIndexVbo = 0;
- }
+ void unBindBuffer(GLuint id);
- int bindBuffer(GLenum target, GLuint id)
- {
- int err = 0;
- switch(target) {
- case GL_ARRAY_BUFFER:
- m_currentArrayVbo = id;
- break;
- case GL_ELEMENT_ARRAY_BUFFER:
- m_currentIndexVbo = id;
- break;
- default:
- err = -1;
- }
- return err;
- }
+ int bindBuffer(GLenum target, GLuint id);
+ void bindIndexedBuffer(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride);
+ int getMaxIndexedBufferBindings(GLenum target) const;
+
+ int getBuffer(GLenum target);
- int getBuffer(GLenum target)
- {
- int ret=0;
- switch (target) {
- case GL_ARRAY_BUFFER:
- ret = m_currentArrayVbo;
- break;
- case GL_ELEMENT_ARRAY_BUFFER:
- ret = m_currentIndexVbo;
- break;
- default:
- ret = -1;
- }
- return ret;
- }
size_t pixelDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const;
size_t pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const;
size_t clearBufferNumElts(GLenum buffer) const;
void setCurrentProgram(GLint program) { m_currentProgram = program; }
GLint currentProgram() const { return m_currentProgram; }
+ struct UniformBlockInfoKey {
+ GLuint program;
+ GLuint uniformBlockIndex;
+ };
+ struct UniformBlockInfoKeyCompare {
+ bool operator() (const UniformBlockInfoKey& a,
+ const UniformBlockInfoKey& b) const {
+ if (a.program != b.program) return a.program < b.program;
+ if (a.uniformBlockIndex != b.uniformBlockIndex) return a.uniformBlockIndex < b.uniformBlockIndex;
+ return false;
+ }
+ };
+ struct UniformBlockUniformInfo {
+ size_t numActiveUniforms;
+ };
+
+ typedef std::map<UniformBlockInfoKey, UniformBlockUniformInfo, UniformBlockInfoKeyCompare> UniformBlockInfoMap;
+ UniformBlockInfoMap m_uniformBlockInfoMap;
+
void setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms);
size_t numActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex) const;
/* OES_EGL_image_external
// set eglsurface property on default framebuffer
// if coming from eglMakeCurrent
void fromMakeCurrent();
+ // set indexed buffer state.
+ // We need to query the underlying OpenGL to get
+ // accurate values for indexed buffers
+ // and # render targets.
+ void initFromCaps(
+ int max_transform_feedback_separate_attribs,
+ int max_uniform_buffer_bindings,
+ int max_atomic_counter_buffer_bindings,
+ int max_shader_storage_buffer_bindings,
+ int max_vertex_attrib_bindings,
+ int max_color_attachments,
+ int max_draw_buffers);
+ bool needsInitFromCaps() const;
// Queries the format backing the current framebuffer.
// Type differs depending on whether the attachment
GLenum attachment, FboFormatInfo* res_info) const;
private:
+ void init();
+ bool m_initialized;
PixelStoreState m_pixelStore;
- VertexAttribState *m_states;
+
+ // GL_ARRAY_BUFFER_BINDING is separate from VAO state
+ GLuint m_arrayBuffer;
+ VAOStateMap m_vaoMap;
+ VAOStateRef m_currVaoState;
+
+ // Other buffer id's, other targets
+ GLuint m_copyReadBuffer;
+ GLuint m_copyWriteBuffer;
+
+ GLuint m_pixelPackBuffer;
+ GLuint m_pixelUnpackBuffer;
+
+ GLuint m_transformFeedbackBuffer;
+ GLuint m_uniformBuffer;
+
+ GLuint m_atomicCounterBuffer;
+ GLuint m_dispatchIndirectBuffer;
+ GLuint m_drawIndirectBuffer;
+ GLuint m_shaderStorageBuffer;
+
+ bool m_transformFeedbackActiveUnpaused;
+
+ int m_max_transform_feedback_separate_attribs;
+ int m_max_uniform_buffer_bindings;
+ int m_max_atomic_counter_buffer_bindings;
+ int m_max_shader_storage_buffer_bindings;
+ int m_max_vertex_attrib_bindings;
+ std::vector<BufferBinding> m_indexedTransformFeedbackBuffers;
+ std::vector<BufferBinding> m_indexedUniformBuffers;
+ std::vector<BufferBinding> m_indexedAtomicCounterBuffers;
+ std::vector<BufferBinding> m_indexedShaderStorageBuffers;
+
int m_glesMajorVersion;
int m_glesMinorVersion;
int m_maxVertexAttribs;
bool m_maxVertexAttribsDirty;
int m_nLocations;
- GLuint m_currentArrayVbo;
- GLuint m_currentIndexVbo;
int m_activeTexture;
GLint m_currentProgram;
- bool validLocation(int location) { return (location >= 0 && location < m_nLocations); }
-
enum TextureTarget {
TEXTURE_2D = 0,
TEXTURE_EXTERNAL = 1,
int getVertexAttribParameter(GLuint index, GLenum param, T *ptr)
{
bool handled = true;
- const VertexAttribState *vertexAttrib = getState(index);
- if (vertexAttrib == NULL) {
- ERR("getVeterxAttriParameter for non existant index %d\n", index);
- // set gl error;
- return handled;
- }
+ const VertexAttribState& vertexAttrib = getState(index);
+ const BufferBinding& vertexAttribBufferBinding =
+ m_currVaoState.bufferBindings_const()[vertexAttrib.bindingindex];
switch(param) {
case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
- *ptr = (T)(vertexAttrib->bufferObject);
+ *ptr = (T)(vertexAttribBufferBinding.buffer);
break;
case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
- *ptr = (T)(vertexAttrib->enabled);
+ *ptr = (T)(vertexAttrib.enabled);
+ break;
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+ case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
+ *ptr = (T)(vertexAttrib.isInt);
break;
case GL_VERTEX_ATTRIB_ARRAY_SIZE:
- *ptr = (T)(vertexAttrib->size);
+ *ptr = (T)(vertexAttrib.size);
break;
case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
- *ptr = (T)(vertexAttrib->stride);
+ *ptr = (T)(vertexAttribBufferBinding.stride);
break;
case GL_VERTEX_ATTRIB_ARRAY_TYPE:
- *ptr = (T)(vertexAttrib->type);
+ *ptr = (T)(vertexAttrib.type);
break;
case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
- *ptr = (T)(vertexAttrib->normalized);
+ *ptr = (T)(vertexAttrib.normalized);
break;
case GL_CURRENT_VERTEX_ATTRIB:
handled = false;
}
template <class T>
- bool getClientStateParameter(GLenum param, T* ptr)
+ bool getClientStateParameter(GLenum param, T* out)
{
bool isClientStateParam = false;
switch (param) {
case GL_CLIENT_ACTIVE_TEXTURE: {
GLint tex = getActiveTexture() + GL_TEXTURE0;
- *ptr = tex;
+ *out = tex;
isClientStateParam = true;
break;
}
case GL_VERTEX_ARRAY_SIZE: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
- *ptr = state->size;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::VERTEX_LOCATION);
+ *out = state.size;
isClientStateParam = true;
break;
}
case GL_VERTEX_ARRAY_TYPE: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
- *ptr = state->type;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::VERTEX_LOCATION);
+ *out = state.type;
isClientStateParam = true;
break;
}
case GL_VERTEX_ARRAY_STRIDE: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
- *ptr = state->stride;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::VERTEX_LOCATION);
+ *out = state.stride;
isClientStateParam = true;
break;
}
case GL_COLOR_ARRAY_SIZE: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
- *ptr = state->size;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::COLOR_LOCATION);
+ *out = state.size;
isClientStateParam = true;
break;
}
case GL_COLOR_ARRAY_TYPE: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
- *ptr = state->type;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::COLOR_LOCATION);
+ *out = state.type;
isClientStateParam = true;
break;
}
case GL_COLOR_ARRAY_STRIDE: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
- *ptr = state->stride;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::COLOR_LOCATION);
+ *out = state.stride;
isClientStateParam = true;
break;
}
case GL_NORMAL_ARRAY_TYPE: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION);
- *ptr = state->type;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::NORMAL_LOCATION);
+ *out = state.type;
isClientStateParam = true;
break;
}
case GL_NORMAL_ARRAY_STRIDE: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION);
- *ptr = state->stride;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::NORMAL_LOCATION);
+ *out = state.stride;
isClientStateParam = true;
break;
}
case GL_TEXTURE_COORD_ARRAY_SIZE: {
- const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
- *ptr = state->size;
+ const GLClientState::VertexAttribState& state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
+ *out = state.size;
isClientStateParam = true;
break;
}
case GL_TEXTURE_COORD_ARRAY_TYPE: {
- const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
- *ptr = state->type;
+ const GLClientState::VertexAttribState& state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
+ *out = state.type;
isClientStateParam = true;
break;
}
case GL_TEXTURE_COORD_ARRAY_STRIDE: {
- const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
- *ptr = state->stride;
+ const GLClientState::VertexAttribState& state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
+ *out = state.stride;
isClientStateParam = true;
break;
}
case GL_POINT_SIZE_ARRAY_TYPE_OES: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION);
- *ptr = state->type;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::POINTSIZE_LOCATION);
+ *out = state.type;
isClientStateParam = true;
break;
}
case GL_POINT_SIZE_ARRAY_STRIDE_OES: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION);
- *ptr = state->stride;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::POINTSIZE_LOCATION);
+ *out = state.stride;
isClientStateParam = true;
break;
}
case GL_MATRIX_INDEX_ARRAY_SIZE_OES: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
- *ptr = state->size;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::MATRIXINDEX_LOCATION);
+ *out = state.size;
isClientStateParam = true;
break;
}
case GL_MATRIX_INDEX_ARRAY_TYPE_OES: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
- *ptr = state->type;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::MATRIXINDEX_LOCATION);
+ *out = state.type;
isClientStateParam = true;
break;
}
case GL_MATRIX_INDEX_ARRAY_STRIDE_OES: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
- *ptr = state->stride;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::MATRIXINDEX_LOCATION);
+ *out = state.stride;
isClientStateParam = true;
break;
}
case GL_WEIGHT_ARRAY_SIZE_OES: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
- *ptr = state->size;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::WEIGHT_LOCATION);
+ *out = state.size;
isClientStateParam = true;
break;
}
case GL_WEIGHT_ARRAY_TYPE_OES: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
- *ptr = state->type;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::WEIGHT_LOCATION);
+ *out = state.type;
isClientStateParam = true;
break;
}
case GL_WEIGHT_ARRAY_STRIDE_OES: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
- *ptr = state->stride;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::WEIGHT_LOCATION);
+ *out = state.stride;
isClientStateParam = true;
break;
}
case GL_VERTEX_ARRAY_BUFFER_BINDING: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
- *ptr = state->bufferObject;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::VERTEX_LOCATION);
+ *out = state.bufferObject;
isClientStateParam = true;
break;
}
case GL_NORMAL_ARRAY_BUFFER_BINDING: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION);
- *ptr = state->bufferObject;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::NORMAL_LOCATION);
+ *out = state.bufferObject;
isClientStateParam = true;
break;
}
case GL_COLOR_ARRAY_BUFFER_BINDING: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
- *ptr = state->bufferObject;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::COLOR_LOCATION);
+ *out = state.bufferObject;
isClientStateParam = true;
break;
}
case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: {
- const GLClientState::VertexAttribState *state = getState(getActiveTexture()+GLClientState::TEXCOORD0_LOCATION);
- *ptr = state->bufferObject;
+ const GLClientState::VertexAttribState& state = getState(getActiveTexture()+GLClientState::TEXCOORD0_LOCATION);
+ *out = state.bufferObject;
isClientStateParam = true;
break;
}
case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION);
- *ptr = state->bufferObject;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::POINTSIZE_LOCATION);
+ *out = state.bufferObject;
isClientStateParam = true;
break;
}
case GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
- *ptr = state->bufferObject;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::MATRIXINDEX_LOCATION);
+ *out = state.bufferObject;
isClientStateParam = true;
break;
}
case GL_WEIGHT_ARRAY_BUFFER_BINDING_OES: {
- const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
- *ptr = state->bufferObject;
+ const GLClientState::VertexAttribState& state = getState(GLClientState::WEIGHT_LOCATION);
+ *out = state.bufferObject;
isClientStateParam = true;
break;
}
case GL_ARRAY_BUFFER_BINDING: {
int buffer = getBuffer(GL_ARRAY_BUFFER);
- *ptr = buffer;
+ *out = buffer;
isClientStateParam = true;
break;
}
case GL_ELEMENT_ARRAY_BUFFER_BINDING: {
int buffer = getBuffer(GL_ELEMENT_ARRAY_BUFFER);
- *ptr = buffer;
+ *out = buffer;
isClientStateParam = true;
break;
}
if (m_maxVertexAttribsDirty) {
isClientStateParam = false;
} else {
- *ptr = m_maxVertexAttribs;
+ *out = m_maxVertexAttribs;
isClientStateParam = true;
}
break;
- }
+ }
}
return isClientStateParam;
}
/**** BufferData ****/
-BufferData::BufferData() : m_size(0) {};
-BufferData::BufferData(GLsizeiptr size, void * data) : m_size(size)
+BufferData::BufferData() : m_size(0), m_usage(0), m_mapped(false) {};
+BufferData::BufferData(GLsizeiptr size, void * data) : m_size(size), m_usage(0), m_mapped(false)
{
void * buffer = NULL;
if (size>0) buffer = m_fixedBuffer.alloc(size);
}
}
+void GLSharedGroup::setBufferUsage(GLuint bufferId, GLenum usage) {
+ android::AutoMutex _lock(m_lock);
+ ssize_t idx = m_buffers.indexOfKey(bufferId);
+ if (idx >= 0) {
+ m_buffers.editValueAt(idx)->m_usage = usage;
+ }
+}
+
+void GLSharedGroup::setBufferMapped(GLuint bufferId, bool mapped) {
+ BufferData * buf = m_buffers.valueFor(bufferId);
+ if (!buf) return;
+ buf->m_mapped = mapped;
+}
+
+GLenum GLSharedGroup::getBufferUsage(GLuint bufferId) {
+ BufferData * buf = m_buffers.valueFor(bufferId);
+ if (!buf) return 0;
+ return buf->m_usage;
+}
+
+bool GLSharedGroup::isBufferMapped(GLuint bufferId) {
+ BufferData * buf = m_buffers.valueFor(bufferId);
+ if (!buf) return false;
+ return buf->m_mapped;
+}
+
GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data)
{
android::AutoMutex _lock(m_lock);
struct BufferData {
BufferData();
BufferData(GLsizeiptr size, void * data);
- GLsizeiptr m_size;
- FixedBuffer m_fixedBuffer;
+
+ // General buffer state
+ GLsizeiptr m_size;
+ GLenum m_usage;
+
+ // Mapped buffer state
+ bool m_mapped;
+ GLbitfield m_mappedAccess;
+ GLintptr m_mappedOffset;
+ GLsizeiptr m_mappedLength;
+
+ // Internal bookkeeping
+ FixedBuffer m_fixedBuffer; // actual buffer is shadowed here
IndexRangeCache m_indexRangeCache;
};
SharedTextureDataMap* getTextureData();
void addBufferData(GLuint bufferId, GLsizeiptr size, void * data);
void updateBufferData(GLuint bufferId, GLsizeiptr size, void * data);
+ void setBufferUsage(GLuint bufferId, GLenum usage);
+ void setBufferMapped(GLuint bufferId, bool mapped);
+ GLenum getBufferUsage(GLuint bufferId);
+ bool isBufferMapped(GLuint bufferId);
GLenum subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data);
void deleteBufferData(GLuint);