diff options
author | 2017-04-04 10:51:39 -0700 | |
---|---|---|
committer | 2017-04-11 14:51:42 -0700 | |
commit | 6b376713907086c9642e7b7e66e51ddfa531b003 (patch) | |
tree | 85a14f06713e9d2fb5f977737136e0242f778cfa | |
parent | 99dfb8a6466b653afc63ed91f07f59daa3c66385 (diff) |
egl: Avoid use of retire as present
Retire fences from HWC1 are implemented inconsitently,
so present emulation doesn't always work well.
This patch disables present for all HWC1 based devices.
Test: adb shell /data/nativetest/libgui_test/libgui_test
--gtest_filter=*GetFrameTimestamps*
Bug: 36730849, 36887025
Change-Id: I1eba2f8490c2f6feced2a36d1efc4cd66be7da40
-rw-r--r-- | include/gui/ISurfaceComposer.h | 5 | ||||
-rw-r--r-- | include/gui/Surface.h | 4 | ||||
-rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 63 | ||||
-rw-r--r-- | libs/gui/Surface.cpp | 40 | ||||
-rw-r--r-- | libs/gui/tests/Surface_test.cpp | 76 | ||||
-rw-r--r-- | libs/hwc2on1adapter/HWC2On1Adapter.cpp | 5 | ||||
-rw-r--r-- | libs/nativewindow/include/system/window.h | 6 | ||||
-rw-r--r-- | opengl/libs/EGL/eglApi.cpp | 7 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 19 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 15 |
11 files changed, 235 insertions, 7 deletions
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index 2fbe07aa57..9870ba0715 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -126,6 +126,11 @@ public: virtual bool authenticateSurfaceTexture( const sp<IGraphicBufferProducer>& surface) const = 0; + /* Returns the frame timestamps supported by SurfaceFlinger. + */ + virtual status_t getSupportedFrameTimestamps( + std::vector<FrameEvent>* outSupported) const = 0; + /* set display power mode. depending on the mode, it can either trigger * screen on, off or low power mode and wait for it to complete. * requires ACCESS_SURFACE_FLINGER permission. diff --git a/include/gui/Surface.h b/include/gui/Surface.h index 88ef010368..8b1d1069b3 100644 --- a/include/gui/Surface.h +++ b/include/gui/Surface.h @@ -426,6 +426,10 @@ protected: uint64_t mNextFrameNumber = 1; uint64_t mLastFrameNumber = 0; + // Mutable because ANativeWindow::query needs this class const. + mutable bool mQueriedSupportedTimestamps; + mutable bool mFrameTimestampsSupportsPresent; + // A cached copy of the FrameEventHistory maintained by the consumer. bool mEnableFrameTimestamps = false; std::unique_ptr<ProducerFrameEventHistory> mFrameEventHistory; diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 5a32d0524a..4d2692fe62 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -166,6 +166,50 @@ public: return result != 0; } + virtual status_t getSupportedFrameTimestamps( + std::vector<FrameEvent>* outSupported) const { + if (!outSupported) { + return UNEXPECTED_NULL; + } + outSupported->clear(); + + Parcel data, reply; + + status_t err = data.writeInterfaceToken( + ISurfaceComposer::getInterfaceDescriptor()); + if (err != NO_ERROR) { + return err; + } + + err = remote()->transact( + BnSurfaceComposer::GET_SUPPORTED_FRAME_TIMESTAMPS, + data, &reply); + if (err != NO_ERROR) { + return err; + } + + int32_t result = 0; + err = reply.readInt32(&result); + if (err != NO_ERROR) { + return err; + } + if (result != NO_ERROR) { + return result; + } + + std::vector<int32_t> supported; + err = reply.readInt32Vector(&supported); + if (err != NO_ERROR) { + return err; + } + + outSupported->reserve(supported.size()); + for (int32_t s : supported) { + outSupported->push_back(static_cast<FrameEvent>(s)); + } + return NO_ERROR; + } + virtual sp<IDisplayEventConnection> createDisplayEventConnection() { Parcel data, reply; @@ -536,6 +580,25 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(result); return NO_ERROR; } + case GET_SUPPORTED_FRAME_TIMESTAMPS: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + std::vector<FrameEvent> supportedTimestamps; + status_t result = getSupportedFrameTimestamps(&supportedTimestamps); + status_t err = reply->writeInt32(result); + if (err != NO_ERROR) { + return err; + } + if (result != NO_ERROR) { + return result; + } + + std::vector<int32_t> supported; + supported.reserve(supportedTimestamps.size()); + for (FrameEvent s : supportedTimestamps) { + supported.push_back(static_cast<int32_t>(s)); + } + return reply->writeInt32Vector(supported); + } case CREATE_DISPLAY_EVENT_CONNECTION: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IDisplayEventConnection> connection(createDisplayEventConnection()); diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 1149b8980b..41221aab8d 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -52,6 +52,8 @@ Surface::Surface( mAutoRefresh(false), mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT), mSharedBufferHasBeenQueued(false), + mQueriedSupportedTimestamps(false), + mFrameTimestampsSupportsPresent(false), mEnableFrameTimestamps(false), mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>()) { @@ -209,8 +211,8 @@ static bool checkConsumerForUpdates( bool checkForDisplayPresent = (outDisplayPresentTime != nullptr) && !e->hasDisplayPresentInfo(); - // LastRefreshStart, DequeueReady, and Release are never - // available for the last frame. + // LastRefreshStart, DequeueReady, and Release are never available for the + // last frame. bool checkForLastRefreshStart = (outLastRefreshStartTime != nullptr) && !e->hasLastRefreshStartInfo() && (e->frameNumber != lastFrameNumber); @@ -252,6 +254,12 @@ status_t Surface::getFrameTimestamps(uint64_t frameNumber, return INVALID_OPERATION; } + // Verify the requested timestamps are supported. + querySupportedTimestampsLocked(); + if (outDisplayPresentTime != nullptr && !mFrameTimestampsSupportsPresent) { + return BAD_VALUE; + } + FrameEvents* events = mFrameEventHistory->getFrame(frameNumber); if (events == nullptr) { // If the entry isn't available in the producer, it's definitely not @@ -739,6 +747,29 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { return err; } +void Surface::querySupportedTimestampsLocked() const { + // mMutex must be locked when calling this method. + + if (mQueriedSupportedTimestamps) { + return; + } + mQueriedSupportedTimestamps = true; + + std::vector<FrameEvent> supportedFrameTimestamps; + status_t err = composerService()->getSupportedFrameTimestamps( + &supportedFrameTimestamps); + + if (err != NO_ERROR) { + return; + } + + for (auto sft : supportedFrameTimestamps) { + if (sft == FrameEvent::DISPLAY_PRESENT) { + mFrameTimestampsSupportsPresent = true; + } + } +} + int Surface::query(int what, int* value) const { ATRACE_CALL(); ALOGV("Surface::query"); @@ -800,6 +831,11 @@ int Surface::query(int what, int* value) const { static_cast<int>(durationUs); return NO_ERROR; } + case NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT: { + querySupportedTimestampsLocked(); + *value = mFrameTimestampsSupportsPresent ? 1 : 0; + return NO_ERROR; + } case NATIVE_WINDOW_IS_VALID: { *value = mGraphicBufferProducer != nullptr ? 1 : 0; return NO_ERROR; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index ce114864aa..00a374d273 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -368,6 +368,10 @@ class FakeSurfaceComposer : public ISurfaceComposer{ public: ~FakeSurfaceComposer() override {} + void setSupportsPresent(bool supportsPresent) { + mSupportsPresent = supportsPresent; + } + sp<ISurfaceComposerClient> createConnection() override { return nullptr; } sp<ISurfaceComposerClient> createScopedConnection( const sp<IGraphicBufferProducer>& /* parent */) override { @@ -391,6 +395,26 @@ public: const sp<IGraphicBufferProducer>& /*surface*/) const override { return false; } + + status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) + const override { + *outSupported = { + FrameEvent::REQUESTED_PRESENT, + FrameEvent::ACQUIRE, + FrameEvent::LATCH, + FrameEvent::FIRST_REFRESH_START, + FrameEvent::LAST_REFRESH_START, + FrameEvent::GPU_COMPOSITION_DONE, + FrameEvent::DEQUEUE_READY, + FrameEvent::RELEASE + }; + if (mSupportsPresent) { + outSupported->push_back( + FrameEvent::DISPLAY_PRESENT); + } + return NO_ERROR; + } + void setPowerMode(const sp<IBinder>& /*display*/, int /*mode*/) override {} status_t getDisplayConfigs(const sp<IBinder>& /*display*/, Vector<DisplayInfo>* /*configs*/) override { return NO_ERROR; } @@ -435,7 +459,6 @@ protected: private: bool mSupportsPresent{true}; - bool mSupportsRetire{true}; }; class FakeProducerFrameEventHistory : public ProducerFrameEventHistory { @@ -864,6 +887,28 @@ TEST_F(GetFrameTimestampsTest, EnabledSimple) { EXPECT_EQ(4, mFakeConsumer->mGetFrameTimestampsCount); } +TEST_F(GetFrameTimestampsTest, QueryPresentSupported) { + bool displayPresentSupported = true; + mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported); + + // Verify supported bits are forwarded. + int supportsPresent = -1; + mWindow.get()->query(mWindow.get(), + NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &supportsPresent); + EXPECT_EQ(displayPresentSupported, supportsPresent); +} + +TEST_F(GetFrameTimestampsTest, QueryPresentNotSupported) { + bool displayPresentSupported = false; + mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported); + + // Verify supported bits are forwarded. + int supportsPresent = -1; + mWindow.get()->query(mWindow.get(), + NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &supportsPresent); + EXPECT_EQ(displayPresentSupported, supportsPresent); +} + TEST_F(GetFrameTimestampsTest, SnapToNextTickBasic) { nsecs_t phase = 4000; nsecs_t interval = 1000; @@ -1228,8 +1273,8 @@ TEST_F(GetFrameTimestampsTest, ZeroRequestedTimestampsNoSync) { // Verify a request for no timestamps doesn't result in a sync call. int oldCount = mFakeConsumer->mGetFrameTimestampsCount; int result = native_window_get_frame_timestamps(mWindow.get(), fId2, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr); + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); } @@ -1371,7 +1416,7 @@ TEST_F(GetFrameTimestampsTest, NoGpuNoSync) { // This test verifies that if the certain timestamps can't possibly exist for // the most recent frame, then a sync call is not done. -TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) { +TEST_F(GetFrameTimestampsTest, NoReleaseNoSync) { enableFrameTimestamps(); // Dequeue and queue frame 1. @@ -1431,4 +1476,27 @@ TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) { EXPECT_EQ(0, outReleaseTime); } +// This test verifies there are no sync calls for present times +// when they aren't supported and that an error is returned. + +TEST_F(GetFrameTimestampsTest, PresentUnsupportedNoSync) { + enableFrameTimestamps(); + mSurface->mFakeSurfaceComposer->setSupportsPresent(false); + + // Dequeue and queue frame 1. + const uint64_t fId1 = getNextFrameId(); + dequeueAndQueue(0); + + // Verify a query for the Present times do not trigger a sync call if they + // are not supported. + resetTimestamps(); + int oldCount = mFakeConsumer->mGetFrameTimestampsCount; + int result = native_window_get_frame_timestamps(mWindow.get(), fId1, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + &outDisplayPresentTime, nullptr, nullptr); + EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); + EXPECT_EQ(BAD_VALUE, result); + EXPECT_EQ(-1, outDisplayPresentTime); +} + } diff --git a/libs/hwc2on1adapter/HWC2On1Adapter.cpp b/libs/hwc2on1adapter/HWC2On1Adapter.cpp index e35bfc9fea..8c6ef691a2 100644 --- a/libs/hwc2on1adapter/HWC2On1Adapter.cpp +++ b/libs/hwc2on1adapter/HWC2On1Adapter.cpp @@ -2246,6 +2246,11 @@ void HWC2On1Adapter::populateCapabilities() { mHwc1SupportsBackgroundColor = true; } } + + // Some devices might have HWC1 retire fences that accurately emulate + // HWC2 present fences when they are deferred, but it's not very reliable. + // To be safe, we indicate PresentFenceIsNotReliable for all HWC1 devices. + mCapabilities.insert(Capability::PresentFenceIsNotReliable); } HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) { diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index 63d1ad18a7..0251aedeac 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -186,6 +186,12 @@ enum { * if it is safe (i.e. no crash will occur) to call any method on it. */ NATIVE_WINDOW_IS_VALID = 17, + + /* + * Returns 1 if NATIVE_WINDOW_GET_FRAME_TIMESTAMPS will return display + * present info, 0 if it won't. + */ + NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT = 18, }; /* Valid operations for the (*perform)() hook. diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index b00d4013bc..0807d1f52c 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -2166,10 +2166,15 @@ EGLBoolean eglGetFrameTimestampSupportedANDROID( case EGL_FIRST_COMPOSITION_START_TIME_ANDROID: case EGL_LAST_COMPOSITION_START_TIME_ANDROID: case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID: - case EGL_DISPLAY_PRESENT_TIME_ANDROID: case EGL_DEQUEUE_READY_TIME_ANDROID: case EGL_READS_DONE_TIME_ANDROID: return EGL_TRUE; + case EGL_DISPLAY_PRESENT_TIME_ANDROID: { + int value = 0; + window->query(window, + NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value); + return value == 0 ? EGL_FALSE : EGL_TRUE; + } default: return EGL_FALSE; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 26baaaecb2..c523407f20 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -651,6 +651,25 @@ bool SurfaceFlinger::authenticateSurfaceTextureLocked( return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0; } +status_t SurfaceFlinger::getSupportedFrameTimestamps( + std::vector<FrameEvent>* outSupported) const { + *outSupported = { + FrameEvent::REQUESTED_PRESENT, + FrameEvent::ACQUIRE, + FrameEvent::LATCH, + FrameEvent::FIRST_REFRESH_START, + FrameEvent::LAST_REFRESH_START, + FrameEvent::GPU_COMPOSITION_DONE, + FrameEvent::DEQUEUE_READY, + FrameEvent::RELEASE, + }; + if (!getHwComposer().hasCapability( + HWC2::Capability::PresentFenceIsNotReliable)) { + outSupported->push_back(FrameEvent::DISPLAY_PRESENT); + } + return NO_ERROR; +} + status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayInfo>* configs) { if ((configs == NULL) || (display.get() == NULL)) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 46121cfa63..69655ed461 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -265,6 +265,8 @@ private: virtual void bootFinished(); virtual bool authenticateSurfaceTexture( const sp<IGraphicBufferProducer>& bufferProducer) const; + virtual status_t getSupportedFrameTimestamps( + std::vector<FrameEvent>* outSupported) const; virtual sp<IDisplayEventConnection> createDisplayEventConnection(); virtual status_t captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index e640ef71ee..a237ae3f24 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -647,6 +647,21 @@ bool SurfaceFlinger::authenticateSurfaceTextureLocked( return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0; } +status_t SurfaceFlinger::getSupportedFrameTimestamps( + std::vector<FrameEvent>* outSupported) const { + *outSupported = { + FrameEvent::REQUESTED_PRESENT, + FrameEvent::ACQUIRE, + FrameEvent::LATCH, + FrameEvent::FIRST_REFRESH_START, + FrameEvent::LAST_REFRESH_START, + FrameEvent::GPU_COMPOSITION_DONE, + FrameEvent::DEQUEUE_READY, + FrameEvent::RELEASE, + }; + return NO_ERROR; +} + status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayInfo>* configs) { if ((configs == NULL) || (display.get() == NULL)) { |