Bug 1322650 - Adjust Android Flash support to API changes r=jchen
☠☠ backed out by c74f6afe9f3c ☠ ☠
authorJames Willcox <snorp@snorp.net>
Thu, 09 Mar 2017 17:51:17 -0600
changeset 356753 d6516a10c8088a6ce872c888d88bc98a545a7fee
parent 356752 0c01bf8a1bd94de932c384cd51f5843922a82058
child 356754 9d3843274c67c036f273697a0226156e096740b5
push id89951
push userjwillcox@mozilla.com
push dateFri, 05 May 2017 13:57:17 +0000
treeherdermozilla-inbound@f94c4f5bf53a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjchen
bugs1322650
milestone55.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 1322650 - Adjust Android Flash support to API changes r=jchen MozReview-Commit-ID: CmMINaGcTER
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsNPAPIPluginInstance.h
dom/plugins/base/nsPluginInstanceOwner.cpp
gfx/gl/AndroidNativeWindow.h
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SurfaceTextureListener.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/JNIObject.java
widget/android/jni/Natives.h
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -53,16 +53,18 @@ using namespace mozilla::dom;
 #include "mozilla/CondVar.h"
 #include "mozilla/dom/ScreenOrientation.h"
 #include "mozilla/Hal.h"
 #include "GLContextProvider.h"
 #include "GLContext.h"
 #include "TexturePoolOGL.h"
 #include "SurfaceTypes.h"
 #include "EGLUtils.h"
+#include "GeneratedJNIWrappers.h"
+#include "GeneratedJNINatives.h"
 
 using namespace mozilla;
 using namespace mozilla::gl;
 
 typedef nsNPAPIPluginInstance::VideoInfo VideoInfo;
 
 class PluginEventRunnable : public Runnable
 {
@@ -101,17 +103,17 @@ static bool EnsureGLContext()
     sPluginContext = GLContextProvider::CreateHeadless(flags, &discardedFailureId);
   }
 
   return sPluginContext != nullptr;
 }
 
 static std::map<NPP, nsNPAPIPluginInstance*> sPluginNPPMap;
 
-#endif
+#endif // MOZ_WIDGET_ANDROID
 
 using namespace mozilla;
 using namespace mozilla::plugins::parent;
 using namespace mozilla::layers;
 
 static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
 
 NS_IMPL_ISUPPORTS(nsNPAPIPluginInstance, nsIAudioChannelAgentCallback)
@@ -197,24 +199,22 @@ uint32_t nsNPAPIPluginInstance::gInUnsaf
 void
 nsNPAPIPluginInstance::Destroy()
 {
   Stop();
   mPlugin = nullptr;
   mAudioChannelAgent = nullptr;
 
 #if MOZ_WIDGET_ANDROID
-  if (mContentSurface)
-    mContentSurface->SetFrameAvailableCallback(nullptr);
-
-  mContentSurface = nullptr;
+  if (mContentSurface) {
+    java::SurfaceAllocator::DisposeSurface(mContentSurface);
+  }
 
   std::map<void*, VideoInfo*>::iterator it;
   for (it = mVideos.begin(); it != mVideos.end(); it++) {
-    it->second->mSurfaceTexture->SetFrameAvailableCallback(nullptr);
     delete it->second;
   }
   mVideos.clear();
   SetWakeLock(false);
 #endif
 }
 
 TimeStamp
