diff options
author | boliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-07 09:03:27 +0000 |
---|---|---|
committer | boliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-07 09:03:27 +0000 |
commit | 2b154b2a2a4c2adf2d145cddbae49767acc67633 (patch) | |
tree | 2966cd155581d9786b1ea892dcd438696b1ef2c7 | |
parent | 8d0e6fe215548a3c19a569d300cc0f01e2e1f2ac (diff) | |
download | chromium_src-2b154b2a2a4c2adf2d145cddbae49767acc67633.zip chromium_src-2b154b2a2a4c2adf2d145cddbae49767acc67633.tar.gz chromium_src-2b154b2a2a4c2adf2d145cddbae49767acc67633.tar.bz2 |
cc::OutputSurfaceClient::DeferredInitialize
SynchronousCompositorOutputSurface first starts in software only
mode, then cc::OutputSurfaceClient::InitializeForGL is called to
initialize the GL parts.
BUG=230197
Review URL: https://chromiumcodereview.appspot.com/14772021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@204771 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | cc/output/output_surface_client.h | 7 | ||||
-rw-r--r-- | cc/output/output_surface_unittest.cc | 4 | ||||
-rw-r--r-- | cc/scheduler/frame_rate_controller.cc | 4 | ||||
-rw-r--r-- | cc/scheduler/frame_rate_controller.h | 1 | ||||
-rw-r--r-- | cc/scheduler/scheduler.cc | 4 | ||||
-rw-r--r-- | cc/scheduler/scheduler.h | 1 | ||||
-rw-r--r-- | cc/test/fake_layer_tree_host_impl_client.h | 3 | ||||
-rw-r--r-- | cc/test/fake_output_surface.cc | 11 | ||||
-rw-r--r-- | cc/test/fake_output_surface.h | 8 | ||||
-rw-r--r-- | cc/test/fake_picture_layer_impl.cc | 11 | ||||
-rw-r--r-- | cc/test/fake_picture_layer_impl.h | 5 | ||||
-rw-r--r-- | cc/test/test_web_graphics_context_3d.cc | 10 | ||||
-rw-r--r-- | cc/test/test_web_graphics_context_3d.h | 4 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.cc | 26 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.h | 8 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl_unittest.cc | 41 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest.cc | 68 | ||||
-rw-r--r-- | cc/trees/single_thread_proxy.cc | 7 | ||||
-rw-r--r-- | cc/trees/single_thread_proxy.h | 3 | ||||
-rw-r--r-- | cc/trees/thread_proxy.cc | 31 | ||||
-rw-r--r-- | cc/trees/thread_proxy.h | 3 |
21 files changed, 246 insertions, 14 deletions
diff --git a/cc/output/output_surface_client.h b/cc/output/output_surface_client.h index 26edec8..dc68e96 100644 --- a/cc/output/output_surface_client.h +++ b/cc/output/output_surface_client.h @@ -5,8 +5,10 @@ #ifndef CC_OUTPUT_OUTPUT_SURFACE_CLIENT_H_ #define CC_OUTPUT_OUTPUT_SURFACE_CLIENT_H_ +#include "base/memory/ref_counted.h" #include "base/time.h" #include "cc/base/cc_export.h" +#include "cc/output/context_provider.h" #include "ui/gfx/rect.h" namespace gfx { @@ -19,6 +21,11 @@ class CompositorFrameAck; class CC_EXPORT OutputSurfaceClient { public: + // Called to synchronously re-initialize using the Context3D. Upon returning + // the compositor should be able to draw using GL what was previously + // committed. + virtual bool DeferredInitialize( + scoped_refptr<ContextProvider> offscreen_context_provider) = 0; virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) = 0; virtual void OnVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval) = 0; diff --git a/cc/output/output_surface_unittest.cc b/cc/output/output_surface_unittest.cc index d54afe2..1d365d9 100644 --- a/cc/output/output_surface_unittest.cc +++ b/cc/output/output_surface_unittest.cc @@ -28,6 +28,10 @@ class TestOutputSurface : public OutputSurface { class FakeOutputSurfaceClient : public OutputSurfaceClient { public: + virtual bool DeferredInitialize( + scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE { + return true; + } virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) OVERRIDE {} virtual void OnVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval) OVERRIDE {} diff --git a/cc/scheduler/frame_rate_controller.cc b/cc/scheduler/frame_rate_controller.cc index 4fcea23..bcb12d2 100644 --- a/cc/scheduler/frame_rate_controller.cc +++ b/cc/scheduler/frame_rate_controller.cc @@ -88,6 +88,10 @@ void FrameRateController::SetTimebaseAndInterval(base::TimeTicks timebase, time_source_->SetTimebaseAndInterval(timebase, interval); } +bool FrameRateController::swap_buffers_complete_supported() const { + return swap_buffers_complete_supported_; +} + void FrameRateController::SetSwapBuffersCompleteSupported(bool supported) { swap_buffers_complete_supported_ = supported; } diff --git a/cc/scheduler/frame_rate_controller.h b/cc/scheduler/frame_rate_controller.h index 9210a670..339578a 100644 --- a/cc/scheduler/frame_rate_controller.h +++ b/cc/scheduler/frame_rate_controller.h @@ -63,6 +63,7 @@ class CC_EXPORT FrameRateController { void SetTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval); + bool swap_buffers_complete_supported() const; void SetSwapBuffersCompleteSupported(bool supported); protected: diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index 737ffc1..e34e6d5 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc @@ -100,6 +100,10 @@ int Scheduler::NumFramesPendingForTesting() const { return frame_rate_controller_->NumFramesPendingForTesting(); } +bool Scheduler::swap_buffers_complete_supported() const { + return frame_rate_controller_->swap_buffers_complete_supported(); +} + void Scheduler::SetSwapBuffersCompleteSupported(bool supported) { frame_rate_controller_->SetSwapBuffersCompleteSupported(supported); } diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h index aec0cdf..5bdb186 100644 --- a/cc/scheduler/scheduler.h +++ b/cc/scheduler/scheduler.h @@ -90,6 +90,7 @@ class CC_EXPORT Scheduler : FrameRateControllerClient { int MaxFramesPending() const; int NumFramesPendingForTesting() const; + bool swap_buffers_complete_supported() const; void SetSwapBuffersCompleteSupported(bool supported); void DidSwapBuffersComplete(); diff --git a/cc/test/fake_layer_tree_host_impl_client.h b/cc/test/fake_layer_tree_host_impl_client.h index 44e5380..184bacc 100644 --- a/cc/test/fake_layer_tree_host_impl_client.h +++ b/cc/test/fake_layer_tree_host_impl_client.h @@ -12,6 +12,9 @@ namespace cc { class FakeLayerTreeHostImplClient : public LayerTreeHostImplClient { public: // LayerTreeHostImplClient implementation. + virtual void DidTryInitializeRendererOnImplThread( + bool success, + scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE {} virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {} virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {} virtual void OnVSyncParametersChanged( diff --git a/cc/test/fake_output_surface.cc b/cc/test/fake_output_surface.cc index 6c5bc9f..d393ba0 100644 --- a/cc/test/fake_output_surface.cc +++ b/cc/test/fake_output_surface.cc @@ -30,6 +30,17 @@ FakeOutputSurface::FakeOutputSurface( capabilities_.has_parent_compositor = has_parent; } +FakeOutputSurface::FakeOutputSurface( + scoped_ptr<WebKit::WebGraphicsContext3D> context3d, + scoped_ptr<SoftwareOutputDevice> software_device, + bool has_parent) + : OutputSurface(context3d.Pass(), software_device.Pass()), + num_sent_frames_(0), + forced_draw_to_software_device_(false), + weak_ptr_factory_(this) { + capabilities_.has_parent_compositor = has_parent; +} + FakeOutputSurface::~FakeOutputSurface() {} void FakeOutputSurface::SendFrameToParentCompositor( diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h index 6eff484..7460f93 100644 --- a/cc/test/fake_output_surface.h +++ b/cc/test/fake_output_surface.h @@ -58,9 +58,10 @@ class FakeOutputSurface : public OutputSurface { } static scoped_ptr<FakeOutputSurface> CreateDeferredGL( + scoped_ptr<WebKit::WebGraphicsContext3D> context3d, scoped_ptr<SoftwareOutputDevice> software_device) { scoped_ptr<FakeOutputSurface> result( - new FakeOutputSurface(software_device.Pass(), false)); + new FakeOutputSurface(context3d.Pass(), software_device.Pass(), false)); result->capabilities_.deferred_gl_initialization = true; return result.Pass(); } @@ -90,6 +91,11 @@ class FakeOutputSurface : public OutputSurface { scoped_ptr<SoftwareOutputDevice> software_device, bool has_parent); + FakeOutputSurface( + scoped_ptr<WebKit::WebGraphicsContext3D> context3d, + scoped_ptr<SoftwareOutputDevice> software_device, + bool has_parent); + void SendFrameAck(); CompositorFrame last_sent_frame_; diff --git a/cc/test/fake_picture_layer_impl.cc b/cc/test/fake_picture_layer_impl.cc index 576c866..4b30bd7 100644 --- a/cc/test/fake_picture_layer_impl.cc +++ b/cc/test/fake_picture_layer_impl.cc @@ -10,14 +10,15 @@ FakePictureLayerImpl::FakePictureLayerImpl( LayerTreeImpl* tree_impl, int id, scoped_refptr<PicturePileImpl> pile) - : PictureLayerImpl(tree_impl, id) { + : PictureLayerImpl(tree_impl, id), + append_quads_count_(0) { pile_ = pile; SetBounds(pile_->size()); CreateTilingSet(); } FakePictureLayerImpl::FakePictureLayerImpl(LayerTreeImpl* tree_impl, int id) - : PictureLayerImpl(tree_impl, id) {} + : PictureLayerImpl(tree_impl, id), append_quads_count_(0) {} scoped_ptr<LayerImpl> FakePictureLayerImpl::CreateLayerImpl( LayerTreeImpl* tree_impl) { @@ -25,6 +26,12 @@ scoped_ptr<LayerImpl> FakePictureLayerImpl::CreateLayerImpl( new FakePictureLayerImpl(tree_impl, id())).PassAs<LayerImpl>(); } +void FakePictureLayerImpl::AppendQuads(QuadSink* quad_sink, + AppendQuadsData* append_quads_data) { + PictureLayerImpl::AppendQuads(quad_sink, append_quads_data); + ++append_quads_count_; +} + gfx::Size FakePictureLayerImpl::CalculateTileSize(gfx::Size content_bounds) { if (fixed_tile_size_.IsEmpty()) { return PictureLayerImpl::CalculateTileSize(content_bounds); diff --git a/cc/test/fake_picture_layer_impl.h b/cc/test/fake_picture_layer_impl.h index c3d28f8..37d9645 100644 --- a/cc/test/fake_picture_layer_impl.h +++ b/cc/test/fake_picture_layer_impl.h @@ -24,6 +24,8 @@ class FakePictureLayerImpl : public PictureLayerImpl { virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) OVERRIDE; + virtual void AppendQuads(QuadSink* quad_sink, + AppendQuadsData* append_quads_data) OVERRIDE; virtual gfx::Size CalculateTileSize(gfx::Size content_bounds) OVERRIDE; using PictureLayerImpl::AddTiling; @@ -33,6 +35,7 @@ class FakePictureLayerImpl : public PictureLayerImpl { PictureLayerImpl* twin_layer() { return twin_layer_; } PictureLayerTilingSet* tilings() { return tilings_.get(); } + size_t append_quads_count() { return append_quads_count_; } const Region& invalidation() const { return invalidation_; } void set_invalidation(const Region& region) { invalidation_ = region; } @@ -48,6 +51,8 @@ class FakePictureLayerImpl : public PictureLayerImpl { private: gfx::Size fixed_tile_size_; + + size_t append_quads_count_; }; } // namespace cc diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc index aaeff68..8956aec 100644 --- a/cc/test/test_web_graphics_context_3d.cc +++ b/cc/test/test_web_graphics_context_3d.cc @@ -41,6 +41,7 @@ TestWebGraphicsContext3D::TestWebGraphicsContext3D() next_buffer_id_(1), next_image_id_(1), next_texture_id_(1), + support_swapbuffers_complete_callback_(true), have_extension_io_surface_(false), have_extension_egl_image_(false), times_make_current_succeeds_(-1), @@ -64,6 +65,7 @@ TestWebGraphicsContext3D::TestWebGraphicsContext3D( next_image_id_(1), next_texture_id_(1), attributes_(attributes), + support_swapbuffers_complete_callback_(true), have_extension_io_surface_(false), have_extension_egl_image_(false), times_make_current_succeeds_(-1), @@ -132,7 +134,10 @@ WebGraphicsContext3D::Attributes } WebKit::WebString TestWebGraphicsContext3D::getString(WGC3Denum name) { - std::string string("GL_CHROMIUM_swapbuffers_complete_callback"); + std::string string; + + if (support_swapbuffers_complete_callback_) + string += "GL_CHROMIUM_swapbuffers_complete_callback"; if (name == GL_EXTENSIONS) { if (have_extension_io_surface_) @@ -355,7 +360,8 @@ void TestWebGraphicsContext3D::signalSyncPoint( void TestWebGraphicsContext3D::setSwapBuffersCompleteCallbackCHROMIUM( WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* callback) { - swap_buffers_callback_ = callback; + if (support_swapbuffers_complete_callback_) + swap_buffers_callback_ = callback; } void TestWebGraphicsContext3D::prepareTexture() { diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h index ffd847d..449b2bb 100644 --- a/cc/test/test_web_graphics_context_3d.h +++ b/cc/test/test_web_graphics_context_3d.h @@ -163,6 +163,9 @@ class TestWebGraphicsContext3D : public FakeWebGraphicsContext3D { } void ResetUsedTextures() { used_textures_.clear(); } + void set_support_swapbuffers_complete_callback(bool support) { + support_swapbuffers_complete_callback_ = support; + } void set_have_extension_io_surface(bool have) { have_extension_io_surface_ = have; } @@ -197,6 +200,7 @@ class TestWebGraphicsContext3D : public FakeWebGraphicsContext3D { unsigned next_image_id_; unsigned next_texture_id_; Attributes attributes_; + bool support_swapbuffers_complete_callback_; bool have_extension_io_surface_; bool have_extension_egl_image_; int times_make_current_succeeds_; diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 2b8d453..d384ea7 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -1454,7 +1454,15 @@ bool LayerTreeHostImpl::InitializeRenderer( if (!output_surface->BindToClient(this)) return false; - if (output_surface->capabilities().deferred_gl_initialization) { + return DoInitializeRenderer(output_surface.Pass(), + false /* is_deferred_init */); +} + +bool LayerTreeHostImpl::DoInitializeRenderer( + scoped_ptr<OutputSurface> output_surface, + bool is_deferred_init) { + if (output_surface->capabilities().deferred_gl_initialization && + !is_deferred_init) { // TODO(joth): Defer creating the Renderer too, until GL is initialized. // See http://crbug.com/230197 renderer_ = SoftwareRenderer::Create(this, output_surface.get(), NULL); @@ -1511,6 +1519,22 @@ bool LayerTreeHostImpl::InitializeRenderer( return true; } +bool LayerTreeHostImpl::DeferredInitialize( + scoped_refptr<ContextProvider> offscreen_context_provider) { + DCHECK(output_surface_->capabilities().deferred_gl_initialization); + DCHECK(output_surface_->context3d()); + + // TODO(boliu): This is temporary until proper resource clean up is possible + // without resetting |tile_manager_| or |resource_provider_|. + DCHECK(!resource_provider_); + + bool success = + DoInitializeRenderer(output_surface_.Pass(), true /* is_deferred_init */); + client_->DidTryInitializeRendererOnImplThread(success, + offscreen_context_provider); + return success; +} + void LayerTreeHostImpl::SetViewportSize(gfx::Size device_viewport_size) { if (device_viewport_size == device_viewport_size_) return; diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 055a7d6..fee3f46 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h @@ -50,6 +50,9 @@ struct RendererCapabilities; // LayerTreeHost->Proxy callback interface. class LayerTreeHostImplClient { public: + virtual void DidTryInitializeRendererOnImplThread( + bool success, + scoped_refptr<ContextProvider> offscreen_context_provider) = 0; virtual void DidLoseOutputSurfaceOnImplThread() = 0; virtual void OnSwapBuffersCompleteOnImplThread() = 0; virtual void OnVSyncParametersChanged(base::TimeTicks timebase, @@ -200,6 +203,8 @@ class CC_EXPORT LayerTreeHostImpl OVERRIDE; // OutputSurfaceClient implementation. + virtual bool DeferredInitialize( + scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE; virtual void SetNeedsRedrawRect(gfx::Rect rect) OVERRIDE; virtual void OnVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval) OVERRIDE; @@ -397,6 +402,9 @@ class CC_EXPORT LayerTreeHostImpl Proxy* proxy_; private: + bool DoInitializeRenderer(scoped_ptr<OutputSurface> output_surface, + bool is_deffered_init); + void AnimatePageScale(base::TimeTicks monotonic_time); void AnimateScrollbars(base::TimeTicks monotonic_time); void AnimateTopControls(base::TimeTicks monotonic_time); diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 95bc4fe..9bb674a 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -64,6 +64,7 @@ class LayerTreeHostImplTest : public testing::Test, : proxy_(scoped_ptr<Thread>(NULL)), always_impl_thread_(&proxy_), always_main_thread_blocked_(&proxy_), + did_try_initialize_renderer_(false), on_can_draw_state_changed_called_(false), has_pending_tree_(false), did_request_commit_(false), @@ -90,6 +91,11 @@ class LayerTreeHostImplTest : public testing::Test, virtual void TearDown() OVERRIDE {} + virtual void DidTryInitializeRendererOnImplThread( + bool success, + scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE { + did_try_initialize_renderer_ = true; + } virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {} virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {} virtual void OnVSyncParametersChanged(base::TimeTicks timebase, @@ -275,6 +281,7 @@ class LayerTreeHostImplTest : public testing::Test, scoped_ptr<LayerTreeHostImpl> host_impl_; FakeRenderingStatsInstrumentation stats_instrumentation_; + bool did_try_initialize_renderer_; bool on_can_draw_state_changed_called_; bool has_pending_tree_; bool did_request_commit_; @@ -5786,6 +5793,7 @@ TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) { host_impl_->SetViewportSize(gfx::Size(50, 50)); CountingSoftwareDevice* software_device = new CountingSoftwareDevice(); FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL( + scoped_ptr<WebKit::WebGraphicsContext3D>(), scoped_ptr<SoftwareOutputDevice>(software_device)).release(); host_impl_->InitializeRenderer(scoped_ptr<OutputSurface>(output_surface)); @@ -5808,6 +5816,7 @@ TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) { TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) { FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL( + scoped_ptr<WebKit::WebGraphicsContext3D>(), scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())).release(); host_impl_->InitializeRenderer( scoped_ptr<OutputSurface>(output_surface)); @@ -5838,5 +5847,37 @@ TEST_F(LayerTreeHostImplTest, EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]); } +TEST_F(LayerTreeHostImplTest, DeferredInitializeSmoke) { + host_impl_->InitializeRenderer( + scoped_ptr<OutputSurface>(FakeOutputSurface::CreateDeferredGL( + scoped_ptr<WebKit::WebGraphicsContext3D>( + TestWebGraphicsContext3D::Create( + WebKit::WebGraphicsContext3D::Attributes())), + scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())))); + + // Add two layers. + scoped_ptr<SolidColorLayerImpl> root_layer = + SolidColorLayerImpl::Create(host_impl_->active_tree(), 1); + FakeVideoFrameProvider provider; + scoped_ptr<VideoLayerImpl> video_layer = + VideoLayerImpl::Create(host_impl_->active_tree(), 2, &provider); + video_layer->SetBounds(gfx::Size(10, 10)); + video_layer->SetContentBounds(gfx::Size(10, 10)); + video_layer->SetDrawsContent(true); + root_layer->AddChild(video_layer.PassAs<LayerImpl>()); + SetupRootLayerImpl(root_layer.PassAs<LayerImpl>()); + + // Software draw. + DrawFrame(); + + // DeferredInitialize and hardware draw. + EXPECT_FALSE(did_try_initialize_renderer_); + host_impl_->DeferredInitialize(scoped_refptr<ContextProvider>()); + EXPECT_TRUE(did_try_initialize_renderer_); + + // Defer intialized GL draw. + DrawFrame(); +} + } // namespace } // namespace cc diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 89faf49..5a92d0b 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc @@ -25,6 +25,8 @@ #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_output_surface.h" +#include "cc/test/fake_picture_layer.h" +#include "cc/test/fake_picture_layer_impl.h" #include "cc/test/fake_proxy.h" #include "cc/test/fake_scrollbar_layer.h" #include "cc/test/geometry_test_utils.h" @@ -2841,5 +2843,71 @@ TEST_F(LayerTreeHostTestNumFramesPending, GLRenderer) { RunTest(true, false, true); } +class LayerTreeHostTestDeferredInitialize : public LayerTreeHostTest { + public: + virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE { + // PictureLayer can only be used with impl side painting enabled. + settings->impl_side_painting = true; + } + + virtual void SetupTree() OVERRIDE { + layer_ = FakePictureLayer::Create(&client_); + layer_tree_host()->SetRootLayer(layer_); + LayerTreeHostTest::SetupTree(); + } + + virtual void BeginTest() OVERRIDE { + initialized_gl_ = false; + PostSetNeedsCommitToMainThread(); + } + + virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE { + scoped_ptr<TestWebGraphicsContext3D> context3d( + TestWebGraphicsContext3D::Create()); + context3d->set_support_swapbuffers_complete_callback(false); + + return FakeOutputSurface::CreateDeferredGL( + context3d.PassAs<WebKit::WebGraphicsContext3D>(), + scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice)) + .PassAs<OutputSurface>(); + } + + virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + ASSERT_TRUE(host_impl->RootLayer()); + FakePictureLayerImpl* layer_impl = + static_cast<FakePictureLayerImpl*>(host_impl->RootLayer()); + if (!initialized_gl_) { + EXPECT_EQ(1u, layer_impl->append_quads_count()); + ImplThread()->PostTask(base::Bind( + &LayerTreeHostTestDeferredInitialize::DeferredInitializeAndRedraw, + base::Unretained(this), + base::Unretained(host_impl))); + } else { + EXPECT_EQ(2u, layer_impl->append_quads_count()); + EndTest(); + } + } + + void DeferredInitializeAndRedraw(LayerTreeHostImpl* host_impl) { + EXPECT_TRUE( + host_impl->DeferredInitialize(scoped_refptr<ContextProvider>())); + initialized_gl_ = true; + + // Force redraw again. + host_impl->SetNeedsRedrawRect(gfx::Rect(1, 1)); + } + + virtual void AfterTest() OVERRIDE { + EXPECT_TRUE(initialized_gl_); + } + + private: + FakeContentLayerClient client_; + scoped_refptr<FakePictureLayer> layer_; + bool initialized_gl_; +}; + +MULTI_THREAD_TEST_F(LayerTreeHostTestDeferredInitialize); + } // namespace } // namespace cc diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index 51355d9..e8d3e76 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc @@ -327,6 +327,13 @@ void SingleThreadProxy::SendManagedMemoryStats() { bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; } +void SingleThreadProxy::DidTryInitializeRendererOnImplThread( + bool success, + scoped_refptr<ContextProvider> offscreen_context_provider) { + NOTREACHED() + << "This is only used on threaded compositing with impl-side painting"; +} + void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() { // Cause a commit so we can notice the lost context. SetNeedsCommitOnImplThread(); diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h index 4d98b5b..6a963e80 100644 --- a/cc/trees/single_thread_proxy.h +++ b/cc/trees/single_thread_proxy.h @@ -46,6 +46,9 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient { virtual bool CommitPendingForTesting() OVERRIDE; // LayerTreeHostImplClient implementation + virtual void DidTryInitializeRendererOnImplThread( + bool success, + scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE; virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE; virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {} virtual void OnVSyncParametersChanged(base::TimeTicks timebase, diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc index 4fcb8ac..d1c4471 100644 --- a/cc/trees/thread_proxy.cc +++ b/cc/trees/thread_proxy.cc @@ -1164,9 +1164,6 @@ void ThreadProxy::InitializeOutputSurfaceOnImplThread( *success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass()); - if (offscreen_context_provider.get()) - offscreen_context_provider->BindToCurrentThread(); - if (*success) { *capabilities = layer_tree_host_impl_->GetRendererCapabilities(); scheduler_on_impl_thread_->SetSwapBuffersCompleteSupported( @@ -1183,16 +1180,34 @@ void ThreadProxy::InitializeOutputSurfaceOnImplThread( scheduler_on_impl_thread_->SetMaxFramesPending(max_frames_pending); - if (layer_tree_host_impl_->resource_provider()) + scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface(); + } + + DidTryInitializeRendererOnImplThread(*success, offscreen_context_provider); + + completion->Signal(); +} + +void ThreadProxy::DidTryInitializeRendererOnImplThread( + bool success, + scoped_refptr<ContextProvider> offscreen_context_provider) { + DCHECK(IsImplThread()); + DCHECK(!inside_draw_); + + if (offscreen_context_provider.get()) + offscreen_context_provider->BindToCurrentThread(); + + if (success) { + DCHECK_EQ(layer_tree_host_impl_->GetRendererCapabilities() + .using_swap_complete_callback, + scheduler_on_impl_thread_->swap_buffers_complete_supported()); + if (layer_tree_host_impl_->resource_provider()) { layer_tree_host_impl_->resource_provider()-> set_offscreen_context_provider(offscreen_context_provider); - - scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface(); + } } else if (offscreen_context_provider.get()) { offscreen_context_provider->VerifyContexts(); } - - completion->Signal(); } void ThreadProxy::FinishGLOnImplThread(CompletionEvent* completion) { diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h index eff23db..8d62dd1 100644 --- a/cc/trees/thread_proxy.h +++ b/cc/trees/thread_proxy.h @@ -61,6 +61,9 @@ class ThreadProxy : public Proxy, virtual bool CommitPendingForTesting() OVERRIDE; // LayerTreeHostImplClient implementation + virtual void DidTryInitializeRendererOnImplThread( + bool success, + scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE; virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE; virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE; virtual void OnVSyncParametersChanged(base::TimeTicks timebase, |