Add OpenGL ES 2.0 initialization unit tests.

Create an OpenGL ES 2.0 context and verify the renderer string. This
ensures the expected libGLESv2 get loaded and initialized correctly.
Also add unittests to the Visual Studio solution.

Change-Id: I848079215434ce1fb9a18564ce47de5b598b21d2
Reviewed-on: https://swiftshader-review.googlesource.com/10108
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/SwiftShader.sln b/SwiftShader.sln
index e4ffb2f..d0501a3 100644
--- a/SwiftShader.sln
+++ b/SwiftShader.sln
@@ -257,6 +257,8 @@
 EndProject

 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SubzeroLLVMDependencies", "src\Reactor\SubzeroLLVMDependencies.vcxproj", "{E3BBD7DA-45C1-43EF-9C87-3F411031BDE4}"

 EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittests", "tests\unittests\unittests.vcxproj", "{CF8EBC89-8762-49DC-9440-6C82B3499913}"

+EndProject

 Global

 	GlobalSection(SolutionConfigurationPlatforms) = preSolution

 		Debug|Win32 = Debug|Win32

@@ -768,6 +770,18 @@
 		{E3BBD7DA-45C1-43EF-9C87-3F411031BDE4}.Release|Win32.Build.0 = Release|Win32

 		{E3BBD7DA-45C1-43EF-9C87-3F411031BDE4}.Release|x64.ActiveCfg = Release|x64

 		{E3BBD7DA-45C1-43EF-9C87-3F411031BDE4}.Release|x64.Build.0 = Release|x64

+		{CF8EBC89-8762-49DC-9440-6C82B3499913}.Debug|Win32.ActiveCfg = Debug|Win32

+		{CF8EBC89-8762-49DC-9440-6C82B3499913}.Debug|Win32.Build.0 = Debug|Win32

+		{CF8EBC89-8762-49DC-9440-6C82B3499913}.Debug|x64.ActiveCfg = Debug|x64

+		{CF8EBC89-8762-49DC-9440-6C82B3499913}.Debug|x64.Build.0 = Debug|x64

+		{CF8EBC89-8762-49DC-9440-6C82B3499913}.Profile|Win32.ActiveCfg = Release|Win32

+		{CF8EBC89-8762-49DC-9440-6C82B3499913}.Profile|Win32.Build.0 = Release|Win32

+		{CF8EBC89-8762-49DC-9440-6C82B3499913}.Profile|x64.ActiveCfg = Release|x64

+		{CF8EBC89-8762-49DC-9440-6C82B3499913}.Profile|x64.Build.0 = Release|x64

+		{CF8EBC89-8762-49DC-9440-6C82B3499913}.Release|Win32.ActiveCfg = Release|Win32

+		{CF8EBC89-8762-49DC-9440-6C82B3499913}.Release|Win32.Build.0 = Release|Win32

+		{CF8EBC89-8762-49DC-9440-6C82B3499913}.Release|x64.ActiveCfg = Release|x64

+		{CF8EBC89-8762-49DC-9440-6C82B3499913}.Release|x64.Build.0 = Release|x64

 	EndGlobalSection

 	GlobalSection(SolutionProperties) = preSolution

 		HideSolutionNode = FALSE

@@ -810,5 +824,6 @@
 		{09ABE661-9BC0-4152-A820-1FB0522CAC01} = {B7E24D8E-6BE9-4DEF-A8B9-6A6E60CA60E9}

 		{9088FC9E-9843-4E0D-85D0-1B657AFC480A} = {B7E24D8E-6BE9-4DEF-A8B9-6A6E60CA60E9}

 		{4EC107AB-89E8-4A0B-8366-B3E81085AE07} = {ED25C308-5BDB-43A7-BED6-C2C059FC2D7D}

+		{CF8EBC89-8762-49DC-9440-6C82B3499913} = {ED25C308-5BDB-43A7-BED6-C2C059FC2D7D}

 	EndGlobalSection

 EndGlobal

