Merge changes from topic 'presentFenceNotReliable' into oc-dev
* changes:
egl: Use reserved values for eglGetFrameTimestamps
egl: Differentiate pending vs invalid timestamps.
egl: Avoid use of retire as present
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 92251ed..9716be4 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -54,8 +54,7 @@
static constexpr auto EVENT_COUNT =
static_cast<size_t>(FrameEvent::EVENT_COUNT);
static_assert(EVENT_COUNT <= 32, "Event count sanity check failed.");
- static constexpr nsecs_t TIMESTAMP_PENDING =
- std::numeric_limits<nsecs_t>::max();
+ static constexpr nsecs_t TIMESTAMP_PENDING = -2;
static inline bool isValidTimestamp(nsecs_t time) {
return time != TIMESTAMP_PENDING;
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 2fbe07a..9870ba0 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -126,6 +126,11 @@
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 88ef010..8b1d106 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -426,6 +426,10 @@
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 5a32d05..4d2692f 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -166,6 +166,50 @@
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 @@
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 1149b89..a6d9e66 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -52,6 +52,8 @@
mAutoRefresh(false),
mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
mSharedBufferHasBeenQueued(false),
+ mQueriedSupportedTimestamps(false),
+ mFrameTimestampsSupportsPresent(false),
mEnableFrameTimestamps(false),
mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>())
{
@@ -209,8 +211,8 @@
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);
@@ -227,14 +229,26 @@
static void getFrameTimestamp(nsecs_t *dst, const nsecs_t& src) {
if (dst != nullptr) {
- *dst = FrameEvents::isValidTimestamp(src) ? src : 0;
+ // We always get valid timestamps for these eventually.
+ *dst = (src == FrameEvents::TIMESTAMP_PENDING) ?
+ NATIVE_WINDOW_TIMESTAMP_PENDING : src;
}
}
-static void getFrameTimestampFence(nsecs_t *dst, const std::shared_ptr<FenceTime>& src) {
+static void getFrameTimestampFence(nsecs_t *dst,
+ const std::shared_ptr<FenceTime>& src, bool fenceShouldBeKnown) {
if (dst != nullptr) {
+ if (!fenceShouldBeKnown) {
+ *dst = NATIVE_WINDOW_TIMESTAMP_PENDING;
+ return;
+ }
+
nsecs_t signalTime = src->getSignalTime();
- *dst = Fence::isValidTimestamp(signalTime) ? signalTime : 0;
+ *dst = (signalTime == Fence::SIGNAL_TIME_PENDING) ?
+ NATIVE_WINDOW_TIMESTAMP_PENDING :
+ (signalTime == Fence::SIGNAL_TIME_INVALID) ?
+ NATIVE_WINDOW_TIMESTAMP_INVALID :
+ signalTime;
}
}
@@ -252,6 +266,12 @@
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
@@ -282,12 +302,15 @@
getFrameTimestamp(outLastRefreshStartTime, events->lastRefreshStartTime);
getFrameTimestamp(outDequeueReadyTime, events->dequeueReadyTime);
- getFrameTimestampFence(outAcquireTime, events->acquireFence);
- getFrameTimestampFence(
- outGpuCompositionDoneTime, events->gpuCompositionDoneFence);
- getFrameTimestampFence(
- outDisplayPresentTime, events->displayPresentFence);
- getFrameTimestampFence(outReleaseTime, events->releaseFence);
+ getFrameTimestampFence(outAcquireTime, events->acquireFence,
+ events->hasAcquireInfo());
+ getFrameTimestampFence(outGpuCompositionDoneTime,
+ events->gpuCompositionDoneFence,
+ events->hasGpuCompositionDoneInfo());
+ getFrameTimestampFence(outDisplayPresentTime, events->displayPresentFence,
+ events->hasDisplayPresentInfo());
+ getFrameTimestampFence(outReleaseTime, events->releaseFence,
+ events->hasReleaseInfo());
return NO_ERROR;
}
@@ -739,6 +762,29 @@
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 +846,11 @@
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 ce11486..cf3d1b2 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -368,6 +368,10 @@
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 @@
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 @@
private:
bool mSupportsPresent{true};
- bool mSupportsRetire{true};
};
class FakeProducerFrameEventHistory : public ProducerFrameEventHistory {
@@ -864,6 +887,28 @@
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;
@@ -1139,8 +1184,8 @@
EXPECT_EQ(mFrames[1].mRefreshes[0].kGpuCompositionDoneTime,
outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
- EXPECT_EQ(0, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDequeueReadyTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
}
// This test verifies the acquire fence recorded by the consumer is not sent
@@ -1163,7 +1208,7 @@
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
- EXPECT_EQ(0, outAcquireTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outAcquireTime);
// Signal acquire fences. Verify a sync call still isn't necessary.
mFrames[0].signalQueueFences();
@@ -1192,7 +1237,7 @@
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
- EXPECT_EQ(0, outAcquireTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outAcquireTime);
// Signal acquire fences. Verify a sync call still isn't necessary.
mFrames[1].signalQueueFences();
@@ -1228,8 +1273,8 @@
// 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);
}
@@ -1265,10 +1310,10 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
- EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
// Verify available timestamps are correct for frame 1 again, before any
// fence has been signaled.
@@ -1283,10 +1328,10 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
- EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
// Signal the fences for frame 1.
mFrames[0].signalRefreshFences();
@@ -1342,10 +1387,10 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
- EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
// Signal the fences for frame 1.
mFrames[0].signalRefreshFences();
@@ -1363,7 +1408,7 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kPresentTime, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime);
@@ -1371,7 +1416,7 @@
// 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.
@@ -1401,10 +1446,10 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
- EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
mFrames[0].signalRefreshFences();
mFrames[0].signalReleaseFences();
@@ -1425,10 +1470,33 @@
EXPECT_EQ(mFrames[1].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[1].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[1].mRefreshes[1].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
- EXPECT_EQ(0, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDequeueReadyTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, 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 e35bfc9..8c6ef69 100644
--- a/libs/hwc2on1adapter/HWC2On1Adapter.cpp
+++ b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -2246,6 +2246,11 @@
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 63d1ad1..fb67a51 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -186,6 +186,12 @@
* 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.
@@ -305,6 +311,14 @@
*/
static const int64_t NATIVE_WINDOW_TIMESTAMP_AUTO = (-9223372036854775807LL-1);
+/* parameter for NATIVE_WINDOW_GET_FRAME_TIMESTAMPS
+ *
+ * Special timestamp value to indicate the timestamps aren't yet known or
+ * that they are invalid.
+ */
+static const int64_t NATIVE_WINDOW_TIMESTAMP_PENDING = -2;
+static const int64_t NATIVE_WINDOW_TIMESTAMP_INVALID = -1;
+
struct ANativeWindow
{
#ifdef __cplusplus
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index bf831a7..d0996f0 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -627,19 +627,21 @@
#ifndef EGL_ANDROID_get_frame_timestamps
#define EGL_ANDROID_get_frame_timestamps 1
-#define EGL_TIMESTAMPS_ANDROID 0x314D
-#define EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
-#define EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
-#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
-#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
-#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
-#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
-#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
-#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
-#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3156
-#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
-#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3158
-#define EGL_READS_DONE_TIME_ANDROID 0x3159
+#define EGL_TIMESTAMPS_ANDROID 0x3430
+#define EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
+#define EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
+#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
+#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
+#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
+#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
+#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
+#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
+#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
+#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
+#define EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
+#define EGL_READS_DONE_TIME_ANDROID 0x343C
+#define EGL_TIMESTAMP_PENDING_ANDROID EGL_CAST(EGLnsecsANDROID, -2)
+#define EGL_TIMESTAMP_INVALID_ANDROID EGL_CAST(EGLnsecsANDROID, -1)
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
EGLAPI EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values);
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index b00d401..0807d1f 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -2166,10 +2166,15 @@
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/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
index 61b9b66..b8a9add 100644
--- a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
+++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
@@ -28,7 +28,7 @@
Version
- Version 1, January 13, 2017
+ Version 8, April 11, 2017
Number
@@ -81,19 +81,21 @@
New Tokens
- EGL_TIMESTAMPS_ANDROID 0x314D
- EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
- EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
- EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
- EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
- EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
- EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
- EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
- EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
- EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3156
- EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
- EGL_DEQUEUE_READY_TIME_ANDROID 0x3158
- EGL_READS_DONE_TIME_ANDROID 0x3159
+ EGL_TIMESTAMPS_ANDROID 0x3430
+ EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
+ EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
+ EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
+ EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
+ EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
+ EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
+ EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
+ EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
+ EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
+ EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
+ EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
+ EGL_READS_DONE_TIME_ANDROID 0x343C
+ EGL_TIMESTAMP_PENDING_ANDROID -2
+ EGL_TIMESTAMP_INVALID_ANDROID -1
Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6
"Surface Attributes", page 43:
@@ -155,10 +157,12 @@
limited history of timestamp data. If a query is made for a frame whose
timestamp history no longer exists then EGL_BAD_ACCESS is generated. If
timestamp collection has not been enabled for the surface then
- EGL_BAD_SURFACE is generated. Timestamps for events that will not occur or
- have not yet occurred will be zero. Timestamp queries that are not
- supported will generate an EGL_BAD_PARAMETER error. If any error is
- generated the function will return EGL_FALSE.
+ EGL_BAD_SURFACE is generated. Timestamps for events that might still occur
+ will have the value EGL_TIMESTAMP_PENDING_ANDROID. Timestamps for events
+ that did not occur will have the value EGL_TIMESTAMP_INVALID_ANDROID.
+ Otherwise, the timestamp will be valid and indicate the event has occured.
+ Timestamp queries that are not supported will generate an EGL_BAD_PARAMETER
+ error. If any error is generated the function will return EGL_FALSE.
The application can poll for the timestamp of particular events by calling
eglGetFrameTimestamps over and over without needing to call any other EGL
@@ -222,6 +226,12 @@
Revision History
+#8 (Brian Anderson, April 11, 2017)
+ - Use reserved enumerant values.
+
+#7 (Brian Anderson, March 21, 2017)
+ - Differentiate between pending events and events that did not occur.
+
#6 (Brian Anderson, March 16, 2017)
- Remove DISPLAY_RETIRE_TIME_ANDROID.
diff --git a/opengl/specs/README b/opengl/specs/README
index e922740..cba4453 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -4,8 +4,14 @@
The table below tracks usage of EGL enumerant values that have been reserved
for use by Android extensions.
+See https://github.com/KhronosGroup/EGL-Registry/blob/master/api/egl.xml
+for a list of all enumarant values currently reserved and registered with
+Khronos.
+
Value Extension
----------------- ----------------------------------
+================ ==================================
+0x3140 - 0x314F Reserved block
+================ ==================================
0x3140 EGL_NATIVE_BUFFER_ANDROID (EGL_ANDROID_image_native_buffer)
0x3141 EGL_PLATFORM_ANDROID_KHR (KHR_platform_android)
0x3142 EGL_RECORDABLE_ANDROID (EGL_ANDROID_recordable)
@@ -18,17 +24,23 @@
0x314A EGL_IMAGE_CROP_RIGHT_ANDROID (EGL_ANDROID_image_crop)
0x314B EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop)
0x314C EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID (EGL_ANDROID_front_buffer_auto_refresh)
-0x314D EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314E EGL_COMPOSITE_DEADLINE_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314F EGL_COMPOSITE_INTERVAL_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3150 EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3151 EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3152 EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3153 EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3154 EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3155 EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3156 EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3157 EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3158 EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3159 EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x315A - 0x315F (unused)
+0x314D - 0x314F (unused)
+
+ Value Extension
+================ ==================================
+0x3430 - 0x343F Reserved block
+================ ==================================
+0x3430 EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3431 EGL_COMPOSITE_DEADLINE_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3432 EGL_COMPOSITE_INTERVAL_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3433 EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3434 EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3435 EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3436 EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3437 EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3438 EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3439 EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343A EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343B EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343C EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343D - 0x343F (unused)
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 76a5d06..d72b3b5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -651,6 +651,25 @@
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 219d662..e15c6ff 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -266,6 +266,8 @@
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 cd2acef..a9000c0 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -647,6 +647,21 @@
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)) {
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 68f09c4..6149894 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -78,6 +78,7 @@
"libutils",
"libcutils",
"libz",
+ "libnativewindow",
],
static_libs: ["libgrallocusage"],
}
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 3b785e6..caa2674 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -114,14 +114,34 @@
: vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
native_frame_id_(nativeFrameId) {}
bool ready() const {
- return (timestamp_desired_present_time_ &&
- timestamp_actual_present_time_ &&
- timestamp_render_complete_time_ &&
- timestamp_composition_latch_time_);
+ return (timestamp_desired_present_time_ !=
+ NATIVE_WINDOW_TIMESTAMP_PENDING &&
+ timestamp_actual_present_time_ !=
+ NATIVE_WINDOW_TIMESTAMP_PENDING &&
+ timestamp_render_complete_time_ !=
+ NATIVE_WINDOW_TIMESTAMP_PENDING &&
+ timestamp_composition_latch_time_ !=
+ NATIVE_WINDOW_TIMESTAMP_PENDING);
}
- void calculate(uint64_t rdur) {
- vals_.actualPresentTime = timestamp_actual_present_time_;
- uint64_t margin = (timestamp_composition_latch_time_ -
+ void calculate(int64_t rdur) {
+ bool anyTimestampInvalid =
+ (timestamp_actual_present_time_ ==
+ NATIVE_WINDOW_TIMESTAMP_INVALID) ||
+ (timestamp_render_complete_time_ ==
+ NATIVE_WINDOW_TIMESTAMP_INVALID) ||
+ (timestamp_composition_latch_time_ ==
+ NATIVE_WINDOW_TIMESTAMP_INVALID);
+ if (anyTimestampInvalid) {
+ ALOGE("Unexpectedly received invalid timestamp.");
+ vals_.actualPresentTime = 0;
+ vals_.earliestPresentTime = 0;
+ vals_.presentMargin = 0;
+ return;
+ }
+
+ vals_.actualPresentTime =
+ static_cast<uint64_t>(timestamp_actual_present_time_);
+ int64_t margin = (timestamp_composition_latch_time_ -
timestamp_render_complete_time_);
// Calculate vals_.earliestPresentTime, and potentially adjust
// vals_.presentMargin. The initial value of vals_.earliestPresentTime
@@ -132,14 +152,14 @@
// it did (per the extension specification). If for some reason, we
// can do this subtraction repeatedly, we do, since
// vals_.earliestPresentTime really is supposed to be the "earliest".
- uint64_t early_time = vals_.actualPresentTime;
+ int64_t early_time = timestamp_actual_present_time_;
while ((margin > rdur) &&
((early_time - rdur) > timestamp_composition_latch_time_)) {
early_time -= rdur;
margin -= rdur;
}
- vals_.earliestPresentTime = early_time;
- vals_.presentMargin = margin;
+ vals_.earliestPresentTime = static_cast<uint64_t>(early_time);
+ vals_.presentMargin = static_cast<uint64_t>(margin);
}
void get_values(VkPastPresentationTimingGOOGLE* values) const {
*values = vals_;
@@ -149,10 +169,11 @@
VkPastPresentationTimingGOOGLE vals_ { 0, 0, 0, 0, 0 };
uint64_t native_frame_id_ { 0 };
- uint64_t timestamp_desired_present_time_ { 0 };
- uint64_t timestamp_actual_present_time_ { 0 };
- uint64_t timestamp_render_complete_time_ { 0 };
- uint64_t timestamp_composition_latch_time_ { 0 };
+ int64_t timestamp_desired_present_time_{ NATIVE_WINDOW_TIMESTAMP_PENDING };
+ int64_t timestamp_actual_present_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
+ int64_t timestamp_render_complete_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
+ int64_t timestamp_composition_latch_time_
+ { NATIVE_WINDOW_TIMESTAMP_PENDING };
};
// ----------------------------------------------------------------------------
@@ -187,18 +208,16 @@
shared(present_mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
ANativeWindow* window = surface.window.get();
- int64_t rdur;
native_window_get_refresh_cycle_duration(
window,
- &rdur);
- refresh_duration = static_cast<uint64_t>(rdur);
+ &refresh_duration);
}
Surface& surface;
uint32_t num_images;
bool mailbox_mode;
bool frame_timestamps_enabled;
- uint64_t refresh_duration;
+ int64_t refresh_duration;
bool shared;
struct Image {
@@ -327,14 +346,10 @@
// Record the timestamp(s) we received, and then see if this TimingInfo
// is ready to be reported to the user:
- ti.timestamp_desired_present_time_ =
- static_cast<uint64_t>(desired_present_time);
- ti.timestamp_actual_present_time_ =
- static_cast<uint64_t>(actual_present_time);
- ti.timestamp_render_complete_time_ =
- static_cast<uint64_t>(render_complete_time);
- ti.timestamp_composition_latch_time_ =
- static_cast<uint64_t>(composition_latch_time);
+ ti.timestamp_desired_present_time_ = desired_present_time;
+ ti.timestamp_actual_present_time_ = actual_present_time;
+ ti.timestamp_render_complete_time_ = render_complete_time;
+ ti.timestamp_composition_latch_time_ = composition_latch_time;
if (ti.ready()) {
// The TimingInfo has received enough timestamps, and should now
@@ -1494,7 +1509,8 @@
Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
VkResult result = VK_SUCCESS;
- pDisplayTimingProperties->refreshDuration = swapchain.refresh_duration;
+ pDisplayTimingProperties->refreshDuration =
+ static_cast<uint64_t>(swapchain.refresh_duration);
return result;
}