Android display架构分析(5-8)

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

Android display架构分析五-Display接口介绍

1、User Space display接口

在Android平台下,应用程序面对的显示部分的接口就是HAL,参考copybit.cpp (qcom\diaplay\libcopybit),具体接口如下介绍:

open_copybit                                初始化相关变量,并调用open(“/dev/graphics/fb0″, O_RDWR, 0);打开fb设备。

set_parameter_copybit              设置各种操作参数,如rotate、alpha、dither等。

stretch_copybit                              Copy一块数据(Rectangle)到显存,然后并命令msm_fb进行显示。

close_copybit                                  调用close(ctx->mFD);关闭fb设备。


Note:另外,应用程序在使用上面接口之前,需要调用mapFrameBuffer接口(EGLDisplaySurface.cpp),其功能如下:

1、 初始化显示相关参数,并设置到底层。

2、 映射出显存的虚拟地址。


2、Kernel display接口

Kernel部分显示的接口全部都在fbmem.c中,这里详细介绍一下:

fb_open                        打开Linux下fb设备。

fb_read/fb_write          读写显存中的数据

fb_ioctl                          对显示设备的命令操作。如get或set一些显示参数、通知底层进行刷屏等。

在典型应用中,画屏的一般步骤如下:

1. 打开/dev/fb设备文件。

2. 用ioctrl操作取得当前显示屏幕的参数,如屏幕分辨率,每个像素点的比特数。根据屏幕参数可计算屏幕缓冲区的大小。

3. 将屏幕缓冲区映射到用户空间。

4. 映射后就可以直接读写屏幕缓冲区,进行绘图和图片显示了。

典型程序段如下:

[html]  view plain copy print ?
  1. #include <linux/fb.h>  
  2.    
  3. int main()     
  4. {     
  5. int fbfd = 0;  
  6.    
  7. struct fb_var_screeninfo vinfo;  
  8.    
  9. struct fb_fix_screeninfo finfo;  
  10.    
  11. long int screensize = 0;  
  12.    
  13. /*打开设备文件*/  
  14.    
  15. fbfd = open("/dev/fb0", O_RDWR);  
  16.    
  17. /*取得屏幕相关参数*/  
  18.    
  19. ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo); 
  20. ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo);           //该函数最后会将参数传递给finfo、vinfo
  21.    
  22. /*计算屏幕缓冲区大小*/  
  23.    
  24. screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;  
  25.    
  26. /*映射屏幕缓冲区到用户地址空间*/  
  27.    
  28. fbp=(char*)mmap(0,screensize,PROT_READ|PROT_WRITE,MAP_SHARED, fbfd, 0);  
  29.    
  30. /*下面可通过fbp指针读写缓冲区*/  
  31.    ...     
  32. }  

3典型应用flow分析

在不同应用程序中,上层的调用会有所不同,比如Andriod下会选择应用程序跳过Linux fb操作层,直接操作显卡驱动层,称之为BLT accelerator。

下面看一下Android平台下画屏的操作流程。

1、 通过mapFrameBuffer直接把用户空间的数据映射到显存中。

2、 调用HAL中的stretch函数直接命令MSM设备提取显存数据然后送入MDP PPP进行处理并经MDDI接口送到外围LCD组件

具体的函数调用流程如下:

[html]  view plain copy print ?
  1. copybit_open();               //打开BlitEngine,同时也打开fb设备  
  2.      
  3. mapFrameBuffer();               //设置显示参数,同时得到显存虚拟地址  
  4.    
  5. copybit->stretch(copybit, &dst, &src, &sdrect, &sdrect, &it);         //通知底层去刷屏  
