Emulator Opengl unit test - use sperate implementation libraries

Use seperate EGL_emul, GLESv1_CM_emul and GLESv2_emul implementation
libraries.  This replaces GLES_emul that was prviously included
EGL and GLESv1.
This change enables the wrapper to support GLESv2. However,
this current EGL implementation uses the native android emulator
EGL thus will not expose this GLESv2 capability.

Change-Id: Ib0a309d71cce1248efe9a08aa59434101d0ac607
diff --git a/tools/emulator/opengl/tests/gles_android_wrapper/Android.mk b/tools/emulator/opengl/tests/gles_android_wrapper/Android.mk
index 15e2e98..7901220 100644
--- a/tools/emulator/opengl/tests/gles_android_wrapper/Android.mk
+++ b/tools/emulator/opengl/tests/gles_android_wrapper/Android.mk
@@ -1,13 +1,87 @@
 LOCAL_PATH := $(call my-dir)
 
-##### libGLES_emul.so ###########
+emulatorOpengl := $(LOCAL_PATH)/../..
+logTag := -DLOG_TAG=\"eglWrapper\"
+EMUGEN = $(BUILD_OUT_EXECUTABLES)/emugen
+
+#### libGLESv1_CM_emul.so
+include $(CLEAR_VARS)
+
+
+
+LOCAL_MODULE := libGLESv1_CM_emul
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_SRC_FILES := glesv1_emul_ifc.cpp
+
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_TAGS := debug
+LOCAL_SHARED_LIBRARIES := libdl
+
+LOCAL_C_INCLUDES += \
+	$(emulatorOpengl)/system/GLESv1_enc \
+	$(emulatorOpengl)/shared/OpenglCodecCommon
+
+glesv1_emul_intermediates := $(local-intermediates-dir)
+
+GEN_GLESv1_emul := \
+	$(glesv1_emul_intermediates)/gl_wrapper_entry.cpp \
+	$(glesv1_emul_intermediates)/gl_wrapper_context.cpp
+$(GEN_GLESv1_emul) : PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN_GLESv1_emul) : PRIVATE_CUSTOM_TOOL := \
+	$(EMUGEN) -W $(glesv1_emul_intermediates) -i $(emulatorOpengl)/system/GLESv1_enc gl
+$(GEN_GLESv1_emul) : $(EMUGEN) \
+	$(emulatorOpengl)/system/GLESv1_enc/gl.in \
+	$(emulatorOpengl)/system/GLESv1_enc/gl.attrib \
+	$(emulatorOpengl)/system/GLESv1_enc/gl.types 
+	$(transform-generated-source)
+
+LOCAL_GENERATED_SOURCES += $(GEN_GLESv1_emul)
+
+include $(BUILD_SHARED_LIBRARY)
+
+#### libGLESv2_CM_emul.so
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libGLESv2_emul
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_SRC_FILES := glesv2_emul_ifc.cpp
+
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_TAGS := debug
+LOCAL_SHARED_LIBRARIES := libdl
+
+LOCAL_C_INCLUDES += \
+	$(emulatorOpengl)/system/GLESv2_enc \
+	$(emulatorOpengl)/shared/OpenglCodecCommon
+
+glesv2_emul_intermediates := $(local-intermediates-dir)
+
+GEN_GLESv2_emul := \
+	$(glesv2_emul_intermediates)/gl2_wrapper_entry.cpp \
+	$(glesv2_emul_intermediates)/gl2_wrapper_context.cpp
+
+$(GEN_GLESv2_emul) : PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN_GLESv2_emul) : PRIVATE_CUSTOM_TOOL := \
+	$(EMUGEN) -W $(glesv2_emul_intermediates) -i $(emulatorOpengl)/system/GLESv2_enc gl2
+$(GEN_GLESv2_emul) : $(EMUGEN) \
+	$(emulatorOpengl)/system/GLESv2_enc/gl2.in \
+	$(emulatorOpengl)/system/GLESv2_enc/gl2.attrib \
+	$(emulatorOpengl)/system/GLESv2_enc/gl2.types 
+	$(transform-generated-source)
+
+LOCAL_GENERATED_SOURCES += $(GEN_GLESv2_emul)
+
+include $(BUILD_SHARED_LIBRARY)
+
+
+##### libEGL_emul.so ###########
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES :=  \
         egl.cpp \
         egl_dispatch.cpp \