diff --git a/tests/unittests/BUILD.gn b/tests/unittests/BUILD.gn
index 5448bc6..0d2a119 100644
--- a/tests/unittests/BUILD.gn
+++ b/tests/unittests/BUILD.gn
@@ -33,6 +33,10 @@
     "../../include",   # Khronos headers
   ]
 
+  defines = [
+    "GL_GLEXT_PROTOTYPES",
+  ]
+
   # Make sure we're loading SwiftShader's libraries, not ANGLE's or the system
   # provided ones. On Windows an explicit LoadLibrary("swiftshader\lib*.dll")
   # is required before making the first EGL or OpenGL ES call.
diff --git a/tests/unittests/unittests.cpp b/tests/unittests/unittests.cpp
index 11c2061..f363756 100644
--- a/tests/unittests/unittests.cpp
+++ b/tests/unittests/unittests.cpp
@@ -27,9 +27,9 @@
 protected:
 	void SetUp() override
 	{
-		#if defined(_WIN32)
+		#if defined(_WIN32) && !defined(STANDALONE)
 			// The DLLs are delay loaded (see BUILD.gn), so we can load
-			// the correct ones from the swiftshader subdirectory.
+			// the correct ones from Chrome's swiftshader subdirectory.
 			HMODULE libEGL = LoadLibraryA("swiftshader\\libEGL.dll");
 			EXPECT_NE((HMODULE)NULL, libEGL);
 
@@ -63,11 +63,130 @@
 	EXPECT_EQ(1, major);
 	EXPECT_EQ(4, minor);
 
-	const char *vendor = eglQueryString(display, EGL_VENDOR);
+	const char *eglVendor = eglQueryString(display, EGL_VENDOR);
 	EXPECT_EQ(EGL_SUCCESS, eglGetError());
-	EXPECT_STREQ("Google Inc.", vendor);
+	EXPECT_STREQ("Google Inc.", eglVendor);
 
-	const char *version = eglQueryString(display, EGL_VERSION);
+	const char *eglVersion = eglQueryString(display, EGL_VERSION);
 	EXPECT_EQ(EGL_SUCCESS, eglGetError());
-	EXPECT_THAT(version, testing::HasSubstr("1.4 SwiftShader "));
+	EXPECT_THAT(eglVersion, testing::HasSubstr("1.4 SwiftShader "));
+
+	eglBindAPI(EGL_OPENGL_ES_API);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+	const EGLint configAttributes[] =
+	{
+		EGL_SURFACE_TYPE,		EGL_PBUFFER_BIT,
+		EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
+		EGL_NONE
+	};
+
+	EGLConfig config;
+	EGLint num_config = -1;
+	EGLBoolean success = eglChooseConfig(display, configAttributes, &config, 1, &num_config);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_EQ(num_config, 1);
+	EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
+
+	EGLint conformant = 0;
+	eglGetConfigAttrib(display, config, EGL_CONFORMANT, &conformant);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_TRUE(conformant & EGL_OPENGL_ES2_BIT);
+
+	EGLint renderableType = 0;
+	eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_TRUE(renderableType & EGL_OPENGL_ES2_BIT);
+
+	EGLint surfaceType = 0;
+	eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &surfaceType);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_TRUE(surfaceType & EGL_WINDOW_BIT);
+
+	EGLint surfaceAttributes[] =
+	{
+		EGL_WIDTH, 1920,
+		EGL_HEIGHT, 1080,
+		EGL_NONE
+	};
+
+	EGLSurface surface = eglCreatePbufferSurface(display, config, surfaceAttributes);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_NE(EGL_NO_SURFACE, surface);
+
+	EGLint contextAttributes[] =
+	{
+		EGL_CONTEXT_CLIENT_VERSION, 2,
+		EGL_NONE
+	};
+
+	EGLContext context = eglCreateContext(display, config, NULL, contextAttributes);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_NE(EGL_NO_SURFACE, surface);
+
+	success = eglMakeCurrent(display, surface, surface, context);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
+
+	EGLDisplay currentDisplay = eglGetCurrentDisplay();
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_NE(EGL_NO_DISPLAY, currentDisplay);
+
+	EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_NE(EGL_NO_SURFACE, currentDrawSurface);
+
+	EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_NE(EGL_NO_SURFACE, currentReadSurface);
+
+	EGLContext currentContext = eglGetCurrentContext();
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_NE(EGL_NO_CONTEXT, currentContext);
+
+	EXPECT_EQ((GLenum)GL_NO_ERROR, glGetError());
+
+	const GLubyte *glVendor = glGetString(GL_VENDOR);
+	EXPECT_EQ((GLenum)GL_NO_ERROR, glGetError());
+	EXPECT_STREQ("Google Inc.", (const char*)glVendor);
+
+	const GLubyte *glRenderer = glGetString(GL_RENDERER);
+	EXPECT_EQ((GLenum)GL_NO_ERROR, glGetError());
+	EXPECT_STREQ("Google SwiftShader", (const char*)glRenderer);
+
+	const GLubyte *glVersion = glGetString(GL_VERSION);
+	EXPECT_EQ((GLenum)GL_NO_ERROR, glGetError());
+	EXPECT_THAT((const char*)glVersion, testing::HasSubstr("OpenGL ES 2.0 SwiftShader "));
+
+	success = eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
+
+//	currentDisplay = eglGetCurrentDisplay();
+//	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+//	EXPECT_EQ(EGL_NO_DISPLAY, currentDisplay);
+
+	currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_EQ(EGL_NO_SURFACE, currentDrawSurface);
+
+	currentReadSurface = eglGetCurrentSurface(EGL_READ);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_EQ(EGL_NO_SURFACE, currentReadSurface);
+
+	currentContext = eglGetCurrentContext();
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_EQ(EGL_NO_CONTEXT, currentContext);
+
+	success = eglDestroyContext(display, context);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
+
+	success = eglDestroySurface(display, surface);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
+
+	success = eglTerminate(display);
+	EXPECT_EQ(EGL_SUCCESS, eglGetError());
+	EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
 }
