首先看一下总体函数
void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
preComposition();
rebuildLayerStacks();
setUpHWComposer();
doDebugFlashRegions();
doComposition();
postComposition(refreshStartTime);
}
我们详细的一一分析
第一个函数preComposition()
void SurfaceFlinger::preComposition()
{
bool needExtraInvalidate = false;
const LayerVector& layers(mDrawingState.layersSortedByZ);
const size_t count = layers.size();
for (size_t i=0 ; i<count ; i++) {
if (layers[i]->onPreComposition()) {
needExtraInvalidate = true;
}
}
if (needExtraInvalidate) {
signalLayerUpdate();
}
}
这个函数就是遍历mDrawingState中的每个layer,然后执行layers[i]->onPreComposition(),如果onPreComposition()返回为真则设置needExtraInvalidate = true,最终如果needExtraInvalidate == true 则请求下一个vsync.
好我们来看下 Layer::onPreComposition()干了什么
bool Layer::onPreComposition() {
mRefreshPending = false;
return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
}
其实很简单,就是判断还有没有需要未处理的数据,如果有就返回true,这三个条件我们已经看到过很多次了就不解释了.
第二个函数 SurfaceFlinger::rebuildLayerStacks()
void SurfaceFlinger::rebuildLayerStacks() {
// rebuild the visible layer list per screen
if (CC_UNLIKELY(mVisibleRegionsDirty)) {
ATRACE_CALL();
mVisibleRegionsDirty = false;
invalidateHwcGeometry();
const LayerVector& layers(mDrawingState.layersSortedByZ);
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
Region opaqueRegion;
Region dirtyRegion;
Vector< sp<Layer> > layersSortedByZ;
const sp<DisplayDevice>& hw(mDisplays[dpy]);
const Transform& tr(hw->getTransform());
const Rect bounds(hw->getBounds());
if (hw->isDisplayOn()) {
SurfaceFlinger::computeVisibleRegions(layers,
hw->getLayerStack(), dirtyRegion, opaqueRegion);
const size_t count = layers.size();
for (size_t i=0 ; i<count ; i++) {
const sp<Layer>& layer(layers[i]);
const Layer::State& s(layer->getDrawingState());
if (s.layerStack == hw->getLayerStack()) {
Region drawRegion(tr.transform(
layer->visibleNonTransparentRegion));
drawRegion.andSelf(bounds);
if (!drawRegion.isEmpty()) {
layersSortedByZ.add(layer);
}
}
}
}
hw->setVisibleLayersSortedByZ(layersSortedByZ);
hw->undefinedRegion.set(bounds);
hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
hw->dirtyRegion.orSelf(dirtyRegion);
}
}
}
在上一篇文章我们看了很多状态的变化都会导致可见区域的变化(一般都是窗口大小,增加减少才会引起).
这里总结一下引起可见区域变化的原因:
1 视频边带数据变化
2 大小发生变化
3 透明区域变化
4 裁剪发生变化
5 layer的第一个buffer
6 不透明度发生变化
7 关屏亮屏
8 display发生变化
9 layer数量发生变化和数量没有便但是有增加或者减少
10 layerStack变化
等等
有这么多情况引起可见区域变化,但是发生这种情况还是比较少的,相比于不发生变化的情况还是少很多的,所以这里使用CC_UNLIKELY去修饰条件,告诉编译器可以优化
所以当可见区域发生变化的时候这个函数就用于处理可见区域的变化.进入条件后首先设置mVisibleRegionsDirty = false复位变量.然后调用invalidateHwcGeometry()函数,设置mHwWorkListDirty变量为true,用于请求重建hwc的layer_list.后面才可是真正的处理可见区域的变化(之处理那些还亮屏的设备).
后面这半段还是很有意思的,主要就是计算各个layer的透明部分,脏部分,和不透明,半透明部分.
函数9-38行有两层循环第一层遍历Display,第二层遍历layer,我们只看一个Display的处理,首先opaqueRegion和dirtyRegion是作为传出传入参数,用于记录按照layer的z轴从上到下计算出的不透明区域和脏区域(注意不透明区域遮挡下面的layer相同的区域),每次计算每个layer的可见区域的时候要把这两部分区域传入到下一个layer区域的计算中去,用于计算下一个layer的可见区域,另外计算完成下一个layer的根据还要更新这这两个总体的opaqueRegion和dirtyRegion,之后在传递给更底层的layer. 关于Region的说明请参考Android Region代码分析 这篇文章写的很详细,这里就不多解释了.
首先获取应用在该Display上面的Transform,有关Transform请参考我的另一篇文章Surfaceflinger(3):变换,代码15行获取Bound,也就是屏幕的大小.
17-18行是关键代码,我们进入函数重点分析
void SurfaceFlinger::computeVisibleRegions(
const LayerVector& currentLayers, uint32_t layerStack,
Region& outDirtyRegion, Region& outOpaqueRegion)
{
ATRACE_CALL();
Region aboveOpaqueLayers;
Region aboveCoveredLayers;
Region dirty;
outDirtyRegion.clear();
size_t i = currentLayers.size();
while (i--) {
const sp<Layer>& layer = currentLayers[i];
// start with the whole surface at its current location
const Layer::State& s(layer->getDrawingState());
// only consider the layers on the given layer stack
if (s.layerStack != layerStack)
continue;
/*
* opaqueRegion: area of a surface that is fully opaque.
*/
Region opaqueRegion;
/*
* visibleRegion: area of a surface that is visible on screen
* and not fully transparent. This is essentially the layer's
* footprint minus the opaque regions above it.
* Areas covered by a translucent surface are considered visible.
*/
Region visibleRegion;
/*
* coveredRegion: area of a surface that is covered by all
* visible regions above it (which includes the translucent areas).
*/
Region coveredRegion;
/*
* transparentRegion: area of a surface that is hinted to be completely
* transparent. This is only used to tell when the layer has no visible
* non-transparent regions and can be removed from the layer list. It
* does not affect the visibleRegion of this layer or any layers
* beneath it. The hint may not be correct if apps don't respect the
* SurfaceView restrictions (which, sadly, some don't).
*/
Region transparentRegion;
// handle hidden surfaces by setting the visible region to empty
if (CC_LIKELY(layer->isVisible())) {
const bool translucent = !layer->isOpaque(s);
Rect bounds(s.active.transform.transform(layer->computeBounds()));
visibleRegion.set(bounds);
if (!visibleRegion.isEmpty()) {
// Remove the transparent area from the visible region
if (translucent) {
const Transform tr(s.active.transform);
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();
}
}
// compute the opaque region
const int32_t layerOrientation = s.active.transform.getOrientation();
if (s.alpha==255 && !translucent &&
((layerOrientation & Transform::ROT_INVALID) == false)) {
// the opaque region is the layer's footprint
opaqueRegion = visibleRegion;
}
}
}
// Clip the covered region to the visible region
coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
// Update aboveCoveredLayers for next (lower) layer
aboveCoveredLayers.orSelf(visibleRegion);
// subtract the opaque region covered by the layers above us
visibleRegion.subtractSelf(aboveOpaqueLayers);
// compute this layer's dirty region
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 {
/* compute the exposed region:
* the exposed region consists of two components:
* 1) what's VISIBLE now and was COVERED before
* 2) what's EXPOSED now less what was EXPOSED before
*
* note that (1) is conservative, we start with the whole
* visible region but only keep what used to be covered by
* something -- which mean it may have been exposed.
*
* (2) handles areas that were not covered by anything but got
* exposed because of a resize.
*/
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);
// accumulate to the screen dirty region
outDirtyRegion.orSelf(dirty);
// Update aboveOpaqueLayers for next (lower) layer
aboveOpaqueLayers.orSelf(opaqueRegion);
// Store the visible region in screen space
layer->setVisibleRegion(visibleRegion);
layer->setCoveredRegion(coveredRegion);
layer->setVisibleNonTransparentRegion(
visibleRegion.subtract(transparentRegion));
}
outOpaqueRegion = aboveOpaqueLayers;
}
首先先介绍下代码出现的各个区域变量的含义
Region aboveOpaqueLayers; 代表不透明区域,由于从上向下遍历layer,所以不透明区域会遮挡下层layer
Region aboveCoveredLayers; 覆盖区域:由于可见区域会遮盖下层(遮盖下层不代表下层不可见,当遮盖区域为半透明的时候下层是可见的),遮盖区域只是用于计算dirtyRegion(如果上次计算的遮盖区域与这一次计算的不一样,那么就可以利用这次的遮盖区域与上次的遮盖区域计算出变化的区域,我们一会详细用代码解释).
Region dirty:每个layer的变化区域 ,完全可以拿到while区域
在while循环中的本地变量:
Region opaqueRegion; 本次循环的不可见区域,用于存入全局不可见区域
Region visibleRegion:本次循环的layer可见区域
Region coveredRegion:可见区域被覆盖的区域(有可能被不透明部分遮盖,也有可能被半透明区域遮盖)
Region transparentRegion: 透明区域
55行-81行代码首先确定layer的可见区域,然后对可见区域进行变换,在确定可见区域是半透明还是不透明的,如果是不透明的就将可见区域赋值给opaqueRegion,半透明的就用transparentRegion保存.
84行计算出被遮盖的区域
87行计算出新的遮盖区域
90行计算出不被遮挡的区域
93-117行分为两种情况分析:
第一种 93-98 如果内容发生了变化,则整个可见区域都是dirty区域,重新渲染合成
第二种 100-117行 如果可见区域内容没有发生变化只是遮挡部分和裸漏部分发生变化,只把新遮挡的部分和新裸漏的部分作为dirty区域
118-124行更新各个区域
126-130 设置layer的可见区域,遮挡区域和可见不透明区域
最后设置aboveOpaqueLayers区域,最终传出参数outOpaqueRegion和不透outDirtyRegion都设置了.
其实函数还是比较简单的,较难理解的就是region的概念
回到void SurfaceFlinger::rebuildLayerStacks()函数中:
21-31行,有根据Display的变换属性对各个layer的可见不透明区域进行变换,然后与上屏幕的边界,如果变换后的区域不为null,说明真的有东西要更新,就把这样的layer放到layersSortedByZ容器中.
最后34-38行分别设置了这个Display的三个变量,分别是: 设备上发生变化的layer集合,透明或者半透明区域,和脏区域,注意这里38行要orSelf dirtyRegion是因为还要在其他地方设置这个变量,在一次绘制完成后清除该变量
到这里rebuildLayerStacks()就分析完成了
接下来就是setUpHWComposer()函数,函数比较长我们分段阅读
void SurfaceFlinger::setUpHWComposer() {
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty();
bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0;
bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers;
// If nothing has changed (!dirty), don't recompose.
// If something changed, but we don't currently have any visible layers,
// and didn't when we last did a composition, then skip it this time.
// The second rule does two things:
// - When all layers are removed from a display, we'll emit one black
// frame, then nothing more until we get new layers.
// - When a display is created with a private layer stack, we won't
// emit any black frames until a layer is added to the layer stack.
bool mustRecompose = dirty && !(empty && wasEmpty);
ALOGV_IF(mDisplays[dpy]->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL,
"dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy,
mustRecompose ? "doing" : "skipping",
dirty ? "+" : "-",
empty ? "+" : "-",
wasEmpty ? "+" : "-");
mDisplays[dpy]->beginFrame(mustRecompose);
if (mustRecompose) {
mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty;
}
}
这一段逻辑很简单,就是判断是否有必要重新合成屏幕区域,有连个条件,一个是变脏,另一个是内容有无的变化,满足其一就要重新合成,并且最主要的一步就是调用mDisplays[dpy]->beginFrame(mustRecompose);函数,这个函数在Display管理一文中已经分析,主要用于处理虚拟设备,这里就不再复述.
SurfaceFlinger::setUpHWComposer() 剩下的部分全都是在满足 if (hwc.initCheck() == NO_ERROR) 条件下完成,也就是必须hwc设备没有问题的条件下完成
if (CC_UNLIKELY(mHwWorkListDirty)) {
mHwWorkListDirty = false;
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
const Vector< sp<Layer> >& currentLayers(
hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
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<count ; ++i, ++cur) {
const sp<Layer>& layer(currentLayers[i]);
layer->setGeometry(hw, *cur);
if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) {
cur->setSkip(true);
}
}
}
}
}
}
mHwWorkListDirty在每次事务处理的时候都设置为true,这里用CC_UNLIKELY显然是不合适的.这一段主要的作用就是对每一个Display重建WorkList.我们来具体分析下如何创建worklist以及它的作用.
status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
return BAD_INDEX;
}
if (mHwc) {
DisplayData& disp(mDisplayData[id]);
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// we need space for the HWC_FRAMEBUFFER_TARGET
numLayers++;
}
if (disp.capacity < numLayers || disp.list == NULL) {
size_t size = sizeof(hwc_display_contents_1_t)
+ numLayers * sizeof(hwc_layer_1_t);
free(disp.list);
disp.list = (hwc_display_contents_1_t*)malloc(size);
disp.capacity = numLayers;
}
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));
const DisplayConfig& currentConfig =
disp.configs[disp.currentConfig];
const hwc_rect_t r = { 0, 0,
(int) currentConfig.width, (int) currentConfig.height };
disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
disp.framebufferTarget->hints = 0;
disp.framebufferTarget->flags = 0;
disp.framebufferTarget->handle = disp.fbTargetHandle;
disp.framebufferTarget->transform = 0;
disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
disp.framebufferTarget->sourceCropf.left = 0;
disp.framebufferTarget->sourceCropf.top = 0;
disp.framebufferTarget->sourceCropf.right =
currentConfig.width;
disp.framebufferTarget->sourceCropf.bottom =
currentConfig.height;
} else {
disp.framebufferTarget->sourceCrop = r;
}
disp.framebufferTarget->displayFrame = r;
disp.framebufferTarget->visibleRegionScreen.numRects = 1;
disp.framebufferTarget->visibleRegionScreen.rects =
&disp.framebufferTarget->displayFrame;
disp.framebufferTarget->acquireFenceFd = -1;
disp.framebufferTarget->releaseFenceFd = -1;
disp.framebufferTarget->planeAlpha = 0xFF;
}
disp.list->retireFenceFd = -1;
disp.list->flags = HWC_GEOMETRY_CHANGED;
disp.list->numHwLayers = numLayers;
}
return NO_ERROR;
}
第二行和第六行检查了display id是否存在和hwc是否存在,不满足条件直接返回.
8-10行 如果hwc 1.1以上版本则要多创建一个layer(HWC_FRAMEBUFFER_TARGET),用于Surfaceflinger保存GL ES合成的数据
12-17行 分配worklist容器. 这个分配手段很巧秒,
typedef struct hwc_display_contents_1 { int retireFenceFd;
union {
struct {
hwc_display_t dpy;
hwc_surface_t sur;
};
struct {
buffer_handle_t outbuf;
int outbufAcquireFenceFd;
};
};
uint32_t flags;
size_t numHwLayers;
hwc_layer_1_t hwLayers[0]; } hwc_display_contents_1_t;
虽然hwc_display_contents_1数据结构中hwLayers数组只包含一个元素,但是这里面却分配了大小为numLayers * sizeof(hwc_layer_1_t)的内存,就可以当做numLayers个元素的数组来使用,这就是c语言的强大之处.
19-49行就是填充这多分配的那个HWC_FRAMEBUFFER_TARGET类型的hwc_layer_1_t. 这里把compositionType设置成HWC_FRAMEBUFFER_TARGET类型, 这时候disp.framebufferTarget->handle 设置为 disp.fbTargetHandle有可能是0,因为当前阶段是要询问hwc怎么合成,还没有真正交给hwc去合成.剩下的部分都是这只framebufferTarget的边界信息.
最后50-52行设置disp.list->flags 为HWC_GEOMETRY_CHANGED,表示要求hwc重新计算每个layer用什么方式合成.
这样worklist就创建完成了.
回到SurfaceFlinger::setUpHWComposer()函数,创建完worklist,填充了HWC_FRAMEBUFFER_TARGET对应的layer数据后还要对其他layer信息进行设置,是通过layer->setGeometry(hw, *cur)完成.我们只看hwc1的逻辑
void Layer::setGeometry(
const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface& layer)
{
layer.setDefaultState();
// enable this layer
layer.setSkip(false);
if (isSecure() && !hw->isSecure()) {
layer.setSkip(true);
}
// this gives us only the "orientation" component of the transform
const State& s(getDrawingState());
if (!isOpaque(s) || s.alpha != 0xFF) {
layer.setBlending(mPremultipliedAlpha ?
HWC_BLENDING_PREMULT :
HWC_BLENDING_COVERAGE);
}
// apply the layer's transform, followed by the display's global transform
// here we're guaranteed that the layer's transform preserves rects
Region activeTransparentRegion(s.activeTransparentRegion);
if (!s.crop.isEmpty()) {
Rect activeCrop(s.crop);
activeCrop = s.active.transform.transform(activeCrop);
if(!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
activeCrop.clear();
}
activeCrop = s.active.transform.inverse().transform(activeCrop, true);
// This needs to be here as transform.transform(Rect) computes the
// transformed rect and then takes the bounding box of the result before
// returning. This means
// transform.inverse().transform(transform.transform(Rect)) != Rect
// in which case we need to make sure the final rect is clipped to the
// display bounds.
if(!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) {
activeCrop.clear();
}
// mark regions outside the crop as transparent
activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top));
activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom,
s.active.w, s.active.h));
activeTransparentRegion.orSelf(Rect(0, activeCrop.top,
activeCrop.left, activeCrop.bottom));
activeTransparentRegion.orSelf(Rect(activeCrop.right, activeCrop.top,
s.active.w, activeCrop.bottom));
}
Rect frame(s.active.transform.transform(computeBounds(activeTransparentRegion)));
if (!s.finalCrop.isEmpty()) {
if(!frame.intersect(s.finalCrop, &frame)) {
frame.clear();
}
}
if (!frame.intersect(hw->getViewport(), &frame)) {
frame.clear();
}
const Transform& tr(hw->getTransform());
layer.setFrame(tr.transform(frame));
layer.setCrop(computeCrop(hw));
layer.setPlaneAlpha(s.alpha);
/*
* Transformations are applied in this order:
* 1) buffer orientation/flip/mirror
* 2) state transformation (window manager)
* 3) layer orientation (screen orientation)
* (NOTE: the matrices are multiplied in reverse order)
*/
const Transform bufferOrientation(mCurrentTransform);
Transform transform(tr * s.active.transform * bufferOrientation);
if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
/*
* the code below applies the primary display's inverse transform to the
* buffer
*/
uint32_t invTransform =
DisplayDevice::getPrimaryDisplayOrientationTransform();
// calculate the inverse transform
if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
NATIVE_WINDOW_TRANSFORM_FLIP_H;
}
// and apply to the current transform
transform = Transform(invTransform) * transform;
}
// this gives us only the "orientation" component of the transform
const uint32_t orientation = transform.getOrientation();
if (orientation & Transform::ROT_INVALID) {
// we can only handle simple transformation
layer.setSkip(true);
} else {
layer.setTransform(orientation);
}
}
5行layer.setDefaultState()是把hwc_layer_1_t设置为初始值
virtual void setDefaultState() {
hwc_layer_1_t* const l = getLayer();
l->compositionType = HWC_FRAMEBUFFER;
l->hints = 0;
l->flags = HWC_SKIP_LAYER;
l->handle = 0;
l->transform = 0;
l->blending = HWC_BLENDING_NONE;
l->visibleRegionScreen.numRects = 0;
l->visibleRegionScreen.rects = NULL;
l->acquireFenceFd = -1;
l->releaseFenceFd = -1;
l->planeAlpha = 0xFF;
}
compositionType设置为HWC_FRAMEBUFFER,代表有GLES合成.
hints设置成0,调用hwc->prepare()时由hwc驱动设置该值.
flags设置成HWC_SKIP_LAYER告诉hwc模块不用处理该layer.
handle代表申请的grolloc buffer如果两次调用hwc->prepare handler没有变化,并且没有设置HWC_GEOMETRY_CHANGED标志,则hwc模块会认为layer缓冲区内容没有变化,不会重新计算由谁来合成.
transform buffer变换
blending 混合
visibleRegionScreen 设置可见区域为空的
acquireFenceFd fence相关 会在fence一节进行说明
releaseFenceFd
planeAlpha 用于计算alpha
if (blending == HWC_BLENDING_PREMULT)
* pixel.rgb = pixel.rgb * planeAlpha / 255
pixel.a = pixel.a * planeAlpha / 255
9行调用setSkip去掉layer->flags中的HWC_SKIP_LAYER位.
10-13行对于那些不想被虚拟显示设备抓取的layer设置layer->flags中的HWC_SKIP_LAYER位
15-20 设置混合模式 (可以参考opengl 红宝书4.5.6节)
ONE_MINUS_SRC_ALPHA:表示用1.0减去源颜色的alpha值来作为因子
HWC_BLENDING_COVERAGE:表示直接覆盖(并不是真正的融混)
24-61行对各个layer进行裁剪变换最终计算出layer->displayFrame用于表示要重新合成的区域,以及裁剪区域layer->sourceCrop 在分析裁剪变换一章中详细分析这个过程.最后设置了PlaneAlpha.
63-97都是对变换的处理,也在分析裁剪变换一章中详细分析.
到这里hwc创建worklist就完成了,到这里还没有给hwc的layer设置buffer.回到SurfaceFlinger::setUpHWComposer() 函数中后面一段正式做这件事情的.
// set the per-frame data
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
const Vector< sp<Layer> >& 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<count ; ++i, ++cur) {
/*
* update the per-frame h/w composer data for each layer
* and build the transparent region of the FB
*/
const sp<Layer>& layer(currentLayers[i]);
layer->setPerFrameData(hw, *cur);
}
}
}
这段主要就是对每个设备上的各个layer执行了setPerFrameData函数
void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface& layer) {
// we have to set the visible region on every frame because
// we currently free it during onLayerDisplayed(), which is called
// after HWComposer::commit() -- every frame.
// Apply this display's projection's viewport to the visible region
// before giving it to the HWC HAL.
const Transform& tr = hw->getTransform();
Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
layer.setVisibleRegionScreen(visible);
layer.setSurfaceDamage(surfaceDamageRegion);
mIsGlesComposition = (layer.getCompositionType() == HWC_FRAMEBUFFER);
if (mSidebandStream.get()) {
layer.setSidebandStream(mSidebandStream);
} else {
// NOTE: buffer can be NULL if the client never drew into this
// layer yet, or if we ran out of memory
layer.setBuffer(mActiveBuffer);
}
}
这个函数设置了视频边拼带,buffer handler和可见区域.
再次回到SurfaceFlinger::setUpHWComposer()函数
// If possible, attempt to use the cursor overlay on each display.
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
const Vector< sp<Layer> >& 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<count ; ++i, ++cur) {
const sp<Layer>& layer(currentLayers[i]);
if (layer->isPotentialCursor()) {
cur->setIsCursorLayerHint();
break;
}
}
}
}
这个for循环是对cursorlayer的处理,主题就是调用setIsCursorLayerHint函数设置HWC_IS_CURSOR_LAYER的flags位,函数很简单就不做说明
virtual void setIsCursorLayerHint(bool isCursor) {
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
if (isCursor) {
getLayer()->flags |= HWC_IS_CURSOR_LAYER;
}
else {
getLayer()->flags &= ~HWC_IS_CURSOR_LAYER;
}
}
}
回到SurfaceFlinger::setUpHWComposer()函数
接下来就是最关键且不起眼的一个函数调用status_t err = hwc.prepare(); 询问hwc设备如何合status_t
HWComposer::prepare() {
Mutex::Autolock _l(mDisplayLock);
for (size_t i=0 ; i<mNumDisplays ; i++) {
DisplayData& disp(mDisplayData[i]);
if (disp.framebufferTarget) {
// make sure to reset the type to HWC_FRAMEBUFFER_TARGET
// DO NOT reset the handle field to NULL, because it's possible
// that we have nothing to redraw (eg: eglSwapBuffers() not called)
// in which case, we should continue to use the same buffer.
LOG_FATAL_IF(disp.list == NULL);
disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
}
if (!disp.connected && disp.list != NULL) {
ALOGW("WARNING: disp %zu: connected, non-null list, layers=%zu",
i, disp.list->numHwLayers);
}
mLists[i] = disp.list;
if (mLists[i]) {
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
mLists[i]->outbuf = disp.outbufHandle;
mLists[i]->outbufAcquireFenceFd = -1;
} else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// garbage data to catch improper use
mLists[i]->dpy = (hwc_display_t)0xDEADBEEF;
mLists[i]->sur = (hwc_surface_t)0xDEADBEEF;
} else {
mLists[i]->dpy = EGL_NO_DISPLAY;
mLists[i]->sur = EGL_NO_SURFACE;
}
}
}
int err = mHwc->prepare(mHwc, mNumDisplays, mLists);
ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));
if (err == NO_ERROR) {
// here we're just making sure that "skip" layers are set
// to HWC_FRAMEBUFFER and we're also counting how many layers
// we have of each type.
//
// If there are no window layers, we treat the display has having FB
// composition, because SurfaceFlinger will use GLES to draw the
// wormhole region.
for (size_t i=0 ; i<mNumDisplays ; i++) {
DisplayData& disp(mDisplayData[i]);
disp.hasFbComp = false;
disp.hasOvComp = false;
if (disp.list) {
for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
hwc_layer_1_t& l = disp.list->hwLayers[i];
//ALOGD("prepare: %d, type=%d, handle=%p",
// i, l.compositionType, l.handle);
if (l.flags & HWC_SKIP_LAYER) {
l.compositionType = HWC_FRAMEBUFFER;
}
if (l.compositionType == HWC_FRAMEBUFFER) {
disp.hasFbComp = true;
}
if (l.compositionType == HWC_OVERLAY) {
disp.hasOvComp = true;
}
if (l.compositionType == HWC_CURSOR_OVERLAY) {
disp.hasOvComp = true;
}
}
if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
disp.hasFbComp = true;
}
} else {
disp.hasFbComp = true;
}
}
}
return (status_t)err; }
3-31行的for循环只是设置了disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET,
设置了mLists数组的每个元素代表一个display,另外如果hwc的version大于1.3表示支持虚拟设备,则会设置一个 disp.outbufHandle用于接收输出数据,只有虚拟缓冲区设置这个buffer. 另外比较有意思的是对于hwc版本大于1.1小于1.3的情况会设置0xDEADBEEF的值给dpy和sur元素,这个含义是死牛肉,是一个垃圾值用于调试
设置outbuf后跳出for循环33行 mHwc->prepare()函数就是询问hwc设备如何合成的函数,实现在驱动里面,这里就不深入分析,只说明它的作用,函数的注释写的很清楚,如果layer有hwc处理,则hwc会设置layer的compositionType为HWC_OVERLAY或者HWC_CURSOR_OVERLAY, 若由surfaceflinger gles合成则设置compositionType为HWC_FRAMEBUFFER. 另外返回0表示成功,返回负数则所有layer的合成都由gles处理.
36-75行 根据prepare函数返回的结果去设置DisplayData的hasFbComp和hasOvComp变量,用于后面确定是否需要gles和hwc合成.
再次回到SurfaceFlinger::setUpHWComposer()函数,函数的逻辑只差最后一个for循环没有分析
for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
auto& displayDevice = mDisplays[displayId];
if (!displayDevice->isDisplayOn()) {
continue;
}
status_t result = displayDevice->prepareFrame(*mHwc);
ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:"
" %d (%s)", displayId, result, strerror(-result));
}
最后一个for循环,对于开启的display,调用函数displayDevice->prepareFrame(*mHwc) 进行gles和hwc合成
status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const {
DisplaySurface::CompositionType compositionType;
bool haveGles = hwc.hasGlesComposition(mHwcDisplayId);
bool haveHwc = hwc.hasHwcComposition(mHwcDisplayId);
if (haveGles && haveHwc) {
compositionType = DisplaySurface::COMPOSITION_MIXED;
} else if (haveGles) {
compositionType = DisplaySurface::COMPOSITION_GLES;
} else if (haveHwc) {
compositionType = DisplaySurface::COMPOSITION_HWC;
} else {
// Nothing to do -- when turning the screen off we get a frame like
// this. Call it a HWC frame since we won't be doing any GLES work but
// will do a prepare/set cycle.
compositionType = DisplaySurface::COMPOSITION_HWC;
}
return mDisplaySurface->prepareFrame(compositionType);
}
函数根据之前prepare询问的结果计算出当前要合成的类型compositionType,有三种类型,
COMPOSITION_MIXED代表这个设备上既有hwc合成的layer,也有需要gles合成的layer.
COMPOSITION_GLES 代表所有的layer都由gles合成
COMPOSITION_HWC: 代表由完全由hwc硬件合成
到mDisplaySurface->prepareFrame这里,函数有开叉了,分为虚拟设备和物理设备两种情况,我们先分析物理设备的情况FramebufferSurface
status_t FramebufferSurface::prepareFrame(CompositionType /*compositionType*/) {
return NO_ERROR;
}
什么都没有做.
虚拟设备的实现如下
status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) {
if (mDisplayId < 0)
return NO_ERROR;
VDS_LOGW_IF(mDbgState != DBG_STATE_BEGUN,
"Unexpected prepareFrame() in %s state", dbgStateStr());
mDbgState = DBG_STATE_PREPARED;
mCompositionType = compositionType;
if (sForceHwcCopy && mCompositionType == COMPOSITION_GLES) {
// Some hardware can do RGB->YUV conversion more efficiently in hardware
// controlled by HWC than in hardware controlled by the video encoder.
// Forcing GLES-composed frames to go through an extra copy by the HWC
// allows the format conversion to happen there, rather than passing RGB
// directly to the consumer.
//
// On the other hand, when the consumer prefers RGB or can consume RGB
// inexpensively, this forces an unnecessary copy.
mCompositionType = COMPOSITION_MIXED;
}
if (mCompositionType != mDbgLastCompositionType) {
VDS_LOGV("prepareFrame: composition type changed to %s",
dbgCompositionTypeStr(mCompositionType));
mDbgLastCompositionType = mCompositionType;
}
if (mCompositionType != COMPOSITION_GLES &&
(mOutputFormat != mDefaultOutputFormat ||
mOutputUsage != GRALLOC_USAGE_HW_COMPOSER)) {
// We must have just switched from GLES-only to MIXED or HWC
// composition. Stop using the format and usage requested by the GLES
// driver; they may be suboptimal when HWC is writing to the output
// buffer. For example, if the output is going to a video encoder, and
// HWC can write directly to YUV, some hardware can skip a
// memory-to-memory RGB-to-YUV conversion step.
//
// If we just switched *to* GLES-only mode, we'll change the
// format/usage and get a new buffer when the GLES driver calls
// dequeueBuffer().
mOutputFormat = mDefaultOutputFormat;
mOutputUsage = GRALLOC_USAGE_HW_COMPOSER;
refreshOutputBuffer();
}
return NO_ERROR;
}
这里如果合成类型从COMPOSITION_GLES变成其他类型并且驱动请求的合适或者用法发生变化,就要重新申请一块buffer,用于输出数据给虚拟设备(如screen recorder).
到这里SurfaceFlinger::setUpHWComposer() 函数也分析完了.
回到void SurfaceFlinger::handleMessageRefresh()函数,后面的doDebugFlashRegions()只是调试作用,这里不分析
直接分析void SurfaceFlinger::doComposition()函数
void SurfaceFlinger::doComposition() {
ATRACE_CALL();
const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
const sp<DisplayDevice>& hw(mDisplays[dpy]);
if (hw->isDisplayOn()) {
// transform the dirty region into this screen's coordinate space
const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
// repaint the framebuffer (if needed)
doDisplayComposition(hw, dirtyRegion);
hw->dirtyRegion.clear();
hw->flip(hw->swapRegion);
hw->swapRegion.clear();
}
// inform the h/w that we're done compositing
hw->compositionComplete();
}
postFramebuffer();
}
首先函数对每个Display执行doDisplayComposition(hw, dirtyRegion);函数用于合成
void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
const Region& inDirtyRegion)
{
// We only need to actually compose the display if:
// 1) It is being handled by hardware composer, which may need this to
// keep its virtual display state machine in sync, or
// 2) There is work to be done (the dirty region isn't empty)
bool isHwcDisplay = hw->getHwcDisplayId() >= 0;
if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
return;
}
Region dirtyRegion(inDirtyRegion);
// compute the invalid region
hw->swapRegion.orSelf(dirtyRegion);
uint32_t flags = hw->getFlags();
if (flags & DisplayDevice::SWAP_RECTANGLE) {
// we can redraw only what's dirty, but since SWAP_RECTANGLE only
// takes a rectangle, we must make sure to update that whole
// rectangle in that case
dirtyRegion.set(hw->swapRegion.bounds());
} else {
if (flags & DisplayDevice::PARTIAL_UPDATES) {
// We need to redraw the rectangle that will be updated
// (pushed to the framebuffer).
// This is needed because PARTIAL_UPDATES only takes one
// rectangle instead of a region (see DisplayDevice::flip())
dirtyRegion.set(hw->swapRegion.bounds());
} else {
// we need to redraw everything (the whole screen)
dirtyRegion.set(hw->bounds());
hw->swapRegion = dirtyRegion;
}
}
if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) {
if (!doComposeSurfaces(hw, dirtyRegion)) return;
} else {
RenderEngine& engine(getRenderEngine());
mat4 colorMatrix = mColorMatrix;
if (mDaltonize) {
colorMatrix = colorMatrix * mDaltonizer();
}
mat4 oldMatrix = engine.setupColorTransform(colorMatrix);
doComposeSurfaces(hw, dirtyRegion);
engine.setupColorTransform(oldMatrix);
}
// update the swap region and clear the dirty region
hw->swapRegion.orSelf(dirtyRegion);
// swap buffers (presentation)
hw->swapBuffers(getHwComposer());
}
这里13-36行根据swapRegion去计算dirtyRegion 到底是做什么的我也没有弄清楚,不过会在变换一章中进行详细分析.
38-40行如果没有设置高杜比和颜色矩阵则直接执行doComposeSurfaces(hw, dirtyRegion)进行合成,否则的话41-49行要先设置color变换模式再执行完成doComposeSurfaces(hw, dirtyRegion).反正二者都要走到doComposeSurfaces(hw, dirtyRegion) 函数,我们先分析doComposeSurfaces(hw, dirtyRegion)函数
bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
{
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) {
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());
}
}
}
/*
* and then, render the layers targeted at the framebuffer
*/
const Vector< sp<Layer> >& layers(hw->getVisibleLayersSortedByZ());
const size_t count = layers.size();
const Transform& tr = hw->getTransform();
if (cur != end) {
// we're using h/w composer
for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {
const sp<Layer>& 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) {
// never clear the very first layer since we're
// guaranteed the FB is already cleared
layer->clearWithOpenGL(hw, clip);
}
break;
}
case HWC_FRAMEBUFFER: {
layer->draw(hw, clip);
break;
}
case HWC_FRAMEBUFFER_TARGET: {
// this should not happen as the iterator shouldn't
// let us get there.
ALOGW("HWC_FRAMEBUFFER_TARGET found in hwc list (index=%zu)", i);
break;
}
}
}
layer->setAcquireFence(hw, *cur);
}
} else {
// we're not using h/w composer
for (size_t i=0 ; i<count ; ++i) {
const sp<Layer>& layer(layers[i]);
const Region clip(dirty.intersect(
tr.transform(layer->visibleRegion)));
if (!clip.isEmpty()) {
layer->draw(hw, clip);
}
}
}
// disable scissor at the end of the frame
engine.disableScissor();
return true;
}
函数很长,老规矩逐段分析.
9-69行完成需要进行gles合成的处理,其中11-19行标记egl上下文设置当前surface为绘图表面.
23-29行如果需要进行hwc合成,设置整个layer背景色为透明 否则31-50行计算出需要设置背景的区域,设置为透明
52-68行对于不是主屏幕的输出,设置剪切测试,关于剪切测试可以参考opengl红宝书4.5.1节
78-122行,首先78行的判断条件代表一个display如果只有一个layer,则进入112-122的代码块,直接调用layer->draw()用opengl进行绘制,否则进入80-110的代码块.这两部分代码根据layer的不同合成类型进行处理,对于硬件处理的85-96行,如果设备上有需要opengl合成的layer,则对于这些硬件合成的layer还有清除opengl的画笔颜色.102-105行对于HWC_FRAMEBUFFER_TARGET不做处理.
现在只剩下99行layer->draw(hw, clip);没有分析.其实函数很简单,就是绑定纹理到GL_TEXTURE_EXTERNAL_OES,并设置纹理的换少方式等属性.然后根据顶点信息绘制该layer.
当设备的所有需要用opengl绘制的layer都绘制完成后,就调用 hw->swapBuffers(getHwComposer())交换buffer,这里其实另有玄机.
void DisplayDevice::swapBuffers(HWComposer& hwc) const {
// We need to call eglSwapBuffers() if:
// (1) we don't have a hardware composer, or
// (2) we did GLES composition this frame, and either
// (a) we have framebuffer target support (not present on legacy
// devices, where HWComposer::commit() handles things); or
// (b) this is a virtual display
if (hwc.initCheck() != NO_ERROR ||
(hwc.hasGlesComposition(mHwcDisplayId) &&
(hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
if (!success) {
EGLint error = eglGetError();
if (error == EGL_CONTEXT_LOST ||
mType == DisplayDevice::DISPLAY_PRIMARY) {
LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
mDisplay, mSurface, error);
} else {
ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
mDisplay, mSurface, error);
}
}
}
status_t result = mDisplaySurface->advanceFrame();
if (result != NO_ERROR) {
ALOGE("[%s] failed pushing new frame to HWC: %d",
mDisplayName.string(), result);
}
}
对于需要opengl渲染并且支持FramebufferTarget的hwc版本,又或者该设备是一个虚拟设备,就要执行 eglSwapBuffers真正的交换buffer. 这里会调到生产者的queueBuffer,并且回调用到消费者的onFrameAvailable监听,对于物理设备的FramebufferSurface监听者就是它自身,也实现了onFrameAvailable方法,对于VirtualDisplaySurface并没有实现超类方法,也没有添加listener,不进行分析.
// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
sp<GraphicBuffer> buf;
sp<Fence> acquireFence;
status_t err = nextBuffer(buf, acquireFence);
if (err != NO_ERROR) {
ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
strerror(-err), err);
return;
}
err = mHwc.fbPost(mDisplayType, acquireFence, buf);
if (err != NO_ERROR) {
ALOGE("error posting framebuffer: %d", err);
}
}
这里的nextBuffer函数也很简单 如下
status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
Mutex::Autolock lock(mMutex);
BufferItem item;
status_t err = acquireBufferLocked(&item, 0);
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
outBuffer = mCurrentBuffer;
return NO_ERROR;
} else if (err != NO_ERROR) {
ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
return err;
}
// If the BufferQueue has freed and reallocated a buffer in mCurrentSlot
// then we may have acquired the slot we already own. If we had released
// our current buffer before we call acquireBuffer then that release call
// would have returned STALE_BUFFER_SLOT, and we would have called
// freeBufferLocked on that slot. Because the buffer slot has already
// been overwritten with the new buffer all we have to do is skip the
// releaseBuffer call and we should be in the same state we'd be in if we
// had released the old buffer first.
if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
item.mSlot != mCurrentBufferSlot) {
// Release the previous buffer.
err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,
EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
if (err < NO_ERROR) {
ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);
return err;
}
}
mCurrentBufferSlot = item.mSlot;
mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
mCurrentFence = item.mFence;
outFence = item.mFence;
outBuffer = mCurrentBuffer;
return NO_ERROR;
}
就是调用acquireBufferLocked 获取buffer,这个buffer其实是之前在swapbuffer时候queueBuffer 入队列的buffer,也是一个framebuffer,并且上面已经合成了由gpu合成的内容,接下来就是由hwc再与这个buffer进行合成图像,图像合成部分就算处理完了
之后回到doComposition,最后一步就是调用postFramebuffer()进行提交
void SurfaceFlinger::postFramebuffer()
{
ATRACE_CALL();
const nsecs_t now = systemTime();
mDebugInSwapBuffers = now;
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();
}
// make the default display current because the VirtualDisplayDevice code cannot
// deal with dequeueBuffer() being called outside of the composition loop; however
// the code below can call glFlush() which is allowed (and does in some case) call
// dequeueBuffer().
getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
const Vector< sp<Layer> >& currentLayers(hw->getVisibleLayersSortedByZ());
hw->onSwapBuffersCompleted(hwc);
const size_t count = currentLayers.size();
int32_t id = hw->getHwcDisplayId();
if (id >=0 && hwc.initCheck() == NO_ERROR) {
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
for (size_t i = 0; cur != end && i < count; ++i, ++cur) {
currentLayers[i]->onLayerDisplayed(hw, &*cur);
}
} else {
for (size_t i = 0; i < count; i++) {
currentLayers[i]->onLayerDisplayed(hw, NULL);
}
}
}
mLastSwapBufferTime = systemTime() - now;
mDebugInSwapBuffers = 0;
uint32_t flipCount = getDefaultDisplayDevice()->getPageFlipCount();
if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
logFrameStats();
}
}
这里最关键的其实就是绘制提交.
另外值得注意的是每半个小时打印一次的log
这样doComposition();函数就分析完成了,再来看下最后一个函数postComposition(refreshStartTime);
void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
{
const LayerVector& layers(mDrawingState.layersSortedByZ);
const size_t count = layers.size();
for (size_t i=0 ; i