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

Commit 2b406365 authored by David Sodman's avatar David Sodman
Browse files

SF: Restructure message refresh

Bug: 112259502
Test: cts -m CtsViewTestCases
      SurfaceFlinger_test
      vrflinger_test

Change-Id: I08091d64114b644edb32504779b3d05185d2f552
parent 79bba0e9
Loading
Loading
Loading
Loading
+53 −45
Original line number Diff line number Diff line
@@ -265,6 +265,7 @@ SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag)
        mForceFullDamage(false),
        mPrimaryHWVsyncEnabled(false),
        mHWVsyncAvailable(false),
        mRefreshStartTime(0),
        mHasPoweredOff(false),
        mNumLayers(0),
        mVrFlingerRequestsDisplay(false),
@@ -1574,16 +1575,16 @@ void SurfaceFlinger::handleMessageRefresh() {

    mRefreshPending = false;

    nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);

    preComposition(refreshStartTime);
    preComposition();
    rebuildLayerStacks();
    calculateWorkingSet();
    beginFrame();
    prepareFrame();
    doDebugFlashRegions();
    doTracing("handleRefresh");
    logLayerStats();
    doComposition();
    postComposition(refreshStartTime);
    postComposition();

    mHadClientComposition = false;
    for (const auto& [token, display] : mDisplays) {
@@ -1599,32 +1600,6 @@ void SurfaceFlinger::calculateWorkingSet() {
    ATRACE_CALL();
    ALOGV(__FUNCTION__);

    for (const auto& [token, display] : mDisplays) {
        bool dirty = !display->getDirtyRegion(mRepaintEverything).isEmpty();
        bool empty = display->getVisibleLayersSortedByZ().size() == 0;
        bool wasEmpty = !display->lastCompositionHadVisibleLayers;

        // If nothing has changed (!dirty), don't recompose.
        // If something changed, but we don't currently have any visible layers,
        //   and didn't when we last did a composition, then skip it this time.
        // The second rule does two things:
        // - When all layers are removed from a display, we'll emit one black
        //   frame, then nothing more until we get new layers.
        // - When a display is created with a private layer stack, we won't
        //   emit any black frames until a layer is added to the layer stack.
        bool mustRecompose = dirty && !(empty && wasEmpty);

        ALOGV_IF(display->isVirtual(), "Display %d: %s composition (%sdirty %sempty %swasEmpty)",
                 display->getId(), mustRecompose ? "doing" : "skipping", dirty ? "+" : "-",
                 empty ? "+" : "-", wasEmpty ? "+" : "-");

        display->beginFrame(mustRecompose);

        if (mustRecompose) {
            display->lastCompositionHadVisibleLayers = !empty;
        }
    }

    // build the h/w work list
    if (CC_UNLIKELY(mGeometryInvalid)) {
        mGeometryInvalid = false;
@@ -1697,16 +1672,6 @@ void SurfaceFlinger::calculateWorkingSet() {
    }

    mDrawingState.colorMatrixChanged = false;

    for (const auto& [token, display] : mDisplays) {
        if (!display->isPoweredOn()) {
            continue;
        }

        status_t result = display->prepareFrame(*getBE().mHwc);
        ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)",
                 display->getId(), result, strerror(-result));
    }
}

void SurfaceFlinger::doDebugFlashRegions()
@@ -1773,14 +1738,16 @@ void SurfaceFlinger::logLayerStats() {
    }
}