@@ -853,73 +853,93 @@ void nsNPAPIPluginInstance::SetWakeLock(
 GLContext* nsNPAPIPluginInstance::GLContext()
 {
   if (!EnsureGLContext())
     return nullptr;
 
   return sPluginContext;
 }
 
-already_AddRefed<AndroidSurfaceTexture> nsNPAPIPluginInstance::CreateSurfaceTexture()
+class PluginTextureListener
+  : public java::SurfaceTextureListener::Natives<PluginTextureListener>
 {
-  if (!EnsureGLContext())
-    return nullptr;
+  using Base = java::SurfaceTextureListener::Natives<PluginTextureListener>;
+
+  const nsCOMPtr<nsIRunnable> mCallback;
+public:
+  using Base::AttachNative;
+  using Base::DisposeNative;
+
+  PluginTextureListener(nsIRunnable* aCallback) : mCallback(aCallback) {}
 
-  GLuint texture = TexturePoolOGL::AcquireTexture();
-  if (!texture)
-    return nullptr;
+  void OnFrameAvailable()
+  {
+    if (NS_IsMainThread()) {
+      mCallback->Run();
+      return;
+    }
+    NS_DispatchToMainThread(mCallback);
+  }
+};
 
-  RefPtr<AndroidSurfaceTexture> surface = AndroidSurfaceTexture::Create(TexturePoolOGL::GetGLContext(),
-                                                                        texture);
-  if (!surface) {
+java::GeckoSurface::LocalRef nsNPAPIPluginInstance::CreateSurface()
+{
+  java::GeckoSurface::LocalRef surf = java::SurfaceAllocator::AcquireSurface(0, 0, false);
+  if (!surf) {
     return nullptr;
   }
 
   nsCOMPtr<nsIRunnable> frameCallback = NewRunnableMethod(this, &nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable);
-  surface->SetFrameAvailableCallback(frameCallback);
-  return surface.forget();
+
+  java::SurfaceTextureListener::LocalRef listener = java::SurfaceTextureListener::New();
+
+  PluginTextureListener::AttachNative(listener, MakeUnique<PluginTextureListener>(frameCallback.get()));
+
+  java::GeckoSurfaceTexture::LocalRef gst = java::GeckoSurfaceTexture::Lookup(surf->GetHandle());
+  if (!gst) {
+    return nullptr;
+  }
+
+  const auto& st = java::sdk::SurfaceTexture::Ref::From(gst);
+  st->SetOnFrameAvailableListener(listener);
+
+  return surf;
 }
 
 void nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable()
 {
   if (mRunning == RUNNING && mOwner)
     mOwner->Recomposite();
 }
 
 void* nsNPAPIPluginInstance::AcquireContentWindow()
 {
-  if (!mContentSurface) {
-    mContentSurface = CreateSurfaceTexture();
-
+  if (!mContentWindow.NativeWindow()) {
+    mContentSurface = CreateSurface();
     if (!mContentSurface)
       return nullptr;
+
+    mContentWindow = AndroidNativeWindow(mContentSurface);
   }
 
-  return mContentSurface->NativeWindow();
+  return mContentWindow.NativeWindow();
 }
 
-AndroidSurfaceTexture*
-nsNPAPIPluginInstance::AsSurfaceTexture()
+java::GeckoSurface::Param
+nsNPAPIPluginInstance::AsSurface()
 {
-  if (!mContentSurface)
-    return nullptr;
-
   return mContentSurface;
 }
 
 void* nsNPAPIPluginInstance::AcquireVideoWindow()
 {
-  RefPtr<AndroidSurfaceTexture> surface = CreateSurfaceTexture();
-  if (!surface) {
-    return nullptr;
-  }
-
+  java::GeckoSurface::LocalRef surface = CreateSurface();
   VideoInfo* info = new VideoInfo(surface);
 
-  void* window = info->mSurfaceTexture->NativeWindow();
+  void* window = info->mNativeWindow.NativeWindow();
   mVideos.insert(std::pair<void*, VideoInfo*>(window, info));
 
   return window;
 }
 
 void nsNPAPIPluginInstance::ReleaseVideoWindow(void* window)
 {
   std::map<void*, VideoInfo*>::iterator it = mVideos.find(window);
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -16,17 +16,17 @@
 #include "nsIChannel.h"
 #include "nsHashKeys.h"
 #include <prinrval.h>
 #include "js/TypeDecls.h"
 #include "nsIAudioChannelAgent.h"
 #ifdef MOZ_WIDGET_ANDROID
 #include "nsIRunnable.h"
 #include "GLContextTypes.h"
-#include "AndroidSurfaceTexture.h"
+#include "AndroidNativeWindow.h"
 #include "AndroidBridge.h"
 #include <map>
 class PluginEventRunnable;
 #endif
 
 #include "mozilla/EventForwards.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/PluginLibrary.h"
@@ -210,32 +210,34 @@ public:
     int32_t mWidth;
     int32_t mHeight;
     GLuint mInternalFormat;
   };
 
   // For ANPNativeWindow
   void* AcquireContentWindow();
 
-  mozilla::gl::AndroidSurfaceTexture* AsSurfaceTexture();
+  mozilla::java::GeckoSurface::Param AsSurface();
 
   // For ANPVideo
   class VideoInfo {
   public:
-    VideoInfo(mozilla::gl::AndroidSurfaceTexture* aSurfaceTexture) :
-      mSurfaceTexture(aSurfaceTexture)
+    VideoInfo(mozilla::java::GeckoSurface::Param aSurface)
+      : mSurface(aSurface)
+      , mNativeWindow(aSurface)
     {
     }
 
     ~VideoInfo()
     {
-      mSurfaceTexture = nullptr;
+      mozilla::java::SurfaceAllocator::DisposeSurface(mSurface);
     }
 
-    RefPtr<mozilla::gl::AndroidSurfaceTexture> mSurfaceTexture;
+    mozilla::java::GeckoSurface::GlobalRef mSurface;
+    mozilla::gl::AndroidNativeWindow mNativeWindow;
     gfxRect mDimensions;
   };
 
   void* AcquireVideoWindow();
   void ReleaseVideoWindow(void* aWindow);
   void SetVideoDimensions(void* aWindow, gfxRect aDimensions);
 
   void GetVideos(nsTArray<VideoInfo*>& aVideos);
@@ -354,17 +356,18 @@ protected:
   void PopPostedEvent(PluginEventRunnable* r);
   void OnSurfaceTextureFrameAvailable();
 
   uint32_t mFullScreenOrientation;
   bool mWakeLocked;
   bool mFullScreen;
   mozilla::gl::OriginPos mOriginPos;
 
-  RefPtr<mozilla::gl::AndroidSurfaceTexture> mContentSurface;
+  mozilla::java::GeckoSurface::GlobalRef mContentSurface;
+  mozilla::gl::AndroidNativeWindow mContentWindow;
 #endif
 
   enum {
     NOT_STARTED,
     RUNNING,
     DESTROYING,
     DESTROYED
   } mRunning;
@@ -404,18 +407,17 @@ private:
   void* mCurrentPluginEvent;
 #endif
 
   // Timestamp for the last time this plugin was stopped.
   // This is only valid when the plugin is actually stopped!
   mozilla::TimeStamp mStopTime;
 
 #ifdef MOZ_WIDGET_ANDROID
-  already_AddRefed<mozilla::gl::AndroidSurfaceTexture> CreateSurfaceTexture();
-
+  mozilla::java::GeckoSurface::LocalRef CreateSurface();
   std::map<void*, VideoInfo*> mVideos;
   bool mOnScreen;
 
   nsIntSize mCurrentSize;
 #endif
 
   // is this instance Java and affected by bug 750480?
   bool mHaveJavaC2PJSObjectQuirk;
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -160,32 +160,33 @@ nsPluginInstanceOwner::NotifyPaintWaiter
     // receive it immediately
     nsContentUtils::AddScriptRunner(event);
     mWaitingForPaint = true;
   }
 }
 
 #if MOZ_WIDGET_ANDROID
 static void
-AttachToContainerAsSurfaceTexture(ImageContainer* container,
-                                  nsNPAPIPluginInstance* instance,
-                                  const LayoutDeviceRect& rect,
-                                  RefPtr<Image>* out_image)
+AttachToContainerAsSurface(ImageContainer* container,
+                           nsNPAPIPluginInstance* instance,
+                           const LayoutDeviceRect& rect,
+                           RefPtr<Image>* out_image)
 {
   MOZ_ASSERT(out_image);
   MOZ_ASSERT(!*out_image);
 
-  mozilla::gl::AndroidSurfaceTexture* surfTex = instance->AsSurfaceTexture();
-  if (!surfTex) {
+  java::GeckoSurface::LocalRef surface = instance->AsSurface();
+  if (!surface) {
     return;
   }
 
   RefPtr<Image> img = new SurfaceTextureImage(
-    surfTex,
+    surface->GetHandle(),
     gfx::IntSize::Truncate(rect.width, rect.height),
+    true, // continuously update without a transaction
     instance->OriginPos());
   *out_image = img;
 }
 #endif
 
 bool
 nsPluginInstanceOwner::NeedsScrollImageLayer()
 {
@@ -218,17 +219,17 @@ nsPluginInstanceOwner::GetImageContainer
   ScreenSize screenSize = (r * LayoutDeviceToScreenScale(resolution)).Size();
   mInstance->NotifySize(nsIntSize::Truncate(screenSize.width, screenSize.height));
 
   container = LayerManager::CreateImageContainer();
 
   if (r.width && r.height) {
     // Try to get it as an EGLImage first.
     RefPtr<Image> img;
-    AttachToContainerAsSurfaceTexture(container, mInstance, r, &img);
+    AttachToContainerAsSurface(container, mInstance, r, &img);
 
     if (img) {
       container->SetCurrentImageInTransaction(img);
     }
   }
 #else
   if (NeedsScrollImageLayer()) {
     // windowed plugin under e10s
@@ -1580,18 +1581,19 @@ nsPluginInstanceOwner::GetVideos(nsTArra
 
 already_AddRefed<ImageContainer>
 nsPluginInstanceOwner::GetImageContainerForVideo(nsNPAPIPluginInstance::VideoInfo* aVideoInfo)
 {
   RefPtr<ImageContainer> container = LayerManager::CreateImageContainer();
 
   if (aVideoInfo->mDimensions.width && aVideoInfo->mDimensions.height) {
     RefPtr<Image> img = new SurfaceTextureImage(
-      aVideoInfo->mSurfaceTexture,
+      aVideoInfo->mSurface->GetHandle(),
       gfx::IntSize::Truncate(aVideoInfo->mDimensions.width, aVideoInfo->mDimensions.height),
+      true, /* continuous */
       gl::OriginPos::BottomLeft);
     container->SetCurrentImageInTransaction(img);
   }
 
   return container.forget();
 }
 
 void nsPluginInstanceOwner::Invalidate() {
--- a/gfx/gl/AndroidNativeWindow.h
+++ b/gfx/gl/AndroidNativeWindow.h
@@ -14,16 +14,19 @@
 #include "GeneratedJNIWrappers.h"
 #include "SurfaceTexture.h"
 
 namespace mozilla {
 namespace gl {
 
 class AndroidNativeWindow {
 public:
+  AndroidNativeWindow() : mNativeWindow(nullptr) {
+  }
+
   AndroidNativeWindow(java::sdk::Surface::Param aSurface) {
     mNativeWindow = ANativeWindow_fromSurface(jni::GetEnvForThread(),
                                               aSurface.Get());
   }
 
   AndroidNativeWindow(java::GeckoSurface::Param aSurface) {
     auto surf = java::sdk::Surface::LocalRef(java::sdk::Surface::Ref::From(aSurface));
     mNativeWindow = ANativeWindow_fromSurface(jni::GetEnvForThread(),
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SurfaceTextureListener.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SurfaceTextureListener.java
@@ -12,20 +12,22 @@ import android.graphics.SurfaceTexture;
 
 final class SurfaceTextureListener
     extends JNIObject implements SurfaceTexture.OnFrameAvailableListener
 {
     @WrapForJNI(calledFrom = "gecko")
     private SurfaceTextureListener() {
     }
 
+    @WrapForJNI(dispatchTo = "gecko") @Override // JNIObject
+    protected native void disposeNative();
+
     @Override
-    protected void disposeNative() {
-        // SurfaceTextureListener is disposed inside AndroidSurfaceTexture.
-        throw new IllegalStateException("unreachable code");
+    protected void finalize() {
+        disposeNative();
     }
 
     @WrapForJNI(stubName = "OnFrameAvailable")
     private native void nativeOnFrameAvailable();
 
     @Override // SurfaceTexture.OnFrameAvailableListener
     public void onFrameAvailable(SurfaceTexture surfaceTexture) {
         try {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/JNIObject.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/JNIObject.java
@@ -2,10 +2,15 @@ package org.mozilla.gecko.mozglue;
 
 // Class that all classes with native methods extend from.
 public abstract class JNIObject
 {
     // Pointer to a WeakPtr object that refers to the native object.
     private long mHandle;
 
     // Dispose of any reference to a native object.
+    //
+    // If the native instance is destroyed from the native side, this should never be
+    // called, so you should throw an UnsupportedOperationException. If instead you
+    // want to destroy the native side from the Java end, make override this with
+    // a native call, and the right thing will be done in the native code.
     protected abstract void disposeNative();
 }
--- a/widget/android/jni/Natives.h
+++ b/widget/android/jni/Natives.h
@@ -39,17 +39,17 @@ namespace jni {
  *       // ...
  *
  *   public:
  *       MOZ_DECLARE_WEAKREFERENCE_TYPENAME(MyClass)
  *       using MyJavaClass::Natives<MyClass>::DisposeNative;
  *
  *       void AttachTo(const MyJavaClass::LocalRef& instance)
  *       {
- *           MyJavaClass::Natives<MyClass>::AttachInstance(
+ *           MyJavaClass::Natives<MyClass>::AttachNative(
  *                   instance, static_cast<SupportsWeakPtr<MyClass>*>(this));
  *
  *           // "instance" does NOT own "this", so the C++ object
  *           // lifetime is separate from the Java object lifetime.
  *       }
  *   };
  *
  * * If the C++ class contains public members AddRef() and Release(), the Java
@@ -65,17 +65,17 @@ namespace jni {
  *   {
  *       // ...
  *
  *   public:
  *       using MyJavaClass::Natives<MyClass>::DisposeNative;
  *
  *       void AttachTo(const MyJavaClass::LocalRef& instance)
  *       {
- *           MyJavaClass::Natives<MyClass>::AttachInstance(instance, this);
+ *           MyJavaClass::Natives<MyClass>::AttachNative(instance, this);
  *
  *           // "instance" owns "this" through the RefPtr, so the C++ object
  *           // may be destroyed as soon as instance.disposeNative() is called.
  *       }
  *   };
  *
  * * In other cases, the Java instance will store and own a pointer to the C++
  *   object itself. This pointer must not be stored or deleted elsewhere. To
@@ -86,17 +86,17 @@ namespace jni {
  *   {
  *       // ...
  *
  *   public:
  *       using MyJavaClass::Natives<MyClass>::DisposeNative;
  *
  *       static void AttachTo(const MyJavaClass::LocalRef& instance)
  *       {
- *           MyJavaClass::Natives<MyClass>::AttachInstance(
+ *           MyJavaClass::Natives<MyClass>::AttachNative(
  *                   instance, mozilla::MakeUnique<MyClass>());
  *
  *           // "instance" owns the newly created C++ object, so the C++
  *           // object is destroyed as soon as instance.disposeNative() is
  *           // called.
  *       }
  *   };
  */