接下的流程是:
[html]  view plain copy print ?
  1. stretch_copybit    
  2. 调用:status = msm_copybit(ctx, &list);
  3.                 ->msm_copybit
  4.                      调用int err = ioctl(dev->mFD, MSMFB_BLIT, (struct mdp_blit_req_list const*)list);
  5. //此处应该没有调用到:fb_ioctl(),直接跳到msm_fb_ioctl
  6.                                   ->msm_fb_ioctl(MSMFB_BLIT)    //此处将调用msm_fb.c文件中msm_fb_ioctl()函数中的switch结构,跳入MSMFB_BLIT分支调用:
  7.                                       ->case MSMFB_BLIT:
  8.                                                                       ret = msmfb_blit(info, argp);
  9.                                                                               -> int ret = mdp_blit(info, &(req_list[i]));
  10.                                                                                       -> mdp_ppp_blit
  11.                                                                                                  -> mdp_start_ppp
  12.                                                                                                          ->MDP&MDDI HW operation 
 

本部分介绍的完全是用户空间显示部分的架构,与kernel并没有直接的联系,主要是JNI以下到HAL以上的部分。
1、Surface manager(surface flinger)简介

Surface manager是用户空间中framework下libraries中负责显示相关的一个模块。如下:

当系统同时执行多个应用程序时,Surface Manager会负责管理显示与存取操作间的互动,另外也负责将2D绘图与3D绘图进行显示上的合成。

surface manager 可以准备一块 surface(可以看作一个layer),把 surface 的 fd (一块内存) 传给一个 app,让 app 可以在上面作画。 典型应用如下:

2、Surface manager架构分析

Android中的图形系统采用Client/Server架构,如下:

Client端:应用程序相关部分。代码分为两部分,一部分是由Java提供的供应用使用的api,另一部分则是由c++写成的底层实现。

Server端:即SurfaceFlinger,负责合成并送入buffer显示。其主要由c++代码编写而成。

Client和Server之前通过Binder的IPC方式进行通信,总体结构图如下:

如上图所示,Surface的client部分其实是提供给各应用程序进行画图操作的一个桥梁,该桥梁通过binder通向server端的Surfaceflinger,Surfaceflinger负责合成各个surface,然后把buffer传送到framebuffer端进行底层显示。其中每个surface对应2个buffer,一个front buffer, 一个back buffer,更新时,数据更新在back buffer上,需要显示时,则将back buffer和front buffer互换。

下一部分我们重点研究一下Surfaceflinger。

Android display架构分析七-Surfaceflinger process流程分析

根据前面的介绍,surfaceflinger作为一个server process,上层的应用程序(作为client)通过Binder方式与其进行通信。Surfaceflinger作为一个thread,这里把它分为3个部分,如下:

1、 Thread本身处理部分,包括初始化以及thread loop。

2、 Binder部分,负责接收上层应用的各个设置和命令,并反馈状态标志给上层。

3、 与底层的交互,负责调用底层接口(HAL)。

结构图如下:

注释:

a、 Binder接收到应用程序的命令(如创建surface、设置参数等),传递给flinger。

b、 Flinger完成对应命令后将相关结果状态反馈给上层。

c、 在处理上层命令过程中,根据需要设置event(主要和显示有关),通知Thread Loop进行处理。

d、 Flinger根据上层命令通知底层进行处理(主要是设置一些参数,Layer、position等)

e、 Thread Loop中进行surface的合成并通知底层进行显示(Post buffer)。

f、 DisplayHardware层根据flinger命令调用HAL进行HW的操作。

 

下面来具体分析一些SurfaceFlinger中重要的处理函数以及surface、Layer的属性

 

1)、readToRun     