diff --git a/tests/unittests/unittests.vcxproj b/tests/unittests/unittests.vcxproj
index 72efcd0..537801f 100644
--- a/tests/unittests/unittests.vcxproj
+++ b/tests/unittests/unittests.vcxproj
@@ -91,10 +91,11 @@
       </PrecompiledHeader>

       <WarningLevel>Level3</WarningLevel>

       <Optimization>Disabled</Optimization>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <PreprocessorDefinitions>GL_GLEXT_PROTOTYPES;STANDALONE;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <SDLCheck>true</SDLCheck>

-      <AdditionalIncludeDirectories>$(SolutionDir)third_party\googletest\googletest\include\;$(SolutionDir)third_party\googletest\googletest\;SubmoduleCheck;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <ForcedIncludeFiles>gtest/gtest.h</ForcedIncludeFiles>

+      <AdditionalIncludeDirectories>$(SolutionDir)include\;$(SolutionDir)third_party\googletest\googletest\include\;$(SolutionDir)third_party\googletest\googletest\;$(SolutionDir)third_party\googletest\googlemock\include\;SubmoduleCheck;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <ForcedIncludeFiles>

+      </ForcedIncludeFiles>

     </ClCompile>

     <Link>

       <SubSystem>Console</SubSystem>

@@ -107,10 +108,11 @@
       </PrecompiledHeader>

       <WarningLevel>Level3</WarningLevel>

       <Optimization>Disabled</Optimization>

-      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <PreprocessorDefinitions>GL_GLEXT_PROTOTYPES;STANDALONE;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <SDLCheck>true</SDLCheck>

-      <AdditionalIncludeDirectories>$(SolutionDir)third_party\googletest\googletest\include\;$(SolutionDir)third_party\googletest\googletest\;SubmoduleCheck;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <ForcedIncludeFiles>gtest/gtest.h</ForcedIncludeFiles>

