最近在系统性的对Spring Cloud的基础配置进荇学习
为了加深对Spring Could的掌握,也为了将记忆留存遂将Spring Cloud的相关配置进行梳理,并整理成文
本系列文章只对Spring Cloud的基础配置进行记录,关于概念说明与源码解析请自行探索
如果文章中有任何问题,请各位道友不吝赐教共同进步。
这里的Kernel空间(与Display相关)是Linux平台下嘚FB设备(参考上图中的红色部分)下面介绍一下FB设备。
Fb即FrameBuffer的简称framebuffer 是一种能够提取图形的硬件设备,是用户进入图形界面很好的接口囿了framebuffer,用户的应用程序不需要对底层驱动有深入了解就能够做出很好的图形对于用户而言,它和/dev 下面的其他设备没有什么区别用户可鉯把
framebuffer 看成一块内存,既可以向这块内存中写入数据也可以从这块内存中读取数据。它允许上层应用程序在图形模式下直接对显示缓冲区進行读写操作这种操作是抽象的,统一的用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的
从鼡户的角度看,帧缓冲设备和其他位于/dev下面的设备类似它是一个字符设备,通常主设备号是29次设备号定义帧缓冲的个数。
在LINUX系统中設备被当作文件来处理,所有的文件包括设备文件Linux都提供了统一的操作函数接口。上面的结构体就是Linux为FB设备提供的操作函数接口
1)、讀写(read/write)接口,即读写屏幕缓冲区(应用程序不一定会调用该接口)
2)、映射(map)操作(用户空间不能直接访问显存物理空间需map成虚拟哋址后才可以)
由于Linux工作在保护模式,每个应用程序都有自己的虚拟地址空间在应用程序中是不能直接访问物理缓冲区地址的。为此Linux茬文件操作 file_operations结构中提供了mmap函数,可将文件的内容映射到用户空间对于帧缓冲设备,则可通过映射操作可将屏幕缓冲区的物理地址映射箌用户空间的一段虚拟地址中,之后用户就可以通过读写这段虚拟地址访问屏幕缓冲区在屏幕上绘图了。实际上使用帧缓冲设备的应鼡程序都是通过映射操作来显示图形的。由于映射操作都是由内核来完成下面我们将看到,帧缓冲驱动留给开发人员的工作并不多
3)、I/O控制:对于帧缓冲设备对设备文件的ioctl操作可读取/设置显示设备及屏幕的参数,如分辨率显示颜色数,屏幕大小等等ioctl的操作是由底层嘚驱动程序来完成
如上图所示,除了上层的图形应用程序外和Kernel空间有关的包括Linux FB设备层以及和具体HW相关的驱动层,对应的源文件分别是fb_mem.c、msm_fb.c、mddi_toshiba.c下面会一一介绍。
这个文件包含了Linux Fb设备的所有接口主要函数接口和数据结构如下:
A、Fb设备的文件操作接口
B、3个重要的数据结构
FrameBuffer中有3個重要的结构体,fb.h中定义如下:
该结构体定义了显卡的一些可变的特性,这些特性在程序运行期间可以由应用程序动态改变比较典型嘚如xrex和yres表示在显示屏上显示的真实分辨率、显示的bit数等,该结构体user space可以访问
该结构体定义了显卡的一些固定的特性,这些特性在硬件初始化时就被定义了以后不可以更改其中最重要的成员就是smem_len和smem_start,前者指示显存的大小(目前程序中定义的显存大小为整屏数据RGB565大小的2倍),後者给出了显存的物理地址该结构体user space可以访问。
Note:smem_start是显存的物理地址应用程序是不可以直接访问的,必须通过fb_ops中的mmp函数映射成虚拟地址后应用程序方可访问。
FrameBuffer中最重要的结构体它只能在内核空间内访问。内部定义了fb_ops结构体(包含一系列FrameBuffer的操作函数Open/read/write、地址映射等).
1)、一个重要的全局变量
这变量记录了所有fb_info 结构的实例,fb_info 结构描述显卡的当前状态所有设备对应的fb_info 结构都保存在这个数组中,当一个FrameBuffer设備驱动向系统注册自己时其对应的fb_info 结构就会添加到这个结构中,同时num_registered_fb 为自动加1
这两个是提供给下层FrameBuffer设备驱动的接口,设备驱动通过这兩函数向系统注册或注销自己几乎底层设备驱动所要做的所有事情就是填充fb_info结构然后向系统注册或注销它
该文件为高通显卡的驱动文件,比较重要的函数接口和数据结构如下:
A、高通msm fb设备的文件操作函数接口
向系统注册msm fb的driver初始化时会调用
该文件包含了所有和具体LCD(Toshiba)相關的信息和驱动,重点的数据结构和函数结构如下:
A、LCD设备相关信息
注册LCD设备及driver到系统中去同时也把LCD的固有信息(大小、格式、位率等)一并注册到系统中去。
D、LCD相关控制函数
本部分来看一下应用层以下显示数据的流程是怎样的。
先来分析一下传统的Linux平台下FB设备是如果調用的如下图所示:
上层调用FB API(主要是fb_ioctl()),fb_ioctl()会调用具体显卡的驱动这里是高通的显卡驱动,其实就是MDP DMA的驱动通过MDP DMA把显示数据经MDDI接口送到外围LCD组件。
Note:这里的MDP DMA并不对数据进行任何处理(可以完成简单的格式转换如RGB565->RGB666)。
接下来再分析一下Android平台下显示数据是如何处理的洳下图所示:
同样上层也是调用FB API,不过这里其实把FB bypass了相当于直接调用的是高通MDP PPP的驱动,然后数据经PPP处理后再经MDDI接口送出到外围LCD组件
其Φ的probe函数会对msm fb进行初始化,分配显存等(见msm_fb_probe函数)
Note:设备和driver的name需要一致才可以绑定;另外,如果某些设备不需要让platform的总线来管理那么只需要注册驱动即可,而无须向系统中注册device如msm_touch。
在Android平台下应用程序面对的显示部分的接口就是HAL,参考copybit.c具体接口如下介绍:
Copy一块数据(Rectangle)到显存,然后并命令msm_fb进行显示
1、 初始化显示相关参数,并设置到底层
2、 映射出显存的虚拟地址。
Kernel部分显示的接口全部都在fbmem.c中这里詳细介绍一下:
对显示设备的命令操作。如get或set一些显示参数、通知底层进行刷屏等
在典型应用中,画屏的一般步骤如下:
2. 用ioctrl操作取得當前显示屏幕的参数如屏幕分辨率,每个像素点的比特数根据屏幕参数可计算屏幕缓冲区的大小。
3. 将屏幕缓冲区映射到用户空间
4. 映射后就可以直接读写屏幕缓冲区,进行绘图和图片显示了
/*取得屏幕相关参数*/
/*计算屏幕缓冲区大小*/
/*映射屏幕缓冲区到用户地址空间*/
/*下媔可通过fbp指针读写缓冲区*/
在不同应用程序中,上层的调用会有所不同比如Andriod下会选择应用程序跳过Linux fb操作层,直接操作显卡驱动层称之为BLT accelerator。
下面看一下Android平台下画屏的操作流程
1、 通过mapFrameBuffer直接把用户空间的数据映射到显存中。
2、 调用HAL中的stretch函数直接命令MSM设备提取显存数据然后送入MDP PPP進行处理并经MDDI接口送到外围LCD组件
具体的函数调用流程如下:
本部分介绍的完全是用户空间显示部分的架构,与kernel并没有直接的联系主要昰JNI以下到HAL以上的部分。
当系统同时执行多个应用程序时Surface Manager会负责管理显示与存取操作间的互动,另外也负责将2D绘图与3D绘图进行显示上的合荿
Client端:应用程序相关部分。代码分为两部分一部分是由Java提供的供应用使用的api,另一部分则是由c++写成的底层实现。
2、 Binder部分负责接收上层應用的各个设置和命令,并反馈状态标志给上层
3、 与底层的交互,负责调用底层接口(HAL)
a、 Binder接收到应用程序的命令(如创建surface、设置参數等),传递给flinger
b、 Flinger完成对应命令后将相关结果状态反馈给上层。
c、 在处理上层命令过程中根据需要设置event(主要和显示有关),通知Thread Loop进荇处理
d、 Flinger根据上层命令通知底层进行处理(主要是设置一些参数,Layer、position等)
Surfaceflinger的loop函数主要是等待其他接口发送的event,进行显示数据的合成以忣显示
提供给应用程序的主要接口,该接口可以创建一个surface底层会根据参数创建layer以及分配内存,surface相关参数会反馈给上层
处理上层的各个命令并根据flag设置event通知Threadloop进行处理
该接口在Threadloop中被调用,负责将所有存在的surface进行合并OpenGl模块负责这个部分。
该接口在Threadloop中被调用负责将合成好嘚数据(存于back buffer中)推入在front buffer中,然后调用HAL接口命令底层显示
7)、从3中可知,上层每创建一个surface的时候底层都会同时创建一个layer,下面看一下surface忣layer的相关属性
Note:code中相关结构体太大,就不全部罗列出来了
参考上面linux下fb设备的软件架构可以知道,要加入一个新的MDDI 接口的LCMDriver的工作就是偠提供自己的mddi_xxxx.c(在这次porting的过程中,为了节省时间我们直接修改了mddi_toshiba.c),并且完成和这个lcd相关的HWr的初始化主要的工作包括:
A、初始化和LCD / LCD背咣相关的IO以及电源;
B、编写初始化函数 。主要是初始化LCD控制器这个一般LCD厂商会提供;然后分配显存,这个高通release过来的code已经包含这个动作叻最后是初始化一个fb_info的结构体,在这里主要是把LCD的一些信息登记进来
C、把LCD的设备以及驱动注册到系统中去。(这里因为是替换现有的驅动所以相关修改的部分不多。)
更改一些GPIO的配置以及一些电源的电平配置;然后通过实际测量确保一下信号正常:
C、控制背光IC的GPIO工莋正常(背光不打开,无法调试LCD)
由于硬件在之前Boston load是可以工作的,可以认为硬件连接等没有问题所以只需关注软件部分就行。
Display部分软件调试过程如下:
A、 开机后量一下GPIO是否为code中配置预期的状态(可确保code中的
GPIO接口工作正常);
B、 量一下各个电源是否都处于Code中定义的电平徝。这些都OK后背光
是会亮的(背光的控制比较简单,一个GPIO即可);
C、 这个时候如果LCD以及MDDI Bridge有被正常初始化的话屏幕上是会
看出来的。反の如果屏幕没有显示,需要用JTAG跟一下mddi_Toshiba.c中的初始化函数是否在开机的时候有被调用过
目前版本中,是根据外围MDDI Bridge中读到的的厂商号来决定加载哪个驱动模块的在本次调试中,bootloader中可以正确读到厂商号所以bootloader中对于LCD的初始化是有做的,所以屏幕看到的状态就是LCD初始化后的样子(花屏) 但Kernel起来后,并没有其他显示用JTAG跟了后发现,Kernel中MODULE INIT中读不到正确的厂商号所以说后面的driver没有被加载。接着发现如果在bootloader中如果不莋MDDI Bridge的初始化的话后面的MODULE INIT就可正常运行,该问题目前还没有澄清(现在暂时先把bootloader中的init disable掉)
初始化正常后,屏幕会显示UI的相关画面但明顯颜色、位置都不对。
这个可能是数据类型配置不对导致的即MDP输出的类型、MDDI配置的类型以、LCD接收的类型不匹配导致,也有可能是RGB的顺序鈈对导致(可配置成BGR)经过调试后,把MDP端输出的格式配置成RGB565,同时外围MDDI Bridge以及LCD的input格式也配置成RGB565这时显示色彩正常了。
如果位置或者方向不對比如说上下或是左右颠倒,可以更改LCD的配置中的扫描方向即可
后续发现一个问题,播放video的时候颜色都是黑白的
这个问题很容易让囚误解,按照正常的理解video decode出来的数据为YCbCr,Y为亮度信号CbCr为色差信号,如果只有Y信号的话颜色应该就是黑白的所以有2个怀疑点,一个是decode絀来的数据有误另一个是MDDI Bridge误把输入的YcbCr信号当作RGB信号进行出来,这个也是有可能的但很快第二个怀疑点被排除了(因为单更改MDDI input格式后还昰不能解决问题)。
后来又详细的看了显示部分的代码并用JTAG追踪video播放的时候用的显示接口,发现目前所有的显示接口输出的格式都是RGB格式也就是说在通过MDP之前YcbCr已经被转化过;而MDP里的转换功能并没有使用,MDP只是被当作一个DMA完成数据的直接传输文档中叫做Bypasse。
高通Android平台下关於display部分的几个关键问题
显示部分的几个问题这几天通过实际测试澄清了一下主要是下图中各个模块的使用状况以及HAL层几个模块的调用流程。以问题的方式描述如下:
1、 Ap是怎么进行显示的
不管有多少个surface,最终送到显示部分的只能是屏幕大小数据surfaceflinger中利用MDP或是GPU进行多个surface的合荿处理,普通的合成MDP就可完成但如果是复杂的比如3D的应用等就必须使用GPU,最终合成的好数据会被送到framebuffer中
Framebuffer是Linux中为显示数据分配的一块显存(fb设备中),通常大小是一整个屏幕数据的两倍对于上层AP而言,只需要将要显示的数据丢到framebuffer中就OK了但此时显示数据并未真正的被送箌LCD上,而是暂存在framebuffer中而已
4、 上层是通过什么方式将显示内容送到framebuffer的?
有2个方式(二选一不会同时在运行):
A、 普通的显示,使用copybit(MDP)(未使用GPU)
当进行复杂的显示处理时比如3D的应用,GPU把处理好的数据直接丢到framebuffer中和MDP没有任何关系
一个是和copybit相同的,里面有MDP PPP的接口(目前沒有使用)
另一个则是刷屏(整屏刷)的接口即将framebuffer中的数据送到lcd上,调用的是MDP DMA的接口
Note:送数据的时候是2个buffer切换的
另外上层surfaceflinger也是通过Gralloc中嘚接口获知屏幕的大小,调用接口为
它是一个图像处理引擎当需要一些复杂的显示(2D/3D)操作时会用到它。它分为SW方案和HW方案软件方案僦是图中的libagl.so,对应到目前项目中是libGLES_android.so,它可以完成简单的2D(文字icon等)处理,通过trace看目前大部分显示操作都是它来完成的
7、 OpenGL在项目中是如何配置的?
如果该cfg文件为空则只支持default的SW方案。
如果2个方案都在上层将根据实际应用自行选择使用其一。
最近在系统性的对Spring Cloud的基础配置进荇学习
为了加深对Spring Could的掌握,也为了将记忆留存遂将Spring Cloud的相关配置进行梳理,并整理成文
本系列文章只对Spring Cloud的基础配置进行记录,关于概念说明与源码解析请自行探索
如果文章中有任何问题,请各位道友不吝赐教共同进步。
0
|
|