opengles emulator: Support current value for attribute 0
In GLES, a vertex shader attribute can be at location 0 and have
a current value. In OpenGL, the spec is not clear, resulting in
absurdities like the ATI driver binding an attribute to location
0, does not give an erro when you set it, but gives an error when
you try to get it back. And it doesn't actually set the value in
the shader.
So, in this patch we:
1. Track attribute 0 value internally, setting and getting it
as necessary.
2. Upon glDrawArrays and glDrawElements, if attribute 0 is not
"array enabled" (that is, it should use a current value) we
create a dummy array, fill it with the intended current value,
and attach and enable it. After the draw, we disable it.
Change-Id: I35f3e8a924e6fba236f4f4d85423b04ae448dad4
This commit is contained in:
committed by
David 'Digit' Turner
parent
c9d192691e
commit
97fa8de7a2
@@ -26,11 +26,61 @@ void GLESv2Context::init() {
|
|||||||
for(int i=0; i < s_glSupport.maxVertexAttribs;i++){
|
for(int i=0; i < s_glSupport.maxVertexAttribs;i++){
|
||||||
m_map[i] = new GLESpointer();
|
m_map[i] = new GLESpointer();
|
||||||
}
|
}
|
||||||
|
setAttribute0value(0.0, 0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLESv2Context::GLESv2Context():GLEScontext(){};
|
GLESv2Context::GLESv2Context():GLEScontext(), m_att0Array(NULL), m_att0ArrayLength(0), m_att0NeedsDisable(false){};
|
||||||
|
|
||||||
|
GLESv2Context::~GLESv2Context()
|
||||||
|
{
|
||||||
|
delete[] m_att0Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLESv2Context::setAttribute0value(float x, float y, float z, float w)
|
||||||
|
{
|
||||||
|
m_attribute0value[0] = x;
|
||||||
|
m_attribute0value[1] = y;
|
||||||
|
m_attribute0value[2] = z;
|
||||||
|
m_attribute0value[3] = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLESv2Context::validateAtt0PreDraw(unsigned int count)
|
||||||
|
{
|
||||||
|
m_att0NeedsDisable = false;
|
||||||
|
|
||||||
|
if(count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int enabled = 0;
|
||||||
|
s_glDispatch.glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
|
||||||
|
if(enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(count > m_att0ArrayLength)
|
||||||
|
{
|
||||||
|
delete [] m_att0Array;
|
||||||
|
m_att0Array = new GLfloat[4*count];
|
||||||
|
m_att0ArrayLength = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(unsigned int i=0; i<count; i++)
|
||||||
|
memcpy(m_att0Array+i*4, m_attribute0value, 4*sizeof(GLfloat));
|
||||||
|
|
||||||
|
s_glDispatch.glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, m_att0Array);
|
||||||
|
s_glDispatch.glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
m_att0NeedsDisable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLESv2Context::validateAtt0PostDraw(void)
|
||||||
|
{
|
||||||
|
if(m_att0NeedsDisable)
|
||||||
|
s_glDispatch.glDisableVertexAttribArray(0);
|
||||||
|
|
||||||
|
m_att0NeedsDisable = false;
|
||||||
|
}
|
||||||
|
|
||||||
void GLESv2Context::setupArraysPointers(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct) {
|
void GLESv2Context::setupArraysPointers(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct) {
|
||||||
ArraysMap::iterator it;
|
ArraysMap::iterator it;
|
||||||
|
|||||||
@@ -28,13 +28,29 @@ class GLESv2Context : public GLEScontext{
|
|||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
GLESv2Context();
|
GLESv2Context();
|
||||||
|
virtual ~GLESv2Context();
|
||||||
void setupArraysPointers(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct);
|
void setupArraysPointers(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct);
|
||||||
int getMaxTexUnits();
|
int getMaxTexUnits();
|
||||||
|
|
||||||
|
// This whole att0 thing is about a incompatibility between GLES and OpenGL.
|
||||||
|
// GLES allows a vertex shader attribute to be in location 0 and have a
|
||||||
|
// current value, while OpenGL is not very clear about this, which results
|
||||||
|
// in each implementation doing something different.
|
||||||
|
void setAttribute0value(float x, float y, float z, float w);
|
||||||
|
void validateAtt0PreDraw(unsigned int count);
|
||||||
|
void validateAtt0PostDraw(void);
|
||||||
|
const float* getAtt0(void) {return m_attribute0value;}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool needConvert(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id);
|
bool needConvert(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id);
|
||||||
private:
|
private:
|
||||||
void setupArr(const GLvoid* arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized, int pointsIndex = -1);
|
void setupArr(const GLvoid* arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized, int pointsIndex = -1);
|
||||||
void initExtensionString();
|
void initExtensionString();
|
||||||
|
|
||||||
|
float m_attribute0value[4];
|
||||||
|
GLfloat* m_att0Array;
|
||||||
|
unsigned int m_att0ArrayLength;
|
||||||
|
bool m_att0NeedsDisable;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ GL_APICALL void GL_APIENTRY glDisableVertexAttribArray(GLuint index){
|
|||||||
}
|
}
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count){
|
GL_APICALL void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count){
|
||||||
GET_CTX();
|
GET_CTX_V2();
|
||||||
SET_ERROR_IF(count < 0,GL_INVALID_VALUE)
|
SET_ERROR_IF(count < 0,GL_INVALID_VALUE)
|
||||||
SET_ERROR_IF(!GLESv2Validate::drawMode(mode),GL_INVALID_ENUM);
|
SET_ERROR_IF(!GLESv2Validate::drawMode(mode),GL_INVALID_ENUM);
|
||||||
|
|
||||||
@@ -555,6 +555,8 @@ GL_APICALL void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei coun
|
|||||||
GLESConversionArrays tmpArrs;
|
GLESConversionArrays tmpArrs;
|
||||||
ctx->setupArraysPointers(tmpArrs,first,count,0,NULL,true);
|
ctx->setupArraysPointers(tmpArrs,first,count,0,NULL,true);
|
||||||
|
|
||||||
|
ctx->validateAtt0PreDraw(count);
|
||||||
|
|
||||||
//Enable texture generation for GL_POINTS and gl_PointSize shader variable
|
//Enable texture generation for GL_POINTS and gl_PointSize shader variable
|
||||||
//GLES2 assumes this is enabled by default, we need to set this state for GL
|
//GLES2 assumes this is enabled by default, we need to set this state for GL
|
||||||
if (mode==GL_POINTS) {
|
if (mode==GL_POINTS) {
|
||||||
@@ -568,10 +570,12 @@ GL_APICALL void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei coun
|
|||||||
ctx->dispatcher().glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
ctx->dispatcher().glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||||
ctx->dispatcher().glDisable(GL_POINT_SPRITE);
|
ctx->dispatcher().glDisable(GL_POINT_SPRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->validateAtt0PostDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* elementsIndices){
|
GL_APICALL void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* elementsIndices){
|
||||||
GET_CTX();
|
GET_CTX_V2();
|
||||||
SET_ERROR_IF(count < 0,GL_INVALID_VALUE)
|
SET_ERROR_IF(count < 0,GL_INVALID_VALUE)
|
||||||
SET_ERROR_IF(!(GLESv2Validate::drawMode(mode) && GLESv2Validate::drawType(type)),GL_INVALID_ENUM);
|
SET_ERROR_IF(!(GLESv2Validate::drawMode(mode) && GLESv2Validate::drawType(type)),GL_INVALID_ENUM);
|
||||||
|
|
||||||
@@ -586,6 +590,9 @@ GL_APICALL void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum t
|
|||||||
GLESConversionArrays tmpArrs;
|
GLESConversionArrays tmpArrs;
|
||||||
ctx->setupArraysPointers(tmpArrs,0,count,type,indices,false);
|
ctx->setupArraysPointers(tmpArrs,0,count,type,indices,false);
|
||||||
|
|
||||||
|
int maxIndex = ctx->findMaxIndex(count, type, indices);
|
||||||
|
ctx->validateAtt0PreDraw(maxIndex);
|
||||||
|
|
||||||
//See glDrawArrays
|
//See glDrawArrays
|
||||||
if (mode==GL_POINTS) {
|
if (mode==GL_POINTS) {
|
||||||
ctx->dispatcher().glEnable(GL_POINT_SPRITE);
|
ctx->dispatcher().glEnable(GL_POINT_SPRITE);
|
||||||
@@ -598,6 +605,8 @@ GL_APICALL void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum t
|
|||||||
ctx->dispatcher().glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
ctx->dispatcher().glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||||
ctx->dispatcher().glDisable(GL_POINT_SPRITE);
|
ctx->dispatcher().glDisable(GL_POINT_SPRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->validateAtt0PostDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glEnable(GLenum cap){
|
GL_APICALL void GL_APIENTRY glEnable(GLenum cap){
|
||||||
@@ -1300,7 +1309,7 @@ GL_APICALL int GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar* na
|
|||||||
|
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params){
|
GL_APICALL void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params){
|
||||||
GET_CTX();
|
GET_CTX_V2();
|
||||||
const GLESpointer* p = ctx->getPointer(index);
|
const GLESpointer* p = ctx->getPointer(index);
|
||||||
if(p) {
|
if(p) {
|
||||||
switch(pname){
|
switch(pname){
|
||||||
@@ -1323,6 +1332,13 @@ GL_APICALL void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLf
|
|||||||
*params = p->isNormalize();
|
*params = p->isNormalize();
|
||||||
break;
|
break;
|
||||||
case GL_CURRENT_VERTEX_ATTRIB:
|
case GL_CURRENT_VERTEX_ATTRIB:
|
||||||
|
if(index == 0)
|
||||||
|
{
|
||||||
|
const float* att0 = ctx->getAtt0();
|
||||||
|
for(int i=0; i<4; i++)
|
||||||
|
params[i] = att0[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
ctx->dispatcher().glGetVertexAttribfv(index,pname,params);
|
ctx->dispatcher().glGetVertexAttribfv(index,pname,params);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1334,7 +1350,7 @@ GL_APICALL void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLf
|
|||||||
}
|
}
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params){
|
GL_APICALL void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params){
|
||||||
GET_CTX();
|
GET_CTX_V2();
|
||||||
const GLESpointer* p = ctx->getPointer(index);
|
const GLESpointer* p = ctx->getPointer(index);
|
||||||
if(p) {
|
if(p) {
|
||||||
switch(pname){
|
switch(pname){
|
||||||
@@ -1357,6 +1373,13 @@ GL_APICALL void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLi
|
|||||||
*params = p->isNormalize();
|
*params = p->isNormalize();
|
||||||
break;
|
break;
|
||||||
case GL_CURRENT_VERTEX_ATTRIB:
|
case GL_CURRENT_VERTEX_ATTRIB:
|
||||||
|
if(index == 0)
|
||||||
|
{
|
||||||
|
const float* att0 = ctx->getAtt0();
|
||||||
|
for(int i=0; i<4; i++)
|
||||||
|
params[i] = (GLint)att0[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
ctx->dispatcher().glGetVertexAttribiv(index,pname,params);
|
ctx->dispatcher().glGetVertexAttribiv(index,pname,params);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1816,43 +1839,59 @@ GL_APICALL void GL_APIENTRY glValidateProgram(GLuint program){
|
|||||||
}
|
}
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glVertexAttrib1f(GLuint indx, GLfloat x){
|
GL_APICALL void GL_APIENTRY glVertexAttrib1f(GLuint indx, GLfloat x){
|
||||||
GET_CTX();
|
GET_CTX_V2();
|
||||||
ctx->dispatcher().glVertexAttrib1f(indx,x);
|
ctx->dispatcher().glVertexAttrib1f(indx,x);
|
||||||
|
if(indx == 0)
|
||||||
|
ctx->setAttribute0value(x, 0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glVertexAttrib1fv(GLuint indx, const GLfloat* values){
|
GL_APICALL void GL_APIENTRY glVertexAttrib1fv(GLuint indx, const GLfloat* values){
|
||||||
GET_CTX();
|
GET_CTX_V2();
|
||||||
ctx->dispatcher().glVertexAttrib1fv(indx,values);
|
ctx->dispatcher().glVertexAttrib1fv(indx,values);
|
||||||
|
if(indx == 0)
|
||||||
|
ctx->setAttribute0value(values[0], 0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y){
|
GL_APICALL void GL_APIENTRY glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y){
|
||||||
GET_CTX();
|
GET_CTX_V2();
|
||||||
ctx->dispatcher().glVertexAttrib2f(indx,x,y);
|
ctx->dispatcher().glVertexAttrib2f(indx,x,y);
|
||||||
|
if(indx == 0)
|
||||||
|
ctx->setAttribute0value(x, y, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glVertexAttrib2fv(GLuint indx, const GLfloat* values){
|
GL_APICALL void GL_APIENTRY glVertexAttrib2fv(GLuint indx, const GLfloat* values){
|
||||||
GET_CTX();
|
GET_CTX_V2();
|
||||||
ctx->dispatcher().glVertexAttrib2fv(indx,values);
|
ctx->dispatcher().glVertexAttrib2fv(indx,values);
|
||||||
|
if(indx == 0)
|
||||||
|
ctx->setAttribute0value(values[0], values[1], 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z){
|
GL_APICALL void GL_APIENTRY glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z){
|
||||||
GET_CTX();
|
GET_CTX_V2();
|
||||||
ctx->dispatcher().glVertexAttrib3f(indx,x,y,z);
|
ctx->dispatcher().glVertexAttrib3f(indx,x,y,z);
|
||||||
|
if(indx == 0)
|
||||||
|
ctx->setAttribute0value(x, y, z, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glVertexAttrib3fv(GLuint indx, const GLfloat* values){
|
GL_APICALL void GL_APIENTRY glVertexAttrib3fv(GLuint indx, const GLfloat* values){
|
||||||
GET_CTX();
|
GET_CTX_V2();
|
||||||
ctx->dispatcher().glVertexAttrib3fv(indx,values);
|
ctx->dispatcher().glVertexAttrib3fv(indx,values);
|
||||||
|
if(indx == 0)
|
||||||
|
ctx->setAttribute0value(values[0], values[1], values[2], 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w){
|
GL_APICALL void GL_APIENTRY glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w){
|
||||||
GET_CTX();
|
GET_CTX_V2();
|
||||||
ctx->dispatcher().glVertexAttrib4f(indx,x,y,z,w);
|
ctx->dispatcher().glVertexAttrib4f(indx,x,y,z,w);
|
||||||
|
if(indx == 0)
|
||||||
|
ctx->setAttribute0value(x, y, z, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glVertexAttrib4fv(GLuint indx, const GLfloat* values){
|
GL_APICALL void GL_APIENTRY glVertexAttrib4fv(GLuint indx, const GLfloat* values){
|
||||||
GET_CTX();
|
GET_CTX_V2();
|
||||||
ctx->dispatcher().glVertexAttrib4fv(indx,values);
|
ctx->dispatcher().glVertexAttrib4fv(indx,values);
|
||||||
|
if(indx == 0)
|
||||||
|
ctx->setAttribute0value(values[0], values[1], values[2], values[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_APICALL void GL_APIENTRY glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr){
|
GL_APICALL void GL_APIENTRY glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr){
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
|
||||||
//decleration
|
//decleration
|
||||||
static int findMaxIndex(GLsizei count,GLenum type,const GLvoid* indices);
|
|
||||||
static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize);
|
static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize);
|
||||||
static void convertFixedIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize);
|
static void convertFixedIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize);
|
||||||
static void convertByteDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize);
|
static void convertByteDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize);
|
||||||
@@ -331,7 +330,7 @@ void GLEScontext::convertDirectVBO(GLESConversionArrays& cArrs,GLint first,GLsiz
|
|||||||
cArrs.setArr(data,p->getStride(),GL_FLOAT);
|
cArrs.setArr(data,p->getStride(),GL_FLOAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int findMaxIndex(GLsizei count,GLenum type,const GLvoid* indices) {
|
int GLEScontext::findMaxIndex(GLsizei count,GLenum type,const GLvoid* indices) {
|
||||||
//finding max index
|
//finding max index
|
||||||
int max = 0;
|
int max = 0;
|
||||||
if(type == GL_UNSIGNED_BYTE) {
|
if(type == GL_UNSIGNED_BYTE) {
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ public:
|
|||||||
static Version glslVersion(){return s_glSupport.glslVersion;}
|
static Version glslVersion(){return s_glSupport.glslVersion;}
|
||||||
static bool isAutoMipmapSupported(){return s_glSupport.GL_SGIS_GENERATE_MIPMAP;}
|
static bool isAutoMipmapSupported(){return s_glSupport.GL_SGIS_GENERATE_MIPMAP;}
|
||||||
static TextureTarget GLTextureTargetToLocal(GLenum target);
|
static TextureTarget GLTextureTargetToLocal(GLenum target);
|
||||||
|
static int findMaxIndex(GLsizei count,GLenum type,const GLvoid* indices);
|
||||||
|
|
||||||
virtual bool glGetIntegerv(GLenum pname, GLint *params);
|
virtual bool glGetIntegerv(GLenum pname, GLint *params);
|
||||||
virtual bool glGetBooleanv(GLenum pname, GLboolean *params);
|
virtual bool glGetBooleanv(GLenum pname, GLboolean *params);
|
||||||
|
|||||||
Reference in New Issue
Block a user