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

Commit cd5edad6 authored by Huihong Luo's avatar Huihong Luo Committed by Android (Google) Code Review
Browse files

Merge "Round up virtual display refresh rate" into udc-dev

parents f8538d60 59a60b7b
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -535,8 +535,8 @@ void DisplayDevice::clearDesiredActiveModeState() {
}

void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) {
    using fps_approx_ops::operator==;
    if (mRequestedRefreshRate == 0_Hz) {
    using fps_approx_ops::operator<=;
    if (mRequestedRefreshRate <= 0_Hz) {
        return;
    }

@@ -547,7 +547,12 @@ void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) {
    }

    unsigned divisor = static_cast<unsigned>(
            std::round(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue()));
            std::floor(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue()));
    if (divisor == 0) {
        mAdjustedRefreshRate = 0_Hz;
        return;
    }

    mAdjustedRefreshRate = pacesetterDisplayRefreshRate / divisor;
}

+1 −1
Original line number Diff line number Diff line
@@ -499,7 +499,7 @@ private:

    // Implements ISurfaceComposer
    sp<IBinder> createDisplay(const String8& displayName, bool secure,
                              float requestedRefreshRate = 0);
                              float requestedRefreshRate = 0.0f);
    void destroyDisplay(const sp<IBinder>& displayToken);
    std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const EXCLUDES(mStateLock) {
        Mutex::Autolock lock(mStateLock);
+126 −1
Original line number Diff line number Diff line
@@ -17,12 +17,60 @@
#undef LOG_TAG
#define LOG_TAG "LibSurfaceFlingerUnittests"

#include <scheduler/Fps.h>

#include "DisplayTransactionTestHelpers.h"
#include "FpsOps.h"

namespace android {
namespace {

class CreateDisplayTest : public DisplayTransactionTest {};
class CreateDisplayTest : public DisplayTransactionTest {
public:
    void createDisplayWithRequestedRefreshRate(const String8& name, uint64_t displayId,
                                               float pacesetterDisplayRefreshRate,
                                               float requestedRefreshRate,
                                               float expectedAdjustedRefreshRate) {
        // --------------------------------------------------------------------
        // Call Expectations

        // --------------------------------------------------------------------
        // Invocation

        sp<IBinder> displayToken = mFlinger.createDisplay(name, false, requestedRefreshRate);

        // --------------------------------------------------------------------
        // Postconditions

        // The display should have been added to the current state
        ASSERT_TRUE(hasCurrentDisplayState(displayToken));
        const auto& display = getCurrentDisplayState(displayToken);
        EXPECT_TRUE(display.isVirtual());
        EXPECT_EQ(display.requestedRefreshRate, Fps::fromValue(requestedRefreshRate));
        EXPECT_EQ(name.string(), display.displayName);

        std::optional<VirtualDisplayId> vid =
                DisplayId::fromValue<VirtualDisplayId>(displayId | DisplayId::FLAG_VIRTUAL);
        ASSERT_TRUE(vid.has_value());

        sp<DisplayDevice> device =
                mFlinger.createVirtualDisplayDevice(displayToken, *vid, requestedRefreshRate);
        EXPECT_TRUE(device->isVirtual());
        device->adjustRefreshRate(Fps::fromValue(pacesetterDisplayRefreshRate));
        // verifying desired value
        EXPECT_EQ(device->getAdjustedRefreshRate(), Fps::fromValue(expectedAdjustedRefreshRate));
        // verifying rounding up
        if (requestedRefreshRate < pacesetterDisplayRefreshRate) {
            EXPECT_GE(device->getAdjustedRefreshRate(), Fps::fromValue(requestedRefreshRate));
        } else {
            EXPECT_EQ(device->getAdjustedRefreshRate(),
                      Fps::fromValue(pacesetterDisplayRefreshRate));
        }

        // --------------------------------------------------------------------
        // Cleanup conditions
    }
};

TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForNonsecureDisplay) {
    const String8 name("virtual.test");
@@ -84,5 +132,82 @@ TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForSecureDisplay) {
    EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
}

// Requesting 0 tells SF not to do anything, i.e., default to refresh as physical displays
TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRate0) {
    const String8 displayName("virtual.test");
    const uint64_t displayId = 123ull;
    const float kPacesetterDisplayRefreshRate = 60.f;
    const float kRequestedRefreshRate = 0.f;
    const float kExpectedAdjustedRefreshRate = 0.f;
    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
                                          kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
}

// Requesting negative refresh rate, will be ignored, same as requesting 0
TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNegative) {
    const String8 displayName("virtual.test");
    const uint64_t displayId = 123ull;
    const float kPacesetterDisplayRefreshRate = 60.f;
    const float kRequestedRefreshRate = -60.f;
    const float kExpectedAdjustedRefreshRate = 0.f;
    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
                                          kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
}

