Access library dependencies through a single object.

Bug 18752589

Change-Id: I93155cead50b30faa876023f9ed00f60b7c9e34e
Reviewed-on: https://swiftshader-review.googlesource.com/2831
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Greg Hartman <ghartman@google.com>
Tested-by: Greg Hartman <ghartman@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 983914e..e5225ce 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -300,7 +300,7 @@
     markAllStateDirty();

 }

 

-EGLint Context::getClientVersion()

+EGLint Context::getClientVersion() const

 {

 	return clientVersion;

 }

@@ -4125,11 +4125,8 @@
 

 }

 

-// Exported functions for use by EGL

-extern "C"

+egl::Context *es2CreateContext(const egl::Config *config, const egl::Context *shareContext, int clientVersion)

 {

-	es2::Context *glCreateContext(const egl::Config *config, const es2::Context *shareContext, int clientVersion)

-	{

-		return new es2::Context(config, shareContext, clientVersion);

-	}

+	ASSERT(!shareContext || shareContext->getClientVersion() == clientVersion);   // Should be checked by eglCreateContext

+	return new es2::Context(config, static_cast<const es2::Context*>(shareContext), clientVersion);

 }

diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h
index 4da5a75..995015a 100644
--- a/src/OpenGL/libGLESv2/Context.h
+++ b/src/OpenGL/libGLESv2/Context.h
@@ -353,7 +353,7 @@
     Context(const egl::Config *config, const Context *shareContext, EGLint clientVersion);

 

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

-	virtual EGLint getClientVersion();

+	virtual EGLint getClientVersion() const;

 

     void markAllStateDirty();

 

diff --git a/src/OpenGL/libGLESv2/Texture.cpp b/src/OpenGL/libGLESv2/Texture.cpp
index 3d84215..a9002a2 100644
--- a/src/OpenGL/libGLESv2/Texture.cpp
+++ b/src/OpenGL/libGLESv2/Texture.cpp
@@ -1797,60 +1797,57 @@
 

 }

 

-// Exported functions for use by EGL

-extern "C"

+egl::Image *createBackBuffer(int width, int height, const egl::Config *config)

 {

-	egl::Image *createBackBuffer(int width, int height, const egl::Config *config)

+	if(config)

 	{

-		if(config)

-		{

-			return new es2::Image(0, width, height, config->mAlphaSize ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE);

-		}

+		return new es2::Image(0, width, height, config->mAlphaSize ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE);

+	}

 

+	return 0;

+}

+

+egl::Image *createDepthStencil(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)

+{

+	if(width == 0 || height == 0 || height > OUTLINE_RESOLUTION)

+	{

+		ERR("Invalid parameters");

+		return 0;

+	}

+		

+	bool lockable = true;

+

+	switch(format)

+	{

+//	case sw::FORMAT_D15S1:

+	case sw::FORMAT_D24S8:

+	case sw::FORMAT_D24X8:

+//	case sw::FORMAT_D24X4S4:

+	case sw::FORMAT_D24FS8:

+	case sw::FORMAT_D32:

+	case sw::FORMAT_D16:

+		lockable = false;

+		break;

+//	case sw::FORMAT_S8_LOCKABLE:

+//	case sw::FORMAT_D16_LOCKABLE:

+	case sw::FORMAT_D32F_LOCKABLE:

+//	case sw::FORMAT_D32_LOCKABLE:

+	case sw::FORMAT_DF24S8:

+	case sw::FORMAT_DF16S8:

+		lockable = true;

+		break;

+	default:

+		UNREACHABLE();

+	}

+

+	es2::Image *surface = new es2::Image(0, width, height, format, multiSampleDepth, lockable, true);

+

+	if(!surface)

+	{

+		ERR("Out of memory");

 		return 0;

 	}

 

-	egl::Image *createDepthStencil(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)

-	{

-		if(width == 0 || height == 0 || height > OUTLINE_RESOLUTION)

-		{

-			ERR("Invalid parameters");

-			return 0;

-		}

-		

-		bool lockable = true;

-

-		switch(format)

-		{

-	//	case sw::FORMAT_D15S1:

-		case sw::FORMAT_D24S8:

-		case sw::FORMAT_D24X8:

-	//	case sw::FORMAT_D24X4S4:

-		case sw::FORMAT_D24FS8:

-		case sw::FORMAT_D32:

-		case sw::FORMAT_D16:

-			lockable = false;

-			break;

-	//	case sw::FORMAT_S8_LOCKABLE:

-	//	case sw::FORMAT_D16_LOCKABLE:

-		case sw::FORMAT_D32F_LOCKABLE:

-	//	case sw::FORMAT_D32_LOCKABLE:

-		case sw::FORMAT_DF24S8:

-		case sw::FORMAT_DF16S8:

-			lockable = true;

-			break;

-		default:

-			UNREACHABLE();

-		}

-

-		es2::Image *surface = new es2::Image(0, width, height, format, multiSampleDepth, lockable, true);

-

-		if(!surface)

-		{

-			ERR("Out of memory");

-			return 0;

-		}

-

-		return surface;

-	}

+	return surface;

 }

