Buffer mapping state validation fixes

- Can't update an already mapped bufferData
- Can't unmap an unmapped buffer
- Disallowed illegal mapBufferRange flag combinations
- Can't flush buffer if not mapped

Change-Id: I7013f63e5db64c1016f9ce50a43d0629f0a2950e
Reviewed-on: https://swiftshader-review.googlesource.com/13788
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index d268656..8b9116c 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -560,7 +560,7 @@
 			GLuint index = (src - GL_COLOR_ATTACHMENT0);
 			if(index >= MAX_COLOR_ATTACHMENTS)
 			{
-				return error(GL_INVALID_ENUM);
+				return error(GL_INVALID_OPERATION);
 			}
 			if(readFramebufferName == 0)
 			{
@@ -570,7 +570,7 @@
 		}
 			break;
 		default:
-			error(GL_INVALID_ENUM);
+			return error(GL_INVALID_ENUM);
 		}
 	}
 }
@@ -1096,6 +1096,12 @@
 			return error(GL_INVALID_OPERATION, GL_TRUE);
 		}
 
+		if(!buffer->isMapped())
+		{
+			// Already unmapped
+			return error(GL_INVALID_OPERATION, GL_TRUE);
+		}
+
 		return buffer->unmap() ? GL_TRUE : GL_FALSE;
 	}
 
@@ -1574,6 +1580,27 @@
 	TRACE("(GLenum target = 0x%X,  GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = %X)",
 	      target, offset, length, access);
 
+	if((offset < 0) || (length < 0))
+	{
+		return error(GL_INVALID_VALUE, nullptr);
+	}
+
+	if(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)))
+	{
+		// Must be able to read or write the buffer
+		return error(GL_INVALID_OPERATION, nullptr);
+	}
+	else if((access & GL_MAP_READ_BIT) && (access & (GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT)))
+	{
+		// GL_MAP_INVALIDATE_RANGE_BIT, GL_MAP_INVALIDATE_BUFFER_BIT and GL_MAP_UNSYNCHRONIZED_BIT can't be used with GL_MAP_READ_BIT
+		return error(GL_INVALID_OPERATION, nullptr);
+	}
+	else if((!(access & GL_MAP_WRITE_BIT)) && (access & GL_MAP_FLUSH_EXPLICIT_BIT))
+	{
+		// GL_MAP_FLUSH_EXPLICIT_BIT can't be used without GL_MAP_WRITE_BIT
+		return error(GL_INVALID_OPERATION, nullptr);
+	}
+
 	es2::Context *context = es2::getContext();
 
 	if(context)
@@ -1597,9 +1624,9 @@
 		}
 
 		GLsizeiptr bufferSize = buffer->size();
-		if((offset < 0) || (length < 0) || ((offset + length) > bufferSize))
+		if((offset + length) > bufferSize)
 		{
-			error(GL_INVALID_VALUE);
+			return error(GL_INVALID_VALUE, nullptr);
 		}
 
 		if((access & ~(GL_MAP_READ_BIT |
@@ -1609,7 +1636,7 @@
 		               GL_MAP_FLUSH_EXPLICIT_BIT |
 		               GL_MAP_UNSYNCHRONIZED_BIT)) != 0)
 		{
-			error(GL_INVALID_VALUE);
+			return error(GL_INVALID_VALUE, nullptr);
 		}
 
 		return buffer->mapRange(offset, length, access);
@@ -1623,6 +1650,11 @@
 	TRACE("(GLenum target = 0x%X,  GLintptr offset = %d, GLsizeiptr length = %d)",
 	      target, offset, length);
 
+	if((offset < 0) || (length < 0))
+	{
+		return error(GL_INVALID_VALUE);
+	}
+
 	es2::Context *context = es2::getContext();
 
 	if(context)
@@ -1639,10 +1671,22 @@
 			return error(GL_INVALID_OPERATION);
 		}
 
-		GLsizeiptr bufferSize = buffer->size();
-		if((offset < 0) || (length < 0) || ((offset + length) > bufferSize))
+		if(!buffer->isMapped())
 		{
-			error(GL_INVALID_VALUE);
+			// Buffer must be mapped
+			return error(GL_INVALID_OPERATION);
+		}
+
+		GLsizeiptr bufferSize = buffer->length();
+		if((offset + length) > bufferSize)
+		{
+			return error(GL_INVALID_VALUE);
+		}
+
+		if(!(buffer->usage() & GL_MAP_FLUSH_EXPLICIT_BIT))
+		{
+			// Flush must be explicitly allowed
+			return error(GL_INVALID_OPERATION);
 		}
 
 		buffer->flushMappedRange(offset, length);
@@ -3014,7 +3058,7 @@
 
 	if((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
 	{
-		error(GL_INVALID_VALUE);
+		return error(GL_INVALID_VALUE, GL_FALSE);
 	}
 
 	es2::Context *context = es2::getContext();