Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / android / stream_texture_factory_synchronous_impl.cc
index b5512a4..c6eb63d 100644 (file)
@@ -11,7 +11,7 @@
 #include "base/location.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop_proxy.h"
-#include "base/process/process.h"
+#include "base/process/process_handle.h"
 #include "base/synchronization/lock.h"
 #include "cc/output/context_provider.h"
 #include "content/common/android/surface_texture_peer.h"
@@ -34,23 +34,25 @@ class StreamTextureProxyImpl
   virtual ~StreamTextureProxyImpl();
 
   // StreamTextureProxy implementation:
-  virtual void BindToCurrentThread(int32 stream_id) OVERRIDE;
-  virtual void SetClient(cc::VideoFrameProvider::Client* client) OVERRIDE;
-  virtual void Release() OVERRIDE;
+  virtual void BindToLoop(int32 stream_id,
+                          cc::VideoFrameProvider::Client* client,
+                          scoped_refptr<base::MessageLoopProxy> loop) override;
+  virtual void Release() override;
 
  private:
-  void BindOnCompositorThread(int stream_id);
+  void BindOnThread(int32 stream_id);
   void OnFrameAvailable();
 
-  scoped_refptr<base::MessageLoopProxy> loop_;
-  base::Lock client_lock_;
+  // Protects access to |client_| and |loop_|.
+  base::Lock lock_;
   cc::VideoFrameProvider::Client* client_;
-  base::Closure callback_;
+  scoped_refptr<base::MessageLoopProxy> loop_;
 
+  // Accessed on the |loop_| thread only.
+  base::Closure callback_;
   scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
       context_provider_;
   scoped_refptr<gfx::SurfaceTexture> surface_texture_;
-
   float current_matrix_[16];
   bool has_updated_;
 
@@ -59,43 +61,56 @@ class StreamTextureProxyImpl
 
 StreamTextureProxyImpl::StreamTextureProxyImpl(
     StreamTextureFactorySynchronousImpl::ContextProvider* provider)
