android 图形系统加速学习系列 (一)

Android中opengles,egl库的结构 目录 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壳,对应.. 阅读详情

  Android 系统使用OpenGL的标准接口来支持3D图形功能,包含框架层及本地代码两个主要部分,这里先介绍本地代码部分。

  源代码目录为:frameworks\base\opengl\libs

  在这个代码路径下面会编译生成三个库: libEGL , libGLESv1_CM.so  , libGLESv2.so ,那么这三个库之间是个什么关系呢?

  首先说明一下主要实现的功能: 

  EGL是用来管理绘图表面的(Drawing surfaces),并且提供了如下的机制
 (1) 与本地窗口系统进行通信
 (2) 查找绘图表面可用的类型和配置信息
 (3) 创建绘图表面
 (4) 同步OpenGL ES 2.0和其他的渲染API(Open VG、本地窗口系统的绘图命令等)
 (5) 管理渲染资源,比如材质

 2. EGL 和 OpenGL ES API的联系
 (1) 通过解析OpenGL ES API函数库 libGLES_android.so来获取函数指针,进行调用。
 (2) 通过线程局部存储机制进行联系

 3. libGLESv1_CM.so  及 libGLESv2.so  都是一个简单的wrapper, 针对OpenGl ES API进行封装

 

这里使用到了线程局部存储机制,这是一个什么东东呢?

概念:线程局部存储(Thread Local Storage,TLS)用来将数据与一个正在执行的指定线程关联起来。

进程中的全局变量与函数内定义的静态(static)变量,是各个线程都可以访问的共享变量。在一个线程修改的内存内容,对所有线程都生效。这是一个优点也是一个缺点。说它是优点,线程的数据交换变得非常快捷。说它是缺点,一个线程死掉了,其它线程也性命不保; 多个线程访问共享数据,需要昂贵的同步开销,也容易造成同步相关的BUG。

如果需要在一个线程内部的各个函数调用都能访问、但其它线程不能访问的变量(被称为static memory local to a thread 线程局部静态变量),就需要新的机制来实现。这就是TLS。

功能:它主要是为了避免多个线程同时访存同一全局变量或者静态变量时所导致的冲突,尤其是多个线程同时需要修改这一变量时。为了解决这个问题,我们可以通过TLS机制,为每一个使用该全局变量的线程都提供一个变量值的副本,每一个线程均可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。而从全局变量的角度上来看,就好像一个全局变量被克隆成了多份副本,而每一份副本都可以被一个线程独立地改变。

 

好了,介绍完毕,下面介绍系统中代码如何体现的:

由于OpenGL是一个其于上下文Context 环境开发的,所以每个线程需要保存自已的运行环境,如果没有的话则会报错:

"call to OpenGL ES API with no current context logged once per thread"

如何创建TLS:

static pthread_once_t once_control = PTHREAD_ONCE_INIT;
static int sEarlyInitState = pthread_once(&once_control, &early_egl_init);

这两条语句会先于eglGetDisplay函数执行。第二条语句中将函数指针early_egl_init作为参数传入,会执行回调,并且保证单个线程只会执行一次。在early_egl_init()中,对TLS机制进行初始化。将TLS里放入一个结构体指针,这个指针指向gHooksNoContext(gl_hooks_t类型),这个结构体里的每个函数指针被初始化为了gl_no_context。也就是现在如果通过TLS调用的OpenGL ES API都会调到gl_no_context这个函数中。
综上,这两条语句完成了TLS的初始化。
另一处初始化时在eglInitialize函数中,同样设置成了gHooksNoContext。

 

TLS的赋值
在eglMakeCurrent中,会将渲染上下文绑定到渲染面。在EGL中首先会处理完一系列和本地窗口系统的变量后,调用libGLES_android.so中的eglMakeCurrent,调用成功的话会设置TLS。将TLS指针指向前面已经初始化化好的gl_hooks_t结构体指针,这个结构体里的成员都已经指向了libGLES_android.so中的OpenGL API函数,至此EGL的大部分初始化工作就已经完成了。基本就可以使用OpenGL ES API进行绘图了。
static inline void setGlThreadSpecific(gl_hooks_t const *value) {
    gl_hooks_t const * volatile * tls_hooks = get_tls_hooks();
    tls_hooks[TLS_SLOT_OPENGL_API] = value;
}

