Chromium Code Reviews| 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. |