New VertexAttribute data types

Added int and unsigned int as possible
internal storage types for VertexAttribute
on top of the existing float type by using
a union in order to be able to store the new
VertexAttribute types in their native types.

Change-Id: I5a98aeded065095df6b44fa20f4c293ae230bc37
Reviewed-on: https://swiftshader-review.googlesource.com/2828
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 2ef8661..c610e59 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -746,6 +746,11 @@
     mState.vertexAttribute[attribNum].mArrayEnabled = enabled;

 }

 

+void Context::setVertexAttribDivisor(unsigned int attribNum, GLuint divisor)

+{

+	mState.vertexAttribute[attribNum].mDivisor = divisor;

+}

+

 const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)

 {

     return mState.vertexAttribute[attribNum];

@@ -3408,14 +3413,29 @@
 {

     ASSERT(index < MAX_VERTEX_ATTRIBS);

 

-    mState.vertexAttribute[index].mCurrentValue[0] = values[0];

-    mState.vertexAttribute[index].mCurrentValue[1] = values[1];

-    mState.vertexAttribute[index].mCurrentValue[2] = values[2];

-    mState.vertexAttribute[index].mCurrentValue[3] = values[3];

+    mState.vertexAttribute[index].setCurrentValue(values);

 

     mVertexDataManager->dirtyCurrentValue(index);

 }

 

+void Context::setVertexAttrib(GLuint index, const GLint *values)

+{

+	ASSERT(index < MAX_VERTEX_ATTRIBS);

+

+	mState.vertexAttribute[index].setCurrentValue(values);

+

+	mVertexDataManager->dirtyCurrentValue(index);

+}

+

+void Context::setVertexAttrib(GLuint index, const GLuint *values)

+{

+	ASSERT(index < MAX_VERTEX_ATTRIBS);

+

+	mState.vertexAttribute[index].setCurrentValue(values);

+

+	mVertexDataManager->dirtyCurrentValue(index);

+}

+

 void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 

                               GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,

                               GLbitfield mask)

diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h
index 2105cc4..aa7fccc 100644
--- a/src/OpenGL/libGLESv2/Context.h
+++ b/src/OpenGL/libGLESv2/Context.h
@@ -133,12 +133,13 @@
 class VertexAttribute

 {

   public:

-    VertexAttribute() : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false)

+    VertexAttribute() : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mDivisor(0), mPointer(NULL), mArrayEnabled(false)

     {

-        mCurrentValue[0] = 0.0f;

-        mCurrentValue[1] = 0.0f;

-        mCurrentValue[2] = 0.0f;

-        mCurrentValue[3] = 1.0f;

+        mCurrentValue[0].f = 0.0f;

+        mCurrentValue[1].f = 0.0f;

+        mCurrentValue[2].f = 0.0f;

+        mCurrentValue[3].f = 1.0f;

+		mCurrentValueType = ValueUnion::FloatType;

     }

 

     int typeSize() const

@@ -160,11 +161,72 @@
         return mStride ? mStride : typeSize();

     }

 

+	inline float getCurrentValue(int i) const

+	{

+		switch(mCurrentValueType)

+		{

+		case ValueUnion::FloatType:	return mCurrentValue[i].f;

+		case ValueUnion::IntType:	return static_cast<float>(mCurrentValue[i].i);

+		case ValueUnion::UIntType:	return static_cast<float>(mCurrentValue[i].ui);

+		default: UNREACHABLE();		return mCurrentValue[i].f;

+		}

+	}

+

+	inline GLint getCurrentValueI(int i) const

+	{

+		switch(mCurrentValueType)

+		{

+		case ValueUnion::FloatType:	return static_cast<GLint>(mCurrentValue[i].f);

+		case ValueUnion::IntType:	return mCurrentValue[i].i;

+		case ValueUnion::UIntType:	return static_cast<GLint>(mCurrentValue[i].ui);

+		default: UNREACHABLE();		return mCurrentValue[i].i;

+		}

+	}

+

+	inline GLuint getCurrentValueUI(int i) const

+	{

+		switch(mCurrentValueType)

+		{

+		case ValueUnion::FloatType:	return static_cast<GLuint>(mCurrentValue[i].f);

+		case ValueUnion::IntType:	return static_cast<GLuint>(mCurrentValue[i].i);

+		case ValueUnion::UIntType:	return mCurrentValue[i].ui;

+		default: UNREACHABLE();		return mCurrentValue[i].ui;

+		}

+	}

