Add support for sending VSYNC events to the framework
use gui/DisplayEvent to receive the events. Events are
dispatched through a unix pipe, so the API is compatible
with utils/Looper. see gui/DisplayEvent.h for more info.
Bug: 1475048
Change-Id: Ia720f64d1b950328b47b22c6a86042e481d35f09
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index f94d321..3bbc75e 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -140,6 +140,7 @@
mDpiX = mNativeWindow->xdpi;
mDpiY = mNativeWindow->ydpi;
mRefreshRate = fbDev->fps;
+ mNextFakeVSync = 0;
/* FIXME: this is a temporary HACK until we are able to report the refresh rate
@@ -152,6 +153,8 @@
#warning "refresh rate set via makefile to REFRESH_RATE"
#endif
+ mRefreshPeriod = nsecs_t(1e9 / mRefreshRate);
+
EGLint w, h, dummy;
EGLint numConfigs=0;
EGLSurface surface;
@@ -346,6 +349,37 @@
return mPageFlipCount;
}
+// this needs to be thread safe
+nsecs_t DisplayHardware::waitForVSync() const {
+ nsecs_t timestamp;
+ if (mVSync.wait(×tamp) < 0) {
+ // vsync not supported!
+ usleep( getDelayToNextVSyncUs(×tamp) );
+ }
+ return timestamp;
+}
+
+int32_t DisplayHardware::getDelayToNextVSyncUs(nsecs_t* timestamp) const {
+ Mutex::Autolock _l(mFakeVSyncMutex);
+ const nsecs_t period = mRefreshPeriod;
+ const nsecs_t now = systemTime(CLOCK_MONOTONIC);
+ nsecs_t next_vsync = mNextFakeVSync;
+ nsecs_t sleep = next_vsync - now;
+ if (sleep < 0) {
+ // we missed, find where the next vsync should be
+ sleep = (period - ((now - next_vsync) % period));
+ next_vsync = now + sleep;
+ }
+ mNextFakeVSync = next_vsync + period;
+ timestamp[0] = next_vsync;
+
+ // round to next microsecond
+ int32_t sleep_us = (sleep + 999LL) / 1000LL;
+
+ // guaranteed to be > 0
+ return sleep_us;
+}
+
status_t DisplayHardware::compositionComplete() const {
return mNativeWindow->compositionComplete();
}
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index f02c954..45d4b45 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -32,6 +32,7 @@
#include "GLExtensions.h"
#include "DisplayHardware/DisplayHardwareBase.h"
+#include "DisplayHardware/VSyncBarrier.h"
namespace android {
@@ -74,6 +75,9 @@
uint32_t getMaxTextureSize() const;
uint32_t getMaxViewportDims() const;
+ // waits for the next vsync and returns the timestamp of when it happened
+ nsecs_t waitForVSync() const;
+
uint32_t getPageFlipCount() const;
EGLDisplay getEGLDisplay() const { return mDisplay; }
@@ -95,6 +99,7 @@
private:
void init(uint32_t displayIndex) __attribute__((noinline));
void fini() __attribute__((noinline));
+ int32_t getDelayToNextVSyncUs(nsecs_t* timestamp) const;
sp<SurfaceFlinger> mFlinger;
EGLDisplay mDisplay;
@@ -112,7 +117,12 @@
mutable uint32_t mPageFlipCount;
GLint mMaxViewportDims[2];
GLint mMaxTextureSize;
-
+ VSyncBarrier mVSync;
+
+ mutable Mutex mFakeVSyncMutex;
+ mutable nsecs_t mNextFakeVSync;
+ nsecs_t mRefreshPeriod;
+
HWComposer* mHwc;
sp<FramebufferNativeWindow> mNativeWindow;
diff --git a/services/surfaceflinger/DisplayHardware/VSyncBarrier.cpp b/services/surfaceflinger/DisplayHardware/VSyncBarrier.cpp
new file mode 100644
index 0000000..187da20
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/VSyncBarrier.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+
+#include "DisplayHardware/VSyncBarrier.h"
+
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+#endif
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+VSyncBarrier::VSyncBarrier() : mFd(-EINVAL) {
+#if HAS_WAITFORVSYNC
+ mFd = open("/dev/graphics/fb0", O_RDWR);
+ if (mFd < 0) {
+ mFd = -errno;
+ }
+ // try to see if FBIO_WAITFORVSYNC is supported
+ uint32_t crt = 0;
+ int err = ioctl(mFd, FBIO_WAITFORVSYNC, &crt);
+ if (err < 0) {
+ close(mFd);
+ mFd = -EINVAL;
+ }
+#endif
+}
+
+VSyncBarrier::~VSyncBarrier() {
+ if (mFd >= 0) {
+ close(mFd);
+ }
+}
+
+status_t VSyncBarrier::initCheck() const {
+ return mFd < 0 ? mFd : status_t(NO_ERROR);
+}
+
+// this must be thread-safe
+status_t VSyncBarrier::wait(nsecs_t* timestamp) const {
+ if (mFd < 0) {
+ return mFd;
+ }
+
+ int err;
+ uint32_t crt = 0;
+ do {
+ err = ioctl(mFd, FBIO_WAITFORVSYNC, &crt);
+ } while (err<0 && errno==EINTR);
+ if (err < 0) {
+ return -errno;
+ }
+ // ideally this would come from the driver
+ timestamp[0] = systemTime();
+ return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/VSyncBarrier.h b/services/surfaceflinger/DisplayHardware/VSyncBarrier.h
new file mode 100644
index 0000000..3c32950
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/VSyncBarrier.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SURFACE_FLINGER_VSYNCBARRIER_H_
+#define ANDROID_SURFACE_FLINGER_VSYNCBARRIER_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/Timers.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class VSyncBarrier {
+ int mFd;
+public:
+ VSyncBarrier();
+ ~VSyncBarrier();
+ status_t initCheck() const;
+ status_t wait(nsecs_t* timestamp) const;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif /* ANDROID_SURFACE_FLINGER_VSYNCBARRIER_H_ */