Android display架构分析(5-8)

18 篇文章 2 订阅
16 篇文章 4 订阅

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)


  • 0
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值