SurfaceFlinger thread的初始化函数,主要任务是分配内存和设置底层接口(EGL&HAL)。

  1. status_t SurfaceFlinger::readyToRun()  
  2.    
  3. {   
  4. …  
  5. mServerHeap = new MemoryDealer(4096, MemoryDealer::READ_ONLY);            //为IPC分配共享内存  
  6.    
  7. …  
  8.    
  9. mSurfaceHeapManager = new SurfaceHeapManager(this, 8 << 20);         //为flinger分配heap,大小为8M,存放具体的显示数据  
  10.    
  11.     {     
  12.        // initialize the main display  
  13.    
  14.         GraphicPlane& plane(graphicPlane(dpy));  
  15.    
  16.         DisplayHardware* const hw = new DisplayHardware(this, dpy);  
  17.    
  18.         plane.setDisplayHardware(hw);                                                             //保存显示接口  
  19.    
  20. }  
  21.    
  22. //获取显示相关参数  
  23.    
  24.     const GraphicPlane& plane(graphicPlane(dpy));  
  25.    
  26.     const DisplayHardware& hw = plane.displayHardware();  
  27.    
  28.     const uint32_t w = hw.getWidth();  
  29.    
  30.     const uint32_t h = hw.getHeight();  
  31.    
  32.     const uint32_t f = hw.getFormat();  
  33. …  
  34.    
  35.     // Initialize OpenGL|ES  
  36.    
  37.     glActiveTexture(GL_TEXTURE0);  
  38.    
  39.     glBindTexture(GL_TEXTURE_2D, 0);  
  40.    
  41.     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);  
  42.    
  43.     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);  
  44.    
  45.     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  
  46.    
  47. … 
  48. 此部分可以参考文章:SurfaceFlinger启动过程分析   Android系统Surface机制的SurfaceFlinger服务的启动过程分析  

2)、ThreadLoop

Surfaceflinger的loop函数,主要是等待其他接口发送的event,进行显示数据的合成以及显示

  1. bool SurfaceFlinger::threadLoop()  
  2.    
  3. {  
  4.    
  5.     waitForEvent();                         //等待其他接口的signal event     
  6.     …  
  7.        
  8.     handlePageFlip();                        //处理翻页机制  
  9.    
  10.     const DisplayHardware& hw(graphicPlane(0).displayHardware());  
  11.    
  12.     if (LIKELY(hw.canDraw()))  
  13.    
  14.    {  
  15.    
  16.         // repaint the framebuffer (if needed)  
  17.    
  18.         handleRepaint();                   //合并所有layer并填充到buffer中去  
  19.    
  20. … 
  21.         postFramebuffer();                 //互换front buffer和back buffer,调用EGL接口进行显示  
  22.    
  23.     }  
  24.    
  25. …  
  26. }  

在最新的4.1的代码中,threadLoop只调用了waitForEvent,其他部分的实现均放在onMessageReceived()函数中实现【SurfaceFlinger.cpp】

谷歌在Android native层实现的一个异步消息机制,在这个机制中几乎不存在同步锁,所有的处理都是异步的,将变量封装到一个消息AMessage结构体中,然后放到队列中去,后台专门有一个线程会从这个队列中取出消息然后执行,执行函数就是onMessageReceived,这个函数中会有很多分支,用于处理不同的消息;在很多类中都会有各种消息post出来,而后台的异步消息处理线程又是怎么知道发送给哪个类的onMessageReceived函数处理呢,要搞懂这个问题,就需要把谷歌实现的这个异步消息处理框架搞明白,参考文章:http://blog.sina.com.cn/s/blog_645b74b90101cx69.html

3)、createSurface

提供给应用程序的主要接口,该接口可以创建一个surface,底层会根据参数创建layer以及分配内存,surface相关参数会反馈给上层

  1. sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,  
  2.    
  3.         ISurfaceFlingerClient::surface_data_t* params,  
  4.    
  5.         DisplayID d, uint32_t w, uint32_t h, PixelFormat format,  
  6.    
  7.         uint32_t flags)  
  8.    
  9. {     
  10. …     
  11.     int32_t id = c->generateId(pid);  
  12.    
  13.     if (uint32_t(id) >= NUM_LAYERS_MAX) //NUM_LAYERS_MAX=31  
  14.    
  15.     {  
  16.         LOGE("createSurface() failed, generateId = %d", id);     
  17.         return     
  18.     }   
  19. …    
  20. layer = createNormalSurfaceLocked(c, d, id, w, h, format, flags);          //创建layer,根据参数(宽高格式)分配内存(共2个buffer:front/back buffer)  
  21.    
  22.     if (layer)     
  23.     {     
  24.         setTransactionFlags(eTransactionNeeded);  
  25.    
  26.         surfaceHandle = layer->getSurface();                          //创建surface  
  27.    
  28.         if (surfaceHandle != 0)  
  29.    
  30.             surfaceHandle->getSurfaceData(params);            //创建的surface参数反馈给应用层  
  31.    
  32.     }  
  33.    
  34. }  

