合成流程详解(未完待续)

知其所以然

整体流程

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;
        }
    }
}

合成分为两步:INVALIDATEREFRESH

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() 的作用主要是遍历 mPendingTransactionQueuesmTransactionQueue 这两个 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

LayerFELayer 的父类:

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 国际许可协议 进行许可。