Implementation of EGL_KHR_fence_sync.

Bug 21662268

Change-Id: Iefdc18303c42967ccc25fd6580851e05520dc2b9
Reviewed-on: https://swiftshader-review.googlesource.com/4071
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libEGL/Context.hpp b/src/OpenGL/libEGL/Context.hpp
index a19f983..35d948a 100644
--- a/src/OpenGL/libEGL/Context.hpp
+++ b/src/OpenGL/libEGL/Context.hpp
@@ -19,6 +19,7 @@
 	virtual EGLenum validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel) = 0;

 	virtual Image *createSharedImage(EGLenum target, GLuint name, GLuint textureLevel) = 0;

 	virtual int getClientVersion() const = 0;

+    virtual void finish() = 0;

 

 protected:

 	virtual ~Context() {};

diff --git a/src/OpenGL/libEGL/exports.map b/src/OpenGL/libEGL/exports.map
index 24e4fb7..e41ac1e 100644
--- a/src/OpenGL/libEGL/exports.map
+++ b/src/OpenGL/libEGL/exports.map
@@ -39,8 +39,12 @@
 	eglCreateImageKHR;

 	eglDestroyImageKHR;

 	eglGetPlatformDisplayEXT;

-    eglCreatePlatformWindowSurfaceEXT;

-    eglCreatePlatformPixmapSurfaceEXT;

+	eglCreatePlatformWindowSurfaceEXT;

+	eglCreatePlatformPixmapSurfaceEXT;

+	eglCreateSyncKHR;

+	eglDestroySyncKHR;

+	eglClientWaitSyncKHR;

+	eglGetSyncAttribKHR;

 

 	libEGL_swiftshader;

 

diff --git a/src/OpenGL/libEGL/libEGL.cpp b/src/OpenGL/libEGL/libEGL.cpp
index 491da27..0b79fec 100644
--- a/src/OpenGL/libEGL/libEGL.cpp
+++ b/src/OpenGL/libEGL/libEGL.cpp
@@ -177,6 +177,7 @@
 		return success("EGL_KHR_gl_texture_2D_image "

 		               "EGL_KHR_gl_texture_cubemap_image "

 		               "EGL_KHR_gl_renderbuffer_image "

+		               "EGL_KHR_fence_sync "

 		               "EGL_KHR_image_base "

 		               "EGL_ANDROID_framebuffer_target "

 		               "EGL_ANDROID_recordable");

@@ -428,12 +429,12 @@
 

 	switch(api)

 	{

-		case EGL_OPENGL_API:

-		case EGL_OPENVG_API:

+	case EGL_OPENGL_API:

+	case EGL_OPENVG_API:

 		return error(EGL_BAD_PARAMETER, EGL_FALSE);   // Not supported by this implementation

-		case EGL_OPENGL_ES_API:

+	case EGL_OPENGL_ES_API:

 		break;

-		default:

+	default:

 		return error(EGL_BAD_PARAMETER, EGL_FALSE);

 	}

 

@@ -960,6 +961,131 @@
 	return CreatePixmapSurface(dpy, config, (EGLNativePixmapType)native_pixmap, attrib_list);

 }

 

+class FenceSync

+{

+public:

+	explicit FenceSync(Context *context) : context(context)

+	{

+		status = EGL_UNSIGNALED_KHR;

+		context->addRef();

+	}

+

+	~FenceSync()

+	{

+		context->release();

+		context = nullptr;

+	}

+

+	void wait() const { return context->finish(); }

+	void signal() { status = EGL_SIGNALED_KHR; }

+	bool isSignaled() const { return status == EGL_SIGNALED_KHR; }

+

+private:

+	EGLint status;

+	Context *context;

+};

+

+EGLSyncKHR CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)

+{

+	TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLint *attrib_list=%p)", dpy, type, attrib_list);

+

+	egl::Display *display = static_cast<egl::Display*>(dpy);

+

+	if(!validateDisplay(display))

+	{

+		return error(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);

+	}

+

+	if(type != EGL_SYNC_FENCE_KHR)

+	{

+		return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);

+	}

+

+	if(attrib_list && attrib_list[0] != EGL_NONE)

+	{

+		return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);

+	}

+

+	egl::Context *context = static_cast<egl::Context*>(egl::getCurrentContext());

+

+	if(!validateContext(display, context))

+	{

+		return error(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);

+	}

+

+	return new FenceSync(context);

+}

+

+EGLBoolean DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)

+{

+	TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p)", dpy, sync);

+

+	egl::Display *display = static_cast<egl::Display*>(dpy);

+	FenceSync *eglSync = static_cast<FenceSync*>(sync);

+

+	if(!validateDisplay(display))

+	{

+		return error(EGL_BAD_DISPLAY, EGL_FALSE);

+	}

+

+	delete eglSync;

+

+	return EGL_TRUE;

+}

+

+EGLint ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)

+{

+	TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint flags = %x, EGLTimeKHR value = %llx)", dpy, sync, flags, timeout);

+

+	egl::Display *display = static_cast<egl::Display*>(dpy);

+	FenceSync *eglSync = static_cast<FenceSync*>(sync);