4)、setClientState

处理上层的各个命令,并根据flag设置event通知Threadloop进行处理

  1. status_t SurfaceFlinger::setClientState(  
  2.    
  3.         ClientID cid,  
  4.    
  5.         int32_t count,  
  6.    
  7.         const layer_state_t* states)  
  8.    {     
  9.     Mutex::Autolock _l(mStateLock);  
  10.    
  11.     uint32_t flags = 0;  
  12.    
  13.     cid <<= 16;  
  14.    
  15.     for (int i=0 ; i<count ; i++)                                                  //检测所有存在layer的状态标志  
  16.        {     
  17.         const layer_state_t& s = states[i];  
  18.    
  19.         LayerBaseClient* layer = getLayerUser_l(s.surface | cid);  
  20.    
  21.         if (layer)  
  22.    
  23.              {  
  24.    
  25.             const uint32_t what = s.what;                  // 检测应用层是否设置各个标志,如果有则通知底层完成对应操作,并通知ThreadLoop做对应的处理  
  26.    
  27.             if (what & eDestroyed)                              //删除该层Layer     
  28.                  {     
  29.                       if (removeLayer_l(layer) == NO_ERROR)     
  30.                  {     
  31.                     flags |= eTransactionNeeded;  
  32.                        continue;  
  33.                    }  
  34.                }  
  35.    
  36.             if (what & ePositionChanged)                    //显示位置变化  
  37.    
  38.                  {  
  39.    
  40.                 if (layer->setPosition(s.x, s.y))  
  41.    
  42.                     flags |= eTraversalNeeded;  
  43.    
  44.             }  
  45.    
  46.             if (what & eLayerChanged)                         //Layer改变     
  47.                  {     
  48.                 if (layer->setLayer(s.z))     
  49.                   {     
  50.                     mCurrentState.layersSortedByZ.reorder(  
  51.    
  52.                             layer, &Layer::compareCurrentStateZ);  
  53.    
  54.                     flags |= eTransactionNeeded|eTraversalNeeded;     
  55.                 }     
  56.             }  
  57.    
  58.             if (what & eSizeChanged)     
  59.            {     
  60.                 if (layer->setSize(s.w, s.h))                                                       //设置宽高变化     
  61.                     flags |= eTraversalNeeded;     
  62.             }  
  63.    
  64.             if (what & eAlphaChanged) {                                                        //设置Alpha效果  
  65.    
  66.                 if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))  
  67.    
  68.                   flags |= eTraversalNeeded;  
  69.    
  70.             }  
  71.    
  72.             if (what & eMatrixChanged) {//矩阵参数变化  
  73.    
  74.                 if (layer->setMatrix(s.matrix))  
  75.    
  76.                     flags |= eTraversalNeeded;  
  77.    
  78.             } 
  79.             if (what & eTransparentRegionChanged) {                                   //显示区域变化  
  80.    
  81.                 if (layer->setTransparentRegionHint(s.transparentRegion))  
  82.    
  83.                     flags |= eTraversalNeeded;  
  84.             }     
  85.             if (what & eVisibilityChanged) {//是否显示  
  86.    
  87.                 if (layer->setFlags(s.flags, s.mask))  
  88.    
  89.                     flags |= eTraversalNeeded;    
  90.             }     
  91.         }     
  92.     }  
  93.    
  94. if (flags)    
  95. {          setTransactionFlags(flags);                                                            //通过signal通知ThreadLoop  
  96.        }  
  97.    
  98.     return NO_ERROR;  
  99.    
  100. }  

