/* * 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 "ThreadInfo.h" #include #include #include "eglContext.h" namespace ClientAPIExts { // // define function pointer type for each extention function // typename has the form __egl_{funcname}_t // #define FUNC_TYPE(fname) __egl_ ## fname ## _t // NOLINT: clang-tidy adds parentheses around 'params'. #define API_ENTRY(fname,params,args) \ typedef void (GL_APIENTRY *FUNC_TYPE(fname)) params; // NOLINT #define API_ENTRY_RET(rtype,fname,params,args) \ typedef rtype (GL_APIENTRY *FUNC_TYPE(fname)) params; // NOLINT #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[2]; #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(const EGLClient_glesInterface *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. // // NOLINT: clang-tidy adds parentheses around 'args'. #define API_ENTRY(fname,params,args) \ static void _egl_ ## fname params \ { \ EGLThreadInfo* thread = getEGLThreadInfo(); \ if (!thread->currentContext) { \ return; \ } \ int clientMajorVersion = (int)thread->currentContext->majorVersion; \ int idx = clientMajorVersion == 1 ? 0 : 1; \ if (!s_client_extensions[idx].fname) { \ return; \ } \ (*s_client_extensions[idx].fname) args; /* NOLINT */ \ } #define API_ENTRY_RET(rtype,fname,params,args) \ static rtype _egl_ ## fname params \ { \ EGLThreadInfo* thread = getEGLThreadInfo(); \ if (!thread->currentContext) { \ return (rtype)0; \ } \ int idx = (int)thread->currentContext->majorVersion - 1; \ if (!s_client_extensions[idx].fname) { \ return (rtype)0; \ } \ return (*s_client_extensions[idx].fname) args; /* NOLINT */ \ } #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, (void*)_egl_ ## fname}, #define API_ENTRY_RET(rtype,fname,params,args) \ API_ENTRY(fname,params,args) static const struct _client_ext_funcs { const char *fname; void* 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. // void* getProcAddress(const char *fname) { for (int i=0; i