// Requesting a higher refresh rate than the pacesetter
TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateHigh) {
    const String8 displayName("virtual.test");
    const uint64_t displayId = 123ull;
    const float kPacesetterDisplayRefreshRate = 60.f;
    const float kRequestedRefreshRate = 90.f;
    const float kExpectedAdjustedRefreshRate = 60.f;
    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
                                          kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
}

// Requesting the same refresh rate as the pacesetter
TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateSame) {
    const String8 displayName("virtual.test");
    const uint64_t displayId = 123ull;
    const float kPacesetterDisplayRefreshRate = 60.f;
    const float kRequestedRefreshRate = 60.f;
    const float kExpectedAdjustedRefreshRate = 60.f;
    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
                                          kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
}

// Requesting a divisor (30) of the pacesetter (60) should be honored
TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateDivisor) {
    const String8 displayName("virtual.test");
    const uint64_t displayId = 123ull;
    const float kPacesetterDisplayRefreshRate = 60.f;
    const float kRequestedRefreshRate = 30.f;
    const float kExpectedAdjustedRefreshRate = 30.f;
    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
                                          kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
}

// Requesting a non divisor (45) of the pacesetter (120) should round up to a divisor (60)
TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNoneDivisor) {
    const String8 displayName("virtual.test");
    const uint64_t displayId = 123ull;
    const float kPacesetterDisplayRefreshRate = 120.f;
    const float kRequestedRefreshRate = 45.f;
    const float kExpectedAdjustedRefreshRate = 60.f;
    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
                                          kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
}

// Requesting a non divisor (75) of the pacesetter (120) should round up to pacesetter (120)
TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNoneDivisorMax) {
    const String8 displayName("virtual.test");
    const uint64_t displayId = 123ull;
    const float kPacesetterDisplayRefreshRate = 120.f;
    const float kRequestedRefreshRate = 75.f;
    const float kExpectedAdjustedRefreshRate = 120.f;
    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
                                          kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
}

} // namespace
} // namespace android
+23 −2
Original line number Diff line number Diff line
@@ -48,10 +48,12 @@
#include "TestableScheduler.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockDisplayMode.h"
#include "mock/DisplayHardware/MockPowerAdvisor.h"
#include "mock/MockEventThread.h"
#include "mock/MockFrameTimeline.h"
#include "mock/MockFrameTracer.h"
#include "mock/MockSchedulerCallback.h"
#include "mock/system/window/MockNativeWindow.h"

namespace android {
namespace renderengine {
@@ -375,8 +377,8 @@ public:

    void commitAndComposite() { mFlinger->composite(commit(), kVsyncId); }

    auto createDisplay(const String8& displayName, bool secure) {
        return mFlinger->createDisplay(displayName, secure);
    auto createDisplay(const String8& displayName, bool secure, float requestedRefreshRate = 0.0f) {
        return mFlinger->createDisplay(displayName, secure, requestedRefreshRate);
    }

    auto destroyDisplay(const sp<IBinder>& displayToken) {
@@ -525,6 +527,24 @@ public:
        mFlinger->getDynamicDisplayInfoFromToken(displayToken, dynamicDisplayInfo);
    }

    sp<DisplayDevice> createVirtualDisplayDevice(const sp<IBinder> displayToken,
                                                 VirtualDisplayId displayId,
                                                 float requestedRefreshRate) {
        constexpr ui::Size kResolution = {1080, 1920};
        auto compositionDisplay = compositionengine::impl::
                createDisplay(mFlinger->getCompositionEngine(),
                              compositionengine::DisplayCreationArgsBuilder()
                                      .setId(displayId)
                                      .setPixels(kResolution)
                                      .setPowerAdvisor(&mPowerAdvisor)
                                      .build());
        DisplayDeviceCreationArgs creationArgs(mFlinger, mFlinger->getHwComposer(), displayToken,
                                               compositionDisplay);
        creationArgs.requestedRefreshRate = Fps::fromValue(requestedRefreshRate);
        creationArgs.nativeWindow = sp<mock::NativeWindow>::make();
        return sp<DisplayDevice>::make(creationArgs);
    }

    /* ------------------------------------------------------------------------
     * Read-only access to private data to assert post-conditions.
     */
@@ -962,6 +982,7 @@ private:
    scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback;
    std::unique_ptr<frametimeline::impl::TokenManager> mTokenManager;
    scheduler::TestableScheduler* mScheduler = nullptr;
    Hwc2::mock::PowerAdvisor mPowerAdvisor;
};

} // namespace android