// Copyright 2011 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. #ifndef CC_TEST_LAYER_TREE_TEST_H_ #define CC_TEST_LAYER_TREE_TEST_H_ #include "base/memory/ref_counted.h" #include "base/threading/thread.h" #include "cc/animation/animation_delegate.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_host_impl.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { class FakeExternalBeginFrameSource; class FakeLayerTreeHostClient; class FakeOutputSurface; class LayerImpl; class LayerTreeHost; class LayerTreeHostClient; class LayerTreeHostImpl; class TestContextProvider; class TestGpuMemoryBufferManager; class TestWebGraphicsContext3D; // Used by test stubs to notify the test when something interesting happens. class TestHooks : public AnimationDelegate { public: TestHooks(); ~TestHooks() override; void ReadSettings(const LayerTreeSettings& settings); virtual void CreateResourceAndTileTaskWorkerPool( LayerTreeHostImpl* host_impl, scoped_ptr* tile_task_worker_pool, scoped_ptr* resource_pool, scoped_ptr* staging_resource_pool); virtual void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl, const BeginFrameArgs& args) {} virtual void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl, CommitEarlyOutReason reason) {} virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) {} virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) {} virtual void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) {} virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) {} virtual void InitializedRendererOnThread(LayerTreeHostImpl* host_impl, bool success) {} virtual DrawResult PrepareToDrawOnThread( LayerTreeHostImpl* host_impl, LayerTreeHostImpl::FrameData* frame_data, DrawResult draw_result); virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) {} virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) {} virtual void SwapBuffersCompleteOnThread(LayerTreeHostImpl* host_impl) {} virtual void NotifyReadyToActivateOnThread(LayerTreeHostImpl* host_impl) {} virtual void NotifyReadyToDrawOnThread(LayerTreeHostImpl* host_impl) {} virtual void NotifyTileStateChangedOnThread(LayerTreeHostImpl* host_impl, const Tile* tile) {} virtual void AnimateLayers(LayerTreeHostImpl* host_impl, base::TimeTicks monotonic_time) {} virtual void UpdateAnimationState(LayerTreeHostImpl* host_impl, bool has_unfinished_animation) {} virtual void WillAnimateLayers(LayerTreeHostImpl* host_impl, base::TimeTicks monotonic_time) {} virtual void ApplyViewportDeltas( const gfx::Vector2dF& inner_delta, const gfx::Vector2dF& outer_delta, const gfx::Vector2dF& elastic_overscroll_delta, float scale, float top_controls_delta) {} virtual void ApplyViewportDeltas(const gfx::Vector2d& scroll_delta, float scale, float top_controls_delta) {} virtual void BeginMainFrame(const BeginFrameArgs& args) {} virtual void WillBeginMainFrame() {} virtual void DidBeginMainFrame() {} virtual void Layout() {} virtual void DidInitializeOutputSurface() {} virtual void DidFailToInitializeOutputSurface() {} virtual void DidAddAnimation() {} virtual void WillCommit() {} virtual void DidCommit() {} virtual void DidCommitAndDrawFrame() {} virtual void DidCompleteSwapBuffers() {} virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* host_impl, bool visible) {} virtual void ScheduleComposite() {} virtual void SendBeginFramesToChildren(const BeginFrameArgs& args) {} // Hooks for SchedulerClient. virtual void WillBeginImplFrame(const BeginFrameArgs& args) {} virtual void ScheduledActionWillSendBeginMainFrame() {} virtual void ScheduledActionSendBeginMainFrame() {} virtual void ScheduledActionDrawAndSwapIfPossible() {} virtual void ScheduledActionAnimate() {} virtual void ScheduledActionCommit() {} virtual void ScheduledActionBeginOutputSurfaceCreation() {} virtual void ScheduledActionPrepareTiles() {} virtual void ScheduledActionInvalidateOutputSurface() {} // Implementation of AnimationDelegate: void NotifyAnimationStarted(base::TimeTicks monotonic_time, Animation::TargetProperty target_property, int group) override {} void NotifyAnimationFinished(base::TimeTicks monotonic_time, Animation::TargetProperty target_property, int group) override {} virtual void RequestNewOutputSurface() = 0; }; class BeginTask; class LayerTreeHostClientForTesting; class TimeoutTask; // The LayerTreeTests runs with the main loop running. It instantiates a single // LayerTreeHostForTesting and associated LayerTreeHostImplForTesting and // LayerTreeHostClientForTesting. // // BeginTest() is called once the main message loop is running and the layer // tree host is initialized. // // Key stages of the drawing loop, e.g. drawing or commiting, redirect to // LayerTreeTest methods of similar names. To track the commit process, override // these functions. // // The test continues until someone calls EndTest. EndTest can be called on any // thread, but be aware that ending the test is an asynchronous process. class LayerTreeTest : public testing::Test, public TestHooks { public: ~LayerTreeTest() override; virtual void EndTest(); void EndTestAfterDelayMs(int delay_milliseconds); void PostAddAnimationToMainThread(Layer* layer_to_receive_animation); void PostAddInstantAnimationToMainThread(Layer* layer_to_receive_animation); void PostAddLongAnimationToMainThread(Layer* layer_to_receive_animation); void PostSetDeferCommitsToMainThread(bool defer_commits); void PostSetNeedsCommitToMainThread(); void PostSetNeedsUpdateLayersToMainThread(); void PostSetNeedsRedrawToMainThread(); void PostSetNeedsRedrawRectToMainThread(const gfx::Rect& damage_rect); void PostSetVisibleToMainThread(bool visible); void PostSetNextCommitForcesRedrawToMainThread(); void PostCompositeImmediatelyToMainThread(); void DoBeginTest(); void Timeout(); bool verify_property_trees() const { return verify_property_trees_; } void set_verify_property_trees(bool verify_property_trees) { verify_property_trees_ = verify_property_trees; } protected: LayerTreeTest(); virtual void InitializeSettings(LayerTreeSettings* settings) {} void RealEndTest(); virtual void DispatchAddAnimation(Layer* layer_to_receive_animation, double animation_duration); void DispatchSetDeferCommits(bool defer_commits); void DispatchSetNeedsCommit(); void DispatchSetNeedsUpdateLayers(); void DispatchSetNeedsRedraw(); void DispatchSetNeedsRedrawRect(const gfx::Rect& damage_rect); void DispatchSetVisible(bool visible); void DispatchSetNextCommitForcesRedraw(); void DispatchDidAddAnimation(); void DispatchCompositeImmediately(); virtual void AfterTest() = 0; virtual void WillBeginTest(); virtual void BeginTest() = 0; virtual void SetupTree(); virtual void RunTest(bool threaded, bool delegating_renderer, bool impl_side_painting); virtual void RunTestWithImplSidePainting(); bool HasImplThread() { return proxy() ? proxy()->HasImplThread() : false; } base::SingleThreadTaskRunner* ImplThreadTaskRunner() { DCHECK(proxy()); return proxy()->ImplThreadTaskRunner() ? proxy()->ImplThreadTaskRunner() : main_task_runner_.get(); } base::SingleThreadTaskRunner* MainThreadTaskRunner() { return main_task_runner_.get(); } Proxy* proxy() const { return layer_tree_host_ ? layer_tree_host_->proxy() : NULL; } TaskGraphRunner* task_graph_runner() const { return task_graph_runner_.get(); } bool TestEnded() const { return ended_; } LayerTreeHost* layer_tree_host(); bool delegating_renderer() const { return delegating_renderer_; } FakeOutputSurface* output_surface() { return output_surface_; } int LastCommittedSourceFrameNumber(LayerTreeHostImpl* impl) const; void DestroyLayerTreeHost(); // By default, output surface recreation is synchronous. void RequestNewOutputSurface() override; // Override this for pixel tests, where you need a real output surface. virtual scoped_ptr CreateOutputSurface(); // Override this for unit tests, which should not produce pixel output. virtual scoped_ptr CreateFakeOutputSurface(); TestWebGraphicsContext3D* TestContext(); private: LayerTreeSettings settings_; scoped_ptr client_; scoped_ptr layer_tree_host_; FakeOutputSurface* output_surface_; FakeExternalBeginFrameSource* external_begin_frame_source_; bool beginning_; bool end_when_begin_returns_; bool timed_out_; bool scheduled_; bool started_; bool ended_; bool delegating_renderer_; bool verify_property_trees_; int timeout_seconds_; scoped_refptr main_task_runner_; scoped_ptr impl_thread_; scoped_ptr shared_bitmap_manager_; scoped_ptr gpu_memory_buffer_manager_; scoped_ptr task_graph_runner_; base::CancelableClosure timeout_; scoped_refptr compositor_contexts_; base::WeakPtr main_thread_weak_ptr_; base::WeakPtrFactory weak_factory_; }; } // namespace cc #define SINGLE_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME) \ TEST_F(TEST_FIXTURE_NAME, RunSingleThread_DirectRenderer_MainThreadPaint) { \ RunTest(false, false, false); \ } \ class SingleThreadDirectNoImplNeedsSemicolon##TEST_FIXTURE_NAME {} #define SINGLE_THREAD_DIRECT_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) \ TEST_F(TEST_FIXTURE_NAME, RunSingleThread_DirectRenderer_ImplSidePaint) { \ RunTest(false, false, true); \ } \ class SingleThreadDirectImplNeedsSemicolon##TEST_FIXTURE_NAME {} #define SINGLE_THREAD_DIRECT_RENDERER_TEST_F(TEST_FIXTURE_NAME) \ SINGLE_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME); \ SINGLE_THREAD_DIRECT_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) #define SINGLE_THREAD_DELEGATING_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME) \ TEST_F(TEST_FIXTURE_NAME, \ RunSingleThread_DelegatingRenderer_MainThreadPaint) { \ RunTest(false, true, false); \ } \ class SingleThreadDelegatingNoImplNeedsSemicolon##TEST_FIXTURE_NAME {} #define SINGLE_THREAD_DELEGATING_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) \ TEST_F(TEST_FIXTURE_NAME, \ RunSingleThread_DelegatingRenderer_ImplSidePaint) { \ RunTest(false, true, true); \ } \ class SingleThreadDelegatingImplNeedsSemicolon##TEST_FIXTURE_NAME {} #define SINGLE_THREAD_DELEGATING_RENDERER_TEST_F(TEST_FIXTURE_NAME) \ SINGLE_THREAD_DELEGATING_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME); \ SINGLE_THREAD_DELEGATING_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) #define SINGLE_THREAD_NOIMPL_TEST_F(TEST_FIXTURE_NAME) \ SINGLE_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME); \ SINGLE_THREAD_DELEGATING_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME) #define SINGLE_THREAD_IMPL_TEST_F(TEST_FIXTURE_NAME) \ SINGLE_THREAD_DIRECT_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME); \ SINGLE_THREAD_DELEGATING_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) #define SINGLE_THREAD_TEST_F(TEST_FIXTURE_NAME) \ SINGLE_THREAD_DIRECT_RENDERER_TEST_F(TEST_FIXTURE_NAME); \ SINGLE_THREAD_DELEGATING_RENDERER_TEST_F(TEST_FIXTURE_NAME) #define MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME) \ TEST_F(TEST_FIXTURE_NAME, RunMultiThread_DirectRenderer_MainThreadPaint) { \ RunTest(true, false, false); \ } \ class MultiThreadDirectNoImplNeedsSemicolon##TEST_FIXTURE_NAME {} #define MULTI_THREAD_DIRECT_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) \ TEST_F(TEST_FIXTURE_NAME, RunMultiThread_DirectRenderer_ImplSidePaint) { \ RunTest(true, false, true); \ } \ class MultiThreadDirectImplNeedsSemicolon##TEST_FIXTURE_NAME {} #define MULTI_THREAD_DIRECT_RENDERER_TEST_F(TEST_FIXTURE_NAME) \ MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME); \ MULTI_THREAD_DIRECT_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) #define MULTI_THREAD_DELEGATING_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME) \ TEST_F(TEST_FIXTURE_NAME, \ RunMultiThread_DelegatingRenderer_MainThreadPaint) { \ RunTest(true, true, false); \ } \ class MultiThreadDelegatingNoImplNeedsSemicolon##TEST_FIXTURE_NAME {} #define MULTI_THREAD_DELEGATING_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) \ TEST_F(TEST_FIXTURE_NAME, RunMultiThread_DelegatingRenderer_ImplSidePaint) { \ RunTest(true, true, true); \ } \ class MultiThreadDelegatingImplNeedsSemicolon##TEST_FIXTURE_NAME {} #define MULTI_THREAD_DELEGATING_RENDERER_TEST_F(TEST_FIXTURE_NAME) \ MULTI_THREAD_DELEGATING_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME); \ MULTI_THREAD_DELEGATING_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) #define MULTI_THREAD_NOIMPL_TEST_F(TEST_FIXTURE_NAME) \ MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME); \ MULTI_THREAD_DELEGATING_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME) #define MULTI_THREAD_IMPL_TEST_F(TEST_FIXTURE_NAME) \ MULTI_THREAD_DIRECT_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME); \ MULTI_THREAD_DELEGATING_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) #define MULTI_THREAD_TEST_F(TEST_FIXTURE_NAME) \ MULTI_THREAD_DIRECT_RENDERER_TEST_F(TEST_FIXTURE_NAME); \ MULTI_THREAD_DELEGATING_RENDERER_TEST_F(TEST_FIXTURE_NAME) #define SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F( \ TEST_FIXTURE_NAME) \ SINGLE_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME); \ MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME) #define SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) \ SINGLE_THREAD_DIRECT_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME); \ MULTI_THREAD_DIRECT_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) #define SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TEST_FIXTURE_NAME) \ SINGLE_THREAD_DIRECT_RENDERER_TEST_F(TEST_FIXTURE_NAME); \ MULTI_THREAD_DIRECT_RENDERER_TEST_F(TEST_FIXTURE_NAME) #define SINGLE_AND_MULTI_THREAD_DELEGATING_RENDERER_NOIMPL_TEST_F( \ TEST_FIXTURE_NAME) \ SINGLE_THREAD_DELEGATING_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME); \ MULTI_THREAD_DELEGATING_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME) #define SINGLE_AND_MULTI_THREAD_DELEGATING_RENDERER_IMPL_TEST_F( \ TEST_FIXTURE_NAME) \ SINGLE_THREAD_DELEGATING_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME); \ MULTI_THREAD_DELEGATING_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) #define SINGLE_AND_MULTI_THREAD_DELEGATING_RENDERER_TEST_F(TEST_FIXTURE_NAME) \ SINGLE_THREAD_DELEGATING_RENDERER_TEST_F(TEST_FIXTURE_NAME); \ MULTI_THREAD_DELEGATING_RENDERER_TEST_F(TEST_FIXTURE_NAME) #define SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(TEST_FIXTURE_NAME) \ SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME); \ SINGLE_AND_MULTI_THREAD_DELEGATING_RENDERER_NOIMPL_TEST_F(TEST_FIXTURE_NAME) #define SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(TEST_FIXTURE_NAME) \ SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME); \ SINGLE_AND_MULTI_THREAD_DELEGATING_RENDERER_IMPL_TEST_F(TEST_FIXTURE_NAME) #define SINGLE_AND_MULTI_THREAD_TEST_F(TEST_FIXTURE_NAME) \ SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TEST_FIXTURE_NAME); \ SINGLE_AND_MULTI_THREAD_DELEGATING_RENDERER_TEST_F(TEST_FIXTURE_NAME) // Some tests want to control when notify ready for activation occurs, // but this is not supported in the single-threaded case. #define SINGLE_AND_MULTI_THREAD_BLOCKNOTIFY_TEST_F(TEST_FIXTURE_NAME) \ SINGLE_THREAD_NOIMPL_TEST_F(TEST_FIXTURE_NAME); \ MULTI_THREAD_TEST_F(TEST_FIXTURE_NAME) #endif // CC_TEST_LAYER_TREE_TEST_H_