Fix validating sync object pointers.

The spec states that "If <sync> is not a valid sync object for <dpy>,
EGL_FALSE is returned and an EGL_BAD_PARAMETER error is generated."

Change-Id: I4bbd2ddfefd7baba9c301decb644bfb545e66f01
Reviewed-on: https://swiftshader-review.googlesource.com/5290
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/Display.cpp b/src/OpenGL/libEGL/Display.cpp
index cbef7fd..06fb58d 100644
--- a/src/OpenGL/libEGL/Display.cpp
+++ b/src/OpenGL/libEGL/Display.cpp
@@ -444,6 +444,15 @@
     return success(context);
 }
 
+EGLSyncKHR Display::createSync(Context *context)
+{
+	FenceSync *fenceSync = new egl::FenceSync(context);
+
+	mSyncSet.insert(fenceSync);
+
+	return fenceSync;
+}
+
 void Display::destroySurface(egl::Surface *surface)
 {
 	surface->release();
@@ -473,6 +482,13 @@
 	}
 }
 
+void Display::destroySync(FenceSync *sync)
+{
+	mSyncSet.erase(sync);
+
+	delete sync;
+}
+
 bool Display::isInitialized() const
 {
     return mConfigSet.size() > 0;
@@ -480,7 +496,7 @@
 
 bool Display::isValidConfig(EGLConfig config)
 {
-    return mConfigSet.get(config) != NULL;
+    return mConfigSet.get(config) != nullptr;
 }
 
 bool Display::isValidContext(egl::Context *context)
@@ -542,6 +558,11 @@
     return false;
 }
 
+bool Display::isValidSync(FenceSync *sync)
+{
+	return mSyncSet.find(sync) != mSyncSet.end();
+}
+
 EGLint Display::getMinSwapInterval() const
 {
     return mMinSwapInterval;
diff --git a/src/OpenGL/libEGL/Display.h b/src/OpenGL/libEGL/Display.h
index d08b9a4..3864770 100644
--- a/src/OpenGL/libEGL/Display.h
+++ b/src/OpenGL/libEGL/Display.h
@@ -17,6 +17,7 @@
 #define INCLUDE_DISPLAY_H_

 

 #include "Config.h"

+#include "Sync.hpp"

 

 #include <set>

 

@@ -42,9 +43,11 @@
 		EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList);

 		EGLSurface createPBufferSurface(EGLConfig config, const EGLint *attribList);

 		EGLContext createContext(EGLConfig configHandle, const Context *shareContext, EGLint clientVersion);

+		EGLSyncKHR createSync(Context *context);

 

 		void destroySurface(Surface *surface);

 		void destroyContext(Context *context);

+		void destroySync(FenceSync *sync);

 

 		bool isInitialized() const;

 		bool isValidConfig(EGLConfig config);

@@ -52,6 +55,7 @@
 		bool isValidSurface(Surface *surface);

 		bool isValidWindow(EGLNativeWindowType window);

 		bool hasExistingWindowSurface(EGLNativeWindowType window);

+		bool isValidSync(FenceSync *sync);

 

 		EGLint getMinSwapInterval() const;

 		EGLint getMaxSwapInterval() const;

@@ -77,6 +81,9 @@
 

 		typedef std::set<Context*> ContextSet;

 		ContextSet mContextSet;

+

+		typedef std::set<FenceSync*> SyncSet;

+		SyncSet mSyncSet;

 	};

 }

 

diff --git a/src/OpenGL/libEGL/Sync.hpp b/src/OpenGL/libEGL/Sync.hpp
new file mode 100644
index 0000000..c1756ec
--- /dev/null
+++ b/src/OpenGL/libEGL/Sync.hpp
@@ -0,0 +1,50 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Sync.hpp: Defines sync objects for the EGL_KHR_fence_sync extension.

+

+#ifndef LIBEGL_SYNC_H_

+#define LIBEGL_SYNC_H_