我们来看看在OpenGl中如何使用TLS的: (frameworks\base\opengl\libs\GLES_CM\gl.cpp)

 #define GET_TLS(reg) \
            "mov   " #reg ", #0xFFFF0FFF      \n"  \
            "ldr   " #reg ", [" #reg ", #-15] \n"

    #define CALL_GL_API(_api, ...)                              \
         asm volatile(                                          \
            GET_TLS(r12)                                        \
            "ldr   r12, [r12, %[tls]] \n"                       \
            "cmp   r12, #0            \n"                       \
            "ldrne pc,  [r12, %[api]] \n"                       \
            "bx    lr                 \n"                       \
            :                                                   \
            : [tls] "J"(TLS_SLOT_OPENGL_API*4),                 \
              [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api))    \
            :                                                   \
            );

    #define CALL_GL_API_RETURN(_api, ...) \
        CALL_GL_API(_api, __VA_ARGS__) \
        return 0; // placate gcc's warnings. never reached.


CALL_GL_API这个带参数的宏。它的意思是获取TLS_SLOT_OPENGL_API的TLS,如果它的值不是NULL,就跳到相应的OpenGL ES API的地址去执行。这个地方为什么会跳过去呢??因为从线程局部存储保存的线程指针,指向了一个gl_hooks_t指针,而这个指针指向的结构体里的成员已经在EGL中被初始化为了libGLES_android.so里的函数地址了。所以就可以跳过去了。

 

那么在哪里初始化gl_hooks_t指针的呢? (frameworks\base\opengl\libs\EGL\Loader.cpp)

    FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r");
    if (cfg == NULL) {  // 如果找不到这个配置则默认加载软件3D库即 libGLES_android.so
        // default config
        LOGD("egl.cfg not found, using default config");
        gConfig.add( entry_t(0, 0, "android") );
    } 

 否则根据配置文件加载硬件3D库,egl.cfg 文件格式是“dpy impl tag”比如自己添加的硬件加速库是libGLES_mali.so,则需要在此文件里这样编写
   0 1 mali

   修改后要重启才可生效。

   加载就是利用dlopen、dlsym加载并赋值:

   void* dso = dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);

  char const * const * api = egl_names;
        while (*api) {
            char const * name = *api;
            __eglMustCastToProperFunctionPointerType f =
                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
            if (f == NULL) {
                // couldn't find the entry-point, use eglGetProcAddress()
                f = getProcAddress(name);
                if (f == NULL) {
                    f = (__eglMustCastToProperFunctionPointerType)0;
                }
            }
            *curr++ = f;
            api++;
        }

  char const * const gl_names[] = {
    #include "entries.in"
    NULL
  };

   char const * const egl_names[] = {
    #include "egl_entries.in"
    NULL
};

这里面包含的函数头文件在:gl2_api.in 及 gl_api.in 中对应于不同的版本,对应用C头文件接口是: include/RGL/egl.h 及

include\GLES\中的gl.h和glext.h,这些接口供外部调用OpenGL本库所使用接口,这些接口基本上和OpenGL标准接口一致。

 #include <EGL/egl.h>
 #include <GLES/gl.h>

 

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

 

插一句如何知道哪些OpenGL函数没有实现呢?

在init_api函数添加打印即可知道哪些函数没有实现:

        if (f == NULL) {
            //LOGD("%s", name);
            f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;
        }
最麻烦的事情也就是实现以上两个头文件,扩展OpenGl函数最好不要使用,需要进行GPU编程,一般由芯片公司提供。

 

目前手机上使用最广范的GPU CORE当属 Imagination Technologies 公司开发的 PowerVR graphics core

 ARM公司收购的 Falanx公司提供 Mali, Mali-200, Mali-400

 Vivante公司提供的 GPU core 

Android 图形系统之一:概览 Android 图形系统是一套完整的架构,用于管理从应用绘制到显示屏幕的整个流程。它涉及多个层次和组件,从应用程序到硬件,确保每一帧都能准确、高效地呈现到用户的设备屏幕上。 阅读详情

相关推荐

Android图形系统概述

图形系统是Android中非常重要的子系统,与其他子系统相互协作,完成图形界面的渲染和显示。 概述 官方提供了一个图形系统的关键组件协作图,如下所示:这幅图大致描述了图形数据的流转:OpenGL ES、MediaPlayer等生产者生产图形数据到Surface,Surface通过IGraphicBufferProducer把GraphicBuffer跨进程传输给消费者SurfaceFlinger,...

tli600605的专栏 803

error while loading shared libraries: libGLESv2.so:cannot open shared object file:No such file or di

使用buildroot制作文件系统包含qt库,可以运行qt的例子,但是不能运行自己写的qt程序,运行就会提示缺少库

m0_46138233的博客 1375

libEGL libGLESv2

qt5.0.1用vs2010编译时,编译到opengl时会缺少这两个库,把.lib放到lib目录下,dll放到bin目录下就可以了。 强调一下,这个是forvs2010的。

修复树莓派Stretch运行QT程序时缺失 libGLESv2.so库问题

sudo ln -s /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2 /usr/lib/arm-linux-gnueabihf/libGLESv2.so

sharess234的专栏 4116

OpenCL头文件+libGLES_mali.so.rar

