Uniform Buffers API implementation

Implemented the necessary functions
for the API level implementation of
glBindBufferBase and glBindBufferRange.
Also cleaned up the TransformFeedback
API functions a little for uniformity
with uniform buffers.

Change-Id: Iccc835f175d4e8bc4ee030343936714b7ff224ac
Reviewed-on: https://swiftshader-review.googlesource.com/3030
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/OpenGL/libGLESv2/Buffer.cpp b/src/OpenGL/libGLESv2/Buffer.cpp
index 42a1eea..0c164fa 100644
--- a/src/OpenGL/libGLESv2/Buffer.cpp
+++ b/src/OpenGL/libGLESv2/Buffer.cpp
@@ -64,7 +64,8 @@
 
 		if(data)
 		{
-			memcpy((void*)mContents->data(), data, size);
+			char *buffer = (char*)mContents->data();
+			memcpy(buffer + mOffset, data, size);
 		}
 	}
 }
diff --git a/src/OpenGL/libGLESv2/Buffer.h b/src/OpenGL/libGLESv2/Buffer.h
index b9acf8e..1f509ec 100644
--- a/src/OpenGL/libGLESv2/Buffer.h
+++ b/src/OpenGL/libGLESv2/Buffer.h
@@ -36,7 +36,7 @@
     void bufferData(const void *data, GLsizeiptr size, GLenum usage);

     void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);

 

-	const void *data() { return mContents ? mContents->data() : 0; }

+	const void *data() const { return mContents ? mContents->data() : 0; }

     size_t size() const { return mSize; }

     GLenum usage() const { return mUsage; }

 	bool isMapped() const { return mIsMapped; }

@@ -44,6 +44,8 @@
 	GLsizeiptr length() const { return mLength; }

 	GLbitfield access() const { return mAccess; }

 

+	void setOffset(GLintptr offset) { mOffset = offset; }

+	void setSize(size_t size) { mSize = size; }

 	void* mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access);

 	bool unmap();

 	void flushMappedRange(GLintptr offset, GLsizeiptr length) {}

diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 07543be..121e956 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -151,6 +151,7 @@
     bindReadFramebuffer(0);

     bindDrawFramebuffer(0);

     bindRenderbuffer(0);

+    bindGenericUniformBuffer(0);

     bindTransformFeedback(0);

 

 	mState.readFramebufferColorIndex = 0;

@@ -246,7 +247,7 @@
 	mState.copyWriteBuffer = NULL;

 	mState.pixelPackBuffer = NULL;

 	mState.pixelUnpackBuffer = NULL;

-	mState.uniformBuffer = NULL;

+	mState.genericUniformBuffer = NULL;

 	mState.renderbuffer = NULL;

 

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

@@ -1196,13 +1197,6 @@
 	}

 }

 

-void Context::bindUniformBuffer(GLuint buffer)

-{

-	mResourceManager->checkBufferAllocation(buffer);

-

-	mState.uniformBuffer = getBuffer(buffer);

-}

-

 void Context::bindTexture2D(GLuint texture)

 {

     mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);

@@ -1278,6 +1272,46 @@
 	return !!vertexArray;

 }

 

+void Context::bindGenericUniformBuffer(GLuint buffer)

+{

+	mResourceManager->checkBufferAllocation(buffer);

+

+	mState.genericUniformBuffer = getBuffer(buffer);

+}

+

+void Context::bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size)

+{

+	mResourceManager->checkBufferAllocation(buffer);

+

+	Buffer* bufferObject = getBuffer(buffer);

+	if(bufferObject)

+	{

+		bufferObject->setOffset(offset);

+		bufferObject->setSize(size);

+	}

+	mState.uniformBuffers[index] = bufferObject;

+}

+

+void Context::bindGenericTransformFeedbackBuffer(GLuint buffer)

+{

+	mResourceManager->checkBufferAllocation(buffer);

+

+	getTransformFeedback()->setGenericBuffer(getBuffer(buffer));

+}

+

+void Context::bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size)

+{

+	mResourceManager->checkBufferAllocation(buffer);

+

+	Buffer* bufferObject = getBuffer(buffer);

+	if(bufferObject)

+	{

+		bufferObject->setOffset(offset);

+		bufferObject->setSize(size);

+	}

+	getTransformFeedback()->setBuffer(index, bufferObject);

+}

+

 bool Context::bindTransformFeedback(GLuint id)

 {

 	if(!getTransformFeedback(id))

@@ -1566,9 +1600,9 @@
 	return mState.pixelUnpackBuffer;

 }

 

-Buffer *Context::getUniformBuffer() const

+Buffer *Context::getGenericUniformBuffer() const

 {

-	return mState.uniformBuffer;

+	return mState.genericUniformBuffer;

 }

 

 bool Context::getBuffer(GLenum target, es2::Buffer **buffer) const

@@ -1620,7 +1654,7 @@
 	case GL_UNIFORM_BUFFER:

 		if(clientVersion >= 3)

 		{

-			*buffer = getUniformBuffer();

+			*buffer = getGenericUniformBuffer();

 			break;

 		}

 		else return false;

@@ -2137,7 +2171,6 @@
 		*params = 16384;

 		break;

 	case GL_MAX_UNIFORM_BUFFER_BINDINGS: // integer, at least 36

-		UNIMPLEMENTED();

 		*params = IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS;

 		break;

 	case GL_MAX_VARYING_COMPONENTS: // integer, at least 60

@@ -2217,7 +2250,7 @@
 	case GL_UNIFORM_BUFFER_BINDING: // name, initially 0

 		if(clientVersion >= 3)

 		{

-			*params = mState.uniformBuffer.name();

+			*params = mState.genericUniformBuffer.name();

 		}

 		else

 		{

@@ -2225,15 +2258,27 @@
 		}

 		break;

 	case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: // integer, defaults to 1

