Android中opengles,egl库的结构

2023-10-31

目录

egl,opengl es的软硬件实现

需要的库

库的分工

加载模块

软件实现模块

硬件实现模块


egl,opengl es的软硬件实现

需要的库

//算是android中的egl库,用来加载具体的实现(软件实现或者硬件实现)

system\lib\libEGL.so

//opengl具体实现的wrapper,无论软件硬件实现时,均需加载这2个调用转发库



 system\lib\libGLESv1_CM.so  // opengl es 1.0调用的wrapper壳,对应的源文件是:                                                              

///frameworks/native/opengl/libs/GLES_CM/gl.cpp

system\lib\libGLESv2.so      // opengl es 2.0调用的wrapper壳,可shader编程, 对应的源文件是:

//opengl软件实现,即agl,包括egl和gl的实现,不分opengl es 1.0和2.0

system\lib\egl\libGLES_android.so



//opengl的硬件实现,例如高通的实现

system\vendor\lib\egl\libEGL_adreno.so

//opengl硬件实现

system\vendor\lib\egl\libGLESv1_CM_adreno.so

system\vendor\lib\egl\libGLESv2_adreno.so

以上无论软件还是硬件具体实现的接口是 EGL/egl.h,GLES/gl.h。

库的分工

Eglgl的标准在/frameworks/native/opengl/include/下,通常如下加入标准:

include <EGL/egl.h>

include <GLES/gl.h>

加载模块

这俩标准的实现一个是软件实现,一个硬件实现,无论软硬,都需要一个加载模块。在/frameworks/native/opengl/libs/Android.mk文件里的libEGL模块便是。

23LOCAL_SRC_FILES:= 	       \
24	EGL/egl_tls.cpp        \
25	EGL/egl_cache.cpp      \
26	EGL/egl_display.cpp    \
27	EGL/egl_object.cpp     \
28	EGL/egl.cpp 	       \
29	EGL/eglApi.cpp 	       \   ,
30	EGL/trace.cpp              \
31	EGL/getProcAddress.cpp.arm \
32	EGL/Loader.cpp 	       \

37LOCAL_MODULE:= libEGL

当开始使用libEGL 模块中的egl接口(eglApi.cpp中的某些函数,他们是eglGetDisplay,eglGetProcAddress,eglBindAPI等,他们包含了egl_init_drivers()函数用来初始化模块的加载,它是实现在egl.cpp中,而且eglApi.cpp是egl接口实现,它是软件实现的第一层调用)时,就会触发软硬件实现模块的加载,加载软件实现还硬件实现,在4.3版本中的判断是:

153    FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r");
154    if (cfg == NULL) {//说明软件模块
155        // default config
156        ALOGD("egl.cfg not found, using default config");
157        mDriverTag.setTo("android");//说明软件模块
158    } else {//硬件模块
159        while (fgets(line, 256, cfg)) {
160            int dpy, impl;
161            if (sscanf(line, "%u %u %s", &dpy, &impl, tag) == 3) {
162                //ALOGD(">>> %u %u %s", dpy, impl, tag);
163                // We only load the h/w accelerated implementation
164                if (tag != String8("android")) {
165                    mDriverTag = tag;
166                }
167            }
168        }
169        fclose(cfg);
170    }

其中EGL/eglApi.cpp 实现了egl接口,这里的是egl接口的第一层调用,最终调用的是软硬件实现里面的egl实现,为什么?Loader.cpp加载libGLES_android.so或者加载其他opengl厂商实现的so包的时候,有如下一段代码:

void *Loader::load_driver(const char* kind, const char *tag,
282        egl_connection_t* cnx, uint32_t mask)
……
	egl_t* egl = &cnx->egl;//加载实现包里的egl接口实现到此处。
342        __eglMustCastToProperFunctionPointerType* curr =
343            (__eglMustCastToProperFunctionPointerType*)egl;
344        char const * const * api = egl_names;
345        while (*api) {
346            char const * name = *api;
347            __eglMustCastToProperFunctionPointerType f =
348                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
349            if (f == NULL) {
350                // couldn't find the entry-point, use eglGetProcAddress()
351                f = getProcAddress(name);
352                if (f == NULL) {
353                    f = (__eglMustCastToProperFunctionPointerType)0;
354                }
355            }
356            *curr++ = f;
357            api++;
358        }