+

diff --git a/src/OpenGL/libGLESv2/exports.map b/src/OpenGL/libGLESv2/exports.map
index cab96a0..4670a61 100644
--- a/src/OpenGL/libGLESv2/exports.map
+++ b/src/OpenGL/libGLESv2/exports.map
@@ -168,13 +168,7 @@
 	glEGLImageTargetTexture2DOES;
 	glEGLImageTargetRenderbufferStorageOES;
 
-    # EGL dependencies
-    glCreateContext;
-    glGetProcAddress;
-
-	createFrameBuffer;
-	createBackBuffer;
-	createDepthStencil;
+    libGLESv2exports;
 
 	Register;
 
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cbp b/src/OpenGL/libGLESv2/libGLESv2.cbp
index 4615472..18b8ab6 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cbp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cbp
@@ -372,6 +372,7 @@
 		<Unit filename="VertexDataManager.h" />
 		<Unit filename="exports.map" />
 		<Unit filename="libGLESv2.cpp" />
+		<Unit filename="libGLESv2.hpp" />
 		<Unit filename="main.cpp" />
 		<Unit filename="main.h" />
 		<Unit filename="mathutil.h" />
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index 13f6f6d..3277120 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -37,6 +37,8 @@
 #include <cutils/log.h>

 #endif

 

+using namespace es2;

+

 typedef std::pair<GLenum, GLenum> InternalFormatTypePair;

 typedef std::map<InternalFormatTypePair, GLenum> FormatMap;

 

@@ -6690,8 +6692,7 @@
 {

 	if(egl::getClientVersion() == 1)

 	{

-		static auto glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)es1::getProcAddress("glEGLImageTargetTexture2DOES");

-		return glEGLImageTargetTexture2DOES(target, image);

+		return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);

 	}

 

 	TRACE("(GLenum target = 0x%X, GLeglImageOES image = 0x%0.8p)", target, image);

@@ -6741,7 +6742,7 @@
 	UNIMPLEMENTED();

 }

 

-__eglMustCastToProperFunctionPointerType glGetProcAddress(const char *procname)

