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..14e992b939ac2145411a2f269d595ab16df5fd93 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,199 +18,227 @@ 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), |
- mirrored_compositor_(mirrored_compositor), |
- mirroring_compositor_(mirroring_layer->GetCompositor()), |
- mirroring_layer_(mirroring_layer), |
+ : impl_unsafe_(output_surface_map), |
+ main_unsafe_(mirrored_compositor, mirroring_layer), |
impl_message_loop_(ui::Compositor::GetCompositorMessageLoop()), |
main_message_loop_(base::MessageLoopProxy::current()), |
surface_id_(surface_id) { |
+ GLHelper* helper = ImageTransportFactory::GetInstance()->GetGLHelper(); |
+ MainThreadData& main = GetMain(); |
+ main.mailbox = new OwnedMailbox(helper); |
impl_message_loop_->PostTask( |
FROM_HERE, |
- base::Bind(&ReflectorImpl::InitOnImplThread, this)); |
+ base::Bind( |
+ &ReflectorImpl::InitOnImplThread, this, main.mailbox->holder())); |
} |
-void ReflectorImpl::InitOnImplThread() { |
+ReflectorImpl::MainThreadData::MainThreadData( |
+ ui::Compositor* mirrored_compositor, |
+ ui::Layer* mirroring_layer) |
+ : needs_set_mailbox(true), |
+ mirrored_compositor(mirrored_compositor), |
+ mirroring_layer(mirroring_layer) {} |
+ |
+ReflectorImpl::MainThreadData::~MainThreadData() {} |
+ |
+ReflectorImpl::ImplThreadData::ImplThreadData( |
+ IDMap<BrowserCompositorOutputSurface>* output_surface_map) |
+ : output_surface_map(output_surface_map), |
+ output_surface(NULL), |
+ texture_id(0) {} |
+ |
+ReflectorImpl::ImplThreadData::~ImplThreadData() {} |
+ |
+ReflectorImpl::ImplThreadData& ReflectorImpl::GetImpl() { |
+ DCHECK(impl_message_loop_->BelongsToCurrentThread()); |
+ return impl_unsafe_; |
+} |
+ |
+ReflectorImpl::MainThreadData& ReflectorImpl::GetMain() { |
+ DCHECK(main_message_loop_->BelongsToCurrentThread()); |
+ return main_unsafe_; |
+} |
+ |
+void ReflectorImpl::InitOnImplThread(const gpu::MailboxHolder& mailbox_holder) { |
+ ImplThreadData& impl = GetImpl(); |
// Ignore if the reflector was shutdown before |
// initialized, or it's already initialized. |
- if (!output_surface_map_ || gl_helper_.get()) |
+ if (!impl.output_surface_map || impl.gl_helper.get()) |
return; |
+ impl.mailbox_holder = mailbox_holder; |
+ |
BrowserCompositorOutputSurface* source_surface = |
- output_surface_map_->Lookup(surface_id_); |
+ impl.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.mailbox_holder, source_surface); |
} |
-void ReflectorImpl::OnSourceSurfaceReady(int surface_id) { |
- DCHECK_EQ(surface_id_, surface_id); |
- InitOnImplThread(); |
+void ReflectorImpl::OnSourceSurfaceReady( |
+ BrowserCompositorOutputSurface* source_surface) { |
+ ImplThreadData& impl = GetImpl(); |
+ AttachToOutputSurfaceOnImplThread(impl.mailbox_holder, source_surface); |
} |
void ReflectorImpl::Shutdown() { |
- mirroring_compositor_ = NULL; |
- mirroring_layer_ = NULL; |
- { |
- base::AutoLock lock(texture_lock_); |
- texture_id_ = 0; |
- } |
- shared_texture_ = NULL; |
+ MainThreadData& main = GetMain(); |
+ main.mailbox = NULL; |
+ main.mirroring_layer->SetShowPaintedContent(); |
+ main.mirroring_layer = NULL; |
impl_message_loop_->PostTask( |
- FROM_HERE, |
- base::Bind(&ReflectorImpl::ShutdownOnImplThread, this)); |
+ FROM_HERE, base::Bind(&ReflectorImpl::ShutdownOnImplThread, this)); |
+} |
+ |
+void ReflectorImpl::DetachFromOutputSurface() { |
+ ImplThreadData& impl = GetImpl(); |
+ DCHECK(impl.output_surface); |
+ impl.output_surface->SetReflector(NULL); |
+ DCHECK(impl.texture_id); |
+ impl.gl_helper->DeleteTexture(impl.texture_id); |
+ impl.texture_id = 0; |
+ impl.gl_helper.reset(); |
+ impl.output_surface = NULL; |
} |
void ReflectorImpl::ShutdownOnImplThread() { |
- BrowserCompositorOutputSurface* output_surface = |
- output_surface_map_->Lookup(surface_id_); |
- if (output_surface) |
- output_surface->SetReflector(NULL); |
- output_surface_map_ = NULL; |
- gl_helper_.reset(); |
+ ImplThreadData& impl = GetImpl(); |
+ if (impl.output_surface) |
+ DetachFromOutputSurface(); |
+ impl.output_surface_map = NULL; |
// The instance must be deleted on main thread. |
- main_message_loop_->PostTask( |
- FROM_HERE, |
- base::Bind(&ReflectorImpl::DeleteOnMainThread, |
- scoped_refptr<ReflectorImpl>(this))); |
+ main_message_loop_->PostTask(FROM_HERE, |
+ base::Bind(&ReflectorImpl::DeleteOnMainThread, |
+ scoped_refptr<ReflectorImpl>(this))); |
} |
void ReflectorImpl::ReattachToOutputSurfaceFromMainThread( |
BrowserCompositorOutputSurface* output_surface) { |
+ MainThreadData& main = GetMain(); |
+ GLHelper* helper = ImageTransportFactory::GetInstance()->GetGLHelper(); |
+ main.mailbox = new OwnedMailbox(helper); |
+ main.needs_set_mailbox = true; |
+ main.mirroring_layer->SetShowPaintedContent(); |
impl_message_loop_->PostTask( |
FROM_HERE, |
base::Bind(&ReflectorImpl::AttachToOutputSurfaceOnImplThread, |
- this, output_surface)); |
+ this, |
+ main.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_)); |
+ MainThreadData& main = GetMain(); |
+ main.mirroring_layer->SchedulePaint(main.mirroring_layer->bounds()); |
} |
void ReflectorImpl::OnSwapBuffers() { |
- { |
- base::AutoLock lock(texture_lock_); |
- if (texture_id_) { |
- gl_helper_->CopyTextureFullImage(texture_id_, texture_size_); |
- gl_helper_->Flush(); |
- } |
+ ImplThreadData& impl = GetImpl(); |
+ gfx::Size size = impl.output_surface->SurfaceSize(); |
+ if (impl.texture_id) { |
+ impl.gl_helper->CopyTextureFullImage(impl.texture_id, size); |
+ impl.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(); |
- } |
+ ImplThreadData& impl = GetImpl(); |
+ if (impl.texture_id) { |
+ impl.gl_helper->CopyTextureSubImage(impl.texture_id, rect); |
+ impl.gl_helper->Flush(); |
} |
main_message_loop_->PostTask( |
FROM_HERE, |
base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread, |
this->AsWeakPtr(), |
- texture_size_, |
+ impl.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()); |
+ 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) { |
+ ImplThreadData& impl = GetImpl(); |
+ if (output_surface == impl.output_surface) |
+ return; |
+ if (impl.output_surface) |
+ DetachFromOutputSurface(); |
+ impl.output_surface = output_surface; |
output_surface->context_provider()->BindToCurrentThread(); |
- gl_helper_.reset( |
+ impl.gl_helper.reset( |
new GLHelper(output_surface->context_provider()->ContextGL(), |
output_surface->context_provider()->ContextSupport())); |
+ impl.texture_id = impl.gl_helper->ConsumeMailboxToTexture( |
+ mailbox_holder.mailbox, mailbox_holder.sync_point); |
+ impl.gl_helper->ResizeTexture(impl.texture_id, output_surface->SurfaceSize()); |
+ impl.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_) |
+ MainThreadData& main = GetMain(); |
+ if (!main.mirroring_layer || !main.mailbox || |
+ main.mailbox->mailbox().IsZero()) |
return; |
- mirroring_layer_->SetBounds(gfx::Rect(size)); |
+ if (main.needs_set_mailbox) { |
+ main.mirroring_layer->SetTextureMailbox( |
+ cc::TextureMailbox(main.mailbox->holder()), |
+ cc::SingleReleaseCallback::Create( |
+ base::Bind(ReleaseMailbox, main.mailbox)), |
+ size); |
+ main.needs_set_mailbox = false; |
+ } else { |
+ main.mirroring_layer->SetTextureSize(size); |
+ } |
+ main.mirroring_layer->SetBounds(gfx::Rect(size)); |
} |
void ReflectorImpl::FullRedrawOnMainThread(gfx::Size size) { |
- if (!mirroring_compositor_) |
+ MainThreadData& main = GetMain(); |
+ if (!main.mirroring_layer) |
return; |
UpdateTextureSizeOnMainThread(size); |
- mirroring_compositor_->ScheduleFullRedraw(); |
+ main.mirroring_layer->SchedulePaint(main.mirroring_layer->bounds()); |
} |
void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size, |
gfx::Rect rect) { |
- if (!mirroring_compositor_) |
+ MainThreadData& main = GetMain(); |
+ if (!main.mirroring_layer) |
return; |
UpdateTextureSizeOnMainThread(size); |
// Flip the coordinates to compositor's one. |
int y = size.height() - rect.y() - rect.height(); |
gfx::Rect new_rect(rect.x(), y, rect.width(), rect.height()); |
- mirroring_layer_->SchedulePaint(new_rect); |
+ main.mirroring_layer->SchedulePaint(new_rect); |
} |
void ReflectorImpl::FullRedrawContentOnMainThread() { |
- mirrored_compositor_->ScheduleFullRedraw(); |
+ MainThreadData& main = GetMain(); |
+ main.mirrored_compositor->ScheduleFullRedraw(); |
} |
} // namespace content |