+

+	inline void setCurrentValue(const GLfloat *values)

+	{

+		mCurrentValue[0].f = values[0];

+		mCurrentValue[1].f = values[1];

+		mCurrentValue[2].f = values[2];

+		mCurrentValue[3].f = values[3];

+		mCurrentValueType = ValueUnion::FloatType;

+	}

+

+	inline void setCurrentValue(const GLint *values)

+	{

+		mCurrentValue[0].i = values[0];

+		mCurrentValue[1].i = values[1];

+		mCurrentValue[2].i = values[2];

+		mCurrentValue[3].i = values[3];

+		mCurrentValueType = ValueUnion::IntType;

+	}

+

+	inline void setCurrentValue(const GLuint *values)

+	{

+		mCurrentValue[0].ui = values[0];

+		mCurrentValue[1].ui = values[1];

+		mCurrentValue[2].ui = values[2];

+		mCurrentValue[3].ui = values[3];

+		mCurrentValueType = ValueUnion::UIntType;

+	}

+

     // From glVertexAttribPointer

     GLenum mType;

     GLint mSize;

     bool mNormalized;

     GLsizei mStride;   // 0 means natural stride

+    GLuint mDivisor;   // From glVertexAttribDivisor

 

     union

     {

@@ -175,7 +237,17 @@
     gl::BindingPointer<Buffer> mBoundBuffer;   // Captured when glVertexAttribPointer is called.

 

     bool mArrayEnabled;   // From glEnable/DisableVertexAttribArray

-    float mCurrentValue[4];   // From glVertexAttrib

+private:

+	union ValueUnion

+	{

+		enum Type { FloatType, IntType, UIntType };

+

+		float f;

+		GLint i;

+		GLuint ui;

+	};

+	ValueUnion mCurrentValue[4];   // From glVertexAttrib

+	ValueUnion::Type mCurrentValueType;

 };

 

 typedef VertexAttribute VertexAttributeArray[MAX_VERTEX_ATTRIBS];

@@ -353,6 +425,7 @@
     GLuint getArrayBufferName() const;

 

     void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);

+    void setVertexAttribDivisor(unsigned int attribNum, GLuint divisor);

     const VertexAttribute &getVertexAttribState(unsigned int attribNum);

     void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type,

                               bool normalized, GLsizei stride, const void *pointer);

@@ -426,6 +499,8 @@
     void setRenderbufferStorage(RenderbufferStorage *renderbuffer);

 

     void setVertexAttrib(GLuint index, const GLfloat *values);

+    void setVertexAttrib(GLuint index, const GLint *values);

+    void setVertexAttrib(GLuint index, const GLuint *values);

 

     Buffer *getBuffer(GLuint handle);

     Fence *getFence(GLuint handle);

diff --git a/src/OpenGL/libGLESv2/VertexDataManager.cpp b/src/OpenGL/libGLESv2/VertexDataManager.cpp
index 800ddfa..b6d7742 100644
--- a/src/OpenGL/libGLESv2/VertexDataManager.cpp
+++ b/src/OpenGL/libGLESv2/VertexDataManager.cpp
@@ -189,7 +189,7 @@
                 if(mDirtyCurrentValue[i])

                 {

                     delete mCurrentValueBuffer[i];

-                    mCurrentValueBuffer[i] = new ConstantVertexBuffer(attribs[i].mCurrentValue[0], attribs[i].mCurrentValue[1], attribs[i].mCurrentValue[2], attribs[i].mCurrentValue[3]);

+                    mCurrentValueBuffer[i] = new ConstantVertexBuffer(attribs[i].getCurrentValue(0), attribs[i].getCurrentValue(1), attribs[i].getCurrentValue(2), attribs[i].getCurrentValue(3));

                     mDirtyCurrentValue[i] = false;

                 }

 

diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index f5bed4f..21c1232 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -3655,7 +3655,7 @@
 		case GL_CURRENT_VERTEX_ATTRIB:

 			for(int i = 0; i < 4; ++i)

 			{

-				params[i] = attribState.mCurrentValue[i];

+				params[i] = attribState.getCurrentValue(i);

 			}

 			break;

 		case GL_VERTEX_ATTRIB_ARRAY_INTEGER:

