Store EGL images in a namespace.

This allows validating the EGL image handles. It also ensures that on 64-bit
platforms the handles fit in 32-bit so they can be exchanged through 32-bit
applications (e.g. on a 32-bit virtual machine).

Change-Id: Ie02b00edd2cf7fa02b38316ee7d21c22eae720b5
Reviewed-on: https://swiftshader-review.googlesource.com/5500
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 0e8465e..f2e8555 100644
--- a/src/OpenGL/libEGL/Display.cpp
+++ b/src/OpenGL/libEGL/Display.cpp
@@ -21,6 +21,7 @@
 #include "main.h"
 #include "libEGL/Surface.h"
 #include "libEGL/Context.hpp"
+#include "common/Image.hpp"
 #include "common/debug.h"
 #include "Common/MutexLock.hpp"
 
@@ -196,6 +197,11 @@
 	{
 		destroyContext(*mContextSet.begin());
 	}
+
+	while(!mSharedImageNameSpace.empty())
+	{
+		destroySharedImage((EGLImageKHR)mSharedImageNameSpace.firstName());
+	}
 }
 
 bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
@@ -581,6 +587,33 @@
 	return nativeDisplay;
 }
 
+EGLImageKHR Display::createSharedImage(Image *image)
+{
+	return (EGLImageKHR)mSharedImageNameSpace.allocate(image);
+}
+
+bool Display::destroySharedImage(EGLImageKHR image)
+{
+	GLuint name = (GLuint)reinterpret_cast<intptr_t>(image);
+	Image *eglImage = mSharedImageNameSpace.find(name);
+
+	if(!eglImage)
+	{
+		return false;
+	}
+
+	eglImage->destroyShared();
+	mSharedImageNameSpace.remove(name);
+
+	return true;
+}
+
+Image *Display::getSharedImage(EGLImageKHR image)
+{
+	GLuint name = (GLuint)reinterpret_cast<intptr_t>(image);
+	return mSharedImageNameSpace.find(name);
+}
+
 sw::Format Display::getDisplayFormat() const
 {
 	#if defined(_WIN32)
diff --git a/src/OpenGL/libEGL/Display.h b/src/OpenGL/libEGL/Display.h
index 14d0fe3..456c1f2 100644
--- a/src/OpenGL/libEGL/Display.h
+++ b/src/OpenGL/libEGL/Display.h
@@ -21,6 +21,7 @@
 
 #include "Config.h"
 #include "Sync.hpp"
+#include "common/NameSpace.hpp"
 
 #include <set>
 
@@ -28,6 +29,7 @@
 {
 	class Surface;
 	class Context;
+	class Image;
 
 	const EGLDisplay PRIMARY_DISPLAY = (EGLDisplay)1;
 	const EGLDisplay HEADLESS_DISPLAY = (EGLDisplay)0xFACE1E55;
@@ -64,7 +66,10 @@
 		EGLint getMaxSwapInterval() const;
 
 		void *getNativeDisplay() const;
-		const char *getExtensionString() const;
+
+		EGLImageKHR createSharedImage(Image *image);
+		bool destroySharedImage(EGLImageKHR);
+		virtual Image *getSharedImage(EGLImageKHR name);
 
 	private:
 		explicit Display(void *nativeDisplay);
@@ -87,6 +92,8 @@
 
 		typedef std::set<FenceSync*> SyncSet;
 		SyncSet mSyncSet;
+
+		gl::NameSpace<Image> mSharedImageNameSpace;
 	};
 }
 
diff --git a/src/OpenGL/libEGL/libEGL.cbp b/src/OpenGL/libEGL/libEGL.cbp
index c3c209c..df54852 100644
--- a/src/OpenGL/libEGL/libEGL.cbp
+++ b/src/OpenGL/libEGL/libEGL.cbp
@@ -117,6 +117,7 @@
 		<Unit filename="../../Common/SharedLibrary.hpp" />
 		<Unit filename="../../Main/libX11.cpp" />
 		<Unit filename="../../Main/libX11.hpp" />
+		<Unit filename="../common/NameSpace.hpp" />
 		<Unit filename="../common/Object.cpp" />
 		<Unit filename="../common/Object.hpp" />
 		<Unit filename="../common/debug.cpp" />
diff --git a/src/OpenGL/libEGL/libEGL.cpp b/src/OpenGL/libEGL/libEGL.cpp
index 610d1c3..4d8a169 100644
--- a/src/OpenGL/libEGL/libEGL.cpp
+++ b/src/OpenGL/libEGL/libEGL.cpp
@@ -982,7 +982,10 @@
 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
 			}
 
-			return success(new AndroidNativeImage(nativeBuffer));
+			Image *image = new AndroidNativeImage(nativeBuffer);
+			EGLImageKHR eglImage = display->createSharedImage(image);
+
+			return success(eglImage);
 		}
 	#endif
 