5)、composeSurfaces  ,在 handleRepaint()中调用到

该接口在Threadloop中被调用,负责将所有存在的surface进行合并,OpenGl模块负责这个部分。

6)、postFramebuffer

该接口在Threadloop中被调用,负责将合成好的数据(存于back buffer中)推入在front buffer中,然后调用HAL接口命令底层显示。

7)、从3中可知,上层每创建一个surface的时候,底层都会同时创建一个layer,下面看一下surface及layer的相关属性。

Note:code中相关结构体太大,就不全部罗列出来了

A、Surface相关属性(详细参考文件surface.h)

   a1:SurfaceID:  根据此ID把相关surface和layer对应起来

   a2:SurfaceInfo    包括宽高格式等信息

   a3:2个buffer指针、buffer索引等信息

B、Layer相关属性(详细参考文件layer.h/layerbase.h/layerbitmap.h)

包括Layer的ID、宽高、位置、layer、alpha指、前后buffer地址及索引、layer的状态信息(如eFlipRequested、eBusy、eLocked等)

 

Android display架构分析八-Display 开发的经验分享

1添加新的Display Driver的工作内容

参考上面linux下fb设备的软件架构,可以知道,要加入一个新的MDDI 接口的LCM,Driver的工作就是要提供自己的mddi_xxxx.c(在这次porting的过程中,为了节省时间,我们直接修改了mddi_toshiba.c),并且完成和这个lcd相关的HWr的初始化。主要的工作包括:

A、初始化和LCD / LCD背光相关的IO以及电源;

B、编写初始化函数 。主要是初始化LCD控制器,这个一般LCD厂商会提供;然后分配显存,这个高通release过来的code已经包含这个动作了,最后是初始化一个fb_info的结构体,在这里主要是把LCD的一些信息登记进来。

C、把LCD的设备以及驱动注册到系统中去。(这里因为是替换现有的驱动,所以相关修改的部分不多。)

上述B、C部分代码请参考kernel\drivers\video\msm\mddi_toshiba.c。

2Display Driver开发过程

1.2.1配置Power和IO

更改一些GPIO的配置以及一些电源的电平配置;然后通过实际测量,确保一下信号正常:

A、供给LCD以及MDDI Bridge的电源;

B、MDDI Bridge以及LCD reset信号;

C、控制背光IC的GPIO工作正常(背光不打开,无法调试LCD)。

1.2.2Porting LCD初始化序列

LCD init的code以及外围MDDI Bridge的初始化code,都可以之前Boston Windows Mobile系统的code base中获得;把这部分code移植到mddi_Toshiba.c中,并更改相应的图像格式、分辨率等配置,编译通过。LCD初始化部分就算基本完成。

1.2.3LCD初始化过程的调试

由于硬件在之前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掉)。

1.2.4LCD的调整

初始化正常后,屏幕会显示UI的相关画面,但明显颜色、位置都不对。

这个可能是数据类型配置不对导致的,即MDP输出的类型、MDDI配置的类型以LCD接收的类型不匹配导致,也有可能是RGB的顺序不对导致(可配置成BGR)。经过调试后,把MDP端输出的格式配置成RGB565,同时外围MDDI Bridge以及LCD的input格式也配置成RGB565,这时显示色彩正常了。

如果位置或者方向不对,比如说上下或是左右颠倒,可以更改LCD的配置中的扫描方向即可。

1.2.5其他

后续发现一个问题,播放video的时候颜色都是黑白的。

