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("ro.kernel.qemu", prop, "0"); if (atoi(prop) != 1) return; property_get("ro.kernel.qemu.gles",prop,"0"); if (atoi(prop) == 1) { ALOGD("Emulator has host GPU support, qemu.gles is set to 1."); property_set("qemu.gles", "1"); return; } // for now, checking the following // directory is good enough for emulator system images const char* vendor_lib_path = #if defined(__LP64__) "/vendor/lib64/egl"; #else "/vendor/lib/egl"; #endif const bool has_vendor_lib = (access(vendor_lib_path, R_OK) == 0); if (has_vendor_lib) { ALOGD("Emulator has vendor provided software renderer, qemu.gles is set to 2."); property_set("qemu.gles", "2"); } else { ALOGD("Emulator without GPU support detected. " "Fallback to legacy software renderer, qemu.gles is set to 0."); property_set("qemu.gles", "0"); } } void* Loader::open(egl_connection_t* cnx) { void* dso; driver_t* hnd = 0; setEmulatorGlesValue(); dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2); if (dso) { hnd = new driver_t(dso); } else { // Always load EGL first dso = load_driver("EGL", cnx, EGL); if (dso) { hnd = new driver_t(dso); hnd->set( load_driver("GLESv1_CM", cnx, GLESv1_CM), GLESv1_CM ); hnd->set( load_driver("GLESv2", cnx, GLESv2), GLESv2 ); } } LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation"); cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so"); cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so"); cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so"); LOG_ALWAYS_FATAL_IF(!cnx->libEgl, "couldn't load system EGL wrapper libraries"); LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1, "couldn't load system OpenGL ES wrapper libraries"); return (void*)hnd; } |
这个函数中,执行步骤如下:
-
为设备是模拟器的情况,设置系统属性
qemu.gles
。 -
加载设备特有的图形驱动库,包括 EGL 库,OpenGL ES 1.0 和 2.0 的库。
-
加载图形驱动 Wrapper,它们都位于
/system/lib64
或/system/lib
。
egl_connection_t
中的几个指针中,dso
实际为 struct driver_t
指针,该结构定义(位于 frameworks/native/opengl/libs/EGL/Loader.h
)如下:
1 2 3 4 5 6 |
struct driver_t { driver_t(void* gles); ~driver_t(); status_t set(void* hnd, int32_t api); void* dso[3]; }; |
struct driver_t
包含设备生产商提供的设备特有 EGL 和 OpenGL ES 实现库的句柄,如果 EGL 接口和 OpenGL 接口由单独的库实现,它包含一个库的句柄,即这个单独的库,如果 EGL 接口由不同的库实现,它则包含所有这些库的句柄。
egl_connection_t
的 libEgl
、libGles2
和 libGles1
为动态链接库句柄,其中 libEgl
指向 Android 的 EGL Wrapper 库;libGles1
指向 Android 的 GLESv1_CM
Wrapper 库;libGles2
指向 Android 的 GLESv2
Wrapper 库。
然后来看 Loader::load_driver()
:
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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 < |