Implement EGL_KHR_get_all_proc_addresses.

This also improves GetProcAddress performance by using binary search
instead of linear search.

Fixes bug b/20110899

Change-Id: I6c58e17f0580904338e4d806e310cccbec398f28
Reviewed-on: https://swiftshader-review.googlesource.com/15748
Tested-by: Krzysztof Kosiński <krzysio@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/libEGL/libEGL.cpp b/src/OpenGL/libEGL/libEGL.cpp
index 21ef933..08861c2 100644
--- a/src/OpenGL/libEGL/libEGL.cpp
+++ b/src/OpenGL/libEGL/libEGL.cpp
@@ -29,6 +29,7 @@
 #include "Main/libX11.hpp"
 #endif
 
+#include <algorithm>
 #include <string.h>
 
 using namespace egl;
@@ -174,6 +175,7 @@
 	if(dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
 	{
 		return success(
+			"EGL_KHR_client_get_all_proc_addresses "
 #if defined(__linux__) && !defined(__ANDROID__)
 			"EGL_KHR_platform_gbm "
 			"EGL_KHR_platform_x11 "
@@ -195,6 +197,7 @@
 		return success("OpenGL_ES");
 	case EGL_EXTENSIONS:
 		return success("EGL_KHR_create_context "
+		               "EGL_KHR_get_all_proc_addresses "
 		               "EGL_KHR_gl_texture_2D_image "
 		               "EGL_KHR_gl_texture_cubemap_image "
 		               "EGL_KHR_gl_renderbuffer_image "
@@ -1241,34 +1244,85 @@
 {
 	TRACE("(const char *procname = \"%s\")", procname);
 
-	struct Extension
+	struct Function
 	{
 		const char *name;
 		__eglMustCastToProperFunctionPointerType address;
 	};
 
-	static const Extension eglExtensions[] =
+	struct CompareFunctor
 	{
-		#define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
-
-		EXTENSION(eglCreateImageKHR),
-		EXTENSION(eglDestroyImageKHR),
-		EXTENSION(eglGetPlatformDisplayEXT),
-		EXTENSION(eglCreatePlatformWindowSurfaceEXT),
-		EXTENSION(eglCreatePlatformPixmapSurfaceEXT),
-		EXTENSION(eglCreateSyncKHR),
-		EXTENSION(eglDestroySyncKHR),
-		EXTENSION(eglClientWaitSyncKHR),
-		EXTENSION(eglGetSyncAttribKHR),
-
-		#undef EXTENSION
+		bool operator()(const Function &a, const Function &b) const
+		{
+			return strcmp(a.name, b.name) < 0;
+		}
 	};
 
-	for(unsigned int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++)
+	// This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
+	// The Unix command "LC_COLLATE=C sort" will generate the correct order.
+	static const Function eglFunctions[] =
 	{
-		if(strcmp(procname, eglExtensions[ext].name) == 0)
+		#define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
+
+		FUNCTION(eglBindAPI),
+		FUNCTION(eglBindTexImage),
+		FUNCTION(eglChooseConfig),
+		FUNCTION(eglClientWaitSyncKHR),
+		FUNCTION(eglCopyBuffers),
+		FUNCTION(eglCreateContext),
+		FUNCTION(eglCreateImageKHR),
+		FUNCTION(eglCreatePbufferFromClientBuffer),
+		FUNCTION(eglCreatePbufferSurface),
+		FUNCTION(eglCreatePixmapSurface),
+		FUNCTION(eglCreatePlatformPixmapSurfaceEXT),
+		FUNCTION(eglCreatePlatformWindowSurfaceEXT),
+		FUNCTION(eglCreateSyncKHR),
+		FUNCTION(eglCreateWindowSurface),
+		FUNCTION(eglDestroyContext),
+		FUNCTION(eglDestroyImageKHR),
+		FUNCTION(eglDestroySurface),
+		FUNCTION(eglDestroySyncKHR),
+		FUNCTION(eglGetConfigAttrib),
+		FUNCTION(eglGetConfigs),
+		FUNCTION(eglGetCurrentContext),
+		FUNCTION(eglGetCurrentDisplay),
+		FUNCTION(eglGetCurrentSurface),
+		FUNCTION(eglGetDisplay),
+		FUNCTION(eglGetError),
+		FUNCTION(eglGetPlatformDisplayEXT),
+		FUNCTION(eglGetProcAddress),
+		FUNCTION(eglGetSyncAttribKHR),
+		FUNCTION(eglInitialize),
+		FUNCTION(eglMakeCurrent),
+		FUNCTION(eglQueryAPI),
+		FUNCTION(eglQueryContext),
+		FUNCTION(eglQueryString),
+		FUNCTION(eglQuerySurface),
+		FUNCTION(eglReleaseTexImage),
+		FUNCTION(eglReleaseThread),
+		FUNCTION(eglSurfaceAttrib),
+		FUNCTION(eglSwapBuffers),
+		FUNCTION(eglSwapInterval),
+		FUNCTION(eglTerminate),
+		FUNCTION(eglWaitClient),
+		FUNCTION(eglWaitGL),
+		FUNCTION(eglWaitNative),
+
+		#undef FUNCTION
+	};
+
+	static const size_t numFunctions = sizeof eglFunctions / sizeof(Function);
+	static const Function *const eglFunctionsEnd = eglFunctions + numFunctions;
+
+	Function needle;
+	needle.name = procname;
+
+	if(procname && strncmp("egl", procname, 3) == 0)
+	{
+		const Function *result = std::lower_bound(eglFunctions, eglFunctionsEnd, needle, CompareFunctor());
+		if (result != eglFunctionsEnd && strcmp(procname, result->name) == 0)
 		{
-			return success((__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address);
+			return success((__eglMustCastToProperFunctionPointerType)result->address);
 		}
 	}
 
diff --git a/src/OpenGL/libGLES_CM/libGLES_CM.cpp b/src/OpenGL/libGLES_CM/libGLES_CM.cpp
index 62acae1..88a19e8 100644
--- a/src/OpenGL/libGLES_CM/libGLES_CM.cpp
+++ b/src/OpenGL/libGLES_CM/libGLES_CM.cpp
@@ -32,6 +32,7 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+#include <algorithm>
 #include <limits>
 
 namespace es1
@@ -4727,46 +4728,215 @@
 
 extern "C" __eglMustCastToProperFunctionPointerType es1GetProcAddress(const char *procname)
 {
-	struct Extension
+	struct Function
 	{
 		const char *name;
 		__eglMustCastToProperFunctionPointerType address;
 	};
 
-	static const Extension glExtensions[] =
+	struct CompareFunctor
 	{
-		#define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
-
-		EXTENSION(glEGLImageTargetTexture2DOES),
-		EXTENSION(glEGLImageTargetRenderbufferStorageOES),
-		EXTENSION(glIsRenderbufferOES),
-		EXTENSION(glBindRenderbufferOES),
-		EXTENSION(glDeleteRenderbuffersOES),
-		EXTENSION(glGenRenderbuffersOES),
-		EXTENSION(glRenderbufferStorageOES),
-		EXTENSION(glGetRenderbufferParameterivOES),
-		EXTENSION(glIsFramebufferOES),
-		EXTENSION(glBindFramebufferOES),
-		EXTENSION(glDeleteFramebuffersOES),
-		EXTENSION(glGenFramebuffersOES),
-		EXTENSION(glCheckFramebufferStatusOES),
-		EXTENSION(glFramebufferRenderbufferOES),
-		EXTENSION(glFramebufferTexture2DOES),
-		EXTENSION(glGetFramebufferAttachmentParameterivOES),
-		EXTENSION(glGenerateMipmapOES),
-		EXTENSION(glBlendEquationOES),
-		EXTENSION(glBlendEquationSeparateOES),
-		EXTENSION(glBlendFuncSeparateOES),
-		EXTENSION(glPointSizePointerOES),
-
-		#undef EXTENSION
+		bool operator()(const Function &a, const Function &b) const
+		{
+			return strcmp(a.name, b.name) < 0;
+		}
 	};
 
-	for(unsigned int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
+	// This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
+	// The Unix command "LC_COLLATE=C sort" will generate the correct order.
+	static const Function glFunctions[] =
 	{
-		if(strcmp(procname, glExtensions[ext].name) == 0)
+		#define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
+
+		FUNCTION(glActiveTexture),
+		FUNCTION(glAlphaFunc),
+		FUNCTION(glAlphaFuncx),
+		FUNCTION(glBindBuffer),
+		FUNCTION(glBindFramebufferOES),
+		FUNCTION(glBindRenderbufferOES),
+		FUNCTION(glBindTexture),
+		FUNCTION(glBlendEquationOES),
+		FUNCTION(glBlendEquationSeparateOES),
+		FUNCTION(glBlendFunc),
+		FUNCTION(glBlendFuncSeparateOES),
+		FUNCTION(glBufferData),
+		FUNCTION(glBufferSubData),
+		FUNCTION(glCheckFramebufferStatusOES),
+		FUNCTION(glClear),
+		FUNCTION(glClearColor),
+		FUNCTION(glClearColorx),
+		FUNCTION(glClearDepthf),
+		FUNCTION(glClearDepthx),
+		FUNCTION(glClearStencil),
+		FUNCTION(glClientActiveTexture),
+		FUNCTION(glClipPlanef),
+		FUNCTION(glClipPlanex),
+		FUNCTION(glColor4f),
+		FUNCTION(glColor4ub),
+		FUNCTION(glColor4x),
+		FUNCTION(glColorMask),
+		FUNCTION(glColorPointer),
+		FUNCTION(glCompressedTexImage2D),
+		FUNCTION(glCompressedTexSubImage2D),
+		FUNCTION(glCopyTexImage2D),
+		FUNCTION(glCopyTexSubImage2D),
+		FUNCTION(glCullFace),
+		FUNCTION(glDeleteBuffers),
+		FUNCTION(glDeleteFramebuffersOES),
+		FUNCTION(glDeleteRenderbuffersOES),
+		FUNCTION(glDeleteTextures),
+		FUNCTION(glDepthFunc),
+		FUNCTION(glDepthMask),
+		FUNCTION(glDepthRangef),
+		FUNCTION(glDepthRangex),
+		FUNCTION(glDisable),
+		FUNCTION(glDisableClientState),
+		FUNCTION(glDrawArrays),
+		FUNCTION(glDrawElements),
+		FUNCTION(glDrawTexfOES),
+		FUNCTION(glDrawTexfvOES),
+		FUNCTION(glDrawTexiOES),
+		FUNCTION(glDrawTexivOES),
+		FUNCTION(glDrawTexsOES),
+		FUNCTION(glDrawTexsvOES),
+		FUNCTION(glDrawTexxOES),
+		FUNCTION(glDrawTexxvOES),
+		FUNCTION(glEGLImageTargetRenderbufferStorageOES),
+		FUNCTION(glEGLImageTargetTexture2DOES),
+		FUNCTION(glEnable),
+		FUNCTION(glEnableClientState),
+		FUNCTION(glFinish),
+		FUNCTION(glFlush),
+		FUNCTION(glFogf),
+		FUNCTION(glFogfv),
+		FUNCTION(glFogx),
+		FUNCTION(glFogxv),
+		FUNCTION(glFramebufferRenderbufferOES),
+		FUNCTION(glFramebufferTexture2DOES),
+		FUNCTION(glFrontFace),
+		FUNCTION(glFrustumf),
+		FUNCTION(glFrustumx),
+		FUNCTION(glGenBuffers),
+		FUNCTION(glGenFramebuffersOES),
+		FUNCTION(glGenRenderbuffersOES),
+		FUNCTION(glGenTextures),
+		FUNCTION(glGenerateMipmapOES),
+		FUNCTION(glGetBooleanv),
+		FUNCTION(glGetBufferParameteriv),
+		FUNCTION(glGetClipPlanef),
+		FUNCTION(glGetClipPlanex),
+		FUNCTION(glGetError),
+		FUNCTION(glGetFixedv),
+		FUNCTION(glGetFloatv),
+		FUNCTION(glGetFramebufferAttachmentParameterivOES),
+		FUNCTION(glGetIntegerv),
+		FUNCTION(glGetLightfv),
+		FUNCTION(glGetLightxv),
+		FUNCTION(glGetMaterialfv),
+		FUNCTION(glGetMaterialxv),
+		FUNCTION(glGetPointerv),
+		FUNCTION(glGetRenderbufferParameterivOES),
+		FUNCTION(glGetString),
+		FUNCTION(glGetTexEnvfv),
+		FUNCTION(glGetTexEnviv),
+		FUNCTION(glGetTexEnvxv),
+		FUNCTION(glGetTexParameterfv),
+		FUNCTION(glGetTexParameteriv),
+		FUNCTION(glGetTexParameterxv),
+		FUNCTION(glHint),
+		FUNCTION(glIsBuffer),
+		FUNCTION(glIsEnabled),
+		FUNCTION(glIsFramebufferOES),
+		FUNCTION(glIsRenderbufferOES),
+		FUNCTION(glIsTexture),
+		FUNCTION(glLightModelf),
+		FUNCTION(glLightModelfv),
+		FUNCTION(glLightModelx),
+		FUNCTION(glLightModelxv),
+		FUNCTION(glLightf),
+		FUNCTION(glLightfv),
+		FUNCTION(glLightx),
+		FUNCTION(glLightxv),
+		FUNCTION(glLineWidth),
+		FUNCTION(glLineWidthx),
+		FUNCTION(glLoadIdentity),
+		FUNCTION(glLoadMatrixf),
+		FUNCTION(glLoadMatrixx),
+		FUNCTION(glLogicOp),
+		FUNCTION(glMaterialf),
+		FUNCTION(glMaterialfv),
+		FUNCTION(glMaterialx),
+		FUNCTION(glMaterialxv),
+		FUNCTION(glMatrixMode),
+		FUNCTION(glMultMatrixf),
+		FUNCTION(glMultMatrixx),
+		FUNCTION(glMultiTexCoord4f),
+		FUNCTION(glMultiTexCoord4x),
+		FUNCTION(glNormal3f),
+		FUNCTION(glNormal3x),
+		FUNCTION(glNormalPointer),
+		FUNCTION(glOrthof),
+		FUNCTION(glOrthox),
+		FUNCTION(glPixelStorei),
+		FUNCTION(glPointParameterf),
+		FUNCTION(glPointParameterfv),
+		FUNCTION(glPointParameterx),
+		FUNCTION(glPointParameterxv),
+		FUNCTION(glPointSize),
+		FUNCTION(glPointSizePointerOES),
+		FUNCTION(glPointSizex),
+		FUNCTION(glPolygonOffset),
+		FUNCTION(glPolygonOffsetx),
+		FUNCTION(glPopMatrix),
+		FUNCTION(glPushMatrix),
+		FUNCTION(glReadPixels),
+		FUNCTION(glRenderbufferStorageOES),
+		FUNCTION(glRotatef),
+		FUNCTION(glRotatex),
+		FUNCTION(glSampleCoverage),
+		FUNCTION(glSampleCoveragex),
+		FUNCTION(glScalef),
+		FUNCTION(glScalex),
+		FUNCTION(glScissor),
+		FUNCTION(glShadeModel),
+		FUNCTION(glStencilFunc),
+		FUNCTION(glStencilMask),
+		FUNCTION(glStencilOp),
+		FUNCTION(glTexCoordPointer),
+		FUNCTION(glTexEnvf),
+		FUNCTION(glTexEnvfv),
+		FUNCTION(glTexEnvi),
+		FUNCTION(glTexEnviv),
+		FUNCTION(glTexEnvx),
+		FUNCTION(glTexEnvxv),
+		FUNCTION(glTexImage2D),
+		FUNCTION(glTexParameterf),
+		FUNCTION(glTexParameterfv),
+		FUNCTION(glTexParameteri),
+		FUNCTION(glTexParameteriv),
+		FUNCTION(glTexParameterx),
+		FUNCTION(glTexParameterxv),
+		FUNCTION(glTexSubImage2D),
+		FUNCTION(glTranslatef),
+		FUNCTION(glTranslatex),
+		FUNCTION(glVertexPointer),
+		FUNCTION(glViewport),
+
+		#undef FUNCTION
+	};
+
+	static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
+	static const Function *const glFunctionsEnd = glFunctions + numFunctions;
+
+	Function needle;
+	needle.name = procname;
+
+	if(procname && strncmp("gl", procname, 2) == 0)
+	{
+		const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
+		if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
 		{
-			return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
+			return (__eglMustCastToProperFunctionPointerType)result->address;
 		}
 	}
 
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index 9f96d47..f9fe511 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -34,6 +34,7 @@
 #include <GLES2/gl2ext.h>
 #include <GLES3/gl3.h>
 
+#include <algorithm>
 #include <limits>
 
 #ifdef __ANDROID__
@@ -6872,71 +6873,327 @@
 
 extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
 {
-	struct Extension
+	struct Function
 	{
 		const char *name;
 		__eglMustCastToProperFunctionPointerType address;
 	};
 
-	static const Extension glExtensions[] =
+	struct CompareFunctor
 	{
-		#define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
-
-		EXTENSION(glTexImage3DOES),
-		EXTENSION(glBlitFramebufferANGLE),
-		EXTENSION(glBlitFramebufferNV),
-		EXTENSION(glRenderbufferStorageMultisampleANGLE),
-		EXTENSION(glDeleteFencesNV),
-		EXTENSION(glGenFencesNV),
-		EXTENSION(glIsFenceNV),
-		EXTENSION(glTestFenceNV),
-		EXTENSION(glGetFenceivNV),
-		EXTENSION(glFinishFenceNV),
-		EXTENSION(glSetFenceNV),
-		EXTENSION(glGetGraphicsResetStatusEXT),
-		EXTENSION(glReadnPixelsEXT),
-		EXTENSION(glGetnUniformfvEXT),
-		EXTENSION(glGetnUniformivEXT),
-		EXTENSION(glGenQueriesEXT),
-		EXTENSION(glDeleteQueriesEXT),
-		EXTENSION(glIsQueryEXT),
-		EXTENSION(glBeginQueryEXT),
-		EXTENSION(glEndQueryEXT),
-		EXTENSION(glGetQueryivEXT),
-		EXTENSION(glGetQueryObjectuivEXT),
-		EXTENSION(glEGLImageTargetTexture2DOES),
-		EXTENSION(glEGLImageTargetRenderbufferStorageOES),
-		EXTENSION(glDrawElementsInstancedEXT),
-		EXTENSION(glDrawArraysInstancedEXT),
-		EXTENSION(glVertexAttribDivisorEXT),
-		EXTENSION(glDrawArraysInstancedANGLE),
-		EXTENSION(glDrawElementsInstancedANGLE),
-		EXTENSION(glVertexAttribDivisorANGLE),
-		EXTENSION(glIsRenderbufferOES),
-		EXTENSION(glBindRenderbufferOES),
-		EXTENSION(glDeleteRenderbuffersOES),
-		EXTENSION(glGenRenderbuffersOES),
-		EXTENSION(glRenderbufferStorageOES),
-		EXTENSION(glGetRenderbufferParameterivOES),
-		EXTENSION(glIsFramebufferOES),
-		EXTENSION(glBindFramebufferOES),
-		EXTENSION(glDeleteFramebuffersOES),
-		EXTENSION(glGenFramebuffersOES),
-		EXTENSION(glCheckFramebufferStatusOES),
-		EXTENSION(glFramebufferRenderbufferOES),
-		EXTENSION(glFramebufferTexture2DOES),
-		EXTENSION(glGetFramebufferAttachmentParameterivOES),
-		EXTENSION(glGenerateMipmapOES),
-		EXTENSION(glDrawBuffersEXT),
-
-		#undef EXTENSION
+		bool operator()(const Function &a, const Function &b) const
+		{
+			return strcmp(a.name, b.name) < 0;
+		}
 	};
 
-	for(unsigned int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
+	// This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
+	// The Unix command "LC_COLLATE=C sort" will generate the correct order.
+	static const Function glFunctions[] =
 	{
-		if(strcmp(procname, glExtensions[ext].name) == 0)
+		#define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
+
+		FUNCTION(glActiveTexture),
+		FUNCTION(glAttachShader),
+		FUNCTION(glBeginQuery),
+		FUNCTION(glBeginQueryEXT),
+		FUNCTION(glBeginTransformFeedback),
+		FUNCTION(glBindAttribLocation),
+		FUNCTION(glBindBuffer),
+		FUNCTION(glBindBufferBase),
+		FUNCTION(glBindBufferRange),
+		FUNCTION(glBindFramebuffer),
+		FUNCTION(glBindFramebufferOES),
+		FUNCTION(glBindRenderbuffer),
+		FUNCTION(glBindRenderbufferOES),
+		FUNCTION(glBindSampler),
+		FUNCTION(glBindTexture),
+		FUNCTION(glBindTransformFeedback),
+		FUNCTION(glBindVertexArray),
+		FUNCTION(glBlendColor),
+		FUNCTION(glBlendEquation),
+		FUNCTION(glBlendEquationSeparate),
+		FUNCTION(glBlendFunc),
+		FUNCTION(glBlendFuncSeparate),
+		FUNCTION(glBlitFramebuffer),
+		FUNCTION(glBlitFramebufferANGLE),
+		FUNCTION(glBufferData),
+		FUNCTION(glBufferSubData),
+		FUNCTION(glCheckFramebufferStatus),
+		FUNCTION(glCheckFramebufferStatusOES),
+		FUNCTION(glClear),
+		FUNCTION(glClearBufferfi),
+		FUNCTION(glClearBufferfv),
+		FUNCTION(glClearBufferiv),
+		FUNCTION(glClearBufferuiv),
+		FUNCTION(glClearColor),
+		FUNCTION(glClearDepthf),
+		FUNCTION(glClearStencil),
+		FUNCTION(glClientWaitSync),
+		FUNCTION(glColorMask),
+		FUNCTION(glCompileShader),
+		FUNCTION(glCompressedTexImage2D),
+		FUNCTION(glCompressedTexImage3D),
+		FUNCTION(glCompressedTexSubImage2D),
+		FUNCTION(glCompressedTexSubImage3D),
+		FUNCTION(glCopyBufferSubData),
+		FUNCTION(glCopyTexImage2D),
+		FUNCTION(glCopyTexSubImage2D),
+		FUNCTION(glCopyTexSubImage3D),
+		FUNCTION(glCreateProgram),
+		FUNCTION(glCreateShader),
+		FUNCTION(glCullFace),
+		FUNCTION(glDeleteBuffers),
+		FUNCTION(glDeleteFencesNV),
+		FUNCTION(glDeleteFramebuffers),
+		FUNCTION(glDeleteFramebuffersOES),
+		FUNCTION(glDeleteProgram),
+		FUNCTION(glDeleteQueries),
+		FUNCTION(glDeleteQueriesEXT),
+		FUNCTION(glDeleteRenderbuffers),
+		FUNCTION(glDeleteRenderbuffersOES),
+		FUNCTION(glDeleteSamplers),
+		FUNCTION(glDeleteShader),
+		FUNCTION(glDeleteSync),
+		FUNCTION(glDeleteTextures),
+		FUNCTION(glDeleteTransformFeedbacks),
+		FUNCTION(glDeleteVertexArrays),
+		FUNCTION(glDepthFunc),
+		FUNCTION(glDepthMask),
+		FUNCTION(glDepthRangef),
+		FUNCTION(glDetachShader),
+		FUNCTION(glDisable),
+		FUNCTION(glDisableVertexAttribArray),
+		FUNCTION(glDrawArrays),
+		FUNCTION(glDrawArraysInstanced),
+		FUNCTION(glDrawBuffers),
+		FUNCTION(glDrawBuffersEXT),
+		FUNCTION(glDrawElements),
+		FUNCTION(glDrawElementsInstanced),
+		FUNCTION(glDrawRangeElements),
+		FUNCTION(glEGLImageTargetRenderbufferStorageOES),
+		FUNCTION(glEGLImageTargetTexture2DOES),
+		FUNCTION(glEnable),
+		FUNCTION(glEnableVertexAttribArray),
+		FUNCTION(glEndQuery),
+		FUNCTION(glEndQueryEXT),
+		FUNCTION(glEndTransformFeedback),
+		FUNCTION(glFenceSync),
+		FUNCTION(glFinish),
+		FUNCTION(glFinishFenceNV),
+		FUNCTION(glFlush),
+		FUNCTION(glFlushMappedBufferRange),
+		FUNCTION(glFramebufferRenderbuffer),
+		FUNCTION(glFramebufferRenderbufferOES),
+		FUNCTION(glFramebufferTexture2D),
+		FUNCTION(glFramebufferTexture2DOES),
+		FUNCTION(glFramebufferTextureLayer),
+		FUNCTION(glFrontFace),
+		FUNCTION(glGenBuffers),
+		FUNCTION(glGenFencesNV),
+		FUNCTION(glGenFramebuffers),
+		FUNCTION(glGenFramebuffersOES),
+		FUNCTION(glGenQueries),
+		FUNCTION(glGenQueriesEXT),
+		FUNCTION(glGenRenderbuffers),
+		FUNCTION(glGenRenderbuffersOES),
+		FUNCTION(glGenSamplers),
+		FUNCTION(glGenTextures),
+		FUNCTION(glGenTransformFeedbacks),
+		FUNCTION(glGenVertexArrays),
+		FUNCTION(glGenerateMipmap),
+		FUNCTION(glGenerateMipmapOES),
+		FUNCTION(glGetActiveAttrib),
+		FUNCTION(glGetActiveUniform),
+		FUNCTION(glGetActiveUniformBlockName),
+		FUNCTION(glGetActiveUniformBlockiv),
+		FUNCTION(glGetActiveUniformsiv),
+		FUNCTION(glGetAttachedShaders),
+		FUNCTION(glGetAttribLocation),
+		FUNCTION(glGetBooleanv),
+		FUNCTION(glGetBufferParameteri64v),
+		FUNCTION(glGetBufferParameteriv),
+		FUNCTION(glGetBufferPointerv),
+		FUNCTION(glGetError),
+		FUNCTION(glGetFenceivNV),
+		FUNCTION(glGetFloatv),
+		FUNCTION(glGetFragDataLocation),
+		FUNCTION(glGetFramebufferAttachmentParameteriv),
+		FUNCTION(glGetFramebufferAttachmentParameterivOES),
+		FUNCTION(glGetGraphicsResetStatusEXT),
+		FUNCTION(glGetInteger64i_v),
+		FUNCTION(glGetInteger64v),
+		FUNCTION(glGetIntegeri_v),
+		FUNCTION(glGetIntegerv),
+		FUNCTION(glGetInternalformativ),
+		FUNCTION(glGetProgramBinary),
+		FUNCTION(glGetProgramInfoLog),
+		FUNCTION(glGetProgramiv),
+		FUNCTION(glGetQueryObjectuiv),
+		FUNCTION(glGetQueryObjectuivEXT),
+		FUNCTION(glGetQueryiv),
+		FUNCTION(glGetQueryivEXT),
+		FUNCTION(glGetRenderbufferParameteriv),
+		FUNCTION(glGetRenderbufferParameterivOES),
+		FUNCTION(glGetSamplerParameterfv),
+		FUNCTION(glGetSamplerParameteriv),
+		FUNCTION(glGetShaderInfoLog),
+		FUNCTION(glGetShaderPrecisionFormat),
+		FUNCTION(glGetShaderSource),
+		FUNCTION(glGetShaderiv),
+		FUNCTION(glGetString),
+		FUNCTION(glGetStringi),
+		FUNCTION(glGetSynciv),
+		FUNCTION(glGetTexParameterfv),
+		FUNCTION(glGetTexParameteriv),
+		FUNCTION(glGetTransformFeedbackVarying),
+		FUNCTION(glGetUniformBlockIndex),
+		FUNCTION(glGetUniformIndices),
+		FUNCTION(glGetUniformLocation),
+		FUNCTION(glGetUniformfv),
+		FUNCTION(glGetUniformiv),
+		FUNCTION(glGetUniformuiv),
+		FUNCTION(glGetVertexAttribIiv),
+		FUNCTION(glGetVertexAttribIuiv),
+		FUNCTION(glGetVertexAttribPointerv),
+		FUNCTION(glGetVertexAttribfv),
+		FUNCTION(glGetVertexAttribiv),
+		FUNCTION(glGetnUniformfvEXT),
+		FUNCTION(glGetnUniformivEXT),
+		FUNCTION(glHint),
+		FUNCTION(glInvalidateFramebuffer),
+		FUNCTION(glInvalidateSubFramebuffer),
+		FUNCTION(glIsBuffer),
+		FUNCTION(glIsEnabled),
+		FUNCTION(glIsFenceNV),
+		FUNCTION(glIsFramebuffer),
+		FUNCTION(glIsFramebufferOES),
+		FUNCTION(glIsProgram),
+		FUNCTION(glIsQuery),
+		FUNCTION(glIsQueryEXT),
+		FUNCTION(glIsRenderbuffer),
+		FUNCTION(glIsRenderbufferOES),
+		FUNCTION(glIsSampler),
+		FUNCTION(glIsShader),
+		FUNCTION(glIsSync),
+		FUNCTION(glIsTexture),
+		FUNCTION(glIsTransformFeedback),
+		FUNCTION(glIsVertexArray),
+		FUNCTION(glLineWidth),
+		FUNCTION(glLinkProgram),
+		FUNCTION(glMapBufferRange),
+		FUNCTION(glPauseTransformFeedback),
+		FUNCTION(glPixelStorei),
+		FUNCTION(glPolygonOffset),
+		FUNCTION(glProgramBinary),
+		FUNCTION(glProgramParameteri),
+		FUNCTION(glReadBuffer),
+		FUNCTION(glReadPixels),
+		FUNCTION(glReadnPixelsEXT),
+		FUNCTION(glReleaseShaderCompiler),
+		FUNCTION(glRenderbufferStorage),
+		FUNCTION(glRenderbufferStorageMultisample),
+		FUNCTION(glRenderbufferStorageMultisampleANGLE),
+		FUNCTION(glRenderbufferStorageOES),
+		FUNCTION(glResumeTransformFeedback),
+		FUNCTION(glSampleCoverage),
+		FUNCTION(glSamplerParameterf),
+		FUNCTION(glSamplerParameterfv),
+		FUNCTION(glSamplerParameteri),
+		FUNCTION(glSamplerParameteriv),
+		FUNCTION(glScissor),
+		FUNCTION(glSetFenceNV),
+		FUNCTION(glShaderBinary),
+		FUNCTION(glShaderSource),
+		FUNCTION(glStencilFunc),
+		FUNCTION(glStencilFuncSeparate),
+		FUNCTION(glStencilMask),
+		FUNCTION(glStencilMaskSeparate),
+		FUNCTION(glStencilOp),
+		FUNCTION(glStencilOpSeparate),
+		FUNCTION(glTestFenceNV),
+		FUNCTION(glTexImage2D),
+		FUNCTION(glTexImage3D),
+		FUNCTION(glTexImage3DOES),
+		FUNCTION(glTexParameterf),
+		FUNCTION(glTexParameterfv),
+		FUNCTION(glTexParameteri),
+		FUNCTION(glTexParameteriv),
+		FUNCTION(glTexStorage2D),
+		FUNCTION(glTexStorage3D),
+		FUNCTION(glTexSubImage2D),
+		FUNCTION(glTexSubImage3D),
+		FUNCTION(glTransformFeedbackVaryings),
+		FUNCTION(glUniform1f),
+		FUNCTION(glUniform1fv),
+		FUNCTION(glUniform1i),
+		FUNCTION(glUniform1iv),
+		FUNCTION(glUniform1ui),
+		FUNCTION(glUniform1uiv),
+		FUNCTION(glUniform2f),
+		FUNCTION(glUniform2fv),
+		FUNCTION(glUniform2i),
+		FUNCTION(glUniform2iv),
+		FUNCTION(glUniform2ui),
+		FUNCTION(glUniform2uiv),
+		FUNCTION(glUniform3f),
+		FUNCTION(glUniform3fv),
+		FUNCTION(glUniform3i),
+		FUNCTION(glUniform3iv),
+		FUNCTION(glUniform3ui),
+		FUNCTION(glUniform3uiv),
+		FUNCTION(glUniform4f),
+		FUNCTION(glUniform4fv),
+		FUNCTION(glUniform4i),
+		FUNCTION(glUniform4iv),
+		FUNCTION(glUniform4ui),
+		FUNCTION(glUniform4uiv),
+		FUNCTION(glUniformBlockBinding),
+		FUNCTION(glUniformMatrix2fv),
+		FUNCTION(glUniformMatrix2x3fv),
+		FUNCTION(glUniformMatrix2x4fv),
+		FUNCTION(glUniformMatrix3fv),
+		FUNCTION(glUniformMatrix3x2fv),
+		FUNCTION(glUniformMatrix3x4fv),
+		FUNCTION(glUniformMatrix4fv),
+		FUNCTION(glUniformMatrix4x2fv),
+		FUNCTION(glUniformMatrix4x3fv),
+		FUNCTION(glUnmapBuffer),
+		FUNCTION(glUseProgram),
+		FUNCTION(glValidateProgram),
+		FUNCTION(glVertexAttrib1f),
+		FUNCTION(glVertexAttrib1fv),
+		FUNCTION(glVertexAttrib2f),
+		FUNCTION(glVertexAttrib2fv),
+		FUNCTION(glVertexAttrib3f),
+		FUNCTION(glVertexAttrib3fv),
+		FUNCTION(glVertexAttrib4f),
+		FUNCTION(glVertexAttrib4fv),
+		FUNCTION(glVertexAttribDivisor),
+		FUNCTION(glVertexAttribI4i),
+		FUNCTION(glVertexAttribI4iv),
+		FUNCTION(glVertexAttribI4ui),
+		FUNCTION(glVertexAttribI4uiv),
+		FUNCTION(glVertexAttribIPointer),
+		FUNCTION(glVertexAttribPointer),
+		FUNCTION(glViewport),
+		FUNCTION(glWaitSync),
+
+		#undef FUNCTION
+	};
+
+	static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
+	static const Function *const glFunctionsEnd = glFunctions + numFunctions;
+
+	Function needle;
+	needle.name = procname;
+
+	if(procname && strncmp("gl", procname, 2) == 0)
+	{
+		const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
+		if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
 		{
-			return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
+			return (__eglMustCastToProperFunctionPointerType)result->address;
 		}
 	}