通過前面小節的講解我們知道,surfaceflinger在接收到Vsync信号之後,會執行一系列的函數,這些函數做了哪些事情呢?在之前提到SurfaceFlinger.cpp中:
void SurfaceFlinger::onMessageReceived(int32_t what) {
case MessageQueue::INVALIDATE: {
/*處理事務,實際大部分做了一些标志位的操作*/
bool refreshNeeded = handleMessageTransaction();
/*切換各個層的buffer*/
refreshNeeded |= handleMessageInvalidate();
/*發出一個界面更新的信号,最終導緻handleMessageRefresh被調用*/
refreshNeeded |= mRepaintEverything;
case MessageQueue::REFRESH: {
handleMessageRefresh();
以上函數都做了哪些工作呢?下面是一個草圖:
我們猜測一下handleMessageRefresh函數會做什麼事情。在android系統中存在對個應用程式,每個程式都有有一個Layer,這些Layer從上到下,一層層的排放,上面的層會擋住下面的。那麼handleMessageRefresh會去算出每個層的可視區域,最終在他他們合并顯示出來。如下圖:
主要工作如下:
1.計算各個Layer的顯示區域
2.合成顯示:a(軟體).使用openGL把各個Layer的可視區域在一個記憶體上描繪出來。b(硬體).使用HWcomposer合成
下面我們檢視handleMessageRefresh:
void SurfaceFlinger::handleMessageRefresh() {
/*做一些預先的處理*/
preComposition();
/*計算各個層的可視區域。對每個螢幕建構可視的Layer*/
rebuildLayerStacks();
setUpHWComposer();
doDebugFlashRegions();
doComposition();
postComposition(refreshStartTime);
首先我們來看看preComposition
preComposition
void SurfaceFlinger::preComposition()
/*在Layer.cpp中實作*/
onPreComposition()
/*如果有多個buffer需要處理傳回true*/
return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
needExtraInvalidate = true;
signalLayerUpdate();
rebuildLayerStacks
void SurfaceFlinger::rebuildLayerStacks() {
// rebuild the visible layer list per screen
/*對每個顯示器質性for中代碼*/
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
/*如果顯示器是打開的狀态*/
if (hw->isDisplayOn()) {
/*計算可視區域*/
SurfaceFlinger::computeVisibleRegions(layers,hw->getLayerStack(), dirtyRegion, opaqueRegion);
假設有多個APP,如下體所示:
在最上面的APP可以完全顯示,下面的APP會被遮擋一部分。怎麼計算各個Layer的可視區域了?
1.從Z軸最大的層開始計算,
2.Z軸小的Layer會被他上面的Layer遮蓋
下面我們使用一個例子來講解這些代碼:
假設有3個層:
void SurfaceFlinger::computeVisibleRegions(
const LayerVector& currentLayers, uint32_t layerStack,
Region& outDirtyRegion, Region& outOpaqueRegion)
{
ATRACE_CALL();
/*在目前層之上的不透明區域*/
Region aboveOpaqueLayers;
/*目前層之前的被遮蓋的區域:.opaque+transucent,目前層之上各層課時區域*/
Region aboveCoveredLayers;
/**/
Region dirty;
outDirtyRegion.clear();
/*目前需要合成的Layer層數*/
size_t i = currentLayers.size();
while (i--) {
/*從Z軸最大的那一層開始處理*/
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;
}
代碼注釋比較詳細,有興趣的同學可以分析一下。