#include "cc/test/animation_test_common.h"
#include "cc/test/fake_layer_tree_host_client.h"
#include "cc/test/fake_output_surface.h"
-#include "cc/test/occlusion_tracker_test_common.h"
#include "cc/test/test_context_provider.h"
+#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/tiled_layer_test_common.h"
+#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_impl.h"
+#include "cc/trees/layer_tree_host_single_thread_client.h"
+#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/single_thread_proxy.h"
+#include "cc/trees/thread_proxy.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/gfx/frame_time.h"
#include "ui/gfx/size_conversions.h"
TestHooks::~TestHooks() {}
-bool TestHooks::PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
- LayerTreeHostImpl::FrameData* frame_data,
- bool result) {
- return true;
+DrawResult TestHooks::PrepareToDrawOnThread(
+ LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ DrawResult draw_result) {
+ return draw_result;
}
base::TimeDelta TestHooks::LowFrequencyAnimationInterval() const {
return base::TimeDelta::FromMilliseconds(16);
}
+// Adapts ThreadProxy for test. Injects test hooks for testing.
+class ThreadProxyForTest : public ThreadProxy {
+ public:
+ static scoped_ptr<Proxy> Create(
+ TestHooks* test_hooks,
+ LayerTreeHost* host,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
+ return make_scoped_ptr(
+ new ThreadProxyForTest(
+ test_hooks, host, main_task_runner, impl_task_runner))
+ .PassAs<Proxy>();
+ }
+
+ virtual ~ThreadProxyForTest() {}
+
+ void test() {
+ test_hooks_->Layout();
+ }
+
+ private:
+ TestHooks* test_hooks_;
+
+ virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {
+ test_hooks_->ScheduledActionWillSendBeginMainFrame();
+ ThreadProxy::ScheduledActionSendBeginMainFrame();
+ test_hooks_->ScheduledActionSendBeginMainFrame();
+ }
+
+ virtual DrawResult ScheduledActionDrawAndSwapIfPossible() OVERRIDE {
+ DrawResult result = ThreadProxy::ScheduledActionDrawAndSwapIfPossible();
+ test_hooks_->ScheduledActionDrawAndSwapIfPossible();
+ return result;
+ }
+
+ virtual void ScheduledActionAnimate() OVERRIDE {
+ ThreadProxy::ScheduledActionAnimate();
+ test_hooks_->ScheduledActionAnimate();
+ }
+
+ virtual void ScheduledActionCommit() OVERRIDE {
+ ThreadProxy::ScheduledActionCommit();
+ test_hooks_->ScheduledActionCommit();
+ }
+
+ virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {
+ ThreadProxy::ScheduledActionBeginOutputSurfaceCreation();
+ test_hooks_->ScheduledActionBeginOutputSurfaceCreation();
+ }
+
+ ThreadProxyForTest(
+ TestHooks* test_hooks,
+ LayerTreeHost* host,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)
+ : ThreadProxy(host, main_task_runner, impl_task_runner),
+ test_hooks_(test_hooks) {}
+};
+
// Adapts LayerTreeHostImpl for test. Runs real code, then invokes test hooks.
class LayerTreeHostImplForTesting : public LayerTreeHostImpl {
public:
const LayerTreeSettings& settings,
LayerTreeHostImplClient* host_impl_client,
Proxy* proxy,
+ SharedBitmapManager* manager,
RenderingStatsInstrumentation* stats_instrumentation) {
return make_scoped_ptr(
new LayerTreeHostImplForTesting(test_hooks,
settings,
host_impl_client,
proxy,
+ manager,
stats_instrumentation));
}
const LayerTreeSettings& settings,
LayerTreeHostImplClient* host_impl_client,
Proxy* proxy,
+ SharedBitmapManager* manager,
RenderingStatsInstrumentation* stats_instrumentation)
: LayerTreeHostImpl(settings,
host_impl_client,
proxy,
stats_instrumentation,
- NULL),
+ manager,
+ 0),
test_hooks_(test_hooks),
block_notify_ready_to_activate_for_testing_(false),
notify_ready_to_activate_was_blocked_(false) {}
- virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE {
+ virtual void WillBeginImplFrame(const BeginFrameArgs& args) OVERRIDE {
+ LayerTreeHostImpl::WillBeginImplFrame(args);
test_hooks_->WillBeginImplFrameOnThread(this, args);
- LayerTreeHostImpl::BeginImplFrame(args);
- test_hooks_->DidBeginImplFrameOnThread(this, args);
+ }
+
+ virtual void BeginMainFrameAborted(bool did_handle) OVERRIDE {
+ LayerTreeHostImpl::BeginMainFrameAborted(did_handle);
+ test_hooks_->BeginMainFrameAbortedOnThread(this, did_handle);
}
virtual void BeginCommit() OVERRIDE {
virtual void CommitComplete() OVERRIDE {
LayerTreeHostImpl::CommitComplete();
test_hooks_->CommitCompleteOnThread(this);
-
- if (!settings().impl_side_painting) {
- test_hooks_->WillActivateTreeOnThread(this);
- test_hooks_->DidActivateTreeOnThread(this);
- }
}
- virtual bool PrepareToDraw(FrameData* frame, gfx::Rect damage_rect) OVERRIDE {
- bool result = LayerTreeHostImpl::PrepareToDraw(frame, damage_rect);
- if (!test_hooks_->PrepareToDrawOnThread(this, frame, result))
- result = false;
- return result;
+ virtual DrawResult PrepareToDraw(FrameData* frame) OVERRIDE {
+ DrawResult draw_result = LayerTreeHostImpl::PrepareToDraw(frame);
+ return test_hooks_->PrepareToDrawOnThread(this, frame, draw_result);
}
virtual void DrawLayers(FrameData* frame,
return result;
}
- virtual void OnSwapBuffersComplete() OVERRIDE {
- LayerTreeHostImpl::OnSwapBuffersComplete();
+ virtual void DidSwapBuffersComplete() OVERRIDE {
+ LayerTreeHostImpl::DidSwapBuffersComplete();
test_hooks_->SwapBuffersCompleteOnThread(this);
}
}
}
- virtual void ActivatePendingTree() OVERRIDE {
+ virtual void ActivateSyncTree() OVERRIDE {
test_hooks_->WillActivateTreeOnThread(this);
- LayerTreeHostImpl::ActivatePendingTree();
+ LayerTreeHostImpl::ActivateSyncTree();
DCHECK(!pending_tree());
test_hooks_->DidActivateTreeOnThread(this);
}
test_hooks_->DidSetVisibleOnImplTree(this, visible);
}
- virtual void AnimateLayers(base::TimeTicks monotonic_time,
- base::Time wall_clock_time) OVERRIDE {
+ virtual void AnimateLayers(base::TimeTicks monotonic_time) OVERRIDE {
test_hooks_->WillAnimateLayers(this, monotonic_time);
- LayerTreeHostImpl::AnimateLayers(monotonic_time, wall_clock_time);
+ LayerTreeHostImpl::AnimateLayers(monotonic_time);
test_hooks_->AnimateLayers(this, monotonic_time);
}
bool notify_ready_to_activate_was_blocked_;
};
-// Adapts LayerTreeHost for test. Injects LayerTreeHostImplForTesting.
-class LayerTreeHostForTesting : public LayerTreeHost {
- public:
- static scoped_ptr<LayerTreeHostForTesting> Create(
- TestHooks* test_hooks,
- LayerTreeHostClient* host_client,
- const LayerTreeSettings& settings,
- scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
- scoped_ptr<LayerTreeHostForTesting> layer_tree_host(
- new LayerTreeHostForTesting(test_hooks, host_client, settings));
- bool success = layer_tree_host->Initialize(impl_task_runner);
- EXPECT_TRUE(success);
- return layer_tree_host.Pass();
- }
-
- virtual scoped_ptr<LayerTreeHostImpl> CreateLayerTreeHostImpl(
- LayerTreeHostImplClient* host_impl_client) OVERRIDE {
- return LayerTreeHostImplForTesting::Create(
- test_hooks_,
- settings(),
- host_impl_client,
- proxy(),
- rendering_stats_instrumentation()).PassAs<LayerTreeHostImpl>();
- }
-
- virtual void SetNeedsCommit() OVERRIDE {
- if (!test_started_)
- return;
- LayerTreeHost::SetNeedsCommit();
- }
-
- void set_test_started(bool started) { test_started_ = started; }
-
- virtual void DidDeferCommit() OVERRIDE {
- test_hooks_->DidDeferCommit();
- }
-
- private:
- LayerTreeHostForTesting(TestHooks* test_hooks,
- LayerTreeHostClient* client,
- const LayerTreeSettings& settings)
- : LayerTreeHost(client, NULL, settings),
- test_hooks_(test_hooks),
- test_started_(false) {}
-
- TestHooks* test_hooks_;
- bool test_started_;
-};
-
// Implementation of LayerTreeHost callback interface.
-class LayerTreeHostClientForTesting : public LayerTreeHostClient {
+class LayerTreeHostClientForTesting : public LayerTreeHostClient,
+ public LayerTreeHostSingleThreadClient {
public:
static scoped_ptr<LayerTreeHostClientForTesting> Create(
TestHooks* test_hooks) {
}
virtual ~LayerTreeHostClientForTesting() {}
- virtual void WillBeginMainFrame() OVERRIDE {
+ virtual void WillBeginMainFrame(int frame_id) OVERRIDE {
test_hooks_->WillBeginMainFrame();
}
test_hooks_->DidBeginMainFrame();
}
- virtual void Animate(double monotonic_time) OVERRIDE {
- test_hooks_->Animate(base::TimeTicks::FromInternalValue(
- monotonic_time * base::Time::kMicrosecondsPerSecond));
+ virtual void Animate(base::TimeTicks monotonic_time) OVERRIDE {
+ test_hooks_->Animate(monotonic_time);
}
- virtual void Layout() OVERRIDE {
- test_hooks_->Layout();
- }
+ virtual void Layout() OVERRIDE { test_hooks_->Layout(); }
- virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta,
+ virtual void ApplyScrollAndScale(const gfx::Vector2d& scroll_delta,
float scale) OVERRIDE {
test_hooks_->ApplyScrollAndScale(scroll_delta, scale);
}
return test_hooks_->CreateOutputSurface(fallback);
}
- virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
- test_hooks_->DidInitializeOutputSurface(succeeded);
+ virtual void DidInitializeOutputSurface() OVERRIDE {
+ test_hooks_->DidInitializeOutputSurface();
}
virtual void DidFailToInitializeOutputSurface() OVERRIDE {
virtual void WillCommit() OVERRIDE { test_hooks_->WillCommit(); }
- virtual void DidCommit() OVERRIDE {
- test_hooks_->DidCommit();
- }
+ virtual void DidCommit() OVERRIDE { test_hooks_->DidCommit(); }
virtual void DidCommitAndDrawFrame() OVERRIDE {
test_hooks_->DidCommitAndDrawFrame();
test_hooks_->ScheduleComposite();
}
- virtual scoped_refptr<ContextProvider> OffscreenContextProvider() OVERRIDE {
- return test_hooks_->OffscreenContextProvider();
+ virtual void ScheduleAnimation() OVERRIDE {
+ test_hooks_->ScheduleAnimation();
}
+ virtual void DidPostSwapBuffers() OVERRIDE {}
+ virtual void DidAbortSwapBuffers() OVERRIDE {}
+
private:
explicit LayerTreeHostClientForTesting(TestHooks* test_hooks)
: test_hooks_(test_hooks) {}
TestHooks* test_hooks_;
};
+// Adapts LayerTreeHost for test. Injects LayerTreeHostImplForTesting.
+class LayerTreeHostForTesting : public LayerTreeHost {
+ public:
+ static scoped_ptr<LayerTreeHostForTesting> Create(
+ TestHooks* test_hooks,
+ LayerTreeHostClientForTesting* client,
+ const LayerTreeSettings& settings,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
+ scoped_ptr<LayerTreeHostForTesting> layer_tree_host(
+ new LayerTreeHostForTesting(test_hooks, client, settings));
+ if (impl_task_runner.get()) {
+ layer_tree_host->InitializeForTesting(
+ ThreadProxyForTest::Create(test_hooks,
+ layer_tree_host.get(),
+ main_task_runner,
+ impl_task_runner));
+ } else {
+ layer_tree_host->InitializeForTesting(SingleThreadProxy::Create(
+ layer_tree_host.get(), client, main_task_runner));
+ }
+ return layer_tree_host.Pass();
+ }
+
+ virtual scoped_ptr<LayerTreeHostImpl> CreateLayerTreeHostImpl(
+ LayerTreeHostImplClient* host_impl_client) OVERRIDE {
+ return LayerTreeHostImplForTesting::Create(
+ test_hooks_,
+ settings(),
+ host_impl_client,
+ proxy(),
+ shared_bitmap_manager_.get(),
+ rendering_stats_instrumentation()).PassAs<LayerTreeHostImpl>();
+ }
+
+ virtual void SetNeedsCommit() OVERRIDE {
+ if (!test_started_)
+ return;
+ LayerTreeHost::SetNeedsCommit();
+ }
+
+ void set_test_started(bool started) { test_started_ = started; }
+
+ virtual void DidDeferCommit() OVERRIDE { test_hooks_->DidDeferCommit(); }
+
+ private:
+ LayerTreeHostForTesting(TestHooks* test_hooks,
+ LayerTreeHostClient* client,
+ const LayerTreeSettings& settings)
+ : LayerTreeHost(client, NULL, settings),
+ shared_bitmap_manager_(new TestSharedBitmapManager()),
+ test_hooks_(test_hooks),
+ test_started_(false) {}
+
+ scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
+ TestHooks* test_hooks_;
+ bool test_started_;
+};
+
LayerTreeTest::LayerTreeTest()
: beginning_(false),
end_when_begin_returns_(false),
}
void LayerTreeTest::EndTestAfterDelay(int delay_milliseconds) {
- main_task_runner_->PostTask(
- FROM_HERE, base::Bind(&LayerTreeTest::EndTest, main_thread_weak_ptr_));
+ main_task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&LayerTreeTest::EndTest, main_thread_weak_ptr_),
+ base::TimeDelta::FromMilliseconds(delay_milliseconds));
}
void LayerTreeTest::PostAddAnimationToMainThread(
FROM_HERE,
base::Bind(&LayerTreeTest::DispatchAddAnimation,
main_thread_weak_ptr_,
- base::Unretained(layer_to_receive_animation)));
+ base::Unretained(layer_to_receive_animation),
+ 0.000001));
}
void LayerTreeTest::PostAddInstantAnimationToMainThread(
Layer* layer_to_receive_animation) {
main_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&LayerTreeTest::DispatchAddInstantAnimation,
+ base::Bind(&LayerTreeTest::DispatchAddAnimation,
+ main_thread_weak_ptr_,
+ base::Unretained(layer_to_receive_animation),
+ 0.0));
+}
+
+void LayerTreeTest::PostAddLongAnimationToMainThread(
+ Layer* layer_to_receive_animation) {
+ main_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&LayerTreeTest::DispatchAddAnimation,
main_thread_weak_ptr_,
- base::Unretained(layer_to_receive_animation)));
+ base::Unretained(layer_to_receive_animation),
+ 1.0));
}
void LayerTreeTest::PostSetNeedsCommitToMainThread() {
main_thread_weak_ptr_));
}
-void LayerTreeTest::PostReadbackToMainThread() {
- main_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&LayerTreeTest::DispatchReadback, main_thread_weak_ptr_));
-}
-
-void LayerTreeTest::PostAcquireLayerTextures() {
+void LayerTreeTest::PostSetNeedsUpdateLayersToMainThread() {
main_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&LayerTreeTest::DispatchAcquireLayerTextures,
+ base::Bind(&LayerTreeTest::DispatchSetNeedsUpdateLayers,
main_thread_weak_ptr_));
}
main_thread_weak_ptr_));
}
-void LayerTreeTest::PostSetNeedsRedrawRectToMainThread(gfx::Rect damage_rect) {
+void LayerTreeTest::PostSetNeedsRedrawRectToMainThread(
+ const gfx::Rect& damage_rect) {
main_task_runner_->PostTask(
FROM_HERE,
base::Bind(&LayerTreeTest::DispatchSetNeedsRedrawRect,
main_thread_weak_ptr_));
}
+void LayerTreeTest::WillBeginTest() {
+ layer_tree_host_->SetLayerTreeHostClientReady();
+}
+
void LayerTreeTest::DoBeginTest() {
client_ = LayerTreeHostClientForTesting::Create(this);
this,
client_.get(),
settings_,
+ base::MessageLoopProxy::current(),
impl_thread_ ? impl_thread_->message_loop_proxy() : NULL);
ASSERT_TRUE(layer_tree_host_);
started_ = true;
beginning_ = true;
SetupTree();
- layer_tree_host_->SetLayerTreeHostClientReady();
+ WillBeginTest();
BeginTest();
beginning_ = false;
if (end_when_begin_returns_)
// Allow commits to happen once BeginTest() has had a chance to post tasks
// so that those tasks will happen before the first commit.
if (layer_tree_host_) {
- static_cast<LayerTreeHostForTesting*>(layer_tree_host_.get())->
- set_test_started(true);
+ static_cast<LayerTreeHostForTesting*>(layer_tree_host_.get())
+ ->set_test_started(true);
}
}
void LayerTreeTest::SetupTree() {
if (!layer_tree_host_->root_layer()) {
scoped_refptr<Layer> root_layer = Layer::Create();
- root_layer->SetAnchorPoint(gfx::PointF());
root_layer->SetBounds(gfx::Size(1, 1));
root_layer->SetIsDrawable(true);
layer_tree_host_->SetRootLayer(root_layer);
}
void LayerTreeTest::RealEndTest() {
- if (layer_tree_host_ && proxy()->CommitPendingForTesting()) {
+ if (layer_tree_host_ && !timed_out_ &&
+ proxy()->MainFrameWillHappenForTesting()) {
main_task_runner_->PostTask(
FROM_HERE,
base::Bind(&LayerTreeTest::RealEndTest, main_thread_weak_ptr_));
base::MessageLoop::current()->Quit();
}
-void LayerTreeTest::DispatchAddInstantAnimation(
- Layer* layer_to_receive_animation) {
- DCHECK(!proxy() || proxy()->IsMainThread());
-
- if (layer_to_receive_animation) {
- AddOpacityTransitionToLayer(layer_to_receive_animation,
- 0,
- 0,
- 0.5,
- false);
- }
-}
-
-void LayerTreeTest::DispatchAddAnimation(Layer* layer_to_receive_animation) {
+void LayerTreeTest::DispatchAddAnimation(Layer* layer_to_receive_animation,
+ double animation_duration) {
DCHECK(!proxy() || proxy()->IsMainThread());
if (layer_to_receive_animation) {
- AddOpacityTransitionToLayer(layer_to_receive_animation,
- 0.000001,
- 0,
- 0.5,
- true);
+ AddOpacityTransitionToLayer(
+ layer_to_receive_animation, animation_duration, 0, 0.5, true);
}
}
layer_tree_host_->SetNeedsCommit();
}
-void LayerTreeTest::DispatchReadback() {
- DCHECK(!proxy() || proxy()->IsMainThread());
-
- if (layer_tree_host_) {
- char pixels[4];
- layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(0, 0, 1, 1));
- }
-}
-
-void LayerTreeTest::DispatchAcquireLayerTextures() {
+void LayerTreeTest::DispatchSetNeedsUpdateLayers() {
DCHECK(!proxy() || proxy()->IsMainThread());
if (layer_tree_host_)
- layer_tree_host_->AcquireLayerTextures();
+ layer_tree_host_->SetNeedsUpdateLayers();
}
void LayerTreeTest::DispatchSetNeedsRedraw() {
layer_tree_host_->SetNeedsRedraw();
}
-void LayerTreeTest::DispatchSetNeedsRedrawRect(gfx::Rect damage_rect) {
+void LayerTreeTest::DispatchSetNeedsRedrawRect(const gfx::Rect& damage_rect) {
DCHECK(!proxy() || proxy()->IsMainThread());
if (layer_tree_host_)
delegating_renderer_ = delegating_renderer;
- // Spend less time waiting for BeginImplFrame because the output is
+ // Spend less time waiting for BeginFrame because the output is
// mocked out.
settings_.refresh_rate = 200.0;
if (impl_side_painting) {
- DCHECK(threaded) <<
- "Don't run single thread + impl side painting, it doesn't exist.";
+ DCHECK(threaded)
+ << "Don't run single thread + impl side painting, it doesn't exist.";
settings_.impl_side_painting = true;
}
InitializeSettings(&settings_);
}
base::MessageLoop::current()->Run();
- if (layer_tree_host_ && layer_tree_host_->root_layer())
- layer_tree_host_->root_layer()->SetLayerTreeHost(NULL);
- layer_tree_host_.reset();
+ DestroyLayerTreeHost();
timeout_.Cancel();
}
scoped_ptr<OutputSurface> LayerTreeTest::CreateOutputSurface(bool fallback) {
- scoped_ptr<FakeOutputSurface> output_surface;
- if (delegating_renderer_)
- output_surface = FakeOutputSurface::CreateDelegating3d();
- else
- output_surface = FakeOutputSurface::Create3d();
+ scoped_ptr<FakeOutputSurface> output_surface =
+ CreateFakeOutputSurface(fallback);
+ if (output_surface) {
+ DCHECK_EQ(delegating_renderer_,
+ output_surface->capabilities().delegated_rendering);
+ }
output_surface_ = output_surface.get();
return output_surface.PassAs<OutputSurface>();
}
-scoped_refptr<ContextProvider> LayerTreeTest::OffscreenContextProvider() {
- if (!compositor_contexts_.get() ||
- compositor_contexts_->DestroyedOnMainThread())
- compositor_contexts_ = TestContextProvider::Create();
- return compositor_contexts_;
+scoped_ptr<FakeOutputSurface> LayerTreeTest::CreateFakeOutputSurface(
+ bool fallback) {
+ if (delegating_renderer_)
+ return FakeOutputSurface::CreateDelegating3d();
+ else
+ return FakeOutputSurface::Create3d();
+}
+
+TestWebGraphicsContext3D* LayerTreeTest::TestContext() {
+ return static_cast<TestContextProvider*>(
+ output_surface_->context_provider().get())->TestContext3d();
+}
+
+int LayerTreeTest::LastCommittedSourceFrameNumber(LayerTreeHostImpl* impl)
+ const {
+ if (impl->pending_tree())
+ return impl->pending_tree()->source_frame_number();
+ if (impl->active_tree())
+ return impl->active_tree()->source_frame_number();
+ // Source frames start at 0, so this is invalid.
+ return -1;
+}
+
+void LayerTreeTest::DestroyLayerTreeHost() {
+ if (layer_tree_host_ && layer_tree_host_->root_layer())
+ layer_tree_host_->root_layer()->SetLayerTreeHost(NULL);
+ layer_tree_host_.reset();
}
} // namespace cc