含有rk3288 OpenCL 所需的头文件和.so库文件,使用GPU 进行计算时,需要用到该资源。

Android15 AndroidV冻结和解冻的场景

cgroup 最初由 Google 工程师 Paul Menage 和 Rohit Seth 在 2006 年提出,是一种细粒度资源控制的Linux内核机制。于 2007 年合并到 Linux 内核主线中。然而 Google 原生系统直到 Android 11 或更高版本上才支持 CACHE 应用的 CPU 冻结功能。当应用切换到后台并且没有其他活动时,系统会在一定时间内通过状态判断,将进程 ID 迁移到冻结的 cgroup 节点上,实现冻结 CACHE 应用。

苏法迪的专栏 1785

Android 图形系统概述

图形系统是 Android 中非常重要的子系统,与其他子系统相互协作,完成图形界面的渲染和显示。概述官方提供了一个图形系统的关键组件协作图,如下所示:这幅图大致描述了图形数据的流转:Op...

Peter的专栏 1767

SAP 发货在途库存管理:POD确认差异下的2种后续调整方案对比

本文详细解析了SAP发货在途库存管理中POD确认差异后的财务调整方案,对比了移动类型417和555 T两种处理方式的适用场景及财务影响。通过实际案例说明如何优化POD流程,减少库存差异损失,提升供应链管理效率。特别适合SAP SD模块用户及供应链管理人员参考。

chiman6219的博客 393

深入理解Android图形系统

一、图形系统简介图形系统是计算机中最重要的子系统之一。我们平时使用的电脑、手机都是图形界面的。对于普通人来说,没有图形界面的计算机几乎是没法用的,今天我们就来讲一讲图形系统背后的原理。1.1 图形系统的诞生早期的计算机是没有图形界面的,都是命令行界面。大家坐在终端前面输入命令、执行命令、等待命令完成,如此循环往复。这样的计算机比较适合科研人员、理工男使用,但是想要普及到千家万户是不可能的。后来施乐公司帕克研究中心(Xerox Palo Alto Research Center,Xerox PARC)率先研究

a546036242的博客 1383

NVIDIA DGX Spark 深度应用解析:从大模型训练到边缘推理的完整实践指南

内存管理:充分利用统一内存架构,避免不必要的数据传输批处理大小:根据模型大小调整批处理大小以优化内存使用精度选择:在精度损失可接受范围内使用较低精度计算流水线优化:重叠计算和数据传输操作DGX Spark作为一个专门的AI计算平台,在大模型开发的各个阶段都能发挥重要作用。从数据预处理到模型训练,从微调到推理部署,其统一内存架构和强大的计算能力为AI开发者提供了前所未有的本地开发体验。需要注意的是,虽然DGX Spark性能强大,但合理的算法设计和系统优化仍然是获得最佳性能的关键。

time_days的博客 2868

在没有实验数据的情况下,如何高效快速发表高影响因子论文

最新基于Citespace、vosviewer、R语言的文献计量学可视化分析技术及全流程文献可视化SCI论文高效写作方法

glldxh的博客 370

Android 图形系统(Graphics)

系统绘制的是什么?图形缓冲区,也叫Buffer。应用层的View树最终会转换成Buffer,置于BufferQueue中被绘制。绘制的位置在哪里?应用端会把一切内容渲染到surface上,最终显示到LCD/OLED显示屏如何把图像绘制到屏幕?绘制任务由应用发起,通过跨进程方式把Buffer传到FW层,由FW层中的SurfaceFlinger服务调用Linux 硬件驱动最终绘制到硬件屏幕上。

cmyperson的博客 2195

编译CycloneDDS和CycloneDDS-CXX踩过的坑——CMake Error at CMakeLists.txt:227 (find_package):

最近编译CycloneDDS和CycloneDDS-CXX踩了两个坑,花了不少时间。做个简单的记录,免得以后又踩到。注意:CycloneDDS-CXX编译依赖CycloneDDS,因此必须先编译CycloneDDS需要严格按照步骤进行,否则要入坑步骤如下,1先编译CycloneDDS以上步骤完成CycloneDDS的编译和安装,生成的bin include lib等位于install目录下面。

usstmiracle的博客 1900

Android 图形系统及其应用

                               Android 图形系统及其应用                      一. Android 图形系统本着知其然,要知其所以然的精神,我探索了Android的图形系统。Android 的图形系统采用client/server架构。Server端(SurfaceFlinger)主要由C++代码编写而成。Client 端代码分为

wukunting的专栏 5849

STM32F401RCT6最小系统原理图设计