-        gles.cpp \
-        gles_dispatch.cpp \
         ServerConnection.cpp \
         ThreadInfo.cpp
 
@@ -15,27 +89,37 @@
 # is generated
 LOCAL_ADDITIONAL_DEPENDENCIES := \
 	$(TARGET_OUT_SHARED_LIBRARIES)/libut_rendercontrol_enc$(TARGET_SHLIB_SUFFIX) \
-	$(TARGET_OUT_SHARED_LIBRARIES)/libGLESv1_enc$(TARGET_SHLIB_SUFFIX)
+	$(TARGET_OUT_SHARED_LIBRARIES)/libGLESv1_enc$(TARGET_SHLIB_SUFFIX) \
+	$(TARGET_OUT_SHARED_LIBRARIES)/libGLESv2_enc$(TARGET_SHLIB_SUFFIX) \
+	$(TARGET_OUT_SHARED_LIBRARIES)/egl/libGLESv1_CM_emul$(TARGET_SHLIB_SUFFIX) \
+	$(TARGET_OUT_SHARED_LIBRARIES)/egl/libGLESv2_emul$(TARGET_SHLIB_SUFFIX)
 
 
-emulatorOpengl := $(LOCAL_PATH)/../..
 
 LOCAL_C_INCLUDES := $(emulatorOpengl)/shared/OpenglCodecCommon \
         $(emulatorOpengl)/host/include/libOpenglRender \
 		$(call intermediates-dir-for, SHARED_LIBRARIES, libut_rendercontrol_enc) \
 		$(call intermediates-dir-for, SHARED_LIBRARIES, libGLESv1_enc) \
+		$(call intermediates-dir-for, SHARED_LIBRARIES, libGLESv2_enc) \
+		$(call intermediates-dir-for, SHARED_LIBRARIES, libGLESv1_CM_emul) \
+		$(call intermediates-dir-for, SHARED_LIBRARIES, libGLESv2_emul) \
         $(emulatorOpengl)/system/GLESv1_enc \
+        $(emulatorOpengl)/system/GLESv2_enc \
         $(emulatorOpengl)/tests/ut_rendercontrol_enc 
 
 
-LOCAL_CFLAGS := -DLOG_TAG=\"eglWrapper\"
+LOCAL_CFLAGS := $(logTag)
 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
-LOCAL_MODULE := libGLES_emul
+LOCAL_MODULE := libEGL_emul
 LOCAL_MODULE_TAGS := debug
 LOCAL_PRELINK_MODULE := false
 
 #LOCAL_LDLIBS := -lpthread -ldl
