Bug 1075025 - part 2: implement AndroidVsyncSource. r=snorp
authorJohn Lin <jolin@mozilla.com>
Tue, 20 Dec 2016 15:24:49 +0800
changeset 374262 8b358cc2fdd46b4a5a0f1918bb12d3b1f707a8ae
parent 374261 fb838c37b5be519227a4225ff512b3e04ce9e25a
child 374263 c8cb5fc30a367f7e023c2c381689e2b596f40100
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1075025
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1075025 - part 2: implement AndroidVsyncSource. r=snorp MozReview-Commit-ID: FRgVsLEdKan
gfx/thebes/gfxAndroidPlatform.cpp
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -24,16 +24,18 @@
 #include "gfxPrefs.h"
 #include "cairo.h"
 #include "VsyncSource.h"
 
 #include "ft2build.h"
 #include FT_FREETYPE_H
 #include FT_MODULE_H
 
+#include "GeneratedJNINatives.h"
+
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 
 static FT_Library gPlatformFTLibrary = nullptr;
 
 class FreetypeReporter final : public nsIMemoryReporter,
                                public CountingAllocatorBase<FreetypeReporter>
@@ -296,17 +298,17 @@ gfxAndroidPlatform::FontHintingEnabled()
 {
     // In "mobile" builds, we sometimes use non-reflow-zoom, so we
     // might not want hinting.  Let's see.
 
 #ifdef MOZ_WIDGET_ANDROID
     // On Android, we currently only use gecko to render web
     // content that can always be be non-reflow-zoomed.  So turn off
     // hinting.
-    // 
+    //
     // XXX when gecko-android-java is used as an "app runtime", we may
     // want to re-enable hinting for non-browser processes there.
     return false;
 #endif //  MOZ_WIDGET_ANDROID
 
     // Currently, we don't have any other targets, but if/when we do,
     // decide how to handle them here.
 
@@ -325,13 +327,105 @@ gfxAndroidPlatform::RequiresLinearZoom()
     // want to use linear zoom only for the web browser process, not other apps.
     return true;
 #endif
 
     NS_NOTREACHED("oops, what platform is this?");
     return gfxPlatform::RequiresLinearZoom();
 }
 
+class AndroidVsyncSource final : public VsyncSource {
+public:
+    class JavaVsyncSupport final : public java::VsyncSource::Natives<JavaVsyncSupport>
+    {
+    public:
+        using Base = java::VsyncSource::Natives<JavaVsyncSupport>;
+        using Base::DisposeNative;
+
+        static void NotifyVsync() {
+            GetDisplayInstance().NotifyVsync(TimeStamp::Now());
+        }
+    };
+
+    class Display final : public VsyncSource::Display {
+    public:
+        Display()
+            : mJavaVsync(java::VsyncSource::GetInstance())
+            , mObservingVsync(false)
+        {
+            JavaVsyncSupport::Init(); // To register native methods.
+        }
+
+        ~Display() { DisableVsync(); }
+
+        bool IsVsyncEnabled() override
+        {
+            MOZ_ASSERT(NS_IsMainThread());
+            MOZ_ASSERT(mJavaVsync);
+
+            return mObservingVsync;
+        }
+
+        void EnableVsync() override
+        {
+            MOZ_ASSERT(NS_IsMainThread());
+            MOZ_ASSERT(mJavaVsync);
+
+            if (mObservingVsync) {
+                return;
+            }
+            bool ok = mJavaVsync->ObserveVsync(true);
+            if (ok && !mVsyncDuration) {
+                float fps = mJavaVsync->GetRefreshRate();
+                mVsyncDuration = TimeDuration::FromMilliseconds(1000.0 / fps);
+            }
+            mObservingVsync = ok;
+            MOZ_ASSERT(mObservingVsync);
+        }
+
+        void DisableVsync() override
+        {
+            MOZ_ASSERT(NS_IsMainThread());
+            MOZ_ASSERT(mJavaVsync);
+
+            if (!mObservingVsync) {
+              return;
+            }
+            mObservingVsync = mJavaVsync->ObserveVsync(false);
+            MOZ_ASSERT(!mObservingVsync);
+        }
+
+        TimeDuration GetVsyncRate() override { return mVsyncDuration; }
+
+        void Shutdown() override {
+            DisableVsync();
+            mJavaVsync = nullptr;
+        }
+
+    private:
+        java::VsyncSource::GlobalRef mJavaVsync;
+        bool mObservingVsync;
+        TimeDuration mVsyncDuration;
+    };
+
+    Display& GetGlobalDisplay() final { return GetDisplayInstance(); }
+
+private:
+   virtual ~AndroidVsyncSource() {}
+
+   static Display& GetDisplayInstance()
+   {
+       static Display globalDisplay;
+       return globalDisplay;
+   }
+};
+
 already_AddRefed<mozilla::gfx::VsyncSource>
 gfxAndroidPlatform::CreateHardwareVsyncSource()
 {
+    if (java::VsyncSource::IsVsyncSupported()) {
+        RefPtr<AndroidVsyncSource> vsyncSource = new AndroidVsyncSource();
+        return vsyncSource.forget();
+    }
+
+    NS_WARNING("Vsync not supported. Falling back to software vsync");
     return gfxPlatform::CreateHardwareVsyncSource();
 }