加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Android OpenGL库加载和调用过程

(2016-04-28 21:24:13)
标签:

android

opengl

egl

OpenGLEGL

Android里跟OpenGL相关的模块主要是两个,一个是OpenGL ES, 另一个是EGLEGLOpenGL和本地窗口的接口。在调用GLES glXX函数进行绘图之前,必须要调用egl的函数进行opengl环境的初始化,比如eglGetDisplayeglInitializeeglChooseConfigeglCreateWindowSurface等。这些函数结合本地窗口,做完后就可以调OpenGLglxxxx函数来画图了。Android的起机动画是一个很好的例子,frameworks/base/cmds/bootanimation/BootAnimation.cpp

 

EGLOpenGL的关系网上有很多教程和文章,这里就不细述了。

 

OpenGL/EGL库加载过程

当前支持Android主流SOC平台都硬件支持OpenGL ES,这些平台提供预先编译好的对OpenGL ES支持的二进制库文件,一般库文件位于/system/lib/egl/system/vendor/lib/egl/目录中。这个加载方式跟grallochwcomposer类似,都是用dlopen的方式加载。

 

eglGetDisplay被调用时,opengl的库文件就被加载了,具体过程是:

eglApi.cpp:: eglGetDisplay

egl_init_drivers

egl_init_drivers_locked

Loader::open

load_driver("GLES",…);

Loader.cpp::load_driver里,它把所有eglxxx, glxxx函数定位,并存到egl_connection_t. gl_hooks_t(hooks[2]).gl里,两个hooks是针对于gles v1v2

gl_hooks_t的结构定义

struct gl_hooks_t {

    struct gl_t {

        #include "entries.in"

} gl;

};

entries.in里定义了GLES的函数集,库加载时根据这个表循环就可以查找GLES函数的实现了:

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)

GL_ENTRY(void, glAlphaFuncx, GLenum func, GLfixed ref)

GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLfixed ref)

GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader)

GL_ENTRY(void, glBeginPerfMonitorAMD, GLuint monitor)

GL_ENTRY(void, glBeginPerfQueryINTEL, GLuint queryHandle)

GL_ENTRY(void, glBeginQuery, GLenum target, GLuint id)

 

加载egl的函数表和GLES的方式非常类似,区别就在于egl的函数表是在egl_entries.in里定义:

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的函数不在hooks里存,它存在egl_connection_t. egl_t里,这里egl_t也是一个函数表:

struct egl_t {

    #include "EGL/egl_entries.in"

};

 

OpenGL/EGL函数调用流程

这一节是说java/native c/c++glxxx/eglxxx函数是怎么调用Soc提供的.so库文件里的。

 

egl函数调用

egl函数可以在javanative里调用,如果从java里调用,直接调EGL14的静态函数:

mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);

然后函数就走到jni里:

android_opengl_EGL14.cpp::android_eglGetDisplay里,最后调到eglAPI.cpp:: eglGetDisplay里了。

有些egl函数会调用加载的库函数表里,有些不会。比如下面这个eglGetConfigs会:

    if (cnx->dso) {

        res = cnx->egl.eglGetConfigs(

                dp->disp.dpy, configs, config_size, num_config);

}

 

cnx->egl就是前面说的函数表

struct egl_t {

    #include "EGL/egl_entries.in"

};

 

GLES函数调用

GLES也是既可以从java/jni里调,也可以在native里调用。GLES函数都以gl开头。

比如java/native glViewport,这个函数GLES v1/V2里都有,以v1为例,javaglViewport通过android_opengl_GLES10.cpp:: android_glViewport__IIII调到了glViewport(native函数)。这个函数是在frameworks/native/opengl/libs/GLES_CM/gl.cpp里实现。这个文件里有:

extern "C" {

#pragma GCC diagnostic ignored "-Wunused-parameter"

#include "gl_api.in"

#include "glext_api.in"

#pragma GCC diagnostic warning "-Wunused-parameter"

}

它跟前面类似,函数定于在函数表gl_api.in里。gl_api.in里定义是:

void API_ENTRY(glVertexPointer)(GLint size, GLenum type, GLsizei stride, const void * pointer) {

    CALL_GL_API(glVertexPointer, size, type, stride, pointer);

}

void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {

    CALL_GL_API(glViewport, x, y, width, height);

}

 

CALL_GL_API是一个宏定义,就在gl.cpp里。它定义是如果调了这个函数(比如glViewport),最终会调用gl_hooks_t里的函数指针。

ARM的:

  

   [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api))    \

            : "r12"

I386的:

  

 [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \

            : "cc"                                             

前面说过,GLES的函数库动态加载,并存于gl_hooks_t里。这里就跟前面对上了,也就是说,如果调了GLESglxxxx函数,它会最终调用存在gl_hooks_t里动态加载的函数指针。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有