现在的位置: 首页 > 综合 > 正文

android overlay based on msm8930

2013年11月11日 ⁄ 综合 ⁄ 共 9120字 ⁄ 字号 评论关闭

   本文重点针对HDMIandroid上的应用,而比较相关的就是overlay机制。overlay在这里只是简单的介绍,后续会有文章再专门详述。

      我没记错的话,高通从7X30开始,平台就可以支持HDMI1.3)输出了。只不过在7x30上通过RGB接口外接一颗HDMItransmitter来实现;而到了8系列(8x60),高通把这颗IC也集成了,直接就提供HDMI的输出了。(这样下去,以后渐渐的把外围器件都集成了,做底层的估计要失业了,做硬件的似乎工作量也没多少了)。

       先来看看HW的能力,下图是MDP4.0的结构图:

       

可以看到,MDP4内部有4overlay pipe2个是for
UI
RGB)的,2个是VG for videographics的;另外有2mixermixer1for
primary display
的(可以是MDDI接口的,也可以是RGB接口的lcdoled等);mixer2for
external display
的,如通过RGB interface2外接HDMI transmitterTV,也可以是NTSC/PAL等模拟电视信号。

        NoteVG1RGB1mixer1混合到primary
lcd
VG2RGB2mixer2混合到external LCD(如HDMI TV

        如果是MDP4.1的话,MDDI接口被移除了,另外RGB接口只有一个,另一个内部集成为HDMI接口了。

     

      上面提到的是硬件平台相关的,就是说硬件有支持HDMI输出的能力,但是软件的状况呢?我们来看看Android和高通的状况。

      关于HDMI本身,我就不介绍了,网上随便找找都可以看明白。

      研究过Android的都知道,surfacefinger负责管理应用程序的显示窗口,每个窗口可以由多个surface组成,surfaceflinger通过OpenGL(可以通过HW,也可以是SW)把所有的surface合成后,通过调用gralloc模块或是overlay模块(MDP4.X才支持)把整屏数据送到显示设备上。可是Android(截止到2.23.0的状况还未知)上目前只支持一个显示设备,也就是说在surfaceflinger只能固定一个显示设备,那么HDMI这个应用在android手机上如何应用呢?

     这里介绍2个做法,一个是高通给做好的,叫做UI mirroringvideo mirroring;另一个就是我们自己添加接口,AP自己来实现想要的功能。

     先来看高通在android中的做法,根据字面不难理解,UI mirroringvideo mirroring其实就是把原来显示在primary
LCD
上的数据mirrorHDMI接口。下图为软件框架图:

      

     先来看看HDMI的控制方面,上图的右侧,user空间中有一个HDMI service,包含一个listener(都是java的),当HDMI cable插入后,底层HDMI的驱动检测到(HPD)后,通过kobject_uevent传送给HDMI daemondaemon再把event发送给HDMIserviceHDMI service除了判断这个eventcable状态),另外还要判断qualcomm
setting
HDMIon/off选项,然后把判断结果broadcast给各个AP,各个AP也就知道当前是否要开启HDMI输出了

      接着先看UI mirroring(不含video的状况)的实现,它针对的是界面的操作,数据为RGB格式。我们知道在kernel中每个显示设备都对应一个fb,初始化时都会分配framebuffer,在这里,primary
lcd
对应fb0设备,HDMI对应fb1设备。正常情况下,surfaceflinger合成好一个main
surface
后,通过post buffergralloc模块)把数据放入fb0,然后,通过overlaykernel下做的,上层看到的还是通过IOCRLFBIOPUT_VSCREENINFO命令实现)输出到primary
lcd
;当平台支持HDMI并且UI mirroring开启时,gralloc中(framebuffer.cpp)初始化时会多创建一个taskhdmi_ui_loop),并新建一个overlay(主要是控制和数据,参考overlaylib.h),这个overlay对应的channel固定为fb1src
fd
就是fb0,也就是说这个overlay的源数据就是fb0,也就是primary lcd上的数据,通过rotator进行旋转(电视是横屏),然后在overlay中再scale
up
后再通过HDMI送到TV。这样看来,送到HDMI上的数据其实就是把fb0中的数据copybit了一份并放大,多少会有些失真的,但对于UI界面来说是可以接受的。上述整个过程,surfaceflinger是不参与的。

       再来看video mirroring是怎么做的?

       先来看看什么是video mirroring,其实就是手机播放视频,同时通过HDMI输出到TV上,手机上的内容分为2个部分,一个是视频本身部分,另一个是UI,这已经占用2overlay
