From 6f0fdcbf68437182793bebc39f2655a171f610df Mon Sep 17 00:00:00 2001 From: "simonhong@chromium.org" Date: Thu, 22 May 2014 02:51:56 +0000 Subject: cc: Add testing stubs for proxy test This is initial patch for proxy unittests. New testing stubs are added to LayerTreeTest. R=brianderson@chromium.org, danakj@chomium.org BUG=356832 TEST=*ProxyTest* Review URL: https://codereview.chromium.org/242783003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@272051 0039d316-1c4b-4281-b951-d872f2087c98 --- cc/cc_tests.gyp | 1 + cc/test/layer_tree_test.cc | 66 ++++++++- cc/test/layer_tree_test.h | 6 + cc/trees/layer_tree_host_unittest_proxy.cc | 135 ++++++++++++++++++ cc/trees/single_thread_proxy.h | 3 +- cc/trees/thread_proxy.h | 217 +++++++++++++++-------------- 6 files changed, 318 insertions(+), 110 deletions(-) create mode 100644 cc/trees/layer_tree_host_unittest_proxy.cc (limited to 'cc') diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index b46b4e9..127bb1d 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -106,6 +106,7 @@ 'trees/layer_tree_host_unittest_delegated.cc', 'trees/layer_tree_host_unittest_occlusion.cc', 'trees/layer_tree_host_unittest_picture.cc', + 'trees/layer_tree_host_unittest_proxy.cc', 'trees/layer_tree_host_unittest_scroll.cc', 'trees/layer_tree_host_unittest_video.cc', 'trees/layer_tree_impl_unittest.cc', diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index 8a80f89..2aab75c 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc @@ -25,6 +25,7 @@ #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" @@ -46,6 +47,58 @@ 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 Create( + TestHooks* test_hooks, + LayerTreeHost* host, + scoped_refptr impl_task_runner) { + return make_scoped_ptr( + new ThreadProxyForTest(test_hooks, + host, + impl_task_runner)).PassAs(); + } + + virtual ~ThreadProxyForTest() {} + + void test() { + test_hooks_->Layout(); + } + + private: + TestHooks* test_hooks_; + + virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE { + ThreadProxy::ScheduledActionBeginOutputSurfaceCreation(); + test_hooks_->ScheduledActionBeginOutputSurfaceCreation(); + } + + virtual void ScheduledActionSendBeginMainFrame() OVERRIDE { + ThreadProxy::ScheduledActionSendBeginMainFrame(); + test_hooks_->ScheduledActionSendBeginMainFrame(); + } + + virtual void ScheduledActionCommit() OVERRIDE { + ThreadProxy::ScheduledActionCommit(); + test_hooks_->ScheduledActionCommit(); + } + + virtual DrawResult ScheduledActionDrawAndSwapIfPossible() OVERRIDE { + DrawResult result = ThreadProxy::ScheduledActionDrawAndSwapIfPossible(); + test_hooks_->ScheduledActionDrawAndSwapIfPossible(); + return result; + } + + ThreadProxyForTest( + TestHooks* test_hooks, + LayerTreeHost* host, + scoped_refptr impl_task_runner) + : ThreadProxy(host, impl_task_runner), + test_hooks_(test_hooks) { + } +}; + // Adapts LayerTreeHostImpl for test. Runs real code, then invokes test hooks. class LayerTreeHostImplForTesting : public LayerTreeHostImpl { public: @@ -285,10 +338,15 @@ class LayerTreeHostForTesting : public LayerTreeHost { scoped_refptr impl_task_runner) { scoped_ptr layer_tree_host( new LayerTreeHostForTesting(test_hooks, client, settings)); - if (impl_task_runner.get()) - layer_tree_host->InitializeThreaded(impl_task_runner); - else - layer_tree_host->InitializeSingleThreaded(client); + if (impl_task_runner.get()) { + layer_tree_host->InitializeForTesting( + ThreadProxyForTest::Create(test_hooks, + layer_tree_host.get(), + impl_task_runner)); + } else { + layer_tree_host->InitializeForTesting( + SingleThreadProxy::Create(layer_tree_host.get(), client)); + } return layer_tree_host.Pass(); } diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h index 41e27f0..2c078a1 100644 --- a/cc/test/layer_tree_test.h +++ b/cc/test/layer_tree_test.h @@ -78,6 +78,12 @@ class TestHooks : public AnimationDelegate { bool visible) {} virtual base::TimeDelta LowFrequencyAnimationInterval() const; + // Hooks for SchedulerClient. + virtual void ScheduledActionBeginOutputSurfaceCreation() {} + virtual void ScheduledActionSendBeginMainFrame() {} + virtual void ScheduledActionCommit() {} + virtual void ScheduledActionDrawAndSwapIfPossible() {} + // Implementation of AnimationDelegate: virtual void NotifyAnimationStarted(base::TimeTicks monotonic_time, Animation::TargetProperty target_property) diff --git a/cc/trees/layer_tree_host_unittest_proxy.cc b/cc/trees/layer_tree_host_unittest_proxy.cc new file mode 100644 index 0000000..4f79311 --- /dev/null +++ b/cc/trees/layer_tree_host_unittest_proxy.cc @@ -0,0 +1,135 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "cc/test/layer_tree_test.h" +#include "cc/trees/thread_proxy.h" + +#define THREAD_PROXY_NO_IMPL_TEST_F(TEST_FIXTURE_NAME) \ + TEST_F(TEST_FIXTURE_NAME, Run_MainThreadPaint) { \ + Run(true, false); \ + } + +#define THREAD_PROXY_TEST_F(TEST_FIXTURE_NAME) \ + THREAD_PROXY_NO_IMPL_TEST_F(TEST_FIXTURE_NAME); \ + TEST_F(TEST_FIXTURE_NAME, Run_ImplSidePaint) { \ + Run(true, true); \ + } + +// Do common tests for single thread proxy and thread proxy. +// TODO(simonhong): Add SINGLE_THREAD_PROXY_TEST_F +#define PROXY_TEST_SCHEDULED_ACTION(TEST_FIXTURE_NAME) \ + THREAD_PROXY_TEST_F(TEST_FIXTURE_NAME); + +namespace cc { + +class ProxyTest : public LayerTreeTest { + protected: + ProxyTest() {} + virtual ~ProxyTest() {} + + void Run(bool threaded, bool impl_side_painting) { + // We don't need to care about delegating mode. + bool delegating_renderer = true; + + RunTest(threaded, delegating_renderer, impl_side_painting); + } + + virtual void BeginTest() OVERRIDE {} + virtual void AfterTest() OVERRIDE {} + + private: + DISALLOW_COPY_AND_ASSIGN(ProxyTest); +}; + +class ProxyTestScheduledActionsBasic : public ProxyTest { + protected: + virtual void BeginTest() OVERRIDE { + proxy()->SetNeedsCommit(); + } + + virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE { + EXPECT_EQ(0, action_phase_++); + } + + virtual void ScheduledActionSendBeginMainFrame() OVERRIDE { + EXPECT_EQ(1, action_phase_++); + } + + virtual void ScheduledActionCommit() OVERRIDE { + EXPECT_EQ(2, action_phase_++); + } + + virtual void ScheduledActionDrawAndSwapIfPossible() OVERRIDE { + EXPECT_EQ(3, action_phase_++); + EndTest(); + } + + virtual void AfterTest() OVERRIDE { + EXPECT_EQ(4, action_phase_); + } + + ProxyTestScheduledActionsBasic() : action_phase_(0) { + } + virtual ~ProxyTestScheduledActionsBasic() {} + + private: + int action_phase_; + + DISALLOW_COPY_AND_ASSIGN(ProxyTestScheduledActionsBasic); +}; + +PROXY_TEST_SCHEDULED_ACTION(ProxyTestScheduledActionsBasic); + +class ThreadProxyTest : public ProxyTest { + protected: + ThreadProxyTest() {} + virtual ~ThreadProxyTest() {} + + const ThreadProxy::MainThreadOnly& ThreadProxyMainOnly() const { + DCHECK(proxy()); + DCHECK(proxy()->HasImplThread()); + return static_cast(proxy())->main(); + } + + const ThreadProxy::CompositorThreadOnly& ThreadProxyImplOnly() const { + DCHECK(proxy()); + DCHECK(proxy()->HasImplThread()); + return static_cast(proxy())->impl(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ThreadProxyTest); +}; + +class ThreadProxyTestSetNeedsCommit : public ThreadProxyTest { + protected: + ThreadProxyTestSetNeedsCommit() {} + virtual ~ThreadProxyTestSetNeedsCommit() {} + + virtual void BeginTest() OVERRIDE { + EXPECT_FALSE(ThreadProxyMainOnly().commit_requested); + EXPECT_FALSE(ThreadProxyMainOnly().commit_request_sent_to_impl_thread); + + proxy()->SetNeedsCommit(); + + EXPECT_TRUE(ThreadProxyMainOnly().commit_requested); + EXPECT_TRUE(ThreadProxyMainOnly().commit_request_sent_to_impl_thread); + } + + virtual void DidBeginMainFrame() OVERRIDE { + EXPECT_FALSE(ThreadProxyMainOnly().commit_requested); + EXPECT_FALSE(ThreadProxyMainOnly().commit_request_sent_to_impl_thread); + + EndTest(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsCommit); +}; + +THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsCommit); + +} // namespace cc diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h index dc87f5f..5de42b5 100644 --- a/cc/trees/single_thread_proxy.h +++ b/cc/trees/single_thread_proxy.h @@ -19,7 +19,8 @@ class ContextProvider; class LayerTreeHost; class LayerTreeHostSingleThreadClient; -class SingleThreadProxy : public Proxy, LayerTreeHostImplClient { +class CC_EXPORT SingleThreadProxy : public Proxy, + NON_EXPORTED_BASE(LayerTreeHostImplClient) { public: static scoped_ptr Create( LayerTreeHost* layer_tree_host, diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h index 7af16cd..134d5c5 100644 --- a/cc/trees/thread_proxy.h +++ b/cc/trees/thread_proxy.h @@ -31,10 +31,10 @@ class ResourceUpdateQueue; class Scheduler; class ScopedThreadProxy; -class ThreadProxy : public Proxy, - LayerTreeHostImplClient, - SchedulerClient, - ResourceUpdateControllerClient { +class CC_EXPORT ThreadProxy : public Proxy, + NON_EXPORTED_BASE(LayerTreeHostImplClient), + NON_EXPORTED_BASE(SchedulerClient), + NON_EXPORTED_BASE(ResourceUpdateControllerClient) { public: static scoped_ptr Create( LayerTreeHost* layer_tree_host, @@ -42,6 +42,111 @@ class ThreadProxy : public Proxy, virtual ~ThreadProxy(); + struct BeginMainFrameAndCommitState { + BeginMainFrameAndCommitState(); + ~BeginMainFrameAndCommitState(); + + base::TimeTicks monotonic_frame_begin_time; + scoped_ptr scroll_info; + size_t memory_allocation_limit_bytes; + int memory_allocation_priority_cutoff; + bool evicted_ui_resources; + }; + + struct MainThreadOnly { + MainThreadOnly(ThreadProxy* proxy, int layer_tree_host_id); + ~MainThreadOnly(); + + const int layer_tree_host_id; + + // Set only when SetNeedsAnimate is called. + bool animate_requested; + // Set only when SetNeedsCommit is called. + bool commit_requested; + // Set by SetNeedsAnimate, SetNeedsUpdateLayers, and SetNeedsCommit. + bool commit_request_sent_to_impl_thread; + + bool started; + bool manage_tiles_pending; + bool can_cancel_commit; + bool defer_commits; + + base::CancelableClosure output_surface_creation_callback; + RendererCapabilities renderer_capabilities_main_thread_copy; + + scoped_ptr pending_deferred_commit; + base::WeakPtrFactory weak_factory; + }; + + // Accessed on the main thread, or when main thread is blocked. + struct MainThreadOrBlockedMainThread { + explicit MainThreadOrBlockedMainThread(LayerTreeHost* host); + ~MainThreadOrBlockedMainThread(); + + PrioritizedResourceManager* contents_texture_manager(); + + LayerTreeHost* layer_tree_host; + bool commit_waits_for_activation; + bool main_thread_inside_commit; + + base::TimeTicks last_monotonic_frame_begin_time; + }; + + struct ReadbackRequest; + + struct CompositorThreadOnly { + CompositorThreadOnly(ThreadProxy* proxy, int layer_tree_host_id); + ~CompositorThreadOnly(); + + const int layer_tree_host_id; + + // Copy of the main thread side contents texture manager for work + // that needs to be done on the compositor thread. + PrioritizedResourceManager* contents_texture_manager; + + scoped_ptr scheduler; + + // Set when the main thread is waiting on a + // ScheduledActionSendBeginMainFrame to be issued. + CompletionEvent* begin_main_frame_sent_completion_event; + + // Set when the main thread is waiting on a commit to complete. + CompletionEvent* commit_completion_event; + + // Set when the main thread is waiting on a pending tree activation. + CompletionEvent* completion_event_for_commit_held_on_tree_activation; + + scoped_ptr current_resource_update_controller; + + // Set when the next draw should post DidCommitAndDrawFrame to the main + // thread. + bool next_frame_is_newly_committed_frame; + + bool inside_draw; + + bool input_throttled_until_commit; + + // Set when we freeze animations to avoid checkerboarding. + bool animations_frozen_until_next_draw; + base::TimeTicks animation_time; + + // Whether a commit has been completed since the last time animations were + // ticked. If this happens, we need to animate again. + bool did_commit_after_animating; + + base::TimeTicks smoothness_takes_priority_expiration_time; + bool renew_tree_priority_pending; + + ProxyTimingHistory timing_history; + + scoped_ptr layer_tree_host_impl; + base::WeakPtrFactory weak_factory; + }; + + const MainThreadOnly& main() const; + const MainThreadOrBlockedMainThread& blocked_main() const; + const CompositorThreadOnly& impl() const; + // Proxy implementation virtual void FinishAllRendering() OVERRIDE; virtual bool IsStarted() const OVERRIDE; @@ -124,21 +229,11 @@ class ThreadProxy : public Proxy, // ResourceUpdateControllerClient implementation virtual void ReadyToFinalizeTextureUpdates() OVERRIDE; - private: + protected: ThreadProxy(LayerTreeHost* layer_tree_host, scoped_refptr impl_task_runner); - struct BeginMainFrameAndCommitState { - BeginMainFrameAndCommitState(); - ~BeginMainFrameAndCommitState(); - - base::TimeTicks monotonic_frame_begin_time; - scoped_ptr scroll_info; - size_t memory_allocation_limit_bytes; - int memory_allocation_priority_cutoff; - bool evicted_ui_resources; - }; - + private: // Called on main thread. void SetRendererCapabilitiesMainThreadCopy( const RendererCapabilities& capabilities); @@ -166,7 +261,7 @@ class ThreadProxy : public Proxy, void HasInitializedOutputSurfaceOnImplThread( CompletionEvent* completion, bool* has_initialized_output_surface); - void InitializeOutputSurfaceOnImplThread( + virtual void InitializeOutputSurfaceOnImplThread( CompletionEvent* completion, scoped_ptr output_surface, bool* success, @@ -189,105 +284,17 @@ class ThreadProxy : public Proxy, LayerTreeHost* layer_tree_host(); const LayerTreeHost* layer_tree_host() const; - struct MainThreadOnly { - MainThreadOnly(ThreadProxy* proxy, int layer_tree_host_id); - ~MainThreadOnly(); - - const int layer_tree_host_id; - - // Set only when SetNeedsAnimate is called. - bool animate_requested; - // Set only when SetNeedsCommit is called. - bool commit_requested; - // Set by SetNeedsAnimate, SetNeedsUpdateLayers, and SetNeedsCommit. - bool commit_request_sent_to_impl_thread; - - bool started; - bool manage_tiles_pending; - bool can_cancel_commit; - bool defer_commits; - - base::CancelableClosure output_surface_creation_callback; - RendererCapabilities renderer_capabilities_main_thread_copy; - - scoped_ptr pending_deferred_commit; - base::WeakPtrFactory weak_factory; - }; // Use accessors instead of this variable directly. MainThreadOnly main_thread_only_vars_unsafe_; MainThreadOnly& main(); - const MainThreadOnly& main() const; - // Accessed on the main thread, or when main thread is blocked. - struct MainThreadOrBlockedMainThread { - explicit MainThreadOrBlockedMainThread(LayerTreeHost* host); - ~MainThreadOrBlockedMainThread(); - - PrioritizedResourceManager* contents_texture_manager(); - - LayerTreeHost* layer_tree_host; - bool commit_waits_for_activation; - bool main_thread_inside_commit; - - base::TimeTicks last_monotonic_frame_begin_time; - }; // Use accessors instead of this variable directly. MainThreadOrBlockedMainThread main_thread_or_blocked_vars_unsafe_; MainThreadOrBlockedMainThread& blocked_main(); - const MainThreadOrBlockedMainThread& blocked_main() const; - - struct CompositorThreadOnly { - CompositorThreadOnly(ThreadProxy* proxy, int layer_tree_host_id); - ~CompositorThreadOnly(); - - const int layer_tree_host_id; - - // Copy of the main thread side contents texture manager for work - // that needs to be done on the compositor thread. - PrioritizedResourceManager* contents_texture_manager; - - scoped_ptr scheduler; - - // Set when the main thread is waiting on a - // ScheduledActionSendBeginMainFrame to be issued. - CompletionEvent* begin_main_frame_sent_completion_event; - - // Set when the main thread is waiting on a commit to complete. - CompletionEvent* commit_completion_event; - - // Set when the main thread is waiting on a pending tree activation. - CompletionEvent* completion_event_for_commit_held_on_tree_activation; - - scoped_ptr current_resource_update_controller; - // Set when the next draw should post DidCommitAndDrawFrame to the main - // thread. - bool next_frame_is_newly_committed_frame; - - bool inside_draw; - - bool input_throttled_until_commit; - - // Set when we freeze animations to avoid checkerboarding. - bool animations_frozen_until_next_draw; - base::TimeTicks animation_time; - - // Whether a commit has been completed since the last time animations were - // ticked. If this happens, we need to animate again. - bool did_commit_after_animating; - - base::TimeTicks smoothness_takes_priority_expiration_time; - bool renew_tree_priority_pending; - - ProxyTimingHistory timing_history; - - scoped_ptr layer_tree_host_impl; - base::WeakPtrFactory weak_factory; - }; // Use accessors instead of this variable directly. CompositorThreadOnly compositor_thread_vars_unsafe_; CompositorThreadOnly& impl(); - const CompositorThreadOnly& impl() const; base::WeakPtr main_thread_weak_ptr_; base::WeakPtr impl_thread_weak_ptr_; -- cgit v1.1