+__eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)

 {

 	struct Extension

 	{

diff --git a/src/OpenGL/libGLESv2/libGLESv2.def b/src/OpenGL/libGLESv2/libGLESv2.def
index 9b42766..0ce826c 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.def
+++ b/src/OpenGL/libGLESv2/libGLESv2.def
@@ -274,12 +274,6 @@
     glTexStorage3D                  @304
     glGetInternalformativ           @308
 
-    ; EGL dependencies
-    glCreateContext
-    glGetProcAddress
-
-	createFrameBuffer
-	createBackBuffer
-	createDepthStencil
+    libGLESv2exports
 
 	Register
\ No newline at end of file
diff --git a/src/OpenGL/libGLESv2/libGLESv2.hpp b/src/OpenGL/libGLESv2/libGLESv2.hpp
new file mode 100644
index 0000000..15f6528
--- /dev/null
+++ b/src/OpenGL/libGLESv2/libGLESv2.hpp
@@ -0,0 +1,93 @@
+#ifndef libGLESv2_hpp
+#define libGLESv2_hpp
+
+#define GL_API
+#include <GLES/gl.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GLES/glext.h>
+#define EGLAPI
+#include <EGL/egl.h>
+
+#include "Common/SharedLibrary.hpp"
+
+namespace sw
+{
+class FrameBuffer;
+enum Format : unsigned char;
+}
+
+namespace egl
+{
+class Context;
+class Image;
+class Config;
+}
+
+class LibGLESv2exports
+{
+public:
+	LibGLESv2exports();
+
+	egl::Context *(*es2CreateContext)(const egl::Config *config, const egl::Context *shareContext, int clientVersion);
+	__eglMustCastToProperFunctionPointerType (*es2GetProcAddress)(const char *procname);
+	egl::Image *(*createBackBuffer)(int width, int height, const egl::Config *config);
+	egl::Image *(*createDepthStencil)(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard);
+	sw::FrameBuffer *(*createFrameBuffer)(EGLNativeDisplayType display, EGLNativeWindowType window, int width, int height);
+};
+
+class LibGLESv2
+{
+public:
+	LibGLESv2()
+	{
+		libGLESv2 = nullptr;
+		libGLESv2exports = nullptr;
+	}
+
+	~LibGLESv2()
+	{
+		freeLibrary(libGLESv2);
+	}
+
+	operator bool()
+	{
+		return loadExports();
+	}
+
+	LibGLESv2exports *operator->()
+	{
+		return loadExports();
+	}
+
+private:
+	LibGLESv2exports *loadExports()
+	{
+		if(!libGLESv2)
+		{
+			#if defined(_WIN32)
+			const char *libGLESv2_lib[] = {"libGLESv2.dll", "libGLES_V2_translator.dll"};
+			#elif defined(__ANDROID__)
+			const char *libGLESv2_lib[] = {"/vendor/lib/egl/libGLESv2_swiftshader.so"};
+			#elif defined(__LP64__)
+			const char *libGLESv2_lib[] = {"lib64GLES_V2_translator.so", "libGLESv2.so.2", "libGLESv2.so"};
+			#else
+			const char *libGLESv2_lib[] = {"libGLES_V2_translator.so", "libGLESv2.so.2", "libGLESv2.so"};
+			#endif
+
+			libGLESv2 = loadLibrary(libGLESv2_lib);
+
+			if(libGLESv2)
+			{
+				auto libGLESv2exportsProc = (LibGLESv2exports *(*)())getProcAddress(libGLESv2, "libGLESv2exports");
+				libGLESv2exports = libGLESv2exportsProc();
+			}
+		}
+
+		return libGLESv2exports;
+	}
+
+	void *libGLESv2;
+	LibGLESv2exports *libGLESv2exports;
+};
+
+#endif   // libGLESv2_hpp
diff --git a/src/OpenGL/libGLESv2/libGLESv2.vcxproj b/src/OpenGL/libGLESv2/libGLESv2.vcxproj
index f47b891..7bba1e6 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.vcxproj
+++ b/src/OpenGL/libGLESv2/libGLESv2.vcxproj
@@ -355,6 +355,7 @@
     <ClInclude Include="Framebuffer.h" />

     <ClInclude Include="Image.hpp" />

     <ClInclude Include="IndexDataManager.h" />

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

     <ClInclude Include="main.h" />

     <ClInclude Include="mathutil.h" />

     <ClInclude Include="Program.h" />

diff --git a/src/OpenGL/libGLESv2/libGLESv2.vcxproj.filters b/src/OpenGL/libGLESv2/libGLESv2.vcxproj.filters
index 683b67a..fa96948 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.vcxproj.filters
+++ b/src/OpenGL/libGLESv2/libGLESv2.vcxproj.filters
@@ -160,6 +160,9 @@
     <ClInclude Include="VertexArray.h">

       <Filter>Header Files</Filter>

     </ClInclude>

+    <ClInclude Include="libGLESv2.hpp">

+      <Filter>Header Files</Filter>

+    </ClInclude>

   </ItemGroup>

   <ItemGroup>

     <ResourceCompile Include="libGLESv2.rc" />

diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index 469bbe4..05f2468 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -23,6 +23,8 @@
 #include <GLES3/gl3.h>

 #include <GLES2/gl2ext.h>

 

+using namespace es2;

+

 typedef std::pair<GLenum, GLenum> InternalFormatTypePair;

 typedef std::map<InternalFormatTypePair, GLenum> FormatMap;

 

diff --git a/src/OpenGL/libGLESv2/main.cpp b/src/OpenGL/libGLESv2/main.cpp
index f185bee..d77b784 100644
--- a/src/OpenGL/libGLESv2/main.cpp
+++ b/src/OpenGL/libGLESv2/main.cpp
@@ -13,7 +13,9 @@
 

 #include "main.h"

 

+#include "libGLESv2.hpp"

 #include "Framebuffer.h"

+#include "libEGL/main.h"

 #include "libEGL/Surface.h"

 #include "Common/Thread.hpp"

 #include "Common/SharedLibrary.hpp"

@@ -37,40 +39,11 @@
     TRACE("()");

 }

 

-CONSTRUCTOR static bool glAttachProcess()

+CONSTRUCTOR static void glAttachProcess()

 {

     TRACE("()");

 

     glAttachThread();

-

-	#if defined(_WIN32)

-	const char *libEGL_lib[] = {"libEGL.dll", "libEGL_translator.dll"};

-	#elif defined(__ANDROID__)

-	const char *libEGL_lib[] = {"/vendor/lib/egl/libEGL_swiftshader.so"};

-	#elif defined(__LP64__)

-	const char *libEGL_lib[] = {"lib64EGL_translator.so", "libEGL.so.1", "libEGL.so"};

-	#else

-	const char *libEGL_lib[] = {"libEGL_translator.so", "libEGL.so.1", "libEGL.so"};

-	#endif

-

-	libEGL = loadLibrary(libEGL_lib);

-	egl::getCurrentContext = (egl::Context *(*)())getProcAddress(libEGL, "clientGetCurrentContext");

-	egl::getCurrentDisplay = (egl::Display *(*)())getProcAddress(libEGL, "clientGetCurrentDisplay");

-

-	#if defined(_WIN32)

-	const char *libGLES_CM_lib[] = {"libGLES_CM.dll", "libGLES_CM_translator.dll"};

-	#elif defined(__ANDROID__)

-	const char *libGLES_CM_lib[] = {"/vendor/lib/egl/libGLESv1_CM_swiftshader.so"};

-	#elif defined(__LP64__)

-	const char *libGLES_CM_lib[] = {"lib64GLES_CM_translator.so", "libGLES_CM.so.1", "libGLES_CM.so"};

-	#else

-	const char *libGLES_CM_lib[] = {"libGLES_CM_translator.so", "libGLES_CM.so.1", "libGLES_CM.so"};

-	#endif

-

-	libGLES_CM = loadLibrary(libGLES_CM_lib);

-	es1::getProcAddress = (__eglMustCastToProperFunctionPointerType (*)(const char*))getProcAddress(libGLES_CM, "glGetProcAddress");

-

-    return libEGL != 0;

 }

 

 DESTRUCTOR static void glDetachProcess()

@@ -78,8 +51,6 @@
     TRACE("()");

 

 	glDetachThread();

-	freeLibrary(libEGL);

-	freeLibrary(libGLES_CM);

 }

 

 #if defined(_WIN32)

