Android(安卓)Window的添加和显示过程
文章目录
- 1. Android Window
- 2. Window的添加流程
- 1. Native Surface的面貌
- 3. BufferQueue
- BufferQueue的消费者模型大概的通信流程:
- 4. Surface 和 Layer
- 1. Surface绘图过程
- 2. 整体绘制过程概述:
- 5. 总结
本文基于Android N;
1. Android Window
Android中的Window是一个抽象概念,并不是真正的window,而是一个用于对真正的图形显示组件(Surface)做管理的 “虚拟窗口概念”。
我们在开发过程中的意识上可以认为Window就是一个屏幕窗口,这也是Android提出Window概念的目的所在,可以更好的面向开发者理解。
实质上的Window其实是一块 图形缓冲区 ,这块图形缓冲区的承载者就是我们在自定义View的时候所见的Canvas,而对Canvas也有其缓冲区管理者,叫做Surface。
Surface的作用是向SurfaceFlinger获取App界面创建时候的 GraphicBuffer(IGraphicBufferProducer),并向Buffer中默认填充一个Bitmap数据格式,并设置到Canvas中,这整个流程在接下来都会有讲到。
2. Window的添加流程
Window的添加流程从WindowManager的addView开始,这个接口是所有客户端对窗口的新建的统一接口,并且调用之后,会直接显示在界面上(系统Window的使用会有权限问题)
如上图所示,addWindow的流程其实就是向WindowManagerService注册Window的格式/类型/尺寸等大小,然后向SurfaceFlinger申请图形缓存Layer,Layer中会有创建好的GraphicBuffer,和用于提交图形的producer对象,消费图形数据的consumer对象。
- 图中重要的几点:
- ViewRootImpl创建的时候,会创建一个Surface,此时这个Surface对象是空的;
- Surface的对象填充是在requestLayout之后,底层会返回Native Surface的地址,并通过1中创建的Surface对象中;
1. Native Surface的面貌
- 看一下Native的Surface是什么样子的?
//frameworks/native/libs/gui/Surface.cppSurface::Surface( const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp) : mGraphicBufferProducer(bufferProducer), mCrop(Rect::EMPTY_RECT), mGenerationNumber(0), mSharedBufferMode(false), mAutoRefresh(false), mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT), mSharedBufferHasBeenQueued(false){
对IGraphicBufferProducer的一个封装。
- bufferProducer对象是怎么来的?
//frameworks/native/libs/gui/SurfaceControl.cppSurfaceControl::SurfaceControl( const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle, const sp<IGraphicBufferProducer>& gbp) : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp) //来自构造函数;{} ......sp<Surface> SurfaceControl::getSurface() const{ Mutex::Autolock _l(mLock); if (mSurfaceData == 0) { // This surface is always consumed by SurfaceFlinger, so the // producerControlledByApp value doesn't matter; using false. //Native Surface创建 mSurfaceData = new Surface(mGraphicBufferProducer, false); } return mSurfaceData;}
SurfaceControl创建的时候会传递gbp对象并赋给mGraphicBufferProducer。
- gbp怎么来的?
//frameworks/native/libs/gui/SurfaceComposerClient.cppsp<SurfaceControl> SurfaceComposerClient::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags){ sp<SurfaceControl> sur; if (mStatus == NO_ERROR) { sp<IBinder> handle; sp<IGraphicBufferProducer> gbp; status_t err = mClient->createSurface(name, w, h, format, flags, &handle, &gbp); ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err)); if (err == NO_ERROR) { sur = new SurfaceControl(this, handle, gbp); } } return sur;}
在requestLayout的时候,调用createSurface创建的,并通过SurfaceControl包装的(构造时候传递进去的)。
还是没有说到gbp怎么来的,继续跟:
//frameworks/native/services/surfaceflinger/SurfaceFlinger_hwc1.cppstatus_t SurfaceFlinger::createLayer( const String8& name, const sp<Client>& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp){ ... sp<Layer> layer; switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceNormal: result = createNormalLayer(client, name, w, h, flags, format, handle, gbp, &layer); break; case ISurfaceComposerClient::eFXSurfaceDim: ... break; default: ... }...}status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer){ ... *outLayer = new Layer(this, client, name, w, h, flags); status_t err = (*outLayer)->setBuffers(w, h, format, flags); if (err == NO_ERROR) { *handle = (*outLayer)->getHandle(); *gbp = (*outLayer)->getProducer(); //**gbp来自于这里 }...}
继续跟
void Layer::onFirstRef() { sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer); //创建producer和consumer mProducer = new MonitoredProducer(producer, mFlinger); //包装producer mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName); //包装consumer mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mSurfaceFlingerConsumer->setContentsChangedListener(this); //设置consumer的FrameAvailable监听器, //会在producer queueBuffer之后,通知consumer有可用的帧数据需要合成; mSurfaceFlingerConsumer->setName(mName);}sp<IGraphicBufferProducer> Layer::getProducer() const { return mProducer; //gbp实体就是这位大哥, //在Layer创建的时候创建的MonitoredProducer,但是这个只是一个包装,实体还不是这个。}
继续看…
///frameworks/native/libs/gui/BufferQueue.cpp//!!createBufferQueue是创建BufferQueue需要的元素:BufferQueueCore, Producer和Consumer。void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer, const sp<IGraphicBufferAlloc>& allocator) { LOG_ALWAYS_FATAL_IF(outProducer == NULL, "BufferQueue: outProducer must not be NULL"); LOG_ALWAYS_FATAL_IF(outConsumer == NULL, "BufferQueue: outConsumer must not be NULL"); sp<BufferQueueCore> core(new BufferQueueCore(allocator)); LOG_ALWAYS_FATAL_IF(core == NULL, "BufferQueue: failed to create BufferQueueCore"); //***BufferQueueProducer 才是真正的Producer sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core)); LOG_ALWAYS_FATAL_IF(producer == NULL, "BufferQueue: failed to create BufferQueueProducer"); sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core)); LOG_ALWAYS_FATAL_IF(consumer == NULL, "BufferQueue: failed to create BufferQueueConsumer"); *outProducer = producer; *outConsumer = consumer;}
3. BufferQueue
参考:
Android BufferQueue生产消费原理概述
BufferQueue的消费者模型大概的通信流程:
4. Surface 和 Layer
Surface 和 Layer是一一对应的, Surface属于图形生产者(Producer),Layer属于图形消费者(Consumer)。
App通过Surface提交的图形数据,通过enqueueBuffer之后,SurfaceFlinger会通过Layer获取到图形缓冲数据,最终渲染提交到屏幕做显示。
1. Surface绘图过程
ViewRootImpl创建空Surface之后,经过requestLayout操作或创建真正的Surface(见上图),然后App进程会经过measure,layout和draw最终将画面绘制出来。
这里着重看draw方法。
下图是Surface申请 GraphicBuffer, 绘制填充Buffer, 提交Buffer的流程。Buffer的设置其实是设置到了SKBitmap(Skia)中,然后再把SKBitmap设置到Canvas中,所以真正的Buffer携带者其实是Canvas,Surface负责申请Buffer,控制Buffer在绘制过程中的lock和unlock同步操作:
图形绘制的生产者消费者模型:
[在这里Producer是Surface
, Consumer是Layer
]
2. 整体绘制过程概述:
- 1_ Surface -> lock,连接BufferQueue, 注册用于接收consumer消费完并会受到Buffer Queue的可用Frame的监听器(DummyProducerListener);
- 2_ dequeueBuffer, 向QueueBuffer申请可用的GraphicBuffer;
- 3_ 将申请的GraphicBuffer包装成SkBitmap,并设置到Canvas中,最后返回lockedSurface给Java层;
- 4_ View绘制Canvas,填充图形数据到Canvas中;
- 5_ Surface-> unlockAndPost, 提交填充完成的Buffer到BufferQueue;
- 6_ BufferQueue会通知Consumer(Layer)当前有需要合成的Buffer存在,Layer收到监听之后,会通知SurfaceFlinger,最后通过Layer更新Texture,渲染完成后提交到屏幕显示;
综合两张图可以大致的看下从addView开始到Surface创建、申请Buffer、填充Buffer、绘制到体提交Buffer的整体流程:
5. 总结
从软件层面上看,Android的Graphic框架主要有几个模块:
Activity、Window、Surface、Layer、Canvas、BufferQueue。
其中:
- Activity:标记一个活动,是活动的管理者(并不参与绘制),是Window的承载者;
- Window:标记一个窗口(真实其实是WindowState),是一个抽象概念,用来对承载和管理Surface;
- Surface:标记一个绘制流程,面向开发者弱化了GraphicBuffer的概念,用来申请/提交Buffer,管理Canvas,管理一个绘制回合(绘制流程的同步);
- Layer:Graphic服务端的Buffer承载者,对应一个Surface,它受SurfaceFlinger的管理。SurfaceFlinger是Surface的消费者,消费单位是Layer;
- Canvas: 真正用于图形数据填充(绘制)的对象,Surface申请的Buffer会保存在Canvas中的SKBitmap中,绘制完成后,Surface会将Canvas对应的已经填充了有效数据的缓冲区enqueue到BufferQueue,然后通消费者有需要渲染的Buffer入队,然后交由消费者消费;
在App侧,只需要使用2D/3D图形绘制引擎来绘制出自己的图形数据,然后提交到这一块申请好的Buffer中,
并提交到BufferQueue,消费者SurfaceFlinger会从BufferQueue取出数据经由opengl渲染之后递交到屏幕显示。
- App一般使用的事2D图形引擎Skia,3D由OpenGL做渲染。也可以通过开启硬件加速交由opengl来渲染,在Android N上有hwui作为硬件加速的可选项。
- 关于Android APP中 Skia和openGL的了解,可以参考:
Android Graphic : apk and Skia/OpenGL|ES
- BufferQueue: Android Graphic的核心之一,管理生产者和消费者之间对Buffer使用的同步,还有GPU/CPU的跨硬件同步(Fence),在Graphic系统上起着关键的作用。具体参考上面的第三大点。
以上所有的流程个人总结为:
初始化会话链接 -> 添加Window,设置Window信息(显示屏幕、显示大小,格式等等) -> 创建Surface ->
初始化Layer -> 创建BufferQueue -> 申请Buffer -> 填充Buffer -> 提交Buffer -> 消费Buffer(渲染)->显示渲染内容
更多相关文章
- Android(安卓)P wakeup 亮屏流程
- android中的数据存取 之 File
- Android(安卓)onNewIntent的应用
- Android-使用OpengGL实现的Canvas进行绘制(简单介绍)
- Android(安卓)文字绘制,多行文字绘制
- Android的绘制详解(Canvas、Paint、Path等)
- Android(安卓)创建与解析XML(四)—— Pull方式
- Android(安卓)发布release版本的apk软件
- opengl fbo 离屏渲染