diff options
author | 2018-07-13 12:59:48 -0700 | |
---|---|---|
committer | 2018-08-07 12:36:42 -0700 | |
commit | 6d46c1e2bb6ac6a90c7cb4993e920443a6fcecfe (patch) | |
tree | 5fa34eccc6b882c5e86f3ab7542bad2e6103761c | |
parent | 0c2a6f8cc9d5be9e93f247cdbe55729972b8a270 (diff) |
SF: enable high refresh rate virtual mode
Add support for SF backdoor to set a multiplier
and divisor on the period for VSYNC-sf and
VSYNC-app from the primary DispSync object.
Bug: 111549030
Test: enable high refresh rate in devOptions and
view with systrace
Change-Id: I4226d5791d8d7ddeae1ad96577713c9c2141ed58
-rw-r--r-- | services/surfaceflinger/DispSync.cpp | 18 | ||||
-rw-r--r-- | services/surfaceflinger/DispSync.h | 8 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWC2.h | 12 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 27 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/mock/MockDispSync.h | 1 |
5 files changed, 63 insertions, 3 deletions
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index cdfbba32dd..b789d04ce9 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -515,12 +515,26 @@ status_t DispSync::changePhaseOffset(Callback* callback, nsecs_t phase) { void DispSync::setPeriod(nsecs_t period) { Mutex::Autolock lock(mMutex); - mPeriod = period; + mPeriodBase = mPeriod = period; mPhase = 0; mReferenceTime = 0; mThread->updateModel(mPeriod, mPhase, mReferenceTime); } +void DispSync::scalePeriod(uint32_t multiplier, uint32_t divisor) { + Mutex::Autolock lock(mMutex); + + // if only 1 of the properties is updated, we will get to this + // point "attempting" to set the scale to 1 when it is already + // 1. Check that special case so that we don't do a useless + // update of the model. + if ((multiplier == 1) && (divisor == 1) && (mPeriod == mPeriodBase)) + return; + + mPeriod = mPeriodBase * multiplier / divisor; + mThread->updateModel(mPeriod, mPhase, mReferenceTime); +} + nsecs_t DispSync::getPeriod() { // lock mutex as mPeriod changes multiple times in updateModelLocked Mutex::Autolock lock(mMutex); @@ -545,7 +559,7 @@ void DispSync::updateModelLocked() { // Exclude the min and max from the average durationSum -= minDuration + maxDuration; - mPeriod = durationSum / (mNumResyncSamples - 3); + mPeriodBase = mPeriod = durationSum / (mNumResyncSamples - 3); ALOGV("[%s] mPeriod = %" PRId64, mName, ns2us(mPeriod)); diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h index 1be131ff6e..183966feba 100644 --- a/services/surfaceflinger/DispSync.h +++ b/services/surfaceflinger/DispSync.h @@ -48,6 +48,7 @@ public: virtual bool addResyncSample(nsecs_t timestamp) = 0; virtual void endResync() = 0; virtual void setPeriod(nsecs_t period) = 0; + virtual void scalePeriod(const uint32_t multiplier, uint32_t divisor) = 0; virtual nsecs_t getPeriod() = 0; virtual void setRefreshSkipCount(int count) = 0; virtual status_t addEventListener(const char* name, nsecs_t phase, Callback* callback) = 0; @@ -117,6 +118,12 @@ public: // turned on. It should NOT be used after that. void setPeriod(nsecs_t period) override; + // The scalePeriod method applies the multiplier and divisor to + // scale the vsync event model's period. The function is added + // for an experimental test mode and should not be used outside + // of that purpose. + void scalePeriod(const uint32_t multiplier, uint32_t divisor); + // The getPeriod method returns the current vsync period. nsecs_t getPeriod() override; @@ -176,6 +183,7 @@ private: // mPeriod is the computed period of the modeled vsync events in // nanoseconds. nsecs_t mPeriod; + nsecs_t mPeriodBase; // mPhase is the phase offset of the modeled vsync events. It is the // number of nanoseconds from time 0 to the first vsync event. diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 900b3d7304..e0d6eccb1c 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -23,6 +23,7 @@ #undef HWC2_INCLUDE_STRINGIFICATION #undef HWC2_USE_CPP11 +#include <cutils/properties.h> #include <gui/HdrMetadata.h> #include <math/mat4.h> #include <ui/GraphicTypes.h> @@ -160,6 +161,8 @@ public: } Builder& setVsyncPeriod(int32_t vsyncPeriod) { mConfig->mVsyncPeriod = vsyncPeriod; + mConfig->mPeriodMultiplier = 1; + mConfig->mPeriodDivisor = 1; return *this; } Builder& setDpiX(int32_t dpiX) { @@ -189,7 +192,12 @@ public: int32_t getWidth() const { return mWidth; } int32_t getHeight() const { return mHeight; } - nsecs_t getVsyncPeriod() const { return mVsyncPeriod; } + nsecs_t getVsyncPeriod() const { + return mVsyncPeriod * mPeriodMultiplier / mPeriodDivisor; } + void scalePanelFrequency(int32_t multiplier, int32_t divisor) const { + mPeriodMultiplier = multiplier; + mPeriodDivisor = divisor; + } float getDpiX() const { return mDpiX; } float getDpiY() const { return mDpiY; } @@ -202,6 +210,8 @@ public: int32_t mWidth; int32_t mHeight; nsecs_t mVsyncPeriod; + mutable int32_t mPeriodMultiplier; + mutable int32_t mPeriodDivisor; float mDpiX; float mDpiY; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 31e44449b3..1c12bd5b96 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4855,6 +4855,33 @@ status_t SurfaceFlinger::onTransact( reply->writeBool(getBE().mHwc->isUsingVrComposer()); return NO_ERROR; } + case 1029: { + // Code 1029 is an experimental feature that allows applications to + // simulate a high frequency panel by setting a multiplier and divisor + // on the VSYNC-sf clock. If either the multiplier or divisor are + // 0, then the code will set both to 1 to return the VSYNC-sf clock + // to it's normal frequency. + int multiplier = data.readInt32(); + int divisor = data.readInt32(); + + if ((multiplier == 0) || (divisor == 0)) { + multiplier = 1; + divisor = 1; + } + + if ((multiplier == 1) && (divisor == 1)) { + enableHardwareVsync(); + } else { + disableHardwareVsync(true); + } + getBE().mHwc->getActiveConfig(DisplayDevice::DISPLAY_PRIMARY) + ->scalePanelFrequency(multiplier, divisor); + mPrimaryDispSync->scalePeriod(multiplier, divisor); + + ATRACE_INT("PeriodMultiplier", multiplier); + ATRACE_INT("PeriodDivisor", divisor); + return NO_ERROR; + } } } return err; diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h index 4a466efd2d..cd8d943dff 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h +++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h @@ -35,6 +35,7 @@ public: MOCK_METHOD1(addResyncSample, bool(nsecs_t)); MOCK_METHOD0(endResync, void()); MOCK_METHOD1(setPeriod, void(nsecs_t)); + MOCK_METHOD2(scalePeriod, void(uint32_t, uint32_t)); MOCK_METHOD0(getPeriod, nsecs_t()); MOCK_METHOD1(setRefreshSkipCount, void(int)); MOCK_METHOD3(addEventListener, status_t(const char*, nsecs_t, Callback*)); |