整体流程
flowchart TD
a[onMessageReceived]--> b[onMessageInvalidate]
a --> c[onMessageRefresh]
b --> d[handleMessageTransaction]
b --> e[handleMessageInvalidate]
d --> f[transactionIsReadyToBeApplied]
d --> g[setBuffer]
d --> h[handleTransaction]
e --> i[handlePageFlip]
i --> j[doTransaction]
i --> k[BufferLayer::latchBuffer]
k --> l[BufferStateLayer::updateTexImage]
k --> m[BufferStateLayer::updateActiveBuffer]
c --> o[present]
c --> p[postComposition]
SurfaceFlinger::onMessageReceived
是 SurfaceFlinger 合成的起点:
void SurfaceFlinger::onMessageReceived(int32_t what, int64_t vsyncId, nsecs_t expectedVSyncTime) {
switch (what) {
case MessageQueue::INVALIDATE: {
onMessageInvalidate(vsyncId, expectedVSyncTime);
break;
}
case MessageQueue::REFRESH: {
onMessageRefresh();
break;
}
}
}
合成分为两步:INVALIDATE 和 REFRESH。
INVALIDATE
INVALIDATE 阶段主要有两个函数:handleMessageTransaction()
和 handleMessageInvalidate()
,这两个函数的主要作用是:
handleMessageTransaction()
handleMessageInvalidate()
handleMessageTransaction ()
bool SurfaceFlinger::handleMessageTransaction() {
if (getTransactionFlags(eTransactionFlushNeeded)) {
flushTransactionQueues();
}
uint32_t transactionFlags = peekTransactionFlags();
bool runHandleTransaction =
((transactionFlags & (~eTransactionFlushNeeded)) != 0) || mForceTraversal;
if (runHandleTransaction) {
handleTransaction(eTransactionMask);
}
if (transactionFlushNeeded()) {
setTransactionFlags(eTransactionFlushNeeded);
}
return runHandleTransaction;
}
首先会先检查上个 VSYNC 周期内是否有 Client 设置了 eTransactionFlushNeeded
这个标志位(设置这个标志位有两个途径:应用提交改动(Buffer 或者几何改动)或者有 Pending Transaction),如果有的话会调用 flushTransactionQueues()
来处理这些 Transaction。
flushTransactionQueues()
flushTransactionQueues()
的作用主要是遍历 mPendingTransactionQueues
和 mTransactionQueue
这两个 TransactionState 队列。先处理 mPendingTransactionQueues
再处理 mTransactionQueue
。当 mTransactionQueue
里有 Transaction 没法完成的时候,会将其加入 mPendingTransactionQueues
在下次 VSYNC 的时候再处理。
处理 Transaction 的步骤很简单:
- transactionIsReadyToBeApplied ()
- traverseStatesWithBuffers
transactionIsReadyToBeApplied()
的作用是检查该 Transaction 是否可用,把可用的 TransactionState
收集起来,统一使用 applyTransactionState()
来进行处理。applyTransactionState()
里最重要的就是 setClientStateLocked()
,在 setClientStateLocked()
会检查所有的 SurfaceComposerClient::Transaction
里设置的所有 what 都给检查一遍,然后将涉及到的参数改变同步到 Layer!
SurfaceControl::Transaction::apply()
的作用是将有变动相关的 SurfaceControl
对应的 ComposerState
等打包发送给 SurfaceFlinger。然后这些值会被重新封装到 SurfaceFlinger::TransactionState
,并加入到 mTransactionQueue
里。
handleMessageInvalidate()
这两个函数的返回值一起决定是否要进行进入 REFRESH 阶段。
handlePageFlip()
最核心的函数是 latchBuffer()
:
/*
* latchBuffer - called each time the screen is redrawn and returns whether
* the visible regions need to be recomputed (this is a fairly heavy
* operation, so this should be set only if needed). Typically this is used
* to figure out if the content or size of a surface has changed.
*/
virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/,
nsecs_t /*expectedPresentTime*/) {
return false;
}
通过 updateActiveBuffer()
将前面调用 setBuffer()
是从 Surface 同步到 Layer::mDrawingState
的 buffer 更新到 mBufferInfo
里:
status_t BufferStateLayer::updateActiveBuffer() {
const State& s(getDrawingState());
if (s.buffer == nullptr) {
return BAD_VALUE;
}
if (!mBufferInfo.mBuffer || s.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) {
decrementPendingBufferCount();
}
mPreviousReleaseCallbackId = {getCurrentBufferId(), mBufferInfo.mFrameNumber};
mBufferInfo.mBuffer = s.buffer;
mBufferInfo.mFence = s.acquireFence;
mBufferInfo.mFrameNumber = s.frameNumber;
return NO_ERROR;
}
REFRESH
Surface 上的 Buffer 改动是怎么一步步同步到 Layer 的呢?
Layer.State 和 SurfaceFlinger.State
首先看一下 Layer.State
的结构:
struct State {
Geometry active_legacy;
Geometry requested_legacy;
int32_t z;
// The identifier of the layer stack this layer belongs to. A layer can
// only be associated to a single layer stack. A layer stack is a
// z-ordered group of layers which can be associated to one or more
// displays. Using the same layer stack on different displays is a way
// to achieve mirroring.
uint32_t layerStack;
uint32_t flags;
uint8_t reserved[2];
int32_t sequence; // changes when visible regions can change
bool modified;
// Crop is expressed in layer space coordinate.
Rect crop;
Rect requestedCrop;
// the transparentRegion hint is a bit special, it's latched only
// when we receive a buffer -- this is because it's "content"
// dependent.
Region activeTransparentRegion_legacy;
Region requestedTransparentRegion_legacy;
LayerMetadata metadata;
// If non-null, a Surface this Surface's Z-order is interpreted relative to.
wp<Layer> zOrderRelativeOf;
bool isRelativeOf{false};
// A list of surfaces whose Z-order is interpreted relative to ours.
SortedVector<wp<Layer>> zOrderRelatives;
half4 color;
float cornerRadius;
int backgroundBlurRadius;
InputWindowInfo inputInfo;
wp<Layer> touchableRegionCrop;
// dataspace is only used by BufferStateLayer and EffectLayer
ui::Dataspace dataspace;
// The fields below this point are only used by BufferStateLayer
uint64_t frameNumber;
uint32_t width;
uint32_t height;
ui::Transform transform;
uint32_t bufferTransform;
bool transformToDisplayInverse;
Region transparentRegionHint;
std::shared_ptr<renderengine::ExternalTexture> buffer;
client_cache_t clientCacheId;
sp<Fence> acquireFence;
std::shared_ptr<FenceTime> acquireFenceTime;
HdrMetadata hdrMetadata;
Region surfaceDamageRegion;
int32_t api;
sp<NativeHandle> sidebandStream;
mat4 colorTransform;
bool hasColorTransform;
// pointer to background color layer that, if set, appears below the buffer state layer
// and the buffer state layer's children. Z order will be set to
// INT_MIN
sp<Layer> bgColorLayer;
// The deque of callback handles for this frame. The back of the deque contains the most
// recent callback handle.
std::deque<sp<CallbackHandle>> callbackHandles;
bool colorSpaceAgnostic;
nsecs_t desiredPresentTime = 0;
bool isAutoTimestamp = true;
// Length of the cast shadow. If the radius is > 0, a shadow of length shadowRadius will
// be rendered around the layer.
float shadowRadius;
// Layer regions that are made of custom materials, like frosted glass
std::vector<BlurRegion> blurRegions;
// Priority of the layer assigned by Window Manager.
int32_t frameRateSelectionPriority;
FrameRate frameRate;
// The combined frame rate of parents / children of this layer
FrameRate frameRateForLayerTree;
// Set by window manager indicating the layer and all its children are
// in a different orientation than the display. The hint suggests that
// the graphic producers should receive a transform hint as if the
// display was in this orientation. When the display changes to match
// the layer orientation, the graphic producer may not need to allocate
// a buffer of a different size. ui::Transform::ROT_INVALID means the
// a fixed transform hint is not set.
ui::Transform::RotationFlags fixedTransformHint;
// The vsync info that was used to start the transaction
FrameTimelineInfo frameTimelineInfo;
// When the transaction was posted
nsecs_t postTime;
sp<ITransactionCompletedListener> releaseBufferListener;
// SurfaceFrame that tracks the timeline of Transactions that contain a Buffer. Only one
// such SurfaceFrame exists because only one buffer can be presented on the layer per vsync.
// If multiple buffers are queued, the prior ones will be dropped, along with the
// SurfaceFrame that's tracking them.
std::shared_ptr<frametimeline::SurfaceFrame> bufferSurfaceFrameTX;
// A map of token(frametimelineVsyncId) to the SurfaceFrame that's tracking a transaction
// that contains the token. Only one SurfaceFrame exisits for transactions that share the
// same token, unless they are presented in different vsyncs.
std::unordered_map<int64_t, std::shared_ptr<frametimeline::SurfaceFrame>>
bufferlessSurfaceFramesTX;
// An arbitrary threshold for the number of BufferlessSurfaceFrames in the state. Used to
// trigger a warning if the number of SurfaceFrames crosses the threshold.
static constexpr uint32_t kStateSurfaceFramesThreshold = 25;
// Stretch effect to apply to this layer
StretchEffect stretchEffect;
// Whether or not this layer is a trusted overlay for input
bool isTrustedOverlay;
Rect bufferCrop;
Rect destinationFrame;
};
SurfaceFlinger.State
:
class State {
public:
explicit State(LayerVector::StateSet set) : stateSet(set), layersSortedByZ(set) {}
State& operator=(const State& other) {
// We explicitly don't copy stateSet so that, e.g., mDrawingState
// always uses the Drawing StateSet.
layersSortedByZ = other.layersSortedByZ;
displays = other.displays;
colorMatrixChanged = other.colorMatrixChanged;
if (colorMatrixChanged) {
colorMatrix = other.colorMatrix;
}
globalShadowSettings = other.globalShadowSettings;
return *this;
}
const LayerVector::StateSet stateSet = LayerVector::StateSet::Invalid;
LayerVector layersSortedByZ;
DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays;
bool colorMatrixChanged = true;
mat4 colorMatrix;
renderengine::ShadowSettings globalShadowSettings;
void traverse(const LayerVector::Visitor& visitor) const;
void traverseInZOrder(const LayerVector::Visitor& visitor) const;
void traverseInReverseZOrder(const LayerVector::Visitor& visitor) const;
};
/*
* Used by the top-level SurfaceFlinger state and individual layers
* to track layers they own sorted according to Z-order. Provides traversal
* functions for traversing all owned layers, and their descendents.
*/
class LayerVector : public SortedVector<sp<Layer>> {
public:
enum class StateSet {
Invalid,
Current,
Drawing,
};
explicit LayerVector(const StateSet stateSet);
LayerVector(const LayerVector& rhs, const StateSet stateSet);
~LayerVector() override;
LayerVector& operator=(const LayerVector& rhs);
// Sorts layer by layer-stack, Z order, and finally creation order (sequence).
int do_compare(const void* lhs, const void* rhs) const override;
using Visitor = std::function<void(Layer*)>;
void traverseInReverseZOrder(StateSet stateSet, const Visitor& visitor) const;
void traverseInZOrder(StateSet stateSet, const Visitor& visitor) const;
void traverse(const Visitor& visitor) const;
private:
const StateSet mStateSet;
};
可以看到,这两个类/结构虽然名字一样,但是内部成员和作用完全不一样:
Layer.State
主要存储了该 Layer 相关的数据,例如长宽,各种矩阵,阴影等SurfaceFlinger.State
主要存储了当前的所有 Layer 以及 Display 设备,并且提供按照 z 值正序/逆序遍历的方法。
Surface 的 Buffer 是怎么传递给 HWC 呢?
@startuml
SurfaceFlinger -> SurfaceFlinger: onMessageInvalidate()
activate SurfaceFlinger
SurfaceFlinger -> SurfaceFlinger: onMessageRefresh()
SurfaceFlinger -> "impl::CompositionEngine": present()
"impl::CompositionEngine" -> "impl::Output": present()
"impl::Output" -> "impl::Output": writeCompositionState()
activate "impl::Output"
loop "for (auto* layer : getOutputLayersOrderedByZ())"
"impl::Output" -> "impl::OutputLayer": writeStateToHWC()
"impl::OutputLayer" -> "impl::OutputLayer": writeOutputIndependentPerFrameStateToHWC()
"impl::OutputLayer" -> "impl::OutputLayer": writeBufferStateToHWC()
"impl::OutputLayer" -> "HWC2::impl::Layer": setBuffer()
"HWC2::impl::Layer" -> "Hwc2::impl::Composer": setLayerBuffer()
SurfaceFlinger -> SurfaceFlinger: onMessageInvalidate()
deactivate "impl::Output"
end
deactivate SurfaceFlinger
@enduml
// frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.cpp
Error Layer::setBuffer(uint32_t slot, const sp<GraphicBuffer>& buffer,
const sp<Fence>& acquireFence)
{
if (CC_UNLIKELY(!mDisplay)) {
return Error::BAD_DISPLAY;
}
if (buffer == nullptr && mBufferSlot == slot) {
return Error::NONE;
}
mBufferSlot = slot;
int32_t fenceFd = acquireFence->dup();
auto intError = mComposer.setLayerBuffer(mDisplay->getId(), mId, slot, buffer, fenceFd);
return static_cast<Error>(intError);
}
// frameworks/native/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
Error Composer::setLayerBuffer(Display display, Layer layer,
uint32_t slot, const sp<GraphicBuffer>& buffer, int acquireFence)
{
mWriter.selectDisplay(display);
mWriter.selectLayer(layer);
const native_handle_t* handle = nullptr;
if (buffer.get()) {
handle = buffer->getNativeBuffer()->handle;
}
mWriter.setLayerBuffer(slot, handle, acquireFence);
return Error::NONE;
}
app 通过 dequeueBuffer
分配 Graphicsbuffer,然后调用 gralloc ion 分配,返回fd
然后通过 Layer::setBuffer()
将该 Buffer 从 Surface 同步到 Layer 侧
之后 sf 调用 setLayerBuffer()
会把 GraphicBuffer 信息通过handle = buffer->getNativeBuffer()->handle
给到hwc
hwc 之后就能拿到 fd,然后通过 drm 传递到 kenrel,kernel通过 fd 能找到这个内存
LayerFE
LayerFE
是 Layer
的父类:
class Layer : public virtual RefBase, compositionengine::LayerFE {
是在这个 change 里引入的改动:
commit feb73d7951302cb24e86d00a1b72add9ff4121ca
Author: Lloyd Pique <lpique@google.com>
Date: Tue Dec 4 17:23:44 2018 -0800
SF: Setup CompositionEngine::Layer
Add a Layer class to CompositionEngine, and modify ColorLayer and
BufferLayer to create them.
Also sets up CompositionEngine::LayerFE as an interface to be
implemented by the SF Layer class.
Test: atest libsurfaceflinger_unittest libcompositionengine_test
Bug: 121291683
Change-Id: I2ed83355e81f36954b034ec60dd1a24c631f4874
Author: simowce
Permalink: https://blog.simowce.com/all-about-composition/
本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。