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

Commit d71fd189 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I1348da2c,I103d2a56,I4ed64966

* changes:
  SurfaceFlinger: set change phase offsets for 90Hz
  SurfaceFlinger: get expectedPresentTime from Scheduler
  SF: set active config state machine
parents 45a16abf 482b4b1b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -232,7 +232,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t
                    getTransformToDisplayInverse(), mFreezeGeometryUpdates);

    const nsecs_t expectedPresentTime = mFlinger->mUseScheduler
            ? mFlinger->mScheduler->mPrimaryDispSync->expectedPresentTime()
            ? mFlinger->mScheduler->expectedPresentTime()
            : mFlinger->mPrimaryDispSync->expectedPresentTime();

    // updateTexImage() below might drop the some buffers at the head of the queue if there is a
+3 −3
Original line number Diff line number Diff line
@@ -59,10 +59,10 @@ PhaseOffsets::PhaseOffsets() {
    const int highFpsEarlyGlAppOffsetNs = atoi(value);

    // TODO(b/122905996): Define these in device.mk.
    property_get("debug.sf.high_fps_late_app_phase_offset_ns", value, "1000000");
    property_get("debug.sf.high_fps_late_app_phase_offset_ns", value, "2000000");
    const int highFpsLateAppOffsetNs = atoi(value);

    property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "8000000");
    property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "1000000");
    const int highFpsLateSfOffsetNs = atoi(value);

    mDefaultRefreshRateOffsets.early = {earlySfOffsetNs != -1 ? earlySfOffsetNs
@@ -83,7 +83,7 @@ PhaseOffsets::PhaseOffsets() {
                                                                      : highFpsLateAppOffsetNs,
                                       highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
                                                                       : highFpsLateSfOffsetNs};
    mHighRefreshRateOffsets.late = {highFpsLateAppOffsetNs, highFpsLateSfOffsetNs};
    mHighRefreshRateOffsets.late = {highFpsLateSfOffsetNs, highFpsLateAppOffsetNs};
}

