该系列文章总纲链接:Android GUI系统之SurfaceFlinger 系列文章目录
本章节思维导图如上。主要讲述了SurfaceFlinger 处理Vsync机制的流程。主要分析handleMessageRefresh 处理方法。
1 从signalRefresh到handleMessageRefresh
signalRefresh的代码实现如下:
void SurfaceFlinger::signalRefresh() {
mEventQueue.refresh();
}
这里继续分析mEventQueue的refresh方法,代码实现如下:
void MessageQueue::refresh() {
#if INVALIDATE_ON_VSYNC
mHandler->dispatchRefresh();//调用这里
#else
mEvents->requestNextVsync();
#endif
}
继续分析mHandler的dispatchRefresh()方法,代码实现如下:
void MessageQueue::Handler::dispatchRefresh() {
if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
}
}
这里使用了handler Message 机制,因此看如何处理的,代码如下:
void MessageQueue::Handler::handleMessage(const Message& message) {
switch (message.what) {
case INVALIDATE:
android_atomic_and(~eventMaskInvalidate, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
case REFRESH:
android_atomic_and(~eventMaskRefresh, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
case TRANSACTION:
android_atomic_and(~eventMaskTransaction, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
}
}
这里会调用SurfaceFlinger的onMessageReceived方法,最后调用的是onMessageReceived,代码如下:
void SurfaceFlinger::onMessageReceived(int32_t what) {
switch (what) {
//...
case MessageQueue::REFRESH: {
handleMessageRefresh();
break;
}
}
}
到这里可以看到,signalRefresh的调用最后还会回到SurfaceFlinger的onMessageReceived调用,只不过参数变成了MessageQueue::REFRESH,这里继续分析handleMessageRefresh(),
2 handleMessageRefresh 分析
handleMessageRefresh()的代码实现如下:
void SurfaceFlinger::handleMessageRefresh() {
//关键点1 合成前预处理
preComposition();
//关键点2 计算可见区域,主要依据:z-order大的覆盖有重叠区域z-order小的
rebuildLayerStacks();
//关键点3 下面几个方法都是页面合成相关
setUpHWComposer();
doDebugFlashRegions();
//关键点4 合成所有层的图像, 经过这一步后,就显示新的内容了
doComposition();
//合成之后的工作
postComposition();
}
这里重点分析rebuildLayerStacks,最后整体简要分析下preComposition函数 和 合成界面相关的函数。
2.1 preComposition简要分析
先看Vsync Rate相关的代码:
virtual void setVsyncRate(uint32_t count)
当count为1时,表示每个信号都要报告,当count =2 时,表示信号 间隔一个后才报告,当count=0时表示不自动报告,除非主动触发requestNextVsync,接下来分析preComposition,代码实现如下:
void SurfaceFlinger::preComposition()
{
bool needExtraInvalidate = false;
const LayerVector& layers(mDrawingState.layersSortedByZ);
const size_t count = layers.size();
//获取全部的layer
for (size_t i=0 ; ionPreComposition()) {
needExtraInvalidate = true;
}
}
if (needExtraInvalidate) {
signalLayerUpdate();//请求VSYNC
}
}
这里会调用 每个Layer 的onPreComposition,代码实现如下:
bool Layer::onPreComposition() {
mRefreshPending = false;
return mQueuedFrames > 0 || mSidebandStreamChanged;
}
也就是说,当layer里存放被queue的frame以后,就会出发layer update,signalLayerUpdate这这里分析过,具体位置在这个链接:(Android GUI系统之SurfaceFlinger(06)服务端分析1-处理VSYNC)因此这里就不展开了。
2.2 rebuildLayerStacks 分析
在分析之前需要明确个基本概念:
说明:对于opaqueRegion,应为layer是按Z-order排序的,左右排在前面的opaqueRegion 会挡住后面的layer。
接下来开始分析代码,rebuildLayerStacks 代码 实现如下:
void SurfaceFlinger::rebuildLayerStacks() {
// rebuild the visible layer list per screen
if (CC_UNLIKELY(mVisibleRegionsDirty)) {
mVisibleRegionsDirty = false;
invalidateHwcGeometry();
//计算每个设备上的可见Layer
const LayerVector& layers(mDrawingState.layersSortedByZ);
//系统的display可能不止一个,存在于mDisplays中
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()) {
//计算可视区域,最关键方法
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());
//这里只要 和显示设备的layerStack相同的 layer
if (s.layerStack == hw->getLayerStack()) {
//程序需要进一步得出每个layer 绘制的区域
Region drawRegion(tr.transform(
layer->visibleNonTransparentRegion));
drawRegion.andSelf(bounds);
//如果Layer的显示区域和显示设备的窗口有交集
if (!drawRegion.isEmpty()) {
layersSortedByZ.add(layer);
}
}
}
}
//设置显示设备的可见列表,将这些结果保存在hw中
hw->setVisibleLayersSortedByZ(layersSortedByZ);//Z序layer
hw->undefinedRegion.set(bounds);
hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));//
hw->dirtyRegion.orSelf(dirtyRegion);//刷新区
}
}
}
rebuildLayerStacks主要是做两件事:
这里 主要关注computeVisibleRegions的实现,代码如下:
void SurfaceFlinger::computeVisibleRegions(
const LayerVector& currentLayers, uint32_t layerStack,
Region& outDirtyRegion, Region& outOpaqueRegion)
{
Region aboveOpaqueLayers;//当前层之上累计的不透明区域
Region aboveCoveredLayers;//当前层之上累计的被覆盖区域,不透明+半透明
Region dirty;
outDirtyRegion.clear();总值
size_t i = currentLayers.size();//最上层layer的索引
while (i--) {//从Z轴 最上面的layer开始处理,由上到下
const sp& layer = currentLayers[i];
const Layer::State& s(layer->getDrawingState());
// 只计算和layerstack相同的layer,其他忽略
if (s.layerStack != layerStack)
continue;
Region opaqueRegion; //不透明区域
Region visibleRegion; //可见区域,不透明区域+半透明区域
Region coveredRegion; //覆盖区域,可见区域覆盖的地方
Region transparentRegion; //完全透明区域
//stage1-start 得到当前Layer的原始可视区域 和 opaque区域
// handle hidden surfaces by setting the visible region to empty
if (CC_LIKELY(layer->isVisible())) {
const bool translucent = !layer->isOpaque(s);
Rect bounds(s.transform.transform(layer->computeBounds()));
visibleRegion.set(bounds);
if (!visibleRegion.isEmpty()) {
// Remove the transparent area from the visible region
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)) {
opaqueRegion = visibleRegion;
}
}
}
//stage1-end
//当前Layer被遮盖区域:上层的覆盖区 和 layer所在区域的 交集
coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
// 扩大覆盖区域,为下次循环、即下层计算做准备
aboveCoveredLayers.orSelf(visibleRegion);
//可见区域 = 抠掉上层的不透明区域
visibleRegion.subtractSelf(aboveOpaqueLayers);
// 计算需要重绘的区域
if (layer->contentDirty) {
//内容变了,重绘整个可见区域
dirty = visibleRegion;
//以前的看见区域也要加进来,因为以前的内容需要抹掉
dirty.orSelf(layer->visibleRegion);
layer->contentDirty = false;
} else {
//暴露区域 = 可见区域-被覆盖区域
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);
}
//layer的重绘区域 = 抠掉上层的不透明区域
dirty.subtractSelf(aboveOpaqueLayers);
//累计每层需要重绘的区域
outDirtyRegion.orSelf(dirty);
//更新aboveOpaqueLayers,为下层layer绘制做准备
aboveOpaqueLayers.orSelf(opaqueRegion);
//设置layer对象的区域
layer->setVisibleRegion(visibleRegion);
layer->setCoveredRegion(coveredRegion);
//设置可见的非透明区域
layer->setVisibleNonTransparentRegion(
visibleRegion.subtract(transparentRegion));
}
outOpaqueRegion = aboveOpaqueLayers;
}
总结下computeVisibleRegions的逻辑如下:
先计算每个layer在设备上的可见区域visibleRegion(不透明区域 + 半透明区域)。计算方法:整个Layer的区域-上层所有不透明区域aboveOpaqueLayers。而上层所有不透明区域的值 是一个逐层累积的过程,每层都把自己的不透明区域累加到aboveOpaqueLayers中。
每层的不透明区域的计算方法:如果layer的alpha值=255,并且layer的isOpaque = true,则本层的不透明区域 == layer所在区域。否则为0。这样一层层计算下来,就很容易得到每层的可见区域大小了。
这里以下图为例,解读下computeVisibleRegions这段逻辑:
假设有三个Layer,按照Z值从大到小,依次是Layer1->Layer2->Layer3,最后按照computeVisibleRegions的规则来合成Layer。有了这个图,看这段逻辑 便会更加直观。同时理解这段逻辑 最好的方法是将3个Layer带入到computeVisibleRegions方法中。
2.3 setUpHWComposer
setUpHWComposer的代码实现如下:
void SurfaceFlinger::setUpHWComposer() {
//mDisplays变量中维护者每个显示变量的信息
for (size_t dpy=0 ; dpygetDirtyRegion(false).isEmpty();
bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0;
bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers;
bool mustRecompose = dirty && !(empty && wasEmpty);
mDisplays[dpy]->beginFrame(mustRecompose);
if (mustRecompose) {
mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty;
}
}
HWComposer& hwc(getHwComposer());//得到系统的HWC对象
if (hwc.initCheck() == NO_ERROR) {
// build the h/w work list
if (CC_UNLIKELY(mHwWorkListDirty)) {
mHwWorkListDirty = false;
for (size_t dpy=0 ; dpy hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
//遍历DisplayDevice所有可见layer
const Vector< sp >& currentLayers(
hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
//根据layer数量调用createWorkList创建hwc_layer_list_t列表
if (hwc.createWorkList(id, count) == NO_ERROR) {
//...
}
}
}
}
// set the per-frame data
for (size_t dpy=0 ; dpy hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
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的ActiveBuffer设置到HWComposer中的hwc_layer_1_t中
layer->setPerFrameData(hw, *cur);
}
}
}
// If possible, attempt to use the cursor overlay on each display.
for (size_t dpy=0 ; dpy hw(mDisplays[dpy]);
hw->prepareFrame(hwc);
}
}
}
该函数的作用是更新HWComposer对象中图层对象列表以及涂层属性。详细点就是 构造Worklist,并且给DisplayData的list 申请空间,并填充各个layer的数据,最后调用HWComposer的prepare函数(往下延伸,这部分就是由厂家来实现了)。
2.4 doCompostion
setUpHWComposer 只是交给HWC来负责显示,真正显示的地方在这,doCompostion的代码实现如下:
void SurfaceFlinger::doComposition() {
const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
for (size_t dpy=0 ; dpy& hw(mDisplays[dpy]);
if (hw->isDisplayOn()) {
// transform the dirty region into this screen's coordinate space
const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
//关键点1:进行图像合成
doDisplayComposition(hw, dirtyRegion);
hw->dirtyRegion.clear();
hw->flip(hw->swapRegion);
hw->swapRegion.clear();
}
// 通知HWC合成结束了
hw->compositionComplete();
}
//关键点2:完成后调用该方法
postFramebuffer();
}
这里我们关键分析几个方法:getDirtyRegion、doDisplayComposition和postFramebuffer。
2.4.1 getDirtyRegion分析
在前面重构Layer时,Display的脏区域dirtyRegion已经计算出来。如果是重画,mRepaintEverything为true,那么脏区域就是整个屏幕的大小。getDirtyRegion的代码实现如下:
Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
Region dirty;
if (repaintEverything) {
dirty.set(getBounds());
} else {
const Transform& planeTransform(mGlobalTransform);
dirty = planeTransform.transform(this->dirtyRegion);
dirty.andSelf(getBounds());
}
return dirty;
}
2.4.2 doDisplayComposition分析
doDisplayComposition代码实现如下:
void SurfaceFlinger::doDisplayComposition(const sp& hw,
const Region& inDirtyRegion)
{
bool isHwcDisplay = hw->getHwcDisplayId() >= 0;
if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
return;
}
Region dirtyRegion(inDirtyRegion);
//swapRegion设置为 需要更新的区域
hw->swapRegion.orSelf(dirtyRegion);
uint32_t flags = hw->getFlags();
if (flags & DisplayDevice::SWAP_RECTANGLE) {//支持矩形更更新
dirtyRegion.set(hw->swapRegion.bounds());
} else {//支持部分更新
if (flags & DisplayDevice::PARTIAL_UPDATES) {
dirtyRegion.set(hw->swapRegion.bounds());
} else {
// we need to redraw everything (the whole screen)
dirtyRegion.set(hw->bounds());//将更新区域调整为整个窗口的大小
hw->swapRegion = dirtyRegion;
}
}
//关键点1:都会执行 doComposeSurfaces方法
if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) {
if (!doComposeSurfaces(hw, dirtyRegion)) return;
} else {
RenderEngine& engine(getRenderEngine());
mat4 colorMatrix = mColorMatrix;
if (mDaltonize) {
colorMatrix = colorMatrix * mDaltonizer();
}
engine.beginGroup(colorMatrix);
doComposeSurfaces(hw, dirtyRegion);
engine.endGroup();
}
// update the swap region and clear the dirty region
hw->swapRegion.orSelf(dirtyRegion);
//关键点2:在系统不支持HWC的情况下调用eglSwapBuffers来输出图像到显示设备。
hw->swapBuffers(getHwComposer());
}
传入的参数inDirtyRegion,是要刷新的“脏”区域,但我们的刷新机制决定了必须是矩形的区域。因此需要一个最小的矩形,能够包裹inDirtyRegion的区域。这里有两种模式:
总之 最后就是重绘这个区域。 该部分专注两个关键方法 doComposeSurfaces 和 hw->swapBuffers(getHwComposer());
@1 doComposeSurfaces分析
doComposeSurfaces的代码实现如下:
bool SurfaceFlinger::doComposeSurfaces(const sp& 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)) {
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) {
engine.clearWithColor(0, 0, 0, 0);
} else {
const Region bounds(hw->getBounds());
const Region letterbox(bounds.subtract(hw->getScissor()));
Region region(hw->undefinedRegion.merge(letterbox));
region.andSelf(dirty);
// screen is already cleared here
if (!region.isEmpty()) {
// can happen with SurfaceView
drawWormhole(hw, region);
}
}
if (hw->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
const Rect& bounds(hw->getBounds());
const Rect& scissor(hw->getScissor());
if (scissor != bounds) {
const uint32_t height = hw->getHeight();
engine.setScissor(scissor.left, height - scissor.bottom,
scissor.getWidth(), scissor.getHeight());
}
}
}
const Vector< sp >& layers(hw->getVisibleLayersSortedByZ());
const size_t count = layers.size();
const Transform& tr = hw->getTransform();
if (cur != end) {
// 使用 h/w composer
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->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 {
// 不使用 h/w composer,只用openGL ES
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);
}
}
}
// disable scissor at the end of the frame
engine.disableScissor();
return true;
}
这里无论是使用openGL ES 还是HWC 来处理,都会调用layer->draw方法。只不过HWC的相对复杂一些而已。
@2 hw->swapBuffers(getHwComposer())分析
这里hw就是DisplayDevice,该部分 在章节(Android GUI系统之SurfaceFlinger(14)理解DisplayDevice)中 分析过,所以这里不再重复。
2.4.3 postFramebuffer分析
postFramebuffer代码实现如下:
void SurfaceFlinger::postFramebuffer()
{
const nsecs_t now = systemTime();
mDebugInSwapBuffers = now;
HWComposer& hwc(getHwComposer());
//检查是否支持HWC,如果不支持在前面就输出了,直接返回
if (hwc.initCheck() == NO_ERROR) {
if (!hwc.supportsFramebufferTarget()) {
getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
}
//关键点:支持HWC则 调用该方法
hwc.commit();
}
//...
}
这里继续分析hwc的commit()方法,代码实现如下:
status_t HWComposer::commit() {
int err = NO_ERROR;
if (mHwc) {
if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
mLists[0]->dpy = eglGetCurrentDisplay();
mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
}
for (size_t i=VIRTUAL_DISPLAY_ID_BASE; ioutbuf = disp.outbufHandle;
mLists[i]->outbufAcquireFenceFd =
disp.outbufAcquireFence->dup();
}
}
//关键点
err = mHwc->set(mHwc, mNumDisplays, mLists);
//...
}
return (status_t)err;
}
这里主要调用了HWC的 set函数处理之后的工作(set的代码实现往下延伸,就是由厂家来实现了)。同时图像最后输出到显示屏上。
2.5 postComposition分析
postComposition的代码实现如下:
void SurfaceFlinger::postComposition()
{
const LayerVector& layers(mDrawingState.layersSortedByZ);
const size_t count = layers.size();
for (size_t i=0 ; ionPostComposition();
}
const HWComposer& hwc = getHwComposer();
sp presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
//VSync同步
if (presentFence->isValid()) {
if (mPrimaryDispSync.addPresentFence(presentFence)) {
enableHardwareVsync();
} else {
disableHardwareVsync(false);
}
}
if (kIgnorePresentFences) {
const sp hw(getDefaultDisplayDevice());
if (hw->isDisplayOn()) {
enableHardwareVsync();
}
}
//动画合成处理
if (mAnimCompositionPending) {
mAnimCompositionPending = false;
if (presentFence->isValid()) {
mAnimFrameTracker.setActualPresentFence(presentFence);
} else {
nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
mAnimFrameTracker.setActualPresentTime(presentTime);
}
mAnimFrameTracker.advanceFrame();
}
}
至此,整个handleMessageRefresh的处理流程就分析结束了。