文章目录
-
- 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.cpp
Surface::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.cpp
SurfaceControl::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.cpp
sp<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.cpp
status_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(渲染)->显示渲染内容