diff options
author | reveman <reveman@chromium.org> | 2015-09-23 17:19:43 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-09-24 00:34:48 +0000 |
commit | d180dfc3198c1e58a8c10f7349f3d949e22c5f3d (patch) | |
tree | 3f1b2d58647d991dd3ab1d3ba13da4f7d8205979 | |
parent | f86718093f9c88d956207b527cf5bed4a872a24f (diff) | |
download | chromium_src-d180dfc3198c1e58a8c10f7349f3d949e22c5f3d.zip chromium_src-d180dfc3198c1e58a8c10f7349f3d949e22c5f3d.tar.gz chromium_src-d180dfc3198c1e58a8c10f7349f3d949e22c5f3d.tar.bz2 |
Re-land: cc: Implement shared worker contexts.
This moves the responsibility to call BindToCurrentThread/SetupLock out
of cc::OutputSurface and to the maintainer of the (possibly) shared
context.
OutputSurface now needs to be destroyed on the same thread they
were created. OutputSurface::DetachFromClient() can be used to
destroy any resources that need to be destroyed on the thread
that the OutputSurface has been bound to.
BUG=523411,525811
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
Review URL: https://codereview.chromium.org/1336733002
Cr-Commit-Position: refs/heads/master@{#350409}
54 files changed, 451 insertions, 199 deletions
diff --git a/cc/layers/delegated_renderer_layer_impl_unittest.cc b/cc/layers/delegated_renderer_layer_impl_unittest.cc index 69857dc..8410221 100644 --- a/cc/layers/delegated_renderer_layer_impl_unittest.cc +++ b/cc/layers/delegated_renderer_layer_impl_unittest.cc @@ -32,13 +32,14 @@ class DelegatedRendererLayerImplTest : public testing::Test { public: DelegatedRendererLayerImplTest() : proxy_(), - always_impl_thread_and_main_thread_blocked_(&proxy_) { + always_impl_thread_and_main_thread_blocked_(&proxy_), + output_surface_(FakeOutputSurface::Create3d()) { LayerTreeSettings settings; settings.minimum_occlusion_tracking_size = gfx::Size(); host_impl_.reset(new FakeLayerTreeHostImpl( settings, &proxy_, &shared_bitmap_manager_, &task_graph_runner_)); - host_impl_->InitializeRenderer(FakeOutputSurface::Create3d()); + host_impl_->InitializeRenderer(output_surface_.get()); host_impl_->SetViewportSize(gfx::Size(10, 10)); } @@ -48,6 +49,7 @@ class DelegatedRendererLayerImplTest : public testing::Test { always_impl_thread_and_main_thread_blocked_; TestSharedBitmapManager shared_bitmap_manager_; TestTaskGraphRunner task_graph_runner_; + scoped_ptr<OutputSurface> output_surface_; scoped_ptr<LayerTreeHostImpl> host_impl_; }; diff --git a/cc/layers/heads_up_display_layer_impl_unittest.cc b/cc/layers/heads_up_display_layer_impl_unittest.cc index ad22155..ef37783 100644 --- a/cc/layers/heads_up_display_layer_impl_unittest.cc +++ b/cc/layers/heads_up_display_layer_impl_unittest.cc @@ -34,10 +34,11 @@ TEST(HeadsUpDisplayLayerImplTest, ResourcelessSoftwareDrawAfterResourceLoss) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; TestTaskGraphRunner task_graph_runner; + scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(); FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, &task_graph_runner); host_impl.CreatePendingTree(); - host_impl.InitializeRenderer(FakeOutputSurface::Create3d()); + host_impl.InitializeRenderer(output_surface.get()); scoped_ptr<HeadsUpDisplayLayerImpl> layer = HeadsUpDisplayLayerImpl::Create(host_impl.pending_tree(), 1); layer->SetBounds(gfx::Size(100, 100)); diff --git a/cc/layers/layer_impl_unittest.cc b/cc/layers/layer_impl_unittest.cc index 0676597..7404e4e 100644 --- a/cc/layers/layer_impl_unittest.cc +++ b/cc/layers/layer_impl_unittest.cc @@ -89,9 +89,10 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; TestTaskGraphRunner task_graph_runner; + scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(); FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, &task_graph_runner); - EXPECT_TRUE(host_impl.InitializeRenderer(FakeOutputSurface::Create3d())); + EXPECT_TRUE(host_impl.InitializeRenderer(output_surface.get())); scoped_ptr<LayerImpl> root_clip = LayerImpl::Create(host_impl.active_tree(), 1); scoped_ptr<LayerImpl> root_ptr = @@ -247,9 +248,10 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; TestTaskGraphRunner task_graph_runner; + scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(); FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, &task_graph_runner); - EXPECT_TRUE(host_impl.InitializeRenderer(FakeOutputSurface::Create3d())); + EXPECT_TRUE(host_impl.InitializeRenderer(output_surface.get())); host_impl.active_tree()->SetRootLayer( LayerImpl::Create(host_impl.active_tree(), 1)); LayerImpl* root = host_impl.active_tree()->root_layer(); @@ -361,9 +363,10 @@ TEST(LayerImplTest, SafeOpaqueBackgroundColor) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; TestTaskGraphRunner task_graph_runner; + scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(); FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, &task_graph_runner); - EXPECT_TRUE(host_impl.InitializeRenderer(FakeOutputSurface::Create3d())); + EXPECT_TRUE(host_impl.InitializeRenderer(output_surface.get())); scoped_ptr<LayerImpl> layer = LayerImpl::Create(host_impl.active_tree(), 1); for (int contents_opaque = 0; contents_opaque < 2; ++contents_opaque) { diff --git a/cc/layers/nine_patch_layer_impl_unittest.cc b/cc/layers/nine_patch_layer_impl_unittest.cc index ac77d12..3405bc5 100644 --- a/cc/layers/nine_patch_layer_impl_unittest.cc +++ b/cc/layers/nine_patch_layer_impl_unittest.cc @@ -46,9 +46,10 @@ void NinePatchLayerLayoutTest(const gfx::Size& bitmap_size, FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; TestTaskGraphRunner task_graph_runner; + scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(); FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, &task_graph_runner); - host_impl.InitializeRenderer(FakeOutputSurface::Create3d()); + host_impl.InitializeRenderer(output_surface.get()); scoped_ptr<NinePatchLayerImpl> layer = NinePatchLayerImpl::Create(host_impl.active_tree(), 1); diff --git a/cc/layers/picture_image_layer_impl_unittest.cc b/cc/layers/picture_image_layer_impl_unittest.cc index 2a9dda7..01ad1f3 100644 --- a/cc/layers/picture_image_layer_impl_unittest.cc +++ b/cc/layers/picture_image_layer_impl_unittest.cc @@ -43,12 +43,13 @@ class PictureImageLayerImplTest : public testing::Test { public: PictureImageLayerImplTest() : proxy_(base::ThreadTaskRunnerHandle::Get()), + output_surface_(FakeOutputSurface::Create3d()), host_impl_(PictureLayerImplImageTestSettings(), &proxy_, &shared_bitmap_manager_, &task_graph_runner_) { host_impl_.CreatePendingTree(); - host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()); + host_impl_.InitializeRenderer(output_surface_.get()); } scoped_ptr<TestablePictureImageLayerImpl> CreateLayer(int id, @@ -93,6 +94,7 @@ class PictureImageLayerImplTest : public testing::Test { FakeImplProxy proxy_; TestSharedBitmapManager shared_bitmap_manager_; TestTaskGraphRunner task_graph_runner_; + scoped_ptr<OutputSurface> output_surface_; FakeLayerTreeHostImpl host_impl_; }; diff --git a/cc/layers/picture_layer_impl_perftest.cc b/cc/layers/picture_layer_impl_perftest.cc index 9e7d82b..85d8c26 100644 --- a/cc/layers/picture_layer_impl_perftest.cc +++ b/cc/layers/picture_layer_impl_perftest.cc @@ -41,6 +41,7 @@ class PictureLayerImplPerfTest : public testing::Test { public: PictureLayerImplPerfTest() : proxy_(base::ThreadTaskRunnerHandle::Get()), + output_surface_(FakeOutputSurface::Create3d()), host_impl_(LayerTreeSettings(), &proxy_, &shared_bitmap_manager_, @@ -50,7 +51,7 @@ class PictureLayerImplPerfTest : public testing::Test { kTimeCheckInterval) {} void SetUp() override { - host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()); + host_impl_.InitializeRenderer(output_surface_.get()); } void SetupActiveTree(const gfx::Size& layer_bounds, @@ -164,6 +165,7 @@ class PictureLayerImplPerfTest : public testing::Test { TestSharedBitmapManager shared_bitmap_manager_; TestTaskGraphRunner task_graph_runner_; FakeImplProxy proxy_; + scoped_ptr<OutputSurface> output_surface_; FakeLayerTreeHostImpl host_impl_; FakePictureLayerImpl* active_layer_; LapTimer timer_; diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index 1628c0c5..970742b 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc @@ -93,6 +93,7 @@ class PictureLayerImplTest : public testing::Test { public: PictureLayerImplTest() : proxy_(base::ThreadTaskRunnerHandle::Get()), + output_surface_(FakeOutputSurface::Create3d()), host_impl_(LowResTilingsSettings(), &proxy_, &shared_bitmap_manager_, @@ -107,6 +108,7 @@ class PictureLayerImplTest : public testing::Test { explicit PictureLayerImplTest(const LayerTreeSettings& settings) : proxy_(base::ThreadTaskRunnerHandle::Get()), + output_surface_(FakeOutputSurface::Create3d()), host_impl_(settings, &proxy_, &shared_bitmap_manager_, @@ -121,7 +123,7 @@ class PictureLayerImplTest : public testing::Test { void SetUp() override { InitializeRenderer(); } virtual void InitializeRenderer() { - host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()); + host_impl_.InitializeRenderer(output_surface_.get()); } void SetupDefaultTrees(const gfx::Size& layer_bounds) { @@ -359,6 +361,7 @@ class PictureLayerImplTest : public testing::Test { FakeImplProxy proxy_; TestSharedBitmapManager shared_bitmap_manager_; TestTaskGraphRunner task_graph_runner_; + scoped_ptr<OutputSurface> output_surface_; FakeLayerTreeHostImpl host_impl_; int root_id_; int id_; @@ -1627,8 +1630,10 @@ TEST_F(PictureLayerImplTest, ClampTilesToMaxTileSize) { TestWebGraphicsContext3D::Create(); context->set_max_texture_size(140); host_impl_.DidLoseOutputSurface(); - host_impl_.InitializeRenderer( - FakeOutputSurface::Create3d(context.Pass()).Pass()); + scoped_ptr<OutputSurface> new_output_surface = + FakeOutputSurface::Create3d(context.Pass()); + host_impl_.InitializeRenderer(new_output_surface.get()); + output_surface_ = new_output_surface.Pass(); SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, 0.f, false); @@ -1672,8 +1677,10 @@ TEST_F(PictureLayerImplTest, ClampSingleTileToToMaxTileSize) { TestWebGraphicsContext3D::Create(); context->set_max_texture_size(140); host_impl_.DidLoseOutputSurface(); - host_impl_.InitializeRenderer( - FakeOutputSurface::Create3d(context.Pass()).Pass()); + scoped_ptr<OutputSurface> new_output_surface = + FakeOutputSurface::Create3d(context.Pass()); + host_impl_.InitializeRenderer(new_output_surface.get()); + output_surface_ = new_output_surface.Pass(); SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, 0.f, false); @@ -3925,10 +3932,12 @@ TEST_F(PictureLayerImplTest, SharedQuadStateContainsMaxTilingScale) { class PictureLayerImplTestWithDelegatingRenderer : public PictureLayerImplTest { public: - PictureLayerImplTestWithDelegatingRenderer() : PictureLayerImplTest() {} + PictureLayerImplTestWithDelegatingRenderer() : PictureLayerImplTest() { + output_surface_ = FakeOutputSurface::CreateDelegating3d(); + } void InitializeRenderer() override { - host_impl_.InitializeRenderer(FakeOutputSurface::CreateDelegating3d()); + host_impl_.InitializeRenderer(output_surface_.get()); } }; diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc index 22962a7..8c138c3 100644 --- a/cc/layers/texture_layer_unittest.cc +++ b/cc/layers/texture_layer_unittest.cc @@ -189,6 +189,7 @@ class TextureLayerTest : public testing::Test { TextureLayerTest() : fake_client_( FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)), + output_surface_(FakeOutputSurface::Create3d()), host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_), test_data_(&shared_bitmap_manager_) {} @@ -214,6 +215,7 @@ class TextureLayerTest : public testing::Test { FakeLayerTreeHostClient fake_client_; TestSharedBitmapManager shared_bitmap_manager_; TestTaskGraphRunner task_graph_runner_; + scoped_ptr<OutputSurface> output_surface_; FakeLayerTreeHostImpl host_impl_; CommonMailboxObjects test_data_; LayerSettings layer_settings_; @@ -833,7 +835,7 @@ class TextureLayerImplWithMailboxTest : public TextureLayerTest { TextureLayerTest::SetUp(); layer_tree_host_ = MockLayerTreeHost::Create(&fake_client_, &task_graph_runner_); - EXPECT_TRUE(host_impl_.InitializeRenderer(FakeOutputSurface::Create3d())); + EXPECT_TRUE(host_impl_.InitializeRenderer(output_surface_.get())); } bool WillDraw(TextureLayerImpl* layer, DrawMode mode) { diff --git a/cc/layers/ui_resource_layer_impl_unittest.cc b/cc/layers/ui_resource_layer_impl_unittest.cc index e31d68a..826c53f 100644 --- a/cc/layers/ui_resource_layer_impl_unittest.cc +++ b/cc/layers/ui_resource_layer_impl_unittest.cc @@ -60,9 +60,10 @@ TEST(UIResourceLayerImplTest, VerifyDrawQuads) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; TestTaskGraphRunner task_graph_runner; + scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(); FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, &task_graph_runner); - host_impl.InitializeRenderer(FakeOutputSurface::Create3d()); + host_impl.InitializeRenderer(output_surface.get()); // Make sure we're appending quads when there are valid values. gfx::Size bitmap_size(100, 100); @@ -106,9 +107,10 @@ TEST(UIResourceLayerImplTest, VerifySetOpaqueOnSkBitmap) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; TestTaskGraphRunner task_graph_runner; + scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(); FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, &task_graph_runner); - host_impl.InitializeRenderer(FakeOutputSurface::Create3d()); + host_impl.InitializeRenderer(output_surface.get()); gfx::Size bitmap_size(100, 100); gfx::Size layer_size(100, 100);; @@ -136,9 +138,10 @@ TEST(UIResourceLayerImplTest, VerifySetOpaqueOnLayer) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; TestTaskGraphRunner task_graph_runner; + scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(); FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, &task_graph_runner); - host_impl.InitializeRenderer(FakeOutputSurface::Create3d()); + host_impl.InitializeRenderer(output_surface.get()); gfx::Size bitmap_size(100, 100); gfx::Size layer_size(100, 100); diff --git a/cc/output/context_provider.h b/cc/output/context_provider.h index c024e02..47eff20 100644 --- a/cc/output/context_provider.h +++ b/cc/output/context_provider.h @@ -32,11 +32,11 @@ class ContextProvider : public base::RefCountedThreadSafe<ContextProvider> { explicit ScopedContextLock(ContextProvider* context_provider) : context_provider_(context_provider), context_lock_(*context_provider_->GetLock()) { - // Allow current thread to bind to |context_provider|. + // Allow current thread to use |context_provider_|. context_provider_->DetachFromThread(); } ~ScopedContextLock() { - // Allow a different thread to bind to |context_provider|. + // Allow usage by thread for which |context_provider_| is bound to. context_provider_->DetachFromThread(); } @@ -51,7 +51,9 @@ class ContextProvider : public base::RefCountedThreadSafe<ContextProvider> { // Bind the 3d context to the current thread. This should be called before // accessing the contexts. Calling it more than once should have no effect. // Once this function has been called, the class should only be accessed - // from the same thread. + // from the same thread unless the function has some explicitly specified + // rules for access on a different thread. See SetupLockOnMainThread(), which + // can be used to provide access from multiple threads. virtual bool BindToCurrentThread() = 0; virtual void DetachFromThread() {} @@ -70,11 +72,13 @@ class ContextProvider : public base::RefCountedThreadSafe<ContextProvider> { // See skia GrContext::resetContext for details. virtual void InvalidateGrContext(uint32_t state) = 0; - // Sets up a lock so this context can be used from multiple threads. + // Sets up a lock so this context can be used from multiple threads. After + // calling this, all functions without explicit thread usage constraints can + // be used on any thread while the lock returned by GetLock() is acquired. virtual void SetupLock() = 0; // Returns the lock that should be held if using this context from multiple - // threads. + // threads. This can be called on any thread. virtual base::Lock* GetLock() = 0; // Returns the capabilities of the currently bound 3d context. diff --git a/cc/output/output_surface.cc b/cc/output/output_surface.cc index 5014fc0..d0300fe 100644 --- a/cc/output/output_surface.cc +++ b/cc/output/output_surface.cc @@ -120,6 +120,7 @@ OutputSurface::OutputSurface( device_scale_factor_(-1), external_stencil_test_enabled_(false), weak_ptr_factory_(this) { + client_thread_checker_.DetachFromThread(); } OutputSurface::OutputSurface( @@ -194,12 +195,8 @@ OutputSurface::~OutputSurface() { base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( this); - if (context_provider_.get()) { - context_provider_->SetLostContextCallback( - ContextProvider::LostContextCallback()); - context_provider_->SetMemoryPolicyChangedCallback( - ContextProvider::MemoryPolicyChangedCallback()); - } + if (client_) + DetachFromClient(); } bool OutputSurface::HasExternalStencilTest() const { @@ -207,7 +204,9 @@ bool OutputSurface::HasExternalStencilTest() const { } bool OutputSurface::BindToClient(OutputSurfaceClient* client) { + DCHECK(client_thread_checker_.CalledOnValidThread()); DCHECK(client); + DCHECK(!client_); client_ = client; bool success = true; @@ -221,12 +220,6 @@ bool OutputSurface::BindToClient(OutputSurfaceClient* client) { } } - if (success && worker_context_provider_.get()) { - success = worker_context_provider_->BindToCurrentThread(); - if (success) - worker_context_provider_->SetupLock(); - } - if (!success) client_ = NULL; @@ -244,6 +237,20 @@ bool OutputSurface::BindToClient(OutputSurfaceClient* client) { return success; } +void OutputSurface::DetachFromClient() { + DCHECK(client_thread_checker_.CalledOnValidThread()); + DCHECK(client_); + if (context_provider_.get()) { + context_provider_->SetLostContextCallback( + ContextProvider::LostContextCallback()); + context_provider_->SetMemoryPolicyChangedCallback( + ContextProvider::MemoryPolicyChangedCallback()); + } + context_provider_ = nullptr; + client_ = nullptr; + weak_ptr_factory_.InvalidateWeakPtrs(); +} + void OutputSurface::EnsureBackbuffer() { if (software_device_) software_device_->EnsureBackbuffer(); diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h index f2cace6..0b7c194 100644 --- a/cc/output/output_surface.h +++ b/cc/output/output_surface.h @@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/threading/thread_checker.h" #include "cc/base/cc_export.h" #include "cc/output/context_provider.h" #include "cc/output/overlay_candidate_validator.h" @@ -112,10 +113,14 @@ class CC_EXPORT OutputSurface : public base::trace_event::MemoryDumpProvider { // Called by the compositor on the compositor thread. This is a place where // thread-specific data for the output surface can be initialized, since from - // this point on the output surface will only be used on the compositor - // thread. + // this point to when DetachFromClient() is called the output surface will + // only be used on the compositor thread. virtual bool BindToClient(OutputSurfaceClient* client); + // Called by the compositor on the compositor thread. This is a place where + // thread-specific data for the output surface can be uninitialized. + virtual void DetachFromClient(); + virtual void EnsureBackbuffer(); virtual void DiscardBackbuffer(); @@ -180,6 +185,7 @@ class CC_EXPORT OutputSurface : public base::trace_event::MemoryDumpProvider { scoped_ptr<SoftwareOutputDevice> software_device_; gfx::Size surface_size_; float device_scale_factor_; + base::ThreadChecker client_thread_checker_; void CommitVSyncParameters(base::TimeTicks timebase, base::TimeDelta interval); diff --git a/cc/raster/tile_task_worker_pool_unittest.cc b/cc/raster/tile_task_worker_pool_unittest.cc index d8e0d19..8ecdb6c 100644 --- a/cc/raster/tile_task_worker_pool_unittest.cc +++ b/cc/raster/tile_task_worker_pool_unittest.cc @@ -130,9 +130,10 @@ class TileTaskWorkerPoolTest TileTaskWorkerPoolTest() : context_provider_(TestContextProvider::Create()), - worker_context_provider_(TestContextProvider::Create()), + worker_context_provider_(TestContextProvider::CreateWorker()), all_tile_tasks_finished_( - base::ThreadTaskRunnerHandle::Get().get(), + base::ThreadTaskRunnerHandle::Get() + .get(), base::Bind(&TileTaskWorkerPoolTest::AllTileTasksFinished, base::Unretained(this))), timeout_seconds_(5), diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h index 066f027..d2af2e3 100644 --- a/cc/test/fake_output_surface.h +++ b/cc/test/fake_output_surface.h @@ -23,14 +23,15 @@ class FakeOutputSurface : public OutputSurface { ~FakeOutputSurface() override; static scoped_ptr<FakeOutputSurface> Create3d() { - return make_scoped_ptr(new FakeOutputSurface( - TestContextProvider::Create(), TestContextProvider::Create(), false)); + return make_scoped_ptr( + new FakeOutputSurface(TestContextProvider::Create(), + TestContextProvider::CreateWorker(), false)); } static scoped_ptr<FakeOutputSurface> Create3d( scoped_refptr<ContextProvider> context_provider) { return make_scoped_ptr(new FakeOutputSurface( - context_provider, TestContextProvider::Create(), false)); + context_provider, TestContextProvider::CreateWorker(), false)); } static scoped_ptr<FakeOutputSurface> Create3d( @@ -44,7 +45,7 @@ class FakeOutputSurface : public OutputSurface { scoped_ptr<TestWebGraphicsContext3D> context) { return make_scoped_ptr( new FakeOutputSurface(TestContextProvider::Create(context.Pass()), - TestContextProvider::Create(), false)); + TestContextProvider::CreateWorker(), false)); } static scoped_ptr<FakeOutputSurface> CreateSoftware( @@ -54,21 +55,22 @@ class FakeOutputSurface : public OutputSurface { } static scoped_ptr<FakeOutputSurface> CreateDelegating3d() { - return make_scoped_ptr(new FakeOutputSurface( - TestContextProvider::Create(), TestContextProvider::Create(), true)); + return make_scoped_ptr( + new FakeOutputSurface(TestContextProvider::Create(), + TestContextProvider::CreateWorker(), true)); } static scoped_ptr<FakeOutputSurface> CreateDelegating3d( scoped_refptr<TestContextProvider> context_provider) { return make_scoped_ptr(new FakeOutputSurface( - context_provider, TestContextProvider::Create(), true)); + context_provider, TestContextProvider::CreateWorker(), true)); } static scoped_ptr<FakeOutputSurface> CreateDelegating3d( scoped_ptr<TestWebGraphicsContext3D> context) { return make_scoped_ptr( new FakeOutputSurface(TestContextProvider::Create(context.Pass()), - TestContextProvider::Create(), true)); + TestContextProvider::CreateWorker(), true)); } static scoped_ptr<FakeOutputSurface> CreateDelegatingSoftware( diff --git a/cc/test/fake_proxy.cc b/cc/test/fake_proxy.cc index 87bea06..cc254eb 100644 --- a/cc/test/fake_proxy.cc +++ b/cc/test/fake_proxy.cc @@ -24,9 +24,7 @@ RendererCapabilities& FakeProxy::GetRendererCapabilities() { return capabilities_; } -scoped_ptr<OutputSurface> FakeProxy::ReleaseOutputSurface() { - return nullptr; -} +void FakeProxy::ReleaseOutputSurface() {} bool FakeProxy::BeginMainFrameRequested() const { return false; } diff --git a/cc/test/fake_proxy.h b/cc/test/fake_proxy.h index 0226431..d11d072 100644 --- a/cc/test/fake_proxy.h +++ b/cc/test/fake_proxy.h @@ -24,8 +24,8 @@ class FakeProxy : public Proxy { void FinishAllRendering() override {} bool IsStarted() const override; bool CommitToActiveTree() const override; - void SetOutputSurface(scoped_ptr<OutputSurface>) override {} - scoped_ptr<OutputSurface> ReleaseOutputSurface() override; + void SetOutputSurface(OutputSurface* output_surface) override {} + void ReleaseOutputSurface() override; void SetLayerTreeHostClientReady() override {} void SetVisible(bool visible) override {} void SetThrottleFrameProduction(bool throttle) override {} diff --git a/cc/test/layer_test_common.cc b/cc/test/layer_test_common.cc index 7cb97cd..8ed49a2 100644 --- a/cc/test/layer_test_common.cc +++ b/cc/test/layer_test_common.cc @@ -116,13 +116,13 @@ LayerTestCommon::LayerImplTest::LayerImplTest() LayerTestCommon::LayerImplTest::LayerImplTest(const LayerTreeSettings& settings) : client_(FakeLayerTreeHostClient::DIRECT_3D), + output_surface_(FakeOutputSurface::Create3d()), host_(FakeLayerTreeHost::Create(&client_, &task_graph_runner_, settings)), root_layer_impl_(LayerImpl::Create(host_->host_impl()->active_tree(), 1)), render_pass_(RenderPass::Create()), layer_impl_id_(2) { root_layer_impl_->SetHasRenderSurface(true); - scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d(); - host_->host_impl()->InitializeRenderer(FakeOutputSurface::Create3d()); + host_->host_impl()->InitializeRenderer(output_surface_.get()); } LayerTestCommon::LayerImplTest::~LayerImplTest() {} diff --git a/cc/test/layer_test_common.h b/cc/test/layer_test_common.h index a915b59..f801461 100644 --- a/cc/test/layer_test_common.h +++ b/cc/test/layer_test_common.h @@ -139,6 +139,7 @@ class LayerTestCommon { private: FakeLayerTreeHostClient client_; TestTaskGraphRunner task_graph_runner_; + scoped_ptr<OutputSurface> output_surface_; scoped_ptr<FakeLayerTreeHost> host_; scoped_ptr<LayerImpl> root_layer_impl_; scoped_ptr<RenderPass> render_pass_; diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index c87c36b..e2d19b0 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc @@ -404,8 +404,8 @@ class LayerTreeHostImplForTesting : public LayerTreeHostImpl { test_hooks_->DidActivateTreeOnThread(this); } - bool InitializeRenderer(scoped_ptr<OutputSurface> output_surface) override { - bool success = LayerTreeHostImpl::InitializeRenderer(output_surface.Pass()); + bool InitializeRenderer(OutputSurface* output_surface) override { + bool success = LayerTreeHostImpl::InitializeRenderer(output_surface); test_hooks_->InitializedRendererOnThread(this, success); return success; } diff --git a/cc/test/test_context_provider.cc b/cc/test/test_context_provider.cc index ca7714d..5e43ee3 100644 --- a/cc/test/test_context_provider.cc +++ b/cc/test/test_context_provider.cc @@ -19,7 +19,20 @@ namespace cc { // static scoped_refptr<TestContextProvider> TestContextProvider::Create() { - return Create(TestWebGraphicsContext3D::Create().Pass()); + return Create(TestWebGraphicsContext3D::Create()); +} + +// static +scoped_refptr<TestContextProvider> TestContextProvider::CreateWorker() { + scoped_refptr<TestContextProvider> worker_context_provider = + Create(TestWebGraphicsContext3D::Create()); + if (!worker_context_provider) + return nullptr; + // Worker contexts are bound to the thread they are created on. + if (!worker_context_provider->BindToCurrentThread()) + return nullptr; + worker_context_provider->SetupLock(); + return worker_context_provider; } // static diff --git a/cc/test/test_context_provider.h b/cc/test/test_context_provider.h index 82b3e61..3ff9092 100644 --- a/cc/test/test_context_provider.h +++ b/cc/test/test_context_provider.h @@ -25,6 +25,9 @@ class TestContextProvider : public ContextProvider { CreateCallback; static scoped_refptr<TestContextProvider> Create(); + // Creates a worker context provider that can be used on any thread. This is + // equivalent to: Create(); BindToCurrentThread(); SetupLock(). + static scoped_refptr<TestContextProvider> CreateWorker(); static scoped_refptr<TestContextProvider> Create( scoped_ptr<TestWebGraphicsContext3D> context); diff --git a/cc/tiles/tile_manager_perftest.cc b/cc/tiles/tile_manager_perftest.cc index 1542233..0ba9c8e 100644 --- a/cc/tiles/tile_manager_perftest.cc +++ b/cc/tiles/tile_manager_perftest.cc @@ -89,6 +89,7 @@ class TileManagerPerfTest : public testing::Test { max_tiles_(10000), id_(7), proxy_(base::ThreadTaskRunnerHandle::Get()), + output_surface_(FakeOutputSurface::Create3d()), host_impl_(LayerTreeSettings(), &proxy_, &shared_bitmap_manager_, @@ -119,7 +120,7 @@ class TileManagerPerfTest : public testing::Test { } virtual void InitializeRenderer() { - host_impl_.InitializeRenderer(FakeOutputSurface::Create3d().Pass()); + host_impl_.InitializeRenderer(output_surface_.get()); tile_manager()->SetTileTaskRunnerForTesting( g_fake_tile_task_runner.Pointer()); } @@ -412,6 +413,7 @@ class TileManagerPerfTest : public testing::Test { int max_tiles_; int id_; FakeImplProxy proxy_; + scoped_ptr<OutputSurface> output_surface_; FakeLayerTreeHostImpl host_impl_; FakePictureLayerImpl* pending_root_layer_; FakePictureLayerImpl* active_root_layer_; diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc index e1fd51e..44bc756 100644 --- a/cc/tiles/tile_manager_unittest.cc +++ b/cc/tiles/tile_manager_unittest.cc @@ -46,6 +46,7 @@ class TileManagerTilePriorityQueueTest : public testing::Test { ready_to_activate_(false), id_(7), proxy_(base::ThreadTaskRunnerHandle::Get()), + output_surface_(FakeOutputSurface::Create3d()), host_impl_(LowResTilingsSettings(), &proxy_, &shared_bitmap_manager_, @@ -74,7 +75,7 @@ class TileManagerTilePriorityQueueTest : public testing::Test { } virtual void InitializeRenderer() { - host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()); + host_impl_.InitializeRenderer(output_surface_.get()); } void SetupDefaultTrees(const gfx::Size& layer_bounds) { @@ -156,6 +157,7 @@ class TileManagerTilePriorityQueueTest : public testing::Test { bool ready_to_activate_; int id_; FakeImplProxy proxy_; + scoped_ptr<OutputSurface> output_surface_; FakeLayerTreeHostImpl host_impl_; FakePictureLayerImpl* pending_layer_; FakePictureLayerImpl* active_layer_; @@ -1423,7 +1425,11 @@ TEST_F(TileManagerTilePriorityQueueTest, RasterQueueAllUsesCorrectTileBounds) { class TileManagerTest : public testing::Test { public: TileManagerTest() - : host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_) {} + : output_surface_(FakeOutputSurface::CreateSoftware( + make_scoped_ptr(new SoftwareOutputDevice))), + host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_) { + host_impl_.InitializeRenderer(output_surface_.get()); + } protected: // MockLayerTreeHostImpl allows us to intercept tile manager callbacks. @@ -1432,10 +1438,7 @@ class TileManagerTest : public testing::Test { MockLayerTreeHostImpl(Proxy* proxy, SharedBitmapManager* manager, TaskGraphRunner* task_graph_runner) - : FakeLayerTreeHostImpl(proxy, manager, task_graph_runner) { - InitializeRenderer(FakeOutputSurface::CreateSoftware( - make_scoped_ptr(new SoftwareOutputDevice))); - } + : FakeLayerTreeHostImpl(proxy, manager, task_graph_runner) {} MOCK_METHOD0(NotifyAllTileTasksCompleted, void()); }; @@ -1443,6 +1446,7 @@ class TileManagerTest : public testing::Test { TestSharedBitmapManager shared_bitmap_manager_; TestTaskGraphRunner task_graph_runner_; FakeImplProxy proxy_; + scoped_ptr<OutputSurface> output_surface_; MockLayerTreeHostImpl host_impl_; }; diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index d5bbe66..cece54d 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc @@ -385,7 +385,9 @@ void LayerTreeHost::SetOutputSurface(scoped_ptr<OutputSurface> surface) { DCHECK(output_surface_lost_); DCHECK(surface); - proxy_->SetOutputSurface(surface.Pass()); + DCHECK(!new_output_surface_); + new_output_surface_ = surface.Pass(); + proxy_->SetOutputSurface(new_output_surface_.get()); } scoped_ptr<OutputSurface> LayerTreeHost::ReleaseOutputSurface() { @@ -393,7 +395,8 @@ scoped_ptr<OutputSurface> LayerTreeHost::ReleaseOutputSurface() { DCHECK(!output_surface_lost_); DidLoseOutputSurface(); - return proxy_->ReleaseOutputSurface(); + proxy_->ReleaseOutputSurface(); + return current_output_surface_.Pass(); } void LayerTreeHost::RequestNewOutputSurface() { @@ -401,12 +404,20 @@ void LayerTreeHost::RequestNewOutputSurface() { } void LayerTreeHost::DidInitializeOutputSurface() { + DCHECK(new_output_surface_); output_surface_lost_ = false; + current_output_surface_ = new_output_surface_.Pass(); client_->DidInitializeOutputSurface(); } void LayerTreeHost::DidFailToInitializeOutputSurface() { DCHECK(output_surface_lost_); + DCHECK(new_output_surface_); + // Note: It is safe to drop all output surface references here as + // LayerTreeHostImpl will not keep a pointer to either the old or + // new output surface after failing to initialize the new one. + current_output_surface_ = nullptr; + new_output_surface_ = nullptr; client_->DidFailToInitializeOutputSurface(); } diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index 6ddef26..5c92f97 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h @@ -427,6 +427,13 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { int meta_information_sequence_number_; scoped_ptr<RenderingStatsInstrumentation> rendering_stats_instrumentation_; + // |current_output_surface_| can't be updated until we've successfully + // initialized a new output surface. |new_output_surface_| contains the + // new output surface that is currently being initialized. If initialization + // is successful then |new_output_surface_| replaces + // |current_output_surface_|. + scoped_ptr<OutputSurface> new_output_surface_; + scoped_ptr<OutputSurface> current_output_surface_; bool output_surface_lost_; scoped_refptr<Layer> root_layer_; diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index 23e38e1..f0ca935 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc @@ -2695,6 +2695,7 @@ TEST_F(LayerTreeHostCommonTest, FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; TestTaskGraphRunner task_graph_runner; + scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(); FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, &task_graph_runner); scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1); @@ -2734,7 +2735,7 @@ TEST_F(LayerTreeHostCommonTest, root->AddChild(child.Pass()); root->AddChild(occluding_child.Pass()); host_impl.active_tree()->SetRootLayer(root.Pass()); - host_impl.InitializeRenderer(FakeOutputSurface::Create3d()); + host_impl.InitializeRenderer(output_surface.get()); bool update_lcd_text = false; host_impl.active_tree()->UpdateDrawProperties(update_lcd_text); diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 36e7bdd..de1e213b 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -172,6 +172,7 @@ LayerTreeHostImpl::LayerTreeHostImpl( : client_(client), proxy_(proxy), current_begin_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE), + output_surface_(nullptr), content_is_suitable_for_gpu_rasterization_(true), has_gpu_rasterization_trigger_(false), use_gpu_rasterization_(false), @@ -284,6 +285,13 @@ LayerTreeHostImpl::~LayerTreeHostImpl() { } CleanUpTileManager(); + renderer_ = nullptr; + resource_provider_ = nullptr; + + if (output_surface_) { + output_surface_->DetachFromClient(); + output_surface_ = nullptr; + } } void LayerTreeHostImpl::BeginMainFrameAborted(CommitEarlyOutReason reason) { @@ -1565,7 +1573,7 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame) { scoped_ptr<SoftwareRenderer> temp_software_renderer = SoftwareRenderer::Create(this, &settings_.renderer_settings, - output_surface_.get(), NULL); + output_surface_, NULL); temp_software_renderer->DrawFrame(&frame->render_passes, device_scale_factor_, DeviceViewport(), @@ -1627,7 +1635,7 @@ bool LayerTreeHostImpl::CanUseGpuRasterization() { ContextProvider* context_provider = output_surface_->worker_context_provider(); - base::AutoLock context_lock(*context_provider->GetLock()); + ContextProvider::ScopedContextLock scoped_context(context_provider); if (!context_provider->GrContext()) return false; @@ -2010,18 +2018,18 @@ void LayerTreeHostImpl::CreateAndSetRenderer() { DCHECK(resource_provider_); if (output_surface_->capabilities().delegated_rendering) { - renderer_ = DelegatingRenderer::Create(this, &settings_.renderer_settings, - output_surface_.get(), - resource_provider_.get()); + renderer_ = + DelegatingRenderer::Create(this, &settings_.renderer_settings, + output_surface_, resource_provider_.get()); } else if (output_surface_->context_provider()) { renderer_ = GLRenderer::Create( - this, &settings_.renderer_settings, output_surface_.get(), + this, &settings_.renderer_settings, output_surface_, resource_provider_.get(), texture_mailbox_deleter_.get(), settings_.renderer_settings.highp_threshold_min); } else if (output_surface_->software_device()) { - renderer_ = SoftwareRenderer::Create(this, &settings_.renderer_settings, - output_surface_.get(), - resource_provider_.get()); + renderer_ = + SoftwareRenderer::Create(this, &settings_.renderer_settings, + output_surface_, resource_provider_.get()); } DCHECK(renderer_); @@ -2150,7 +2158,7 @@ void LayerTreeHostImpl::CleanUpTileManager() { single_thread_synchronous_task_graph_runner_ = nullptr; } -scoped_ptr<OutputSurface> LayerTreeHostImpl::ReleaseOutputSurface() { +void LayerTreeHostImpl::ReleaseOutputSurface() { TRACE_EVENT0("cc", "LayerTreeHostImpl::ReleaseOutputSurface"); // Since we will create a new resource provider, we cannot continue to use @@ -2163,11 +2171,16 @@ scoped_ptr<OutputSurface> LayerTreeHostImpl::ReleaseOutputSurface() { CleanUpTileManager(); resource_provider_ = nullptr; - return output_surface_.Pass(); + // Detach from the old output surface and reset |output_surface_| pointer + // as this surface is going to be destroyed independent of if binding the + // new output surface succeeds or not. + if (output_surface_) { + output_surface_->DetachFromClient(); + output_surface_ = nullptr; + } } -bool LayerTreeHostImpl::InitializeRenderer( - scoped_ptr<OutputSurface> output_surface) { +bool LayerTreeHostImpl::InitializeRenderer(OutputSurface* output_surface) { TRACE_EVENT0("cc", "LayerTreeHostImpl::InitializeRenderer"); ReleaseOutputSurface(); @@ -2178,9 +2191,9 @@ bool LayerTreeHostImpl::InitializeRenderer( return false; } - output_surface_ = output_surface.Pass(); + output_surface_ = output_surface; resource_provider_ = ResourceProvider::Create( - output_surface_.get(), shared_bitmap_manager_, gpu_memory_buffer_manager_, + output_surface_, shared_bitmap_manager_, gpu_memory_buffer_manager_, proxy_->blocking_main_thread_task_runner(), settings_.renderer_settings.highp_threshold_min, settings_.renderer_settings.use_rgba_4444_textures, diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index f3d4a67..7e8a85b 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h @@ -360,14 +360,15 @@ class CC_EXPORT LayerTreeHostImpl // Implementation. int id() const { return id_; } bool CanDraw() const; - OutputSurface* output_surface() const { return output_surface_.get(); } - scoped_ptr<OutputSurface> ReleaseOutputSurface(); + OutputSurface* output_surface() const { return output_surface_; } + void ReleaseOutputSurface(); + std::string LayerTreeAsJson() const; void FinishAllRendering(); int RequestedMSAASampleCount() const; - virtual bool InitializeRenderer(scoped_ptr<OutputSurface> output_surface); + virtual bool InitializeRenderer(OutputSurface* output_surface); TileManager* tile_manager() { return tile_manager_.get(); } void SetHasGpuRasterizationTrigger(bool flag) { @@ -696,7 +697,7 @@ class CC_EXPORT LayerTreeHostImpl // request queue. std::set<UIResourceId> evicted_ui_resources_; - scoped_ptr<OutputSurface> output_surface_; + OutputSurface* output_surface_; scoped_ptr<ResourceProvider> resource_provider_; bool content_is_suitable_for_gpu_rasterization_; diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 9921731..2f55c72 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -168,7 +168,8 @@ class LayerTreeHostImplTest : public testing::Test, settings, this, &proxy_, &stats_instrumentation_, &shared_bitmap_manager_, &gpu_memory_buffer_manager_, &task_graph_runner_, 0); - bool init = host_impl_->InitializeRenderer(output_surface.Pass()); + output_surface_ = output_surface.Pass(); + bool init = host_impl_->InitializeRenderer(output_surface_.get()); host_impl_->SetViewportSize(gfx::Size(10, 10)); host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f); // Set the BeginFrameArgs so that methods which use it are able to. @@ -420,6 +421,7 @@ class LayerTreeHostImplTest : public testing::Test, TestSharedBitmapManager shared_bitmap_manager_; TestGpuMemoryBufferManager gpu_memory_buffer_manager_; TestTaskGraphRunner task_graph_runner_; + scoped_ptr<OutputSurface> output_surface_; scoped_ptr<LayerTreeHostImpl> host_impl_; FakeRenderingStatsInstrumentation stats_instrumentation_; bool on_can_draw_state_changed_called_; @@ -2117,7 +2119,8 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { settings, this, &proxy_, &shared_bitmap_manager_, &task_graph_runner_, &stats_instrumentation_); host_impl_ = make_scoped_ptr(host_impl_override_time); - host_impl_->InitializeRenderer(CreateOutputSurface()); + output_surface_ = CreateOutputSurface(); + host_impl_->InitializeRenderer(output_surface_.get()); SetupScrollAndContentsLayers(content_size); host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f); @@ -5669,7 +5672,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { LayerTreeHostImpl::Create( settings, this, &proxy_, &stats_instrumentation_, &shared_bitmap_manager_, NULL, &task_graph_runner_, 0); - layer_tree_host_impl->InitializeRenderer(output_surface.Pass()); + layer_tree_host_impl->InitializeRenderer(output_surface.get()); layer_tree_host_impl->WillBeginImplFrame( CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500)); @@ -5946,19 +5949,14 @@ static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity( Proxy* proxy, SharedBitmapManager* manager, TaskGraphRunner* task_graph_runner, - RenderingStatsInstrumentation* stats_instrumentation) { - scoped_refptr<TestContextProvider> provider(TestContextProvider::Create()); - scoped_ptr<OutputSurface> output_surface( - FakeOutputSurface::Create3d(provider)); - provider->BindToCurrentThread(); - provider->TestContext3d()->set_have_post_sub_buffer(true); - + RenderingStatsInstrumentation* stats_instrumentation, + OutputSurface* output_surface) { LayerTreeSettings settings; settings.renderer_settings.partial_swap_enabled = partial_swap; scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(settings, client, proxy, stats_instrumentation, manager, nullptr, task_graph_runner, 0); - my_host_impl->InitializeRenderer(output_surface.Pass()); + my_host_impl->InitializeRenderer(output_surface); my_host_impl->WillBeginImplFrame( CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); my_host_impl->SetViewportSize(gfx::Size(100, 100)); @@ -6021,9 +6019,14 @@ static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity( TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) { TestSharedBitmapManager shared_bitmap_manager; TestTaskGraphRunner task_graph_runner; - scoped_ptr<LayerTreeHostImpl> my_host_impl = - SetupLayersForOpacity(true, this, &proxy_, &shared_bitmap_manager, - &task_graph_runner, &stats_instrumentation_); + scoped_refptr<TestContextProvider> provider(TestContextProvider::Create()); + provider->BindToCurrentThread(); + provider->TestContext3d()->set_have_post_sub_buffer(true); + scoped_ptr<OutputSurface> output_surface( + FakeOutputSurface::Create3d(provider)); + scoped_ptr<LayerTreeHostImpl> my_host_impl = SetupLayersForOpacity( + true, this, &proxy_, &shared_bitmap_manager, &task_graph_runner, + &stats_instrumentation_, output_surface.get()); { LayerTreeHostImpl::FrameData frame; EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame)); @@ -6045,9 +6048,14 @@ TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) { TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) { TestSharedBitmapManager shared_bitmap_manager; TestTaskGraphRunner task_graph_runner; - scoped_ptr<LayerTreeHostImpl> my_host_impl = - SetupLayersForOpacity(false, this, &proxy_, &shared_bitmap_manager, - &task_graph_runner, &stats_instrumentation_); + scoped_refptr<TestContextProvider> provider(TestContextProvider::Create()); + provider->BindToCurrentThread(); + provider->TestContext3d()->set_have_post_sub_buffer(true); + scoped_ptr<OutputSurface> output_surface( + FakeOutputSurface::Create3d(provider)); + scoped_ptr<LayerTreeHostImpl> my_host_impl = SetupLayersForOpacity( + false, this, &proxy_, &shared_bitmap_manager, &task_graph_runner, + &stats_instrumentation_, output_surface.get()); { LayerTreeHostImpl::FrameData frame; EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame)); @@ -6466,9 +6474,9 @@ TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) { settings, this, &proxy_, &stats_instrumentation_, &shared_bitmap_manager_, &gpu_memory_buffer_manager_, &task_graph_runner_, 0); - scoped_ptr<OutputSurface> output_surface( - FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create())); - host_impl_->InitializeRenderer(output_surface.Pass()); + output_surface_ = + FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()); + host_impl_->InitializeRenderer(output_surface_.get()); EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes()); } @@ -6529,7 +6537,8 @@ class LayerTreeHostImplTestPrepareTiles : public LayerTreeHostImplTest { new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_, &shared_bitmap_manager_, &task_graph_runner_); host_impl_.reset(fake_host_impl_); - host_impl_->InitializeRenderer(CreateOutputSurface()); + output_surface_ = CreateOutputSurface(); + host_impl_->InitializeRenderer(output_surface_.get()); host_impl_->SetViewportSize(gfx::Size(10, 10)); } @@ -8522,7 +8531,8 @@ class MockReclaimResourcesOutputSurface : public FakeOutputSurface { public: static scoped_ptr<MockReclaimResourcesOutputSurface> Create3d() { return make_scoped_ptr(new MockReclaimResourcesOutputSurface( - TestContextProvider::Create(), TestContextProvider::Create(), false)); + TestContextProvider::Create(), TestContextProvider::CreateWorker(), + false)); } MOCK_METHOD0(ForceReclaimResources, void()); diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 1481b99..0afcd9f 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc @@ -465,7 +465,7 @@ class LayerTreeHostFreeWorkerContextResourcesTest : public LayerTreeHostTest { explicit MockSetWorkerContextShouldAggressivelyFreeResourcesOutputSurface( bool delegated_rendering) : FakeOutputSurface(TestContextProvider::Create(), - TestContextProvider::Create(), + TestContextProvider::CreateWorker(), delegated_rendering) {} MOCK_METHOD1(SetWorkerContextShouldAggressivelyFreeResources, void(bool is_visible)); @@ -6258,5 +6258,21 @@ class LayerTreeHostScrollingAndScalingUpdatesLayers : public LayerTreeHostTest { MULTI_THREAD_TEST_F(LayerTreeHostScrollingAndScalingUpdatesLayers); +class LayerTreeHostTestDestroyWhileInitializingOutputSurface + : public LayerTreeHostTest { + protected: + void BeginTest() override { + // By ending the test immediately we start initialization of an output + // surface but destroy the LTH before it completes. This test verifies + // that this works correctly and the output surface is destroyed on + // the correct thread. + EndTest(); + } + + void AfterTest() override {} +}; + +MULTI_THREAD_TEST_F(LayerTreeHostTestDestroyWhileInitializingOutputSurface); + } // namespace } // namespace cc diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc index 3a41b55..34a70b9 100644 --- a/cc/trees/layer_tree_host_unittest_context.cc +++ b/cc/trees/layer_tree_host_unittest_context.cc @@ -416,7 +416,6 @@ class LayerTreeHostClientTakeAwayOutputSurface scoped_ptr<OutputSurface> surface = layer_tree_host()->ReleaseOutputSurface(); CHECK(surface); - surface->context_provider()->DetachFromThread(); MainThreadTaskRunner()->PostTask( FROM_HERE, base::Bind(&LayerTreeHostClientTakeAwayOutputSurface::MakeVisible, diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc index 34d26d5..e00e7c8 100644 --- a/cc/trees/layer_tree_impl_unittest.cc +++ b/cc/trees/layer_tree_impl_unittest.cc @@ -22,12 +22,12 @@ namespace { class LayerTreeImplTest : public LayerTreeHostCommonTest { public: - LayerTreeImplTest() { + LayerTreeImplTest() : output_surface_(FakeOutputSurface::Create3d()) { LayerTreeSettings settings; settings.layer_transforms_should_scale_layer_contents = true; host_impl_.reset(new FakeLayerTreeHostImpl( settings, &proxy_, &shared_bitmap_manager_, &task_graph_runner_)); - EXPECT_TRUE(host_impl_->InitializeRenderer(FakeOutputSurface::Create3d())); + EXPECT_TRUE(host_impl_->InitializeRenderer(output_surface_.get())); } FakeLayerTreeHostImpl& host_impl() { return *host_impl_; } @@ -42,6 +42,7 @@ class LayerTreeImplTest : public LayerTreeHostCommonTest { TestSharedBitmapManager shared_bitmap_manager_; TestTaskGraphRunner task_graph_runner_; FakeImplProxy proxy_; + scoped_ptr<OutputSurface> output_surface_; scoped_ptr<FakeLayerTreeHostImpl> host_impl_; }; @@ -97,10 +98,11 @@ TEST_F(LayerTreeImplTest, UpdateViewportAndHitTest) { FakeImplProxy proxy; LayerTreeSettings settings; settings.verify_property_trees = true; + scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(); scoped_ptr<FakeLayerTreeHostImpl> host_impl; host_impl.reset(new FakeLayerTreeHostImpl( settings, &proxy, &shared_bitmap_manager, &task_graph_runner)); - EXPECT_TRUE(host_impl->InitializeRenderer(FakeOutputSurface::Create3d())); + EXPECT_TRUE(host_impl->InitializeRenderer(output_surface.get())); scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl->active_tree(), 12345); diff --git a/cc/trees/occlusion_tracker_perftest.cc b/cc/trees/occlusion_tracker_perftest.cc index 209399d..01b63de 100644 --- a/cc/trees/occlusion_tracker_perftest.cc +++ b/cc/trees/occlusion_tracker_perftest.cc @@ -35,13 +35,14 @@ class OcclusionTrackerPerfTest : public testing::Test { base::TimeDelta::FromMilliseconds(kTimeLimitMillis), kTimeCheckInterval), proxy_(base::ThreadTaskRunnerHandle::Get(), nullptr), - impl_(&proxy_) {} + impl_(&proxy_), + output_surface_(FakeOutputSurface::Create3d()) {} void CreateHost() { LayerTreeSettings settings; host_impl_ = LayerTreeHostImpl::Create(settings, &client_, &proxy_, &stats_, &shared_bitmap_manager_, nullptr, &task_graph_runner_, 1); - host_impl_->InitializeRenderer(FakeOutputSurface::Create3d()); + host_impl_->InitializeRenderer(output_surface_.get()); scoped_ptr<LayerImpl> root_layer = LayerImpl::Create(active_tree(), 1); root_layer->SetHasRenderSurface(true); @@ -71,6 +72,7 @@ class OcclusionTrackerPerfTest : public testing::Test { FakeRenderingStatsInstrumentation stats_; TestSharedBitmapManager shared_bitmap_manager_; TestTaskGraphRunner task_graph_runner_; + scoped_ptr<OutputSurface> output_surface_; scoped_ptr<LayerTreeHostImpl> host_impl_; }; diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h index 05dfe69..b40bb2f 100644 --- a/cc/trees/proxy.h +++ b/cc/trees/proxy.h @@ -60,9 +60,9 @@ class CC_EXPORT Proxy { // Will call LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted // with the result of this function. - virtual void SetOutputSurface(scoped_ptr<OutputSurface> output_surface) = 0; + virtual void SetOutputSurface(OutputSurface* output_surface) = 0; - virtual scoped_ptr<OutputSurface> ReleaseOutputSurface() = 0; + virtual void ReleaseOutputSurface() = 0; // Indicates that the compositing surface associated with our context is // ready to use. diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index 8ab3bc2..cefc074 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc @@ -149,7 +149,7 @@ void SingleThreadProxy::RequestNewOutputSurface() { layer_tree_host_->RequestNewOutputSurface(); } -scoped_ptr<OutputSurface> SingleThreadProxy::ReleaseOutputSurface() { +void SingleThreadProxy::ReleaseOutputSurface() { // |layer_tree_host_| should already be aware of this. DCHECK(layer_tree_host_->output_surface_lost()); @@ -158,8 +158,7 @@ scoped_ptr<OutputSurface> SingleThreadProxy::ReleaseOutputSurface() { return layer_tree_host_impl_->ReleaseOutputSurface(); } -void SingleThreadProxy::SetOutputSurface( - scoped_ptr<OutputSurface> output_surface) { +void SingleThreadProxy::SetOutputSurface(OutputSurface* output_surface) { DCHECK(Proxy::IsMainThread()); DCHECK(layer_tree_host_->output_surface_lost()); DCHECK(output_surface_creation_requested_); @@ -169,7 +168,7 @@ void SingleThreadProxy::SetOutputSurface( { DebugScopedSetMainThreadBlocked main_thread_blocked(this); DebugScopedSetImplThread impl(this); - success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass()); + success = layer_tree_host_impl_->InitializeRenderer(output_surface); } if (success) { diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h index 4829d22..3caf139 100644 --- a/cc/trees/single_thread_proxy.h +++ b/cc/trees/single_thread_proxy.h @@ -38,8 +38,8 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void FinishAllRendering() override; bool IsStarted() const override; bool CommitToActiveTree() const override; - void SetOutputSurface(scoped_ptr<OutputSurface>) override; - scoped_ptr<OutputSurface> ReleaseOutputSurface() override; + void SetOutputSurface(OutputSurface* output_surface) override; + void ReleaseOutputSurface() override; void SetLayerTreeHostClientReady() override; void SetVisible(bool visible) override; void SetThrottleFrameProduction(bool throttle) override; diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc index df9d560..585cbf5 100644 --- a/cc/trees/thread_proxy.cc +++ b/cc/trees/thread_proxy.cc @@ -210,26 +210,22 @@ void ThreadProxy::RequestNewOutputSurface() { layer_tree_host()->RequestNewOutputSurface(); } -void ThreadProxy::SetOutputSurface(scoped_ptr<OutputSurface> output_surface) { +void ThreadProxy::SetOutputSurface(OutputSurface* output_surface) { Proxy::ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread, - impl_thread_weak_ptr_, base::Passed(&output_surface))); + FROM_HERE, base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread, + impl_thread_weak_ptr_, output_surface)); } -scoped_ptr<OutputSurface> ThreadProxy::ReleaseOutputSurface() { +void ThreadProxy::ReleaseOutputSurface() { DCHECK(IsMainThread()); DCHECK(layer_tree_host()->output_surface_lost()); DebugScopedSetMainThreadBlocked main_thread_blocked(this); CompletionEvent completion; - scoped_ptr<OutputSurface> output_surface; Proxy::ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ThreadProxy::ReleaseOutputSurfaceOnImplThread, - impl_thread_weak_ptr_, &completion, &output_surface)); + FROM_HERE, base::Bind(&ThreadProxy::ReleaseOutputSurfaceOnImplThread, + impl_thread_weak_ptr_, &completion)); completion.Wait(); - return output_surface; } void ThreadProxy::DidInitializeOutputSurface( @@ -1041,12 +1037,12 @@ void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) { } void ThreadProxy::InitializeOutputSurfaceOnImplThread( - scoped_ptr<OutputSurface> output_surface) { + OutputSurface* output_surface) { TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread"); DCHECK(IsImplThread()); LayerTreeHostImpl* host_impl = impl().layer_tree_host_impl.get(); - bool success = host_impl->InitializeRenderer(output_surface.Pass()); + bool success = host_impl->InitializeRenderer(output_surface); RendererCapabilities capabilities; if (success) { capabilities = @@ -1065,14 +1061,13 @@ void ThreadProxy::InitializeOutputSurfaceOnImplThread( } void ThreadProxy::ReleaseOutputSurfaceOnImplThread( - CompletionEvent* completion, - scoped_ptr<OutputSurface>* output_surface) { + CompletionEvent* completion) { DCHECK(IsImplThread()); // Unlike DidLoseOutputSurfaceOnImplThread, we don't need to call // LayerTreeHost::DidLoseOutputSurface since it already knows. impl().scheduler->DidLoseOutputSurface(); - *output_surface = impl().layer_tree_host_impl->ReleaseOutputSurface(); + impl().layer_tree_host_impl->ReleaseOutputSurface(); completion->Signal(); } diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h index 9cbfc9a..9abca17 100644 --- a/cc/trees/thread_proxy.h +++ b/cc/trees/thread_proxy.h @@ -155,7 +155,7 @@ class CC_EXPORT ThreadProxy : public Proxy, void FinishAllRendering() override; bool IsStarted() const override; bool CommitToActiveTree() const override; - void SetOutputSurface(scoped_ptr<OutputSurface>) override; + void SetOutputSurface(OutputSurface* output_surface) override; void SetLayerTreeHostClientReady() override; void SetVisible(bool visible) override; void SetThrottleFrameProduction(bool throttle) override; @@ -176,7 +176,7 @@ class CC_EXPORT ThreadProxy : public Proxy, bool MainFrameWillHappenForTesting() override; void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override; void SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) override; - scoped_ptr<OutputSurface> ReleaseOutputSurface() override; + void ReleaseOutputSurface() override; // LayerTreeHostImplClient implementation void UpdateRendererCapabilitiesOnImplThread() override; @@ -272,11 +272,8 @@ class CC_EXPORT ThreadProxy : public Proxy, CompletionEvent* completion, bool* has_initialized_output_surface); void DeleteContentsTexturesOnImplThread(CompletionEvent* completion); - void InitializeOutputSurfaceOnImplThread( - scoped_ptr<OutputSurface> output_surface); - void ReleaseOutputSurfaceOnImplThread( - CompletionEvent* completion, - scoped_ptr<OutputSurface>* output_surface); + void InitializeOutputSurfaceOnImplThread(OutputSurface* output_surface); + void ReleaseOutputSurfaceOnImplThread(CompletionEvent* completion); void FinishGLOnImplThread(CompletionEvent* completion); void LayerTreeHostClosedOnImplThread(CompletionEvent* completion); DrawResult DrawSwapInternal(bool forced_draw); diff --git a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc index b90edd6..5d62030 100644 --- a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc +++ b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc @@ -24,6 +24,7 @@ #include "content/renderer/render_thread_impl.h" #include "gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h" #include "gpu/command_buffer/client/gl_in_process_context.h" +#include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "ui/gl/android/surface_texture.h" #include "ui/gl/gl_surface.h" @@ -170,8 +171,7 @@ SynchronousCompositorFactoryImpl::CreateOutputSurface( scoped_refptr<cc::ContextProvider> onscreen_context = CreateContextProviderForCompositor(surface_id, RENDER_COMPOSITOR_CONTEXT); scoped_refptr<cc::ContextProvider> worker_context = - CreateContextProviderForCompositor(0, RENDER_WORKER_CONTEXT); - + GetSharedWorkerContextProvider(); return make_scoped_ptr(new SynchronousCompositorOutputSurface( onscreen_context, worker_context, routing_id, frame_swap_message_queue)); } @@ -211,6 +211,9 @@ SynchronousCompositorFactoryImpl::CreateContextProviderForCompositor( // This is half of what RenderWidget uses because synchronous compositor // pipeline is only one frame deep. But twice of half for low end here // because 16bit texture is not supported. + // TODO(reveman): This limit is based on the usage required by async + // uploads. Determine what a good limit is now that async uploads are + // no longer used. unsigned int mapped_memory_reclaim_limit = (base::SysInfo::IsLowEndDevice() ? 2 : 6) * 1024 * 1024; blink::WebGraphicsContext3D::Attributes attributes = GetDefaultAttribs(); @@ -232,6 +235,67 @@ SynchronousCompositorFactoryImpl::CreateContextProviderForCompositor( "Child-Compositor"); } +scoped_refptr<cc::ContextProvider> +SynchronousCompositorFactoryImpl::GetSharedWorkerContextProvider() { + // TODO(reveman): This limit is based on the usage required by async + // uploads. Determine what a good limit is now that async uploads are + // no longer used. + unsigned int mapped_memory_reclaim_limit = + (base::SysInfo::IsLowEndDevice() ? 2 : 6) * 1024 * 1024; + + if (use_ipc_command_buffer_) { + bool shared_worker_context_lost = false; + if (shared_worker_context_) { + // Note: If context is lost, we delete reference after releasing the lock. + base::AutoLock lock(*shared_worker_context_->GetLock()); + if (shared_worker_context_->ContextGL()->GetGraphicsResetStatusKHR() != + GL_NO_ERROR) { + shared_worker_context_lost = true; + } + } + if (!shared_worker_context_ || shared_worker_context_lost) { + WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits mem_limits; + mem_limits.mapped_memory_reclaim_limit = mapped_memory_reclaim_limit; + scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context = + CreateContext3D(0, GetDefaultAttribs(), mem_limits); + shared_worker_context_ = + make_scoped_refptr(new SynchronousCompositorContextProvider( + context.Pass(), RENDER_WORKER_CONTEXT)); + if (!shared_worker_context_->BindToCurrentThread()) + shared_worker_context_ = nullptr; + if (shared_worker_context_) + shared_worker_context_->SetupLock(); + } + + return shared_worker_context_; + } + + bool in_process_shared_worker_context_lost = false; + if (in_process_shared_worker_context_) { + // Note: If context is lost, we delete reference after releasing the lock. + base::AutoLock lock(*in_process_shared_worker_context_->GetLock()); + if (in_process_shared_worker_context_->ContextGL() + ->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { + in_process_shared_worker_context_lost = true; + } + } + if (!in_process_shared_worker_context_ || + in_process_shared_worker_context_lost) { + gpu::GLInProcessContextSharedMemoryLimits mem_limits; + mem_limits.mapped_memory_reclaim_limit = mapped_memory_reclaim_limit; + ContextHolder holder = CreateContextHolder( + GetDefaultAttribs(), GpuThreadService(), mem_limits, true); + in_process_shared_worker_context_ = ContextProviderInProcess::Create( + holder.command_buffer.Pass(), "Child-Worker"); + if (!in_process_shared_worker_context_->BindToCurrentThread()) + in_process_shared_worker_context_ = nullptr; + if (in_process_shared_worker_context_) + in_process_shared_worker_context_->SetupLock(); + } + + return in_process_shared_worker_context_; +} + scoped_refptr<StreamTextureFactory> SynchronousCompositorFactoryImpl::CreateStreamTextureFactory(int frame_id) { scoped_refptr<StreamTextureFactorySynchronousImpl> factory( diff --git a/content/browser/android/in_process/synchronous_compositor_factory_impl.h b/content/browser/android/in_process/synchronous_compositor_factory_impl.h index 84ceb03..90d6105 100644 --- a/content/browser/android/in_process/synchronous_compositor_factory_impl.h +++ b/content/browser/android/in_process/synchronous_compositor_factory_impl.h @@ -28,6 +28,7 @@ class WebGraphicsContext3DInProcessCommandBufferImpl; namespace content { class InProcessChildThreadParams; +class SynchronousCompositorContextProvider; class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { public: @@ -74,6 +75,7 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { scoped_refptr<cc::ContextProvider> CreateContextProviderForCompositor( int surface_id, CommandBufferContextType type); + scoped_refptr<cc::ContextProvider> GetSharedWorkerContextProvider(); bool CanCreateMainThreadContext(); scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider> TryCreateStreamTextureFactory(); @@ -88,6 +90,10 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { class VideoContextProvider; scoped_refptr<VideoContextProvider> video_context_provider_; + scoped_refptr<SynchronousCompositorContextProvider> shared_worker_context_; + scoped_refptr<cc_blink::ContextProviderWebContext> + in_process_shared_worker_context_; + bool use_ipc_command_buffer_; // |num_hardware_compositor_lock_| is updated on UI thread only but can be diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.cc b/content/browser/android/in_process/synchronous_compositor_output_surface.cc index 85c7bcb..f03f992 100644 --- a/content/browser/android/in_process/synchronous_compositor_output_surface.cc +++ b/content/browser/android/in_process/synchronous_compositor_output_surface.cc @@ -83,11 +83,6 @@ SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface( } SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() { - DCHECK(CalledOnValidThread()); - if (registered_) { - SynchronousCompositorRegistry::GetInstance()->UnregisterOutputSurface( - routing_id_, this); - } } bool SynchronousCompositorOutputSurface::BindToClient( @@ -105,6 +100,15 @@ bool SynchronousCompositorOutputSurface::BindToClient( return true; } +void SynchronousCompositorOutputSurface::DetachFromClient() { + DCHECK(CalledOnValidThread()); + if (registered_) { + SynchronousCompositorRegistry::GetInstance()->UnregisterOutputSurface( + routing_id_, this); + } + cc::OutputSurface::DetachFromClient(); +} + void SynchronousCompositorOutputSurface::SetCompositor( SynchronousCompositorImpl* compositor) { DCHECK(CalledOnValidThread()); diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.h b/content/browser/android/in_process/synchronous_compositor_output_surface.h index 4146952..b1baa64 100644 --- a/content/browser/android/in_process/synchronous_compositor_output_surface.h +++ b/content/browser/android/in_process/synchronous_compositor_output_surface.h @@ -58,6 +58,7 @@ class SynchronousCompositorOutputSurface // OutputSurface. bool BindToClient(cc::OutputSurfaceClient* surface_client) override; + void DetachFromClient() override; void Reshape(const gfx::Size& size, float scale_factor) override; void SwapBuffers(cc::CompositorFrame* frame) override; void Invalidate() override; diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index a5b1433..1af8acd 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc @@ -244,11 +244,14 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( scoped_refptr<ContextProviderCommandBuffer> context_provider; if (create_gpu_output_surface) { // Try to reuse existing worker context provider. + bool shared_worker_context_provider_lost = false; if (shared_worker_context_provider_) { + // Note: If context is lost, we delete reference after releasing the lock. base::AutoLock lock(*shared_worker_context_provider_->GetLock()); if (shared_worker_context_provider_->ContextGL() - ->GetGraphicsResetStatusKHR() != GL_NO_ERROR) - shared_worker_context_provider_ = nullptr; + ->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { + shared_worker_context_provider_lost = true; + } } scoped_refptr<GpuChannelHost> gpu_channel_host = BrowserGpuChannelHostFactory::instance()->GetGpuChannel(); @@ -259,7 +262,8 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( BROWSER_COMPOSITOR_ONSCREEN_CONTEXT); if (context_provider && !context_provider->BindToCurrentThread()) context_provider = nullptr; - if (!shared_worker_context_provider_) { + if (!shared_worker_context_provider_ || + shared_worker_context_provider_lost) { shared_worker_context_provider_ = ContextProviderCommandBuffer::Create( GpuProcessTransportFactory::CreateContextCommon(gpu_channel_host, 0), @@ -267,6 +271,8 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( if (shared_worker_context_provider_ && !shared_worker_context_provider_->BindToCurrentThread()) shared_worker_context_provider_ = nullptr; + if (shared_worker_context_provider_) + shared_worker_context_provider_->SetupLock(); } } diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index bfb1f3a..47e2aef 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc @@ -590,7 +590,7 @@ scoped_ptr<base::SharedMemory> ChildThreadImpl::AllocateSharedMemory( shared_buf.reset(new base::SharedMemory); if (!shared_buf->CreateAnonymous(buf_size)) { NOTREACHED(); - return NULL; + return nullptr; } #else // On POSIX, we need to ask the browser to create the shared memory for us, @@ -602,11 +602,11 @@ scoped_ptr<base::SharedMemory> ChildThreadImpl::AllocateSharedMemory( shared_buf.reset(new base::SharedMemory(shared_mem_handle, false)); } else { NOTREACHED() << "Browser failed to allocate shared memory"; - return NULL; + return nullptr; } } else { - NOTREACHED() << "Browser allocation request message failed"; - return NULL; + // Send is allowed to fail during shutdown. Return null in this case. + return nullptr; } #endif return shared_buf; diff --git a/content/renderer/gpu/compositor_output_surface.cc b/content/renderer/gpu/compositor_output_surface.cc index c3298d0..3f96ef3 100644 --- a/content/renderer/gpu/compositor_output_surface.cc +++ b/content/renderer/gpu/compositor_output_surface.cc @@ -50,28 +50,15 @@ CompositorOutputSurface::CompositorOutputSurface( weak_ptrs_(this) { DCHECK(output_surface_filter_.get()); DCHECK(frame_swap_message_queue_.get()); - DetachFromThread(); capabilities_.max_frames_pending = 1; message_sender_ = RenderThreadImpl::current()->sync_message_filter(); DCHECK(message_sender_.get()); } -CompositorOutputSurface::~CompositorOutputSurface() { - DCHECK(CalledOnValidThread()); - if (!HasClient()) - return; - UpdateSmoothnessTakesPriority(false); - if (output_surface_proxy_.get()) - output_surface_proxy_->ClearOutputSurface(); - output_surface_filter_->RemoveHandlerOnCompositorThread( - routing_id_, - output_surface_filter_handler_); -} +CompositorOutputSurface::~CompositorOutputSurface() {} bool CompositorOutputSurface::BindToClient( cc::OutputSurfaceClient* client) { - DCHECK(CalledOnValidThread()); - if (!cc::OutputSurface::BindToClient(client)) return false; @@ -94,6 +81,17 @@ bool CompositorOutputSurface::BindToClient( return true; } +void CompositorOutputSurface::DetachFromClient() { + if (!HasClient()) + return; + UpdateSmoothnessTakesPriority(false); + if (output_surface_proxy_.get()) + output_surface_proxy_->ClearOutputSurface(); + output_surface_filter_->RemoveHandlerOnCompositorThread( + routing_id_, output_surface_filter_handler_); + cc::OutputSurface::DetachFromClient(); +} + void CompositorOutputSurface::ShortcutSwapAck( uint32 output_surface_id, scoped_ptr<cc::GLFrameData> gl_frame_data) { @@ -156,7 +154,7 @@ void CompositorOutputSurface::SwapBuffers(cc::CompositorFrame* frame) { } void CompositorOutputSurface::OnMessageReceived(const IPC::Message& message) { - DCHECK(CalledOnValidThread()); + DCHECK(client_thread_checker_.CalledOnValidThread()); if (!HasClient()) return; IPC_BEGIN_MESSAGE_MAP(CompositorOutputSurface, message) @@ -170,7 +168,7 @@ void CompositorOutputSurface::OnMessageReceived(const IPC::Message& message) { void CompositorOutputSurface::OnUpdateVSyncParametersFromBrowser( base::TimeTicks timebase, base::TimeDelta interval) { - DCHECK(CalledOnValidThread()); + DCHECK(client_thread_checker_.CalledOnValidThread()); CommitVSyncParameters(timebase, interval); } diff --git a/content/renderer/gpu/compositor_output_surface.h b/content/renderer/gpu/compositor_output_surface.h index fa91b75..909bf5f 100644 --- a/content/renderer/gpu/compositor_output_surface.h +++ b/content/renderer/gpu/compositor_output_surface.h @@ -51,6 +51,7 @@ class CompositorOutputSurface // cc::OutputSurface implementation. bool BindToClient(cc::OutputSurfaceClient* client) override; + void DetachFromClient() override; void SwapBuffers(cc::CompositorFrame* frame) override; // TODO(epenner): This seems out of place here and would be a better fit diff --git a/content/renderer/gpu/mailbox_output_surface.cc b/content/renderer/gpu/mailbox_output_surface.cc index b7c3045..fe6bd6a 100644 --- a/content/renderer/gpu/mailbox_output_surface.cc +++ b/content/renderer/gpu/mailbox_output_surface.cc @@ -43,7 +43,9 @@ MailboxOutputSurface::MailboxOutputSurface( capabilities_.uses_default_gl_framebuffer = false; } -MailboxOutputSurface::~MailboxOutputSurface() { +MailboxOutputSurface::~MailboxOutputSurface() {} + +void MailboxOutputSurface::DetachFromClient() { DiscardBackbuffer(); while (!pending_textures_.empty()) { if (pending_textures_.front().texture_id) { @@ -52,6 +54,7 @@ MailboxOutputSurface::~MailboxOutputSurface() { } pending_textures_.pop_front(); } + cc::OutputSurface::DetachFromClient(); } void MailboxOutputSurface::EnsureBackbuffer() { diff --git a/content/renderer/gpu/mailbox_output_surface.h b/content/renderer/gpu/mailbox_output_surface.h index f907fb8..fc789c4 100644 --- a/content/renderer/gpu/mailbox_output_surface.h +++ b/content/renderer/gpu/mailbox_output_surface.h @@ -37,6 +37,7 @@ class MailboxOutputSurface : public CompositorOutputSurface { ~MailboxOutputSurface() override; // cc::OutputSurface implementation. + void DetachFromClient() override; void EnsureBackbuffer() override; void DiscardBackbuffer() override; void Reshape(const gfx::Size& size, float scale_factor) override; diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 0cdb8c3..71a8781 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -846,6 +846,7 @@ void RenderThreadImpl::Shutdown() { main_thread_compositor_task_runner_ = NULL; // Context providers must be released prior to destroying the GPU channel. + shared_worker_context_provider_ = nullptr; gpu_va_context_provider_ = nullptr; shared_main_thread_contexts_ = nullptr; @@ -1893,6 +1894,31 @@ base::TaskRunner* RenderThreadImpl::GetWorkerTaskRunner() { return raster_worker_pool_.get(); } +scoped_refptr<ContextProviderCommandBuffer> +RenderThreadImpl::SharedWorkerContextProvider() { + DCHECK(IsMainThread()); + // Try to reuse existing shared worker context provider. + bool shared_worker_context_provider_lost = false; + if (shared_worker_context_provider_) { + // Note: If context is lost, delete reference after releasing the lock. + base::AutoLock lock(*shared_worker_context_provider_->GetLock()); + if (shared_worker_context_provider_->ContextGL() + ->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { + shared_worker_context_provider_lost = true; + } + } + if (!shared_worker_context_provider_ || shared_worker_context_provider_lost) { + shared_worker_context_provider_ = ContextProviderCommandBuffer::Create( + CreateOffscreenContext3d(), RENDER_WORKER_CONTEXT); + if (shared_worker_context_provider_ && + !shared_worker_context_provider_->BindToCurrentThread()) + shared_worker_context_provider_ = nullptr; + if (shared_worker_context_provider_) + shared_worker_context_provider_->SetupLock(); + } + return shared_worker_context_provider_; +} + void RenderThreadImpl::SampleGamepads(blink::WebGamepads* data) { blink_platform_impl_->sampleGamepads(*data); } diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 3b99b4e..c3f9ab6 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h @@ -325,6 +325,9 @@ class CONTENT_EXPORT RenderThreadImpl // A TaskRunner instance that runs tasks on the raster worker pool. base::TaskRunner* GetWorkerTaskRunner(); + // Returns a shared worker context provider that can be used on any thread. + scoped_refptr<ContextProviderCommandBuffer> SharedWorkerContextProvider(); + // Causes the idle handler to skip sending idle notifications // on the two next scheduled calls, so idle notifications are // not sent for at least one notification delay. @@ -591,6 +594,7 @@ class CONTENT_EXPORT RenderThreadImpl base::ObserverList<RenderProcessObserver> observers_; + scoped_refptr<ContextProviderCommandBuffer> shared_worker_context_provider_; scoped_refptr<ContextProviderCommandBuffer> gpu_va_context_provider_; scoped_ptr<AudioRendererMixerManager> audio_renderer_mixer_manager_; diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index ec6203b..7fa1172 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc @@ -1018,10 +1018,9 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) { // Cause the compositor to wait and try again. return nullptr; } - - worker_context_provider = ContextProviderCommandBuffer::Create( - CreateGraphicsContext3D(false), RENDER_WORKER_CONTEXT); - if (!worker_context_provider.get()) { + worker_context_provider = + RenderThreadImpl::current()->SharedWorkerContextProvider(); + if (!worker_context_provider) { // Cause the compositor to wait and try again. return nullptr; } diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc index 942947d..1d96e01 100644 --- a/ui/compositor/test/in_process_context_factory.cc +++ b/ui/compositor/test/in_process_context_factory.cc @@ -112,19 +112,37 @@ void InProcessContextFactory::CreateOutputSurface( InProcessContextProvider::Create(attribs, &gpu_memory_buffer_manager_, &image_factory_, compositor->widget(), "UICompositor"); - scoped_refptr<InProcessContextProvider> worker_context_provider = - InProcessContextProvider::CreateOffscreen(&gpu_memory_buffer_manager_, - &image_factory_); + + // Try to reuse existing shared worker context provider. + bool shared_worker_context_provider_lost = false; + if (shared_worker_context_provider_) { + // Note: If context is lost, delete reference after releasing the lock. + base::AutoLock lock(*shared_worker_context_provider_->GetLock()); + if (shared_worker_context_provider_->ContextGL() + ->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { + shared_worker_context_provider_lost = true; + } + } + if (!shared_worker_context_provider_ || shared_worker_context_provider_lost) { + shared_worker_context_provider_ = InProcessContextProvider::CreateOffscreen( + &gpu_memory_buffer_manager_, &image_factory_); + if (shared_worker_context_provider_ && + !shared_worker_context_provider_->BindToCurrentThread()) + shared_worker_context_provider_ = nullptr; + if (shared_worker_context_provider_) + shared_worker_context_provider_->SetupLock(); + } scoped_ptr<cc::OutputSurface> real_output_surface; if (use_test_surface_) { bool flipped_output_surface = false; real_output_surface = make_scoped_ptr(new cc::PixelTestOutputSurface( - context_provider, worker_context_provider, flipped_output_surface)); + context_provider, shared_worker_context_provider_, + flipped_output_surface)); } else { - real_output_surface = make_scoped_ptr( - new DirectOutputSurface(context_provider, worker_context_provider)); + real_output_surface = make_scoped_ptr(new DirectOutputSurface( + context_provider, shared_worker_context_provider_)); } if (surface_manager_) { @@ -136,7 +154,7 @@ void InProcessContextFactory::CreateOutputSurface( scoped_ptr<cc::SurfaceDisplayOutputSurface> surface_output_surface( new cc::SurfaceDisplayOutputSurface( surface_manager_, compositor->surface_id_allocator(), - context_provider, worker_context_provider)); + context_provider, shared_worker_context_provider_)); display_client->set_surface_output_surface(surface_output_surface.get()); surface_output_surface->set_display_client(display_client.get()); diff --git a/ui/compositor/test/in_process_context_factory.h b/ui/compositor/test/in_process_context_factory.h index 4387adc..3c4e176 100644 --- a/ui/compositor/test/in_process_context_factory.h +++ b/ui/compositor/test/in_process_context_factory.h @@ -21,6 +21,7 @@ class SurfaceManager; } namespace ui { +class InProcessContextProvider; class InProcessContextFactory : public ContextFactory { public: @@ -56,7 +57,8 @@ class InProcessContextFactory : public ContextFactory { const gfx::Size& size) override; private: - scoped_refptr<cc::ContextProvider> shared_main_thread_contexts_; + scoped_refptr<InProcessContextProvider> shared_main_thread_contexts_; + scoped_refptr<InProcessContextProvider> shared_worker_context_provider_; cc::TestSharedBitmapManager shared_bitmap_manager_; cc::TestGpuMemoryBufferManager gpu_memory_buffer_manager_; cc::TestImageFactory image_factory_; diff --git a/ui/compositor/test/in_process_context_provider.h b/ui/compositor/test/in_process_context_provider.h index 0f5f35f..628eaec 100644 --- a/ui/compositor/test/in_process_context_provider.h +++ b/ui/compositor/test/in_process_context_provider.h @@ -38,15 +38,6 @@ class InProcessContextProvider : public cc::ContextProvider { gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, gpu::ImageFactory* image_factory); - private: - InProcessContextProvider( - const gpu::gles2::ContextCreationAttribHelper& attribs, - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, - gpu::ImageFactory* image_factory, - gfx::AcceleratedWidget window, - const std::string& debug_name); - ~InProcessContextProvider() override; - // cc::ContextProvider: bool BindToCurrentThread() override; void DetachFromThread() override; @@ -66,6 +57,15 @@ class InProcessContextProvider : public cc::ContextProvider { const MemoryPolicyChangedCallback& memory_policy_changed_callback) override; + private: + InProcessContextProvider( + const gpu::gles2::ContextCreationAttribHelper& attribs, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, + gpu::ImageFactory* image_factory, + gfx::AcceleratedWidget window, + const std::string& debug_name); + ~InProcessContextProvider() override; + void OnLostContext(); base::ThreadChecker main_thread_checker_; |