-    : context_provider_(provider), has_updated_(false) {
-  DCHECK(RenderThreadImpl::current());
-  loop_ = RenderThreadImpl::current()->compositor_message_loop_proxy();
+    : client_(NULL), context_provider_(provider), has_updated_(false) {
   std::fill(current_matrix_, current_matrix_ + 16, 0);
 }
 
 StreamTextureProxyImpl::~StreamTextureProxyImpl() {}
 
 void StreamTextureProxyImpl::Release() {
-  SetClient(NULL);
-  if (!loop_->BelongsToCurrentThread())
-    loop_->DeleteSoon(FROM_HERE, this);
-  else
+  {
+    // Cannot call into |client_| anymore (from any thread) after returning
+    // from here.
+    base::AutoLock lock(lock_);
+    client_ = NULL;
+  }
+  // Release is analogous to the destructor, so there should be no more external
+  // calls to this object in Release. Therefore there is no need to acquire the
+  // lock to access |loop_|.
+  if (!loop_.get() || loop_->BelongsToCurrentThread() ||
+      !loop_->DeleteSoon(FROM_HERE, this)) {
     delete this;
+  }
 }
 
-void StreamTextureProxyImpl::SetClient(cc::VideoFrameProvider::Client* client) {
-  base::AutoLock lock(client_lock_);
-  client_ = client;
-}
+void StreamTextureProxyImpl::BindToLoop(
+    int32 stream_id,
+    cc::VideoFrameProvider::Client* client,
+    scoped_refptr<base::MessageLoopProxy> loop) {
+  DCHECK(loop.get());
+
+  {
+    base::AutoLock lock(lock_);
+    DCHECK(!loop_.get() || (loop.get() == loop_.get()));
+    loop_ = loop;
+    client_ = client;
+  }
 
-void StreamTextureProxyImpl::BindToCurrentThread(int stream_id) {
-  if (loop_->BelongsToCurrentThread()) {
-    BindOnCompositorThread(stream_id);
+  if (loop->BelongsToCurrentThread()) {
+    BindOnThread(stream_id);
     return;
   }
-
-  // Weakptr is only used on compositor thread loop, so this is safe.
-  loop_->PostTask(FROM_HERE,
-                  base::Bind(&StreamTextureProxyImpl::BindOnCompositorThread,
-                             AsWeakPtr(),
-                             stream_id));
+  // Unretained is safe here only because the object is deleted on |loop_|
+  // thread.
+  loop->PostTask(FROM_HERE,
+                 base::Bind(&StreamTextureProxyImpl::BindOnThread,
+                            base::Unretained(this),
+                            stream_id));
 }
 
-void StreamTextureProxyImpl::BindOnCompositorThread(int stream_id) {
+void StreamTextureProxyImpl::BindOnThread(int32 stream_id) {
   surface_texture_ = context_provider_->GetSurfaceTexture(stream_id);
-  if (!surface_texture_) {
+  if (!surface_texture_.get()) {
     LOG(ERROR) << "Failed to get SurfaceTexture for stream.";
     return;
   }
@@ -116,7 +131,7 @@ void StreamTextureProxyImpl::OnFrameAvailable() {
     if (memcmp(current_matrix_, matrix, sizeof(matrix)) != 0) {
       memcpy(current_matrix_, matrix, sizeof(matrix));
 
-      base::AutoLock lock(client_lock_);
+      base::AutoLock lock(lock_);
       if (client_)
         client_->DidUpdateMatrix(current_matrix_);
     }
@@ -125,7 +140,7 @@ void StreamTextureProxyImpl::OnFrameAvailable() {
   // updateTexImage since after we received the first frame.
   has_updated_ = true;
 
-  base::AutoLock lock(client_lock_);
+  base::AutoLock lock(lock_);
   if (client_)
     client_->DidReceiveFrame();
 }
@@ -136,38 +151,43 @@ void StreamTextureProxyImpl::OnFrameAvailable() {
 scoped_refptr<StreamTextureFactorySynchronousImpl>
 StreamTextureFactorySynchronousImpl::Create(
     const CreateContextProviderCallback& try_create_callback,
-    int view_id) {
-  return new StreamTextureFactorySynchronousImpl(try_create_callback, view_id);
+    int frame_id) {
+  return new StreamTextureFactorySynchronousImpl(try_create_callback, frame_id);
 }
 
 StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl(
     const CreateContextProviderCallback& try_create_callback,
-    int view_id)
+    int frame_id)
     : create_context_provider_callback_(try_create_callback),
       context_provider_(create_context_provider_callback_.Run()),
-      view_id_(view_id) {}
+      frame_id_(frame_id),
+      observer_(NULL) {}
 
 StreamTextureFactorySynchronousImpl::~StreamTextureFactorySynchronousImpl() {}
 
 StreamTextureProxy* StreamTextureFactorySynchronousImpl::CreateProxy() {
-  if (!context_provider_)
+  bool had_proxy = !!context_provider_.get();
+  if (!had_proxy)
     context_provider_ = create_context_provider_callback_.Run();
 
-  if (!context_provider_)
+  if (!context_provider_.get())
     return NULL;
-  return new StreamTextureProxyImpl(context_provider_);
+
+  if (observer_ && !had_proxy)
+    context_provider_->AddObserver(observer_);
+  return new StreamTextureProxyImpl(context_provider_.get());
 }
 
 void StreamTextureFactorySynchronousImpl::EstablishPeer(int32 stream_id,
                                                         int player_id) {
-  DCHECK(context_provider_);
+  DCHECK(context_provider_.get());
   scoped_refptr<gfx::SurfaceTexture> surface_texture =
       context_provider_->GetSurfaceTexture(stream_id);
-  if (surface_texture) {
+  if (surface_texture.get()) {
     SurfaceTexturePeer::GetInstance()->EstablishSurfaceTexturePeer(
-        base::Process::Current().handle(),
+        base::GetCurrentProcessHandle(),
         surface_texture,
-        view_id_,
+        frame_id_,
         player_id);
   }
 }
@@ -176,15 +196,15 @@ unsigned StreamTextureFactorySynchronousImpl::CreateStreamTexture(
     unsigned texture_target,
     unsigned* texture_id,
     gpu::Mailbox* texture_mailbox) {
-  DCHECK(context_provider_);
+  DCHECK(context_provider_.get());
   unsigned stream_id = 0;
   GLES2Interface* gl = context_provider_->ContextGL();
   gl->GenTextures(1, texture_id);
   stream_id = gl->CreateStreamTextureCHROMIUM(*texture_id);
 
   gl->GenMailboxCHROMIUM(texture_mailbox->name);
-  gl->BindTexture(texture_target, *texture_id);
-  gl->ProduceTextureCHROMIUM(texture_target, texture_mailbox->name);
+  gl->ProduceTextureDirectCHROMIUM(
+      *texture_id, texture_target, texture_mailbox->name);
   return stream_id;
 }
 
@@ -193,8 +213,24 @@ void StreamTextureFactorySynchronousImpl::SetStreamTextureSize(
     const gfx::Size& size) {}
 
 gpu::gles2::GLES2Interface* StreamTextureFactorySynchronousImpl::ContextGL() {
-  DCHECK(context_provider_);
+  DCHECK(context_provider_.get());
   return context_provider_->ContextGL();
 }
 
+void StreamTextureFactorySynchronousImpl::AddObserver(
+    StreamTextureFactoryContextObserver* obs) {
+  DCHECK(!observer_);
+  observer_ = obs;
+  if (context_provider_.get())
+    context_provider_->AddObserver(obs);
+}
+
+void StreamTextureFactorySynchronousImpl::RemoveObserver(
+    StreamTextureFactoryContextObserver* obs) {
+  DCHECK_EQ(observer_, obs);
+  observer_ = NULL;
+  if (context_provider_.get())
+    context_provider_->RemoveObserver(obs);
+}
+
 }  // namespace content