void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
void SurfaceFlinger::preComposition()
{
    ATRACE_CALL();
    ALOGV("preComposition");

    mRefreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);

    bool needExtraInvalidate = false;
    mDrawingState.traverseInZOrder([&](Layer* layer) {
        if (layer->onPreComposition(refreshStartTime)) {
        if (layer->onPreComposition(mRefreshStartTime)) {
            needExtraInvalidate = true;
        }
    });
@@ -1849,7 +1816,7 @@ void SurfaceFlinger::setCompositorTimingSnapped(nsecs_t vsyncPhase,
    getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
}

void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
void SurfaceFlinger::postComposition()
{
    ATRACE_CALL();
    ALOGV("postComposition");
@@ -1882,11 +1849,11 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
    nsecs_t vsyncPhase = mPrimaryDispSync->computeNextRefresh(0);
    nsecs_t vsyncInterval = mPrimaryDispSync->getPeriod();

    // We use the refreshStartTime which might be sampled a little later than
    // We use the mRefreshStartTime which might be sampled a little later than
    // when we started doing work for this frame, but that should be okay
    // since updateCompositorTiming has snapping logic.
    updateCompositorTiming(
        vsyncPhase, vsyncInterval, refreshStartTime, presentFenceTime);
        vsyncPhase, vsyncInterval, mRefreshStartTime, presentFenceTime);
    CompositorTiming compositorTiming;
    {
        std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
@@ -2108,6 +2075,47 @@ void SurfaceFlinger::pickColorMode(const sp<DisplayDevice>& display, ColorMode*
    display->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent);
}

void SurfaceFlinger::beginFrame()
{
    for (const auto& [token, display] : mDisplays) {
        bool dirty = !display->getDirtyRegion(mRepaintEverything).isEmpty();
        bool empty = display->getVisibleLayersSortedByZ().size() == 0;
        bool wasEmpty = !display->lastCompositionHadVisibleLayers;

        // If nothing has changed (!dirty), don't recompose.
        // If something changed, but we don't currently have any visible layers,
        //   and didn't when we last did a composition, then skip it this time.
        // The second rule does two things:
        // - When all layers are removed from a display, we'll emit one black
        //   frame, then nothing more until we get new layers.
        // - When a display is created with a private layer stack, we won't
        //   emit any black frames until a layer is added to the layer stack.
        bool mustRecompose = dirty && !(empty && wasEmpty);

        ALOGV_IF(display->isVirtual(), "Display %d: %s composition (%sdirty %sempty %swasEmpty)",
                 display->getId(), mustRecompose ? "doing" : "skipping", dirty ? "+" : "-",
                 empty ? "+" : "-", wasEmpty ? "+" : "-");

        display->beginFrame(mustRecompose);

        if (mustRecompose) {
            display->lastCompositionHadVisibleLayers = !empty;
        }
    }
}

void SurfaceFlinger::prepareFrame()
{
    for (const auto& [token, display] : mDisplays) {
        if (!display->isPoweredOn()) {
            continue;
        }

        status_t result = display->prepareFrame(*getBE().mHwc);
        ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)",
                 display->getId(), result, strerror(-result));
    }
}

void SurfaceFlinger::doComposition() {
    ATRACE_CALL();
+14 −2
Original line number Diff line number Diff line
@@ -648,8 +648,8 @@ private:
    void computeVisibleRegions(const sp<const DisplayDevice>& display, Region& dirtyRegion,
                               Region& opaqueRegion);

    void preComposition(nsecs_t refreshStartTime);
    void postComposition(nsecs_t refreshStartTime);
    void preComposition();
    void postComposition();
    void updateCompositorTiming(
            nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
            std::shared_ptr<FenceTime>& presentFenceTime);
@@ -668,6 +668,17 @@ private:
                       ui::Dataspace* outDataSpace, ui::RenderIntent* outRenderIntent) const;

    void calculateWorkingSet();
    /*
     * beginFrame - This function handles any pre-frame processing that needs to be
     * prior to any CompositionInfo handling and is not dependent on data in
     * CompositionInfo
     */
    void beginFrame();
    /* prepareFrame - This function will call into the DisplayDevice to prepare a
     * frame after CompositionInfo has been programmed.   This provides a mechanism
     * to prepare the hardware composer
     */
    void prepareFrame();
    void doComposition();
    void doDebugFlashRegions();
    void doTracing(const char* where);
@@ -863,6 +874,7 @@ private:
    Mutex mHWVsyncLock;
    bool mPrimaryHWVsyncEnabled;
    bool mHWVsyncAvailable;
    nsecs_t mRefreshStartTime;

    std::atomic<bool> mRefreshPending{false};