pipe
了(一个VG pipe,一个RGB pipe),TV上视频部分肯定是需要一个VG pipe,另外,由于视频大小问题,视频不可能正好为全屏模式,这样必须还需要一个RGB
pipe
来实现一个背景(全黑)。4pipe都被占用了,没有多余的pipe来把UI部分传到TV上,所以再使用高通平台时候,进行video
mirroring
时,TV上只能播放视频画面,UI部分(如菜单)在TV上是无法显示的。

        接着来看video部分是怎么处理的?首先手机端UI部分的处理模式不变,只不过上面提到的hdmi_ui_loop这个task会被停掉(UI不需要送到HDMI,原因上面已经解释过);video部分的frame通过opencore解码出来后,首先会通过surfaceflinger来创建overlay(参考layerbuffer.cpp),当系统支持HDMI时通过create
overlay
都会创建2个通道(这里是2VG通道),其中包含2control channel2data
channel
,它们的HAL层接口都再overlaylib.cpp中,channel0 for fb0channel1 for fb1,如果需要旋转,则从系统pmem中再分配对应的内存。APoverlay基本上的流程是这样的(可以参考overlays.cpp,里面不全,我补充了一些):


    sp<SurfaceComposerClient> client = new SurfaceComposerClient();//新建surface客户端

    // create pushbuffer surface
    sp<Surface> surface = client->createSurface(getpid(), 0, 320, 240, 
            PIXEL_FORMAT_UNKNOWN, ISurfaceComposer::ePushBuffers);//
创建一个surface

    // get to the isurface
    sp<ISurface> isurface = Test::getISurface(surface);//
得到surface相关接口
    printf("isurface = %p\n", isurface.get());
    
    // now request an overlay
    sp<OverlayRef> ref = isurface->createOverlay(320, 240, PIXEL_FORMAT_RGB_565);//
创建overlay,并得到控制通道
    sp<Overlay> overlay = new Overlay(ref);//初始化overlay并得到数据通道

    overlay->setFd(mFd);//设置src datafd

    overlay->setCrop(x,y,w,h);//设置剪裁信息(根据需要)

    overlay->queueBuffer(offset);//设置显示数据的偏移

     这样video player没解码出一个frame,都会调用quene函数把数据送入2个数据通道,overlay
engine
会把数据送到2个显示设备。

     关于那个背景,暂时在code中还没发现,也许是因为目前的版本不是最终版本,后续还会更新。

    上面的做法是高通的;但它是有限制的,比如说无法在2个屏幕上显示不同的内容。如果我们要做,也是可以的,主要就是看AP怎么定义规则了。另外framework中需要添加接口,主要是提供一个针对fb1设备的控制接口,同样也是绕过surfaceflinger。比如说手机在播放一个影片,通过HDMI把影片传送到TV上,同时手机端可以去浏览网页。这个功能可以这样做,AP背景播放影片,得到的frame不送到primary
display
上,而是通过新加的接口输出到fb1设备上,而browserUI正常显示即可。如果是在高通平台去实现的话,需要把qualcomm setting里面的HDMI选项关掉,否则高通的做法和你自己AP的做法就乱套了。不过目前看,高通提供的方式似乎也可以满足应用了,但应用是永无止境的,只要user有这样的需求,developer就要去做,呵呵!

OVERLAY

首次post后仍会更新,转载请注明出处http://blog.csdn.net/zirconsdu/article/details/8773263

File Orgnization

目录/hardware/qcom/display/liboverlay/

Android.mk

mdpRotator.cpp               Overlay Rotator Wrpper

mdpWrapper.h                 MDP Normal and Overlay FrameBuffer IOCTL Wrapper

mdssRotator.cpp             Overlay MDSS Rotator Wrapper

