/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _GL_CLIENT_STATE_H_ #define _GL_CLIENT_STATE_H_ #define GL_API #ifndef ANDROID #define GL_APIENTRY #define GL_APIENTRYP #endif #include <GLES/gl.h> #include <GLES/glext.h> #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> #include <stdio.h> #include <stdlib.h> #include "ErrorLog.h" #include "codec_defs.h" class GLClientState { public: typedef enum { VERTEX_LOCATION = 0, NORMAL_LOCATION = 1, COLOR_LOCATION = 2, POINTSIZE_LOCATION = 3, TEXCOORD0_LOCATION = 4, TEXCOORD1_LOCATION = 5, TEXCOORD2_LOCATION = 6, TEXCOORD3_LOCATION = 7, TEXCOORD4_LOCATION = 8, TEXCOORD5_LOCATION = 9, TEXCOORD6_LOCATION = 10, TEXCOORD7_LOCATION = 11, MATRIXINDEX_LOCATION = 12, WEIGHT_LOCATION = 13, LAST_LOCATION = 14 } StateLocation; typedef struct { GLint enabled; GLint size; GLenum type; GLsizei stride; void *data; GLuint bufferObject; GLenum glConst; unsigned int elementSize; bool enableDirty; // true if any enable state has changed since last draw bool normalized; } VertexAttribState; typedef struct { int unpack_alignment; int pack_alignment; } PixelStoreState; enum { MAX_TEXTURE_UNITS = 32, }; public: GLClientState(int nLocations = CODEC_MAX_VERTEX_ATTRIBUTES); ~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; } 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); int getLocation(GLenum loc); void setActiveTexture(int texUnit) {m_activeTexture = texUnit; }; int getActiveTexture() const { return m_activeTexture; } 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 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, GLenum format, GLenum type, int pack) const; void setCurrentProgram(GLint program) { m_currentProgram = program; } GLint currentProgram() const { return m_currentProgram; } /* OES_EGL_image_external * * These functions manipulate GL state which interacts with the * OES_EGL_image_external extension, to support client-side emulation on * top of host implementations that don't have it. * * Most of these calls should only be used with TEXTURE_2D or * TEXTURE_EXTERNAL_OES texture targets; TEXTURE_CUBE_MAP or other extension * targets should bypass this. An exception is bindTexture(), which should * see all glBindTexture() calls for any target. */ // glActiveTexture(GL_TEXTURE0 + i) // Sets the active texture unit. Up to MAX_TEXTURE_UNITS are supported. GLenum setActiveTextureUnit(GLenum texture); GLenum getActiveTextureUnit() const; // glEnable(GL_TEXTURE_(2D|EXTERNAL_OES)) void enableTextureTarget(GLenum target); // glDisable(GL_TEXTURE_(2D|EXTERNAL_OES)) void disableTextureTarget(GLenum target); // Implements the target priority logic: // * Return GL_TEXTURE_EXTERNAL_OES if enabled, else // * Return GL_TEXTURE_2D if enabled, else // * Return the allDisabled value. // For some cases passing GL_TEXTURE_2D for allDisabled makes callee code // simpler; for other cases passing a recognizable enum like GL_ZERO or // GL_INVALID_ENUM is appropriate. GLenum getPriorityEnabledTarget(GLenum allDisabled) const; // glBindTexture(GL_TEXTURE_*, ...) // Set the target binding of the active texture unit to texture. Returns // GL_NO_ERROR on success or GL_INVALID_OPERATION if the texture has // previously been bound to a different target. If firstUse is not NULL, // it is set to indicate whether this is the first use of the texture. // For accurate error detection, bindTexture should be called for *all* // targets, not just 2D and EXTERNAL_OES. GLenum bindTexture(GLenum target, GLuint texture, GLboolean* firstUse); // Return the texture currently bound to GL_TEXTURE_(2D|EXTERNAL_OES). GLuint getBoundTexture(GLenum target) const; // glDeleteTextures(...) // Remove references to the to-be-deleted textures. void deleteTextures(GLsizei n, const GLuint* textures); private: PixelStoreState m_pixelStore; VertexAttribState *m_states; 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, TEXTURE_TARGET_COUNT }; struct TextureUnit { unsigned int enables; GLuint texture[TEXTURE_TARGET_COUNT]; }; struct TextureRec { GLuint id; GLenum target; }; struct TextureState { TextureUnit unit[MAX_TEXTURE_UNITS]; TextureUnit* activeUnit; TextureRec* textures; GLuint numTextures; GLuint allocTextures; }; TextureState m_tex; static int compareTexId(const void* pid, const void* prec); TextureRec* addTextureRec(GLuint id, GLenum target); public: void getClientStatePointer(GLenum pname, GLvoid** params); template <class T> 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; } switch(param) { case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: *ptr = (T)(vertexAttrib->bufferObject); break; case GL_VERTEX_ATTRIB_ARRAY_ENABLED: *ptr = (T)(vertexAttrib->enabled); break; case GL_VERTEX_ATTRIB_ARRAY_SIZE: *ptr = (T)(vertexAttrib->size); break; case GL_VERTEX_ATTRIB_ARRAY_STRIDE: *ptr = (T)(vertexAttrib->stride); break; case GL_VERTEX_ATTRIB_ARRAY_TYPE: *ptr = (T)(vertexAttrib->type); break; case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: *ptr = (T)(vertexAttrib->normalized); break; case GL_CURRENT_VERTEX_ATTRIB: handled = false; break; default: handled = false; ERR("unknown vertex-attrib parameter param %d\n", param); } return handled; } template <class T> bool getClientStateParameter(GLenum param, T* ptr) { bool isClientStateParam = false; switch (param) { case GL_CLIENT_ACTIVE_TEXTURE: { GLint tex = getActiveTexture() + GL_TEXTURE0; *ptr = tex; isClientStateParam = true; break; } case GL_VERTEX_ARRAY_SIZE: { const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION); *ptr = state->size; isClientStateParam = true; break; } case GL_VERTEX_ARRAY_TYPE: { const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION); *ptr = state->type; isClientStateParam = true; break; } case GL_VERTEX_ARRAY_STRIDE: { const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION); *ptr = state->stride; isClientStateParam = true; break; } case GL_COLOR_ARRAY_SIZE: { const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION); *ptr = state->size; isClientStateParam = true; break; } case GL_COLOR_ARRAY_TYPE: { const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION); *ptr = state->type; isClientStateParam = true; break; } case GL_COLOR_ARRAY_STRIDE: { const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION); *ptr = state->stride; isClientStateParam = true; break; } case GL_NORMAL_ARRAY_TYPE: { const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION); *ptr = state->type; isClientStateParam = true; break; } case GL_NORMAL_ARRAY_STRIDE: { const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION); *ptr = state->stride; isClientStateParam = true; break; } case GL_TEXTURE_COORD_ARRAY_SIZE: { const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION); *ptr = state->size; isClientStateParam = true; break; } case GL_TEXTURE_COORD_ARRAY_TYPE: { const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION); *ptr = state->type; isClientStateParam = true; break; } case GL_TEXTURE_COORD_ARRAY_STRIDE: { const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION); *ptr = state->stride; isClientStateParam = true; break; } case GL_POINT_SIZE_ARRAY_TYPE_OES: { const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION); *ptr = state->type; isClientStateParam = true; break; } case GL_POINT_SIZE_ARRAY_STRIDE_OES: { const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION); *ptr = state->stride; isClientStateParam = true; break; } case GL_MATRIX_INDEX_ARRAY_SIZE_OES: { const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION); *ptr = state->size; isClientStateParam = true; break; } case GL_MATRIX_INDEX_ARRAY_TYPE_OES: { const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION); *ptr = state->type; isClientStateParam = true; break; } case GL_MATRIX_INDEX_ARRAY_STRIDE_OES: { const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION); *ptr = state->stride; isClientStateParam = true; break; } case GL_WEIGHT_ARRAY_SIZE_OES: { const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION); *ptr = state->size; isClientStateParam = true; break; } case GL_WEIGHT_ARRAY_TYPE_OES: { const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION); *ptr = state->type; isClientStateParam = true; break; } case GL_WEIGHT_ARRAY_STRIDE_OES: { const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION); *ptr = state->stride; isClientStateParam = true; break; } case GL_VERTEX_ARRAY_BUFFER_BINDING: { const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION); *ptr = state->bufferObject; isClientStateParam = true; break; } case GL_NORMAL_ARRAY_BUFFER_BINDING: { const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION); *ptr = state->bufferObject; isClientStateParam = true; break; } case GL_COLOR_ARRAY_BUFFER_BINDING: { const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION); *ptr = state->bufferObject; isClientStateParam = true; break; } case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: { const GLClientState::VertexAttribState *state = getState(getActiveTexture()+GLClientState::TEXCOORD0_LOCATION); *ptr = state->bufferObject; isClientStateParam = true; break; } case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: { const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION); *ptr = state->bufferObject; isClientStateParam = true; break; } case GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES: { const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION); *ptr = state->bufferObject; isClientStateParam = true; break; } case GL_WEIGHT_ARRAY_BUFFER_BINDING_OES: { const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION); *ptr = state->bufferObject; isClientStateParam = true; break; } case GL_ARRAY_BUFFER_BINDING: { int buffer = getBuffer(GL_ARRAY_BUFFER); *ptr = buffer; isClientStateParam = true; break; } case GL_ELEMENT_ARRAY_BUFFER_BINDING: { int buffer = getBuffer(GL_ELEMENT_ARRAY_BUFFER); *ptr = buffer; isClientStateParam = true; break; } } return isClientStateParam; } }; #endif