diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk index 946e84914..060f3c6d1 100644 --- a/opengl/libagl/Android.mk +++ b/opengl/libagl/Android.mk @@ -47,6 +47,8 @@ LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger LOCAL_CFLAGS += -fvisibility=hidden LOCAL_LDLIBS := -lpthread -ldl -LOCAL_MODULE:= libagl + +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl +LOCAL_MODULE:= libGLES_android include $(BUILD_SHARED_LIBRARY) diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk index 67a67ec8b..33a169888 100644 --- a/opengl/libs/Android.mk +++ b/opengl/libs/Android.mk @@ -8,9 +8,11 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ EGL/egl.cpp \ + EGL/hooks.cpp \ + EGL/Loader.cpp \ # -LOCAL_SHARED_LIBRARIES += libcutils +LOCAL_SHARED_LIBRARIES += libcutils libutils LOCAL_LDLIBS := -lpthread -ldl LOCAL_MODULE:= libEGL @@ -27,8 +29,24 @@ LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES LOCAL_CFLAGS += -fvisibility=hidden include $(BUILD_SHARED_LIBRARY) +installed_libEGL := $(LOCAL_INSTALLED_MODULE) +# OpenGL drivers config file +ifneq ($(BOARD_EGL_CFG),) + +include $(CLEAR_VARS) +LOCAL_MODULE := egl.cfg +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/egl +LOCAL_SRC_FILES := ../../../../$(BOARD_EGL_CFG) +include $(BUILD_PREBUILT) + +# make sure we depend on egl.cfg, so it gets installed +$(installed_libEGL): | egl.cfg + +endif ############################################################################### # Build the wrapper OpenGL ES 1.x library diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp new file mode 100644 index 000000000..0e0f2c263 --- /dev/null +++ b/opengl/libs/EGL/Loader.cpp @@ -0,0 +1,278 @@ +/* + ** Copyright 2007, 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 +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "hooks.h" +#include "egl_impl.h" + +#include "Loader.h" + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + + +/* + * EGL drivers are called + * + * /system/lib/egl/lib{[EGL|GLESv1_CM|GLESv2] | GLES}_$TAG.so + * + */ + +ANDROID_SINGLETON_STATIC_INSTANCE( Loader ) + +// ---------------------------------------------------------------------------- + +Loader::driver_t::driver_t(void* gles) +{ + dso[0] = gles; + for (size_t i=1 ; i>> %u %u %s", dpy, impl, tag); + gConfig.add( entry_t(dpy, impl, tag) ); + } + } + fclose(cfg); + } +} + +Loader::~Loader() +{ +} + +const char* Loader::getTag(int dpy, int impl) +{ + const Vector& cfgs(gConfig); + const size_t c = cfgs.size(); + for (size_t i=0 ; iset( load_driver(path, hooks, GLESv1_CM), GLESv1_CM ); + + snprintf(path, PATH_MAX, format, "GLESv2", tag); + hnd->set( load_driver(path, hooks, GLESv2), GLESv2 ); + } + } + } + + LOG_FATAL_IF(!index && !impl && !hnd, + "couldn't't find the default OpenGL ES implementation " + "for default display"); + + return (void*)hnd; +} + +status_t Loader::close(void* driver) +{ + driver_t* hnd = (driver_t*)driver; + delete hnd; + return NO_ERROR; +} + +void Loader::init_api(void* dso, + char const * const * api, + __eglMustCastToProperFunctionPointerType* curr, + getProcAddressType getProcAddress) +{ + char scrap[256]; + while (*api) { + char const * name = *api; + __eglMustCastToProperFunctionPointerType f = + (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); + if (f == NULL) { + // couldn't find the entry-point, use eglGetProcAddress() + f = getProcAddress(name); + } + if (f == NULL) { + // Try without the OES postfix + ssize_t index = ssize_t(strlen(name)) - 3; + if ((index>0 && (index<255)) && (!strcmp(name+index, "OES"))) { + strncpy(scrap, name, index); + scrap[index] = 0; + f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap); + //LOGD_IF(f, "found <%s> instead", scrap); + } + } + if (f == NULL) { + // Try with the OES postfix + ssize_t index = ssize_t(strlen(name)) - 3; + if ((index>0 && (index<252)) && (strcmp(name+index, "OES"))) { + strncpy(scrap, name, index); + scrap[index] = 0; + strcat(scrap, "OES"); + f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap); + //LOGD_IF(f, "found <%s> instead", scrap); + } + } + if (f == NULL) { + //LOGD("%s", name); + f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented; + } + *curr++ = f; + api++; + } +} + +void *Loader::load_driver(const char* driver, gl_hooks_t* hooks, uint32_t mask) +{ + //LOGD("%s", driver); + void* dso = dlopen(driver, RTLD_NOW | RTLD_LOCAL); + LOGE_IF(!dso, + "couldn't load <%s> library (%s)", + driver, dlerror()); + if (dso == 0) + return 0; + + if (mask & EGL) { + getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress"); + + LOGE_IF(!getProcAddress, + "can't find eglGetProcAddress() in %s", driver); + + gl_hooks_t::egl_t* egl = &hooks->egl; + __eglMustCastToProperFunctionPointerType* curr = + (__eglMustCastToProperFunctionPointerType*)egl; + char const * const * api = egl_names; + while (*api) { + char const * name = *api; + __eglMustCastToProperFunctionPointerType f = + (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); + if (f == NULL) { + // couldn't find the entry-point, use eglGetProcAddress() + f = getProcAddress(name); + if (f == NULL) { + f = (__eglMustCastToProperFunctionPointerType)0; + } + } + *curr++ = f; + api++; + } + } + + if (mask & GLESv1_CM) { + init_api(dso, gl_names, + (__eglMustCastToProperFunctionPointerType*)&hooks->gl, + getProcAddress); + } + + if (mask & GLESv2) { + init_api(dso, gl2_names, + (__eglMustCastToProperFunctionPointerType*)&hooks->gl2, + getProcAddress); + } + + return dso; +} + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h new file mode 100644 index 000000000..69f6dd5c2 --- /dev/null +++ b/opengl/libs/EGL/Loader.h @@ -0,0 +1,90 @@ +/* + ** Copyright 2009, 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_EGL_LOADER_H +#define ANDROID_EGL_LOADER_H + +#include +#include +#include + +#include +#include +#include +#include + +#include + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +struct gl_hooks_t; + +class Loader : public Singleton +{ + friend class Singleton; + + typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)( + const char*); + + enum { + EGL = 0x01, + GLESv1_CM = 0x02, + GLESv2 = 0x04 + }; + struct driver_t { + driver_t(void* gles); + ~driver_t(); + status_t set(void* hnd, int32_t api); + void* dso[3]; + }; + + struct entry_t { + entry_t() { } + entry_t(int dpy, int impl, const char* tag); + int dpy; + int impl; + String8 tag; + }; + + Vector gConfig; + getProcAddressType getProcAddress; + + const char* getTag(int dpy, int impl); + +public: + ~Loader(); + + void* open(EGLNativeDisplayType display, int impl, gl_hooks_t* hooks); + status_t close(void* driver); + +private: + Loader(); + void *load_driver(const char* driver, gl_hooks_t* hooks, uint32_t mask); + + static __attribute__((noinline)) + void init_api(void* dso, + char const * const * api, + __eglMustCastToProperFunctionPointerType* curr, + getProcAddressType getProcAddress); +}; + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + +#endif /* ANDROID_EGL_LOADER_H */ diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index 4eae98eee..77648f280 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -38,7 +38,7 @@ #include "hooks.h" #include "egl_impl.h" - +#include "Loader.h" #define MAKE_CONFIG(_impl, _index) ((EGLConfig)(((_impl)<<24) | (_index))) #define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r) @@ -139,38 +139,6 @@ struct tls_t EGLContext ctx; }; -static void gl_unimplemented() { - LOGE("called unimplemented OpenGL ES API"); -} - -// ---------------------------------------------------------------------------- -// GL / EGL hooks -// ---------------------------------------------------------------------------- - -#undef GL_ENTRY -#undef EGL_ENTRY -#define GL_ENTRY(_r, _api, ...) #_api, -#define EGL_ENTRY(_r, _api, ...) #_api, - -static char const * const gl_names[] = { - #include "GLES_CM/gl_entries.in" - #include "GLES_CM/glext_entries.in" - NULL -}; - -static char const * const gl2_names[] = { - #include "GLES2/gl2_entries.in" - #include "GLES2/gl2ext_entries.in" - NULL -}; - -static char const * const egl_names[] = { - #include "egl_entries.in" - NULL -}; - -#undef GL_ENTRY -#undef EGL_ENTRY // ---------------------------------------------------------------------------- @@ -281,105 +249,6 @@ EGLContext getContext() { /*****************************************************************************/ -typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)( - const char*); - -static __attribute__((noinline)) -void init_api(void* dso, - char const * const * api, - __eglMustCastToProperFunctionPointerType* curr, - getProcAddressType getProcAddress) -{ - char scrap[256]; - while (*api) { - char const * name = *api; - __eglMustCastToProperFunctionPointerType f = - (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); - if (f == NULL) { - // couldn't find the entry-point, use eglGetProcAddress() - f = getProcAddress(name); - } - if (f == NULL) { - // Try without the OES postfix - ssize_t index = ssize_t(strlen(name)) - 3; - if ((index>0 && (index<255)) && (!strcmp(name+index, "OES"))) { - strncpy(scrap, name, index); - scrap[index] = 0; - f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap); - //LOGD_IF(f, "found <%s> instead", scrap); - } - } - if (f == NULL) { - // Try with the OES postfix - ssize_t index = ssize_t(strlen(name)) - 3; - if ((index>0 && (index<252)) && (strcmp(name+index, "OES"))) { - strncpy(scrap, name, index); - scrap[index] = 0; - strcat(scrap, "OES"); - f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap); - //LOGD_IF(f, "found <%s> instead", scrap); - } - } - if (f == NULL) { - //LOGD("%s", name); - f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented; - } - *curr++ = f; - api++; - } -} - -static __attribute__((noinline)) -void *load_driver(const char* driver, gl_hooks_t* hooks) -{ - //LOGD("%s", driver); - void* dso = dlopen(driver, RTLD_NOW | RTLD_LOCAL); - LOGE_IF(!dso, - "couldn't load <%s> library (%s)", - driver, dlerror()); - - if (dso) { - // first find the symbol for eglGetProcAddress - - typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)( - const char*); - - getProcAddressType getProcAddress = - (getProcAddressType)dlsym(dso, "eglGetProcAddress"); - - LOGE_IF(!getProcAddress, - "can't find eglGetProcAddress() in %s", driver); - - gl_hooks_t::egl_t* egl = &hooks->egl; - __eglMustCastToProperFunctionPointerType* curr = - (__eglMustCastToProperFunctionPointerType*)egl; - char const * const * api = egl_names; - while (*api) { - char const * name = *api; - __eglMustCastToProperFunctionPointerType f = - (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); - if (f == NULL) { - // couldn't find the entry-point, use eglGetProcAddress() - f = getProcAddress(name); - if (f == NULL) { - f = (__eglMustCastToProperFunctionPointerType)0; - } - } - *curr++ = f; - api++; - } - - init_api(dso, gl_names, - (__eglMustCastToProperFunctionPointerType*)&hooks->gl, - getProcAddress); - - init_api(dso, gl2_names, - (__eglMustCastToProperFunctionPointerType*)&hooks->gl2, - getProcAddress); - } - return dso; -} - template static __attribute__((noinline)) int binarySearch( @@ -605,12 +474,15 @@ EGLDisplay egl_init_displays(NativeDisplayType display) EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU); egl_display_t* d = &gDisplay[index]; + // get our driver loader + Loader& loader(Loader::getInstance()); + // dynamically load all our EGL implementations for that display // and call into the real eglGetGisplay() egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE]; if (cnx->dso == 0) { cnx->hooks = &gHooks[IMPL_SOFTWARE]; - cnx->dso = load_driver("libagl.so", cnx->hooks); + cnx->dso = loader.open(display, 0, cnx->hooks); } if (cnx->dso && d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY) { d->dpys[IMPL_SOFTWARE] = cnx->hooks->egl.eglGetDisplay(display); @@ -624,7 +496,7 @@ EGLDisplay egl_init_displays(NativeDisplayType display) property_get("debug.egl.hw", value, "1"); if (atoi(value) != 0) { cnx->hooks = &gHooks[IMPL_HARDWARE]; - cnx->dso = load_driver("libhgl2.so", cnx->hooks); + cnx->dso = loader.open(display, 1, cnx->hooks); } else { LOGD("3D hardware acceleration is disabled"); } @@ -656,7 +528,8 @@ EGLDisplay egl_init_displays(NativeDisplayType display) if (d->dpys[IMPL_HARDWARE] == EGL_NO_DISPLAY) { LOGE("h/w accelerated eglGetDisplay() failed (%s)", egl_strerror(cnx->hooks->egl.eglGetError())); - dlclose((void*)cnx->dso); + + loader.close(cnx->dso); cnx->dso = 0; // in case of failure, we want to make sure we don't try again // as it's expensive. @@ -768,6 +641,8 @@ EGLBoolean eglTerminate(EGLDisplay dpy) if (android_atomic_dec(&dp->refs) != 1) return EGL_TRUE; + Loader& loader(Loader::getInstance()); + EGLBoolean res = EGL_FALSE; for (int i=0 ; iqueryString[i].extensions); dp->numConfigs[i] = 0; dp->dpys[i] = EGL_NO_DISPLAY; - dlclose((void*)cnx->dso); + + loader.close(cnx->dso); cnx->dso = 0; res = EGL_TRUE; } diff --git a/opengl/libs/EGL/hooks.cpp b/opengl/libs/EGL/hooks.cpp new file mode 100644 index 000000000..224636669 --- /dev/null +++ b/opengl/libs/EGL/hooks.cpp @@ -0,0 +1,67 @@ +/* + ** Copyright 2009, 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 +#include +#include + +#include + +#include "hooks.h" + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +void gl_unimplemented() { + LOGE("called unimplemented OpenGL ES API"); +} + + +// ---------------------------------------------------------------------------- +// GL / EGL hooks +// ---------------------------------------------------------------------------- + +#undef GL_ENTRY +#undef EGL_ENTRY +#define GL_ENTRY(_r, _api, ...) #_api, +#define EGL_ENTRY(_r, _api, ...) #_api, + +char const * const gl_names[] = { + #include "GLES_CM/gl_entries.in" + #include "GLES_CM/glext_entries.in" + NULL +}; + +char const * const gl2_names[] = { + #include "GLES2/gl2_entries.in" + #include "GLES2/gl2ext_entries.in" + NULL +}; + +char const * const egl_names[] = { + #include "egl_entries.in" + NULL +}; + +#undef GL_ENTRY +#undef EGL_ENTRY + + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h index 80455d0a2..c5f753d56 100644 --- a/opengl/libs/egl_impl.h +++ b/opengl/libs/egl_impl.h @@ -31,7 +31,7 @@ struct gl_hooks_t; struct egl_connection_t { - void volatile * dso; + void * dso; gl_hooks_t * hooks; EGLint major; EGLint minor; diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h index 1257785c0..37292eef0 100644 --- a/opengl/libs/hooks.h +++ b/opengl/libs/hooks.h @@ -21,12 +21,12 @@ #include #include +#include + #include #include - #include #include - #include #include @@ -102,6 +102,13 @@ struct gl_hooks_t { extern gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS]; extern pthread_key_t gGLWrapperKey; +extern "C" void gl_unimplemented(); + +extern char const * const gl_names[]; +extern char const * const gl2_names[]; +extern char const * const egl_names[]; + +// ---------------------------------------------------------------------------- #if USE_FAST_TLS_KEY