Split platform functions from entrypoints

Test: Built, flashed, ran some GLES apps
Bug: 110883880
Change-Id: I8697002582c9ca4deea926c298c5e9ab7ac39580
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 78309d4..fb6a221 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -141,6 +141,7 @@
         "EGL/egl_display.cpp",
         "EGL/egl_object.cpp",
         "EGL/egl.cpp",
+        "EGL/eglApi.cpp",
         "EGL/egl_platform_entries.cpp",
         "EGL/Loader.cpp",
         "EGL/egl_angle_platform.cpp",
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 018d979..5aa03a7 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -33,6 +33,7 @@
 #endif
 #include <vndksupport/linker.h>
 
+#include "egl_platform_entries.h"
 #include "egl_trace.h"
 #include "egldefs.h"
 
@@ -237,12 +238,12 @@
 
     setEmulatorGlesValue();
 
-    dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2);
+    dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2 | PLATFORM);
     if (dso) {
         hnd = new driver_t(dso);
     } else {
         // Always load EGL first
-        dso = load_driver("EGL", cnx, EGL);
+        dso = load_driver("EGL", cnx, EGL | PLATFORM);
         if (dso) {
             hnd = new driver_t(dso);
             hnd->set( load_driver("GLESv1_CM", cnx, GLESv1_CM), GLESv1_CM );
@@ -623,6 +624,25 @@
             return nullptr;
     }
 
+    if (mask & PLATFORM) {
+        // For each entrypoint tracked by the platform
+        char const* const* entries = platform_names;
+        EGLFuncPointer* curr = reinterpret_cast<EGLFuncPointer*>(&cnx->platform);
+
+        while (*entries) {
+            const char* name = *entries;
+            EGLFuncPointer f = FindPlatformImplAddr(name);
+
+            if (f == nullptr) {
+                // If no entry found, update the lookup table: sPlatformImplMap
+                ALOGE("No entry found in platform lookup table for %s", name);
+            }
+
+            *curr++ = f;
+            entries++;
+        }
+    }
+
     if (mask & EGL) {
         getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
 
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 6a32bb3..93c33a8 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -33,7 +33,8 @@
     enum {
         EGL         = 0x01,
         GLESv1_CM   = 0x02,
-        GLESv2      = 0x04
+        GLESv2      = 0x04,
+        PLATFORM    = 0x08
     };
     struct driver_t {
         explicit driver_t(void* gles);
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index e292b80..d0cfada 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -167,6 +167,10 @@
     return (GLint)c->tokenized_gl_extensions.size();
 }
 
+egl_connection_t* egl_get_connection() {
+    return &gEGLImpl;
+}
+
 // ----------------------------------------------------------------------------
 
 // this mutex protects:
@@ -257,6 +261,11 @@
     nullptr
 };
 
+char const * const platform_names[] = {
+    #include "platform_entries.in"
+    nullptr
+};
+
 #undef GL_ENTRY
 #undef EGL_ENTRY
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
new file mode 100644
index 0000000..8202c4e
--- /dev/null
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -0,0 +1,585 @@
+/*
+ ** Copyright 2018, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "../egl_impl.h"
+
+#include "egl_layers.h"
+#include "egl_platform_entries.h"
+#include "egl_tls.h"
+#include "egl_trace.h"
+
+using namespace android;
+
+namespace android {
+
+extern EGLBoolean egl_init_drivers();
+
+} // namespace android
+
+static inline void clearError() {
+    egl_tls_t::clearError();
+}
+
+EGLDisplay eglGetDisplay(EGLNativeDisplayType display) {
+    ATRACE_CALL();
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+    }
+
+    // Call down the chain, which usually points directly to the impl
+    // but may also be routed through layers
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetDisplay(display);
+}
+
+EGLBoolean eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglInitialize(dpy, major, minor);
+}
+
+EGLBoolean eglTerminate(EGLDisplay dpy) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglTerminate(dpy);
+}
+
+EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size,
+                         EGLint* num_config) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetConfigs(dpy, configs, config_size, num_config);
+}
+
+EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs,
+                           EGLint config_size, EGLint* num_config) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglChooseConfig(dpy, attrib_list, configs, config_size, num_config);
+}
+
+EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetConfigAttrib(dpy, config, attribute, value);
+}
+
+EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window,
+                                  const EGLint* attrib_list) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglCreateWindowSurface(dpy, config, window, attrib_list);
+}
+
+EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap,
+                                  const EGLint* attrib_list) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglCreatePixmapSurface(dpy, config, pixmap, attrib_list);
+}
+
+EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglCreatePbufferSurface(dpy, config, attrib_list);
+}
+
+EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglDestroySurface(dpy, surface);
+}
+
+EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint* value) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglQuerySurface(dpy, surface, attribute, value);
+}
+
+void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
+    ATRACE_CALL();
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    cnx->platform.eglBeginFrame(dpy, surface);
+}
+
+EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
+                            const EGLint* attrib_list) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglCreateContext(dpy, config, share_list, attrib_list);
+}
+
+EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglDestroyContext(dpy, ctx);
+}
+
+EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglMakeCurrent(dpy, draw, read, ctx);
+}
+
+EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglQueryContext(dpy, ctx, attribute, value);
+}
+
+EGLContext eglGetCurrentContext(void) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetCurrentContext();
+}
+
+EGLSurface eglGetCurrentSurface(EGLint readdraw) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetCurrentSurface(readdraw);
+}
+
+EGLDisplay eglGetCurrentDisplay(void) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetCurrentDisplay();
+}
+
+EGLBoolean eglWaitGL(void) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglWaitGL();
+}
+
+EGLBoolean eglWaitNative(EGLint engine) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglWaitNative(engine);
+}
+
+EGLint eglGetError(void) {
+    egl_connection_t* const cnx = &gEGLImpl;
+    if (cnx->platform.eglGetError) {
+        return cnx->platform.eglGetError();
+    } else {
+        return egl_tls_t::getError();
+    }
+}
+
+__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char* procname) {
+    // eglGetProcAddress() could be the very first function called
+    // in which case we must make sure we've initialized ourselves, this
+    // happens the first time egl_get_display() is called.
+
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        setError(EGL_BAD_PARAMETER, NULL);
+        return nullptr;
+    }
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetProcAddress(procname);
+}
+
+EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw, EGLint* rects,
+                                       EGLint n_rects) {
+    ATRACE_CALL();
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglSwapBuffersWithDamageKHR(dpy, draw, rects, n_rects);
+}
+
+EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
+    ATRACE_CALL();
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglSwapBuffers(dpy, surface);
+}
+
+EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglCopyBuffers(dpy, surface, target);
+}
+
+const char* eglQueryString(EGLDisplay dpy, EGLint name) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglQueryString(dpy, name);
+}
+
+extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglQueryStringImplementationANDROID(dpy, name);
+}
+
+EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglSurfaceAttrib(dpy, surface, attribute, value);
+}
+
+EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglBindTexImage(dpy, surface, buffer);
+}
+
+EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglReleaseTexImage(dpy, surface, buffer);
+}
+
+EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglSwapInterval(dpy, interval);
+}
+
+EGLBoolean eglWaitClient(void) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglWaitClient();
+}
+
+EGLBoolean eglBindAPI(EGLenum api) {
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
+    }
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglBindAPI(api);
+}
+
+EGLenum eglQueryAPI(void) {
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
+    }
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglQueryAPI();
+}
+
+EGLBoolean eglReleaseThread(void) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglReleaseThread();
+}
+
+EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
+                                            EGLConfig config, const EGLint* attrib_list) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglCreatePbufferFromClientBuffer(dpy, buftype, buffer, config,
+                                                          attrib_list);
+}
+
+EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, const EGLint* attrib_list) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglLockSurfaceKHR(dpy, surface, attrib_list);
+}
+
+EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglUnlockSurfaceKHR(dpy, surface);
+}
+
+EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+                              EGLClientBuffer buffer, const EGLint* attrib_list) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
+}
+
+EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglDestroyImageKHR(dpy, img);
+}
+
+EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglCreateSyncKHR(dpy, type, attrib_list);
+}
+
+EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglDestroySyncKHR(dpy, sync);
+}
+
+EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglSignalSyncKHR(dpy, sync, mode);
+}
+
+EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglClientWaitSyncKHR(dpy, sync, flags, timeout);
+}
+
+EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint* value) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetSyncAttribKHR(dpy, sync, attribute, value);
+}
+
+EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint* attrib_list) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglCreateStreamKHR(dpy, attrib_list);
+}
+
+EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglDestroyStreamKHR(dpy, stream);
+}
+
+EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute,
+                              EGLint value) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglStreamAttribKHR(dpy, stream, attribute, value);
+}
+
+EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute,
+                             EGLint* value) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglQueryStreamKHR(dpy, stream, attribute, value);
+}
+
+EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute,
+                                EGLuint64KHR* value) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglQueryStreamu64KHR(dpy, stream, attribute, value);
+}
+
+EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute,
+                                 EGLTimeKHR* value) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglQueryStreamTimeKHR(dpy, stream, attribute, value);
+}
+
+EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream,
+                                             const EGLint* attrib_list) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglCreateStreamProducerSurfaceKHR(dpy, config, stream, attrib_list);
+}
+
+EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, EGLStreamKHR stream) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglStreamConsumerGLTextureExternalKHR(dpy, stream);
+}
+
+EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglStreamConsumerAcquireKHR(dpy, stream);
+}
+
+EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglStreamConsumerReleaseKHR(dpy, stream);
+}
+
+EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(EGLDisplay dpy, EGLStreamKHR stream) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetStreamFileDescriptorKHR(dpy, stream);
+}
+
+EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(EGLDisplay dpy,
+                                                  EGLNativeFileDescriptorKHR file_descriptor) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglCreateStreamFromFileDescriptorKHR(dpy, file_descriptor);
+}
+
+EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
+    clearError();
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglWaitSyncKHR(dpy, sync, flags);
+}
+
+EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglDupNativeFenceFDANDROID(dpy, sync);
+}
+
+EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface, EGLnsecsANDROID time) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglPresentationTimeANDROID(dpy, surface, time);
+}
+
+EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer* buffer) {
+    clearError();
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetNativeClientBufferANDROID(buffer);
+}
+
+EGLuint64NV eglGetSystemTimeFrequencyNV() {
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
+    }
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetSystemTimeFrequencyNV();
+}
+
+EGLuint64NV eglGetSystemTimeNV() {
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
+    }
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetSystemTimeNV();
+}
+
+EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface, EGLint* rects,
+                                 EGLint n_rects) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglSetDamageRegionKHR(dpy, surface, rects, n_rects);
+}
+
+EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR* frameId) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetNextFrameIdANDROID(dpy, surface, frameId);
+}
+
+EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps,
+                                         const EGLint* names, EGLnsecsANDROID* values) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetCompositorTimingANDROID(dpy, surface, numTimestamps, names, values);
+}
+
+EGLBoolean eglGetCompositorTimingSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint name) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetCompositorTimingSupportedANDROID(dpy, surface, name);
+}
+
+EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId,
+                                        EGLint numTimestamps, const EGLint* timestamps,
+                                        EGLnsecsANDROID* values) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetFrameTimestampsANDROID(dpy, surface, frameId, numTimestamps,
+                                                      timestamps, values);
+}
+
+EGLBoolean eglGetFrameTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface,
+                                                EGLint timestamp) {
+    clearError();
+
+    egl_connection_t* const cnx = &gEGLImpl;
+    return cnx->platform.eglGetFrameTimestampSupportedANDROID(dpy, surface, timestamp);
+}
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index d2dc514..296ee44 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -16,6 +16,8 @@
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
+#include "egl_platform_entries.h"
+
 #include <ctype.h>
 #include <dlfcn.h>
 #include <stdlib.h>
@@ -268,30 +270,19 @@
 extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
 extern gl_hooks_t gHooksTrace;
 
-} // namespace android;
-
-
 // ----------------------------------------------------------------------------
 
-static inline void clearError() { egl_tls_t::clearError(); }
 static inline EGLContext getContext() { return egl_tls_t::getContext(); }
 
 // ----------------------------------------------------------------------------
 
-EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
+EGLDisplay eglGetDisplayImpl(EGLNativeDisplayType display)
 {
-    ATRACE_CALL();
-    clearError();
-
     uintptr_t index = reinterpret_cast<uintptr_t>(display);
     if (index >= NUM_DISPLAYS) {
         return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
     }
 
-    if (egl_init_drivers() == EGL_FALSE) {
-        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
-    }
-
     EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
     return dpy;
 }
@@ -300,10 +291,8 @@
 // Initialization
 // ----------------------------------------------------------------------------
 
-EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+EGLBoolean eglInitializeImpl(EGLDisplay dpy, EGLint *major, EGLint *minor)
 {
-    clearError();
-
     egl_display_ptr dp = get_display(dpy);
     if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
 
@@ -312,14 +301,12 @@
     return res;
 }
 
-EGLBoolean eglTerminate(EGLDisplay dpy)
+EGLBoolean eglTerminateImpl(EGLDisplay dpy)
 {
     // NOTE: don't unload the drivers b/c some APIs can be called
     // after eglTerminate() has been called. eglTerminate() only
     // terminates an EGLDisplay, not a EGL itself.
 
-    clearError();
-
     egl_display_ptr dp = get_display(dpy);
     if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
 
@@ -332,12 +319,10 @@
 // configuration
 // ----------------------------------------------------------------------------
 
-EGLBoolean eglGetConfigs(   EGLDisplay dpy,
-                            EGLConfig *configs,
-                            EGLint config_size, EGLint *num_config)
+EGLBoolean eglGetConfigsImpl(EGLDisplay dpy,
+                             EGLConfig *configs,
+                             EGLint config_size, EGLint *num_config)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -357,12 +342,10 @@
     return res;
 }
 
-EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
-                            EGLConfig *configs, EGLint config_size,
-                            EGLint *num_config)
+EGLBoolean eglChooseConfigImpl( EGLDisplay dpy, const EGLint *attrib_list,
+                                EGLConfig *configs, EGLint config_size,
+                                EGLint *num_config)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -436,11 +419,9 @@
     return res;
 }
 
-EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
+EGLBoolean eglGetConfigAttribImpl(EGLDisplay dpy, EGLConfig config,
         EGLint attribute, EGLint *value)
 {
-    clearError();
-
     egl_connection_t* cnx = nullptr;
     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
     if (!dp) return EGL_FALSE;
@@ -701,12 +682,11 @@
     return EGL_TRUE;
 }
 
-EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
-                                    NativeWindowType window,
-                                    const EGLint *attrib_list)
+EGLSurface eglCreateWindowSurfaceImpl(  EGLDisplay dpy, EGLConfig config,
+                                        NativeWindowType window,
+                                        const EGLint *attrib_list)
 {
     const EGLint *origAttribList = attrib_list;
-    clearError();
 
     egl_connection_t* cnx = nullptr;
     egl_display_ptr dp = validate_display_connection(dpy, cnx);
@@ -791,12 +771,10 @@
     return EGL_NO_SURFACE;
 }
 
-EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
-                                    NativePixmapType pixmap,
-                                    const EGLint *attrib_list)
+EGLSurface eglCreatePixmapSurfaceImpl(  EGLDisplay dpy, EGLConfig config,
+                                        NativePixmapType pixmap,
+                                        const EGLint *attrib_list)
 {
-    clearError();
-
     egl_connection_t* cnx = nullptr;
     egl_display_ptr dp = validate_display_connection(dpy, cnx);
     if (dp) {
@@ -826,11 +804,9 @@
     return EGL_NO_SURFACE;
 }
 
-EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
-                                    const EGLint *attrib_list)
+EGLSurface eglCreatePbufferSurfaceImpl( EGLDisplay dpy, EGLConfig config,
+                                        const EGLint *attrib_list)
 {
-    clearError();
-
     egl_connection_t* cnx = nullptr;
     egl_display_ptr dp = validate_display_connection(dpy, cnx);
     if (dp) {
@@ -860,10 +836,8 @@
     return EGL_NO_SURFACE;
 }
 
-EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
+EGLBoolean eglDestroySurfaceImpl(EGLDisplay dpy, EGLSurface surface)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -879,11 +853,9 @@
     return result;
 }
 
-EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
-                            EGLint attribute, EGLint *value)
+EGLBoolean eglQuerySurfaceImpl( EGLDisplay dpy, EGLSurface surface,
+                                EGLint attribute, EGLint *value)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -902,10 +874,7 @@
     return s->cnx->egl.eglQuerySurface(dp->disp.dpy, s->surface, attribute, value);
 }
 
-void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
-    ATRACE_CALL();
-    clearError();
-
+void EGLAPI eglBeginFrameImpl(EGLDisplay dpy, EGLSurface surface) {
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) {
         return;
@@ -921,11 +890,9 @@
 // Contexts
 // ----------------------------------------------------------------------------
 
-EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
-                            EGLContext share_list, const EGLint *attrib_list)
+EGLContext eglCreateContextImpl(EGLDisplay dpy, EGLConfig config,
+                                EGLContext share_list, const EGLint *attrib_list)
 {
-    clearError();
-
     egl_connection_t* cnx = nullptr;
     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
     if (dp) {
@@ -962,10 +929,8 @@
     return EGL_NO_CONTEXT;
 }
 
-EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+EGLBoolean eglDestroyContextImpl(EGLDisplay dpy, EGLContext ctx)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp)
         return EGL_FALSE;
@@ -982,11 +947,9 @@
     return result;
 }
 
-EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
-                            EGLSurface read, EGLContext ctx)
+EGLBoolean eglMakeCurrentImpl(  EGLDisplay dpy, EGLSurface draw,
+                                EGLSurface read, EGLContext ctx)
 {
-    clearError();
-
     egl_display_ptr dp = validate_display(dpy);
     if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
 
@@ -1076,12 +1039,9 @@
     return result;
 }
 
-
-EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
-                            EGLint attribute, EGLint *value)
+EGLBoolean eglQueryContextImpl( EGLDisplay dpy, EGLContext ctx,
+                                EGLint attribute, EGLint *value)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1094,24 +1054,19 @@
 
 }
 
-EGLContext eglGetCurrentContext(void)
+EGLContext eglGetCurrentContextImpl(void)
 {
     // could be called before eglInitialize(), but we wouldn't have a context
     // then, and this function would correctly return EGL_NO_CONTEXT.
-
-    clearError();
-
     EGLContext ctx = getContext();
     return ctx;
 }
 
-EGLSurface eglGetCurrentSurface(EGLint readdraw)
+EGLSurface eglGetCurrentSurfaceImpl(EGLint readdraw)
 {
     // could be called before eglInitialize(), but we wouldn't have a context
     // then, and this function would correctly return EGL_NO_SURFACE.
 
-    clearError();
-
     EGLContext ctx = getContext();
     if (ctx) {
         egl_context_t const * const c = get_context(ctx);
@@ -1125,13 +1080,11 @@
     return EGL_NO_SURFACE;
 }
 
-EGLDisplay eglGetCurrentDisplay(void)
+EGLDisplay eglGetCurrentDisplayImpl(void)
 {
     // could be called before eglInitialize(), but we wouldn't have a context
     // then, and this function would correctly return EGL_NO_DISPLAY.
 
-    clearError();
-
     EGLContext ctx = getContext();
     if (ctx) {
         egl_context_t const * const c = get_context(ctx);
@@ -1141,10 +1094,8 @@
     return EGL_NO_DISPLAY;
 }
 
-EGLBoolean eglWaitGL(void)
+EGLBoolean eglWaitGLImpl(void)
 {
-    clearError();
-
     egl_connection_t* const cnx = &gEGLImpl;
     if (!cnx->dso)
         return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
@@ -1152,10 +1103,8 @@
     return cnx->egl.eglWaitGL();
 }
 
-EGLBoolean eglWaitNative(EGLint engine)
+EGLBoolean eglWaitNativeImpl(EGLint engine)
 {
-    clearError();
-
     egl_connection_t* const cnx = &gEGLImpl;
     if (!cnx->dso)
         return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
@@ -1163,7 +1112,7 @@
     return cnx->egl.eglWaitNative(engine);
 }
 
-EGLint eglGetError(void)
+EGLint eglGetErrorImpl(void)
 {
     EGLint err = EGL_SUCCESS;
     egl_connection_t* const cnx = &gEGLImpl;
@@ -1193,19 +1142,8 @@
     return nullptr;
 }
 
-__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
+__eglMustCastToProperFunctionPointerType eglGetProcAddressImpl(const char *procname)
 {
-    // eglGetProcAddress() could be the very first function called
-    // in which case we must make sure we've initialized ourselves, this
-    // happens the first time egl_get_display() is called.
-
-    clearError();
-
-    if (egl_init_drivers() == EGL_FALSE) {
-        setError(EGL_BAD_PARAMETER, NULL);
-        return  nullptr;
-    }
-
     if (FILTER_EXTENSIONS(procname)) {
         return nullptr;
     }
@@ -1346,12 +1284,9 @@
     std::mutex mMutex;
 };
 
-EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
+EGLBoolean eglSwapBuffersWithDamageKHRImpl(EGLDisplay dpy, EGLSurface draw,
         EGLint *rects, EGLint n_rects)
 {
-    ATRACE_CALL();
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1416,16 +1351,14 @@
     }
 }
 
-EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
+EGLBoolean eglSwapBuffersImpl(EGLDisplay dpy, EGLSurface surface)
 {
-    return eglSwapBuffersWithDamageKHR(dpy, surface, nullptr, 0);
+    return eglSwapBuffersWithDamageKHRImpl(dpy, surface, nullptr, 0);
 }
 
-EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
-                            NativePixmapType target)
+EGLBoolean eglCopyBuffersImpl(  EGLDisplay dpy, EGLSurface surface,
+                                NativePixmapType target)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1437,10 +1370,8 @@
     return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
 }
 
-const char* eglQueryString(EGLDisplay dpy, EGLint name)
+const char* eglQueryStringImpl(EGLDisplay dpy, EGLint name)
 {
-    clearError();
-
     // Generate an error quietly when client extensions (as defined by
     // EGL_EXT_client_extensions) are queried.  We do not want to rely on
     // validate_display to generate the error as validate_display would log
@@ -1469,10 +1400,8 @@
     return setError(EGL_BAD_PARAMETER, (const char *)nullptr);
 }
 
-extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
+EGLAPI const char* eglQueryStringImplementationANDROIDImpl(EGLDisplay dpy, EGLint name)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return (const char *) nullptr;
 
@@ -1495,11 +1424,9 @@
 // EGL 1.1
 // ----------------------------------------------------------------------------
 
-EGLBoolean eglSurfaceAttrib(
+EGLBoolean eglSurfaceAttribImpl(
         EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1536,11 +1463,9 @@
     return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
 }
 
-EGLBoolean eglBindTexImage(
+EGLBoolean eglBindTexImageImpl(
         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1556,11 +1481,9 @@
     return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
 }
 
-EGLBoolean eglReleaseTexImage(
+EGLBoolean eglReleaseTexImageImpl(
         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1576,10 +1499,8 @@
     return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
 }
 
-EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
+EGLBoolean eglSwapIntervalImpl(EGLDisplay dpy, EGLint interval)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1597,10 +1518,8 @@
 // EGL 1.2
 // ----------------------------------------------------------------------------
 
-EGLBoolean eglWaitClient(void)
+EGLBoolean eglWaitClientImpl(void)
 {
-    clearError();
-
     egl_connection_t* const cnx = &gEGLImpl;
     if (!cnx->dso)
         return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
@@ -1614,14 +1533,8 @@
     return res;
 }
 
-EGLBoolean eglBindAPI(EGLenum api)
+EGLBoolean eglBindAPIImpl(EGLenum api)
 {
-    clearError();
-
-    if (egl_init_drivers() == EGL_FALSE) {
-        return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
-    }
-
     // bind this API on all EGLs
     EGLBoolean res = EGL_TRUE;
     egl_connection_t* const cnx = &gEGLImpl;
@@ -1631,14 +1544,8 @@
     return res;
 }
 
-EGLenum eglQueryAPI(void)
+EGLenum eglQueryAPIImpl(void)
 {
-    clearError();
-
-    if (egl_init_drivers() == EGL_FALSE) {
-        return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
-    }
-
     egl_connection_t* const cnx = &gEGLImpl;
     if (cnx->dso && cnx->egl.eglQueryAPI) {
         return cnx->egl.eglQueryAPI();
@@ -1648,10 +1555,8 @@
     return EGL_OPENGL_ES_API;
 }
 
-EGLBoolean eglReleaseThread(void)
+EGLBoolean eglReleaseThreadImpl(void)
 {
-    clearError();
-
     egl_connection_t* const cnx = &gEGLImpl;
     if (cnx->dso && cnx->egl.eglReleaseThread) {
         cnx->egl.eglReleaseThread();
@@ -1664,12 +1569,10 @@
     return EGL_TRUE;
 }
 
-EGLSurface eglCreatePbufferFromClientBuffer(
+EGLSurface eglCreatePbufferFromClientBufferImpl(
           EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
           EGLConfig config, const EGLint *attrib_list)
 {
-    clearError();
-
     egl_connection_t* cnx = nullptr;
     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
     if (!dp) return EGL_FALSE;
@@ -1684,11 +1587,9 @@
 // EGL_EGLEXT_VERSION 3
 // ----------------------------------------------------------------------------
 
-EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
+EGLBoolean eglLockSurfaceKHRImpl(EGLDisplay dpy, EGLSurface surface,
         const EGLint *attrib_list)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1704,10 +1605,8 @@
     return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
 }
 
-EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
+EGLBoolean eglUnlockSurfaceKHRImpl(EGLDisplay dpy, EGLSurface surface)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1722,11 +1621,9 @@
     return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
 }
 
-EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+EGLImageKHR eglCreateImageKHRImpl(EGLDisplay dpy, EGLContext ctx, EGLenum target,
         EGLClientBuffer buffer, const EGLint *attrib_list)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_NO_IMAGE_KHR;
 
@@ -1744,10 +1641,8 @@
     return result;
 }
 
-EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
+EGLBoolean eglDestroyImageKHRImpl(EGLDisplay dpy, EGLImageKHR img)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1764,10 +1659,8 @@
 // ----------------------------------------------------------------------------
 
 
-EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
+EGLSyncKHR eglCreateSyncKHRImpl(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_NO_SYNC_KHR;
 
@@ -1779,10 +1672,8 @@
     return result;
 }
 
-EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
+EGLBoolean eglDestroySyncKHRImpl(EGLDisplay dpy, EGLSyncKHR sync)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1794,9 +1685,7 @@
     return result;
 }
 
-EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
-    clearError();
-
+EGLBoolean eglSignalSyncKHRImpl(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1809,11 +1698,9 @@
     return result;
 }
 
-EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
+EGLint eglClientWaitSyncKHRImpl(EGLDisplay dpy, EGLSyncKHR sync,
         EGLint flags, EGLTimeKHR timeout)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1826,11 +1713,9 @@
     return result;
 }
 
-EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
+EGLBoolean eglGetSyncAttribKHRImpl(EGLDisplay dpy, EGLSyncKHR sync,
         EGLint attribute, EGLint *value)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1843,10 +1728,8 @@
     return result;
 }
 
-EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
+EGLStreamKHR eglCreateStreamKHRImpl(EGLDisplay dpy, const EGLint *attrib_list)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_NO_STREAM_KHR;
 
@@ -1859,10 +1742,8 @@
     return result;
 }
 
-EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
+EGLBoolean eglDestroyStreamKHRImpl(EGLDisplay dpy, EGLStreamKHR stream)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1875,11 +1756,9 @@
     return result;
 }
 
-EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
+EGLBoolean eglStreamAttribKHRImpl(EGLDisplay dpy, EGLStreamKHR stream,
         EGLenum attribute, EGLint value)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1892,11 +1771,9 @@
     return result;
 }
 
-EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
+EGLBoolean eglQueryStreamKHRImpl(EGLDisplay dpy, EGLStreamKHR stream,
         EGLenum attribute, EGLint *value)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1909,11 +1786,9 @@
     return result;
 }
 
-EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
+EGLBoolean eglQueryStreamu64KHRImpl(EGLDisplay dpy, EGLStreamKHR stream,
         EGLenum attribute, EGLuint64KHR *value)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1926,11 +1801,9 @@
     return result;
 }
 
-EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
+EGLBoolean eglQueryStreamTimeKHRImpl(EGLDisplay dpy, EGLStreamKHR stream,
         EGLenum attribute, EGLTimeKHR *value)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1943,11 +1816,9 @@
     return result;
 }
 
-EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
+EGLSurface eglCreateStreamProducerSurfaceKHRImpl(EGLDisplay dpy, EGLConfig config,
         EGLStreamKHR stream, const EGLint *attrib_list)
 {
-    clearError();
-
     egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_NO_SURFACE;
 
@@ -1964,11 +1835,9 @@
     return EGL_NO_SURFACE;
 }
 
-EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
+EGLBoolean eglStreamConsumerGLTextureExternalKHRImpl(EGLDisplay dpy,
         EGLStreamKHR stream)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1981,11 +1850,9 @@
     return result;
 }
 
-EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
+EGLBoolean eglStreamConsumerAcquireKHRImpl(EGLDisplay dpy,
         EGLStreamKHR stream)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -1998,11 +1865,9 @@
     return result;
 }
 
-EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
+EGLBoolean eglStreamConsumerReleaseKHRImpl(EGLDisplay dpy,
         EGLStreamKHR stream)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
@@ -2015,11 +1880,9 @@
     return result;
 }
 
-EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
+EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHRImpl(
         EGLDisplay dpy, EGLStreamKHR stream)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
 
@@ -2032,11 +1895,9 @@
     return result;
 }
 
-EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
+EGLStreamKHR eglCreateStreamFromFileDescriptorKHRImpl(
         EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_NO_STREAM_KHR;
 
@@ -2053,8 +1914,7 @@
 // EGL_EGLEXT_VERSION 15
 // ----------------------------------------------------------------------------
 
-EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
-    clearError();
+EGLint eglWaitSyncKHRImpl(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
     EGLint result = EGL_FALSE;
@@ -2069,10 +1929,8 @@
 // ANDROID extensions
 // ----------------------------------------------------------------------------
 
-EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
+EGLint eglDupNativeFenceFDANDROIDImpl(EGLDisplay dpy, EGLSyncKHR sync)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
 
@@ -2084,11 +1942,9 @@
     return result;
 }
 
-EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
+EGLBoolean eglPresentationTimeANDROIDImpl(EGLDisplay dpy, EGLSurface surface,
         EGLnsecsANDROID time)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) {
         return EGL_FALSE;
@@ -2106,8 +1962,7 @@
     return EGL_TRUE;
 }
 
-EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) {
-    clearError();
+EGLClientBuffer eglGetNativeClientBufferANDROIDImpl(const AHardwareBuffer *buffer) {
     // AHardwareBuffer_to_ANativeWindowBuffer is a platform-only symbol and thus
     // this function cannot be implemented when this libEGL is built for
     // vendors.
@@ -2122,14 +1977,8 @@
 // ----------------------------------------------------------------------------
 // NVIDIA extensions
 // ----------------------------------------------------------------------------
-EGLuint64NV eglGetSystemTimeFrequencyNV()
+EGLuint64NV eglGetSystemTimeFrequencyNVImpl()
 {
-    clearError();
-
-    if (egl_init_drivers() == EGL_FALSE) {
-        return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
-    }
-
     EGLuint64NV ret = 0;
     egl_connection_t* const cnx = &gEGLImpl;
 
@@ -2140,14 +1989,8 @@
     return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
 }
 
-EGLuint64NV eglGetSystemTimeNV()
+EGLuint64NV eglGetSystemTimeNVImpl()
 {
-    clearError();
-
-    if (egl_init_drivers() == EGL_FALSE) {
-        return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
-    }
-
     EGLuint64NV ret = 0;
     egl_connection_t* const cnx = &gEGLImpl;
 
@@ -2161,11 +2004,9 @@
 // ----------------------------------------------------------------------------
 // Partial update extension
 // ----------------------------------------------------------------------------
-EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
+EGLBoolean eglSetDamageRegionKHRImpl(EGLDisplay dpy, EGLSurface surface,
         EGLint *rects, EGLint n_rects)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) {
         setError(EGL_BAD_DISPLAY, EGL_FALSE);
@@ -2187,10 +2028,8 @@
     return EGL_FALSE;
 }
 
-EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
+EGLBoolean eglGetNextFrameIdANDROIDImpl(EGLDisplay dpy, EGLSurface surface,
             EGLuint64KHR *frameId) {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) {
         return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
@@ -2221,11 +2060,9 @@
     return EGL_TRUE;
 }
 
-EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface,
+EGLBoolean eglGetCompositorTimingANDROIDImpl(EGLDisplay dpy, EGLSurface surface,
         EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) {
         return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
@@ -2278,11 +2115,9 @@
     }
 }
 
-EGLBoolean eglGetCompositorTimingSupportedANDROID(
+EGLBoolean eglGetCompositorTimingSupportedANDROIDImpl(
         EGLDisplay dpy, EGLSurface surface, EGLint name)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) {
         return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
@@ -2310,12 +2145,10 @@
     }
 }
 
-EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
+EGLBoolean eglGetFrameTimestampsANDROIDImpl(EGLDisplay dpy, EGLSurface surface,
         EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps,
         EGLnsecsANDROID *values)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) {
         return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
@@ -2398,11 +2231,9 @@
     }
 }
 
-EGLBoolean eglGetFrameTimestampSupportedANDROID(
+EGLBoolean eglGetFrameTimestampSupportedANDROIDImpl(
         EGLDisplay dpy, EGLSurface surface, EGLint timestamp)
 {
-    clearError();
-
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) {
         return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
@@ -2443,3 +2274,182 @@
             return EGL_FALSE;
     }
 }
+
+const GLubyte * glGetStringImpl(GLenum name) {
+    const GLubyte * ret = egl_get_string_for_current_context(name);
+    if (ret == NULL) {
+        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
+        if(_c) ret = _c->glGetString(name);
+    }
+    return ret;
+}
+
+const GLubyte * glGetStringiImpl(GLenum name, GLuint index) {
+    const GLubyte * ret = egl_get_string_for_current_context(name, index);
+    if (ret == NULL) {
+        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
+        if(_c) ret = _c->glGetStringi(name, index);
+    }
+    return ret;
+}
+
+void glGetBooleanvImpl(GLenum pname, GLboolean * data) {
+    if (pname == GL_NUM_EXTENSIONS) {
+        int num_exts = egl_get_num_extensions_for_current_context();
+        if (num_exts >= 0) {
+            *data = num_exts > 0 ? GL_TRUE : GL_FALSE;
+            return;
+        }
+    }
+
+    gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
+    if (_c) _c->glGetBooleanv(pname, data);
+}
+
+void glGetFloatvImpl(GLenum pname, GLfloat * data) {
+    if (pname == GL_NUM_EXTENSIONS) {
+        int num_exts = egl_get_num_extensions_for_current_context();
+        if (num_exts >= 0) {
+            *data = (GLfloat)num_exts;
+            return;
+        }
+    }
+
+    gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
+    if (_c) _c->glGetFloatv(pname, data);
+}
+
+void glGetIntegervImpl(GLenum pname, GLint * data) {
+    if (pname == GL_NUM_EXTENSIONS) {
+        int num_exts = egl_get_num_extensions_for_current_context();
+        if (num_exts >= 0) {
+            *data = (GLint)num_exts;
+            return;
+        }
+    }
+
+    gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
+    if (_c) _c->glGetIntegerv(pname, data);
+}
+
+void glGetInteger64vImpl(GLenum pname, GLint64 * data) {
+    if (pname == GL_NUM_EXTENSIONS) {
+        int num_exts = egl_get_num_extensions_for_current_context();
+        if (num_exts >= 0) {
+            *data = (GLint64)num_exts;
+            return;
+        }
+    }
+
+    gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
+    if (_c) _c->glGetInteger64v(pname, data);
+}
+
+struct implementation_map_t {
+    const char* name;
+    EGLFuncPointer address;
+};
+
+static const implementation_map_t sPlatformImplMap[] = {
+    { "eglGetDisplay", (EGLFuncPointer)&eglGetDisplayImpl },
+    { "eglInitialize", (EGLFuncPointer)&eglInitializeImpl },
+    { "eglTerminate", (EGLFuncPointer)&eglTerminateImpl },
+    { "eglGetConfigs", (EGLFuncPointer)&eglGetConfigsImpl },
+    { "eglChooseConfig", (EGLFuncPointer)&eglChooseConfigImpl },
+    { "eglGetConfigAttrib", (EGLFuncPointer)&eglGetConfigAttribImpl },
+    { "eglCreateWindowSurface", (EGLFuncPointer)&eglCreateWindowSurfaceImpl },
+    { "eglCreatePixmapSurface", (EGLFuncPointer)&eglCreatePixmapSurfaceImpl },
+    { "eglCreatePbufferSurface", (EGLFuncPointer)&eglCreatePbufferSurfaceImpl },
+    { "eglDestroySurface", (EGLFuncPointer)&eglDestroySurfaceImpl },
+    { "eglQuerySurface", (EGLFuncPointer)&eglQuerySurfaceImpl },
+    { "eglBeginFrame", (EGLFuncPointer)&eglBeginFrameImpl },
+    { "eglCreateContext", (EGLFuncPointer)&eglCreateContextImpl },
+    { "eglDestroyContext", (EGLFuncPointer)&eglDestroyContextImpl },
+    { "eglMakeCurrent", (EGLFuncPointer)&eglMakeCurrentImpl },
+    { "eglQueryContext", (EGLFuncPointer)&eglQueryContextImpl },
+    { "eglGetCurrentContext", (EGLFuncPointer)&eglGetCurrentContextImpl },
+    { "eglGetCurrentSurface", (EGLFuncPointer)&eglGetCurrentSurfaceImpl },
+    { "eglGetCurrentDisplay", (EGLFuncPointer)&eglGetCurrentDisplayImpl },
+    { "eglWaitGL", (EGLFuncPointer)&eglWaitGLImpl },
+    { "eglWaitNative", (EGLFuncPointer)&eglWaitNativeImpl },
+    { "eglGetError", (EGLFuncPointer)&eglGetErrorImpl },
+    { "eglSwapBuffersWithDamageKHR", (EGLFuncPointer)&eglSwapBuffersWithDamageKHRImpl },
+    { "eglGetProcAddress", (EGLFuncPointer)&eglGetProcAddressImpl },
+    { "eglSwapBuffers", (EGLFuncPointer)&eglSwapBuffersImpl },
+    { "eglCopyBuffers", (EGLFuncPointer)&eglCopyBuffersImpl },
+    { "eglQueryString", (EGLFuncPointer)&eglQueryStringImpl },
+    { "eglQueryStringImplementationANDROID", (EGLFuncPointer)&eglQueryStringImplementationANDROIDImpl },
+    { "eglSurfaceAttrib", (EGLFuncPointer)&eglSurfaceAttribImpl },
+    { "eglBindTexImage", (EGLFuncPointer)&eglBindTexImageImpl },
+    { "eglReleaseTexImage", (EGLFuncPointer)&eglReleaseTexImageImpl },
+    { "eglSwapInterval", (EGLFuncPointer)&eglSwapIntervalImpl },
+    { "eglWaitClient", (EGLFuncPointer)&eglWaitClientImpl },
+    { "eglBindAPI", (EGLFuncPointer)&eglBindAPIImpl },
+    { "eglQueryAPI", (EGLFuncPointer)&eglQueryAPIImpl },
+    { "eglReleaseThread", (EGLFuncPointer)&eglReleaseThreadImpl },
+    { "eglCreatePbufferFromClientBuffer", (EGLFuncPointer)&eglCreatePbufferFromClientBufferImpl },
+    { "eglLockSurfaceKHR", (EGLFuncPointer)&eglLockSurfaceKHRImpl },
+    { "eglUnlockSurfaceKHR", (EGLFuncPointer)&eglUnlockSurfaceKHRImpl },
+    { "eglCreateImageKHR", (EGLFuncPointer)&eglCreateImageKHRImpl },
+    { "eglDestroyImageKHR", (EGLFuncPointer)&eglDestroyImageKHRImpl },
+    { "eglCreateSyncKHR", (EGLFuncPointer)&eglCreateSyncKHRImpl },
+    { "eglDestroySyncKHR", (EGLFuncPointer)&eglDestroySyncKHRImpl },
+    { "eglSignalSyncKHR", (EGLFuncPointer)&eglSignalSyncKHRImpl },
+    { "eglClientWaitSyncKHR", (EGLFuncPointer)&eglClientWaitSyncKHRImpl },
+    { "eglGetSyncAttribKHR", (EGLFuncPointer)&eglGetSyncAttribKHRImpl },
+    { "eglCreateStreamKHR", (EGLFuncPointer)&eglCreateStreamKHRImpl },
+    { "eglDestroyStreamKHR", (EGLFuncPointer)&eglDestroyStreamKHRImpl },
+    { "eglStreamAttribKHR", (EGLFuncPointer)&eglStreamAttribKHRImpl },
+    { "eglQueryStreamKHR", (EGLFuncPointer)&eglQueryStreamKHRImpl },
+    { "eglQueryStreamu64KHR", (EGLFuncPointer)&eglQueryStreamu64KHRImpl },
+    { "eglQueryStreamTimeKHR", (EGLFuncPointer)&eglQueryStreamTimeKHRImpl },
+    { "eglCreateStreamProducerSurfaceKHR", (EGLFuncPointer)&eglCreateStreamProducerSurfaceKHRImpl },
+    { "eglStreamConsumerGLTextureExternalKHR", (EGLFuncPointer)&eglStreamConsumerGLTextureExternalKHRImpl },
+    { "eglStreamConsumerAcquireKHR", (EGLFuncPointer)&eglStreamConsumerAcquireKHRImpl },
+    { "eglStreamConsumerReleaseKHR", (EGLFuncPointer)&eglStreamConsumerReleaseKHRImpl },
+    { "eglGetStreamFileDescriptorKHR", (EGLFuncPointer)&eglGetStreamFileDescriptorKHRImpl },
+    { "eglCreateStreamFromFileDescriptorKHR", (EGLFuncPointer)&eglCreateStreamFromFileDescriptorKHRImpl },
+    { "eglWaitSyncKHR", (EGLFuncPointer)&eglWaitSyncKHRImpl },
+    { "eglDupNativeFenceFDANDROID", (EGLFuncPointer)&eglDupNativeFenceFDANDROIDImpl },
+    { "eglPresentationTimeANDROID", (EGLFuncPointer)&eglPresentationTimeANDROIDImpl },
+    { "eglGetNativeClientBufferANDROID", (EGLFuncPointer)&eglGetNativeClientBufferANDROIDImpl },
+    { "eglGetSystemTimeFrequencyNV", (EGLFuncPointer)&eglGetSystemTimeFrequencyNVImpl },
+    { "eglGetSystemTimeNV", (EGLFuncPointer)&eglGetSystemTimeNVImpl },
+    { "eglSetDamageRegionKHR", (EGLFuncPointer)&eglSetDamageRegionKHRImpl },
+    { "eglGetNextFrameIdANDROID", (EGLFuncPointer)&eglGetNextFrameIdANDROIDImpl },
+    { "eglGetCompositorTimingANDROID", (EGLFuncPointer)&eglGetCompositorTimingANDROIDImpl },
+    { "eglGetCompositorTimingSupportedANDROID", (EGLFuncPointer)&eglGetCompositorTimingSupportedANDROIDImpl },
+    { "eglGetFrameTimestampsANDROID", (EGLFuncPointer)&eglGetFrameTimestampsANDROIDImpl },
+    { "eglGetFrameTimestampSupportedANDROID", (EGLFuncPointer)&eglGetFrameTimestampSupportedANDROIDImpl },
+    { "glGetString", (EGLFuncPointer)&glGetStringImpl },
+    { "glGetStringi", (EGLFuncPointer)&glGetStringiImpl },
+    { "glGetBooleanv", (EGLFuncPointer)&glGetBooleanvImpl },
+    { "glGetFloatv", (EGLFuncPointer)&glGetFloatvImpl },
+    { "glGetIntegerv", (EGLFuncPointer)&glGetIntegervImpl },
+    { "glGetInteger64v", (EGLFuncPointer)&glGetInteger64vImpl },
+};
+
+EGLFuncPointer FindPlatformImplAddr(const char* name)
+{
+    static const bool DEBUG = false;
+
+    if (name == nullptr) {
+        ALOGV("FindPlatformImplAddr called with null name");
+        return nullptr;
+    }
+
+    for (int i = 0; i < NELEM(sPlatformImplMap); i++) {
+        if (sPlatformImplMap[i].name == nullptr) {
+            ALOGV("FindPlatformImplAddr found nullptr for sPlatformImplMap[%i].name (%s)", i, name);
+            return nullptr;
+        }
+        if (!strcmp(name, sPlatformImplMap[i].name)) {
+            ALOGV("FindPlatformImplAddr found %llu for sPlatformImplMap[%i].address (%s)", (unsigned long long)sPlatformImplMap[i].address, i, name);
+            return sPlatformImplMap[i].address;
+        }
+    }
+
+    ALOGV("FindPlatformImplAddr did not find an entry for %s", name);
+    return nullptr;
+}
+} // namespace android
diff --git a/opengl/libs/EGL/egl_platform_entries.h b/opengl/libs/EGL/egl_platform_entries.h
new file mode 100644
index 0000000..7cd80d6
--- /dev/null
+++ b/opengl/libs/EGL/egl_platform_entries.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EGLAPI_H
+#define ANDROID_EGLAPI_H
+
+#include <EGL/egl.h>
+
+typedef __eglMustCastToProperFunctionPointerType EGLFuncPointer;
+
+namespace android {
+
+EGLFuncPointer FindPlatformImplAddr(const char* name);
+
+}; // namespace android
+
+#endif // ANDROID_EGLAPI_H
+
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index 4990af6..1a88678 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -38,12 +38,16 @@
     };
 
     inline egl_connection_t() : dso(nullptr) { }
+
     void *              dso;
     gl_hooks_t *        hooks[2];
     EGLint              major;
     EGLint              minor;
     egl_t               egl;
 
+    // Functions implemented or redirected by platform libraries
+    platform_impl_t     platform;
+
     void*               libEgl;
     void*               libGles1;
     void*               libGles2;
@@ -63,6 +67,7 @@
 
 extern char const * const gl_names[];
 extern char const * const egl_names[];
+extern char const * const platform_names[];
 
 extern egl_connection_t gEGLImpl;
 
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index f7fde96..65f50f5 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -301,71 +301,31 @@
 }
 
 const GLubyte * glGetString(GLenum name) {
-    const GLubyte * ret = egl_get_string_for_current_context(name);
-    if (ret == NULL) {
-        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
-        if(_c) ret = _c->glGetString(name);
-    }
-    return ret;
+    egl_connection_t* const cnx = egl_get_connection();
+    return cnx->platform.glGetString(name);
 }
 
 const GLubyte * glGetStringi(GLenum name, GLuint index) {
-    const GLubyte * ret = egl_get_string_for_current_context(name, index);
-    if (ret == NULL) {
-        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
-        if(_c) ret = _c->glGetStringi(name, index);
-    }
-    return ret;
+    egl_connection_t* const cnx = egl_get_connection();
+    return cnx->platform.glGetStringi(name, index);
 }
 
 void glGetBooleanv(GLenum pname, GLboolean * data) {
-    if (pname == GL_NUM_EXTENSIONS) {
-        int num_exts = egl_get_num_extensions_for_current_context();
-        if (num_exts >= 0) {
-            *data = num_exts > 0 ? GL_TRUE : GL_FALSE;
-            return;
-        }
-    }
-
-    gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
-    if (_c) _c->glGetBooleanv(pname, data);
+    egl_connection_t* const cnx = egl_get_connection();
+    return cnx->platform.glGetBooleanv(pname, data);
 }
 
 void glGetFloatv(GLenum pname, GLfloat * data) {
-    if (pname == GL_NUM_EXTENSIONS) {
-        int num_exts = egl_get_num_extensions_for_current_context();
-        if (num_exts >= 0) {
-            *data = (GLfloat)num_exts;
-            return;
-        }
-    }
-
-    gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
-    if (_c) _c->glGetFloatv(pname, data);
+    egl_connection_t* const cnx = egl_get_connection();
+    return cnx->platform.glGetFloatv(pname, data);
 }
 
 void glGetIntegerv(GLenum pname, GLint * data) {
-    if (pname == GL_NUM_EXTENSIONS) {
-        int num_exts = egl_get_num_extensions_for_current_context();
-        if (num_exts >= 0) {
-            *data = (GLint)num_exts;
-            return;
-        }
-    }
-
-    gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
-    if (_c) _c->glGetIntegerv(pname, data);
+    egl_connection_t* const cnx = egl_get_connection();
+    return cnx->platform.glGetIntegerv(pname, data);
 }
 
 void glGetInteger64v(GLenum pname, GLint64 * data) {
-    if (pname == GL_NUM_EXTENSIONS) {
-        int num_exts = egl_get_num_extensions_for_current_context();
-        if (num_exts >= 0) {
-            *data = (GLint64)num_exts;
-            return;
-        }
-    }
-
-    gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
-    if (_c) _c->glGetInteger64v(pname, data);
+    egl_connection_t* const cnx = egl_get_connection();
+    return cnx->platform.glGetInteger64v(pname, data);
 }
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index a8855ef..0af0501 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -21,15 +21,18 @@
 #include <EGL/eglext.h>
 #include <EGL/eglplatform.h>
 
+#include "EGL/egldefs.h"
 #include "hooks.h"
 
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
 
+
 EGLAPI const GLubyte * egl_get_string_for_current_context(GLenum name);
 EGLAPI const GLubyte * egl_get_string_for_current_context(GLenum name, GLuint index);
 EGLAPI GLint egl_get_num_extensions_for_current_context();
+EGLAPI egl_connection_t* egl_get_connection();
 
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 81dbe0e..63a0e14 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -59,6 +59,10 @@
 #define GL_ENTRY(_r, _api, ...) _r (*(_api))(__VA_ARGS__);
 #define EGL_ENTRY(_r, _api, ...) _r (*(_api))(__VA_ARGS__);
 
+struct platform_impl_t {
+    #include "platform_entries.in"
+};
+
 struct egl_t {
     #include "EGL/egl_entries.in"
 };
diff --git a/opengl/libs/platform_entries.in b/opengl/libs/platform_entries.in
new file mode 100644
index 0000000..b28f6cc
--- /dev/null
+++ b/opengl/libs/platform_entries.in
@@ -0,0 +1,76 @@
+EGL_ENTRY(EGLDisplay, eglGetDisplay, EGLNativeDisplayType)
+EGL_ENTRY(EGLBoolean, eglInitialize, EGLDisplay, EGLint*, EGLint*)
+EGL_ENTRY(EGLBoolean, eglTerminate, EGLDisplay)
+EGL_ENTRY(EGLBoolean, eglGetConfigs, EGLDisplay, EGLConfig*, EGLint, EGLint*)
+EGL_ENTRY(EGLBoolean, eglChooseConfig, EGLDisplay, const EGLint*, EGLConfig*, EGLint, EGLint*)
+EGL_ENTRY(EGLBoolean, eglGetConfigAttrib, EGLDisplay, EGLConfig, EGLint, EGLint*)
+EGL_ENTRY(EGLSurface, eglCreateWindowSurface, EGLDisplay, EGLConfig, NativeWindowType, const EGLint*)
+EGL_ENTRY(EGLSurface, eglCreatePixmapSurface, EGLDisplay, EGLConfig, NativePixmapType, const EGLint*)
+EGL_ENTRY(EGLSurface, eglCreatePbufferSurface, EGLDisplay, EGLConfig, const EGLint*)
+EGL_ENTRY(EGLBoolean, eglDestroySurface, EGLDisplay, EGLSurface)
+EGL_ENTRY(EGLBoolean, eglQuerySurface, EGLDisplay, EGLSurface, EGLint, EGLint*)
+EGL_ENTRY(void, eglBeginFrame, EGLDisplay, EGLSurface)
+EGL_ENTRY(EGLContext, eglCreateContext, EGLDisplay, EGLConfig, EGLContext, const EGLint*)
+EGL_ENTRY(EGLBoolean, eglDestroyContext, EGLDisplay, EGLContext)
+EGL_ENTRY(EGLBoolean, eglMakeCurrent, EGLDisplay, EGLSurface, EGLSurface, EGLContext)
+EGL_ENTRY(EGLBoolean, eglQueryContext, EGLDisplay, EGLContext, EGLint, EGLint*)
+EGL_ENTRY(EGLContext, eglGetCurrentContext, void)
+EGL_ENTRY(EGLSurface, eglGetCurrentSurface, EGLint)
+EGL_ENTRY(EGLDisplay, eglGetCurrentDisplay, void)
+EGL_ENTRY(EGLBoolean, eglWaitGL, void)
+EGL_ENTRY(EGLBoolean, eglWaitNative, EGLint)
+EGL_ENTRY(EGLint, eglGetError, void)
+EGL_ENTRY(__eglMustCastToProperFunctionPointerType, eglGetProcAddress, const char*)
+EGL_ENTRY(EGLBoolean, eglSwapBuffersWithDamageKHR, EGLDisplay, EGLSurface, EGLint*, EGLint)
+EGL_ENTRY(EGLBoolean, eglSwapBuffers, EGLDisplay, EGLSurface)
+EGL_ENTRY(EGLBoolean, eglCopyBuffers, EGLDisplay, EGLSurface, NativePixmapType)
+EGL_ENTRY(const char*, eglQueryString, EGLDisplay, EGLint)
+EGL_ENTRY(const char*, eglQueryStringImplementationANDROID, EGLDisplay, EGLint)
+EGL_ENTRY(EGLBoolean, eglSurfaceAttrib, EGLDisplay, EGLSurface, EGLint, EGLint)
+EGL_ENTRY(EGLBoolean, eglBindTexImage, EGLDisplay, EGLSurface, EGLint)
+EGL_ENTRY(EGLBoolean, eglReleaseTexImage, EGLDisplay, EGLSurface, EGLint)
+EGL_ENTRY(EGLBoolean, eglSwapInterval, EGLDisplay, EGLint)
+EGL_ENTRY(EGLBoolean, eglWaitClient, void)
+EGL_ENTRY(EGLBoolean, eglBindAPI, EGLenum)
+EGL_ENTRY(EGLenum, eglQueryAPI, void)
+EGL_ENTRY(EGLBoolean, eglReleaseThread, void)
+EGL_ENTRY(EGLSurface, eglCreatePbufferFromClientBuffer, EGLDisplay, EGLenum, EGLClientBuffer, EGLConfig, const EGLint*)
+EGL_ENTRY(EGLBoolean, eglLockSurfaceKHR, EGLDisplay, EGLSurface, const EGLint*)
+EGL_ENTRY(EGLBoolean, eglUnlockSurfaceKHR, EGLDisplay, EGLSurface)
+EGL_ENTRY(EGLImageKHR, eglCreateImageKHR, EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*)
+EGL_ENTRY(EGLBoolean, eglDestroyImageKHR, EGLDisplay, EGLImageKHR)
+EGL_ENTRY(EGLSyncKHR, eglCreateSyncKHR, EGLDisplay, EGLenum, const EGLint*)
+EGL_ENTRY(EGLBoolean, eglDestroySyncKHR, EGLDisplay, EGLSyncKHR)
+EGL_ENTRY(EGLBoolean, eglSignalSyncKHR, EGLDisplay, EGLSyncKHR, EGLenum)
+EGL_ENTRY(EGLint, eglClientWaitSyncKHR, EGLDisplay, EGLSyncKHR, EGLint, EGLTimeKHR)
+EGL_ENTRY(EGLBoolean, eglGetSyncAttribKHR, EGLDisplay, EGLSyncKHR, EGLint, EGLint*)
+EGL_ENTRY(EGLStreamKHR, eglCreateStreamKHR, EGLDisplay, const EGLint*)
+EGL_ENTRY(EGLBoolean, eglDestroyStreamKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLBoolean, eglStreamAttribKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLint)
+EGL_ENTRY(EGLBoolean, eglQueryStreamKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLint*)
+EGL_ENTRY(EGLBoolean, eglQueryStreamu64KHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLuint64KHR*)
+EGL_ENTRY(EGLBoolean, eglQueryStreamTimeKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLTimeKHR*)
+EGL_ENTRY(EGLSurface, eglCreateStreamProducerSurfaceKHR, EGLDisplay, EGLConfig, EGLStreamKHR, const EGLint*)
+EGL_ENTRY(EGLBoolean, eglStreamConsumerGLTextureExternalKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLBoolean, eglStreamConsumerAcquireKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLBoolean, eglStreamConsumerReleaseKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLNativeFileDescriptorKHR, eglGetStreamFileDescriptorKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLStreamKHR, eglCreateStreamFromFileDescriptorKHR, EGLDisplay, EGLNativeFileDescriptorKHR)
+EGL_ENTRY(EGLint, eglWaitSyncKHR, EGLDisplay, EGLSyncKHR, EGLint)
+EGL_ENTRY(EGLint, eglDupNativeFenceFDANDROID, EGLDisplay, EGLSyncKHR)
+EGL_ENTRY(EGLBoolean, eglPresentationTimeANDROID, EGLDisplay, EGLSurface, EGLnsecsANDROID)
+EGL_ENTRY(EGLClientBuffer, eglGetNativeClientBufferANDROID, const AHardwareBuffer*)
+EGL_ENTRY(EGLuint64NV, eglGetSystemTimeFrequencyNV, void)
+EGL_ENTRY(EGLuint64NV, eglGetSystemTimeNV, void)
+EGL_ENTRY(EGLBoolean, eglSetDamageRegionKHR, EGLDisplay, EGLSurface, EGLint*, EGLint)
+EGL_ENTRY(EGLBoolean, eglGetNextFrameIdANDROID, EGLDisplay, EGLSurface, EGLuint64KHR*)
+EGL_ENTRY(EGLBoolean, eglGetCompositorTimingANDROID, EGLDisplay, EGLSurface, EGLint, const EGLint*, EGLnsecsANDROID*)
+EGL_ENTRY(EGLBoolean, eglGetCompositorTimingSupportedANDROID, EGLDisplay, EGLSurface, EGLint)
+EGL_ENTRY(EGLBoolean, eglGetFrameTimestampsANDROID, EGLDisplay, EGLSurface, EGLuint64KHR, EGLint, const EGLint*, EGLnsecsANDROID*)
+EGL_ENTRY(EGLBoolean, eglGetFrameTimestampSupportedANDROID, EGLDisplay, EGLSurface, EGLint)
+GL_ENTRY(const GLubyte*, glGetString, GLenum)
+GL_ENTRY(const GLubyte*, glGetStringi, GLenum, GLuint)
+GL_ENTRY(void, glGetBooleanv, GLenum, GLboolean*)
+GL_ENTRY(void, glGetFloatv, GLenum, GLfloat*)
+GL_ENTRY(void, glGetIntegerv, GLenum, GLint*)
+GL_ENTRY(void, glGetInteger64v, GLenum, GLint64*)