这个问题很容易让人误解,按照正常的理解,video decode出来的数据为YCbCr,Y为亮度信号,CbCr为色差信号,如果只有Y信号的话颜色应该就是黑白的。所以有2个怀疑点,一个是decode出来的数据有误,另一个是MDDI Bridge误把输入的YcbCr信号当作RGB信号进行出来,这个也是有可能的。但很快第二个怀疑点被排除了(因为单更改MDDI input格式后还是不能解决问题)。

后来又详细的看了显示部分的代码,并用JTAG追踪video播放的时候用的显示接口,发现目前所有的显示接口输出的格式都是RGB格式,也就是说在通过MDP之前YcbCr已经被转化过;而MDP里的转换功能并没有使用,MDP只是被当作一个DMA完成数据的直接传输,文档中叫做Bypasse。

YcbCr到RGB的转换是由Android的lib来完成。发了个SR给高通,高通的回复也确认了,在6.3.50中,Android上层缺少这个lib(copybit.default.so),6.3.60之后的版本经解决了这个问题。



显示部分的几个问题这几天通过实际测试澄清了一下,主要是下图中各个模块的使用状况以及HAL层几个模块的调用流程。以问题的方式描述如下:

1Ap是怎么进行显示的?

Surfaceflinger负责所有上层的显示处理,对于AP(2D或是3D的应用程序)而言,只要到surfaceflinger中创建surface,设置好参数,接下来都是统一交给surfaceflinger进行处理

2Surface是怎么管理多个surface的?

不管有多少个surface,最终送到显示部分的只能是屏幕大小数据,surfaceflinger中利用MDP或是GPU进行多个surface的合成处理,普通的合成MDP就可完成,但如果是复杂的比如3D的应用等就必须使用GPU,最终合成的好数据会被送到framebuffer中。

3Framebuffer是什么?

Framebuffer是Linux中为显示数据分配的一块显存(fb设备中),通常大小是一整个屏幕数据的两倍,对于上层AP而言,只需要将要显示的数据丢到framebuffer中就OK了,但此时显示数据并未真正的被送到LCD上,而是暂存在framebuffer中而已。

 

4、上层是通过什么方式将显示内容送到framebuffer的?

有2个方式(二选一,不会同时在运行):

 A、普通的显示,使用copybit(MDP)(未使用GPU)

         Surfaceflinger通过copybit将要显示的数据送到framebuffer。

         Note:copybit可以看做是MDP PPP的接口,它提供了MDP的功能,如多个layer合成,scale、rotate等。

         其接口在:android/hardware/msm7k/libcopybit/copybit.cpp

 B、使用GPU(即使用图中的Graphics driver)

           当进行复杂的显示处理时,比如3D的应用,GPU把处理好的数据直接丢到framebuffer中,和MDP没有任何关系

 

5、Framebuffer中的数据是如何被送到LCD显示的?

图中的Gralloc完成的。

Gralloc有2个功能:

         一个是和copybit相同的,里面有MDP PPP的接口(目前没有使用)

          另一个则是刷屏(整屏刷)的接口,即将framebuffer中的数据送到lcd上,调用的是MDP DMA的接口

          这部分的code在android/hardware/msm7k/libgralloc-qsd8k目录下,之前没有留意,以为没有使用。现在可以看出开机初始化后就创建了disp_loop thread,里面的操作就是调用系统接口ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info)将数据送到lcd

Note:送数据的时候是2个buffer切换的

另外,上层surfaceflinger也是通过Gralloc中的接口获知屏幕的大小,调用接口为ioctl(fd, FBIOGET_VSCREENINFO, &info),info中的屏幕宽高对应的就是底层driver设置的宽高值

 

6OpenGL是什么?

它是一个图像处理引擎,当需要一些复杂的显示(2D/3D)操作时会用到它。它分为SW方案和HW方案,

软件方案就是图中的libagl.so,对应到目前项目中是libGLES_android.so,它可以完成简单的2D(文字,icon等)处理,通过trace看目前大部分显示操作都是它来完成的。

   Note:它是软件方案,处理好的数据是通过copybit送到framebuffer的,而不是GPU其接口部分参考:android/frameworks/base/opengl/libagl