+

+	if(!validateDisplay(display))

+	{

+		return error(EGL_BAD_DISPLAY, EGL_FALSE);

+	}

+

+	(void)flags;

+	(void)timeout;

+

+	if(!eglSync->isSignaled())

+	{

+		eglSync->wait();

+		eglSync->signal();

+	}

+

+	return EGL_CONDITION_SATISFIED_KHR;

+}

+

+EGLBoolean GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)

+{

+	TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint attribute = %x, EGLint *value = %p)", dpy, sync, attribute, value);

+

+	egl::Display *display = static_cast<egl::Display*>(dpy);

+

+	if(!validateDisplay(display))

+	{

+		return error(EGL_BAD_DISPLAY, EGL_FALSE);

+	}

+

+	FenceSync *eglSync = static_cast<FenceSync*>(sync);

+

+	switch(attribute)

+	{

+	case EGL_SYNC_TYPE_KHR:

+		*value = EGL_SYNC_FENCE_KHR;

+		return EGL_TRUE;

+	case EGL_SYNC_STATUS_KHR:

+		*value = eglSync->isSignaled() ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR;

+		return EGL_TRUE;

+	case EGL_SYNC_CONDITION_KHR:

+		*value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;

+		return EGL_TRUE;

+	default:

+		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);

+	}

+}

+

 __eglMustCastToProperFunctionPointerType GetProcAddress(const char *procname)

 {

 	TRACE("(const char *procname = \"%s\")", procname);

@@ -979,6 +1105,10 @@
 		EXTENSION(eglGetPlatformDisplayEXT),

 		EXTENSION(eglCreatePlatformWindowSurfaceEXT),

 		EXTENSION(eglCreatePlatformPixmapSurfaceEXT),

+		EXTENSION(eglCreateSyncKHR),

+		EXTENSION(eglDestroySyncKHR),

+		EXTENSION(eglClientWaitSyncKHR),

+		EXTENSION(eglGetSyncAttribKHR),

 

 		#undef EXTENSION

 	};

diff --git a/src/OpenGL/libEGL/libEGL.def b/src/OpenGL/libEGL/libEGL.def
index 325d241..972d87c 100644
--- a/src/OpenGL/libEGL/libEGL.def
+++ b/src/OpenGL/libEGL/libEGL.def
@@ -41,5 +41,9 @@
 	eglGetPlatformDisplayEXT

     eglCreatePlatformWindowSurfaceEXT

     eglCreatePlatformPixmapSurfaceEXT

+	eglCreateSyncKHR

+	eglDestroySyncKHR

+	eglClientWaitSyncKHR

+	eglGetSyncAttribKHR

 

-	libEGL_swiftshader
\ No newline at end of file
+	libEGL_swiftshader

diff --git a/src/OpenGL/libEGL/libEGL.hpp b/src/OpenGL/libEGL/libEGL.hpp
index 33055ac..a2496a2 100644
--- a/src/OpenGL/libEGL/libEGL.hpp
+++ b/src/OpenGL/libEGL/libEGL.hpp
@@ -47,6 +47,10 @@
 	EGLImageKHR (*eglCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
 	EGLBoolean (*eglDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image);
 	__eglMustCastToProperFunctionPointerType (*eglGetProcAddress)(const char*);
+	EGLSyncKHR (*eglCreateSyncKHR)(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+	EGLBoolean (*eglDestroySyncKHR)(EGLDisplay dpy, EGLSyncKHR sync);
+	EGLint (*eglClientWaitSyncKHR)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+	EGLBoolean (*eglGetSyncAttribKHR)(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
 
 	// Functions that don't change the error code, for use by client APIs
 	egl::Context *(*clientGetCurrentContext)();
diff --git a/src/OpenGL/libEGL/main.cpp b/src/OpenGL/libEGL/main.cpp
index 40b53a4..c0690e7 100644
--- a/src/OpenGL/libEGL/main.cpp
+++ b/src/OpenGL/libEGL/main.cpp
@@ -359,6 +359,10 @@
 EGLDisplay GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list);

 EGLSurface CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);

 EGLSurface CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);

+EGLSyncKHR CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);

+EGLBoolean DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync);

+EGLint ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);

+EGLBoolean GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);

 __eglMustCastToProperFunctionPointerType GetProcAddress(const char *procname);

 }

 

@@ -554,6 +558,26 @@
 	return egl::CreatePlatformPixmapSurfaceEXT(dpy, config, native_pixmap, attrib_list);

 }

 

+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)

+{

+	return egl::CreateSyncKHR(dpy, type, attrib_list);

+}

+

+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)

+{

+	return egl::DestroySyncKHR(dpy, sync);

+}

+

+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)

+{

+	return egl::ClientWaitSyncKHR(dpy, sync, flags, timeout);

+}

+

+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)

+{

+	return egl::GetSyncAttribKHR(dpy, sync, attribute, value);

+}

