首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > Android >

Android OpenGL库加载历程源码分析

2013-10-08 
Android OpenGL库加载过程源码分析Android系统采用OpenGL绘制3D图形,使用skia来绘制二维图形;OpenGL源码位

Android OpenGL库加载过程源码分析

Android系统采用OpenGL绘制3D图形,使用skia来绘制二维图形;OpenGL源码位于:

frameworks/native/opengl

Android OpenGL库加载历程源码分析

frameworks/base/opengl

本文简单介绍OpenGL库的加载过程。OpenGL以动态库的方式提供,因此在使用OpenGL的接口函数绘图前,需要加载OpenGL库,并得到接口函数指针。函数EGLBoolean egl_init_drivers()就是负责OpenGL库的加载。


因此变量dpy=0, impl = 1, tag = mali


由于libGLES_mali.so库不存在,因此最终加载的是libEGL_mali.so,libGLESv1_CM_mali.so,libGLESv2_mali.so三个库


void Loader::init_api(void* dso, char const * const * api,         __eglMustCastToProperFunctionPointerType* curr,         getProcAddressType getProcAddress) {    const ssize_t SIZE = 256;    char scrap[SIZE];    while (*api) {        char const * name = *api;//根据函数名称从动态库中查找函数指针        __eglMustCastToProperFunctionPointerType f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);        if (f == NULL) {            //使用eglGetProcAddress()得到指定函数指针            f = getProcAddress(name);        }        if (f == NULL) {            //将函数名称去掉后缀OES            ssize_t index = ssize_t(strlen(name)) - 3;            if ((index>0 && (index<SIZE-1)) && (!strcmp(name+index, "OES"))) {                strncpy(scrap, name, index);                scrap[index] = 0;                f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);            }        }        if (f == NULL) {            //将函数名称增加后缀OES             ssize_t index = ssize_t(strlen(name)) - 3;            if (index>0 && strcmp(name+index, "OES")) {                snprintf(scrap, SIZE, "%sOES", name);                f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);            }        }        if (f == NULL) {            f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;            if (!strcmp(name, "glInsertEventMarkerEXT")) {                f = (__eglMustCastToProperFunctionPointerType)gl_noop;            } else if (!strcmp(name, "glPushGroupMarkerEXT")) {                f = (__eglMustCastToProperFunctionPointerType)gl_noop;            } else if (!strcmp(name, "glPopGroupMarkerEXT")) {                f = (__eglMustCastToProperFunctionPointerType)gl_noop;            }        }        *curr++ = f;        api++;    }}
load_driver函数所做的工作:首先通过dlopen加载/system/lib/egl/libGLES_mali.so库,然后从/system/lib/egl/libGLES_mali.so库中提取EGL的各个API函数的地址放到cnx->egl中,从libGLES_mali.so获取GLESv1_CM的API保存到cnx->hooks[GLESv1_INDEX]->gl中,从libGLES_mali.so获取GLESv1_CM的API保存到cnx->hooks[GLESv2_INDEX]->gl。提取EGLAPI地址的方法是首先通过dlsym函数获得一个获取函数地址的函数eglGetProcAddress的地址,然后遍历EGL的API所在文件frameworks/base/opengl/libs/EGL/egl_entries.in。先通过dlsym获取各个API地址,如果返回NULL再利用eglGetProcAddress去获得,如果依旧为空就把函数地址赋值为0;提取GLESv1_CM和GLESv1_CM库中函数地址方法和提取EGL差不多,只是他们的函数文件保存在frameworks/base/opengl/libs/entries.in中。还有它们把函数地址复制给了cnx->hooks[GLESv1_INDEX]->gl和cnx->hooks[GLESv2_INDEX]->gl。

热点排行