-LOCAL_SHARED_LIBRARIES := libdl libcutils libGLESv1_enc libut_rendercontrol_enc
+LOCAL_SHARED_LIBRARIES := libdl \
+	libcutils \
+	libGLESv1_enc \
+	libGLESv2_enc \
+	libut_rendercontrol_enc
 LOCAL_STATIC_LIBRARIES := libOpenglCodecCommon
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/tools/emulator/opengl/tests/gles_android_wrapper/ApiInitializer.h b/tools/emulator/opengl/tests/gles_android_wrapper/ApiInitializer.h
new file mode 100644
index 0000000..7dc5006
--- /dev/null
+++ b/tools/emulator/opengl/tests/gles_android_wrapper/ApiInitializer.h
@@ -0,0 +1,26 @@
+#ifndef _API_INITIALIZER_H_
+#define _API_INITIALIZER_H_
+#include <stdlib.h>
+#include <dlfcn.h>
+
+class ApiInitializer {
+public:
+    ApiInitializer(void *dso) :
+        m_dso(dso) {
+    }
+    static void *s_getProc(const char *name, void *userData) {
+        ApiInitializer *self = (ApiInitializer *)userData;
+        return self->getProc(name);
+    }
+private:
+    void *m_dso;
+    void *getProc(const char *name) {
+        void *symbol = NULL;
+        if (m_dso) {
+            symbol = dlsym(m_dso, name);
+        }
+        return symbol;
+    }
+};
+
+#endif
diff --git a/tools/emulator/opengl/tests/gles_android_wrapper/ServerConnection.cpp b/tools/emulator/opengl/tests/gles_android_wrapper/ServerConnection.cpp
index 2a82bfa..ea36c72 100644
--- a/tools/emulator/opengl/tests/gles_android_wrapper/ServerConnection.cpp
+++ b/tools/emulator/opengl/tests/gles_android_wrapper/ServerConnection.cpp
@@ -28,6 +28,15 @@
     return NULL;
 }
 
+gl2_client_context_t *ServerConnection::s_getGl2Context()
+{
+    EGLThreadInfo *ti = getEGLThreadInfo();
+    if (ti->serverConn) {
+        return ti->serverConn->m_gl2Enc;
+    }
+    return NULL;
+}
+
 ServerConnection *ServerConnection::s_getServerConnection()
 {
     EGLThreadInfo *ti = getEGLThreadInfo();
@@ -85,6 +94,9 @@
     m_glEnc = new GLEncoder(m_stream);
     m_glEnc->setContextAccessor(s_getGlContext);
 
+    m_gl2Enc = new GL2Encoder(m_stream);
+    m_gl2Enc->setContextAccessor(s_getGl2Context);
+
     m_ut_enc = new ut_rendercontrol_encoder_context_t(m_stream);
     return 0;
 }
diff --git a/tools/emulator/opengl/tests/gles_android_wrapper/ServerConnection.h b/tools/emulator/opengl/tests/gles_android_wrapper/ServerConnection.h
index 6eae859..ed5b314 100644
--- a/tools/emulator/opengl/tests/gles_android_wrapper/ServerConnection.h
+++ b/tools/emulator/opengl/tests/gles_android_wrapper/ServerConnection.h
@@ -17,6 +17,7 @@
 #define _SERVER_CONNECTION_H
 
 #include "GLEncoder.h"
+#include "GL2Encoder.h"
 #include "TcpStream.h"
 #include "codec_defs.h"
 #include "ut_rendercontrol_enc.h"
@@ -31,6 +32,7 @@
     int create(size_t buf_size = 4 * 1024 * 1024, const char *defaultServer = RGL_DEFAULT_SERVER);
     static gl_client_context_t *s_getGlContext();
     static ServerConnection *s_getServerConnection();
+    static gl2_client_context_t *s_getGl2Context();
     GLEncoder *glEncoder() { return m_glEnc; }
     ut_rendercontrol_encoder_context_t * utEnc() { return m_ut_enc; }
 
@@ -43,6 +45,7 @@
     static void s_initKeys();
     TcpStream *m_stream;
     GLEncoder *m_glEnc;
+    GL2Encoder *m_gl2Enc;
     ut_rendercontrol_encoder_context_t *m_ut_enc;
 
 };
diff --git a/tools/emulator/opengl/tests/gles_android_wrapper/egl.cpp b/tools/emulator/opengl/tests/gles_android_wrapper/egl.cpp
index ea78bbb..cc6b4f5 100644
--- a/tools/emulator/opengl/tests/gles_android_wrapper/egl.cpp
+++ b/tools/emulator/opengl/tests/gles_android_wrapper/egl.cpp
@@ -32,18 +32,71 @@
 #include "ServerConnection.h"
 #include "ThreadInfo.h"
 #include <pthread.h>