@@ -88,7 +59,7 @@
     switch(reason)

     {

     case DLL_PROCESS_ATTACH:

-        return glAttachProcess();

+        glAttachProcess();

         break;

     case DLL_THREAD_ATTACH:

         glAttachThread();

@@ -111,7 +82,7 @@
 {

 es2::Context *getContext()

 {

-	egl::Context *context = egl::getCurrentContext();

+	egl::Context *context = libEGL->clientGetCurrentContext();

 

 	if(context && (context->getClientVersion() == 2 ||

 	               context->getClientVersion() == 3))

@@ -124,7 +95,7 @@
 

 egl::Display *getDisplay()

 {

-    return egl::getCurrentDisplay();

+    return libEGL->clientGetCurrentDisplay();

 }

 

 Device *getDevice()

@@ -133,17 +104,6 @@
 

     return context ? context->getDevice() : 0;

 }

-}

-

-namespace egl

-{

-GLint getClientVersion()

-{

-	Context *context = egl::getCurrentContext();

-

-    return context ? context->getClientVersion() : 0;

-}

-}

 

 // Records an error code

 void error(GLenum errorCode)

@@ -178,17 +138,38 @@
         }

     }

 }

+}

 

 namespace egl

 {

-	egl::Context *(*getCurrentContext)() = 0;

-	egl::Display *(*getCurrentDisplay)() = 0;

-}