PhaseOffsets::Offsets PhaseOffsets::getCurrentOffsets() const {
+5 −1
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function)
    mEventControlThread = std::make_unique<impl::EventControlThread>(function);

    char value[PROPERTY_VALUE_MAX];
    property_get("debug.sf.set_idle_timer_ms", value, "30");
    property_get("debug.sf.set_idle_timer_ms", value, "0");
    mSetIdleTimerMs = atoi(value);

    if (mSetIdleTimerMs > 0) {
@@ -238,6 +238,10 @@ void Scheduler::makeHWSyncAvailable(bool makeAvailable) {
    mHWVsyncAvailable = makeAvailable;
}

nsecs_t Scheduler::expectedPresentTime() {
    return mPrimaryDispSync->expectedPresentTime();
}

void Scheduler::addFramePresentTimeForLayer(const nsecs_t framePresentTime, bool isAutoTimestamp,
                                            const std::string layerName) {
    // This is V1 logic. It calculates the average FPS based on the timestamp frequency
+1 −3
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ public:
    void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
    void setIgnorePresentFences(bool ignore);
    void makeHWSyncAvailable(bool makeAvailable);
    nsecs_t expectedPresentTime();
    // Adds the present time for given layer to the history of present times.
    void addFramePresentTimeForLayer(const nsecs_t framePresentTime, bool isAutoTimestamp,
                                     const std::string layerName);
@@ -142,9 +143,6 @@ private:
    // Function that is called when the timer expires.
    void expiredTimerCallback();

    // TODO(b/113612090): Instead of letting BufferQueueLayer to access mDispSync directly, it
    // should make request to Scheduler to compute next refresh.
    friend class BufferQueueLayer;

    // If fences from sync Framework are supported.
    const bool mHasSyncFramework;
+126 −37
Original line number Diff line number Diff line
@@ -351,10 +351,6 @@ SurfaceFlinger::SurfaceFlinger(surfaceflinger::Factory& factory)
    }
    ALOGV("Primary Display Orientation is set to %2d.", SurfaceFlinger::primaryDisplayOrientation);

    mPrimaryDispSync =
            getFactory().createDispSync("PrimaryDispSync", SurfaceFlinger::hasSyncFramework,
                                        SurfaceFlinger::dispSyncPresentTimeOffset);

    auto surfaceFlingerConfigsServiceV1_2 = V1_2::ISurfaceFlingerConfigs::getService();
    if (surfaceFlingerConfigsServiceV1_2) {
        surfaceFlingerConfigsServiceV1_2->getDisplayNativePrimaries(
@@ -400,6 +396,12 @@ SurfaceFlinger::SurfaceFlinger(surfaceflinger::Factory& factory)
    property_get("debug.sf.use_scheduler", value, "0");
    mUseScheduler = atoi(value);

    if (!mUseScheduler) {
        mPrimaryDispSync =
                getFactory().createDispSync("PrimaryDispSync", SurfaceFlinger::hasSyncFramework,
                                            SurfaceFlinger::dispSyncPresentTimeOffset);
    }

    const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
    mVsyncModulator.setPhaseOffsets(early, gl, late);

@@ -719,8 +721,10 @@ void SurfaceFlinger::init() {
        }
    }

    if (!mUseScheduler) {
        mEventControlThread = getFactory().createEventControlThread(
                [this](bool enabled) { setPrimaryVsyncEnabled(enabled); });
    }

    // initialize our drawing state
    mDrawingState = mCurrentState;
@@ -822,14 +826,12 @@ status_t SurfaceFlinger::getSupportedFrameTimestamps(
    return NO_ERROR;
}

status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& displayToken,
status_t SurfaceFlinger::getDisplayConfigsLocked(const sp<IBinder>& displayToken,
                                                 Vector<DisplayInfo>* configs) {
    if (!displayToken || !configs) {
        return BAD_VALUE;
    }

    ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);

    const auto displayId = getPhysicalDisplayIdLocked(displayToken);
    if (!displayId) {
        return NAME_NOT_FOUND;
@@ -957,22 +959,19 @@ int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) {
    return display->getActiveConfig();
}

status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
    ATRACE_NAME("setActiveConfigSync");
    postMessageSync(new LambdaMessage(
            [&]() NO_THREAD_SAFETY_ANALYSIS { setActiveConfigInternal(displayToken, mode); }));
    return NO_ERROR;
}
void SurfaceFlinger::setDesiredActiveConfig(const sp<IBinder>& displayToken, int mode) {
    ATRACE_CALL();

void SurfaceFlinger::setActiveConfigInternal(const sp<IBinder>& displayToken, int mode) {
    Vector<DisplayInfo> configs;
    getDisplayConfigs(displayToken, &configs);
    // Lock is acquired by setRefreshRateTo.
    getDisplayConfigsLocked(displayToken, &configs);
    if (mode < 0 || mode >= static_cast<int>(configs.size())) {
        ALOGE("Attempt to set active config %d for display with %zu configs", mode, configs.size());
        return;
    }

    const auto display = getDisplayDevice(displayToken);
    // Lock is acquired by setRefreshRateTo.
    const auto display = getDisplayDeviceLocked(displayToken);
    if (!display) {
        ALOGE("Attempt to set active config %d for invalid display token %p", mode,
              displayToken.get());
@@ -988,23 +987,95 @@ void SurfaceFlinger::setActiveConfigInternal(const sp<IBinder>& displayToken, in
        return;
    }

    int currentMode = display->getActiveConfig();
    if (mode == currentMode) {
        // Don't update config if we are already running in the desired mode.
        return;
    // Don't check against the current mode yet. Worst case we set the desired
    // config twice.
    {
        std::lock_guard<std::mutex> lock(mActiveConfigLock);
        mDesiredActiveConfig = ActiveConfigInfo{mode, displayToken};
    }
    if (mUseScheduler) {
        mRefreshRateStats->setConfigMode(mode);
    // This will trigger HWC refresh without resetting the idle timer.
    repaintEverythingForHWC();
}

status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
    ATRACE_CALL();
    postMessageSync(new LambdaMessage(
            [&]() NO_THREAD_SAFETY_ANALYSIS { setDesiredActiveConfig(displayToken, mode); }));
    return NO_ERROR;
}

void SurfaceFlinger::setActiveConfigInHWC() {
    ATRACE_CALL();

    const auto display = getDisplayDevice(mUpcomingActiveConfig.displayToken);
    if (!display) {
        return;
    }
    const auto displayId = display->getId();
    LOG_ALWAYS_FATAL_IF(!displayId);

    display->setActiveConfig(mode);
    getHwComposer().setActiveConfig(*displayId, mode);
    ATRACE_INT("ActiveConfigModeHWC", mUpcomingActiveConfig.configId);
    getHwComposer().setActiveConfig(*displayId, mUpcomingActiveConfig.configId);
    mSetActiveConfigState = SetActiveConfigState::NOTIFIED_HWC;
    ATRACE_INT("SetActiveConfigState", mSetActiveConfigState);
}

void SurfaceFlinger::setActiveConfigInternal() {
    ATRACE_CALL();

    std::lock_guard<std::mutex> lock(mActiveConfigLock);
    if (mUseScheduler) {
        mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId);
    }

    const auto display = getDisplayDeviceLocked(mUpcomingActiveConfig.displayToken);
    display->setActiveConfig(mUpcomingActiveConfig.configId);

    mSetActiveConfigState = SetActiveConfigState::NONE;
    ATRACE_INT("SetActiveConfigState", mSetActiveConfigState);

    ATRACE_INT("ActiveConfigMode", mode);
    resyncToHardwareVsync(true, getVsyncPeriod());
    ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId);
}

bool SurfaceFlinger::updateSetActiveConfigStateMachine() NO_THREAD_SAFETY_ANALYSIS {
    // Store the local variable to release the lock.
    ActiveConfigInfo desiredActiveConfig;
    {
        std::lock_guard<std::mutex> lock(mActiveConfigLock);
        desiredActiveConfig = mDesiredActiveConfig;
    }

    const auto display = getDisplayDevice(desiredActiveConfig.displayToken);
    if (display) {
        if (mSetActiveConfigState == SetActiveConfigState::NONE &&
            display->getActiveConfig() != desiredActiveConfig.configId) {
            // Step 1) Desired active config was set, it is different than the
            // config currently in use. Notify HWC.
            mUpcomingActiveConfig = desiredActiveConfig;
            setActiveConfigInHWC();
        } else if (mSetActiveConfigState == SetActiveConfigState::NOTIFIED_HWC) {
            // Step 2) HWC was notified and we received refresh from it.
            mSetActiveConfigState = SetActiveConfigState::REFRESH_RECEIVED;
            ATRACE_INT("SetActiveConfigState", mSetActiveConfigState);
            repaintEverythingForHWC();
            // We do not want to give another frame to HWC while we are transitioning.
            return false;
        } else if (mSetActiveConfigState == SetActiveConfigState::REFRESH_RECEIVED &&
                   !(mPreviousPresentFence != Fence::NO_FENCE &&
                     (mPreviousPresentFence->getStatus() == Fence::Status::Unsignaled))) {
            // Step 3) We received the present fence from the HWC, so we assume it
            // successfully updated the config, hence we update SF.
            setActiveConfigInternal();
            // If the config changed again while we were transitioning, restart the
            // process.
            if (desiredActiveConfig != mUpcomingActiveConfig) {
                mUpcomingActiveConfig = desiredActiveConfig;
                setActiveConfigInHWC(); // sets the state to NOTIFY_HWC
            }
        }
    }
    return true;
}

status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken,
@@ -1332,6 +1403,7 @@ nsecs_t SurfaceFlinger::getVsyncPeriod() const {
}

void SurfaceFlinger::enableHardwareVsync() {
    assert(!mUseScheduler);
    Mutex::Autolock _l(mHWVsyncLock);
    if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
        mPrimaryDispSync->beginResync();
@@ -1374,6 +1446,7 @@ void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable, nsecs_t period) {
}

void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
    assert(!mUseScheduler);
    Mutex::Autolock _l(mHWVsyncLock);
    if (mPrimaryHWVsyncEnabled) {
        mEventControlThread->setVsyncEnabled(false);
@@ -1482,8 +1555,7 @@ void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate) {
        // TODO(b/113612090): There should be a better way at determining which config
        // has the right refresh rate.
        if (std::abs(fps - newFps) <= 1) {
            setActiveConfigInternal(getInternalDisplayTokenLocked(), i);
            ATRACE_INT("FPS", newFps);
            setDesiredActiveConfig(getInternalDisplayTokenLocked(), i);
        }
    }
}
@@ -1627,14 +1699,16 @@ void SurfaceFlinger::onMessageReceived(int32_t what) {
    ATRACE_CALL();
    switch (what) {
        case MessageQueue::INVALIDATE: {
            if (!updateSetActiveConfigStateMachine()) {
                break;
            }

            if (mUseScheduler) {
                // This call is made each time SF wakes up and creates a new frame.
                mScheduler->incrementFrameCounter();
            }
            bool frameMissed = !mHadClientComposition &&
                    mPreviousPresentFence != Fence::NO_FENCE &&
                    (mPreviousPresentFence->getSignalTime() ==
                            Fence::SIGNAL_TIME_PENDING);
            bool frameMissed = !mHadClientComposition && mPreviousPresentFence != Fence::NO_FENCE &&
                    (mPreviousPresentFence->getStatus() == Fence::Status::Unsignaled);
            mFrameMissedCount += frameMissed;
            ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
            if (frameMissed) {
@@ -3041,7 +3115,12 @@ void SurfaceFlinger::updateCursorAsync()

void SurfaceFlinger::latchAndReleaseBuffer(const sp<Layer>& layer) {
    if (layer->hasReadyFrame()) {
        const nsecs_t expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
        nsecs_t expectedPresentTime;
        if (mUseScheduler) {
            expectedPresentTime = mScheduler->expectedPresentTime();
        } else {
            expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
        }
        if (layer->shouldPresentNow(expectedPresentTime)) {
            bool ignored = false;
            layer->latchBuffer(ignored, systemTime(), Fence::NO_FENCE);
@@ -3273,7 +3352,12 @@ bool SurfaceFlinger::handlePageFlip()
    mDrawingState.traverseInZOrder([&](Layer* layer) {
        if (layer->hasReadyFrame()) {
            frameQueued = true;
            const nsecs_t expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
            nsecs_t expectedPresentTime;
            if (mUseScheduler) {
                expectedPresentTime = mScheduler->expectedPresentTime();
            } else {
                expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
            }
            if (layer->shouldPresentNow(expectedPresentTime)) {
                mLayersWithQueuedFrames.push_back(layer);
            } else {
@@ -3614,7 +3698,12 @@ bool SurfaceFlinger::containsAnyInvalidClientState(const Vector<ComposerState>&

bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
                                                   const Vector<ComposerState>& states) {
    const nsecs_t expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
    nsecs_t expectedPresentTime;
    if (mUseScheduler) {
        expectedPresentTime = mScheduler->expectedPresentTime();
    } else {
        expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
    }
    // Do not present if the desiredPresentTime has not passed unless it is more than one second
    // in the future. We ignore timestamps more than 1 second in the future for stability reasons.
    if (desiredPresentTime >= 0 && desiredPresentTime >= expectedPresentTime &&
Loading