@@ -1000,7 +1003,7 @@
 		return error(validationResult, EGL_NO_IMAGE_KHR);
 	}
 
-	egl::Image *image = context->createSharedImage(target, name, textureLevel);
+	Image *image = context->createSharedImage(target, name, textureLevel);
 
 	if(!image)
 	{
@@ -1012,7 +1015,9 @@
 		return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
 	}
 
-	return success((EGLImageKHR)image);
+	EGLImageKHR eglImage = display->createSharedImage(image);
+
+	return success(eglImage);
 }
 
 EGLBoolean DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
@@ -1026,14 +1031,11 @@
 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
 	}
 
-	if(!image)
+	if(!display->destroySharedImage(image))
 	{
 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
 	}
 
-	egl::Image *glImage = static_cast<egl::Image*>(image);
-	glImage->destroyShared();
-
 	return success(EGL_TRUE);
 }
 
diff --git a/src/OpenGL/libEGL/libEGL.vcxproj b/src/OpenGL/libEGL/libEGL.vcxproj
index 9b1b7bb..e2375fd 100644
--- a/src/OpenGL/libEGL/libEGL.vcxproj
+++ b/src/OpenGL/libEGL/libEGL.vcxproj
@@ -308,6 +308,7 @@
   <ItemGroup>

     <ClInclude Include="..\common\debug.h" />

     <ClInclude Include="..\common\Image.hpp" />

+    <ClInclude Include="..\common\NameSpace.hpp" />

     <ClInclude Include="..\common\Object.hpp" />

     <ClInclude Include="..\include\EGL\egl.h" />

     <ClInclude Include="..\include\EGL\eglext.h" />

diff --git a/src/OpenGL/libEGL/libEGL.vcxproj.filters b/src/OpenGL/libEGL/libEGL.vcxproj.filters
index 4400f20..3848f41 100644
--- a/src/OpenGL/libEGL/libEGL.vcxproj.filters
+++ b/src/OpenGL/libEGL/libEGL.vcxproj.filters
@@ -79,6 +79,9 @@
     <ClInclude Include="Sync.hpp">

       <Filter>Header Files</Filter>

     </ClInclude>

+    <ClInclude Include="..\common\NameSpace.hpp">

+      <Filter>Header Files</Filter>

+    </ClInclude>

   </ItemGroup>

   <ItemGroup>

     <ResourceCompile Include="libEGL.rc" />

diff --git a/src/OpenGL/libGLES_CM/Context.cpp b/src/OpenGL/libGLES_CM/Context.cpp
index ba34dab..0c9fed1 100644
--- a/src/OpenGL/libGLES_CM/Context.cpp
+++ b/src/OpenGL/libGLES_CM/Context.cpp
@@ -3158,7 +3158,12 @@
 	}
 	else UNREACHABLE(target);
 
-	return 0;
+	return nullptr;
+}
+
+egl::Image *Context::getSharedImage(GLeglImageOES image)
+{
+	return display->getSharedImage(image);
 }
 
 Device *Context::getDevice()
diff --git a/src/OpenGL/libGLES_CM/Context.h b/src/OpenGL/libGLES_CM/Context.h
index 2dee4fa..1bef6b6 100644
--- a/src/OpenGL/libGLES_CM/Context.h
+++ b/src/OpenGL/libGLES_CM/Context.h
@@ -509,6 +509,7 @@
 	virtual void bindTexImage(egl::Surface *surface);
 	virtual EGLenum validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel);
 	virtual egl::Image *createSharedImage(EGLenum target, GLuint name, GLuint textureLevel);
+	egl::Image *getSharedImage(GLeglImageOES image);
 
 	Device *getDevice();
 
diff --git a/src/OpenGL/libGLES_CM/Texture.cpp b/src/OpenGL/libGLES_CM/Texture.cpp
index b8817a0..4731635 100644
--- a/src/OpenGL/libGLES_CM/Texture.cpp
+++ b/src/OpenGL/libGLES_CM/Texture.cpp
@@ -614,7 +614,7 @@
 	renderTarget->release();
 }
 
-void Texture2D::setImage(egl::Image *sharedImage)
+void Texture2D::setSharedImage(egl::Image *sharedImage)
 {
 	sharedImage->addRef();
 
diff --git a/src/OpenGL/libGLES_CM/Texture.h b/src/OpenGL/libGLES_CM/Texture.h
index f28022d..ba0c4d5 100644
--- a/src/OpenGL/libGLES_CM/Texture.h
+++ b/src/OpenGL/libGLES_CM/Texture.h
@@ -150,7 +150,7 @@
 	void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
 	void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
 
-	void setImage(egl::Image *image);
+	void setSharedImage(egl::Image *image);
 
 	virtual bool isSamplerComplete() const;
 	virtual bool isCompressed(GLenum target, GLint level) const;
diff --git a/src/OpenGL/libGLES_CM/libGLES_CM.cpp b/src/OpenGL/libGLES_CM/libGLES_CM.cpp
index f9c5ab5..bd2de54 100644
--- a/src/OpenGL/libGLES_CM/libGLES_CM.cpp
+++ b/src/OpenGL/libGLES_CM/libGLES_CM.cpp
@@ -4623,16 +4623,11 @@
 		return error(GL_INVALID_ENUM);
 	}
 
