Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 167bdde8 authored by Robert Carr's avatar Robert Carr Committed by Rob Carr
Browse files

Prevent HDRLayerInfoListener traversal from running on every frame

We should only have to update the HDRLayerInfoListener in a few
scenarios.
    1. A new listener appeared
    2. A buffer changed colorspace
    3. Surface geometry (visibility, parenting, display, etc) changed
We protect the traversal behind these flags to avoid the runtime in the
hot path of continuous buffer updates. A follow up fix could consider
directly recursively traversing and early returning if !Layer->isVisible.

Bug: 186200583
Test: Existing tests pass, simpleperf
Change-Id: I549fdf6ea228344f79f6989b86b8e73a6065158a
parent 6a409e17
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -890,7 +890,11 @@ void BufferStateLayer::gatherBufferInfo() {
    mBufferInfo.mFenceTime = std::make_shared<FenceTime>(s.acquireFence);
    mBufferInfo.mFence = s.acquireFence;
    mBufferInfo.mTransform = s.bufferTransform;
    auto lastDataspace = mBufferInfo.mDataspace;
    mBufferInfo.mDataspace = translateDataspace(s.dataspace);
    if (lastDataspace != mBufferInfo.mDataspace) {
        mFlinger->mSomeDataspaceChanged = true;
    }
    mBufferInfo.mCrop = computeBufferCrop(s);
    mBufferInfo.mScaleMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
    mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion;
+37 −23
Original line number Diff line number Diff line
@@ -1643,6 +1643,9 @@ status_t SurfaceFlinger::addHdrLayerInfoListener(const sp<IBinder>& displayToken
        hdrInfoReporter = sp<HdrLayerInfoReporter>::make();
    }
    hdrInfoReporter->addListener(listener);


    mAddingHDRLayerInfoListener = true;
    return OK;
}

@@ -2143,6 +2146,8 @@ void SurfaceFlinger::onMessageRefresh() {
            mTracing.notify("bufferLatched");
        }
    }

    mVisibleRegionsWereDirtyThisFrame = mVisibleRegionsDirty; // Cache value for use in post-comp
    mVisibleRegionsDirty = false;

    if (mCompositionEngine->needsAnotherUpdate()) {
@@ -2287,6 +2292,7 @@ void SurfaceFlinger::postComposition() {

    std::vector<std::pair<std::shared_ptr<compositionengine::Display>, sp<HdrLayerInfoReporter>>>
            hdrInfoListeners;
    bool haveNewListeners = false;
    {
        Mutex::Autolock lock(mStateLock);
        if (mFpsReporter) {
@@ -2304,8 +2310,11 @@ void SurfaceFlinger::postComposition() {
                }
            }
        }
        haveNewListeners = mAddingHDRLayerInfoListener; // grab this with state lock
        mAddingHDRLayerInfoListener = false;
    }

    if (haveNewListeners || mSomeDataspaceChanged || mVisibleRegionsWereDirtyThisFrame) {
        for (auto& [compositionDisplay, listener] : hdrInfoListeners) {
            HdrLayerInfoReporter::HdrLayerInfo info;
            int32_t maxArea = 0;
@@ -2318,7 +2327,8 @@ void SurfaceFlinger::postComposition() {
                                        transfer == Dataspace::TRANSFER_HLG);

                    if (isHdr) {
                    const auto* outputLayer = compositionDisplay->getOutputLayerForLayer(layerFe);
                        const auto* outputLayer =
                            compositionDisplay->getOutputLayerForLayer(layerFe);
                        if (outputLayer) {
                            info.numberOfHdrLayers++;
                            const auto displayFrame = outputLayer->getState().displayFrame;
@@ -2334,6 +2344,10 @@ void SurfaceFlinger::postComposition() {
            });
            listener->dispatchHdrLayerInfo(info);
        }
    }

    mSomeDataspaceChanged = false;
    mVisibleRegionsWereDirtyThisFrame = false;

    mTransactionCallbackInvoker.addPresentFence(mPreviousPresentFences[0].fence);
    mTransactionCallbackInvoker.sendCallbacks();
+8 −0
Original line number Diff line number Diff line
@@ -1240,11 +1240,19 @@ private:
    State mDrawingState{LayerVector::StateSet::Drawing};
    bool mVisibleRegionsDirty = false;

    // VisibleRegions dirty is already cleared by postComp, but we need to track it to prevent
    // extra work in the HDR layer info listener.
    bool mVisibleRegionsWereDirtyThisFrame = false;
    // Used to ensure we omit a callback when HDR layer info listener is newly added but the
    // scene hasn't changed
    bool mAddingHDRLayerInfoListener = false;

    // Set during transaction application stage to track if the input info or children
    // for a layer has changed.
    // TODO: Also move visibleRegions over to a boolean system.
    bool mInputInfoChanged = false;
    bool mSomeChildrenChanged;
    bool mSomeDataspaceChanged = false;
    bool mForceTransactionDisplayChange = false;

    bool mGeometryInvalid = false;