Index: content/browser/compositor/reflector_impl.cc |
diff --git a/content/browser/compositor/reflector_impl.cc b/content/browser/compositor/reflector_impl.cc |
index 428aaad4105cee636b9a6fab236f2c9365a157c6..528237c1d2a9220330d635eda0d42fd36ec23e35 100644 |
--- a/content/browser/compositor/reflector_impl.cc |
+++ b/content/browser/compositor/reflector_impl.cc |
@@ -7,6 +7,7 @@ |
#include "base/bind.h" |
#include "base/location.h" |
#include "content/browser/compositor/browser_compositor_output_surface.h" |
+#include "content/browser/compositor/owned_mailbox.h" |
#include "content/common/gpu/client/gl_helper.h" |
#include "ui/compositor/layer.h" |
@@ -17,67 +18,71 @@ ReflectorImpl::ReflectorImpl( |
ui::Layer* mirroring_layer, |
IDMap<BrowserCompositorOutputSurface>* output_surface_map, |
int surface_id) |
- : texture_id_(0), |
- texture_size_(mirrored_compositor->size()), |
- output_surface_map_(output_surface_map), |
+ : output_surface_map_(output_surface_map), |
+ output_surface_(NULL), |
+ impl_thread_texture_id_(0), |
+ needs_set_mailbox_(true), |
mirrored_compositor_(mirrored_compositor), |
- mirroring_compositor_(mirroring_layer->GetCompositor()), |
mirroring_layer_(mirroring_layer), |
impl_message_loop_(ui::Compositor::GetCompositorMessageLoop()), |
main_message_loop_(base::MessageLoopProxy::current()), |
surface_id_(surface_id) { |
- impl_message_loop_->PostTask( |
- FROM_HERE, |
- base::Bind(&ReflectorImpl::InitOnImplThread, this)); |
+ GLHelper* helper = ImageTransportFactory::GetInstance()->GetGLHelper(); |
+ main_thread_mailbox_ = new OwnedMailbox(helper); |
+ impl_message_loop_->PostTask(FROM_HERE, |
+ base::Bind(&ReflectorImpl::InitOnImplThread, |
+ this, |
+ main_thread_mailbox_->holder())); |
} |
-void ReflectorImpl::InitOnImplThread() { |
+void ReflectorImpl::InitOnImplThread(const gpu::MailboxHolder& mailbox_holder) { |
// Ignore if the reflector was shutdown before |
// initialized, or it's already initialized. |
if (!output_surface_map_ || gl_helper_.get()) |
return; |
+ impl_thread_mailbox_holder_ = mailbox_holder; |
+ |
BrowserCompositorOutputSurface* source_surface = |
output_surface_map_->Lookup(surface_id_); |
// Skip if the source surface isn't ready yet. This will be |
- // initiailze when the source surface becomes ready. |
+ // initialized when the source surface becomes ready. |
if (!source_surface) |
return; |
- AttachToOutputSurfaceOnImplThread(source_surface); |
- // The shared texture doesn't have the data, so invokes full redraw |
- // now. |
- main_message_loop_->PostTask( |
- FROM_HERE, |
- base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread, |
- scoped_refptr<ReflectorImpl>(this))); |
+ AttachToOutputSurfaceOnImplThread(impl_thread_mailbox_holder_, |
+ source_surface); |
} |
-void ReflectorImpl::OnSourceSurfaceReady(int surface_id) { |
- DCHECK_EQ(surface_id_, surface_id); |
- InitOnImplThread(); |
+void ReflectorImpl::OnSourceSurfaceReady( |
+ BrowserCompositorOutputSurface* source_surface) { |
+ AttachToOutputSurfaceOnImplThread(impl_thread_mailbox_holder_, |
+ source_surface); |
} |
void ReflectorImpl::Shutdown() { |
- mirroring_compositor_ = NULL; |
+ main_thread_mailbox_ = NULL; |
+ mirroring_layer_->SetShowPaintedContent(); |
mirroring_layer_ = NULL; |
- { |
- base::AutoLock lock(texture_lock_); |
- texture_id_ = 0; |
- } |
- shared_texture_ = NULL; |
impl_message_loop_->PostTask( |
FROM_HERE, |
base::Bind(&ReflectorImpl::ShutdownOnImplThread, this)); |
} |
+void ReflectorImpl::DetachFromOutputSurface() { |
+ DCHECK(output_surface_); |
+ output_surface_->SetReflector(NULL); |
+ DCHECK(impl_thread_texture_id_); |
+ gl_helper_->DeleteTexture(impl_thread_texture_id_); |
+ impl_thread_texture_id_ = 0; |
+ gl_helper_.reset(); |
+ output_surface_ = NULL; |
+} |
+ |
void ReflectorImpl::ShutdownOnImplThread() { |
- BrowserCompositorOutputSurface* output_surface = |
- output_surface_map_->Lookup(surface_id_); |
- if (output_surface) |
- output_surface->SetReflector(NULL); |
+ if (output_surface_) |
+ DetachFromOutputSurface(); |
output_surface_map_ = NULL; |
- gl_helper_.reset(); |
// The instance must be deleted on main thread. |
main_message_loop_->PostTask( |
FROM_HERE, |
@@ -87,119 +92,113 @@ void ReflectorImpl::ShutdownOnImplThread() { |
void ReflectorImpl::ReattachToOutputSurfaceFromMainThread( |
BrowserCompositorOutputSurface* output_surface) { |
+ GLHelper* helper = ImageTransportFactory::GetInstance()->GetGLHelper(); |
+ main_thread_mailbox_ = new OwnedMailbox(helper); |
+ needs_set_mailbox_ = true; |
impl_message_loop_->PostTask( |
FROM_HERE, |
base::Bind(&ReflectorImpl::AttachToOutputSurfaceOnImplThread, |
- this, output_surface)); |
+ this, |
+ main_thread_mailbox_->holder(), |
+ output_surface)); |
} |
void ReflectorImpl::OnMirroringCompositorResized() { |
- mirroring_compositor_->ScheduleFullRedraw(); |
-} |
- |
-void ReflectorImpl::OnLostResources() { |
- mirroring_layer_->SetShowPaintedContent(); |
-} |
- |
-void ReflectorImpl::OnReshape(gfx::Size size) { |
- if (texture_size_ == size) |
- return; |
- texture_size_ = size; |
- { |
- base::AutoLock lock(texture_lock_); |
- if (texture_id_) { |
- gl_helper_->ResizeTexture(texture_id_, size); |
- gl_helper_->Flush(); |
- } |
- } |
- main_message_loop_->PostTask( |
- FROM_HERE, |
- base::Bind(&ReflectorImpl::UpdateTextureSizeOnMainThread, |
- this->AsWeakPtr(), |
- texture_size_)); |
+ mirroring_layer_->SchedulePaint(mirroring_layer_->bounds()); |
} |
void ReflectorImpl::OnSwapBuffers() { |
- { |
- base::AutoLock lock(texture_lock_); |
- if (texture_id_) { |
- gl_helper_->CopyTextureFullImage(texture_id_, texture_size_); |
- gl_helper_->Flush(); |
- } |
+ gfx::Size size = output_surface_->SurfaceSize(); |
+ if (impl_thread_texture_id_) { |
+ gl_helper_->CopyTextureFullImage(impl_thread_texture_id_, size); |
+ gl_helper_->Flush(); |
} |
main_message_loop_->PostTask( |
FROM_HERE, |
- base::Bind(&ReflectorImpl::FullRedrawOnMainThread, |
- this->AsWeakPtr(), |
- texture_size_)); |
+ base::Bind( |
+ &ReflectorImpl::FullRedrawOnMainThread, this->AsWeakPtr(), size)); |
} |
void ReflectorImpl::OnPostSubBuffer(gfx::Rect rect) { |
- { |
- base::AutoLock lock(texture_lock_); |
- if (texture_id_) { |
- gl_helper_->CopyTextureSubImage(texture_id_, rect); |
- gl_helper_->Flush(); |
- } |
+ if (impl_thread_texture_id_) { |
+ gl_helper_->CopyTextureSubImage(impl_thread_texture_id_, rect); |
+ gl_helper_->Flush(); |
} |
main_message_loop_->PostTask( |
FROM_HERE, |
base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread, |
this->AsWeakPtr(), |
- texture_size_, |
+ output_surface_->SurfaceSize(), |
rect)); |
} |
-void ReflectorImpl::CreateSharedTextureOnMainThread(gfx::Size size) { |
- { |
- base::AutoLock lock(texture_lock_); |
- texture_id_ = |
- ImageTransportFactory::GetInstance()->GetGLHelper()->CreateTexture(); |
- shared_texture_ = |
- ImageTransportFactory::GetInstance()->CreateOwnedTexture( |
- size, 1.0f, texture_id_); |
- ImageTransportFactory::GetInstance()->GetGLHelper()->Flush(); |
- } |
- mirroring_layer_->SetExternalTexture(shared_texture_.get()); |
- FullRedrawOnMainThread(size); |
-} |
- |
ReflectorImpl::~ReflectorImpl() { |
// Make sure the reflector is deleted on main thread. |
DCHECK_EQ(main_message_loop_.get(), |
base::MessageLoopProxy::current().get()); |
} |
+static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox, |
+ unsigned int sync_point, |
+ bool is_lost) { |
+ mailbox->UpdateSyncPoint(sync_point); |
+} |
+ |
void ReflectorImpl::AttachToOutputSurfaceOnImplThread( |
+ const gpu::MailboxHolder& mailbox_holder, |
BrowserCompositorOutputSurface* output_surface) { |
+ if (output_surface == output_surface_) |
+ return; |
+ if (output_surface_) |
+ DetachFromOutputSurface(); |
+ output_surface_ = output_surface; |
output_surface->context_provider()->BindToCurrentThread(); |
gl_helper_.reset( |
new GLHelper(output_surface->context_provider()->ContextGL(), |
output_surface->context_provider()->ContextSupport())); |
+ impl_thread_texture_id_ = gl_helper_->ConsumeMailboxToTexture( |
+ mailbox_holder.mailbox, mailbox_holder.sync_point); |
+ gl_helper_->ResizeTexture(impl_thread_texture_id_, |
+ output_surface->SurfaceSize()); |
+ gl_helper_->Flush(); |
output_surface->SetReflector(this); |
+ // The texture doesn't have the data, so invokes full redraw now. |
main_message_loop_->PostTask( |
FROM_HERE, |
- base::Bind(&ReflectorImpl::CreateSharedTextureOnMainThread, |
- this->AsWeakPtr(), |
- texture_size_)); |
+ base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread, |
+ scoped_refptr<ReflectorImpl>(this))); |
} |
void ReflectorImpl::UpdateTextureSizeOnMainThread(gfx::Size size) { |
- if (!mirroring_layer_) |
+ if (!mirroring_layer_ || !main_thread_mailbox_ || |
+ main_thread_mailbox_->mailbox().IsZero()) |
danakj
2014/04/08 16:08:01
I'm not sure where this method is all called, but
piman
2014/04/08 23:17:46
It can't fail in ReattachToOutputSurfaceFromMainTh
|
return; |
+ if (needs_set_mailbox_) { |
+ mirroring_layer_->SetTextureMailbox( |
+ cc::TextureMailbox(main_thread_mailbox_->holder()), |
+ cc::SingleReleaseCallback::Create( |
+ base::Bind(ReleaseMailbox, main_thread_mailbox_)), |
+ size); |
+ needs_set_mailbox_ = false; |
+ } else if (size != texture_size_) { |
danakj
2014/04/08 16:08:01
This texture_size_ is only here to prevent extra c
piman
2014/04/08 23:17:46
I wanted to avoid full layer invalidations if the
|
+ mirroring_layer_->SetTextureSize(size); |
+ } else { |
+ return; |
+ } |
mirroring_layer_->SetBounds(gfx::Rect(size)); |
+ texture_size_ = size; |
} |
void ReflectorImpl::FullRedrawOnMainThread(gfx::Size size) { |
- if (!mirroring_compositor_) |
+ if (!mirroring_layer_) |
return; |
UpdateTextureSizeOnMainThread(size); |
- mirroring_compositor_->ScheduleFullRedraw(); |
+ mirroring_layer_->SchedulePaint(mirroring_layer_->bounds()); |
} |
void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size, |
gfx::Rect rect) { |
- if (!mirroring_compositor_) |
+ if (!mirroring_layer_) |
return; |
UpdateTextureSizeOnMainThread(size); |
// Flip the coordinates to compositor's one. |