glGetSynciv implementation

Added the missing part of the FenceSync object
implementation based on the assumption that all
fence operations are always signaled before
calling any sync related wait functions.

Passes all related dEQP tests.

Change-Id: I2fd2ac160dfd1250f55240fc3f696f00579d12d4
Reviewed-on: https://swiftshader-review.googlesource.com/8855
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 27d608b..b1faa01 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -2157,7 +2157,6 @@
 			*params = MAX_PROGRAM_TEXEL_OFFSET;
 			return true;
 		case GL_MAX_SERVER_WAIT_TIMEOUT:
-			UNIMPLEMENTED();
 			*params = 0;
 			return true;
 		case GL_MAX_TEXTURE_LOD_BIAS:
diff --git a/src/OpenGL/libGLESv2/Fence.cpp b/src/OpenGL/libGLESv2/Fence.cpp
index 17a2228..fce4c52 100644
--- a/src/OpenGL/libGLESv2/Fence.cpp
+++ b/src/OpenGL/libGLESv2/Fence.cpp
@@ -125,11 +125,49 @@
 
 GLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout)
 {
-	return GL_TRUE;
+	// The current assumtion is that no matter where the fence is placed, it is
+	// done by the time it is tested, which is similar to Context::flush(), since
+	// we don't queue anything without processing it as fast as possible.
+	return GL_ALREADY_SIGNALED;
 }
 
 void FenceSync::serverWait(GLbitfield flags, GLuint64 timeout)
 {
 }
 
+void FenceSync::getSynciv(GLenum pname, GLsizei *length, GLint *values)
+{
+	switch(pname)
+	{
+	case GL_OBJECT_TYPE:
+		values[0] = GL_SYNC_FENCE;
+		if(length) {
+			*length = 1;
+		}
+		break;
+	case GL_SYNC_STATUS:
+		// The current assumtion is that no matter where the fence is placed, it is
+		// done by the time it is tested, which is similar to Context::flush(), since
+		// we don't queue anything without processing it as fast as possible.
+		values[0] = GL_SIGNALED;
+		if(length) {
+			*length = 1;
+		}
+		break;
+	case GL_SYNC_CONDITION:
+		values[0] = GL_SYNC_GPU_COMMANDS_COMPLETE;
+		if(length) {
+			*length = 1;
+		}
+		break;
+	case GL_SYNC_FLAGS:
+		if(length) {
+			*length = 0;
+		}
+		break;
+	default:
+		return error(GL_INVALID_ENUM);
+	}
+}
+
 }
diff --git a/src/OpenGL/libGLESv2/Fence.h b/src/OpenGL/libGLESv2/Fence.h
index 4a1d8b5..6ccb7d0 100644
--- a/src/OpenGL/libGLESv2/Fence.h
+++ b/src/OpenGL/libGLESv2/Fence.h
@@ -49,6 +49,7 @@
 
 	GLenum clientWait(GLbitfield flags, GLuint64 timeout);
 	void serverWait(GLbitfield flags, GLuint64 timeout);
+	void getSynciv(GLenum pname, GLsizei *length, GLint *values);
 
 	GLenum getCondition() const { return mCondition; }
 	GLbitfield getFlags() const { return mFlags; }
diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index b91a451..bba2179 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -3233,7 +3233,18 @@
 		return error(GL_INVALID_VALUE);
 	}
 
-	UNIMPLEMENTED();
+	es2::Context *context = es2::getContext();
+
+	if(context)
+	{
+		es2::FenceSync *fenceSyncObject = context->getFenceSync(sync);
+		if(!fenceSyncObject)
+		{
+			return error(GL_INVALID_VALUE);
+		}
+
+		fenceSyncObject->getSynciv(pname, length, values);
+	}
 }
 
 GL_APICALL void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64 *data)