overlay.cpp        Overlay Top level implementation file

overlay.h             Overlay Top level declaration file

overlayCtrl.cpp   OverlayCtrl implementation file

overlayCtrlData.h       OverlayCtrl and OverlayData declaration file including OverlayData implementation

overlayImpl.h    Overlay implementation which operates overlay pipes pair(LayerMixer)              

overlayMdp.cpp    Overlay implementation on MDP, used by OverlayCtrlData    

overlayMdp.h   Overlay on MDP

overlayMem.h  Overlay VG pipe input kernel memory file descriptor, maybe graphic buffer or rotator output buffer

overlayRotator.cpp         Overlay Rotator top level implementation

overlayRotator.h              Overlay Rotator top level declaration

overlayState.h  Overlay state machine

overlayUtils.cpp                 Overlay Utils

overlayUtils.h    Overlay Utils

pipes/   Overlay Pipes, that is Overlay channel. It is a VG and RGB pipe pair on MDP.

 

Platform architecture

MDP中每个VGRGB pipe pair作为一个LayerMixer的输入,由LayerMixer完成Overlay功能,作为一个Overlay
channel

当使用Overlay功能时:

RGB pipe的输入是普通的Framebuffer,是Surfaceflinger的合成输出;

VG的输入是videographicscamera图像等,是内核空间内存buffer,其owner一般是VideoGraphicsV4L2等。当其前端是Rotator时,Rotator的输入是这些bufferRotator的输出Overlay
rotator frame buffer
作为VG的输入。

每个Overlay Channel结构如下图所示

关于Overlay Buffer(FrameBuffer RotatorBuffer OverlayBuffer)这些名称并不特别明确,只要明白Overlay Channel数据流路上的各输入输出Buffer的位置和作用即可。

下面以Layermixer1(对应/dev/graphics/fb0)为参考详述各buffer:

只UI显示时,

Framebuffer是fb0的framebuffer,是从启动时预留出的bootmem中的分配出来的。LayerMixer1处于BLT模式,Layermixer1和DMA_P(Primary display driver)分离,可以由软件完全控制。该Framebuffer做为DMA_P的输入,经MIPI_DSI输出到主屏上。

启用Overlay时,

上述Framebuffer做为RGB1 pipe的输入,而视频或图像的内核buffer做为VG pipe的输入,二者经Layermixer1合成;此时LayerMixer1工作在非BLT模式,LayerMixer1和DMA_P attach在一起,LayerMixer1输出控制参数直接提供给DMA_P使用。此时LayerMixer1仍有两种工作模式,FrameBuffer模式和DIRECT_OUT模式,前者时LayerMixer1和DMA_P之间使用一个overlaydouble
buffer做缓冲,输出给DMA_P;DIRECT_OUT模式下不使用该ovl double buffer,LayerMixer1直接输出给DMA_P

一般VGRGB的输入都可以是double bufferping-pang;LayerMixer的输出也是double
buffer。DMA_P/S/E做为display driver传输前端buffer
作为后端接口控制器的输入。

下面两图是QC MDP UI mirrorVideo mirror时的两结构图,并没有明确画出LayerMix1Overlay流程路径,个别bufferowner可能也有所差错,buffer也并不全,仅是大致描述Overlay及其部分buffer

 

MDPDSI和后端显示控制器和接口的连接结构如下图。

 

Layer architecture

Overlay   ->  OverlayImpl

OverlayCtrlData

OverlayMDPCtrlData

MDPWrapper

FrameBuffer

 

KeyPoint

Ctrl用来设置overlay channel的参数,Data用来提交bufferOverlay
channel queue
。其实使用overlay本质上就是设置好pin路由,设置好通道工作参数,然后不停的提交数据让Overlay Enginee工作。MDPOverlay
Channel
并没有别的特殊的编程接口,都是使用控制、状态和数据寄存器来访问。其实MDP提供了远比Android Overlay实现强得多的Overlay功能。

Some flow

Ctrl::commit()  ->  MDPCtrl::set() -> mdp_wrapper::setOverlay()  -> ioctl(fd, MSMFB_OVERLAY_SET, &ov)