-

-namespace es1

+GLint getClientVersion()

 {

-	__eglMustCastToProperFunctionPointerType (*getProcAddress)(const char *procname) = 0;

+	Context *context = libEGL->clientGetCurrentContext();

+

+    return context ? context->getClientVersion() : 0;

+}

 }

 

-void *libEGL = 0;   // Handle to the libEGL module

-void *libGLES_CM = 0;   // Handle to the libGLES_CM module

+egl::Context *es2CreateContext(const egl::Config *config, const egl::Context *shareContext, int clientVersion);

+extern "C" __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname);

+egl::Image *createBackBuffer(int width, int height, const egl::Config *config);

+egl::Image *createDepthStencil(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard);

+sw::FrameBuffer *createFrameBuffer(EGLNativeDisplayType display, EGLNativeWindowType window, int width, int height);

+

+LibGLESv2exports::LibGLESv2exports()

+{

+	this->es2CreateContext = ::es2CreateContext;

+	this->es2GetProcAddress = ::es2GetProcAddress;

+	this->createBackBuffer = ::createBackBuffer;

+	this->createDepthStencil = ::createDepthStencil;

+	this->createFrameBuffer = ::createFrameBuffer;

+}

+

+extern "C" LibGLESv2exports *libGLESv2exports()

+{

+	static LibGLESv2exports libGLESv2;

+	return &libGLESv2;

+}

+

+LibEGL libEGL;

+LibGLES_CM libGLES_CM;
\ No newline at end of file
diff --git a/src/OpenGL/libGLESv2/main.h b/src/OpenGL/libGLESv2/main.h
index 09ffb88..de5a2c4 100644
--- a/src/OpenGL/libGLESv2/main.h
+++ b/src/OpenGL/libGLESv2/main.h
@@ -17,7 +17,9 @@
 #include "Context.h"
 #include "Device.hpp"
 #include "common/debug.h"
+#include "libEGL/libEGL.hpp"
 #include "libEGL/Display.h"
+#include "libGLES_CM/libGLES_CM.hpp"
 
 #define GL_APICALL
 #include <GLES2/gl2.h>
@@ -29,6 +31,16 @@
 	Context *getContext();
 	egl::Display *getDisplay();
 	Device *getDevice();
+
+	void error(GLenum errorCode);
+
+	template<class T>
+	const T &error(GLenum errorCode, const T &returnValue)
+	{
+		error(errorCode);
+
+		return returnValue;
+	}
 }
 
 namespace egl
@@ -36,30 +48,7 @@
 	GLint getClientVersion();
 }
 
-void error(GLenum errorCode);
-
-template<class T>
-const T &error(GLenum errorCode, const T &returnValue)
-{
-    error(errorCode);
-
-    return returnValue;
-}
-
-// libEGL dependencies
-namespace egl
-{
-	extern egl::Context *(*getCurrentContext)();
-	extern egl::Display *(*getCurrentDisplay)();
-}
-
-// libGLES_CM dependencies
-namespace es1
-{
-	extern __eglMustCastToProperFunctionPointerType (*getProcAddress)(const char *procname);
-}
-
-extern void *libEGL;       // Handle to the libEGL module
-extern void *libGLES_CM;   // Handle to the libGLES_CM module
+extern LibEGL libEGL;
+extern LibGLES_CM libGLES_CM;
 
 #endif   // LIBGLESV2_MAIN_H_