-		UNIMPLEMENTED();

 		*params = IMPLEMENTATION_UNIFORM_BUFFER_OFFSET_ALIGNMENT;

 		break;

 	case GL_UNIFORM_BUFFER_SIZE: // indexed[n] 64-bit integer, initially 0

-		UNIMPLEMENTED();

-		*params = 0;

+		if(clientVersion >= 3)

+		{

+			*params = mState.genericUniformBuffer->size();

+		}

+		else

+		{

+			return false;

+		}

 		break;

 	case GL_UNIFORM_BUFFER_START: // indexed[n] 64-bit integer, initially 0

-		UNIMPLEMENTED();

+		if(clientVersion >= 3)

+		{

+			*params = mState.genericUniformBuffer->offset();

+		}

+		else

+		{

+			return false;

+		}

 		*params = 0;

 		break;

 	case GL_UNPACK_IMAGE_HEIGHT: // integer, initially 0

diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h
index 61d7f29..6ad4289 100644
--- a/src/OpenGL/libGLESv2/Context.h
+++ b/src/OpenGL/libGLESv2/Context.h
@@ -336,7 +336,8 @@
 	gl::BindingPointer<Buffer> copyWriteBuffer;

 	gl::BindingPointer<Buffer> pixelPackBuffer;

 	gl::BindingPointer<Buffer> pixelUnpackBuffer;

-	gl::BindingPointer<Buffer> uniformBuffer;

+	gl::BindingPointer<Buffer> genericUniformBuffer;

+	gl::BindingPointer<Buffer> uniformBuffers[MAX_UNIFORM_BUFFER_BINDINGS];

 

     GLuint readFramebuffer;

     GLuint drawFramebuffer;

@@ -517,7 +518,6 @@
 	void bindPixelPackBuffer(GLuint buffer);

 	void bindPixelUnpackBuffer(GLuint buffer);

 	void bindTransformFeedbackBuffer(GLuint buffer);

-	void bindUniformBuffer(GLuint buffer);

     void bindTexture2D(GLuint texture);

     void bindTextureCubeMap(GLuint texture);

     void bindTextureExternal(GLuint texture);

@@ -527,6 +527,10 @@
     void bindDrawFramebuffer(GLuint framebuffer);

     void bindRenderbuffer(GLuint renderbuffer);

 	bool bindVertexArray(GLuint array);

+	void bindGenericUniformBuffer(GLuint buffer);

+	void bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size);

+	void bindGenericTransformFeedbackBuffer(GLuint buffer);

+	void bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size);

 	bool bindTransformFeedback(GLuint transformFeedback);

 	bool bindSampler(GLuint unit, GLuint sampler);

     void useProgram(GLuint program);

@@ -563,7 +567,7 @@
 	Buffer *getCopyWriteBuffer() const;

 	Buffer *getPixelPackBuffer() const;

 	Buffer *getPixelUnpackBuffer() const;

-	Buffer *getUniformBuffer() const;

+	Buffer *getGenericUniformBuffer() const;

 	bool getBuffer(GLenum target, es2::Buffer **buffer) const;

 	Program *getCurrentProgram() const;

 	Texture2D *getTexture2D() const;

diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index c6c7ef8..6507d9d 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -469,7 +469,7 @@
 		case GL_UNIFORM_BUFFER:

 			if(clientVersion >= 3)

 			{

-				context->bindUniformBuffer(buffer);

+				context->bindGenericUniformBuffer(buffer);

 				return;

 			}

 			else return error(GL_INVALID_ENUM);

diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index 0c78ced..5832bef 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -1886,11 +1886,8 @@
 			{

 				return error(GL_INVALID_VALUE);

 			}

-			else

-			{

-				es2::TransformFeedback* transformFeedback = context->getTransformFeedback();

-				transformFeedback->setBuffer(index, context->getBuffer(buffer), offset, size);

-			}

+			context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size);

+			context->bindGenericTransformFeedbackBuffer(buffer);

 			break;

 		case GL_UNIFORM_BUFFER:

 			if(index >= es2::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS)

@@ -1901,7 +1898,8 @@
 			{

 				return error(GL_INVALID_VALUE);

 			}

-			UNIMPLEMENTED();

+			context->bindIndexedUniformBuffer(buffer, index, offset, size);

+			context->bindGenericUniformBuffer(buffer);

 			break;

 		default:

 			return error(GL_INVALID_ENUM);

@@ -1925,18 +1923,16 @@
 			{

 				return error(GL_INVALID_VALUE);

 			}

-			else

-			{

-				es2::TransformFeedback* transformFeedback = context->getTransformFeedback();

-				transformFeedback->setBuffer(index, context->getBuffer(buffer));

-			}

+			context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0);

+			context->bindGenericTransformFeedbackBuffer(buffer);

 			break;

 		case GL_UNIFORM_BUFFER:

 			if(index >= es2::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS)

 			{

 				return error(GL_INVALID_VALUE);

 			}

-			UNIMPLEMENTED();

+			context->bindIndexedUniformBuffer(buffer, index, 0, 0);

+			context->bindGenericUniformBuffer(buffer);

 			break;

 		default:

 			return error(GL_INVALID_ENUM);

@@ -3227,7 +3223,7 @@
 			UNIMPLEMENTED();

 			break;

 		case GL_UNIFORM_BUFFER:

-			buffer = context->getUniformBuffer();

+			buffer = context->getGenericUniformBuffer();

 			break;

 		default:

 			return error(GL_INVALID_ENUM);