/*
* 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