HW方案就是图中的Graphics driver,它通过使用GPU硬件来完成图像处理,处理后的数据直接送到framebuffer中。其接口部分参考android/frameworks/base/opengl/libs(有几个版本)

 

7OpenGL在项目中是如何配置的?

在android/vendor/qcom/msm7627_ffa目录下有一个egl.cfg文件,里面指定了当前版本中的OpenGL信息,目前如下:

0 0 android            第一行代表该codebase支持SW 方案的OpenGL,是android default的

0 1 adreno200       第二行代表该codebase也支持HW方案的OpenGL,是高通的adreno引擎

如果该cfg文件为空,则只支持default的SW方案。

如果2个方案都在,上层将根据实际应用自行选择使用其一。

该部分请参考:android/frameworks/base/opengl/libs/EGL/loader.cpp


 

 

上一篇:Android display架构分析-SW架构分析(1-4)


Android display架构学习 一、Linux FrameBuffer 设备 什么是framebuffer设备? Documentation\fb\framebuffer.rst fbmem.c 阅读详情

相关推荐

Android Display

DisplayManagerService用来管理显示的生命周期,它决定如何根据当前连接的物理显示设备控制其逻辑显示,并且在状态更改时,向系统和应用程序发送通知,等等。DisplayAdapter 是 DisplayManagerService 所依赖的集合组件,其为系统显示,收集并发现物理显示设备提供了适配器的作用。目前有以下两种方式的适配器供使用一、为本地显示设备提供适配器。二、为开发者提供的模拟显示适配器。

liuning1985622的博客 1885

android__display框架分析

android__display框架分析 android__display框架分析

Android Qcom Display学习(十三)

该系列文章总目录链接与各部分简介:在上一篇中dump GraphicBuffer中,知道了护眼模式中调用setColorTransform应用于每一层Layer,于是想往上了解一些。

Android驱动开发 3841

Android display架构分析

对高通Android Display驱动架构分析得比较详细,包括9讲,网上下来的。

Android Display架构分析,黑屏,系统架构

其实,Android 系统完全可以没有 HAL 层,访问硬件可以通过调用 Linux 内核的标准函数来实现,但是,如何访问 Linux 内核就涉及到了技术专利和商业机密,厂商不想公开源代码,只愿提供二进制代码。HAL(Hardware Abstract Layer)硬件抽象层,是 Google 开发的 Android 系统上层应用对底层硬件操作屏蔽的一个层次结构,简单来说就是,上层应用不需要关心底层硬件是如何工作的,只需要调用底层提供的统一接口即可。1.1 Linux 内核层(Linux Kernel)

sun007700的专栏 1158

Android Display架构分析

android display

lin20080410的专栏 8591

Android 11 Display亮灭屏

Android 11 Display亮灭屏,从framwork到hal层流程分析

zjy764219923的专栏 2018

Android display架构分析(七-2)

转 http://hi.baidu.com/leowenj/blog/item/ba4c5d6378a5da48eaf8f86a.html   Android display架构分析(七-2)   4)、 setClientState 处理上层的各个命令,并根据 flag 设置 event 通知 Thread...

Flash Flex AIR 3D 206

Android 图形架构 之七——Choreographer 源码分析

前言 在Android4.1之后增加了Choreographer机制,用于同Vsync机制配合,控制同步处理输入(Input)、动画(Animation)、绘制(Draw)三个UI操作。其实UI显示的时候每一帧要完成的事情只有这三种。如下图是官网的相关说明: Choreographer接收显示系统的时间脉冲(垂直同步信号-VSync信号),在下一个frame渲染时控制执行这些操作。 Choreographer中文翻译过来是"舞蹈指挥",字面上的意思就是优雅地指挥以上三个UI操作一起跳一支舞。这个词可以概括这

薛瑄的博客 4115

Android display架构分析(八)

