summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorboliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-07 09:03:27 +0000
committerboliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-07 09:03:27 +0000
commit2b154b2a2a4c2adf2d145cddbae49767acc67633 (patch)
tree2966cd155581d9786b1ea892dcd438696b1ef2c7
parent8d0e6fe215548a3c19a569d300cc0f01e2e1f2ac (diff)
downloadchromium_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.h7
-rw-r--r--cc/output/output_surface_unittest.cc4
-rw-r--r--cc/scheduler/frame_rate_controller.cc4
-rw-r--r--cc/scheduler/frame_rate_controller.h1
-rw-r--r--cc/scheduler/scheduler.cc4
-rw-r--r--cc/scheduler/scheduler.h1
-rw-r--r--cc/test/fake_layer_tree_host_impl_client.h3
-rw-r--r--cc/test/fake_output_surface.cc11
-rw-r--r--cc/test/fake_output_surface.h8
-rw-r--r--cc/test/fake_picture_layer_impl.cc11
-rw-r--r--cc/test/fake_picture_layer_impl.h5
-rw-r--r--cc/test/test_web_graphics_context_3d.cc10
-rw-r--r--cc/test/test_web_graphics_context_3d.h4
-rw-r--r--cc/trees/layer_tree_host_impl.cc26
-rw-r--r--cc/trees/layer_tree_host_impl.h8
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc41
-rw-r--r--cc/trees/layer_tree_host_unittest.cc68
-rw-r--r--cc/trees/single_thread_proxy.cc7
-rw-r--r--cc/trees/single_thread_proxy.h3
-rw-r--r--cc/trees/thread_proxy.cc31
-rw-r--r--cc/trees/thread_proxy.h3
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,