+      <AdditionalIncludeDirectories>$(SolutionDir)include\;$(SolutionDir)third_party\googletest\googletest\include\;$(SolutionDir)third_party\googletest\googletest\;$(SolutionDir)third_party\googletest\googlemock\include\;SubmoduleCheck;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <ForcedIncludeFiles>

+      </ForcedIncludeFiles>

     </ClCompile>

     <Link>

       <SubSystem>Console</SubSystem>

@@ -125,10 +127,11 @@
       <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <PreprocessorDefinitions>GL_GLEXT_PROTOTYPES;STANDALONE;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <SDLCheck>true</SDLCheck>

-      <AdditionalIncludeDirectories>$(SolutionDir)third_party\googletest\googletest\include\;$(SolutionDir)third_party\googletest\googletest\;SubmoduleCheck;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <ForcedIncludeFiles>gtest/gtest.h</ForcedIncludeFiles>

+      <AdditionalIncludeDirectories>$(SolutionDir)include\;$(SolutionDir)third_party\googletest\googletest\include\;$(SolutionDir)third_party\googletest\googletest\;$(SolutionDir)third_party\googletest\googlemock\include\;SubmoduleCheck;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <ForcedIncludeFiles>

+      </ForcedIncludeFiles>

     </ClCompile>

     <Link>

       <SubSystem>Console</SubSystem>

@@ -145,10 +148,11 @@
       <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

-      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <PreprocessorDefinitions>GL_GLEXT_PROTOTYPES;STANDALONE;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <SDLCheck>true</SDLCheck>

-      <AdditionalIncludeDirectories>$(SolutionDir)third_party\googletest\googletest\include\;$(SolutionDir)third_party\googletest\googletest\;SubmoduleCheck;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <ForcedIncludeFiles>gtest/gtest.h</ForcedIncludeFiles>

+      <AdditionalIncludeDirectories>$(SolutionDir)include\;$(SolutionDir)third_party\googletest\googletest\include\;$(SolutionDir)third_party\googletest\googletest\;$(SolutionDir)third_party\googletest\googlemock\include\;SubmoduleCheck;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <ForcedIncludeFiles>

+      </ForcedIncludeFiles>

     </ClCompile>

     <Link>

       <SubSystem>Console</SubSystem>

@@ -162,6 +166,14 @@
     <ClCompile Include="main.cpp" />

     <ClCompile Include="unittests.cpp" />

   </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="..\..\src\OpenGL\libEGL\libEGL.vcxproj">

+      <Project>{e746fca9-64c3-433e-85e8-9a5a67ab7ed6}</Project>

+    </ProjectReference>

+    <ProjectReference Include="..\..\src\OpenGL\libGLESv2\libGLESv2.vcxproj">

+      <Project>{b5871a7a-968c-42e3-a33b-981e6f448e78}</Project>

+    </ProjectReference>

+  </ItemGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

   <ImportGroup Label="ExtensionTargets">

   </ImportGroup>

diff --git a/tests/unittests/unittests.vcxproj.user b/tests/unittests/unittests.vcxproj.user
index 190f1da..234e386 100644
--- a/tests/unittests/unittests.vcxproj.user
+++ b/tests/unittests/unittests.vcxproj.user
@@ -1,4 +1,19 @@
-<?xml version="1.0" encoding="utf-8"?>

+<?xml version="1.0" encoding="utf-8"?>

 <Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <PropertyGroup />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LocalDebuggerEnvironment>PATH=$(SolutionDir)lib\$(Configuration)_$(Platform)</LocalDebuggerEnvironment>

+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LocalDebuggerEnvironment>PATH=$(SolutionDir)lib\$(Configuration)_$(Platform)</LocalDebuggerEnvironment>

+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LocalDebuggerEnvironment>PATH=$(SolutionDir)lib\$(Configuration)_$(Platform)</LocalDebuggerEnvironment>

+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LocalDebuggerEnvironment>PATH=$(SolutionDir)lib\$(Configuration)_$(Platform)</LocalDebuggerEnvironment>

+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>

+  </PropertyGroup>

 </Project>
\ No newline at end of file