//看一下egl_connection_t结构:
34struct egl_connection_t {
35    enum {
36        GLESv1_INDEX = 0,
37        GLESv2_INDEX = 1
38    };
39
40    inline egl_connection_t() : dso(0) { }
41    void *              dso;
42    gl_hooks_t *        hooks[2];//gl1,gl2接口函数实现加载到此处
43    EGLint              major;
44    EGLint              minor;
45    egl_t               egl;//软硬件实现的egl接口函数加载到此处
46
47    void*               libGles1;
48    void*               libGles2;
49};

//在看一下其中的egl_t,gl_hooks_t结构:
71struct egl_t {
72    #include "EGL/egl_entries.in",//一系列egl接口中的函数指针变量,待实现库来填充
73};
74
75struct gl_hooks_t {
76    struct gl_t {
77        #include "entries.in"//,一系列gl接口中函数指针变量,待实现库来填充
78    } gl;
79    struct gl_ext_t {
80        __eglMustCastToProperFunctionPointerType extensions[MAX_NUMBER_OF_GL_EXTENSIONS];
81    } ext;
82};

总结,无论是SF模块,还是Bootanimation模块,他们在使用egl的时候,首先找到eglApi.cpp的第一层调用,然后再:例如:

344EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
345        EGLint attribute, EGLint *value)
346{
347    clearError();
348
349    egl_connection_t* cnx = NULL;
350    const egl_display_ptr dp = validate_display_connection(dpy, cnx);
351    if (!dp) return EGL_FALSE;
352
353    return cnx->egl.eglGetConfigAttrib(//!
354            dp->disp.dpy, config, attribute, value);
355}	

         至于gl的调用逻辑,在调用egl_init_drivers()函数用来初始化模块的加载的时候,也把软硬家的gl实现加载到了一个地方。

361    if (mask & GLESv1_CM) {
362        init_api(dso, gl_names,
363            (__eglMustCastToProperFunctionPointerType*)
364                &cnx->hooks[egl_connection_t::GLESv1_INDEX]->gl,
365            getProcAddress);
366    }
367
368    if (mask & GLESv2) {
369      init_api(dso, gl_names,
370            (__eglMustCastToProperFunctionPointerType*)
371                &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,
372            getProcAddress);
373    }

         就是egl_connection_t的hooks成员中。

         那么egl_connection_t又在哪里存储呢?libEGL 模块的egl_context_t里。当我们eglcreateContext后,我们会把创建的eglcontext中的egl_connection_t的hooks存储在线程相关的tls中,当调用的gl函数的时候,就从当前线程的tls里取出hooks来,然后再调用相关gl函数。它的存储过程是在eglMakeCurrent函数中:

581EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
582                            EGLSurface read, EGLContext ctx)
583{
……
613    // these are our objects structs passed in
614    egl_context_t       * c = NULL;
……
621    if (ctx != EGL_NO_CONTEXT) {
622        c = get_context(ctx);
623        impl_ctx = c->context;
624    } else {
……
650    EGLBoolean result = dp->makeCurrent(c, cur_c,
651            draw, read, ctx,
652            impl_draw, impl_read, impl_ctx);
653
654    if (result == EGL_TRUE) {
655        if (c) {
656            setGLHooksThreadSpecific(c->cnx->hooks[c->version]);//!
……
}

libGLESv1_CM.solibGLESv2.so他们其实是对gl接口的第一层实现,他们转发调用了当前线程里的hooks里相关的实现。

         看一下gl2接口的调用逻辑,:

// /frameworks/native/opengl/libs/GLES2/gl2.cpp 
109    #define API_ENTRY(_api) _api
110
111    #define CALL_GL_API(_api, ...)                                       \
112        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \  //!
113        _c->_api(__VA_ARGS__);
114
115    #define CALL_GL_API_RETURN(_api, ...)                                \
116        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
117        return _c->_api(__VA_ARGS__)
……
122extern "C" {
123#include "gl3_api.in"
124#include "gl2ext_api.in"
125#include "gl3ext_api.in"
126}

// /frameworks/native/opengl/libs/GLES2/gl3_api.in :
1void API_ENTRY(glActiveTexture)(GLenum texture) {
2    CALL_GL_API(glActiveTexture, texture);
3}
4void API_ENTRY(glAttachShader)(GLuint program, GLuint shader) {
5    CALL_GL_API(glAttachShader, program, shader);
6}
7void API_ENTRY(glBindAttribLocation)(GLuint program, GLuint index, const GLchar* name) {
8    CALL_GL_API(glBindAttribLocation, program, index, name);
9}
…….


//	最后看一下关于hooks的本地线程存储:
368void setGlThreadSpecific(gl_hooks_t const *value) {
369    pthread_setspecific(gGLWrapperKey, value);
370}
371
372gl_hooks_t const* getGlThreadSpecific() {
373    gl_hooks_t const* hooks =  static_cast<gl_hooks_t*>(pthread_getspecific(gGLWrapperKey));
374    if (hooks) return hooks;
375    return &gHooksNoContext;
376}

         总结,无论是SF模块,还是Bootanimation模块,他们在使用gl接口的时候,先去找libGLESv1_CM.solibGLESv2.so的第一层实现,然后再转发软件或硬件实现。

软件实现模块

这俩标准的agl软件实现在/frameworks/native/opengl/libagl/下,观其部分mk文件:

9LOCAL_SRC_FILES:= \
10	egl.cpp                     \  //egl的实现,其余是gl的实现
11	state.cpp		            \
12	texture.cpp		            \
13    Tokenizer.cpp               \
14    TokenManager.cpp            \
15    TextureObjectManager.cpp    \
16    BufferObjectManager.cpp     \
17	array.cpp.arm		        \
18	fp.cpp.arm		            \
19	light.cpp.arm		        \
20	matrix.cpp.arm		        \
21	mipmap.cpp.arm		        \
22	primitives.cpp.arm	        \
23	vertex.cpp.arm
……
29LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils liblog libpixelflinger libETC1 libui
30LOCAL_LDLIBS := -lpthread -ldl
31
32ifeq ($(TARGET_ARCH),arm)
33	LOCAL_SRC_FILES += fixed_asm.S iterators.S
34	LOCAL_CFLAGS += -fstrict-aliasing
35endif

……

44# we need to access the private Bionic header <bionic_tls.h>
45LOCAL_C_INCLUDES += bionic/libc/private

……

48LOCAL_MODULE:= libGLES_android
49
50include $(BUILD_SHARED_LIBRARY)

硬件实现模块

硬件的实现包括在/frameworks/native/opengl/libs/Android.mk文件里:

Egl实现:例如高通的\libEGL_adreno.so

Gl实现:system\vendor\lib\egl\libGLESv1_CM_adreno.so,system\vendor\lib\egl\libGLESv2_adreno.so

图示:

转载请注明。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android中opengles,egl库的结构 的相关文章

随机推荐

  • 【计算机视觉

    文章目录 一 Co Scale Conv attentional Image Transformer CoaT 二 Pyramid Vision Transformer v2 PVTv2 三 Class Attention in Image
  • android studio编程时出现的错误:Cannot get property 'XXXX' on extra properties extension as it does not exist

    用Android Studio中导入第三方库工程的时候出现的问题 Error 28 0 Cannot get property junitVersion on extra properties extension as it does no
  • springAop实现事务管理控制

    Aop简要概述 Aop面向切面编程 可以实现代码的解耦合 提高代码的复用性 1 切面 切面的意思通俗的意思就是切入的代码 比如开启事务方法的代码 提交事务的代码 2 切入点 需要切入代码的地方 比如待执行代码的前 或者后 3 连接点 满足规
  • keil的错误: Error: Encountered an improper argument 的2019.6.22最新解决方法

    keil的错误 Error Encountered an improper argument 的解决方法 什么都不要改动 最正确的办法是重新破解
  • QT信号与槽连接(松耦合)

    GUI用户界面中 当用户操作一个窗口部件时 需要其他窗口部件响应 传统方式经常使用callback 回调机制 来实现 所谓回调即事先将函数指针作为参数传递另一个函数 然后在函数处理过程中适当地方调用回调函数回调机制有两个缺陷 类型不安全 不
  • 传感器学习——旋转编码器

    旋转编码器是将旋转机械位移量转换为电器信号 对该信号进行处理后检测位置 速度等的传感器 旋转编码器可分为 增量式 编码器和 绝对值 式编码器 1 增量式编码器 旋转盘转动时 光敏二极管断续收到发光二极管发出的光 从而输出方波 增量式编码器通
  • cuda11.1和cuDNN v8.8.1的安装目录问题

    cuda的不同版本文件路径是不一致的 在cuda10 1中 配置cudnn的文件路径是 sudo cp cuda include cudnn h usr local cuda 10 1 include sudo cp P cuda lib6
  • ESLint 工具

    ESLint 可组装的 javaScript 和 JSX 检查工具 规范代码风格 官网 ESLint 插件化的 JavaScript 代码检测工具 ESLint中文文档 VSCode 自动格式化代码 ESLint安装 项目创建时 配置 ES
  • pscp无密传数据

    pscp 是 PuTTY 带的工具 可用作 Windows 上的 scp 替代 就在 PuTTY 的安装目录 加入 PATH 就可以敲命令用 无密上传 下载数据需要将公钥写入服务器 但是 PuTTY 用的公 私钥是 ppk 的 不同于 ss
  • BufferedImage 和 Graphics2D 画图,背景色透明

    File f new File D tag 20141204 chengxu business dossier business dossier web src main webapp upload 2017 08 07 C7A23630C
  • Element级联选择器Cascader使用(保存、回显)

    环境 版本 idea 2020 1 Element UI 2 13 2 vue 2 6 11 官方文档 https element eleme cn zh CN component cascader 业务场景 业务需求要给设备选择存放位置
  • c#连接读取mysql内容(报警无法连接处理方法)

    文章目录 一 Unable to connect to any of the specified MySQL hosts 二 Authentication to host 127 0 0 1 for user root using meth
  • csdn要考试了

    csdn要考试了 对于自己的是一次考验 第一次顺利过关 那第二次呢 还能如愿吗 人不是很多 竞争不是很激烈 我对自己有绝对的信心 因为我知道努力就会有收获 希望所有的河软的学生能进入csdn深造 能有一个好的机会 能够有一个好的前途 我希望
  • 并发编程系列之并发容器:ConcurrentHashMap

    前言 之前我们讲了线程 锁以及队列同步器等等一些并发相关底层的东西 当然Java开发者在开发中很少直接去使用之前所讲的 因为Java为了简化开发 为我们提供了一整套并发容器和框架 但是这些容器和框架都是建立在之前所讲的基础之上的 今天就让我
  • 基于 attention 机制的 LSTM 神经网络 超短期负荷预测方法学习记录

    LSTM long short term memory 长短期记忆 模型基础介绍 在标准LSTM体系结构中 有1个记忆单元状态和3个门 即更新门 u 遗忘门 f和输出门 o 标准LSTM的体系结构如图2所示 采用X1 X2 XT 表示LST
  • 数据相似性的度量

    在聚类 离散点分析等应用场景 我们往往需要度量数据之间的相似程度 提高模型的泛化性 一 首先 我们先从用于数据相似性度量的基本数据结构开始 数据矩阵和相异性矩阵 数据矩阵 或称对象 属性结构 矩阵每一行代表一个数据对象 每一列代表一个属性
  • IMT-2020(5G)推进组发布《5G-Advanced 场景需求与关键技术白皮书》

    11月16日 由工业和信息化部 深圳市人民政府主办的2022年中国5G发展大会在深圳举行 本届大会以 5G领航新基建 构筑发展新底座 为主题 会上 IMT 2020 5G 推进组发布 5G Advanced 场景需求与关键技术白皮书 中国工
  • 收藏的链接

    Epoll的本质 内部实现原理 Likes的博客 CSDN博客 epoll实现原理本文主体转自https zhuanlan zhihu com p 63179839 加上了自己的理解和批注从事服务端开发 少不了要接触网络编程 epoll作为
  • 改手机型号模块_2020年华为5g手机型号及价格

    这些年华为手机的发展 我们有目共睹 华为手机已经打出名号 特别是华为5G手机已经成为了华为占据市场的有力技术和产品 今年华为手机和荣耀手机齐发力 用了华为高端芯片 华为现在有三款集成5G芯片 麒麟990 麒麟990是华为当下麒麟系列最旗舰级
  • Android中opengles,egl库的结构

    目录 egl opengl es的软硬件实现 需要的库 库的分工 加载模块 软件实现模块 硬件实现模块 egl opengl es的软硬件实现 需要的库 算是android中的egl库 用来加载具体的实现 软件实现或者硬件实现 system