-	if(!image)
-	{
-		return error(GL_INVALID_OPERATION);
-	}
-
 	es1::Context *context = es1::getContext();
 
 	if(context)
 	{
-		es1::Texture2D *texture = 0;
+		es1::Texture2D *texture = nullptr;
 
 		switch(target)
 		{
@@ -4646,9 +4641,14 @@
 			return error(GL_INVALID_OPERATION);
 		}
 
-		egl::Image *glImage = static_cast<egl::Image*>(image);
+		egl::Image *eglImage = context->getSharedImage(image);
 
-		texture->setImage(glImage);
+		if(!eglImage)
+		{
+			return error(GL_INVALID_OPERATION);
+		}
+
+		texture->setSharedImage(eglImage);
 	}
 }
 
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 8583f12..dd44f79 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -4263,7 +4263,12 @@
 	}
 	else UNREACHABLE(target);
 
-	return 0;
+	return nullptr;
+}
+
+egl::Image *Context::getSharedImage(GLeglImageOES image)
+{
+	return display->getSharedImage(image);
 }
 
 Device *Context::getDevice()
diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h
index 4750485..bf1f4ae 100644
--- a/src/OpenGL/libGLESv2/Context.h
+++ b/src/OpenGL/libGLESv2/Context.h
@@ -688,6 +688,7 @@
 	virtual void bindTexImage(egl::Surface *surface);
 	virtual EGLenum validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel);
 	virtual egl::Image *createSharedImage(EGLenum target, GLuint name, GLuint textureLevel);
+	egl::Image *getSharedImage(GLeglImageOES image);
 
 	Device *getDevice();
 
diff --git a/src/OpenGL/libGLESv2/Texture.cpp b/src/OpenGL/libGLESv2/Texture.cpp
index d1a0cde..50ab54b 100644
--- a/src/OpenGL/libGLESv2/Texture.cpp
+++ b/src/OpenGL/libGLESv2/Texture.cpp
@@ -810,7 +810,7 @@
 	renderTarget->release();
 }
 
-void Texture2D::setImage(egl::Image *sharedImage)
+void Texture2D::setSharedImage(egl::Image *sharedImage)
 {
 	if(sharedImage == image[0])
 	{
@@ -1775,7 +1775,7 @@
 	renderTarget->release();
 }
 
-void Texture3D::setImage(egl::Image *sharedImage)
+void Texture3D::setSharedImage(egl::Image *sharedImage)
 {
 	sharedImage->addRef();
 
diff --git a/src/OpenGL/libGLESv2/Texture.h b/src/OpenGL/libGLESv2/Texture.h
index 74452b0..a97f168 100644
--- a/src/OpenGL/libGLESv2/Texture.h
+++ b/src/OpenGL/libGLESv2/Texture.h
@@ -175,7 +175,7 @@
 	void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
 	virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
 
-	void setImage(egl::Image *image);
+	void setSharedImage(egl::Image *image);
 
 	virtual bool isSamplerComplete() const;
 	virtual bool isCompressed(GLenum target, GLint level) const;
@@ -295,7 +295,7 @@
 	void copyImage(GLint level, GLenum format, GLint x, GLint y, GLint z, GLsizei width, GLsizei height, GLsizei depth, Framebuffer *source);
 	void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
 
-	void setImage(egl::Image *image);
+	void setSharedImage(egl::Image *image);
 
 	virtual bool isSamplerComplete() const;
 	virtual bool isCompressed(GLenum target, GLint level) const;
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index ec21154..3e040b4 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -35,7 +35,7 @@
 
 #include <limits>
 
-#ifdef ANDROID
+#ifdef __ANDROID__
 #include <cutils/log.h>
 #endif
 
@@ -6682,16 +6682,11 @@
 		return error(GL_INVALID_ENUM);
 	}
 
-	if(!image)
-	{
-		return error(GL_INVALID_OPERATION);
-	}
-
 	es2::Context *context = es2::getContext();
 
 	if(context)
 	{
-		es2::Texture2D *texture = 0;
+		es2::Texture2D *texture = nullptr;
 
 		switch(target)
 		{
@@ -6705,9 +6700,14 @@
 			return error(GL_INVALID_OPERATION);
 		}
 
-		egl::Image *glImage = static_cast<egl::Image*>(image);
+		egl::Image *eglImage = context->getSharedImage(image);
 
-		texture->setImage(glImage);
+		if(!eglImage)
+		{
+			return error(GL_INVALID_OPERATION);
+		}
+
+		texture->setSharedImage(eglImage);
 	}
 }