/*
* 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 "TextureSharedData.h"
#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"
#include <vector>
#include <map>
#include <set>
// Tracking framebuffer objects:
// which framebuffer is bound,
// and which texture names
// are currently bound to which attachment points.
struct FboProps {
GLuint name;
bool previouslyBound;
std::vector<GLuint> colorAttachmenti_textures;
GLuint depthAttachment_texture;
GLuint stencilAttachment_texture;
GLuint depthstencilAttachment_texture;
std::vector<bool> colorAttachmenti_hasTex;
bool depthAttachment_hasTexObj;
bool stencilAttachment_hasTexObj;
bool depthstencilAttachment_hasTexObj;
std::vector<GLuint> colorAttachmenti_rbos;
GLuint depthAttachment_rbo;
GLuint stencilAttachment_rbo;
GLuint depthstencilAttachment_rbo;
std::vector<bool> colorAttachmenti_hasRbo;
bool depthAttachment_hasRbo;
bool stencilAttachment_hasRbo;
bool depthstencilAttachment_hasRbo;
};
// Same for Rbo's
struct RboProps {
GLenum target;
GLuint name;
GLenum format;
GLsizei multisamples;
bool previouslyBound;
};
// Enum for describing whether a framebuffer attachment
// is a texture or renderbuffer.
enum FboAttachmentType {
FBO_ATTACHMENT_RENDERBUFFER = 0,
FBO_ATTACHMENT_TEXTURE = 1,
FBO_ATTACHMENT_NONE = 2
};
// Tracking FBO format
struct FboFormatInfo {
FboAttachmentType type;
GLenum rb_format;
GLsizei rb_multisamples;
GLint tex_internalformat;
GLenum tex_format;
GLenum tex_type;
GLsizei tex_multisamples;
};
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 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;
int unpack_row_length;
int unpack_image_height;
int unpack_skip_pixels;
int unpack_skip_rows;
int unpack_skip_images;
int pack_alignment;
int pack_row_length;
int pack_skip_pixels;
int pack_skip_rows;
} PixelStoreState;
enum {
MAX_TEXTURE_UNITS = 256,
};
public:
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 currentVertexArrayObject() const { return m_currVaoState.vaoId(); }
const VertexAttribBindingVector& currentVertexBufferBindings() const {
return m_currVaoState.bufferBindings_const();
}
GLuint currentArrayVbo() { return m_arrayBuffer; }
GLuint currentIndexVbo() { return m_currVaoState.iboId(); }
void enable(int location, int state);
// 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; }
void setMaxVertexAttribs(int val) {
m_maxVertexAttribs = val;
m_maxVertexAttribsDirty = false;
}
void addBuffer(GLuint id);
void removeBuffer(GLuint id);
bool bufferIdExists(GLuint id) const;
void unBindBuffer(GLuint id);
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);
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 getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const;
void setCurrentProgram(GLint program) { m_currentProgram = program; }
void setCurrentShaderProgram(GLint program) { m_currentShaderProgram = program; }
GLint currentProgram() const { return m_currentProgram; }
GLint currentShaderProgram() const { return m_currentShaderProgram; }
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;
typedef std::map<GLuint, GLuint> ProgramPipelineMap;
typedef ProgramPipelineMap::iterator ProgramPipelineIterator;
void associateProgramWithPipeline(GLuint program, GLuint pipeline);
ProgramPipelineIterator programPipelineBegin();
ProgramPipelineIterator programPipelineEnd();
/* 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);
void setBoundEGLImage(GLenum target, GLeglImageOES image);
// Return the texture currently bound to GL_TEXTURE_(2D|EXTERNAL_OES).
GLuint getBoundTexture(GLenum target) const;
// Other publicly-visible texture queries
GLenum queryTexLastBoundTarget(GLuint name) const;
GLenum queryTexFormat(GLuint name) const;
GLint queryTexInternalFormat(GLuint name) const;
GLsizei queryTexWidth(GLsizei level, GLuint name) const;
GLsizei queryTexHeight(GLsizei level, GLuint name) const;
GLsizei queryTexDepth(GLsizei level, GLuint name) const;
bool queryTexEGLImageBacked(GLuint name) const;
// For AMD GPUs, it is easy for the emulator to segfault
// (esp. in dEQP) when a cube map is defined using glCopyTexImage2D
// and uses GL_LUMINANCE as internal format.
// In particular, the segfault happens when negative components of
// cube maps are defined before positive ones,
// This procedure checks internal state to see if we have defined
// the positive component of a cube map already. If not, it returns
// which positive component needs to be defined first.
// If there is no need for the extra definition, 0 is returned.
GLenum copyTexImageLuminanceCubeMapAMDWorkaround(GLenum target, GLint level,
GLenum internalformat);
// Tracks the format of the currently bound texture.
// This is to pass dEQP tests for fbo completeness.
void setBoundTextureInternalFormat(GLenum target, GLint format);
void setBoundTextureFormat(GLenum target, GLenum format);
void setBoundTextureType(GLenum target, GLenum type);
void setBoundTextureDims(GLenum target, GLsizei level, GLsizei width, GLsizei height, GLsizei depth);
void setBoundTextureSamples(GLenum target, GLsizei samples);
// glTexStorage2D disallows any change in texture format after it is set for a particular texture.
void setBoundTextureImmutableFormat(GLenum target);
bool isBoundTextureImmutableFormat(GLenum target) const;
// glDeleteTextures(...)
// Remove references to the to-be-deleted textures.
void deleteTextures(GLsizei n, const GLuint* textures);
// Render buffer objects
void addRenderbuffers(GLsizei n, GLuint* renderbuffers);
void removeRenderbuffers(GLsizei n, const GLuint* renderbuffers);
bool usedRenderbufferName(GLuint name) const;
void bindRenderbuffer(GLenum target, GLuint name);
GLuint boundRenderbuffer() const;
void setBoundRenderbufferFormat(GLenum format);
void setBoundRenderbufferSamples(GLsizei samples);
// Frame buffer objects
void addFramebuffers(GLsizei n, GLuint* framebuffers);
void removeFramebuffers(GLsizei n, const GLuint* framebuffers);
bool usedFramebufferName(GLuint name) const;
void bindFramebuffer(GLenum target, GLuint name);
void setCheckFramebufferStatus(GLenum target, GLenum status);
GLenum getCheckFramebufferStatus(GLenum target) const;
GLuint boundFramebuffer(GLenum target) const;
// Texture object -> FBO
void attachTextureObject(GLenum target, GLenum attachment, GLuint texture);
GLuint getFboAttachmentTextureId(GLenum target, GLenum attachment) const;
// RBO -> FBO
void detachRbo(GLuint renderbuffer);
void detachRboFromFbo(GLenum target, GLenum attachment, GLuint renderbuffer);
void attachRbo(GLenum target, GLenum attachment, GLuint renderbuffer);
GLuint getFboAttachmentRboId(GLenum target, GLenum attachment) const;
// FBO attachments in general
bool attachmentHasObject(GLenum target, GLenum attachment) const;
GLuint objectOfAttachment(GLenum target, GLenum attachment) const;
// Transform feedback state
void setTransformFeedbackActiveUnpaused(bool activeUnpaused);
bool getTransformFeedbackActiveUnpaused() const;
void setTextureData(SharedTextureDataMap* sharedTexData);
// 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
// is a texture or renderbuffer.
void getBoundFramebufferFormat(
GLenum target,
GLenum attachment,
FboFormatInfo* res_info) const;
FboAttachmentType getBoundFramebufferAttachmentType(
GLenum target,
GLenum attachment) const;
int getMaxColorAttachments() const;
int getMaxDrawBuffers() const;
private:
void init();
bool m_initialized;
PixelStoreState m_pixelStore;
std::set<GLuint> mBufferIds;
// 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;
int m_activeTexture;
GLint m_currentProgram;
GLint m_currentShaderProgram;
ProgramPipelineMap m_programPipelines;
enum TextureTarget {
TEXTURE_2D = 0,
TEXTURE_EXTERNAL = 1,
TEXTURE_CUBE_MAP = 2,
TEXTURE_2D_ARRAY = 3,
TEXTURE_3D = 4,
TEXTURE_2D_MULTISAMPLE = 5,
TEXTURE_TARGET_COUNT
};
struct TextureUnit {
unsigned int enables;
GLuint texture[TEXTURE_TARGET_COUNT];
};
struct TextureState {
TextureUnit unit[MAX_TEXTURE_UNITS];
TextureUnit* activeUnit;
// Initialized from shared group.
SharedTextureDataMap* textureRecs;
};
TextureState m_tex;
// State tracking of cube map definitions.
// Currently used only for driver workarounds
// when using GL_LUMINANCE and defining cube maps with
// glCopyTexImage2D.
struct CubeMapDef {
GLuint id;
GLenum target;
GLint level;
GLenum internalformat;
};
struct CubeMapDefCompare {
bool operator() (const CubeMapDef& a,
const CubeMapDef& b) const {
if (a.id != b.id) return a.id < b.id;
if (a.target != b.target) return a.target < b.target;
if (a.level != b.level) return a.level < b.level;
if (a.internalformat != b.internalformat)
return a.internalformat < b.internalformat;
return false;
}
};
std::set<CubeMapDef, CubeMapDefCompare> m_cubeMapDefs;
void writeCopyTexImageState(GLenum target, GLint level,
GLenum internalformat);
GLenum copyTexImageNeededTarget(GLenum target, GLint level,
GLenum internalformat);
int m_max_color_attachments;
int m_max_draw_buffers;
struct RboState {
GLuint boundRenderbuffer;
size_t boundRenderbufferIndex;
std::vector<RboProps> rboData;
};
RboState mRboState;
void addFreshRenderbuffer(GLuint name);
void setBoundRenderbufferIndex();
size_t getRboIndex(GLuint name) const;
RboProps& boundRboProps();
const RboProps& boundRboProps_const() const;
struct FboState {
GLuint boundDrawFramebuffer;
GLuint boundReadFramebuffer;
size_t boundFramebufferIndex;
std::map<GLuint, FboProps> fboData;
GLenum drawFboCheckStatus;
GLenum readFboCheckStatus;
};
FboState mFboState;
void addFreshFramebuffer(GLuint name);
FboProps& boundFboProps(GLenum target);
const FboProps& boundFboProps_const(GLenum target) const;
// Querying framebuffer format
GLenum queryRboFormat(GLuint name) const;
GLsizei queryRboSamples(GLuint name) const;
GLenum queryTexType(GLuint name) const;
GLsizei queryTexSamples(GLuint name) const;
static int compareTexId(const void* pid, const void* prec);
TextureRec* addTextureRec(GLuint id, GLenum target);
TextureRec* getTextureRec(GLuint id) const;
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);
const BufferBinding& vertexAttribBufferBinding =
m_currVaoState.bufferBindings_const()[vertexAttrib.bindingindex];
switch(param) {
#define GL_VERTEX_ATTRIB_BINDING 0x82D4
case GL_VERTEX_ATTRIB_BINDING:
*ptr = (T)vertexAttrib.bindingindex;
break;
#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
*ptr = (T)vertexAttrib.reloffset;
break;
case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
*ptr = (T)(vertexAttribBufferBinding.buffer);
break;
case GL_VERTEX_ATTRIB_ARRAY_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);
break;
case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
*ptr = (T)(vertexAttribBufferBinding.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* out)
{
bool isClientStateParam = false;
switch (param) {
case GL_CLIENT_ACTIVE_TEXTURE: {
GLint tex = getActiveTexture() + GL_TEXTURE0;
*out = tex;
isClientStateParam = true;
break;
}
case GL_VERTEX_ARRAY_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);
*out = state.type;
isClientStateParam = true;
break;
}
case GL_VERTEX_ARRAY_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);
*out = state.size;
isClientStateParam = true;
break;
}
case GL_COLOR_ARRAY_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);
*out = state.stride;
isClientStateParam = true;
break;
}
case GL_NORMAL_ARRAY_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);
*out = state.stride;
isClientStateParam = true;
break;
}
case GL_TEXTURE_COORD_ARRAY_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);
*out = state.type;
isClientStateParam = true;
break;
}
case GL_TEXTURE_COORD_ARRAY_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);
*out = state.type;
isClientStateParam = true;
break;
}
case GL_POINT_SIZE_ARRAY_STRIDE_OES: {
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);
*out = state.size;
isClientStateParam = true;
break;
}
case GL_MATRIX_INDEX_ARRAY_TYPE_OES: {
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);
*out = state.stride;
isClientStateParam = true;
break;
}
case GL_WEIGHT_ARRAY_SIZE_OES: {
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);
*out = state.type;
isClientStateParam = true;
break;
}
case GL_WEIGHT_ARRAY_STRIDE_OES: {
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);
*out = state.bufferObject;
isClientStateParam = true;
break;
}
case GL_NORMAL_ARRAY_BUFFER_BINDING: {
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);
*out = state.bufferObject;
isClientStateParam = true;
break;
}
case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: {
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);
*out = state.bufferObject;
isClientStateParam = true;
break;
}
case GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES: {
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);
*out = state.bufferObject;
isClientStateParam = true;
break;
}
case GL_ARRAY_BUFFER_BINDING: {
int buffer = getBuffer(GL_ARRAY_BUFFER);
*out = buffer;
isClientStateParam = true;
break;
}
case GL_ELEMENT_ARRAY_BUFFER_BINDING: {
int buffer = getBuffer(GL_ELEMENT_ARRAY_BUFFER);
*out = buffer;
isClientStateParam = true;
break;
}
case GL_MAX_VERTEX_ATTRIBS: {
if (m_maxVertexAttribsDirty) {
isClientStateParam = false;
} else {
*out = m_maxVertexAttribs;
isClientStateParam = true;
}
break;
}
}
return isClientStateParam;
}
};
#endif