-
+#include "gl_wrapper_context.h"
+#include "gl2_wrapper_context.h"
 
 #define GLES_EMUL_TARGETS_FILE "/system/etc/gles_emul.cfg"
+// implementation libraries;
+#define GLESv1_enc_LIB "/system/lib/libGLESv1_enc.so"
+#define GLESv2_enc_LIB "/system/lib/libGLESv2_enc.so"
+#define GLES_android_LIB "/system/lib/egl/libGLES_android.so"
+// driver libraries;
+#define GLESv1_DRIVER "/system/lib/egl/libGLESv1_CM_emul.so"
+#define GLESv2_DRIVER "/system/lib/egl/libGLESv2_emul.so"
+
 
 static struct egl_dispatch *s_dispatch = NULL;
 pthread_once_t dispatchTablesInitialized = PTHREAD_ONCE_INIT;
 
 static bool s_needEncode = false;
 
-extern void init_gles(void *gles_android);
-extern __eglMustCastToProperFunctionPointerType gles_getProcAddress(const char *procname);
+static gl_wrapper_context_t *g_gl_dispatch = NULL;
+static gl2_wrapper_context_t *g_gl2_dispatch = NULL;
 
+template <class T>
+int initApi(const char *driverLibName, const char *implLibName, T **dispatchTable, T *(*accessor)())
+{
+    void *driverLib = dlopen(driverLibName, RTLD_NOW | RTLD_LOCAL);
+    if (driverLib == NULL) {
+        LOGE("failed to load %s : %s\n", driverLibName, dlerror());
+        return -1;
+    }
+
+    typedef T *(*createFcn_t)(void *, T *(*accessor)());
+    createFcn_t createFcn;
+    createFcn = (createFcn_t) dlsym(driverLib, "createFromLib");
+    if (createFcn == NULL) {
+        LOGE("failed to load createFromLib constructor function\n");
+        return -1;
+    }
+
+    void *implLib = dlopen(implLibName, RTLD_NOW | RTLD_LOCAL);
+    if (implLib == NULL) {
+        LOGE("couldn't open %s", implLibName);
+        return -2;
+    }
+    *dispatchTable = createFcn(implLib, accessor);
+    if (*dispatchTable == NULL) {
+        return -3;
+    }
+
+    // XXX - we do close the impl library since it doesn't have data, as far as we concern.
+    dlclose(implLib);
+
+    // XXX - we do not dlclose the driver library, so its not initialized when
+    // later loaded by android - is this required?
+    return 0;
+}
+
+static gl_wrapper_context_t *getGLContext()
+{
+    return g_gl_dispatch;
+}
+
+static gl2_wrapper_context_t *getGL2Context()
+{
+    return g_gl2_dispatch;
+}
 
 const char *getProcName()
 {
@@ -156,26 +209,31 @@
     s_needEncode = isNeedEncode();
     void *gles_encoder = NULL;
     if (s_needEncode) {
+        // initialize a connection to the server, and the GLESv1/v2 encoders;
         ServerConnection * connection = ServerConnection::s_getServerConnection();
         if (connection == NULL) {
             LOGE("couldn't create server connection\n");
             s_needEncode = false;
-        } else {
-            LOGD("Created server connection for %s\n", getProcName());
-            gles_encoder = dlopen("/system/lib/libGLESv1_enc.so", RTLD_NOW);
-            if (gles_encoder == NULL) {
-                LOGE("couldn't open libGLESv1_enc.so... aborting connection");
-                delete connection;
-                s_needEncode = false;
-            }
         }
     }
 
-    if (s_needEncode && gles_encoder) {
-        init_gles(gles_encoder);
-    } else {
+    // init dispatch tabels for GLESv1 & GLESv2
+    if (s_needEncode) {
+        // XXX - we do not check the retrun value because there isn't much we can do here on failure.
+
+        if (initApi<gl_wrapper_context_t>(GLESv1_DRIVER, GLESv1_enc_LIB, &g_gl_dispatch, getGLContext) < 0) {
+            // fallback to android on faluire
+            s_needEncode = false;
+        } else {
+            initApi<gl2_wrapper_context_t>(GLESv2_DRIVER, GLESv2_enc_LIB, &g_gl2_dispatch, getGL2Context);
+        }
+    }
+
+    if (!s_needEncode) {
         LOGD("Initializing native opengl for %s\n", getProcName());
-        init_gles(gles_android);
+        initApi<gl_wrapper_context_t>(GLESv1_DRIVER, GLES_android_LIB, &g_gl_dispatch, getGLContext);
+        // try to initialize gl2 from GLES, though its probably going to fail
+        initApi<gl2_wrapper_context_t>(GLESv2_DRIVER, GLES_android_LIB, &g_gl2_dispatch, getGL2Context);
     }
 }
 
@@ -195,14 +253,9 @@
         }
     }
 