+

+#include "Context.hpp"

+

+#include <EGL/eglext.h>

+

+namespace egl

+{

+

+class FenceSync

+{

+public:

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

+	{

+		status = EGL_UNSIGNALED_KHR;

+		context->addRef();

+	}

+

+	~FenceSync()

+	{

+		context->release();

+		context = nullptr;

+	}

+

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

+	void signal() { status = EGL_SIGNALED_KHR; }

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

+

+private:

+	EGLint status;

+	Context *context;

+};

+

+}

+

+#endif   // LIBEGL_SYNC_H_

diff --git a/src/OpenGL/libEGL/libEGL.cpp b/src/OpenGL/libEGL/libEGL.cpp
index d67d2cc..e54c60f 100644
--- a/src/OpenGL/libEGL/libEGL.cpp
+++ b/src/OpenGL/libEGL/libEGL.cpp
@@ -1017,30 +1017,6 @@
 	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() { context->finish(); signal(); }

-	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);

@@ -1069,7 +1045,9 @@
 		return error(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);

 	}

 

-	return success(new FenceSync(context));

+	EGLSyncKHR sync = display->createSync(context);

+

+	return success(sync);

 }

 

 EGLBoolean DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)

@@ -1084,7 +1062,12 @@
 		return error(EGL_BAD_DISPLAY, EGL_FALSE);

 	}

 

-	delete eglSync;

+	if(!display->isValidSync(eglSync))

+	{

+		return error(EGL_BAD_PARAMETER, EGL_FALSE);

+	}

+

+	display->destroySync(eglSync);

 

 	return success(EGL_TRUE);

 }

@@ -1101,6 +1084,11 @@
 		return error(EGL_BAD_DISPLAY, EGL_FALSE);

 	}

 

+	if(!display->isValidSync(eglSync))

+	{

+		return error(EGL_BAD_PARAMETER, EGL_FALSE);

+	}

+

 	(void)flags;

 	(void)timeout;

 

@@ -1117,13 +1105,17 @@
 	TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint attribute = %x, EGLint *value = %p)", dpy, sync, attribute, value);

 

 	egl::Display *display = egl::Display::get(dpy);

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

 

 	if(!validateDisplay(display))

 	{

 		return error(EGL_BAD_DISPLAY, EGL_FALSE);

 	}

 

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

+	if(!display->isValidSync(eglSync))

+	{

+		return error(EGL_BAD_PARAMETER, EGL_FALSE);

+	}

 

 	switch(attribute)

 	{

diff --git a/src/OpenGL/libEGL/libEGL.vcxproj b/src/OpenGL/libEGL/libEGL.vcxproj
index a01f28c..501d7a1 100644
--- a/src/OpenGL/libEGL/libEGL.vcxproj
+++ b/src/OpenGL/libEGL/libEGL.vcxproj
@@ -319,6 +319,7 @@
     <ClInclude Include="main.h" />

     <ClInclude Include="resource.h" />

     <ClInclude Include="Surface.h" />

+    <ClInclude Include="Sync.hpp" />

     <ClInclude Include="Texture.hpp" />

   </ItemGroup>

   <ItemGroup>

diff --git a/src/OpenGL/libEGL/libEGL.vcxproj.filters b/src/OpenGL/libEGL/libEGL.vcxproj.filters
index 6ec4c50..4400f20 100644
--- a/src/OpenGL/libEGL/libEGL.vcxproj.filters
+++ b/src/OpenGL/libEGL/libEGL.vcxproj.filters
@@ -76,6 +76,9 @@
     <ClInclude Include="..\common\Image.hpp">

       <Filter>Header Files</Filter>

     </ClInclude>

+    <ClInclude Include="Sync.hpp">

+      <Filter>Header Files</Filter>

+    </ClInclude>

   </ItemGroup>

   <ItemGroup>

     <ResourceCompile Include="libEGL.rc" />