本文基于Android N;
Android中的Window是一个抽象概念,并不是真正的window,而是一个用于对真正的图形显示组件(Surface)做管理的 “虚拟窗口概念”。
我们在开发过程中的意识上可以认为Window就是一个屏幕窗口,这也是Android提出Window概念的目的所在,可以更好的面向开发者理解。
实质上的Window其实是一块 图形缓冲区 ,这块图形缓冲区的承载者就是我们在自定义View的时候所见的Canvas,而对Canvas也有其缓冲区管理者,叫做Surface。
Surface的作用是向SurfaceFlinger获取App界面创建时候的 GraphicBuffer(IGraphicBufferProducer),并向Buffer中默认填充一个Bitmap数据格式,并设置到Canvas中,这整个流程在接下来都会有讲到。
Window的添加流程从WindowManager的addView开始,这个接口是所有客户端对窗口的新建的统一接口,并且调用之后,会直接显示在界面上(系统Window的使用会有权限问题)
如上图所示,addWindow的流程其实就是向WindowManagerService注册Window的格式/类型/尺寸等大小,然后向SurfaceFlinger申请图形缓存Layer,Layer中会有创建好的GraphicBuffer,和用于提交图形的producer对象,消费图形数据的consumer对象。
- 图中重要的几点:
- ViewRootImpl创建的时候,会创建一个Surface,此时这个Surface对象是空的;
- Surface的对象填充是在requestLayout之后,底层会返回Native Surface的地址,并通过1中创建的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的一个封装。
//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。
//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;
}
参考:
Android BufferQueue生产消费原理概述
Surface 和 Layer是一一对应的, Surface属于图形生产者(Producer),Layer属于图形消费者(Consumer)。
App通过Surface提交的图形数据,通过enqueueBuffer之后,SurfaceFlinger会通过Layer获取到图形缓冲数据,最终渲染提交到屏幕做显示。
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
]
综合两张图可以大致的看下从addView开始到Surface创建、申请Buffer、填充Buffer、绘制到体提交Buffer的整体流程:
从软件层面上看,Android的Graphic框架主要有几个模块:
Activity、Window、Surface、Layer、Canvas、BufferQueue。
其中:
在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
以上所有的流程个人总结为:
初始化会话链接 -> 添加Window,设置Window信息(显示屏幕、显示大小,格式等等) -> 创建Surface ->
初始化Layer -> 创建BufferQueue -> 申请Buffer -> 填充Buffer -> 提交Buffer -> 消费Buffer(渲染)->显示渲染内容