它仅是 void 指针的 typedef。
总结一下获取 Display 的整个过程
-
通过
frameworks/native/opengl/libs/EGL
初始化图形驱动; -
通过厂商提供的设备特有的 EGL 库接口初始化 Display。
Android 图形驱动初始化
===============
接下来更详细地看一下图形驱动初始化。这通过 egl_init_drivers()
完成,该函数定义 (位于frameworks/native/opengl/libs/EGL/egl.cpp
) 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
egl_connection_t gEGLImpl; gl_hooks_t gHooks[2]; . . . . . . static EGLBoolean egl_init_drivers_locked() { if (sEarlyInitState) { // initialized by static ctor. should be set here. return EGL_FALSE; } // get our driver loader Loader& loader(Loader::getInstance()); // dynamically load our EGL implementation egl_connection_t* cnx = &gEGLImpl; if (cnx->dso == 0) { cnx->hooks[egl_connection_t::GLESv1_INDEX] = &gHooks[egl_connection_t::GLESv1_INDEX]; cnx->hooks[egl_connection_t::GLESv2_INDEX] = &gHooks[egl_connection_t::GLESv2_INDEX]; cnx->dso = loader.open(cnx); } return cnx->dso ? EGL_TRUE : EGL_FALSE; } static pthread_mutex_t sInitDriverMutex = PTHREAD_MUTEX_INITIALIZER; EGLBoolean egl_init_drivers() { EGLBoolean res; pthread_mutex_lock(&sInitDriverMutex); res = egl_init_drivers_locked(); pthread_mutex_unlock(&sInitDriverMutex); return res; } |
图形驱动初始化通过 Loader::open(egl_connection_t* cnx)
完成,初始化的结果将存储于全局结构 egl_connection_t gEGLImpl
和 gl_hooks_t gHooks[2]
中。
来看一下 gl_hooks_t
的定义(位于 frameworks/native/opengl/libs/hooks.h
):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// maximum number of GL extensions that can be used simultaneously in // a given process. this limitation exists because we need to have // a static function for each extension and currently these static functions // are generated at compile time. #define MAX_NUMBER_OF_GL_EXTENSIONS 256 . . . . . . #undef GL_ENTRY #undef EGL_ENTRY #define GL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__); #define EGL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__); struct egl_t { #include "EGL/egl_entries.in" }; struct gl_hooks_t { struct gl_t { #include "entries.in" } gl; struct gl_ext_t { __eglMustCastToProperFunctionPointerType extensions[MAX_NUMBER_OF_GL_EXTENSIONS]; } ext; }; #undef GL_ENTRY #undef EGL_ENTRY |
其中 __eglMustCastToProperFunctionPointerType
定义 (位于frameworks/native/opengl/include/EGL/egl.h
) 如下:
1 2 3 4 |
/* This is a generic function pointer type, whose name indicates it must * be cast to the proper type *and calling convention* before use. */ typedef void (*__eglMustCastToProperFunctionPointerType)(void); |
__eglMustCastToProperFunctionPointerType
是函数指针类型。struct gl_hooks_t
的 struct gl_ext_t ext
即为函数指针表,它们用来描述 EGL 扩展接口。
struct gl_hooks_t
内的 struct gl_t
结构体,其结构体成员在另外一个文件,即 entries.in
中定义,该文件位于 frameworks/native/opengl/libs/entries.in
:
1 2 3 4 5 6 |
GL_ENTRY(void, glActiveShaderProgram, GLuint pipeline, GLuint program) GL_ENTRY(void, glActiveShaderProgramEXT, GLuint pipeline, GLuint program) GL_ENTRY(void, glActiveTexture, GLenum texture) GL_ENTRY(void, glAlphaFunc, GLenum func, GLfloat ref) GL_ENTRY(void, glAlphaFuncQCOM, GLenum func, GLclampf ref) . . . . . . |
配合 frameworks/native/opengl/libs/hooks.h
中 GL_ENTRY
宏的定义:
1 |
#define GL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__); |
可以看到 struct gl_hooks_t
的 struct gl_t gl
的所有成员都是函数指针,即它是一个函数表,一个 OpenGL 接口函数的函数表。
上面看到的 struct egl_t
与 struct gl_hooks_t
的 struct gl_t gl
定义类似,只是它的结构体成员来自于另外一个文件 frameworks/native/opengl/libs/EGL/egl_entries.in
:
1 2 3 4 5 6 |
EGL_ENTRY(EGLDisplay, eglGetDisplay, NativeDisplayType) EGL_ENTRY(EGLBoolean, eglInitialize, EGLDisplay, EGLint*, EGLint*) EGL_ENTRY(EGLBoolean, eglTerminate, EGLDisplay) EGL_ENTRY(EGLBoolean, eglGetConfigs, EGLDisplay, EGLConfig*, EGLint, EGLint*) EGL_ENTRY(EGLBoolean, eglChooseConfig, EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *) . . . . . . |
EGL_ENTRY
宏的定义与 GL_ENTRY
宏的完全相同。struct egl_t
同样为一个函数表,只是它是 EGL 接口的函数表。
再来看 egl_connection_t
的定义,位于 frameworks/native/opengl/libs/EGL/egldefs.h
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
struct egl_connection_t { enum { GLESv1_INDEX = 0, GLESv2_INDEX = 1 }; inline egl_connection_t() : dso(0) { } void * dso; gl_hooks_t * hooks[2]; EGLint major; EGLint minor; egl_t egl; void* libEgl; void* libGles1; void* libGles2; }; |
这个结构包含了主、次版本号; 4 个指针;两个函数表的指针以及一个函数表。
Loader::open(egl_connection_t* cnx)
初始化图形驱动,主要是初始化这些函数表和指针。Loader::open(egl_connection_t* cnx)
的定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
static void* load_wrapper(const char* path) { void* so = dlopen(path, RTLD_NOW | RTLD_LOCAL); ALOGE_IF(!so, "dlopen(\"%s\") failed: %s", path, dlerror()); return so; } #ifndef EGL_WRAPPER_DIR #if defined(__LP64__) #define EGL_WRAPPER_DIR "/system/lib64" #else #define EGL_WRAPPER_DIR "/system/lib" #endif #endif static void setEmulatorGlesValue(void) { char prop[PROPERTY_VALUE_MAX]; property_get |