#define CALL_GL_API_RETURN(_api, ...) \
CALL_GL_API(_api, __VA_ARGS__) \
return 0; // placate gcc's warnings. never reached.
CALL_GL_API这个带参数的宏。它的意思是获取TLS_SLOT_OPENGL_API的TLS,如果它的值不是NULL,就跳到相应的OpenGL ES API的地址去执行。这个地方为什么会跳过去呢??因为从线程局部存储保存的线程指针,指向了一个gl_hooks_t指针,而这个指针指向的结构体里的成员已经在EGL中被初始化为了libGLES_android.so里的函数地址了。所以就可以跳过去了。
那么在哪里初始化gl_hooks_t指针的呢? (frameworks\base\opengl\libs\EGL\Loader.cpp)
FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r");
if (cfg == NULL) { // 如果找不到这个配置则默认加载软件3D库即 libGLES_android.so
// default config
LOGD("egl.cfg not found, using default config");
gConfig.add( entry_t(0, 0, "android") );
}
否则根据配置文件加载硬件3D库,egl.cfg 文件格式是“dpy impl tag”比如自己添加的硬件加速库是libGLES_mali.so,则需要在此文件里这样编写
0 1 mali
修改后要重启才可生效。
加载就是利用dlopen、dlsym加载并赋值:
void* dso = dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
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++;
}
char const * const gl_names[] = {
#include "entries.in"
NULL
};
char const * const egl_names[] = {
#include "egl_entries.in"
NULL
};
这里面包含的函数头文件在:gl2_api.in 及 gl_api.in 中对应于不同的版本,对应用C头文件接口是: include/RGL/egl.h 及
include\GLES\中的gl.h和glext.h,这些接口供外部调用OpenGL本库所使用接口,这些接口基本上和OpenGL标准接口一致。
#include <EGL/egl.h>
#include <GLES/gl.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
插一句如何知道哪些OpenGL函数没有实现呢?
在init_api函数添加打印即可知道哪些函数没有实现: