上一篇介绍了在Vsync到来时, SF首先会处理Layer属性变化, 显示设备变化等情况,然后将mCurrentState提交到了mDrawingState,等待合成处理,然后将遍历所有待处理的Layer,将新Buffer内容更新绑定到Layer纹理对象。经过这些处理流程,决定是否需SF要重新合成图像,如果需要则调用handleMessageRefresh方法合成并刷新。
void SurfaceFlinger::handleMessageRefresh() {
......
//合成预处理工作
preComposition();
//计算和存储每个Layer的脏区域
rebuildLayerStacks();
//创建HWC硬件合成的任务列表
setUpHWComposer();
doDebugFlashRegions();
//先进行GL合成,将合成后的图像放在HWC任务列表的最后为止
//然后有HWC进行合成并输出到屏幕
doComposition();
//合成善后工作
postComposition();
......
}
下面逐个方法的分析下SF合成主要工作内容和逻辑。
preComposition
void SurfaceFlinger::preComposition()
{
bool needExtraInvalidate = false;
//遍历mDrawingState中所有的Layer,调用Layer的onPreComposition方法,来决定是否需要预约下一次Vsync事件
const LayerVector& layers(mDrawingState.layersSortedByZ);
const size_t count = layers.size();
for (size_t i=0 ; ionPreComposition()) {
needExtraInvalidate = true;
}
}
if (needExtraInvalidate) {
signalLayerUpdate();
}
}
bool Layer::onPreComposition() {
mRefreshPending = false;
return mQueuedFrames > 0 || mSidebandStreamChanged;
}
这个方法不是很复杂,就是遍历mDrawingState中所有的Layer,调用Layer的onPreComposition方法,根据onPreComposition,来决定是否需要预约下一次Vsync事件.
如果此时Layer中的mSidebandStreamChanged发生了变化, 或者Layer中仍然有新的待处理的Buffer,此时就需要下次Vsync信号到来的时候再次执行合成过程。
rebuildLayerStacks
在看rebuildLayerStacks方法前先看下computeVisibleRegions方法如何来计算各个显示设备上的脏区域?
void SurfaceFlinger::computeVisibleRegions(
const LayerVector& currentLayers, uint32_t layerStack,
Region& outDirtyRegion, Region& outOpaqueRegion)
{
ATRACE_CALL();
//处于该Layer上层的非透明区域
Region aboveOpaqueLayers;
//
Region aboveCoveredLayers;
//脏区域
Region dirty;
outDirtyRegion.clear();
//layerSortByZ 从列表0位置到列表尾部, Layer存放依次为从底层到最上层
//此处从列表尾部及最上层开始遍历来计算相关的显示区域.
size_t i = currentLayers.size();
while (i--) {
const sp& layer = currentLayers[i];
const Layer::State& s(layer->getDrawingState());
//只计算当前显示设备的Layer
if (s.layerStack != layerStack)
continue;
/*
* opaqueRegion: Layer完全不透明的显示区域
*/
Region opaqueRegion;
/*
* visibleRegion: 屏幕上可见且完全不透明的区域, 该层的不透明区域opaqueRegion - 上层所有不透明区域
* 理论上,被透明区域覆盖的区域仍然属于 visibleRegion
*/
Region visibleRegion;
/*
* coveredRegion: 被上方所有可见区域覆盖的区域, (包括透明区域覆盖的区域)
*/
Region coveredRegion;
/*
* transparentRegion: 完全透明的区域,如果某一个Layer中没有可见切非透明的区域的话,就会被从合成列表中移除(完全透明的Layer没必要做任何合成操作).
*/
Region transparentRegion;
//仅处理所有的属性为可见的Layer,属性为Hidden的Layer没必要处理
if (CC_LIKELY(layer->isVisible())) {
//是否设置了Layer为透明
const bool translucent = !layer->isOpaque(s);
//计算Layer的边界
Rect bounds(s.transform.transform(layer->computeBounds()));
//默认visibleRegion为整个Layer的大小
visibleRegion.set(bounds);
if (!visibleRegion.isEmpty()) {
// visibleRegion中需要移除透明区域
if (translucent) {
const Transform tr(s.transform);
if (tr.transformed()) {
if (tr.preserveRects()) {
// transform the transparent region
transparentRegion = tr.transform(s.activeTransparentRegion);
} else {
// transformation too complex, can't do the
// transparent region optimization.
transparentRegion.clear();
}
} else {
transparentRegion = s.activeTransparentRegion;
}
}
// 计算非透明区域
const int32_t layerOrientation = s.transform.getOrientation();
if (s.alpha==255 && !translucent &&
((layerOrientation & Transform::ROT_INVALID) == false)) {
// the opaque region is the layer's footprint
opaqueRegion = visibleRegion;
}
}
}
// aboveCoveredLayers(存放了上层所有层的visibleRegion)和visibleRegion的交集就是被覆盖区域
coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
//将Layer自身的visibleRegion也添加到aboveCoveredLayers中, 方便下层Layer计算覆盖区域
aboveCoveredLayers.orSelf(visibleRegion);
// VisbleRegion需要减去上层所有的非透明区域
visibleRegion.subtractSelf(aboveOpaqueLayers);
// 如果Layer中的内容被修改了,需要显示将旧的VisibleRegion也进行刷新
if (layer->contentDirty) {
// we need to invalidate the whole region
dirty = visibleRegion;
// as well, as the old visible region
dirty.orSelf(layer->visibleRegion);
layer->contentDirty = false;
} else {
/* 计算暴露区域的变化:
* 1) 原先被覆盖的区域变成可见了
* 2) 现在暴露区域减去原先的暴露区域
*/
const Region newExposed = visibleRegion - coveredRegion;
const Region oldVisibleRegion = layer->visibleRegion;
const Region oldCoveredRegion = layer->coveredRegion;
const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
}
//脏区域需要减去被覆盖的部分
dirty.subtractSelf(aboveOpaqueLayers);
// 累加所有Layer的脏区域
outDirtyRegion.orSelf(dirty);
// 将当前Layer的不透明区域添加到 aboveOpaqueLayers
aboveOpaqueLayers.orSelf(opaqueRegion);
// 保存计算出的region到Layer中
layer->setVisibleRegion(visibleRegion);
layer->setCoveredRegion(coveredRegion);
layer->setVisibleNonTransparentRegion(
visibleRegion.subtract(transparentRegion));
}
outOpaqueRegion = aboveOpaqueLayers;
}
首先介绍下SF中一些区域相关的概念:
opaqueRegion Layer完全不透明的显示区域
visibleRegion: 屏幕上可见且完全不透明的区域, 该层的不透明区域opaqueRegion - 上层所有不透明区域,理论上,被透明区域覆盖的区域仍然属于 visibleRegion
coveredRegion: 被上方所有可见区域覆盖的区域, (包括透明区域覆盖的区域)
transparentRegion: 完全透明的区域,如果某一个Layer中没有可见切非透明的区域的话,就会被从合成列表中移除(完全透明的Layer没必要做任何合成操作).
aboveOpaqueLayers : 当前Layer上层所有Layer不透明区域的累加
aboveCoveredLayers : 当前Layer上层所有Layer可见区域的累加
computeVisibleRegions方法做了什么工作呢?
1: 从Layer Z轴最上层开始遍历该显示设备中所有的Layer
2: 计算该Layer的被覆盖区域 coveredRegion = aboveCoveredLayers(上层所有Layer的显示区域) 和 当前Layer除去非透明区域部分 的交集
3: 将 当前Layer除去非透明区域部分 添加到aboveCoveredLayers中,为下一层Layer计算提供条件
4: 计算当前Layer的可见区域 VisibleRegion = 当前Layer除去非透明区域部分 - aboveOpaqueLayers(上层所有非透明区域)
5: 计算脏区域, 脏区域需要减去被遮盖的部分,并将当前Layer的脏区域累加到当前显示设备的脏区域outDirtyRegion
6: 保存计算的Region到Layer中
//重新构建每个显示设备的Layer Statck
void SurfaceFlinger::rebuildLayerStacks() {
//mVisibleRegionsDirty表示Visible相关的显示区域是否发生变化,如果发生变化则需要重新构造LayerStack
if (CC_UNLIKELY(mVisibleRegionsDirty)) {
ATRACE_CALL();
//处理后将mVisibleRegionsDirty设置为false
mVisibleRegionsDirty = false;
invalidateHwcGeometry();
//遍历所有显示设备,根据显示设备来计算该显示设备中dirtyRegion(变化区域)和opaqueRegion(非透明区域)
const LayerVector& layers(mDrawingState.layersSortedByZ);
for (size_t dpy=0 ; dpy > layersSortedByZ;
const sp& hw(mDisplays[dpy]);
const Transform& tr(hw->getTransform());
const Rect bounds(hw->getBounds());
if (hw->isDisplayOn()) {
//遍历该显示设备上所有的Layer并计算, 得出变化区域和非透明区域
SurfaceFlinger::computeVisibleRegions(layers,
hw->getLayerStack(), dirtyRegion, opaqueRegion);
const size_t count = layers.size();
for (size_t i=0 ; i& layer(layers[i]);
const Layer::State& s(layer->getDrawingState());
if (s.layerStack == hw->getLayerStack()) {
//获取当前Layer的非透明的可见区域,和显示设备边界比较,时候和显示设备有交集,有的话则需要显示,将它放入layersSortedByZ列表中.
Region drawRegion(tr.transform(
layer->visibleNonTransparentRegion));
drawRegion.andSelf(bounds);
if (!drawRegion.isEmpty()) {
layersSortedByZ.add(layer);
}
}
}
}
//将要绘制的Layer存放到一样display的VisibleLayersSortedByZ中等待合成处理。
hw->setVisibleLayersSortedByZ(layersSortedByZ);
hw->undefinedRegion.set(bounds);
hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
hw->dirtyRegion.orSelf(dirtyRegion);
}
}
}
rebuildLayerStacks在合成方法中主要作用是存储待显示的Layer及该显示设备的脏区域.
Android支持多个屏幕,每个屏幕的显示数据并不是完全一样的,每个Display是分开合成的;也就是说,layersSortedByZ中的layer需要根据显示屏的特性,分别进行合成,合成后的数据,送给各自的显示屏。
rebuildLayerStacks会遍历所有Layer计算Layer的脏区域, 然后和当前的显示设备进行比较,看Layer的脏区域是否在显示设备的显示区域内,如果在显示区域内的话说明该layer是需要绘制的,则更新到显示设备的VisibleLayersSortedByZ列表中,等待被合成.
setUpHWComposer
SurfaceFlinger合成图像的时候会调用setHWComposer函数,来设置HWComposer硬件合成相关的参数
//创建HWComposer任务列表,并初始化基本的属性信息
HWComposer& hwc(getHwComposer());
if (hwc.initCheck() == NO_ERROR) {
// 创建HWC 合成的工作列表
if (CC_UNLIKELY(mHwWorkListDirty)) {
mHwWorkListDirty = false;
//变量所有的显示设备列表,为每个显示设备都创建工作任务列表
for (size_t dpy=0 ; dpy hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
//获取当前显示设备需要显示的Layer列表,存放在VisibleLayersSortedByZ列表中
const Vector< sp >& currentLayers(
hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
//调用HWComposer的createWorkList创建工作列表,指定显示设备ID和Layer数量
if (hwc.createWorkList(id, count) == NO_ERROR) {
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
for (size_t i=0 ; cur!=end && i& layer(currentLayers[i]);
//遍历通过SurfaceFlinger的Layer设置HWC Layer的混合模式,裁剪区域等属性
layer->setGeometry(hw, *cur);
if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) {
cur->setSkip(true);
}
}
}
}
}
}
// 为HWComposer的每个Layer设置图形数据
// 遍历所有的显示设备,为每个设备的工作列表中的Layer设置数据
for (size_t dpy=0 ; dpy hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
//获取当前显示设备中需要显示的Layer列表
const Vector< sp >& currentLayers(
hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
for (size_t i=0 ; cur!=end && i& layer(currentLayers[i]);
layer->setPerFrameData(hw, *cur);
}
}
}
//调用HWC的prepare,做硬件合成准备
status_t err = hwc.prepare();
ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
SF设置HWComposer的顺序如下:
1:调用HWComposer的createWorkList创建合成任务列表
2:遍历所有的Layer为HWComposer的Layer设置图形数据
3:调用HWComposer的prepare做合成准备
doComposition
void SurfaceFlinger::doComposition() {
ATRACE_CALL();
const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
for (size_t dpy=0 ; dpy& hw(mDisplays[dpy]);
if (hw->isDisplayOn()) {
//获取rebuildLayerStacks时计算的当前显示设备的脏区域DirtyRegion,。如果是强制重画,mRepaintEverything为true,那么脏区域就是整个屏幕的大小。
const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
// 主要是对当前的显示设备上的所有不支持硬件合成Layer进行OpenGL合成处理
doDisplayComposition(hw, dirtyRegion);
hw->dirtyRegion.clear();
//flip计数
hw->flip(hw->swapRegion);
hw->swapRegion.clear();
}
hw->compositionComplete();
}
//调用HWC硬件合成并显示
postFramebuffer();
}
doComposition进行合成,获取rebuildLayerStacks时计算的当前显示设备的脏区域DirtyRegion,如果是强制重画,mRepaintEverything为true,那么脏区域就是整个屏幕的大小。然后调用doDisplayComposition对当前设备中需要OpenGL方式合成的Layer进行软件合成。
软件合成之后,统一交由HWC, 由HWC硬件合成并输出到显示屏。
先分析下软件GL合成Layer的过程。
void SurfaceFlinger::doDisplayComposition(const sp& hw,
const Region& inDirtyRegion)
{
// 只有在以下情况下才去真正合成这个Display的图像:
// 1) 需要HWC硬件合成
// 2) 脏区域不为空
bool isHwcDisplay = hw->getHwcDisplayId() >= 0;
if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
return;
}
Region dirtyRegion(inDirtyRegion);
......
//调用doComposeSurfaces进行合成
doComposeSurfaces(hw, dirtyRegion);
}
......
//调用SwapBuffer将软件合成的图像提交到该显示设备对应的FrameBufferSurface
hw->swapBuffers(getHwComposer());
}
合成的操作主要在doComposeSurfaces函数中完成,合成方式,主要有两种,一种是使用软件方式的OpenGL合成;另外一种,用的是HWC硬件进行合成,合成策略也是能用HWC合成的尽量用HWC方式合成,不能用的硬件方式再用软件方式合成,毕竟硬件合成效率要高很多。doComposeSurfaces主要是主要是来处理无法用HWC合成的Layer。
GL方式合成完成以后调用SwapBuffers将合成后的Buffer提交给该显示设备的BufferQueue,最终有FrameBufferSurface进行处理。
bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const Region& dirty)
{
//获取SF的RenderEngine, 主要封装openGL一些操作,这个RenderEngine是SurfaceFlinger初始化的时候创建的
RenderEngine& engine(getRenderEngine());
const int32_t id = hw->getHwcDisplayId();
HWComposer& hwc(getHwComposer());
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
bool hasGlesComposition = hwc.hasGlesComposition(id);
if (hasGlesComposition) {
//调用DisplayDevice的makeCurrent设置当前openGL的上下文为当前显示设备的上下
//文,包括当前显示设备的ANativeWindow,后续该设备的Layer使用openGL软件合
//成绘制最终都会绘制到当前显示设备的ANativeWindow中去, 调用swapBuffer的时候
//提交给该显示设备的BufferQueue。
if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {
ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
hw->getDisplayName().string());
eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if(!getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext)) {
ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
}
return false;
}
// Never touch the framebuffer if we don't have any framebuffer layers
const bool hasHwcComposition = hwc.hasHwcComposition(id);
if (hasHwcComposition) {
// when using overlays, we assume a fully transparent framebuffer
// NOTE: we could reduce how much we need to clear, for instance
// remove where there are opaque FB layers. however, on some
// GPUs doing a "clean slate" clear might be more efficient.
// We'll revisit later if needed.
engine.clearWithColor(0, 0, 0, 0);
} else {
// we start with the whole screen area
const Region bounds(hw->getBounds());
// we remove the scissor part
// we're left with the letterbox region
// (common case is that letterbox ends-up being empty)
const Region letterbox(bounds.subtract(hw->getScissor()));
// compute the area to clear
Region region(hw->undefinedRegion.merge(letterbox));
// but limit it to the dirty region
region.andSelf(dirty);
// screen is already cleared here
if (!region.isEmpty()) {
// can happen with SurfaceView
drawWormhole(hw, region);
}
}
if (hw->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
// just to be on the safe side, we don't set the
// scissor on the main display. It should never be needed
// anyways (though in theory it could since the API allows it).
const Rect& bounds(hw->getBounds());
const Rect& scissor(hw->getScissor());
if (scissor != bounds) {
// scissor doesn't match the screen's dimensions, so we
// need to clear everything outside of it and enable
// the GL scissor so we don't draw anything where we shouldn't
// enable scissor for this frame
const uint32_t height = hw->getHeight();
engine.setScissor(scissor.left, height - scissor.bottom,
scissor.getWidth(), scissor.getHeight());
}
}
}
第一步分,主要设置openGL相关的信息,以方便后续使用openGL进行合成,因为Layer是根据显示设备来进行合成的,不同的显示设备的Layer分别合成,所以在进行当前显示设备的Layer合成的时候首先会设置当前显示设备的上下文,每个显示设备DisplayDevice在初始化创建的时候都会创建一个自己显示设备的ANativeWindow,用来作为当前显示设备的画布,这个以前分析过,后续该设备所有使用OpenGL合成的Layer最终会合成并绘制到该Window上去,ANativeWindow的具体实现是在Surface中,也就是生产者,这一帧合成绘制完成后提交到BufferQueue,由该显示设备的消费这FrameBufferSurface接收处理,RenderEngine封装了SF openGL相关的信息和操作.对于非主屏还要设置其裁剪区.
/*
* and then, render the layers targeted at the framebuffer
*/
const Vector< sp >& layers(hw->getVisibleLayersSortedByZ());
const size_t count = layers.size();
const Transform& tr = hw->getTransform();
if (cur != end) {
// 遍历所有的Layer,根据该Layer的类型,如果需要GL合成,则调用该Layer的draw方法
for (size_t i=0 ; i& layer(layers[i]);
const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
if (!clip.isEmpty()) {
switch (cur->getCompositionType()) {
case HWC_CURSOR_OVERLAY:
case HWC_OVERLAY: {
const Layer::State& state(layer->getDrawingState());
if ((cur->getHints() & HWC_HINT_CLEAR_FB)
&& i
&& layer->isOpaque(state) && (state.alpha == 0xFF)
&& hasGlesComposition) {
// 如果该Layer使用硬件合成,需要做一些清理工作
layer->clearWithOpenGL(hw, clip);
}
break;
}
case HWC_FRAMEBUFFER: {
//使用软件合成的话,则需要调用Layer的draw方法进行OpenGL绘制
layer->draw(hw, clip);
break;
}
case HWC_FRAMEBUFFER_TARGET: {
//在分析HWComposer的时候知道,HWC中最后一个Layer是HWC硬件合成的输出
//Layer,必须使用GL合成,所有这个Layer调用draw方法进行openGL绘制
//如果这个Layer是HWC_FRAMEBUFFER_TARGET类型,是openGL软件最终
//输出的Layer, 则无需处理
ALOGW("HWC_FRAMEBUFFER_TARGET found in hwc list (index=%zu)", i);
break;
}
}
}
layer->setAcquireFence(hw, *cur);
}
} else {
// 如果该显示设备上只有一个Layer, 直接用OpenGL合成就可以了,无需使用HWC硬件合成
for (size_t i=0 ; i& layer(layers[i]);
const Region clip(dirty.intersect(
tr.transform(layer->visibleRegion)));
if (!clip.isEmpty()) {
layer->draw(hw, clip);
}
}
}
return true;
}
第二部分:主要是作用是渲染那些需要使用OpenGL合成的Layer, 将会调用Layer的draw方法使用openGL绘制该Layer对应的Texture纹理,最终这些Layer的纹理将会合成输出到RenderEngine创建的ANativeWindow中。
有哪些Layer需要openGL方式来合成呢?
1:显示设备只有一个Layer的时候直接使用GL软件方式合成
2:合成类型是HWC_FRAMEBUFFER的Layer使用GL软件方式合成
如果HWC_FRAMEBUFFER_TARGET类型,则不需要处理, 在分析HWComposer的时候了解过, workList最后一个Layer是给openGL最终合成的图像来准备的,这些Layer在软件GL合成的最终会存放到HWC workList的最后一个Layer中。
那是什么时候放入的呢?接着看DisplayDevice的swapBuffers函数.
软件合成的图像最终输出
void DisplayDevice::swapBuffers(HWComposer& hwc) const {
// 只有以下几种情况下才会调用eglSwapBuffers输出到FrameBufferSurface
// (1) 没有HWC硬件设备
// (2) 有部分Layer需要软件GLES方式合成
// (a) 需要输出的FrameBuffer Target
// (b) 这个是虚拟显示设备
if (hwc.initCheck() != NO_ERROR ||
(hwc.hasGlesComposition(mHwcDisplayId) &&
(hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
//调用EGL,提交到对应的BufferQueue队列
EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
......
}
}
swapBuffers直接将上一步中GLES合成到ANativeWindow中的图像提交到了BufferQueue队列,等待FrameBufferSurface消费者进行处理。
void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
sp buf;
sp acquireFence;
//从BufferQueue队列中获取新的Buffer, 不再详细分析
status_t err = nextBuffer(buf, acquireFence);
//调用HWC的fbPost来输出Buffer
err = mHwc.fbPost(mDisplayType, acquireFence, buf);
}
DisplayDevice提交Buffer之后,FrameBufferSurface会接收到onFrameAvailable函数通知,然后调用nextBuffer从BufferQueue获取新的待处理的Buffer。使用fbPost来输出。
int HWComposer::fbPost(int32_t id,
const sp& acquireFence, const sp& buffer) {
//如果有HWC硬件设备,则调用setFramebufferTarget将GL合成的图像放到workList最后一个Layer中
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
return setFramebufferTarget(id, acquireFence, buffer);
} else {
//没有HWC硬件,则直接调用Gralloc模块的mFbDev的post函数,将图像设置到FrameBuffer显存,进行显示。
acquireFence->waitForever("HWComposer::fbPost");
return mFbDev->post(mFbDev, buffer->handle);
}
}
我们设备目前是有HWC硬件设备的,此时只需要调用setFramebufferTarget将GL合成的图像放到workList最后一个Layer中。可以用硬件合成的Layer硬件放在了workList列表中,不能用硬件合成的Layer 现在也已经使用GL软件合成后放到了workList列表最后一个Layer中,所有待使用硬件合成的数据都已经准备好,放到了硬件合成工作列表workList中,只需最后一步硬件合成并显示了。
硬件合成并显示
硬件合成并显示是由postFramebuffer函数实现的.
void SurfaceFlinger::postFramebuffer()
{
......
HWComposer& hwc(getHwComposer());
if (hwc.initCheck() == NO_ERROR) {
if (!hwc.supportsFramebufferTarget()) {
// EGL spec says:
// "surface must be bound to the calling thread's current context,
// for the current rendering API."
getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
}
//调用HWC的commit函数来提交合成任务
hwc.commit();
}
......
}
status_t HWComposer::commit() {
......
err = mHwc->set(mHwc, mNumDisplays, mLists);
}
postFramebuffer最终调用了HWComposer的commit, 而commit则调用了HWC的set函数提交了硬件合成任务给HWC驱动. HWC会实现Layer的合成,并最终将合成后的图像显示到屏幕上。
void SurfaceFlinger::postComposition()
{
//调用Layer的onPostComposition, 处理Layer中刚刚绘制的Buffer的Fence
//此时才会真正释放掉一个Buffer
const LayerVector& layers(mDrawingState.layersSortedByZ);
const size_t count = layers.size();
for (size_t i=0 ; ionPostComposition();
}
//平常我们用的Vsync都是mPrimaryDispSync分发出来的,并不是每一次都是从底层
//硬件上报的,所以mPrimaryDispSync需要和底层的硬件Vsync保持同步
//如果和硬件Vsync不同步的话则需要重新打开硬件Vsync,有DispSync重新采样计算模型
const HWComposer& hwc = getHwComposer();
sp presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
if (presentFence->isValid()) {
if (mPrimaryDispSync.addPresentFence(presentFence)) {
enableHardwareVsync();
} else {
disableHardwareVsync(false);
}
}
const sp hw(getDefaultDisplayDevice());
if (kIgnorePresentFences) {
if (hw->isDisplayOn()) {
enableHardwareVsync();
}
}
//处理动画合成的逻辑
if (mAnimCompositionPending) {
mAnimCompositionPending = false;
if (presentFence->isValid()) {
mAnimFrameTracker.setActualPresentFence(presentFence);
} else {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
mAnimFrameTracker.setActualPresentTime(presentTime);
}
mAnimFrameTracker.advanceFrame();
}
}
postComposition主要做一些合成的善后处理工作. 有一个关键的部分就是Vsync的处理,每次合成后会对软件Vsync做一次校验,平常我们用的Vsync都是mPrimaryDispSync分发出来的,并不是每一次都是从底层硬件上报的,所以mPrimaryDispSync需要和底层的硬件Vsync保持同步,如果和硬件Vsync不同步的话则需要重新打开硬件Vsync,由DispSync重新采样计算软件 Vsync模型。
到此为止, SurfaceFlinger的图像合成就简单分析完了。