| Index: cc/trees/layer_tree_host_impl_unittest.cc
|
| diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
|
| deleted file mode 100644
|
| index 284cae0f7416c23c28d9375d7d58ad33b1b1466d..0000000000000000000000000000000000000000
|
| --- a/cc/trees/layer_tree_host_impl_unittest.cc
|
| +++ /dev/null
|
| @@ -1,8479 +0,0 @@
|
| -// 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.
|
| -
|
| -#include "cc/trees/layer_tree_host_impl.h"
|
| -
|
| -#include <algorithm>
|
| -#include <cmath>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/command_line.h"
|
| -#include "base/containers/hash_tables.h"
|
| -#include "base/containers/scoped_ptr_hash_map.h"
|
| -#include "cc/animation/scrollbar_animation_controller_thinning.h"
|
| -#include "cc/base/math_util.h"
|
| -#include "cc/input/page_scale_animation.h"
|
| -#include "cc/input/top_controls_manager.h"
|
| -#include "cc/layers/append_quads_data.h"
|
| -#include "cc/layers/delegated_renderer_layer_impl.h"
|
| -#include "cc/layers/heads_up_display_layer_impl.h"
|
| -#include "cc/layers/io_surface_layer_impl.h"
|
| -#include "cc/layers/layer_impl.h"
|
| -#include "cc/layers/painted_scrollbar_layer_impl.h"
|
| -#include "cc/layers/render_surface_impl.h"
|
| -#include "cc/layers/solid_color_layer_impl.h"
|
| -#include "cc/layers/solid_color_scrollbar_layer_impl.h"
|
| -#include "cc/layers/texture_layer_impl.h"
|
| -#include "cc/layers/tiled_layer_impl.h"
|
| -#include "cc/output/begin_frame_args.h"
|
| -#include "cc/output/compositor_frame_ack.h"
|
| -#include "cc/output/compositor_frame_metadata.h"
|
| -#include "cc/output/copy_output_request.h"
|
| -#include "cc/output/copy_output_result.h"
|
| -#include "cc/output/gl_renderer.h"
|
| -#include "cc/output/latency_info_swap_promise.h"
|
| -#include "cc/quads/render_pass_draw_quad.h"
|
| -#include "cc/quads/solid_color_draw_quad.h"
|
| -#include "cc/quads/texture_draw_quad.h"
|
| -#include "cc/quads/tile_draw_quad.h"
|
| -#include "cc/resources/layer_tiling_data.h"
|
| -#include "cc/test/animation_test_common.h"
|
| -#include "cc/test/begin_frame_args_test.h"
|
| -#include "cc/test/fake_layer_tree_host_impl.h"
|
| -#include "cc/test/fake_output_surface.h"
|
| -#include "cc/test/fake_output_surface_client.h"
|
| -#include "cc/test/fake_picture_layer_impl.h"
|
| -#include "cc/test/fake_picture_pile_impl.h"
|
| -#include "cc/test/fake_proxy.h"
|
| -#include "cc/test/geometry_test_utils.h"
|
| -#include "cc/test/layer_test_common.h"
|
| -#include "cc/test/layer_tree_test.h"
|
| -#include "cc/test/render_pass_test_common.h"
|
| -#include "cc/test/test_gpu_memory_buffer_manager.h"
|
| -#include "cc/test/test_shared_bitmap_manager.h"
|
| -#include "cc/test/test_task_graph_runner.h"
|
| -#include "cc/test/test_web_graphics_context_3d.h"
|
| -#include "cc/trees/layer_tree_impl.h"
|
| -#include "cc/trees/single_thread_proxy.h"
|
| -#include "testing/gmock/include/gmock/gmock.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -#include "third_party/skia/include/core/SkMallocPixelRef.h"
|
| -#include "ui/gfx/frame_time.h"
|
| -#include "ui/gfx/geometry/rect_conversions.h"
|
| -#include "ui/gfx/geometry/size_conversions.h"
|
| -#include "ui/gfx/geometry/vector2d_conversions.h"
|
| -
|
| -using ::testing::Mock;
|
| -using ::testing::Return;
|
| -using ::testing::AnyNumber;
|
| -using ::testing::AtLeast;
|
| -using ::testing::_;
|
| -
|
| -namespace cc {
|
| -namespace {
|
| -
|
| -class LayerTreeHostImplTest : public testing::Test,
|
| - public LayerTreeHostImplClient {
|
| - public:
|
| - LayerTreeHostImplTest()
|
| - : proxy_(base::MessageLoopProxy::current(),
|
| - base::MessageLoopProxy::current()),
|
| - always_impl_thread_(&proxy_),
|
| - always_main_thread_blocked_(&proxy_),
|
| - shared_bitmap_manager_(new TestSharedBitmapManager),
|
| - gpu_memory_buffer_manager_(new TestGpuMemoryBufferManager),
|
| - task_graph_runner_(new TestTaskGraphRunner),
|
| - on_can_draw_state_changed_called_(false),
|
| - did_notify_ready_to_activate_(false),
|
| - did_request_commit_(false),
|
| - did_request_redraw_(false),
|
| - did_request_animate_(false),
|
| - did_request_prepare_tiles_(false),
|
| - did_complete_page_scale_animation_(false),
|
| - reduce_memory_result_(true),
|
| - current_limit_bytes_(0),
|
| - current_priority_cutoff_value_(0) {
|
| - }
|
| -
|
| - LayerTreeSettings DefaultSettings() {
|
| - LayerTreeSettings settings;
|
| - settings.minimum_occlusion_tracking_size = gfx::Size();
|
| - settings.impl_side_painting = true;
|
| - settings.renderer_settings.texture_id_allocation_chunk_size = 1;
|
| - settings.report_overscroll_only_for_scrollable_axes = true;
|
| - settings.use_pinch_virtual_viewport = true;
|
| - return settings;
|
| - }
|
| -
|
| - void SetUp() override {
|
| - CreateHostImpl(DefaultSettings(), CreateOutputSurface());
|
| - }
|
| -
|
| - void TearDown() override {}
|
| -
|
| - void UpdateRendererCapabilitiesOnImplThread() override {}
|
| - void DidLoseOutputSurfaceOnImplThread() override {}
|
| - void CommitVSyncParameters(base::TimeTicks timebase,
|
| - base::TimeDelta interval) override {}
|
| - void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override {}
|
| - void SetMaxSwapsPendingOnImplThread(int max) override {}
|
| - void DidSwapBuffersOnImplThread() override {}
|
| - void DidSwapBuffersCompleteOnImplThread() override {}
|
| - void OnCanDrawStateChanged(bool can_draw) override {
|
| - on_can_draw_state_changed_called_ = true;
|
| - }
|
| - void NotifyReadyToActivate() override {
|
| - did_notify_ready_to_activate_ = true;
|
| - host_impl_->ActivateSyncTree();
|
| - }
|
| - void NotifyReadyToDraw() override {}
|
| - void SetNeedsRedrawOnImplThread() override { did_request_redraw_ = true; }
|
| - void SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) override {
|
| - did_request_redraw_ = true;
|
| - }
|
| - void SetNeedsAnimateOnImplThread() override { did_request_animate_ = true; }
|
| - void SetNeedsPrepareTilesOnImplThread() override {
|
| - did_request_prepare_tiles_ = true;
|
| - }
|
| - void SetNeedsCommitOnImplThread() override { did_request_commit_ = true; }
|
| - void PostAnimationEventsToMainThreadOnImplThread(
|
| - scoped_ptr<AnimationEventsVector> events) override {}
|
| - bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
|
| - int priority_cutoff) override {
|
| - current_limit_bytes_ = limit_bytes;
|
| - current_priority_cutoff_value_ = priority_cutoff;
|
| - return reduce_memory_result_;
|
| - }
|
| - bool IsInsideDraw() override { return false; }
|
| - void RenewTreePriority() override {}
|
| - void PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
|
| - base::TimeDelta delay) override {
|
| - animation_task_ = task;
|
| - requested_animation_delay_ = delay;
|
| - }
|
| - void DidActivateSyncTree() override {}
|
| - void DidPrepareTiles() override {}
|
| - void DidCompletePageScaleAnimationOnImplThread() override {
|
| - did_complete_page_scale_animation_ = true;
|
| - }
|
| -
|
| - void set_reduce_memory_result(bool reduce_memory_result) {
|
| - reduce_memory_result_ = reduce_memory_result;
|
| - }
|
| -
|
| - virtual bool CreateHostImpl(const LayerTreeSettings& settings,
|
| - scoped_ptr<OutputSurface> output_surface) {
|
| - host_impl_ = LayerTreeHostImpl::Create(
|
| - settings, this, &proxy_, &stats_instrumentation_,
|
| - shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(),
|
| - task_graph_runner_.get(), 0);
|
| - bool init = host_impl_->InitializeRenderer(output_surface.Pass());
|
| - host_impl_->SetViewportSize(gfx::Size(10, 10));
|
| - return init;
|
| - }
|
| -
|
| - void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
|
| - root->SetPosition(gfx::PointF());
|
| - root->SetBounds(gfx::Size(10, 10));
|
| - root->SetContentBounds(gfx::Size(10, 10));
|
| - root->SetDrawsContent(true);
|
| - root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
|
| - root->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - }
|
| -
|
| - static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
|
| - ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
|
| - for (size_t i = 0; i < layer->children().size(); ++i)
|
| - ExpectClearedScrollDeltasRecursive(layer->children()[i]);
|
| - }
|
| -
|
| - static void ExpectContains(const ScrollAndScaleSet& scroll_info,
|
| - int id,
|
| - const gfx::Vector2d& scroll_delta) {
|
| - int times_encountered = 0;
|
| -
|
| - for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
|
| - if (scroll_info.scrolls[i].layer_id != id)
|
| - continue;
|
| - EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
|
| - times_encountered++;
|
| - }
|
| -
|
| - ASSERT_EQ(1, times_encountered);
|
| - }
|
| -
|
| - static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
|
| - int times_encountered = 0;
|
| -
|
| - for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
|
| - if (scroll_info.scrolls[i].layer_id != id)
|
| - continue;
|
| - times_encountered++;
|
| - }
|
| -
|
| - ASSERT_EQ(0, times_encountered);
|
| - }
|
| -
|
| - LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
|
| - const gfx::Size& content_size) {
|
| - const int kInnerViewportScrollLayerId = 2;
|
| - const int kInnerViewportClipLayerId = 4;
|
| - const int kPageScaleLayerId = 5;
|
| - scoped_ptr<LayerImpl> root =
|
| - LayerImpl::Create(layer_tree_impl, 1);
|
| - root->SetBounds(content_size);
|
| - root->SetContentBounds(content_size);
|
| - root->SetPosition(gfx::PointF());
|
| - root->SetHasRenderSurface(true);
|
| -
|
| - scoped_ptr<LayerImpl> scroll =
|
| - LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
|
| - LayerImpl* scroll_layer = scroll.get();
|
| - scroll->SetIsContainerForFixedPositionLayers(true);
|
| - scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
|
| -
|
| - scoped_ptr<LayerImpl> clip =
|
| - LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
|
| - clip->SetBounds(
|
| - gfx::Size(content_size.width() / 2, content_size.height() / 2));
|
| -
|
| - scoped_ptr<LayerImpl> page_scale =
|
| - LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
|
| -
|
| - scroll->SetScrollClipLayer(clip->id());
|
| - scroll->SetBounds(content_size);
|
| - scroll->SetContentBounds(content_size);
|
| - scroll->SetPosition(gfx::PointF());
|
| - scroll->SetIsContainerForFixedPositionLayers(true);
|
| -
|
| - scoped_ptr<LayerImpl> contents =
|
| - LayerImpl::Create(layer_tree_impl, 3);
|
| - contents->SetDrawsContent(true);
|
| - contents->SetBounds(content_size);
|
| - contents->SetContentBounds(content_size);
|
| - contents->SetPosition(gfx::PointF());
|
| -
|
| - scroll->AddChild(contents.Pass());
|
| - page_scale->AddChild(scroll.Pass());
|
| - clip->AddChild(page_scale.Pass());
|
| - root->AddChild(clip.Pass());
|
| -
|
| - layer_tree_impl->SetRootLayer(root.Pass());
|
| - layer_tree_impl->SetViewportLayersFromIds(
|
| - Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
|
| - Layer::INVALID_ID);
|
| -
|
| - return scroll_layer;
|
| - }
|
| -
|
| - LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
|
| - LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
|
| - host_impl_->active_tree(), content_size);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - return scroll_layer;
|
| - }
|
| -
|
| - // TODO(wjmaclean) Add clip-layer pointer to parameters.
|
| - scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
|
| - const gfx::Size& size,
|
| - LayerImpl* clip_layer) {
|
| - DCHECK(clip_layer);
|
| - DCHECK(id != clip_layer->id());
|
| - scoped_ptr<LayerImpl> layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), id);
|
| - layer->SetScrollClipLayer(clip_layer->id());
|
| - layer->SetDrawsContent(true);
|
| - layer->SetBounds(size);
|
| - layer->SetContentBounds(size);
|
| - clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
|
| - return layer.Pass();
|
| - }
|
| -
|
| - void DrawFrame() {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| - 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 CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
|
| - // Note: It is not possible to disable the renderer once it has been set,
|
| - // so we do not need to test that disabling the renderer notifies us
|
| - // that can_draw changed.
|
| - EXPECT_FALSE(host_impl_->CanDraw());
|
| - on_can_draw_state_changed_called_ = false;
|
| -
|
| - // Set up the root layer, which allows us to draw.
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - EXPECT_TRUE(host_impl_->CanDraw());
|
| - EXPECT_TRUE(on_can_draw_state_changed_called_);
|
| - on_can_draw_state_changed_called_ = false;
|
| -
|
| - // Toggle the root layer to make sure it toggles can_draw
|
| - host_impl_->active_tree()->SetRootLayer(nullptr);
|
| - EXPECT_FALSE(host_impl_->CanDraw());
|
| - EXPECT_TRUE(on_can_draw_state_changed_called_);
|
| - on_can_draw_state_changed_called_ = false;
|
| -
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - EXPECT_TRUE(host_impl_->CanDraw());
|
| - EXPECT_TRUE(on_can_draw_state_changed_called_);
|
| - on_can_draw_state_changed_called_ = false;
|
| -
|
| - // Toggle the device viewport size to make sure it toggles can_draw.
|
| - host_impl_->SetViewportSize(gfx::Size());
|
| - if (always_draw) {
|
| - EXPECT_TRUE(host_impl_->CanDraw());
|
| - } else {
|
| - EXPECT_FALSE(host_impl_->CanDraw());
|
| - }
|
| - EXPECT_TRUE(on_can_draw_state_changed_called_);
|
| - on_can_draw_state_changed_called_ = false;
|
| -
|
| - host_impl_->SetViewportSize(gfx::Size(100, 100));
|
| - EXPECT_TRUE(host_impl_->CanDraw());
|
| - EXPECT_TRUE(on_can_draw_state_changed_called_);
|
| - on_can_draw_state_changed_called_ = false;
|
| -
|
| - // Toggle contents textures purged without causing any evictions,
|
| - // and make sure that it does not change can_draw.
|
| - set_reduce_memory_result(false);
|
| - host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
|
| - host_impl_->memory_allocation_limit_bytes() - 1));
|
| - EXPECT_TRUE(host_impl_->CanDraw());
|
| - EXPECT_FALSE(on_can_draw_state_changed_called_);
|
| - on_can_draw_state_changed_called_ = false;
|
| -
|
| - // Toggle contents textures purged to make sure it toggles can_draw.
|
| - set_reduce_memory_result(true);
|
| - host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
|
| - host_impl_->memory_allocation_limit_bytes() - 1));
|
| - if (always_draw) {
|
| - EXPECT_TRUE(host_impl_->CanDraw());
|
| - } else {
|
| - EXPECT_FALSE(host_impl_->CanDraw());
|
| - }
|
| - EXPECT_TRUE(on_can_draw_state_changed_called_);
|
| - on_can_draw_state_changed_called_ = false;
|
| -
|
| - host_impl_->active_tree()->ResetContentsTexturesPurged();
|
| - EXPECT_TRUE(host_impl_->CanDraw());
|
| - EXPECT_TRUE(on_can_draw_state_changed_called_);
|
| - on_can_draw_state_changed_called_ = false;
|
| - }
|
| -
|
| - void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
|
| -
|
| - protected:
|
| - virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
|
| - return FakeOutputSurface::Create3d();
|
| - }
|
| -
|
| - void DrawOneFrame() {
|
| - LayerTreeHostImpl::FrameData frame_data;
|
| - host_impl_->PrepareToDraw(&frame_data);
|
| - host_impl_->DidDrawAllLayers(frame_data);
|
| - }
|
| -
|
| - FakeProxy proxy_;
|
| - DebugScopedSetImplThread always_impl_thread_;
|
| - DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
|
| -
|
| - scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
|
| - scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
|
| - scoped_ptr<TestTaskGraphRunner> task_graph_runner_;
|
| - scoped_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_animate_;
|
| - bool did_request_prepare_tiles_;
|
| - bool did_complete_page_scale_animation_;
|
| - bool reduce_memory_result_;
|
| - base::Closure animation_task_;
|
| - base::TimeDelta requested_animation_delay_;
|
| - size_t current_limit_bytes_;
|
| - int current_priority_cutoff_value_;
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
|
| - bool always_draw = false;
|
| - CheckNotifyCalledIfCanDrawChanged(always_draw);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
|
| - CreateHostImpl(DefaultSettings(),
|
| - FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
|
| -
|
| - bool always_draw = true;
|
| - CheckNotifyCalledIfCanDrawChanged(always_draw);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
|
| - ASSERT_FALSE(host_impl_->active_tree()->root_layer());
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ASSERT_EQ(scroll_info->scrolls.size(), 0u);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
|
| - {
|
| - scoped_ptr<LayerImpl> root =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
|
| - root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
|
| - root->children()[1]->AddChild(
|
| - LayerImpl::Create(host_impl_->active_tree(), 4));
|
| - root->children()[1]->AddChild(
|
| - LayerImpl::Create(host_impl_->active_tree(), 5));
|
| - root->children()[1]->children()[0]->AddChild(
|
| - LayerImpl::Create(host_impl_->active_tree(), 6));
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - }
|
| - LayerImpl* root = host_impl_->active_tree()->root_layer();
|
| -
|
| - ExpectClearedScrollDeltasRecursive(root);
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info;
|
| -
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ASSERT_EQ(scroll_info->scrolls.size(), 0u);
|
| - ExpectClearedScrollDeltasRecursive(root);
|
| -
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ASSERT_EQ(scroll_info->scrolls.size(), 0u);
|
| - ExpectClearedScrollDeltasRecursive(root);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
|
| - gfx::ScrollOffset scroll_offset(20, 30);
|
| - gfx::Vector2d scroll_delta(11, -15);
|
| - {
|
| - scoped_ptr<LayerImpl> root_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 2);
|
| - scoped_ptr<LayerImpl> root =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root_clip->SetBounds(gfx::Size(10, 10));
|
| - LayerImpl* root_layer = root.get();
|
| - root_clip->AddChild(root.Pass());
|
| - root_layer->SetBounds(gfx::Size(110, 110));
|
| - root_layer->SetScrollClipLayer(root_clip->id());
|
| - root_layer->PushScrollOffsetFromMainThread(scroll_offset);
|
| - root_layer->ScrollBy(scroll_delta);
|
| - host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
|
| - }
|
| - LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info;
|
| -
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ASSERT_EQ(scroll_info->scrolls.size(), 1u);
|
| - ExpectContains(*scroll_info, root->id(), scroll_delta);
|
| -
|
| - gfx::Vector2d scroll_delta2(-5, 27);
|
| - root->ScrollBy(scroll_delta2);
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ASSERT_EQ(scroll_info->scrolls.size(), 1u);
|
| - ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
|
| -
|
| - root->ScrollBy(gfx::Vector2d());
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
|
| - InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
|
| - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
|
| - InputHandler::WHEEL));
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
|
| - InputHandler::WHEEL));
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_commit_);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollActiveOnlyAfterScrollMovement) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - EXPECT_FALSE(host_impl_->IsActivelyScrolling());
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
|
| - EXPECT_TRUE(host_impl_->IsActivelyScrolling());
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_FALSE(host_impl_->IsActivelyScrolling());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
|
| - // We should not crash when trying to scroll an empty layer tree.
|
| - EXPECT_EQ(InputHandler::SCROLL_IGNORED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
|
| - scoped_ptr<TestWebGraphicsContext3D> context_owned =
|
| - TestWebGraphicsContext3D::Create();
|
| - context_owned->set_context_lost(true);
|
| -
|
| - // Initialization will fail.
|
| - EXPECT_FALSE(CreateHostImpl(
|
| - DefaultSettings(), FakeOutputSurface::Create3d(context_owned.Pass())));
|
| -
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| -
|
| - // We should not crash when trying to scroll after the renderer initialization
|
| - // fails.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| -
|
| - // We should not crash if the tree is replaced while we are scrolling.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - host_impl_->active_tree()->DetachLayerTree();
|
| -
|
| - scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| -
|
| - // We should still be scrolling, because the scrolled layer also exists in the
|
| - // new tree.
|
| - gfx::Vector2d scroll_delta(0, 10);
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| - LayerImpl* root = host_impl_->active_tree()->root_layer();
|
| -
|
| - // With registered event handlers, wheel scrolls don't necessarily
|
| - // have to go to the main thread.
|
| - root->SetHaveWheelEventHandlers(true);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // But typically the scroll-blocks-on mode will require them to.
|
| - root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
|
| - SCROLL_BLOCKS_ON_START_TOUCH);
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| -
|
| - // But gesture scrolls can still be handled.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // And if the handlers go away, wheel scrolls can again be processed
|
| - // on impl (despite the scroll-blocks-on mode).
|
| - root->SetHaveWheelEventHandlers(false);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - host_impl_->ScrollEnd();
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) {
|
| - LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| - LayerImpl* root = host_impl_->active_tree()->root_layer();
|
| -
|
| - LayerImpl* child = 0;
|
| - {
|
| - scoped_ptr<LayerImpl> child_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 6);
|
| - child = child_layer.get();
|
| - child_layer->SetDrawsContent(true);
|
| - child_layer->SetPosition(gfx::PointF(0, 20));
|
| - child_layer->SetBounds(gfx::Size(50, 50));
|
| - child_layer->SetContentBounds(gfx::Size(50, 50));
|
| - scroll->AddChild(child_layer.Pass());
|
| - }
|
| -
|
| - // Touch handler regions determine whether touch events block scroll.
|
| - root->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
|
| - EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
|
| - root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH |
|
| - SCROLL_BLOCKS_ON_WHEEL_EVENT);
|
| - EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
|
| -
|
| - // But they don't influence the actual handling of the scroll gestures.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // It's the union of scroll-blocks-on mode bits across all layers in the
|
| - // scroll paret chain that matters.
|
| - EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
|
| - root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE);
|
| - EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
|
| - child->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH);
|
| - EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollBlocksOnScrollEventHandlers) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| - LayerImpl* root = host_impl_->active_tree()->root_layer();
|
| -
|
| - // With registered scroll handlers, scrolls don't generally have to go
|
| - // to the main thread.
|
| - root->SetHaveScrollEventHandlers(true);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // Even the default scroll blocks on mode doesn't require this.
|
| - root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
|
| - SCROLL_BLOCKS_ON_START_TOUCH);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // But the page can opt in to blocking on scroll event handlers.
|
| - root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| -
|
| - // GESTURE and WHEEL scrolls behave identically in this regard.
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| -
|
| - // And if the handlers go away, scrolls can again be processed on impl
|
| - // (despite the scroll-blocks-on mode).
|
| - root->SetHaveScrollEventHandlers(false);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollEnd();
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollBlocksOnLayerTopology) {
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| -
|
| - // Create a normal scrollable root layer
|
| - LayerImpl* root_scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - LayerImpl* root_child = root_scroll->children()[0];
|
| - LayerImpl* root = host_impl_->active_tree()->root_layer();
|
| - DrawFrame();
|
| -
|
| - // Create two child scrollable layers
|
| - LayerImpl* child1 = 0;
|
| - {
|
| - scoped_ptr<LayerImpl> scrollable_child_clip_1 =
|
| - LayerImpl::Create(host_impl_->active_tree(), 6);
|
| - scoped_ptr<LayerImpl> scrollable_child_1 = CreateScrollableLayer(
|
| - 7, gfx::Size(10, 10), scrollable_child_clip_1.get());
|
| - child1 = scrollable_child_1.get();
|
| - scrollable_child_1->SetPosition(gfx::Point(5, 5));
|
| - scrollable_child_1->SetHaveWheelEventHandlers(true);
|
| - scrollable_child_1->SetHaveScrollEventHandlers(true);
|
| - scrollable_child_clip_1->AddChild(scrollable_child_1.Pass());
|
| - root_child->AddChild(scrollable_child_clip_1.Pass());
|
| - }
|
| -
|
| - LayerImpl* child2 = 0;
|
| - {
|
| - scoped_ptr<LayerImpl> scrollable_child_clip_2 =
|
| - LayerImpl::Create(host_impl_->active_tree(), 8);
|
| - scoped_ptr<LayerImpl> scrollable_child_2 = CreateScrollableLayer(
|
| - 9, gfx::Size(10, 10), scrollable_child_clip_2.get());
|
| - child2 = scrollable_child_2.get();
|
| - scrollable_child_2->SetPosition(gfx::Point(5, 20));
|
| - scrollable_child_2->SetHaveWheelEventHandlers(true);
|
| - scrollable_child_2->SetHaveScrollEventHandlers(true);
|
| - scrollable_child_clip_2->AddChild(scrollable_child_2.Pass());
|
| - root_child->AddChild(scrollable_child_clip_2.Pass());
|
| - }
|
| -
|
| - // Scroll-blocks-on on a layer affects scrolls that hit that layer.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
|
| - host_impl_->ScrollEnd();
|
| - child1->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
|
| -
|
| - // But not those that hit only other layers.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // It's the union of bits set across the scroll ancestor chain that matters.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
|
| - host_impl_->ScrollEnd();
|
| - root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
|
| - child2->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| -
|
| - // Ignore the fling since no layer is being scrolled
|
| - EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
|
| -
|
| - // Start scrolling a layer
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| -
|
| - // Now the fling should go ahead since we've started scrolling a layer
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| -
|
| - // Ignore the fling since no layer is being scrolled
|
| - EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
|
| -
|
| - // Start scrolling a layer
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| -
|
| - // Now the fling should go ahead since we've started scrolling a layer
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| - LayerImpl* root = host_impl_->active_tree()->root_layer();
|
| -
|
| - root->SetShouldScrollOnMainThread(true);
|
| -
|
| - // Start scrolling a layer
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| -
|
| - // The fling should be ignored since there's no layer being scrolled impl-side
|
| - EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| - LayerImpl* root = host_impl_->active_tree()->root_layer();
|
| -
|
| - root->SetShouldScrollOnMainThread(true);
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
|
| - SetupScrollAndContentsLayers(gfx::Size(200, 200));
|
| - host_impl_->SetViewportSize(gfx::Size(100, 100));
|
| -
|
| - LayerImpl* root = host_impl_->active_tree()->root_layer();
|
| - root->SetContentsScale(2.f, 2.f);
|
| - root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
|
| -
|
| - DrawFrame();
|
| -
|
| - // All scroll types inside the non-fast scrollable region should fail.
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL));
|
| - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
|
| - InputHandler::WHEEL));
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE));
|
| - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
|
| - InputHandler::GESTURE));
|
| -
|
| - // All scroll types outside this region should succeed.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL));
|
| - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
|
| - InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
|
| - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
|
| - InputHandler::GESTURE));
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
|
| - InputHandler::GESTURE));
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE));
|
| - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
|
| - InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
|
| - InputHandler::GESTURE));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
|
| - SetupScrollAndContentsLayers(gfx::Size(200, 200));
|
| - host_impl_->SetViewportSize(gfx::Size(100, 100));
|
| -
|
| - LayerImpl* root = host_impl_->active_tree()->root_layer();
|
| - root->SetContentsScale(2.f, 2.f);
|
| - root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
|
| - root->SetPosition(gfx::PointF(-25.f, 0.f));
|
| -
|
| - DrawFrame();
|
| -
|
| - // This point would fall into the non-fast scrollable region except that we've
|
| - // moved the layer down by 25 pixels.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL));
|
| - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
|
| - InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // This point is still inside the non-fast region.
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
|
| - EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| -
|
| - EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
|
| - EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
|
| - scroll_layer->SetHaveScrollEventHandlers(true);
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| -
|
| - EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
|
| - EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
|
| - SetupScrollAndContentsLayers(gfx::Size(200, 200));
|
| - host_impl_->SetViewportSize(gfx::Size(100, 100));
|
| -
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| -
|
| - // Trying to scroll to the left/top will not succeed.
|
| - EXPECT_FALSE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
|
| - EXPECT_FALSE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
|
| - EXPECT_FALSE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
|
| -
|
| - // Scrolling to the right/bottom will succeed.
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll);
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll);
|
| -
|
| - // Scrolling to left/top will now succeed.
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
|
| -
|
| - // Scrolling diagonally against an edge will succeed.
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll);
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll);
|
| -
|
| - // Trying to scroll more than the available space will also succeed.
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
|
| - SetupScrollAndContentsLayers(gfx::Size(200, 2000));
|
| - host_impl_->SetViewportSize(gfx::Size(100, 1000));
|
| -
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| -
|
| - // Trying to scroll without a vertical scrollbar will fail.
|
| - EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
|
| - gfx::Point(), SCROLL_FORWARD));
|
| - EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
|
| - gfx::Point(), SCROLL_BACKWARD));
|
| -
|
| - scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
|
| - PaintedScrollbarLayerImpl::Create(
|
| - host_impl_->active_tree(),
|
| - 20,
|
| - VERTICAL));
|
| - vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
|
| - host_impl_->InnerViewportScrollLayer()->AddScrollbar(
|
| - vertical_scrollbar.get());
|
| -
|
| - // Trying to scroll with a vertical scrollbar will succeed.
|
| - EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
|
| - gfx::Point(), SCROLL_FORWARD));
|
| - EXPECT_FLOAT_EQ(875.f,
|
| - host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
|
| - EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
|
| - gfx::Point(), SCROLL_BACKWARD));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
|
| - host_impl_->SetViewportSize(gfx::Size(100, 100));
|
| -
|
| - gfx::Size overflow_size(400, 400);
|
| - ASSERT_EQ(1u, scroll_layer->children().size());
|
| - LayerImpl* overflow = scroll_layer->children()[0];
|
| - overflow->SetBounds(overflow_size);
|
| - overflow->SetContentBounds(overflow_size);
|
| - overflow->SetScrollClipLayer(scroll_layer->parent()->id());
|
| - overflow->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
|
| - overflow->SetPosition(gfx::PointF());
|
| -
|
| - DrawFrame();
|
| - gfx::Point scroll_position(10, 10);
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->CurrentScrollOffset());
|
| -
|
| - gfx::Vector2dF scroll_delta(10, 10);
|
| - host_impl_->ScrollBy(scroll_position, scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
|
| -
|
| - overflow->set_user_scrollable_horizontal(false);
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
|
| -
|
| - host_impl_->ScrollBy(scroll_position, scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
|
| -
|
| - overflow->set_user_scrollable_vertical(false);
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
|
| -
|
| - host_impl_->ScrollBy(scroll_position, scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->CurrentScrollOffset());
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
|
| - LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
|
| - EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
|
| -
|
| - float min_page_scale = 1.f, max_page_scale = 4.f;
|
| - float page_scale_factor = 1.f;
|
| -
|
| - // The impl-based pinch zoom should adjust the max scroll position.
|
| - {
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(
|
| - page_scale_factor, min_page_scale, max_page_scale);
|
| - host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
|
| - scroll_layer->SetScrollDelta(gfx::Vector2d());
|
| -
|
| - float page_scale_delta = 2.f;
|
| -
|
| - host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
|
| - host_impl_->PinchGestureBegin();
|
| - host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
|
| - host_impl_->PinchGestureEnd();
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_FALSE(did_request_animate_);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_commit_);
|
| - EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
|
| -
|
| - EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
|
| - scroll_layer->MaxScrollOffset().ToString());
|
| - }
|
| -
|
| - // Scrolling after a pinch gesture should always be in local space. The
|
| - // scroll deltas have the page scale factor applied.
|
| - {
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(
|
| - page_scale_factor, min_page_scale, max_page_scale);
|
| - host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
|
| - scroll_layer->SetScrollDelta(gfx::Vector2d());
|
| -
|
| - float page_scale_delta = 2.f;
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
|
| - host_impl_->PinchGestureBegin();
|
| - host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
|
| - host_impl_->PinchGestureEnd();
|
| - host_impl_->ScrollEnd();
|
| -
|
| - gfx::Vector2d scroll_delta(0, 10);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - ExpectContains(*scroll_info.get(), scroll_layer->id(),
|
| - gfx::Vector2d(0, scroll_delta.y() / page_scale_delta));
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
|
| - ui::LatencyInfo latency_info;
|
| - latency_info.trace_id = 1234;
|
| - scoped_ptr<SwapPromise> swap_promise(
|
| - new LatencyInfoSwapPromise(latency_info));
|
| -
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
|
| - host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass());
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
|
| - EXPECT_EQ(1u, scroll_info->swap_promises.size());
|
| - EXPECT_EQ(latency_info.trace_id, scroll_info->swap_promises[0]->TraceId());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, PinchGesture) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| -
|
| - LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
|
| - DCHECK(scroll_layer);
|
| -
|
| - float min_page_scale = 1.f;
|
| - float max_page_scale = 4.f;
|
| -
|
| - // Basic pinch zoom in gesture
|
| - {
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
|
| - max_page_scale);
|
| - scroll_layer->SetScrollDelta(gfx::Vector2d());
|
| -
|
| - float page_scale_delta = 2.f;
|
| - host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
|
| - host_impl_->PinchGestureBegin();
|
| - host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
|
| - host_impl_->PinchGestureEnd();
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_FALSE(did_request_animate_);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_commit_);
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
|
| - }
|
| -
|
| - // Zoom-in clamping
|
| - {
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
|
| - max_page_scale);
|
| - scroll_layer->SetScrollDelta(gfx::Vector2d());
|
| - float page_scale_delta = 10.f;
|
| -
|
| - host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
|
| - host_impl_->PinchGestureBegin();
|
| - host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
|
| - host_impl_->PinchGestureEnd();
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
|
| - }
|
| -
|
| - // Zoom-out clamping
|
| - {
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
|
| - max_page_scale);
|
| - scroll_layer->SetScrollDelta(gfx::Vector2d());
|
| - scroll_layer->PullDeltaForMainThread();
|
| - scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
|
| -
|
| - float page_scale_delta = 0.1f;
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
|
| - host_impl_->PinchGestureBegin();
|
| - host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
|
| - host_impl_->PinchGestureEnd();
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
|
| -
|
| - EXPECT_TRUE(scroll_info->scrolls.empty());
|
| - }
|
| -
|
| - // Two-finger panning should not happen based on pinch events only
|
| - {
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
|
| - max_page_scale);
|
| - scroll_layer->SetScrollDelta(gfx::Vector2d());
|
| - scroll_layer->PullDeltaForMainThread();
|
| - scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
|
| -
|
| - float page_scale_delta = 1.f;
|
| - host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
|
| - host_impl_->PinchGestureBegin();
|
| - host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
|
| - host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
|
| - host_impl_->PinchGestureEnd();
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
|
| - EXPECT_TRUE(scroll_info->scrolls.empty());
|
| - }
|
| -
|
| - // Two-finger panning should work with interleaved scroll events
|
| - {
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
|
| - max_page_scale);
|
| - scroll_layer->SetScrollDelta(gfx::Vector2d());
|
| - scroll_layer->PullDeltaForMainThread();
|
| - scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
|
| -
|
| - float page_scale_delta = 1.f;
|
| - host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
|
| - host_impl_->PinchGestureBegin();
|
| - host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
|
| - host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
|
| - host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
|
| - host_impl_->PinchGestureEnd();
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
|
| - ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
|
| - }
|
| -
|
| - // Two-finger panning should work when starting fully zoomed out.
|
| - {
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(0.5f, 0.5f, 4.f);
|
| - scroll_layer->SetScrollDelta(gfx::Vector2d());
|
| - scroll_layer->PullDeltaForMainThread();
|
| - scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
|
| -
|
| - host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
|
| - host_impl_->PinchGestureBegin();
|
| - host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
|
| - host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
|
| - host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
|
| - host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
|
| - host_impl_->PinchGestureEnd();
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
|
| - ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| -
|
| - LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
|
| - DCHECK(scroll_layer);
|
| -
|
| - float min_page_scale = 0.5f;
|
| - float max_page_scale = 4.f;
|
| - base::TimeTicks start_time = base::TimeTicks() +
|
| - base::TimeDelta::FromSeconds(1);
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
|
| - base::TimeTicks halfway_through_animation = start_time + duration / 2;
|
| - base::TimeTicks end_time = start_time + duration;
|
| -
|
| - // Non-anchor zoom-in
|
| - {
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
|
| - max_page_scale);
|
| - scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
|
| -
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - host_impl_->active_tree()->SetPendingPageScaleAnimation(
|
| - scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
|
| - gfx::Vector2d(),
|
| - false,
|
| - 2.f,
|
| - duration)));
|
| - host_impl_->ActivateSyncTree();
|
| - EXPECT_FALSE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_animate_);
|
| -
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - host_impl_->Animate(start_time);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_animate_);
|
| -
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - host_impl_->Animate(halfway_through_animation);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_animate_);
|
| -
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - did_request_commit_ = false;
|
| - host_impl_->Animate(end_time);
|
| - EXPECT_TRUE(did_request_commit_);
|
| - EXPECT_FALSE(did_request_animate_);
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - EXPECT_EQ(scroll_info->page_scale_delta, 2);
|
| - ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
|
| - }
|
| -
|
| - // Anchor zoom-out
|
| - {
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
|
| - max_page_scale);
|
| - scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
|
| -
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - host_impl_->active_tree()->SetPendingPageScaleAnimation(
|
| - scoped_ptr<PendingPageScaleAnimation> (new PendingPageScaleAnimation(
|
| - gfx::Vector2d(25, 25),
|
| - true,
|
| - min_page_scale,
|
| - duration)));
|
| - host_impl_->ActivateSyncTree();
|
| - EXPECT_FALSE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_animate_);
|
| -
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - host_impl_->Animate(start_time);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_animate_);
|
| -
|
| - did_request_redraw_ = false;
|
| - did_request_commit_ = false;
|
| - did_request_animate_ = false;
|
| - host_impl_->Animate(end_time);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_FALSE(did_request_animate_);
|
| - EXPECT_TRUE(did_request_commit_);
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
|
| - // Pushed to (0,0) via clamping against contents layer size.
|
| - ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| -
|
| - LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
|
| - DCHECK(scroll_layer);
|
| -
|
| - float min_page_scale = 0.5f;
|
| - float max_page_scale = 4.f;
|
| - base::TimeTicks start_time = base::TimeTicks() +
|
| - base::TimeDelta::FromSeconds(1);
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
|
| - base::TimeTicks halfway_through_animation = start_time + duration / 2;
|
| - base::TimeTicks end_time = start_time + duration;
|
| -
|
| - // Anchor zoom with unchanged page scale should not change scroll or scale.
|
| - {
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
|
| - max_page_scale);
|
| - scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
|
| -
|
| - host_impl_->active_tree()->SetPendingPageScaleAnimation(
|
| - scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
|
| - gfx::Vector2d(),
|
| - true,
|
| - 1.f,
|
| - duration)));
|
| - host_impl_->ActivateSyncTree();
|
| - host_impl_->Animate(start_time);
|
| - host_impl_->Animate(halfway_through_animation);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - host_impl_->Animate(end_time);
|
| - EXPECT_TRUE(did_request_commit_);
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - EXPECT_EQ(scroll_info->page_scale_delta, 1);
|
| - ExpectNone(*scroll_info, scroll_layer->id());
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
|
| - host_impl_->CreatePendingTree();
|
| - CreateScrollAndContentsLayers(
|
| - host_impl_->pending_tree(),
|
| - gfx::Size(100, 100));
|
| - host_impl_->ActivateSyncTree();
|
| - DrawFrame();
|
| -
|
| - LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
|
| - DCHECK(scroll_layer);
|
| -
|
| - float min_page_scale = 0.5f;
|
| - float max_page_scale = 4.f;
|
| - host_impl_->sync_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
|
| - max_page_scale);
|
| - host_impl_->ActivateSyncTree();
|
| -
|
| - base::TimeTicks start_time = base::TimeTicks() +
|
| - base::TimeDelta::FromSeconds(1);
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
|
| - base::TimeTicks third_through_animation = start_time + duration / 3;
|
| - base::TimeTicks halfway_through_animation = start_time + duration / 2;
|
| - base::TimeTicks end_time = start_time + duration;
|
| - float target_scale = 2.f;
|
| -
|
| - scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
|
| -
|
| - // Make sure TakePageScaleAnimation works properly.
|
| -
|
| - host_impl_->sync_tree()->SetPendingPageScaleAnimation(
|
| - scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
|
| - gfx::Vector2d(),
|
| - false,
|
| - target_scale,
|
| - duration)));
|
| - scoped_ptr<PendingPageScaleAnimation> psa =
|
| - host_impl_->sync_tree()->TakePendingPageScaleAnimation();
|
| - EXPECT_EQ(target_scale, psa->scale);
|
| - EXPECT_EQ(duration, psa->duration);
|
| - EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePendingPageScaleAnimation());
|
| -
|
| - // Recreate the PSA. Nothing should happen here since the tree containing the
|
| - // PSA hasn't been activated yet.
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - host_impl_->sync_tree()->SetPendingPageScaleAnimation(
|
| - scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
|
| - gfx::Vector2d(),
|
| - false,
|
| - target_scale,
|
| - duration)));
|
| - host_impl_->Animate(halfway_through_animation);
|
| - EXPECT_FALSE(did_request_animate_);
|
| - EXPECT_FALSE(did_request_redraw_);
|
| -
|
| - // Activate the sync tree. This should cause the animation to become enabled.
|
| - // It should also clear the pointer on the sync tree.
|
| - host_impl_->ActivateSyncTree();
|
| - EXPECT_EQ(nullptr,
|
| - host_impl_->sync_tree()->TakePendingPageScaleAnimation().get());
|
| - EXPECT_FALSE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_animate_);
|
| -
|
| - // From here on, make sure the animation runs as normal.
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - host_impl_->Animate(start_time);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_animate_);
|
| -
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - host_impl_->Animate(third_through_animation);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_animate_);
|
| -
|
| - // Another activation shouldn't have any effect on the animation.
|
| - host_impl_->ActivateSyncTree();
|
| -
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - host_impl_->Animate(halfway_through_animation);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_animate_);
|
| -
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - did_request_commit_ = false;
|
| - host_impl_->Animate(end_time);
|
| - EXPECT_TRUE(did_request_commit_);
|
| - EXPECT_FALSE(did_request_animate_);
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - EXPECT_EQ(scroll_info->page_scale_delta, target_scale);
|
| - ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, PageScaleAnimationCompletedNotification) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| -
|
| - LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
|
| - DCHECK(scroll_layer);
|
| -
|
| - base::TimeTicks start_time =
|
| - base::TimeTicks() + base::TimeDelta::FromSeconds(1);
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
|
| - base::TimeTicks halfway_through_animation = start_time + duration / 2;
|
| - base::TimeTicks end_time = start_time + duration;
|
| -
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
|
| - scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
|
| -
|
| - did_complete_page_scale_animation_ = false;
|
| - host_impl_->active_tree()->SetPendingPageScaleAnimation(
|
| - scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
|
| - gfx::Vector2d(), false, 2.f, duration)));
|
| - host_impl_->ActivateSyncTree();
|
| - host_impl_->Animate(start_time);
|
| - EXPECT_FALSE(did_complete_page_scale_animation_);
|
| -
|
| - host_impl_->Animate(halfway_through_animation);
|
| - EXPECT_FALSE(did_complete_page_scale_animation_);
|
| -
|
| - host_impl_->Animate(end_time);
|
| - EXPECT_TRUE(did_complete_page_scale_animation_);
|
| -}
|
| -
|
| -class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
|
| - public:
|
| - LayerTreeHostImplOverridePhysicalTime(
|
| - const LayerTreeSettings& settings,
|
| - LayerTreeHostImplClient* client,
|
| - Proxy* proxy,
|
| - SharedBitmapManager* manager,
|
| - RenderingStatsInstrumentation* rendering_stats_instrumentation)
|
| - : LayerTreeHostImpl(settings,
|
| - client,
|
| - proxy,
|
| - rendering_stats_instrumentation,
|
| - manager,
|
| - NULL,
|
| - NULL,
|
| - 0) {}
|
| -
|
| - BeginFrameArgs CurrentBeginFrameArgs() const override {
|
| - return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
|
| - fake_current_physical_time_);
|
| - }
|
| -
|
| - void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
|
| - fake_current_physical_time_ = fake_now;
|
| - }
|
| -
|
| - private:
|
| - base::TimeTicks fake_current_physical_time_;
|
| -};
|
| -
|
| -class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
|
| - protected:
|
| - void SetupLayers(LayerTreeSettings settings) {
|
| - gfx::Size viewport_size(10, 10);
|
| - gfx::Size content_size(100, 100);
|
| -
|
| - LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
|
| - new LayerTreeHostImplOverridePhysicalTime(settings, this, &proxy_,
|
| - shared_bitmap_manager_.get(),
|
| - &stats_instrumentation_);
|
| - host_impl_ = make_scoped_ptr(host_impl_override_time);
|
| - host_impl_->InitializeRenderer(CreateOutputSurface());
|
| - host_impl_->SetViewportSize(viewport_size);
|
| -
|
| - scoped_ptr<LayerImpl> root =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->SetBounds(viewport_size);
|
| -
|
| - scoped_ptr<LayerImpl> scroll =
|
| - LayerImpl::Create(host_impl_->active_tree(), 2);
|
| - scroll->SetScrollClipLayer(root->id());
|
| - scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
|
| - root->SetBounds(viewport_size);
|
| - scroll->SetBounds(content_size);
|
| - scroll->SetContentBounds(content_size);
|
| - scroll->SetIsContainerForFixedPositionLayers(true);
|
| -
|
| - scoped_ptr<LayerImpl> contents =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - contents->SetDrawsContent(true);
|
| - contents->SetBounds(content_size);
|
| - contents->SetContentBounds(content_size);
|
| -
|
| - scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =
|
| - SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 4,
|
| - VERTICAL, 10, 0, false, true);
|
| - EXPECT_FLOAT_EQ(0.f, scrollbar->opacity());
|
| -
|
| - scroll->AddChild(contents.Pass());
|
| - root->AddChild(scroll.Pass());
|
| - root->SetHasRenderSurface(true);
|
| - scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
|
| - root->AddChild(scrollbar.Pass());
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
|
| - Layer::INVALID_ID);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - DrawFrame();
|
| - }
|
| -
|
| - void RunTest(LayerTreeSettings::ScrollbarAnimator animator) {
|
| - LayerTreeSettings settings;
|
| - settings.scrollbar_animator = animator;
|
| - settings.scrollbar_fade_delay_ms = 20;
|
| - settings.scrollbar_fade_duration_ms = 20;
|
| -
|
| - SetupLayers(settings);
|
| -
|
| - base::TimeTicks fake_now = gfx::FrameTime::Now();
|
| -
|
| - EXPECT_FALSE(did_request_animate_);
|
| - EXPECT_FALSE(did_request_redraw_);
|
| - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
|
| - EXPECT_TRUE(animation_task_.Equals(base::Closure()));
|
| -
|
| - // If no scroll happened during a scroll gesture, it should have no effect.
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_FALSE(did_request_animate_);
|
| - EXPECT_FALSE(did_request_redraw_);
|
| - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
|
| - EXPECT_TRUE(animation_task_.Equals(base::Closure()));
|
| -
|
| - // After a scroll, a scrollbar animation should be scheduled about 20ms from
|
| - // now.
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
|
| - EXPECT_FALSE(did_request_animate_);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - did_request_redraw_ = false;
|
| - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
|
| - EXPECT_TRUE(animation_task_.Equals(base::Closure()));
|
| -
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_FALSE(did_request_animate_);
|
| - EXPECT_FALSE(did_request_redraw_);
|
| - EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
|
| - requested_animation_delay_);
|
| - EXPECT_FALSE(animation_task_.Equals(base::Closure()));
|
| -
|
| - fake_now += requested_animation_delay_;
|
| - requested_animation_delay_ = base::TimeDelta();
|
| - animation_task_.Run();
|
| - animation_task_ = base::Closure();
|
| - EXPECT_TRUE(did_request_animate_);
|
| - did_request_animate_ = false;
|
| - EXPECT_FALSE(did_request_redraw_);
|
| -
|
| - // After the scrollbar animation begins, we should start getting redraws.
|
| - host_impl_->Animate(fake_now);
|
| - EXPECT_TRUE(did_request_animate_);
|
| - did_request_animate_ = false;
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - did_request_redraw_ = false;
|
| - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
|
| - EXPECT_TRUE(animation_task_.Equals(base::Closure()));
|
| -
|
| - // Setting the scroll offset outside a scroll should also cause the
|
| - // scrollbar to appear and to schedule a scrollbar animation.
|
| - host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
|
| - gfx::ScrollOffset(5, 5));
|
| - EXPECT_FALSE(did_request_animate_);
|
| - EXPECT_FALSE(did_request_redraw_);
|
| - EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
|
| - requested_animation_delay_);
|
| - EXPECT_FALSE(animation_task_.Equals(base::Closure()));
|
| - requested_animation_delay_ = base::TimeDelta();
|
| - animation_task_ = base::Closure();
|
| -
|
| - // Scrollbar animation is not triggered unnecessarily.
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
|
| - EXPECT_FALSE(did_request_animate_);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - did_request_redraw_ = false;
|
| - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
|
| - EXPECT_TRUE(animation_task_.Equals(base::Closure()));
|
| -
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_FALSE(did_request_animate_);
|
| - EXPECT_FALSE(did_request_redraw_);
|
| - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
|
| - EXPECT_TRUE(animation_task_.Equals(base::Closure()));
|
| -
|
| - // Changing page scale triggers scrollbar animation.
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
|
| - host_impl_->SetPageScaleOnActiveTree(1.1f);
|
| - EXPECT_FALSE(did_request_animate_);
|
| - EXPECT_FALSE(did_request_redraw_);
|
| - EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
|
| - requested_animation_delay_);
|
| - EXPECT_FALSE(animation_task_.Equals(base::Closure()));
|
| - requested_animation_delay_ = base::TimeDelta();
|
| - animation_task_ = base::Closure();
|
| - }
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTestScrollbarAnimation, LinearFade) {
|
| - RunTest(LayerTreeSettings::LINEAR_FADE);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTestScrollbarAnimation, Thinning) {
|
| - RunTest(LayerTreeSettings::THINNING);
|
| -}
|
| -
|
| -void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
|
| - float device_scale_factor) {
|
| - LayerTreeSettings settings;
|
| - settings.scrollbar_fade_delay_ms = 500;
|
| - settings.scrollbar_fade_duration_ms = 300;
|
| - settings.scrollbar_animator = LayerTreeSettings::THINNING;
|
| -
|
| - gfx::Size viewport_size(300, 200);
|
| - gfx::Size device_viewport_size = gfx::ToFlooredSize(
|
| - gfx::ScaleSize(viewport_size, device_scale_factor));
|
| - gfx::Size content_size(1000, 1000);
|
| -
|
| - CreateHostImpl(settings, CreateOutputSurface());
|
| - host_impl_->SetDeviceScaleFactor(device_scale_factor);
|
| - host_impl_->SetViewportSize(device_viewport_size);
|
| -
|
| - scoped_ptr<LayerImpl> root =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->SetBounds(viewport_size);
|
| - root->SetHasRenderSurface(true);
|
| -
|
| - scoped_ptr<LayerImpl> scroll =
|
| - LayerImpl::Create(host_impl_->active_tree(), 2);
|
| - scroll->SetScrollClipLayer(root->id());
|
| - scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
|
| - scroll->SetBounds(content_size);
|
| - scroll->SetContentBounds(content_size);
|
| - scroll->SetIsContainerForFixedPositionLayers(true);
|
| -
|
| - scoped_ptr<LayerImpl> contents =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - contents->SetDrawsContent(true);
|
| - contents->SetBounds(content_size);
|
| - contents->SetContentBounds(content_size);
|
| -
|
| - // The scrollbar is on the right side.
|
| - scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
|
| - PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
|
| - scrollbar->SetDrawsContent(true);
|
| - scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
|
| - scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
|
| - scrollbar->SetPosition(gfx::Point(285, 0));
|
| -
|
| - scroll->AddChild(contents.Pass());
|
| - root->AddChild(scroll.Pass());
|
| - scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
|
| - root->AddChild(scrollbar.Pass());
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
|
| - Layer::INVALID_ID);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - DrawFrame();
|
| -
|
| - LayerImpl* root_scroll =
|
| - host_impl_->active_tree()->InnerViewportScrollLayer();
|
| - ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
|
| - ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
|
| - static_cast<ScrollbarAnimationControllerThinning*>(
|
| - root_scroll->scrollbar_animation_controller());
|
| - scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
|
| -
|
| - host_impl_->MouseMoveAt(gfx::Point(1, 1));
|
| - EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
|
| -
|
| - host_impl_->MouseMoveAt(gfx::Point(200, 50));
|
| - EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
|
| -
|
| - host_impl_->MouseMoveAt(gfx::Point(184, 100));
|
| - EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
|
| -
|
| - scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
|
| - host_impl_->MouseMoveAt(gfx::Point(184, 100));
|
| - EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
|
| -
|
| - did_request_redraw_ = false;
|
| - EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
|
| - host_impl_->MouseMoveAt(gfx::Point(290, 100));
|
| - EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
|
| - host_impl_->MouseMoveAt(gfx::Point(290, 120));
|
| - EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
|
| - host_impl_->MouseMoveAt(gfx::Point(150, 120));
|
| - EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
|
| - SetupMouseMoveAtWithDeviceScale(1.f);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
|
| - SetupMouseMoveAtWithDeviceScale(2.f);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
|
| - DrawFrame();
|
| - {
|
| - CompositorFrameMetadata metadata =
|
| - host_impl_->MakeCompositorFrameMetadata();
|
| - EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
|
| - EXPECT_EQ(1.f, metadata.page_scale_factor);
|
| - EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size);
|
| - EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
|
| - EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
|
| - EXPECT_EQ(4.f, metadata.max_page_scale_factor);
|
| - EXPECT_FALSE(metadata.root_overflow_x_hidden);
|
| - EXPECT_FALSE(metadata.root_overflow_y_hidden);
|
| - }
|
| -
|
| - // Scrolling should update metadata immediately.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
|
| - {
|
| - CompositorFrameMetadata metadata =
|
| - host_impl_->MakeCompositorFrameMetadata();
|
| - EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
|
| - }
|
| - host_impl_->ScrollEnd();
|
| - {
|
| - CompositorFrameMetadata metadata =
|
| - host_impl_->MakeCompositorFrameMetadata();
|
| - EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
|
| - }
|
| -
|
| - // Root "overflow: hidden" properties should be reflected.
|
| - {
|
| - host_impl_->active_tree()
|
| - ->InnerViewportScrollLayer()
|
| - ->set_user_scrollable_horizontal(false);
|
| - CompositorFrameMetadata metadata =
|
| - host_impl_->MakeCompositorFrameMetadata();
|
| - EXPECT_TRUE(metadata.root_overflow_x_hidden);
|
| - EXPECT_FALSE(metadata.root_overflow_y_hidden);
|
| -
|
| - host_impl_->active_tree()
|
| - ->InnerViewportScrollLayer()
|
| - ->set_user_scrollable_vertical(false);
|
| - metadata = host_impl_->MakeCompositorFrameMetadata();
|
| - EXPECT_TRUE(metadata.root_overflow_x_hidden);
|
| - EXPECT_TRUE(metadata.root_overflow_y_hidden);
|
| - }
|
| -
|
| - // Page scale should update metadata correctly (shrinking only the viewport).
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
|
| - host_impl_->PinchGestureBegin();
|
| - host_impl_->PinchGestureUpdate(2.f, gfx::Point());
|
| - host_impl_->PinchGestureEnd();
|
| - host_impl_->ScrollEnd();
|
| - {
|
| - CompositorFrameMetadata metadata =
|
| - host_impl_->MakeCompositorFrameMetadata();
|
| - EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
|
| - EXPECT_EQ(2.f, metadata.page_scale_factor);
|
| - EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size);
|
| - EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
|
| - EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
|
| - EXPECT_EQ(4.f, metadata.max_page_scale_factor);
|
| - }
|
| -
|
| - // Likewise if set from the main thread.
|
| - host_impl_->ProcessScrollDeltas();
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(4.f, 0.5f, 4.f);
|
| - host_impl_->SetPageScaleOnActiveTree(4.f);
|
| - {
|
| - CompositorFrameMetadata metadata =
|
| - host_impl_->MakeCompositorFrameMetadata();
|
| - EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
|
| - EXPECT_EQ(4.f, metadata.page_scale_factor);
|
| - EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size);
|
| - EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
|
| - EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
|
| - EXPECT_EQ(4.f, metadata.max_page_scale_factor);
|
| - }
|
| -}
|
| -
|
| -class DidDrawCheckLayer : public LayerImpl {
|
| - public:
|
| - static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
|
| - return make_scoped_ptr(new DidDrawCheckLayer(tree_impl, id));
|
| - }
|
| -
|
| - bool WillDraw(DrawMode draw_mode, ResourceProvider* provider) override {
|
| - will_draw_called_ = true;
|
| - if (will_draw_returns_false_)
|
| - return false;
|
| - return LayerImpl::WillDraw(draw_mode, provider);
|
| - }
|
| -
|
| - void AppendQuads(RenderPass* render_pass,
|
| - AppendQuadsData* append_quads_data) override {
|
| - append_quads_called_ = true;
|
| - LayerImpl::AppendQuads(render_pass, append_quads_data);
|
| - }
|
| -
|
| - void DidDraw(ResourceProvider* provider) override {
|
| - did_draw_called_ = true;
|
| - LayerImpl::DidDraw(provider);
|
| - }
|
| -
|
| - bool will_draw_called() const { return will_draw_called_; }
|
| - 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() {
|
| - will_draw_called_ = false;
|
| - append_quads_called_ = false;
|
| - did_draw_called_ = false;
|
| - }
|
| -
|
| - static void IgnoreResult(scoped_ptr<CopyOutputResult> result) {}
|
| -
|
| - void AddCopyRequest() {
|
| - ScopedPtrVector<CopyOutputRequest> requests;
|
| - requests.push_back(
|
| - CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult)));
|
| - SetHasRenderSurface(true);
|
| - PassCopyRequests(&requests);
|
| - }
|
| -
|
| - protected:
|
| - DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
|
| - : LayerImpl(tree_impl, id),
|
| - will_draw_returns_false_(false),
|
| - will_draw_called_(false),
|
| - append_quads_called_(false),
|
| - did_draw_called_(false) {
|
| - SetBounds(gfx::Size(10, 10));
|
| - SetContentBounds(gfx::Size(10, 10));
|
| - SetDrawsContent(true);
|
| - draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
|
| - }
|
| -
|
| - private:
|
| - bool will_draw_returns_false_;
|
| - bool will_draw_called_;
|
| - bool append_quads_called_;
|
| - bool did_draw_called_;
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
|
| - // The root layer is always drawn, so run this test on a child layer that
|
| - // will be masked out by the root layer's bounds.
|
| - host_impl_->active_tree()->SetRootLayer(
|
| - DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
|
| - DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
|
| - host_impl_->active_tree()->root_layer());
|
| -
|
| - root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
|
| - root->SetHasRenderSurface(true);
|
| - DidDrawCheckLayer* layer =
|
| - static_cast<DidDrawCheckLayer*>(root->children()[0]);
|
| -
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - EXPECT_TRUE(layer->will_draw_called());
|
| - EXPECT_TRUE(layer->append_quads_called());
|
| - EXPECT_TRUE(layer->did_draw_called());
|
| - }
|
| -
|
| - host_impl_->SetViewportDamage(gfx::Rect(10, 10));
|
| -
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| -
|
| - layer->set_will_draw_returns_false();
|
| - layer->ClearDidDrawCheck();
|
| -
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - EXPECT_TRUE(layer->will_draw_called());
|
| - EXPECT_FALSE(layer->append_quads_called());
|
| - EXPECT_FALSE(layer->did_draw_called());
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
|
| - // The root layer is always drawn, so run this test on a child layer that
|
| - // will be masked out by the root layer's bounds.
|
| - host_impl_->active_tree()->SetRootLayer(
|
| - DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
|
| - DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
|
| - host_impl_->active_tree()->root_layer());
|
| - root->SetMasksToBounds(true);
|
| - root->SetHasRenderSurface(true);
|
| - root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
|
| - DidDrawCheckLayer* layer =
|
| - static_cast<DidDrawCheckLayer*>(root->children()[0]);
|
| - // Ensure visible_content_rect for layer is empty.
|
| - layer->SetPosition(gfx::PointF(100.f, 100.f));
|
| - layer->SetBounds(gfx::Size(10, 10));
|
| - layer->SetContentBounds(gfx::Size(10, 10));
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| -
|
| - EXPECT_FALSE(layer->will_draw_called());
|
| - EXPECT_FALSE(layer->did_draw_called());
|
| -
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - EXPECT_FALSE(layer->will_draw_called());
|
| - EXPECT_FALSE(layer->did_draw_called());
|
| -
|
| - EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
|
| -
|
| - // Ensure visible_content_rect for layer is not empty
|
| - layer->SetPosition(gfx::PointF());
|
| -
|
| - EXPECT_FALSE(layer->will_draw_called());
|
| - EXPECT_FALSE(layer->did_draw_called());
|
| -
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - EXPECT_TRUE(layer->will_draw_called());
|
| - EXPECT_TRUE(layer->did_draw_called());
|
| -
|
| - EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
|
| - gfx::Size big_size(1000, 1000);
|
| - host_impl_->SetViewportSize(big_size);
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(
|
| - DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
|
| - DidDrawCheckLayer* root =
|
| - static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
|
| -
|
| - root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
|
| - DidDrawCheckLayer* occluded_layer =
|
| - static_cast<DidDrawCheckLayer*>(root->children()[0]);
|
| -
|
| - root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
|
| - root->SetHasRenderSurface(true);
|
| - DidDrawCheckLayer* top_layer =
|
| - static_cast<DidDrawCheckLayer*>(root->children()[1]);
|
| - // This layer covers the occluded_layer above. Make this layer large so it can
|
| - // occlude.
|
| - top_layer->SetBounds(big_size);
|
| - top_layer->SetContentBounds(big_size);
|
| - top_layer->SetContentsOpaque(true);
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| -
|
| - EXPECT_FALSE(occluded_layer->will_draw_called());
|
| - EXPECT_FALSE(occluded_layer->did_draw_called());
|
| - EXPECT_FALSE(top_layer->will_draw_called());
|
| - EXPECT_FALSE(top_layer->did_draw_called());
|
| -
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - EXPECT_FALSE(occluded_layer->will_draw_called());
|
| - EXPECT_FALSE(occluded_layer->did_draw_called());
|
| - EXPECT_TRUE(top_layer->will_draw_called());
|
| - EXPECT_TRUE(top_layer->did_draw_called());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
|
| - host_impl_->active_tree()->SetRootLayer(
|
| - DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
|
| - DidDrawCheckLayer* root =
|
| - static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
|
| -
|
| - root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
|
| - root->SetHasRenderSurface(true);
|
| - DidDrawCheckLayer* layer1 =
|
| - static_cast<DidDrawCheckLayer*>(root->children()[0]);
|
| -
|
| - layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
|
| - DidDrawCheckLayer* layer2 =
|
| - static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
|
| -
|
| - layer1->SetHasRenderSurface(true);
|
| - layer1->SetShouldFlattenTransform(true);
|
| -
|
| - EXPECT_FALSE(root->did_draw_called());
|
| - EXPECT_FALSE(layer1->did_draw_called());
|
| - EXPECT_FALSE(layer2->did_draw_called());
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
|
| - host_impl_->active_tree()->root_layer());
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - EXPECT_TRUE(root->did_draw_called());
|
| - EXPECT_TRUE(layer1->did_draw_called());
|
| - EXPECT_TRUE(layer2->did_draw_called());
|
| -
|
| - EXPECT_NE(root->render_surface(), layer1->render_surface());
|
| - EXPECT_TRUE(!!layer1->render_surface());
|
| -}
|
| -
|
| -class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
|
| - public:
|
| - static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
|
| - int id,
|
| - bool tile_missing,
|
| - bool had_incomplete_tile,
|
| - bool animating,
|
| - ResourceProvider* resource_provider) {
|
| - return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl,
|
| - id,
|
| - tile_missing,
|
| - had_incomplete_tile,
|
| - animating,
|
| - resource_provider));
|
| - }
|
| -
|
| - void AppendQuads(RenderPass* render_pass,
|
| - AppendQuadsData* append_quads_data) override {
|
| - LayerImpl::AppendQuads(render_pass, append_quads_data);
|
| - if (had_incomplete_tile_)
|
| - append_quads_data->num_incomplete_tiles++;
|
| - if (tile_missing_)
|
| - append_quads_data->num_missing_tiles++;
|
| - }
|
| -
|
| - private:
|
| - MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
|
| - int id,
|
| - bool tile_missing,
|
| - bool had_incomplete_tile,
|
| - bool animating,
|
| - ResourceProvider* resource_provider)
|
| - : DidDrawCheckLayer(tree_impl, id),
|
| - tile_missing_(tile_missing),
|
| - had_incomplete_tile_(had_incomplete_tile) {
|
| - if (animating)
|
| - AddAnimatedTransformToLayer(this, 10.0, 3, 0);
|
| - }
|
| -
|
| - bool tile_missing_;
|
| - bool had_incomplete_tile_;
|
| -};
|
| -
|
| -struct PrepareToDrawSuccessTestCase {
|
| - struct State {
|
| - bool has_missing_tile = false;
|
| - bool has_incomplete_tile = false;
|
| - bool is_animating = false;
|
| - bool has_copy_request = false;
|
| - };
|
| - bool high_res_required = false;
|
| - State layer_before;
|
| - State layer_between;
|
| - State layer_after;
|
| - DrawResult expected_result;
|
| -
|
| - explicit PrepareToDrawSuccessTestCase(DrawResult result)
|
| - : expected_result(result) {}
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) {
|
| - std::vector<PrepareToDrawSuccessTestCase> cases;
|
| -
|
| - // 0. Default case.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - // 1. Animated layer first.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().layer_before.is_animating = true;
|
| - // 2. Animated layer between.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().layer_between.is_animating = true;
|
| - // 3. Animated layer last.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().layer_after.is_animating = true;
|
| - // 4. Missing tile first.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().layer_before.has_missing_tile = true;
|
| - // 5. Missing tile between.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().layer_between.has_missing_tile = true;
|
| - // 6. Missing tile last.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().layer_after.has_missing_tile = true;
|
| - // 7. Incomplete tile first.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().layer_before.has_incomplete_tile = true;
|
| - // 8. Incomplete tile between.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().layer_between.has_incomplete_tile = true;
|
| - // 9. Incomplete tile last.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().layer_after.has_incomplete_tile = true;
|
| - // 10. Animation with missing tile.
|
| - cases.push_back(
|
| - PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS));
|
| - cases.back().layer_between.has_missing_tile = true;
|
| - cases.back().layer_between.is_animating = true;
|
| - // 11. Animation with missing tile and copy request after. Must succeed
|
| - // because the animation checkerboard means we'll get a new frame and the copy
|
| - // request's layer may be destroyed.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().layer_between.has_missing_tile = true;
|
| - cases.back().layer_between.is_animating = true;
|
| - cases.back().layer_after.has_copy_request = true;
|
| - // 12. Animation with missing tile and copy request before. Must succeed
|
| - // because the animation checkerboard means we'll get a new frame and the copy
|
| - // request's layer may be destroyed.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().layer_between.has_missing_tile = true;
|
| - cases.back().layer_between.is_animating = true;
|
| - cases.back().layer_before.has_copy_request = true;
|
| - // 13. Animation with incomplete tile.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().layer_between.has_incomplete_tile = true;
|
| - cases.back().layer_between.is_animating = true;
|
| -
|
| - // 14. High res required.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().high_res_required = true;
|
| - // 15. High res required with incomplete tile.
|
| - cases.push_back(
|
| - PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
|
| - cases.back().high_res_required = true;
|
| - cases.back().layer_between.has_incomplete_tile = true;
|
| - // 16. High res required with missing tile.
|
| - cases.push_back(
|
| - PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
|
| - cases.back().high_res_required = true;
|
| - cases.back().layer_between.has_missing_tile = true;
|
| -
|
| - // 17. High res required is higher priority than animating missing tiles.
|
| - cases.push_back(
|
| - PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
|
| - cases.back().high_res_required = true;
|
| - cases.back().layer_between.has_missing_tile = true;
|
| - cases.back().layer_after.has_missing_tile = true;
|
| - cases.back().layer_after.is_animating = true;
|
| - // 18. High res required is higher priority than animating missing tiles.
|
| - cases.push_back(
|
| - PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
|
| - cases.back().high_res_required = true;
|
| - cases.back().layer_between.has_missing_tile = true;
|
| - cases.back().layer_before.has_missing_tile = true;
|
| - cases.back().layer_before.is_animating = true;
|
| -
|
| - // 19. High res required is higher priority than copy requests.
|
| - cases.push_back(
|
| - PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
|
| - cases.back().high_res_required = true;
|
| - cases.back().layer_between.has_missing_tile = true;
|
| - cases.back().layer_after.has_copy_request = true;
|
| - // 20. High res required is higher priority than copy requests.
|
| - cases.push_back(
|
| - PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
|
| - cases.back().high_res_required = true;
|
| - cases.back().layer_between.has_missing_tile = true;
|
| - cases.back().layer_before.has_copy_request = true;
|
| - // 21. High res required is higher priority than copy requests.
|
| - cases.push_back(
|
| - PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
|
| - cases.back().high_res_required = true;
|
| - cases.back().layer_between.has_missing_tile = true;
|
| - cases.back().layer_between.has_copy_request = true;
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(
|
| - DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
|
| - DidDrawCheckLayer* root =
|
| - static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
|
| - root->SetHasRenderSurface(true);
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - host_impl_->SwapBuffers(frame);
|
| -
|
| - for (size_t i = 0; i < cases.size(); ++i) {
|
| - const auto& testcase = cases[i];
|
| - std::vector<LayerImpl*> to_remove;
|
| - for (auto* child : root->children())
|
| - to_remove.push_back(child);
|
| - for (auto* child : to_remove)
|
| - root->RemoveChild(child);
|
| -
|
| - std::ostringstream scope;
|
| - scope << "Test case: " << i;
|
| - SCOPED_TRACE(scope.str());
|
| -
|
| - root->AddChild(MissingTextureAnimatingLayer::Create(
|
| - host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
|
| - testcase.layer_before.has_incomplete_tile,
|
| - testcase.layer_before.is_animating, host_impl_->resource_provider()));
|
| - DidDrawCheckLayer* before =
|
| - static_cast<DidDrawCheckLayer*>(root->children().back());
|
| - if (testcase.layer_before.has_copy_request)
|
| - before->AddCopyRequest();
|
| -
|
| - root->AddChild(MissingTextureAnimatingLayer::Create(
|
| - host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
|
| - testcase.layer_between.has_incomplete_tile,
|
| - testcase.layer_between.is_animating, host_impl_->resource_provider()));
|
| - DidDrawCheckLayer* between =
|
| - static_cast<DidDrawCheckLayer*>(root->children().back());
|
| - if (testcase.layer_between.has_copy_request)
|
| - between->AddCopyRequest();
|
| -
|
| - root->AddChild(MissingTextureAnimatingLayer::Create(
|
| - host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
|
| - testcase.layer_after.has_incomplete_tile,
|
| - testcase.layer_after.is_animating, host_impl_->resource_provider()));
|
| - DidDrawCheckLayer* after =
|
| - static_cast<DidDrawCheckLayer*>(root->children().back());
|
| - if (testcase.layer_after.has_copy_request)
|
| - after->AddCopyRequest();
|
| -
|
| - if (testcase.high_res_required)
|
| - host_impl_->SetRequiresHighResToDraw();
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - host_impl_->SwapBuffers(frame);
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest,
|
| - PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame) {
|
| - CreateHostImpl(DefaultSettings(),
|
| - FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
|
| - EXPECT_TRUE(host_impl_->output_surface()
|
| - ->capabilities()
|
| - .draw_and_swap_full_viewport_every_frame);
|
| -
|
| - std::vector<PrepareToDrawSuccessTestCase> cases;
|
| -
|
| - // 0. Default case.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - // 1. Animation with missing tile.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().layer_between.has_missing_tile = true;
|
| - cases.back().layer_between.is_animating = true;
|
| - // 2. High res required with incomplete tile.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().high_res_required = true;
|
| - cases.back().layer_between.has_incomplete_tile = true;
|
| - // 3. High res required with missing tile.
|
| - cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
|
| - cases.back().high_res_required = true;
|
| - cases.back().layer_between.has_missing_tile = true;
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(
|
| - DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
|
| - DidDrawCheckLayer* root =
|
| - static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
|
| - root->SetHasRenderSurface(true);
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - host_impl_->SwapBuffers(frame);
|
| -
|
| - for (size_t i = 0; i < cases.size(); ++i) {
|
| - const auto& testcase = cases[i];
|
| - std::vector<LayerImpl*> to_remove;
|
| - for (auto* child : root->children())
|
| - to_remove.push_back(child);
|
| - for (auto* child : to_remove)
|
| - root->RemoveChild(child);
|
| -
|
| - std::ostringstream scope;
|
| - scope << "Test case: " << i;
|
| - SCOPED_TRACE(scope.str());
|
| -
|
| - root->AddChild(MissingTextureAnimatingLayer::Create(
|
| - host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
|
| - testcase.layer_before.has_incomplete_tile,
|
| - testcase.layer_before.is_animating, host_impl_->resource_provider()));
|
| - DidDrawCheckLayer* before =
|
| - static_cast<DidDrawCheckLayer*>(root->children().back());
|
| - if (testcase.layer_before.has_copy_request)
|
| - before->AddCopyRequest();
|
| -
|
| - root->AddChild(MissingTextureAnimatingLayer::Create(
|
| - host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
|
| - testcase.layer_between.has_incomplete_tile,
|
| - testcase.layer_between.is_animating, host_impl_->resource_provider()));
|
| - DidDrawCheckLayer* between =
|
| - static_cast<DidDrawCheckLayer*>(root->children().back());
|
| - if (testcase.layer_between.has_copy_request)
|
| - between->AddCopyRequest();
|
| -
|
| - root->AddChild(MissingTextureAnimatingLayer::Create(
|
| - host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
|
| - testcase.layer_after.has_incomplete_tile,
|
| - testcase.layer_after.is_animating, host_impl_->resource_provider()));
|
| - DidDrawCheckLayer* after =
|
| - static_cast<DidDrawCheckLayer*>(root->children().back());
|
| - if (testcase.layer_after.has_copy_request)
|
| - after->AddCopyRequest();
|
| -
|
| - if (testcase.high_res_required)
|
| - host_impl_->SetRequiresHighResToDraw();
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - host_impl_->SwapBuffers(frame);
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
|
| - scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->SetScrollClipLayer(Layer::INVALID_ID);
|
| - root->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - DrawFrame();
|
| -
|
| - // Scroll event is ignored because layer is not scrollable.
|
| - EXPECT_EQ(InputHandler::SCROLL_IGNORED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - EXPECT_FALSE(did_request_redraw_);
|
| - EXPECT_FALSE(did_request_commit_);
|
| -}
|
| -
|
| -// TODO(bokan): Convert these tests to create inner and outer viewports.
|
| -class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
|
| - public:
|
| - LayerTreeHostImplTopControlsTest()
|
| - // Make the clip size the same as the layer (content) size so the layer is
|
| - // non-scrollable.
|
| - : layer_size_(10, 10),
|
| - clip_size_(layer_size_),
|
| - top_controls_height_(50) {
|
| - settings_.use_pinch_virtual_viewport = true;
|
| -
|
| - viewport_size_ = gfx::Size(clip_size_.width(),
|
| - clip_size_.height() + top_controls_height_);
|
| - }
|
| -
|
| - bool CreateHostImpl(const LayerTreeSettings& settings,
|
| - scoped_ptr<OutputSurface> output_surface) override {
|
| - bool init =
|
| - LayerTreeHostImplTest::CreateHostImpl(settings, output_surface.Pass());
|
| - if (init) {
|
| - host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
|
| - host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
|
| - }
|
| - return init;
|
| - }
|
| -
|
| - void SetupTopControlsAndScrollLayer() {
|
| - scoped_ptr<LayerImpl> root =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - scoped_ptr<LayerImpl> root_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 2);
|
| - root_clip->SetBounds(clip_size_);
|
| - root->SetScrollClipLayer(root_clip->id());
|
| - root->SetBounds(layer_size_);
|
| - root->SetContentBounds(layer_size_);
|
| - root->SetPosition(gfx::PointF());
|
| - root->SetDrawsContent(false);
|
| - root->SetIsContainerForFixedPositionLayers(true);
|
| - int inner_viewport_scroll_layer_id = root->id();
|
| - int page_scale_layer_id = root_clip->id();
|
| - root_clip->SetHasRenderSurface(true);
|
| - root_clip->AddChild(root.Pass());
|
| - root_clip->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(
|
| - Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
|
| - Layer::INVALID_ID);
|
| - // Set a viewport size that is large enough to contain both the top controls
|
| - // and some content.
|
| - host_impl_->SetViewportSize(viewport_size_);
|
| - host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
|
| -
|
| - host_impl_->DidChangeTopControlsPosition();
|
| -
|
| - host_impl_->CreatePendingTree();
|
| - host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
|
| - root =
|
| - LayerImpl::Create(host_impl_->sync_tree(), 1);
|
| - root_clip =
|
| - LayerImpl::Create(host_impl_->sync_tree(), 2);
|
| - root_clip->SetBounds(clip_size_);
|
| - root->SetScrollClipLayer(root_clip->id());
|
| - root->SetBounds(layer_size_);
|
| - root->SetContentBounds(layer_size_);
|
| - root->SetPosition(gfx::PointF());
|
| - root->SetDrawsContent(false);
|
| - root->SetIsContainerForFixedPositionLayers(true);
|
| - inner_viewport_scroll_layer_id = root->id();
|
| - page_scale_layer_id = root_clip->id();
|
| - root_clip->AddChild(root.Pass());
|
| - host_impl_->sync_tree()->SetRootLayer(root_clip.Pass());
|
| - host_impl_->sync_tree()->SetViewportLayersFromIds(
|
| - Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
|
| - Layer::INVALID_ID);
|
| - // Set a viewport size that is large enough to contain both the top controls
|
| - // and some content.
|
| - host_impl_->SetViewportSize(viewport_size_);
|
| - host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
|
| - host_impl_->DidChangeTopControlsPosition();
|
| - }
|
| -
|
| - void SetupTopControlsAndScrollLayerWithVirtualViewport(
|
| - const gfx::Size& inner_viewport_size,
|
| - const gfx::Size& outer_viewport_size,
|
| - const gfx::Size& scroll_layer_size) {
|
| - CreateHostImpl(settings_, CreateOutputSurface());
|
| - host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
|
| - host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
|
| - host_impl_->DidChangeTopControlsPosition();
|
| -
|
| - scoped_ptr<LayerImpl> root =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - scoped_ptr<LayerImpl> root_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 2);
|
| - scoped_ptr<LayerImpl> page_scale =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| -
|
| - scoped_ptr<LayerImpl> outer_scroll =
|
| - LayerImpl::Create(host_impl_->active_tree(), 4);
|
| - scoped_ptr<LayerImpl> outer_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 5);
|
| -
|
| - root_clip->SetBounds(inner_viewport_size);
|
| - root->SetScrollClipLayer(root_clip->id());
|
| - root->SetBounds(outer_viewport_size);
|
| - root->SetContentBounds(outer_viewport_size);
|
| - root->SetPosition(gfx::PointF());
|
| - root->SetDrawsContent(false);
|
| - root->SetIsContainerForFixedPositionLayers(true);
|
| - root_clip->SetHasRenderSurface(true);
|
| - outer_clip->SetBounds(outer_viewport_size);
|
| - outer_scroll->SetScrollClipLayer(outer_clip->id());
|
| - outer_scroll->SetBounds(scroll_layer_size);
|
| - outer_scroll->SetContentBounds(scroll_layer_size);
|
| - outer_scroll->SetPosition(gfx::PointF());
|
| - outer_scroll->SetDrawsContent(false);
|
| - outer_scroll->SetIsContainerForFixedPositionLayers(true);
|
| -
|
| - int inner_viewport_scroll_layer_id = root->id();
|
| - int outer_viewport_scroll_layer_id = outer_scroll->id();
|
| - int page_scale_layer_id = page_scale->id();
|
| -
|
| - outer_clip->AddChild(outer_scroll.Pass());
|
| - root->AddChild(outer_clip.Pass());
|
| - page_scale->AddChild(root.Pass());
|
| - root_clip->AddChild(page_scale.Pass());
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(
|
| - Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
|
| - outer_viewport_scroll_layer_id);
|
| -
|
| - host_impl_->SetViewportSize(inner_viewport_size);
|
| - LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
|
| - EXPECT_EQ(inner_viewport_size, root_clip_ptr->bounds());
|
| - }
|
| -
|
| - protected:
|
| - gfx::Size layer_size_;
|
| - gfx::Size clip_size_;
|
| - gfx::Size viewport_size_;
|
| - float top_controls_height_;
|
| -
|
| - LayerTreeSettings settings_;
|
| -}; // class LayerTreeHostImplTopControlsTest
|
| -
|
| -TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
|
| - SetupTopControlsAndScrollLayerWithVirtualViewport(
|
| - gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| -
|
| - // Make the test scroll delta a fractional amount, to verify that the
|
| - // fixed container size delta is (1) non-zero, and (2) fractional, and
|
| - // (3) matches the movement of the top controls.
|
| - gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
|
| - host_impl_->top_controls_manager()->ScrollBegin();
|
| - host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
|
| - host_impl_->top_controls_manager()->ScrollEnd();
|
| -
|
| - LayerImpl* inner_viewport_scroll_layer =
|
| - host_impl_->active_tree()->InnerViewportScrollLayer();
|
| - DCHECK(inner_viewport_scroll_layer);
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(),
|
| - inner_viewport_scroll_layer->FixedContainerSizeDelta().y());
|
| -}
|
| -
|
| -// In this test, the outer viewport is initially unscrollable. We test that a
|
| -// scroll initiated on the inner viewport, causing the top controls to show and
|
| -// thus making the outer viewport scrollable, still scrolls the outer viewport.
|
| -TEST_F(LayerTreeHostImplTopControlsTest,
|
| - TopControlsOuterViewportBecomesScrollable) {
|
| - SetupTopControlsAndScrollLayerWithVirtualViewport(
|
| - gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
|
| - DrawFrame();
|
| -
|
| - LayerImpl *inner_scroll =
|
| - host_impl_->active_tree()->InnerViewportScrollLayer();
|
| - LayerImpl *inner_container =
|
| - host_impl_->active_tree()->InnerViewportContainerLayer();
|
| - LayerImpl *outer_scroll =
|
| - host_impl_->active_tree()->OuterViewportScrollLayer();
|
| - LayerImpl *outer_container =
|
| - host_impl_->active_tree()->OuterViewportContainerLayer();
|
| -
|
| - // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
|
| - outer_scroll->SetDrawsContent(true);
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 1.f, 2.f);
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 50.f));
|
| -
|
| - // The entire scroll delta should have been used to hide the top controls.
|
| - // The viewport layers should be resized back to their full sizes.
|
| - EXPECT_EQ(0.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
|
| - EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
|
| - EXPECT_EQ(100.f, inner_container->BoundsForScrolling().height());
|
| - EXPECT_EQ(100.f, outer_container->BoundsForScrolling().height());
|
| -
|
| - // The inner viewport should be scrollable by 50px * page_scale.
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 100.f));
|
| - EXPECT_EQ(50.f, inner_scroll->CurrentScrollOffset().y());
|
| - EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
|
| - EXPECT_EQ(gfx::ScrollOffset(), outer_scroll->MaxScrollOffset());
|
| -
|
| - host_impl_->ScrollEnd();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
|
| -
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
|
| -
|
| - // The entire scroll delta should have been used to show the top controls.
|
| - // The outer viewport should be resized to accomodate and scrolled to the
|
| - // bottom of the document to keep the viewport in place.
|
| - EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
|
| - EXPECT_EQ(50.f, outer_container->BoundsForScrolling().height());
|
| - EXPECT_EQ(50.f, inner_container->BoundsForScrolling().height());
|
| - EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y());
|
| - EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
|
| -
|
| - // Now when we continue scrolling, make sure the outer viewport gets scrolled
|
| - // since it wasn't scrollable when the scroll began.
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -20.f));
|
| - EXPECT_EQ(15.f, outer_scroll->CurrentScrollOffset().y());
|
| - EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
|
| -
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -30.f));
|
| - EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
|
| - EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
|
| -
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
|
| - host_impl_->ScrollEnd();
|
| -
|
| - EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
|
| - EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
|
| -}
|
| -
|
| -// Test that the fixed position container delta is appropriately adjusted
|
| -// by the top controls showing/hiding and page scale doesn't affect it.
|
| -TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
|
| - SetupTopControlsAndScrollLayerWithVirtualViewport(
|
| - gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
|
| - DrawFrame();
|
| -
|
| - float page_scale = 1.5f;
|
| - LayerImpl* outer_viewport_scroll_layer =
|
| - host_impl_->active_tree()->OuterViewportScrollLayer();
|
| -
|
| - // Zoom in, since the fixed container is the outer viewport, the delta should
|
| - // not be scaled.
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f);
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| -
|
| - // Scroll down, the top controls hiding should expand the viewport size so
|
| - // the delta should be equal to the scroll distance.
|
| - gfx::Vector2dF top_controls_scroll_delta(0.f, 20.f);
|
| - host_impl_->top_controls_manager()->ScrollBegin();
|
| - host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
|
| - EXPECT_FLOAT_EQ(top_controls_height_ - top_controls_scroll_delta.y(),
|
| - host_impl_->top_controls_manager()->ContentTopOffset());
|
| - EXPECT_VECTOR_EQ(top_controls_scroll_delta,
|
| - outer_viewport_scroll_layer->FixedContainerSizeDelta());
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // Scroll past the maximum extent. The delta shouldn't be greater than the
|
| - // top controls height.
|
| - host_impl_->top_controls_manager()->ScrollBegin();
|
| - host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
|
| - host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
|
| - host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
|
| - EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_),
|
| - outer_viewport_scroll_layer->FixedContainerSizeDelta());
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // Scroll in the direction to make the top controls show.
|
| - host_impl_->top_controls_manager()->ScrollBegin();
|
| - host_impl_->top_controls_manager()->ScrollBy(-top_controls_scroll_delta);
|
| - EXPECT_EQ(top_controls_scroll_delta.y(),
|
| - host_impl_->top_controls_manager()->ContentTopOffset());
|
| - EXPECT_VECTOR_EQ(
|
| - gfx::Vector2dF(0, top_controls_height_ - top_controls_scroll_delta.y()),
|
| - outer_viewport_scroll_layer->FixedContainerSizeDelta());
|
| - host_impl_->top_controls_manager()->ScrollEnd();
|
| -}
|
| -
|
| -// Test that if a scrollable sublayer doesn't consume the scroll,
|
| -// top controls should hide when scrolling down.
|
| -TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollableSublayer) {
|
| - gfx::Size sub_content_size(100, 400);
|
| - gfx::Size sub_content_layer_size(100, 300);
|
| - SetupTopControlsAndScrollLayerWithVirtualViewport(
|
| - gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
|
| - DrawFrame();
|
| -
|
| - // Show top controls
|
| - EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
|
| -
|
| - LayerImpl* outer_viewport_scroll_layer =
|
| - host_impl_->active_tree()->OuterViewportScrollLayer();
|
| - int id = outer_viewport_scroll_layer->id();
|
| -
|
| - scoped_ptr<LayerImpl> child =
|
| - LayerImpl::Create(host_impl_->active_tree(), id + 2);
|
| - scoped_ptr<LayerImpl> child_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), id + 3);
|
| -
|
| - child_clip->SetBounds(sub_content_layer_size);
|
| - child->SetScrollClipLayer(child_clip->id());
|
| - child->SetBounds(sub_content_size);
|
| - child->SetContentBounds(sub_content_size);
|
| - child->SetPosition(gfx::PointF());
|
| - child->SetDrawsContent(true);
|
| - child->SetIsContainerForFixedPositionLayers(true);
|
| -
|
| - // scroll child to limit
|
| - child->SetScrollDelta(gfx::Vector2dF(0, 100.f));
|
| - child_clip->AddChild(child.Pass());
|
| - outer_viewport_scroll_layer->AddChild(child_clip.Pass());
|
| -
|
| - // Scroll 25px to hide top controls
|
| - gfx::Vector2dF scroll_delta(0.f, 25.f);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // Top controls should be hidden
|
| - EXPECT_EQ(scroll_delta.y(),
|
| - top_controls_height_ -
|
| - host_impl_->top_controls_manager()->ContentTopOffset());
|
| -}
|
| -
|
| -// Ensure setting the top controls position explicitly using the setters on the
|
| -// TreeImpl correctly affects the top controls manager and viewport bounds.
|
| -TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) {
|
| - CreateHostImpl(settings_, CreateOutputSurface());
|
| - SetupTopControlsAndScrollLayer();
|
| - DrawFrame();
|
| -
|
| - host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
|
| - host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
|
| - 30.f / top_controls_height_);
|
| - host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
|
| - EXPECT_FLOAT_EQ(30.f, host_impl_->top_controls_manager()->ContentTopOffset());
|
| - EXPECT_FLOAT_EQ(-20.f,
|
| - host_impl_->top_controls_manager()->ControlsTopOffset());
|
| -
|
| - host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
|
| - EXPECT_FLOAT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
|
| - EXPECT_FLOAT_EQ(-50.f,
|
| - host_impl_->top_controls_manager()->ControlsTopOffset());
|
| -
|
| - host_impl_->DidChangeTopControlsPosition();
|
| -
|
| - // Now that top controls have moved, expect the clip to resize.
|
| - LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
|
| - EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
|
| -}
|
| -
|
| -// Test that the top_controls delta and sent delta are appropriately
|
| -// applied on sync tree activation. The total top controls offset shouldn't
|
| -// change after the activation.
|
| -TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) {
|
| - CreateHostImpl(settings_, CreateOutputSurface());
|
| - SetupTopControlsAndScrollLayer();
|
| - DrawFrame();
|
| -
|
| - host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
|
| - 20.f / top_controls_height_);
|
| - host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
|
| - host_impl_->active_tree()->SetCurrentTopControlsShownRatio(
|
| - 15.f / top_controls_height_);
|
| - host_impl_->active_tree()
|
| - ->top_controls_shown_ratio()
|
| - ->PullDeltaForMainThread();
|
| - host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
|
| - host_impl_->sync_tree()->PushTopControlsFromMainThread(15.f /
|
| - top_controls_height_);
|
| -
|
| - host_impl_->DidChangeTopControlsPosition();
|
| - LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
|
| - EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
|
| - EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
|
| -
|
| - host_impl_->ActivateSyncTree();
|
| -
|
| - root_clip_ptr = host_impl_->active_tree()->root_layer();
|
| - EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
|
| - EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
|
| -
|
| - EXPECT_FLOAT_EQ(
|
| - -15.f, host_impl_->active_tree()->top_controls_shown_ratio()->Delta() *
|
| - top_controls_height_);
|
| - EXPECT_FLOAT_EQ(
|
| - 15.f,
|
| - host_impl_->active_tree()->top_controls_shown_ratio()->ActiveBase() *
|
| - top_controls_height_);
|
| -}
|
| -
|
| -// Test that changing the top controls layout height is correctly applied to
|
| -// the inner viewport container bounds. That is, the top controls layout
|
| -// height is the amount that the inner viewport container was shrunk outside
|
| -// the compositor to accommodate the top controls.
|
| -TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) {
|
| - CreateHostImpl(settings_, CreateOutputSurface());
|
| - SetupTopControlsAndScrollLayer();
|
| - DrawFrame();
|
| -
|
| - host_impl_->sync_tree()->PushTopControlsFromMainThread(1.f);
|
| - host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
|
| -
|
| - host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
|
| - 1.f);
|
| - host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
|
| - host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
|
| -
|
| - host_impl_->DidChangeTopControlsPosition();
|
| - LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
|
| - EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
|
| - EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
|
| -
|
| - host_impl_->sync_tree()->root_layer()->SetBounds(
|
| - gfx::Size(root_clip_ptr->bounds().width(),
|
| - root_clip_ptr->bounds().height() - 50.f));
|
| -
|
| - host_impl_->ActivateSyncTree();
|
| -
|
| - root_clip_ptr = host_impl_->active_tree()->root_layer();
|
| - EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
|
| -
|
| - // The total bounds should remain unchanged since the bounds delta should
|
| - // account for the difference between the layout height and the current
|
| - // top controls offset.
|
| - EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 50.f), root_clip_ptr->bounds_delta());
|
| -
|
| - host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
|
| - host_impl_->DidChangeTopControlsPosition();
|
| -
|
| - EXPECT_EQ(1.f, host_impl_->top_controls_manager()->TopControlsShownRatio());
|
| - EXPECT_EQ(50.f, host_impl_->top_controls_manager()->TopControlsHeight());
|
| - EXPECT_EQ(50.f, host_impl_->top_controls_manager()->ContentTopOffset());
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), root_clip_ptr->bounds_delta());
|
| - EXPECT_EQ(gfx::Size(viewport_size_.width(), viewport_size_.height() - 50.f),
|
| - root_clip_ptr->bounds());
|
| -}
|
| -
|
| -// Test that showing/hiding the top controls when the viewport is fully scrolled
|
| -// doesn't incorrectly change the viewport offset due to clamping from changing
|
| -// viewport bounds.
|
| -TEST_F(LayerTreeHostImplTopControlsTest, TopControlsViewportOffsetClamping) {
|
| - SetupTopControlsAndScrollLayerWithVirtualViewport(
|
| - gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
|
| -
|
| - LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
|
| - LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
|
| -
|
| - // Scroll the viewports to max scroll offset.
|
| - outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
|
| - inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
|
| -
|
| - gfx::ScrollOffset viewport_offset =
|
| - host_impl_->active_tree()->TotalScrollOffset();
|
| - EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), viewport_offset);
|
| -
|
| - // Hide the top controls by 25px.
|
| - gfx::Vector2dF scroll_delta(0.f, 25.f);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| -
|
| - // scrolling down at the max extents no longer hides the top controls
|
| - EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
|
| -
|
| - // forcefully hide the top controls by 25px
|
| - host_impl_->top_controls_manager()->ScrollBy(scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - EXPECT_FLOAT_EQ(scroll_delta.y(),
|
| - top_controls_height_ -
|
| - host_impl_->top_controls_manager()->ContentTopOffset());
|
| -
|
| - inner_scroll->ClampScrollToMaxScrollOffset();
|
| - outer_scroll->ClampScrollToMaxScrollOffset();
|
| -
|
| - // We should still be fully scrolled.
|
| - EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
|
| - host_impl_->active_tree()->TotalScrollOffset());
|
| -
|
| - viewport_offset = host_impl_->active_tree()->TotalScrollOffset();
|
| -
|
| - // Bring the top controls down by 25px.
|
| - scroll_delta = gfx::Vector2dF(0.f, -25.f);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // The viewport offset shouldn't have changed.
|
| - EXPECT_EQ(viewport_offset,
|
| - host_impl_->active_tree()->TotalScrollOffset());
|
| -
|
| - // Scroll the viewports to max scroll offset.
|
| - outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
|
| - inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
|
| - EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
|
| - host_impl_->active_tree()->TotalScrollOffset());
|
| -}
|
| -
|
| -// Test that the top controls coming in and out maintains the same aspect ratio
|
| -// between the inner and outer viewports.
|
| -TEST_F(LayerTreeHostImplTopControlsTest, TopControlsAspectRatio) {
|
| - SetupTopControlsAndScrollLayerWithVirtualViewport(
|
| - gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
|
| - DrawFrame();
|
| -
|
| - EXPECT_FLOAT_EQ(top_controls_height_,
|
| - host_impl_->top_controls_manager()->ContentTopOffset());
|
| -
|
| - gfx::Vector2dF scroll_delta(0.f, 25.f);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - EXPECT_FLOAT_EQ(scroll_delta.y(),
|
| - top_controls_height_ -
|
| - host_impl_->top_controls_manager()->ContentTopOffset());
|
| -
|
| - // Top controls were hidden by 25px so the inner viewport should have expanded
|
| - // by that much.
|
| - LayerImpl* outer_container =
|
| - host_impl_->active_tree()->OuterViewportContainerLayer();
|
| - LayerImpl* inner_container =
|
| - host_impl_->active_tree()->InnerViewportContainerLayer();
|
| - EXPECT_EQ(gfx::Size(100, 100+25), inner_container->BoundsForScrolling());
|
| -
|
| - // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
|
| - float aspect_ratio = inner_container->BoundsForScrolling().width() /
|
| - inner_container->BoundsForScrolling().height();
|
| - gfx::Size expected = gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio));
|
| - EXPECT_EQ(expected, outer_container->BoundsForScrolling());
|
| - EXPECT_EQ(expected,
|
| - host_impl_->InnerViewportScrollLayer()->BoundsForScrolling());
|
| -}
|
| -
|
| -// Test that scrolling the outer viewport affects the top controls.
|
| -TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) {
|
| - SetupTopControlsAndScrollLayerWithVirtualViewport(
|
| - gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(top_controls_height_,
|
| - host_impl_->top_controls_manager()->ContentTopOffset());
|
| -
|
| - // Send a gesture scroll that will scroll the outer viewport, make sure the
|
| - // top controls get scrolled.
|
| - gfx::Vector2dF scroll_delta(0.f, 15.f);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
|
| - host_impl_->CurrentlyScrollingLayer());
|
| - host_impl_->ScrollEnd();
|
| -
|
| - EXPECT_FLOAT_EQ(scroll_delta.y(),
|
| - top_controls_height_ -
|
| - host_impl_->top_controls_manager()->ContentTopOffset());
|
| -
|
| - scroll_delta = gfx::Vector2dF(0.f, 50.f);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| -
|
| - EXPECT_EQ(0, host_impl_->top_controls_manager()->ContentTopOffset());
|
| - EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
|
| - host_impl_->CurrentlyScrollingLayer());
|
| -
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // Position the viewports such that the inner viewport will be scrolled.
|
| - gfx::Vector2dF inner_viewport_offset(0.f, 25.f);
|
| - host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
|
| - host_impl_->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset);
|
| -
|
| - scroll_delta = gfx::Vector2dF(0.f, -65.f);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| -
|
| - EXPECT_EQ(top_controls_height_,
|
| - host_impl_->top_controls_manager()->ContentTopOffset());
|
| - EXPECT_FLOAT_EQ(
|
| - inner_viewport_offset.y() + (scroll_delta.y() + top_controls_height_),
|
| - host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
|
| -
|
| - host_impl_->ScrollEnd();
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTopControlsTest,
|
| - ScrollNonScrollableRootWithTopControls) {
|
| - CreateHostImpl(settings_, CreateOutputSurface());
|
| - SetupTopControlsAndScrollLayer();
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| -
|
| - host_impl_->top_controls_manager()->ScrollBegin();
|
| - host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
|
| - host_impl_->top_controls_manager()->ScrollEnd();
|
| - EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
|
| - // Now that top controls have moved, expect the clip to resize.
|
| - LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
|
| - EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
|
| -
|
| - host_impl_->ScrollEnd();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| -
|
| - float scroll_increment_y = -25.f;
|
| - host_impl_->top_controls_manager()->ScrollBegin();
|
| - host_impl_->top_controls_manager()->ScrollBy(
|
| - gfx::Vector2dF(0.f, scroll_increment_y));
|
| - EXPECT_FLOAT_EQ(-scroll_increment_y,
|
| - host_impl_->top_controls_manager()->ContentTopOffset());
|
| - // Now that top controls have moved, expect the clip to resize.
|
| - EXPECT_EQ(gfx::Size(viewport_size_.width(),
|
| - viewport_size_.height() + scroll_increment_y),
|
| - root_clip_ptr->bounds());
|
| -
|
| - host_impl_->top_controls_manager()->ScrollBy(
|
| - gfx::Vector2dF(0.f, scroll_increment_y));
|
| - host_impl_->top_controls_manager()->ScrollEnd();
|
| - EXPECT_FLOAT_EQ(-2 * scroll_increment_y,
|
| - host_impl_->top_controls_manager()->ContentTopOffset());
|
| - // Now that top controls have moved, expect the clip to resize.
|
| - EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
|
| -
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // Verify the layer is once-again non-scrollable.
|
| - EXPECT_EQ(
|
| - gfx::ScrollOffset(),
|
| - host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
|
| - // Test the configuration where a non-composited root layer is embedded in a
|
| - // scrollable outer layer.
|
| - gfx::Size surface_size(10, 10);
|
| - gfx::Size contents_size(20, 20);
|
| -
|
| - scoped_ptr<LayerImpl> content_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - content_layer->SetDrawsContent(true);
|
| - content_layer->SetPosition(gfx::PointF());
|
| - content_layer->SetBounds(contents_size);
|
| - content_layer->SetContentBounds(contents_size);
|
| - content_layer->SetContentsScale(2.f, 2.f);
|
| -
|
| - scoped_ptr<LayerImpl> scroll_clip_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - scroll_clip_layer->SetBounds(surface_size);
|
| -
|
| - scoped_ptr<LayerImpl> scroll_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 2);
|
| - scroll_layer->SetScrollClipLayer(3);
|
| - scroll_layer->SetBounds(contents_size);
|
| - scroll_layer->SetContentBounds(contents_size);
|
| - scroll_layer->SetPosition(gfx::PointF());
|
| - scroll_layer->AddChild(content_layer.Pass());
|
| - scroll_clip_layer->AddChild(scroll_layer.Pass());
|
| -
|
| - scroll_clip_layer->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
|
| - host_impl_->SetViewportSize(surface_size);
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_commit_);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
|
| - gfx::Size surface_size(10, 10);
|
| - gfx::Size contents_size(20, 20);
|
| - scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->SetBounds(surface_size);
|
| - root->SetContentBounds(contents_size);
|
| - root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
|
| - root->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - host_impl_->SetViewportSize(surface_size);
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_commit_);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
|
| - gfx::Size surface_size(10, 10);
|
| - scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
|
| - root->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - host_impl_->SetViewportSize(surface_size);
|
| - DrawFrame();
|
| -
|
| - // Scroll event is ignored because the input coordinate is outside the layer
|
| - // boundaries.
|
| - EXPECT_EQ(InputHandler::SCROLL_IGNORED,
|
| - host_impl_->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL));
|
| - EXPECT_FALSE(did_request_redraw_);
|
| - EXPECT_FALSE(did_request_commit_);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
|
| - gfx::Size surface_size(10, 10);
|
| - scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->SetHasRenderSurface(true);
|
| - scoped_ptr<LayerImpl> child =
|
| - CreateScrollableLayer(2, surface_size, root.get());
|
| - host_impl_->SetViewportSize(surface_size);
|
| -
|
| - gfx::Transform matrix;
|
| - matrix.RotateAboutXAxis(180.0);
|
| - child->SetTransform(matrix);
|
| - child->SetDoubleSided(false);
|
| -
|
| - root->AddChild(child.Pass());
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - DrawFrame();
|
| -
|
| - // Scroll event is ignored because the scrollable layer is not facing the
|
| - // viewer and there is nothing scrollable behind it.
|
| - EXPECT_EQ(InputHandler::SCROLL_IGNORED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
|
| - EXPECT_FALSE(did_request_redraw_);
|
| - EXPECT_FALSE(did_request_commit_);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
|
| - gfx::Size surface_size(10, 10);
|
| - scoped_ptr<LayerImpl> clip_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - scoped_ptr<LayerImpl> content_layer =
|
| - CreateScrollableLayer(1, surface_size, clip_layer.get());
|
| - content_layer->SetShouldScrollOnMainThread(true);
|
| - content_layer->SetScrollClipLayer(Layer::INVALID_ID);
|
| -
|
| - // Note: we can use the same clip layer for both since both calls to
|
| - // CreateScrollableLayer() use the same surface size.
|
| - scoped_ptr<LayerImpl> scroll_layer =
|
| - CreateScrollableLayer(2, surface_size, clip_layer.get());
|
| - scroll_layer->AddChild(content_layer.Pass());
|
| - clip_layer->AddChild(scroll_layer.Pass());
|
| - clip_layer->SetHasRenderSurface(true);
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
|
| - host_impl_->SetViewportSize(surface_size);
|
| - DrawFrame();
|
| -
|
| - // Scrolling fails because the content layer is asking to be scrolled on the
|
| - // main thread.
|
| - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
|
| - gfx::Size surface_size(20, 20);
|
| - gfx::Size viewport_size(10, 10);
|
| - float page_scale = 2.f;
|
| - scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - scoped_ptr<LayerImpl> root_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 2);
|
| - scoped_ptr<LayerImpl> root_scrolling =
|
| - CreateScrollableLayer(3, surface_size, root_clip.get());
|
| - EXPECT_EQ(viewport_size, root_clip->bounds());
|
| - root_scrolling->SetIsContainerForFixedPositionLayers(true);
|
| - root_clip->AddChild(root_scrolling.Pass());
|
| - root->AddChild(root_clip.Pass());
|
| - root->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - // The behaviour in this test assumes the page scale is applied at a layer
|
| - // above the clip layer.
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
|
| - Layer::INVALID_ID);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - host_impl_->SetViewportSize(viewport_size);
|
| - DrawFrame();
|
| -
|
| - LayerImpl* root_scroll =
|
| - host_impl_->active_tree()->InnerViewportScrollLayer();
|
| - EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
|
| -
|
| - gfx::Vector2d scroll_delta(0, 10);
|
| - gfx::Vector2d expected_scroll_delta = scroll_delta;
|
| - gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // Set new page scale from main thread.
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, page_scale,
|
| - page_scale);
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
|
| -
|
| - // The scroll range should also have been updated.
|
| - EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
|
| -
|
| - // The page scale delta remains constant because the impl thread did not
|
| - // scale.
|
| - EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
|
| - gfx::Size surface_size(20, 20);
|
| - gfx::Size viewport_size(10, 10);
|
| - float page_scale = 2.f;
|
| - scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - scoped_ptr<LayerImpl> root_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 2);
|
| - scoped_ptr<LayerImpl> root_scrolling =
|
| - CreateScrollableLayer(3, surface_size, root_clip.get());
|
| - EXPECT_EQ(viewport_size, root_clip->bounds());
|
| - root_scrolling->SetIsContainerForFixedPositionLayers(true);
|
| - root_clip->AddChild(root_scrolling.Pass());
|
| - root->AddChild(root_clip.Pass());
|
| - root->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - // The behaviour in this test assumes the page scale is applied at a layer
|
| - // above the clip layer.
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
|
| - Layer::INVALID_ID);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - host_impl_->SetViewportSize(viewport_size);
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, page_scale);
|
| - DrawFrame();
|
| -
|
| - LayerImpl* root_scroll =
|
| - host_impl_->active_tree()->InnerViewportScrollLayer();
|
| - EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
|
| -
|
| - gfx::Vector2d scroll_delta(0, 10);
|
| - gfx::Vector2d expected_scroll_delta = scroll_delta;
|
| - gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // Set new page scale on impl thread by pinching.
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
|
| - host_impl_->PinchGestureBegin();
|
| - host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
|
| - host_impl_->PinchGestureEnd();
|
| - host_impl_->ScrollEnd();
|
| - DrawOneFrame();
|
| -
|
| - // The scroll delta is not scaled because the main thread did not scale.
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
|
| -
|
| - // The scroll range should also have been updated.
|
| - EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
|
| -
|
| - // The page scale delta should match the new scale on the impl side.
|
| - EXPECT_EQ(page_scale, host_impl_->active_tree()->current_page_scale_factor());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
|
| - gfx::Size surface_size(10, 10);
|
| - float default_page_scale = 1.f;
|
| - gfx::Transform default_page_scale_matrix;
|
| - default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
|
| -
|
| - float new_page_scale = 2.f;
|
| - gfx::Transform new_page_scale_matrix;
|
| - new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
|
| -
|
| - // Create a normal scrollable root layer and another scrollable child layer.
|
| - LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
|
| - LayerImpl* root = host_impl_->active_tree()->root_layer();
|
| - LayerImpl* child = scroll->children()[0];
|
| -
|
| - scoped_ptr<LayerImpl> scrollable_child_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 6);
|
| - scoped_ptr<LayerImpl> scrollable_child =
|
| - CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
|
| - scrollable_child_clip->AddChild(scrollable_child.Pass());
|
| - child->AddChild(scrollable_child_clip.Pass());
|
| - LayerImpl* grand_child = child->children()[0];
|
| -
|
| - // Set new page scale on impl thread by pinching.
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
|
| - host_impl_->PinchGestureBegin();
|
| - host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
|
| - host_impl_->PinchGestureEnd();
|
| - host_impl_->ScrollEnd();
|
| - DrawOneFrame();
|
| -
|
| - EXPECT_EQ(1.f, root->contents_scale_x());
|
| - EXPECT_EQ(1.f, root->contents_scale_y());
|
| - EXPECT_EQ(1.f, scroll->contents_scale_x());
|
| - EXPECT_EQ(1.f, scroll->contents_scale_y());
|
| - EXPECT_EQ(1.f, child->contents_scale_x());
|
| - EXPECT_EQ(1.f, child->contents_scale_y());
|
| - EXPECT_EQ(1.f, grand_child->contents_scale_x());
|
| - EXPECT_EQ(1.f, grand_child->contents_scale_y());
|
| -
|
| - // Make sure all the layers are drawn with the page scale delta applied, i.e.,
|
| - // the page scale delta on the root layer is applied hierarchically.
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
|
| - EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
|
| - EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
|
| - EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
|
| - EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
|
| - EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
|
| - EXPECT_EQ(new_page_scale,
|
| - grand_child->draw_transform().matrix().getDouble(0, 0));
|
| - EXPECT_EQ(new_page_scale,
|
| - grand_child->draw_transform().matrix().getDouble(1, 1));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
|
| - gfx::Size surface_size(30, 30);
|
| - scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->SetBounds(gfx::Size(5, 5));
|
| - root->SetHasRenderSurface(true);
|
| - scoped_ptr<LayerImpl> root_scrolling =
|
| - LayerImpl::Create(host_impl_->active_tree(), 2);
|
| - root_scrolling->SetBounds(surface_size);
|
| - root_scrolling->SetContentBounds(surface_size);
|
| - root_scrolling->SetScrollClipLayer(root->id());
|
| - root_scrolling->SetIsContainerForFixedPositionLayers(true);
|
| - LayerImpl* root_scrolling_ptr = root_scrolling.get();
|
| - root->AddChild(root_scrolling.Pass());
|
| - int child_scroll_layer_id = 3;
|
| - scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
|
| - child_scroll_layer_id, surface_size, root_scrolling_ptr);
|
| - LayerImpl* child = child_scrolling.get();
|
| - root_scrolling_ptr->AddChild(child_scrolling.Pass());
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
|
| - Layer::INVALID_ID);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - host_impl_->SetViewportSize(surface_size);
|
| - DrawFrame();
|
| -
|
| - gfx::Vector2d scroll_delta(0, 10);
|
| - gfx::Vector2d expected_scroll_delta(scroll_delta);
|
| - gfx::ScrollOffset expected_max_scroll(child->MaxScrollOffset());
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - float page_scale = 2.f;
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f,
|
| - page_scale);
|
| -
|
| - DrawOneFrame();
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ExpectContains(
|
| - *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
|
| -
|
| - // The scroll range should not have changed.
|
| - EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
|
| -
|
| - // The page scale delta remains constant because the impl thread did not
|
| - // scale.
|
| - EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
|
| - // Scroll a child layer beyond its maximum scroll range and make sure the
|
| - // parent layer is scrolled on the axis on which the child was unable to
|
| - // scroll.
|
| - gfx::Size surface_size(10, 10);
|
| - gfx::Size content_size(20, 20);
|
| - scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->SetBounds(surface_size);
|
| - root->SetHasRenderSurface(true);
|
| - scoped_ptr<LayerImpl> grand_child =
|
| - CreateScrollableLayer(3, content_size, root.get());
|
| -
|
| - scoped_ptr<LayerImpl> child =
|
| - CreateScrollableLayer(2, content_size, root.get());
|
| - LayerImpl* grand_child_layer = grand_child.get();
|
| - child->AddChild(grand_child.Pass());
|
| -
|
| - LayerImpl* child_layer = child.get();
|
| - root->AddChild(child.Pass());
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - host_impl_->SetViewportSize(surface_size);
|
| - grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
|
| - child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
|
| -
|
| - DrawFrame();
|
| - {
|
| - gfx::Vector2d scroll_delta(-8, -7);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| -
|
| - // The grand child should have scrolled up to its limit.
|
| - LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
|
| - LayerImpl* grand_child = child->children()[0];
|
| - ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
|
| -
|
| - // The child should have only scrolled on the other axis.
|
| - ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
|
| - // Scroll a child layer beyond its maximum scroll range and make sure the
|
| - // the scroll doesn't bubble up to the parent layer.
|
| - gfx::Size surface_size(20, 20);
|
| - gfx::Size viewport_size(10, 10);
|
| - scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->SetHasRenderSurface(true);
|
| - scoped_ptr<LayerImpl> root_scrolling =
|
| - CreateScrollableLayer(2, surface_size, root.get());
|
| - root_scrolling->SetIsContainerForFixedPositionLayers(true);
|
| -
|
| - scoped_ptr<LayerImpl> grand_child =
|
| - CreateScrollableLayer(4, surface_size, root.get());
|
| -
|
| - scoped_ptr<LayerImpl> child =
|
| - CreateScrollableLayer(3, surface_size, root.get());
|
| - LayerImpl* grand_child_layer = grand_child.get();
|
| - child->AddChild(grand_child.Pass());
|
| -
|
| - LayerImpl* child_layer = child.get();
|
| - root_scrolling->AddChild(child.Pass());
|
| - root->AddChild(root_scrolling.Pass());
|
| - EXPECT_EQ(viewport_size, root->bounds());
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
|
| - Layer::INVALID_ID);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - host_impl_->SetViewportSize(viewport_size);
|
| -
|
| - grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
|
| - child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
|
| -
|
| - DrawFrame();
|
| - {
|
| - gfx::Vector2d scroll_delta(0, -10);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(),
|
| - InputHandler::NON_BUBBLING_GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| -
|
| - // The grand child should have scrolled up to its limit.
|
| - LayerImpl* child =
|
| - host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
|
| - LayerImpl* grand_child = child->children()[0];
|
| - ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
|
| -
|
| - // The child should not have scrolled.
|
| - ExpectNone(*scroll_info.get(), child->id());
|
| -
|
| - // The next time we scroll we should only scroll the parent.
|
| - scroll_delta = gfx::Vector2d(0, -3);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5),
|
| - InputHandler::NON_BUBBLING_GESTURE));
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| -
|
| - // The child should have scrolled up to its limit.
|
| - ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
|
| -
|
| - // The grand child should not have scrolled.
|
| - ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
|
| -
|
| - // After scrolling the parent, another scroll on the opposite direction
|
| - // should still scroll the child.
|
| - scroll_delta = gfx::Vector2d(0, 7);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5),
|
| - InputHandler::NON_BUBBLING_GESTURE));
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| -
|
| - // The grand child should have scrolled.
|
| - ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
|
| -
|
| - // The child should not have scrolled.
|
| - ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
|
| -
|
| -
|
| - // Scrolling should be adjusted from viewport space.
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 2.f, 2.f);
|
| - host_impl_->SetPageScaleOnActiveTree(2.f);
|
| -
|
| - scroll_delta = gfx::Vector2d(0, -2);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(1, 1),
|
| - InputHandler::NON_BUBBLING_GESTURE));
|
| - EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| -
|
| - // Should have scrolled by half the amount in layer space (5 - 2/2)
|
| - ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
|
| - }
|
| -}
|
| -TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
|
| - // When we try to scroll a non-scrollable child layer, the scroll delta
|
| - // should be applied to one of its ancestors if possible.
|
| - gfx::Size surface_size(10, 10);
|
| - gfx::Size content_size(20, 20);
|
| - scoped_ptr<LayerImpl> root_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - root_clip->SetHasRenderSurface(true);
|
| - scoped_ptr<LayerImpl> root =
|
| - CreateScrollableLayer(1, content_size, root_clip.get());
|
| - // Make 'root' the clip layer for child: since they have the same sizes the
|
| - // child will have zero max_scroll_offset and scrolls will bubble.
|
| - scoped_ptr<LayerImpl> child =
|
| - CreateScrollableLayer(2, content_size, root.get());
|
| - child->SetIsContainerForFixedPositionLayers(true);
|
| - root->SetBounds(content_size);
|
| -
|
| - int root_scroll_id = root->id();
|
| - root->AddChild(child.Pass());
|
| - root_clip->AddChild(root.Pass());
|
| -
|
| - host_impl_->SetViewportSize(surface_size);
|
| - host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 2,
|
| - Layer::INVALID_ID);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - DrawFrame();
|
| - {
|
| - gfx::Vector2d scroll_delta(0, 4);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| -
|
| - // Only the root scroll should have scrolled.
|
| - ASSERT_EQ(scroll_info->scrolls.size(), 1u);
|
| - ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
|
| - gfx::Size surface_size(10, 10);
|
| - scoped_ptr<LayerImpl> root_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - scoped_ptr<LayerImpl> root_scroll =
|
| - CreateScrollableLayer(2, surface_size, root_clip.get());
|
| - root_scroll->SetIsContainerForFixedPositionLayers(true);
|
| - root_clip->SetHasRenderSurface(true);
|
| - root_clip->AddChild(root_scroll.Pass());
|
| - host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
|
| - Layer::INVALID_ID);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - host_impl_->SetViewportSize(surface_size);
|
| -
|
| - // Draw one frame and then immediately rebuild the layer tree to mimic a tree
|
| - // synchronization.
|
| - DrawFrame();
|
| - host_impl_->active_tree()->DetachLayerTree();
|
| - scoped_ptr<LayerImpl> root_clip2 =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - scoped_ptr<LayerImpl> root_scroll2 =
|
| - CreateScrollableLayer(4, surface_size, root_clip2.get());
|
| - root_scroll2->SetIsContainerForFixedPositionLayers(true);
|
| - root_clip2->AddChild(root_scroll2.Pass());
|
| - root_clip2->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 4,
|
| - Layer::INVALID_ID);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| -
|
| - // Scrolling should still work even though we did not draw yet.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| -
|
| - // Rotate the root layer 90 degrees counter-clockwise about its center.
|
| - gfx::Transform rotate_transform;
|
| - rotate_transform.Rotate(-90.0);
|
| - host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
|
| -
|
| - gfx::Size surface_size(50, 50);
|
| - host_impl_->SetViewportSize(surface_size);
|
| - DrawFrame();
|
| -
|
| - // Scroll to the right in screen coordinates with a gesture.
|
| - gfx::Vector2d gesture_scroll_delta(10, 0);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // The layer should have scrolled down in its local coordinates.
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ExpectContains(*scroll_info.get(), scroll_layer->id(),
|
| - gfx::Vector2d(0, gesture_scroll_delta.x()));
|
| -
|
| - // Reset and scroll down with the wheel.
|
| - scroll_layer->SetScrollDelta(gfx::Vector2dF());
|
| - gfx::Vector2d wheel_scroll_delta(0, 10);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // The layer should have scrolled down in its local coordinates.
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ExpectContains(*scroll_info.get(),
|
| - scroll_layer->id(),
|
| - wheel_scroll_delta);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - int child_clip_layer_id = 6;
|
| - int child_layer_id = 7;
|
| - float child_layer_angle = -20.f;
|
| -
|
| - // Create a child layer that is rotated to a non-axis-aligned angle.
|
| - scoped_ptr<LayerImpl> clip_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
|
| - scoped_ptr<LayerImpl> child = CreateScrollableLayer(
|
| - child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
|
| - gfx::Transform rotate_transform;
|
| - rotate_transform.Translate(-50.0, -50.0);
|
| - rotate_transform.Rotate(child_layer_angle);
|
| - rotate_transform.Translate(50.0, 50.0);
|
| - clip_layer->SetTransform(rotate_transform);
|
| -
|
| - // Only allow vertical scrolling.
|
| - clip_layer->SetBounds(
|
| - gfx::Size(child->bounds().width(), child->bounds().height() / 2));
|
| - // The rotation depends on the layer's transform origin, and the child layer
|
| - // is a different size than the clip, so make sure the clip layer's origin
|
| - // lines up over the child.
|
| - clip_layer->SetTransformOrigin(gfx::Point3F(
|
| - clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
|
| - LayerImpl* child_ptr = child.get();
|
| - clip_layer->AddChild(child.Pass());
|
| - scroll_layer->AddChild(clip_layer.Pass());
|
| -
|
| - gfx::Size surface_size(50, 50);
|
| - host_impl_->SetViewportSize(surface_size);
|
| - DrawFrame();
|
| - {
|
| - // Scroll down in screen coordinates with a gesture.
|
| - gfx::Vector2d gesture_scroll_delta(0, 10);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // The child layer should have scrolled down in its local coordinates an
|
| - // amount proportional to the angle between it and the input scroll delta.
|
| - gfx::Vector2d expected_scroll_delta(
|
| - 0, gesture_scroll_delta.y() *
|
| - std::cos(MathUtil::Deg2Rad(child_layer_angle)));
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
|
| -
|
| - // The root scroll layer should not have scrolled, because the input delta
|
| - // was close to the layer's axis of movement.
|
| - EXPECT_EQ(scroll_info->scrolls.size(), 1u);
|
| - }
|
| - {
|
| - // Now reset and scroll the same amount horizontally.
|
| - child_ptr->SetScrollDelta(gfx::Vector2dF());
|
| - gfx::Vector2d gesture_scroll_delta(10, 0);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // The child layer should have scrolled down in its local coordinates an
|
| - // amount proportional to the angle between it and the input scroll delta.
|
| - gfx::Vector2d expected_scroll_delta(
|
| - 0, -gesture_scroll_delta.x() *
|
| - std::sin(MathUtil::Deg2Rad(child_layer_angle)));
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| - ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
|
| -
|
| - // The root scroll layer should have scrolled more, since the input scroll
|
| - // delta was mostly orthogonal to the child layer's vertical scroll axis.
|
| - gfx::Vector2d expected_root_scroll_delta(
|
| - gesture_scroll_delta.x() *
|
| - std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
|
| - 0);
|
| - ExpectContains(*scroll_info.get(),
|
| - scroll_layer->id(),
|
| - expected_root_scroll_delta);
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
|
| - LayerImpl* scroll_layer =
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| -
|
| - // Scale the layer to twice its normal size.
|
| - int scale = 2;
|
| - gfx::Transform scale_transform;
|
| - scale_transform.Scale(scale, scale);
|
| - scroll_layer->SetTransform(scale_transform);
|
| -
|
| - gfx::Size surface_size(50, 50);
|
| - host_impl_->SetViewportSize(surface_size);
|
| - DrawFrame();
|
| -
|
| - // Scroll down in screen coordinates with a gesture.
|
| - gfx::Vector2d scroll_delta(0, 10);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // The layer should have scrolled down in its local coordinates, but half the
|
| - // amount.
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ExpectContains(*scroll_info.get(),
|
| - scroll_layer->id(),
|
| - gfx::Vector2d(0, scroll_delta.y() / scale));
|
| -
|
| - // Reset and scroll down with the wheel.
|
| - scroll_layer->SetScrollDelta(gfx::Vector2dF());
|
| - gfx::Vector2d wheel_scroll_delta(0, 10);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // It should apply the scale factor to the scroll delta for the wheel event.
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ExpectContains(*scroll_info.get(),
|
| - scroll_layer->id(),
|
| - wheel_scroll_delta);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
|
| - int width = 332;
|
| - int height = 20;
|
| - int scale = 3;
|
| - SetupScrollAndContentsLayers(gfx::Size(width, height));
|
| - host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
|
| - gfx::Size(width * scale - 1, height * scale));
|
| - host_impl_->SetDeviceScaleFactor(scale);
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
|
| -
|
| - LayerImpl* inner_viewport_scroll_layer =
|
| - host_impl_->active_tree()->InnerViewportScrollLayer();
|
| - EXPECT_EQ(gfx::ScrollOffset(0, 0),
|
| - inner_viewport_scroll_layer->MaxScrollOffset());
|
| -}
|
| -
|
| -class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
|
| - public:
|
| - TestScrollOffsetDelegate()
|
| - : page_scale_factor_(0.f),
|
| - min_page_scale_factor_(-1.f),
|
| - max_page_scale_factor_(-1.f) {}
|
| -
|
| - ~TestScrollOffsetDelegate() override {}
|
| -
|
| - gfx::ScrollOffset GetTotalScrollOffset() override {
|
| - return getter_return_value_;
|
| - }
|
| -
|
| - bool IsExternalFlingActive() const override { return false; }
|
| -
|
| - void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset,
|
| - const gfx::ScrollOffset& max_scroll_offset,
|
| - const gfx::SizeF& scrollable_size,
|
| - float page_scale_factor,
|
| - float min_page_scale_factor,
|
| - float max_page_scale_factor) override {
|
| - DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
|
| - DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
|
| - last_set_scroll_offset_ = total_scroll_offset;
|
| - max_scroll_offset_ = max_scroll_offset;
|
| - scrollable_size_ = scrollable_size;
|
| - page_scale_factor_ = page_scale_factor;
|
| - min_page_scale_factor_ = min_page_scale_factor;
|
| - max_page_scale_factor_ = max_page_scale_factor;
|
| -
|
| - set_getter_return_value(last_set_scroll_offset_);
|
| - }
|
| -
|
| - gfx::ScrollOffset last_set_scroll_offset() {
|
| - return last_set_scroll_offset_;
|
| - }
|
| -
|
| - void set_getter_return_value(const gfx::ScrollOffset& value) {
|
| - getter_return_value_ = value;
|
| - }
|
| -
|
| - gfx::ScrollOffset max_scroll_offset() const {
|
| - return max_scroll_offset_;
|
| - }
|
| -
|
| - gfx::SizeF scrollable_size() const {
|
| - return scrollable_size_;
|
| - }
|
| -
|
| - float page_scale_factor() const {
|
| - return page_scale_factor_;
|
| - }
|
| -
|
| - float min_page_scale_factor() const {
|
| - return min_page_scale_factor_;
|
| - }
|
| -
|
| - float max_page_scale_factor() const {
|
| - return max_page_scale_factor_;
|
| - }
|
| -
|
| - private:
|
| - gfx::ScrollOffset last_set_scroll_offset_;
|
| - gfx::ScrollOffset getter_return_value_;
|
| - gfx::ScrollOffset max_scroll_offset_;
|
| - gfx::SizeF scrollable_size_;
|
| - float page_scale_factor_;
|
| - float min_page_scale_factor_;
|
| - float max_page_scale_factor_;
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
|
| - TestScrollOffsetDelegate scroll_delegate;
|
| - host_impl_->SetViewportSize(gfx::Size(10, 20));
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - LayerImpl* clip_layer = scroll_layer->parent()->parent();
|
| - clip_layer->SetBounds(gfx::Size(10, 20));
|
| -
|
| - // Setting the delegate results in the current scroll offset being set.
|
| - gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
|
| - scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
|
| - scroll_layer->SetScrollDelta(initial_scroll_delta);
|
| - host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
|
| - EXPECT_EQ(initial_scroll_delta.ToString(),
|
| - scroll_delegate.last_set_scroll_offset().ToString());
|
| -
|
| - // Setting the delegate results in the scrollable_size, max_scroll_offset,
|
| - // page_scale_factor and {min|max}_page_scale_factor being set.
|
| - EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
|
| - EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate.max_scroll_offset());
|
| - EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
|
| - EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
|
| - EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
|
| -
|
| - // Updating page scale immediately updates the delegate.
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 0.5f, 4.f);
|
| - EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
|
| - EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
|
| - EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
|
| - host_impl_->SetPageScaleOnActiveTree(2.f * 1.5f);
|
| - EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
|
| - EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
|
| - EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
|
| - host_impl_->SetPageScaleOnActiveTree(2.f);
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
|
| - EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
|
| - EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
|
| - EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
|
| -
|
| - // The pinch gesture doesn't put the delegate into a state where the scroll
|
| - // offset is outside of the scroll range. (this is verified by DCHECKs in the
|
| - // delegate).
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
|
| - host_impl_->PinchGestureBegin();
|
| - host_impl_->PinchGestureUpdate(2.f, gfx::Point());
|
| - host_impl_->PinchGestureUpdate(.5f, gfx::Point());
|
| - host_impl_->PinchGestureEnd();
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // Scrolling should be relative to the offset as returned by the delegate.
|
| - gfx::Vector2dF scroll_delta(0.f, 10.f);
|
| - gfx::ScrollOffset current_offset(7.f, 8.f);
|
| -
|
| - scroll_delegate.set_getter_return_value(current_offset);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| -
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
|
| - scroll_delegate.last_set_scroll_offset());
|
| -
|
| - current_offset = gfx::ScrollOffset(42.f, 41.f);
|
| - scroll_delegate.set_getter_return_value(current_offset);
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
|
| - scroll_delegate.last_set_scroll_offset());
|
| - host_impl_->ScrollEnd();
|
| - scroll_delegate.set_getter_return_value(gfx::ScrollOffset());
|
| -
|
| - // Forces a full tree synchronization and ensures that the scroll delegate
|
| - // sees the correct size of the new tree.
|
| - gfx::Size new_size(42, 24);
|
| - host_impl_->CreatePendingTree();
|
| - CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
|
| - host_impl_->ActivateSyncTree();
|
| - EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
|
| -
|
| - // Un-setting the delegate should propagate the delegate's current offset to
|
| - // the root scrollable layer.
|
| - current_offset = gfx::ScrollOffset(13.f, 12.f);
|
| - scroll_delegate.set_getter_return_value(current_offset);
|
| - host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
|
| -
|
| - EXPECT_EQ(current_offset.ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -}
|
| -
|
| -void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
|
| - const gfx::Transform target_space_transform =
|
| - layer->draw_properties().target_space_transform;
|
| - EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
|
| - gfx::Point translated_point;
|
| - target_space_transform.TransformPoint(&translated_point);
|
| - gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
|
| - EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest,
|
| - ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
|
| - TestScrollOffsetDelegate scroll_delegate;
|
| - host_impl_->SetViewportSize(gfx::Size(10, 20));
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - LayerImpl* clip_layer = scroll_layer->parent()->parent();
|
| - clip_layer->SetBounds(gfx::Size(10, 20));
|
| - host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
|
| -
|
| - // Draw first frame to clear any pending draws and check scroll.
|
| - DrawFrame();
|
| - CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
|
| - EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
|
| -
|
| - // Set external scroll delta on delegate and notify LayerTreeHost.
|
| - gfx::ScrollOffset scroll_offset(10.f, 10.f);
|
| - scroll_delegate.set_getter_return_value(scroll_offset);
|
| - host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
|
| -
|
| - // Check scroll delta reflected in layer.
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - EXPECT_FALSE(frame.has_no_damage);
|
| - CheckLayerScrollDelta(scroll_layer, ScrollOffsetToVector2dF(scroll_offset));
|
| -
|
| - host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
|
| - InputHandlerScrollResult scroll_result;
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
|
| - DrawFrame();
|
| - EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
|
| -
|
| - // In-bounds scrolling does not affect overscroll.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
|
| - EXPECT_TRUE(scroll_result.did_scroll);
|
| - EXPECT_FALSE(scroll_result.did_overscroll_root);
|
| - EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
|
| -
|
| - // Overscroll events are reflected immediately.
|
| - scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
|
| - EXPECT_TRUE(scroll_result.did_scroll);
|
| - EXPECT_TRUE(scroll_result.did_overscroll_root);
|
| - EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
|
| - EXPECT_EQ(scroll_result.accumulated_root_overscroll,
|
| - host_impl_->accumulated_root_overscroll());
|
| -
|
| - // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
|
| - scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
|
| - EXPECT_TRUE(scroll_result.did_scroll);
|
| - EXPECT_FALSE(scroll_result.did_overscroll_root);
|
| - EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
|
| - EXPECT_EQ(scroll_result.accumulated_root_overscroll,
|
| - host_impl_->accumulated_root_overscroll());
|
| -
|
| - scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
|
| - EXPECT_FALSE(scroll_result.did_scroll);
|
| - EXPECT_TRUE(scroll_result.did_overscroll_root);
|
| - EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
|
| - EXPECT_EQ(scroll_result.accumulated_root_overscroll,
|
| - host_impl_->accumulated_root_overscroll());
|
| -
|
| - scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
|
| - EXPECT_TRUE(scroll_result.did_scroll);
|
| - EXPECT_FALSE(scroll_result.did_overscroll_root);
|
| - EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
|
| - EXPECT_EQ(scroll_result.accumulated_root_overscroll,
|
| - host_impl_->accumulated_root_overscroll());
|
| -
|
| - scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
|
| - EXPECT_TRUE(scroll_result.did_scroll);
|
| - EXPECT_TRUE(scroll_result.did_overscroll_root);
|
| - EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
|
| - EXPECT_EQ(scroll_result.accumulated_root_overscroll,
|
| - host_impl_->accumulated_root_overscroll());
|
| -
|
| - scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
|
| - EXPECT_TRUE(scroll_result.did_scroll);
|
| - EXPECT_TRUE(scroll_result.did_overscroll_root);
|
| - EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
|
| - EXPECT_EQ(scroll_result.accumulated_root_overscroll,
|
| - host_impl_->accumulated_root_overscroll());
|
| -
|
| - scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
|
| - EXPECT_TRUE(scroll_result.did_scroll);
|
| - EXPECT_TRUE(scroll_result.did_overscroll_root);
|
| - EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
|
| - EXPECT_EQ(scroll_result.accumulated_root_overscroll,
|
| - host_impl_->accumulated_root_overscroll());
|
| -
|
| - // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
|
| - // as no scroll occurs.
|
| - scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
|
| - EXPECT_FALSE(scroll_result.did_scroll);
|
| - EXPECT_TRUE(scroll_result.did_overscroll_root);
|
| - EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
|
| - EXPECT_EQ(scroll_result.accumulated_root_overscroll,
|
| - host_impl_->accumulated_root_overscroll());
|
| -
|
| - scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
|
| - EXPECT_FALSE(scroll_result.did_scroll);
|
| - EXPECT_TRUE(scroll_result.did_overscroll_root);
|
| - EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
|
| - EXPECT_EQ(scroll_result.accumulated_root_overscroll,
|
| - host_impl_->accumulated_root_overscroll());
|
| -
|
| - // Overscroll resets on valid scroll.
|
| - scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
|
| - EXPECT_TRUE(scroll_result.did_scroll);
|
| - EXPECT_FALSE(scroll_result.did_overscroll_root);
|
| - EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
|
| - EXPECT_EQ(scroll_result.accumulated_root_overscroll,
|
| - host_impl_->accumulated_root_overscroll());
|
| -
|
| - scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
|
| - EXPECT_TRUE(scroll_result.did_scroll);
|
| - EXPECT_TRUE(scroll_result.did_overscroll_root);
|
| - EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
|
| - EXPECT_EQ(scroll_result.accumulated_root_overscroll,
|
| - host_impl_->accumulated_root_overscroll());
|
| -
|
| - host_impl_->ScrollEnd();
|
| -}
|
| -
|
| -
|
| -TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
|
| - // Scroll child layers beyond their maximum scroll range and make sure root
|
| - // overscroll does not accumulate.
|
| - gfx::Size surface_size(10, 10);
|
| - scoped_ptr<LayerImpl> root_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 4);
|
| - root_clip->SetHasRenderSurface(true);
|
| -
|
| - scoped_ptr<LayerImpl> root =
|
| - CreateScrollableLayer(1, surface_size, root_clip.get());
|
| -
|
| - scoped_ptr<LayerImpl> grand_child =
|
| - CreateScrollableLayer(3, surface_size, root_clip.get());
|
| -
|
| - scoped_ptr<LayerImpl> child =
|
| - CreateScrollableLayer(2, surface_size, root_clip.get());
|
| - LayerImpl* grand_child_layer = grand_child.get();
|
| - child->AddChild(grand_child.Pass());
|
| -
|
| - LayerImpl* child_layer = child.get();
|
| - root->AddChild(child.Pass());
|
| - root_clip->AddChild(root.Pass());
|
| - child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
|
| - grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
|
| - host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - host_impl_->SetViewportSize(surface_size);
|
| - DrawFrame();
|
| - {
|
| - gfx::Vector2d scroll_delta(0, -10);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(),
|
| - InputHandler::NON_BUBBLING_GESTURE));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // The next time we scroll we should only scroll the parent, but overscroll
|
| - // should still not reach the root layer.
|
| - scroll_delta = gfx::Vector2d(0, -30);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5),
|
| - InputHandler::NON_BUBBLING_GESTURE));
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
|
| - EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
|
| - EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
|
| - host_impl_->ScrollEnd();
|
| -
|
| - // After scrolling the parent, another scroll on the opposite direction
|
| - // should scroll the child.
|
| - scroll_delta = gfx::Vector2d(0, 70);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5),
|
| - InputHandler::NON_BUBBLING_GESTURE));
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
|
| - EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
|
| - host_impl_->ScrollEnd();
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
|
| - // When we try to scroll a non-scrollable child layer, the scroll delta
|
| - // should be applied to one of its ancestors if possible. Overscroll should
|
| - // be reflected only when it has bubbled up to the root scrolling layer.
|
| - gfx::Size surface_size(10, 10);
|
| - gfx::Size content_size(20, 20);
|
| - scoped_ptr<LayerImpl> root_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - root_clip->SetHasRenderSurface(true);
|
| -
|
| - scoped_ptr<LayerImpl> root =
|
| - CreateScrollableLayer(1, content_size, root_clip.get());
|
| - root->SetIsContainerForFixedPositionLayers(true);
|
| - scoped_ptr<LayerImpl> child =
|
| - CreateScrollableLayer(2, content_size, root_clip.get());
|
| -
|
| - child->SetScrollClipLayer(Layer::INVALID_ID);
|
| - root->AddChild(child.Pass());
|
| - root_clip->AddChild(root.Pass());
|
| -
|
| - host_impl_->SetViewportSize(surface_size);
|
| - host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
|
| - Layer::INVALID_ID);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - DrawFrame();
|
| - {
|
| - gfx::Vector2d scroll_delta(0, 8);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
|
| - host_impl_->ScrollEnd();
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
|
| - LayerTreeSettings settings;
|
| - CreateHostImpl(settings, CreateOutputSurface());
|
| -
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
|
| - LayerImpl* clip_layer = scroll_layer->parent()->parent();
|
| - clip_layer->SetBounds(gfx::Size(50, 50));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
|
| - DrawFrame();
|
| - EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
|
| -
|
| - // Even though the layer can't scroll the overscroll still happens.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
|
| - EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
|
| - gfx::Size surface_size(980, 1439);
|
| - gfx::Size content_size(980, 1438);
|
| - float device_scale_factor = 1.5f;
|
| - scoped_ptr<LayerImpl> root_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - root_clip->SetHasRenderSurface(true);
|
| -
|
| - scoped_ptr<LayerImpl> root =
|
| - CreateScrollableLayer(1, content_size, root_clip.get());
|
| - root->SetIsContainerForFixedPositionLayers(true);
|
| - scoped_ptr<LayerImpl> child =
|
| - CreateScrollableLayer(2, content_size, root_clip.get());
|
| - root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(0.326531f, 0.326531f,
|
| - 5.f);
|
| - host_impl_->SetPageScaleOnActiveTree(0.326531f);
|
| - child->SetScrollClipLayer(Layer::INVALID_ID);
|
| - root->AddChild(child.Pass());
|
| - root_clip->AddChild(root.Pass());
|
| -
|
| - host_impl_->SetViewportSize(surface_size);
|
| - host_impl_->SetDeviceScaleFactor(device_scale_factor);
|
| - host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
|
| - Layer::INVALID_ID);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - DrawFrame();
|
| - {
|
| - // Horizontal & Vertical GlowEffect should not be applied when
|
| - // content size is less then view port size. For Example Horizontal &
|
| - // vertical GlowEffect should not be applied in about:blank page.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
|
| - EXPECT_EQ(gfx::Vector2dF().ToString(),
|
| - host_impl_->accumulated_root_overscroll().ToString());
|
| -
|
| - host_impl_->ScrollEnd();
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
|
| - gfx::Size surface_size(100, 100);
|
| - gfx::Size content_size(200, 200);
|
| - scoped_ptr<LayerImpl> root_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - root_clip->SetHasRenderSurface(true);
|
| -
|
| - scoped_ptr<LayerImpl> root =
|
| - CreateScrollableLayer(1, content_size, root_clip.get());
|
| - root->SetIsContainerForFixedPositionLayers(true);
|
| - scoped_ptr<LayerImpl> child =
|
| - CreateScrollableLayer(2, content_size, root_clip.get());
|
| -
|
| - child->SetScrollClipLayer(Layer::INVALID_ID);
|
| - root->AddChild(child.Pass());
|
| - root_clip->AddChild(root.Pass());
|
| -
|
| - host_impl_->SetViewportSize(surface_size);
|
| - host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
|
| - Layer::INVALID_ID);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - DrawFrame();
|
| - {
|
| - // Edge glow effect should be applicable only upon reaching Edges
|
| - // of the content. unnecessary glow effect calls shouldn't be
|
| - // called while scrolling up without reaching the edge of the content.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
|
| - EXPECT_EQ(gfx::Vector2dF().ToString(),
|
| - host_impl_->accumulated_root_overscroll().ToString());
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
|
| - EXPECT_EQ(gfx::Vector2dF().ToString(),
|
| - host_impl_->accumulated_root_overscroll().ToString());
|
| - host_impl_->ScrollEnd();
|
| - // unusedrootDelta should be subtracted from applied delta so that
|
| - // unwanted glow effect calls are not called.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(0, 0),
|
| - InputHandler::NON_BUBBLING_GESTURE));
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
|
| - EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
|
| - host_impl_->accumulated_root_overscroll().ToString());
|
| -
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
|
| - EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
|
| - host_impl_->accumulated_root_overscroll().ToString());
|
| - host_impl_->ScrollEnd();
|
| - // TestCase to check kEpsilon, which prevents minute values to trigger
|
| - // gloweffect without reaching edge.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
|
| - EXPECT_EQ(gfx::Vector2dF().ToString(),
|
| - host_impl_->accumulated_root_overscroll().ToString());
|
| - host_impl_->ScrollEnd();
|
| - }
|
| -}
|
| -
|
| -class BlendStateCheckLayer : public LayerImpl {
|
| - public:
|
| - static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
|
| - int id,
|
| - ResourceProvider* resource_provider) {
|
| - return make_scoped_ptr(
|
| - new BlendStateCheckLayer(tree_impl, id, resource_provider));
|
| - }
|
| -
|
| - void AppendQuads(RenderPass* render_pass,
|
| - AppendQuadsData* append_quads_data) override {
|
| - quads_appended_ = true;
|
| -
|
| - gfx::Rect opaque_rect;
|
| - if (contents_opaque())
|
| - opaque_rect = quad_rect_;
|
| - else
|
| - opaque_rect = opaque_content_rect_;
|
| - gfx::Rect visible_quad_rect = quad_rect_;
|
| -
|
| - SharedQuadState* shared_quad_state =
|
| - render_pass->CreateAndAppendSharedQuadState();
|
| - PopulateSharedQuadState(shared_quad_state);
|
| -
|
| - TileDrawQuad* test_blending_draw_quad =
|
| - render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
|
| - test_blending_draw_quad->SetNew(shared_quad_state,
|
| - quad_rect_,
|
| - opaque_rect,
|
| - visible_quad_rect,
|
| - resource_id_,
|
| - gfx::RectF(0.f, 0.f, 1.f, 1.f),
|
| - gfx::Size(1, 1),
|
| - false,
|
| - false);
|
| - test_blending_draw_quad->visible_rect = quad_visible_rect_;
|
| - EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
|
| - EXPECT_EQ(has_render_surface_, !!render_surface());
|
| - }
|
| -
|
| - void SetExpectation(bool blend, bool has_render_surface) {
|
| - blend_ = blend;
|
| - has_render_surface_ = has_render_surface;
|
| - quads_appended_ = false;
|
| - }
|
| -
|
| - bool quads_appended() const { return quads_appended_; }
|
| -
|
| - void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
|
| - void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
|
| - void SetOpaqueContentRect(const gfx::Rect& rect) {
|
| - opaque_content_rect_ = rect;
|
| - }
|
| -
|
| - private:
|
| - BlendStateCheckLayer(LayerTreeImpl* tree_impl,
|
| - int id,
|
| - ResourceProvider* resource_provider)
|
| - : LayerImpl(tree_impl, id),
|
| - blend_(false),
|
| - has_render_surface_(false),
|
| - quads_appended_(false),
|
| - quad_rect_(5, 5, 5, 5),
|
| - quad_visible_rect_(5, 5, 5, 5),
|
| - resource_id_(resource_provider->CreateResource(
|
| - gfx::Size(1, 1),
|
| - GL_CLAMP_TO_EDGE,
|
| - ResourceProvider::TEXTURE_HINT_IMMUTABLE,
|
| - RGBA_8888)) {
|
| - resource_provider->AllocateForTesting(resource_id_);
|
| - SetBounds(gfx::Size(10, 10));
|
| - SetContentBounds(gfx::Size(10, 10));
|
| - SetDrawsContent(true);
|
| - }
|
| -
|
| - bool blend_;
|
| - bool has_render_surface_;
|
| - bool quads_appended_;
|
| - gfx::Rect quad_rect_;
|
| - gfx::Rect opaque_content_rect_;
|
| - gfx::Rect quad_visible_rect_;
|
| - ResourceProvider::ResourceId resource_id_;
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
|
| - {
|
| - scoped_ptr<LayerImpl> root =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->SetBounds(gfx::Size(10, 10));
|
| - root->SetContentBounds(root->bounds());
|
| - root->SetDrawsContent(false);
|
| - root->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - }
|
| - LayerImpl* root = host_impl_->active_tree()->root_layer();
|
| -
|
| - root->AddChild(
|
| - BlendStateCheckLayer::Create(host_impl_->active_tree(),
|
| - 2,
|
| - host_impl_->resource_provider()));
|
| - BlendStateCheckLayer* layer1 =
|
| - static_cast<BlendStateCheckLayer*>(root->children()[0]);
|
| - layer1->SetPosition(gfx::PointF(2.f, 2.f));
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| -
|
| - // Opaque layer, drawn without blending.
|
| - layer1->SetContentsOpaque(true);
|
| - layer1->SetExpectation(false, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - // Layer with translucent content and painting, so drawn with blending.
|
| - layer1->SetContentsOpaque(false);
|
| - layer1->SetExpectation(true, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - // Layer with translucent opacity, drawn with blending.
|
| - layer1->SetContentsOpaque(true);
|
| - layer1->SetOpacity(0.5f);
|
| - layer1->SetExpectation(true, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - // Layer with translucent opacity and painting, drawn with blending.
|
| - layer1->SetContentsOpaque(true);
|
| - layer1->SetOpacity(0.5f);
|
| - layer1->SetExpectation(true, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - layer1->AddChild(
|
| - BlendStateCheckLayer::Create(host_impl_->active_tree(),
|
| - 3,
|
| - host_impl_->resource_provider()));
|
| - BlendStateCheckLayer* layer2 =
|
| - static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
|
| - layer2->SetPosition(gfx::PointF(4.f, 4.f));
|
| -
|
| - // 2 opaque layers, drawn without blending.
|
| - layer1->SetContentsOpaque(true);
|
| - layer1->SetOpacity(1.f);
|
| - layer1->SetExpectation(false, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - layer2->SetContentsOpaque(true);
|
| - layer2->SetOpacity(1.f);
|
| - layer2->SetExpectation(false, false);
|
| - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - EXPECT_TRUE(layer2->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - // Parent layer with translucent content, drawn with blending.
|
| - // Child layer with opaque content, drawn without blending.
|
| - layer1->SetContentsOpaque(false);
|
| - layer1->SetExpectation(true, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - layer2->SetExpectation(false, false);
|
| - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - EXPECT_TRUE(layer2->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - // Parent layer with translucent content but opaque painting, drawn without
|
| - // blending.
|
| - // Child layer with opaque content, drawn without blending.
|
| - layer1->SetContentsOpaque(true);
|
| - layer1->SetExpectation(false, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - layer2->SetExpectation(false, false);
|
| - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - EXPECT_TRUE(layer2->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - // Parent layer with translucent opacity and opaque content. Since it has a
|
| - // drawing child, it's drawn to a render surface which carries the opacity,
|
| - // so it's itself drawn without blending.
|
| - // Child layer with opaque content, drawn without blending (parent surface
|
| - // carries the inherited opacity).
|
| - layer1->SetContentsOpaque(true);
|
| - layer1->SetOpacity(0.5f);
|
| - layer1->SetHasRenderSurface(true);
|
| - layer1->SetExpectation(false, true);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - layer2->SetExpectation(false, false);
|
| - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
|
| - host_impl_->active_tree()->root_layer());
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - EXPECT_TRUE(layer2->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - layer1->SetHasRenderSurface(false);
|
| -
|
| - // Draw again, but with child non-opaque, to make sure
|
| - // layer1 not culled.
|
| - layer1->SetContentsOpaque(true);
|
| - layer1->SetOpacity(1.f);
|
| - layer1->SetExpectation(false, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - layer2->SetContentsOpaque(true);
|
| - layer2->SetOpacity(0.5f);
|
| - layer2->SetExpectation(true, false);
|
| - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - EXPECT_TRUE(layer2->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - // A second way of making the child non-opaque.
|
| - layer1->SetContentsOpaque(true);
|
| - layer1->SetOpacity(1.f);
|
| - layer1->SetExpectation(false, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - layer2->SetContentsOpaque(false);
|
| - layer2->SetOpacity(1.f);
|
| - layer2->SetExpectation(true, false);
|
| - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - EXPECT_TRUE(layer2->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - // And when the layer says its not opaque but is painted opaque, it is not
|
| - // blended.
|
| - layer1->SetContentsOpaque(true);
|
| - layer1->SetOpacity(1.f);
|
| - layer1->SetExpectation(false, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - layer2->SetContentsOpaque(true);
|
| - layer2->SetOpacity(1.f);
|
| - layer2->SetExpectation(false, false);
|
| - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - EXPECT_TRUE(layer2->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - // Layer with partially opaque contents, drawn with blending.
|
| - layer1->SetContentsOpaque(false);
|
| - layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
|
| - layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
|
| - layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
|
| - layer1->SetExpectation(true, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - // Layer with partially opaque contents partially culled, drawn with blending.
|
| - layer1->SetContentsOpaque(false);
|
| - layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
|
| - layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
|
| - layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
|
| - layer1->SetExpectation(true, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - // Layer with partially opaque contents culled, drawn with blending.
|
| - layer1->SetContentsOpaque(false);
|
| - layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
|
| - layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
|
| - layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
|
| - layer1->SetExpectation(true, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - // Layer with partially opaque contents and translucent contents culled, drawn
|
| - // without blending.
|
| - layer1->SetContentsOpaque(false);
|
| - layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
|
| - layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
|
| - layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
|
| - layer1->SetExpectation(false, false);
|
| - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(layer1->quads_appended());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -}
|
| -
|
| -class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
|
| - protected:
|
| - LayerTreeHostImplViewportCoveredTest() :
|
| - gutter_quad_material_(DrawQuad::SOLID_COLOR),
|
| - child_(NULL),
|
| - did_activate_pending_tree_(false) {}
|
| -
|
| - scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
|
| - if (always_draw) {
|
| - return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
|
| - }
|
| - return FakeOutputSurface::Create3d();
|
| - }
|
| -
|
| - void SetupActiveTreeLayers() {
|
| - host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
|
| - host_impl_->active_tree()->SetRootLayer(
|
| - LayerImpl::Create(host_impl_->active_tree(), 1));
|
| - host_impl_->active_tree()->root_layer()->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->root_layer()->AddChild(
|
| - BlendStateCheckLayer::Create(host_impl_->active_tree(),
|
| - 2,
|
| - host_impl_->resource_provider()));
|
| - child_ = static_cast<BlendStateCheckLayer*>(
|
| - host_impl_->active_tree()->root_layer()->children()[0]);
|
| - child_->SetExpectation(false, false);
|
| - child_->SetContentsOpaque(true);
|
| - }
|
| -
|
| - // Expect no gutter rects.
|
| - void TestLayerCoversFullViewport() {
|
| - gfx::Rect layer_rect(viewport_size_);
|
| - child_->SetPosition(layer_rect.origin());
|
| - child_->SetBounds(layer_rect.size());
|
| - child_->SetContentBounds(layer_rect.size());
|
| - child_->SetQuadRect(gfx::Rect(layer_rect.size()));
|
| - child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| -
|
| - EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
|
| - EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
|
| - ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
|
| -
|
| - VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| - // Expect fullscreen gutter rect.
|
| - void TestEmptyLayer() {
|
| - gfx::Rect layer_rect(0, 0, 0, 0);
|
| - child_->SetPosition(layer_rect.origin());
|
| - child_->SetBounds(layer_rect.size());
|
| - child_->SetContentBounds(layer_rect.size());
|
| - child_->SetQuadRect(gfx::Rect(layer_rect.size()));
|
| - child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| -
|
| - EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
|
| - EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
|
| - ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
|
| -
|
| - VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| - // Expect four surrounding gutter rects.
|
| - void TestLayerInMiddleOfViewport() {
|
| - gfx::Rect layer_rect(500, 500, 200, 200);
|
| - child_->SetPosition(layer_rect.origin());
|
| - child_->SetBounds(layer_rect.size());
|
| - child_->SetContentBounds(layer_rect.size());
|
| - child_->SetQuadRect(gfx::Rect(layer_rect.size()));
|
| - child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| -
|
| - EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
|
| - EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
|
| - ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
|
| -
|
| - VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| - // Expect no gutter rects.
|
| - void TestLayerIsLargerThanViewport() {
|
| - gfx::Rect layer_rect(viewport_size_.width() + 10,
|
| - viewport_size_.height() + 10);
|
| - child_->SetPosition(layer_rect.origin());
|
| - child_->SetBounds(layer_rect.size());
|
| - child_->SetContentBounds(layer_rect.size());
|
| - child_->SetQuadRect(gfx::Rect(layer_rect.size()));
|
| - child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| -
|
| - EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
|
| - EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
|
| - ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
|
| -
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| - void DidActivateSyncTree() override { did_activate_pending_tree_ = true; }
|
| -
|
| - void set_gutter_quad_material(DrawQuad::Material material) {
|
| - gutter_quad_material_ = material;
|
| - }
|
| - void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
|
| - gutter_texture_size_ = gutter_texture_size;
|
| - }
|
| -
|
| - protected:
|
| - size_t CountGutterQuads(const QuadList& quad_list) {
|
| - size_t num_gutter_quads = 0;
|
| - for (const auto& quad : quad_list) {
|
| - num_gutter_quads += (quad->material == gutter_quad_material_) ? 1 : 0;
|
| - }
|
| - return num_gutter_quads;
|
| - }
|
| -
|
| - void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
|
| - LayerTestCommon::VerifyQuadsExactlyCoverRect(
|
| - quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
|
| - }
|
| -
|
| - // Make sure that the texture coordinates match their expectations.
|
| - void ValidateTextureDrawQuads(const QuadList& quad_list) {
|
| - for (const auto& quad : quad_list) {
|
| - if (quad->material != DrawQuad::TEXTURE_CONTENT)
|
| - continue;
|
| - const TextureDrawQuad* texture_quad = TextureDrawQuad::MaterialCast(quad);
|
| - gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
|
| - gutter_texture_size_, host_impl_->device_scale_factor());
|
| - EXPECT_EQ(texture_quad->uv_top_left.x(),
|
| - texture_quad->rect.x() / gutter_texture_size_pixels.width());
|
| - EXPECT_EQ(texture_quad->uv_top_left.y(),
|
| - texture_quad->rect.y() / gutter_texture_size_pixels.height());
|
| - EXPECT_EQ(
|
| - texture_quad->uv_bottom_right.x(),
|
| - texture_quad->rect.right() / gutter_texture_size_pixels.width());
|
| - EXPECT_EQ(
|
| - texture_quad->uv_bottom_right.y(),
|
| - texture_quad->rect.bottom() / gutter_texture_size_pixels.height());
|
| - }
|
| - }
|
| -
|
| - gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
|
| - return gfx::ToRoundedSize(
|
| - gfx::ScaleSize(size, host_impl_->device_scale_factor()));
|
| - }
|
| -
|
| - DrawQuad::Material gutter_quad_material_;
|
| - gfx::Size gutter_texture_size_;
|
| - gfx::Size viewport_size_;
|
| - BlendStateCheckLayer* child_;
|
| - bool did_activate_pending_tree_;
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
|
| - viewport_size_ = gfx::Size(1000, 1000);
|
| -
|
| - bool always_draw = false;
|
| - CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
|
| -
|
| - host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
|
| - SetupActiveTreeLayers();
|
| - TestLayerCoversFullViewport();
|
| - TestEmptyLayer();
|
| - TestLayerInMiddleOfViewport();
|
| - TestLayerIsLargerThanViewport();
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
|
| - viewport_size_ = gfx::Size(1000, 1000);
|
| -
|
| - bool always_draw = false;
|
| - CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
|
| -
|
| - host_impl_->SetDeviceScaleFactor(2.f);
|
| - host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
|
| - SetupActiveTreeLayers();
|
| - TestLayerCoversFullViewport();
|
| - TestEmptyLayer();
|
| - TestLayerInMiddleOfViewport();
|
| - TestLayerIsLargerThanViewport();
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
|
| - viewport_size_ = gfx::Size(1000, 1000);
|
| -
|
| - bool always_draw = true;
|
| - CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
|
| -
|
| - // Pending tree to force active_tree size invalid. Not used otherwise.
|
| - host_impl_->CreatePendingTree();
|
| - host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
|
| - EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
|
| -
|
| - SetupActiveTreeLayers();
|
| - TestEmptyLayer();
|
| - TestLayerInMiddleOfViewport();
|
| - TestLayerIsLargerThanViewport();
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
|
| - viewport_size_ = gfx::Size(1000, 1000);
|
| -
|
| - bool always_draw = true;
|
| - CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
|
| -
|
| - // Set larger viewport and activate it to active tree.
|
| - host_impl_->CreatePendingTree();
|
| - gfx::Size larger_viewport(viewport_size_.width() + 100,
|
| - viewport_size_.height() + 100);
|
| - host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
|
| - EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
|
| - host_impl_->ActivateSyncTree();
|
| - EXPECT_TRUE(did_activate_pending_tree_);
|
| - EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
|
| -
|
| - // Shrink pending tree viewport without activating.
|
| - host_impl_->CreatePendingTree();
|
| - host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
|
| - EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
|
| -
|
| - SetupActiveTreeLayers();
|
| - TestEmptyLayer();
|
| - TestLayerInMiddleOfViewport();
|
| - TestLayerIsLargerThanViewport();
|
| -}
|
| -
|
| -class FakeDrawableLayerImpl: public LayerImpl {
|
| - public:
|
| - static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
|
| - return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl, id));
|
| - }
|
| - protected:
|
| - FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
|
| - : LayerImpl(tree_impl, id) {}
|
| -};
|
| -
|
| -// Only reshape when we know we are going to draw. Otherwise, the reshape
|
| -// can leave the window at the wrong size if we never draw and the proper
|
| -// viewport size is never set.
|
| -TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
|
| - scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
|
| - scoped_ptr<OutputSurface> output_surface(
|
| - FakeOutputSurface::Create3d(provider));
|
| - CreateHostImpl(DefaultSettings(), output_surface.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> root =
|
| - FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->SetBounds(gfx::Size(10, 10));
|
| - root->SetContentBounds(gfx::Size(10, 10));
|
| - root->SetDrawsContent(true);
|
| - root->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - EXPECT_FALSE(provider->TestContext3d()->reshape_called());
|
| - provider->TestContext3d()->clear_reshape_called();
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - host_impl_->SetViewportSize(gfx::Size(10, 10));
|
| - host_impl_->SetDeviceScaleFactor(1.f);
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(provider->TestContext3d()->reshape_called());
|
| - EXPECT_EQ(provider->TestContext3d()->width(), 10);
|
| - EXPECT_EQ(provider->TestContext3d()->height(), 10);
|
| - EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - provider->TestContext3d()->clear_reshape_called();
|
| -
|
| - host_impl_->SetViewportSize(gfx::Size(20, 30));
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(provider->TestContext3d()->reshape_called());
|
| - EXPECT_EQ(provider->TestContext3d()->width(), 20);
|
| - EXPECT_EQ(provider->TestContext3d()->height(), 30);
|
| - EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - provider->TestContext3d()->clear_reshape_called();
|
| -
|
| - host_impl_->SetDeviceScaleFactor(2.f);
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - EXPECT_TRUE(provider->TestContext3d()->reshape_called());
|
| - EXPECT_EQ(provider->TestContext3d()->width(), 20);
|
| - EXPECT_EQ(provider->TestContext3d()->height(), 30);
|
| - EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - provider->TestContext3d()->clear_reshape_called();
|
| -}
|
| -
|
| -// Make sure damage tracking propagates all the way to the graphics context,
|
| -// where it should request to swap only the sub-buffer that is damaged.
|
| -TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
|
| - scoped_refptr<TestContextProvider> context_provider(
|
| - TestContextProvider::Create());
|
| - context_provider->BindToCurrentThread();
|
| - context_provider->TestContext3d()->set_have_post_sub_buffer(true);
|
| -
|
| - scoped_ptr<FakeOutputSurface> output_surface(
|
| - FakeOutputSurface::Create3d(context_provider));
|
| - FakeOutputSurface* fake_output_surface = output_surface.get();
|
| -
|
| - // This test creates its own LayerTreeHostImpl, so
|
| - // that we can force partial swap enabled.
|
| - LayerTreeSettings settings;
|
| - settings.renderer_settings.partial_swap_enabled = true;
|
| - scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
|
| - LayerTreeHostImpl::Create(
|
| - settings, this, &proxy_, &stats_instrumentation_,
|
| - shared_bitmap_manager_.get(), NULL, task_graph_runner_.get(), 0);
|
| - layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
|
| - layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
|
| -
|
| - scoped_ptr<LayerImpl> root =
|
| - FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
|
| - root->SetHasRenderSurface(true);
|
| - scoped_ptr<LayerImpl> child =
|
| - FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
|
| - child->SetPosition(gfx::PointF(12.f, 13.f));
|
| - child->SetBounds(gfx::Size(14, 15));
|
| - child->SetContentBounds(gfx::Size(14, 15));
|
| - child->SetDrawsContent(true);
|
| - root->SetBounds(gfx::Size(500, 500));
|
| - root->SetContentBounds(gfx::Size(500, 500));
|
| - root->SetDrawsContent(true);
|
| - root->AddChild(child.Pass());
|
| - layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| -
|
| - // First frame, the entire screen should get swapped.
|
| - EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
|
| - layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - layer_tree_host_impl->DidDrawAllLayers(frame);
|
| - layer_tree_host_impl->SwapBuffers(frame);
|
| - gfx::Rect expected_swap_rect(0, 0, 500, 500);
|
| - EXPECT_EQ(expected_swap_rect.ToString(),
|
| - fake_output_surface->last_swap_rect().ToString());
|
| -
|
| - // Second frame, only the damaged area should get swapped. Damage should be
|
| - // the union of old and new child rects.
|
| - // expected damage rect: gfx::Rect(26, 28);
|
| - // expected swap rect: vertically flipped, with origin at bottom left corner.
|
| - layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
|
| - gfx::PointF());
|
| - EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
|
| - layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - layer_tree_host_impl->SwapBuffers(frame);
|
| -
|
| - // Make sure that partial swap is constrained to the viewport dimensions
|
| - // expected damage rect: gfx::Rect(500, 500);
|
| - // expected swap rect: flipped damage rect, but also clamped to viewport
|
| - expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
|
| - EXPECT_EQ(expected_swap_rect.ToString(),
|
| - fake_output_surface->last_swap_rect().ToString());
|
| -
|
| - layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
|
| - // This will damage everything.
|
| - layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
|
| - SK_ColorBLACK);
|
| - EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
|
| - layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - layer_tree_host_impl->SwapBuffers(frame);
|
| -
|
| - expected_swap_rect = gfx::Rect(0, 0, 10, 10);
|
| - EXPECT_EQ(expected_swap_rect.ToString(),
|
| - fake_output_surface->last_swap_rect().ToString());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
|
| - scoped_ptr<LayerImpl> root =
|
| - FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
|
| - scoped_ptr<LayerImpl> child =
|
| - FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
|
| - child->SetBounds(gfx::Size(10, 10));
|
| - child->SetContentBounds(gfx::Size(10, 10));
|
| - child->SetDrawsContent(true);
|
| - root->SetBounds(gfx::Size(10, 10));
|
| - root->SetContentBounds(gfx::Size(10, 10));
|
| - root->SetDrawsContent(true);
|
| - root->SetHasRenderSurface(true);
|
| - root->AddChild(child.Pass());
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| -
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - EXPECT_EQ(1u, frame.render_surface_layer_list->size());
|
| - EXPECT_EQ(1u, frame.render_passes.size());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -}
|
| -
|
| -class FakeLayerWithQuads : public LayerImpl {
|
| - public:
|
| - static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
|
| - return make_scoped_ptr(new FakeLayerWithQuads(tree_impl, id));
|
| - }
|
| -
|
| - void AppendQuads(RenderPass* render_pass,
|
| - AppendQuadsData* append_quads_data) override {
|
| - SharedQuadState* shared_quad_state =
|
| - render_pass->CreateAndAppendSharedQuadState();
|
| - PopulateSharedQuadState(shared_quad_state);
|
| -
|
| - SkColor gray = SkColorSetRGB(100, 100, 100);
|
| - gfx::Rect quad_rect(content_bounds());
|
| - gfx::Rect visible_quad_rect(quad_rect);
|
| - SolidColorDrawQuad* my_quad =
|
| - render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
|
| - my_quad->SetNew(
|
| - shared_quad_state, quad_rect, visible_quad_rect, gray, false);
|
| - }
|
| -
|
| - private:
|
| - FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
|
| - : LayerImpl(tree_impl, id) {}
|
| -};
|
| -
|
| -class MockContext : public TestWebGraphicsContext3D {
|
| - public:
|
| - MOCK_METHOD1(useProgram, void(GLuint program));
|
| - MOCK_METHOD5(uniform4f, void(GLint location,
|
| - GLfloat x,
|
| - GLfloat y,
|
| - GLfloat z,
|
| - GLfloat w));
|
| - MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
|
| - GLsizei count,
|
| - GLboolean transpose,
|
| - const GLfloat* value));
|
| - MOCK_METHOD4(drawElements, void(GLenum mode,
|
| - GLsizei count,
|
| - GLenum type,
|
| - GLintptr offset));
|
| - MOCK_METHOD1(enable, void(GLenum cap));
|
| - MOCK_METHOD1(disable, void(GLenum cap));
|
| - MOCK_METHOD4(scissor, void(GLint x,
|
| - GLint y,
|
| - GLsizei width,
|
| - GLsizei height));
|
| -};
|
| -
|
| -class MockContextHarness {
|
| - private:
|
| - MockContext* context_;
|
| -
|
| - public:
|
| - explicit MockContextHarness(MockContext* context)
|
| - : context_(context) {
|
| - context_->set_have_post_sub_buffer(true);
|
| -
|
| - // Catch "uninteresting" calls
|
| - EXPECT_CALL(*context_, useProgram(_))
|
| - .Times(0);
|
| -
|
| - EXPECT_CALL(*context_, drawElements(_, _, _, _))
|
| - .Times(0);
|
| -
|
| - // These are not asserted
|
| - EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
|
| - .WillRepeatedly(Return());
|
| -
|
| - EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
|
| - .WillRepeatedly(Return());
|
| -
|
| - // Any un-sanctioned calls to enable() are OK
|
| - EXPECT_CALL(*context_, enable(_))
|
| - .WillRepeatedly(Return());
|
| -
|
| - // Any un-sanctioned calls to disable() are OK
|
| - EXPECT_CALL(*context_, disable(_))
|
| - .WillRepeatedly(Return());
|
| - }
|
| -
|
| - void MustDrawSolidQuad() {
|
| - EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
|
| - .WillOnce(Return())
|
| - .RetiresOnSaturation();
|
| -
|
| - EXPECT_CALL(*context_, useProgram(_))
|
| - .WillOnce(Return())
|
| - .RetiresOnSaturation();
|
| - }
|
| -
|
| - void MustSetScissor(int x, int y, int width, int height) {
|
| - EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
|
| - .WillRepeatedly(Return());
|
| -
|
| - EXPECT_CALL(*context_, scissor(x, y, width, height))
|
| - .Times(AtLeast(1))
|
| - .WillRepeatedly(Return());
|
| - }
|
| -
|
| - void MustSetNoScissor() {
|
| - EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
|
| - .WillRepeatedly(Return());
|
| -
|
| - EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
|
| - .Times(0);
|
| -
|
| - EXPECT_CALL(*context_, scissor(_, _, _, _))
|
| - .Times(0);
|
| - }
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
|
| - scoped_ptr<MockContext> mock_context_owned(new MockContext);
|
| - MockContext* mock_context = mock_context_owned.get();
|
| - MockContextHarness harness(mock_context);
|
| -
|
| - // Run test case
|
| - LayerTreeSettings settings = DefaultSettings();
|
| - settings.renderer_settings.partial_swap_enabled = false;
|
| - CreateHostImpl(settings,
|
| - FakeOutputSurface::Create3d(mock_context_owned.Pass()));
|
| - SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
|
| -
|
| - // Without partial swap, and no clipping, no scissor is set.
|
| - harness.MustDrawSolidQuad();
|
| - harness.MustSetNoScissor();
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| - Mock::VerifyAndClearExpectations(&mock_context);
|
| -
|
| - // Without partial swap, but a layer does clip its subtree, one scissor is
|
| - // set.
|
| - host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
|
| - harness.MustDrawSolidQuad();
|
| - harness.MustSetScissor(0, 0, 10, 10);
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| - Mock::VerifyAndClearExpectations(&mock_context);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, PartialSwap) {
|
| - scoped_ptr<MockContext> context_owned(new MockContext);
|
| - MockContext* mock_context = context_owned.get();
|
| - MockContextHarness harness(mock_context);
|
| -
|
| - LayerTreeSettings settings = DefaultSettings();
|
| - settings.renderer_settings.partial_swap_enabled = true;
|
| - CreateHostImpl(settings, FakeOutputSurface::Create3d(context_owned.Pass()));
|
| - SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
|
| -
|
| - // The first frame is not a partially-swapped one. No scissor should be set.
|
| - harness.MustSetNoScissor();
|
| - harness.MustDrawSolidQuad();
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| - Mock::VerifyAndClearExpectations(&mock_context);
|
| -
|
| - // Damage a portion of the frame.
|
| - host_impl_->active_tree()->root_layer()->SetUpdateRect(
|
| - gfx::Rect(0, 0, 2, 3));
|
| -
|
| - // The second frame will be partially-swapped (the y coordinates are flipped).
|
| - harness.MustSetScissor(0, 7, 2, 3);
|
| - harness.MustDrawSolidQuad();
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| - Mock::VerifyAndClearExpectations(&mock_context);
|
| -}
|
| -
|
| -static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
|
| - bool partial_swap,
|
| - LayerTreeHostImplClient* client,
|
| - Proxy* proxy,
|
| - SharedBitmapManager* manager,
|
| - RenderingStatsInstrumentation* stats_instrumentation) {
|
| - scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
|
| - scoped_ptr<OutputSurface> output_surface(
|
| - FakeOutputSurface::Create3d(provider));
|
| - provider->BindToCurrentThread();
|
| - provider->TestContext3d()->set_have_post_sub_buffer(true);
|
| -
|
| - LayerTreeSettings settings;
|
| - settings.renderer_settings.partial_swap_enabled = partial_swap;
|
| - scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
|
| - settings, client, proxy, stats_instrumentation, manager, NULL, NULL, 0);
|
| - my_host_impl->InitializeRenderer(output_surface.Pass());
|
| - my_host_impl->SetViewportSize(gfx::Size(100, 100));
|
| -
|
| - /*
|
| - Layers are created as follows:
|
| -
|
| - +--------------------+
|
| - | 1 |
|
| - | +-----------+ |
|
| - | | 2 | |
|
| - | | +-------------------+
|
| - | | | 3 |
|
| - | | +-------------------+
|
| - | | | |
|
| - | +-----------+ |
|
| - | |
|
| - | |
|
| - +--------------------+
|
| -
|
| - Layers 1, 2 have render surfaces
|
| - */
|
| - scoped_ptr<LayerImpl> root =
|
| - LayerImpl::Create(my_host_impl->active_tree(), 1);
|
| - scoped_ptr<LayerImpl> child =
|
| - LayerImpl::Create(my_host_impl->active_tree(), 2);
|
| - scoped_ptr<LayerImpl> grand_child =
|
| - FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
|
| -
|
| - gfx::Rect root_rect(0, 0, 100, 100);
|
| - gfx::Rect child_rect(10, 10, 50, 50);
|
| - gfx::Rect grand_child_rect(5, 5, 150, 150);
|
| -
|
| - root->SetHasRenderSurface(true);
|
| - root->SetPosition(root_rect.origin());
|
| - root->SetBounds(root_rect.size());
|
| - root->SetContentBounds(root->bounds());
|
| - root->draw_properties().visible_content_rect = root_rect;
|
| - root->SetDrawsContent(false);
|
| - root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
|
| -
|
| - child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
|
| - child->SetOpacity(0.5f);
|
| - child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
|
| - child->SetContentBounds(child->bounds());
|
| - child->draw_properties().visible_content_rect = child_rect;
|
| - child->SetDrawsContent(false);
|
| - child->SetHasRenderSurface(true);
|
| -
|
| - grand_child->SetPosition(grand_child_rect.origin());
|
| - grand_child->SetBounds(grand_child_rect.size());
|
| - grand_child->SetContentBounds(grand_child->bounds());
|
| - grand_child->draw_properties().visible_content_rect = grand_child_rect;
|
| - grand_child->SetDrawsContent(true);
|
| -
|
| - child->AddChild(grand_child.Pass());
|
| - root->AddChild(child.Pass());
|
| -
|
| - my_host_impl->active_tree()->SetRootLayer(root.Pass());
|
| - return my_host_impl.Pass();
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
|
| - scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
|
| - new TestSharedBitmapManager());
|
| - scoped_ptr<LayerTreeHostImpl> my_host_impl =
|
| - SetupLayersForOpacity(true,
|
| - this,
|
| - &proxy_,
|
| - shared_bitmap_manager.get(),
|
| - &stats_instrumentation_);
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
|
| -
|
| - // Verify all quads have been computed
|
| - ASSERT_EQ(2U, frame.render_passes.size());
|
| - ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
|
| - ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
|
| - EXPECT_EQ(DrawQuad::SOLID_COLOR,
|
| - frame.render_passes[0]->quad_list.front()->material);
|
| - EXPECT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[1]->quad_list.front()->material);
|
| -
|
| - my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - my_host_impl->DidDrawAllLayers(frame);
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
|
| - scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
|
| - new TestSharedBitmapManager());
|
| - scoped_ptr<LayerTreeHostImpl> my_host_impl =
|
| - SetupLayersForOpacity(false,
|
| - this,
|
| - &proxy_,
|
| - shared_bitmap_manager.get(),
|
| - &stats_instrumentation_);
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
|
| -
|
| - // Verify all quads have been computed
|
| - ASSERT_EQ(2U, frame.render_passes.size());
|
| - ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
|
| - ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
|
| - EXPECT_EQ(DrawQuad::SOLID_COLOR,
|
| - frame.render_passes[0]->quad_list.front()->material);
|
| - EXPECT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[1]->quad_list.front()->material);
|
| -
|
| - my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - my_host_impl->DidDrawAllLayers(frame);
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
|
| - scoped_ptr<TestWebGraphicsContext3D> context =
|
| - TestWebGraphicsContext3D::Create();
|
| - TestWebGraphicsContext3D* context3d = context.get();
|
| - scoped_ptr<OutputSurface> output_surface(
|
| - FakeOutputSurface::Create3d(context.Pass()));
|
| - CreateHostImpl(DefaultSettings(), output_surface.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> root_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root_layer->SetBounds(gfx::Size(10, 10));
|
| - root_layer->SetHasRenderSurface(true);
|
| -
|
| - scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
|
| - IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
|
| - io_surface_layer->SetBounds(gfx::Size(10, 10));
|
| - io_surface_layer->SetContentBounds(gfx::Size(10, 10));
|
| - io_surface_layer->SetDrawsContent(true);
|
| - io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
|
| - root_layer->AddChild(io_surface_layer.Pass());
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
|
| -
|
| - EXPECT_EQ(0u, context3d->NumTextures());
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - host_impl_->SwapBuffers(frame);
|
| -
|
| - EXPECT_GT(context3d->NumTextures(), 0u);
|
| -
|
| - // Kill the layer tree.
|
| - host_impl_->active_tree()->SetRootLayer(
|
| - LayerImpl::Create(host_impl_->active_tree(), 100));
|
| - // There should be no textures left in use after.
|
| - EXPECT_EQ(0u, context3d->NumTextures());
|
| -}
|
| -
|
| -class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
|
| - public:
|
| - MOCK_METHOD1(useProgram, void(GLuint program));
|
| - MOCK_METHOD4(drawElements, void(GLenum mode,
|
| - GLsizei count,
|
| - GLenum type,
|
| - GLintptr offset));
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
|
| - scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
|
| - new MockDrawQuadsToFillScreenContext);
|
| - MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
|
| -
|
| - // Run test case
|
| - LayerTreeSettings settings = DefaultSettings();
|
| - settings.renderer_settings.partial_swap_enabled = false;
|
| - CreateHostImpl(settings,
|
| - FakeOutputSurface::Create3d(mock_context_owned.Pass()));
|
| - SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
|
| - host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
|
| -
|
| - // Verify one quad is drawn when transparent background set is not set.
|
| - host_impl_->active_tree()->set_has_transparent_background(false);
|
| - EXPECT_CALL(*mock_context, useProgram(_))
|
| - .Times(1);
|
| - EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
|
| - .Times(1);
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - Mock::VerifyAndClearExpectations(&mock_context);
|
| -
|
| - // Verify no quads are drawn when transparent background is set.
|
| - host_impl_->active_tree()->set_has_transparent_background(true);
|
| - host_impl_->SetFullRootLayerDamage();
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - Mock::VerifyAndClearExpectations(&mock_context);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
|
| - set_reduce_memory_result(false);
|
| -
|
| - // If changing the memory limit wouldn't result in changing what was
|
| - // committed, then no commit should be requested.
|
| - set_reduce_memory_result(false);
|
| - host_impl_->set_max_memory_needed_bytes(
|
| - host_impl_->memory_allocation_limit_bytes() - 1);
|
| - host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
|
| - host_impl_->memory_allocation_limit_bytes() - 1));
|
| - EXPECT_FALSE(did_request_commit_);
|
| - did_request_commit_ = false;
|
| -
|
| - // If changing the memory limit would result in changing what was
|
| - // committed, then a commit should be requested, even though nothing was
|
| - // evicted.
|
| - set_reduce_memory_result(false);
|
| - host_impl_->set_max_memory_needed_bytes(
|
| - host_impl_->memory_allocation_limit_bytes());
|
| - host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
|
| - host_impl_->memory_allocation_limit_bytes() - 1));
|
| - EXPECT_TRUE(did_request_commit_);
|
| - did_request_commit_ = false;
|
| -
|
| - // Especially if changing the memory limit caused evictions, we need
|
| - // to re-commit.
|
| - set_reduce_memory_result(true);
|
| - host_impl_->set_max_memory_needed_bytes(1);
|
| - host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
|
| - host_impl_->memory_allocation_limit_bytes() - 1));
|
| - EXPECT_TRUE(did_request_commit_);
|
| - did_request_commit_ = false;
|
| -
|
| - // But if we set it to the same value that it was before, we shouldn't
|
| - // re-commit.
|
| - host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
|
| - host_impl_->memory_allocation_limit_bytes()));
|
| - EXPECT_FALSE(did_request_commit_);
|
| -}
|
| -
|
| -class LayerTreeHostImplTestWithDelegatingRenderer
|
| - : public LayerTreeHostImplTest {
|
| - protected:
|
| - scoped_ptr<OutputSurface> CreateOutputSurface() override {
|
| - return FakeOutputSurface::CreateDelegating3d();
|
| - }
|
| -
|
| - void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
|
| - bool expect_to_draw = !expected_damage.IsEmpty();
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - if (!expect_to_draw) {
|
| - // With no damage, we don't draw, and no quads are created.
|
| - ASSERT_EQ(0u, frame.render_passes.size());
|
| - } else {
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| -
|
| - // Verify the damage rect for the root render pass.
|
| - const RenderPass* root_render_pass = frame.render_passes.back();
|
| - EXPECT_EQ(expected_damage, root_render_pass->damage_rect);
|
| -
|
| - // Verify the root and child layers' quads are generated and not being
|
| - // culled.
|
| - ASSERT_EQ(2u, root_render_pass->quad_list.size());
|
| -
|
| - LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
|
| - gfx::RectF expected_child_visible_rect(child->content_bounds());
|
| - EXPECT_EQ(expected_child_visible_rect,
|
| - root_render_pass->quad_list.front()->visible_rect);
|
| -
|
| - LayerImpl* root = host_impl_->active_tree()->root_layer();
|
| - gfx::RectF expected_root_visible_rect(root->content_bounds());
|
| - EXPECT_EQ(expected_root_visible_rect,
|
| - root_render_pass->quad_list.ElementAt(1)->visible_rect);
|
| - }
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
|
| - }
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
|
| - scoped_ptr<SolidColorLayerImpl> root =
|
| - SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->SetPosition(gfx::PointF());
|
| - root->SetBounds(gfx::Size(10, 10));
|
| - root->SetContentBounds(gfx::Size(10, 10));
|
| - root->SetDrawsContent(true);
|
| - root->SetHasRenderSurface(true);
|
| -
|
| - // Child layer is in the bottom right corner.
|
| - scoped_ptr<SolidColorLayerImpl> child =
|
| - SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
|
| - child->SetPosition(gfx::PointF(9.f, 9.f));
|
| - child->SetBounds(gfx::Size(1, 1));
|
| - child->SetContentBounds(gfx::Size(1, 1));
|
| - child->SetDrawsContent(true);
|
| - root->AddChild(child.Pass());
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| -
|
| - // Draw a frame. In the first frame, the entire viewport should be damaged.
|
| - gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
|
| - DrawFrameAndTestDamage(full_frame_damage);
|
| -
|
| - // The second frame has damage that doesn't touch the child layer. Its quads
|
| - // should still be generated.
|
| - gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
|
| - host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
|
| - DrawFrameAndTestDamage(small_damage);
|
| -
|
| - // The third frame should have no damage, so no quads should be generated.
|
| - gfx::Rect no_damage;
|
| - DrawFrameAndTestDamage(no_damage);
|
| -}
|
| -
|
| -// TODO(reveman): Remove this test and the ability to prevent on demand raster
|
| -// when delegating renderer supports PictureDrawQuads. crbug.com/342121
|
| -TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
|
| - LayerTreeSettings settings;
|
| - CreateHostImpl(settings, CreateOutputSurface());
|
| - EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
|
| -}
|
| -
|
| -class FakeMaskLayerImpl : public LayerImpl {
|
| - public:
|
| - static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
|
| - int id) {
|
| - return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
|
| - }
|
| -
|
| - void GetContentsResourceId(ResourceProvider::ResourceId* resource_id,
|
| - gfx::Size* resource_size) const override {
|
| - *resource_id = 0;
|
| - }
|
| -
|
| - private:
|
| - FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
|
| - : LayerImpl(tree_impl, id) {}
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
|
| - LayerTreeSettings settings;
|
| - settings.layer_transforms_should_scale_layer_contents = true;
|
| - CreateHostImpl(settings, CreateOutputSurface());
|
| -
|
| - // Root
|
| - // |
|
| - // +-- Scaling Layer (adds a 2x scale)
|
| - // |
|
| - // +-- Content Layer
|
| - // +--Mask
|
| - scoped_ptr<LayerImpl> scoped_root =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - LayerImpl* root = scoped_root.get();
|
| - root->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> scoped_scaling_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 2);
|
| - LayerImpl* scaling_layer = scoped_scaling_layer.get();
|
| - root->AddChild(scoped_scaling_layer.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> scoped_content_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - LayerImpl* content_layer = scoped_content_layer.get();
|
| - scaling_layer->AddChild(scoped_content_layer.Pass());
|
| -
|
| - scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
|
| - FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
|
| - FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
|
| - content_layer->SetHasRenderSurface(true);
|
| - content_layer->SetMaskLayer(scoped_mask_layer.Pass());
|
| -
|
| - gfx::Size root_size(100, 100);
|
| - root->SetBounds(root_size);
|
| - root->SetContentBounds(root_size);
|
| - root->SetPosition(gfx::PointF());
|
| -
|
| - gfx::Size scaling_layer_size(50, 50);
|
| - scaling_layer->SetBounds(scaling_layer_size);
|
| - scaling_layer->SetContentBounds(scaling_layer_size);
|
| - scaling_layer->SetPosition(gfx::PointF());
|
| - gfx::Transform scale;
|
| - scale.Scale(2.f, 2.f);
|
| - scaling_layer->SetTransform(scale);
|
| -
|
| - content_layer->SetBounds(scaling_layer_size);
|
| - content_layer->SetContentBounds(scaling_layer_size);
|
| - content_layer->SetPosition(gfx::PointF());
|
| - content_layer->SetDrawsContent(true);
|
| -
|
| - mask_layer->SetBounds(scaling_layer_size);
|
| - mask_layer->SetContentBounds(scaling_layer_size);
|
| - mask_layer->SetPosition(gfx::PointF());
|
| - mask_layer->SetDrawsContent(true);
|
| -
|
| -
|
| - // Check that the tree scaling is correctly taken into account for the mask,
|
| - // that should fully map onto the quad.
|
| - float device_scale_factor = 1.f;
|
| - host_impl_->SetViewportSize(root_size);
|
| - host_impl_->SetDeviceScaleFactor(device_scale_factor);
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.front()->material);
|
| - const RenderPassDrawQuad* render_pass_quad =
|
| - RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.front());
|
| - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
|
| - render_pass_quad->rect.ToString());
|
| - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
|
| - render_pass_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
|
| - render_pass_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| -
|
| - // Applying a DSF should change the render surface size, but won't affect
|
| - // which part of the mask is used.
|
| - device_scale_factor = 2.f;
|
| - gfx::Size device_viewport =
|
| - gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
|
| - host_impl_->SetViewportSize(device_viewport);
|
| - host_impl_->SetDeviceScaleFactor(device_scale_factor);
|
| - host_impl_->active_tree()->set_needs_update_draw_properties();
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.front()->material);
|
| - const RenderPassDrawQuad* render_pass_quad =
|
| - RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.front());
|
| - EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
|
| - render_pass_quad->rect.ToString());
|
| - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
|
| - render_pass_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
|
| - render_pass_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| -
|
| - // Applying an equivalent content scale on the content layer and the mask
|
| - // should still result in the same part of the mask being used.
|
| - gfx::Size content_bounds =
|
| - gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
|
| - device_scale_factor));
|
| - content_layer->SetContentBounds(content_bounds);
|
| - content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
|
| - mask_layer->SetContentBounds(content_bounds);
|
| - mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
|
| - host_impl_->active_tree()->set_needs_update_draw_properties();
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.front()->material);
|
| - const RenderPassDrawQuad* render_pass_quad =
|
| - RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.front());
|
| - EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
|
| - render_pass_quad->rect.ToString());
|
| - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
|
| - render_pass_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
|
| - render_pass_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
|
| - // The mask layer has bounds 100x100 but is attached to a layer with bounds
|
| - // 50x50.
|
| -
|
| - scoped_ptr<LayerImpl> scoped_root =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - LayerImpl* root = scoped_root.get();
|
| - root->SetHasRenderSurface(true);
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> scoped_content_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - LayerImpl* content_layer = scoped_content_layer.get();
|
| - root->AddChild(scoped_content_layer.Pass());
|
| -
|
| - scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
|
| - FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
|
| - FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
|
| - content_layer->SetMaskLayer(scoped_mask_layer.Pass());
|
| - content_layer->SetHasRenderSurface(true);
|
| -
|
| - gfx::Size root_size(100, 100);
|
| - root->SetBounds(root_size);
|
| - root->SetContentBounds(root_size);
|
| - root->SetPosition(gfx::PointF());
|
| -
|
| - gfx::Size layer_size(50, 50);
|
| - content_layer->SetBounds(layer_size);
|
| - content_layer->SetContentBounds(layer_size);
|
| - content_layer->SetPosition(gfx::PointF());
|
| - content_layer->SetDrawsContent(true);
|
| -
|
| - gfx::Size mask_size(100, 100);
|
| - mask_layer->SetBounds(mask_size);
|
| - mask_layer->SetContentBounds(mask_size);
|
| - mask_layer->SetPosition(gfx::PointF());
|
| - mask_layer->SetDrawsContent(true);
|
| -
|
| - // Check that the mask fills the surface.
|
| - float device_scale_factor = 1.f;
|
| - host_impl_->SetViewportSize(root_size);
|
| - host_impl_->SetDeviceScaleFactor(device_scale_factor);
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.front()->material);
|
| - const RenderPassDrawQuad* render_pass_quad =
|
| - RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.front());
|
| - EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
|
| - render_pass_quad->rect.ToString());
|
| - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
|
| - render_pass_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
|
| - render_pass_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| - // Applying a DSF should change the render surface size, but won't affect
|
| - // which part of the mask is used.
|
| - device_scale_factor = 2.f;
|
| - gfx::Size device_viewport =
|
| - gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
|
| - host_impl_->SetViewportSize(device_viewport);
|
| - host_impl_->SetDeviceScaleFactor(device_scale_factor);
|
| - host_impl_->active_tree()->set_needs_update_draw_properties();
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.front()->material);
|
| - const RenderPassDrawQuad* render_pass_quad =
|
| - RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.front());
|
| - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
|
| - render_pass_quad->rect.ToString());
|
| - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
|
| - render_pass_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
|
| - render_pass_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| - // Applying an equivalent content scale on the content layer and the mask
|
| - // should still result in the same part of the mask being used.
|
| - gfx::Size layer_size_large =
|
| - gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
|
| - content_layer->SetContentBounds(layer_size_large);
|
| - content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
|
| - gfx::Size mask_size_large =
|
| - gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
|
| - mask_layer->SetContentBounds(mask_size_large);
|
| - mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
|
| - host_impl_->active_tree()->set_needs_update_draw_properties();
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.front()->material);
|
| - const RenderPassDrawQuad* render_pass_quad =
|
| - RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.front());
|
| - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
|
| - render_pass_quad->rect.ToString());
|
| - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
|
| - render_pass_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
|
| - render_pass_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| - // Applying a different contents scale to the mask layer means it will have
|
| - // a larger texture, but it should use the same tex coords to cover the
|
| - // layer it masks.
|
| - mask_layer->SetContentBounds(mask_size);
|
| - mask_layer->SetContentsScale(1.f, 1.f);
|
| - host_impl_->active_tree()->set_needs_update_draw_properties();
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.front()->material);
|
| - const RenderPassDrawQuad* render_pass_quad =
|
| - RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.front());
|
| - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
|
| - render_pass_quad->rect.ToString());
|
| - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
|
| - render_pass_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
|
| - render_pass_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
|
| - // The replica's mask layer has bounds 100x100 but the replica is of a
|
| - // layer with bounds 50x50.
|
| -
|
| - scoped_ptr<LayerImpl> scoped_root =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - LayerImpl* root = scoped_root.get();
|
| - root->SetHasRenderSurface(true);
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> scoped_content_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - LayerImpl* content_layer = scoped_content_layer.get();
|
| - root->AddChild(scoped_content_layer.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> scoped_replica_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 2);
|
| - LayerImpl* replica_layer = scoped_replica_layer.get();
|
| - content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
|
| - content_layer->SetHasRenderSurface(true);
|
| -
|
| - scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
|
| - FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
|
| - FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
|
| - replica_layer->SetMaskLayer(scoped_mask_layer.Pass());
|
| - replica_layer->SetHasRenderSurface(true);
|
| -
|
| - gfx::Size root_size(100, 100);
|
| - root->SetBounds(root_size);
|
| - root->SetContentBounds(root_size);
|
| - root->SetPosition(gfx::PointF());
|
| -
|
| - gfx::Size layer_size(50, 50);
|
| - content_layer->SetBounds(layer_size);
|
| - content_layer->SetContentBounds(layer_size);
|
| - content_layer->SetPosition(gfx::PointF());
|
| - content_layer->SetDrawsContent(true);
|
| -
|
| - gfx::Size mask_size(100, 100);
|
| - mask_layer->SetBounds(mask_size);
|
| - mask_layer->SetContentBounds(mask_size);
|
| - mask_layer->SetPosition(gfx::PointF());
|
| - mask_layer->SetDrawsContent(true);
|
| -
|
| - // Check that the mask fills the surface.
|
| - float device_scale_factor = 1.f;
|
| - host_impl_->SetViewportSize(root_size);
|
| - host_impl_->SetDeviceScaleFactor(device_scale_factor);
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.ElementAt(1)->material);
|
| - const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.ElementAt(1));
|
| - EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
|
| - replica_quad->rect.ToString());
|
| - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
|
| - replica_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
|
| - replica_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| - // Applying a DSF should change the render surface size, but won't affect
|
| - // which part of the mask is used.
|
| - device_scale_factor = 2.f;
|
| - gfx::Size device_viewport =
|
| - gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
|
| - host_impl_->SetViewportSize(device_viewport);
|
| - host_impl_->SetDeviceScaleFactor(device_scale_factor);
|
| - host_impl_->active_tree()->set_needs_update_draw_properties();
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.ElementAt(1)->material);
|
| - const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.ElementAt(1));
|
| - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
|
| - replica_quad->rect.ToString());
|
| - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
|
| - replica_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
|
| - replica_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| - // Applying an equivalent content scale on the content layer and the mask
|
| - // should still result in the same part of the mask being used.
|
| - gfx::Size layer_size_large =
|
| - gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
|
| - content_layer->SetContentBounds(layer_size_large);
|
| - content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
|
| - gfx::Size mask_size_large =
|
| - gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
|
| - mask_layer->SetContentBounds(mask_size_large);
|
| - mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
|
| - host_impl_->active_tree()->set_needs_update_draw_properties();
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.ElementAt(1)->material);
|
| - const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.ElementAt(1));
|
| - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
|
| - replica_quad->rect.ToString());
|
| - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
|
| - replica_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
|
| - replica_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| - // Applying a different contents scale to the mask layer means it will have
|
| - // a larger texture, but it should use the same tex coords to cover the
|
| - // layer it masks.
|
| - mask_layer->SetContentBounds(mask_size);
|
| - mask_layer->SetContentsScale(1.f, 1.f);
|
| - host_impl_->active_tree()->set_needs_update_draw_properties();
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.ElementAt(1)->material);
|
| - const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.ElementAt(1));
|
| - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
|
| - replica_quad->rect.ToString());
|
| - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
|
| - replica_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
|
| - replica_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
|
| - // The replica is of a layer with bounds 50x50, but it has a child that causes
|
| - // the surface bounds to be larger.
|
| -
|
| - scoped_ptr<LayerImpl> scoped_root =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - LayerImpl* root = scoped_root.get();
|
| - root->SetHasRenderSurface(true);
|
| - host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> scoped_content_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 2);
|
| - LayerImpl* content_layer = scoped_content_layer.get();
|
| - root->AddChild(scoped_content_layer.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> scoped_content_child_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - LayerImpl* content_child_layer = scoped_content_child_layer.get();
|
| - content_layer->AddChild(scoped_content_child_layer.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> scoped_replica_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 4);
|
| - LayerImpl* replica_layer = scoped_replica_layer.get();
|
| - content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
|
| - content_layer->SetHasRenderSurface(true);
|
| -
|
| - scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
|
| - FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
|
| - FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
|
| - replica_layer->SetMaskLayer(scoped_mask_layer.Pass());
|
| - replica_layer->SetHasRenderSurface(true);
|
| -
|
| - gfx::Size root_size(100, 100);
|
| - root->SetBounds(root_size);
|
| - root->SetContentBounds(root_size);
|
| - root->SetPosition(gfx::PointF());
|
| -
|
| - gfx::Size layer_size(50, 50);
|
| - content_layer->SetBounds(layer_size);
|
| - content_layer->SetContentBounds(layer_size);
|
| - content_layer->SetPosition(gfx::PointF());
|
| - content_layer->SetDrawsContent(true);
|
| -
|
| - gfx::Size child_size(50, 50);
|
| - content_child_layer->SetBounds(child_size);
|
| - content_child_layer->SetContentBounds(child_size);
|
| - content_child_layer->SetPosition(gfx::Point(50, 0));
|
| - content_child_layer->SetDrawsContent(true);
|
| -
|
| - gfx::Size mask_size(50, 50);
|
| - mask_layer->SetBounds(mask_size);
|
| - mask_layer->SetContentBounds(mask_size);
|
| - mask_layer->SetPosition(gfx::PointF());
|
| - mask_layer->SetDrawsContent(true);
|
| -
|
| - float device_scale_factor = 1.f;
|
| - host_impl_->SetViewportSize(root_size);
|
| - host_impl_->SetDeviceScaleFactor(device_scale_factor);
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
|
| -
|
| - // The surface is 100x50.
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.front()->material);
|
| - const RenderPassDrawQuad* render_pass_quad =
|
| - RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.front());
|
| - EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
|
| - render_pass_quad->rect.ToString());
|
| -
|
| - // The mask covers the owning layer only.
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.ElementAt(1)->material);
|
| - const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.ElementAt(1));
|
| - EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
|
| - replica_quad->rect.ToString());
|
| - EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
|
| - replica_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(2.f, 1.f).ToString(),
|
| - replica_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -
|
| - // Move the child to (-50, 0) instead. Now the mask should be moved to still
|
| - // cover the layer being replicated.
|
| - content_child_layer->SetPosition(gfx::Point(-50, 0));
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
|
| -
|
| - // The surface is 100x50 with its origin at (-50, 0).
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.front()->material);
|
| - const RenderPassDrawQuad* render_pass_quad =
|
| - RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.front());
|
| - EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
|
| - render_pass_quad->rect.ToString());
|
| -
|
| - // The mask covers the owning layer only.
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.ElementAt(1)->material);
|
| - const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.ElementAt(1));
|
| - EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
|
| - replica_quad->rect.ToString());
|
| - EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
|
| - replica_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(2.f, 1.f).ToString(),
|
| - replica_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
|
| - // The masked layer has bounds 50x50, but it has a child that causes
|
| - // the surface bounds to be larger. It also has a parent that clips the
|
| - // masked layer and its surface.
|
| -
|
| - scoped_ptr<LayerImpl> scoped_root =
|
| - LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - LayerImpl* root = scoped_root.get();
|
| - root->SetHasRenderSurface(true);
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> scoped_clipping_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 2);
|
| - LayerImpl* clipping_layer = scoped_clipping_layer.get();
|
| - root->AddChild(scoped_clipping_layer.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> scoped_content_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - LayerImpl* content_layer = scoped_content_layer.get();
|
| - clipping_layer->AddChild(scoped_content_layer.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> scoped_content_child_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 4);
|
| - LayerImpl* content_child_layer = scoped_content_child_layer.get();
|
| - content_layer->AddChild(scoped_content_child_layer.Pass());
|
| -
|
| - scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
|
| - FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
|
| - FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
|
| - content_layer->SetMaskLayer(scoped_mask_layer.Pass());
|
| - content_layer->SetHasRenderSurface(true);
|
| -
|
| - gfx::Size root_size(100, 100);
|
| - root->SetBounds(root_size);
|
| - root->SetContentBounds(root_size);
|
| - root->SetPosition(gfx::PointF());
|
| -
|
| - gfx::Rect clipping_rect(20, 10, 10, 20);
|
| - clipping_layer->SetBounds(clipping_rect.size());
|
| - clipping_layer->SetContentBounds(clipping_rect.size());
|
| - clipping_layer->SetPosition(clipping_rect.origin());
|
| - clipping_layer->SetMasksToBounds(true);
|
| -
|
| - gfx::Size layer_size(50, 50);
|
| - content_layer->SetBounds(layer_size);
|
| - content_layer->SetContentBounds(layer_size);
|
| - content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
|
| - content_layer->SetDrawsContent(true);
|
| -
|
| - gfx::Size child_size(50, 50);
|
| - content_child_layer->SetBounds(child_size);
|
| - content_child_layer->SetContentBounds(child_size);
|
| - content_child_layer->SetPosition(gfx::Point(50, 0));
|
| - content_child_layer->SetDrawsContent(true);
|
| -
|
| - gfx::Size mask_size(100, 100);
|
| - mask_layer->SetBounds(mask_size);
|
| - mask_layer->SetContentBounds(mask_size);
|
| - mask_layer->SetPosition(gfx::PointF());
|
| - mask_layer->SetDrawsContent(true);
|
| -
|
| - float device_scale_factor = 1.f;
|
| - host_impl_->SetViewportSize(root_size);
|
| - host_impl_->SetDeviceScaleFactor(device_scale_factor);
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
|
| -
|
| - // The surface is clipped to 10x20.
|
| - ASSERT_EQ(DrawQuad::RENDER_PASS,
|
| - frame.render_passes[0]->quad_list.front()->material);
|
| - const RenderPassDrawQuad* render_pass_quad =
|
| - RenderPassDrawQuad::MaterialCast(
|
| - frame.render_passes[0]->quad_list.front());
|
| - EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
|
| - render_pass_quad->rect.ToString());
|
| - // The masked layer is 50x50, but the surface size is 10x20. So the texture
|
| - // coords in the mask are scaled by 10/50 and 20/50.
|
| - // The surface is clipped to (20,10) so the mask texture coords are offset
|
| - // by 20/50 and 10/50
|
| - EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f)
|
| - .ToString(),
|
| - render_pass_quad->MaskUVRect().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(10.f / 50.f, 20.f / 50.f).ToString(),
|
| - render_pass_quad->mask_uv_scale.ToString());
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| -}
|
| -
|
| -class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
|
| - public:
|
| - using GLRenderer::ShouldAntialiasQuad;
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
|
| - // Due to precision issues (especially on Android), sometimes far
|
| - // away quads can end up thinking they need AA.
|
| - float device_scale_factor = 4.f / 3.f;
|
| - host_impl_->SetDeviceScaleFactor(device_scale_factor);
|
| - gfx::Size root_size(2000, 1000);
|
| - gfx::Size device_viewport_size =
|
| - gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
|
| - host_impl_->SetViewportSize(device_viewport_size);
|
| -
|
| - host_impl_->CreatePendingTree();
|
| - host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f / 16.f,
|
| - 16.f);
|
| -
|
| - scoped_ptr<LayerImpl> scoped_root =
|
| - LayerImpl::Create(host_impl_->pending_tree(), 1);
|
| - LayerImpl* root = scoped_root.get();
|
| - root->SetHasRenderSurface(true);
|
| -
|
| - host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
|
| -
|
| - scoped_ptr<LayerImpl> scoped_scrolling_layer =
|
| - LayerImpl::Create(host_impl_->pending_tree(), 2);
|
| - LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
|
| - root->AddChild(scoped_scrolling_layer.Pass());
|
| -
|
| - gfx::Size content_layer_bounds(100000, 100);
|
| - gfx::Size pile_tile_size(3000, 3000);
|
| - scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
|
| - pile_tile_size, content_layer_bounds));
|
| -
|
| - scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
|
| - FakePictureLayerImpl::CreateWithRasterSource(host_impl_->pending_tree(),
|
| - 3, pile);
|
| - LayerImpl* content_layer = scoped_content_layer.get();
|
| - scrolling_layer->AddChild(scoped_content_layer.Pass());
|
| - content_layer->SetBounds(content_layer_bounds);
|
| - content_layer->SetDrawsContent(true);
|
| -
|
| - root->SetBounds(root_size);
|
| -
|
| - gfx::ScrollOffset scroll_offset(100000, 0);
|
| - scrolling_layer->SetScrollClipLayer(root->id());
|
| - scrolling_layer->PushScrollOffsetFromMainThread(scroll_offset);
|
| -
|
| - host_impl_->ActivateSyncTree();
|
| -
|
| - bool update_lcd_text = false;
|
| - host_impl_->active_tree()->UpdateDrawProperties(update_lcd_text);
|
| - ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| -
|
| - ASSERT_EQ(1u, frame.render_passes.size());
|
| - ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
|
| - const DrawQuad* quad = frame.render_passes[0]->quad_list.front();
|
| -
|
| - bool antialiased =
|
| - GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
|
| - quad->quadTransform(), quad, false);
|
| - EXPECT_FALSE(antialiased);
|
| -
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -}
|
| -
|
| -
|
| -class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
|
| - public:
|
| - CompositorFrameMetadataTest()
|
| - : swap_buffers_complete_(0) {}
|
| -
|
| - void DidSwapBuffersCompleteOnImplThread() override {
|
| - swap_buffers_complete_++;
|
| - }
|
| -
|
| - int swap_buffers_complete_;
|
| -};
|
| -
|
| -TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
|
| - SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
|
| - {
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, base::TimeTicks());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - }
|
| - CompositorFrameAck ack;
|
| - host_impl_->ReclaimResources(&ack);
|
| - host_impl_->DidSwapBuffersComplete();
|
| - EXPECT_EQ(swap_buffers_complete_, 1);
|
| -}
|
| -
|
| -class CountingSoftwareDevice : public SoftwareOutputDevice {
|
| - public:
|
| - CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
|
| -
|
| - SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
|
| - ++frames_began_;
|
| - return SoftwareOutputDevice::BeginPaint(damage_rect);
|
| - }
|
| - void EndPaint(SoftwareFrameData* frame_data) override {
|
| - ++frames_ended_;
|
| - SoftwareOutputDevice::EndPaint(frame_data);
|
| - }
|
| -
|
| - int frames_began_, frames_ended_;
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
|
| - // No main thread evictions in resourceless software mode.
|
| - set_reduce_memory_result(false);
|
| - CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
|
| - bool delegated_rendering = false;
|
| - FakeOutputSurface* output_surface =
|
| - FakeOutputSurface::CreateDeferredGL(
|
| - scoped_ptr<SoftwareOutputDevice>(software_device),
|
| - delegated_rendering).release();
|
| - EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
|
| - scoped_ptr<OutputSurface>(output_surface)));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| -
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| -
|
| - const gfx::Transform external_transform;
|
| - const gfx::Rect external_viewport;
|
| - const gfx::Rect external_clip;
|
| - const bool resourceless_software_draw = true;
|
| - host_impl_->SetExternalDrawConstraints(external_transform,
|
| - external_viewport,
|
| - external_clip,
|
| - external_viewport,
|
| - external_transform,
|
| - resourceless_software_draw);
|
| -
|
| - EXPECT_EQ(0, software_device->frames_began_);
|
| - EXPECT_EQ(0, software_device->frames_ended_);
|
| -
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(1, software_device->frames_began_);
|
| - EXPECT_EQ(1, software_device->frames_ended_);
|
| -
|
| - // Call another API method that is likely to hit nullptr in this mode.
|
| - scoped_refptr<base::trace_event::TracedValue> state =
|
| - make_scoped_refptr(new base::trace_event::TracedValue());
|
| - host_impl_->ActivationStateAsValueInto(state.get());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest,
|
| - ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
|
| - set_reduce_memory_result(false);
|
| - bool delegated_rendering = false;
|
| - FakeOutputSurface* output_surface =
|
| - FakeOutputSurface::CreateDeferredGL(
|
| - scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
|
| - delegated_rendering).release();
|
| - EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
|
| - scoped_ptr<OutputSurface>(output_surface)));
|
| -
|
| - const gfx::Transform external_transform;
|
| - const gfx::Rect external_viewport;
|
| - const gfx::Rect external_clip;
|
| - const bool resourceless_software_draw = true;
|
| - host_impl_->SetExternalDrawConstraints(external_transform,
|
| - external_viewport,
|
| - external_clip,
|
| - external_viewport,
|
| - external_transform,
|
| - resourceless_software_draw);
|
| -
|
| - // SolidColorLayerImpl will be drawn.
|
| - scoped_ptr<SolidColorLayerImpl> root_layer =
|
| - SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - EXPECT_EQ(1u, frame.will_draw_layers.size());
|
| - EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
|
| -}
|
| -
|
| -class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
|
| - protected:
|
| - void SetUp() override {
|
| - LayerTreeHostImplTest::SetUp();
|
| -
|
| - set_reduce_memory_result(false);
|
| -
|
| - bool delegated_rendering = false;
|
| - scoped_ptr<FakeOutputSurface> output_surface(
|
| - FakeOutputSurface::CreateDeferredGL(
|
| - scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
|
| - delegated_rendering));
|
| - output_surface_ = output_surface.get();
|
| -
|
| - EXPECT_TRUE(CreateHostImpl(DefaultSettings(), output_surface.Pass()));
|
| -
|
| - scoped_ptr<SolidColorLayerImpl> root_layer =
|
| - SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
|
| - SetupRootLayerImpl(root_layer.Pass());
|
| -
|
| - onscreen_context_provider_ = TestContextProvider::Create();
|
| - }
|
| -
|
| - void UpdateRendererCapabilitiesOnImplThread() override {
|
| - did_update_renderer_capabilities_ = true;
|
| - }
|
| -
|
| - FakeOutputSurface* output_surface_;
|
| - scoped_refptr<TestContextProvider> onscreen_context_provider_;
|
| - bool did_update_renderer_capabilities_;
|
| -};
|
| -
|
| -
|
| -TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
|
| - // Software draw.
|
| - DrawFrame();
|
| -
|
| - EXPECT_FALSE(host_impl_->output_surface()->context_provider());
|
| -
|
| - // DeferredInitialize and hardware draw.
|
| - did_update_renderer_capabilities_ = false;
|
| - EXPECT_TRUE(output_surface_->InitializeAndSetContext3d(
|
| - onscreen_context_provider_, nullptr));
|
| - EXPECT_EQ(onscreen_context_provider_.get(),
|
| - host_impl_->output_surface()->context_provider());
|
| - EXPECT_TRUE(did_update_renderer_capabilities_);
|
| -
|
| - // Defer intialized GL draw.
|
| - DrawFrame();
|
| -
|
| - // Revert back to software.
|
| - did_update_renderer_capabilities_ = false;
|
| - output_surface_->ReleaseGL();
|
| - EXPECT_FALSE(host_impl_->output_surface()->context_provider());
|
| - EXPECT_TRUE(did_update_renderer_capabilities_);
|
| -
|
| - // Software draw again.
|
| - DrawFrame();
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails) {
|
| - // Software draw.
|
| - DrawFrame();
|
| -
|
| - // Fail initialization of the onscreen context before the OutputSurface binds
|
| - // it to the thread.
|
| - onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
|
| -
|
| - EXPECT_FALSE(host_impl_->output_surface()->context_provider());
|
| -
|
| - // DeferredInitialize fails.
|
| - did_update_renderer_capabilities_ = false;
|
| - EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
|
| - onscreen_context_provider_, nullptr));
|
| - EXPECT_FALSE(host_impl_->output_surface()->context_provider());
|
| - EXPECT_FALSE(did_update_renderer_capabilities_);
|
| -
|
| - // Software draw again.
|
| - DrawFrame();
|
| -}
|
| -
|
| -// Checks that we have a non-0 default allocation if we pass a context that
|
| -// doesn't support memory management extensions.
|
| -TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
|
| - LayerTreeSettings settings;
|
| - host_impl_ = LayerTreeHostImpl::Create(
|
| - settings, this, &proxy_, &stats_instrumentation_,
|
| - shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(),
|
| - task_graph_runner_.get(), 0);
|
| -
|
| - scoped_ptr<OutputSurface> output_surface(
|
| - FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
|
| - host_impl_->InitializeRenderer(output_surface.Pass());
|
| - EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
|
| - ManagedMemoryPolicy policy1(
|
| - 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
|
| - int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
|
| - gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
|
| - int allow_nice_to_have_cutoff_value =
|
| - ManagedMemoryPolicy::PriorityCutoffToValue(
|
| - gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE);
|
| - int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
|
| - gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
|
| -
|
| - // GPU rasterization should be disabled by default on the tree(s)
|
| - EXPECT_FALSE(host_impl_->active_tree()->use_gpu_rasterization());
|
| - EXPECT_TRUE(host_impl_->pending_tree() == NULL);
|
| -
|
| - host_impl_->SetVisible(true);
|
| - host_impl_->SetMemoryPolicy(policy1);
|
| - EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
|
| - EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
|
| -
|
| - host_impl_->SetVisible(false);
|
| - EXPECT_EQ(0u, current_limit_bytes_);
|
| - EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
|
| -
|
| - host_impl_->SetVisible(true);
|
| - EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
|
| - EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
|
| -
|
| - // Now enable GPU rasterization and test if we get nice to have cutoff,
|
| - // when visible.
|
| - LayerTreeSettings settings;
|
| - settings.gpu_rasterization_enabled = true;
|
| - host_impl_ = LayerTreeHostImpl::Create(
|
| - settings, this, &proxy_, &stats_instrumentation_, NULL, NULL, NULL, 0);
|
| - host_impl_->SetUseGpuRasterization(true);
|
| - host_impl_->SetVisible(true);
|
| - host_impl_->SetMemoryPolicy(policy1);
|
| - EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
|
| - EXPECT_EQ(allow_nice_to_have_cutoff_value, current_priority_cutoff_value_);
|
| -
|
| - host_impl_->SetVisible(false);
|
| - EXPECT_EQ(0u, current_limit_bytes_);
|
| - EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
|
| - ASSERT_TRUE(host_impl_->active_tree());
|
| -
|
| - // RequiresHighResToDraw is set when new output surface is used.
|
| - EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
|
| -
|
| - host_impl_->ResetRequiresHighResToDraw();
|
| -
|
| - host_impl_->SetVisible(false);
|
| - EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
|
| - host_impl_->SetVisible(true);
|
| - EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
|
| - host_impl_->SetVisible(false);
|
| - EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
|
| -
|
| - host_impl_->ResetRequiresHighResToDraw();
|
| -
|
| - EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
|
| - host_impl_->SetVisible(true);
|
| - EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
|
| - ASSERT_TRUE(host_impl_->active_tree());
|
| - EXPECT_FALSE(host_impl_->use_gpu_rasterization());
|
| -
|
| - // RequiresHighResToDraw is set when new output surface is used.
|
| - EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
|
| -
|
| - host_impl_->ResetRequiresHighResToDraw();
|
| -
|
| - host_impl_->SetUseGpuRasterization(false);
|
| - EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
|
| - host_impl_->SetUseGpuRasterization(true);
|
| - EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
|
| - host_impl_->SetUseGpuRasterization(false);
|
| - EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
|
| -
|
| - host_impl_->ResetRequiresHighResToDraw();
|
| -
|
| - EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
|
| - host_impl_->SetUseGpuRasterization(true);
|
| - EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
|
| -}
|
| -
|
| -class LayerTreeHostImplTestPrepareTiles : public LayerTreeHostImplTest {
|
| - public:
|
| - void SetUp() override {
|
| - LayerTreeSettings settings;
|
| - settings.impl_side_painting = true;
|
| -
|
| - fake_host_impl_ = new FakeLayerTreeHostImpl(settings, &proxy_,
|
| - shared_bitmap_manager_.get(),
|
| - task_graph_runner_.get());
|
| - host_impl_.reset(fake_host_impl_);
|
| - host_impl_->InitializeRenderer(CreateOutputSurface());
|
| - host_impl_->SetViewportSize(gfx::Size(10, 10));
|
| - }
|
| -
|
| - FakeLayerTreeHostImpl* fake_host_impl_;
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) {
|
| - fake_host_impl_->DidModifyTilePriorities();
|
| - EXPECT_TRUE(fake_host_impl_->prepare_tiles_needed());
|
| - fake_host_impl_->SetVisible(false);
|
| - EXPECT_FALSE(fake_host_impl_->prepare_tiles_needed());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
|
| - scoped_ptr<TestWebGraphicsContext3D> context =
|
| - TestWebGraphicsContext3D::Create();
|
| - TestWebGraphicsContext3D* context3d = context.get();
|
| - scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
|
| - CreateHostImpl(DefaultSettings(), output_surface.Pass());
|
| -
|
| - EXPECT_EQ(0u, context3d->NumTextures());
|
| -
|
| - UIResourceId ui_resource_id = 1;
|
| - bool is_opaque = false;
|
| - UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
|
| - host_impl_->CreateUIResource(ui_resource_id, bitmap);
|
| - EXPECT_EQ(1u, context3d->NumTextures());
|
| - ResourceProvider::ResourceId id1 =
|
| - host_impl_->ResourceIdForUIResource(ui_resource_id);
|
| - EXPECT_NE(0u, id1);
|
| -
|
| - // Multiple requests with the same id is allowed. The previous texture is
|
| - // deleted.
|
| - host_impl_->CreateUIResource(ui_resource_id, bitmap);
|
| - EXPECT_EQ(1u, context3d->NumTextures());
|
| - ResourceProvider::ResourceId id2 =
|
| - host_impl_->ResourceIdForUIResource(ui_resource_id);
|
| - EXPECT_NE(0u, id2);
|
| - EXPECT_NE(id1, id2);
|
| -
|
| - // Deleting invalid UIResourceId is allowed and does not change state.
|
| - host_impl_->DeleteUIResource(-1);
|
| - EXPECT_EQ(1u, context3d->NumTextures());
|
| -
|
| - // Should return zero for invalid UIResourceId. Number of textures should
|
| - // not change.
|
| - EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
|
| - EXPECT_EQ(1u, context3d->NumTextures());
|
| -
|
| - host_impl_->DeleteUIResource(ui_resource_id);
|
| - EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
|
| - EXPECT_EQ(0u, context3d->NumTextures());
|
| -
|
| - // Should not change state for multiple deletion on one UIResourceId
|
| - host_impl_->DeleteUIResource(ui_resource_id);
|
| - EXPECT_EQ(0u, context3d->NumTextures());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
|
| - scoped_ptr<TestWebGraphicsContext3D> context =
|
| - TestWebGraphicsContext3D::Create();
|
| - TestWebGraphicsContext3D* context3d = context.get();
|
| - CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
|
| -
|
| - EXPECT_EQ(0u, context3d->NumTextures());
|
| -
|
| - gfx::Size size(4, 4);
|
| - // SkImageInfo has no support for ETC1. The |info| below contains the right
|
| - // total pixel size for the bitmap but not the right height and width. The
|
| - // correct width/height are passed directly to UIResourceBitmap.
|
| - SkImageInfo info =
|
| - SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
|
| - skia::RefPtr<SkPixelRef> pixel_ref =
|
| - skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
|
| - pixel_ref->setImmutable();
|
| - UIResourceBitmap bitmap(pixel_ref, size);
|
| - UIResourceId ui_resource_id = 1;
|
| - host_impl_->CreateUIResource(ui_resource_id, bitmap);
|
| - EXPECT_EQ(1u, context3d->NumTextures());
|
| - ResourceProvider::ResourceId id1 =
|
| - host_impl_->ResourceIdForUIResource(ui_resource_id);
|
| - EXPECT_NE(0u, id1);
|
| -}
|
| -
|
| -void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
|
| - scoped_refptr<TestContextProvider> context_provider =
|
| - TestContextProvider::Create();
|
| -
|
| - CreateHostImpl(DefaultSettings(),
|
| - FakeOutputSurface::Create3d(context_provider));
|
| -
|
| - SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
|
| -
|
| - ScopedPtrVector<CopyOutputRequest> requests;
|
| - requests.push_back(CopyOutputRequest::CreateRequest(
|
| - base::Bind(&ShutdownReleasesContext_Callback)));
|
| -
|
| - host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
|
| -
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| -
|
| - // The CopyOutputResult's callback has a ref on the ContextProvider and a
|
| - // texture in a texture mailbox.
|
| - EXPECT_FALSE(context_provider->HasOneRef());
|
| - EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
|
| -
|
| - host_impl_ = nullptr;
|
| -
|
| - // The CopyOutputResult's callback was cancelled, the CopyOutputResult
|
| - // released, and the texture deleted.
|
| - EXPECT_TRUE(context_provider->HasOneRef());
|
| - EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
|
| - // When flinging via touch, only the child should scroll (we should not
|
| - // bubble).
|
| - gfx::Size surface_size(10, 10);
|
| - gfx::Size content_size(20, 20);
|
| - scoped_ptr<LayerImpl> root_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - root_clip->SetHasRenderSurface(true);
|
| -
|
| - scoped_ptr<LayerImpl> root =
|
| - CreateScrollableLayer(1, content_size, root_clip.get());
|
| - root->SetIsContainerForFixedPositionLayers(true);
|
| - scoped_ptr<LayerImpl> child =
|
| - CreateScrollableLayer(2, content_size, root_clip.get());
|
| -
|
| - root->AddChild(child.Pass());
|
| - int root_id = root->id();
|
| - root_clip->AddChild(root.Pass());
|
| -
|
| - host_impl_->SetViewportSize(surface_size);
|
| - host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
|
| - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
|
| - Layer::INVALID_ID);
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - DrawFrame();
|
| - {
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
|
| -
|
| - gfx::Vector2d scroll_delta(0, 100);
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| -
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| -
|
| - // Only the child should have scrolled.
|
| - ASSERT_EQ(1u, scroll_info->scrolls.size());
|
| - ExpectNone(*scroll_info.get(), root_id);
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
|
| - // Scroll a child layer beyond its maximum scroll range and make sure the
|
| - // the scroll doesn't bubble up to the parent layer.
|
| - gfx::Size surface_size(10, 10);
|
| - scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->SetHasRenderSurface(true);
|
| - scoped_ptr<LayerImpl> root_scrolling =
|
| - CreateScrollableLayer(2, surface_size, root.get());
|
| -
|
| - scoped_ptr<LayerImpl> grand_child =
|
| - CreateScrollableLayer(4, surface_size, root.get());
|
| - grand_child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
|
| -
|
| - scoped_ptr<LayerImpl> child =
|
| - CreateScrollableLayer(3, surface_size, root.get());
|
| - child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
|
| - child->AddChild(grand_child.Pass());
|
| -
|
| - root_scrolling->AddChild(child.Pass());
|
| - root->AddChild(root_scrolling.Pass());
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - host_impl_->SetViewportSize(surface_size);
|
| - DrawFrame();
|
| - {
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info;
|
| - LayerImpl* child =
|
| - host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
|
| - LayerImpl* grand_child = child->children()[0];
|
| -
|
| - gfx::Vector2d scroll_delta(0, -2);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
|
| -
|
| - // The grand child should have scrolled up to its limit.
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ASSERT_EQ(1u, scroll_info->scrolls.size());
|
| - ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
|
| -
|
| - // The child should have received the bubbled delta, but the locked
|
| - // scrolling layer should remain set as the grand child.
|
| - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ASSERT_EQ(2u, scroll_info->scrolls.size());
|
| - ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
|
| - ExpectContains(*scroll_info, child->id(), scroll_delta);
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
|
| -
|
| - // The first |ScrollBy| after the fling should re-lock the scrolling
|
| - // layer to the first layer that scrolled, which is the child.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
|
| - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
|
| -
|
| - // The child should have scrolled up to its limit.
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ASSERT_EQ(2u, scroll_info->scrolls.size());
|
| - ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
|
| - ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
|
| -
|
| - // As the locked layer is at it's limit, no further scrolling can occur.
|
| - EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
|
| - host_impl_->ScrollEnd();
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
|
| - // When flinging via wheel, the root should eventually scroll (we should
|
| - // bubble).
|
| - gfx::Size surface_size(10, 10);
|
| - gfx::Size content_size(20, 20);
|
| - scoped_ptr<LayerImpl> root_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), 3);
|
| - root_clip->SetHasRenderSurface(true);
|
| - scoped_ptr<LayerImpl> root_scroll =
|
| - CreateScrollableLayer(1, content_size, root_clip.get());
|
| - int root_scroll_id = root_scroll->id();
|
| - scoped_ptr<LayerImpl> child =
|
| - CreateScrollableLayer(2, content_size, root_clip.get());
|
| -
|
| - root_scroll->AddChild(child.Pass());
|
| - root_clip->AddChild(root_scroll.Pass());
|
| -
|
| - host_impl_->SetViewportSize(surface_size);
|
| - host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - DrawFrame();
|
| - {
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
|
| -
|
| - gfx::Vector2d scroll_delta(0, 100);
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| -
|
| - host_impl_->ScrollEnd();
|
| -
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info =
|
| - host_impl_->ProcessScrollDeltas();
|
| -
|
| - // The root should have scrolled.
|
| - ASSERT_EQ(2u, scroll_info->scrolls.size());
|
| - ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
|
| - // If we ray cast a scroller that is not on the first layer's ancestor chain,
|
| - // we should return SCROLL_UNKNOWN.
|
| - gfx::Size content_size(100, 100);
|
| - SetupScrollAndContentsLayers(content_size);
|
| -
|
| - int scroll_layer_id = 2;
|
| - LayerImpl* scroll_layer =
|
| - host_impl_->active_tree()->LayerById(scroll_layer_id);
|
| - scroll_layer->SetDrawsContent(true);
|
| -
|
| - int page_scale_layer_id = 5;
|
| - LayerImpl* page_scale_layer =
|
| - host_impl_->active_tree()->LayerById(page_scale_layer_id);
|
| -
|
| - int occluder_layer_id = 6;
|
| - scoped_ptr<LayerImpl> occluder_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
|
| - occluder_layer->SetDrawsContent(true);
|
| - occluder_layer->SetBounds(content_size);
|
| - occluder_layer->SetContentBounds(content_size);
|
| - occluder_layer->SetPosition(gfx::PointF());
|
| -
|
| - // The parent of the occluder is *above* the scroller.
|
| - page_scale_layer->AddChild(occluder_layer.Pass());
|
| -
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
|
| - // If we ray cast a scroller this is on the first layer's ancestor chain, but
|
| - // is not the first scroller we encounter when walking up from the layer, we
|
| - // should also return SCROLL_UNKNOWN.
|
| - gfx::Size content_size(100, 100);
|
| - SetupScrollAndContentsLayers(content_size);
|
| -
|
| - int scroll_layer_id = 2;
|
| - LayerImpl* scroll_layer =
|
| - host_impl_->active_tree()->LayerById(scroll_layer_id);
|
| - scroll_layer->SetDrawsContent(true);
|
| -
|
| - int occluder_layer_id = 6;
|
| - scoped_ptr<LayerImpl> occluder_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
|
| - occluder_layer->SetDrawsContent(true);
|
| - occluder_layer->SetBounds(content_size);
|
| - occluder_layer->SetContentBounds(content_size);
|
| - occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
|
| -
|
| - int child_scroll_clip_layer_id = 7;
|
| - scoped_ptr<LayerImpl> child_scroll_clip =
|
| - LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
|
| -
|
| - int child_scroll_layer_id = 8;
|
| - scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
|
| - child_scroll_layer_id, content_size, child_scroll_clip.get());
|
| -
|
| - child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
|
| -
|
| - child_scroll->AddChild(occluder_layer.Pass());
|
| - scroll_layer->AddChild(child_scroll.Pass());
|
| -
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, NotScrollInvisibleScroller) {
|
| - gfx::Size content_size(100, 100);
|
| - SetupScrollAndContentsLayers(content_size);
|
| -
|
| - LayerImpl* root = host_impl_->active_tree()->LayerById(1);
|
| -
|
| - int scroll_layer_id = 2;
|
| - LayerImpl* scroll_layer =
|
| - host_impl_->active_tree()->LayerById(scroll_layer_id);
|
| -
|
| - int child_scroll_layer_id = 7;
|
| - scoped_ptr<LayerImpl> child_scroll =
|
| - CreateScrollableLayer(child_scroll_layer_id, content_size, root);
|
| - child_scroll->SetDrawsContent(false);
|
| -
|
| - scroll_layer->AddChild(child_scroll.Pass());
|
| -
|
| - DrawFrame();
|
| -
|
| - // We should not have scrolled |child_scroll| even though we technically "hit"
|
| - // it. The reason for this is that if the scrolling the scroll would not move
|
| - // any layer that is a drawn RSLL member, then we can ignore the hit.
|
| - //
|
| - // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
|
| - // started scrolling the inner viewport.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| -
|
| - EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleDescendent) {
|
| - gfx::Size content_size(100, 100);
|
| - SetupScrollAndContentsLayers(content_size);
|
| -
|
| - LayerImpl* root = host_impl_->active_tree()->LayerById(1);
|
| - LayerImpl* root_scroll_layer = host_impl_->active_tree()->LayerById(2);
|
| -
|
| - scoped_ptr<LayerImpl> invisible_scroll_layer =
|
| - CreateScrollableLayer(7, content_size, root);
|
| - invisible_scroll_layer->SetDrawsContent(false);
|
| -
|
| - scoped_ptr<LayerImpl> child_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 8);
|
| - child_layer->SetDrawsContent(false);
|
| -
|
| - scoped_ptr<LayerImpl> grand_child_layer =
|
| - LayerImpl::Create(host_impl_->active_tree(), 9);
|
| - grand_child_layer->SetDrawsContent(true);
|
| - grand_child_layer->SetBounds(content_size);
|
| - grand_child_layer->SetContentBounds(content_size);
|
| - // Move the grand child so it's not hit by our test point.
|
| - grand_child_layer->SetPosition(gfx::PointF(10.f, 10.f));
|
| -
|
| - child_layer->AddChild(grand_child_layer.Pass());
|
| - invisible_scroll_layer->AddChild(child_layer.Pass());
|
| - root_scroll_layer->AddChild(invisible_scroll_layer.Pass());
|
| -
|
| - DrawFrame();
|
| -
|
| - // We should have scrolled |invisible_scroll_layer| as it was hit and it has
|
| - // a descendant which is a drawn RSLL member.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| -
|
| - EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
|
| - // This test case is very similar to the one above with one key difference:
|
| - // the invisible scroller has a scroll child that is indeed draw contents.
|
| - // If we attempt to initiate a gesture scroll off of the visible scroll child
|
| - // we should still start the scroll child.
|
| - gfx::Size content_size(100, 100);
|
| - SetupScrollAndContentsLayers(content_size);
|
| -
|
| - LayerImpl* root = host_impl_->active_tree()->LayerById(1);
|
| -
|
| - int scroll_layer_id = 2;
|
| - LayerImpl* scroll_layer =
|
| - host_impl_->active_tree()->LayerById(scroll_layer_id);
|
| -
|
| - int scroll_child_id = 6;
|
| - scoped_ptr<LayerImpl> scroll_child =
|
| - LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
|
| - scroll_child->SetDrawsContent(true);
|
| - scroll_child->SetBounds(content_size);
|
| - scroll_child->SetContentBounds(content_size);
|
| - // Move the scroll child so it's not hit by our test point.
|
| - scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
|
| -
|
| - int invisible_scroll_layer_id = 7;
|
| - scoped_ptr<LayerImpl> invisible_scroll =
|
| - CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
|
| - invisible_scroll->SetDrawsContent(false);
|
| -
|
| - int container_id = 8;
|
| - scoped_ptr<LayerImpl> container =
|
| - LayerImpl::Create(host_impl_->active_tree(), container_id);
|
| -
|
| - scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
|
| - scroll_children->insert(scroll_child.get());
|
| - invisible_scroll->SetScrollChildren(scroll_children.release());
|
| -
|
| - scroll_child->SetScrollParent(invisible_scroll.get());
|
| -
|
| - container->AddChild(invisible_scroll.Pass());
|
| - container->AddChild(scroll_child.Pass());
|
| -
|
| - scroll_layer->AddChild(container.Pass());
|
| -
|
| - DrawFrame();
|
| -
|
| - // We should have scrolled |child_scroll| even though it is invisible.
|
| - // The reason for this is that if the scrolling the scroll would move a layer
|
| - // that is a drawn RSLL member, then we should accept this hit.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| -
|
| - EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
|
| -}
|
| -
|
| -// Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
|
| -// to CompositorFrameMetadata after SwapBuffers();
|
| -TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
|
| - scoped_ptr<SolidColorLayerImpl> root =
|
| - SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
|
| - root->SetPosition(gfx::PointF());
|
| - root->SetBounds(gfx::Size(10, 10));
|
| - root->SetContentBounds(gfx::Size(10, 10));
|
| - root->SetDrawsContent(true);
|
| - root->SetHasRenderSurface(true);
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| -
|
| - FakeOutputSurface* fake_output_surface =
|
| - static_cast<FakeOutputSurface*>(host_impl_->output_surface());
|
| -
|
| - const std::vector<ui::LatencyInfo>& metadata_latency_before =
|
| - fake_output_surface->last_sent_frame().metadata.latency_info;
|
| - EXPECT_TRUE(metadata_latency_before.empty());
|
| -
|
| - ui::LatencyInfo latency_info;
|
| - latency_info.AddLatencyNumber(
|
| - ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
|
| - scoped_ptr<SwapPromise> swap_promise(
|
| - new LatencyInfoSwapPromise(latency_info));
|
| - host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
|
| - host_impl_->SetNeedsRedraw();
|
| -
|
| - gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - EXPECT_TRUE(host_impl_->SwapBuffers(frame));
|
| -
|
| - const std::vector<ui::LatencyInfo>& metadata_latency_after =
|
| - fake_output_surface->last_sent_frame().metadata.latency_info;
|
| - EXPECT_EQ(1u, metadata_latency_after.size());
|
| - EXPECT_TRUE(metadata_latency_after[0].FindLatency(
|
| - ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
|
| - int root_layer_id = 1;
|
| - scoped_ptr<SolidColorLayerImpl> root =
|
| - SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
|
| - root->SetPosition(gfx::PointF());
|
| - root->SetBounds(gfx::Size(10, 10));
|
| - root->SetContentBounds(gfx::Size(10, 10));
|
| - root->SetDrawsContent(true);
|
| - root->SetHasRenderSurface(true);
|
| -
|
| - host_impl_->active_tree()->SetRootLayer(root.Pass());
|
| -
|
| - // Ensure the default frame selection bounds are empty.
|
| - FakeOutputSurface* fake_output_surface =
|
| - static_cast<FakeOutputSurface*>(host_impl_->output_surface());
|
| - const ViewportSelectionBound& selection_start_before =
|
| - fake_output_surface->last_sent_frame().metadata.selection_start;
|
| - const ViewportSelectionBound& selection_end_before =
|
| - fake_output_surface->last_sent_frame().metadata.selection_end;
|
| - EXPECT_EQ(ViewportSelectionBound(), selection_start_before);
|
| - EXPECT_EQ(ViewportSelectionBound(), selection_end_before);
|
| -
|
| - // Plumb the layer-local selection bounds.
|
| - gfx::PointF selection_top(5, 0);
|
| - gfx::PointF selection_bottom(5, 5);
|
| - LayerSelectionBound start, end;
|
| - start.type = SELECTION_BOUND_CENTER;
|
| - start.layer_id = root_layer_id;
|
| - start.edge_bottom = selection_bottom;
|
| - start.edge_top = selection_top;
|
| - end = start;
|
| - host_impl_->active_tree()->RegisterSelection(start, end);
|
| -
|
| - // Trigger a draw-swap sequence.
|
| - host_impl_->SetNeedsRedraw();
|
| -
|
| - gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
|
| - LayerTreeHostImpl::FrameData frame;
|
| - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
|
| - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
|
| - host_impl_->DidDrawAllLayers(frame);
|
| - EXPECT_TRUE(host_impl_->SwapBuffers(frame));
|
| -
|
| - // Ensure the selection bounds have propagated to the frame metadata.
|
| - const ViewportSelectionBound& selection_start_after =
|
| - fake_output_surface->last_sent_frame().metadata.selection_start;
|
| - const ViewportSelectionBound& selection_end_after =
|
| - fake_output_surface->last_sent_frame().metadata.selection_end;
|
| - EXPECT_EQ(start.type, selection_start_after.type);
|
| - EXPECT_EQ(end.type, selection_end_after.type);
|
| - EXPECT_EQ(selection_bottom, selection_start_after.edge_bottom);
|
| - EXPECT_EQ(selection_top, selection_start_after.edge_top);
|
| - EXPECT_TRUE(selection_start_after.visible);
|
| - EXPECT_TRUE(selection_start_after.visible);
|
| -}
|
| -
|
| -class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
|
| - public:
|
| - SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
|
| - LayerTreeHostImpl* layer_tree_host_impl,
|
| - int* set_needs_commit_count,
|
| - int* set_needs_redraw_count,
|
| - int* forward_to_main_count)
|
| - : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
|
| - set_needs_commit_count_(set_needs_commit_count),
|
| - set_needs_redraw_count_(set_needs_redraw_count),
|
| - forward_to_main_count_(forward_to_main_count) {}
|
| -
|
| - ~SimpleSwapPromiseMonitor() override {}
|
| -
|
| - void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; }
|
| -
|
| - void OnSetNeedsRedrawOnImpl() override { (*set_needs_redraw_count_)++; }
|
| -
|
| - void OnForwardScrollUpdateToMainThreadOnImpl() override {
|
| - (*forward_to_main_count_)++;
|
| - }
|
| -
|
| - private:
|
| - int* set_needs_commit_count_;
|
| - int* set_needs_redraw_count_;
|
| - int* forward_to_main_count_;
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
|
| - int set_needs_commit_count = 0;
|
| - int set_needs_redraw_count = 0;
|
| - int forward_to_main_count = 0;
|
| -
|
| - {
|
| - scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
|
| - new SimpleSwapPromiseMonitor(NULL,
|
| - host_impl_.get(),
|
| - &set_needs_commit_count,
|
| - &set_needs_redraw_count,
|
| - &forward_to_main_count));
|
| - host_impl_->SetNeedsRedraw();
|
| - EXPECT_EQ(0, set_needs_commit_count);
|
| - EXPECT_EQ(1, set_needs_redraw_count);
|
| - EXPECT_EQ(0, forward_to_main_count);
|
| - }
|
| -
|
| - // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
|
| - // monitored.
|
| - host_impl_->SetNeedsRedraw();
|
| - EXPECT_EQ(0, set_needs_commit_count);
|
| - EXPECT_EQ(1, set_needs_redraw_count);
|
| - EXPECT_EQ(0, forward_to_main_count);
|
| -
|
| - {
|
| - scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
|
| - new SimpleSwapPromiseMonitor(NULL,
|
| - host_impl_.get(),
|
| - &set_needs_commit_count,
|
| - &set_needs_redraw_count,
|
| - &forward_to_main_count));
|
| - host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
|
| - EXPECT_EQ(0, set_needs_commit_count);
|
| - EXPECT_EQ(2, set_needs_redraw_count);
|
| - EXPECT_EQ(0, forward_to_main_count);
|
| - }
|
| -
|
| - {
|
| - scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
|
| - new SimpleSwapPromiseMonitor(NULL,
|
| - host_impl_.get(),
|
| - &set_needs_commit_count,
|
| - &set_needs_redraw_count,
|
| - &forward_to_main_count));
|
| - // Empty damage rect won't signal the monitor.
|
| - host_impl_->SetNeedsRedrawRect(gfx::Rect());
|
| - EXPECT_EQ(0, set_needs_commit_count);
|
| - EXPECT_EQ(2, set_needs_redraw_count);
|
| - EXPECT_EQ(0, forward_to_main_count);
|
| - }
|
| -
|
| - {
|
| - set_needs_commit_count = 0;
|
| - set_needs_redraw_count = 0;
|
| - forward_to_main_count = 0;
|
| - scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
|
| - new SimpleSwapPromiseMonitor(NULL,
|
| - host_impl_.get(),
|
| - &set_needs_commit_count,
|
| - &set_needs_redraw_count,
|
| - &forward_to_main_count));
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| -
|
| - // Scrolling normally should not trigger any forwarding.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - EXPECT_EQ(0, set_needs_commit_count);
|
| - EXPECT_EQ(1, set_needs_redraw_count);
|
| - EXPECT_EQ(0, forward_to_main_count);
|
| -
|
| - // Scrolling with a scroll handler should defer the swap to the main
|
| - // thread.
|
| - scroll_layer->SetHaveScrollEventHandlers(true);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
|
| - host_impl_->ScrollEnd();
|
| -
|
| - EXPECT_EQ(0, set_needs_commit_count);
|
| - EXPECT_EQ(2, set_needs_redraw_count);
|
| - EXPECT_EQ(1, forward_to_main_count);
|
| - }
|
| -}
|
| -
|
| -class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
|
| - public:
|
| - void SetUp() override {
|
| - LayerTreeSettings settings = DefaultSettings();
|
| - CreateHostImpl(settings, CreateOutputSurface());
|
| - host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
|
| - host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
|
| - host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
|
| - }
|
| -
|
| - protected:
|
| - static const int top_controls_height_;
|
| -};
|
| -
|
| -const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
|
| -
|
| -TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100))
|
| - ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
|
| - host_impl_->Animate(base::TimeTicks());
|
| - EXPECT_FALSE(did_request_redraw_);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsHeightIsCommitted) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - EXPECT_FALSE(did_request_redraw_);
|
| - host_impl_->CreatePendingTree();
|
| - host_impl_->sync_tree()->set_top_controls_height(100);
|
| - host_impl_->ActivateSyncTree();
|
| - EXPECT_EQ(100, host_impl_->top_controls_manager()->TopControlsHeight());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplWithTopControlsTest,
|
| - TopControlsStayFullyVisibleOnHeightChange) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
|
| -
|
| - host_impl_->CreatePendingTree();
|
| - host_impl_->sync_tree()->set_top_controls_height(0);
|
| - host_impl_->ActivateSyncTree();
|
| - EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
|
| -
|
| - host_impl_->CreatePendingTree();
|
| - host_impl_->sync_tree()->set_top_controls_height(50);
|
| - host_impl_->ActivateSyncTree();
|
| - EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 100))
|
| - ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
|
| - host_impl_->DidChangeTopControlsPosition();
|
| - EXPECT_TRUE(did_request_animate_);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
|
| - host_impl_->SetViewportSize(gfx::Size(100, 100));
|
| - host_impl_->top_controls_manager()->UpdateTopControlsState(
|
| - BOTH, SHOWN, false);
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
|
| - EXPECT_EQ(gfx::Vector2dF().ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - // Scroll just the top controls and verify that the scroll succeeds.
|
| - const float residue = 10;
|
| - float offset = top_controls_height_ - residue;
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
|
| - EXPECT_FLOAT_EQ(-offset,
|
| - host_impl_->top_controls_manager()->ControlsTopOffset());
|
| - EXPECT_EQ(gfx::Vector2dF().ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - // Scroll across the boundary
|
| - const float content_scroll = 20;
|
| - offset = residue + content_scroll;
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
|
| - EXPECT_EQ(-top_controls_height_,
|
| - host_impl_->top_controls_manager()->ControlsTopOffset());
|
| - EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - // Now scroll back to the top of the content
|
| - offset = -content_scroll;
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
|
| - EXPECT_EQ(-top_controls_height_,
|
| - host_impl_->top_controls_manager()->ControlsTopOffset());
|
| - EXPECT_EQ(gfx::Vector2dF().ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - // And scroll the top controls completely into view
|
| - offset = -top_controls_height_;
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
|
| - EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
|
| - EXPECT_EQ(gfx::Vector2dF().ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - // And attempt to scroll past the end
|
| - EXPECT_FALSE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
|
| - EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
|
| - EXPECT_EQ(gfx::Vector2dF().ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - host_impl_->ScrollEnd();
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
|
| - host_impl_->SetViewportSize(gfx::Size(100, 200));
|
| - host_impl_->top_controls_manager()->UpdateTopControlsState(
|
| - BOTH, SHOWN, false);
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
|
| - EXPECT_EQ(gfx::Vector2dF().ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - // Scroll the top controls partially.
|
| - const float residue = 35;
|
| - float offset = top_controls_height_ - residue;
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
|
| - EXPECT_FLOAT_EQ(-offset,
|
| - host_impl_->top_controls_manager()->ControlsTopOffset());
|
| - EXPECT_EQ(gfx::Vector2dF().ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - did_request_commit_ = false;
|
| -
|
| - // End the scroll while the controls are still offset from their limit.
|
| - host_impl_->ScrollEnd();
|
| - ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
|
| - EXPECT_TRUE(did_request_animate_);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_FALSE(did_request_commit_);
|
| -
|
| - // The top controls should properly animate until finished, despite the scroll
|
| - // offset being at the origin.
|
| - base::TimeTicks animation_time = gfx::FrameTime::Now();
|
| - while (did_request_animate_) {
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - did_request_commit_ = false;
|
| -
|
| - float old_offset =
|
| - host_impl_->top_controls_manager()->ControlsTopOffset();
|
| -
|
| - animation_time += base::TimeDelta::FromMilliseconds(5);
|
| - host_impl_->Animate(animation_time);
|
| - EXPECT_EQ(gfx::Vector2dF().ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - float new_offset =
|
| - host_impl_->top_controls_manager()->ControlsTopOffset();
|
| -
|
| - // No commit is needed as the controls are animating the content offset,
|
| - // not the scroll offset.
|
| - EXPECT_FALSE(did_request_commit_);
|
| -
|
| - if (new_offset != old_offset)
|
| - EXPECT_TRUE(did_request_redraw_);
|
| -
|
| - if (new_offset != 0) {
|
| - EXPECT_TRUE(host_impl_->top_controls_manager()->animation());
|
| - EXPECT_TRUE(did_request_animate_);
|
| - }
|
| - }
|
| - EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
|
| - host_impl_->SetViewportSize(gfx::Size(100, 100));
|
| - host_impl_->top_controls_manager()->UpdateTopControlsState(
|
| - BOTH, SHOWN, false);
|
| - float initial_scroll_offset = 50;
|
| - scroll_layer->PushScrollOffsetFromMainThread(
|
| - gfx::ScrollOffset(0, initial_scroll_offset));
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
|
| - EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - // Scroll the top controls partially.
|
| - const float residue = 15;
|
| - float offset = top_controls_height_ - residue;
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
|
| - EXPECT_FLOAT_EQ(-offset,
|
| - host_impl_->top_controls_manager()->ControlsTopOffset());
|
| - EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - did_request_commit_ = false;
|
| -
|
| - // End the scroll while the controls are still offset from the limit.
|
| - host_impl_->ScrollEnd();
|
| - ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
|
| - EXPECT_TRUE(did_request_animate_);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_FALSE(did_request_commit_);
|
| -
|
| - // Animate the top controls to the limit.
|
| - base::TimeTicks animation_time = gfx::FrameTime::Now();
|
| - while (did_request_animate_) {
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - did_request_commit_ = false;
|
| -
|
| - float old_offset =
|
| - host_impl_->top_controls_manager()->ControlsTopOffset();
|
| -
|
| - animation_time += base::TimeDelta::FromMilliseconds(5);
|
| - host_impl_->Animate(animation_time);
|
| -
|
| - float new_offset =
|
| - host_impl_->top_controls_manager()->ControlsTopOffset();
|
| -
|
| - if (new_offset != old_offset) {
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_commit_);
|
| - }
|
| - }
|
| - EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
|
| - EXPECT_EQ(-top_controls_height_,
|
| - host_impl_->top_controls_manager()->ControlsTopOffset());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplWithTopControlsTest,
|
| - TopControlsAnimationAfterMainThreadFlingStopped) {
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
|
| - host_impl_->SetViewportSize(gfx::Size(100, 100));
|
| - host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
|
| - false);
|
| - float initial_scroll_offset = 50;
|
| - scroll_layer->PushScrollOffsetFromMainThread(
|
| - gfx::ScrollOffset(0, initial_scroll_offset));
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
|
| - EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - // Scroll the top controls partially.
|
| - const float residue = 15;
|
| - float offset = top_controls_height_ - residue;
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
|
| - EXPECT_FLOAT_EQ(-offset,
|
| - host_impl_->top_controls_manager()->ControlsTopOffset());
|
| - EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - did_request_commit_ = false;
|
| -
|
| - // End the fling while the controls are still offset from the limit.
|
| - host_impl_->MainThreadHasStoppedFlinging();
|
| - ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
|
| - EXPECT_TRUE(did_request_animate_);
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_FALSE(did_request_commit_);
|
| -
|
| - // Animate the top controls to the limit.
|
| - base::TimeTicks animation_time = gfx::FrameTime::Now();
|
| - while (did_request_animate_) {
|
| - did_request_redraw_ = false;
|
| - did_request_animate_ = false;
|
| - did_request_commit_ = false;
|
| -
|
| - float old_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
|
| -
|
| - animation_time += base::TimeDelta::FromMilliseconds(5);
|
| - host_impl_->Animate(animation_time);
|
| -
|
| - float new_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
|
| -
|
| - if (new_offset != old_offset) {
|
| - EXPECT_TRUE(did_request_redraw_);
|
| - EXPECT_TRUE(did_request_commit_);
|
| - }
|
| - }
|
| - EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
|
| - EXPECT_EQ(-top_controls_height_,
|
| - host_impl_->top_controls_manager()->ControlsTopOffset());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplWithTopControlsTest,
|
| - TopControlsScrollDeltaInOverScroll) {
|
| - // test varifies that the overscroll delta should not have accumulated in
|
| - // the top controls if we do a hide and show without releasing finger.
|
| -
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
|
| - host_impl_->SetViewportSize(gfx::Size(100, 100));
|
| - host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
|
| - false);
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
|
| -
|
| - float offset = 50;
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
|
| - EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
|
| - EXPECT_EQ(gfx::Vector2dF().ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
|
| - EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
|
| -
|
| - // Should have fully scrolled
|
| - EXPECT_EQ(gfx::Vector2dF(0, scroll_layer->MaxScrollOffset().y()).ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - float overscrollamount = 10;
|
| -
|
| - // Overscroll the content
|
| - EXPECT_FALSE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount))
|
| - .did_scroll);
|
| - EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| - EXPECT_EQ(gfx::Vector2dF(0, overscrollamount).ToString(),
|
| - host_impl_->accumulated_root_overscroll().ToString());
|
| -
|
| - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset))
|
| - .did_scroll);
|
| - EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| - EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
|
| -
|
| - EXPECT_TRUE(
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset)).did_scroll);
|
| - EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
|
| - scroll_layer->CurrentScrollOffset().ToString());
|
| -
|
| - // Top controls should be fully visible
|
| - EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
|
| -
|
| - host_impl_->ScrollEnd();
|
| -}
|
| -
|
| -class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
|
| - public:
|
| - void SetupVirtualViewportLayers(const gfx::Size& content_size,
|
| - const gfx::Size& outer_viewport,
|
| - const gfx::Size& inner_viewport) {
|
| - LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
|
| - const int kOuterViewportClipLayerId = 6;
|
| - const int kOuterViewportScrollLayerId = 7;
|
| - const int kInnerViewportScrollLayerId = 2;
|
| - const int kInnerViewportClipLayerId = 4;
|
| - const int kPageScaleLayerId = 5;
|
| -
|
| - scoped_ptr<LayerImpl> inner_scroll =
|
| - LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
|
| - inner_scroll->SetIsContainerForFixedPositionLayers(true);
|
| - inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
|
| -
|
| - scoped_ptr<LayerImpl> inner_clip =
|
| - LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
|
| - inner_clip->SetBounds(inner_viewport);
|
| -
|
| - scoped_ptr<LayerImpl> page_scale =
|
| - LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
|
| -
|
| - inner_scroll->SetScrollClipLayer(inner_clip->id());
|
| - inner_scroll->SetBounds(outer_viewport);
|
| - inner_scroll->SetContentBounds(outer_viewport);
|
| - inner_scroll->SetPosition(gfx::PointF());
|
| -
|
| - scoped_ptr<LayerImpl> outer_clip =
|
| - LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
|
| - outer_clip->SetBounds(outer_viewport);
|
| - outer_clip->SetIsContainerForFixedPositionLayers(true);
|
| -
|
| - scoped_ptr<LayerImpl> outer_scroll =
|
| - LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
|
| - outer_scroll->SetScrollClipLayer(outer_clip->id());
|
| - outer_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
|
| - outer_scroll->SetBounds(content_size);
|
| - outer_scroll->SetContentBounds(content_size);
|
| - outer_scroll->SetPosition(gfx::PointF());
|
| -
|
| - scoped_ptr<LayerImpl> contents =
|
| - LayerImpl::Create(layer_tree_impl, 8);
|
| - contents->SetDrawsContent(true);
|
| - contents->SetBounds(content_size);
|
| - contents->SetContentBounds(content_size);
|
| - contents->SetPosition(gfx::PointF());
|
| -
|
| - outer_scroll->AddChild(contents.Pass());
|
| - outer_clip->AddChild(outer_scroll.Pass());
|
| - inner_scroll->AddChild(outer_clip.Pass());
|
| - page_scale->AddChild(inner_scroll.Pass());
|
| - inner_clip->AddChild(page_scale.Pass());
|
| -
|
| - inner_clip->SetHasRenderSurface(true);
|
| - layer_tree_impl->SetRootLayer(inner_clip.Pass());
|
| - layer_tree_impl->SetViewportLayersFromIds(
|
| - Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
|
| - kOuterViewportScrollLayerId);
|
| -
|
| - host_impl_->active_tree()->DidBecomeActive();
|
| - }
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
|
| - gfx::Size content_size = gfx::Size(100, 160);
|
| - gfx::Size outer_viewport = gfx::Size(50, 80);
|
| - gfx::Size inner_viewport = gfx::Size(25, 40);
|
| -
|
| - SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
|
| -
|
| - LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
|
| - LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
|
| - DrawFrame();
|
| - {
|
| - gfx::Vector2dF inner_expected;
|
| - gfx::Vector2dF outer_expected;
|
| - EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
|
| - EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
|
| -
|
| - // Make sure the fling goes to the outer viewport first
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
|
| -
|
| - gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
|
| -
|
| - host_impl_->ScrollEnd();
|
| -
|
| - EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
|
| - EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
|
| -
|
| - // Fling past the outer viewport boundry, make sure inner viewport scrolls.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
|
| -
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
|
| -
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
|
| -
|
| - host_impl_->ScrollEnd();
|
| -
|
| - EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
|
| - EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplVirtualViewportTest,
|
| - DiagonalScrollBubblesPerfectlyToInner) {
|
| - gfx::Size content_size = gfx::Size(100, 160);
|
| - gfx::Size outer_viewport = gfx::Size(50, 80);
|
| - gfx::Size inner_viewport = gfx::Size(25, 40);
|
| -
|
| - SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
|
| -
|
| - LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
|
| - LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
|
| - DrawFrame();
|
| - {
|
| - gfx::Vector2dF inner_expected;
|
| - gfx::Vector2dF outer_expected;
|
| - EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
|
| - EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
|
| -
|
| - // Make sure the scroll goes to the outer viewport first.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
|
| -
|
| - // Scroll near the edge of the outer viewport.
|
| - gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - outer_expected += scroll_delta;
|
| -
|
| - EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
|
| - EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
|
| -
|
| - // Now diagonal scroll across the outer viewport boundary in a single event.
|
| - // The entirety of the scroll should be consumed, as bubbling between inner
|
| - // and outer viewport layers is perfect.
|
| - host_impl_->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2));
|
| - outer_expected += scroll_delta;
|
| - inner_expected += scroll_delta;
|
| - host_impl_->ScrollEnd();
|
| -
|
| - EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
|
| - EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
|
| - }
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplVirtualViewportTest,
|
| - TouchFlingCanLockToViewportLayerAfterBubbling) {
|
| - gfx::Size content_size = gfx::Size(100, 160);
|
| - gfx::Size outer_viewport = gfx::Size(50, 80);
|
| - gfx::Size inner_viewport = gfx::Size(25, 40);
|
| -
|
| - SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
|
| -
|
| - LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
|
| - LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
|
| -
|
| - scoped_ptr<LayerImpl> child =
|
| - CreateScrollableLayer(10, outer_viewport, outer_scroll);
|
| - LayerImpl* child_scroll = child.get();
|
| - outer_scroll->children()[0]->AddChild(child.Pass());
|
| -
|
| - DrawFrame();
|
| - {
|
| - scoped_ptr<ScrollAndScaleSet> scroll_info;
|
| -
|
| - gfx::Vector2d scroll_delta(0, inner_viewport.height());
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
|
| - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
|
| -
|
| - // The child should have scrolled up to its limit.
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ASSERT_EQ(1u, scroll_info->scrolls.size());
|
| - ExpectContains(*scroll_info, child_scroll->id(), scroll_delta);
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
|
| -
|
| - // The first |ScrollBy| after the fling should re-lock the scrolling
|
| - // layer to the first layer that scrolled, the inner viewport scroll layer.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
|
| - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
|
| -
|
| - // The inner viewport should have scrolled up to its limit.
|
| - scroll_info = host_impl_->ProcessScrollDeltas();
|
| - ASSERT_EQ(2u, scroll_info->scrolls.size());
|
| - ExpectContains(*scroll_info, child_scroll->id(), scroll_delta);
|
| - ExpectContains(*scroll_info, inner_scroll->id(), scroll_delta);
|
| -
|
| - // As the locked layer is at its limit, no further scrolling can occur.
|
| - EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
|
| - EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
|
| - host_impl_->ScrollEnd();
|
| - }
|
| -}
|
| -
|
| -class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
|
| - public:
|
| - void SetUp() override {
|
| - LayerTreeSettings settings = DefaultSettings();
|
| - settings.max_memory_for_prepaint_percentage = 50;
|
| - CreateHostImpl(settings, CreateOutputSurface());
|
| - }
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
|
| - // Set up a memory policy and percentages which could cause
|
| - // 32-bit integer overflows.
|
| - ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
|
| -
|
| - // Verify implicit limits are calculated correctly with no overflows
|
| - host_impl_->SetMemoryPolicy(mem_policy);
|
| - EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
|
| - 300u * 1024u * 1024u);
|
| - EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
|
| - 150u * 1024u * 1024u);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
|
| - const gfx::Size layer_size(100, 100);
|
| - gfx::Transform external_transform;
|
| - const gfx::Rect external_viewport(layer_size);
|
| - const gfx::Rect external_clip(layer_size);
|
| - const bool resourceless_software_draw = false;
|
| - LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
|
| -
|
| - host_impl_->SetExternalDrawConstraints(external_transform,
|
| - external_viewport,
|
| - external_clip,
|
| - external_viewport,
|
| - external_transform,
|
| - resourceless_software_draw);
|
| - DrawFrame();
|
| - EXPECT_TRANSFORMATION_MATRIX_EQ(
|
| - external_transform, layer->draw_properties().target_space_transform);
|
| -
|
| - external_transform.Translate(20, 20);
|
| - host_impl_->SetExternalDrawConstraints(external_transform,
|
| - external_viewport,
|
| - external_clip,
|
| - external_viewport,
|
| - external_transform,
|
| - resourceless_software_draw);
|
| - DrawFrame();
|
| - EXPECT_TRANSFORMATION_MATRIX_EQ(
|
| - external_transform, layer->draw_properties().target_space_transform);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
|
| - SetupScrollAndContentsLayers(gfx::Size(100, 200));
|
| - DrawFrame();
|
| -
|
| - base::TimeTicks start_time =
|
| - base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
|
| -
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
|
| -
|
| - LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
|
| -
|
| - host_impl_->Animate(start_time);
|
| - host_impl_->UpdateAnimationState(true);
|
| -
|
| - EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
|
| -
|
| - host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
|
| - host_impl_->UpdateAnimationState(true);
|
| -
|
| - float y = scrolling_layer->CurrentScrollOffset().y();
|
| - EXPECT_TRUE(y > 1 && y < 49);
|
| -
|
| - // Update target.
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
|
| -
|
| - host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
|
| - host_impl_->UpdateAnimationState(true);
|
| -
|
| - y = scrolling_layer->CurrentScrollOffset().y();
|
| - EXPECT_TRUE(y > 50 && y < 100);
|
| - EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
|
| -
|
| - host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
|
| - host_impl_->UpdateAnimationState(true);
|
| -
|
| - EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
|
| - scrolling_layer->CurrentScrollOffset());
|
| - EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairs) {
|
| - host_impl_->CreatePendingTree();
|
| -
|
| - scoped_ptr<PictureLayerImpl> layer =
|
| - FakePictureLayerImpl::Create(host_impl_->pending_tree(), 10);
|
| - layer->SetBounds(gfx::Size(10, 10));
|
| - scoped_ptr<FakePictureLayerImpl> nondraw_layer =
|
| - FakePictureLayerImpl::Create(host_impl_->pending_tree(), 12);
|
| - nondraw_layer->SetBounds(gfx::Size(10, 10));
|
| -
|
| - scoped_refptr<RasterSource> pile(FakePicturePileImpl::CreateEmptyPile(
|
| - gfx::Size(10, 10), gfx::Size(10, 10)));
|
| - Region empty_invalidation;
|
| - const PictureLayerTilingSet* null_tiling_set = nullptr;
|
| - layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size());
|
| - layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
|
| - nondraw_layer->set_gpu_raster_max_texture_size(
|
| - host_impl_->device_viewport_size());
|
| - nondraw_layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
|
| -
|
| - layer->AddChild(nondraw_layer.Pass());
|
| - host_impl_->pending_tree()->SetRootLayer(layer.Pass());
|
| -
|
| - LayerTreeImpl* pending_tree = host_impl_->pending_tree();
|
| - LayerImpl* pending_layer = pending_tree->root_layer();
|
| - FakePictureLayerImpl* pending_nondraw_layer =
|
| - static_cast<FakePictureLayerImpl*>(pending_layer->children()[0]);
|
| -
|
| - pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
|
| -
|
| - std::vector<PictureLayerImpl::Pair> layer_pairs;
|
| - host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
|
| - EXPECT_EQ(1u, layer_pairs.size());
|
| - EXPECT_EQ(pending_layer, layer_pairs[0].pending);
|
| - EXPECT_EQ(nullptr, layer_pairs[0].active);
|
| -
|
| - host_impl_->ActivateSyncTree();
|
| -
|
| - LayerTreeImpl* active_tree = host_impl_->active_tree();
|
| - LayerImpl* active_layer = active_tree->root_layer();
|
| - FakePictureLayerImpl* active_nondraw_layer =
|
| - static_cast<FakePictureLayerImpl*>(active_layer->children()[0]);
|
| - EXPECT_NE(active_tree, pending_tree);
|
| - EXPECT_NE(active_layer, pending_layer);
|
| - EXPECT_NE(active_nondraw_layer, pending_nondraw_layer);
|
| - EXPECT_NE(nullptr, active_tree);
|
| - EXPECT_NE(nullptr, active_layer);
|
| - EXPECT_NE(nullptr, active_nondraw_layer);
|
| -
|
| - active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
|
| -
|
| - host_impl_->CreatePendingTree();
|
| -
|
| - layer_pairs.clear();
|
| - host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
|
| - EXPECT_EQ(1u, layer_pairs.size());
|
| - EXPECT_EQ(active_layer, layer_pairs[0].active);
|
| - EXPECT_EQ(pending_layer, layer_pairs[0].pending);
|
| -
|
| - // Activate, the active layer has no twin now.
|
| - host_impl_->ActivateSyncTree();
|
| -
|
| - layer_pairs.clear();
|
| - host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
|
| - EXPECT_EQ(1u, layer_pairs.size());
|
| - EXPECT_EQ(active_layer, layer_pairs[0].active);
|
| - EXPECT_EQ(nullptr, layer_pairs[0].pending);
|
| -
|
| - // Create another layer in the pending tree that's not in the active tree. We
|
| - // should get two pairs.
|
| - host_impl_->CreatePendingTree();
|
| - host_impl_->pending_tree()->root_layer()->AddChild(
|
| - FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11));
|
| -
|
| - LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[1];
|
| -
|
| - layer_pairs.clear();
|
| - host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
|
| - EXPECT_EQ(2u, layer_pairs.size());
|
| - // The pair ordering is flaky, so make it consistent.
|
| - if (layer_pairs[0].active != active_layer)
|
| - std::swap(layer_pairs[0], layer_pairs[1]);
|
| - EXPECT_EQ(active_layer, layer_pairs[0].active);
|
| - EXPECT_EQ(pending_layer, layer_pairs[0].pending);
|
| - EXPECT_EQ(new_pending_layer, layer_pairs[1].pending);
|
| - EXPECT_EQ(nullptr, layer_pairs[1].active);
|
| -
|
| - host_impl_->pending_tree()->root_layer()->RemoveChild(new_pending_layer);
|
| -
|
| - // Have the pending layer be part of the RSLL now. It should appear in the
|
| - // list without an active twin.
|
| - pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
|
| -
|
| - layer_pairs.clear();
|
| - host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
|
| - EXPECT_EQ(2u, layer_pairs.size());
|
| - // The pair ordering is flaky, so make it consistent.
|
| - if (layer_pairs[0].active != active_layer)
|
| - std::swap(layer_pairs[0], layer_pairs[1]);
|
| - EXPECT_EQ(active_layer, layer_pairs[0].active);
|
| - EXPECT_EQ(pending_layer, layer_pairs[0].pending);
|
| - EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
|
| - EXPECT_EQ(nullptr, layer_pairs[1].active);
|
| -
|
| - // Have the active layer be part of the RSLL now instead. It should appear in
|
| - // the list without a pending twin.
|
| - pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
|
| - active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
|
| -
|
| - layer_pairs.clear();
|
| - host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
|
| - EXPECT_EQ(2u, layer_pairs.size());
|
| - // The pair ordering is flaky, so make it consistent.
|
| - if (layer_pairs[0].active != active_layer)
|
| - std::swap(layer_pairs[0], layer_pairs[1]);
|
| - EXPECT_EQ(active_layer, layer_pairs[0].active);
|
| - EXPECT_EQ(pending_layer, layer_pairs[0].pending);
|
| - EXPECT_EQ(nullptr, layer_pairs[1].pending);
|
| - EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairsWithNonRSLLMembers) {
|
| - host_impl_->CreatePendingTree();
|
| -
|
| - scoped_ptr<PictureLayerImpl> layer =
|
| - FakePictureLayerImpl::Create(host_impl_->pending_tree(), 10);
|
| - layer->SetBounds(gfx::Size(10, 10));
|
| - scoped_ptr<FakePictureLayerImpl> nondraw_layer =
|
| - FakePictureLayerImpl::Create(host_impl_->pending_tree(), 12);
|
| - nondraw_layer->SetBounds(gfx::Size(10, 10));
|
| -
|
| - scoped_refptr<RasterSource> pile(FakePicturePileImpl::CreateEmptyPile(
|
| - gfx::Size(10, 10), gfx::Size(10, 10)));
|
| - Region empty_invalidation;
|
| - const PictureLayerTilingSet* null_tiling_set = nullptr;
|
| - layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size());
|
| - layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
|
| - nondraw_layer->set_gpu_raster_max_texture_size(
|
| - host_impl_->device_viewport_size());
|
| - nondraw_layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
|
| -
|
| - layer->AddChild(nondraw_layer.Pass());
|
| - host_impl_->pending_tree()->SetRootLayer(layer.Pass());
|
| -
|
| - LayerTreeImpl* pending_tree = host_impl_->pending_tree();
|
| - LayerImpl* pending_layer = pending_tree->root_layer();
|
| - FakePictureLayerImpl* pending_nondraw_layer =
|
| - static_cast<FakePictureLayerImpl*>(pending_layer->children()[0]);
|
| -
|
| - pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
|
| -
|
| - std::vector<PictureLayerImpl::Pair> layer_pairs;
|
| - host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
|
| - EXPECT_EQ(2u, layer_pairs.size());
|
| - // The pair ordering is flaky, so make it consistent.
|
| - if (layer_pairs[0].pending != pending_layer)
|
| - std::swap(layer_pairs[0], layer_pairs[1]);
|
| - EXPECT_EQ(pending_layer, layer_pairs[0].pending);
|
| - EXPECT_EQ(nullptr, layer_pairs[0].active);
|
| - EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
|
| - EXPECT_EQ(nullptr, layer_pairs[1].active);
|
| -
|
| - host_impl_->ActivateSyncTree();
|
| -
|
| - LayerTreeImpl* active_tree = host_impl_->active_tree();
|
| - LayerImpl* active_layer = active_tree->root_layer();
|
| - FakePictureLayerImpl* active_nondraw_layer =
|
| - static_cast<FakePictureLayerImpl*>(active_layer->children()[0]);
|
| - EXPECT_NE(active_tree, pending_tree);
|
| - EXPECT_NE(active_layer, pending_layer);
|
| - EXPECT_NE(active_nondraw_layer, pending_nondraw_layer);
|
| - EXPECT_NE(nullptr, active_tree);
|
| - EXPECT_NE(nullptr, active_layer);
|
| - EXPECT_NE(nullptr, active_nondraw_layer);
|
| -
|
| - active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
|
| -
|
| - host_impl_->CreatePendingTree();
|
| -
|
| - layer_pairs.clear();
|
| - host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
|
| - EXPECT_EQ(2u, layer_pairs.size());
|
| - // The pair ordering is flaky, so make it consistent.
|
| - if (layer_pairs[0].active != active_layer)
|
| - std::swap(layer_pairs[0], layer_pairs[1]);
|
| - EXPECT_EQ(active_layer, layer_pairs[0].active);
|
| - EXPECT_EQ(pending_layer, layer_pairs[0].pending);
|
| - EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
|
| - EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
|
| -
|
| - // Activate, the active layer has no twin now.
|
| - host_impl_->ActivateSyncTree();
|
| -
|
| - layer_pairs.clear();
|
| - host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
|
| - EXPECT_EQ(2u, layer_pairs.size());
|
| - // The pair ordering is flaky, so make it consistent.
|
| - if (layer_pairs[0].active != active_layer)
|
| - std::swap(layer_pairs[0], layer_pairs[1]);
|
| - EXPECT_EQ(active_layer, layer_pairs[0].active);
|
| - EXPECT_EQ(nullptr, layer_pairs[0].pending);
|
| - EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
|
| - EXPECT_EQ(nullptr, layer_pairs[1].pending);
|
| -
|
| - // Create another layer in the pending tree that's not in the active tree. We
|
| - // should get three pairs including the nondraw layers.
|
| - host_impl_->CreatePendingTree();
|
| - host_impl_->pending_tree()->root_layer()->AddChild(
|
| - FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11));
|
| -
|
| - LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[1];
|
| -
|
| - layer_pairs.clear();
|
| - host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
|
| - EXPECT_EQ(3u, layer_pairs.size());
|
| - // The pair ordering is flaky, so make it consistent.
|
| - if (layer_pairs[0].active != active_layer)
|
| - std::swap(layer_pairs[0], layer_pairs[1]);
|
| - if (layer_pairs[0].active != active_layer)
|
| - std::swap(layer_pairs[0], layer_pairs[2]);
|
| - if (layer_pairs[1].pending != new_pending_layer)
|
| - std::swap(layer_pairs[1], layer_pairs[2]);
|
| - EXPECT_EQ(active_layer, layer_pairs[0].active);
|
| - EXPECT_EQ(pending_layer, layer_pairs[0].pending);
|
| - EXPECT_EQ(new_pending_layer, layer_pairs[1].pending);
|
| - EXPECT_EQ(nullptr, layer_pairs[1].active);
|
| - EXPECT_EQ(active_nondraw_layer, layer_pairs[2].active);
|
| - EXPECT_EQ(pending_nondraw_layer, layer_pairs[2].pending);
|
| -
|
| - host_impl_->pending_tree()->root_layer()->RemoveChild(new_pending_layer);
|
| -
|
| - // Have the pending layer be part of the RSLL now. It should appear in the
|
| - // list, as should its active twin since we don't request only layers with
|
| - // valid draw properties.
|
| - pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
|
| -
|
| - layer_pairs.clear();
|
| - host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
|
| - EXPECT_EQ(2u, layer_pairs.size());
|
| - // The pair ordering is flaky, so make it consistent.
|
| - if (layer_pairs[0].active != active_layer)
|
| - std::swap(layer_pairs[0], layer_pairs[1]);
|
| - EXPECT_EQ(active_layer, layer_pairs[0].active);
|
| - EXPECT_EQ(pending_layer, layer_pairs[0].pending);
|
| - EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
|
| - EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
|
| -
|
| - // Have the active layer be part of the RSLL now instead. It should appear in
|
| - // the list, as should its pending twin since we don't request only layers
|
| - // with valid draw properties.
|
| - pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
|
| - active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
|
| -
|
| - layer_pairs.clear();
|
| - host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
|
| - EXPECT_EQ(2u, layer_pairs.size());
|
| - // The pair ordering is flaky, so make it consistent.
|
| - if (layer_pairs[0].active != active_layer)
|
| - std::swap(layer_pairs[0], layer_pairs[1]);
|
| - EXPECT_EQ(active_layer, layer_pairs[0].active);
|
| - EXPECT_EQ(pending_layer, layer_pairs[0].pending);
|
| - EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
|
| - EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
|
| - host_impl_->CreatePendingTree();
|
| - host_impl_->ActivateSyncTree();
|
| - host_impl_->CreatePendingTree();
|
| -
|
| - LayerTreeImpl* pending_tree = host_impl_->pending_tree();
|
| -
|
| - scoped_ptr<FakePictureLayerImpl> pending_layer =
|
| - FakePictureLayerImpl::Create(pending_tree, 10);
|
| - FakePictureLayerImpl* raw_pending_layer = pending_layer.get();
|
| - pending_tree->SetRootLayer(pending_layer.Pass());
|
| - ASSERT_EQ(raw_pending_layer, pending_tree->root_layer());
|
| -
|
| - EXPECT_EQ(0u, raw_pending_layer->did_become_active_call_count());
|
| - pending_tree->DidBecomeActive();
|
| - EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
|
| -
|
| - scoped_ptr<FakePictureLayerImpl> mask_layer =
|
| - FakePictureLayerImpl::Create(pending_tree, 11);
|
| - FakePictureLayerImpl* raw_mask_layer = mask_layer.get();
|
| - raw_pending_layer->SetMaskLayer(mask_layer.Pass());
|
| - ASSERT_EQ(raw_mask_layer, raw_pending_layer->mask_layer());
|
| -
|
| - EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
|
| - EXPECT_EQ(0u, raw_mask_layer->did_become_active_call_count());
|
| - pending_tree->DidBecomeActive();
|
| - EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
|
| - EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
|
| -
|
| - scoped_ptr<FakePictureLayerImpl> replica_layer =
|
| - FakePictureLayerImpl::Create(pending_tree, 12);
|
| - scoped_ptr<FakePictureLayerImpl> replica_mask_layer =
|
| - FakePictureLayerImpl::Create(pending_tree, 13);
|
| - FakePictureLayerImpl* raw_replica_mask_layer = replica_mask_layer.get();
|
| - replica_layer->SetMaskLayer(replica_mask_layer.Pass());
|
| - raw_pending_layer->SetReplicaLayer(replica_layer.Pass());
|
| - ASSERT_EQ(raw_replica_mask_layer,
|
| - raw_pending_layer->replica_layer()->mask_layer());
|
| -
|
| - EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
|
| - EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
|
| - EXPECT_EQ(0u, raw_replica_mask_layer->did_become_active_call_count());
|
| - pending_tree->DidBecomeActive();
|
| - EXPECT_EQ(3u, raw_pending_layer->did_become_active_call_count());
|
| - EXPECT_EQ(2u, raw_mask_layer->did_become_active_call_count());
|
| - EXPECT_EQ(1u, raw_replica_mask_layer->did_become_active_call_count());
|
| -}
|
| -
|
| -TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
|
| - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
|
| - host_impl_->SetViewportSize(gfx::Size(50, 50));
|
| - DrawFrame();
|
| -
|
| - EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
|
| -
|
| - float min_page_scale = 1.f, max_page_scale = 4.f;
|
| - float page_scale_factor = 1.f;
|
| -
|
| - // The scroll deltas should have the page scale factor applied.
|
| - {
|
| - host_impl_->active_tree()->PushPageScaleFromMainThread(
|
| - page_scale_factor, min_page_scale, max_page_scale);
|
| - host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
|
| - scroll_layer->SetScrollDelta(gfx::Vector2d());
|
| -
|
| - float page_scale_delta = 2.f;
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
|
| - host_impl_->PinchGestureBegin();
|
| - host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
|
| - host_impl_->PinchGestureEnd();
|
| - host_impl_->ScrollEnd();
|
| -
|
| - gfx::Vector2dF scroll_delta(0, 5);
|
| - EXPECT_EQ(InputHandler::SCROLL_STARTED,
|
| - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
|
| -
|
| - host_impl_->ScrollBy(gfx::Point(), scroll_delta);
|
| - host_impl_->ScrollEnd();
|
| - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
|
| - scroll_layer->CurrentScrollOffset());
|
| - }
|
| -}
|
| -
|
| -class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest {
|
| - public:
|
| - LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
|
| - void DidLoseOutputSurfaceOnImplThread() override { num_lost_surfaces_++; }
|
| -
|
| - protected:
|
| - int num_lost_surfaces_;
|
| -};
|
| -
|
| -TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) {
|
| - // Really we just need at least one client notification each time
|
| - // we go from having a valid output surface to not having a valid output
|
| - // surface.
|
| - EXPECT_EQ(0, num_lost_surfaces_);
|
| - host_impl_->DidLoseOutputSurface();
|
| - EXPECT_EQ(1, num_lost_surfaces_);
|
| - host_impl_->DidLoseOutputSurface();
|
| - EXPECT_LE(1, num_lost_surfaces_);
|
| -}
|
| -
|
| -} // namespace
|
| -} // namespace cc
|
|
|