diff --git a/tools/emulator/opengl/host/libs/Translator/EGL/Android.mk b/tools/emulator/opengl/host/libs/Translator/EGL/Android.mk index 1109f121e..96e87de3c 100644 --- a/tools/emulator/opengl/host/libs/Translator/EGL/Android.mk +++ b/tools/emulator/opengl/host/libs/Translator/EGL/Android.mk @@ -37,7 +37,8 @@ LOCAL_SRC_FILES := \ EglPbufferSurface.cpp \ EglPixmapSurface.cpp \ EglThreadInfo.cpp \ - EglDisplay.cpp + EglDisplay.cpp \ + ClientAPIExts.cpp $(call emugl-end-module) diff --git a/tools/emulator/opengl/host/libs/Translator/EGL/ClientAPIExts.cpp b/tools/emulator/opengl/host/libs/Translator/EGL/ClientAPIExts.cpp new file mode 100644 index 000000000..42d5764b3 --- /dev/null +++ b/tools/emulator/opengl/host/libs/Translator/EGL/ClientAPIExts.cpp @@ -0,0 +1,159 @@ +/* +* 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 "ClientAPIExts.h" +#include "EglGlobalInfo.h" +#include "GLcommon/GLutils.h" +#include "GLcommon/TranslatorIfaces.h" +#include "ThreadInfo.h" +#include +#include + +namespace ClientAPIExts +{ + +// +// define function pointer type for each extention function +// typename has the form __egl_{funcname}_t +// +#define FUNC_TYPE(fname) __egl_ ## fname ## _t +#define API_ENTRY(fname,params,args) \ + typedef void (GL_APIENTRY *FUNC_TYPE(fname)) params; + +#define API_ENTRY_RET(rtype,fname,params,args) \ + typedef rtype (GL_APIENTRY *FUNC_TYPE(fname)) params; + +#include "ClientAPIExts.in" +#undef API_ENTRY +#undef API_ENTRY_RET + +///// +// Define static table to store the function value for each +// client API. functions pointers will get initialized through +// ClientAPIExts::initClientFuncs function after each client API has been +// loaded. +///// +#define API_ENTRY(fname,params,args) \ + FUNC_TYPE(fname) fname; + +#define API_ENTRY_RET(rtype,fname,params,args) \ + API_ENTRY(fname,params,args) + +static struct _ext_table +{ +#include "ClientAPIExts.in" +} s_client_extensions[MAX_GLES_VERSION-1]; + +#undef API_ENTRY +#undef API_ENTRY_RET + +// +// This function initialized each entry in the s_client_extensions +// struct at the givven index using the givven client interface +// +void initClientFuncs(GLESiface *iface, int idx) +{ +#define API_ENTRY(fname,params,args) \ + s_client_extensions[idx].fname = \ + (FUNC_TYPE(fname))iface->getProcAddress(#fname); + +#define API_ENTRY_RET(rtype,fname,params,args) \ + API_ENTRY(fname,params,args) + + // + // reset all func pointers to NULL + // + memset(&s_client_extensions[idx], 0, sizeof(struct _ext_table)); + + // + // And now query the GLES library for each proc address + // +#include "ClientAPIExts.in" +#undef API_ENTRY +#undef API_ENTRY_RET +} + +// +// Define implementation for each extension function which checks +// the current context version and calls to the correct client API +// function. +// +#define API_ENTRY(fname,params,args) \ + static void _egl_ ## fname params \ + { \ + ThreadInfo* thread = getThreadInfo(); \ + if (!thread->eglContext.Ptr()) { \ + return; \ + } \ + int idx = (int)thread->eglContext->version() - 1; \ + if (!s_client_extensions[idx].fname) { \ + return; \ + } \ + (*s_client_extensions[idx].fname) args; \ + } + +#define API_ENTRY_RET(rtype,fname,params,args) \ + static rtype _egl_ ## fname params \ + { \ + ThreadInfo* thread = getThreadInfo(); \ + if (!thread->eglContext.Ptr()) { \ + return (rtype)0; \ + } \ + int idx = (int)thread->eglContext->version() - 1; \ + if (!s_client_extensions[idx].fname) { \ + return (rtype)0; \ + } \ + return (*s_client_extensions[idx].fname) args; \ + } + +#include "ClientAPIExts.in" +#undef API_ENTRY +#undef API_ENTRY_RET + +// +// Define a table to map function names to the local _egl_ version of +// the extension function, to be used in eglGetProcAddress. +// +#define API_ENTRY(fname,params,args) \ + { #fname, (__translatorMustCastToProperFunctionPointerType)_egl_ ## fname}, +#define API_ENTRY_RET(rtype,fname,params,args) \ + API_ENTRY(fname,params,args) + +static struct _client_ext_funcs { + const char *fname; + __translatorMustCastToProperFunctionPointerType proc; +} s_client_ext_funcs[] = { +#include "ClientAPIExts.in" +}; +static const int numExtFuncs = sizeof(s_client_ext_funcs) / + sizeof(s_client_ext_funcs[0]); + +#undef API_ENTRY +#undef API_ENTRY_RET + +// +// returns the __egl_ version of the givven extension function name. +// +__translatorMustCastToProperFunctionPointerType getProcAddress(const char *fname) +{ + for (int i=0; i +#include "ClientAPIExts.h" int EglGlobalInfo::m_refCount = 0; EglGlobalInfo* EglGlobalInfo::m_singleton = NULL; @@ -27,6 +28,7 @@ EglGlobalInfo::EglGlobalInfo(){ EglOS::initPtrToWglFunctions(); #endif memset(m_gles_ifaces,0,sizeof(m_gles_ifaces)); + memset(m_gles_extFuncs_inited,0,sizeof(m_gles_extFuncs_inited)); } EglGlobalInfo* EglGlobalInfo::getInstance() { @@ -91,3 +93,12 @@ EglDisplay* EglGlobalInfo::getDisplay(EGLDisplay dpy) { EGLNativeInternalDisplayType EglGlobalInfo::generateInternalDisplay(EGLNativeDisplayType dpy){ return EglOS::getInternalDisplay(dpy); } + +void EglGlobalInfo::initClientExtFuncTable(GLESVersion ver) +{ + android::Mutex::Autolock mutex(m_lock); + if (!m_gles_extFuncs_inited[ver]) { + ClientAPIExts::initClientFuncs(m_gles_ifaces[ver], (int)ver - 1); + m_gles_extFuncs_inited[ver] = true; + } +} diff --git a/tools/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.h b/tools/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.h index 6be76efc1..ec07ffe1d 100644 --- a/tools/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.h +++ b/tools/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.h @@ -40,9 +40,10 @@ public: void setIface(GLESiface* iface,GLESVersion ver) { m_gles_ifaces[ver] = iface;}; GLESiface* getIface(GLESVersion ver){ return m_gles_ifaces[ver];} - int nDisplays() const { return m_displays.size();}; + void initClientExtFuncTable(GLESVersion ver); + static EglGlobalInfo* getInstance(); static void delInstance(); @@ -56,6 +57,7 @@ private: DisplaysMap m_displays; EGLNativeInternalDisplayType m_default; GLESiface* m_gles_ifaces[MAX_GLES_VERSION]; + bool m_gles_extFuncs_inited[MAX_GLES_VERSION]; android::Mutex m_lock; }; diff --git a/tools/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp b/tools/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp index fd9779fb7..9205aa9f2 100644 --- a/tools/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp +++ b/tools/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp @@ -36,6 +36,7 @@ #include "EglContext.h" #include "EglConfig.h" #include "EglOsApi.h" +#include "ClientAPIExts.h" #define MAJOR 1 #define MINOR 4 @@ -739,6 +740,12 @@ EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay display, EGLSurface draw thread->updateInfo(newCtx,dpy,newCtx->getGlesContext(),newCtx->getShareGroup(),dpy->getManager(newCtx->version())); newCtx->setSurfaces(newReadSrfc,newDrawSrfc); g_eglInfo->getIface(newCtx->version())->initContext(newCtx->getGlesContext(),newCtx->getShareGroup()); + + // Initialize the GLES extension function table used in + // eglGetProcAddress for the context's GLES version if not + // yet initialized. We initialize it here to make sure we call the + // GLES getProcAddress after when a context is bound. + g_eglInfo->initClientExtFuncTable(newCtx->version()); } // release previous context surface binding @@ -928,14 +935,15 @@ EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY break; } } - } else if (!strncmp(procname,"gl",2)){ //GL proc - retVal = g_eglInfo->getIface(GLES_1_1)->getProcAddress(procname); //try to get it from GLES 1.0 - if(!retVal){ //try to get it from GLES 2.0 - retVal = g_eglInfo->getIface(GLES_2_0)->getProcAddress(procname); - } + } + else { + // Look at the clientAPI (GLES) supported extension + // function table. + retVal = ClientAPIExts::getProcAddress(procname); } return retVal; } + //not supported for now /************************* NOT SUPPORTED FOR NOW ***********************/ EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(