aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2014-07-08 21:45:47 +0200
committerDavid 'Digit' Turner <digit@google.com>2014-07-09 18:12:08 +0200
commit242a075e3256fc7f369f0e5f93fd2ae91c255774 (patch)
tree93d82dee2d537a506bd5b204df65495fbc21d663
parentd1dd8ee1e85f60569ddf6ebc7fe1cbde7ebb6f38 (diff)
downloadsdk-242a075e3256fc7f369f0e5f93fd2ae91c255774.zip
sdk-242a075e3256fc7f369f0e5f93fd2ae91c255774.tar.gz
sdk-242a075e3256fc7f369f0e5f93fd2ae91c255774.tar.bz2
emulator/opengl: refactor shared library handling.
+ Add a unit test. Change-Id: I27c993d1dc819e5bd89fc1e9ae266e11e6ef9a76
-rw-r--r--emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp2
-rw-r--r--emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h4
-rw-r--r--emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp2
-rw-r--r--emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h5
-rw-r--r--emulator/opengl/host/libs/Translator/EGL/EglImp.cpp4
-rw-r--r--emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp8
-rw-r--r--emulator/opengl/host/libs/libOpenglRender/EGLDispatch.cpp5
-rw-r--r--emulator/opengl/host/libs/libOpenglRender/GL2Dispatch.cpp7
-rw-r--r--emulator/opengl/host/libs/libOpenglRender/GLDispatch.cpp7
-rw-r--r--emulator/opengl/shared/OpenglOsUtils/Android.mk2
-rw-r--r--emulator/opengl/shared/OpenglOsUtils/osDynLibrary.cpp79
-rw-r--r--emulator/opengl/shared/OpenglOsUtils/osDynLibrary.h71
-rw-r--r--emulator/opengl/shared/emugl/common/Android.mk21
-rw-r--r--emulator/opengl/shared/emugl/common/shared_library.cpp105
-rw-r--r--emulator/opengl/shared/emugl/common/shared_library.h85
-rw-r--r--emulator/opengl/shared/emugl/common/shared_library_unittest.cpp141
-rw-r--r--emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp22
17 files changed, 396 insertions, 174 deletions
diff --git a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp
index 3c5bd70..7aa6ede 100644
--- a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp
+++ b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp
@@ -47,7 +47,7 @@ int GLDecoder::initGL(get_proc_func_t getProcFunc, void *getProcFuncData)
libname = getenv(GLES_LIBNAME_VAR);
}
- m_glesDso = osUtils::dynLibrary::open(libname);
+ m_glesDso = emugl::SharedLibrary::open(libname);
if (m_glesDso == NULL) {
fprintf(stderr, "Couldn't find %s \n", GLES_LIBNAME);
return -1;
diff --git a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h
index 14ca222..0d26090 100644
--- a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h
+++ b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h
@@ -19,7 +19,7 @@
#include "gl_dec.h"
#include "FixedBuffer.h"
#include "GLDecoderContextData.h"
-#include <osDynLibrary.h>
+#include "emugl/common/shared_library.h"
#define GLES_LIBNAME_VAR "ANDROID_GLESv1_LIB"
#define GLES_LIBNAME "libGLES_CM.so"
@@ -65,7 +65,7 @@ private:
static void * s_getProc(const char *name, void *userData);
GLDecoderContextData *m_contextData;
- osUtils::dynLibrary* m_glesDso;
+ emugl::SharedLibrary* m_glesDso;
};
#endif
diff --git a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp
index ccf2f06..2ef306e 100644
--- a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp
+++ b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp
@@ -60,7 +60,7 @@ int GL2Decoder::initGL(get_proc_func_t getProcFunc, void *getProcFuncData)
libname = getenv(GLES2_LIBNAME_VAR);
}
- m_GL2library = osUtils::dynLibrary::open(libname);
+ m_GL2library = emugl::SharedLibrary::open(libname);
if (m_GL2library == NULL) {
fprintf(stderr, "%s: Couldn't find %s \n", __FUNCTION__, libname);
return -1;
diff --git a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h
index dcf2c07..8910da9 100644
--- a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h
+++ b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h
@@ -21,9 +21,8 @@
#define GLES2_LIBNAME "libGLESv2.so"
#include "gl2_dec.h"
-#include "osDynLibrary.h"
#include "GLDecoderContextData.h"
-
+#include "emugl/common/shared_library.h"
class GL2Decoder : public gl2_decoder_context_t
{
@@ -35,7 +34,7 @@ public:
void setContextData(GLDecoderContextData *contextData) { m_contextData = contextData; }
private:
GLDecoderContextData *m_contextData;
- osUtils::dynLibrary * m_GL2library;
+ emugl::SharedLibrary* m_GL2library;
static void *s_getProc(const char *name, void *userData);
static void gl2_APIENTRY s_glGetCompressedTextureFormats(void *self, int count, GLint *formats);
diff --git a/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp b/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp
index 06dcf67..30d358f 100644
--- a/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp
+++ b/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp
@@ -24,7 +24,7 @@
#include <stdio.h>
#include "ThreadInfo.h"
#include <GLcommon/TranslatorIfaces.h>
-#include <OpenglOsUtils/osDynLibrary.h>
+#include "emugl/common/shared_library.h"
#include "EglWindowSurface.h"
#include "EglPbufferSurface.h"
@@ -175,7 +175,7 @@ EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) {
#define TRANSLATOR_GETIFACE_NAME "__translator_getIfaces"
static __translator_getGLESIfaceFunc loadIfaces(const char* libName){
- osUtils::dynLibrary* libGLES = osUtils::dynLibrary::open(libName);
+ emugl::SharedLibrary* libGLES = emugl::SharedLibrary::open(libName);
if(!libGLES) return NULL;
__translator_getGLESIfaceFunc func = (__translator_getGLESIfaceFunc)libGLES->findSymbol(TRANSLATOR_GETIFACE_NAME);
diff --git a/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp b/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp
index 7b217fd..5da7247 100644
--- a/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp
+++ b/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp
@@ -16,7 +16,7 @@
#include <GLcommon/GLDispatch.h>
#include <stdio.h>
-#include <OpenglOsUtils/osDynLibrary.h>
+#include "emugl/common/shared_library.h"
#ifdef __linux__
#include <GL/glx.h>
@@ -31,13 +31,13 @@ typedef void (*GL_FUNC_PTR)();
static GL_FUNC_PTR getGLFuncAddress(const char *funcName) {
GL_FUNC_PTR ret = NULL;
#ifdef __linux__
- static osUtils::dynLibrary* libGL = osUtils::dynLibrary::open("libGL.so");
+ static emugl::SharedLibrary* libGL = emugl::SharedLibrary::open("libGL");
ret = (GL_FUNC_PTR)glXGetProcAddress((const GLubyte*)funcName);
#elif defined(WIN32)
- static osUtils::dynLibrary* libGL = osUtils::dynLibrary::open("opengl32");
+ static emugl::SharedLibrary* libGL = emugl::SharedLibrary::open("opengl32");
ret = (GL_FUNC_PTR)wglGetProcAddress(funcName);
#elif defined(__APPLE__)
- static osUtils::dynLibrary* libGL = osUtils::dynLibrary::open("/System/Library/Frameworks/OpenGL.framework/OpenGL");
+ static emugl::SharedLibrary* libGL = emugl::SharedLibrary::open("/System/Library/Frameworks/OpenGL.framework/OpenGL");
#endif
if(!ret && libGL){
ret = libGL->findSymbol(funcName);
diff --git a/emulator/opengl/host/libs/libOpenglRender/EGLDispatch.cpp b/emulator/opengl/host/libs/libOpenglRender/EGLDispatch.cpp
index 3cf5dbc..7d514e8 100644
--- a/emulator/opengl/host/libs/libOpenglRender/EGLDispatch.cpp
+++ b/emulator/opengl/host/libs/libOpenglRender/EGLDispatch.cpp
@@ -16,7 +16,8 @@
#include "EGLDispatch.h"
#include <stdio.h>
#include <stdlib.h>
-#include "osDynLibrary.h"
+
+#include "emugl/common/shared_library.h"
EGLDispatch s_egl;
@@ -28,7 +29,7 @@ bool init_egl_dispatch()
const char *libName = getenv("ANDROID_EGL_LIB");
if (!libName) libName = DEFAULT_EGL_LIB;
- osUtils::dynLibrary *lib = osUtils::dynLibrary::open(libName);
+ emugl::SharedLibrary *lib = emugl::SharedLibrary::open(libName);
if (!lib) {
printf("Failed to open %s\n", libName);
return NULL;
diff --git a/emulator/opengl/host/libs/libOpenglRender/GL2Dispatch.cpp b/emulator/opengl/host/libs/libOpenglRender/GL2Dispatch.cpp
index cda205f..8c51a4e 100644
--- a/emulator/opengl/host/libs/libOpenglRender/GL2Dispatch.cpp
+++ b/emulator/opengl/host/libs/libOpenglRender/GL2Dispatch.cpp
@@ -17,12 +17,13 @@
#include "GL2Dispatch.h"
#include <stdio.h>
#include <stdlib.h>
-#include "osDynLibrary.h"
+
+#include "emugl/common/shared_library.h"
gl2_decoder_context_t s_gl2;
int s_gl2_enabled;
-static osUtils::dynLibrary *s_gles2_lib = NULL;
+static emugl::SharedLibrary *s_gles2_lib = NULL;
#define DEFAULT_GLES_V2_LIB EMUGL_LIBNAME("GLES_V2_translator")
@@ -38,7 +39,7 @@ bool init_gl2_dispatch()
//
// Load the GLES library
//
- s_gles2_lib = osUtils::dynLibrary::open(libName);
+ s_gles2_lib = emugl::SharedLibrary::open(libName);
if (!s_gles2_lib) return false;
//
diff --git a/emulator/opengl/host/libs/libOpenglRender/GLDispatch.cpp b/emulator/opengl/host/libs/libOpenglRender/GLDispatch.cpp
index 089512a..c127dc3 100644
--- a/emulator/opengl/host/libs/libOpenglRender/GLDispatch.cpp
+++ b/emulator/opengl/host/libs/libOpenglRender/GLDispatch.cpp
@@ -16,11 +16,12 @@
#include "GLDispatch.h"
#include <stdio.h>
#include <stdlib.h>
-#include "osDynLibrary.h"
+
+#include "emugl/common/shared_library.h"
GLDispatch s_gl;
-static osUtils::dynLibrary *s_gles_lib = NULL;
+static emugl::SharedLibrary *s_gles_lib = NULL;
//
// This function is called only once during initialiation before
@@ -34,7 +35,7 @@ bool init_gl_dispatch()
const char *libName = getenv("ANDROID_GLESv1_LIB");
if (!libName) libName = DEFAULT_GLES_CM_LIB;
- s_gles_lib = osUtils::dynLibrary::open(libName);
+ s_gles_lib = emugl::SharedLibrary::open(libName);
if (!s_gles_lib) return false;
s_gl.glAlphaFunc = (glAlphaFunc_t) s_gles_lib->findSymbol("glAlphaFunc");
diff --git a/emulator/opengl/shared/OpenglOsUtils/Android.mk b/emulator/opengl/shared/OpenglOsUtils/Android.mk
index f9673fc..42b57dd 100644
--- a/emulator/opengl/shared/OpenglOsUtils/Android.mk
+++ b/emulator/opengl/shared/OpenglOsUtils/Android.mk
@@ -8,7 +8,7 @@ LOCAL_PATH := $(call my-dir)
### Host library ##############################################
-host_common_SRC_FILES := osDynLibrary.cpp
+host_common_SRC_FILES :=
host_common_LDLIBS :=
host_common_INCLUDES := $(LOCAL_PATH)
diff --git a/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.cpp b/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.cpp
deleted file mode 100644
index e8e6ab7..0000000
--- a/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-* Copyright (C) 2011 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.
-*/
-#include "osDynLibrary.h"
-
-#ifndef _WIN32
-#include <dlfcn.h>
-#endif
-#include <stdio.h>
-
-namespace osUtils {
-
-dynLibrary *dynLibrary::open(const char *p_libName)
-{
- dynLibrary *lib = new dynLibrary();
- if (!lib) {
- return NULL;
- }
-
-#ifdef _WIN32
- lib->m_lib = LoadLibrary(p_libName);
-#else // !WIN32
- lib->m_lib = dlopen(p_libName, RTLD_NOW);
-#endif
-
- if (lib->m_lib == NULL) {
- printf("Failed to load %s\n", p_libName);
-#ifndef _WIN32
- printf("error %s\n", dlerror()); //only on linux
-#endif
- delete lib;
- return NULL;
- }
-
- return lib;
-}
-
-dynLibrary::dynLibrary() :
- m_lib(NULL)
-{
-}
-
-dynLibrary::~dynLibrary()
-{
- if (NULL != m_lib) {
-#ifdef _WIN32
- FreeLibrary(m_lib);
-#else // !WIN32
- dlclose(m_lib);
-#endif
- }
-}
-
-dynFuncPtr dynLibrary::findSymbol(const char *p_symName)
-{
- if (NULL == m_lib) {
- return NULL;
- }
-
-#ifdef _WIN32
- return (dynFuncPtr) GetProcAddress(m_lib, p_symName);
-#else // !WIN32
- return (dynFuncPtr) dlsym(m_lib, p_symName);
-#endif
-}
-
-} // of namespace osUtils
diff --git a/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.h b/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.h
deleted file mode 100644
index c83fbf3..0000000
--- a/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-* Copyright (C) 2011 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 _OSUTILS_DYN_LIBRARY_H
-#define _OSUTILS_DYN_LIBRARY_H
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-namespace osUtils {
-
-typedef void (*dynFuncPtr)(void);
-
-class dynLibrary
-{
-public:
- static dynLibrary *open(const char *p_libName);
- ~dynLibrary();
-
- dynFuncPtr findSymbol(const char *p_symName);
-
-private:
- dynLibrary();
-
-private:
-#ifdef _WIN32
- HMODULE m_lib;
-#else
- void *m_lib;
-#endif
-};
-
-} // of namespace osUtils
-
-
-
-// Macro to compose emugl shared library name under various OS and bitness
-// eg.
-// on x86_64, EMUGL_LIBNAME("foo") --> "lib64foo.so"
-
-#ifdef _WIN32
-# define DLL_EXTENSION "" // _WIN32 LoadLibrary only accept name w/o .dll extension
-#elif defined(__APPLE__)
-# define DLL_EXTENSION ".dylib"
-#else
-# define DLL_EXTENSION ".so"
-#endif
-
-#if defined(__x86_64__)
-# define EMUGL_LIBNAME(name) "lib64" name DLL_EXTENSION
-#elif defined(__i386__)
-# define EMUGL_LIBNAME(name) "lib" name DLL_EXTENSION
-#else
-/* This header is included by target w/o using EMUGL_LIBNAME(). Don't #error, leave it undefined */
-#endif
-
-
-#endif
diff --git a/emulator/opengl/shared/emugl/common/Android.mk b/emulator/opengl/shared/emugl/common/Android.mk
index 58dd6da..e75f887 100644
--- a/emulator/opengl/shared/emugl/common/Android.mk
+++ b/emulator/opengl/shared/emugl/common/Android.mk
@@ -9,16 +9,22 @@ commonSources := \
id_to_object_map.cpp \
lazy_instance.cpp \
pod_vector.cpp \
+ shared_library.cpp \
smart_ptr.cpp \
sockets.cpp \
thread_store.cpp \
host_commonSources := $(commonSources)
+host_commonLdLibs := -lstdc++
+ifneq (windows,$(HOST_OS))
+ host_commonLdLibs += -ldl
+endif
+
$(call emugl-begin-host-static-library,libemugl_common)
LOCAL_SRC_FILES := $(host_commonSources)
$(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/shared)
-$(call emugl-export,LDLIBS,-lstdc++)
+$(call emugl-export,LDLIBS,$(host_commonLdLibs))
$(call emugl-end-module)
ifdef EMUGL_BUILD_64BITS
@@ -26,7 +32,7 @@ ifdef EMUGL_BUILD_64BITS
LOCAL_SRC_FILES := $(host_commonSources)
$(call emugl-export,CFLAGS,-m64 -fPIC)
$(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/shared)
- $(call emugl-export,LDLIBS,-lstdc++)
+ $(call emugl-export,LDLIBS,$(host_commonLdLibs))
$(call emugl-end-module)
endif
@@ -38,6 +44,7 @@ host_commonSources := \
lazy_instance_unittest.cpp \
pod_vector_unittest.cpp \
mutex_unittest.cpp \
+ shared_library_unittest.cpp \
smart_ptr_unittest.cpp \
thread_store_unittest.cpp \
@@ -52,3 +59,13 @@ ifdef EMUGL_BUILD_64BITS
$(call emugl-import,lib64emugl_common lib64emugl_gtest)
$(call emugl-end-module)
endif
+
+$(call emugl-begin-host-shared-library,libemugl_test_shared_library)
+LOCAL_SRC_FILES := testing/test_shared_library.cpp
+$(call emugl-end-module)
+
+ifdef EMUGL_BUILD_64BITS
+ $(call emugl-begin-host64-shared-library,lib64emugl_test_shared_library)
+ LOCAL_SRC_FILES := testing/test_shared_library.cpp
+ $(call emugl-end-module)
+endif
diff --git a/emulator/opengl/shared/emugl/common/shared_library.cpp b/emulator/opengl/shared/emugl/common/shared_library.cpp
new file mode 100644
index 0000000..db1c75c
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/shared_library.cpp
@@ -0,0 +1,105 @@
+// Copyright (C) 2014 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.
+
+#include "emugl/common/shared_library.h"
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifndef _WIN32
+#include <dlfcn.h>
+#include <stdlib.h>
+#endif
+
+namespace emugl {
+
+#ifdef _WIN32
+
+// static
+SharedLibrary* SharedLibrary::open(const char* libraryName) {
+ HMODULE lib = LoadLibrary(libraryName);
+ return lib ? new SharedLibrary(lib) : NULL;
+}
+
+SharedLibrary::SharedLibrary(HandleType lib) : mLib(lib) {}
+
+SharedLibrary::~SharedLibrary() {
+ if (mLib) {
+ FreeLibrary(mLib);
+ }
+}
+
+SharedLibrary::FunctionPtr SharedLibrary::findSymbol(
+ const char* symbolName) {
+ if (!mLib || !symbolName) {
+ return NULL;
+ }
+ return reinterpret_cast<FunctionPtr>(
+ GetProcAddress(mLib, symbolName));
+}
+
+#else // !_WIN32
+
+// static
+SharedLibrary* SharedLibrary::open(const char* libraryName) {
+ const char* libPath = libraryName;
+ char* path = NULL;
+
+ const char* libBaseName = strrchr(libraryName, '/');
+ if (!libBaseName) {
+ libBaseName = libraryName;
+ }
+
+ if (!strchr(libBaseName, '.')) {
+ // There is no extension in this library name, so append one.
+#ifdef __APPLE__
+ static const char kDllExtension[] = ".dylib";
+#else
+ static const char kDllExtension[] = ".so";
+#endif
+ size_t pathLen = strlen(libraryName) + sizeof(kDllExtension);
+ path = static_cast<char*>(malloc(pathLen));
+ snprintf(path, pathLen, "%s%s", libraryName, kDllExtension);
+ libPath = path;
+ }
+
+ void* lib = dlopen(libPath, RTLD_NOW);
+
+ if (path) {
+ free(path);
+ }
+
+ return lib ? new SharedLibrary(lib) : NULL;
+}
+
+SharedLibrary::SharedLibrary(HandleType lib) : mLib(lib) {}
+
+SharedLibrary::~SharedLibrary() {
+ if (mLib) {
+ dlclose(mLib);
+ }
+}
+
+SharedLibrary::FunctionPtr SharedLibrary::findSymbol(
+ const char* symbolName) {
+ if (!mLib || !symbolName) {
+ return NULL;
+ }
+ return reinterpret_cast<FunctionPtr>(dlsym(mLib, symbolName));
+}
+
+#endif // !_WIN32
+
+} // namespace emugl
diff --git a/emulator/opengl/shared/emugl/common/shared_library.h b/emulator/opengl/shared/emugl/common/shared_library.h
new file mode 100644
index 0000000..38d25bd
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/shared_library.h
@@ -0,0 +1,85 @@
+// Copyright (C) 2014 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 EMUGL_COMMON_SHARED_LIBRARY_H
+#define EMUGL_COMMON_SHARED_LIBRARY_H
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+namespace emugl {
+
+// A class used to open a platform-specific shared library, and probe
+// it for symbols. Usage is the following:
+//
+// // Open the library.
+// SharedLibrary* library = SharedLibrary::open("libFoo");
+// if (!library) {
+// ... could not find / open library!
+// }
+//
+// //Probe for function symbol.
+// FunctionPtr my_func = library->findSymbol("my_func");
+//
+// // Closes library/
+// delete library;
+//
+class SharedLibrary {
+public:
+ // Open a given library. |libraryName| can be either a full library
+ // path, or a simple name without an extension. On success, returns
+ // a new SharedLibrary instance that must be deleted by the caller.
+ static SharedLibrary* open(const char* libraryName);
+
+ // Closes an existing SharedLibrary instance.
+ ~SharedLibrary();
+
+ // Generic function pointer type, for values returned by the
+ // findSymbol() method.
+ typedef void (*FunctionPtr)(void);
+
+ // Probe a given SharedLibrary instance to find a symbol named
+ // |symbolName| in it. Return its address as a FunctionPtr, or
+ // NULL if the symbol is not found.
+ FunctionPtr findSymbol(const char* symbolName);
+
+private:
+#ifdef _WIN32
+ typedef HMODULE HandleType;
+#else
+ typedef void* HandleType;
+#endif
+
+ // Constructor intentionally hidden.
+ SharedLibrary(HandleType);
+
+ HandleType mLib;
+};
+
+// Macro to compose emugl shared library name under various OS and bitness
+// eg.
+// on x86_64, EMUGL_LIBNAME("foo") --> "lib64foo"
+
+#if defined(__x86_64__)
+# define EMUGL_LIBNAME(name) "lib64" name
+#elif defined(__i386__)
+# define EMUGL_LIBNAME(name) "lib" name
+#else
+/* This header is included by target w/o using EMUGL_LIBNAME(). Don't #error, leave it undefined */
+#endif
+
+} // namespace emugl
+
+#endif // EMUGL_COMMON_SHARED_LIBRARY_H
diff --git a/emulator/opengl/shared/emugl/common/shared_library_unittest.cpp b/emulator/opengl/shared/emugl/common/shared_library_unittest.cpp
new file mode 100644
index 0000000..cec4c73
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/shared_library_unittest.cpp
@@ -0,0 +1,141 @@
+// Copyright (C) 2014 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.
+
+#include "emugl/common/shared_library.h"
+
+#include <gtest/gtest.h>
+
+#include <string>
+
+#include <limits.h>
+#include <string.h>
+
+// Hack to get the current executable's full path.
+namespace testing {
+namespace internal {
+
+extern std::string g_executable_path;
+
+} // namespace internal
+} // namespace testing
+
+namespace emugl {
+
+namespace {
+
+// Return the name/path of the test shared library to load.
+// Note that this doesn't include a platform-specific extension.
+// This assumes that the test shared library is under the lib/ sub-directory
+// of the current executable's path!
+std::string GetTestLibraryName() {
+ static const char kSubDir[] = "lib/";
+#ifdef __x86_64__
+ static const char kLibraryPrefix[] = "lib64";
+#else
+ static const char kLibraryPrefix[] = "lib";
+#endif
+ static const char kTestLibrarySuffix[] = "emugl_test_shared_library";
+
+ const char* exec_path = testing::internal::g_executable_path.c_str();
+
+#ifdef _WIN32
+ const char* p = strrchr(exec_path, '/');
+ const char* p2 = strrchr(exec_path, '\\');
+ if (p2) {
+ if (!p || p2 > p) {
+ p = p2;
+ }
+ }
+#else
+ const char* p = strrchr(exec_path, '/');
+#endif
+
+ std::string path;
+
+ if (!p) {
+ path = "./";
+ } else {
+ path = std::string(exec_path, p - exec_path + 1U);
+ }
+ path += kSubDir;
+ path += kLibraryPrefix;
+ path += kTestLibrarySuffix;
+ printf("Library path: %s\n", path.c_str());
+ return path;
+}
+
+class SharedLibraryTest : public testing::Test {
+public:
+ SharedLibraryTest() {
+ // Locate the shared library
+ mLibraryPath = GetTestLibraryName();
+ }
+
+ ~SharedLibraryTest() {}
+
+ const char* library_path() const { return mLibraryPath.c_str(); }
+
+private:
+ std::string mLibraryPath;
+};
+
+class ScopedSharedLibrary {
+public:
+ explicit ScopedSharedLibrary(SharedLibrary* lib) : mLib(lib) {}
+ ~ScopedSharedLibrary() {
+ delete mLib;
+ }
+ SharedLibrary* get() const { return mLib; }
+
+ SharedLibrary* operator->() { return mLib; }
+
+private:
+ SharedLibrary* mLib;
+};
+
+} // namespace
+
+TEST_F(SharedLibraryTest, Open) {
+ ScopedSharedLibrary lib(SharedLibrary::open(library_path()));
+ EXPECT_TRUE(lib.get());
+}
+
+TEST_F(SharedLibraryTest, OpenWithExtension) {
+ std::string path = library_path();
+#ifdef _WIN32
+ path += ".dll";
+#elif defined(__APPLE__)
+ path += ".dylib";
+#else
+ path += ".so";
+#endif
+ ScopedSharedLibrary lib(SharedLibrary::open(path.c_str()));
+ EXPECT_TRUE(lib.get());
+}
+
+TEST_F(SharedLibraryTest, FindSymbol) {
+ ScopedSharedLibrary lib(SharedLibrary::open(library_path()));
+ EXPECT_TRUE(lib.get());
+
+ if (lib.get()) {
+ typedef int (*FooFunction)(void);
+
+ FooFunction foo_func = reinterpret_cast<FooFunction>(
+ lib->findSymbol("foo_function"));
+ EXPECT_TRUE(foo_func);
+ EXPECT_EQ(42, (*foo_func)());
+ }
+}
+
+} // namespace emugl
diff --git a/emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp b/emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp
new file mode 100644
index 0000000..598a963
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp
@@ -0,0 +1,22 @@
+// Copyright (C) 2014 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.
+
+// This source file must be compiled into a simple shared library which
+// will be used by shared_library_unittest.cpp to verify that the
+// emugl::SharedLibrary class works properly.
+
+
+extern "C" int foo_function(void) {
+ return 42;
+}