From 97fa8de7a2e2297b46d8565ee42418af32c06463 Mon Sep 17 00:00:00 2001 From: Yochai Shefi Simchon Date: Mon, 8 Aug 2011 13:37:03 +0300 Subject: [PATCH] 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 --- .../libs/Translator/GLES_V2/GLESv2Context.cpp | 52 +++++++++++++- .../libs/Translator/GLES_V2/GLESv2Context.h | 16 +++++ .../libs/Translator/GLES_V2/GLESv2Imp.cpp | 67 +++++++++++++++---- .../libs/Translator/GLcommon/GLEScontext.cpp | 3 +- .../Translator/include/GLcommon/GLEScontext.h | 1 + 5 files changed, 122 insertions(+), 17 deletions(-) diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp b/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp index 1045c9962..92f931902 100644 --- a/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp +++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp @@ -26,11 +26,61 @@ void GLESv2Context::init() { for(int i=0; i < s_glSupport.maxVertexAttribs;i++){ m_map[i] = new GLESpointer(); } + setAttribute0value(0.0, 0.0, 0.0, 1.0); } 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; isetupArraysPointers(tmpArrs,first,count,0,NULL,true); + ctx->validateAtt0PreDraw(count); + //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 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_POINT_SPRITE); } + + ctx->validateAtt0PostDraw(); } 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(!(GLESv2Validate::drawMode(mode) && GLESv2Validate::drawType(type)),GL_INVALID_ENUM); @@ -585,6 +589,9 @@ GL_APICALL void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum t GLESConversionArrays tmpArrs; ctx->setupArraysPointers(tmpArrs,0,count,type,indices,false); + + int maxIndex = ctx->findMaxIndex(count, type, indices); + ctx->validateAtt0PreDraw(maxIndex); //See glDrawArrays if (mode==GL_POINTS) { @@ -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_POINT_SPRITE); } + + ctx->validateAtt0PostDraw(); } 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){ - GET_CTX(); + GET_CTX_V2(); const GLESpointer* p = ctx->getPointer(index); if(p) { switch(pname){ @@ -1323,7 +1332,14 @@ GL_APICALL void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLf *params = p->isNormalize(); break; case GL_CURRENT_VERTEX_ATTRIB: - ctx->dispatcher().glGetVertexAttribfv(index,pname,params); + 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); break; default: ctx->setGLerror(GL_INVALID_ENUM); @@ -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){ - GET_CTX(); + GET_CTX_V2(); const GLESpointer* p = ctx->getPointer(index); if(p) { switch(pname){ @@ -1357,7 +1373,14 @@ GL_APICALL void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLi *params = p->isNormalize(); break; case GL_CURRENT_VERTEX_ATTRIB: - ctx->dispatcher().glGetVertexAttribiv(index,pname,params); + 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); break; default: ctx->setGLerror(GL_INVALID_ENUM); @@ -1816,43 +1839,59 @@ GL_APICALL void GL_APIENTRY glValidateProgram(GLuint program){ } GL_APICALL void GL_APIENTRY glVertexAttrib1f(GLuint indx, GLfloat x){ - GET_CTX(); + GET_CTX_V2(); 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){ - GET_CTX(); + GET_CTX_V2(); 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){ - GET_CTX(); + GET_CTX_V2(); 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){ - GET_CTX(); + GET_CTX_V2(); 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){ - GET_CTX(); + GET_CTX_V2(); 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){ - GET_CTX(); + GET_CTX_V2(); 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){ - GET_CTX(); + GET_CTX_V2(); 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){ - GET_CTX(); + GET_CTX_V2(); 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){ diff --git a/tools/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp b/tools/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp index 25bd14263..22b4c8b06 100644 --- a/tools/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp +++ b/tools/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp @@ -9,7 +9,6 @@ #include //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 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); @@ -331,7 +330,7 @@ void GLEScontext::convertDirectVBO(GLESConversionArrays& cArrs,GLint first,GLsiz 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 int max = 0; if(type == GL_UNSIGNED_BYTE) { diff --git a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h index 3e594386c..d266e3df6 100644 --- a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h +++ b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h @@ -151,6 +151,7 @@ public: static Version glslVersion(){return s_glSupport.glslVersion;} static bool isAutoMipmapSupported(){return s_glSupport.GL_SGIS_GENERATE_MIPMAP;} static TextureTarget GLTextureTargetToLocal(GLenum target); + static int findMaxIndex(GLsizei count,GLenum type,const GLvoid* indices); virtual bool glGetIntegerv(GLenum pname, GLint *params); virtual bool glGetBooleanv(GLenum pname, GLboolean *params);