@@ -3725,7 +3725,7 @@
 		case GL_CURRENT_VERTEX_ATTRIB:

 			for(int i = 0; i < 4; ++i)

 			{

-				float currentValue = attribState.mCurrentValue[i];

+				float currentValue = attribState.getCurrentValue(i);

 				params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));

 			}

 			break;

diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index 0a4b2b6..e58a3ce 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -1761,6 +1761,12 @@
 		case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:

 			*params = attribState.mBoundBuffer.name();

 			break;

+		case GL_CURRENT_VERTEX_ATTRIB:

+			for(int i = 0; i < 4; ++i)

+			{

+				params[i] = attribState.getCurrentValueI(i);

+			}

+			break;

 		case GL_VERTEX_ATTRIB_ARRAY_INTEGER:

 			switch(attribState.mType)

 			{

@@ -1779,6 +1785,9 @@
 				break;

 			}

 			break;

+		case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:

+			*params = attribState.mDivisor;

+			break;

 		default: return error(GL_INVALID_ENUM);

 		}

 	}

@@ -1820,6 +1829,12 @@
 		case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:

 			*params = attribState.mBoundBuffer.name();

 			break;

+		case GL_CURRENT_VERTEX_ATTRIB:

+			for(int i = 0; i < 4; ++i)

+			{

+				params[i] = attribState.getCurrentValueUI(i);

+			}

+			break;

 		case GL_VERTEX_ATTRIB_ARRAY_INTEGER:

 			switch(attribState.mType)

 			{

@@ -1838,6 +1853,9 @@
 				break;

 			}

 			break;

+		case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:

+			*params = attribState.mDivisor;

+			break;

 		default: return error(GL_INVALID_ENUM);

 		}

 	}

@@ -1847,26 +1865,72 @@
 {

 	TRACE("(GLuint index = %d, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",

 	      index, x, y, z, w);

-	UNIMPLEMENTED();

+

+	if(index >= es2::MAX_VERTEX_ATTRIBS)

+	{

+		return error(GL_INVALID_VALUE);

+	}

+

+	es2::Context *context = es2::getContext();

+

+	if(context)

+	{

+		GLint vals[4] = { x, y, z, w };

+		context->setVertexAttrib(index, vals);

+	}

 }

 

 void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)

 {

 	TRACE("(GLuint index = %d, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",

 	      index, x, y, z, w);

-	UNIMPLEMENTED();

+

+	if(index >= es2::MAX_VERTEX_ATTRIBS)

+	{

+		return error(GL_INVALID_VALUE);

+	}

+

+	es2::Context *context = es2::getContext();

+

+	if(context)

+	{

+		GLuint vals[4] = { x, y, z, w };

+		context->setVertexAttrib(index, vals);

+	}

 }

 

 void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint *v)

 {

 	TRACE("(GLuint index = %d, GLint *v = 0x%0.8p)", index, v);

-	UNIMPLEMENTED();

+

+	if(index >= es2::MAX_VERTEX_ATTRIBS)

+	{

+		return error(GL_INVALID_VALUE);

+	}

+

+	es2::Context *context = es2::getContext();

+

+	if(context)

+	{

+		context->setVertexAttrib(index, v);

+	}

 }

 

 void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint *v)

 {

 	TRACE("(GLuint index = %d, GLint *v = 0x%0.8p)", index, v);

-	UNIMPLEMENTED();

+

+	if(index >= es2::MAX_VERTEX_ATTRIBS)

+	{

+		return error(GL_INVALID_VALUE);

+	}

+

+	es2::Context *context = es2::getContext();

+

+	if(context)

+	{

+		context->setVertexAttrib(index, v);

+	}

 }

 

 void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint *params)

@@ -3020,7 +3084,18 @@
 void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor)

 {

 	TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);

-	UNIMPLEMENTED();

+

+	es2::Context *context = es2::getContext();

+

+	if(context)

+	{

+		if(index >= es2::MAX_VERTEX_ATTRIBS)

+		{

+			return error(GL_INVALID_VALUE);

+		}

+

+		context->setVertexAttribDivisor(index, divisor);

+	}

 }

 

 void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id)