#ifndef CC_TREES_LAYER_TREE_HOST_IMPL_TEST_BASE_H_
#define CC_TREES_LAYER_TREE_HOST_IMPL_TEST_BASE_H_
#include <memory>
#include <utility>
#include <vector>
#include "base/task/single_thread_task_runner.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "cc/animation/animation_host.h"
#include "cc/animation/animation_timeline.h"
#include "cc/input/input_handler.h"
#include "cc/layers/layer_impl.h"
#include "cc/test/fake_impl_task_runner_provider.h"
#include "cc/test/fake_layer_tree_frame_sink.h"
#include "cc/test/fake_rendering_stats_instrumentation.h"
#include "cc/test/layer_test_common.h"
#include "cc/test/property_tree_test_utils.h"
#include "cc/test/test_task_graph_runner.h"
#include "cc/trees/frame_data.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_host_impl_client.h"
#include "cc/trees/layer_tree_impl.h"
#include "components/viz/common/quads/compositor_render_pass.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
class PaintedScrollbarLayerImpl;
class SolidColorScrollbarLayerImpl;
constexpr gfx::Size kDefaultLayerSize(100, 100);
struct TestFrameData : public FrameData {
TestFrameData();
~TestFrameData();
};
class DidDrawCheckLayer : public LayerImpl {
public:
static std::unique_ptr<DidDrawCheckLayer> Create(LayerTreeImpl* tree_impl,
int id);
bool WillDraw(DrawMode draw_mode,
viz::ClientResourceProvider* provider) override;
void AppendQuads(const AppendQuadsContext& context,
viz::CompositorRenderPass* render_pass,
AppendQuadsData* append_quads_data) override;
void DidDraw(viz::ClientResourceProvider* provider) override;
bool will_draw_returned_true() const { return will_draw_returned_true_; }
bool append_quads_called() const { return append_quads_called_; }
bool did_draw_called() const { return did_draw_called_; }
void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
void ClearDidDrawCheck();
protected:
DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id);
private:
bool will_draw_returns_false_;
bool will_draw_returned_true_;
bool append_quads_called_;
bool did_draw_called_;
};
class LayerTreeHostImplTestBase : public testing::Test,
public LayerTreeHostImplClient {
public:
LayerTreeHostImplTestBase();
~LayerTreeHostImplTestBase() override;
virtual LayerTreeSettings DefaultSettings();
LayerTreeSettings LegacySWSettings();
void SetUp() override;
void TearDown() override;
void EnsureSyncTree();
void CreatePendingTree();
void DidLoseLayerTreeFrameSinkOnImplThread() override;
void SetBeginFrameSource(viz::BeginFrameSource* source) override;
void DidReceiveCompositorFrameAckOnImplThread() override;
void OnCanDrawStateChanged(bool can_draw) override;
void NotifyReadyToActivate() override;
bool IsReadyToActivate() override;
void NotifyReadyToDraw() override;
void SetNeedsRedrawOnImplThread() override;
void SetNeedsOneBeginImplFrameOnImplThread() override;
void SetNeedsPrepareTilesOnImplThread() override;
void SetNeedsCommitOnImplThread(bool urgent) override;
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
void DidChangeBeginFrameSourcePaused(bool paused) override;
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override;
#if BUILDFLAG(ARKWEB_WEBGL)
void SetDeferInvalidationForFastMainFrameFromImpl(
bool defer_invalidation_for_fast_main_frame) override;
#endif
bool IsInsideDraw() override;
void RenewTreePriority() override;
void PostDelayedAnimationTaskOnImplThread(base::OnceClosure task,
base::TimeDelta delay) override;
void DidActivateSyncTree() override;
void DidPrepareTiles() override;
void DidCompletePageScaleAnimationOnImplThread() override;
void OnDrawForLayerTreeFrameSink(bool resourceless_software_draw,
bool skip_draw) override;
void SetNeedsImplSideInvalidation(
bool needs_first_draw_on_activation) override;
void NotifyImageDecodeRequestFinished(int request_id,
bool speculative,
bool decode_succeeded) override;
void DidPresentCompositorFrameOnImplThread(
uint32_t frame_token,
PresentationTimeCallbackBuffer::PendingCallbacks activated,
const viz::FrameTimingDetails& details) override;
void NotifyAnimationWorkletStateChange(AnimationWorkletMutationState state,
ElementListType tree_type) override;
void NotifyPaintWorkletStateChange(
Scheduler::PaintWorkletState state) override;
void NotifyCompositorMetricsTrackerResults(
CustomTrackerResults results) override;
void DidObserveFirstScrollDelay(
int source_frame_number,
base::TimeDelta first_scroll_delay,
base::TimeTicks first_scroll_timestamp) override;
bool IsInSynchronousComposite() const override;
void FrameSinksToThrottleUpdated(
const base::flat_set<viz::FrameSinkId>& ids) override;
void ClearHistory() override;
void SetHasActiveThreadedScroll(bool is_scrolling) override;
void SetWaitingForScrollEvent(bool waiting_for_scroll_event) override;
size_t CommitDurationSampleCountForTesting() const override;
void NotifyTransitionRequestFinished(
uint32_t sequence_id,
const viz::ViewTransitionElementResourceRects&) override;
void set_reduce_memory_result(bool reduce_memory_result) {
reduce_memory_result_ = reduce_memory_result;
}
AnimationHost* GetImplAnimationHost() const;
virtual bool CreateHostImpl(
const LayerTreeSettings& settings,
std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink);
template <typename T, typename... Args>
T* SetupRootLayer(LayerTreeImpl* layer_tree_impl,
const gfx::Size& viewport_size,
Args&&... args) {
const int kRootLayerId = 1;
DCHECK(!layer_tree_impl->root_layer());
DCHECK(!layer_tree_impl->LayerById(kRootLayerId));
layer_tree_impl->SetRootLayerForTesting(
T::Create(layer_tree_impl, kRootLayerId, std::forward<Args>(args)...));
auto* root = layer_tree_impl->root_layer();
root->SetBounds(viewport_size);
layer_tree_impl->SetDeviceViewportRect(
gfx::Rect(DipSizeToPixelSize(viewport_size)));
SetupRootProperties(root);
return static_cast<T*>(root);
}
LayerImpl* SetupDefaultRootLayer(
const gfx::Size& viewport_size = kDefaultLayerSize);
LayerImpl* root_layer();
gfx::Size DipSizeToPixelSize(const gfx::Size& size);
void PushScrollOffsetsToPendingTree(
const base::flat_map<ElementId, gfx::PointF>& offsets);
void ClearNonScrollSyncTreeDeltasForTesting();
static void ExpectClearedScrollDeltasRecursive(LayerImpl* root);
static ::testing::AssertionResult ScrollInfoContains(
const CompositorCommitData& commit_data,
ElementId id,
const gfx::Vector2dF& scroll_delta);
static void ExpectNone(const CompositorCommitData& commit_data, ElementId id);
template <typename T, typename... Args>
T* AddLayer(LayerTreeImpl* layer_tree_impl, Args&&... args) {
std::unique_ptr<T> layer = T::Create(layer_tree_impl, next_layer_id_++,
std::forward<Args>(args)...);
T* result = layer.get();
layer_tree_impl->AddLayer(std::move(layer));
return result;
}
LayerImpl* AddLayerInActiveTree();
void SetupViewportLayers(LayerTreeImpl* layer_tree_impl,
const gfx::Size& inner_viewport_size,
const gfx::Size& outer_viewport_size,
const gfx::Size& content_size);
void SetupViewportLayersInnerScrolls(const gfx::Size& inner_viewport_size,
const gfx::Size& content_size);
void SetupViewportLayersOuterScrolls(const gfx::Size& viewport_size,
const gfx::Size& content_size);
LayerImpl* AddContentLayer();
void SetupViewportLayersNoScrolls(const gfx::Size& bounds);
void CreateAndTestNonScrollableLayers(bool transparent_layer);
LayerImpl* AddScrollableLayer(LayerImpl* container,
const gfx::Size& scroll_container_bounds,
const gfx::Size& content_size);
void SetupScrollbarLayerCommon(LayerImpl* scroll_layer,
ScrollbarLayerImplBase* scrollbar);
void SetupScrollbarLayer(LayerImpl* scroll_layer,
SolidColorScrollbarLayerImpl* scrollbar);
void SetupScrollbarLayer(LayerImpl* scroll_layer,
PaintedScrollbarLayerImpl* scrollbar);
LayerImpl* InnerViewportScrollLayer();
LayerImpl* OuterViewportScrollLayer();
std::unique_ptr<ScrollState> BeginState(const gfx::Point& point,
const gfx::Vector2dF& delta_hint,
ui::ScrollInputType type);
ScrollState UpdateState(const gfx::Point& point,
const gfx::Vector2dF& delta,
ui::ScrollInputType type);
ScrollState AnimatedUpdateState(const gfx::Point& point,
const gfx::Vector2dF& delta);
void DrawFrame();
void DrawFrameWithArgs(const viz::BeginFrameArgs& args);
RenderFrameMetadata StartDrawAndProduceRenderFrameMetadata();
void AllowedTouchActionTestHelper(float device_scale_factor,
float page_scale_factor);
LayerImpl* CreateLayerForSnapping();
std::optional<SnapContainerData> GetSnapContainerData(LayerImpl* layer);
void ClearLayersAndPropertyTrees(LayerTreeImpl* layer_tree_impl);
void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
void pinch_zoom_pan_viewport_test(float device_scale_factor);
void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
void pinch_zoom_pan_viewport_and_scroll_boundary_test(
float device_scale_factor);
void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
void SetupMouseMoveAtTestScrollbarStates(bool main_thread_scrolling);
scoped_refptr<AnimationTimeline> timeline() { return timeline_; }
protected:
virtual std::unique_ptr<LayerTreeFrameSink> CreateLayerTreeFrameSink();
void DrawOneFrame();
static void SetScrollOffsetDelta(LayerImpl* layer_impl,
const gfx::Vector2dF& delta);
void BeginImplFrameAndAnimate(viz::BeginFrameArgs begin_frame_args,
base::TimeTicks frame_time);
void InitializeImageWorker(const LayerTreeSettings& settings);
InputHandler& GetInputHandler();
FakeImplTaskRunnerProvider task_runner_provider_;
DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
TestTaskGraphRunner task_graph_runner_;
std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink_;
std::unique_ptr<LayerTreeHostImpl> host_impl_;
FakeRenderingStatsInstrumentation stats_instrumentation_;
bool on_can_draw_state_changed_called_;
bool did_notify_ready_to_activate_;
bool did_request_commit_;
bool did_request_redraw_;
bool did_request_next_frame_;
bool did_request_prepare_tiles_;
bool did_prepare_tiles_;
bool did_complete_page_scale_animation_;
bool reduce_memory_result_;
bool did_request_impl_side_invalidation_;
base::OnceClosure animation_task_;
base::TimeDelta requested_animation_delay_;
std::unique_ptr<TestFrameData> last_on_draw_frame_;
viz::CompositorRenderPassList last_on_draw_render_passes_;
scoped_refptr<AnimationTimeline> timeline_;
std::unique_ptr<base::Thread> image_worker_;
int next_layer_id_ = 2;
int first_scroll_observed = 0;
};
class LayerTreeHostImplTest
: public LayerTreeHostImplTestBase,
public testing::WithParamInterface<LayerTreeImplTestMode> {
public:
LayerTreeHostImplTest();
~LayerTreeHostImplTest() override;
static bool CommitsToActiveTree();
LayerTreeSettings DefaultSettings() override;
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
}
#endif