diff options
author | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-09 22:14:17 +0000 |
---|---|---|
committer | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-09 22:14:17 +0000 |
commit | 4508b15bef1094ccf68771f40f7b61013fee43ff (patch) | |
tree | a465e41f18421640c86ebb5326885397eb3b9e79 /content/browser/compositor | |
parent | a4139bb350549d2fefed191f2fb3c98fdfa42d41 (diff) | |
download | chromium_src-4508b15bef1094ccf68771f40f7b61013fee43ff.zip chromium_src-4508b15bef1094ccf68771f40f7b61013fee43ff.tar.gz chromium_src-4508b15bef1094ccf68771f40f7b61013fee43ff.tar.bz2 |
Make ReflectorImpl use mailboxes
- fixes ui::Layer::SetTextureMailbox to not be hard-coded for software
frames.
- adds a ui::Layer::SetTextureSize to update the size without sending a
new mailbox (since it doesn't change).
- entirely removes ui::Layer::SetExternalTexture and ui::Texture, and
derived classes.
- significantly changes the ReflectorImpl implementation:
* an OwnedMailbox is created on the main thread, using the shared main
thread context.
* the mailbox is passed to the impl thread, that creates a texture out
of it with the OutputSurface context, and does operations on that.
* the mailbox is passed to the layer.
* if the OutputSurface is recreated (assuming, after a lost context),
the OwnedMailbox is recreated, and passed to the impl side again,
together with the new surface.
* the OwnedMailbox takes care of deleting the texture, whether because
of a lost context, or when the ReflectorImpl is shut down.
BUG=333408
R=danakj@chromium.org, oshima@chromium.org, sky@chromium.org
Review URL: https://codereview.chromium.org/228083002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@262836 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/compositor')
11 files changed, 189 insertions, 244 deletions
diff --git a/content/browser/compositor/browser_compositor_output_surface.cc b/content/browser/compositor/browser_compositor_output_surface.cc index 6f82df4..b1cdd90 100644 --- a/content/browser/compositor/browser_compositor_output_surface.cc +++ b/content/browser/compositor/browser_compositor_output_surface.cc @@ -40,6 +40,9 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface( BrowserCompositorOutputSurface::~BrowserCompositorOutputSurface() { DCHECK(CalledOnValidThread()); + if (reflector_) + reflector_->DetachFromOutputSurface(); + DCHECK(!reflector_); if (!HasClient()) return; output_surface_map_->Remove(surface_id_); @@ -62,18 +65,11 @@ bool BrowserCompositorOutputSurface::BindToClient( output_surface_map_->AddWithID(this, surface_id_); if (reflector_) - reflector_->OnSourceSurfaceReady(surface_id_); + reflector_->OnSourceSurfaceReady(this); vsync_manager_->AddObserver(this); return true; } -void BrowserCompositorOutputSurface::Reshape(const gfx::Size& size, - float scale_factor) { - OutputSurface::Reshape(size, scale_factor); - if (reflector_.get()) - reflector_->OnReshape(size); -} - void BrowserCompositorOutputSurface::OnUpdateVSyncParameters( base::TimeTicks timebase, base::TimeDelta interval) { diff --git a/content/browser/compositor/browser_compositor_output_surface.h b/content/browser/compositor/browser_compositor_output_surface.h index 7c26b083..5f9378d 100644 --- a/content/browser/compositor/browser_compositor_output_surface.h +++ b/content/browser/compositor/browser_compositor_output_surface.h @@ -29,7 +29,6 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface // cc::OutputSurface implementation. virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE; - virtual void Reshape(const gfx::Size& size, float scale_factor) OVERRIDE; // ui::CompositorOutputSurface::Observer implementation. virtual void OnUpdateVSyncParameters(base::TimeTicks timebase, diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index 5ac65d9..e01a79b 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc @@ -57,55 +57,6 @@ struct GpuProcessTransportFactory::PerCompositorData { scoped_refptr<ReflectorImpl> reflector; }; -class OwnedTexture : public ui::Texture, ImageTransportFactoryObserver { - public: - OwnedTexture(const scoped_refptr<ContextProvider>& provider, - const gfx::Size& size, - float device_scale_factor, - GLuint texture_id) - : ui::Texture(true, size, device_scale_factor), - provider_(provider), - texture_id_(texture_id) { - ImageTransportFactory::GetInstance()->AddObserver(this); - } - - // ui::Texture overrides: - virtual unsigned int PrepareTexture() OVERRIDE { - // It's possible that we may have lost the context owning our - // texture but not yet fired the OnLostResources callback, so poll to see if - // it's still valid. - if (provider_ && provider_->IsContextLost()) - texture_id_ = 0u; - return texture_id_; - } - - // ImageTransportFactory overrides: - virtual void OnLostResources() OVERRIDE { - DeleteTexture(); - provider_ = NULL; - } - - protected: - virtual ~OwnedTexture() { - ImageTransportFactory::GetInstance()->RemoveObserver(this); - DeleteTexture(); - } - - protected: - void DeleteTexture() { - if (texture_id_) { - provider_->ContextGL()->DeleteTextures(1, &texture_id_); - texture_id_ = 0; - } - } - - scoped_refptr<cc::ContextProvider> provider_; - GLuint texture_id_; - - private: - DISALLOW_COPY_AND_ASSIGN(OwnedTexture); -}; - GpuProcessTransportFactory::GpuProcessTransportFactory() : callback_factory_(this), offscreen_content_bound_to_other_thread_(false) { output_surface_proxy_ = new BrowserCompositorOutputSurfaceProxy( @@ -233,12 +184,8 @@ scoped_refptr<ui::Reflector> GpuProcessTransportFactory::CreateReflector( PerCompositorData* data = per_compositor_data_[source]; DCHECK(data); - if (data->reflector.get()) - RemoveObserver(data->reflector.get()); - data->reflector = new ReflectorImpl( source, target, &output_surface_map_, data->surface_id); - AddObserver(data->reflector.get()); return data->reflector; } @@ -249,7 +196,6 @@ void GpuProcessTransportFactory::RemoveReflector( PerCompositorData* data = per_compositor_data_[reflector_impl->mirrored_compositor()]; DCHECK(data); - RemoveObserver(reflector_impl); data->reflector->Shutdown(); data->reflector = NULL; } @@ -290,19 +236,6 @@ gfx::GLSurfaceHandle GpuProcessTransportFactory::GetSharedSurfaceHandle() { return handle; } -scoped_refptr<ui::Texture> GpuProcessTransportFactory::CreateOwnedTexture( - const gfx::Size& size, - float device_scale_factor, - unsigned int texture_id) { - scoped_refptr<cc::ContextProvider> provider = - SharedMainThreadContextProvider(); - if (!provider.get()) - return NULL; - scoped_refptr<OwnedTexture> image(new OwnedTexture( - provider, size, device_scale_factor, texture_id)); - return image; -} - GLHelper* GpuProcessTransportFactory::GetGLHelper() { if (!gl_helper_ && !per_compositor_data_.empty()) { scoped_refptr<cc::ContextProvider> provider = diff --git a/content/browser/compositor/gpu_process_transport_factory.h b/content/browser/compositor/gpu_process_transport_factory.h index 1e936d2..18f7f85 100644 --- a/content/browser/compositor/gpu_process_transport_factory.h +++ b/content/browser/compositor/gpu_process_transport_factory.h @@ -52,10 +52,6 @@ class GpuProcessTransportFactory // ImageTransportFactory implementation. virtual ui::ContextFactory* AsContextFactory() OVERRIDE; virtual gfx::GLSurfaceHandle GetSharedSurfaceHandle() OVERRIDE; - virtual scoped_refptr<ui::Texture> CreateOwnedTexture( - const gfx::Size& size, - float device_scale_factor, - unsigned int texture_id) OVERRIDE; virtual GLHelper* GetGLHelper() OVERRIDE; virtual void AddObserver(ImageTransportFactoryObserver* observer) OVERRIDE; virtual void RemoveObserver( diff --git a/content/browser/compositor/image_transport_factory.h b/content/browser/compositor/image_transport_factory.h index f14fb20..1c6912f 100644 --- a/content/browser/compositor/image_transport_factory.h +++ b/content/browser/compositor/image_transport_factory.h @@ -69,12 +69,6 @@ class CONTENT_EXPORT ImageTransportFactory { virtual gfx::GLSurfaceHandle GetSharedSurfaceHandle() = 0; - // Creates a ui::Texture that deletes the GL texture when deleted. - virtual scoped_refptr<ui::Texture> CreateOwnedTexture( - const gfx::Size& size, - float device_scale_factor, - unsigned int texture_id) = 0; - // Gets a GLHelper instance, associated with the shared context. This // GLHelper will get destroyed whenever the shared context is lost // (ImageTransportFactoryObserver::OnLostResources is called). diff --git a/content/browser/compositor/image_transport_factory_browsertest.cc b/content/browser/compositor/image_transport_factory_browsertest.cc index fede399..d4792fb 100644 --- a/content/browser/compositor/image_transport_factory_browsertest.cc +++ b/content/browser/compositor/image_transport_factory_browsertest.cc @@ -5,6 +5,7 @@ #include "base/run_loop.h" #include "cc/output/context_provider.h" #include "content/browser/compositor/image_transport_factory.h" +#include "content/browser/compositor/owned_mailbox.h" #include "content/public/browser/gpu_data_manager.h" #include "content/public/test/content_browser_test.h" #include "gpu/GLES2/gl2extchromium.h" @@ -38,15 +39,10 @@ IN_PROC_BROWSER_TEST_F(ImageTransportFactoryBrowserTest, return; ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); - ui::ContextFactory* context_factory = ui::ContextFactory::GetInstance(); - gpu::gles2::GLES2Interface* gl = - context_factory->SharedMainThreadContextProvider()->ContextGL(); - GLuint texture_id = 0; - gl->GenTextures(1, &texture_id); - scoped_refptr<ui::Texture> texture = - factory->CreateOwnedTexture(gfx::Size(1, 1), 1.f, texture_id); - ASSERT_TRUE(texture.get()); + scoped_refptr<OwnedMailbox> mailbox = + new OwnedMailbox(factory->GetGLHelper()); + EXPECT_FALSE(mailbox->mailbox().IsZero()); MockImageTransportFactoryObserver observer; factory->AddObserver(&observer); @@ -55,6 +51,9 @@ IN_PROC_BROWSER_TEST_F(ImageTransportFactoryBrowserTest, EXPECT_CALL(observer, OnLostResources()) .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); + ui::ContextFactory* context_factory = ui::ContextFactory::GetInstance(); + gpu::gles2::GLES2Interface* gl = + context_factory->SharedMainThreadContextProvider()->ContextGL(); gl->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB); @@ -63,7 +62,7 @@ IN_PROC_BROWSER_TEST_F(ImageTransportFactoryBrowserTest, gl->Flush(); run_loop.Run(); - EXPECT_EQ(0u, texture->PrepareTexture()); + EXPECT_TRUE(mailbox->mailbox().IsZero()); factory->RemoveObserver(&observer); } diff --git a/content/browser/compositor/no_transport_image_transport_factory.cc b/content/browser/compositor/no_transport_image_transport_factory.cc index fd56b68..d1c5951 100644 --- a/content/browser/compositor/no_transport_image_transport_factory.cc +++ b/content/browser/compositor/no_transport_image_transport_factory.cc @@ -26,13 +26,6 @@ NoTransportImageTransportFactory::GetSharedSurfaceHandle() { return gfx::GLSurfaceHandle(); } -scoped_refptr<ui::Texture> NoTransportImageTransportFactory::CreateOwnedTexture( - const gfx::Size& size, - float device_scale_factor, - unsigned int texture_id) { - return NULL; -} - GLHelper* NoTransportImageTransportFactory::GetGLHelper() { if (!gl_helper_) { context_provider_ = context_factory_->SharedMainThreadContextProvider(); diff --git a/content/browser/compositor/no_transport_image_transport_factory.h b/content/browser/compositor/no_transport_image_transport_factory.h index 1d72449..a0f6216 100644 --- a/content/browser/compositor/no_transport_image_transport_factory.h +++ b/content/browser/compositor/no_transport_image_transport_factory.h @@ -24,10 +24,6 @@ class NoTransportImageTransportFactory : public ImageTransportFactory { // ImageTransportFactory implementation. virtual ui::ContextFactory* AsContextFactory() OVERRIDE; virtual gfx::GLSurfaceHandle GetSharedSurfaceHandle() OVERRIDE; - virtual scoped_refptr<ui::Texture> CreateOwnedTexture( - const gfx::Size& size, - float device_scale_factor, - unsigned int texture_id) OVERRIDE; virtual GLHelper* GetGLHelper() OVERRIDE; virtual void AddObserver(ImageTransportFactoryObserver* observer) OVERRIDE; virtual void RemoveObserver(ImageTransportFactoryObserver* observer) OVERRIDE; diff --git a/content/browser/compositor/owned_mailbox.h b/content/browser/compositor/owned_mailbox.h index 6fc4258..3926c81 100644 --- a/content/browser/compositor/owned_mailbox.h +++ b/content/browser/compositor/owned_mailbox.h @@ -22,6 +22,7 @@ class CONTENT_EXPORT OwnedMailbox : public base::RefCounted<OwnedMailbox>, public: explicit OwnedMailbox(GLHelper* gl_helper); + const gpu::MailboxHolder& holder() const { return mailbox_holder_; } const gpu::Mailbox& mailbox() const { return mailbox_holder_.mailbox; } uint32 texture_id() const { return texture_id_; } uint32 target() const { return mailbox_holder_.texture_target; } diff --git a/content/browser/compositor/reflector_impl.cc b/content/browser/compositor/reflector_impl.cc index 428aaad..14e992b 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 diff --git a/content/browser/compositor/reflector_impl.h b/content/browser/compositor/reflector_impl.h index 82c1f46..e20e4b9 100644 --- a/content/browser/compositor/reflector_impl.h +++ b/content/browser/compositor/reflector_impl.h @@ -10,6 +10,7 @@ #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "content/browser/compositor/image_transport_factory.h" +#include "gpu/command_buffer/common/mailbox_holder.h" #include "ui/compositor/reflector.h" #include "ui/gfx/size.h" @@ -24,12 +25,12 @@ class Layer; namespace content { +class OwnedMailbox; class BrowserCompositorOutputSurface; // A reflector implementation that copies the framebuffer content // to the texture, then draw it onto the mirroring compositor. -class ReflectorImpl : public ImageTransportFactoryObserver, - public base::SupportsWeakPtr<ReflectorImpl>, +class ReflectorImpl : public base::SupportsWeakPtr<ReflectorImpl>, public ui::Reflector { public: ReflectorImpl( @@ -39,10 +40,10 @@ class ReflectorImpl : public ImageTransportFactoryObserver, int surface_id); ui::Compositor* mirrored_compositor() { - return mirrored_compositor_; + return GetMain().mirrored_compositor; } - void InitOnImplThread(); + void InitOnImplThread(const gpu::MailboxHolder& mailbox_holder); void Shutdown(); void ShutdownOnImplThread(); @@ -53,13 +54,6 @@ class ReflectorImpl : public ImageTransportFactoryObserver, // ui::Reflector implementation. virtual void OnMirroringCompositorResized() OVERRIDE; - // ImageTransportFactoryObsever implementation. - virtual void OnLostResources() OVERRIDE; - - // Called when the output surface's size has changed. - // This must be called on ImplThread. - void OnReshape(gfx::Size size); - // Called in |BrowserCompositorOutputSurface::SwapBuffers| to copy // the full screen image to the |texture_id_|. This must be called // on ImplThread. @@ -78,12 +72,36 @@ class ReflectorImpl : public ImageTransportFactoryObserver, // Called when the source surface is bound and available. This must // be called on ImplThread. - void OnSourceSurfaceReady(int surface_id); + void OnSourceSurfaceReady(BrowserCompositorOutputSurface* surface); + + void DetachFromOutputSurface(); private: + struct MainThreadData { + MainThreadData(ui::Compositor* mirrored_compositor, + ui::Layer* mirroring_layer); + ~MainThreadData(); + scoped_refptr<OwnedMailbox> mailbox; + bool needs_set_mailbox; + ui::Compositor* mirrored_compositor; + ui::Layer* mirroring_layer; + }; + + struct ImplThreadData { + explicit ImplThreadData( + IDMap<BrowserCompositorOutputSurface>* output_surface_map); + ~ImplThreadData(); + IDMap<BrowserCompositorOutputSurface>* output_surface_map; + BrowserCompositorOutputSurface* output_surface; + scoped_ptr<GLHelper> gl_helper; + unsigned texture_id; + gpu::MailboxHolder mailbox_holder; + }; + virtual ~ReflectorImpl(); void AttachToOutputSurfaceOnImplThread( + const gpu::MailboxHolder& mailbox_holder, BrowserCompositorOutputSurface* surface); void UpdateTextureSizeOnMainThread(gfx::Size size); @@ -101,25 +119,16 @@ class ReflectorImpl : public ImageTransportFactoryObserver, // so the ReflectorImpl gets deleted when the function returns. static void DeleteOnMainThread(scoped_refptr<ReflectorImpl> reflector) {} - // These variables are initialized on MainThread before - // the reflector is attached to the output surface. Once - // attached, they must be accessed only on ImplThraed unless - // the context is lost. When the context is lost, these - // will be re-ininitiailzed when the new output-surface - // is created on MainThread. - int texture_id_; - base::Lock texture_lock_; - gfx::Size texture_size_; - - // Must be accessed only on ImplThread. - IDMap<BrowserCompositorOutputSurface>* output_surface_map_; - scoped_ptr<GLHelper> gl_helper_; - - // Must be accessed only on MainThread. - ui::Compositor* mirrored_compositor_; - ui::Compositor* mirroring_compositor_; - ui::Layer* mirroring_layer_; - scoped_refptr<ui::Texture> shared_texture_; + MainThreadData& GetMain(); + ImplThreadData& GetImpl(); + + // Must be accessed only on ImplThread, through GetImpl(). + ImplThreadData impl_unsafe_; + + // Must be accessed only on MainThread, through GetMain(). + MainThreadData main_unsafe_; + + // Can be accessed on both. scoped_refptr<base::MessageLoopProxy> impl_message_loop_; scoped_refptr<base::MessageLoopProxy> main_message_loop_; int surface_id_; |