STM32F401RCT6最小系统原理图设计一、主控芯片二、电源电路三、晶振电路三、下载电路四、完整电路图      本文章基于STM32F401RCT6进行最小系统原理图设计,包含主控芯片,电源,晶振电路,下载电路等几部分 一、主控芯片 主控芯片采用STM32F401RCT6,需注意: VBAT在不接电池的情况下需接3.3V,VDDAVREF+需接3.3V,否则会造成芯片供电不正常,无法启动和识别的情况 VDDAVREF+和VCAP1处电容需按照规格书

weixin_43278295的博客 2万+

如何用Python打造PubMed API客户端:科研文献检索自动化实践

PubMed提供了官方的Entrez E-utilities API接口,支持程序化检索文献,但直接调用API需处理请求重试、参数封装、数据解析等问题。批量获取文献ID及结构化详情(标题、作者、DOI等)内置重试机制,应对网络波动或API限流统一数据输出格式,便于后续分析(如文献计量、AI文本处理)灵活适配不同检索需求(如指定数据库、结果数量)本文实现的PubMed API客户端,通过封装API请求、重试机制、数据解析,让科研文献检索从“手动点击”变为“代码自动化”。

ASKCOS博客 357

Android 图形系统之三:SurfaceControl

在 Android 系统中,SurfaceControl 是一个关键的类,用于管理应用窗口和屏幕上的显示内容。它与 SurfaceFlinger 紧密交互,通过 BufferQueue 提供高效的图形缓冲区管理能力。

执剑人 3950

PHP实现获取当地网络时间​(附完整源码)

PHP实现获取当地网络时间​(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 234

android 图形系统加速学习系列 (二)

上一节介绍下android 2D&3D库加载的过程,节绍下软件实现的libagl库并重点介绍一下copybit 2D图形加速部分。 如果处理器只有2D硬件加速而没有3D硬件加速,则可以利用opengl中的libagl,实现封装在libagl里的copybit,因为相对3D API来说,这个模块的封装基本是做好的,只要去实现一个copybit HAL即可; 如果处理器2D/3D硬件加速均

andyhuabing的专栏 7354

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

android图形系统详解

本文只是一个传送门 android图形系统详解一:Canvas android图形系统详解二:Drawables android图形系统详解三:形状Drawable和九宫格 android图形系统详解四:控制硬加速 android图形系统详解五:Android绘制模式 android图形系统详解六:View layer

分享Android应用和系统开发、音视频编码、性能优化相关知识 862

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

安卓高手之路之 图形系统之 图形框架(1)

安卓高手之路之 图形系统之 图形框架(1) - 修补C++ - ITeye技术网站 安卓图形系统理解起来并不容易。那是因为系统对于数据的封装非常多,图形模块与输入输出,应用程序管理等模块参杂在一起。让开发者很难摸清其中的脉络。下面先给出最简单的一张图。 这张图是安卓系统的核心。就这张图来说,我不想说什么。如果不仔细看安卓源代码,是理解...

weixin_30840253的博客 87

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

“一文读懂“系列:Android中的硬件加速

默认情况下Skia的绘制没有采用GPU渲染的方式(虽然Skia也能用GPU渲染),也就说默认drawSoftware工作完全由CPU来完成,不会牵扯到GPU的操作,但是8.0之后,Google逐渐加重了Skia,开始让Skia接手OpenGL,间接统一调用,将来还可能是Skia同Vulkan的结合。这也是手机端硬件性能越来越好的结果吧。如果本篇文章对你有帮助,请帮忙,关注下,,笔者会定期推送一些关于Android移动开发中的高质量文章。小余的自习室参考Android 屏幕绘制机制及硬件加速。

yuhaibing111的博客 3040

深入解析 Android 图形系统:Canvas、Skia、OpenGL 与 SurfaceFlinger 的协作

在 Android 应用开发中,流畅的 UI 渲染是用户体验的核心。但你是否好奇,一个简单的 `View` 是如何从代码中的 `onDraw()` 方法一步步变成屏幕上的像素的?本文将从底层图形系统的视角,解析 Android 中 `Canvas`、Skia、OpenGL ES 和 `SurfaceFlinger` 的协作关系,并揭秘软绘制与硬绘制的完整流程。

居然是阿松的博客 2096

Android应用程序UI硬件加速渲染技术简要介绍和学习计划

Android系统的流畅性一直被拿来与iOS比较,并且认为不如后者。这一方面与Android设备硬件质量参差不齐有关,另一方面也与Android系统的实现有关。例如在3.0前,Android应用程序UI绘制不支持硬件加速。不过从4.0开始,Android系统一直以“run fast, smooth, and responsively”为目标对UI进行优化。本文对这些优化进行简要介绍和制定学习计划。

老罗的Android之旅 4万+
上一篇: 总结过去,开拓未来 -- 我的的2011
下一篇: android 图形系统加速学习系列 (二)
andyhuabing
博客等级 码龄19年 704粉丝 165原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值