Bug 1328115 - 1. Test vsync support in native code; r=snorp
authorJim Chen <nchen@mozilla.com>
Mon, 09 Jan 2017 14:10:23 -0500
changeset 328657 10968c7a6abfaf7069a46aebbe48721448f8a822
parent 328656 4a298007ca24f5f4996c606593d8ccb8365276c0
child 328658 4ddd36462bdf680de40297acfac032b42fa50831
push id31182
push usercbook@mozilla.com
push dateTue, 10 Jan 2017 11:14:56 +0000
treeherdermozilla-central@7011ed1427de [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1328115
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 1328115 - 1. Test vsync support in native code; r=snorp Don't go through the VsyncSource Java class to test support for vsync. Because VsyncSource references symbols from API 16+, Dalvik fails to load it for API 15 and below. Also make several other changes in VsyncSource, including removing the unnecessary JNIObject superclass, and refactoring the instance initialization code, which fixes a possible race when initializing.
gfx/thebes/gfxAndroidPlatform.cpp
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/VsyncSource.java
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -343,17 +343,17 @@ public:
         static void NotifyVsync() {
             GetDisplayInstance().NotifyVsync(TimeStamp::Now());
         }
     };
 
     class Display final : public VsyncSource::Display {
     public:
         Display()
-            : mJavaVsync(java::VsyncSource::GetInstance())
+            : mJavaVsync(java::VsyncSource::INSTANCE())
             , mObservingVsync(false)
         {
             JavaVsyncSupport::Init(); // To register native methods.
         }
 
         ~Display() { DisableVsync(); }
 
         bool IsVsyncEnabled() override
@@ -416,16 +416,19 @@ private:
        static Display globalDisplay;
        return globalDisplay;
    }
 };
 
 already_AddRefed<mozilla::gfx::VsyncSource>
 gfxAndroidPlatform::CreateHardwareVsyncSource()
 {
-    if (jni::IsAvailable() && java::VsyncSource::IsVsyncSupported()) {
+    // Vsync was introduced since JB (API 16~18) but inaccurate. Enable only for
+    // KK (API 19) and later.
+    if (AndroidBridge::Bridge() &&
+            AndroidBridge::Bridge()->GetAPIVersion() >= 19) {
         RefPtr<AndroidVsyncSource> vsyncSource = new AndroidVsyncSource();
         return vsyncSource.forget();
     }
 
     NS_WARNING("Vsync not supported. Falling back to software vsync");
     return gfxPlatform::CreateHardwareVsyncSource();
 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/VsyncSource.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/VsyncSource.java
@@ -7,75 +7,56 @@ package org.mozilla.gecko.gfx;
 
 import android.content.Context;
 import android.hardware.display.DisplayManager;
 import android.os.HandlerThread;
 import android.os.Process;
 import android.util.Log;
 import android.view.Choreographer;
 import android.view.Display;
-import java.util.concurrent.CountDownLatch;
 import org.mozilla.gecko.annotation.WrapForJNI;
 import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.mozglue.JNIObject;
 
 /**
  * This class receives HW vsync events through a {@link Choreographer}.
  */
-public final class VsyncSource extends JNIObject implements Choreographer.FrameCallback {
+public final class VsyncSource implements Choreographer.FrameCallback {
     private static final String LOGTAG = "GeckoVsyncSource";
 
-    // Vsync was introduced since JB (API 16~18) but inaccurate. Enable only for KK and later.
-    public static final boolean SUPPORT_VSYNC =
-        android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT;
-
-    private static VsyncSource sInstance;
-
-    private Choreographer mChoreographer;
-    private CountDownLatch mInitLatch = new CountDownLatch(1);
-
-    private volatile boolean mObservingVsync;
-
-    @WrapForJNI
-    public static boolean isVsyncSupported() { return SUPPORT_VSYNC; }
-
     @WrapForJNI
-    public static synchronized VsyncSource getInstance() {
-        if (!SUPPORT_VSYNC) {
-            Log.w(LOGTAG, "HW vsync avaiable only for KK and later.");
-            return null;
-        }
-         if (sInstance == null) {
-           sInstance = new VsyncSource();
+    private static final VsyncSource INSTANCE = new VsyncSource();
+
+    /* package */ Choreographer mChoreographer;
+    private volatile boolean mObservingVsync;
 
-            HandlerThread thread = new HandlerThread(LOGTAG, Process.THREAD_PRIORITY_DISPLAY) {
-                protected void onLooperPrepared() {
-                    sInstance.mChoreographer = Choreographer.getInstance();
-                    sInstance.mInitLatch.countDown();
-                }
-            };
+    private VsyncSource() {
+        final Thread thread = new HandlerThread(LOGTAG, Process.THREAD_PRIORITY_DISPLAY) {
+            @Override
+            protected synchronized void onLooperPrepared() {
+                mChoreographer = Choreographer.getInstance();
+                notifyAll();
+            }
+        };
+
+        synchronized (thread) {
             thread.start();
 
-            // Wait until the choreographer singleton is created in its thread.
-            try {
-                sInstance.mInitLatch.await();
-            } catch (InterruptedException e) { /* do nothing */ }
+            while (mChoreographer == null) {
+                try {
+                    thread.wait();
+                } catch (final InterruptedException e) {
+                    // Ignore
+                }
+            }
         }
-
-        return sInstance;
     }
 
-    private VsyncSource() {}
-
     @WrapForJNI(stubName = "NotifyVsync")
     private static native void nativeNotifyVsync();
 
-    @Override // JNIObject
-    protected native void disposeNative();
-
     // Choreographer callback implementation.
     public void doFrame(long frameTimeNanos) {
         if (mObservingVsync) {
             mChoreographer.postFrameCallback(this);
             nativeNotifyVsync();
         }
     }