转 http://hi.baidu.com/leowenj/blog/item/03aae36137acb8d1e6113a75.html   Android display架构分析(八)   1添加新的 Display Driver 的工作内容 参考上面linux 下fb 设备的软件架构,可以知道,要加入一个新的MDDI 接口的LCM ,Driver 的工作...

Flash Flex AIR 3D 204

最新安卓版本对照表,API对照表(持续更新,更新到安卓17)

话不多说,直接上表,持续更新(更新到安卓16)。 列出了所有记录的可能会影响应用开发者的功能和行为变更。请使用此列表查找影响您的变更,然后点击相应的链接以阅读文档。下表列出了所有记录的可能会影响应用开发者的功能和行为变更。请使用此列表查找影响您的变更,然后点击相应的链接以阅读文档。Java 和 OpenJDK 是 Oracle 及/或其关联公司的商标或注册商标。

雨季余静的博客 9万+

eDBG内存操作详解:dump、write、display命令的深度应用

eDBG作为一款基于eBPF的轻量级Android调试器,提供了强大的内存操作功能,帮助开发者高效分析和修改进程内存。本文将深入解析eDBG中dump、write、display三大核心内存操作命令的使用方法与实战技巧,让你轻松掌握内存调试的精髓。 ## 一、内存操作基础:认识eDBG的内存调试能力 eDBG通过简洁的命令行接口提供了全面的内存操作支持,其核心功能实现主要集中在[control

gitblog_00491的博客 584

RK3588性能榨取指南:在香橙派5 Plus上搭建8路安卓云手机集群

本文详细介绍了如何在香橙派5 Plus上利用RK3588芯片搭建8路安卓云手机集群。通过优化Docker环境和Redroid安卓容器部署,实现高性能边缘计算,适用于云游戏、自动化测试和边缘AI推理等场景。RK3588的强大性能与香橙派5 Plus的黄金组合,为开发者提供了高效、低功耗的解决方案。

weixin_42699679的博客 287

公司项目Android8.0适配分析

两个官方链接: 1. 官方推荐的兼容测试方式 2. Android8.0行为变更说明 Android 8.0 行为变更包括两个部分:针对所有 API 级别的应用和针对 Android 8.0 的应用(8.0专属部分大部分用不到,所以没专门列出),当然,全局API级改变在项目中的使用场景也很少。 针对所有 API 级别的应用 api修改 相应的说明 是否需要适配 后台执

听风-Android进阶 1万+

display:flex和display:box布局浏览器兼容性分析

原文地址:https://www.cnblogs.com/walk-on-the-way/p/5997073.html display:flex和display:box布局浏览器兼容性分析 display:flex和display:box都可用于弹性布局,不同的是display:box是2009年的命名,已经过时,用的时候需要加上前缀;display:flex是2012年之后的命名。在实际的测...

farmerXU的博客 1508

关于"Use 32-bit Display Buffer"

一个Bug:辉光没了 在 Android 设备上,之前工作良好的 辉光 在某一个版本突然没了。 看了一下 svn log,并没有什么代码改动,但 主美哥 用他的 24K氪金狗眼 跟我保证:辉光真的没了。 好吧,检查了一下发现,辉光的计算依然还在,但是计算结果却是一片黑… 下面是 FrameDebugger 的调试结果: 辉光计算依然存在 _BloomTex一片漆黑 _BloomTex 存储的...

weixin_45979158的博客 1628

高通8x25平台display模块总结

高通8x25平台display模块总结 一、概述   1.1  简介        本文档主要包括LCD模块的驱动流程分析、Framebuffer相关知识、Gralloc等相关内容,以及LCD调试的一些经验和相关bug的分析和讲解。   1.2  开发环境          Android:4.0          Kernel: Linux3.0          Ubuntu

liwei405499的专栏 1570
上一篇: assert用法总结
下一篇: Linux驱动调试中的Debugfs的使用简介
专注android开发
博客等级 码龄16年 110粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值