+

 EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname)

 {

 	return egl::GetProcAddress(procname);

@@ -598,6 +622,10 @@
 	this->eglCreateImageKHR = egl::CreateImageKHR;

 	this->eglDestroyImageKHR = egl::DestroyImageKHR;

 	this->eglGetProcAddress = egl::GetProcAddress;

+	this->eglCreateSyncKHR = egl::CreateSyncKHR;

+	this->eglDestroySyncKHR = egl::DestroySyncKHR;

+	this->eglClientWaitSyncKHR = egl::ClientWaitSyncKHR;

+	this->eglGetSyncAttribKHR = egl::GetSyncAttribKHR;

 

 	this->clientGetCurrentContext = egl::getCurrentContext;

 	this->clientGetCurrentDisplay = egl::getCurrentDisplay;

diff --git a/src/OpenGL/libGLES_CM/Context.h b/src/OpenGL/libGLES_CM/Context.h
index 9c03e26..fc15144 100644
--- a/src/OpenGL/libGLES_CM/Context.h
+++ b/src/OpenGL/libGLES_CM/Context.h
@@ -294,6 +294,7 @@
 

 	virtual void makeCurrent(egl::Surface *surface);

 	virtual int getClientVersion() const;

+    virtual void finish();

 

     void markAllStateDirty();

 

@@ -486,7 +487,6 @@
     void drawArrays(GLenum mode, GLint first, GLsizei count);

     void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);

     void drawTexture(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height);

-    void finish();

     void flush();

 

     void recordInvalidEnum();

diff --git a/src/OpenGL/libGLES_CM/exports.map b/src/OpenGL/libGLES_CM/exports.map
index 22246b1..dcf548f 100644
--- a/src/OpenGL/libGLES_CM/exports.map
+++ b/src/OpenGL/libGLES_CM/exports.map
@@ -205,6 +205,10 @@
     glDrawTexxvOES;
     glDrawTexfOES;
     glDrawTexfvOES;
+    eglCreateSyncKHR;
+    eglDestroySyncKHR;
+    eglClientWaitSyncKHR;
+    eglGetSyncAttribKHR;
 
     libGLES_CM_swiftshader;
 
diff --git a/src/OpenGL/libGLES_CM/libGLES_CM.cpp b/src/OpenGL/libGLES_CM/libGLES_CM.cpp
index 1951dd9..ea1291d 100644
--- a/src/OpenGL/libGLES_CM/libGLES_CM.cpp
+++ b/src/OpenGL/libGLES_CM/libGLES_CM.cpp
@@ -2273,6 +2273,7 @@
 			"GL_OES_depth_texture "

 			"GL_OES_EGL_image "

 			"GL_OES_EGL_image_external "

+			"GL_OES_EGL_sync "

 			"GL_OES_element_index_uint "

 			"GL_OES_framebuffer_object "

 			"GL_OES_packed_depth_stencil "

diff --git a/src/OpenGL/libGLES_CM/libGLES_CM.def b/src/OpenGL/libGLES_CM/libGLES_CM.def
index 0864513..cf15c8b 100644
--- a/src/OpenGL/libGLES_CM/libGLES_CM.def
+++ b/src/OpenGL/libGLES_CM/libGLES_CM.def
@@ -204,7 +204,11 @@
     glDrawTexxvOES
     glDrawTexfOES
     glDrawTexfvOES
+    eglCreateSyncKHR
+    eglDestroySyncKHR
+    eglClientWaitSyncKHR
+    eglGetSyncAttribKHR
 
 	libGLES_CM_swiftshader
 
-	Register
\ No newline at end of file
+	Register
diff --git a/src/OpenGL/libGLES_CM/main.cpp b/src/OpenGL/libGLES_CM/main.cpp
index 9ec5656..38a50aa 100644
--- a/src/OpenGL/libGLES_CM/main.cpp
+++ b/src/OpenGL/libGLES_CM/main.cpp
@@ -521,6 +521,26 @@
 	return libEGL->eglGetProcAddress(procname);

 }

 

+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)

+{

+	return libEGL->eglCreateSyncKHR(dpy, type, attrib_list);

+}

+

+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)

+{

+	return libEGL->eglDestroySyncKHR(dpy, sync);

+}

+

+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)

+{

+	return libEGL->eglClientWaitSyncKHR(dpy, sync, flags, timeout);

+}

+

+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)

+{

+	return libEGL->eglGetSyncAttribKHR(dpy, sync, attribute, value);

+}

+

 GL_API void GL_APIENTRY glActiveTexture(GLenum texture)

 {

 	return es1::ActiveTexture(texture);

@@ -1593,4 +1613,4 @@
 	return &libGLES_CM;

 }

 

-LibEGL libEGL;
\ No newline at end of file
+LibEGL libEGL;

diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index db33e8d..9f79396 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -4485,6 +4485,7 @@
 		(const GLubyte*)"GL_OES_depth_texture_cube_map",

 		(const GLubyte*)"GL_OES_EGL_image",

 		(const GLubyte*)"GL_OES_EGL_image_external",

+		(const GLubyte*)"GL_OES_EGL_sync",

 		(const GLubyte*)"GL_OES_element_index_uint",

 		(const GLubyte*)"GL_OES_packed_depth_stencil",

 		(const GLubyte*)"GL_OES_rgb8_rgba8",