-> msm_fb -> mdp4_overlay设置Overlay工作参数。

Data::queueBuffer -> MDPData::play -> mdp_wrapper::play() -> ioctl(fd, MSMFB_OVERLAY_PLAY, &od)

-> msm_fb -> mdp4_overlay进行Overlay合成。注意queueBuffer第一参数fd是memFd,是内核空间的buffer,并不在用户空间和内核空间拷贝buffer数据。作用与framebuffer类似的是提交内核空间的该buffer到Overlay Enginee
Queue。

有了这些平台相关知识,msm_fbmdp4_overlay驱动的功能也就容易理解了。

android gralloc流程分析for msm8960

原文转载自http://blog.csdn.net/g_salamander/article/details/8424334

增加了Gralloc模块的平台背景和功能概述部分。

对原文针对msm8960 android display做了修正。

增加了Surfaceflinger初始化FrameBufferNativeWindow的代码部分。

平台中内存有ashmen、PMEM等多种内存类型,为了Video、Graphics、GPU内存访问的需要,android引入Gralloc模块实现内存的管理。Gralloc把FrameBuffer的分配也纳入了其中,并且新引入ION做为Gralloc的非FrameBuffer内存的分配器。ION对于内核态内存在用户进程之间的访问和硬件平台模块之间数据流转提供了高效的解决方案。

Android 中 lcd 是一个帧缓冲设备,驱动程序通过处理器的 lcd 控制器将物理内存的一段区域设置为显存,如果向这段内存区域写入数据就会马上在 lcd 上显示出来。Android 在 HAL 中提供了gralloc 模块,封装了用户层对帧缓冲设备的所有操作接口,并通过 SurfaceFlinger 服务向应用提供显示支持。在启动过程中系统会加载 gralloc 模块,然后打开帧缓冲设备,获取设备的各种参数并完成
gralloc 模块的初始化。当应用程序需要把内容显示到 lcd 上时,需要通过 gralloc 模块申请一块图形缓冲区,然后将这块图形缓冲区映射到自己的地址空间并写入内容即可。当应用程序不再需要这块图形缓冲区时需要通过 gralloc 模块释放掉,然后解除对缓冲区的映射。

1、基础数据结构

gralloc 模块通过 struct private_module_t 来描述,该结构定义如下:

  1. <span style="font-size:12px;">struct private_module_t {  
  2.     gralloc_module_t base;  
  3.   
  4.     private_handle_t* framebuffer;  /* 指向图形缓冲区的句柄 */  
  5.     uint32_t flags;                 /* 用来标志系统帧缓冲区是否支持双缓冲 */  
  6.     uint32_t numBuffers;            /* 表示系统帧缓冲的个数 */  
  7.     uint32_t bufferMask;            /* 记录系统帧缓冲的使用情况 */  
  8.     pthread_mutex_t lock;           /* 保护结构体private_module_t的并行访问 */  
  9.     buffer_handle_t currentBuffer;  /* 描述当前正在被渲染的图形缓冲区 */  
  10.     int pmem_master;                /* pmem设备节点的描述符 */  
  11.     void* pmem_master_base;         /* pmem的起始虚拟地址 */  
  12.   
  13.     struct fb_var_screeninfo info;  /* lcd的可变参数 */  
  14.     struct fb_fix_screeninfo finfo; /* lcd的固定参数 */  
  15.     float xdpi;                     /* x方向上每英寸的像素数量 */  
  16.     float ydpi;                     /* y方向上每英寸的像素数量 */  
  17.     float fps;                      /* lcd的刷新率 */  
  18.       
  19.     int orientation;                /* 显示方向 */  
  20.   
  21.     enum {  
  22.         PRIV_USAGE_LOCKED_FOR_POST = 0x80000000  /* flag to indicate we'll post this buffer */  
  23.     };  
  24. };</span>  
该结构的成员记录了 gralloc 模块的各种参数,主要为模块自己使用,应用程序操作的图形缓冲区的数据结构是struct private_handle_t,定义如下:
  1. <span style="font-size:12px;">#ifdef __cplusplus  
  2. struct private_handle_t : public native_handle {  
  3. #else  

抱歉!评论已关闭.