-    // search in GLES function table
-    __eglMustCastToProperFunctionPointerType f = gles_getProcAddress(procname);
-    if (f != NULL) {
-        return f;
-    }
-
-    // should probably fail - search in back-end anyway.
-    return getDispatch()->eglGetProcAddress(procname);
+    // we do not support eglGetProcAddress for GLESv1 & GLESv2. The loader
+    // should be able to find this function through dynamic loading.
+    return NULL;
 }
 
 ////////////////  Path through functions //////////
diff --git a/tools/emulator/opengl/tests/gles_android_wrapper/glesv1_emul_ifc.cpp b/tools/emulator/opengl/tests/gles_android_wrapper/glesv1_emul_ifc.cpp
new file mode 100644
index 0000000..41e7b7a
--- /dev/null
+++ b/tools/emulator/opengl/tests/gles_android_wrapper/glesv1_emul_ifc.cpp
@@ -0,0 +1,23 @@
+#include <stdlib.h>
+#include "ApiInitializer.h"
+#include <dlfcn.h>
+#include "gl_wrapper_context.h"
+
+extern "C" {
+    gl_wrapper_context_t *createFromLib(void *solib, gl_wrapper_context_t *(*accessor)());
+}
+
+gl_wrapper_context_t * createFromLib(void *solib, gl_wrapper_context_t *(accessor)())
+{
+    gl_wrapper_context_t *ctx = new gl_wrapper_context_t;
+    if (ctx == NULL) {
+        return NULL;
+    }
+    ApiInitializer *initializer = new ApiInitializer(solib);
+    ctx->initDispatchByName(ApiInitializer::s_getProc, initializer);
+    gl_wrapper_context_t::setContextAccessor(accessor);
+    delete initializer;
+    return ctx;
+}
+
+
diff --git a/tools/emulator/opengl/tests/gles_android_wrapper/glesv2_emul_ifc.cpp b/tools/emulator/opengl/tests/gles_android_wrapper/glesv2_emul_ifc.cpp
new file mode 100644
index 0000000..cf0dfed
--- /dev/null
+++ b/tools/emulator/opengl/tests/gles_android_wrapper/glesv2_emul_ifc.cpp
@@ -0,0 +1,24 @@
+#include <stdlib.h>
+#include "ApiInitializer.h"
+#include <dlfcn.h>
+#include "gl2_wrapper_context.h"
+
+extern "C" {
+    gl2_wrapper_context_t *createFromLib(void *solib, gl2_wrapper_context_t *(*accessor)());
+}
+
+gl2_wrapper_context_t * createFromLib(void *solib, gl2_wrapper_context_t *(*accessor)())
+{
+    gl2_wrapper_context_t *ctx = new gl2_wrapper_context_t;
+    if (ctx == NULL) {
+        return NULL;
+    }
+    ApiInitializer *initializer = new ApiInitializer(solib);
+    ctx->initDispatchByName(ApiInitializer::s_getProc, initializer);
+    gl2_wrapper_context_t::setContextAccessor(accessor);
+    delete initializer;
+    return ctx;
+}
+
+
+